Example #1
0
        /// <summary>
        /// Parses base parameters from the provided dictionary.
        /// </summary>
        /// <param name="dictionary">The dictionary containing KDF parameters.</param>
        public KdfParameters(VariantDictionary dictionary)
        {
            if (dictionary == null)
            {
                throw new ArgumentNullException(nameof(dictionary));
            }

            object uuid = dictionary.GetValue(UuidKey);

            if (uuid == null)
            {
                throw new FormatException("No UUID value in dictionary for KdfParameters");
            }

            byte[] uuidBytes = uuid as byte[];
            if (uuidBytes == null)
            {
                throw new FormatException("UUID value in KdfParameters was not a byte array");
            }

            if (uuidBytes.Length != 16)
            {
                throw new FormatException($"Expected 16 UUID bytes in KdfParameters, got {uuidBytes.Length}");
            }

            this.uuid = new Guid(uuidBytes);
        }
Example #2
0
        /// <summary>
        /// Initializes the parameters given a dictionary.
        /// </summary>
        /// <param name="dictionary"></param>
        public Argon2Parameters(VariantDictionary dictionary)
            : base(dictionary)
        {
            this.salt           = dictionary.GetValue(SaltKey) as byte[] ?? new byte[0];
            this.secretKey      = dictionary.GetValue(SecretKey) as byte[] ?? new byte[0];
            this.associatedData = dictionary.GetValue(DataKey) as byte[] ?? new byte[0];

            uint?dictParallelism = dictionary.GetValue(ParallelismKey) as uint?;

            if (dictParallelism == null)
            {
                throw new FormatException("Could not parse parallelism uint from dictionary");
            }
            this.parallelism = dictParallelism.Value;
            if (this.parallelism > Argon2d.MaxParallelism || this.parallelism < Argon2d.MinParallelism)
            {
                throw new FormatException("Parsed parallelism is out of bounds");
            }

            ulong?dictByteCount = dictionary.GetValue(ByteCountKey) as ulong?;

            if (dictByteCount == null)
            {
                throw new FormatException("Could not parse memory ulong from dictionary");
            }
            this.blockCount = dictByteCount.Value / 1024;
            if (this.blockCount > (ulong)Argon2d.MaxMemorySize)
            {
                throw new FormatException("Parsed block count is higher than allowed");
            }

            ulong?dictIterations = dictionary.GetValue(IterationsKey) as ulong?;

            if (dictIterations == null)
            {
                throw new FormatException("Could not parse iterations ulong from dictionary");
            }
            this.iterations = dictIterations.Value;
            if (this.iterations < (ulong)Argon2d.MinIterations || this.iterations > (ulong)Argon2d.MaxIterations)
            {
                throw new FormatException("Parsed iterations is out of bounds");
            }

            uint?dictVersion = dictionary.GetValue(VersionKey) as uint?;

            if (dictVersion == null)
            {
                throw new FormatException("Argon2 version was not present");
            }

            if (dictVersion.Value != Argon2d.VersionNumber)
            {
                throw new FormatException($"Unsupported Argon2 version: {dictVersion.Value}");
            }
        }
Example #3
0
        /// <summary>
        /// Initializes the parameters given a dictionary.
        /// </summary>
        /// <param name="dictionary"></param>
        public AesParameters(VariantDictionary dictionary)
            : base(dictionary)
        {
            if (Uuid != AesUuid)
            {
                throw new FormatException("Wrong UUID for AesParameters");
            }

            ulong?dictRounds = dictionary.GetValue(RoundsKey) as ulong?;

            Rounds = dictRounds ?? DefaultRounds;

            if (!(dictionary.GetValue(SeedKey) is byte[] dictSeed))
            {
                throw new FormatException("AesParameters requires a byte[] seed value");
            }

            Seed = dictSeed.AsBuffer();
        }
Example #4
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);
        }
        private byte[] GenerateHeader()
        {
            byte[] pbHeader;
            using (MemoryStream ms = new MemoryStream())
            {
                MemUtil.Write(ms, MemUtil.UInt32ToBytes(FileSignature1));
                MemUtil.Write(ms, MemUtil.UInt32ToBytes(FileSignature2));
                MemUtil.Write(ms, MemUtil.UInt32ToBytes(m_uFileVersion));

                WriteHeaderField(ms, KdbxHeaderFieldID.CipherID,
                                 m_pwDatabase.DataCipherUuid.UuidBytes);

                int nCprID = (int)m_pwDatabase.Compression;
                WriteHeaderField(ms, KdbxHeaderFieldID.CompressionFlags,
                                 MemUtil.UInt32ToBytes((uint)nCprID));

                WriteHeaderField(ms, KdbxHeaderFieldID.MasterSeed, m_pbMasterSeed);

                if (m_uFileVersion < FileVersion32_4)
                {
                    Debug.Assert(m_pwDatabase.KdfParameters.KdfUuid.Equals(
                                     (new AesKdf()).Uuid));
                    WriteHeaderField(ms, KdbxHeaderFieldID.TransformSeed,
                                     m_pwDatabase.KdfParameters.GetByteArray(AesKdf.ParamSeed));
                    WriteHeaderField(ms, KdbxHeaderFieldID.TransformRounds,
                                     MemUtil.UInt64ToBytes(m_pwDatabase.KdfParameters.GetUInt64(
                                                               AesKdf.ParamRounds, PwDefs.DefaultKeyEncryptionRounds)));
                }
                else
                {
                    WriteHeaderField(ms, KdbxHeaderFieldID.KdfParameters,
                                     KdfParameters.SerializeExt(m_pwDatabase.KdfParameters));
                }

                if (m_pbEncryptionIV.Length > 0)
                {
                    WriteHeaderField(ms, KdbxHeaderFieldID.EncryptionIV, m_pbEncryptionIV);
                }

                if (m_uFileVersion < FileVersion32_4)
                {
                    WriteHeaderField(ms, KdbxHeaderFieldID.InnerRandomStreamKey,
                                     m_pbInnerRandomStreamKey);

                    WriteHeaderField(ms, KdbxHeaderFieldID.StreamStartBytes,
                                     m_pbStreamStartBytes);

                    int nIrsID = (int)m_craInnerRandomStream;
                    WriteHeaderField(ms, KdbxHeaderFieldID.InnerRandomStreamID,
                                     MemUtil.Int32ToBytes(nIrsID));
                }

                // Write public custom data only when there is at least one item,
                // because KDBX 3.1 didn't support this field yet
                if (m_pwDatabase.PublicCustomData.Count > 0)
                {
                    WriteHeaderField(ms, KdbxHeaderFieldID.PublicCustomData,
                                     VariantDictionary.Serialize(m_pwDatabase.PublicCustomData));
                }

                WriteHeaderField(ms, KdbxHeaderFieldID.EndOfHeader, new byte[] {
                    (byte)'\r', (byte)'\n', (byte)'\r', (byte)'\n'
                });

                pbHeader = ms.ToArray();
            }

            return(pbHeader);
        }
Example #6
0
        public override bool Export(PwExportInfo pwExportInfo, Stream sOutput,
                                    IStatusLogger slLogger)
        {
            PwDatabase pd     = pwExportInfo.ContextDatabase;
            PwGroup    pgRoot = pwExportInfo.DataGroup;

            // Remove everything that requires KDBX 4 or higher;
            // see also KdbxFile.GetMinKdbxVersion

            PwUuid puCipher = pd.DataCipherUuid;

            if (puCipher.Equals(ChaCha20Engine.ChaCha20Uuid))
            {
                pd.DataCipherUuid = StandardAesEngine.AesUuid;
            }

            KdfParameters pKdf   = pd.KdfParameters;
            AesKdf        kdfAes = new AesKdf();

            if (!pKdf.KdfUuid.Equals(kdfAes.Uuid))
            {
                pd.KdfParameters = kdfAes.GetDefaultParameters();
            }

            VariantDictionary vdPublic = pd.PublicCustomData;

            pd.PublicCustomData = new VariantDictionary();

            List <PwGroup>            lCustomGK = new List <PwGroup>();
            List <StringDictionaryEx> lCustomGV = new List <StringDictionaryEx>();
            List <PwEntry>            lCustomEK = new List <PwEntry>();
            List <StringDictionaryEx> lCustomEV = new List <StringDictionaryEx>();

            GroupHandler gh = delegate(PwGroup pg)
            {
                if (pg == null)
                {
                    Debug.Assert(false); return(true);
                }
                if (pg.CustomData.Count > 0)
                {
                    lCustomGK.Add(pg);
                    lCustomGV.Add(pg.CustomData);
                    pg.CustomData = new StringDictionaryEx();
                }
                return(true);
            };
            EntryHandler eh = delegate(PwEntry pe)
            {
                if (pe == null)
                {
                    Debug.Assert(false); return(true);
                }
                if (pe.CustomData.Count > 0)
                {
                    lCustomEK.Add(pe);
                    lCustomEV.Add(pe.CustomData);
                    pe.CustomData = new StringDictionaryEx();
                }
                return(true);
            };

            gh(pgRoot);
            pgRoot.TraverseTree(TraversalMethod.PreOrder, gh, eh);

            try
            {
                KdbxFile kdbx = new KdbxFile(pd);
                kdbx.ForceVersion = KdbxFile.FileVersion32_3_1;
                kdbx.Save(sOutput, pgRoot, KdbxFormat.Default, slLogger);
            }
            finally
            {
                // Restore

                pd.DataCipherUuid   = puCipher;
                pd.KdfParameters    = pKdf;
                pd.PublicCustomData = vdPublic;

                for (int i = 0; i < lCustomGK.Count; ++i)
                {
                    lCustomGK[i].CustomData = lCustomGV[i];
                }
                for (int i = 0; i < lCustomEK.Count; ++i)
                {
                    lCustomEK[i].CustomData = lCustomEV[i];
                }
            }

            return(true);
        }
Example #7
0
        private bool ReadHeaderField(BinaryReaderEx brSource)
        {
            Debug.Assert(brSource != null);
            if (brSource == null)
            {
                throw new ArgumentNullException("brSource");
            }

            byte btFieldID = brSource.ReadByte();

            int cbSize;

            Debug.Assert(m_uFileVersion > 0);
            if (m_uFileVersion < FileVersion32_4)
            {
                cbSize = (int)MemUtil.BytesToUInt16(brSource.ReadBytes(2));
            }
            else
            {
                cbSize = MemUtil.BytesToInt32(brSource.ReadBytes(4));
            }
            if (cbSize < 0)
            {
                throw new FormatException(KLRes.FileCorrupted);
            }

            byte[] pbData = MemUtil.EmptyByteArray;
            if (cbSize > 0)
            {
                pbData = brSource.ReadBytes(cbSize);
            }

            bool bResult            = true;
            KdbxHeaderFieldID kdbID = (KdbxHeaderFieldID)btFieldID;

            switch (kdbID)
            {
            case KdbxHeaderFieldID.EndOfHeader:
                bResult = false;                         // Returning false indicates end of header
                break;

            case KdbxHeaderFieldID.CipherID:
                SetCipher(pbData);
                break;

            case KdbxHeaderFieldID.CompressionFlags:
                SetCompressionFlags(pbData);
                break;

            case KdbxHeaderFieldID.MasterSeed:
                m_pbMasterSeed = pbData;
                CryptoRandom.Instance.AddEntropy(pbData);
                break;

            // Obsolete; for backward compatibility only
            case KdbxHeaderFieldID.TransformSeed:
                Debug.Assert(m_uFileVersion < FileVersion32_4);

                AesKdf kdfS = new AesKdf();
                if (!m_pwDatabase.KdfParameters.KdfUuid.Equals(kdfS.Uuid))
                {
                    m_pwDatabase.KdfParameters = kdfS.GetDefaultParameters();
                }

                // m_pbTransformSeed = pbData;
                m_pwDatabase.KdfParameters.SetByteArray(AesKdf.ParamSeed, pbData);

                CryptoRandom.Instance.AddEntropy(pbData);
                break;

            // Obsolete; for backward compatibility only
            case KdbxHeaderFieldID.TransformRounds:
                Debug.Assert(m_uFileVersion < FileVersion32_4);

                AesKdf kdfR = new AesKdf();
                if (!m_pwDatabase.KdfParameters.KdfUuid.Equals(kdfR.Uuid))
                {
                    m_pwDatabase.KdfParameters = kdfR.GetDefaultParameters();
                }

                // m_pwDatabase.KeyEncryptionRounds = MemUtil.BytesToUInt64(pbData);
                m_pwDatabase.KdfParameters.SetUInt64(AesKdf.ParamRounds,
                                                     MemUtil.BytesToUInt64(pbData));
                break;

            case KdbxHeaderFieldID.EncryptionIV:
                m_pbEncryptionIV = pbData;
                break;

            case KdbxHeaderFieldID.InnerRandomStreamKey:
                Debug.Assert(m_uFileVersion < FileVersion32_4);
                Debug.Assert(m_pbInnerRandomStreamKey == null);
                m_pbInnerRandomStreamKey = pbData;
                CryptoRandom.Instance.AddEntropy(pbData);
                break;

            case KdbxHeaderFieldID.StreamStartBytes:
                Debug.Assert(m_uFileVersion < FileVersion32_4);
                m_pbStreamStartBytes = pbData;
                break;

            case KdbxHeaderFieldID.InnerRandomStreamID:
                Debug.Assert(m_uFileVersion < FileVersion32_4);
                SetInnerRandomStreamID(pbData);
                break;

            case KdbxHeaderFieldID.KdfParameters:
                m_pwDatabase.KdfParameters = KdfParameters.DeserializeExt(pbData);
                break;

            case KdbxHeaderFieldID.PublicCustomData:
                Debug.Assert(m_pwDatabase.PublicCustomData.Count == 0);
                m_pwDatabase.PublicCustomData = VariantDictionary.Deserialize(pbData);
                break;

            default:
                Debug.Assert(false);
                if (m_slLogger != null)
                {
                    m_slLogger.SetText(KLRes.UnknownHeaderId + ": " +
                                       kdbID.ToString() + "!", LogStatusType.Warning);
                }
                break;
            }

            return(bResult);
        }
Example #8
0
 public static byte[] SerializeExt(KdfParameters p)
 {
     return(VariantDictionary.Serialize(p));
 }