protected byte[] InternalEncryptBytes(byte[] buffer, int offset, int size, ContentType type) // only accepts sizes of less than 16Kb; does not do any error checking { byte[] bytes = new byte[size]; Array.Copy(buffer, offset, bytes, 0, size); RecordMessage message = new RecordMessage(MessageType.PlainText, type, m_HandshakeLayer.GetVersion(), bytes); WrapMessage(message); return(message.ToBytes()); }
} //*/ protected void UnwrapMessage(RecordMessage message) { if (message.length != message.fragment.Length) throw new SslException(AlertDescription.IllegalParameter, "Message length is invalid."); byte[] remoteMac = null, decrypted = null, localMac = null; bool cipherError = false; // decrypt and verify the message if (m_BulkDecryption != null) { if (message.length <= m_RemoteHasher.HashSize / 8) throw new SslException(AlertDescription.DecodeError, "Message is too small."); if (message.length % m_BulkDecryption.OutputBlockSize != 0) throw new SslException(AlertDescription.DecryptError, "Message length is invalid."); // decrypt the message if (m_BulkDecryption.OutputBlockSize == 1) { // is stream cipher? decrypted = new byte[message.length]; m_BulkDecryption.TransformBlock(message.fragment, 0, message.length, decrypted, 0); remoteMac = new byte[m_RemoteHasher.HashSize / 8]; Array.Copy(decrypted, message.length - remoteMac.Length, remoteMac, 0, remoteMac.Length); message.fragment = new byte[decrypted.Length - remoteMac.Length]; Array.Copy(decrypted, 0, message.fragment, 0, message.fragment.Length); message.length = (ushort)message.fragment.Length; } else { // cipher is block cipher decrypted = new byte[message.fragment.Length]; m_BulkDecryption.TransformBlock(message.fragment, 0, decrypted.Length, decrypted, 0); byte padding = decrypted[decrypted.Length - 1]; if (message.length < padding + m_RemoteHasher.HashSize / 8 + 1) { cipherError = true; remoteMac = new byte[m_RemoteHasher.HashSize / 8]; } else { int realSize = (message.length - padding) - 1; remoteMac = new byte[m_RemoteHasher.HashSize / 8]; Array.Copy(decrypted, realSize - remoteMac.Length, remoteMac, 0, remoteMac.Length); message.fragment = new byte[realSize - remoteMac.Length]; Array.Copy(decrypted, 0, message.fragment, 0, message.fragment.Length); message.length = (ushort)message.fragment.Length; if (m_HandshakeLayer.GetProtocol() == SecureProtocol.Tls1) { // check padding for(int i = realSize; i < decrypted.Length; i++) { if (decrypted[i] != padding) { cipherError = true; } } } } } // calculate the MAC localMac = GetULongBytes(m_InputSequenceNumber); m_RemoteHasher.Initialize(); m_RemoteHasher.TransformBlock(localMac, 0, localMac.Length, localMac, 0); // seq_num + .. localMac = message.ToBytes(); if (m_HandshakeLayer.GetProtocol() == SecureProtocol.Tls1) { m_RemoteHasher.TransformFinalBlock(localMac, 0, localMac.Length); // .. + TLSCompressed.type + TLSCompressed.version + TLSCompressed.length + TLSCompressed.fragment } else if (m_HandshakeLayer.GetProtocol() == SecureProtocol.Ssl3) { m_RemoteHasher.TransformBlock(localMac, 0, 1, localMac, 0); // type m_RemoteHasher.TransformFinalBlock(localMac, 3, localMac.Length - 3); // length + fragment } else { throw new NotSupportedException("Only SSL3 and TLS1 are supported"); } localMac = m_RemoteHasher.Hash; // compare MACs for(int i = 0; i < remoteMac.Length; i++) { if (remoteMac[i] != localMac[i]) { cipherError = true; } } // throw cipher error, if necessary if (cipherError) throw new SslException(AlertDescription.BadRecordMac, "An error occurred during the decryption and verification process."); } // decompress the message if (m_RemoteCompressor != null) { message.fragment = m_RemoteCompressor.Decompress(message.fragment); message.length = (ushort)message.fragment.Length; } // final adjustments message.messageType = MessageType.PlainText; m_InputSequenceNumber++; }
protected void WrapMessage(RecordMessage message) { if (message.length != message.fragment.Length) throw new SslException(AlertDescription.IllegalParameter, "Message length is invalid."); byte[] mac = null; try { // compress the message if (m_LocalCompressor != null) { message.fragment = m_LocalCompressor.Compress(message.fragment); message.length = (ushort)message.fragment.Length; } // encrypt the message and MAC if (m_LocalHasher != null) { // calculate the MAC mac = GetULongBytes(m_OutputSequenceNumber); m_LocalHasher.Initialize(); m_LocalHasher.TransformBlock(mac, 0, mac.Length, mac, 0); // seq_num + .. mac = message.ToBytes(); if (m_HandshakeLayer.GetProtocol() == SecureProtocol.Tls1) { m_LocalHasher.TransformFinalBlock(mac, 0, mac.Length); // .. + TLSCompressed.type + TLSCompressed.version + TLSCompressed.length + TLSCompressed.fragment } else if (m_HandshakeLayer.GetProtocol() == SecureProtocol.Ssl3) { m_LocalHasher.TransformBlock(mac, 0, 1, mac, 0); // type m_LocalHasher.TransformFinalBlock(mac, 3, mac.Length - 3); // length + fragment } else { throw new NotSupportedException("Only SSL3 and TLS1 are supported"); } mac = m_LocalHasher.Hash; // encrypt the message if (m_BulkEncryption.OutputBlockSize == 1) { // is stream cipher? byte[] ret = new byte[message.length + mac.Length]; m_BulkEncryption.TransformBlock(message.fragment, 0, message.length, ret, 0); m_BulkEncryption.TransformBlock(mac, 0, mac.Length, ret, message.length); message.fragment = ret; } else { // cipher is block cipher int obs = m_BulkEncryption.OutputBlockSize; byte padding = (byte)((obs - (message.length + mac.Length + 1) % obs) % obs); byte[] ret = new byte[message.length + mac.Length + padding + 1]; Array.Copy(message.fragment, 0, ret, 0, message.length); Array.Copy(mac, 0, ret, message.length, mac.Length); if (m_HandshakeLayer.GetProtocol() == SecureProtocol.Tls1) { for(int i = message.length + mac.Length; i < ret.Length; i++) { ret[i] = padding; } } else { byte[] buffer = new byte[ret.Length - message.length - mac.Length]; m_HandshakeLayer.RNG.GetBytes(buffer); Array.Copy(buffer, 0, ret, message.length + mac.Length, buffer.Length); ret[ret.Length - 1] = padding; } m_BulkEncryption.TransformBlock(ret, 0, ret.Length, ret, 0); message.fragment = ret; } message.length = (ushort)message.fragment.Length; } } catch (Exception e) { throw new SslException(e, AlertDescription.InternalError, "An exception occurred"); } // final adjustments message.messageType = MessageType.Encrypted; m_OutputSequenceNumber++; } //*/
protected byte[] InternalEncryptBytes(byte[] buffer, int offset, int size, ContentType type) { // only accepts sizes of less than 16Kb; does not do any error checking byte[] bytes = new byte[size]; Array.Copy(buffer, offset, bytes, 0, size); RecordMessage message = new RecordMessage(MessageType.PlainText, type, m_HandshakeLayer.GetVersion(), bytes); WrapMessage(message); return message.ToBytes(); }
} //*/ protected void UnwrapMessage(RecordMessage message) { if (message.length != message.fragment.Length) { throw new SslException(AlertDescription.IllegalParameter, "Message length is invalid."); } byte[] remoteMac = null, decrypted = null, localMac = null; bool cipherError = false; // decrypt and verify the message if (m_BulkDecryption != null) { if (message.length <= m_RemoteHasher.HashSize / 8) { throw new SslException(AlertDescription.DecodeError, "Message is too small."); } if (message.length % m_BulkDecryption.OutputBlockSize != 0) { throw new SslException(AlertDescription.DecryptError, "Message length is invalid."); } // decrypt the message if (m_BulkDecryption.OutputBlockSize == 1) // is stream cipher? { decrypted = new byte[message.length]; m_BulkDecryption.TransformBlock(message.fragment, 0, message.length, decrypted, 0); remoteMac = new byte[m_RemoteHasher.HashSize / 8]; Array.Copy(decrypted, message.length - remoteMac.Length, remoteMac, 0, remoteMac.Length); message.fragment = new byte[decrypted.Length - remoteMac.Length]; Array.Copy(decrypted, 0, message.fragment, 0, message.fragment.Length); message.length = (ushort)message.fragment.Length; } else // cipher is block cipher { decrypted = new byte[message.fragment.Length]; m_BulkDecryption.TransformBlock(message.fragment, 0, decrypted.Length, decrypted, 0); byte padding = decrypted[decrypted.Length - 1]; if (message.length < padding + m_RemoteHasher.HashSize / 8 + 1) { cipherError = true; remoteMac = new byte[m_RemoteHasher.HashSize / 8]; } else { int realSize = (message.length - padding) - 1; remoteMac = new byte[m_RemoteHasher.HashSize / 8]; Array.Copy(decrypted, realSize - remoteMac.Length, remoteMac, 0, remoteMac.Length); message.fragment = new byte[realSize - remoteMac.Length]; Array.Copy(decrypted, 0, message.fragment, 0, message.fragment.Length); message.length = (ushort)message.fragment.Length; if (m_HandshakeLayer.GetProtocol() == SecureProtocol.Tls1) { // check padding for (int i = realSize; i < decrypted.Length; i++) { if (decrypted[i] != padding) { cipherError = true; } } } } } // calculate the MAC localMac = GetULongBytes(m_InputSequenceNumber); m_RemoteHasher.Initialize(); m_RemoteHasher.TransformBlock(localMac, 0, localMac.Length, localMac, 0); // seq_num + .. localMac = message.ToBytes(); if (m_HandshakeLayer.GetProtocol() == SecureProtocol.Tls1) { m_RemoteHasher.TransformFinalBlock(localMac, 0, localMac.Length); // .. + TLSCompressed.type + TLSCompressed.version + TLSCompressed.length + TLSCompressed.fragment } else if (m_HandshakeLayer.GetProtocol() == SecureProtocol.Ssl3) { m_RemoteHasher.TransformBlock(localMac, 0, 1, localMac, 0); // type m_RemoteHasher.TransformFinalBlock(localMac, 3, localMac.Length - 3); // length + fragment } else { throw new NotSupportedException("Only SSL3 and TLS1 are supported"); } localMac = m_RemoteHasher.Hash; // compare MACs for (int i = 0; i < remoteMac.Length; i++) { if (remoteMac[i] != localMac[i]) { cipherError = true; } } // throw cipher error, if necessary if (cipherError) { throw new SslException(AlertDescription.BadRecordMac, "An error occurred during the decryption and verification process."); } } // decompress the message if (m_RemoteCompressor != null) { message.fragment = m_RemoteCompressor.Decompress(message.fragment); message.length = (ushort)message.fragment.Length; } // final adjustments message.messageType = MessageType.PlainText; m_InputSequenceNumber++; }
protected void WrapMessage(RecordMessage message) { if (message.length != message.fragment.Length) { throw new SslException(AlertDescription.IllegalParameter, "Message length is invalid."); } byte[] mac = null; try { // compress the message if (m_LocalCompressor != null) { message.fragment = m_LocalCompressor.Compress(message.fragment); message.length = (ushort)message.fragment.Length; } // encrypt the message and MAC if (m_LocalHasher != null) { // calculate the MAC mac = GetULongBytes(m_OutputSequenceNumber); m_LocalHasher.Initialize(); m_LocalHasher.TransformBlock(mac, 0, mac.Length, mac, 0); // seq_num + .. mac = message.ToBytes(); if (m_HandshakeLayer.GetProtocol() == SecureProtocol.Tls1) { m_LocalHasher.TransformFinalBlock(mac, 0, mac.Length); // .. + TLSCompressed.type + TLSCompressed.version + TLSCompressed.length + TLSCompressed.fragment } else if (m_HandshakeLayer.GetProtocol() == SecureProtocol.Ssl3) { m_LocalHasher.TransformBlock(mac, 0, 1, mac, 0); // type m_LocalHasher.TransformFinalBlock(mac, 3, mac.Length - 3); // length + fragment } else { throw new NotSupportedException("Only SSL3 and TLS1 are supported"); } mac = m_LocalHasher.Hash; // encrypt the message if (m_BulkEncryption.OutputBlockSize == 1) // is stream cipher? { byte[] ret = new byte[message.length + mac.Length]; m_BulkEncryption.TransformBlock(message.fragment, 0, message.length, ret, 0); m_BulkEncryption.TransformBlock(mac, 0, mac.Length, ret, message.length); message.fragment = ret; } else // cipher is block cipher { int obs = m_BulkEncryption.OutputBlockSize; byte padding = (byte)((obs - (message.length + mac.Length + 1) % obs) % obs); byte[] ret = new byte[message.length + mac.Length + padding + 1]; Array.Copy(message.fragment, 0, ret, 0, message.length); Array.Copy(mac, 0, ret, message.length, mac.Length); if (m_HandshakeLayer.GetProtocol() == SecureProtocol.Tls1) { for (int i = message.length + mac.Length; i < ret.Length; i++) { ret[i] = padding; } } else { byte[] buffer = new byte[ret.Length - message.length - mac.Length]; m_HandshakeLayer.RNG.GetBytes(buffer); Array.Copy(buffer, 0, ret, message.length + mac.Length, buffer.Length); ret[ret.Length - 1] = padding; } m_BulkEncryption.TransformBlock(ret, 0, ret.Length, ret, 0); message.fragment = ret; } message.length = (ushort)message.fragment.Length; } } catch (Exception e) { throw new SslException(e, AlertDescription.InternalError, "An exception occurred"); } // final adjustments message.messageType = MessageType.Encrypted; m_OutputSequenceNumber++; } //*/