Ejemplo n.º 1
0
        bool CompareFields(ItemField x, Item that, ItemField y)
        {
            if (x.Length != y.Length)
            {
                Debug.WriteLine($"Field lengths mismatched ('{x.Type}, {x.Length}', '{y.Type}, {y.Length}')");
                return(false);
            }
            if (x.Type != y.Type)
            {
                Debug.WriteLine($"Field types mismatched ('{x.Type}', '{y.Type}')");
                return(false);
            }
            var a      = GetField(x);
            var b      = that.GetField(y);
            var result = a.SequenceEqual(b);

#if DEBUG
            if (!result)
            {
                Debug.WriteLine($"Fields {x.Type} mismatched ('{string.Join(",", a)}', '{string.Join(", ", b)}')");
            }
#endif
            PwsUtil.TrashMemory(a);
            PwsUtil.TrashMemory(b);
            return(result);
        }
Ejemplo n.º 2
0
        internal byte[] Get(BlowFish bf)
        {
            if (_length == 0)
            {
                return(new byte[0]);
            }
            // we have data to decrypt
            var result    = new byte[_length];
            var decrypted = bf.Decrypt_ECB(_data);

            Array.Copy(decrypted, result, _length);
            PwsUtil.TrashMemory(decrypted);
            return(result);
        }
Ejemplo n.º 3
0
        private async Task WriteCbcInternalAsync(byte[] buffer, int bufferIdx, int length, ICryptoTransform algorithm)
        {
            var bs     = algorithm.OutputBlockSize;
            var block1 = new byte[16];

            var curblock = block1;

            try
            {
                using (var rng = RandomNumberGenerator.Create())
                {
                    rng.GetBytes(curblock);

                    if (length > 0 ||
                        bs == 8 && length == 0) // This part for bwd compat w/pre-3 format)
                    {
                        var blockLength = (length + (bs - 1)) / bs * bs;
                        if (blockLength == 0 && bs == 8)
                        {
                            blockLength = bs;
                        }

                        // Now, encrypt and write the (rest of the) buffer
                        for (var x = 0; x < blockLength; x += bs)
                        {
                            if (length == 0 || length % bs != 0 && length - x < bs)
                            {
                                //This is for an uneven last block
                                rng.GetBytes(curblock);
                                Array.Copy(buffer, bufferIdx + x, curblock, 0, length % bs);
                            }
                            else
                            {
                                Array.Copy(buffer, bufferIdx + x, curblock, 0, bs);
                            }
                            XorArray(curblock, Ipthing, bs);
                            algorithm.TransformBlock(curblock, 0, 16, curblock, 0);
                            Array.Copy(curblock, Ipthing, bs);

                            await _stream.WriteAsync(curblock, 0, bs);
                        }
                    }
                }
            }
            finally
            {
                PwsUtil.TrashMemory(curblock);
            }
        }
Ejemplo n.º 4
0
        private async Task WriteCbcInternalAsync(byte type, byte[] buffer, int length, ICryptoTransform algorithm)
        {
            var bs     = algorithm.OutputBlockSize;
            var block1 = new byte[16];

            var curblock = block1;

            try
            {
                var bufferIdx = 0;

                using (var rng = RandomNumberGenerator.Create())
                {
                    rng.GetBytes(curblock);
                }

                // block length overwrites 4 bytes of the above randomness.
                var len = BitConverter.GetBytes(length);
                Array.Copy(len, curblock, len.Length);

                // following new for format 2.0 - lengthblock bytes 4-7 were unused before.
                curblock[sizeof(int)] = type;

                if (bs == 16)
                {
                    // In this case, we've too many (11) wasted bytes in the length block
                    // So we store actual data there:
                    // (11 = BlockSize - 4 (length) - 1 (type)
                    var len1 = length > 11 ? 11 : length;
                    Array.Copy(buffer, 0, curblock, 5, len1);
                    length    -= len1;
                    bufferIdx += len1;
                }

                XorArray(curblock, Ipthing, bs);   // do the CBC thing
                algorithm.TransformBlock(curblock, 0, 16, curblock, 0);
                Array.Copy(curblock, Ipthing, bs); // update CBC for next round

                await _stream.WriteAsync(curblock, 0, bs);

                await WriteCbcInternalAsync(buffer, bufferIdx, length, algorithm);
            }
            finally
            {
                PwsUtil.TrashMemory(curblock);
            }
        }
Ejemplo n.º 5
0
        /*
         * Reads an encrypted record into buffer.
         * The first block of the record contains the encrypted record length
         * We have the usual ugly problem of fixed buffer lengths in C/C++.
         * allocate the buffer here, to ensure that it's long enough.
         * *** THE CALLER MUST delete[] IT AFTER USE *** UGH++
         *
         * (unless buffer_len is zero)
         *
         * Note that the buffer is a byte array, and buffer_len is number of
         * bytes. This means that any data can be passed, and we don't
         * care at this level if strings are char or wchar_t.
         *
         * If TERMINAL_BLOCK is non-NULL, the first block read is tested against it,
         * and -1 is returned if it matches. (used in V3)
         */
        private async Task <PwsRecord> ReadCbcInternalAsync(ICryptoTransform algorithm,
                                                            byte[] terminalBlock)
        {
            var bs          = algorithm.InputBlockSize;
            var block1      = new byte[16];
            var block2      = new byte[16];
            var block3      = new byte[16];
            var lengthblock = block1;
            var numRead     = await _stream.ReadAsync(lengthblock, 0, bs);

            if (numRead != bs)
            {
                return(null);
            }

            if (terminalBlock != null && lengthblock.SequenceEqual(terminalBlock))
            {
                return(null);
            }

            var lcpy = block2;

            Array.Copy(lengthblock, lcpy, bs);


            algorithm.TransformBlock(lengthblock, 0, lengthblock.Length, lengthblock, 0);
            XorArray(lengthblock, Ipthing, bs);
            Array.Copy(lcpy, Ipthing, bs);

            var length = BitConverter.ToUInt32(lengthblock, 0);

            var result = new PwsRecord();

            // new for 2.0 -- lengthblock[4..7] previously set to zero
            result.Type = lengthblock[sizeof(int)]; // type is first byte after the length

            if (_stream.Length != 0 && length >= _stream.Length)
            {
                PwsUtil.TrashMemory(lengthblock);
                return(null);
            }

            var bufferLen = length;
            var buffer    = new byte[length / bs * bs + 2 * bs]; // round upwards
            var bufferidx = 0;

            if (bs == 16)
            {
                // length block contains up to 11 (= 16 - 4 - 1) bytes
                // of data
                var len1 = length > 11 ? 11 : length;
                Array.Copy(lengthblock, 5, buffer, bufferidx, (int)len1);
                length    -= len1;
                bufferidx += (int)len1;
            }

            var blockLength = (length + (bs - 1)) / bs * bs;

            // Following is meant for lengths < BS,
            // but results in a block being read even
            // if length is zero. This is wasteful,
            // but fixing it would break all existing pre-3.0 databases.
            if (blockLength == 0 && bs == 8)
            {
                blockLength = bs;
            }

            PwsUtil.TrashMemory(lengthblock);

            if (length > 0 || bs == 8 && length == 0)
            {
                // pre-3 pain
                var tempcbc = block3;
                numRead += await _stream.ReadAsync(buffer, bufferidx, (int)blockLength);

                for (var x = 0; x < blockLength; x += bs)
                {
                    Array.Copy(buffer, bufferidx + x, tempcbc, 0, bs);
                    algorithm.TransformBlock(buffer, bufferidx + x, 16, buffer, bufferidx + x);
                    XorArray(buffer, bufferidx + x, Ipthing, 0, bs);
                    Array.Copy(tempcbc, Ipthing, bs);
                }
            }

            if (bufferLen == 0)
            {
                result.Buffer = new byte[0];
            }
            else
            {
                result.Buffer = new byte[bufferLen];
                Array.Copy(buffer, result.Buffer, (int)bufferLen);
                PwsUtil.TrashMemory(buffer);
            }
            result.ReadBytes = numRead;

            return(result);
        }