public void SetCipherSuite(CipherSuite suite, AsymmetricAlgorithm signAlgo) { CipherSuiteInfo info = SupportedCipherSuites.GetSuiteInfo(suite); if (info == null) { throw new NotSupportedException(); } _bulk_cipher = info.BulkCipherAlgorithm; _cipherType = info.CipherType; _enc_key_length = info.EncKeyLength; _block_length = info.BlockLength; _fixed_iv_length = info.FixedIVLength; _record_iv_length = info.RecordIVLength; _mac = info.MACAlgorithm; _mac_length = info.MACLength; _mac_key_length = info.MACKeyLength; _keyExchange = info.KeyExchangeAlgorithm; // TODO: TLS1.2spec ? switch (_prfType) { case PRFAlgorithm.MD5_AND_SHA1: _prf = new MD5_AND_SHA1(); break; case PRFAlgorithm.SSL3: _prf = new SSL3_PRF(this); break; default: throw new NotSupportedException(); } switch (_keyExchange) { case KeyExchangeAlgorithm.ECDHE_ECDSA: _keyExchanger = new ECDHE_ECDSA((openCrypto.EllipticCurve.Signature.ECDSA)signAlgo); break; case KeyExchangeAlgorithm.DHE_DSS: _keyExchanger = new DHE_DSS((DSACryptoServiceProvider)signAlgo); break; case KeyExchangeAlgorithm.RSA: _keyExchanger = new KeyExchange.RSA((RSACryptoServiceProvider)signAlgo); break; default: throw new NotImplementedException(); } }
void ProcessHandshake() { ClientHello clientHello = _recordLayer.Read() as ClientHello; if (clientHello == null) { throw new Exception(); } Console.WriteLine("[TLSServer] Receive ClientHello Version: {0}", clientHello.Version); Console.WriteLine("[TLSServer] CipherSuites"); for (int i = 0; i < clientHello.CipherSuites.Length; i++) { Console.WriteLine(" {0}", clientHello.CipherSuites[i]); } CipherSuite selected = _selector.Select(clientHello.CipherSuites); Console.WriteLine("[TLSServer] CipherSuite Selected. {0}", selected); if (selected == CipherSuite.NONE) { // Alertを送るべき? throw new Exception(); } CipherSuiteInfo selectedInfo = SupportedCipherSuites.GetSuiteInfo(selected); _sparams.SetVersion(clientHello.Version); _sparams.SetCipherSuite(selected, _signAlgo); _sparams.ClientRandom = clientHello.Random; _recordLayer.ProtocolVersion = clientHello.Version; byte[] serverRandom = new byte[RandomData.Size]; Extension[] serverExtensions = null; if (selectedInfo.IsECC) { serverExtensions = new Extension[] { new Extension(ExtensionType.EcPointFormats, new byte[] { 1, 0 }) } } ; RandomData.CreateRandomData(serverRandom, 0); _sparams.ServerRandom = serverRandom; ServerHello serverHello = new ServerHello(clientHello.Version, serverRandom, Utility.EmptyByteArray, selected, CompressionMethod.Null, serverExtensions); _recordLayer.Write(serverHello); Certificate serverCert = new Certificate(_certs); _recordLayer.Write(serverCert); if (Utility.IsNeedServerKeyExchangeMessage(_states.SecurityParameters.KeyExchangeAlgorithm)) { ServerKeyExchange serverExchange = new ServerKeyExchange(_sparams); _recordLayer.Write(serverExchange); } _recordLayer.Write(new ServerHelloDone()); TLSMessage msg = _recordLayer.Read(); ClientKeyExchange clientExchange = (ClientKeyExchange)msg; clientExchange.ComputeServerMasterSecret(_sparams); Console.WriteLine("MasterSecret"); Utility.Dump(_sparams.MasterSecret); _sparams.ComputeKeyBlock(); ChangeCipherSpec changeCipherSpec = (ChangeCipherSpec)_recordLayer.Read(); _recordLayer.EnableReceiveCipher(_sparams.CreateServerDecryptor(), _sparams.CreateClientWriteHMAC()); Finished finished = (Finished)_recordLayer.Read(); Console.WriteLine("VerifyData"); Utility.Dump(finished.VerifyData); Console.WriteLine("Computed VerifyData"); byte[] verifyData = _sparams.ComputeFinishedVerifyData(false); Utility.Dump(verifyData); if (!Utility.Equals(finished.VerifyData, 0, verifyData, 0, verifyData.Length)) { throw new Exception(); } _recordLayer.Write(ChangeCipherSpec.Instance); _recordLayer.EnableSendCipher(_sparams.CreateServerEncryptor(), _sparams.CreateServerWriteHMAC()); _recordLayer.ComputeHandshakeHash(true); verifyData = _sparams.ComputeFinishedVerifyData(true); Console.WriteLine("Finished VerifyData"); Utility.Dump(verifyData); finished = new Finished(_recordLayer.ProtocolVersion, verifyData); _recordLayer.Write(finished); }