Minor test-crypto fixes.

This commit is contained in:
levlam 2021-02-25 14:57:50 +03:00
parent 1e7795354d
commit 4e8732a197
2 changed files with 52 additions and 31 deletions

View File

@ -32,9 +32,20 @@ set(TESTS_MAIN
if (NOT CMAKE_CROSSCOMPILING OR EMSCRIPTEN) if (NOT CMAKE_CROSSCOMPILING OR EMSCRIPTEN)
#Tests #Tests
add_executable(test-crypto EXCLUDE_FROM_ALL ${CMAKE_CURRENT_SOURCE_DIR}/crypto.cpp) if (OPENSSL_FOUND)
target_include_directories(test-crypto PUBLIC ${OPENSSL_INCLUDE_DIR}) add_executable(test-crypto EXCLUDE_FROM_ALL ${CMAKE_CURRENT_SOURCE_DIR}/crypto.cpp)
target_link_libraries(test-crypto ${OPENSSL_LIBRARIES} tdutils tdcore) target_include_directories(test-crypto SYSTEM PRIVATE ${OPENSSL_INCLUDE_DIR})
target_link_libraries(test-crypto PRIVATE ${OPENSSL_CRYPTO_LIBRARY} ${CMAKE_DL_LIBS} ${ZLIB_LIBRARIES} tdutils tdcore)
if (WIN32)
if (MINGW)
target_link_libraries(test-crypto PRIVATE ws2_32 mswsock crypt32)
else()
target_link_libraries(test-crypto PRIVATE ws2_32 Mswsock Crypt32)
endif()
endif()
endif()
add_executable(test-tdutils EXCLUDE_FROM_ALL ${TESTS_MAIN} ${TDUTILS_TEST_SOURCE}) add_executable(test-tdutils EXCLUDE_FROM_ALL ${TESTS_MAIN} ${TDUTILS_TEST_SOURCE})
add_executable(test-online EXCLUDE_FROM_ALL online.cpp) add_executable(test-online EXCLUDE_FROM_ALL online.cpp)
add_executable(run_all_tests ${TESTS_MAIN} ${TD_TEST_SOURCE}) add_executable(run_all_tests ${TESTS_MAIN} ${TD_TEST_SOURCE})

View File

@ -1,20 +1,27 @@
//
#include <stdio.h> // Copyright Aliaksei Levin (levlam@telegram.org), Arseny Smirnov (arseny30@gmail.com) 2014-2021
#include <openssl/evp.h> //
#include <openssl/bio.h> // Distributed under the Boost Software License, Version 1.0. (See accompanying
#include <openssl/pem.h> // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
#include "td/utils/Status.h"
#include "td/utils/SharedSlice.h"
#include "td/utils/base64.h"
#include "td/utils/tl_storers.h"
#include "td/utils/crypto.h"
#include "td/mtproto/AuthKey.h" #include "td/mtproto/AuthKey.h"
#include "td/mtproto/KDF.h"
#include "td/mtproto/Transport.h" #include "td/mtproto/Transport.h"
#include "td/utils/base64.h"
#include "td/utils/common.h"
#include "td/utils/crypto.h"
#include "td/utils/logging.h"
#include "td/utils/ScopeGuard.h"
#include "td/utils/SharedSlice.h"
#include "td/utils/Slice.h"
#include "td/utils/Status.h"
#include "td/utils/StringBuilder.h"
#include "td/utils/UInt.h"
#include <openssl/bio.h>
#include <openssl/evp.h>
#include <openssl/pem.h>
class Handshake { class Handshake {
public: public:
struct KeyPair { struct KeyPair {
@ -23,17 +30,18 @@ class Handshake {
}; };
static td::Result<KeyPair> generate_key_pair() { static td::Result<KeyPair> generate_key_pair() {
EVP_PKEY *pkey = NULL; EVP_PKEY_CTX *pctx = EVP_PKEY_CTX_new_id(NID_X25519, nullptr);
EVP_PKEY_CTX *pctx = EVP_PKEY_CTX_new_id(NID_X25519, NULL);
SCOPE_EXIT {
EVP_PKEY_CTX_free(pctx);
};
if (pctx == nullptr) { if (pctx == nullptr) {
return td::Status::Error("Can't create EXP_PKEY_CTX"); return td::Status::Error("Can't create EXP_PKEY_CTX");
} }
SCOPE_EXIT {
EVP_PKEY_CTX_free(pctx);
};
if (EVP_PKEY_keygen_init(pctx) <= 0) { if (EVP_PKEY_keygen_init(pctx) <= 0) {
return td::Status::Error("Can't init keygen"); return td::Status::Error("Can't init keygen");
} }
EVP_PKEY *pkey = nullptr;
if (EVP_PKEY_keygen(pctx, &pkey) <= 0) { if (EVP_PKEY_keygen(pctx, &pkey) <= 0) {
return td::Status::Error("Can't generate key"); return td::Status::Error("Can't generate key");
} }
@ -138,7 +146,7 @@ class Handshake {
} }
char *data_ptr = nullptr; char *data_ptr = nullptr;
auto data_size = BIO_get_mem_data(mem_bio, &data_ptr); auto data_size = BIO_get_mem_data(mem_bio, &data_ptr);
return std::string(data_ptr, data_size); return td::SecureString(data_ptr, data_size);
} }
}; };
@ -152,7 +160,7 @@ struct HandshakeTest {
namespace td { namespace td {
void KDF2(Slice auth_key, const UInt128 &msg_key, int X, UInt256 *aes_key, UInt128 *aes_iv) { static void KDF3(Slice auth_key, const UInt128 &msg_key, int X, UInt256 *aes_key, UInt128 *aes_iv) {
uint8 buf_raw[36 + 16]; uint8 buf_raw[36 + 16];
MutableSlice buf(buf_raw, 36 + 16); MutableSlice buf(buf_raw, 36 + 16);
Slice msg_key_slice = as_slice(msg_key); Slice msg_key_slice = as_slice(msg_key);
@ -183,9 +191,10 @@ void KDF2(Slice auth_key, const UInt128 &msg_key, int X, UInt256 *aes_key, UInt1
aes_iv_slice.substr(4).copy_from(sha256_a.substr(8, 8)); aes_iv_slice.substr(4).copy_from(sha256_a.substr(8, 8));
aes_iv_slice.substr(12).copy_from(sha256_b.substr(24, 4)); aes_iv_slice.substr(12).copy_from(sha256_b.substr(24, 4));
} }
} // namespace td } // namespace td
td::SecureString encrypt(td::Slice key, td::Slice data, td::int32 seqno, int X) { static td::SecureString encrypt(td::Slice key, td::Slice data, td::int32 seqno, int X) {
td::SecureString res(data.size() + 4 + 16); td::SecureString res(data.size() + 4 + 16);
res.as_mutable_slice().substr(20).copy_from(data); res.as_mutable_slice().substr(20).copy_from(data);
@ -201,7 +210,7 @@ td::SecureString encrypt(td::Slice key, td::Slice data, td::int32 seqno, int X)
td::UInt128 msg_key = td::mtproto::Transport::calc_message_key2(auth_key, X, payload).second; td::UInt128 msg_key = td::mtproto::Transport::calc_message_key2(auth_key, X, payload).second;
td::UInt256 aes_key; td::UInt256 aes_key;
td::UInt128 aes_iv; td::UInt128 aes_iv;
td::KDF2(key, msg_key, X, &aes_key, &aes_iv); td::KDF3(key, msg_key, X, &aes_key, &aes_iv);
td::AesCtrState aes; td::AesCtrState aes;
aes.init(aes_key.as_slice(), aes_iv.as_slice()); aes.init(aes_key.as_slice(), aes_iv.as_slice());
aes.encrypt(payload, payload); aes.encrypt(payload, payload);
@ -209,7 +218,7 @@ td::SecureString encrypt(td::Slice key, td::Slice data, td::int32 seqno, int X)
return res; return res;
} }
HandshakeTest gen_test() { static HandshakeTest gen_test() {
HandshakeTest res; HandshakeTest res;
res.alice = Handshake::generate_key_pair().move_as_ok(); res.alice = Handshake::generate_key_pair().move_as_ok();
@ -219,7 +228,7 @@ HandshakeTest gen_test() {
return res; return res;
} }
void run_test(const HandshakeTest &test) { static void run_test(const HandshakeTest &test) {
auto alice_secret = Handshake::calc_shared_secret(test.alice.private_key, test.bob.public_key).move_as_ok(); auto alice_secret = Handshake::calc_shared_secret(test.alice.private_key, test.bob.public_key).move_as_ok();
auto bob_secret = Handshake::calc_shared_secret(test.bob.private_key, test.alice.public_key).move_as_ok(); auto bob_secret = Handshake::calc_shared_secret(test.bob.private_key, test.alice.public_key).move_as_ok();
auto key = Handshake::expand_secret(alice_secret); auto key = Handshake::expand_secret(alice_secret);
@ -229,13 +238,14 @@ void run_test(const HandshakeTest &test) {
CHECK(key == test.key); CHECK(key == test.key);
} }
td::StringBuilder &operator<<(td::StringBuilder &sb, const Handshake::KeyPair &key_pair) { static td::StringBuilder &operator<<(td::StringBuilder &sb, const Handshake::KeyPair &key_pair) {
sb << "\tpublic_key (base64url) = " << td::base64url_encode(key_pair.public_key) << "\n"; sb << "\tpublic_key (base64url) = " << td::base64url_encode(key_pair.public_key) << "\n";
sb << "\tprivate_key (base64url) = " << td::base64url_encode(key_pair.private_key) << "\n"; sb << "\tprivate_key (base64url) = " << td::base64url_encode(key_pair.private_key) << "\n";
sb << "\tprivate_key (pem) = \n" << Handshake::privateKeyToPem(key_pair.private_key).ok() << "\n"; sb << "\tprivate_key (pem) = \n" << Handshake::privateKeyToPem(key_pair.private_key).ok() << "\n";
return sb; return sb;
} }
td::StringBuilder &operator<<(td::StringBuilder &sb, const HandshakeTest &test) {
static td::StringBuilder &operator<<(td::StringBuilder &sb, const HandshakeTest &test) {
sb << "Alice\n" << test.alice; sb << "Alice\n" << test.alice;
sb << "Bob\n" << test.bob; sb << "Bob\n" << test.bob;
sb << "SharedSecret\n\t" << td::base64url_encode(test.shared_secret) << "\n"; sb << "SharedSecret\n\t" << td::base64url_encode(test.shared_secret) << "\n";
@ -247,7 +257,7 @@ td::StringBuilder &operator<<(td::StringBuilder &sb, const HandshakeTest &test)
return sb; return sb;
} }
HandshakeTest pregenerated_test() { static HandshakeTest pregenerated_test() {
HandshakeTest test; HandshakeTest test;
test.alice.public_key = td::base64url_decode_secure("QlCME5fXLyyQQWeYnBiGAZbmzuD4ayOuADCFgmioOBY").move_as_ok(); test.alice.public_key = td::base64url_decode_secure("QlCME5fXLyyQQWeYnBiGAZbmzuD4ayOuADCFgmioOBY").move_as_ok();
test.alice.private_key = td::base64url_decode_secure("8NZGWKfRCJfiks74RG9_xHmYydarLiRsoq8VcJGPglg").move_as_ok(); test.alice.private_key = td::base64url_decode_secure("8NZGWKfRCJfiks74RG9_xHmYydarLiRsoq8VcJGPglg").move_as_ok();