SuperTuxKart
Loading...
Searching...
No Matches
crypto_mbedtls.hpp
1//
2// SuperTuxKart - a fun racing game with go-kart
3// Copyright (C) 2018 SuperTuxKart-Team
4//
5// This program is free software; you can redistribute it and/or
6// modify it under the terms of the GNU General Public License
7// as published by the Free Software Foundation; either version 3
8// of the License, or (at your option) any later version.
9//
10// This program is distributed in the hope that it will be useful,
11// but WITHOUT ANY WARRANTY; without even the implied warranty of
12// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13// GNU General Public License for more details.
14//
15// You should have received a copy of the GNU General Public License
16// along with this program; if not, write to the Free Software
17// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
18
19#ifdef ENABLE_CRYPTO_MBEDTLS
20
21#ifndef HEADER_CRYPTO_MBEDTLS_HPP
22#define HEADER_CRYPTO_MBEDTLS_HPP
23
24#include "utils/log.hpp"
25
26#include <enet/enet.h>
27#include <mbedtls/ctr_drbg.h>
28#include <mbedtls/entropy.h>
29#include <mbedtls/gcm.h>
30
31#include <algorithm>
32#include <array>
33#include <cassert>
34#include <memory>
35#include <mutex>
36#include <random>
37#include <string>
38#include <vector>
39
41class NetworkString;
42
43class Crypto
44{
45private:
46 static std::string m_client_key;
47
48 static std::string m_client_iv;
49
50 std::array<uint8_t, 12> m_iv;
51
52 uint32_t m_packet_counter;
53
54 mbedtls_gcm_context m_aes_encrypt_context, m_aes_decrypt_context;
55
56 std::mutex m_crypto_mutex;
57
58public:
59 // ------------------------------------------------------------------------
60 static std::string base64(const std::vector<uint8_t>& input);
61 // ------------------------------------------------------------------------
62 static std::vector<uint8_t> decode64(std::string input);
63 // ------------------------------------------------------------------------
64 static std::array<uint8_t, 32> sha256(const std::string& input);
65 // ------------------------------------------------------------------------
66 static std::unique_ptr<Crypto> getClientCrypto()
67 {
68 assert(!m_client_key.empty());
69 assert(!m_client_iv.empty());
70 auto c = std::unique_ptr<Crypto>(new Crypto(decode64(m_client_key),
71 decode64(m_client_iv)));
72 c->m_packet_counter = 0;
73 return c;
74 }
75 // ------------------------------------------------------------------------
76 static void initClientAES()
77 {
78 mbedtls_entropy_context entropy;
79 mbedtls_entropy_init(&entropy);
80 mbedtls_ctr_drbg_context ctr_drbg;
81 mbedtls_ctr_drbg_init(&ctr_drbg);
82 std::random_device rd;
83 std::mt19937 g(rd());
84 std::array<uint8_t, 28> seed, key_iv;
85 for (unsigned i = 0; i < 28; i++)
86 seed[i] = (uint8_t)(g() % 255);
87 key_iv = seed;
88 if (mbedtls_ctr_drbg_seed(&ctr_drbg, mbedtls_entropy_func,
89 &entropy, seed.data(), seed.size()) == 0)
90 {
91 // If failed use the seed in the beginning
92 if (mbedtls_ctr_drbg_random((void*)&ctr_drbg, key_iv.data(),
93 key_iv.size()) != 0)
94 key_iv = seed;
95 }
96 m_client_key = base64({ key_iv.begin(), key_iv.begin() + 16 });
97 m_client_iv = base64({ key_iv.begin() + 16, key_iv.end() });
98 }
99 // ------------------------------------------------------------------------
100 static void resetClientAES()
101 {
102 m_client_key = "";
103 m_client_iv = "";
104 }
105 // ------------------------------------------------------------------------
106 static const std::string& getClientKey() { return m_client_key; }
107 // ------------------------------------------------------------------------
108 static const std::string& getClientIV() { return m_client_iv; }
109 // ------------------------------------------------------------------------
110 Crypto(const std::vector<uint8_t>& key,
111 const std::vector<uint8_t>& iv)
112 {
113 assert(key.size() == 16);
114 assert(iv.size() == 12);
115 std::copy_n(iv.begin(), 12, m_iv.begin());
116 m_packet_counter = 0;
117 mbedtls_gcm_init(&m_aes_encrypt_context);
118 mbedtls_gcm_init(&m_aes_decrypt_context);
119 mbedtls_gcm_setkey(&m_aes_encrypt_context, MBEDTLS_CIPHER_ID_AES,
120 key.data(), key.size() * 8);
121 mbedtls_gcm_setkey(&m_aes_decrypt_context, MBEDTLS_CIPHER_ID_AES,
122 key.data(), key.size() * 8);
123 }
124 // ------------------------------------------------------------------------
125 ~Crypto()
126 {
127 mbedtls_gcm_free(&m_aes_encrypt_context);
128 mbedtls_gcm_free(&m_aes_decrypt_context);
129 }
130 // ------------------------------------------------------------------------
131 bool encryptConnectionRequest(BareNetworkString& ns);
132 // ------------------------------------------------------------------------
133 bool decryptConnectionRequest(BareNetworkString& ns);
134 // ------------------------------------------------------------------------
135 ENetPacket* encryptSend(BareNetworkString& ns, bool reliable);
136 // ------------------------------------------------------------------------
137 NetworkString* decryptRecieve(ENetPacket* p);
138
139};
140
141#endif // HEADER_CRYPTO_MBEDTLS_HPP
142
143#endif
Describes a chain of 8-bit unsigned integers.
Definition: network_string.hpp:53
A new implementation of NetworkString, which has a fixed format: Byte 0: The type of the message,...
Definition: network_string.hpp:422
CScriptArray * sha256(std::string *input)
Return a sha256 checksum of string in an array of integers of size 32.
Definition: script_utils.cpp:164