DataBuffer ZLibCompression::compress(const DataBuffer &data, bool raw, int compression_level, CompressionMode mode) { const int window_bits = 15; DataBuffer zbuffer(1024*1024); IODevice_Memory output; int strategy = MZ_DEFAULT_STRATEGY; switch (mode) { case default_strategy: strategy = MZ_DEFAULT_STRATEGY; break; case filtered: strategy = MZ_FILTERED; break; case huffman_only: strategy = MZ_HUFFMAN_ONLY; break; case rle: strategy = MZ_RLE; break; case fixed: strategy = MZ_FIXED; break; } mz_stream zs = { nullptr }; int result = mz_deflateInit2(&zs, compression_level, MZ_DEFLATED, raw ? -window_bits : window_bits, 8, strategy); // Undocumented: if wbits is negative, zlib skips header check if (result != MZ_OK) throw Exception("Zlib deflateInit failed"); try { zs.next_in = (unsigned char *) data.get_data(); zs.avail_in = data.get_size(); while (true) { zs.next_out = (unsigned char *) zbuffer.get_data(); zs.avail_out = zbuffer.get_size(); int result = mz_deflate(&zs, MZ_FINISH); if (result == MZ_NEED_DICT) throw Exception("Zlib deflate wants a dictionary!"); if (result == MZ_DATA_ERROR) throw Exception("Zip data stream is corrupted"); if (result == MZ_STREAM_ERROR) throw Exception("Zip stream structure was inconsistent!"); if (result == MZ_MEM_ERROR) throw Exception("Zlib did not have enough memory to compress file!"); if (result == MZ_BUF_ERROR) throw Exception("Not enough data in buffer when Z_FINISH was used"); if (result != MZ_OK && result != MZ_STREAM_END) throw Exception("Zlib deflate failed while compressing zip file!"); int zsize = zbuffer.get_size() - zs.avail_out; if (zsize == 0) break; output.write(zbuffer.get_data(), zsize); if (result == MZ_STREAM_END) break; } mz_deflateEnd(&zs); } catch (...) { mz_deflateEnd(&zs); throw; } return output.get_data(); }
void TLSClient_Impl::change_cipher_spec_data(DataBuffer record_plaintext) { if (conversation_state != cl_tls_state_receive_change_cipher_spec) throw Exception("Unexpected TLS change cipher record received"); if (record_plaintext.get_size() != 1) throw Exception("Invalid TLS content change cipher spec size"); security_parameters.read_sequence_number = 0; uint8_t value = record_plaintext.get_data<uint8_t>()[0]; if (value != 1) throw Exception("TLS server change cipher spec did not send 1"); security_parameters.is_receive_encrypted = true; conversation_state = cl_tls_state_receive_finished; }
DataBuffer ZLibCompression::decompress(const DataBuffer &data, bool raw) { const int window_bits = 15; DataBuffer zbuffer(1024*1024); IODevice_Memory output; mz_stream zs = { nullptr }; int result = mz_inflateInit2(&zs, raw ? -window_bits : window_bits); if (result != MZ_OK) throw Exception("Zlib inflateInit failed"); zs.next_in = (unsigned char *) data.get_data(); zs.avail_in = data.get_size(); // Continue feeding zlib data until we get our data: while (true) { zs.next_out = (unsigned char *) zbuffer.get_data(); zs.avail_out = zbuffer.get_size(); // Decompress data: int result = mz_inflate(&zs, 0); if (result == MZ_NEED_DICT) throw Exception("Zlib inflate wants a dictionary!"); if (result == MZ_DATA_ERROR) throw Exception("Zip data stream is corrupted"); if (result == MZ_STREAM_ERROR) throw Exception("Zip stream structure was inconsistent!"); if (result == MZ_MEM_ERROR) throw Exception("Zlib did not have enough memory to decompress file!"); if (result == MZ_BUF_ERROR) throw Exception("Not enough data in buffer when Z_FINISH was used"); if (result != MZ_OK && result != MZ_STREAM_END) throw Exception("Zlib inflate failed while decompressing zip file!"); output.write(zbuffer.get_data(), zbuffer.get_size() - zs.avail_out); if (result == MZ_STREAM_END) break; } mz_inflateEnd(&zs); return output.get_data(); }
void SHA384::add(const DataBuffer &data) { add(data.get_data(), data.get_size()); }
Secret RSA::decrypt(const Secret &in_private_exponent, const DataBuffer &in_modulus, const DataBuffer &in_data) { return RSA_Impl::decrypt(in_private_exponent, in_modulus.get_data(), in_modulus.get_size(), in_data.get_data(), in_data.get_size()); }
DataBuffer RSA::encrypt(int block_type, Random &random, const DataBuffer &in_public_exponent, const DataBuffer &in_modulus, const Secret &in_data) { return RSA_Impl::encrypt(block_type, random, in_public_exponent.get_data(), in_public_exponent.get_size(), in_modulus.get_data(), in_modulus.get_size(), in_data.get_data(), in_data.get_size()); }
void HashFunctions::md5(const DataBuffer &data, unsigned char out_hash[16]) { md5(data.get_data(), data.get_size(), out_hash); }
std::string HashFunctions::md5(const DataBuffer &data, bool uppercase) { return md5(data.get_data(), data.get_size(), uppercase); }
std::string HashFunctions::sha512_256(const DataBuffer &data, bool uppercase) { return sha512_256(data.get_data(), data.get_size(), uppercase); }
void HashFunctions::sha384(const DataBuffer &data, unsigned char out_hash[48]) { sha384(data.get_data(), data.get_size(), out_hash); }
void File::write_bytes(const std::string &filename, const DataBuffer &bytes) { File file(filename, create_always, access_write); file.write(bytes.get_data(), bytes.get_size()); file.close(); }
void AES192_Encrypt::add(const DataBuffer &data) { add(data.get_data(), data.get_size()); }
void SHA512_256::add(const DataBuffer &data) { add(data.get_data(), data.get_size()); }
void RegistryKey::set_value_binary(const std::string &name, const DataBuffer &value) { LONG result = RegSetValueEx(impl->key, name.empty() ? 0 : StringHelp::utf8_to_ucs2(name).c_str(), 0, REG_BINARY, (const BYTE *) value.get_data(), value.get_size()); if (result != ERROR_SUCCESS) throw Exception(string_format("Unable to set registry key value %1", name)); }
void TLSClient_Impl::alert_data(DataBuffer record_plaintext) { if (record_plaintext.get_size() != 2) // To do: theoretically this is not safe - it could be split into two 1 byte records. throw Exception("Invalid TLS content alert message"); uint8_t *alert_data = record_plaintext.get_data<uint8_t>(); if (alert_data[0] == cl_tls_warning) return; const char *desc = "Unknown"; switch (alert_data[1]) { case cl_tls_close_notify: desc = "close_notify"; break; case cl_tls_unexpected_message: desc = "unexpected_message"; break; case cl_tls_bad_record_mac: desc = "bad_record_mac"; break; case cl_tls_decryption_failed: desc = "decryption_failed"; break; case cl_tls_record_overflow: desc = "record_overflow"; break; case cl_tls_decompression_failure: desc = "decompression_failure"; break; case cl_tls_handshake_failure: desc = "handshake_failure"; break; case cl_tls_bad_certificate: desc = "bad_certificate"; break; case cl_tls_unsupported_certificate: desc = "unsupported_certificate"; break; case cl_tls_certificate_revoked: desc = "certificate_revoked"; break; case cl_tls_certificate_expired: desc = "certificate_expired"; break; case cl_tls_certificate_unknown: desc = "certificate_unknown"; break; case cl_tls_illegal_parameter: desc = "illegal_parameter"; break; case cl_tls_unknown_ca: desc = "unknown_ca"; break; case cl_tls_access_denied: desc = "access_denied"; break; case cl_tls_decode_error: desc = "decode_error"; break; case cl_tls_decrypt_error: desc = "decrypt_error"; break; case cl_tls_export_restriction: desc = "export_restriction"; break; case cl_tls_protocol_version: desc = "protocol_version"; break; case cl_tls_insufficient_security: desc = "insufficient_security"; break; case cl_tls_internal_error: desc = "internal_error"; break; case cl_tls_user_canceled: desc = "user_canceled"; break; case cl_tls_no_renegotiation: desc = "no_renegotiation"; break; } std::string string(string_format("TLS Alert %1", desc)); throw Exception(string); }
void TLSClient_Impl::handshake_data(DataBuffer record_plaintext) { // Copy handshake data into input buffer for easier processing: // "RFC 2246 (5.2.1) multiple client messages of the same ContentType may be coalesced into a single TLSPlaintext record" int pos = handshake_in_data.get_size(); handshake_in_data.set_size(pos + record_plaintext.get_size()); memcpy(handshake_in_data.get_data() + pos, record_plaintext.get_data(), record_plaintext.get_size()); // Check if we have received enough data to peek at the handshake header: int available = handshake_in_data.get_size() - handshake_in_read_pos; if (available < sizeof(TLS_Handshake)) return; // Check if we have received enough data to read the entire handshake message: TLS_Handshake &handshake = *reinterpret_cast<TLS_Handshake*>(handshake_in_data.get_data() + handshake_in_read_pos); int length = handshake.length[0] << 16 | handshake.length[1] << 8 | handshake.length[2]; if (sizeof(TLS_Handshake) + length > available) return; const char *data = handshake_in_data.get_data() + handshake_in_read_pos + sizeof(TLS_Handshake); // We got a full message. // All handshake messages except handshake_finished needs to be included in the handshake hash calculation: if (handshake.msg_type != cl_tls_handshake_finished) { hash_handshake(&handshake, length + sizeof(TLS_Handshake)); } // Dispatch message for further parsing: switch (handshake.msg_type) { case cl_tls_handshake_hello_request: handshake_hello_request_received(data, length); break; case cl_tls_handshake_client_hello: handshake_client_hello_received(data, length); break; case cl_tls_handshake_server_hello: handshake_server_hello_received(data, length); break; case cl_tls_handshake_certificate: handshake_certificate_received(data, length); break; case cl_tls_handshake_server_key_exchange: handshake_server_key_exchange_received(data, length); break; case cl_tls_handshake_certificate_request: handshake_certificate_request_received(data, length); break; case cl_tls_handshake_server_hello_done: handshake_server_hello_done_received(data, length); break; case cl_tls_handshake_certificate_verify: handshake_certificate_verify_received(data, length); break; case cl_tls_handshake_client_key_exchange: handshake_client_key_exchange_received(data, length); break; case cl_tls_handshake_finished: handshake_finished_received(data, length); break; default: throw Exception("Unknown handshake type"); } // Remove processed handshake message from the input buffer: handshake_in_read_pos += sizeof(TLS_Handshake) + length; if (handshake_in_read_pos >= desired_buffer_size / 2) { available = handshake_in_data.get_size() - handshake_in_read_pos; memmove(handshake_in_data.get_data(), handshake_in_data.get_data() + handshake_in_read_pos, available); handshake_in_data.set_size(available); } }
void HashFunctions::sha512_256(const DataBuffer &data, unsigned char out_hash[32]) { sha512_256(data.get_data(), data.get_size(), out_hash); }