diff --git a/wrapper/CSharp/README.md b/wrapper/CSharp/README.md
index be054a88fc..912192f871 100644
--- a/wrapper/CSharp/README.md
+++ b/wrapper/CSharp/README.md
@@ -46,7 +46,7 @@ apt-get install mono-complete
```
./autogen.sh
-./configure --enable-keygen --enable-ed25519 --enable-curve25519 --enable-aesgcm
+./configure --enable-keygen --enable--eccencrypt --enable-ed25519 --enable-curve25519 --enable-aesgcm
make
make check
sudo make install
diff --git a/wrapper/CSharp/user_settings.h b/wrapper/CSharp/user_settings.h
index c98d84cae3..b9d2ff738d 100644
--- a/wrapper/CSharp/user_settings.h
+++ b/wrapper/CSharp/user_settings.h
@@ -45,6 +45,7 @@
#define WOLFSSL_KEY_GEN /* RSA key gen */
#define WOLFSSL_ASN_TEMPLATE /* default */
#define WOLFSSL_SHA3
+
#if 0
#define OPENSSL_EXTRA
#endif
@@ -67,6 +68,8 @@
#define HAVE_HKDF
#undef NO_DH
+#define HAVE_PUBLIC_FFDHE
+#define HAVE_FFDHE_2048
#define HAVE_FFDHE_4096
#undef NO_RSA
diff --git a/wrapper/CSharp/wolfCrypt-Test/wolfCrypt-Test.cs b/wrapper/CSharp/wolfCrypt-Test/wolfCrypt-Test.cs
index c96f8ee862..4f79e186aa 100755
--- a/wrapper/CSharp/wolfCrypt-Test/wolfCrypt-Test.cs
+++ b/wrapper/CSharp/wolfCrypt-Test/wolfCrypt-Test.cs
@@ -633,6 +633,106 @@ private static void hash_test(uint hashType)
}
} /* END hash_test */
+ private static void ecies_test()
+{
+ const int keySize = 32;
+ const int bufferSize = 128;
+ const string message = "Hello wolfSSL!";
+ byte[] salt = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 };
+
+ IntPtr a = IntPtr.Zero;
+ IntPtr b = IntPtr.Zero;
+ IntPtr aCtx = IntPtr.Zero;
+ IntPtr bCtx = IntPtr.Zero;
+ IntPtr rng = IntPtr.Zero;
+ IntPtr heap = IntPtr.Zero;
+
+ byte[] plaintext = new byte[bufferSize];
+ byte[] encrypted = new byte[bufferSize];
+ byte[] decrypted = new byte[bufferSize];
+
+ try
+ {
+ Console.WriteLine($"\nStarting ecies test for {keySize} key size...");
+
+ /* Create a new RNG context */
+ rng = wolfcrypt.RandomNew();
+ if (rng == IntPtr.Zero)
+ {
+ throw new Exception("RNG initialization failed.");
+ }
+
+ /* Initialize keys */
+ a = wolfcrypt.EccMakeKey(keySize);
+ b = wolfcrypt.EccMakeKey(keySize);
+ if (a == IntPtr.Zero || b == IntPtr.Zero)
+ {
+ throw new Exception("Key generation failed.");
+ }
+ Console.WriteLine("ECC key generation passed.");
+
+ /* Create ECIES contexts for encryption and decryption */
+ aCtx = wolfcrypt.EciesNewCtx((int)wolfcrypt.ecFlags.REQ_RESP_CLIENT, rng, heap);
+ bCtx = wolfcrypt.EciesNewCtx((int)wolfcrypt.ecFlags.REQ_RESP_SERVER, rng, heap);
+ if (aCtx == IntPtr.Zero || bCtx == IntPtr.Zero)
+ {
+ throw new Exception("Context creation failed.");
+ }
+ Console.WriteLine("ECC context creation passed.");
+
+ /* Set KDF salt */
+ if (wolfcrypt.EciesSetKdfSalt(aCtx, salt) != 0 ||
+ wolfcrypt.EciesSetKdfSalt(bCtx, salt) != 0)
+ {
+ throw new Exception("Failed to set KDF salt.");
+ }
+ Console.WriteLine("KDF salt setup passed.");
+
+ /* Prepare plaintext */
+ Array.Clear(plaintext, 0, plaintext.Length);
+ Array.Copy(Encoding.ASCII.GetBytes(message), plaintext, message.Length);
+ /* Pad to block size */
+ int plaintextLen = ((message.Length + (wolfcrypt.AES_BLOCK_SIZE - 1)) /
+ wolfcrypt.AES_BLOCK_SIZE) * wolfcrypt.AES_BLOCK_SIZE;
+
+ /* Encrypt message */
+ int ret = wolfcrypt.EciesEncrypt(a, b, plaintext, (uint)plaintextLen, encrypted, aCtx);
+ if (ret < 0)
+ {
+ throw new Exception("Encryption failed.");
+ }
+
+ int encryptedLen = ret;
+ Console.WriteLine("ECC encryption passed.");
+
+ /* Decrypt message */
+ ret = wolfcrypt.EciesDecrypt(b, a, encrypted, (uint)encryptedLen, decrypted, bCtx);
+ if (ret < 0)
+ {
+ throw new Exception("Decryption failed.");
+ }
+
+ int decryptedLen = ret;
+ Console.WriteLine("ECC decryption passed.");
+
+ /* Compare decrypted text to original plaintext */
+ if (!wolfcrypt.ByteArrayVerify(plaintext, decrypted))
+ {
+ throw new Exception("Decrypted text does not match original plaintext.");
+ }
+ Console.WriteLine("Decrypted text matches original plaintext.");
+ }
+ finally
+ {
+ /* Cleanup key and context */
+ if (a != IntPtr.Zero) wolfcrypt.EccFreeKey(a);
+ if (b != IntPtr.Zero) wolfcrypt.EccFreeKey(b);
+ if (aCtx != IntPtr.Zero) wolfcrypt.EciesFreeCtx(aCtx);
+ if (bCtx != IntPtr.Zero) wolfcrypt.EciesFreeCtx(bCtx);
+ if (rng != IntPtr.Zero) wolfcrypt.RandomFree(rng);
+ }
+} /* END ecies_test */
+
public static void standard_log(int lvl, StringBuilder msg)
{
Console.WriteLine(msg);
@@ -670,6 +770,8 @@ public static void Main(string[] args)
hash_test((uint)wolfcrypt.hashType.WC_HASH_TYPE_SHA512); /* SHA-512 HASH test */
hash_test((uint)wolfcrypt.hashType.WC_HASH_TYPE_SHA3_256); /* SHA3_256 HASH test */
+ ecies_test(); /* ECIES test */
+
wolfcrypt.Cleanup();
Console.WriteLine("\nAll tests completed successfully");
diff --git a/wrapper/CSharp/wolfSSL_CSharp/wolfCrypt.cs b/wrapper/CSharp/wolfSSL_CSharp/wolfCrypt.cs
index bb8547499e..5c280429fd 100755
--- a/wrapper/CSharp/wolfSSL_CSharp/wolfCrypt.cs
+++ b/wrapper/CSharp/wolfSSL_CSharp/wolfCrypt.cs
@@ -49,6 +49,7 @@ public class wolfcrypt
[DllImport(wolfssl_dll, CallingConvention = CallingConvention.Cdecl)]
private extern static int wc_RNG_GenerateBlock(IntPtr rng, IntPtr output, UInt32 sz);
+
/********************************
* ECC
*/
@@ -71,14 +72,38 @@ public class wolfcrypt
[DllImport(wolfssl_dll, CallingConvention = CallingConvention.Cdecl)]
private static extern int wc_EccPrivateKeyToDer(IntPtr key, byte[] output, uint inLen);
[DllImport(wolfssl_dll, CallingConvention = CallingConvention.Cdecl)]
- private static extern int wc_EccPublicKeyToDer(IntPtr key, byte[] output, uint inLen, int with_AlgCurve);
-
- /* ASN.1 export private */
- /* int wc_EccKeyToDer(ecc_key* key, byte* output, word32 inLen); */
-
- /* RAW elements of ECC key (private d, public qX/qY) import and export and unsigned bin
- /* int wc_ecc_import_raw_ex(ecc_key* key, const char* qx, const char* qy, const char* d, int curve_id) */
- /* int wc_ecc_export_ex(ecc_key* key, byte* qx, word32* qxLen, byte* qy, word32* qyLen, byte* d, word32* dLen, int encType) */
+ private static extern int wc_EccPublicKeyToDer(IntPtr key, byte[] output, uint inLen, int with_AlgCurve);
+
+
+ /********************************
+ * ECIES
+ */
+ [DllImport(wolfssl_dll, CallingConvention = CallingConvention.Cdecl)]
+ private extern static IntPtr wc_ecc_ctx_new(int flags, IntPtr rng);
+ [DllImport(wolfssl_dll, CallingConvention = CallingConvention.Cdecl)]
+ private extern static IntPtr wc_ecc_ctx_new_ex(int flags, IntPtr rng, IntPtr heap);
+ [DllImport(wolfssl_dll, CallingConvention = CallingConvention.Cdecl)]
+ private extern static void wc_ecc_ctx_free(IntPtr ctx);
+ [DllImport(wolfssl_dll, CallingConvention = CallingConvention.Cdecl)]
+ private extern static int wc_ecc_ctx_reset(IntPtr ctx, IntPtr rng);
+ [DllImport(wolfssl_dll, CallingConvention = CallingConvention.Cdecl)]
+ private extern static int wc_ecc_ctx_set_algo(IntPtr ctx, byte encAlgo, byte kdfAlgo, byte macAlgo);
+ [DllImport(wolfssl_dll, CallingConvention = CallingConvention.Cdecl)]
+ private extern static IntPtr wc_ecc_ctx_get_own_salt(IntPtr ctx);
+ [DllImport(wolfssl_dll, CallingConvention = CallingConvention.Cdecl)]
+ private extern static int wc_ecc_ctx_set_peer_salt(IntPtr ctx, IntPtr salt);
+ [DllImport(wolfssl_dll, CallingConvention = CallingConvention.Cdecl)]
+ private extern static int wc_ecc_ctx_set_own_salt(IntPtr ctx, IntPtr salt, uint sz);
+ [DllImport(wolfssl_dll, CallingConvention = CallingConvention.Cdecl)]
+ private extern static int wc_ecc_ctx_set_kdf_salt(IntPtr ctx, IntPtr salt, uint sz);
+ [DllImport(wolfssl_dll, CallingConvention = CallingConvention.Cdecl)]
+ private extern static int wc_ecc_ctx_set_info(IntPtr ctx, IntPtr info, int sz);
+ [DllImport(wolfssl_dll, CallingConvention = CallingConvention.Cdecl)]
+ private extern static int wc_ecc_encrypt(IntPtr privKey, IntPtr pubKey, IntPtr msg, uint msgSz, IntPtr outBuffer, IntPtr outSz, IntPtr ctx);
+ [DllImport(wolfssl_dll, CallingConvention = CallingConvention.Cdecl)]
+ private extern static int wc_ecc_encrypt_ex(IntPtr privKey, IntPtr pubKey, IntPtr msg, uint msgSz, IntPtr outBuffer, IntPtr outSz, IntPtr ctx, int compressed);
+ [DllImport(wolfssl_dll, CallingConvention = CallingConvention.Cdecl)]
+ private extern static int wc_ecc_decrypt(IntPtr privKey, IntPtr pubKey, IntPtr msg, uint msgSz, IntPtr outBuffer, IntPtr outSz, IntPtr ctx);
/********************************
@@ -236,15 +261,15 @@ public class wolfcrypt
/********************************
* ChaCha20
*/
-
/* wc_Chacha_SetIV, wc_Chacha_Process, wc_Chacha_SetKey */
/* wc_Poly1305SetKey, wc_Poly1305Update, wc_Poly1305Final */
/* wc_ChaCha20Poly1305_Encrypt, wc_ChaCha20Poly1305_Decrypt, wc_ChaCha20Poly1305_Init,
- wc_ChaCha20Poly1305_UpdateAad, wc_ChaCha20Poly1305_UpdateData, wc_ChaCha20Poly1305_Final */
+ wc_ChaCha20Poly1305_UpdateAad, wc_ChaCha20Poly1305_UpdateData, wc_ChaCha20Poly1305_Final */
+
/********************************
- * Logging
- */
+ * Logging
+ */
[DllImport(wolfssl_dll, CallingConvention = CallingConvention.Cdecl)]
private extern static IntPtr wc_GetErrorString(int error);
@@ -265,10 +290,10 @@ private static void log(int lvl, string msg)
internal_log(lvl, ptr);
}
+
/********************************
* Enum types from wolfSSL library
*/
-
/* Logging levels */
public static readonly int ERROR_LOG = 0;
public static readonly int INFO_LOG = 1;
@@ -283,18 +308,20 @@ private static void log(int lvl, string msg)
public static readonly int AES_128_KEY_SIZE = 16; /* for 128 bit */
public static readonly int AES_192_KEY_SIZE = 24; /* for 192 bit */
public static readonly int AES_256_KEY_SIZE = 32; /* for 256 bit */
+ public static readonly int AES_BLOCK_SIZE = 16;
/* Error codes */
-
public static readonly int SUCCESS = 0;
public static readonly int SIG_VERIFY_E = -229; /* wolfcrypt signature verify error */
public static readonly int MEMORY_E = -125; /* Out of memory error */
public static readonly int EXCEPTION_E = -1;
public static readonly int BUFFER_E = -131; /* RSA buffer error, output too small/large */
+
/***********************************************************************
* Class Public Functions
**********************************************************************/
+
///
/// Initialize wolfCrypt library
///
@@ -732,6 +759,445 @@ public static void EccFreeKey(IntPtr key)
/* END ECC */
+ /***********************************************************************
+ * ECIES
+ **********************************************************************/
+
+ ///
+ /// Create a new ECIES context with flags, RNG, and custom heap.
+ ///
+ /// Flags for the context initialization.
+ /// Random Number Generator (RNG) pointer.
+ /// Custom heap pointer for memory allocations.
+ /// Pointer to the newly created ECIES context or IntPtr.Zero on failure.
+ public static IntPtr EciesNewCtx(int flags, IntPtr rng, IntPtr heap)
+ {
+ IntPtr ctx = IntPtr.Zero;
+ heap = IntPtr.Zero;
+
+ try
+ {
+ ctx = wc_ecc_ctx_new_ex(flags, rng, heap);
+ if (ctx == IntPtr.Zero)
+ {
+ log(ERROR_LOG, "ECIES context creation with custom heap failed: returned IntPtr.Zero");
+ }
+ }
+ catch (Exception e)
+ {
+ log(ERROR_LOG, "ECIES context creation with custom heap failed: " + e.ToString());
+ return IntPtr.Zero;
+ }
+
+ return ctx;
+ }
+
+ ///
+ /// Reset the ECIES context with a new RNG.
+ ///
+ /// Pointer to the ECIES context to reset.
+ /// New RNG to set.
+ /// 0 on success, or a negative error code on failure.
+ public static int EciesCtxReset(IntPtr ctx, IntPtr rng)
+ {
+ int ret;
+
+ try
+ {
+ ret = wc_ecc_ctx_reset(ctx, rng);
+ }
+ catch (Exception e)
+ {
+ log(ERROR_LOG, "ECIES context reset exception: " + e.ToString());
+ ret = EXCEPTION_E;
+ }
+
+ return ret;
+ }
+
+ ///
+ /// Set encryption, KDF, and MAC algorithms for the ECIES context.
+ ///
+ /// Pointer to the ECIES context.
+ /// Encryption algorithm identifier.
+ /// Key Derivation Function (KDF) algorithm identifier.
+ /// MAC algorithm identifier.
+ /// 0 on success, or a negative error code on failure.
+ public static int EciesSetAlgo(IntPtr ctx, byte encAlgo, byte kdfAlgo, byte macAlgo)
+ {
+ int ret;
+
+ try
+ {
+ ret = wc_ecc_ctx_set_algo(ctx, encAlgo, kdfAlgo, macAlgo);
+ }
+ catch (Exception e)
+ {
+ log(ERROR_LOG, "ECIES set algorithm exception: " + e.ToString());
+ ret = EXCEPTION_E;
+ }
+
+ return ret;
+ }
+
+ ///
+ /// Get the ECIES own salt.
+ ///
+ /// Pointer to the ECIES context.
+ /// Pointer to the own salt, or IntPtr.Zero if there is an error.
+ public static IntPtr EciesGetOwnSalt(IntPtr ctx)
+ {
+ IntPtr saltPtr = IntPtr.Zero;
+
+ try
+ {
+ /* Check */
+ if (ctx == IntPtr.Zero)
+ {
+ log(ERROR_LOG, "Invalid ECIES context pointer.");
+ return IntPtr.Zero;
+ }
+
+ /* Retrieve own salt */
+ saltPtr = wc_ecc_ctx_get_own_salt(ctx);
+
+ if (saltPtr == IntPtr.Zero)
+ {
+ log(ERROR_LOG, "Failed to get own salt.");
+ return IntPtr.Zero;
+ }
+ }
+ catch (Exception e)
+ {
+ log(ERROR_LOG, "ECIES get own salt exception: " + e.ToString());
+ saltPtr = IntPtr.Zero;
+ }
+
+ return saltPtr;
+ }
+
+
+ ///
+ /// Set the peer salt for the ECIES context.
+ ///
+ /// Pointer to the ECIES context.
+ /// Peer salt as a byte array.
+ /// 0 on success, or a negative error code on failure.
+ public static int EciesSetPeerSalt(IntPtr ctx, byte[] salt)
+ {
+ IntPtr saltPtr = IntPtr.Zero;
+ int ret;
+
+ try
+ {
+ /* Allocate memory */
+ saltPtr = Marshal.AllocHGlobal(salt.Length);
+ Marshal.Copy(salt, 0, saltPtr, salt.Length);
+
+ /* Set the peer salt */
+ ret = wc_ecc_ctx_set_peer_salt(ctx, saltPtr);
+ }
+ catch (Exception e)
+ {
+ log(ERROR_LOG, "ECIES set peer salt exception: " + e.ToString());
+ ret = EXCEPTION_E;
+ }
+ finally
+ {
+ /* Cleanup */
+ if (saltPtr != IntPtr.Zero) Marshal.FreeHGlobal(saltPtr);
+ }
+
+ return ret;
+ }
+
+ ///
+ /// Set the own salt for the ECIES context.
+ ///
+ /// Pointer to the ECIES context.
+ /// Own salt as a byte array.
+ /// 0 on success, or a negative error code on failure.
+ public static int EciesSetOwnSalt(IntPtr ctx, byte[] salt)
+ {
+ IntPtr saltPtr = IntPtr.Zero;
+ uint saltSz;
+ int ret;
+
+ try
+ {
+ /* Allocate memory */
+ saltSz = (uint)salt.Length;
+ saltPtr = Marshal.AllocHGlobal(salt.Length);
+ Marshal.Copy(salt, 0, saltPtr, salt.Length);
+
+ /* Set the own salt */
+ ret = wc_ecc_ctx_set_own_salt(ctx, saltPtr, saltSz);
+ }
+ catch (Exception e)
+ {
+ log(ERROR_LOG, "ECIES set own salt exception: " + e.ToString());
+ ret = EXCEPTION_E;
+ }
+ finally
+ {
+ /* Cleanup */
+ if (saltPtr != IntPtr.Zero) Marshal.FreeHGlobal(saltPtr);
+ }
+
+ return ret;
+ }
+
+ ///
+ /// Set the KDF salt for the ECIES context.
+ ///
+ /// Pointer to the ECIES context.
+ /// KDF salt as a byte array.
+ /// 0 on success, or a negative error code on failure.
+ public static int EciesSetKdfSalt(IntPtr ctx, byte[] salt)
+ {
+ IntPtr saltPtr = IntPtr.Zero;
+ uint saltSz;
+ int ret;
+
+ try
+ {
+ /* Allocate memory */
+ saltSz = (uint)salt.Length;
+ saltPtr = Marshal.AllocHGlobal(salt.Length);
+ Marshal.Copy(salt, 0, saltPtr, salt.Length);
+
+ /* Set the KDF salt */
+ ret = wc_ecc_ctx_set_kdf_salt(ctx, saltPtr, saltSz);
+ }
+ catch (Exception e)
+ {
+ log(ERROR_LOG, "ECIES set KDF salt exception: " + e.ToString());
+ ret = EXCEPTION_E;
+ }
+ finally
+ {
+ /* Cleanup */
+ if (saltPtr != IntPtr.Zero) Marshal.FreeHGlobal(saltPtr);
+ }
+
+ return ret;
+ }
+
+ ///
+ /// Set the info for the ECIES context.
+ ///
+ /// Pointer to the ECIES context.
+ /// Info as a byte array.
+ /// 0 on success, or a negative error code on failure.
+ public static int EciesSetInfo(IntPtr ctx, byte[] info)
+ {
+ IntPtr infoPtr = IntPtr.Zero;
+ int ret;
+
+ try
+ {
+ /* Allocate memory */
+ infoPtr = Marshal.AllocHGlobal(info.Length);
+ Marshal.Copy(info, 0, infoPtr, info.Length);
+
+ /* Set the info */
+ ret = wc_ecc_ctx_set_info(ctx, infoPtr, info.Length);
+ }
+ catch (Exception e)
+ {
+ log(ERROR_LOG, "ECIES set info exception: " + e.ToString());
+ ret = EXCEPTION_E;
+ }
+ finally
+ {
+ /* Cleanup */
+ if (infoPtr != IntPtr.Zero) Marshal.FreeHGlobal(infoPtr);
+ }
+
+ return ret;
+ }
+
+ ///
+ /// Encrypt a message using ECIES.
+ ///
+ /// Private key.
+ /// Public key.
+ /// Message to encrypt.
+ /// Message size.
+ /// Output buffer.
+ /// ECIES context.
+ /// 0 on success, or a negative error code on failure.
+ public static int EciesEncrypt(IntPtr privKey, IntPtr pubKey, byte[] msg, uint msgSz, byte[] outBuffer, IntPtr ctx)
+ {
+ int ret;
+ int outBufferLength = 0;
+ IntPtr msgPtr = IntPtr.Zero;
+ IntPtr outBufferPtr = IntPtr.Zero;
+ IntPtr outSz = IntPtr.Zero;
+
+ try
+ {
+ /* Allocate memory */
+ msgPtr = Marshal.AllocHGlobal(msg.Length);
+ outBufferPtr = Marshal.AllocHGlobal(outBuffer.Length);
+ outSz = Marshal.AllocHGlobal(sizeof(uint));
+
+ Marshal.WriteInt32(outSz, outBuffer.Length);
+ Marshal.Copy(msg, 0, msgPtr, msg.Length);
+
+ /* Encrypt */
+ ret = wc_ecc_encrypt(privKey, pubKey, msgPtr, msgSz, outBufferPtr, outSz, ctx);
+ if (ret < 0)
+ {
+ log(ERROR_LOG, "Failed to encrypt message using ECIES. Error code: " + ret);
+ }
+ /* Output actual output buffer length */
+ if (ret == 0)
+ {
+ outBufferLength = Marshal.ReadInt32(outSz);
+ if (outBufferLength <= outBuffer.Length)
+ {
+ Marshal.Copy(outBufferPtr, outBuffer, 0, outBufferLength);
+ }
+ else
+ {
+ ret = BUFFER_E;
+ }
+ }
+ }
+ catch (Exception e)
+ {
+ log(ERROR_LOG, "ECIES encryption exception: " + e.ToString());
+ ret = EXCEPTION_E;
+ }
+ finally
+ {
+ /* Cleanup */
+ if (msgPtr != IntPtr.Zero) Marshal.FreeHGlobal(msgPtr);
+ if (outBufferPtr != IntPtr.Zero) Marshal.FreeHGlobal(outBufferPtr);
+ if (outSz != IntPtr.Zero) Marshal.FreeHGlobal(outSz);
+ }
+
+ return ret == 0 ? outBufferLength : ret;
+ }
+
+ ///
+ /// Decrypt a message using ECIES.
+ ///
+ /// Private key.
+ /// Public key.
+ /// Encrypted message.
+ /// Message size.
+ /// Output buffer for the decrypted message.
+ /// ECIES context.
+ /// 0 on success, or a negative error code on failure.
+ public static int EciesDecrypt(IntPtr privKey, IntPtr pubKey, byte[] msg, uint msgSz, byte[] outBuffer, IntPtr ctx)
+ {
+ int ret;
+ int outBufferLength = 0;
+ IntPtr msgPtr = IntPtr.Zero;
+ IntPtr outBufferPtr = IntPtr.Zero;
+ IntPtr outSz = IntPtr.Zero;
+
+ try
+ {
+ /* Allocate memory */
+ msgPtr = Marshal.AllocHGlobal(msg.Length);
+ outBufferPtr = Marshal.AllocHGlobal(outBuffer.Length);
+ outSz = Marshal.AllocHGlobal(sizeof(uint));
+
+ Marshal.WriteInt32(outSz, outBuffer.Length);
+ Marshal.Copy(msg, 0, msgPtr, msg.Length);
+
+ /* Decrypt */
+ ret = wc_ecc_decrypt(privKey, pubKey, msgPtr, msgSz, outBufferPtr, outSz, ctx);
+ if (ret < 0)
+ {
+ log(ERROR_LOG, "Failed to decrypt message using ECIES. Error code: " + ret);
+ }
+ /* Output actual output buffer length */
+ if (ret == 0)
+ {
+ outBufferLength = Marshal.ReadInt32(outSz);
+ if (outBufferLength <= outBuffer.Length)
+ {
+ Marshal.Copy(outBufferPtr, outBuffer, 0, outBufferLength);
+ }
+ else
+ {
+ ret = BUFFER_E;
+ }
+ }
+ }
+ catch (Exception e)
+ {
+ log(ERROR_LOG, "ECIES decryption exception: " + e.ToString());
+ return EXCEPTION_E;
+ }
+ finally
+ {
+ /* Cleanup */
+ if (msgPtr != IntPtr.Zero) Marshal.FreeHGlobal(msgPtr);
+ if (outBufferPtr != IntPtr.Zero) Marshal.FreeHGlobal(outBufferPtr);
+ if (outSz != IntPtr.Zero) Marshal.FreeHGlobal(outSz);
+ }
+
+ return ret == 0 ? outBufferLength : ret;
+ }
+
+ ///
+ /// Free the ECIES context.
+ ///
+ /// Pointer to the ECIES context to free.
+ public static void EciesFreeCtx(IntPtr ctx)
+ {
+ if (ctx != IntPtr.Zero)
+ {
+ wc_ecc_ctx_free(ctx);
+ }
+ }
+
+ /********************************
+ * ENUMS
+ */
+ public enum ecEncAlgo {
+ ecAES_128_CBC = 1, /* default */
+ ecAES_256_CBC = 2,
+ ecAES_128_CTR = 3,
+ ecAES_256_CTR = 4
+ }
+
+ public enum ecKdfAlgo {
+ ecHKDF_SHA256 = 1, /* default */
+ ecHKDF_SHA1 = 2,
+ ecKDF_X963_SHA1 = 3,
+ ecKDF_X963_SHA256 = 4,
+ ecKDF_SHA1 = 5,
+ ecKDF_SHA256 = 6
+ }
+
+ public enum ecMacAlgo {
+ ecHMAC_SHA256 = 1, /* default */
+ ecHMAC_SHA1 = 2
+ }
+
+ public enum ecKeySizea {
+ KEY_SIZE_128 = 16,
+ KEY_SIZE_256 = 32,
+ IV_SIZE_64 = 8,
+ IV_SIZE_128 = 16,
+ ECC_MAX_IV_SIZE = 16,
+ EXCHANGE_SALT_SZ = 16,
+ EXCHANGE_INFO_SZ = 23
+ }
+
+ public enum ecFlags {
+ REQ_RESP_CLIENT = 1,
+ REQ_RESP_SERVER = 2
+ }
+ /* END ECIES */
+
+
/***********************************************************************
* RSA
**********************************************************************/
@@ -2207,7 +2673,6 @@ public static int HashFinal(IntPtr hash, uint hashType, out byte[] output)
try
{
-
/* Get hash size and initialize */
int hashSize = wc_HashGetDigestSize(hashType);
output = new byte[hashSize];
@@ -2277,22 +2742,22 @@ public static int HashFree(IntPtr hash, uint hashType)
///
public enum hashType
{
- WC_HASH_TYPE_NONE = 0,
- WC_HASH_TYPE_MD2 = 1,
- WC_HASH_TYPE_MD4 = 2,
- WC_HASH_TYPE_MD5 = 3,
- WC_HASH_TYPE_SHA = 4, /* SHA-1 (not old SHA-0) */
- WC_HASH_TYPE_SHA224 = 5,
- WC_HASH_TYPE_SHA256 = 6,
- WC_HASH_TYPE_SHA384 = 7,
- WC_HASH_TYPE_SHA512 = 8,
- WC_HASH_TYPE_MD5_SHA = 9,
+ WC_HASH_TYPE_NONE = 0,
+ WC_HASH_TYPE_MD2 = 1,
+ WC_HASH_TYPE_MD4 = 2,
+ WC_HASH_TYPE_MD5 = 3,
+ WC_HASH_TYPE_SHA = 4, /* SHA-1 (not old SHA-0) */
+ WC_HASH_TYPE_SHA224 = 5,
+ WC_HASH_TYPE_SHA256 = 6,
+ WC_HASH_TYPE_SHA384 = 7,
+ WC_HASH_TYPE_SHA512 = 8,
+ WC_HASH_TYPE_MD5_SHA = 9,
WC_HASH_TYPE_SHA3_224 = 10,
WC_HASH_TYPE_SHA3_256 = 11,
WC_HASH_TYPE_SHA3_384 = 12,
WC_HASH_TYPE_SHA3_512 = 13,
- WC_HASH_TYPE_BLAKE2B = 14,
- WC_HASH_TYPE_BLAKE2S = 15,
+ WC_HASH_TYPE_BLAKE2B = 14,
+ WC_HASH_TYPE_BLAKE2S = 15,
}
/* END HASH */