From db0b0e28d259cc3bae4597eda543bfef4d1585c2 Mon Sep 17 00:00:00 2001 From: David Garske Date: Thu, 22 May 2025 16:34:54 -0700 Subject: [PATCH 1/2] Fix issue with CSharp and Windows CE with conversion of ASCII->Unicode and Unicode->ASCII with odd length and extra null terminator. --- wrapper/CSharp/wolfSSL_CSharp/wolfSSL.cs | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/wrapper/CSharp/wolfSSL_CSharp/wolfSSL.cs b/wrapper/CSharp/wolfSSL_CSharp/wolfSSL.cs index 0153b8ab0..624c1910e 100644 --- a/wrapper/CSharp/wolfSSL_CSharp/wolfSSL.cs +++ b/wrapper/CSharp/wolfSSL_CSharp/wolfSSL.cs @@ -51,7 +51,9 @@ namespace wolfSSL.CSharp /* Convert Unicode to Bytes */ byte[] bytes = Encoding.Unicode.GetBytes((string)msg.ToString()); /* Convert to ASCII */ - return Encoding.ASCII.GetString(bytes, 0, bytes.Length); + string ret = Encoding.ASCII.GetString(bytes, 0, bytes.Length); + /* odd length unicode might have extra null terminator, so remove */ + return ret.Replace("\0", ""); } /// @@ -61,14 +63,20 @@ namespace wolfSSL.CSharp { if (msg == null) return null; - /* Convert ASCII to Bytes */ - byte[] bytes = Encoding.ASCII.GetBytes((string)msg.ToString()); + /* Get length and round up to even unicode */ + int msgLen = msg.Length; + msgLen = ((msgLen + 1) & ~1); + byte[] bytes = new byte[msgLen]; + /* Convert Ascii to Bytes */ + byte[] msgBytes = Encoding.ASCII.GetBytes((string)msg.ToString()); + msgBytes.CopyTo(bytes, 0); /* Convert to Unicode */ return Encoding.Unicode.GetString(bytes, 0, bytes.Length); } /// - /// WinCE version of Marshal for Unicode or Multi-byte pointer to ASCII string + /// WinCE version of Marshal for Unicode or Multi-byte pointer to + /// ASCII string /// public static string PtrToStringAnsi(IntPtr ptr) { From 18aab1a8831b5f70a2f682ebdabefaae93c713c8 Mon Sep 17 00:00:00 2001 From: David Garske Date: Wed, 28 May 2025 15:35:10 -0700 Subject: [PATCH 2/2] Further improvements to MultiByte and WideChar conversions. --- wrapper/CSharp/wolfSSL_CSharp/wolfSSL.cs | 66 +++++++++++------------- 1 file changed, 30 insertions(+), 36 deletions(-) diff --git a/wrapper/CSharp/wolfSSL_CSharp/wolfSSL.cs b/wrapper/CSharp/wolfSSL_CSharp/wolfSSL.cs index 624c1910e..bee90c481 100644 --- a/wrapper/CSharp/wolfSSL_CSharp/wolfSSL.cs +++ b/wrapper/CSharp/wolfSSL_CSharp/wolfSSL.cs @@ -42,41 +42,43 @@ namespace wolfSSL.CSharp */ #if WindowsCE /// - /// Convert unicode string to ASCII + /// Convert MBCS (8-bit single/multi byte) to Wide Char/Unicode (16-bit) character set /// - public static string UnicodeToAscii(string msg) + public static string MultiByteToWideChar(string msg) { if (msg == null) return null; - /* Convert Unicode to Bytes */ + /* Convert to Byte Array */ byte[] bytes = Encoding.Unicode.GetBytes((string)msg.ToString()); - /* Convert to ASCII */ + /* Convert to String */ string ret = Encoding.ASCII.GetString(bytes, 0, bytes.Length); - /* odd length unicode might have extra null terminator, so remove */ - return ret.Replace("\0", ""); + /* Remove possible extra null terminator */ + int len = 0; + while (len < ret.Length && ret[len] != 0) len++; + return ret.Substring(0, len); } /// - /// Convert string to Unicode + /// Convert Unicode/Wide Char (16-bit) to MBCS (8-bit single/multi byte) character set /// - public static string AsciiToUnicode(string msg) + public static string WideCharToMultiByte(string msg) { if (msg == null) return null; - /* Get length and round up to even unicode */ + /* Get length and round up to even for multibyte / unicode */ int msgLen = msg.Length; msgLen = ((msgLen + 1) & ~1); byte[] bytes = new byte[msgLen]; - /* Convert Ascii to Bytes */ + /* Convert to Byte Array */ byte[] msgBytes = Encoding.ASCII.GetBytes((string)msg.ToString()); msgBytes.CopyTo(bytes, 0); - /* Convert to Unicode */ + /* Convert to String */ return Encoding.Unicode.GetString(bytes, 0, bytes.Length); } /// - /// WinCE version of Marshal for Unicode or Multi-byte pointer to - /// ASCII string + /// WinCE version of Marshal for Multi-byte pointer to ASCII string + /// Similar conversion used in MultiByteToWideChar, but input is IntPtr /// public static string PtrToStringAnsi(IntPtr ptr) { @@ -570,7 +572,7 @@ namespace wolfSSL.CSharp */ #if WindowsCE [DllImport(wolfssl_dll)] - private extern static IntPtr wolfSSL_ERR_error_string(uint err, StringBuilder errOut); + private extern static IntPtr wolfSSL_ERR_reason_error_string(uint err); [DllImport(wolfssl_dll)] private extern static int wolfSSL_get_error(IntPtr ssl, int err); public delegate void loggingCb(int lvl, string msg); @@ -582,7 +584,7 @@ namespace wolfSSL.CSharp private extern static int wolfSSL_SetLoggingCb(loggingCb vc); #else [DllImport(wolfssl_dll, CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Ansi)] - private extern static IntPtr wolfSSL_ERR_error_string(uint err, StringBuilder errOut); + private extern static IntPtr wolfSSL_ERR_reason_error_string(uint err); [DllImport(wolfssl_dll, CallingConvention = CallingConvention.Cdecl)] private extern static int wolfSSL_get_error(IntPtr ssl, int err); [UnmanagedFunctionPointer(CallingConvention.Cdecl)] @@ -1579,7 +1581,7 @@ namespace wolfSSL.CSharp } #if WindowsCE - return wolfSSL_CTX_use_psk_identity_hint(local_ctx, wolfssl.AsciiToUnicode(hint)); + return wolfSSL_CTX_use_psk_identity_hint(local_ctx, wolfssl.WideCharToMultiByte(hint)); #else return wolfSSL_CTX_use_psk_identity_hint(local_ctx, hint); #endif @@ -1870,7 +1872,7 @@ namespace wolfSSL.CSharp return null; #if WindowsCE - return wolfssl.UnicodeToAscii(ciphers); + return wolfssl.MultiByteToWideChar(ciphers); #else return ciphers.ToString(); #endif @@ -2141,7 +2143,7 @@ namespace wolfSSL.CSharp } #if WindowsCE - return wolfSSL_CTX_set_cipher_list(local_ctx, wolfssl.AsciiToUnicode(list)); + return wolfSSL_CTX_set_cipher_list(local_ctx, wolfssl.WideCharToMultiByte(list)); #else return wolfSSL_CTX_set_cipher_list(local_ctx, list); #endif @@ -2176,7 +2178,7 @@ namespace wolfSSL.CSharp } #if WindowsCE - return wolfSSL_set_cipher_list(sslCtx, wolfssl.AsciiToUnicode(list)); + return wolfSSL_set_cipher_list(sslCtx, wolfssl.WideCharToMultiByte(list)); #else return wolfSSL_set_cipher_list(sslCtx, list); #endif @@ -2235,10 +2237,6 @@ namespace wolfSSL.CSharp try { - int err; - StringBuilder err_name; - StringBuilder ret; - IntPtr sslCtx = unwrap_ssl(ssl); if (sslCtx == IntPtr.Zero) { @@ -2246,14 +2244,10 @@ namespace wolfSSL.CSharp return null; } - /* wolfSSL max error length is 80 */ - ret = new StringBuilder(' ', 100); - err = wolfSSL_get_error(sslCtx, 0); - err_name = new StringBuilder(new String(' ', 80)); - wolfSSL_ERR_error_string((uint)err, err_name); - ret.Append("Error " + err + " " + err_name.ToString()); - - return ret.ToString(); + int err = wolfSSL_get_error(sslCtx, 0); + IntPtr err_ptr = wolfSSL_ERR_reason_error_string((uint)err); + string err_str = wolfssl.PtrToStringAnsi(err_ptr); + return "Error " + err + " " + err_str; } catch (Exception e) { @@ -2282,7 +2276,7 @@ namespace wolfSSL.CSharp } #if WindowsCE - return wolfSSL_CTX_use_certificate_file(local_ctx, wolfssl.AsciiToUnicode(fileCert), type); + return wolfSSL_CTX_use_certificate_file(local_ctx, wolfssl.WideCharToMultiByte(fileCert), type); #else return wolfSSL_CTX_use_certificate_file(local_ctx, fileCert, type); #endif @@ -2314,7 +2308,7 @@ namespace wolfSSL.CSharp } #if WindowsCE - return wolfSSL_CTX_load_verify_locations(local_ctx, wolfssl.AsciiToUnicode(fileCert), wolfssl.AsciiToUnicode(path)); + return wolfSSL_CTX_load_verify_locations(local_ctx, wolfssl.WideCharToMultiByte(fileCert), wolfssl.WideCharToMultiByte(path)); #else return wolfSSL_CTX_load_verify_locations(local_ctx, fileCert, path); #endif @@ -2345,7 +2339,7 @@ namespace wolfSSL.CSharp } #if WindowsCE - return wolfSSL_CTX_use_PrivateKey_file(local_ctx, wolfssl.AsciiToUnicode(fileKey), type); + return wolfSSL_CTX_use_PrivateKey_file(local_ctx, wolfssl.WideCharToMultiByte(fileKey), type); #else return wolfSSL_CTX_use_PrivateKey_file(local_ctx, fileKey, type); #endif @@ -2381,7 +2375,7 @@ namespace wolfSSL.CSharp } #if WindowsCE - return wolfSSL_SetTmpDH_file(sslCtx, wolfssl.AsciiToUnicode(dhparam), file_type); + return wolfSSL_SetTmpDH_file(sslCtx, wolfssl.WideCharToMultiByte(dhparam), file_type); #else return wolfSSL_SetTmpDH_file(sslCtx, dhparam, file_type); #endif @@ -2416,7 +2410,7 @@ namespace wolfSSL.CSharp } #if WindowsCE - return wolfSSL_CTX_SetTmpDH_file(local_ctx, wolfssl.AsciiToUnicode(dhparam), file_type); + return wolfSSL_CTX_SetTmpDH_file(local_ctx, wolfssl.WideCharToMultiByte(dhparam), file_type); #else return wolfSSL_CTX_SetTmpDH_file(local_ctx, dhparam, file_type); #endif