diff --git a/ModernKeePassLib.Test/ModernKeePassLib.Test.csproj b/ModernKeePassLib.Test/ModernKeePassLib.Test.csproj index 3f8c429..702570f 100644 --- a/ModernKeePassLib.Test/ModernKeePassLib.Test.csproj +++ b/ModernKeePassLib.Test/ModernKeePassLib.Test.csproj @@ -8,7 +8,7 @@ Properties ModernKeePassLib.Test ModernKeePassLib.Test - v4.6.2 + v4.5.1 512 {3AC096D0-A1C2-E12C-1390-A8335801FDAB};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} @@ -33,9 +33,8 @@ 4 - - False - ..\packages\Portable.BouncyCastle.1.8.1.1\lib\portable-net4+sl5+wp8+win8+wpa81\crypto.dll + + ..\packages\Portable.BouncyCastle.1.8.1.3\lib\net40\BouncyCastle.Crypto.dll ..\packages\NUnit.3.8.1\lib\net45\nunit.framework.dll diff --git a/ModernKeePassLib.Test/Utility/GfxUtilTests.cs b/ModernKeePassLib.Test/Utility/GfxUtilTests.cs index 9ae1ee1..9977178 100644 --- a/ModernKeePassLib.Test/Utility/GfxUtilTests.cs +++ b/ModernKeePassLib.Test/Utility/GfxUtilTests.cs @@ -21,10 +21,10 @@ namespace ModernKeePassLib.Test.Shared.Utility "QMdny4VogAAAABJRU5ErkJggg=="; [Test ()] - public void TestLoadImage () + public async void TestLoadImage () { var testData = Convert.FromBase64String (testImageData); - var image = GfxUtil.LoadImage (testData); + var image = await GfxUtil.LoadImage (testData); Assert.That (image.Width, Is.EqualTo (16)); Assert.That (image.Height, Is.EqualTo (16)); } diff --git a/ModernKeePassLib.Test/app.config b/ModernKeePassLib.Test/app.config index 042eee6..8f23061 100644 --- a/ModernKeePassLib.Test/app.config +++ b/ModernKeePassLib.Test/app.config @@ -1,23 +1,23 @@ - + - - + + - - + + - - + + - - + + - \ No newline at end of file + diff --git a/ModernKeePassLib/Cryptography/CryptoRandom.cs b/ModernKeePassLib/Cryptography/CryptoRandom.cs index 3eec91a..c3888ab 100644 --- a/ModernKeePassLib/Cryptography/CryptoRandom.cs +++ b/ModernKeePassLib/Cryptography/CryptoRandom.cs @@ -43,6 +43,9 @@ namespace ModernKeePassLib.Cryptography { private byte[] m_pbEntropyPool = new byte[64]; private ulong m_uCounter; +#if !ModernKeePassLib + private RNGCryptoServiceProvider m_rng = new RNGCryptoServiceProvider(); +#endif private ulong m_uGeneratedBytesCount = 0; private static readonly object g_oSyncRoot = new object(); @@ -192,7 +195,7 @@ namespace ModernKeePassLib.Cryptography pb = MemUtil.UInt32ToBytes((uint)Environment.CurrentManagedThreadId); ms.Write(pb, 0, pb.Length); #else - pb = MemUtil.UInt32ToBytes((uint)NativeLib.GetPlatformID()); + pb = MemUtil.UInt32ToBytes((uint)NativeLib.GetPlatformID()); MemUtil.Write(ms, pb); try @@ -308,8 +311,11 @@ namespace ModernKeePassLib.Cryptography private byte[] GetCspData() { byte[] pbCspRandom = new byte[32]; - //m_rng.GetBytes(pbCspRandom); - CryptographicBuffer.CopyToByteArray(CryptographicBuffer.GenerateRandom(32), out pbCspRandom); +#if ModernKeePassLib + CryptographicBuffer.CopyToByteArray(CryptographicBuffer.GenerateRandom(32), out pbCspRandom); +#else + m_rng.GetBytes(pbCspRandom); +#endif return pbCspRandom; } diff --git a/ModernKeePassLib/Cryptography/KeyDerivation/AesKdf.cs b/ModernKeePassLib/Cryptography/KeyDerivation/AesKdf.cs index 100568c..9abf6da 100644 --- a/ModernKeePassLib/Cryptography/KeyDerivation/AesKdf.cs +++ b/ModernKeePassLib/Cryptography/KeyDerivation/AesKdf.cs @@ -117,9 +117,11 @@ namespace ModernKeePassLib.Cryptography.KeyDerivation try { +#if !ModernKeePassLib // Try to use the native library first - /*if(NativeLib.TransformKey256(pbNewKey, pbKeySeed32, uNumRounds)) - return CryptoUtil.HashSha256(pbNewKey);*/ + if(NativeLib.TransformKey256(pbNewKey, pbKeySeed32, uNumRounds)) + return CryptoUtil.HashSha256(pbNewKey); +#endif if(TransformKeyGCrypt(pbNewKey, pbKeySeed32, uNumRounds)) return CryptoUtil.HashSha256(pbNewKey); @@ -135,6 +137,7 @@ namespace ModernKeePassLib.Cryptography.KeyDerivation internal static bool TransformKeyManaged(byte[] pbNewKey32, byte[] pbKeySeed32, ulong uNumRounds) { +#if ModernKeePassLib || KeePassUAP KeyParameter kp = new KeyParameter(pbKeySeed32); AesEngine aes = new AesEngine(); aes.Init(true, kp); @@ -144,6 +147,39 @@ namespace ModernKeePassLib.Cryptography.KeyDerivation aes.ProcessBlock(pbNewKey32, 0, pbNewKey32, 0); aes.ProcessBlock(pbNewKey32, 16, pbNewKey32, 16); } +#else + byte[] pbIV = new byte[16]; + Array.Clear(pbIV, 0, pbIV.Length); + + SymmetricAlgorithm a = CryptoUtil.CreateAes(); + if(a.BlockSize != 128) // AES block size + { + Debug.Assert(false); + a.BlockSize = 128; + } + + a.IV = pbIV; + a.Mode = CipherMode.ECB; + a.KeySize = 256; + a.Key = pbKeySeed32; + ICryptoTransform iCrypt = a.CreateEncryptor(); + + // !iCrypt.CanReuseTransform -- doesn't work with Mono + if((iCrypt == null) || (iCrypt.InputBlockSize != 16) || + (iCrypt.OutputBlockSize != 16)) + { + Debug.Assert(false, "Invalid ICryptoTransform."); + Debug.Assert((iCrypt.InputBlockSize == 16), "Invalid input block size!"); + Debug.Assert((iCrypt.OutputBlockSize == 16), "Invalid output block size!"); + return false; + } + + for(ulong i = 0; i < uNumRounds; ++i) + { + iCrypt.TransformBlock(pbNewKey32, 0, 16, pbNewKey32, 0); + iCrypt.TransformBlock(pbNewKey32, 16, 16, pbNewKey32, 16); + } +#endif return true; } @@ -152,14 +188,14 @@ namespace ModernKeePassLib.Cryptography.KeyDerivation { KdfParameters p = GetDefaultParameters(); ulong uRounds; - +#if !ModernKeePassLib // Try native method - /*if(NativeLib.TransformKeyBenchmark256(uMilliseconds, out uRounds)) + if(NativeLib.TransformKeyBenchmark256(uMilliseconds, out uRounds)) { p.SetUInt64(ParamRounds, uRounds); return p; - }*/ - + } +#endif if(TransformKeyBenchmarkGCrypt(uMilliseconds, out uRounds)) { p.SetUInt64(ParamRounds, uRounds); @@ -173,10 +209,40 @@ namespace ModernKeePassLib.Cryptography.KeyDerivation pbKey[i] = (byte)i; pbNewKey[i] = (byte)i; } - + +#if ModernKeePassLib || KeePassUAP KeyParameter kp = new KeyParameter(pbKey); AesEngine aes = new AesEngine(); aes.Init(true, kp); +#else + byte[] pbIV = new byte[16]; + Array.Clear(pbIV, 0, pbIV.Length); + + SymmetricAlgorithm a = CryptoUtil.CreateAes(); + if(a.BlockSize != 128) // AES block size + { + Debug.Assert(false); + a.BlockSize = 128; + } + + a.IV = pbIV; + a.Mode = CipherMode.ECB; + a.KeySize = 256; + a.Key = pbKey; + ICryptoTransform iCrypt = a.CreateEncryptor(); + + // !iCrypt.CanReuseTransform -- doesn't work with Mono + if((iCrypt == null) || (iCrypt.InputBlockSize != 16) || + (iCrypt.OutputBlockSize != 16)) + { + Debug.Assert(false, "Invalid ICryptoTransform."); + Debug.Assert(iCrypt.InputBlockSize == 16, "Invalid input block size!"); + Debug.Assert(iCrypt.OutputBlockSize == 16, "Invalid output block size!"); + + p.SetUInt64(ParamRounds, PwDefs.DefaultKeyEncryptionRounds); + return p; + } +#endif uRounds = 0; int tStart = Environment.TickCount; @@ -184,8 +250,13 @@ namespace ModernKeePassLib.Cryptography.KeyDerivation { for(ulong j = 0; j < BenchStep; ++j) { +#if ModernKeePassLib || KeePassUAP aes.ProcessBlock(pbNewKey, 0, pbNewKey, 0); aes.ProcessBlock(pbNewKey, 16, pbNewKey, 16); +#else + iCrypt.TransformBlock(pbNewKey, 0, 16, pbNewKey, 0); + iCrypt.TransformBlock(pbNewKey, 16, 16, pbNewKey, 16); +#endif } uRounds += BenchStep; diff --git a/ModernKeePassLib/Cryptography/SelfTest.cs b/ModernKeePassLib/Cryptography/SelfTest.cs index 3c8d842..f5796a8 100644 --- a/ModernKeePassLib/Cryptography/SelfTest.cs +++ b/ModernKeePassLib/Cryptography/SelfTest.cs @@ -105,7 +105,7 @@ namespace ModernKeePassLib.Cryptography HashAlgorithmProvider.OpenAlgorithm(HashAlgorithmNames.Sha256); } #else - try { using(SHA256Managed h = new SHA256Managed()) { } } + try { using(SHA256Managed h = new SHA256Managed()) { } } #endif catch(Exception exSha256) { @@ -715,7 +715,7 @@ namespace ModernKeePassLib.Cryptography throw new SecurityException("HMAC-SHA-256-" + strID + "-R");*/ #else // Original - using(HMACSHA256 h = new HMACSHA256(pbKey)) + using(HMACSHA256 h = new HMACSHA256(pbKey)) { h.TransformBlock(pbMsg, 0, pbMsg.Length, pbMsg, 0); h.TransformFinalBlock(MemUtil.EmptyByteArray, 0, 0); @@ -734,10 +734,10 @@ namespace ModernKeePassLib.Cryptography throw new SecurityException("HMAC-SHA-256-" + strID + "-R"); } #endif - } + } #endif - private static void TestKeyTransform(Random r) + private static void TestKeyTransform(Random r) { #if DEBUG // Up to KeePass 2.34, the OtpKeyProv plugin used the public diff --git a/ModernKeePassLib/Keys/KcpUserAccount.cs b/ModernKeePassLib/Keys/KcpUserAccount.cs index a4c8162..d8e64c3 100644 --- a/ModernKeePassLib/Keys/KcpUserAccount.cs +++ b/ModernKeePassLib/Keys/KcpUserAccount.cs @@ -21,7 +21,7 @@ using System; using System.Diagnostics; using System.IO; using System.Security; - +using Windows.Storage; #if !KeePassUAP using Windows.Security.Cryptography; #endif @@ -98,10 +98,11 @@ namespace ModernKeePassLib.Keys strUserDir = UrlUtil.EnsureTerminatingSeparator(strUserDir, false); strUserDir += PwDefs.ShortProductName; +#if !ModernKeePassLib - if(bCreate && !Directory.Exists(strUserDir)) + if (bCreate && !Directory.Exists(strUserDir)) Directory.CreateDirectory(strUserDir); - +#endif strUserDir = UrlUtil.EnsureTerminatingSeparator(strUserDir, false); return (strUserDir + UserKeyFileName); } @@ -114,9 +115,15 @@ namespace ModernKeePassLib.Keys try { string strFilePath = GetUserKeyFilePath(false); - byte[] pbProtectedKey = File.ReadAllBytes(strFilePath); - - pbKey = ProtectedData.Unprotect(pbProtectedKey, m_pbEntropy, +#if ModernKeePassLib + var fileStream = StorageFile.GetFileFromPathAsync(strFilePath).GetAwaiter().GetResult().OpenStreamForReadAsync().GetAwaiter().GetResult(); + var pbProtectedKey = new byte[(int)fileStream.Length]; + fileStream.Read(pbProtectedKey, 0, (int)fileStream.Length); + fileStream.Dispose(); +#else + byte[] pbProtectedKey = File.ReadAllBytes(strFilePath); +#endif + pbKey = ProtectedData.Unprotect(pbProtectedKey, m_pbEntropy, DataProtectionScope.CurrentUser); } catch(Exception) @@ -126,7 +133,7 @@ namespace ModernKeePassLib.Keys } #endif - return pbKey; + return pbKey; } private static byte[] CreateUserKey() @@ -139,10 +146,15 @@ namespace ModernKeePassLib.Keys byte[] pbRandomKey = CryptoRandom.Instance.GetRandomBytes(64); byte[] pbProtectedKey = ProtectedData.Protect(pbRandomKey, m_pbEntropy, DataProtectionScope.CurrentUser); +#if ModernKeePassLib + var fileStream = StorageFile.GetFileFromPathAsync(strFilePath).GetAwaiter().GetResult().OpenStreamForWriteAsync().GetAwaiter().GetResult(); + fileStream.Write(pbProtectedKey, 0, (int)fileStream.Length); + fileStream.Dispose(); +#else + File.WriteAllBytes(strFilePath, pbProtectedKey); +#endif - File.WriteAllBytes(strFilePath, pbProtectedKey); - - byte[] pbKey = LoadUserKey(true); + byte[] pbKey = LoadUserKey(true); Debug.Assert(MemUtil.ArraysEqual(pbKey, pbRandomKey)); MemUtil.ZeroByteArray(pbRandomKey); diff --git a/ModernKeePassLib/ModernKeePassLib.csproj b/ModernKeePassLib/ModernKeePassLib.csproj index b1fa0d2..2a6fb69 100644 --- a/ModernKeePassLib/ModernKeePassLib.csproj +++ b/ModernKeePassLib/ModernKeePassLib.csproj @@ -31,6 +31,7 @@ DEBUG;ModernKeePassLib prompt 4 + AnyCPU true @@ -126,6 +127,7 @@ + diff --git a/ModernKeePassLib/ModernKeePassLib.nuspec b/ModernKeePassLib/ModernKeePassLib.nuspec index ba47f09..fbe6d49 100644 --- a/ModernKeePassLib/ModernKeePassLib.nuspec +++ b/ModernKeePassLib/ModernKeePassLib.nuspec @@ -2,7 +2,7 @@ ModernKeePassLib - 2.28.5000 + 2.37.1000 ModernKeePassLib Geoffroy Bonneville Geoffroy Bonneville @@ -10,7 +10,7 @@ https://github.com/wismna/ModernKeePass false Portable KeePass Password Management Library that targets .Net Standard and WinRT - Load image in GfxUtil made async to avoid a hang + This version compiles - tests in progress Copyright © 2017 Geoffroy Bonneville KeePass KeePassLib Portable PCL NetStandard diff --git a/ModernKeePassLib/Native/Native.PCL.cs b/ModernKeePassLib/Native/Native.PCL.cs index 878ff26..7d46b61 100644 --- a/ModernKeePassLib/Native/Native.PCL.cs +++ b/ModernKeePassLib/Native/Native.PCL.cs @@ -22,11 +22,39 @@ namespace ModernKeePassLib.Native get { throw new NotImplementedException(); } } - public static int StrCmpNaturally (string s1, string s2) + internal const int GCRY_CIPHER_AES256 = 9; + internal const int GCRY_CIPHER_MODE_ECB = 1; + + public static int StrCmpNaturally (string s1, string s2) { throw new NotImplementedException(); } - } + + internal static void gcry_check_version(IntPtr zero) + { + throw new NotImplementedException(); + } + + public static void gcry_cipher_open(ref IntPtr intPtr, object gcryCipherAes256, object gcryCipherModeEcb, int i) + { + throw new NotImplementedException(); + } + + internal static int gcry_cipher_setkey(IntPtr h, IntPtr pSeed32, IntPtr n32) + { + throw new NotImplementedException(); + } + + internal static void gcry_cipher_close(IntPtr h) + { + throw new NotImplementedException(); + } + + internal static int gcry_cipher_encrypt(IntPtr h, IntPtr pData32, IntPtr n32, IntPtr zero1, IntPtr zero2) + { + throw new NotImplementedException(); + } + } internal enum DataProtectionScope { diff --git a/ModernKeePassLib/Native/NativeLib.cs b/ModernKeePassLib/Native/NativeLib.cs index 866538e..5237f09 100644 --- a/ModernKeePassLib/Native/NativeLib.cs +++ b/ModernKeePassLib/Native/NativeLib.cs @@ -50,6 +50,24 @@ namespace ModernKeePassLib.Native set { m_bAllowNative = value; } } + private static int? g_oiPointerSize = null; + /// + /// Size of a native pointer (in bytes). + /// + public static int PointerSize + { + get + { + if(!g_oiPointerSize.HasValue) +#if KeePassUAP + g_oiPointerSize = Marshal.SizeOf(); +#else + g_oiPointerSize = Marshal.SizeOf(typeof(IntPtr)); +#endif + return g_oiPointerSize.Value; + } + } + private static ulong? m_ouMonoVersion = null; public static ulong MonoVersion { @@ -130,13 +148,13 @@ namespace ModernKeePassLib.Native { if(m_platID.HasValue) return m_platID.Value; -#if KeePassRT - m_platID = PlatformID.Win32NT; +#if KeePassUAP + m_platID = EnvironmentExt.OSVersion.Platform; #else m_platID = Environment.OSVersion.Platform; #endif -#if (!KeePassLibSD && !KeePassRT) +#if (!KeePassLibSD && !KeePassUAP) // Mono returns PlatformID.Unix on Mac OS X, workaround this if(m_platID.Value == PlatformID.Unix) { @@ -149,7 +167,55 @@ namespace ModernKeePassLib.Native return m_platID.Value; } -#if (!KeePassLibSD && !KeePassRT) + private static DesktopType? m_tDesktop = null; + public static DesktopType GetDesktopType() + { + if(!m_tDesktop.HasValue) + { + DesktopType t = DesktopType.None; + if(!IsUnix()) t = DesktopType.Windows; + else + { + try + { + string strXdg = (Environment.GetEnvironmentVariable( + "XDG_CURRENT_DESKTOP") ?? string.Empty).Trim(); + string strGdm = (Environment.GetEnvironmentVariable( + "GDMSESSION") ?? string.Empty).Trim(); + StringComparison sc = StrUtil.CaseIgnoreCmp; + + if(strXdg.Equals("Unity", sc)) + t = DesktopType.Unity; + else if(strXdg.Equals("LXDE", sc)) + t = DesktopType.Lxde; + else if(strXdg.Equals("XFCE", sc)) + t = DesktopType.Xfce; + else if(strXdg.Equals("MATE", sc)) + t = DesktopType.Mate; + else if(strXdg.Equals("X-Cinnamon", sc)) + t = DesktopType.Cinnamon; + else if(strXdg.Equals("Pantheon", sc)) // Elementary OS + t = DesktopType.Pantheon; + else if(strXdg.Equals("KDE", sc) || // Mint 16 + strGdm.Equals("kde-plasma", sc)) // Ubuntu 12.04 + t = DesktopType.Kde; + else if(strXdg.Equals("GNOME", sc)) + { + if(strGdm.Equals("cinnamon", sc)) // Mint 13 + t = DesktopType.Cinnamon; + else t = DesktopType.Gnome; + } + } + catch(Exception) { Debug.Assert(false); } + } + + m_tDesktop = t; + } + + return m_tDesktop.Value; + } + +#if (!KeePassLibSD && !KeePassUAP) public static string RunConsoleApp(string strAppPath, string strParams) { return RunConsoleApp(strAppPath, strParams, null); @@ -192,8 +258,6 @@ namespace ModernKeePassLib.Native if(strStdInput != null) { - // Workaround for Mono Process StdIn BOM bug; - // https://sourceforge.net/p/keepass/bugs/1219/ EnsureNoBom(p.StandardInput); p.StandardInput.Write(strStdInput); @@ -217,7 +281,11 @@ namespace ModernKeePassLib.Native return strOutput; } - catch(Exception) { Debug.Assert(false); } +#if DEBUG + catch(Exception ex) { Debug.Assert(ex is ThreadAbortException); } +#else + catch(Exception) { } +#endif return null; }; @@ -258,7 +326,7 @@ namespace ModernKeePassLib.Native private static void EnsureNoBom(StreamWriter sw) { if(sw == null) { Debug.Assert(false); return; } - if(!NativeLib.IsUnix()) return; + if(!MonoWorkarounds.IsRequired(1219)) return; try { @@ -267,9 +335,24 @@ namespace ModernKeePassLib.Native byte[] pbBom = enc.GetPreamble(); if((pbBom == null) || (pbBom.Length == 0)) return; - FieldInfo fi = typeof(StreamWriter).GetField("preamble_done", + // For Mono >= 4.0 (using Microsoft's reference source) + try + { + FieldInfo fi = typeof(StreamWriter).GetField("haveWrittenPreamble", + BindingFlags.Instance | BindingFlags.NonPublic); + if(fi != null) + { + fi.SetValue(sw, true); + return; + } + } + catch(Exception) { Debug.Assert(false); } + + // For Mono < 4.0 + FieldInfo fiPD = typeof(StreamWriter).GetField("preamble_done", BindingFlags.Instance | BindingFlags.NonPublic); - if(fi != null) fi.SetValue(sw, true); + if(fiPD != null) fiPD.SetValue(sw, true); + else { Debug.Assert(false); } } catch(Exception) { Debug.Assert(false); } } @@ -285,7 +368,10 @@ namespace ModernKeePassLib.Native public static bool TransformKey256(byte[] pBuf256, byte[] pKey256, ulong uRounds) { - if(m_bAllowNative == false) return false; +#if KeePassUAP + return false; +#else + if(!m_bAllowNative) return false; KeyValuePair kvp = PrepareArrays256(pBuf256, pKey256); bool bResult = false; @@ -298,26 +384,31 @@ namespace ModernKeePassLib.Native if(bResult) GetBuffers256(kvp, pBuf256, pKey256); - NativeLib.FreeArrays(kvp); + FreeArrays(kvp); return bResult; +#endif } /// /// Benchmark key transformation. /// - /// Number of seconds to perform the benchmark. + /// Number of milliseconds to perform the benchmark. /// Number of transformations done. /// Returns true, if the benchmark was successful. public static bool TransformKeyBenchmark256(uint uTimeMs, out ulong puRounds) { puRounds = 0; - if(m_bAllowNative == false) return false; +#if KeePassUAP + return false; +#else + if(!m_bAllowNative) return false; try { puRounds = NativeMethods.TransformKeyBenchmark(uTimeMs); } catch(Exception) { return false; } return true; +#endif } private static KeyValuePair PrepareArrays256(byte[] pBuf256, diff --git a/ModernKeePassLib/Native/NativeMethods.Unix.cs b/ModernKeePassLib/Native/NativeMethods.Unix.cs index faa3fc1..3ef7d27 100644 --- a/ModernKeePassLib/Native/NativeMethods.Unix.cs +++ b/ModernKeePassLib/Native/NativeMethods.Unix.cs @@ -29,7 +29,7 @@ namespace ModernKeePassLib.Native { internal static partial class NativeMethods { -#if (!KeePassLibSD && !KeePassRT) +#if (!KeePassLibSD && !KeePassUAP) [StructLayout(LayoutKind.Sequential)] private struct XClassHint { @@ -108,5 +108,106 @@ namespace ModernKeePassLib.Native catch(Exception) { Debug.Assert(false); } } #endif + + // ============================================================= + // LibGCrypt 1.8.1 + + private const string LibGCrypt = "libgcrypt.so.20"; + + internal const int GCRY_CIPHER_AES256 = 9; + internal const int GCRY_CIPHER_MODE_ECB = 1; + + [DllImport(LibGCrypt)] + internal static extern IntPtr gcry_check_version(IntPtr lpReqVersion); + + [DllImport(LibGCrypt)] + internal static extern uint gcry_cipher_open(ref IntPtr ph, int nAlgo, + int nMode, uint uFlags); + + [DllImport(LibGCrypt)] + internal static extern void gcry_cipher_close(IntPtr h); + + [DllImport(LibGCrypt)] + internal static extern uint gcry_cipher_setkey(IntPtr h, IntPtr pbKey, + IntPtr cbKey); // cbKey is size_t + + [DllImport(LibGCrypt)] + internal static extern uint gcry_cipher_encrypt(IntPtr h, IntPtr pbOut, + IntPtr cbOut, IntPtr pbIn, IntPtr cbIn); // cb* are size_t + + /* internal static IntPtr Utf8ZFromString(string str) + { + byte[] pb = StrUtil.Utf8.GetBytes(str ?? string.Empty); + + IntPtr p = Marshal.AllocCoTaskMem(pb.Length + 1); + if(p != IntPtr.Zero) + { + Marshal.Copy(pb, 0, p, pb.Length); + Marshal.WriteByte(p, pb.Length, 0); + } + else { Debug.Assert(false); } + + return p; + } + + internal static string Utf8ZToString(IntPtr p) + { + if(p == IntPtr.Zero) { Debug.Assert(false); return null; } + + List l = new List(); + for(int i = 0; i < int.MaxValue; ++i) + { + byte bt = Marshal.ReadByte(p, i); + if(bt == 0) break; + + l.Add(bt); + } + + return StrUtil.Utf8.GetString(l.ToArray()); + } + + internal static void Utf8ZFree(IntPtr p) + { + if(p != IntPtr.Zero) Marshal.FreeCoTaskMem(p); + } */ + + /* // ============================================================= + // LibGLib 2 + + private const string LibGLib = "libglib-2.0.so.0"; + + internal const int G_FALSE = 0; + + // https://developer.gnome.org/glib/stable/glib-Memory-Allocation.html + [DllImport(LibGLib)] + internal static extern void g_free(IntPtr pMem); // pMem may be null + + // ============================================================= + // LibGTK 3 (3.22.11 / 3.22.24) + + private const string LibGtk = "libgtk-3.so.0"; + + internal static readonly IntPtr GDK_SELECTION_PRIMARY = new IntPtr(1); + internal static readonly IntPtr GDK_SELECTION_CLIPBOARD = new IntPtr(69); + + [DllImport(LibGtk)] + internal static extern int gtk_init_check(IntPtr pArgc, IntPtr pArgv); + + [DllImport(LibGtk)] + // The returned handle is owned by GTK and must not be freed + internal static extern IntPtr gtk_clipboard_get(IntPtr pSelection); + + [DllImport(LibGtk)] + internal static extern void gtk_clipboard_clear(IntPtr hClipboard); + + [DllImport(LibGtk)] + internal static extern IntPtr gtk_clipboard_wait_for_text(IntPtr hClipboard); + + [DllImport(LibGtk)] + internal static extern void gtk_clipboard_set_text(IntPtr hClipboard, + IntPtr lpText, int cbLen); + + [DllImport(LibGtk)] + internal static extern void gtk_clipboard_store(IntPtr hClipboard); */ } } diff --git a/ModernKeePassLib/Native/NativeMethods.cs b/ModernKeePassLib/Native/NativeMethods.cs index 9ce13fe..4edf73b 100644 --- a/ModernKeePassLib/Native/NativeMethods.cs +++ b/ModernKeePassLib/Native/NativeMethods.cs @@ -73,6 +73,7 @@ namespace ModernKeePassLib.Native return TransformKeyTimed32(pBuf256, pKey256, ref puRounds, uSeconds); } */ +#if !KeePassUAP [DllImport("KeePassLibC32.dll", EntryPoint = "TransformKey256")] [return: MarshalAs(UnmanagedType.Bool)] private static extern bool TransformKey32(IntPtr pBuf256, @@ -86,7 +87,7 @@ namespace ModernKeePassLib.Native internal static bool TransformKey(IntPtr pBuf256, IntPtr pKey256, UInt64 uRounds) { - if(Marshal.SizeOf(typeof(IntPtr)) == 8) + if(NativeLib.PointerSize == 8) return TransformKey64(pBuf256, pKey256, uRounds); else return TransformKey32(pBuf256, pKey256, uRounds); @@ -100,10 +101,11 @@ namespace ModernKeePassLib.Native internal static UInt64 TransformKeyBenchmark(UInt32 uTimeMs) { - if(Marshal.SizeOf(typeof(IntPtr)) == 8) + if(NativeLib.PointerSize == 8) return TransformKeyBenchmark64(uTimeMs); return TransformKeyBenchmark32(uTimeMs); } +#endif /* [DllImport("KeePassLibC32.dll", EntryPoint = "TF_ShowLangBar")] [return: MarshalAs(UnmanagedType.Bool)] @@ -120,63 +122,66 @@ namespace ModernKeePassLib.Native return TF_ShowLangBar32(dwFlags); } */ -#if (!KeePassLibSD && !KeePassRT) - [DllImport("ShlWApi.dll", CharSet = CharSet.Unicode, ExactSpelling = true)] - internal static extern int StrCmpLogicalW(string x, string y); - +#if (!KeePassLibSD && !KeePassUAP) [DllImport("ShlWApi.dll", CharSet = CharSet.Auto)] [return: MarshalAs(UnmanagedType.Bool)] internal static extern bool PathRelativePathTo([Out] StringBuilder pszPath, - [In] string pszFrom, [In] uint dwAttrFrom, [In] string pszTo, - [In] uint dwAttrTo); -#endif + [In] string pszFrom, uint dwAttrFrom, [In] string pszTo, uint dwAttrTo); - private static bool? m_bSupportsLogicalCmp = null; + [DllImport("ShlWApi.dll", CharSet = CharSet.Unicode, ExactSpelling = true)] + private static extern int StrCmpLogicalW(string x, string y); + + private static bool? m_obSupportsLogicalCmp = null; private static void TestNaturalComparisonsSupport() { -#if (KeePassLibSD || KeePassRT) -#warning No native natural comparisons supported. - m_bSupportsLogicalCmp = false; -#else try { StrCmpLogicalW("0", "0"); // Throws exception if unsupported - m_bSupportsLogicalCmp = true; + m_obSupportsLogicalCmp = true; } - catch(Exception) { m_bSupportsLogicalCmp = false; } -#endif + catch(Exception) { m_obSupportsLogicalCmp = false; } } +#endif internal static bool SupportsStrCmpNaturally { get { - if(m_bSupportsLogicalCmp.HasValue == false) +#if (!KeePassLibSD && !KeePassUAP) + if(!m_obSupportsLogicalCmp.HasValue) TestNaturalComparisonsSupport(); - return m_bSupportsLogicalCmp.Value; + return m_obSupportsLogicalCmp.Value; +#else + return false; +#endif } } internal static int StrCmpNaturally(string x, string y) { - if(m_bSupportsLogicalCmp.HasValue == false) TestNaturalComparisonsSupport(); - if(m_bSupportsLogicalCmp.Value == false) return 0; +#if (!KeePassLibSD && !KeePassUAP) + if(!NativeMethods.SupportsStrCmpNaturally) + { + Debug.Assert(false); + return string.Compare(x, y, true); + } -#if (KeePassLibSD || KeePassRT) -#warning No native natural comparisons supported. - return x.CompareTo(y); -#else return StrCmpLogicalW(x, y); +#else + Debug.Assert(false); + return string.Compare(x, y, true); #endif } internal static string GetUserRuntimeDir() { -#if !KeePassLibSD -#if KeePassRT - string strRtDir = Windows.Storage.ApplicationData.Current.LocalFolder.Path; +#if KeePassLibSD + return Path.GetTempPath(); +#else +#if KeePassUAP + string strRtDir = EnvironmentExt.AppDataLocalFolderPath; #else string strRtDir = Environment.GetEnvironmentVariable("XDG_RUNTIME_DIR"); if(string.IsNullOrEmpty(strRtDir)) @@ -192,8 +197,6 @@ namespace ModernKeePassLib.Native strRtDir += PwDefs.ShortProductName; return strRtDir; -#else - return Path.GetTempPath(); #endif } } diff --git a/ModernKeePassLib/Properties/AssemblyInfo.cs b/ModernKeePassLib/Properties/AssemblyInfo.cs index 0b99c20..3e24996 100644 --- a/ModernKeePassLib/Properties/AssemblyInfo.cs +++ b/ModernKeePassLib/Properties/AssemblyInfo.cs @@ -40,5 +40,5 @@ using System.Runtime.InteropServices; #endif // Assembly version information -[assembly: AssemblyVersion("2.28.1.4000")] -[assembly: AssemblyFileVersion("2.28.1.4000")] +[assembly: AssemblyVersion("2.37.0.1000")] +[assembly: AssemblyFileVersion("2.37.0.1000")] diff --git a/ModernKeePassLib/Utility/MonoWorkaround.PCL.cs b/ModernKeePassLib/Utility/MonoWorkaround.PCL.cs new file mode 100644 index 0000000..60abb33 --- /dev/null +++ b/ModernKeePassLib/Utility/MonoWorkaround.PCL.cs @@ -0,0 +1,10 @@ +namespace ModernKeePassLib.Utility +{ + public static class MonoWorkarounds + { + public static bool IsRequired(int i) + { + throw new System.NotImplementedException(); + } + } +}