1 /*
2 * Copyright (c) 2013-2021, The PurpleI2P Project
3 *
4 * This file is part of Purple i2pd project and licensed under BSD3
5 *
6 * See full license text in LICENSE file at top of project tree
7 */
8 
9 #include <string.h>
10 #include <string>
11 #include <vector>
12 #include <mutex>
13 #include <memory>
14 #include <openssl/dh.h>
15 #include <openssl/md5.h>
16 #include <openssl/crypto.h>
17 #include "TunnelBase.h"
18 #include <openssl/ssl.h>
19 #if OPENSSL_HKDF
20 #include <openssl/kdf.h>
21 #endif
22 #if !OPENSSL_AEAD_CHACHA20_POLY1305
23 #include "ChaCha20.h"
24 #include "Poly1305.h"
25 #endif
26 #include "Crypto.h"
27 #include "Ed25519.h"
28 #include "I2PEndian.h"
29 #include "Log.h"
30 
31 namespace i2p
32 {
33 namespace crypto
34 {
35 	const uint8_t elgp_[256]=
36 	{
37 		0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xC9, 0x0F, 0xDA, 0xA2, 0x21, 0x68, 0xC2, 0x34,
38 		0xC4, 0xC6, 0x62, 0x8B, 0x80, 0xDC, 0x1C, 0xD1, 0x29, 0x02, 0x4E, 0x08, 0x8A, 0x67, 0xCC, 0x74,
39 		0x02, 0x0B, 0xBE, 0xA6, 0x3B, 0x13, 0x9B, 0x22, 0x51, 0x4A, 0x08, 0x79, 0x8E, 0x34, 0x04, 0xDD,
40 		0xEF, 0x95, 0x19, 0xB3, 0xCD, 0x3A, 0x43, 0x1B, 0x30, 0x2B, 0x0A, 0x6D, 0xF2, 0x5F, 0x14, 0x37,
41 		0x4F, 0xE1, 0x35, 0x6D, 0x6D, 0x51, 0xC2, 0x45, 0xE4, 0x85, 0xB5, 0x76, 0x62, 0x5E, 0x7E, 0xC6,
42 		0xF4, 0x4C, 0x42, 0xE9, 0xA6, 0x37, 0xED, 0x6B, 0x0B, 0xFF, 0x5C, 0xB6, 0xF4, 0x06, 0xB7, 0xED,
43 		0xEE, 0x38, 0x6B, 0xFB, 0x5A, 0x89, 0x9F, 0xA5, 0xAE, 0x9F, 0x24, 0x11, 0x7C, 0x4B, 0x1F, 0xE6,
44 		0x49, 0x28, 0x66, 0x51, 0xEC, 0xE4, 0x5B, 0x3D, 0xC2, 0x00, 0x7C, 0xB8, 0xA1, 0x63, 0xBF, 0x05,
45 		0x98, 0xDA, 0x48, 0x36, 0x1C, 0x55, 0xD3, 0x9A, 0x69, 0x16, 0x3F, 0xA8, 0xFD, 0x24, 0xCF, 0x5F,
46 		0x83, 0x65, 0x5D, 0x23, 0xDC, 0xA3, 0xAD, 0x96, 0x1C, 0x62, 0xF3, 0x56, 0x20, 0x85, 0x52, 0xBB,
47 		0x9E, 0xD5, 0x29, 0x07, 0x70, 0x96, 0x96, 0x6D, 0x67, 0x0C, 0x35, 0x4E, 0x4A, 0xBC, 0x98, 0x04,
48 		0xF1, 0x74, 0x6C, 0x08, 0xCA, 0x18, 0x21, 0x7C, 0x32, 0x90, 0x5E, 0x46, 0x2E, 0x36, 0xCE, 0x3B,
49 		0xE3, 0x9E, 0x77, 0x2C, 0x18, 0x0E, 0x86, 0x03, 0x9B, 0x27, 0x83, 0xA2, 0xEC, 0x07, 0xA2, 0x8F,
50 		0xB5, 0xC5, 0x5D, 0xF0, 0x6F, 0x4C, 0x52, 0xC9, 0xDE, 0x2B, 0xCB, 0xF6, 0x95, 0x58, 0x17, 0x18,
51 		0x39, 0x95, 0x49, 0x7C, 0xEA, 0x95, 0x6A, 0xE5, 0x15, 0xD2, 0x26, 0x18, 0x98, 0xFA, 0x05, 0x10,
52 		0x15, 0x72, 0x8E, 0x5A, 0x8A, 0xAC, 0xAA, 0x68, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF
53 	};
54 
55 	const int elgg_ = 2;
56 
57 	const uint8_t dsap_[128]=
58 	{
59 		0x9c, 0x05, 0xb2, 0xaa, 0x96, 0x0d, 0x9b, 0x97, 0xb8, 0x93, 0x19, 0x63, 0xc9, 0xcc, 0x9e, 0x8c,
60 		0x30, 0x26, 0xe9, 0xb8, 0xed, 0x92, 0xfa, 0xd0, 0xa6, 0x9c, 0xc8, 0x86, 0xd5, 0xbf, 0x80, 0x15,
61 		0xfc, 0xad, 0xae, 0x31, 0xa0, 0xad, 0x18, 0xfa, 0xb3, 0xf0, 0x1b, 0x00, 0xa3, 0x58, 0xde, 0x23,
62 		0x76, 0x55, 0xc4, 0x96, 0x4a, 0xfa, 0xa2, 0xb3, 0x37, 0xe9, 0x6a, 0xd3, 0x16, 0xb9, 0xfb, 0x1c,
63 		0xc5, 0x64, 0xb5, 0xae, 0xc5, 0xb6, 0x9a, 0x9f, 0xf6, 0xc3, 0xe4, 0x54, 0x87, 0x07, 0xfe, 0xf8,
64 		0x50, 0x3d, 0x91, 0xdd, 0x86, 0x02, 0xe8, 0x67, 0xe6, 0xd3, 0x5d, 0x22, 0x35, 0xc1, 0x86, 0x9c,
65 		0xe2, 0x47, 0x9c, 0x3b, 0x9d, 0x54, 0x01, 0xde, 0x04, 0xe0, 0x72, 0x7f, 0xb3, 0x3d, 0x65, 0x11,
66 		0x28, 0x5d, 0x4c, 0xf2, 0x95, 0x38, 0xd9, 0xe3, 0xb6, 0x05, 0x1f, 0x5b, 0x22, 0xcc, 0x1c, 0x93
67 	};
68 
69 	const uint8_t dsaq_[20]=
70 	{
71 		0xa5, 0xdf, 0xc2, 0x8f, 0xef, 0x4c, 0xa1, 0xe2, 0x86, 0x74, 0x4c, 0xd8, 0xee, 0xd9, 0xd2, 0x9d,
72 		0x68, 0x40, 0x46, 0xb7
73 	};
74 
75 	const uint8_t dsag_[128]=
76 	{
77 		0x0c, 0x1f, 0x4d, 0x27, 0xd4, 0x00, 0x93, 0xb4, 0x29, 0xe9, 0x62, 0xd7, 0x22, 0x38, 0x24, 0xe0,
78 		0xbb, 0xc4, 0x7e, 0x7c, 0x83, 0x2a, 0x39, 0x23, 0x6f, 0xc6, 0x83, 0xaf, 0x84, 0x88, 0x95, 0x81,
79 		0x07, 0x5f, 0xf9, 0x08, 0x2e, 0xd3, 0x23, 0x53, 0xd4, 0x37, 0x4d, 0x73, 0x01, 0xcd, 0xa1, 0xd2,
80 		0x3c, 0x43, 0x1f, 0x46, 0x98, 0x59, 0x9d, 0xda, 0x02, 0x45, 0x18, 0x24, 0xff, 0x36, 0x97, 0x52,
81 		0x59, 0x36, 0x47, 0xcc, 0x3d, 0xdc, 0x19, 0x7d, 0xe9, 0x85, 0xe4, 0x3d, 0x13, 0x6c, 0xdc, 0xfc,
82 		0x6b, 0xd5, 0x40, 0x9c, 0xd2, 0xf4, 0x50, 0x82, 0x11, 0x42, 0xa5, 0xe6, 0xf8, 0xeb, 0x1c, 0x3a,
83 		0xb5, 0xd0, 0x48, 0x4b, 0x81, 0x29, 0xfc, 0xf1, 0x7b, 0xce, 0x4f, 0x7f, 0x33, 0x32, 0x1c, 0x3c,
84 		0xb3, 0xdb, 0xb1, 0x4a, 0x90, 0x5e, 0x7b, 0x2b, 0x3e, 0x93, 0xbe, 0x47, 0x08, 0xcb, 0xcc, 0x82
85 	};
86 
87 	const int rsae_ = 65537;
88 
89 	struct CryptoConstants
90 	{
91 		// DH/ElGamal
92 		BIGNUM * elgp;
93 		BIGNUM * elgg;
94 
95 		// DSA
96 		BIGNUM * dsap;
97 		BIGNUM * dsaq;
98 		BIGNUM * dsag;
99 
100 		// RSA
101 		BIGNUM * rsae;
102 
CryptoConstantsi2p::crypto::CryptoConstants103 		CryptoConstants (const uint8_t * elgp_, int elgg_, const uint8_t * dsap_,
104 			const uint8_t * dsaq_, const uint8_t * dsag_, int rsae_)
105 		{
106 			elgp = BN_new ();
107 			BN_bin2bn (elgp_, 256, elgp);
108 			elgg = BN_new ();
109 			BN_set_word (elgg, elgg_);
110 			dsap = BN_new ();
111 			BN_bin2bn (dsap_, 128, dsap);
112 			dsaq = BN_new ();
113 			BN_bin2bn (dsaq_, 20, dsaq);
114 			dsag = BN_new ();
115 			BN_bin2bn (dsag_, 128, dsag);
116 			rsae = BN_new ();
117 			BN_set_word (rsae, rsae_);
118 		}
119 
~CryptoConstantsi2p::crypto::CryptoConstants120 		~CryptoConstants ()
121 		{
122 			BN_free (elgp); BN_free (elgg); BN_free (dsap); BN_free (dsaq); BN_free (dsag); BN_free (rsae);
123 		}
124 	};
125 
GetCryptoConstants()126 	static const CryptoConstants& GetCryptoConstants ()
127 	{
128 		static CryptoConstants cryptoConstants (elgp_, elgg_, dsap_, dsaq_, dsag_, rsae_);
129 		return cryptoConstants;
130 	}
131 
bn2buf(const BIGNUM * bn,uint8_t * buf,size_t len)132 	bool bn2buf (const BIGNUM * bn, uint8_t * buf, size_t len)
133 	{
134 		int offset = len - BN_num_bytes (bn);
135 		if (offset < 0) return false;
136 		BN_bn2bin (bn, buf + offset);
137 		memset (buf, 0, offset);
138 		return true;
139 	}
140 
141 // RSA
142 	#define rsae GetCryptoConstants ().rsae
GetRSAE()143 	const BIGNUM * GetRSAE ()
144 	{
145 		return rsae;
146 	}
147 
148 // DSA
149 	#define dsap GetCryptoConstants ().dsap
150 	#define dsaq GetCryptoConstants ().dsaq
151 	#define dsag GetCryptoConstants ().dsag
CreateDSA()152 	DSA * CreateDSA ()
153 	{
154 		DSA * dsa = DSA_new ();
155 		DSA_set0_pqg (dsa, BN_dup (dsap), BN_dup (dsaq), BN_dup (dsag));
156 		DSA_set0_key (dsa, NULL, NULL);
157 		return dsa;
158 	}
159 
160 // DH/ElGamal
161 
162 	const int ELGAMAL_SHORT_EXPONENT_NUM_BITS = 226;
163 	const int ELGAMAL_SHORT_EXPONENT_NUM_BYTES = ELGAMAL_SHORT_EXPONENT_NUM_BITS/8+1;
164 	const int ELGAMAL_FULL_EXPONENT_NUM_BITS = 2048;
165 	const int ELGAMAL_FULL_EXPONENT_NUM_BYTES = ELGAMAL_FULL_EXPONENT_NUM_BITS/8;
166 
167 	#define elgp GetCryptoConstants ().elgp
168 	#define elgg GetCryptoConstants ().elgg
169 
170 	static BN_MONT_CTX * g_MontCtx = nullptr;
PrecalculateElggTable(BIGNUM * table[][255],int len)171 	static void PrecalculateElggTable (BIGNUM * table[][255], int len) // table is len's array of array of 255 bignums
172 	{
173 		if (len <= 0) return;
174 		BN_CTX * ctx = BN_CTX_new ();
175 		g_MontCtx = BN_MONT_CTX_new ();
176 		BN_MONT_CTX_set (g_MontCtx, elgp, ctx);
177 		auto montCtx = BN_MONT_CTX_new ();
178 		BN_MONT_CTX_copy (montCtx, g_MontCtx);
179 		for (int i = 0; i < len; i++)
180 		{
181 			table[i][0] = BN_new ();
182 			if (!i)
183 				BN_to_montgomery (table[0][0], elgg, montCtx, ctx);
184 			else
185 				BN_mod_mul_montgomery (table[i][0], table[i-1][254], table[i-1][0], montCtx, ctx);
186 			for (int j = 1; j < 255; j++)
187 			{
188 				table[i][j] = BN_new ();
189 				BN_mod_mul_montgomery (table[i][j], table[i][j-1], table[i][0], montCtx, ctx);
190 			}
191 		}
192 		BN_MONT_CTX_free (montCtx);
193 		BN_CTX_free (ctx);
194 	}
195 
DestroyElggTable(BIGNUM * table[][255],int len)196 	static void DestroyElggTable (BIGNUM * table[][255], int len)
197 	{
198 		for (int i = 0; i < len; i++)
199 			for (int j = 0; j < 255; j++)
200 			{
201 				BN_free (table[i][j]);
202 				table[i][j] = nullptr;
203 			}
204 		BN_MONT_CTX_free (g_MontCtx);
205 	}
206 
ElggPow(const uint8_t * exp,int len,BIGNUM * table[][255],BN_CTX * ctx)207 	static BIGNUM * ElggPow (const uint8_t * exp, int len, BIGNUM * table[][255], BN_CTX * ctx)
208 	// exp is in Big Endian
209 	{
210 		if (len <= 0) return nullptr;
211 		auto montCtx = BN_MONT_CTX_new ();
212 		BN_MONT_CTX_copy (montCtx, g_MontCtx);
213 		BIGNUM * res = nullptr;
214 		for (int i = 0; i < len; i++)
215 		{
216 			if (res)
217 			{
218 				if (exp[i])
219 					BN_mod_mul_montgomery (res, res, table[len-1-i][exp[i]-1], montCtx, ctx);
220 			}
221 			else if (exp[i])
222 				res = BN_dup (table[len-i-1][exp[i]-1]);
223 		}
224 		if (res)
225 			BN_from_montgomery (res, res, montCtx, ctx);
226 		BN_MONT_CTX_free (montCtx);
227 		return res;
228 	}
229 
ElggPow(const BIGNUM * exp,BIGNUM * table[][255],BN_CTX * ctx)230 	static BIGNUM * ElggPow (const BIGNUM * exp, BIGNUM * table[][255], BN_CTX * ctx)
231 	{
232 		auto len = BN_num_bytes (exp);
233 		uint8_t * buf = new uint8_t[len];
234 		BN_bn2bin (exp, buf);
235 		auto ret = ElggPow (buf, len, table, ctx);
236 		delete[] buf;
237 		return ret;
238 	}
239 
240 	static BIGNUM * (* g_ElggTable)[255] = nullptr;
241 
242 // DH
243 
DHKeys()244 	DHKeys::DHKeys ()
245 	{
246 		m_DH = DH_new ();
247 		DH_set0_pqg (m_DH, BN_dup (elgp), NULL, BN_dup (elgg));
248 		DH_set0_key (m_DH, NULL, NULL);
249 	}
250 
~DHKeys()251 	DHKeys::~DHKeys ()
252 	{
253 		DH_free (m_DH);
254 	}
255 
GenerateKeys()256 	void DHKeys::GenerateKeys ()
257 	{
258 		BIGNUM * priv_key = NULL, * pub_key = NULL;
259 #if !defined(__x86_64__) // use short exponent for non x64
260 		priv_key = BN_new ();
261 		BN_rand (priv_key, ELGAMAL_SHORT_EXPONENT_NUM_BITS, 0, 1);
262 #endif
263 		if (g_ElggTable)
264 		{
265 #if defined(__x86_64__)
266 			priv_key = BN_new ();
267 			BN_rand (priv_key, ELGAMAL_FULL_EXPONENT_NUM_BITS, 0, 1);
268 #endif
269 			auto ctx = BN_CTX_new ();
270 			pub_key = ElggPow (priv_key, g_ElggTable, ctx);
271 			DH_set0_key (m_DH, pub_key, priv_key);
272 			BN_CTX_free (ctx);
273 		}
274 		else
275 		{
276 			DH_set0_key (m_DH, NULL, priv_key);
277 			DH_generate_key (m_DH);
278 			DH_get0_key (m_DH, (const BIGNUM **)&pub_key, (const BIGNUM **)&priv_key);
279 		}
280 
281 		bn2buf (pub_key, m_PublicKey, 256);
282 	}
283 
Agree(const uint8_t * pub,uint8_t * shared)284 	void DHKeys::Agree (const uint8_t * pub, uint8_t * shared)
285 	{
286 		BIGNUM * pk = BN_bin2bn (pub, 256, NULL);
287 		DH_compute_key (shared, pk, m_DH);
288 		BN_free (pk);
289 	}
290 
291 // x25519
X25519Keys()292 	X25519Keys::X25519Keys ()
293 	{
294 #if OPENSSL_X25519
295 		m_Ctx = EVP_PKEY_CTX_new_id (NID_X25519, NULL);
296 		m_Pkey = nullptr;
297 #else
298 		m_Ctx = BN_CTX_new ();
299 #endif
300 	}
301 
X25519Keys(const uint8_t * priv,const uint8_t * pub)302 	X25519Keys::X25519Keys (const uint8_t * priv, const uint8_t * pub)
303 	{
304 #if OPENSSL_X25519
305 		m_Pkey = EVP_PKEY_new_raw_private_key (EVP_PKEY_X25519, NULL, priv, 32);
306 		m_Ctx = EVP_PKEY_CTX_new (m_Pkey, NULL);
307 		if (pub)
308 			memcpy (m_PublicKey, pub, 32); // TODO: verify against m_Pkey
309 		else
310 		{
311 			size_t len = 32;
312 			EVP_PKEY_get_raw_public_key (m_Pkey, m_PublicKey, &len);
313 		}
314 #else
315 		m_Ctx = BN_CTX_new ();
316 		memcpy (m_PrivateKey, priv, 32);
317 		if (pub)
318 			memcpy (m_PublicKey, pub, 32);
319 		else
320 			GetEd25519 ()->ScalarMulB (m_PrivateKey, m_PublicKey, m_Ctx);
321 #endif
322 	}
323 
~X25519Keys()324 	X25519Keys::~X25519Keys ()
325 	{
326 #if OPENSSL_X25519
327 		EVP_PKEY_CTX_free (m_Ctx);
328 		if (m_Pkey) EVP_PKEY_free (m_Pkey);
329 #else
330 		BN_CTX_free (m_Ctx);
331 #endif
332 	}
333 
GenerateKeys()334 	void X25519Keys::GenerateKeys ()
335 	{
336 #if OPENSSL_X25519
337 		if (m_Pkey)
338 		{
339 			EVP_PKEY_free (m_Pkey);
340 			m_Pkey = nullptr;
341 		}
342 		EVP_PKEY_keygen_init (m_Ctx);
343 		EVP_PKEY_keygen (m_Ctx, &m_Pkey);
344 		EVP_PKEY_CTX_free (m_Ctx);
345 		m_Ctx = EVP_PKEY_CTX_new (m_Pkey, NULL); // TODO: do we really need to re-create m_Ctx?
346 		size_t len = 32;
347 		EVP_PKEY_get_raw_public_key (m_Pkey, m_PublicKey, &len);
348 #else
349 		RAND_bytes (m_PrivateKey, 32);
350 		GetEd25519 ()->ScalarMulB (m_PrivateKey, m_PublicKey, m_Ctx);
351 #endif
352 	}
353 
Agree(const uint8_t * pub,uint8_t * shared)354 	bool X25519Keys::Agree (const uint8_t * pub, uint8_t * shared)
355 	{
356 		if (!pub || (pub[31] & 0x80)) return false; // not x25519 key
357 #if OPENSSL_X25519
358 		EVP_PKEY_derive_init (m_Ctx);
359 		auto pkey = EVP_PKEY_new_raw_public_key (EVP_PKEY_X25519, NULL, pub, 32);
360 		if (!pkey) return false;
361 		EVP_PKEY_derive_set_peer (m_Ctx, pkey);
362 		size_t len = 32;
363 		EVP_PKEY_derive (m_Ctx, shared, &len);
364 		EVP_PKEY_free (pkey);
365 #else
366 		GetEd25519 ()->ScalarMul (pub, m_PrivateKey, shared, m_Ctx);
367 #endif
368 		return true;
369 	}
370 
GetPrivateKey(uint8_t * priv) const371 	void X25519Keys::GetPrivateKey (uint8_t * priv) const
372 	{
373 #if OPENSSL_X25519
374 		size_t len = 32;
375 		EVP_PKEY_get_raw_private_key (m_Pkey, priv, &len);
376 #else
377 		memcpy (priv, m_PrivateKey, 32);
378 #endif
379 	}
380 
SetPrivateKey(const uint8_t * priv,bool calculatePublic)381 	void X25519Keys::SetPrivateKey (const uint8_t * priv, bool calculatePublic)
382 	{
383 #if OPENSSL_X25519
384 		if (m_Ctx) EVP_PKEY_CTX_free (m_Ctx);
385 		if (m_Pkey) EVP_PKEY_free (m_Pkey);
386 		m_Pkey = EVP_PKEY_new_raw_private_key (EVP_PKEY_X25519, NULL, priv, 32);
387 		m_Ctx = EVP_PKEY_CTX_new (m_Pkey, NULL);
388 		if (calculatePublic)
389 		{
390 			size_t len = 32;
391 			EVP_PKEY_get_raw_public_key (m_Pkey, m_PublicKey, &len);
392 		}
393 #else
394 		memcpy (m_PrivateKey, priv, 32);
395 		if (calculatePublic)
396 			GetEd25519 ()->ScalarMulB (m_PrivateKey, m_PublicKey, m_Ctx);
397 #endif
398 	}
399 
400 // ElGamal
ElGamalEncrypt(const uint8_t * key,const uint8_t * data,uint8_t * encrypted)401 	void ElGamalEncrypt (const uint8_t * key, const uint8_t * data, uint8_t * encrypted)
402 	{
403 		BN_CTX * ctx = BN_CTX_new ();
404 		BN_CTX_start (ctx);
405 		// everything, but a, because a might come from table
406 		BIGNUM * k = BN_CTX_get (ctx);
407 		BIGNUM * y = BN_CTX_get (ctx);
408 		BIGNUM * b1 = BN_CTX_get (ctx);
409 		BIGNUM * b = BN_CTX_get (ctx);
410 		// select random k
411 #if defined(__x86_64__)
412 		BN_rand (k, ELGAMAL_FULL_EXPONENT_NUM_BITS, -1, 1); // full exponent for x64
413 #else
414 		BN_rand (k, ELGAMAL_SHORT_EXPONENT_NUM_BITS, -1, 1); // short exponent of 226 bits
415 #endif
416 		// calculate a
417 		BIGNUM * a;
418 		if (g_ElggTable)
419 			a = ElggPow (k, g_ElggTable, ctx);
420 		else
421 		{
422 			a = BN_new ();
423 			BN_mod_exp (a, elgg, k, elgp, ctx);
424 		}
425 
426 		// restore y from key
427 		BN_bin2bn (key, 256, y);
428 		// calculate b1
429 		BN_mod_exp (b1, y, k, elgp, ctx);
430 		// create m
431 		uint8_t m[255];
432 		m[0] = 0xFF;
433 		memcpy (m+33, data, 222);
434 		SHA256 (m+33, 222, m+1);
435 		// calculate b = b1*m mod p
436 		BN_bin2bn (m, 255, b);
437 		BN_mod_mul (b, b1, b, elgp, ctx);
438 		// copy a and b
439 		encrypted[0] = 0;
440 		bn2buf (a, encrypted + 1, 256);
441 		encrypted[257] = 0;
442 		bn2buf (b, encrypted + 258, 256);
443 
444 		BN_free (a);
445 		BN_CTX_end (ctx);
446 		BN_CTX_free (ctx);
447 	}
448 
ElGamalDecrypt(const uint8_t * key,const uint8_t * encrypted,uint8_t * data)449 	bool ElGamalDecrypt (const uint8_t * key, const uint8_t * encrypted, uint8_t * data)
450 	{
451 		BN_CTX * ctx = BN_CTX_new ();
452 		BN_CTX_start (ctx);
453 		BIGNUM * x = BN_CTX_get (ctx), * a = BN_CTX_get (ctx), * b = BN_CTX_get (ctx);
454 		BN_bin2bn (key, 256, x);
455 		BN_sub (x, elgp, x); BN_sub_word (x, 1); // x = elgp - x- 1
456 		BN_bin2bn (encrypted + 1, 256, a);
457 		BN_bin2bn (encrypted + 258, 256, b);
458 		// m = b*(a^x mod p) mod p
459 		BN_mod_exp (x, a, x, elgp, ctx);
460 		BN_mod_mul (b, b, x, elgp, ctx);
461 		uint8_t m[255];
462 		bn2buf (b, m, 255);
463 		BN_CTX_end (ctx);
464 		BN_CTX_free (ctx);
465 		uint8_t hash[32];
466 		SHA256 (m + 33, 222, hash);
467 		if (memcmp (m + 1, hash, 32))
468 		{
469 			LogPrint (eLogError, "ElGamal decrypt hash doesn't match");
470 			return false;
471 		}
472 		memcpy (data, m + 33, 222);
473 		return true;
474 	}
475 
GenerateElGamalKeyPair(uint8_t * priv,uint8_t * pub)476 	void GenerateElGamalKeyPair (uint8_t * priv, uint8_t * pub)
477 	{
478 #if defined(__x86_64__) || defined(__i386__) || defined(_MSC_VER)
479 		RAND_bytes (priv, 256);
480 #else
481 		// lower 226 bits (28 bytes and 2 bits) only. short exponent
482 		auto numBytes = (ELGAMAL_SHORT_EXPONENT_NUM_BITS)/8 + 1; // 29
483 		auto numZeroBytes = 256 - numBytes;
484 		RAND_bytes (priv + numZeroBytes, numBytes);
485 		memset (priv, 0, numZeroBytes);
486 		priv[numZeroBytes] &= 0x03;
487 #endif
488 		BN_CTX * ctx = BN_CTX_new ();
489 		BIGNUM * p = BN_new ();
490 		BN_bin2bn (priv, 256, p);
491 		BN_mod_exp (p, elgg, p, elgp, ctx);
492 		bn2buf (p, pub, 256);
493 		BN_free (p);
494 		BN_CTX_free (ctx);
495 	}
496 
497 // ECIES
ECIESEncrypt(const EC_GROUP * curve,const EC_POINT * key,const uint8_t * data,uint8_t * encrypted)498 	void ECIESEncrypt (const EC_GROUP * curve, const EC_POINT * key, const uint8_t * data, uint8_t * encrypted)
499 	{
500 		BN_CTX * ctx = BN_CTX_new ();
501 		BN_CTX_start (ctx);
502 		BIGNUM * q = BN_CTX_get (ctx);
503 		EC_GROUP_get_order(curve, q, ctx);
504 		int len = BN_num_bytes (q);
505 		BIGNUM * k = BN_CTX_get (ctx);
506 		BN_rand_range (k, q); // 0 < k < q
507 		// point for shared secret
508 		auto p = EC_POINT_new (curve);
509 		EC_POINT_mul (curve, p, k, nullptr, nullptr, ctx);
510 		BIGNUM * x = BN_CTX_get (ctx), * y = BN_CTX_get (ctx);
511 		EC_POINT_get_affine_coordinates_GFp (curve, p, x, y, nullptr);
512 		encrypted[0] = 0;
513 		bn2buf (x, encrypted + 1, len);
514 		bn2buf (y, encrypted + 1 + len, len);
515 		RAND_bytes (encrypted + 1 + 2*len, 256 - 2*len);
516 		// encryption key and iv
517 		EC_POINT_mul (curve, p, nullptr, key, k, ctx);
518 		EC_POINT_get_affine_coordinates_GFp (curve, p, x, y, nullptr);
519 		uint8_t keyBuf[64], iv[64], shared[32];
520 		bn2buf (x, keyBuf, len);
521 		bn2buf (y, iv, len);
522 		SHA256 (keyBuf, len, shared);
523 		// create buffer
524 		uint8_t m[256];
525 		m[0] = 0xFF; m[255] = 0xFF;
526 		memcpy (m+33, data, 222);
527 		SHA256 (m+33, 222, m+1);
528 		// encrypt
529 		CBCEncryption encryption;
530 		encryption.SetKey (shared);
531 		encryption.SetIV (iv);
532 		encrypted[257] = 0;
533 		encryption.Encrypt (m, 256, encrypted + 258);
534 		EC_POINT_free (p);
535 		BN_CTX_end (ctx);
536 		BN_CTX_free (ctx);
537 	}
538 
ECIESDecrypt(const EC_GROUP * curve,const BIGNUM * key,const uint8_t * encrypted,uint8_t * data)539 	bool ECIESDecrypt (const EC_GROUP * curve, const BIGNUM * key, const uint8_t * encrypted, uint8_t * data)
540 	{
541 		bool ret = true;
542 		BN_CTX * ctx = BN_CTX_new ();
543 		BN_CTX_start (ctx);
544 		BIGNUM * q = BN_CTX_get (ctx);
545 		EC_GROUP_get_order(curve, q, ctx);
546 		int len = BN_num_bytes (q);
547 		// point for shared secret
548 		BIGNUM * x = BN_CTX_get (ctx), * y = BN_CTX_get (ctx);
549 		BN_bin2bn (encrypted + 1, len, x);
550 		BN_bin2bn (encrypted + 1 + len, len, y);
551 		auto p = EC_POINT_new (curve);
552 		if (EC_POINT_set_affine_coordinates_GFp (curve, p, x, y, nullptr))
553 		{
554 			auto s = EC_POINT_new (curve);
555 			EC_POINT_mul (curve, s, nullptr, p, key, ctx);
556 			EC_POINT_get_affine_coordinates_GFp (curve, s, x, y, nullptr);
557 			EC_POINT_free (s);
558 			uint8_t keyBuf[64], iv[64], shared[32];
559 			bn2buf (x, keyBuf, len);
560 			bn2buf (y, iv, len);
561 			SHA256 (keyBuf, len, shared);
562 			// decrypt
563 			uint8_t m[256];
564 			CBCDecryption decryption;
565 			decryption.SetKey (shared);
566 			decryption.SetIV (iv);
567 			decryption.Decrypt (encrypted + 258, 256, m);
568 			// verify and copy
569 			uint8_t hash[32];
570 			SHA256 (m + 33, 222, hash);
571 			if (!memcmp (m + 1, hash, 32))
572 				memcpy (data, m + 33, 222);
573 			else
574 			{
575 				LogPrint (eLogError, "ECIES decrypt hash doesn't match");
576 				ret = false;
577 			}
578 		}
579 		else
580 		{
581 			LogPrint (eLogError, "ECIES decrypt point is invalid");
582 			ret = false;
583 		}
584 
585 		EC_POINT_free (p);
586 		BN_CTX_end (ctx);
587 		BN_CTX_free (ctx);
588 		return ret;
589 	}
590 
GenerateECIESKeyPair(const EC_GROUP * curve,BIGNUM * & priv,EC_POINT * & pub)591 	void GenerateECIESKeyPair (const EC_GROUP * curve, BIGNUM *& priv, EC_POINT *& pub)
592 	{
593 		BN_CTX * ctx = BN_CTX_new ();
594 		BIGNUM * q = BN_new ();
595 		EC_GROUP_get_order(curve, q, ctx);
596 		priv = BN_new ();
597 		BN_rand_range (priv, q);
598 		pub = EC_POINT_new (curve);
599 		EC_POINT_mul (curve, pub, priv, nullptr, nullptr, ctx);
600 		BN_free (q);
601 		BN_CTX_free (ctx);
602 	}
603 
604 // HMAC
605 	const uint64_t IPAD = 0x3636363636363636;
606 	const uint64_t OPAD = 0x5C5C5C5C5C5C5C5C;
607 
608 
609 	static const uint64_t ipads[] = { IPAD, IPAD, IPAD, IPAD };
610 	static const uint64_t opads[] = { OPAD, OPAD, OPAD, OPAD };
611 
HMACMD5Digest(uint8_t * msg,size_t len,const MACKey & key,uint8_t * digest)612 	void HMACMD5Digest (uint8_t * msg, size_t len, const MACKey& key, uint8_t * digest)
613 	// key is 32 bytes
614 	// digest is 16 bytes
615 	// block size is 64 bytes
616 	{
617 		uint64_t buf[256];
618 		uint64_t hash[12]; // 96 bytes
619 #if (defined(__x86_64__) || defined(__i386__)) && defined(__AVX__) // not all X86 targets supports AVX (like old Pentium, see #1600)
620 		if(i2p::cpu::avx)
621 		{
622 			__asm__
623 				(
624 					"vmovups %[key], %%ymm0 \n"
625 					"vmovups %[ipad], %%ymm1 \n"
626 					"vmovups %%ymm1, 32(%[buf]) \n"
627 					"vxorps %%ymm0, %%ymm1, %%ymm1 \n"
628 					"vmovups %%ymm1, (%[buf]) \n"
629 					"vmovups %[opad], %%ymm1 \n"
630 					"vmovups %%ymm1, 32(%[hash]) \n"
631 					"vxorps %%ymm0, %%ymm1, %%ymm1 \n"
632 					"vmovups %%ymm1, (%[hash]) \n"
633 					"vzeroall \n" // end of AVX
634 					"movups %%xmm0, 80(%[hash]) \n" // zero last 16 bytes
635 					:
636 					: [key]"m"(*(const uint8_t *)key), [ipad]"m"(*ipads), [opad]"m"(*opads),
637 						[buf]"r"(buf), [hash]"r"(hash)
638 					: "memory", "%xmm0" // TODO: change to %ymm0 later
639 					);
640 		}
641 		else
642 #endif
643 		{
644 			// ikeypad
645 			buf[0] = key.GetLL ()[0] ^ IPAD;
646 			buf[1] = key.GetLL ()[1] ^ IPAD;
647 			buf[2] = key.GetLL ()[2] ^ IPAD;
648 			buf[3] = key.GetLL ()[3] ^ IPAD;
649 			buf[4] = IPAD;
650 			buf[5] = IPAD;
651 			buf[6] = IPAD;
652 			buf[7] = IPAD;
653 			// okeypad
654 			hash[0] = key.GetLL ()[0] ^ OPAD;
655 			hash[1] = key.GetLL ()[1] ^ OPAD;
656 			hash[2] = key.GetLL ()[2] ^ OPAD;
657 			hash[3] = key.GetLL ()[3] ^ OPAD;
658 			hash[4] = OPAD;
659 			hash[5] = OPAD;
660 			hash[6] = OPAD;
661 			hash[7] = OPAD;
662 			// fill last 16 bytes with zeros (first hash size assumed 32 bytes in I2P)
663 			memset (hash + 10, 0, 16);
664 		}
665 
666 		// concatenate with msg
667 		memcpy (buf + 8, msg, len);
668 		// calculate first hash
669 		MD5((uint8_t *)buf, len + 64, (uint8_t *)(hash + 8)); // 16 bytes
670 
671 		// calculate digest
672 		MD5((uint8_t *)hash, 96, digest);
673 	}
674 
675 // AES
676 #ifdef __AES__
677 	#define KeyExpansion256(round0,round1) \
678 		"pshufd $0xff, %%xmm2, %%xmm2 \n" \
679 		"movaps %%xmm1, %%xmm4 \n" \
680 		"pslldq $4, %%xmm4 \n" \
681 		"pxor %%xmm4, %%xmm1 \n" \
682 		"pslldq $4, %%xmm4 \n" \
683 		"pxor %%xmm4, %%xmm1 \n" \
684 		"pslldq $4, %%xmm4 \n" \
685 		"pxor %%xmm4, %%xmm1 \n" \
686 		"pxor %%xmm2, %%xmm1 \n" \
687 		"movaps %%xmm1, "#round0"(%[sched]) \n" \
688 		"aeskeygenassist $0, %%xmm1, %%xmm4 \n" \
689 		"pshufd $0xaa, %%xmm4, %%xmm2 \n" \
690 		"movaps %%xmm3, %%xmm4 \n" \
691 		"pslldq $4, %%xmm4 \n" \
692 		"pxor %%xmm4, %%xmm3 \n" \
693 		"pslldq $4, %%xmm4 \n" \
694 		"pxor %%xmm4, %%xmm3 \n" \
695 		"pslldq $4, %%xmm4 \n" \
696 		"pxor %%xmm4, %%xmm3 \n" \
697 		"pxor %%xmm2, %%xmm3 \n" \
698 		"movaps %%xmm3, "#round1"(%[sched]) \n"
699 #endif
700 
701 #ifdef __AES__
ExpandKey(const AESKey & key)702 	void ECBCryptoAESNI::ExpandKey (const AESKey& key)
703 	{
704 		__asm__
705 		(
706 			"movups (%[key]), %%xmm1 \n"
707 			"movups 16(%[key]), %%xmm3 \n"
708 			"movaps %%xmm1, (%[sched]) \n"
709 			"movaps %%xmm3, 16(%[sched]) \n"
710 			"aeskeygenassist $1, %%xmm3, %%xmm2 \n"
711 			KeyExpansion256(32,48)
712 			"aeskeygenassist $2, %%xmm3, %%xmm2 \n"
713 			KeyExpansion256(64,80)
714 			"aeskeygenassist $4, %%xmm3, %%xmm2 \n"
715 			KeyExpansion256(96,112)
716 			"aeskeygenassist $8, %%xmm3, %%xmm2 \n"
717 			KeyExpansion256(128,144)
718 			"aeskeygenassist $16, %%xmm3, %%xmm2 \n"
719 			KeyExpansion256(160,176)
720 			"aeskeygenassist $32, %%xmm3, %%xmm2 \n"
721 			KeyExpansion256(192,208)
722 			"aeskeygenassist $64, %%xmm3, %%xmm2 \n"
723 			// key expansion final
724 			"pshufd $0xff, %%xmm2, %%xmm2 \n"
725 			"movaps %%xmm1, %%xmm4 \n"
726 			"pslldq $4, %%xmm4 \n"
727 			"pxor %%xmm4, %%xmm1 \n"
728 			"pslldq $4, %%xmm4 \n"
729 			"pxor %%xmm4, %%xmm1 \n"
730 			"pslldq $4, %%xmm4 \n"
731 			"pxor %%xmm4, %%xmm1 \n"
732 			"pxor %%xmm2, %%xmm1 \n"
733 			"movups %%xmm1, 224(%[sched]) \n"
734 			: // output
735 			: [key]"r"((const uint8_t *)key), [sched]"r"(GetKeySchedule ()) // input
736 			: "%xmm1", "%xmm2", "%xmm3", "%xmm4", "memory" // clogged
737 		);
738 	}
739 #endif
740 
741 
742 #ifdef __AES__
743 	#define EncryptAES256(sched) \
744 		"pxor (%["#sched"]), %%xmm0 \n" \
745 		"aesenc	16(%["#sched"]), %%xmm0 \n" \
746 		"aesenc	32(%["#sched"]), %%xmm0 \n" \
747 		"aesenc	48(%["#sched"]), %%xmm0 \n" \
748 		"aesenc	64(%["#sched"]), %%xmm0 \n" \
749 		"aesenc	80(%["#sched"]), %%xmm0 \n" \
750 		"aesenc	96(%["#sched"]), %%xmm0 \n" \
751 		"aesenc	112(%["#sched"]), %%xmm0 \n" \
752 		"aesenc	128(%["#sched"]), %%xmm0 \n" \
753 		"aesenc	144(%["#sched"]), %%xmm0 \n" \
754 		"aesenc	160(%["#sched"]), %%xmm0 \n" \
755 		"aesenc	176(%["#sched"]), %%xmm0 \n" \
756 		"aesenc	192(%["#sched"]), %%xmm0 \n" \
757 		"aesenc	208(%["#sched"]), %%xmm0 \n" \
758 		"aesenclast	224(%["#sched"]), %%xmm0 \n"
759 #endif
760 
Encrypt(const ChipherBlock * in,ChipherBlock * out)761 	void ECBEncryption::Encrypt (const ChipherBlock * in, ChipherBlock * out)
762 	{
763 #ifdef __AES__
764 		if(i2p::cpu::aesni)
765 		{
766 			__asm__
767 				(
768 					"movups (%[in]), %%xmm0 \n"
769 					EncryptAES256(sched)
770 					"movups %%xmm0, (%[out]) \n"
771 					: : [sched]"r"(GetKeySchedule ()), [in]"r"(in), [out]"r"(out) : "%xmm0", "memory"
772 					);
773 		}
774 		else
775 #endif
776 		{
777 			AES_encrypt (in->buf, out->buf, &m_Key);
778 		}
779 	}
780 
781 #ifdef __AES__
782 	#define DecryptAES256(sched) \
783 		"pxor 224(%["#sched"]), %%xmm0 \n" \
784 		"aesdec	208(%["#sched"]), %%xmm0 \n" \
785 		"aesdec	192(%["#sched"]), %%xmm0 \n" \
786 		"aesdec	176(%["#sched"]), %%xmm0 \n" \
787 		"aesdec	160(%["#sched"]), %%xmm0 \n" \
788 		"aesdec	144(%["#sched"]), %%xmm0 \n" \
789 		"aesdec	128(%["#sched"]), %%xmm0 \n" \
790 		"aesdec	112(%["#sched"]), %%xmm0 \n" \
791 		"aesdec	96(%["#sched"]), %%xmm0 \n" \
792 		"aesdec	80(%["#sched"]), %%xmm0 \n" \
793 		"aesdec	64(%["#sched"]), %%xmm0 \n" \
794 		"aesdec	48(%["#sched"]), %%xmm0 \n" \
795 		"aesdec	32(%["#sched"]), %%xmm0 \n" \
796 		"aesdec	16(%["#sched"]), %%xmm0 \n" \
797 		"aesdeclast (%["#sched"]), %%xmm0 \n"
798 #endif
799 
Decrypt(const ChipherBlock * in,ChipherBlock * out)800 	void ECBDecryption::Decrypt (const ChipherBlock * in, ChipherBlock * out)
801 	{
802 #ifdef __AES__
803 		if(i2p::cpu::aesni)
804 		{
805 			__asm__
806 				(
807 					"movups (%[in]), %%xmm0 \n"
808 					DecryptAES256(sched)
809 					"movups %%xmm0, (%[out]) \n"
810 					: : [sched]"r"(GetKeySchedule ()), [in]"r"(in), [out]"r"(out) : "%xmm0", "memory"
811 					);
812 		}
813 		else
814 #endif
815 		{
816 			AES_decrypt (in->buf, out->buf, &m_Key);
817 		}
818 	}
819 
820 #ifdef __AES__
821 	#define CallAESIMC(offset) \
822 		"movaps "#offset"(%[shed]), %%xmm0 \n" \
823 		"aesimc %%xmm0, %%xmm0 \n" \
824 		"movaps %%xmm0, "#offset"(%[shed]) \n"
825 #endif
826 
SetKey(const AESKey & key)827 	void ECBEncryption::SetKey (const AESKey& key)
828 	{
829 #ifdef __AES__
830 		if(i2p::cpu::aesni)
831 		{
832 			ExpandKey (key);
833 		}
834 		else
835 #endif
836 		{
837 			AES_set_encrypt_key (key, 256, &m_Key);
838 		}
839 	}
840 
SetKey(const AESKey & key)841 	void ECBDecryption::SetKey (const AESKey& key)
842 	{
843 #ifdef __AES__
844 		if(i2p::cpu::aesni)
845 		{
846 			ExpandKey (key); // expand encryption key first
847 			// then invert it using aesimc
848 			__asm__
849 				(
850 					CallAESIMC(16)
851 					CallAESIMC(32)
852 					CallAESIMC(48)
853 					CallAESIMC(64)
854 					CallAESIMC(80)
855 					CallAESIMC(96)
856 					CallAESIMC(112)
857 					CallAESIMC(128)
858 					CallAESIMC(144)
859 					CallAESIMC(160)
860 					CallAESIMC(176)
861 					CallAESIMC(192)
862 					CallAESIMC(208)
863 					: : [shed]"r"(GetKeySchedule ()) : "%xmm0", "memory"
864 					);
865 		}
866 		else
867 #endif
868 		{
869 			AES_set_decrypt_key (key, 256, &m_Key);
870 		}
871 	}
872 
Encrypt(int numBlocks,const ChipherBlock * in,ChipherBlock * out)873 	void CBCEncryption::Encrypt (int numBlocks, const ChipherBlock * in, ChipherBlock * out)
874 	{
875 #ifdef __AES__
876 		if(i2p::cpu::aesni)
877 		{
878 			__asm__
879 				(
880 					"movups (%[iv]), %%xmm1 \n"
881 					"1: \n"
882 					"movups (%[in]), %%xmm0 \n"
883 					"pxor %%xmm1, %%xmm0 \n"
884 					EncryptAES256(sched)
885 					"movaps %%xmm0, %%xmm1 \n"
886 					"movups %%xmm0, (%[out]) \n"
887 					"add $16, %[in] \n"
888 					"add $16, %[out] \n"
889 					"dec %[num] \n"
890 					"jnz 1b \n"
891 					"movups %%xmm1, (%[iv]) \n"
892 					:
893 					: [iv]"r"((uint8_t *)m_LastBlock), [sched]"r"(m_ECBEncryption.GetKeySchedule ()),
894 						[in]"r"(in), [out]"r"(out), [num]"r"(numBlocks)
895 					: "%xmm0", "%xmm1", "cc", "memory"
896 					);
897 		}
898 		else
899 #endif
900 		{
901 			for (int i = 0; i < numBlocks; i++)
902 			{
903 				*m_LastBlock.GetChipherBlock () ^= in[i];
904 				m_ECBEncryption.Encrypt (m_LastBlock.GetChipherBlock (), m_LastBlock.GetChipherBlock ());
905 				out[i] = *m_LastBlock.GetChipherBlock ();
906 			}
907 		}
908 	}
909 
Encrypt(const uint8_t * in,std::size_t len,uint8_t * out)910 	void CBCEncryption::Encrypt (const uint8_t * in, std::size_t len, uint8_t * out)
911 	{
912 		// len/16
913 		int numBlocks = len >> 4;
914 		if (numBlocks > 0)
915 			Encrypt (numBlocks, (const ChipherBlock *)in, (ChipherBlock *)out);
916 	}
917 
Encrypt(const uint8_t * in,uint8_t * out)918 	void CBCEncryption::Encrypt (const uint8_t * in, uint8_t * out)
919 	{
920 #ifdef __AES__
921 		if(i2p::cpu::aesni)
922 		{
923 			__asm__
924 				(
925 					"movups (%[iv]), %%xmm1 \n"
926 					"movups (%[in]), %%xmm0 \n"
927 					"pxor %%xmm1, %%xmm0 \n"
928 					EncryptAES256(sched)
929 					"movups %%xmm0, (%[out]) \n"
930 					"movups %%xmm0, (%[iv]) \n"
931 					:
932 					: [iv]"r"((uint8_t *)m_LastBlock), [sched]"r"(m_ECBEncryption.GetKeySchedule ()),
933 						[in]"r"(in), [out]"r"(out)
934 					: "%xmm0", "%xmm1", "memory"
935 					);
936 		}
937 		else
938 #endif
939 			Encrypt (1, (const ChipherBlock *)in, (ChipherBlock *)out);
940 	}
941 
Decrypt(int numBlocks,const ChipherBlock * in,ChipherBlock * out)942 	void CBCDecryption::Decrypt (int numBlocks, const ChipherBlock * in, ChipherBlock * out)
943 	{
944 #ifdef __AES__
945 		if(i2p::cpu::aesni)
946 		{
947 			__asm__
948 				(
949 					"movups (%[iv]), %%xmm1 \n"
950 					"1: \n"
951 					"movups (%[in]), %%xmm0 \n"
952 					"movaps %%xmm0, %%xmm2 \n"
953 					DecryptAES256(sched)
954 					"pxor %%xmm1, %%xmm0 \n"
955 					"movups %%xmm0, (%[out]) \n"
956 					"movaps %%xmm2, %%xmm1 \n"
957 					"add $16, %[in] \n"
958 					"add $16, %[out] \n"
959 					"dec %[num] \n"
960 					"jnz 1b \n"
961 					"movups %%xmm1, (%[iv]) \n"
962 					:
963 					: [iv]"r"((uint8_t *)m_IV), [sched]"r"(m_ECBDecryption.GetKeySchedule ()),
964 						[in]"r"(in), [out]"r"(out), [num]"r"(numBlocks)
965 					: "%xmm0", "%xmm1", "%xmm2", "cc", "memory"
966 					);
967 		}
968 		else
969 #endif
970 		{
971 			for (int i = 0; i < numBlocks; i++)
972 			{
973 				ChipherBlock tmp = in[i];
974 				m_ECBDecryption.Decrypt (in + i, out + i);
975 				out[i] ^= *m_IV.GetChipherBlock ();
976 				*m_IV.GetChipherBlock () = tmp;
977 			}
978 		}
979 	}
980 
Decrypt(const uint8_t * in,std::size_t len,uint8_t * out)981 	void CBCDecryption::Decrypt (const uint8_t * in, std::size_t len, uint8_t * out)
982 	{
983 		int numBlocks = len >> 4;
984 		if (numBlocks > 0)
985 			Decrypt (numBlocks, (const ChipherBlock *)in, (ChipherBlock *)out);
986 	}
987 
Decrypt(const uint8_t * in,uint8_t * out)988 	void CBCDecryption::Decrypt (const uint8_t * in, uint8_t * out)
989 	{
990 #ifdef __AES__
991 		if(i2p::cpu::aesni)
992 		{
993 			__asm__
994 				(
995 					"movups (%[iv]), %%xmm1 \n"
996 					"movups (%[in]), %%xmm0 \n"
997 					"movups %%xmm0, (%[iv]) \n"
998 					DecryptAES256(sched)
999 					"pxor %%xmm1, %%xmm0 \n"
1000 					"movups %%xmm0, (%[out]) \n"
1001 					:
1002 					: [iv]"r"((uint8_t *)m_IV), [sched]"r"(m_ECBDecryption.GetKeySchedule ()),
1003 						[in]"r"(in), [out]"r"(out)
1004 					: "%xmm0", "%xmm1", "memory"
1005 					);
1006 		}
1007 		else
1008 #endif
1009 			Decrypt (1, (const ChipherBlock *)in, (ChipherBlock *)out);
1010 	}
1011 
Encrypt(const uint8_t * in,uint8_t * out)1012 	void TunnelEncryption::Encrypt (const uint8_t * in, uint8_t * out)
1013 	{
1014 #ifdef __AES__
1015 		if(i2p::cpu::aesni)
1016 		{
1017 			__asm__
1018 				(
1019 					// encrypt IV
1020 					"movups (%[in]), %%xmm0 \n"
1021 					EncryptAES256(sched_iv)
1022 					"movaps %%xmm0, %%xmm1 \n"
1023 					// double IV encryption
1024 					EncryptAES256(sched_iv)
1025 					"movups %%xmm0, (%[out]) \n"
1026 					// encrypt data, IV is xmm1
1027 					"1: \n"
1028 					"add $16, %[in] \n"
1029 					"add $16, %[out] \n"
1030 					"movups (%[in]), %%xmm0 \n"
1031 					"pxor %%xmm1, %%xmm0 \n"
1032 					EncryptAES256(sched_l)
1033 					"movaps %%xmm0, %%xmm1 \n"
1034 					"movups %%xmm0, (%[out]) \n"
1035 					"dec %[num] \n"
1036 					"jnz 1b \n"
1037 					:
1038 					: [sched_iv]"r"(m_IVEncryption.GetKeySchedule ()), [sched_l]"r"(m_LayerEncryption.ECB().GetKeySchedule ()),
1039 						[in]"r"(in), [out]"r"(out), [num]"r"(63) // 63 blocks = 1008 bytes
1040 					: "%xmm0", "%xmm1", "cc", "memory"
1041 					);
1042 		}
1043 		else
1044 #endif
1045 		{
1046 			m_IVEncryption.Encrypt ((const ChipherBlock *)in, (ChipherBlock *)out); // iv
1047 			m_LayerEncryption.SetIV (out);
1048 			m_LayerEncryption.Encrypt (in + 16, i2p::tunnel::TUNNEL_DATA_ENCRYPTED_SIZE, out + 16); // data
1049 			m_IVEncryption.Encrypt ((ChipherBlock *)out, (ChipherBlock *)out); // double iv
1050 		}
1051 	}
1052 
Decrypt(const uint8_t * in,uint8_t * out)1053 	void TunnelDecryption::Decrypt (const uint8_t * in, uint8_t * out)
1054 	{
1055 #ifdef __AES__
1056 		if(i2p::cpu::aesni)
1057 		{
1058 			__asm__
1059 				(
1060 					// decrypt IV
1061 					"movups	(%[in]), %%xmm0 \n"
1062 					DecryptAES256(sched_iv)
1063 					"movaps %%xmm0, %%xmm1 \n"
1064 					// double IV encryption
1065 					DecryptAES256(sched_iv)
1066 					"movups %%xmm0, (%[out]) \n"
1067 					// decrypt data, IV is xmm1
1068 					"1: \n"
1069 					"add $16, %[in] \n"
1070 					"add $16, %[out] \n"
1071 					"movups (%[in]), %%xmm0 \n"
1072 					"movaps %%xmm0, %%xmm2 \n"
1073 					DecryptAES256(sched_l)
1074 					"pxor %%xmm1, %%xmm0 \n"
1075 					"movups %%xmm0, (%[out]) \n"
1076 					"movaps %%xmm2, %%xmm1 \n"
1077 					"dec %[num] \n"
1078 					"jnz 1b \n"
1079 					:
1080 					: [sched_iv]"r"(m_IVDecryption.GetKeySchedule ()), [sched_l]"r"(m_LayerDecryption.ECB().GetKeySchedule ()),
1081 						[in]"r"(in), [out]"r"(out), [num]"r"(63) // 63 blocks = 1008 bytes
1082 					: "%xmm0", "%xmm1", "%xmm2", "cc", "memory"
1083 					);
1084 		}
1085 		else
1086 #endif
1087 		{
1088 			m_IVDecryption.Decrypt ((const ChipherBlock *)in, (ChipherBlock *)out); // iv
1089 			m_LayerDecryption.SetIV (out);
1090 			m_LayerDecryption.Decrypt (in + 16, i2p::tunnel::TUNNEL_DATA_ENCRYPTED_SIZE, out + 16); // data
1091 			m_IVDecryption.Decrypt ((ChipherBlock *)out, (ChipherBlock *)out); // double iv
1092 		}
1093 	}
1094 
1095 // AEAD/ChaCha20/Poly1305
1096 
AEADChaCha20Poly1305(const uint8_t * msg,size_t msgLen,const uint8_t * ad,size_t adLen,const uint8_t * key,const uint8_t * nonce,uint8_t * buf,size_t len,bool encrypt)1097 	bool AEADChaCha20Poly1305 (const uint8_t * msg, size_t msgLen, const uint8_t * ad, size_t adLen, const uint8_t * key, const uint8_t * nonce, uint8_t * buf, size_t len, bool encrypt)
1098 	{
1099 		if (len < msgLen) return false;
1100 		if (encrypt && len < msgLen + 16) return false;
1101 		bool ret = true;
1102 #if OPENSSL_AEAD_CHACHA20_POLY1305
1103 		int outlen = 0;
1104 		EVP_CIPHER_CTX *ctx = EVP_CIPHER_CTX_new ();
1105 		if (encrypt)
1106 		{
1107 			EVP_EncryptInit_ex(ctx, EVP_chacha20_poly1305(), 0, 0, 0);
1108 			EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_AEAD_SET_IVLEN, 12, 0);
1109 			EVP_EncryptInit_ex(ctx, NULL, NULL, key, nonce);
1110 			EVP_EncryptUpdate(ctx, NULL, &outlen, ad, adLen);
1111 			EVP_EncryptUpdate(ctx, buf, &outlen, msg, msgLen);
1112 			EVP_EncryptFinal_ex(ctx, buf, &outlen);
1113 			EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_AEAD_GET_TAG, 16, buf + msgLen);
1114 		}
1115 		else
1116 		{
1117 			EVP_DecryptInit_ex(ctx, EVP_chacha20_poly1305(), 0, 0, 0);
1118 			EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_AEAD_SET_IVLEN, 12, 0);
1119 			EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_AEAD_SET_TAG, 16, (uint8_t *)(msg + msgLen));
1120 			EVP_DecryptInit_ex(ctx, NULL, NULL, key, nonce);
1121 			EVP_DecryptUpdate(ctx, NULL, &outlen, ad, adLen);
1122 			EVP_DecryptUpdate(ctx, buf, &outlen, msg, msgLen);
1123 			ret = EVP_DecryptFinal_ex(ctx, buf + outlen, &outlen) > 0;
1124 		}
1125 
1126 		EVP_CIPHER_CTX_free (ctx);
1127 #else
1128 		chacha::Chacha20State state;
1129 		// generate one time poly key
1130 		chacha::Chacha20Init (state, nonce, key, 0);
1131 		uint64_t polyKey[8];
1132 		memset(polyKey, 0, sizeof(polyKey));
1133 		chacha::Chacha20Encrypt (state, (uint8_t *)polyKey, 64);
1134 		// create Poly1305 hash
1135 		Poly1305 polyHash (polyKey);
1136 		if (!ad) adLen = 0;
1137 		uint8_t padding[16]; memset (padding, 0, 16);
1138 		if (ad)
1139 		{
1140 			polyHash.Update (ad, adLen);// additional authenticated data
1141 			auto rem = adLen & 0x0F; // %16
1142 			if (rem)
1143 			{
1144 				// padding1
1145 				rem = 16 - rem;
1146 				polyHash.Update (padding, rem);
1147 			}
1148 		}
1149 		// encrypt/decrypt data and add to hash
1150 		Chacha20SetCounter (state, 1);
1151 		if (buf != msg)
1152 			memcpy (buf, msg, msgLen);
1153 		if (encrypt)
1154 		{
1155 			chacha::Chacha20Encrypt (state, buf, msgLen); // encrypt
1156 			polyHash.Update (buf, msgLen); // after encryption
1157 		}
1158 		else
1159 		{
1160 			polyHash.Update (buf, msgLen); // before decryption
1161 			chacha::Chacha20Encrypt (state, buf, msgLen); // decrypt
1162 		}
1163 
1164 		auto rem = msgLen & 0x0F; // %16
1165 		if (rem)
1166 		{
1167 			// padding2
1168 			rem = 16 - rem;
1169 			polyHash.Update (padding, rem);
1170 		}
1171 		// adLen and msgLen
1172 		htole64buf (padding, adLen);
1173 		htole64buf (padding + 8, msgLen);
1174 		polyHash.Update (padding, 16);
1175 
1176 		if (encrypt)
1177 			// calculate Poly1305 tag and write in after encrypted data
1178 			polyHash.Finish ((uint64_t *)(buf + msgLen));
1179 		else
1180 		{
1181 			uint64_t tag[4];
1182 			// calculate Poly1305 tag
1183 			polyHash.Finish (tag);
1184 			if (memcmp (tag, msg + msgLen, 16)) ret = false; // compare with provided
1185 		}
1186 #endif
1187 		return ret;
1188 	}
1189 
AEADChaCha20Poly1305Encrypt(const std::vector<std::pair<uint8_t *,size_t>> & bufs,const uint8_t * key,const uint8_t * nonce,uint8_t * mac)1190 	void AEADChaCha20Poly1305Encrypt (const std::vector<std::pair<uint8_t *, size_t> >& bufs, const uint8_t * key, const uint8_t * nonce, uint8_t * mac)
1191 	{
1192 		if (bufs.empty ()) return;
1193 #if OPENSSL_AEAD_CHACHA20_POLY1305
1194 		int outlen = 0;
1195 		EVP_CIPHER_CTX *ctx = EVP_CIPHER_CTX_new ();
1196 		EVP_EncryptInit_ex(ctx, EVP_chacha20_poly1305(), 0, 0, 0);
1197 		EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_AEAD_SET_IVLEN, 12, 0);
1198 		EVP_EncryptInit_ex(ctx, NULL, NULL, key, nonce);
1199 		for (const auto& it: bufs)
1200 			EVP_EncryptUpdate(ctx, it.first, &outlen, it.first, it.second);
1201 		EVP_EncryptFinal_ex(ctx, NULL, &outlen);
1202 		EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_AEAD_GET_TAG, 16, mac);
1203 		EVP_CIPHER_CTX_free (ctx);
1204 #else
1205 		chacha::Chacha20State state;
1206 		// generate one time poly key
1207 		chacha::Chacha20Init (state, nonce, key, 0);
1208 		uint64_t polyKey[8];
1209 		memset(polyKey, 0, sizeof(polyKey));
1210 		chacha::Chacha20Encrypt (state, (uint8_t *)polyKey, 64);
1211 		Poly1305 polyHash (polyKey);
1212 		// encrypt buffers
1213 		Chacha20SetCounter (state, 1);
1214 		size_t size = 0;
1215 		for (const auto& it: bufs)
1216 		{
1217 			chacha::Chacha20Encrypt (state, it.first, it.second);
1218 			polyHash.Update (it.first, it.second); // after encryption
1219 			size += it.second;
1220 		}
1221 		// padding
1222 		uint8_t padding[16];
1223 		memset (padding, 0, 16);
1224 		auto rem = size & 0x0F; // %16
1225 		if (rem)
1226 		{
1227 			// padding2
1228 			rem = 16 - rem;
1229 			polyHash.Update (padding, rem);
1230 		}
1231 		// adLen and msgLen
1232 		// adLen is always zero
1233 		htole64buf (padding + 8, size);
1234 		polyHash.Update (padding, 16);
1235 		// MAC
1236 		polyHash.Finish ((uint64_t *)mac);
1237 #endif
1238 	}
1239 
ChaCha20(const uint8_t * msg,size_t msgLen,const uint8_t * key,const uint8_t * nonce,uint8_t * out)1240 	void ChaCha20 (const uint8_t * msg, size_t msgLen, const uint8_t * key, const uint8_t * nonce, uint8_t * out)
1241 	{
1242 #if OPENSSL_AEAD_CHACHA20_POLY1305
1243 		EVP_CIPHER_CTX *ctx = EVP_CIPHER_CTX_new ();
1244 		uint32_t iv[4];
1245 		iv[0] = htole32 (1); memcpy (iv + 1, nonce, 12); // counter | nonce
1246 		EVP_EncryptInit_ex(ctx, EVP_chacha20 (), NULL, key, (const uint8_t *)iv);
1247 		int outlen = 0;
1248 		EVP_EncryptUpdate(ctx, out, &outlen, msg, msgLen);
1249 		EVP_EncryptFinal_ex(ctx, NULL, &outlen);
1250 		EVP_CIPHER_CTX_free (ctx);
1251 #else
1252 		chacha::Chacha20State state;
1253 		chacha::Chacha20Init (state, nonce, key, 1);
1254 		if (out != msg) memcpy (out, msg, msgLen);
1255 		chacha::Chacha20Encrypt (state, out, msgLen);
1256 #endif
1257 	}
1258 
HKDF(const uint8_t * salt,const uint8_t * key,size_t keyLen,const std::string & info,uint8_t * out,size_t outLen)1259 	void HKDF (const uint8_t * salt, const uint8_t * key, size_t keyLen, const std::string& info,
1260 		uint8_t * out, size_t outLen)
1261 	{
1262 #if OPENSSL_HKDF
1263 		EVP_PKEY_CTX * pctx = EVP_PKEY_CTX_new_id (EVP_PKEY_HKDF, nullptr);
1264 		EVP_PKEY_derive_init (pctx);
1265 		EVP_PKEY_CTX_set_hkdf_md (pctx, EVP_sha256());
1266 		if (key && keyLen)
1267 		{
1268 			EVP_PKEY_CTX_set1_hkdf_salt (pctx, salt, 32);
1269 			EVP_PKEY_CTX_set1_hkdf_key (pctx, key, keyLen);
1270 		}
1271 		else
1272 		{
1273 			// zerolen
1274 			EVP_PKEY_CTX_hkdf_mode (pctx, EVP_PKEY_HKDEF_MODE_EXPAND_ONLY);
1275 			uint8_t tempKey[32]; unsigned int len;
1276 			HMAC(EVP_sha256(), salt, 32, nullptr, 0, tempKey, &len);
1277 			EVP_PKEY_CTX_set1_hkdf_key (pctx, tempKey, len);
1278 		}
1279 		if (info.length () > 0)
1280 			EVP_PKEY_CTX_add1_hkdf_info (pctx, (const uint8_t *)info.c_str (), info.length ());
1281 		EVP_PKEY_derive (pctx, out, &outLen);
1282 		EVP_PKEY_CTX_free (pctx);
1283 #else
1284 		uint8_t prk[32]; unsigned int len;
1285 		HMAC(EVP_sha256(), salt, 32, key, keyLen, prk, &len);
1286 		auto l = info.length ();
1287 		memcpy (out, info.c_str (), l); out[l] = 0x01;
1288 		HMAC(EVP_sha256(), prk, 32, out, l + 1, out, &len);
1289 		if (outLen > 32) // 64
1290 		{
1291 			memcpy (out + 32, info.c_str (), l); out[l + 32] = 0x02;
1292 			HMAC(EVP_sha256(), prk, 32, out, l + 33, out + 32, &len);
1293 		}
1294 #endif
1295 	}
1296 
1297 // Noise
1298 
MixHash(const uint8_t * buf,size_t len)1299 	void NoiseSymmetricState::MixHash (const uint8_t * buf, size_t len)
1300 	{
1301 		SHA256_CTX ctx;
1302 		SHA256_Init (&ctx);
1303 		SHA256_Update (&ctx, m_H, 32);
1304 		SHA256_Update (&ctx, buf, len);
1305 		SHA256_Final (m_H, &ctx);
1306 	}
1307 
MixKey(const uint8_t * sharedSecret)1308 	void NoiseSymmetricState::MixKey (const uint8_t * sharedSecret)
1309 	{
1310 		HKDF (m_CK, sharedSecret, 32, "", m_CK);
1311 		// new ck is m_CK[0:31], key is m_CK[32:63]
1312 	}
1313 
InitNoiseState(NoiseSymmetricState & state,const uint8_t * ck,const uint8_t * hh,const uint8_t * pub)1314 	static void InitNoiseState (NoiseSymmetricState& state, const uint8_t * ck,
1315 		const uint8_t * hh, const uint8_t * pub)
1316 	{
1317 		// pub is Bob's public static key, hh = SHA256(h)
1318 		memcpy (state.m_CK, ck, 32);
1319 		SHA256_CTX ctx;
1320 		SHA256_Init (&ctx);
1321 		SHA256_Update (&ctx, hh, 32);
1322 		SHA256_Update (&ctx, pub, 32);
1323 		SHA256_Final (state.m_H, &ctx);  // h = MixHash(pub) = SHA256(hh || pub)
1324 	}
1325 
InitNoiseNState(NoiseSymmetricState & state,const uint8_t * pub)1326 	void InitNoiseNState (NoiseSymmetricState& state, const uint8_t * pub)
1327 	{
1328 		static const char protocolName[] = "Noise_N_25519_ChaChaPoly_SHA256"; // 31 chars
1329 		static const uint8_t hh[32] =
1330 		{
1331 			0x69, 0x4d, 0x52, 0x44, 0x5a, 0x27, 0xd9, 0xad, 0xfa, 0xd2, 0x9c, 0x76, 0x32, 0x39, 0x5d, 0xc1,
1332 			0xe4, 0x35, 0x4c, 0x69, 0xb4, 0xf9, 0x2e, 0xac, 0x8a, 0x1e, 0xe4, 0x6a, 0x9e, 0xd2, 0x15, 0x54
1333 		}; // hh = SHA256(protocol_name || 0)
1334 		InitNoiseState (state, (const uint8_t *)protocolName, hh, pub); // ck = protocol_name || 0
1335 	}
1336 
InitNoiseXKState(NoiseSymmetricState & state,const uint8_t * pub)1337 	void InitNoiseXKState (NoiseSymmetricState& state, const uint8_t * pub)
1338 	{
1339 		static const uint8_t protocolNameHash[] =
1340 		{
1341 			0x72, 0xe8, 0x42, 0xc5, 0x45, 0xe1, 0x80, 0x80, 0xd3, 0x9c, 0x44, 0x93, 0xbb, 0x91, 0xd7, 0xed,
1342 			0xf2, 0x28, 0x98, 0x17, 0x71, 0x21, 0x8c, 0x1f, 0x62, 0x4e, 0x20, 0x6f, 0x28, 0xd3, 0x2f, 0x71
1343 		}; // SHA256 ("Noise_XKaesobfse+hs2+hs3_25519_ChaChaPoly_SHA256")
1344 		static const uint8_t hh[32] =
1345 		{
1346 			0x49, 0xff, 0x48, 0x3f, 0xc4, 0x04, 0xb9, 0xb2, 0x6b, 0x11, 0x94, 0x36, 0x72, 0xff, 0x05, 0xb5,
1347 			0x61, 0x27, 0x03, 0x31, 0xba, 0x89, 0xb8, 0xfc, 0x33, 0x15, 0x93, 0x87, 0x57, 0xdd, 0x3d, 0x1e
1348 		}; // SHA256 (protocolNameHash)
1349 		InitNoiseState (state, protocolNameHash, hh, pub);
1350 	}
1351 
InitNoiseIKState(NoiseSymmetricState & state,const uint8_t * pub)1352 	void InitNoiseIKState (NoiseSymmetricState& state, const uint8_t * pub)
1353 	{
1354 		static const uint8_t protocolNameHash[32] =
1355 		{
1356 			0x4c, 0xaf, 0x11, 0xef, 0x2c, 0x8e, 0x36, 0x56, 0x4c, 0x53, 0xe8, 0x88, 0x85, 0x06, 0x4d, 0xba,
1357 			0xac, 0xbe, 0x00, 0x54, 0xad, 0x17, 0x8f, 0x80, 0x79, 0xa6, 0x46, 0x82, 0x7e, 0x6e, 0xe4, 0x0c
1358 		}; // SHA256("Noise_IKelg2+hs2_25519_ChaChaPoly_SHA256"), 40 bytes
1359 		static const uint8_t hh[32] =
1360 		{
1361 			0x9c, 0xcf, 0x85, 0x2c, 0xc9, 0x3b, 0xb9, 0x50, 0x44, 0x41, 0xe9, 0x50, 0xe0, 0x1d, 0x52, 0x32,
1362 			0x2e, 0x0d, 0x47, 0xad, 0xd1, 0xe9, 0xa5, 0x55, 0xf7, 0x55, 0xb5, 0x69, 0xae, 0x18, 0x3b, 0x5c
1363 		}; // SHA256 (protocolNameHash)
1364 		InitNoiseState (state, protocolNameHash, hh, pub);
1365 	}
1366 
1367 // init and terminate
1368 
1369 /*	std::vector <std::unique_ptr<std::mutex> > m_OpenSSLMutexes;
1370 	static void OpensslLockingCallback(int mode, int type, const char * file, int line)
1371 	{
1372 		if (type > 0 && (size_t)type < m_OpenSSLMutexes.size ())
1373 		{
1374 			if (mode & CRYPTO_LOCK)
1375 				m_OpenSSLMutexes[type]->lock ();
1376 			else
1377 				m_OpenSSLMutexes[type]->unlock ();
1378 		}
1379 	}*/
1380 
InitCrypto(bool precomputation,bool aesni,bool avx,bool force)1381 	void InitCrypto (bool precomputation, bool aesni, bool avx, bool force)
1382 	{
1383 		i2p::cpu::Detect (aesni, avx, force);
1384 #if LEGACY_OPENSSL
1385 		SSL_library_init ();
1386 #endif
1387 /*		auto numLocks = CRYPTO_num_locks();
1388 		for (int i = 0; i < numLocks; i++)
1389 			m_OpenSSLMutexes.emplace_back (new std::mutex);
1390 		CRYPTO_set_locking_callback (OpensslLockingCallback);*/
1391 		if (precomputation)
1392 		{
1393 #if defined(__x86_64__)
1394 			g_ElggTable = new BIGNUM * [ELGAMAL_FULL_EXPONENT_NUM_BYTES][255];
1395 			PrecalculateElggTable (g_ElggTable, ELGAMAL_FULL_EXPONENT_NUM_BYTES);
1396 #else
1397 			g_ElggTable = new BIGNUM * [ELGAMAL_SHORT_EXPONENT_NUM_BYTES][255];
1398 			PrecalculateElggTable (g_ElggTable, ELGAMAL_SHORT_EXPONENT_NUM_BYTES);
1399 #endif
1400 		}
1401 	}
1402 
TerminateCrypto()1403 	void TerminateCrypto ()
1404 	{
1405 		if (g_ElggTable)
1406 		{
1407 			DestroyElggTable (g_ElggTable,
1408 #if defined(__x86_64__)
1409 				ELGAMAL_FULL_EXPONENT_NUM_BYTES
1410 #else
1411 				ELGAMAL_SHORT_EXPONENT_NUM_BYTES
1412 #endif
1413 			);
1414 			delete[] g_ElggTable; g_ElggTable = nullptr;
1415 		}
1416 /*		CRYPTO_set_locking_callback (nullptr);
1417 		m_OpenSSLMutexes.clear ();*/
1418 	}
1419 }
1420 }
1421