ModernKeePassLib custom PCL version

This commit is contained in:
2017-09-22 15:40:24 +02:00
parent baba70e56d
commit a43bc20eb3
98 changed files with 6049 additions and 3038 deletions

View File

@@ -1,6 +1,6 @@
/*
KeePass Password Safe - The Open-Source Password Manager
Copyright (C) 2003-2012 Dominik Reichl <dominik.reichl@t-online.de>
Copyright (C) 2003-2014 Dominik Reichl <dominik.reichl@t-online.de>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -20,33 +20,38 @@
using System;
using System.Collections.Generic;
using System.Security;
using Windows.Security.Cryptography.Core;
#if PCL
using Windows.Security.Cryptography;
#else
using System.Security.Cryptography;
#endif
using System.Text;
using System.Globalization;
using System.Diagnostics;
using ModernKeePassLib.Cryptography.Cipher;
using ModernKeePassLib.Keys;
using ModernKeePassLib.Utility;
using ModernKeePassLib.Resources;
using Windows.Storage.Streams;
using Windows.Security.Cryptography;
using ModernKeePassLib.Security;
namespace ModernKeePassLib.Cryptography
{
/* #pragma warning disable 1591
/// <summary>
/// Return values of the <c>SelfTest.Perform</c> method.
/// </summary>
public enum SelfTestResult
{
Success = 0,
RijndaelEcbError = 1,
Salsa20Error = 2,
NativeKeyTransformationError = 3
}
#pragma warning restore 1591 */
/* /// <summary>
/// Return values of the <c>SelfTest.Perform</c> method.
/// </summary>
public enum SelfTestResult
{
Success = 0,
RijndaelEcbError = 1,
Salsa20Error = 2,
NativeKeyTransformationError = 3
} */
/// <summary>
/// Class containing self-test methods.
/// </summary>
public static class SelfTest
/// <summary>
/// Class containing self-test methods.
/// </summary>
public static class SelfTest
{
/// <summary>
/// Perform a self-test.
@@ -57,8 +62,10 @@ namespace ModernKeePassLib.Cryptography
TestRijndael();
TestSalsa20();
#if !PCL
TestNativeKeyTransform();
#endif
TestHmacOtp();
@@ -74,7 +81,7 @@ namespace ModernKeePassLib.Cryptography
internal static void TestFipsComplianceProblems()
{
#if !KeePassWinRT
#if !PCL && !KeePassRT
try { new RijndaelManaged(); }
catch(Exception exAes)
{
@@ -91,7 +98,7 @@ namespace ModernKeePassLib.Cryptography
private static void TestRijndael()
{
#if !PCL && !KeePassRT
// Test vector (official ECB test vector #356)
byte[] pbIV = new byte[16];
byte[] pbTestKey = new byte[32];
@@ -106,24 +113,6 @@ namespace ModernKeePassLib.Cryptography
for(i = 0; i < 16; ++i) pbTestData[i] = 0;
pbTestData[0] = 0x04;
String strAlgName = "AES_ECB"; // Algorithm name
IBuffer iv = null; // no IV used in ECB.
IBuffer buffMsg = CryptographicBuffer.CreateFromByteArray(pbTestData);
IBuffer keyMaterial = CryptographicBuffer.CreateFromByteArray(pbTestKey);
SymmetricKeyAlgorithmProvider objAlg = SymmetricKeyAlgorithmProvider.OpenAlgorithm(strAlgName);
CryptographicKey key = objAlg.CreateSymmetricKey(keyMaterial);
// Encrypt the data and return.
IBuffer buffEncrypt = CryptographicEngine.Encrypt(key, buffMsg, iv);
CryptographicBuffer.CopyToByteArray(buffEncrypt, out pbTestData);
if (!MemUtil.ArraysEqual(pbTestData, pbReferenceCT))
throw new SecurityException(KLRes.EncAlgorithmAes + ".");
#if false
RijndaelManaged r = new RijndaelManaged();
if(r.BlockSize != 128) // AES block size
@@ -142,7 +131,6 @@ namespace ModernKeePassLib.Cryptography
if(!MemUtil.ArraysEqual(pbTestData, pbReferenceCT))
throw new SecurityException(KLRes.EncAlgorithmAes + ".");
#endif
}
@@ -166,7 +154,7 @@ namespace ModernKeePassLib.Cryptography
Salsa20Cipher c = new Salsa20Cipher(pbKey, pbIV);
c.Encrypt(pb, pb.Length, false);
if(!MemUtil.ArraysEqual(pb, pbExpected))
throw new SecurityException("Salsa20.");
throw new SecurityException("Salsa20-1");
#if DEBUG
// Extended test in debug mode
@@ -183,13 +171,24 @@ namespace ModernKeePassLib.Cryptography
int nPos = Salsa20ToPos(c, r, pb.Length, 65536);
c.Encrypt(pb, pb.Length, false);
if(!MemUtil.ArraysEqual(pb, pbExpected2))
throw new SecurityException("Salsa20-2.");
throw new SecurityException("Salsa20-2");
nPos = Salsa20ToPos(c, r, nPos + pb.Length, 131008);
Array.Clear(pb, 0, pb.Length);
c.Encrypt(pb, pb.Length, true);
if(!MemUtil.ArraysEqual(pb, pbExpected3))
throw new SecurityException("Salsa20-3.");
throw new SecurityException("Salsa20-3");
Dictionary<string, bool> d = new Dictionary<string, bool>();
const int nRounds = 100;
for(int i = 0; i < nRounds; ++i)
{
byte[] z = new byte[32];
c = new Salsa20Cipher(z, BitConverter.GetBytes((long)i));
c.Encrypt(z, z.Length, true);
d[MemUtil.ByteArrayToHexString(z)] = true;
}
if(d.Count != nRounds) throw new SecurityException("Salsa20-4");
#endif
}
@@ -211,9 +210,10 @@ namespace ModernKeePassLib.Cryptography
}
#endif
#if !PCL
private static void TestNativeKeyTransform()
{
#if DEBUG && TODO
#if DEBUG
byte[] pbOrgKey = CryptoRandom.Instance.GetRandomBytes(32);
byte[] pbSeed = CryptoRandom.Instance.GetRandomBytes(32);
ulong uRounds = (ulong)((new Random()).Next(1, 0x3FFF));
@@ -232,11 +232,12 @@ namespace ModernKeePassLib.Cryptography
throw new SecurityException("Native transform.");
#endif
}
#endif
private static void TestMemUtil()
{
#if DEBUG && !KeePassWinRT
Random r = new Random();
{
#if DEBUG
Random r = new Random();
byte[] pb = CryptoRandom.Instance.GetRandomBytes((uint)r.Next(
0, 0x2FFFF));
@@ -244,35 +245,64 @@ namespace ModernKeePassLib.Cryptography
if(!MemUtil.ArraysEqual(MemUtil.Decompress(pbCompressed), pb))
throw new InvalidOperationException("GZip");
pb = Encoding.ASCII.GetBytes("012345678901234567890a");
byte[] pbN = Encoding.ASCII.GetBytes("9012");
Encoding enc = StrUtil.Utf8;
pb = enc.GetBytes("012345678901234567890a");
byte[] pbN = enc.GetBytes("9012");
if(MemUtil.IndexOf<byte>(pb, pbN) != 9)
throw new InvalidOperationException("MemUtil-1");
pbN = Encoding.ASCII.GetBytes("01234567890123");
pbN = enc.GetBytes("01234567890123");
if(MemUtil.IndexOf<byte>(pb, pbN) != 0)
throw new InvalidOperationException("MemUtil-2");
pbN = Encoding.ASCII.GetBytes("a");
pbN = enc.GetBytes("a");
if(MemUtil.IndexOf<byte>(pb, pbN) != 21)
throw new InvalidOperationException("MemUtil-3");
pbN = Encoding.ASCII.GetBytes("0a");
pbN = enc.GetBytes("0a");
if(MemUtil.IndexOf<byte>(pb, pbN) != 20)
throw new InvalidOperationException("MemUtil-4");
pbN = Encoding.ASCII.GetBytes("1");
pbN = enc.GetBytes("1");
if(MemUtil.IndexOf<byte>(pb, pbN) != 1)
throw new InvalidOperationException("MemUtil-5");
pbN = Encoding.ASCII.GetBytes("b");
pbN = enc.GetBytes("b");
if(MemUtil.IndexOf<byte>(pb, pbN) >= 0)
throw new InvalidOperationException("MemUtil-6");
pbN = Encoding.ASCII.GetBytes("012b");
pbN = enc.GetBytes("012b");
if(MemUtil.IndexOf<byte>(pb, pbN) >= 0)
throw new InvalidOperationException("MemUtil-7");
byte[] pbRes = MemUtil.ParseBase32("MY======");
byte[] pbExp = Encoding.UTF8.GetBytes("f");
if(!MemUtil.ArraysEqual(pbRes, pbExp)) throw new Exception("Base32-1");
pbRes = MemUtil.ParseBase32("MZXQ====");
pbExp = Encoding.UTF8.GetBytes("fo");
if(!MemUtil.ArraysEqual(pbRes, pbExp)) throw new Exception("Base32-2");
pbRes = MemUtil.ParseBase32("MZXW6===");
pbExp = Encoding.UTF8.GetBytes("foo");
if(!MemUtil.ArraysEqual(pbRes, pbExp)) throw new Exception("Base32-3");
pbRes = MemUtil.ParseBase32("MZXW6YQ=");
pbExp = Encoding.UTF8.GetBytes("foob");
if(!MemUtil.ArraysEqual(pbRes, pbExp)) throw new Exception("Base32-4");
pbRes = MemUtil.ParseBase32("MZXW6YTB");
pbExp = Encoding.UTF8.GetBytes("fooba");
if(!MemUtil.ArraysEqual(pbRes, pbExp)) throw new Exception("Base32-5");
pbRes = MemUtil.ParseBase32("MZXW6YTBOI======");
pbExp = Encoding.UTF8.GetBytes("foobar");
if(!MemUtil.ArraysEqual(pbRes, pbExp)) throw new Exception("Base32-6");
pbRes = MemUtil.ParseBase32("JNSXSIDQOJXXM2LEMVZCAYTBONSWIIDPNYQG63TFFV2GS3LFEBYGC43TO5XXEZDTFY======");
pbExp = Encoding.UTF8.GetBytes("Key provider based on one-time passwords.");
if(!MemUtil.ArraysEqual(pbRes, pbExp)) throw new Exception("Base32-7");
#endif
}
private static void TestHmacOtp()
{
#if (DEBUG && !KeePassLibSD && TODO)
byte[] pbSecret = Encoding.ASCII.GetBytes("12345678901234567890");
#if (DEBUG && !KeePassLibSD && !KeePassRT)
byte[] pbSecret = StrUtil.Utf8.GetBytes("12345678901234567890");
string[] vExp = new string[]{ "755224", "287082", "359152",
"969429", "338314", "254676", "287922", "162583", "399871",
"520489" };
@@ -287,10 +317,10 @@ namespace ModernKeePassLib.Cryptography
private static void TestProtectedObjects()
{
#if TODO
#if DEBUG
byte[] pbData = Encoding.UTF8.GetBytes("Test Test Test Test");
Encoding enc = StrUtil.Utf8;
byte[] pbData = enc.GetBytes("Test Test Test Test");
ProtectedBinary pb = new ProtectedBinary(true, pbData);
if(!pb.IsProtected) throw new SecurityException("ProtectedBinary-1");
@@ -299,8 +329,8 @@ namespace ModernKeePassLib.Cryptography
throw new SecurityException("ProtectedBinary-2");
if(!pb.IsProtected) throw new SecurityException("ProtectedBinary-3");
byte[] pbData2 = Encoding.UTF8.GetBytes("Test Test Test Test");
byte[] pbData3 = Encoding.UTF8.GetBytes("Test Test Test Test Test");
byte[] pbData2 = enc.GetBytes("Test Test Test Test");
byte[] pbData3 = enc.GetBytes("Test Test Test Test Test");
ProtectedBinary pb2 = new ProtectedBinary(true, pbData2);
ProtectedBinary pb3 = new ProtectedBinary(true, pbData3);
if(!pb.Equals(pb2)) throw new SecurityException("ProtectedBinary-4");
@@ -323,8 +353,7 @@ namespace ModernKeePassLib.Cryptography
throw new SecurityException("ProtectedString-3");
ps = new ProtectedString(true, "Test");
ProtectedString ps2 = new ProtectedString(true,
StrUtil.Utf8.GetBytes("Test"));
ProtectedString ps2 = new ProtectedString(true, enc.GetBytes("Test"));
if(ps.IsEmpty) throw new SecurityException("ProtectedString-4");
pbData = ps.ReadUtf8();
pbData2 = ps2.ReadUtf8();
@@ -340,7 +369,41 @@ namespace ModernKeePassLib.Cryptography
throw new SecurityException("ProtectedString-8");
if(!ps.IsProtected) throw new SecurityException("ProtectedString-9");
if(!ps2.IsProtected) throw new SecurityException("ProtectedString-10");
#endif
Random r = new Random();
string str = string.Empty;
ps = new ProtectedString();
for(int i = 0; i < 100; ++i)
{
bool bProt = ((r.Next() % 4) != 0);
ps = ps.WithProtection(bProt);
int x = r.Next(str.Length + 1);
int c = r.Next(20);
char ch = (char)r.Next(1, 256);
string strIns = new string(ch, c);
str = str.Insert(x, strIns);
ps = ps.Insert(x, strIns);
if(ps.IsProtected != bProt)
throw new SecurityException("ProtectedString-11");
if(ps.ReadString() != str)
throw new SecurityException("ProtectedString-12");
ps = ps.WithProtection(bProt);
x = r.Next(str.Length);
c = r.Next(str.Length - x + 1);
str = str.Remove(x, c);
ps = ps.Remove(x, c);
if(ps.IsProtected != bProt)
throw new SecurityException("ProtectedString-13");
if(ps.ReadString() != str)
throw new SecurityException("ProtectedString-14");
}
#endif
}
@@ -381,16 +444,64 @@ namespace ModernKeePassLib.Cryptography
throw new InvalidOperationException("StrUtil-V3");
if(StrUtil.VersionToString(0x00FF000000000000UL) != "255")
throw new InvalidOperationException("StrUtil-V4");
if(StrUtil.VersionToString(0x00FF000000000000UL, true) != "255.0")
if(StrUtil.VersionToString(0x00FF000000000000UL, 2) != "255.0")
throw new InvalidOperationException("StrUtil-V5");
if(StrUtil.VersionToString(0x0000000000070000UL, true) != "0.0.7")
if(StrUtil.VersionToString(0x0000000000070000UL) != "0.0.7")
throw new InvalidOperationException("StrUtil-V6");
if(StrUtil.VersionToString(0x0000000000000000UL) != "0")
throw new InvalidOperationException("StrUtil-V7");
if(StrUtil.VersionToString(0x00000000FFFF0000UL, 4) != "0.0.65535.0")
throw new InvalidOperationException("StrUtil-V8");
if(StrUtil.VersionToString(0x0000000000000000UL, 4) != "0.0.0.0")
throw new InvalidOperationException("StrUtil-V9");
if(StrUtil.RtfEncodeChar('\u0000') != "\\u0?")
throw new InvalidOperationException("StrUtil-Rtf1");
if(StrUtil.RtfEncodeChar('\u7FFF') != "\\u32767?")
throw new InvalidOperationException("StrUtil-Rtf2");
if(StrUtil.RtfEncodeChar('\u8000') != "\\u-32768?")
throw new InvalidOperationException("StrUtil-Rtf3");
if(StrUtil.RtfEncodeChar('\uFFFF') != "\\u-1?")
throw new InvalidOperationException("StrUtil-Rtf4");
if(!StrUtil.StringToBool(Boolean.TrueString))
throw new InvalidOperationException("StrUtil-Bool1");
if(StrUtil.StringToBool(Boolean.FalseString))
throw new InvalidOperationException("StrUtil-Bool2");
if(StrUtil.Count("Abracadabra", "a") != 4)
throw new InvalidOperationException("StrUtil-Count1");
if(StrUtil.Count("Bla", "U") != 0)
throw new InvalidOperationException("StrUtil-Count2");
if(StrUtil.Count("AAAAA", "AA") != 4)
throw new InvalidOperationException("StrUtil-Count3");
const string sU = "data:mytype;base64,";
if(!StrUtil.IsDataUri(sU))
throw new InvalidOperationException("StrUtil-DataUri1");
if(!StrUtil.IsDataUri(sU, "mytype"))
throw new InvalidOperationException("StrUtil-DataUri2");
if(StrUtil.IsDataUri(sU, "notmytype"))
throw new InvalidOperationException("StrUtil-DataUri3");
uint u = 0x7FFFFFFFU;
if(u.ToString(NumberFormatInfo.InvariantInfo) != "2147483647")
throw new InvalidOperationException("StrUtil-Inv1");
if(uint.MaxValue.ToString(NumberFormatInfo.InvariantInfo) !=
"4294967295")
throw new InvalidOperationException("StrUtil-Inv2");
if(long.MinValue.ToString(NumberFormatInfo.InvariantInfo) !=
"-9223372036854775808")
throw new InvalidOperationException("StrUtil-Inv3");
if(short.MinValue.ToString(NumberFormatInfo.InvariantInfo) !=
"-32768")
throw new InvalidOperationException("StrUtil-Inv4");
#endif
}
private static void TestUrlUtil()
{
#if DEBUG && TODO
#if DEBUG
if(UrlUtil.GetHost(@"scheme://domain:port/path?query_string#fragment_id") !=
"domain")
throw new InvalidOperationException("UrlUtil-H1");
@@ -408,7 +519,7 @@ namespace ModernKeePassLib.Cryptography
if(UrlUtil.GetHost(@"s://u:p@d.tld:p/p?q#f") != "d.tld")
throw new InvalidOperationException("UrlUtil-H7");
if(NativeLib.IsUnix()) return;
//if(NativeLib.IsUnix()) return;
string strBase = "\\\\HOMESERVER\\Apps\\KeePass\\KeePass.exe";
string strDoc = "\\\\HOMESERVER\\Documents\\KeePass\\NewDatabase.kdbx";
@@ -419,6 +530,13 @@ namespace ModernKeePassLib.Cryptography
str = UrlUtil.MakeAbsolutePath(strBase, strRel);
if(!str.Equals(strDoc)) throw new InvalidOperationException("UrlUtil-R2");
str = UrlUtil.GetQuotedAppPath(" \"Test\" \"%1\" ");
if(str != "Test") throw new InvalidOperationException("UrlUtil-Q1");
str = UrlUtil.GetQuotedAppPath("C:\\Program Files\\Test.exe");
if(str != "C:\\Program Files\\Test.exe") throw new InvalidOperationException("UrlUtil-Q2");
str = UrlUtil.GetQuotedAppPath("Reg.exe \"Test\" \"Test 2\"");
if(str != "Reg.exe \"Test\" \"Test 2\"") throw new InvalidOperationException("UrlUtil-Q3");
#endif
}
}