Skip to content

Integrate OpenSSL AES and MD related code into the new framework - not ready to merge#1

Open
thu-ibm wants to merge 5 commits into
move_contextfrom
thu_move_context
Open

Integrate OpenSSL AES and MD related code into the new framework - not ready to merge#1
thu-ibm wants to merge 5 commits into
move_contextfrom
thu_move_context

Conversation

@thu-ibm
Copy link
Copy Markdown
Owner

@thu-ibm thu-ibm commented Apr 21, 2026

Attempted to integrate the OpenSSL native code for the AES and MD algorithms with following two existing PRs. Since these PRs have not yet been merged into main, I created a separate repository to facilitate code sharing and review.

IBM/OpenJCEPlus#1167
IBM/OpenJCEPlus#851

@@ -0,0 +1,259 @@
/*
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.

In general i dont anticipate too many openssl specific tests to be developed. Whatever is developed should be written for both "backends" which includes ockc and openssl and such tests parameterized for all of our desired test configurations ( such as a openssl test only provider )

This being said there could be some on off specific tests for features that are only available in one backend or another however something like what is outlined in this PR with various duplicate tests for algorithms we support we wouldnt want to add.

As part of running tests through mvn a jacoco code coverage report is generated. I highly recommend that we consult this coverage report to see gaps and changes in testing that we want to add for all library backends.

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

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

Thanks for pointing this out. These are not intended to be permanent tests, they are just used for now to verify the Adapter java code and the native functions. Eventually the goal is to use the existing tests that we have when the new framework and tests are updated and ready.

Comment thread src/main/native/openssl/OpenSSLUtils.c Outdated
Comment on lines +56 to +57
static OpenSSLContext* nonFipsContext = NULL;
static OpenSSLContext* fipsContext = NULL;
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 think we should keep with what we already do for OCKC and maintain the different context pointers in the java adapters.

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

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

Ok I will look into that. Thanks!

@KostasTsiounis
Copy link
Copy Markdown
Contributor

Another question is, why all these header files for each of the native files?

@thu-ibm
Copy link
Copy Markdown
Owner Author

thu-ibm commented Apr 30, 2026

Another question is, why all these header files for each of the native files?

To me this way looks cleaner. I asked Bob if this is better way, and this is what it says: :-)

For this codebase: yes, generally one header per native implementation area is the better structure, and you already mostly follow that pattern (OpenSSLSignature.h/.c, OpenSSLDigest.h/.c, OpenSSLHMAC.h/.c, etc.).

Why it is better:

  • Keeps JNI declarations close to the implementation unit
  • Makes symbol review easier when debugging linkage issues
  • Encourages explicit shared types/helpers vs accidental cross-file coupling
  • Improves compile-time checking for exported JNI prototypes
  • Makes maintenance easier as native surface area grows

@KostasTsiounis
Copy link
Copy Markdown
Contributor

Another question is, why all these header files for each of the native files?

To me this way looks cleaner. I asked Bob if this is better way, and this is what it says: :-)

For this codebase: yes, generally one header per native implementation area is the better structure, and you already mostly follow that pattern (OpenSSLSignature.h/.c, OpenSSLDigest.h/.c, OpenSSLHMAC.h/.c, etc.).

Why it is better:

  • Keeps JNI declarations close to the implementation unit
  • Makes symbol review easier when debugging linkage issues
  • Encourages explicit shared types/helpers vs accidental cross-file coupling
  • Improves compile-time checking for exported JNI prototypes
  • Makes maintenance easier as native surface area grows

All these are good reasons in general, but I don't think they fully apply to our project. I asked Bob explicitly, asking it to take the OpenJCEPlus project as context, and the answer was as follows:

No, creating header files for each C file would NOT be useful in your case. Here's why:

Your Current Architecture

Each C file (like DHKey.c, ECKey.c, SymmetricCipher.c) contains:

  • JNI functions that are called directly from Java
  • Functions are JNIEXPORT with signatures like Java_com_ibm_crypto_plus_provider_base_NativeInterface_DHKEY_1generate
  • Each file is self-contained - no C file calls functions from another C file

Why Headers Per File Are Unnecessary

  1. No Inter-C-File Dependencies
       - C files don't call each other's functions
       - Java calls native functions via JNI, not C-to-C calls
       - Each file is truly independent

  2. JNI Functions Are Not Meant to Be Shared
       - JNI functions are entry points from Java, not internal APIs
       - They're already declared in the auto-generated com_ibm_crypto_plus_provider_base_NativeInterface.h

  3. Would Add Maintenance Burden
       - Extra files to maintain with no benefit
       - Duplicate declarations (already in JNI header)
       - More compilation dependencies without value

What You Already Have (and Should Keep)

Shared utility headers like Utils.h - used across multiple files
Shared constant headers like Padding.h, ExceptionCodes.h - define common values
Shared struct headers like Digest.h - define data structures

Conclusion: Your current approach is correct. Only create headers for truly shared code (utilities, constants, structs), not for independent JNI implementation files.

@thu-ibm
Copy link
Copy Markdown
Owner Author

thu-ibm commented May 26, 2026

Another question is, why all these header files for each of the native files?

To me this way looks cleaner. I asked Bob if this is better way, and this is what it says: :-)
For this codebase: yes, generally one header per native implementation area is the better structure, and you already mostly follow that pattern (OpenSSLSignature.h/.c, OpenSSLDigest.h/.c, OpenSSLHMAC.h/.c, etc.).
Why it is better:

  • Keeps JNI declarations close to the implementation unit
  • Makes symbol review easier when debugging linkage issues
  • Encourages explicit shared types/helpers vs accidental cross-file coupling
  • Improves compile-time checking for exported JNI prototypes
  • Makes maintenance easier as native surface area grows

All these are good reasons in general, but I don't think they fully apply to our project. I asked Bob explicitly, asking it to take the OpenJCEPlus project as context, and the answer was as follows:

No, creating header files for each C file would NOT be useful in your case. Here's why:

Your Current Architecture

Each C file (like DHKey.c, ECKey.c, SymmetricCipher.c) contains:

  • JNI functions that are called directly from Java
  • Functions are JNIEXPORT with signatures like Java_com_ibm_crypto_plus_provider_base_NativeInterface_DHKEY_1generate
  • Each file is self-contained - no C file calls functions from another C file

Why Headers Per File Are Unnecessary

  1. No Inter-C-File Dependencies
       - C files don't call each other's functions
       - Java calls native functions via JNI, not C-to-C calls
       - Each file is truly independent
  2. JNI Functions Are Not Meant to Be Shared
       - JNI functions are entry points from Java, not internal APIs
       - They're already declared in the auto-generated com_ibm_crypto_plus_provider_base_NativeInterface.h
  3. Would Add Maintenance Burden
       - Extra files to maintain with no benefit
       - Duplicate declarations (already in JNI header)
       - More compilation dependencies without value

What You Already Have (and Should Keep)

Shared utility headers like Utils.h - used across multiple files ✅ Shared constant headers like Padding.h, ExceptionCodes.h - define common values ✅ Shared struct headers like Digest.h - define data structures

Conclusion: Your current approach is correct. Only create headers for truly shared code (utilities, constants, structs), not for independent JNI implementation files.

Thanks @KostasTsiounis for your further consideration on this! I also thought about it more and asked Bob to look at the project and also our discussions in this pull request. Following is what it said. Please see if you agree.

The better approach for this project is: keep per-module headers, but only where they define a real shared interface; avoid headers that are just mirrors of a single implementation file.

Why that conclusion fits this repo:

The OpenSSL native layer is already organized by implementation area: OpenSSLSignature.h, OpenSSLSymmetricCipher.h, OpenSSLDigest.h, OpenSSLHMAC.h, etc. That matches the PR response and is a sensible structure for a JNI/native boundary.

Some headers are clearly justified because they expose shared types or functions used across files. Example: OpenSSLSymmetricCipher.h defines CipherContext, and both OpenSSLCCM.c and OpenSSLGCM.c include it. Likewise, OpenSSLHelpers.h is a true common utility interface used broadly.

But not every file-paired header is equally valuable. OpenSSLJNI.h is very thin and mainly included by its own implementation in OpenSSLJNI.c. If a header is not consumed by other translation units and contains no important shared declarations, it adds maintenance overhead without much payoff.

So the best rule here is not “one header for every native file” and not “collapse everything into one big header.” It is:

one header per native module/area when that module exports shared declarations, JNI entry points, structs, constants, or helper APIs;

no separate header when the declarations are purely local to one .c file and can be kept static inside that file.
Compared options:

Per-file/per-module headers:

Pros: clearer boundaries, easier navigation, better dependency hygiene, less accidental coupling, closer to how this repo is already structured.

Cons: can become boilerplate if every .c gets a mostly-empty companion header.
Single shared umbrella header:
Pros: fewer files.
Cons: worse isolation, more unnecessary includes, easier for internal details to leak across modules, less scalable as more algorithms are added.

My recommendation for this codebase:

Keep the modular header layout as the default.

Prune or avoid trivial headers like OpenSSLJNI.h when they don’t define meaningful cross-file contracts.

Treat OpenSSLHelpers.h and data-structure headers like OpenSSLSymmetricCipher.h as the good pattern.

Prefer internal static helpers over header declarations unless another file truly needs them.

In short: Kostas’s concern is valid if the headers are merely 1:1 wrappers, but the repo as a whole benefits from module-scoped headers. The strongest design is a selective modular-header approach, not either extreme.

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.

3 participants