TLSMessage ReadPlainText(ContentType type, ProtocolVersion ver, int offset, ushort length) { switch (type) { case ContentType.Alert: return(new Alert((AlertLevel)_recvBuffer[offset], (AlertDescription)_recvBuffer[offset + 1])); case ContentType.ChangeCipherSpec: _recvSeq = 0; return(ChangeCipherSpec.Instance); case ContentType.Handshake: HandshakeType htype = (HandshakeType)_recvBuffer[offset]; uint hlength = BitConverterBE.ReadUInt24(_recvBuffer, offset + 1); if (hlength > MaxFragmentSize - 9) { throw new Exception(); // TODO } if (htype == HandshakeType.Finished) { ComputeHandshakeHash(false); } byte[] temp = new byte[length]; Buffer.BlockCopy(_recvBuffer, offset, temp, 0, length); _handshakePackets.Add(temp); return(Handshake.HandshakeMessage.Create(ver, htype, _recvBuffer, offset + 4, hlength)); case ContentType.ApplicationData: return(new ApplicationData(_recvBuffer, offset, length)); default: throw new Exception(); } }
ushort WriteCipherMessage(ContentType type, TLSMessage msg) { if (_ver == ProtocolVersion.TLS11 || _ver == ProtocolVersion.TLS12) { throw new NotImplementedException(); } int offset = 5; int init_offset = 5; ushort length = WritePlainMessage(type, msg, offset); _sendHMAC.Initialize(); if (_ver == ProtocolVersion.SSL30) { byte[] temp = new byte[11]; BitConverterBE.WriteUInt64(_sendSeq, temp, 0); temp[8] = (byte)type; BitConverterBE.WriteUInt16((ushort)length, temp, 9); _sendHMAC.TransformBlock(temp, 0, temp.Length, temp, 0); } else { byte[] temp = new byte[13]; BitConverterBE.WriteUInt64(_sendSeq, temp, 0); temp[8] = (byte)type; BitConverterBE.WriteUInt16((ushort)_ver, temp, 9); BitConverterBE.WriteUInt16((ushort)length, temp, 11); _sendHMAC.TransformBlock(temp, 0, temp.Length, temp, 0); } _sendHMAC.TransformBlock(_sendBuffer, offset, length, _sendBuffer, offset); _sendHMAC.TransformFinalBlock(Utility.EmptyByteArray, 0, 0); offset += length; Buffer.BlockCopy(_sendHMAC.Hash, 0, _sendBuffer, offset, _sparams.MACLength); Console.WriteLine("Record MAC"); Utility.Dump(_sendBuffer, offset, _sparams.MACLength); offset += _sparams.MACLength; byte padding_length = (byte)((_sparams.BlockLength - ((length + _sparams.MACLength + 1) % _sparams.BlockLength)) % _sparams.BlockLength); for (int i = 0; i < padding_length; i++) { _sendBuffer[offset++] = padding_length; } _sendBuffer[offset++] = padding_length; length += (ushort)(_sparams.MACLength + padding_length + 1); int encrypted = 0; while (encrypted < length) { int tmp = _encryptor.TransformBlock(_sendBuffer, init_offset + encrypted, length - encrypted, _sendBuffer, init_offset + encrypted); if (tmp == 0) { throw new CryptographicException(); } encrypted += tmp; } _sendSeq++; return(length); }
public TLSMessage Read() { ReadComplete(_headerBuffer, 0, _headerBuffer.Length); ContentType type = (ContentType)_headerBuffer[0]; ProtocolVersion ver; ushort length; if (type == ContentType.SSL20Compatible) { _handshakePackets.Add(new byte[] { _headerBuffer[2], _headerBuffer[3], _headerBuffer[4] }); length = (ushort)(_headerBuffer[1] - 3); if (_headerBuffer[2] != 1) { throw new Exception(); } ver = (ProtocolVersion)BitConverterBE.ReadUInt16(_headerBuffer, 3); } else { ver = (ProtocolVersion)BitConverterBE.ReadUInt16(_headerBuffer, 1); length = BitConverterBE.ReadUInt16(_headerBuffer, 3); } if (ver != ProtocolVersion.SSL30 && ver != ProtocolVersion.TLS10 && ver != ProtocolVersion.TLS11 && ver != ProtocolVersion.TLS12) { System.Diagnostics.Debug.WriteLine(string.Format("[RecordLayer] Unknown Version {0:x4}", (ushort)ver), DEBUG_CATEGORY); throw new Exception(); } if (length > MaxFragmentSize) { throw new Exception(); } ReadComplete(_recvBuffer, 0, length); // SSL2.0互換ClientHelloのみ例外的な処理 if (type == ContentType.SSL20Compatible) { byte[] tmp = new byte[length]; Buffer.BlockCopy(_recvBuffer, 0, tmp, 0, length); _handshakePackets.Add(tmp); return(Handshake.ClientHello.CreateFromSSL2CompatibleData(ver, _recvBuffer, 0, length)); } TLSMessage msg; if (_recordType == RecordState.PlainText || _recordType == RecordState.CipherTextSendOnly) { msg = ReadPlainText(type, ver, 0, length); } else { msg = ReadCipherText(type, ver, 0, length); } Console.WriteLine("[RecordLayer] Receive {0}", msg); return(msg); }
public static void CreateRandomData(byte[] buffer, int offset) { uint unixTime = (uint)((DateTime.UtcNow.Ticks - UnixTimeStart) / TimeSpan.TicksPerSecond); BitConverterBE.WriteUInt32(unixTime, buffer, offset); lock (_randBuffer) { RNG.GetBytes(_randBuffer); Buffer.BlockCopy(_randBuffer, 0, buffer, offset + 4, _randBuffer.Length); } }
void Write(ContentType type, TLSMessage msg) { Console.WriteLine("[RecordLayer] {0} {1}", type, msg); _sendBuffer[0] = (byte)type; BitConverterBE.WriteUInt16((ushort)_ver, _sendBuffer, 1); ushort size; if (_recordType == RecordState.PlainText || _recordType == RecordState.CipherTextReceiveOnly) { size = WritePlainMessage(type, msg, 5); } else { size = WriteCipherMessage(type, msg); } BitConverterBE.WriteUInt16(size, _sendBuffer, 3); _strm.Write(_sendBuffer, 0, size + 5); _strm.Flush(); }
TLSMessage ReadCipherText(ContentType type, ProtocolVersion ver, int offset, ushort length) { if (ver == ProtocolVersion.TLS11 && ver == ProtocolVersion.TLS12) { throw new NotImplementedException(); } Console.WriteLine("Encrypted"); Utility.Dump(_recvBuffer, offset, length); int decrypted = 0; while (decrypted < length) { int tmp = _decryptor.TransformBlock(_recvBuffer, offset + decrypted, length - decrypted, _recvBuffer, decrypted); if (tmp == 0) { throw new CryptographicException(); } decrypted += tmp; } Console.WriteLine("Decrypted"); Utility.Dump(_recvBuffer, 0, length); int fragLen = length - _recvBuffer[length - 1] - _sparams.MACLength - 1; if (fragLen < 0) { throw new Exception(); // Decrypt Error } Console.WriteLine("Fragment"); Utility.Dump(_recvBuffer, 0, fragLen); Console.WriteLine("HMAC"); Utility.Dump(_recvBuffer, fragLen, _sparams.MACLength); _recvHMAC.Initialize(); if (_ver == ProtocolVersion.SSL30) { byte[] temp = new byte[11]; BitConverterBE.WriteUInt64(_recvSeq, temp, 0); temp[8] = (byte)type; BitConverterBE.WriteUInt16((ushort)fragLen, temp, 9); _recvHMAC.TransformBlock(temp, 0, temp.Length, temp, 0); } else { byte[] temp = new byte[13]; BitConverterBE.WriteUInt64(_recvSeq, temp, 0); temp[8] = (byte)type; BitConverterBE.WriteUInt16((ushort)ver, temp, 9); BitConverterBE.WriteUInt16((ushort)fragLen, temp, 11); _recvHMAC.TransformBlock(temp, 0, temp.Length, temp, 0); } _recvHMAC.TransformBlock(_recvBuffer, 0, fragLen, _recvBuffer, 0); _recvHMAC.TransformFinalBlock(Utility.EmptyByteArray, 0, 0); Console.WriteLine("Comaputed HMAC"); Utility.Dump(_recvHMAC.Hash); _recvSeq++; return(ReadPlainText(type, ver, 0, (ushort)fragLen)); }