1 #ifndef TGCALLS_CRYPTO_HELPER_H
2 #define TGCALLS_CRYPTO_HELPER_H
3 
4 extern "C" {
5 #include <openssl/sha.h>
6 #include <openssl/aes.h>
7 #ifndef OPENSSL_IS_BORINGSSL
8 #include <openssl/modes.h>
9 #endif
10 #include <openssl/rand.h>
11 #include <openssl/crypto.h>
12 } // extern "C"
13 
14 #include <array>
15 
16 namespace tgcalls {
17 
18 struct MemorySpan {
MemorySpanMemorySpan19 	MemorySpan(const void *data, size_t size) :
20 		data(data),
21 		size(size) {
22 	}
23 
24 	const void *data = nullptr;
25 	size_t size = 0;
26 };
27 
28 struct AesKeyIv {
29 	std::array<uint8_t, 32> key;
30 	std::array<uint8_t, 16> iv;
31 };
32 
33 constexpr auto kSha256Size = size_t(SHA256_DIGEST_LENGTH);
34 
35 template <typename ...Parts>
36 void SHA256Update(SHA256_CTX*, Parts &&...parts);
37 
SHA256Update(SHA256_CTX *)38 inline void SHA256Update(SHA256_CTX*) {
39 }
40 
41 template <typename First, typename ...Others>
SHA256Update(SHA256_CTX * context,First && span,Others &&...others)42 inline void SHA256Update(SHA256_CTX *context, First &&span, Others &&...others) {
43 	static_assert(
44 		std::is_same<std::decay_t<First>, MemorySpan>::value,
45 		"Pass some MemorySpan-s here.");
46 
47 	SHA256_Update(context, span.data, span.size);
48 	SHA256Update(context, std::forward<Others>(others)...);
49 }
50 
51 template <typename ...Parts>
ConcatSHA256(Parts &&...parts)52 inline std::array<uint8_t, kSha256Size> ConcatSHA256(Parts &&... parts) {
53 	static_assert(sizeof...(parts) > 0, "empty list");
54 
55 	auto result = std::array<uint8_t, kSha256Size>();
56 	auto context = SHA256_CTX();
57 	SHA256_Init(&context);
58 	SHA256Update(&context, std::forward<Parts>(parts)...);
59 	SHA256_Final(result.data(), &context);
60 	return result;
61 }
62 
63 AesKeyIv PrepareAesKeyIv(const uint8_t *key, const uint8_t *msgKey, int x);
64 void AesProcessCtr(MemorySpan from, void *to, AesKeyIv &&aesKeyIv);
65 
66 } // namespace tgcalls
67 
68 #endif
69