Example #1
0
		public static KdfParameters DeserializeExt(byte[] pb)
		{
			VariantDictionary d = VariantDictionary.Deserialize(pb);
			if(d == null) { Debug.Assert(false); return null; }

			byte[] pbUuid = d.GetByteArray(ParamUuid);
			if((pbUuid == null) || (pbUuid.Length != (int)PwUuid.UuidSize))
			{
				Debug.Assert(false);
				return null;
			}

			PwUuid pu = new PwUuid(pbUuid);
			KdfParameters p = new KdfParameters(pu);
			d.CopyTo(p);
			return p;
		}
Example #2
0
		public override KdfParameters GetDefaultParameters()
		{
			KdfParameters p = base.GetDefaultParameters();
			p.SetUInt64(ParamRounds, PwDefs.DefaultKeyEncryptionRounds);
			return p;
		}
Example #3
0
		public static byte[] SerializeExt(KdfParameters p)
		{
			return VariantDictionary.Serialize(p);
		}
Example #4
0
        protected void MaximizeParamUInt64(KdfParameters p, string strName,
                                           ulong uMin, ulong uMax, uint uMilliseconds, bool bInterpSearch)
        {
            if (p == null)
            {
                Debug.Assert(false); return;
            }
            if (string.IsNullOrEmpty(strName))
            {
                Debug.Assert(false); return;
            }
            if (uMin > uMax)
            {
                Debug.Assert(false); return;
            }

            if (uMax > (ulong.MaxValue >> 1))
            {
                Debug.Assert(false);
                uMax = ulong.MaxValue >> 1;

                if (uMin > uMax)
                {
                    p.SetUInt64(strName, uMin); return;
                }
            }

            byte[] pbMsg = new byte[32];
            for (int i = 0; i < pbMsg.Length; ++i)
            {
                pbMsg[i] = (byte)i;
            }

            ulong uLow    = uMin;
            ulong uHigh   = uMin + 1UL;
            long  tLow    = 0;
            long  tHigh   = 0;
            long  tTarget = (long)uMilliseconds;

            // Determine range
            while (uHigh <= uMax)
            {
                p.SetUInt64(strName, uHigh);

                // GC.Collect();
                Stopwatch sw = Stopwatch.StartNew();
                Transform(pbMsg, p);
                sw.Stop();

                tHigh = sw.ElapsedMilliseconds;
                if (tHigh > tTarget)
                {
                    break;
                }

                uLow    = uHigh;
                tLow    = tHigh;
                uHigh <<= 1;
            }
            if (uHigh > uMax)
            {
                uHigh = uMax; tHigh = 0;
            }
            if (uLow > uHigh)
            {
                uLow = uHigh;                          // Skips to end
            }
            // Find optimal number of iterations
            while ((uHigh - uLow) >= 2UL)
            {
                ulong u = (uHigh + uLow) >> 1;                 // Binary search
                // Interpolation search, if possible
                if (bInterpSearch && (tLow > 0) && (tHigh > tTarget) &&
                    (tLow <= tTarget))
                {
                    u = uLow + (((uHigh - uLow) * (ulong)(tTarget - tLow)) /
                                (ulong)(tHigh - tLow));
                    if ((u >= uLow) && (u <= uHigh))
                    {
                        u = Math.Max(u, uLow + 1UL);
                        u = Math.Min(u, uHigh - 1UL);
                    }
                    else
                    {
                        Debug.Assert(false);
                        u = (uHigh + uLow) >> 1;
                    }
                }

                p.SetUInt64(strName, u);

                // GC.Collect();
                Stopwatch sw = Stopwatch.StartNew();
                Transform(pbMsg, p);
                sw.Stop();

                long t = sw.ElapsedMilliseconds;
                if (t == tTarget)
                {
                    uLow = u; break;
                }
                else if (t > tTarget)
                {
                    uHigh = u; tHigh = t;
                }
                else
                {
                    uLow = u; tLow = t;
                }
            }

            p.SetUInt64(strName, uLow);
        }
Example #5
0
		public override KdfParameters GetBestParameters(uint uMilliseconds)
		{
			KdfParameters p = GetDefaultParameters();
			ulong uRounds;

			// Try native method
			if(NativeLib.TransformKeyBenchmark256(uMilliseconds, out uRounds))
			{
				p.SetUInt64(ParamRounds, uRounds);
				return p;
			}

			if(TransformKeyBenchmarkGCrypt(uMilliseconds, out uRounds))
			{
				p.SetUInt64(ParamRounds, uRounds);
				return p;
			}

			byte[] pbKey = new byte[32];
			byte[] pbNewKey = new byte[32];
			for(int i = 0; i < pbKey.Length; ++i)
			{
				pbKey[i] = (byte)i;
				pbNewKey[i] = (byte)i;
			}

#if KeePassUAP
			KeyParameter kp = new KeyParameter(pbKey);
			AesEngine aes = new AesEngine();
			aes.Init(true, kp);
#else
			byte[] pbIV = new byte[16];

			using(SymmetricAlgorithm a = CryptoUtil.CreateAes())
			{
				if(a.BlockSize != 128) // AES block size
				{
					Debug.Assert(false);
					a.BlockSize = 128;
				}
				a.KeySize = 256;
				a.Mode = CipherMode.ECB;

				using(ICryptoTransform t = a.CreateEncryptor(pbKey, pbIV))
				{
					// !t.CanReuseTransform -- doesn't work with Mono
					if((t == null) || (t.InputBlockSize != 16) ||
						(t.OutputBlockSize != 16))
					{
						Debug.Assert(false);
						p.SetUInt64(ParamRounds, PwDefs.DefaultKeyEncryptionRounds);
						return p;
					}
#endif

					uRounds = 0;
					int tStart = Environment.TickCount;
					while(true)
					{
						for(ulong j = 0; j < BenchStep; ++j)
						{
#if KeePassUAP
							aes.ProcessBlock(pbNewKey, 0, pbNewKey, 0);
							aes.ProcessBlock(pbNewKey, 16, pbNewKey, 16);
#else
							t.TransformBlock(pbNewKey, 0, 16, pbNewKey, 0);
							t.TransformBlock(pbNewKey, 16, 16, pbNewKey, 16);
#endif
						}

						uRounds += BenchStep;
						if(uRounds < BenchStep) // Overflow check
						{
							uRounds = ulong.MaxValue;
							break;
						}

						uint tElapsed = (uint)(Environment.TickCount - tStart);
						if(tElapsed > uMilliseconds) break;
					}

					p.SetUInt64(ParamRounds, uRounds);
#if KeePassUAP
					aes.Reset();
#else
				}
			}
#endif
			return p;
		}
Example #6
0
 /// <summary>
 /// Generate random seeds and store them in <paramref name="p" />.
 /// </summary>
 public virtual void Randomize(KdfParameters p)
 {
     Debug.Assert(p != null);
     Debug.Assert(p.KdfUuid.Equals(this.Uuid));
 }
Example #7
0
 public abstract byte[] Transform(byte[] pbMsg, KdfParameters p);
Example #8
0
        public override KdfParameters GetBestParameters(uint uMilliseconds)
        {
            const ulong uStep = 3001;
            ulong       uRounds;

            KdfParameters p = GetDefaultParameters();

            // Try native method
            if (NativeLib.TransformKeyBenchmark256(uMilliseconds, out uRounds))
            {
                p.SetUInt64(ParamRounds, uRounds);
                return(p);
            }

            byte[] pbKey    = new byte[32];
            byte[] pbNewKey = new byte[32];
            for (int i = 0; i < pbKey.Length; ++i)
            {
                pbKey[i]    = (byte)i;
                pbNewKey[i] = (byte)i;
            }

#if 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);

            RijndaelManaged r = new RijndaelManaged();
            if (r.BlockSize != 128)            // AES block size
            {
                Debug.Assert(false);
                r.BlockSize = 128;
            }

            r.IV      = pbIV;
            r.Mode    = CipherMode.ECB;
            r.KeySize = 256;
            r.Key     = pbKey;
            ICryptoTransform iCrypt = r.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;
            while (true)
            {
                for (ulong j = 0; j < uStep; ++j)
                {
#if 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 += uStep;
                if (uRounds < uStep)                // Overflow check
                {
                    uRounds = ulong.MaxValue;
                    break;
                }

                uint tElapsed = (uint)(Environment.TickCount - tStart);
                if (tElapsed > uMilliseconds)
                {
                    break;
                }
            }

            p.SetUInt64(ParamRounds, uRounds);
            return(p);
        }
Example #9
0
 public abstract byte[] GetSeed(KdfParameters p);
Example #10
0
 public static byte[] SerializeExt(KdfParameters p)
 {
     return(VariantDictionary.Serialize(p));
 }
Example #11
0
		/// <summary>
		/// Generate a 32-byte (256-bit) key from the composite key.
		/// </summary>
		public ProtectedBinary GenerateKey32(KdfParameters p)
		{
			if(p == null) { Debug.Assert(false); throw new ArgumentNullException("p"); }

			byte[] pbRaw32 = CreateRawCompositeKey32();
			if((pbRaw32 == null) || (pbRaw32.Length != 32))
				{ Debug.Assert(false); return null; }

			KdfEngine kdf = KdfPool.Get(p.KdfUuid);
			if(kdf == null) // CryptographicExceptions are translated to "file corrupted"
				throw new Exception(KLRes.UnknownKdf + MessageService.NewParagraph +
					KLRes.FileNewVerOrPlgReq + MessageService.NewParagraph +
					"UUID: " + p.KdfUuid.ToHexString() + ".");

			byte[] pbTrf32 = kdf.Transform(pbRaw32, p);
			if(pbTrf32 == null) { Debug.Assert(false); return null; }

			if(pbTrf32.Length != 32)
			{
				Debug.Assert(false);
				pbTrf32 = CryptoUtil.HashSha256(pbTrf32);
			}

			ProtectedBinary pbRet = new ProtectedBinary(true, pbTrf32);
			MemUtil.ZeroByteArray(pbTrf32);
			MemUtil.ZeroByteArray(pbRaw32);
			return pbRet;
		}
Example #12
0
 public override byte[] GetSeed(KdfParameters p)
 { return p.GetByteArray(ParamSalt); }
Example #13
0
        public override byte[] Transform(byte[] pbMsg, KdfParameters p)
        {
            if (pbMsg == null)
            {
                throw new ArgumentNullException("pbMsg");
            }
            if (p == null)
            {
                throw new ArgumentNullException("p");
            }

            byte[] pbSalt = p.GetByteArray(ParamSalt);
            if (pbSalt == null)
            {
                throw new ArgumentNullException("p.Salt");
            }
            if ((pbSalt.Length < MinSalt) || (pbSalt.Length > MaxSalt))
            {
                throw new ArgumentOutOfRangeException("p.Salt");
            }

            uint uPar = p.GetUInt32(ParamParallelism, 0);

            if ((uPar < MinParallelism) || (uPar > MaxParallelism))
            {
                throw new ArgumentOutOfRangeException("p.Parallelism");
            }

            ulong uMem = p.GetUInt64(ParamMemory, 0);

            if ((uMem < MinMemory) || (uMem > MaxMemory))
            {
                throw new ArgumentOutOfRangeException("p.Memory");
            }

            ulong uIt = p.GetUInt64(ParamIterations, 0);

            if ((uIt < MinIterations) || (uIt > MaxIterations))
            {
                throw new ArgumentOutOfRangeException("p.Iterations");
            }

            uint v = p.GetUInt32(ParamVersion, 0);

            if ((v < MinVersion) || (v > MaxVersion))
            {
                throw new ArgumentOutOfRangeException("p.Version");
            }

            byte[] pbSecretKey = p.GetByteArray(ParamSecretKey);
            byte[] pbAssocData = p.GetByteArray(ParamAssocData);

            byte[] pbRet;

            if (m_t == Argon2Type.ID)
            {
                pbRet = Argon2Transform(pbMsg, pbSalt, uPar, uMem,
                                        uIt, 32, v, pbSecretKey, pbAssocData);
            }
            else
            {
                if (pbSecretKey != null)
                {
                    throw new ArgumentOutOfRangeException("Unsupported configuration: non-null pbSecretKey");
                }

                if (pbAssocData != null)
                {
                    throw new ArgumentOutOfRangeException("Unsupported configuration: non-null pbAssocData");
                }

                /*
                 * byte[] pbRet = Argon2d(pbMsg, pbSalt, uPar, uMem, uIt,
                 *  32, v, pbSecretKey, pbAssocData);
                 */

                IntPtr msgPtr  = Marshal.AllocHGlobal(pbMsg.Length);
                IntPtr saltPtr = Marshal.AllocHGlobal(pbSalt.Length);
                IntPtr retPtr  = Marshal.AllocHGlobal(32);
                Marshal.Copy(pbMsg, 0, msgPtr, pbMsg.Length);
                Marshal.Copy(pbSalt, 0, saltPtr, pbSalt.Length);

                const UInt32 Argon2_d = 0;

                int ret = argon2_hash(
                    (UInt32)uIt, (UInt32)(uMem / 1024), uPar,
                    msgPtr, (IntPtr)pbMsg.Length,
                    saltPtr, (IntPtr)pbSalt.Length,
                    retPtr, (IntPtr)32,
                    (IntPtr)0, (IntPtr)0, Argon2_d, v);

                if (ret != 0)
                {
                    throw new Exception("argon2_hash failed with " + ret);
                }

                pbRet = new byte[32];
                Marshal.Copy(retPtr, pbRet, 0, 32);

                Marshal.FreeHGlobal(msgPtr);
                Marshal.FreeHGlobal(saltPtr);
                Marshal.FreeHGlobal(retPtr);
            }

            if (uMem > (100UL * 1024UL * 1024UL))
            {
                GC.Collect();
            }
            return(pbRet);
        }
Example #14
0
        public override byte[] Transform(byte[] pbMsg, KdfParameters p)
        {
            if (pbMsg == null)
            {
                throw new ArgumentNullException("pbMsg");
            }
            if (p == null)
            {
                throw new ArgumentNullException("p");
            }

            byte[] pbSalt = p.GetByteArray(ParamSalt);
            if (pbSalt == null)
            {
                throw new ArgumentNullException("p.Salt");
            }
            if ((pbSalt.Length < MinSalt) || (pbSalt.Length > MaxSalt))
            {
                throw new ArgumentOutOfRangeException("p.Salt");
            }

            uint uPar = p.GetUInt32(ParamParallelism, 0);

            if ((uPar < MinParallelism) || (uPar > MaxParallelism))
            {
                throw new ArgumentOutOfRangeException("p.Parallelism");
            }

            ulong uMem = p.GetUInt64(ParamMemory, 0);

            if ((uMem < MinMemory) || (uMem > MaxMemory))
            {
                throw new ArgumentOutOfRangeException("p.Memory");
            }

            ulong uIt = p.GetUInt64(ParamIterations, 0);

            if ((uIt < MinIterations) || (uIt > MaxIterations))
            {
                throw new ArgumentOutOfRangeException("p.Iterations");
            }

            uint v = p.GetUInt32(ParamVersion, 0);

            if ((v < MinVersion) || (v > MaxVersion))
            {
                throw new ArgumentOutOfRangeException("p.Version");
            }

            byte[] pbSecretKey = p.GetByteArray(ParamSecretKey);
            byte[] pbAssocData = p.GetByteArray(ParamAssocData);

            byte[] pbRet = Argon2d(pbMsg, pbSalt, uPar, uMem, uIt,
                                   32, v, pbSecretKey, pbAssocData);

            if (uMem > (100UL * 1024UL * 1024UL))
            {
                GC.Collect();
            }
            return(pbRet);
        }