Result Fragment_EncryptedHandshake(Handshakes.EncryptedFragment frag) { if (State == TLSSessionState.Client_ChangeCipherSpec) { var encrypt = frag.EncryptedData; var decryptedBytes = _params.Cipher.BulkDecrypt(encrypt, frag.IV); // 14 00 00 0C // 12-bytes-verify-data // 32-bytes-mac // 15-bytes-padding // 0x0F(padding-length) if (decryptedBytes[0] == 0x14 && Utils.ToUInt24(decryptedBytes, 1) == 12) { var fragWithoutMac = new Handshakes.Fragment(decryptedBytes.Take(4 + _params.Cipher.VerifyDataLength).ToArray()); AppendHandshakeMessages(fragWithoutMac); var fragWithMac = new Handshakes.Fragment(decryptedBytes); return(Fragment_Handshake(fragWithMac)); } else { return(Result.FatalAlert(AlertDescription.decrypt_error, $"invalid Client_EncryptedHandshake message")); } } else { return(Result.FatalAlert(AlertDescription.unexpected_message, $"State [{State}] check failed on Client_EncryptedHandshake message")); } }
protected Result Fragment_Handshake(Handshakes.Fragment frag) { LogSessionInfo(frag.Body); if (frag.Body is Fragments.ClientHello ch) { return(Fragment_ClientHello(ch)); } else if (frag.Body is Fragments.Certificate cert) { return(Fragment_ClientCertificate(cert)); } else if (frag.Body is Fragments.CertificateVerify certver) { return(Fragment_ClientCertificateVerify(certver)); } else if (frag.Body is Fragments.ClientKeyExchange cke) { return(Fragment_ClientKeyExchange(cke)); } else if (frag.Body is Fragments.Finished cf) { return(Fragment_ClientFinished(cf)); } else if (frag.Body is Fragments.KeyUpdate ku) { return(Fragment_ClientKeyUpdate(ku)); } else { return(Result.FatalAlert(AlertDescription.unexpected_message, $"Unhandled TLS HandshakeFragment.Body {frag.Body.GetType().Name}")); } }
Result Fragment_ClientHello_New(Fragments.ClientHello frag) { var ecdhpub = GeneratePubKey(); var extensions = new TLS.Extensions.Extension[] { new TLS.Extensions.KeyShare(_params.KeyShare.Group, ecdhpub), new TLS.Extensions.SupportedVersions(ProtocolVersion.TLSv1_3) }; var serverhelloBody = new Fragments.ServerHello(ProtocolVersion.TLSv1_2, _params.ServerRandom, _params.Session, _params.Cipher.CipherSuite, extensions); var serverhelloFragment = new Handshakes.Fragment(HandshakeType.Server_Hello, serverhelloBody); var encryptedExtFragment = new Handshakes.Fragment(HandshakeType.Encrypted_Extensions, new Fragments.EncryptedExtensions()); var certRequestFragment = new Handshakes.Fragment(HandshakeType.Certificate_Request, new Fragments.CertificateRequest(new byte[0])); var certificateFragment = new Handshakes.Fragment(HandshakeType.Certificate, new Fragments.Certificate(new[] { new X509Certificate2(_pubkeyfile) }, true)); // add [ServerHello] to list AppendHandshakeMessages(serverhelloFragment); // get (clienthello + serverhello) var clientHello_serverHello = GetHandshakeMessages(); // calculate shared_secret and HandshakeSecret (_params.Cipher as Ciphers.CipherSuiteBase13).KeyExchange(_params.KeyShare.KeyExchange, null, null, _params.ServerKey.Private); (_params.Cipher as Ciphers.CipherSuiteBase13).Calculate_HandshakeSecret(clientHello_serverHello); // add [EncryptedExtensions] to list AppendHandshakeMessages(encryptedExtFragment); // add [CertificateRequest] to list if (_params.ClientCertificateRequire) { AppendHandshakeMessages(certRequestFragment); } // add [Certificate] to list AppendHandshakeMessages(certificateFragment); // get (clienthello + serverhello + encryptedExtensions + certificate) var clientHello_cert = GetHandshakeMessages(); // get signature for CertificateVerify var signature = MakeCertificateVerifySignature(clientHello_cert); var certVerifyFragment = new Handshakes.Fragment(HandshakeType.Certificate_Verify, new Fragments.CertificateVerify(_params.SignatureAlgorithm, signature)); // add [CertificateVerify] to list AppendHandshakeMessages(certVerifyFragment); // get (clienthello + serverhello + encryptedExtensions + certificate + certificateVerify) var clientHello_certVerify = GetHandshakeMessages(); // get verifyData for ServerFinished var verifyData = (_params.Cipher as Ciphers.CipherSuiteBase13).GetVerifyData("finished", clientHello_certVerify); var finishFragment = new Handshakes.Fragment(HandshakeType.Finished, new Fragments.Finished(verifyData)); // add [ServerFinished] to list AppendHandshakeMessages(finishFragment); // before return, calculate ApplicationSecret // get (clienthello + serverhello + encryptedExtensions + certificate + certificateVerify + serverFinished) var clientHello_serverfinish = GetHandshakeMessages(); (_params.Cipher as Ciphers.CipherSuiteBase13).Calculate_ApplicationSecret(clientHello_serverfinish); // wrap 4 fragments in applicationRecord var plainPayload = new List <byte>(); plainPayload.AddRange(encryptedExtFragment.Data); if (_params.ClientCertificateRequire) { plainPayload.AddRange(certRequestFragment.Data); } plainPayload.AddRange(certificateFragment.Data); plainPayload.AddRange(certVerifyFragment.Data); plainPayload.AddRange(finishFragment.Data); // log info LogSessionInfo(serverhelloFragment.Body); LogSessionInfo(encryptedExtFragment.Body); if (_params.ClientCertificateRequire) { LogSessionInfo(certRequestFragment.Body); } LogSessionInfo(certificateFragment.Body); LogSessionInfo(certVerifyFragment.Body); LogSessionInfo(finishFragment.Body); var encryptedPayload = (_params.Cipher as Ciphers.CipherSuiteBase13).BulkEncrypt_Handshake(plainPayload.ToArray()); return(new PacketResult(new Records.TLSRecord[] { new Records.Handshake(new [] { serverhelloFragment }), // ServerHello new Records.ChangeCipherSpec(), // ChangeCipherSpec new Records.ApplicationData(encryptedPayload) // ApplicationData (EncryptedExtensions,Certificate,CertificateVerify,Finished) })); }
protected void AppendHandshakeMessages(Handshakes.Fragment fragment) { _handshakeMessages.Add(fragment); }