Skip to content

Commit c495f1c

Browse files
committed
Peer review fixes
1 parent 0228bac commit c495f1c

File tree

3 files changed

+115
-12
lines changed

3 files changed

+115
-12
lines changed

wrapper/CSharp/README.md

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,8 @@ apt-get install mono-complete
4040

4141
### Build wolfSSL and install
4242

43+
#### System-wide install
44+
4345
```
4446
./autogen.sh
4547
cp wrapper/CSharp/user_settings.h .
@@ -49,6 +51,16 @@ make check
4951
sudo make install
5052
```
5153

54+
#### Local-only install (no sudo required)
55+
56+
```
57+
./autogen.sh
58+
cp wrapper/CSharp/user_settings.h .
59+
./configure --enable-usersettings --prefix=$(pwd)/install
60+
make
61+
make install
62+
```
63+
5264
### Build and run the wolfCrypt test wrapper
5365

5466
From the `wrapper/CSharp` directory (`cd wrapper/CSharp`):
@@ -57,9 +69,20 @@ Compile wolfCrypt test:
5769

5870
```
5971
mcs wolfCrypt-Test/wolfCrypt-Test.cs wolfSSL_CSharp/wolfCrypt.cs wolfSSL_CSharp/wolfSSL.cs wolfSSL_CSharp/X509.cs -OUT:wolfcrypttest.exe
72+
```
73+
74+
Run with system-wide install:
75+
76+
```
6077
mono wolfcrypttest.exe
6178
```
6279

80+
Run with local-only install (from the wolfSSL root directory):
81+
82+
```
83+
LD_LIBRARY_PATH=./install/lib mono wrapper/CSharp/wolfcrypttest.exe
84+
```
85+
6386
### Build and run the wolfSSL client/server test
6487

6588
From the `wrapper/CSharp` directory (`cd wrapper/CSharp`):

wrapper/CSharp/wolfCrypt-Test/wolfCrypt-Test.cs

Lines changed: 42 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -880,17 +880,14 @@ private static void hash_test(uint hashType)
880880
}
881881
} /* END hash_test */
882882

883-
private static void hpke_test()
883+
private static void hpke_test(wolfcrypt.HpkeKem kem,
884+
wolfcrypt.HpkeKdf kdf, wolfcrypt.HpkeAead aead)
884885
{
885886
IntPtr hpke = IntPtr.Zero;
886887
IntPtr receiverKey = IntPtr.Zero;
887888
IntPtr deserializedKey = IntPtr.Zero;
888889
IntPtr ephemeralKey = IntPtr.Zero;
889890

890-
wolfcrypt.HpkeKem kem = wolfcrypt.HpkeKem.DHKEM_P256_HKDF_SHA256;
891-
wolfcrypt.HpkeKdf kdf = wolfcrypt.HpkeKdf.HKDF_SHA256;
892-
wolfcrypt.HpkeAead aead = wolfcrypt.HpkeAead.AES_128_GCM;
893-
894891
try
895892
{
896893
Console.WriteLine("\nStarting HPKE Base mode test...");
@@ -988,7 +985,7 @@ private static void hpke_test()
988985
Console.WriteLine($"HpkeSealBase convenience passed. Output length: {encCiphertext2.Length}");
989986

990987
byte[] decrypted2 = wolfcrypt.HpkeOpenBase(hpke, receiverKey,
991-
encCiphertext2, info, aad, plaintext.Length);
988+
encCiphertext2, info, aad, kem);
992989
if (decrypted2 == null)
993990
{
994991
throw new Exception("HpkeOpenBase (convenience) failed");
@@ -998,6 +995,39 @@ private static void hpke_test()
998995
throw new Exception("Convenience seal/open: decrypted text does not match");
999996
}
1000997
Console.WriteLine("HPKE convenience overload test PASSED.");
998+
999+
/* Negative test: tampered ciphertext should fail */
1000+
Console.WriteLine("Testing HpkeOpenBase with tampered ciphertext...");
1001+
byte[] tampered = (byte[])encCiphertext.Clone();
1002+
tampered[tampered.Length - 1] ^= 0xFF; /* flip last byte (in tag) */
1003+
byte[] badResult = wolfcrypt.HpkeOpenBase(hpke, receiverKey,
1004+
tampered, info, aad, plaintext.Length);
1005+
if (badResult != null)
1006+
{
1007+
throw new Exception("HpkeOpenBase should fail with tampered ciphertext");
1008+
}
1009+
Console.WriteLine("Tampered ciphertext test PASSED (correctly rejected).");
1010+
1011+
/* Negative test: mismatched AAD should fail */
1012+
Console.WriteLine("Testing HpkeOpenBase with mismatched AAD...");
1013+
byte[] wrongAad = Encoding.UTF8.GetBytes("wrong aad");
1014+
badResult = wolfcrypt.HpkeOpenBase(hpke, receiverKey,
1015+
encCiphertext, info, wrongAad, plaintext.Length);
1016+
if (badResult != null)
1017+
{
1018+
throw new Exception("HpkeOpenBase should fail with mismatched AAD");
1019+
}
1020+
Console.WriteLine("Mismatched AAD test PASSED (correctly rejected).");
1021+
1022+
/* Negative test: invalid ptLen should fail */
1023+
Console.WriteLine("Testing HpkeOpenBase with invalid ptLen...");
1024+
badResult = wolfcrypt.HpkeOpenBase(hpke, receiverKey,
1025+
encCiphertext, info, aad, plaintext.Length + 1);
1026+
if (badResult != null)
1027+
{
1028+
throw new Exception("HpkeOpenBase should fail with incorrect ptLen");
1029+
}
1030+
Console.WriteLine("Invalid ptLen test PASSED (correctly rejected).");
10011031
}
10021032
finally
10031033
{
@@ -1076,7 +1106,12 @@ public static void Main(string[] args)
10761106

10771107
Console.WriteLine("\nStarting HPKE tests");
10781108

1079-
hpke_test(); /* HPKE Base mode test */
1109+
hpke_test(wolfcrypt.HpkeKem.DHKEM_P256_HKDF_SHA256,
1110+
wolfcrypt.HpkeKdf.HKDF_SHA256,
1111+
wolfcrypt.HpkeAead.AES_128_GCM);
1112+
hpke_test(wolfcrypt.HpkeKem.DHKEM_X25519_HKDF_SHA256,
1113+
wolfcrypt.HpkeKdf.HKDF_SHA256,
1114+
wolfcrypt.HpkeAead.AES_128_GCM);
10801115

10811116
wolfcrypt.Cleanup();
10821117

wrapper/CSharp/wolfSSL_CSharp/wolfCrypt.cs

Lines changed: 50 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3259,8 +3259,10 @@ public enum HpkeAead : ushort {
32593259
/* HPKE Nt (GCM tag length) */
32603260
private static readonly int HPKE_Nt = 16;
32613261

3262-
/* Hpke struct is ~80 bytes on 64-bit (see hpke.h). Over-allocate to
3263-
* accommodate future growth and platform alignment differences. */
3262+
/* Hpke struct is ~80 bytes on 64-bit (see hpke.h). Allocate 512 bytes
3263+
* (6x headroom) to accommodate platform alignment and future growth.
3264+
* If the native struct ever exceeds this, wc_HpkeInit will write OOB —
3265+
* keep in sync with hpke.h if the struct grows significantly. */
32643266
private static readonly int HPKE_STRUCT_SZ = 512;
32653267

32663268
/// <summary>
@@ -3605,13 +3607,26 @@ public static byte[] HpkeOpenBase(IntPtr hpke, IntPtr receiverKey,
36053607

36063608
/* encCiphertext = enc || ciphertext || GCM tag
36073609
* where ciphertext is ptLen bytes, tag is Nt bytes */
3610+
if (ptLen < 0 || ptLen > int.MaxValue - HPKE_Nt)
3611+
{
3612+
log(ERROR_LOG, "HPKE open base: invalid ptLen");
3613+
return null;
3614+
}
3615+
36083616
int sealLen = ptLen + HPKE_Nt;
3609-
if (ptLen < 0 || encCiphertext.Length < sealLen)
3617+
if (encCiphertext.Length < sealLen)
36103618
{
36113619
log(ERROR_LOG, "HPKE open base: encCiphertext too short for given ptLen");
36123620
return null;
36133621
}
3614-
ushort pubKeySz = (ushort)(encCiphertext.Length - sealLen);
3622+
3623+
int pubKeySzInt = encCiphertext.Length - sealLen;
3624+
if (pubKeySzInt < 0 || pubKeySzInt > ushort.MaxValue)
3625+
{
3626+
log(ERROR_LOG, "HPKE open base: invalid encapsulated public key size");
3627+
return null;
3628+
}
3629+
ushort pubKeySz = (ushort)pubKeySzInt;
36153630

36163631
/* Split enc and sealed data (ciphertext || tag) */
36173632
byte[] pubKey = new byte[pubKeySz];
@@ -3625,7 +3640,7 @@ public static byte[] HpkeOpenBase(IntPtr hpke, IntPtr receiverKey,
36253640
byte[] plaintext = new byte[ptLen];
36263641

36273642
/* ctSz is just the ciphertext length (without tag);
3628-
* wc_HpkeContextOpenBase reads the tag from ct + ctSz */
3643+
* wc_HpkeOpenBase reads the tag from ct + ctSz */
36293644
int ret = wc_HpkeOpenBase(hpke, receiverKey, pubKey, pubKeySz,
36303645
info, infoSz, aad, aadSz, ct, (uint)ptLen, plaintext);
36313646
if (ret != 0)
@@ -3642,6 +3657,36 @@ public static byte[] HpkeOpenBase(IntPtr hpke, IntPtr receiverKey,
36423657
return null;
36433658
}
36443659
}
3660+
3661+
/// <summary>
3662+
/// Convenience SingleShot open (decrypt) using HPKE Base mode.
3663+
/// Derives the plaintext length from the KEM enc length, so the caller
3664+
/// does not need to know ptLen.
3665+
/// </summary>
3666+
/// <param name="hpke">HPKE context from HpkeInit()</param>
3667+
/// <param name="receiverKey">Receiver private keypair</param>
3668+
/// <param name="encCiphertext">enc||ciphertext blob from HpkeSealBase()</param>
3669+
/// <param name="info">Info context bytes (can be null)</param>
3670+
/// <param name="aad">Additional authenticated data (can be null)</param>
3671+
/// <param name="kem">KEM used (to derive enc length)</param>
3672+
/// <returns>Decrypted plaintext byte array or null on failure</returns>
3673+
public static byte[] HpkeOpenBase(IntPtr hpke, IntPtr receiverKey,
3674+
byte[] encCiphertext, byte[] info, byte[] aad, HpkeKem kem)
3675+
{
3676+
ushort encLen = HpkeEncLen(kem);
3677+
if (encLen == 0)
3678+
{
3679+
log(ERROR_LOG, "HPKE open base: unsupported KEM");
3680+
return null;
3681+
}
3682+
if (encCiphertext == null || encCiphertext.Length < encLen + HPKE_Nt)
3683+
{
3684+
log(ERROR_LOG, "HPKE open base: encCiphertext too short");
3685+
return null;
3686+
}
3687+
int ptLen = encCiphertext.Length - encLen - HPKE_Nt;
3688+
return HpkeOpenBase(hpke, receiverKey, encCiphertext, info, aad, ptLen);
3689+
}
36453690
/* END HPKE */
36463691

36473692

0 commit comments

Comments
 (0)