Пример #1
0
        protected void SetUnkownField(PwsRecord field)
        {
            var f = new ItemField((FieldType)field.Type);

            f.Set(field.Buffer, (FieldType)field.Type, MakeBlowFish());
            _unkownItemFields.Add(f);
        }
Пример #2
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);
        }