void TLSClient_Impl::application_data(DataBuffer record_plaintext) { if (conversation_state != cl_tls_state_connected) throw Exception("Unexpected application data record received"); int pos = recv_out_data.get_size(); recv_out_data.set_size(pos + record_plaintext.get_size()); memcpy(recv_out_data.get_data() + pos, record_plaintext.get_data(), record_plaintext.get_size()); }
void TestApp::test_aes128() { Console::write_line(" Header: aes128_encrypt.h and aes128_decrypt.h"); Console::write_line(" Class: AES128_Encrypt and AES128_Decrypt"); // Test data from http://csrc.nist.gov/publications/nistpubs/800-38a/sp800-38a.pdf // and http://csrc.nist.gov/groups/ST/toolkit/documents/Examples/AES_CBC.pdf test_aes128_helper( "2b7e151628aed2a6abf7158809cf4f3c", // KEY "000102030405060708090A0B0C0D0E0F", // IV "6bc1bee22e409f96e93d7e117393172a" // PLAINTEXT "ae2d8a571e03ac9c9eb76fac45af8e51" "30c81c46a35ce411e5fbc1191a0a52ef" "f69f2445df4f9b17ad2b417be66c3710", "7649abac8119b246cee98e9b12e9197d" // CIPHERTEXT "5086cb9b507219ee95db113a917678b2" "73bed6b8e3c1743b7116e69e22229516" "3ff1caa1681fac09120eca307586e1a7" ); const int test_data_length = 128; unsigned char test_data[test_data_length]; std::vector<unsigned char> key; std::vector<unsigned char> iv; convert_ascii("2B7E151628AED2A6ABF7158809CF4F3C", key); convert_ascii("000102030405060708090A0B0C0D0E0F", iv); for (int cnt=0; cnt<test_data_length; cnt++) { test_data[cnt] = (unsigned char) cnt; AES128_Encrypt aes128_encrypt; aes128_encrypt.set_iv(&iv[0]); aes128_encrypt.set_key(&key[0]); aes128_encrypt.add(test_data, cnt+1); aes128_encrypt.calculate(); AES128_Decrypt aes128_decrypt; aes128_decrypt.set_iv(&iv[0]); aes128_decrypt.set_key(&key[0]); DataBuffer buffer = aes128_encrypt.get_data(); aes128_decrypt.add(buffer.get_data(), buffer.get_size()); bool result = aes128_decrypt.calculate(); if (!result) fail(); DataBuffer buffer2 = aes128_decrypt.get_data(); if (buffer2.get_size() != cnt+1) fail(); unsigned char *data_ptr2 = (unsigned char *) buffer2.get_data(); if (memcmp(data_ptr2, test_data, cnt+1)) fail(); } }
void TestApp::test_aes192() { Console::write_line(" Header: aes192_encrypt.h and aes192_decrypt.h"); Console::write_line(" Class: AES192_Encrypt and AES192_Decrypt"); // Test data from http://csrc.nist.gov/publications/nistpubs/800-38a/sp800-38a.pdf // and http://csrc.nist.gov/groups/ST/toolkit/documents/Examples/AES_CBC.pdf test_aes192_helper( "8e73b0f7da0e6452c810f32b809079e562f8ead2522c6b7b", // KEY "000102030405060708090A0B0C0D0E0F", // IV "6bc1bee22e409f96e93d7e117393172a" // PLAINTEXT "ae2d8a571e03ac9c9eb76fac45af8e51" "30c81c46a35ce411e5fbc1191a0a52ef" "f69f2445df4f9b17ad2b417be66c3710", "4f021db243bc633d7178183a9fa071e8" // CIPHERTEXT "b4d9ada9ad7dedf4e5e738763f69145a" "571b242012fb7ae07fa9baac3df102e0" "08b0e27988598881d920a9e64f5615cd" ); const int test_data_length = 192; unsigned char test_data[test_data_length]; std::vector<unsigned char> key; std::vector<unsigned char> iv; convert_ascii("8E73B0F7DA0E6452C810F32B809079E562F8EAD2522C6B7B", key); convert_ascii("000102030405060708090A0B0C0D0E0F", iv); for (int cnt=0; cnt<test_data_length; cnt++) { test_data[cnt] = (unsigned char) cnt; AES192_Encrypt aes192_encrypt; aes192_encrypt.set_iv(&iv[0]); aes192_encrypt.set_key(&key[0]); aes192_encrypt.add(test_data, cnt+1); aes192_encrypt.calculate(); AES192_Decrypt aes192_decrypt; aes192_decrypt.set_iv(&iv[0]); aes192_decrypt.set_key(&key[0]); DataBuffer buffer = aes192_encrypt.get_data(); aes192_decrypt.add(buffer.get_data(), buffer.get_size()); bool result = aes192_decrypt.calculate(); if (!result) fail(); DataBuffer buffer2 = aes192_decrypt.get_data(); if (buffer2.get_size() != cnt+1) fail(); unsigned char *data_ptr2 = (unsigned char *) buffer2.get_data(); if (memcmp(data_ptr2, test_data, cnt+1)) fail(); } }
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 TestApp::test_aes128_helper(const char *key_ptr, const char *iv_ptr, const char *plaintext_ptr, const char *ciphertext_ptr) { std::vector<unsigned char> key; std::vector<unsigned char> iv; std::vector<unsigned char> plaintext; std::vector<unsigned char> ciphertext; convert_ascii(key_ptr, key); convert_ascii(iv_ptr, iv); convert_ascii(plaintext_ptr, plaintext); convert_ascii(ciphertext_ptr, ciphertext); AES128_Encrypt aes128_encrypt; aes128_encrypt.set_padding(false); aes128_encrypt.set_iv(&iv[0]); aes128_encrypt.set_key(&key[0]); aes128_encrypt.add(&plaintext[0], plaintext.size()); aes128_encrypt.calculate(); DataBuffer buffer = aes128_encrypt.get_data(); if (buffer.get_size() != ciphertext.size()) fail(); unsigned char *data_ptr = (unsigned char *) buffer.get_data(); if (memcmp(data_ptr, &ciphertext[0], ciphertext.size())) fail(); AES128_Decrypt aes128_decrypt; aes128_decrypt.set_padding(false); aes128_decrypt.set_iv(&iv[0]); aes128_decrypt.set_key(&key[0]); aes128_decrypt.add(data_ptr, buffer.get_size()); bool result = aes128_decrypt.calculate(); if (!result) fail(); DataBuffer buffer2 = aes128_decrypt.get_data(); if (buffer2.get_size() != plaintext.size()) fail(); unsigned char *data_ptr2 = (unsigned char *) buffer2.get_data(); if (memcmp(data_ptr2, &plaintext[0], plaintext.size())) fail(); }
YETI_Result File::load(const char * path, String & data, FileInterface::open_mode mode /* = YETI_FILE_OPEN_MODE_READ */) { DataBuffer buffer; data = ""; File file(path); YETI_Result result = file.open(mode); if (YETI_FAILED(result)) return result; result = file.load(buffer); if (YETI_SUCCEEDED(result) && buffer.get_data_size() > 0) { data.assign((const char *)buffer.get_data(), buffer.get_data_size()); data.set_length(buffer.get_data_size()); } file.close(); return result; }
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(); }
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()); }
void SHA384::add(const DataBuffer &data) { add(data.get_data(), data.get_size()); }
void HashFunctions::md5(const DataBuffer &data, unsigned char out_hash[16]) { md5(data.get_data(), data.get_size(), out_hash); }
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::sha512_256(const DataBuffer &data, unsigned char out_hash[32]) { sha512_256(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); }
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)); }
std::string HashFunctions::sha512_256(const DataBuffer &data, bool uppercase) { return sha512_256(data.get_data(), data.get_size(), uppercase); }
YETI_Result File::save(const DataBuffer & buffer) { OutputStreamReference output; YETI_CHECK_WARNING(get_output_stream(output)); return output->write_fully(buffer.get_data(), buffer.get_data_size()); }
void SHA512_256::add(const DataBuffer &data) { add(data.get_data(), data.get_size()); }
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()); }
DataBuffer::DataBuffer(const DataBuffer &new_data, unsigned int pos, unsigned int size) : impl(std::make_shared<DataBuffer_Impl>()) { set_size(size); memcpy(impl->data, new_data.get_data() + pos, size); }
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::sha384(const DataBuffer &data, unsigned char out_hash[48]) { sha384(data.get_data(), data.get_size(), out_hash); }