Result ChangeCipherSpecAndFinished() { if (State == TLSSessionState.Client_Finished) { var clienthello_clientfinish = GetHandshakeMessages(); var finishedVerify = _params.Cipher.GetVerifyData("server finished", clienthello_clientfinish); var finishedMessage = new byte[] { 0x14, 0x00, 0x00, 0x0C }.Concat(finishedVerify).ToArray(); var macSeed = Utils.GetMacSeed(_sendSeqNum, (byte)RecordType.Handshake, finishedMessage); var myMac = _params.Cipher.ServerMessageAuthCode(macSeed); var finished = new List <byte>(); finished.AddRange(finishedMessage); finished.AddRange(myMac); var serverIv = Utils.Random(16); var encryptedFinished = _params.Cipher.BulkEncrypt(finished.ToArray(), serverIv); var serverFinishFragment = new Handshakes.EncryptedFragment(serverIv.Concat(encryptedFinished).ToArray()); var changeCipherRecord = new Records.ChangeCipherSpec(); var serverFinishRecord = new Records.Handshake(new[] { serverFinishFragment }); _sendSeqNum++; State = TLSSessionState.Server_Finished; return(new PacketResult(new Records.TLSRecord[] { changeCipherRecord, serverFinishRecord })); } else { return(Result.FatalAlert(AlertDescription.unexpected_message, $"State [{State}] check failed on ChangeCipherSpecAndFinished")); } }
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")); } }