예제 #1
0
		protected SecureBuffer Expand (DisposeContext d, HMac hmac, string label, SecureBuffer seed, int length)
		{
			var blockSize = hmac.MacSize;
			var iterations = (int)(length / blockSize);
			if ((length % blockSize) > 0)
				iterations++;

			var resMacs = d.CreateBuffer (length);
			var resOff = 0;

			var tempBuf = d.CreateBuffer (blockSize);

			var labelBytes = Encoding.ASCII.GetBytes (label);

			for (int i = 1; i <= iterations; i++) {
				hmac.Reset ();
				if (i == 1) {
					hmac.TransformBlock (labelBytes, 0, labelBytes.Length);
					hmac.TransformBlock (seed.Buffer, 0, seed.Size);
				} else {
					hmac.TransformBlock (tempBuf.Buffer, 0, blockSize);
				}
				hmac.TransformFinalBlock (tempBuf.Buffer, 0, blockSize);

				hmac.Reset ();
				hmac.TransformBlock (tempBuf.Buffer, 0, blockSize);
				hmac.TransformBlock (labelBytes, 0, labelBytes.Length);
				hmac.TransformBlock (seed.Buffer, 0, seed.Size);
				hmac.TransformFinalBlock (resMacs.Buffer, resOff, Min (length - resOff, blockSize));
				resOff += blockSize;
			}

			return new SecureBuffer (resMacs.StealBuffer ());
		}
예제 #2
0
		static byte[] ComputeRecordMAC (TlsProtocolCode protocol, HMac hmac, ulong seqnum, ContentType contentType, IBufferOffsetSize fragment)
		{
			var header = new TlsBuffer (13);
			header.Write (seqnum);
			header.Write ((byte)contentType);
			header.Write ((short)protocol);
			header.Write ((short)fragment.Size);

			hmac.Reset ();
			hmac.TransformBlock (header.Buffer, 0, header.Size);
			hmac.TransformBlock (fragment.Buffer, fragment.Offset, fragment.Size);
			return hmac.TransformFinalBlock ();
		}
예제 #3
0
        static byte[] ComputeRecordMAC(TlsProtocolCode protocol, HMac hmac, ulong seqnum, ContentType contentType, IBufferOffsetSize fragment)
        {
            var header = new TlsBuffer(13);

            header.Write(seqnum);
            header.Write((byte)contentType);
            header.Write((short)protocol);
            header.Write((short)fragment.Size);

            hmac.Reset();
            hmac.TransformBlock(header.Buffer, 0, header.Size);
            hmac.TransformBlock(fragment.Buffer, fragment.Offset, fragment.Size);
            return(hmac.TransformFinalBlock());
        }
예제 #4
0
 public override void InitializeCipher()
 {
     // Create the HMAC algorithm
     if (IsClient)
     {
         ClientHMac = HMac.Create(Cipher.HashAlgorithmType, ClientWriteMac);
         ServerHMac = HMac.Create(Cipher.HashAlgorithmType, ServerWriteMac);
     }
     else
     {
         ServerHMac = HMac.Create(Cipher.HashAlgorithmType, ServerWriteMac);
         ClientHMac = HMac.Create(Cipher.HashAlgorithmType, ClientWriteMac);
     }
 }
예제 #5
0
        protected override SecureBuffer PRF(DisposeContext d, SecureBuffer secret, string label, SecureBuffer data, int length)
        {
            /* Secret Length calc exmplain from the RFC2246. Section 5
             *
             * S1 and S2 are the two halves of the secret and each is the same
             * length. S1 is taken from the first half of the secret, S2 from the
             * second half. Their length is created by rounding up the length of the
             * overall secret divided by two; thus, if the original secret is an odd
             * number of bytes long, the last byte of S1 will be the same as the
             * first byte of S2.
             */

            // split secret in 2
            int secretLen = secret.Size >> 1;

            // rounding up
            if ((secret.Size & 0x1) == 0x1)
            {
                secretLen++;
            }

            // Secret 1
            var secret1 = d.CreateBuffer(secretLen);

            Buffer.BlockCopy(secret.Buffer, 0, secret1.Buffer, 0, secretLen);

            // Secret2
            var secret2 = d.CreateBuffer(secretLen);

            Buffer.BlockCopy(secret.Buffer, (secret.Size - secretLen), secret2.Buffer, 0, secretLen);

            // Secret 1 processing
            var p_md5 = d.Add(Expand(d, HMac.Create(HashAlgorithmType.Md5, secret1), label, data, length));

            // Secret 2 processing
            var p_sha = d.Add(Expand(d, HMac.Create(HashAlgorithmType.Sha1, secret2), label, data, length));

            // Perfor XOR of both results
            var masterSecret = new SecureBuffer(length);

            for (int i = 0; i < length; i++)
            {
                masterSecret.Buffer[i] = (byte)(p_md5.Buffer[i] ^ p_sha.Buffer[i]);
            }

            return(masterSecret);
        }
예제 #6
0
 protected override SecureBuffer PRF(DisposeContext d, SecureBuffer secret, string label, SecureBuffer data, int length)
 {
     return(Expand(d, HMac.Create(HandshakeHashType, secret), label, data, length));
 }
예제 #7
0
 public BlockCipherWithHMac(bool isServer, TlsProtocolCode protocol, CipherSuite cipher)
     : base(isServer, protocol, cipher)
 {
     MacSize = HMac.GetMacSize(Cipher.HashAlgorithmType);
 }
예제 #8
0
        protected override int Decrypt(DisposeContext d, ContentType contentType, IBufferOffsetSize input, IBufferOffsetSize output)
        {
            if ((input.Size % BlockSize) != 0)
            {
                return(-1);
            }
            if (input.Size < MinExtraEncryptedBytes)
            {
                return(-1);
            }

            var plen = DecryptRecord(d, input, output);

            if (plen <= 0)
            {
                return(-1);
            }

            var padlen = output.Buffer [output.Offset + plen - 1];

                        #if DEBUG_FULL
            if (Cipher.EnableDebugging)
            {
                DebugHelper.WriteLine("DECRYPT: {0} {1} {2}", input.Size, plen, padlen);
                DebugHelper.WriteBuffer("DECRYPTED", output.Buffer, output.Offset, plen);
            }
                        #endif

            /*
             * VERY IMPORTANT:
             *
             * The Compiler and JIT *** MUST NOT *** optimize the following block of code.
             *
             * It is essential that the dummy checks and dummy calls be kept in place.
             * Also do not put any debugging code into that region as it would mess up with
             * the timing.
             *
             */

            #region The following block of code *** MUST NOT *** be optimized in any way

            if (MacSize + padlen + 1 > plen)
            {
                // Invalid padding: plaintext is not long enough.

                // First run a loop as if there were 256 bytes of padding, with a dummy check.
                int ok = -1;
                for (int i = 0; i < 256; i++)
                {
                    if (output.Buffer [i % output.Size] != padlen)
                    {
                        ok--;
                    }
                }

                // Now assume there's no padding, compute the MAC over the entire buffer.
                var first      = new BufferOffsetSize(output.Buffer, output.Offset, plen - MacSize);
                var invalidMac = ComputeRecordMAC(contentType, first);

                // Constant-time compare - this will always fail, TlsBuffer.ConstantTimeCompare() will return a negative value on error.
                ok += TlsBuffer.ConstantTimeCompare(invalidMac, 0, invalidMac.Length, output.Buffer, output.Offset + plen - MacSize, MacSize);
                return(ok);
            }
            else
            {
                int ok           = 0;
                var resultLength = plen - padlen - MacSize - 1;
                for (int i = 0; i < padlen; i++)
                {
                    if (output.Buffer [output.Offset + resultLength + MacSize + i] != padlen)
                    {
                        ok--;
                    }
                }

                var dummyOk  = ok;
                var dummyLen = 256 - padlen - 1;
                for (int i = 0; i < dummyLen; i++)
                {
                    if (output.Buffer [i % output.Size] != padlen)
                    {
                        dummyOk--;
                    }
                }

                if (ok < 0)
                {
                    // Now assume there's no padding, compute the MAC over the entire buffer.
                    var first      = new BufferOffsetSize(output.Buffer, output.Offset, plen - MacSize);
                    var invalidMac = ComputeRecordMAC(contentType, first);

                    // Constant-time compare - this will always fail, TlsBuffer.ConstantTimeCompare() will return a negative value on error.
                    ok += TlsBuffer.ConstantTimeCompare(invalidMac, 0, invalidMac.Length, output.Buffer, output.Offset + plen - MacSize, MacSize);
                    return(ok);
                }
                else
                {
                    var first    = new BufferOffsetSize(output.Buffer, output.Offset, resultLength);
                    var checkMac = ComputeRecordMAC(contentType, first);

                    var L1 = 13 + plen - MacSize;
                    var L2 = 13 + plen - padlen - 1 - MacSize;

                    var additional = ((L1 - 55) / 64) - ((L2 - 55) / 64);
                    if (additional > 0)
                    {
                        var algorithm = HMac.CreateHash(Cipher.HashAlgorithmType);
                        for (int i = 0; i < additional; i++)
                        {
                            algorithm.TransformBlock(input.Buffer, input.Offset, BlockSize, null, 0);
                        }
                    }

                    ok += TlsBuffer.ConstantTimeCompare(checkMac, 0, checkMac.Length, output.Buffer, output.Offset + resultLength, MacSize);
                    if (ok == 0)
                    {
                        ok = resultLength;
                    }
                    return(ok);
                }
            }

            #endregion
        }
예제 #9
0
		protected SecureBuffer Expand (DisposeContext d, HMac hmac, string label, SecureBuffer seed, int length)
		{
			var blockSize = hmac.MacSize;
			var iterations = (int)(length / blockSize);
			if ((length % blockSize) > 0)
				iterations++;

			var resMacs = d.CreateBuffer (length);
			var resOff = 0;

			var tempBuf = d.CreateBuffer (blockSize);

			var labelBytes = Encoding.ASCII.GetBytes (label);

			for (int i = 1; i <= iterations; i++) {
				hmac.Reset ();
				if (i == 1) {
					hmac.TransformBlock (labelBytes, 0, labelBytes.Length);
					hmac.TransformBlock (seed.Buffer, 0, seed.Size);
				} else {
					hmac.TransformBlock (tempBuf.Buffer, 0, blockSize);
				}
				hmac.TransformFinalBlock (tempBuf.Buffer, 0, blockSize);

				hmac.Reset ();
				hmac.TransformBlock (tempBuf.Buffer, 0, blockSize);
				hmac.TransformBlock (labelBytes, 0, labelBytes.Length);
				hmac.TransformBlock (seed.Buffer, 0, seed.Size);
				hmac.TransformFinalBlock (resMacs.Buffer, resOff, Min (length - resOff, blockSize));
				resOff += blockSize;
			}

			return new SecureBuffer (resMacs.StealBuffer ());
		}