TlsNullCipher
The NULL cipher.
                using Org.BouncyCastle.Utilities;
using System;
namespace Org.BouncyCastle.Tls.Crypto.Impl
{
    public class TlsNullCipher : TlsCipher, TlsCipherExt
    {
        protected readonly TlsCryptoParameters m_cryptoParams;
        protected readonly TlsSuiteHmac m_readMac;
        protected readonly TlsSuiteHmac m_writeMac;
        protected readonly byte[] m_decryptConnectionID;
        protected readonly byte[] m_encryptConnectionID;
        protected readonly bool m_decryptUseInnerPlaintext;
        protected readonly bool m_encryptUseInnerPlaintext;
        public virtual bool UsesOpaqueRecordType => false;
        public unsafe TlsNullCipher(TlsCryptoParameters cryptoParams, TlsHmac clientMac, TlsHmac serverMac)
        {
            SecurityParameters securityParameters = cryptoParams.SecurityParameters;
            if (TlsImplUtilities.IsTlsV13(securityParameters.NegotiatedVersion))
                throw new TlsFatalAlert(80);
            m_decryptConnectionID = securityParameters.ConnectionIDPeer;
            m_encryptConnectionID = securityParameters.ConnectionIDLocal;
            m_decryptUseInnerPlaintext = !Arrays.IsNullOrEmpty(m_decryptConnectionID);
            m_encryptUseInnerPlaintext = !Arrays.IsNullOrEmpty(m_encryptConnectionID);
            m_cryptoParams = cryptoParams;
            int num = clientMac.MacLength + serverMac.MacLength;
            Span<byte> span;
            int num2;
            if (num <= 512) {
                num2 = num;
                span = new Span<byte>(stackalloc byte[(int)(uint)num2], num2);
            } else
                span = new byte[num];
            Span<byte> keyBlock = span;
            TlsImplUtilities.CalculateKeyBlock(cryptoParams, keyBlock);
            clientMac.SetKey(keyBlock.Slice(0, clientMac.MacLength));
            num2 = clientMac.MacLength;
            keyBlock = keyBlock.Slice(num2, keyBlock.Length - num2);
            serverMac.SetKey(keyBlock.Slice(0, serverMac.MacLength));
            num2 = serverMac.MacLength;
            keyBlock = keyBlock.Slice(num2, keyBlock.Length - num2);
            if (!keyBlock.IsEmpty)
                throw new TlsFatalAlert(80);
            if (cryptoParams.IsServer) {
                m_writeMac = new TlsSuiteHmac(cryptoParams, serverMac);
                m_readMac = new TlsSuiteHmac(cryptoParams, clientMac);
            } else {
                m_writeMac = new TlsSuiteHmac(cryptoParams, clientMac);
                m_readMac = new TlsSuiteHmac(cryptoParams, serverMac);
            }
        }
        public virtual int GetCiphertextDecodeLimit(int plaintextLimit)
        {
            return plaintextLimit + (m_decryptUseInnerPlaintext ? 1 : 0) + m_readMac.Size;
        }
        public virtual int GetCiphertextEncodeLimit(int plaintextLength, int plaintextLimit)
        {
            plaintextLimit = System.Math.Min(plaintextLength, plaintextLimit);
            return plaintextLimit + (m_encryptUseInnerPlaintext ? 1 : 0) + m_writeMac.Size;
        }
        public virtual int GetPlaintextLimit(int ciphertextLimit)
        {
            return GetPlaintextEncodeLimit(ciphertextLimit);
        }
        public virtual int GetPlaintextDecodeLimit(int ciphertextLimit)
        {
            return ciphertextLimit - m_readMac.Size - (m_decryptUseInnerPlaintext ? 1 : 0);
        }
        public virtual int GetPlaintextEncodeLimit(int ciphertextLimit)
        {
            return ciphertextLimit - m_writeMac.Size - (m_encryptUseInnerPlaintext ? 1 : 0);
        }
        public virtual TlsEncodeResult EncodePlaintext(long seqNo, short contentType, ProtocolVersion recordVersion, int headerAllocation, byte[] plaintext, int offset, int len)
        {
            return EncodePlaintext(seqNo, contentType, recordVersion, headerAllocation, plaintext.AsSpan(offset, len));
        }
        public virtual TlsEncodeResult EncodePlaintext(long seqNo, short contentType, ProtocolVersion recordVersion, int headerAllocation, ReadOnlySpan<byte> plaintext)
        {
            int size = m_writeMac.Size;
            int num = plaintext.Length + (m_encryptUseInnerPlaintext ? 1 : 0);
            byte[] array = new byte[headerAllocation + num + size];
            plaintext.CopyTo(array.AsSpan(headerAllocation));
            short num2 = contentType;
            if (m_encryptUseInnerPlaintext) {
                array[headerAllocation + plaintext.Length] = (byte)contentType;
                num2 = 25;
            }
            m_writeMac.CalculateMac(seqNo, num2, m_encryptConnectionID, array.AsSpan(headerAllocation, num)).CopyTo(array.AsSpan(headerAllocation + num));
            return new TlsEncodeResult(array, 0, array.Length, num2);
        }
        public virtual TlsDecodeResult DecodeCiphertext(long seqNo, short recordType, ProtocolVersion recordVersion, byte[] ciphertext, int offset, int len)
        {
            int size = m_readMac.Size;
            int num = len - size;
            if (num < (m_decryptUseInnerPlaintext ? 1 : 0))
                throw new TlsFatalAlert(50);
            byte[] a = m_readMac.CalculateMac(seqNo, recordType, m_decryptConnectionID, ciphertext, offset, num);
            if (!TlsUtilities.ConstantTimeAreEqual(size, a, 0, ciphertext, offset + num))
                throw new TlsFatalAlert(20);
            short contentType = recordType;
            int num2 = num;
            if (m_decryptUseInnerPlaintext) {
                byte b;
                do {
                    if (--num2 < 0)
                        throw new TlsFatalAlert(10);
                    b = ciphertext[offset + num2];
                } while (b == 0);
                contentType = (short)(b & 255);
            }
            return new TlsDecodeResult(ciphertext, offset, num2, contentType);
        }
        public virtual void RekeyDecoder()
        {
            throw new TlsFatalAlert(80);
        }
        public virtual void RekeyEncoder()
        {
            throw new TlsFatalAlert(80);
        }
    }
}