SuperTuxKart
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 #define CRYPTO_AES_GCM_32BIT_TAG
24 
25 #include <enet/enet.h>
26 #include <mbedtls/ctr_drbg.h>
27 #include <mbedtls/entropy.h>
28 #include <mbedtls/gcm.h>
29 
30 #include <algorithm>
31 #include <array>
32 #include <cassert>
33 #include <cstdint>
34 #include <memory>
35 #include <mutex>
36 #include <random>
37 #include <string>
38 #include <vector>
39 
40 class BareNetworkString;
41 class NetworkString;
42 
43 class Crypto
44 {
45 private:
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 
58  const size_t m_tag_size;
59 
60 public:
61  // ------------------------------------------------------------------------
62  static std::string base64(const std::vector<uint8_t>& input);
63  // ------------------------------------------------------------------------
64  static std::vector<uint8_t> decode64(std::string input);
65  // ------------------------------------------------------------------------
66  static std::array<uint8_t, 32> sha256(const std::string& input);
67  // ------------------------------------------------------------------------
68  static std::unique_ptr<Crypto> getClientCrypto(size_t tag_size = 4)
69  {
70  assert(!m_client_key.empty());
71  assert(!m_client_iv.empty());
72  assert(tag_size == 4 || tag_size == 16);
73  auto c = std::unique_ptr<Crypto>(new Crypto(decode64(m_client_key),
74  decode64(m_client_iv), tag_size));
75  c->m_packet_counter = 0;
76  return c;
77  }
78  // ------------------------------------------------------------------------
79  static void initClientAES()
80  {
81  mbedtls_entropy_context entropy;
82  mbedtls_entropy_init(&entropy);
83  mbedtls_ctr_drbg_context ctr_drbg;
84  mbedtls_ctr_drbg_init(&ctr_drbg);
85  std::random_device rd;
86  std::mt19937 g(rd());
87  std::array<uint8_t, 28> seed, key_iv;
88  for (unsigned i = 0; i < 28; i++)
89  seed[i] = (uint8_t)(g() % 255);
90  key_iv = seed;
91  if (mbedtls_ctr_drbg_seed(&ctr_drbg, mbedtls_entropy_func,
92  &entropy, seed.data(), seed.size()) == 0)
93  {
94  // If failed use the seed in the beginning
95  if (mbedtls_ctr_drbg_random((void*)&ctr_drbg, key_iv.data(),
96  key_iv.size()) != 0)
97  key_iv = seed;
98  }
99  m_client_key = base64({ key_iv.begin(), key_iv.begin() + 16 });
100  m_client_iv = base64({ key_iv.begin() + 16, key_iv.end() });
101  }
102  // ------------------------------------------------------------------------
103  static void resetClientAES()
104  {
105  m_client_key = "";
106  m_client_iv = "";
107  }
108  // ------------------------------------------------------------------------
109  static const std::string& getClientKey() { return m_client_key; }
110  // ------------------------------------------------------------------------
111  static const std::string& getClientIV() { return m_client_iv; }
112  // ------------------------------------------------------------------------
113  Crypto(const std::vector<uint8_t>& key,
114  const std::vector<uint8_t>& iv,
115  size_t tag_size = 4) : m_tag_size(tag_size)
116  {
117  assert(key.size() == 16);
118  assert(iv.size() == 12);
119  assert(m_tag_size == 4 || m_tag_size == 16);
120  std::copy_n(iv.begin(), 12, m_iv.begin());
121  m_packet_counter = 0;
122  mbedtls_gcm_init(&m_aes_encrypt_context);
123  mbedtls_gcm_init(&m_aes_decrypt_context);
124  mbedtls_gcm_setkey(&m_aes_encrypt_context, MBEDTLS_CIPHER_ID_AES,
125  key.data(), key.size() * 8);
126  mbedtls_gcm_setkey(&m_aes_decrypt_context, MBEDTLS_CIPHER_ID_AES,
127  key.data(), key.size() * 8);
128  }
129  // ------------------------------------------------------------------------
130  ~Crypto()
131  {
132  mbedtls_gcm_free(&m_aes_encrypt_context);
133  mbedtls_gcm_free(&m_aes_decrypt_context);
134  }
135  // ------------------------------------------------------------------------
136  bool encryptConnectionRequest(BareNetworkString& ns);
137  // ------------------------------------------------------------------------
138  bool decryptConnectionRequest(BareNetworkString& ns);
139  // ------------------------------------------------------------------------
140  ENetPacket* encryptSend(BareNetworkString& ns, bool reliable);
141  // ------------------------------------------------------------------------
142  NetworkString* decryptRecieve(ENetPacket* p);
143 
144 };
145 
146 #endif // HEADER_CRYPTO_MBEDTLS_HPP
147 
148 #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:163