예제 #1
0
    public unsafe void Encrypt(ReadOnlySpan <byte> nonce, ReadOnlySpan <byte> source,
                               Span <byte> destination, Span <byte> tag, ReadOnlySpan <byte> associatedData = default)
    {
        CheckInput(nonce, source, destination);

        ulong length = (ulong)source.Length << 3;

        Span <byte> counterBlock = _counterBlock.AsSpan(0, BlockSize);
        Span <byte> counter      = counterBlock.Slice(12, 4);

        nonce.CopyTo(counterBlock);

        counter[0] = 0;
        counter[1] = 0;
        counter[2] = 0;
        counter[3] = 1;

        _crypto.Encrypt(counterBlock, tag);
        counter[3] = 2;
        uint c = 2;

        _gHash.Update(associatedData);

        while (!source.IsEmpty)
        {
            _crypto.Encrypt(counterBlock, _buffer);
            ++c;
            BinaryPrimitives.WriteUInt32BigEndian(counter, c);

            int n = Math.Min(source.Length, BlockSize);

            fixed(byte *pOut = destination)
            fixed(byte *pSource = source)
            fixed(byte *pBuffer = _buffer)
            {
                IntrinsicsUtils.Xor(pSource, pBuffer, pOut, n);
            }

            _gHash.Update(destination[..n]);
예제 #2
0
 protected override unsafe void Xor(byte *stream, byte *source, byte *destination, int length)
 {
     IntrinsicsUtils.Xor(stream, source, destination, length);
 }
예제 #3
0
        public unsafe void Encrypt(ReadOnlySpan <byte> nonce, ReadOnlySpan <byte> source,
                                   Span <byte> destination, Span <byte> tag, ReadOnlySpan <byte> associatedData = default)
        {
            if (nonce.Length != NonceSize)
            {
                throw new ArgumentException(@"Nonce size must be 12 bytes", nameof(nonce));
            }

            if (destination.Length != source.Length)
            {
                throw new ArgumentException(string.Empty, nameof(destination));
            }

            var length = (ulong)source.Length << 3;

            var counterBlock = _counterBlock.AsSpan(0, BlockSize4);
            var counter0     = counterBlock.Slice(12, 4);
            var counter1     = counterBlock.Slice(28, 4);
            var counter2     = counterBlock.Slice(44, 4);
            var counter3     = counterBlock.Slice(60, 4);

            nonce.CopyTo(counterBlock);
            nonce.CopyTo(counterBlock.Slice(16));
            nonce.CopyTo(counterBlock.Slice(32));
            nonce.CopyTo(counterBlock.Slice(48));

            counter0[0] = 0;
            counter0[1] = 0;
            counter0[2] = 0;
            counter0[3] = 1;

            counter1[0] = 0;
            counter1[1] = 0;
            counter1[2] = 0;
            counter1[3] = 3;

            counter2[0] = 0;
            counter2[1] = 0;
            counter2[2] = 0;
            counter2[3] = 4;

            counter3[0] = 0;
            counter3[1] = 0;
            counter3[2] = 0;
            counter3[3] = 5;

            _crypto.Encrypt(counterBlock, tag);
            counter0[3] = 2;

            _gHash.Update(associatedData);

            while (!source.IsEmpty)
            {
                _crypto.Encrypt4(counterBlock, _buffer);
                counter0.IncrementBe4();
                counter1.IncrementBe4();
                counter2.IncrementBe4();
                counter3.IncrementBe4();

                var n = Math.Min(source.Length, BlockSize4);

                fixed(byte *pOut = destination)
                fixed(byte *pSource = source)
                fixed(byte *pBuffer = _buffer)
                {
                    IntrinsicsUtils.Xor(pSource, pBuffer, pOut, n);
                }

                _gHash.Update(destination.Slice(0, n));

                source      = source.Slice(n);
                destination = destination.Slice(n);
            }

            BinaryPrimitives.WriteUInt64BigEndian(_buffer, (ulong)associatedData.Length << 3);
            BinaryPrimitives.WriteUInt64BigEndian(_buffer.AsSpan(8), length);

            _gHash.Update(_buffer.AsSpan(0, TagSize));
            _gHash.GetMac(_buffer);

            fixed(byte *pTag = tag)
            fixed(byte *pBuffer = _buffer)
            {
                IntrinsicsUtils.Xor16(pTag, pBuffer, pTag);
            }
        }