protected void SetUnkownField(PwsRecord field) { var f = new ItemField((FieldType)field.Type); f.Set(field.Buffer, (FieldType)field.Type, MakeBlowFish()); _unkownItemFields.Add(f); }
/* * 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); }