예제 #1
0
        public static void WriteHandshake(this IConnectionStateTls13 state, ref WritableBuffer writer, HandshakeType handshakeType, Func <WritableBuffer, IConnectionStateTls13, WritableBuffer> contentWriter)
        {
            var dataWritten = writer.BytesWritten;

            writer.WriteBigEndian(handshakeType);
            BufferExtensions.WriteVector24Bit(ref writer, contentWriter, state);
            if (state.HandshakeHash != null)
            {
                var hashBuffer = writer.AsReadableBuffer().Slice(dataWritten);
                state.HandshakeHash.HashData(hashBuffer);
            }
        }
예제 #2
0
        public static void WriteHandshake <T>(this T state, ref WritableBuffer writer, HandshakeType handshakeType, Func <WritableBuffer, T, WritableBuffer> contentWriter) where T : IConnectionState
        {
            state.Logger?.LogTrace("Writing handshake {handshake type}", handshakeType);
            var dataWritten = writer.BytesWritten;

            writer.WriteBigEndian(handshakeType);
            BufferExtensions.WriteVector24Bit <T>(ref writer, contentWriter, state);
            if (state.HandshakeHash != null)
            {
                var hashBuffer = writer.AsReadableBuffer().Slice(dataWritten);
                state.HandshakeHash.HashData(hashBuffer);
            }
        }
예제 #3
0
        public unsafe void Encrypt(ref WritableBuffer buffer, RecordType recordType)
        {
            int      outLength;
            GCHandle inHandle;

            ThrowOnError(EVP_CipherInit_ex(_ctx, _cipherType, IntPtr.Zero, (void *)_keyPointer, (void *)_ivPointer, (int)KeyMode.Encryption));
            foreach (var b in buffer.AsReadableBuffer())
            {
                if (b.Length == 0)
                {
                    continue;
                }
                var inPtr = b.GetPointer(out inHandle);
                try
                {
                    outLength = buffer.Memory.Length;
                    ThrowOnError(EVP_CipherUpdate(_ctx, inPtr, ref outLength, inPtr, b.Length));
                    buffer.Advance(outLength);
                }
                finally
                {
                    if (inHandle.IsAllocated)
                    {
                        inHandle.Free();
                    }
                }
            }
            buffer.Ensure(Overhead + sizeof(RecordType));
            var writePtr = buffer.Memory.GetPointer(out inHandle);

            outLength = buffer.Memory.Length;
            ThrowOnError(EVP_CipherUpdate(_ctx, writePtr, ref outLength, &recordType, sizeof(RecordType)));
            buffer.Advance(outLength);
            if (_paddingSize > 0)
            {
                outLength = _paddingSize;
                writePtr  = buffer.Memory.GetPointer(out inHandle);
                ThrowOnError(EVP_CipherUpdate(_ctx, writePtr, ref outLength, (byte *)s_zeroBuffer, _paddingSize));
                buffer.Advance(outLength);
            }
            writePtr  = buffer.Memory.GetPointer(out inHandle);
            outLength = 0;
            ThrowOnError(EVP_CipherFinal_ex(_ctx, null, ref outLength));
            ThrowOnError(EVP_CIPHER_CTX_ctrl(_ctx, EVP_CIPHER_CTRL.EVP_CTRL_GCM_GET_TAG, _overhead, writePtr));
            buffer.Advance(_overhead);
            IncrementSequence();
        }
예제 #4
0
        public unsafe void EncryptWithAuthData(ref WritableBuffer buffer, RecordType recordType, ushort tlsVersion, int plaintextLength)
        {
            var additionalData = stackalloc byte[13];
            var additionalSpan = new Span <byte>(additionalData, 13);

            additionalSpan.Write64BitNumber(_sequenceNumber);
            additionalSpan = additionalSpan.Slice(8);
            additionalSpan.Write(recordType);
            additionalSpan = additionalSpan.Slice(1);
            additionalSpan.Write(tlsVersion);
            additionalSpan = additionalSpan.Slice(2);
            additionalSpan.Write16BitNumber((ushort)plaintextLength);

            var plainText = buffer.AsReadableBuffer();

            plainText = plainText.Slice(plainText.Length - plaintextLength);

            ThrowOnError(EVP_CipherInit_ex(_ctx, _cipherType, IntPtr.Zero, (byte *)_keyPointer, (void *)_ivPointer, (int)KeyMode.Encryption));
            int outSize = 0;

            ThrowOnError(EVP_CipherUpdate(_ctx, null, ref outSize, additionalData, 13));
            void *inPointer;

            foreach (var b in plainText)
            {
                if (b.Length == 0)
                {
                    continue;
                }
                b.TryGetPointer(out inPointer);
                outSize = b.Length;
                ThrowOnError(EVP_CipherUpdate(_ctx, inPointer, ref outSize, inPointer, outSize));
            }
            buffer.Ensure(_overhead);
            buffer.Memory.TryGetPointer(out inPointer);
            ThrowOnError(EVP_CipherFinal_ex(_ctx, null, ref outSize));
            ThrowOnError(EVP_CIPHER_CTX_ctrl(_ctx, EVP_CIPHER_CTRL.EVP_CTRL_GCM_GET_TAG, _overhead, inPointer));
            buffer.Advance(_overhead);
            _sequenceNumber++;
            IncrementSequence();
        }
예제 #5
0
        private string ToHex(WritableBuffer wb)
        {
            var readable = wb.AsReadableBuffer();

            if (readable.IsEmpty)
            {
                return("");
            }
            var sb = new StringBuilder(readable.Length * 2);

            foreach (var mem in readable)
            {
                var span = mem.Span;
                int len  = span.Length;
                for (int i = 0; i < len; i++)
                {
                    sb.Append(span[i].ToString("x2"));
                }
            }
            return(sb.ToString());
        }
예제 #6
0
 public void StartHandshake(ref WritableBuffer writer)
 {
     this.WriteHandshake(ref writer, HandshakeType.client_hello, Hello.WriteClientHello);
     _helloBuffer = writer.AsReadableBuffer().ToArray();
     State        = StateType.WaitServerHello;
 }