예제 #1
0
        public unsafe void Encrypt(ref WritableBuffer buffer, ReadableBuffer plainText, RecordType recordType)
        {
            int      outLength;
            GCHandle inHandle, outHandle;

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

            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 outHandle);
                ThrowOnError(EVP_CipherUpdate(_ctx, writePtr, ref outLength, (byte *)s_zeroBuffer, _paddingSize));
                buffer.Advance(outLength);
            }
            writePtr  = buffer.Memory.GetPointer(out outHandle);
            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();
        }
예제 #2
0
        private static void WriteAsciiString(ref WritableBuffer buffer, ReadOnlySpan <char> value)
        {
            if (value == null || value.Length == 0)
            {
                return;
            }

            while (value.Length != 0)
            {
                buffer.Ensure();

                var span         = buffer.Buffer.Span;
                int bytesToWrite = Math.Min(value.Length, span.Length);

                // todo: Vector.Narrow

                for (int i = 0; i < bytesToWrite; i++)
                {
                    span[i] = (byte)value[i];
                }

                buffer.Advance(bytesToWrite);
                buffer.Commit();
                value = value.Slice(bytesToWrite);
            }
        }
예제 #3
0
        public unsafe static WritableBuffer SendKeyExchange(WritableBuffer buffer, IConnectionStateTls12 connectionState)
        {
            var messageLength = 4 + connectionState.KeyShare.KeyExchangeSize;

            buffer.Ensure(messageLength);
            var bookMark = buffer.Memory;

            buffer.WriteBigEndian(ECCurveType.named_curve);
            buffer.WriteBigEndian(connectionState.KeyShare.NamedGroup);
            buffer.WriteBigEndian((byte)connectionState.KeyShare.KeyExchangeSize);
            connectionState.KeyShare.WritePublicKey(ref buffer);

            buffer.WriteBigEndian(connectionState.SignatureScheme);
            BufferExtensions.WriteVector <ushort>(ref buffer, (writer, state) =>
            {
                var tempBuffer = stackalloc byte[connectionState.ClientRandom.Length * 2 + messageLength];
                var tmpSpan    = new Span <byte>(tempBuffer, connectionState.ClientRandom.Length * 2 + messageLength);
                connectionState.ClientRandom.CopyTo(tmpSpan);
                tmpSpan = tmpSpan.Slice(connectionState.ClientRandom.Length);
                connectionState.ServerRandom.CopyTo(tmpSpan);
                tmpSpan = tmpSpan.Slice(connectionState.ServerRandom.Length);
                bookMark.Span.Slice(0, messageLength).CopyTo(tmpSpan);
                connectionState.Certificate.SignHash(connectionState.CryptoProvider.HashProvider,
                                                     connectionState.SignatureScheme, ref writer, tempBuffer, connectionState.ClientRandom.Length * 2 + messageLength);
                return(writer);
            }, connectionState);

            return(buffer);
        }
예제 #4
0
        public unsafe void WritePublicKey(ref WritableBuffer keyBuffer)
        {
            GenerateECKeySet();
            var    key    = EVP_PKEY_get0_EC_KEY(_eKey);
            var    pubKey = EC_KEY_get0_public_key(key);
            var    group  = EC_KEY_get0_group(key);
            IntPtr size   = EC_POINT_point2oct(group, pubKey, EC_POINT_CONVERSION.POINT_CONVERSION_UNCOMPRESSED, null, IntPtr.Zero, IntPtr.Zero);
            var    s      = (ushort)size.ToInt32();

            keyBuffer.Ensure(s);
            GCHandle handle;
            var      ptr = keyBuffer.Memory.GetPointer(out handle);

            try
            {
                size = EC_POINT_point2oct(group, pubKey, EC_POINT_CONVERSION.POINT_CONVERSION_UNCOMPRESSED, ptr, size, IntPtr.Zero);
                keyBuffer.Advance(s);
            }
            finally
            {
                if (handle.IsAllocated)
                {
                    handle.Free();
                }
            }
        }
예제 #5
0
        // review: make public?
        private static unsafe void WriteString(this WritableBuffer buffer, string value, Encoding encoding)
        {
            int bytesPerChar = encoding.GetMaxByteCount(1);

            fixed(char *s = value)
            {
                int remainingChars = value.Length, charOffset = 0;

                while (remainingChars != 0)
                {
                    buffer.Ensure(bytesPerChar);

                    var memory         = buffer.Memory;
                    var charsThisBatch = Math.Min(remainingChars, memory.Length / bytesPerChar);
                    int bytesWritten   = 0;

                    void *pointer;
                    ArraySegment <byte> data;
                    if (memory.TryGetPointer(out pointer))
                    {
                        bytesWritten = encoding.GetBytes(s + charOffset, charsThisBatch,
                                                         (byte *)pointer, memory.Length);
                    }
                    else if (memory.TryGetArray(out data))
                    {
                        bytesWritten = encoding.GetBytes(value, charOffset, charsThisBatch, data.Array, data.Offset);
                    }

                    charOffset     += charsThisBatch;
                    remainingChars -= charsThisBatch;
                    buffer.Advance(bytesWritten);
                }
            }
        }
        public unsafe void EncryptSessionKey(ref WritableBuffer writer, Span <byte> ticketContent)
        {
            var tagLength = 16;
            var key       = _keys.Take();

            try
            {
                var contentLength = ticketContent.Length + tagLength + sizeof(long) + sizeof(Guid);
                var nonce         = System.Threading.Interlocked.Increment(ref _nounceCounter);
                writer.WriteBigEndian((ushort)contentLength);
                writer.Ensure(contentLength);

                key.IV.Slice(4).Span.Write(nonce);
                key.Init(KeyMode.Encryption);

                writer.WriteBigEndian(_keyGuid);
                writer.WriteBigEndian(_nounceCounter);

                var amountWritten = key.Finish(ticketContent, writer.Buffer.Span);
                writer.Advance(amountWritten);
                key.GetTag(writer.Buffer.Span.Slice(0, tagLength));
                writer.Advance(tagLength);
            }
            finally
            {
                _keys.Add(key);
            }
        }
예제 #7
0
        protected override void WriteRecords(ref ReadableBuffer buffer, ref WritableBuffer writer, RecordType recordType)
        {
            ReadableBuffer append;

            while (buffer.Length > 0)
            {
                append = buffer.Slice(0, Math.Min(_maxMessageSize, buffer.Length));
                buffer = buffer.Slice(append.End);
                var recordHeader = new RecordHeader()
                {
                    RecordType = recordType,
                    Length     = (ushort)append.Length,
                    Version    = _recordVersion
                };
                writer.Ensure(_minimumMessageSize);
                if (_connection?.WriteKey != null)
                {
                    recordHeader.Length += (ushort)(8 + _connection.WriteKey.Overhead);
                }
                writer.Buffer.Span.Write(recordHeader);
                writer.Advance(_minimumMessageSize);
                if (_connection?.WriteKey != null)
                {
                    _connection.WriteKey.Encrypt(ref writer, append, recordType, _recordVersion);
                }
                else
                {
                    writer.Append(append);
                }
            }
        }
예제 #8
0
        public static WritableBuffer CreateNewSessionKey(WritableBuffer buffer, IConnectionStateTls13 state)
        {
            var lifetime = TicketLifeTimeInHours * 60 * 60;

            buffer.WriteBigEndian((uint)lifetime);
            buffer.Ensure(4);
            state.CryptoProvider.FillWithRandom(buffer.Memory.Slice(0, 4));
            buffer.Advance(4);

            BufferExtensions.WriteVector <ushort>(ref buffer, (writer, conn) =>
            {
                state.ResumptionProvider.GenerateSessionTicket(ref writer, conn);
                return(writer);
            }, state);

            BufferExtensions.WriteVector <ushort>(ref buffer, (writer, conn) =>
            {
                writer.WriteBigEndian(ExtensionType.ticket_early_data_info);
                writer.WriteBigEndian <ushort>(sizeof(uint));
                uint maxData = 1024 * 2;
                writer.WriteBigEndian(maxData);
                return(writer);
            }, state);
            return(buffer);
        }
예제 #9
0
        internal static void WriteFrameHeader(ref WritableBuffer output, WebSocketsFrame.FrameFlags flags, WebSocketsFrame.OpCodes opCode, int payloadLength, int mask)
        {
            output.Ensure(MaxHeaderLength);

            int index = 0;
            var span  = output.Buffer.Span;

            span[index++] = (byte)(((int)flags & 240) | ((int)opCode & 15));
            if (payloadLength > ushort.MaxValue)
            { // write as a 64-bit length
                span[index++] = (byte)((mask != 0 ? 128 : 0) | 127);
                span.Slice(index).Write((uint)0);
                span.Slice(index + 4).Write(ToNetworkByteOrder((uint)payloadLength));
                index += 8;
            }
            else if (payloadLength > 125)
            { // write as a 16-bit length
                span[index++] = (byte)((mask != 0 ? 128 : 0) | 126);
                span.Slice(index).Write(ToNetworkByteOrder((ushort)payloadLength));
                index += 2;
            }
            else
            { // write in the header
                span[index++] = (byte)((mask != 0 ? 128 : 0) | payloadLength);
            }
            if (mask != 0)
            {
                span.Slice(index).Write(mask);
                index += 4;
            }
            output.Advance(index);
        }
예제 #10
0
 public static void WriteCertificateEntry(ref WritableBuffer writer, byte[] certificate)
 {
     writer.Ensure(3);
     writer.Memory.Write24BitNumber(certificate.Length);
     writer.Advance(3);
     writer.Write(certificate);
 }
예제 #11
0
        public void WriteBigEndian <T>(T value) where T : struct
        {
            var size = Unsafe.SizeOf <T>();

            if (_bytesRemaining < size)
            {
                _innerBuffer.Ensure(size);
                _bytesRemaining = _innerBuffer.Buffer.Length;
            }
            var s = _innerBuffer.Buffer.Span;

            size = s.WriteBigEndian(value);
            _handshakeHash?.HashData(s.Slice(0, size));
            _innerBuffer.Advance(size);
            _bytesWritten   += size;
            _bytesRemaining -= size;
        }
예제 #12
0
 private unsafe static void FillBuffer(ref WritableBuffer wb, int count)
 {
     for (int i = 0; i < count; i++)
     {
         wb.Ensure(4);
         void *pointer;
         Assert.True(wb.Buffer.TryGetPointer(out pointer));
         *(int *)pointer = i;
         wb.Advance(4);
     }
 }
예제 #13
0
        public static unsafe void WriteAsciiString(ref WritableBuffer buffer, string value)
        {
            // One byte per char
            buffer.Ensure(value.Length);

            fixed(char *s = value)
            {
                int written = ASCIIEncoding.GetBytes(s, value.Length, (byte *)buffer.Memory.UnsafePointer, value.Length);

                buffer.CommitBytes(written);
            }
        }
예제 #14
0
        public static unsafe void WriteUtf8String(ref WritableBuffer buffer, string value)
        {
            fixed(char *s = value)
            {
                var byteCount = Utf8Encoding.GetByteCount(value);

                buffer.Ensure(byteCount);
                int written = Utf8Encoding.GetBytes(s, value.Length, (byte *)buffer.Memory.BufferPtr, byteCount);

                buffer.CommitBytes(written);
            }
        }
예제 #15
0
파일: Hello.cs 프로젝트: vcsjones/Leto
        public static WritableBuffer SendServerHello13(WritableBuffer buffer, IConnectionStateTls13 connectionState)
        {
            buffer.Ensure(RandomLength + sizeof(ushort));
            buffer.WriteBigEndian(connectionState.Version);
            var memoryToFill = buffer.Memory.Slice(0, RandomLength);

            connectionState.CryptoProvider.FillWithRandom(memoryToFill);
            buffer.Advance(RandomLength);
            buffer.WriteBigEndian(connectionState.CipherSuite.CipherCode);
            BufferExtensions.WriteVector <ushort>(ref buffer, ExtensionsWrite.WriteExtensionList, connectionState);
            return(buffer);
        }
예제 #16
0
        public static void WriteVector24Bit(ref WritableBuffer buffer, Func <WritableBuffer, IConnectionStateTls13, WritableBuffer> writeContent, IConnectionStateTls13 state)
        {
            buffer.Ensure(3);
            var bookmark = buffer.Memory;

            buffer.Advance(3);
            int currentSize = buffer.BytesWritten;

            buffer      = writeContent(buffer, state);
            currentSize = buffer.BytesWritten - currentSize;
            bookmark.Write24BitNumber(currentSize);
        }
예제 #17
0
        public static unsafe void WriteAsciiString(ref WritableBuffer buffer, string value)
        {
            // One byte per char
            buffer.Ensure(value.Length);

            fixed(char *s = value)
            {
                int written = Encoding.ASCII.GetBytes(s, value.Length, (byte *)buffer.Memory.BufferPtr, value.Length);

                buffer.UpdateWritten(written);
            }
        }
예제 #18
0
        /// <summary>
        /// Writes the source <see cref="Span{Byte}"/> to the <see cref="WritableBuffer"/>.
        /// </summary>
        /// <param name="buffer">The <see cref="WritableBuffer"/></param>
        /// <param name="source">The <see cref="Span{Byte}"/> to write</param>
        public static void Write(this WritableBuffer buffer, ReadOnlySpan <byte> source)
        {
            if (buffer.Memory.IsEmpty)
            {
                buffer.Ensure();
            }

            // Fast path, try copying to the available memory directly
            if (source.Length <= buffer.Memory.Length)
            {
                source.CopyTo(buffer.Memory.Span);
                buffer.Advance(source.Length);
                return;
            }

            var remaining = source.Length;
            var offset    = 0;

            while (remaining > 0)
            {
                var writable = Math.Min(remaining, buffer.Memory.Length);

                buffer.Ensure(writable);

                if (writable == 0)
                {
                    continue;
                }

                source.Slice(offset, writable).CopyTo(buffer.Memory.Span);

                remaining -= writable;
                offset    += writable;

                buffer.Advance(writable);
            }
        }
예제 #19
0
파일: Hello.cs 프로젝트: vcsjones/Leto
 public static WritableBuffer WriteClientHello(WritableBuffer buffer, IConnectionStateTls13 connectionState)
 {
     buffer.WriteBigEndian <ushort>(0x0303);
     buffer.Ensure(RandomLength);
     connectionState.CryptoProvider.FillWithRandom(buffer.Memory.Slice(0, RandomLength));
     buffer.Advance(RandomLength);
     //legacy sessionid
     buffer.WriteBigEndian((byte)0);
     connectionState.CryptoProvider.WriteCipherSuites(ref buffer);
     //legacy compression
     buffer.WriteBigEndian((byte)1);
     buffer.WriteBigEndian((byte)0);
     connectionState.KeyShare = connectionState.CryptoProvider.GetDefaultKeyShare();
     BufferExtensions.WriteVector <ushort>(ref buffer, ExtensionsWrite.WriteExtensionList, connectionState);
     return(buffer);
 }
        internal static unsafe void Encrypt <T>(this T context, WritableBuffer outBuffer, ReadableBuffer buffer) where T : ISecureContext
        {
            outBuffer.Ensure(context.TrailerSize + context.HeaderSize + buffer.Length);
            void *outBufferPointer;

            outBuffer.Memory.TryGetPointer(out outBufferPointer);

            buffer.CopyTo(outBuffer.Memory.Slice(context.HeaderSize, buffer.Length));

            var securityBuff = stackalloc SecurityBuffer[4];
            SecurityBufferDescriptor sdcInOut = new SecurityBufferDescriptor(4);

            securityBuff[0].size         = context.HeaderSize;
            securityBuff[0].type         = SecurityBufferType.Header;
            securityBuff[0].tokenPointer = outBufferPointer;

            securityBuff[1].size         = buffer.Length;
            securityBuff[1].type         = SecurityBufferType.Data;
            securityBuff[1].tokenPointer = (byte *)outBufferPointer + context.HeaderSize;

            securityBuff[2].size         = context.TrailerSize;
            securityBuff[2].type         = SecurityBufferType.Trailer;
            securityBuff[2].tokenPointer = (byte *)outBufferPointer + context.HeaderSize + buffer.Length;

            securityBuff[3].size         = 0;
            securityBuff[3].tokenPointer = null;
            securityBuff[3].type         = SecurityBufferType.Empty;

            sdcInOut.UnmanagedPointer = securityBuff;

            var handle = context.ContextHandle;
            var result = (SecurityStatus)InteropSspi.EncryptMessage(ref handle, 0, sdcInOut, 0);

            if (result == 0)
            {
                outBuffer.Advance(context.HeaderSize + context.TrailerSize + buffer.Length);
            }
            else
            {
                //Zero out the output buffer before throwing the exception to stop any data being sent in the clear
                //By a misbehaving underlying channel
                Span <byte> memoryToClear = new Span <byte>(outBufferPointer, context.HeaderSize + context.TrailerSize + buffer.Length);
                byte *      empty         = stackalloc byte[context.HeaderSize + context.TrailerSize + buffer.Length];
                memoryToClear.Set(empty, context.HeaderSize + context.TrailerSize + buffer.Length);
                throw new InvalidOperationException($"There was an issue encrypting the data {result}");
            }
        }
예제 #21
0
        public static void WriteRecord(ref WritableBuffer buffer, RecordType recordType, ReadableBuffer plainText, State.IConnectionState state)
        {
            buffer.Ensure(RecordHeaderLength);
            if (state.WriteKey == null)
            {
                buffer.WriteBigEndian(recordType);
                buffer.WriteBigEndian(TlsRecordVersion);
                buffer.WriteBigEndian((ushort)plainText.Length);
                buffer.Append(plainText);
                return;
            }
            buffer.WriteBigEndian(RecordType.Application);
            buffer.WriteBigEndian(TlsRecordVersion);
            var totalSize = plainText.Length + state.WriteKey.Overhead + sizeof(RecordType);

            buffer.WriteBigEndian((ushort)totalSize);
            state.WriteKey.Encrypt(ref buffer, plainText, recordType);
        }
예제 #22
0
        public unsafe int SignHash(IHashProvider provider, SignatureScheme scheme, ref WritableBuffer writer, byte *message, int messageLength)
        {
            var hash = provider.GetHashInstance(_hashType);

            hash.HashData(message, messageLength);

            var digest = new byte[hash.HashSize];

            fixed(byte *dPtr = digest)
            {
                hash.InterimHash(dPtr, digest.Length);
            }

            writer.Ensure(_privateKey.KeySize);
            var result = _privateKey.SignHash(digest);

            writer.Write(result);
            return(result.Length);
        }
예제 #23
0
        private static void WriteUtf8String(ref WritableBuffer buffer, ReadOnlySpan <char> value)
        {
            if (value == null || value.Length == 0)
            {
                return;
            }

            var encoder = TextEncoder.Utf8;

            while (value.Length != 0)
            {
                buffer.Ensure(4); // be able to write at least one character (worst case)

                var span = buffer.Buffer.Span;
                encoder.TryEncode(value, span, out int charsConsumed, out int bytesWritten);
                buffer.Advance(bytesWritten);
                buffer.Commit();
                value = value.Slice(charsConsumed);
            }
        }
예제 #24
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();
        }
예제 #25
0
 public void StartFrame(RecordType recordType, ref WritableBuffer buffer)
 {
     if (_frameStarted)
     {
         ExceptionHelper.ThrowException(new InvalidOperationException("Already writing a frame and started another"));
     }
     _frameStarted = true;
     _recordType   = recordType;
     buffer.Ensure(RecordProcessor.RecordHeaderLength);
     buffer.WriteBigEndian(recordType);
     buffer.WriteBigEndian(_state.TlsRecordVersion);
     _bookmark = buffer.Memory;
     buffer.WriteBigEndian <ushort>(0);
     _messageBodySize = buffer.BytesWritten;
     if (_state.WriteKey == null)
     {
         return;
     }
     _state.WriteKey.WriteNonce(ref buffer);
     _plainTextSize = buffer.BytesWritten;
 }
예제 #26
0
        public override void Encrypt(ref WritableBuffer writer, Span <byte> plainText, RecordType recordType, TlsVersion tlsVersion)
        {
            _key.IV.Span.Slice(4).WriteBigEndian(_sequenceNumber);
            _key.Init(KeyMode.Encryption);
            var additionalInfo = new AdditionalInfo()
            {
                SequenceNumber  = _sequenceNumber,
                RecordType      = recordType,
                TlsVersion      = tlsVersion,
                PlainTextLength = (ushort)plainText.Length
            };

            _key.AddAdditionalInfo(ref additionalInfo);
            writer.WriteBigEndian(_sequenceNumber);
            writer.Ensure(plainText.Length);
            var bytesWritten = _key.Finish(plainText, writer.Buffer.Span);

            writer.Advance(bytesWritten);
            IncrementSequence();
            WriteTag(ref writer);
        }
예제 #27
0
        public unsafe void WritePublicKey(ref WritableBuffer keyBuffer)
        {
            if (!_publicPrivateKey.IsValid())
            {
                GenerateKeyset();
            }
            IntPtr ptr;
            var    buffSize = (int)ThrowOnError(EVP_PKEY_get1_tls_encodedpoint(_publicPrivateKey, out ptr));

            try
            {
                keyBuffer.Ensure(buffSize);
                var span = new Span <byte>((byte *)ptr, buffSize);
                span.CopyTo(keyBuffer.Memory.Span);
                keyBuffer.Advance(span.Length);
            }
            finally
            {
                CRYPTO_clear_free(ptr, (UIntPtr)buffSize, "ECFunctionInstance.cs", 97);
            }
        }
예제 #28
0
        public unsafe void WritePublicKey(ref WritableBuffer keyBuffer)
        {
            BIGNUM priv, pub;

            DH_get0_key(_localKey, out pub, out priv);
            keyBuffer.Ensure(_keyExchangeSize);
            GCHandle handle;
            void *   ptr = keyBuffer.Memory.GetPointer(out handle);

            try
            {
                var written = BN_bn2binpad(pub, ptr, _keyExchangeSize);
                keyBuffer.Advance(written);
            }
            finally
            {
                if (handle.IsAllocated)
                {
                    handle.Free();
                }
            }
        }
예제 #29
0
        public override void Encrypt(ref WritableBuffer writer, ReadableBuffer plainText, RecordType recordType, TlsVersion tlsVersion)
        {
            _key.IV.Span.Slice(4).WriteBigEndian(_sequenceNumber);
            _key.Init(KeyMode.Encryption);
            var additionalInfo = new AdditionalInfo()
            {
                SequenceNumber  = _sequenceNumber,
                RecordType      = recordType,
                TlsVersion      = tlsVersion,
                PlainTextLength = (ushort)plainText.Length
            };

            _key.AddAdditionalInfo(ref additionalInfo);
            writer.WriteBigEndian(_sequenceNumber);
            var totalBytes = plainText.Length;

            foreach (var b in plainText)
            {
                if (b.Length == 0)
                {
                    continue;
                }
                totalBytes -= b.Length;
                writer.Ensure(b.Length);
                int bytesWritten;
                if (totalBytes == 0)
                {
                    bytesWritten = _key.Finish(b.Span, writer.Buffer.Span);
                    writer.Advance(bytesWritten);
                    break;
                }
                bytesWritten = _key.Update(b.Span, writer.Buffer.Span);
                writer.Advance(bytesWritten);
            }
            IncrementSequence();
            WriteTag(ref writer);
        }
        internal static unsafe SecurityStatus Decrypt <T>(this T context, ReadableBuffer buffer, WritableBuffer decryptedData) where T : ISecureContext
        {
            void *pointer;

            if (buffer.IsSingleSpan)
            {
                buffer.First.TryGetPointer(out pointer);
            }
            else
            {
                if (buffer.Length > SecurityContext.MaxStackAllocSize)
                {
                    throw new OverflowException($"We need to create a buffer on the stack of size {buffer.Length} but the max is {SecurityContext.MaxStackAllocSize}");
                }
                byte *      tmpBuffer = stackalloc byte[buffer.Length];
                Span <byte> span      = new Span <byte>(tmpBuffer, buffer.Length);
                buffer.CopyTo(span);
                pointer = tmpBuffer;
            }

            int offset = 0;
            int count  = buffer.Length;

            var secStatus = DecryptMessage(pointer, ref offset, ref count, context.ContextHandle);

            if (buffer.IsSingleSpan)
            {
                buffer = buffer.Slice(offset, count);
                decryptedData.Append(ref buffer);
            }
            else
            {
                decryptedData.Ensure(buffer.Length);
                decryptedData.Write(new Span <byte>(pointer, buffer.Length));
            }
            return(secStatus);
        }