Example #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 ());
		}
Example #2
0
		void ComputeMasterSecret (DisposeContext d, TlsContext ctx, SecureBuffer preMasterSecret)
		{
			// Compute ClientRandom + ServerRandom
			int clen = ctx.HandshakeParameters.ClientRandom.Size;
			int slen = ctx.HandshakeParameters.ServerRandom.Size;
			int rlen = clen + slen;
			var cs = d.CreateBuffer (rlen);
			Buffer.BlockCopy (ctx.HandshakeParameters.ClientRandom.Buffer, 0, cs.Buffer, 0, clen);
			Buffer.BlockCopy (ctx.HandshakeParameters.ServerRandom.Buffer, 0, cs.Buffer, clen, slen);

			// Server Random + Client Random
			var sc = d.CreateBuffer (rlen);
			Buffer.BlockCopy (ctx.HandshakeParameters.ServerRandom.Buffer, 0, sc.Buffer, 0, slen);
			Buffer.BlockCopy (ctx.HandshakeParameters.ClientRandom.Buffer, 0, sc.Buffer, slen, clen);

			// Create master secret
			var crypto = ctx.Session.PendingCrypto;
			crypto.MasterSecret = crypto.Cipher.PRF.ComputeMasterSecret (preMasterSecret, cs);

			#if DEBUG_FULL
			if (ctx.EnableDebugging) {
				DebugHelper.WriteLine ("CS", cs);
				DebugHelper.WriteLine ("SC", sc);
				DebugHelper.WriteLine ("PRE-MASTER", preMasterSecret);
				DebugHelper.WriteLine ("MASTER SECRET", crypto.MasterSecret.Buffer);
			}
			#endif

			var keyBlock = crypto.Cipher.PRF.ComputeKeyExpansion (d, crypto.MasterSecret, sc, crypto.Cipher.KeyBlockSize);

			#if DEBUG_FULL
			if (ctx.EnableDebugging) {
				DebugHelper.WriteLine ("KEY BLOCK SIZE: {0}", crypto.Cipher.KeyBlockSize);
				DebugHelper.WriteLine ("KEY BLOCK", keyBlock.Buffer);
			}
			#endif

			crypto.ClientWriteMac = keyBlock.ReadSecureBuffer (crypto.Cipher.HashSize);
			crypto.ServerWriteMac = keyBlock.ReadSecureBuffer (crypto.Cipher.HashSize);
			crypto.ClientWriteKey = keyBlock.ReadSecureBuffer (crypto.Cipher.KeyMaterialSize);
			crypto.ServerWriteKey = keyBlock.ReadSecureBuffer (crypto.Cipher.KeyMaterialSize);

			if (crypto.Cipher.HasFixedIV) {
				crypto.ClientWriteIV = keyBlock.ReadSecureBuffer (crypto.Cipher.FixedIvSize);
				crypto.ServerWriteIV = keyBlock.ReadSecureBuffer (crypto.Cipher.FixedIvSize);

				#if DEBUG_FULL
				if (ctx.EnableDebugging) {
					DebugHelper.WriteLine ("CLIENT IV", crypto.ClientWriteIV.Buffer);
					DebugHelper.WriteLine ("SERVER IV", crypto.ServerWriteIV.Buffer);
				}
				#endif
			}
		}
        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);
        }
Example #4
0
        protected override int Decrypt(DisposeContext d, ContentType contentType, IBufferOffsetSize input, IBufferOffsetSize output)
        {
            var implicitNonce = IsClient ? ServerWriteIV : ClientWriteIV;
            var writeKey      = IsClient ? ServerWriteKey : ClientWriteKey;

                        #if DEBUG_FULL
            if (Cipher.EnableDebugging)
            {
                DebugHelper.WriteLine("FIXED IV", implicitNonce);
                DebugHelper.WriteLine("WRITE KEY", writeKey);
                DebugHelper.WriteLine("SEQUENCE: {0}", ReadSequenceNumber);
            }
                        #endif

            var length = input.Size - ExplicitNonceSize;

            var aad = new TlsBuffer(13);
            aad.Write(ReadSequenceNumber);
            aad.Write((byte)contentType);
            aad.Write((short)Protocol);
            aad.Write((short)(length - MacSize));

                        #if DEBUG_FULL
            if (Cipher.EnableDebugging)
            {
                DebugHelper.WriteFull("TAG", aad);
            }
                        #endif

            var gcm = new GcmBlockCipher(new AesEngine());
            var key = new KeyParameter(writeKey.Buffer);

            var nonce = d.CreateBuffer(ImplicitNonceSize + ExplicitNonceSize);
            Buffer.BlockCopy(implicitNonce.Buffer, 0, nonce.Buffer, 0, ImplicitNonceSize);
            Buffer.BlockCopy(input.Buffer, input.Offset, nonce.Buffer, ImplicitNonceSize, ExplicitNonceSize);

                        #if DEBUG_FULL
            if (Cipher.EnableDebugging)
            {
                DebugHelper.WriteLine("NONCE", nonce);
            }
                        #endif

            var parameters = new AeadParameters(key, 128, nonce.Buffer, aad.Buffer);
            gcm.Init(false, parameters);

            int ret;
            try {
                ret = gcm.ProcessBytes(input.Buffer, input.Offset + ExplicitNonceSize, length, output.Buffer, output.Offset);

                ret += gcm.DoFinal(output.Buffer, output.Offset + ret);
            } catch (CryptoException ex) {
                throw new TlsException(AlertDescription.BadRecordMAC, ex.Message);
            }

            return(ret);
        }
		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;
		}
Example #6
0
        void ComputeMasterSecret(DisposeContext d, TlsContext ctx, SecureBuffer preMasterSecret)
        {
            // Compute ClientRandom + ServerRandom
            int clen = ctx.HandshakeParameters.ClientRandom.Size;
            int slen = ctx.HandshakeParameters.ServerRandom.Size;
            int rlen = clen + slen;
            var cs   = d.CreateBuffer(rlen);

            Buffer.BlockCopy(ctx.HandshakeParameters.ClientRandom.Buffer, 0, cs.Buffer, 0, clen);
            Buffer.BlockCopy(ctx.HandshakeParameters.ServerRandom.Buffer, 0, cs.Buffer, clen, slen);

            // Server Random + Client Random
            var sc = d.CreateBuffer(rlen);

            Buffer.BlockCopy(ctx.HandshakeParameters.ServerRandom.Buffer, 0, sc.Buffer, 0, slen);
            Buffer.BlockCopy(ctx.HandshakeParameters.ClientRandom.Buffer, 0, sc.Buffer, slen, clen);

            // Create master secret
            var crypto = ctx.Session.PendingCrypto;

            crypto.MasterSecret = crypto.Cipher.PRF.ComputeMasterSecret(preMasterSecret, cs);

                        #if DEBUG_FULL
            if (ctx.EnableDebugging)
            {
                DebugHelper.WriteLine("CS", cs);
                DebugHelper.WriteLine("SC", sc);
                DebugHelper.WriteLine("PRE-MASTER", preMasterSecret);
                DebugHelper.WriteLine("MASTER SECRET", crypto.MasterSecret.Buffer);
            }
                        #endif

            var keyBlock = crypto.Cipher.PRF.ComputeKeyExpansion(d, crypto.MasterSecret, sc, crypto.Cipher.KeyBlockSize);

                        #if DEBUG_FULL
            if (ctx.EnableDebugging)
            {
                DebugHelper.WriteLine("KEY BLOCK SIZE: {0}", crypto.Cipher.KeyBlockSize);
                DebugHelper.WriteLine("KEY BLOCK", keyBlock.Buffer);
            }
                        #endif

            crypto.ClientWriteMac = keyBlock.ReadSecureBuffer(crypto.Cipher.HashSize);
            crypto.ServerWriteMac = keyBlock.ReadSecureBuffer(crypto.Cipher.HashSize);
            crypto.ClientWriteKey = keyBlock.ReadSecureBuffer(crypto.Cipher.KeyMaterialSize);
            crypto.ServerWriteKey = keyBlock.ReadSecureBuffer(crypto.Cipher.KeyMaterialSize);

            if (crypto.Cipher.HasFixedIV)
            {
                crypto.ClientWriteIV = keyBlock.ReadSecureBuffer(crypto.Cipher.FixedIvSize);
                crypto.ServerWriteIV = keyBlock.ReadSecureBuffer(crypto.Cipher.FixedIvSize);

                                #if DEBUG_FULL
                if (ctx.EnableDebugging)
                {
                    DebugHelper.WriteLine("CLIENT IV", crypto.ClientWriteIV.Buffer);
                    DebugHelper.WriteLine("SERVER IV", crypto.ServerWriteIV.Buffer);
                }
                                #endif
            }
        }
		protected override int Decrypt (DisposeContext d, ContentType contentType, IBufferOffsetSize input, IBufferOffsetSize output)
		{
			var implicitNonce = IsClient ? ServerWriteIV : ClientWriteIV;
			var writeKey = IsClient ? ServerWriteKey : ClientWriteKey;

			#if DEBUG_FULL
			if (Cipher.EnableDebugging) {
				DebugHelper.WriteLine ("FIXED IV", implicitNonce);
				DebugHelper.WriteLine ("WRITE KEY", writeKey);
				DebugHelper.WriteLine ("SEQUENCE: {0}", ReadSequenceNumber);
			}
			#endif

			var length = input.Size - ExplicitNonceSize;

			var aad = new TlsBuffer (13);
			aad.Write (ReadSequenceNumber);
			aad.Write ((byte)contentType);
			aad.Write ((short)Protocol);
			aad.Write ((short)(length - MacSize));

			#if DEBUG_FULL
			if (Cipher.EnableDebugging)
				DebugHelper.WriteFull ("TAG", aad);
			#endif

			var gcm = new GcmBlockCipher (new AesEngine ());
			var key = new KeyParameter (writeKey.Buffer);

			var nonce = d.CreateBuffer (ImplicitNonceSize + ExplicitNonceSize);
			Buffer.BlockCopy (implicitNonce.Buffer, 0, nonce.Buffer, 0, ImplicitNonceSize);
			Buffer.BlockCopy (input.Buffer, input.Offset, nonce.Buffer, ImplicitNonceSize, ExplicitNonceSize);

			#if DEBUG_FULL
			if (Cipher.EnableDebugging)
				DebugHelper.WriteLine ("NONCE", nonce);
			#endif

			var parameters = new AeadParameters (key, 128, nonce.Buffer, aad.Buffer);
			gcm.Init (false, parameters);

			int ret;
			try {
				ret = gcm.ProcessBytes (input.Buffer, input.Offset + ExplicitNonceSize, length, output.Buffer, output.Offset);

				ret += gcm.DoFinal (output.Buffer, output.Offset + ret);
			} catch (CryptoException ex) {
				throw new TlsException (AlertDescription.BadRecordMAC, ex.Message);
			}

			return ret;
		}
		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 ());
		}