Skip to content

Add HPKE (RFC 9180) C# wrapper#10171

Open
dgarske wants to merge 1 commit intowolfSSL:masterfrom
dgarske:hpke_csharp
Open

Add HPKE (RFC 9180) C# wrapper#10171
dgarske wants to merge 1 commit intowolfSSL:masterfrom
dgarske:hpke_csharp

Conversation

@dgarske
Copy link
Copy Markdown
Contributor

@dgarske dgarske commented Apr 8, 2026

Description

Add HPKE (RFC 9180) C# wrapper and tests

Testing

Done with CSharp tests

Checklist

  • added tests
  • updated/added doxygen
  • updated appropriate READMEs
  • Updated manual and documentation

@dgarske dgarske self-assigned this Apr 8, 2026
Copilot AI review requested due to automatic review settings April 8, 2026 21:38
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Note

Copilot was unable to run its full agentic suite in this review.

Adds a C# P/Invoke wrapper for HPKE (RFC 9180) plus a console-style test that exercises Base mode seal/open and public-key serialization round-trip.

Changes:

  • Added HPKE native imports and managed helper APIs (init, keygen, serialize/deserialize, seal/open, free).
  • Added HPKE Base mode test flow to the C# test runner.
  • Enabled HAVE_HPKE in the C# wrapper user settings.

Reviewed changes

Copilot reviewed 3 out of 3 changed files in this pull request and generated 7 comments.

File Description
wrapper/CSharp/wolfSSL_CSharp/wolfCrypt.cs Adds HPKE P/Invoke bindings and managed convenience APIs for base-mode single-shot operations
wrapper/CSharp/wolfCrypt-Test/wolfCrypt-Test.cs Adds an HPKE base-mode functional test (keygen, serialize/deserialize, seal/open)
wrapper/CSharp/user_settings.h Enables HPKE in the C# wrapper build configuration

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 4 out of 4 changed files in this pull request and generated 4 comments.


💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 5 out of 5 changed files in this pull request and generated 2 comments.


💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines 22 to 24
using System;
using System.Collections.Concurrent;
using System.Runtime.InteropServices;
Copy link

Copilot AI Apr 10, 2026

Choose a reason for hiding this comment

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

System.Collections.Concurrent is used unconditionally, but this wrapper has #if WindowsCE support throughout the file. ConcurrentDictionary is not available on .NET Compact Framework/Windows CE, so defining WindowsCE will fail to compile. Consider wrapping the HPKE context tracking in #if !WindowsCE (or multi-targeting) and using a simpler Dictionary<IntPtr, HpkeContextState> + lock (or another CF-compatible collection) for WindowsCE builds.

Copilot uses AI. Check for mistakes.
Comment on lines +3561 to +3565
if (plaintext == null || plaintext.Length == 0)
{
log(ERROR_LOG, "HPKE seal base: invalid plaintext");
return null;
}
Copy link

Copilot AI Apr 10, 2026

Choose a reason for hiding this comment

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

HpkeSealBase currently rejects plaintext.Length == 0, but HPKE (and the native wc_HpkeSealBase API) can validly seal an empty plaintext (ciphertext would be just the AEAD tag). Consider allowing zero-length plaintexts (keep rejecting plaintext == null) so callers can encrypt empty messages and so the wrapper matches the native API semantics.

Copilot uses AI. Check for mistakes.
Copilot AI review requested due to automatic review settings April 12, 2026 21:50
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 5 out of 5 changed files in this pull request and generated 3 comments.


💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

uint infoSz = (info != null) ? (uint)info.Length : 0;
uint aadSz = (aad != null) ? (uint)aad.Length : 0;
uint ptSz = (uint)plaintext.Length;

Copy link

Copilot AI Apr 12, 2026

Choose a reason for hiding this comment

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

HpkeSealBase computes sealLen as (int)ptSz + HPKE_Nt without guarding against plaintext.Length > int.MaxValue - HPKE_Nt. For very large inputs this can overflow to a negative length and throw or lead to incorrect buffer sizing. Add an explicit bounds check (similar to HpkeOpenBase) and fail cleanly before allocating arrays.

Suggested change
if (plaintext.Length > int.MaxValue - HPKE_Nt)
{
log(ERROR_LOG, "HPKE seal base: plaintext too large");
return null;
}

Copilot uses AI. Check for mistakes.
Comment on lines +3664 to +3668
/// <param name="kem">KEM used (needed to free the ephemeral key)</param>
/// <returns>enc||ciphertext byte array or null on failure</returns>
public static byte[] HpkeSealBase(IntPtr hpke, IntPtr receiverKey,
byte[] info, byte[] aad, byte[] plaintext, HpkeKem kem)
{
Copy link

Copilot AI Apr 12, 2026

Choose a reason for hiding this comment

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

The convenience overload HpkeSealBase(..., HpkeKem kem) uses the caller-provided kem only to free the internally-generated ephemeralKey in finally. If the caller accidentally passes a mismatched KEM, wc_HpkeFreeKey will free the key with the wrong type (e.g., treating an ecc_key as curve25519_key), which can crash or corrupt memory. Since the wrapper can derive the KEM from the hpke context (it is already stored in HpkeContextState), remove this parameter or validate it against the context before freeing.

Copilot uses AI. Check for mistakes.
}

int pubKeySzInt = encCiphertext.Length - sealLen;
if (pubKeySzInt < 0 || pubKeySzInt > ushort.MaxValue)
Copy link

Copilot AI Apr 12, 2026

Choose a reason for hiding this comment

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

HpkeOpenBase(..., int ptLen) derives pubKeySz from the remaining bytes and currently allows up to ushort.MaxValue (65KB) before allocating/copying. This should be capped to the expected enc length for the context/KEM (or at least HPKE_Npk_MAX) to avoid unnecessary large allocations and to reject malformed inputs earlier.

Suggested change
if (pubKeySzInt < 0 || pubKeySzInt > ushort.MaxValue)
if (pubKeySzInt < 0 || pubKeySzInt > HPKE_Npk_MAX)

Copilot uses AI. Check for mistakes.
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