Exemple #1
0
        private const int MaxBufferSize = 1 << 20; // Max ArrayPool<byte>.Shared buffer size.

        public static void GetHashFinal(this HashAlgorithm alg, ByteSpan hash)
        {
            var data = new byte[0];

            alg.TransformFinalBlock(data, 0, 0);
            alg.Hash.CopyTo(hash);
        }
        public static bool TryParseRequestUri(ByteSpan buffer, out Utf8Span requestUri, out int parsedBytes)
        {
            var uriSpan = HttpReader.SliceTo(buffer, HttpReader.s_SP, out parsedBytes);

            requestUri = new Utf8Span(uriSpan);
            return(parsedBytes != 0);
        }
        public static bool TryParseHttpVersion(ByteSpan buffer, out Utf8Span httpVersion, out int parsedBytes)
        {
            var versionSpan = HttpReader.SliceTo(buffer, HttpReader.s_CR, HttpReader.s_LF, out parsedBytes);

            httpVersion = new Utf8Span(versionSpan);
            return(parsedBytes != 0);
        }
Exemple #4
0
        public override bool TryDecode(string hex, ByteSpan bytes)
        {
            if (hex.Length % 2 == 1)
            {
                throw new ArgumentException("Invalid hex bytes string.", nameof(hex));
            }

            if (hex.Length != bytes.Length * 2)
            {
                throw new ArgumentException("Length mismatch.", nameof(bytes));
            }

            for (int i = 0, j = bytes.Length; i < hex.Length;)
            {
                var a = CharToNibble(hex[i++]);
                var b = CharToNibble(hex[i++]);

                if (a == -1 || b == -1)
                {
                    return(false);
                }
                bytes[--j] = (byte)((a << 4) | b);
            }

            return(true);
        }
        public static bool TryParseMethod(ByteSpan buffer, out HttpMethod method, out int parsedBytes)
        {
            if (buffer.StartsWith(s_Get.Bytes))
            {
                method      = HttpMethod.Get;
                parsedBytes = s_Get.Length;
                return(true);
            }

            if (buffer.StartsWith(s_Post.Bytes))
            {
                method      = HttpMethod.Post;
                parsedBytes = s_Post.Length;
                return(true);
            }

            if (buffer.StartsWith(s_Put.Bytes))
            {
                method      = HttpMethod.Put;
                parsedBytes = s_Put.Length;
                return(true);
            }

            if (buffer.StartsWith(s_Delete.Bytes))
            {
                method      = HttpMethod.Delete;
                parsedBytes = s_Delete.Length;
                return(true);
            }

            method      = HttpMethod.Unknown;
            parsedBytes = 0;
            return(false);
        }
Exemple #6
0
        void pack_roundtrip_check <T>(BitSize bitcount)
            where T : unmanaged
        {
            var src = Random.BitString(bitcount);

            Claim.eq(bitcount, src.Length);

            var x = src.ToBits();

            Claim.eq(bitcount, x.Length);

            var y     = Bits.pack(x);
            var sizeT = size <T>();

            var q     = Math.DivRem(bitcount, 8, out int r);
            var bytes = q + (r == 0 ? 0 : 1);

            Claim.eq(bytes, y.Length);

            var bulk = ByteSpan.ReadValues <T>(y, out Span <byte> rem);

            var merged = rem.Length != 0 ? bulk.Extend(bulk.Length + 1) : bulk;

            if (merged.Length != bulk.Length)
            {
                merged[merged.Length - 1] = rem.TakeScalar <T>();
            }

            var bsOutput = merged.ToBitString().Truncate(bitcount);

            Claim.eq(src, bsOutput);
            Claim.eq((src & ~bsOutput).PopCount(), 0);
        }
Exemple #7
0
        void OnReadWindows(UVBuffer.Windows buffer, IntPtr bytesAvaliable)
        {
            // TODO: all branches need to release buffer, I think
            long bytesRead = bytesAvaliable.ToInt64();

            if (bytesRead == 0)
            {
                buffer.Dispose();
                return;
            }
            else if (bytesRead < 0)
            {
                var error = UVException.ErrorCodeToError((int)bytesRead);
                if (error == UVError.EOF)
                {
                    OnEndOfStream();
                    Dispose();
                    buffer.Dispose();
                }
                else
                {
                    Dispose();
                    buffer.Dispose();
                    throw new UVException((int)bytesRead);
                }
            }
            else
            {
                var readSlice = new ByteSpan((byte *)buffer.Buffer, (int)bytesRead);
                OnReadCompleted(readSlice);
                buffer.Dispose();
            }
        }
Exemple #8
0
 void OnReadCompleted(ByteSpan bytesRead)
 {
     if (ReadCompleted != null)
     {
         ReadCompleted(bytesRead);
     }
 }
Exemple #9
0
 // Write a 32-bit integer in big-endian format to output[0..4)
 public static void WriteBigEndian32(this ByteSpan output, uint value, int offset)
 {
     output[offset + 0] = (byte)(value >> 24);
     output[offset + 1] = (byte)(value >> 16);
     output[offset + 2] = (byte)(value >> 8);
     output[offset + 3] = (byte)(value >> 0);
 }
Exemple #10
0
        public unsafe void ByteSpanEqualsTestsTwoDifferentInstancesOfBuffersWithSameValues()
        {
            const int bufferLength = 128;

            byte[] buffer1 = new byte[bufferLength];
            byte[] buffer2 = new byte[bufferLength];

            for (int i = 0; i < bufferLength; i++)
            {
                buffer1[i] = (byte)(bufferLength + 1 - i);
                buffer2[i] = (byte)(bufferLength + 1 - i);
            }

            fixed(byte *buffer1pinned = buffer1)
            fixed(byte *buffer2pinned = buffer2)
            {
                ByteSpan b1 = new ByteSpan(buffer1pinned, bufferLength);
                ByteSpan b2 = new ByteSpan(buffer2pinned, bufferLength);

                for (int i = 0; i < bufferLength; i++)
                {
                    Assert.True(b1.Slice(i).Equals(b2.Slice(i)));
                }
            }
        }
        /// <summary>
        /// Validates the authentication tag against the provided additional
        /// data, then decrypts the cipher text returning the original
        /// plaintext.
        /// </summary>
        /// <param name="nonce">
        /// The unique value used to seal this message
        /// </param>
        /// <param name="ciphertext">
        /// Combined ciphertext and authentication tag
        /// </param>
        /// <param name="associatedData">
        /// Additional data used to authenticate the message
        /// </param>
        /// <param name="output">
        /// On successful validation and decryprion, Open writes the original
        /// plaintext to output. Must contain enough space to hold
        /// `ciphertext.Length - CiphertextOverhead` bytes.
        /// </param>
        /// <returns>
        /// True if the data was validated and successfully decrypted.
        /// Otherwise, false.
        /// </returns>
        public bool Open(ByteSpan output, ByteSpan nonce, ByteSpan ciphertext, ByteSpan associatedData)
        {
            if (nonce.Length != NonceSize)
            {
                throw new ArgumentException("Invalid nonce size", nameof(nonce));
            }
            if (ciphertext.Length < CiphertextOverhead)
            {
                throw new ArgumentException("Invalid ciphertext size", nameof(ciphertext));
            }
            else if (output.Length < ciphertext.Length - CiphertextOverhead)
            {
                throw new ArgumentException("Invalid output size", nameof(output));
            }

            // Split ciphertext into actual ciphertext and authentication
            // tag components.
            ByteSpan authenticationTag = ciphertext.Slice(ciphertext.Length - TagSize);

            ciphertext = ciphertext.Slice(0, ciphertext.Length - TagSize);

            // Create the initial counter block
            nonce.CopyTo(this.blockJ_);

            // Verify the tags match
            GenerateAuthenticationTag(this.blockScratch_, ciphertext, associatedData);
            if (0 == Const.ConstantCompareSpans(this.blockScratch_, authenticationTag))
            {
                return(false);
            }

            // Decrypt the cipher text to output
            GCTR(output, this.blockJ_, 2, ciphertext);
            return(true);
        }
        /// <inheritdoc />
        public void EncodeServerKeyExchangeMessage(ByteSpan output, object privateKey)
        {
            RSA rsaPrivateKey = privateKey as RSA;

            if (rsaPrivateKey == null)
            {
                throw new ArgumentException("Invalid private key", nameof(privateKey));
            }

            output[0] = (byte)ECCurveType.NamedCurve;
            output.WriteBigEndian16((ushort)NamedCurve.x25519, 1);
            output[3] = (byte)X25519.KeySize;
            X25519.Func(output.Slice(4, X25519.KeySize), this.privateAgreementKey);

            // Hash the key parameters
            byte[] paramterDigest = this.sha256.ComputeHash(output.GetUnderlyingArray(), output.Offset, 4 + X25519.KeySize);

            // Sign the paramter digest
            RSAPKCS1SignatureFormatter signer = new RSAPKCS1SignatureFormatter(rsaPrivateKey);

            signer.SetHashAlgorithm("SHA256");
            ByteSpan signature = signer.CreateSignature(paramterDigest);

            Debug.Assert(signature.Length == rsaPrivateKey.KeySize / 8);
            output[4 + X25519.KeySize] = (byte)HashAlgorithm.Sha256;
            output[5 + X25519.KeySize] = (byte)SignatureAlgorithm.RSA;
            output.Slice(6 + X25519.KeySize).WriteBigEndian16((ushort)signature.Length);
            signature.CopyTo(output.Slice(8 + X25519.KeySize));
        }
Exemple #13
0
        /// <summary>
        /// Flush any queued application data packets
        /// </summary>
        private void FlushQueuedApplicationData()
        {
            foreach (ByteSpan queuedSpan in this.queuedApplicationData)
            {
                Record outgoingRecord = new Record();
                outgoingRecord.ContentType    = ContentType.ApplicationData;
                outgoingRecord.Epoch          = this.epoch;
                outgoingRecord.SequenceNumber = this.currentEpoch.NextOutgoingSequence;
                outgoingRecord.Length         = (ushort)this.currentEpoch.RecordProtection.GetEncryptedSize(queuedSpan.Length);
                ++this.currentEpoch.NextOutgoingSequence;

                // Encode the record to wire format
                ByteSpan packet = new byte[Record.Size + outgoingRecord.Length];
                ByteSpan writer = packet;
                outgoingRecord.Encode(writer);
                writer = writer.Slice(Record.Size);
                queuedSpan.CopyTo(writer);

                // Protect the record
                this.currentEpoch.RecordProtection.EncryptClientPlaintext(
                    packet.Slice(Record.Size, outgoingRecord.Length)
                    , packet.Slice(Record.Size, queuedSpan.Length)
                    , ref outgoingRecord
                    );

                base.WriteBytesToConnection(packet.GetUnderlyingArray(), packet.Length);
            }
            this.queuedApplicationData.Clear();
        }
Exemple #14
0
 public Utf8String(ByteSpan buffer)
 {
     _buffer = buffer;
     _bytes  = null;
     _index  = 0;
     _length = 0;
 }
        /// <summary>
        /// Parse a Handshake HelloVerifyRequest payload from wire
        /// format
        /// </summary>
        /// <returns>
        /// True if we successfully decode the HelloVerifyRequest
        /// message. Otherwise false.
        /// </returns>
        public static bool Parse(out HelloVerifyRequest result, ByteSpan span)
        {
            result = new HelloVerifyRequest();
            if (span.Length < 3)
            {
                return(false);
            }

            ProtocolVersion serverVersion = (ProtocolVersion)span.ReadBigEndian16(0);

            if (serverVersion != ProtocolVersion.DTLS1_2)
            {
                return(false);
            }

            byte cookieSize = span[2];

            span = span.Slice(3);

            if (span.Length < cookieSize)
            {
                return(false);
            }

            result.Cookie = span;
            return(true);
        }
Exemple #16
0
        /// <summary>
        /// Expand a secret key
        /// </summary>
        /// <param name="output">Output span. Length determines how much data to generate</param>
        /// <param name="key">Original key to expand</param>
        /// <param name="label">Label (treated as a salt)</param>
        /// <param name="initialSeed">Seed for expansion (treated as a salt)</param>
        public static void ExpandSecret(ByteSpan output, ByteSpan key, ByteSpan label, ByteSpan initialSeed)
        {
            ByteSpan writer = output;

            byte[] roundSeed = new byte[label.Length + initialSeed.Length];
            label.CopyTo(roundSeed);
            initialSeed.CopyTo(roundSeed, label.Length);

            byte[] hashA = roundSeed;

            using (HMACSHA256 hmac = new HMACSHA256(key.ToArray()))
            {
                byte[] input = new byte[hmac.OutputBlockSize + roundSeed.Length];
                new ByteSpan(roundSeed).CopyTo(input, hmac.OutputBlockSize);

                while (writer.Length > 0)
                {
                    // Update hashA
                    hashA = hmac.ComputeHash(hashA);

                    // generate hash input
                    new ByteSpan(hashA).CopyTo(input);

                    ByteSpan roundOutput = hmac.ComputeHash(input);
                    if (roundOutput.Length > writer.Length)
                    {
                        roundOutput = roundOutput.Slice(0, writer.Length);
                    }

                    roundOutput.CopyTo(writer);
                    writer = writer.Slice(roundOutput.Length);
                }
            }
        }
        /// <summary>
        /// Parse a Handshake ServerHello payload from wire format
        /// </summary>
        /// <returns>
        /// True if we successfully decode the ServerHello
        /// message. Otherwise false.
        /// </returns>
        public static bool Parse(out ServerHello result, ByteSpan span)
        {
            result = new ServerHello();
            if (span.Length < Size)
            {
                return(false);
            }

            ProtocolVersion serverVersion = (ProtocolVersion)span.ReadBigEndian16();

            span = span.Slice(2);

            result.Random = span.Slice(0, Dtls.Random.Size);
            span          = span.Slice(Dtls.Random.Size);

            byte sessionKeySize = span[0];

            span = span.Slice(1 + sessionKeySize);

            result.CipherSuite = (CipherSuite)span.ReadBigEndian16();
            span = span.Slice(2);

            CompressionMethod compressionMethod = (CompressionMethod)span[0];

            if (compressionMethod != CompressionMethod.Null)
            {
                return(false);
            }

            return(true);
        }
        public static bool TryDecodeCodePoint(ByteSpan buffer, out UnicodeCodePoint codePoint, out int encodedBytes)
        {
            if (buffer.Length == 0)
            {
                codePoint = default(UnicodeCodePoint);
                encodedBytes = default(int);
                return false;
            }

            byte first = buffer[0];
            if (!TryGetFirstByteCodePointValue(first, out codePoint, out encodedBytes))
                return false;

            if (buffer.Length < encodedBytes)
                return false;

            // TODO: Should we manually inline this for values 1-4 or will compiler do this for us?
            for (int i = 1; i < encodedBytes; i++)
            {
                if (!TryReadCodePointByte(buffer[i], ref codePoint))
                    return false;
            }

            return true;
        }
Exemple #19
0
        public unsafe void ByteSpanEqualsTestsTwoDifferentInstancesOfBuffersWithOneValueDifferent()
        {
            const int bufferLength = 128;

            byte[] buffer1 = new byte[bufferLength];
            byte[] buffer2 = new byte[bufferLength];

            for (int i = 0; i < bufferLength; i++)
            {
                buffer1[i] = (byte)(bufferLength + 1 - i);
                buffer2[i] = (byte)(bufferLength + 1 - i);
            }

            fixed(byte *buffer1pinned = buffer1)
            fixed(byte *buffer2pinned = buffer2)
            {
                ByteSpan b1 = new ByteSpan(buffer1pinned, bufferLength);
                ByteSpan b2 = new ByteSpan(buffer2pinned, bufferLength);

                for (int i = 0; i < bufferLength; i++)
                {
                    for (int diffPosition = i; diffPosition < bufferLength; diffPosition++)
                    {
                        buffer1[diffPosition] = unchecked ((byte)(buffer1[diffPosition] + 1));
                        Assert.False(b1.Slice(i).Equals(b2.Slice(i)));
                    }
                }
            }
        }
Exemple #20
0
        internal static bool TryParseHttpVersion(ByteSpan buffer, out Utf8String httpVersion, out int parsedBytes)
        {
            var versionSpan = buffer.SliceTo(HttpRequestReader.s_CR, HttpRequestReader.s_LF, out parsedBytes);

            httpVersion = new Utf8String(versionSpan);
            return(parsedBytes != 0);
        }
Exemple #21
0
        internal static bool TryParseRequestUri(ByteSpan buffer, out Utf8String requestUri, out int parsedBytes)
        {
            var uriSpan = buffer.SliceTo(HttpRequestReader.s_SP, out parsedBytes);

            requestUri = new Utf8String(uriSpan);
            return(parsedBytes != 0);
        }
Exemple #22
0
        internal static bool TryParseRequestLine(ByteSpan buffer, out HttpRequestLine requestLine, out int totalParsedBytes)
        {
            requestLine      = new HttpRequestLine();
            totalParsedBytes = 0;

            var reader = new HttpRequestReader();

            reader.Buffer = buffer;

            requestLine.Method = reader.ReadMethod();
            if (requestLine.Method == HttpMethod.Unknown)
            {
                return(false);
            }

            requestLine.RequestUri = reader.ReadRequestUri();
            if (requestLine.RequestUri.Length == 0)
            {
                return(false);
            }

            requestLine.Version = reader.ReadHttpVersion();
            if (requestLine.Version == HttpVersion.Unknown)
            {
                return(false);
            }

            totalParsedBytes = buffer.Length - reader.Buffer.Length;
            return(true);
        }
 /// <summary>
 /// Clear a span's contents to zero
 /// </summary>
 public static void SecureClear(this ByteSpan span)
 {
     if (span.Length > 0)
     {
         Array.Clear(span.GetUnderlyingArray(), span.Offset, span.Length);
     }
 }
Exemple #24
0
 public Utf8Span ReadHeader()
 {
     int parsedBytes;
     var header = SliceTo(Buffer, s_CR, s_LF, out parsedBytes);
     Buffer = Buffer.Slice(parsedBytes);
     return new Utf8Span(header);
 }
Exemple #25
0
        /// <summary>
        /// Creates a new instance of an AEAD_AES128_GCM cipher
        /// </summary>
        /// <param name="key">Symmetric key</param>
        public Aes128Gcm(ByteSpan key)
        {
            if (key.Length != KeySize)
            {
                throw new ArgumentException("Invalid key length", nameof(key));
            }

            // Create the AES block cipher
            using (Aes aes = Aes.Create())
            {
                aes.KeySize   = 128;
                aes.KeySize   = 128;
                aes.BlockSize = 128;
                aes.Mode      = CipherMode.ECB;
                aes.Padding   = PaddingMode.Zeros;
                aes.Key       = key.ToArray();

                this.encryptor_ = aes.CreateEncryptor();
            }

            // Allocate scratch space
            ByteSpan scratchSpace = new byte[96];

            this.hashSubkey_   = scratchSpace.Slice(0, 16);
            this.blockJ_       = scratchSpace.Slice(16, 16);
            this.blockS_       = scratchSpace.Slice(32, 16);
            this.blockZ_       = scratchSpace.Slice(48, 16);
            this.blockV_       = scratchSpace.Slice(64, 16);
            this.blockScratch_ = scratchSpace.Slice(80, 16);

            // Create the GHASH subkey by encrypting the 0-block
            this.encryptor_.TransformBlock(this.hashSubkey_.GetUnderlyingArray(), this.hashSubkey_.Offset, this.hashSubkey_.Length, this.hashSubkey_.GetUnderlyingArray(), this.hashSubkey_.Offset);
        }
        /// <summary>
        /// Encode Handshake ClientHello payload to wire format
        /// </summary>
        public void Encode(ByteSpan span)
        {
            span.WriteBigEndian16((ushort)ProtocolVersion.DTLS1_2);
            span = span.Slice(2);

            Debug.Assert(this.Random.Length == Dtls.Random.Size);
            this.Random.CopyTo(span);
            span = span.Slice(Dtls.Random.Size);

            // Do not encode session ids
            span[0] = (byte)0;
            span    = span.Slice(1);

            span[0] = (byte)this.Cookie.Length;
            this.Cookie.CopyTo(span.Slice(1));
            span = span.Slice(1 + this.Cookie.Length);

            span.WriteBigEndian16((ushort)this.CipherSuites.Length);
            this.CipherSuites.CopyTo(span.Slice(2));
            span = span.Slice(2 + this.CipherSuites.Length);

            span[0] = 1;
            span[1] = (byte)CompressionMethod.Null;
            span    = span.Slice(2);

            // Extensions size
            span.WriteBigEndian16((ushort)(6 + this.SupportedCurves.Length));
            span = span.Slice(2);

            // Supported curves extension
            span.WriteBigEndian16((ushort)ExtensionType.EllipticCurves);
            span.WriteBigEndian16((ushort)(2 + this.SupportedCurves.Length), 2);
            span.WriteBigEndian16((ushort)this.SupportedCurves.Length, 4);
            this.SupportedCurves.CopyTo(span.Slice(6));
        }
        // Run the GHASH function
        void GHASH(ByteSpan output, ByteSpan data, int numBlocks)
        {
            ///TODO(mendsley): See Ref[6] for opitmizations of GHASH on both hardware and software
            ///
            ///[6] D. McGrew, J. Viega, The Galois/Counter Mode of Operation (GCM), Natl. Inst. Stand.
            ///Technol. [Web page], http://www.csrc.nist.gov/groups/ST/toolkit/BCM/documents/
            ///proposedmodes / gcm / gcm - revised - spec.pdf, May 31, 2005.

            Debug.Assert(output.Length == 16);
            Debug.Assert(data.Length >= numBlocks * 16);

            int readIndex = 0;

            for (int ii = 0; ii != numBlocks; ++ii)
            {
                for (int jj = 0; jj != 16; ++jj, ++readIndex)
                {
                    // Y[ii-1] xor X[ii]
                    output[jj] ^= data[readIndex];
                }

                // Y[ii] = (Y[ii-1] xor X[ii]) · H
                MultiplyGF128Elements(output, this.hashSubkey_, this.blockZ_, this.blockV_);
            }
        }
 // Set the contents of a span to all zero
 static void SetSpanToZeros(ByteSpan span)
 {
     for (int ii = 0, nn = span.Length; ii != nn; ++ii)
     {
         span[ii] = 0;
     }
 }
Exemple #29
0
        public bool TryCopyTo(ref ByteSpan span)
        {
            if (IsRaw)
            {
                var len = (int)Length;
                if (len > span.Length)
                {
                    goto fail;
                }
                Operand.Data.Sequence.CopyTo(span.Slice(0, len));
                span = span.Slice(len);
            }
            else
            {
                if (!Operand.TryCopyTo(ref span))
                {
                    goto fail;
                }
            }

            return(true);

fail:
            return(false);
        }
        // Run the GCTR cipher
        void GCTR(ByteSpan output, ByteSpan counterBlock, uint counter, ByteSpan data)
        {
            Debug.Assert(counterBlock.Length == 16);
            Debug.Assert(output.Length >= data.Length);

            // Loop through plaintext blocks
            int writeIndex = 0;
            int numBlocks  = (data.Length + 15) / 16;

            for (int ii = 0; ii != numBlocks; ++ii)
            {
                // Encode counter into block
                // CB[1] = J0
                // CB[i] = inc[32](CB[i-1])
                counterBlock.WriteBigEndian32(counter, 12);
                ++counter;

                // CIPH[k](CB[i])
                this.encryptor_.EncryptBlock(counterBlock.Slice(0, 16), this.blockScratch_);

                // Y[i] = X[i] xor CIPH[k](CB[i])
                for (int jj = 0; jj != 16 && writeIndex < data.Length; ++jj, ++writeIndex)
                {
                    output[writeIndex] = (byte)(data[writeIndex] ^ this.blockScratch_[jj]);
                }
            }
        }
Exemple #31
0
 protected virtual void QueueRawData(ByteSpan span, IPEndPoint remoteEndPoint)
 {
     this.sendQueue.TryAdd(new SendMessageInfo()
     {
         Span = span, Recipient = remoteEndPoint
     });
 }
Exemple #32
0
        public static bool TryEncodeCodePoint(UnicodeCodePoint codePoint, ByteSpan buffer, out int encodedBytes)
        {
            encodedBytes = GetNumberOfEncodedBytes(codePoint);
            if (encodedBytes > buffer.Length)
                return false;

            switch (encodedBytes)
            {
                case 1:
                    buffer[0] = (byte)(mask_0111_1111 & codePoint.Value);
                    return true;
                case 2:
                    buffer[0] = (byte)(((codePoint.Value >> 6) & mask_0001_1111) | mask_1100_0000);
                    buffer[1] = (byte)(((codePoint.Value >> 0) & mask_0011_1111) | mask_1000_0000);
                    return true;
                case 3:
                    buffer[0] = (byte)(((codePoint.Value >> 12) & mask_0000_1111) | mask_1110_0000);
                    buffer[1] = (byte)(((codePoint.Value >> 6) & mask_0011_1111) | mask_1000_0000);
                    buffer[2] = (byte)(((codePoint.Value >> 0) & mask_0011_1111) | mask_1000_0000);
                    return true;
                case 4:
                    buffer[0] = (byte)(((codePoint.Value >> 18) & mask_0000_0111) | mask_1111_0000);
                    buffer[1] = (byte)(((codePoint.Value >> 12) & mask_0011_1111) | mask_1000_0000);
                    buffer[2] = (byte)(((codePoint.Value >> 6) & mask_0011_1111) | mask_1000_0000);
                    buffer[3] = (byte)(((codePoint.Value >> 0) & mask_0011_1111) | mask_1000_0000);
                    return true;
                default:
                    return false;
            }
        }
Exemple #33
0
        /// <summary>
        /// Create a new instance of the AES128_GCM record protection
        /// </summary>
        /// <param name="masterSecret">Shared secret</param>
        /// <param name="serverRandom">Server random data</param>
        /// <param name="clientRandom">Client random data</param>
        public Aes128GcmRecordProtection(ByteSpan masterSecret, ByteSpan serverRandom, ByteSpan clientRandom)
        {
            ByteSpan combinedRandom = new byte[serverRandom.Length + clientRandom.Length];

            serverRandom.CopyTo(combinedRandom);
            clientRandom.CopyTo(combinedRandom.Slice(serverRandom.Length));

            // Expand master_secret to encryption keys
            const int ExpandedSize = 0
                                     + 0                 // mac_key_length
                                     + 0                 // mac_key_length
                                     + Aes128Gcm.KeySize // enc_key_length
                                     + Aes128Gcm.KeySize // enc_key_length
                                     + ImplicitNonceSize // fixed_iv_length
                                     + ImplicitNonceSize // fixed_iv_length
            ;

            ByteSpan expandedKey = new byte[ExpandedSize];

            PrfSha256.ExpandSecret(expandedKey, masterSecret, PrfLabel.KEY_EXPANSION, combinedRandom);

            ByteSpan clientWriteKey = expandedKey.Slice(0, Aes128Gcm.KeySize);
            ByteSpan serverWriteKey = expandedKey.Slice(Aes128Gcm.KeySize, Aes128Gcm.KeySize);

            this.clientWriteIV = expandedKey.Slice(2 * Aes128Gcm.KeySize, ImplicitNonceSize);
            this.serverWriteIV = expandedKey.Slice(2 * Aes128Gcm.KeySize + ImplicitNonceSize, ImplicitNonceSize);

            this.serverWriteCipher = new Aes128Gcm(serverWriteKey);
            this.clientWriteCipher = new Aes128Gcm(clientWriteKey);
        }
Exemple #34
0
 public int BufferIndexFromSpanAddress(ref ByteSpan span)
 {
     var buffer = (ulong)span._data;
     var firstBuffer = (ulong)_memory;
     var offset = buffer - firstBuffer;
     var index = offset / (ulong)_bufferSizeInBytes;
     return (int)index;
 }
Exemple #35
0
 public void Return(ref ByteSpan span)
 {
     int spanIndex = BufferIndexFromSpanAddress(ref span);
     span._data = null;
     if (Interlocked.CompareExchange(ref _freeList[spanIndex], 0, 1) != 1) {
         throw new InvalidOperationException("this span has been already returned");
     }
     if (spanIndex < _nextFree) {
         _nextFree = spanIndex;
     }
 }
 public unsafe void ParseUtf8UInt32()
 {
     byte[] textBuffer = Encoding.UTF8.GetBytes("1258");
     fixed(byte * ptextBuffer = textBuffer) {
         uint value;
         int bytesConsumed;
         ByteSpan text = new ByteSpan(ptextBuffer, textBuffer.Length);
         Assert.True(InvariantParser.TryParse(text, FormattingData.Encoding.Utf8, out value, out bytesConsumed));
         Assert.Equal(1258U, value);
         Assert.Equal(textBuffer.Length, bytesConsumed);
     }
 }
Exemple #37
0
        public static bool TryParse(ByteSpan text, FormattingData.Encoding encoding, out uint value, out int bytesConsumed)
        {
            Precondition.Require(text.Length > 0);
            Precondition.Require(encoding == FormattingData.Encoding.Utf8 || text.Length > 1);

            value = 0;
            bytesConsumed = 0;

            if (text[0] == '0') {
                bytesConsumed = 1;
                if (encoding == FormattingData.Encoding.Utf16)
                {
                    return text[1] == 0;
                }
                return true;
            }

            for (int byteIndex = 0; byteIndex < text.Length; byteIndex++) {
                byte nextByte = text[byteIndex];
                if (nextByte < '0' || nextByte > '9') {
                    if (bytesConsumed == 0) {
                        value = default(uint);
                        return false;
                    }
                    else {
                        return true;
                    }
                }
                uint candidate = value * 10;
                candidate += (uint)nextByte - '0';
                if (candidate > value) {
                    value = candidate;
                }
                else {
                    return true;
                }
                bytesConsumed++;
                if (encoding == FormattingData.Encoding.Utf16)
                {
                    byteIndex++;
                    if(byteIndex >= text.Length || text[byteIndex] != 0)
                    {
                        return false;
                    }
                    bytesConsumed++;
                }
            }

            return true;
        }
        public unsafe Utf8EncodedCodePoint(char highSurrogate, char lowSurrogate)
            : this()
        {
            UnicodeCodePoint codePoint = (UnicodeCodePoint)(uint)char.ConvertToUtf32(highSurrogate, lowSurrogate);

            fixed (byte* encodedData = &_byte0)
            {
                ByteSpan buffer = new ByteSpan(encodedData, 4);
                if (!Utf8Encoder.TryEncodeCodePoint(codePoint, buffer, out _length))
                {
                    // TODO: Change exception type
                    throw new Exception("Internal error: this should never happen as codePoint should be within acceptable range");
                }
            }
        }
        public void Return(ByteSpan buffer)
        {
            int spanIndex = BufferIndexFromSpanAddress(ref buffer);

            if (spanIndex < 0 || spanIndex > _freeList.Length)
            {
                throw new InvalidOperationException("This buffer is not from this pool.");
            }

            if (Interlocked.CompareExchange(ref _freeList[spanIndex], 0, 1) != 1) {
                throw new InvalidOperationException("this buffer has been already returned.");
            }
            if (spanIndex < _nextFree) {
                _nextFree = spanIndex;
            }
        }
Exemple #40
0
        internal static bool TryParse(string text, int index, int count, out uint value, out int charsConsumed)
        {
            Precondition.Require(count > 0);
            Precondition.Require(text.Length >= index + count);

            unsafe
            {
                fixed(char* pText = text)
                {
                    char* pSubstring = pText + index;
                    var span = new ByteSpan((byte*)pSubstring, count << 1);
                    int bytesConsumed;
                    var result = TryParse(span, FormattingData.Encoding.Utf16, out value, out bytesConsumed);
                    charsConsumed = bytesConsumed << 1;
                    return result;
                }
            }
        }
        // TODO: Validate constructors if we decide to keep this class
        public unsafe Utf8EncodedCodePoint(char character)
            : this()
        {
            if (char.IsSurrogate(character))
            {
                throw new ArgumentOutOfRangeException("character", "Surrogate characters are not allowed");
            }

            UnicodeCodePoint codePoint = (UnicodeCodePoint)(uint)character;

            fixed (byte* encodedData = &_byte0)
            {
                ByteSpan buffer = new ByteSpan(encodedData, 4);
                if (!Utf8Encoder.TryEncodeCodePoint(codePoint, buffer, out _length))
                {
                    // TODO: Change exception type
                    throw new Exception("Internal error: this should never happen as codePoint is within acceptable range and is not surrogate");
                }
            }
        }
Exemple #42
0
 public static bool TryParseRequestLine(ByteSpan buffer, out HttpRequestLine requestLine)
 {
     int parsedBytes;
     return TryParseRequestLine(buffer, out requestLine, out parsedBytes);
 }
Exemple #43
0
        public static bool TryParseRequestLine(ByteSpan buffer, out HttpRequestLine requestLine, out int totalParsedBytes)
        {
            requestLine = new HttpRequestLine();
            totalParsedBytes = 0;

            var reader = new HttpRequestReader();
            reader.Buffer = buffer;

            requestLine.Method = reader.ReadMethod();
            if(requestLine.Method == HttpMethod.Unknown) { return false; }

            requestLine.RequestUri = reader.ReadRequestUri();
            if(requestLine.RequestUri.Length == 0) { return false; }

            requestLine.Version = reader.ReadHttpVersion();
            if (requestLine.Version == HttpVersion.Unknown) { return false; }

            totalParsedBytes = buffer.Length - reader.Buffer.Length;
            return true;
        }
Exemple #44
0
 public static bool TryParseHttpVersion(ByteSpan buffer, out Utf8Span httpVersion, out int parsedBytes)
 {
     var versionSpan = HttpRequestReader.SliceTo(buffer, HttpRequestReader.s_CR, HttpRequestReader.s_LF, out parsedBytes);
     httpVersion = new Utf8Span(versionSpan);
     return parsedBytes != 0;
 }
Exemple #45
0
        public static bool TryParseMethod(ByteSpan buffer, out HttpMethod method, out int parsedBytes)
        {
            if(buffer.StartsWith(s_Get.Bytes))
            {
                method = HttpMethod.Get;
                parsedBytes = s_Get.Length;
                return true;
            }

            if (buffer.StartsWith(s_Post.Bytes))
            {
                method = HttpMethod.Post;
                parsedBytes = s_Post.Length;
                return true;
            }

            if (buffer.StartsWith(s_Put.Bytes))
            {
                method = HttpMethod.Put;
                parsedBytes = s_Put.Length;
                return true;
            }

            if (buffer.StartsWith(s_Delete.Bytes))
            {
                method = HttpMethod.Delete;
                parsedBytes = s_Delete.Length;
                return true;
            }

            method = HttpMethod.Unknown;
            parsedBytes = 0;
            return false;
        }
Exemple #46
0
 protected abstract HttpServerBuffer CreateResponse(HttpRequestLine requestLine, ByteSpan headersAndBody);
Exemple #47
0
 public Utf8Span(ByteSpan bytes)
 {
     _bytes = bytes;
 }
Exemple #48
0
 public Utf8Span ReadRequestUri()
 {
     Utf8Span requestUri;
     int parsedBytes;
     if (!HttpRequestParser.TryParseRequestUri(Buffer, out requestUri, out parsedBytes))
     {
         return Utf8Span.Empty;
     }
     Buffer = Buffer.Slice(parsedBytes);
     return requestUri;
 }
Exemple #49
0
        public HttpVersion ReadHttpVersion()
        {
            ByteSpan oldBuffer = Buffer;
            Utf8Span version = ReadHttpVersionAsUtf8String();

            if (version.Equals(s_Http1_1))
            {
                return HttpVersion.V1_1;
            }
            else if (version.Equals(s_Http2_0))
            {
                return HttpVersion.V2_0;
            }
            else if (version.Equals(s_Http1_0))
            {
                return HttpVersion.V1_0;
            }
            else
            {
                Buffer = oldBuffer;
                return HttpVersion.Unknown;
            }
        }
Exemple #50
0
 void OnReadWindows(UVBuffer.Windows buffer, IntPtr bytesAvaliable)
 {
     // TODO: all branches need to release buffer, I think
     long bytesRead = bytesAvaliable.ToInt64();
     if (bytesRead == 0)
     {
         buffer.Dispose();
         return;
     }
     else if (bytesRead < 0)
     {
         var error = UVException.ErrorCodeToError((int)bytesRead);
         if (error == UVError.EOF)
         {
             OnEndOfStream();
             Dispose();
             buffer.Dispose();
         }
         else if(error == UVError.ECONNRESET)
         {
             Debug.Assert(buffer.Buffer == IntPtr.Zero && buffer.Length == 0);
             // no need to dispose
             // TODO: what should we do here?
         }
         else
         {
             Dispose();
             buffer.Dispose();
             throw new UVException((int)bytesRead);
         }
     }
     else
     {
         var readSlice = new ByteSpan((byte*)buffer.Buffer, (int)bytesRead);
         OnReadCompleted(readSlice);
         buffer.Dispose();
     }
 }
Exemple #51
0
 void OnReadUnix(UVBuffer.Unix buffer, IntPtr bytesAvaliable)
 {
     long bytesRead = bytesAvaliable.ToInt64();
     if (bytesRead == 0)
     {
         return;
     }
     else if (bytesRead < 0)
     {
         var error = UVException.ErrorCodeToError((int)bytesRead);
         if (error == UVError.EOF)
         {
             OnEndOfStream();
             Dispose();
         }
         else
         {
             Dispose();
             throw new UVException((int)bytesRead);
         }
     }
     else
     {
         var readSlice = new ByteSpan((byte*)buffer.Buffer, (int)bytesRead);
         OnReadCompleted(readSlice);
         buffer.Dispose();
     }
 }
Exemple #52
0
 void LogRestOfRequest(ByteSpan buffer)
 {
     HttpRequestReader reader = new HttpRequestReader();
     reader.Buffer = buffer;
     while (true)
     {
         var header = reader.ReadHeader();
         if (header.Length == 0) break;
         Log.LogMessage(Log.Level.Verbose, "\tHeader: {0}", header.ToString());
     }
     var messageBody = reader.Buffer;
     Log.LogMessage(Log.Level.Verbose, "\tBody bytecount: {0}", messageBody.Length);
 }
Exemple #53
0
        // Not Found
        protected virtual HttpServerBuffer CreateResponseFor404(HttpRequestLine requestLine, ByteSpan headersAndBody)
        {
            Log.LogMessage(Log.Level.Warning, "Request {0}, Response: 404 Not Found", requestLine);

            BufferFormatter formatter = new BufferFormatter(1024, FormattingData.InvariantUtf8);
            WriteCommonHeaders(formatter, @"HTTP/1.1 404 Not Found");
            formatter.Append(HttpNewline);
            return new HttpServerBuffer(formatter.Buffer, formatter.CommitedByteCount, BufferPool.Shared);
        }
Exemple #54
0
 // Bad Request
 protected virtual HttpServerBuffer CreateResponseFor400(ByteSpan receivedBytes)
 {
     BufferFormatter formatter = new BufferFormatter(1024, FormattingData.InvariantUtf8);
     WriteCommonHeaders(formatter, @"HTTP/1.1 400 Bad Request");
     formatter.Append(HttpNewline);
     return new HttpServerBuffer(formatter.Buffer, formatter.CommitedByteCount, BufferPool.Shared);
 }
Exemple #55
0
 public static bool TryParseRequestUri(ByteSpan buffer, out Utf8Span requestUri, out int parsedBytes)
 {
     var uriSpan = HttpRequestReader.SliceTo(buffer, HttpRequestReader.s_SP, out parsedBytes);
     requestUri = new Utf8Span(uriSpan);
     return parsedBytes != 0;
 }
Exemple #56
0
        internal static ByteSpan SliceTo(ByteSpan buffer, byte terminatorFirst, byte terminatorSecond, out int consumedBytes)
        {
            int index = 0;
            while (index < buffer.Length)
            {
                if (buffer[index] == terminatorFirst && buffer.Length > index + 1 && buffer[index + 1] == terminatorSecond)
                {
                    consumedBytes = index + 2;
                    return buffer.Slice(0, index);
                }
                index++;
            }

            consumedBytes = 0;
            unsafe
            {
                return new ByteSpan(null, 0); // TODO: Empty instance should be used
            }
        }
Exemple #57
0
 void OnReadCompleted(ByteSpan bytesRead)
 {
     if (ReadCompleted != null)
     {
         ReadCompleted(bytesRead);
     }
 }
Exemple #58
0
 Utf8Span ReadHttpVersionAsUtf8String()
 {
     Utf8Span httpVersion;
     int parsedBytes;
     if (!HttpRequestParser.TryParseHttpVersion(Buffer, out httpVersion, out parsedBytes))
     {
         return Utf8Span.Empty;
     }
     Buffer = Buffer.Slice(parsedBytes);
     return httpVersion;
 }
Exemple #59
0
 public HttpMethod ReadMethod()
 {
     HttpMethod method;
     int parsedBytes;
     if (!HttpRequestParser.TryParseMethod(Buffer, out method, out parsedBytes))
     {
         return HttpMethod.Unknown;
     }
     Buffer = Buffer.Slice(parsedBytes);
     return method;
 }
Exemple #60
0
        public unsafe void TryWrite(ByteSpan data)
        {
            EnsureNotDisposed();

            IntPtr ptrData = (IntPtr)data.UnsafeBuffer;
            if (IsUnix)
            {
                var buffer = new UVBuffer.Unix(ptrData, (uint)data.Length);
                UVException.ThrowIfError(UVInterop.uv_try_write(Handle, &buffer, 1));
            }
            else
            {
                var buffer = new UVBuffer.Windows(ptrData, (uint)data.Length);
                UVException.ThrowIfError(UVInterop.uv_try_write(Handle, &buffer, 1));
            }
        }