/ libi2pd / Crypto.cpp
Crypto.cpp
  1  /*
  2  * Copyright (c) 2013-2025, 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  #include <openssl/kdf.h>
 20  #if (OPENSSL_VERSION_NUMBER >= 0x030000000) // since 3.0.0
 21  #include <openssl/param_build.h>
 22  #include <openssl/core_names.h>
 23  #endif
 24  #include "CPU.h"
 25  #include "Crypto.h"
 26  #include "Ed25519.h"
 27  #include "I2PEndian.h"
 28  #include "Log.h"
 29  
 30  namespace i2p
 31  {
 32  namespace crypto
 33  {
 34  	constexpr uint8_t elgp_[256]=
 35  	{
 36  		0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xC9, 0x0F, 0xDA, 0xA2, 0x21, 0x68, 0xC2, 0x34,
 37  		0xC4, 0xC6, 0x62, 0x8B, 0x80, 0xDC, 0x1C, 0xD1, 0x29, 0x02, 0x4E, 0x08, 0x8A, 0x67, 0xCC, 0x74,
 38  		0x02, 0x0B, 0xBE, 0xA6, 0x3B, 0x13, 0x9B, 0x22, 0x51, 0x4A, 0x08, 0x79, 0x8E, 0x34, 0x04, 0xDD,
 39  		0xEF, 0x95, 0x19, 0xB3, 0xCD, 0x3A, 0x43, 0x1B, 0x30, 0x2B, 0x0A, 0x6D, 0xF2, 0x5F, 0x14, 0x37,
 40  		0x4F, 0xE1, 0x35, 0x6D, 0x6D, 0x51, 0xC2, 0x45, 0xE4, 0x85, 0xB5, 0x76, 0x62, 0x5E, 0x7E, 0xC6,
 41  		0xF4, 0x4C, 0x42, 0xE9, 0xA6, 0x37, 0xED, 0x6B, 0x0B, 0xFF, 0x5C, 0xB6, 0xF4, 0x06, 0xB7, 0xED,
 42  		0xEE, 0x38, 0x6B, 0xFB, 0x5A, 0x89, 0x9F, 0xA5, 0xAE, 0x9F, 0x24, 0x11, 0x7C, 0x4B, 0x1F, 0xE6,
 43  		0x49, 0x28, 0x66, 0x51, 0xEC, 0xE4, 0x5B, 0x3D, 0xC2, 0x00, 0x7C, 0xB8, 0xA1, 0x63, 0xBF, 0x05,
 44  		0x98, 0xDA, 0x48, 0x36, 0x1C, 0x55, 0xD3, 0x9A, 0x69, 0x16, 0x3F, 0xA8, 0xFD, 0x24, 0xCF, 0x5F,
 45  		0x83, 0x65, 0x5D, 0x23, 0xDC, 0xA3, 0xAD, 0x96, 0x1C, 0x62, 0xF3, 0x56, 0x20, 0x85, 0x52, 0xBB,
 46  		0x9E, 0xD5, 0x29, 0x07, 0x70, 0x96, 0x96, 0x6D, 0x67, 0x0C, 0x35, 0x4E, 0x4A, 0xBC, 0x98, 0x04,
 47  		0xF1, 0x74, 0x6C, 0x08, 0xCA, 0x18, 0x21, 0x7C, 0x32, 0x90, 0x5E, 0x46, 0x2E, 0x36, 0xCE, 0x3B,
 48  		0xE3, 0x9E, 0x77, 0x2C, 0x18, 0x0E, 0x86, 0x03, 0x9B, 0x27, 0x83, 0xA2, 0xEC, 0x07, 0xA2, 0x8F,
 49  		0xB5, 0xC5, 0x5D, 0xF0, 0x6F, 0x4C, 0x52, 0xC9, 0xDE, 0x2B, 0xCB, 0xF6, 0x95, 0x58, 0x17, 0x18,
 50  		0x39, 0x95, 0x49, 0x7C, 0xEA, 0x95, 0x6A, 0xE5, 0x15, 0xD2, 0x26, 0x18, 0x98, 0xFA, 0x05, 0x10,
 51  		0x15, 0x72, 0x8E, 0x5A, 0x8A, 0xAC, 0xAA, 0x68, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF
 52  	};
 53  
 54  	constexpr int elgg_ = 2;
 55  
 56  	constexpr uint8_t dsap_[128]=
 57  	{
 58  		0x9c, 0x05, 0xb2, 0xaa, 0x96, 0x0d, 0x9b, 0x97, 0xb8, 0x93, 0x19, 0x63, 0xc9, 0xcc, 0x9e, 0x8c,
 59  		0x30, 0x26, 0xe9, 0xb8, 0xed, 0x92, 0xfa, 0xd0, 0xa6, 0x9c, 0xc8, 0x86, 0xd5, 0xbf, 0x80, 0x15,
 60  		0xfc, 0xad, 0xae, 0x31, 0xa0, 0xad, 0x18, 0xfa, 0xb3, 0xf0, 0x1b, 0x00, 0xa3, 0x58, 0xde, 0x23,
 61  		0x76, 0x55, 0xc4, 0x96, 0x4a, 0xfa, 0xa2, 0xb3, 0x37, 0xe9, 0x6a, 0xd3, 0x16, 0xb9, 0xfb, 0x1c,
 62  		0xc5, 0x64, 0xb5, 0xae, 0xc5, 0xb6, 0x9a, 0x9f, 0xf6, 0xc3, 0xe4, 0x54, 0x87, 0x07, 0xfe, 0xf8,
 63  		0x50, 0x3d, 0x91, 0xdd, 0x86, 0x02, 0xe8, 0x67, 0xe6, 0xd3, 0x5d, 0x22, 0x35, 0xc1, 0x86, 0x9c,
 64  		0xe2, 0x47, 0x9c, 0x3b, 0x9d, 0x54, 0x01, 0xde, 0x04, 0xe0, 0x72, 0x7f, 0xb3, 0x3d, 0x65, 0x11,
 65  		0x28, 0x5d, 0x4c, 0xf2, 0x95, 0x38, 0xd9, 0xe3, 0xb6, 0x05, 0x1f, 0x5b, 0x22, 0xcc, 0x1c, 0x93
 66  	};
 67  
 68  	constexpr uint8_t dsaq_[20]=
 69  	{
 70  		0xa5, 0xdf, 0xc2, 0x8f, 0xef, 0x4c, 0xa1, 0xe2, 0x86, 0x74, 0x4c, 0xd8, 0xee, 0xd9, 0xd2, 0x9d,
 71  		0x68, 0x40, 0x46, 0xb7
 72  	};
 73  
 74  	constexpr uint8_t dsag_[128]=
 75  	{
 76  		0x0c, 0x1f, 0x4d, 0x27, 0xd4, 0x00, 0x93, 0xb4, 0x29, 0xe9, 0x62, 0xd7, 0x22, 0x38, 0x24, 0xe0,
 77  		0xbb, 0xc4, 0x7e, 0x7c, 0x83, 0x2a, 0x39, 0x23, 0x6f, 0xc6, 0x83, 0xaf, 0x84, 0x88, 0x95, 0x81,
 78  		0x07, 0x5f, 0xf9, 0x08, 0x2e, 0xd3, 0x23, 0x53, 0xd4, 0x37, 0x4d, 0x73, 0x01, 0xcd, 0xa1, 0xd2,
 79  		0x3c, 0x43, 0x1f, 0x46, 0x98, 0x59, 0x9d, 0xda, 0x02, 0x45, 0x18, 0x24, 0xff, 0x36, 0x97, 0x52,
 80  		0x59, 0x36, 0x47, 0xcc, 0x3d, 0xdc, 0x19, 0x7d, 0xe9, 0x85, 0xe4, 0x3d, 0x13, 0x6c, 0xdc, 0xfc,
 81  		0x6b, 0xd5, 0x40, 0x9c, 0xd2, 0xf4, 0x50, 0x82, 0x11, 0x42, 0xa5, 0xe6, 0xf8, 0xeb, 0x1c, 0x3a,
 82  		0xb5, 0xd0, 0x48, 0x4b, 0x81, 0x29, 0xfc, 0xf1, 0x7b, 0xce, 0x4f, 0x7f, 0x33, 0x32, 0x1c, 0x3c,
 83  		0xb3, 0xdb, 0xb1, 0x4a, 0x90, 0x5e, 0x7b, 0x2b, 0x3e, 0x93, 0xbe, 0x47, 0x08, 0xcb, 0xcc, 0x82
 84  	};
 85  
 86  	constexpr int rsae_ = 65537;
 87  
 88  	struct CryptoConstants
 89  	{
 90  		// DH/ElGamal
 91  		BIGNUM * elgp;
 92  		BIGNUM * elgg;
 93  
 94  		// DSA
 95  		BIGNUM * dsap;
 96  		BIGNUM * dsaq;
 97  		BIGNUM * dsag;
 98  
 99  		// RSA
100  		BIGNUM * rsae;
101  
102  		CryptoConstants (const uint8_t * elgp_, int elgg_, const uint8_t * dsap_,
103  			const uint8_t * dsaq_, const uint8_t * dsag_, int rsae_)
104  		{
105  			elgp = BN_new ();
106  			BN_bin2bn (elgp_, 256, elgp);
107  			elgg = BN_new ();
108  			BN_set_word (elgg, elgg_);
109  			dsap = BN_new ();
110  			BN_bin2bn (dsap_, 128, dsap);
111  			dsaq = BN_new ();
112  			BN_bin2bn (dsaq_, 20, dsaq);
113  			dsag = BN_new ();
114  			BN_bin2bn (dsag_, 128, dsag);
115  			rsae = BN_new ();
116  			BN_set_word (rsae, rsae_);
117  		}
118  
119  		~CryptoConstants ()
120  		{
121  			BN_free (elgp); BN_free (elgg); BN_free (dsap); BN_free (dsaq); BN_free (dsag); BN_free (rsae);
122  		}
123  	};
124  
125  	static const CryptoConstants& GetCryptoConstants ()
126  	{
127  		static CryptoConstants cryptoConstants (elgp_, elgg_, dsap_, dsaq_, dsag_, rsae_);
128  		return cryptoConstants;
129  	}
130  
131  	bool bn2buf (const BIGNUM * bn, uint8_t * buf, size_t len)
132  	{
133  		int offset = len - BN_num_bytes (bn);
134  		if (offset < 0) return false;
135  		BN_bn2bin (bn, buf + offset);
136  		memset (buf, 0, offset);
137  		return true;
138  	}
139  
140  // RSA
141  	#define rsae GetCryptoConstants ().rsae
142  	const BIGNUM * GetRSAE ()
143  	{
144  		return rsae;
145  	}
146  
147  // DSA
148  	#define dsap GetCryptoConstants ().dsap
149  	#define dsaq GetCryptoConstants ().dsaq
150  	#define dsag GetCryptoConstants ().dsag
151  #if (OPENSSL_VERSION_NUMBER >= 0x030000000) // since 3.0.0
152  	EVP_PKEY * CreateDSA (BIGNUM * pubKey, BIGNUM * privKey)
153  	{
154  		EVP_PKEY * pkey = nullptr;
155  		int selection = EVP_PKEY_KEY_PARAMETERS;
156  		auto bld = OSSL_PARAM_BLD_new();
157  		OSSL_PARAM_BLD_push_BN(bld, OSSL_PKEY_PARAM_FFC_P, dsap);
158  		OSSL_PARAM_BLD_push_BN(bld, OSSL_PKEY_PARAM_FFC_Q, dsaq);
159  		OSSL_PARAM_BLD_push_BN(bld, OSSL_PKEY_PARAM_FFC_G, dsag);
160  		if (pubKey)
161  		{	
162  			OSSL_PARAM_BLD_push_BN (bld, OSSL_PKEY_PARAM_PUB_KEY, pubKey);
163  			selection = EVP_PKEY_PUBLIC_KEY;
164  		}	
165  		if (privKey)
166  		{	
167  			OSSL_PARAM_BLD_push_BN (bld, OSSL_PKEY_PARAM_PRIV_KEY, privKey);
168  			selection = EVP_PKEY_KEYPAIR;
169  		}	
170  		auto params = OSSL_PARAM_BLD_to_param(bld);
171  		
172  		EVP_PKEY_CTX *ctx = EVP_PKEY_CTX_new_from_name (NULL, "DSA", NULL);
173  		EVP_PKEY_fromdata_init(ctx);
174          EVP_PKEY_fromdata(ctx, &pkey, selection, params);
175  		
176  		EVP_PKEY_CTX_free(ctx);
177  		OSSL_PARAM_free(params);
178  		OSSL_PARAM_BLD_free(bld);
179  		return pkey;
180  	}	
181  #else	
182  	DSA * CreateDSA ()
183  	{
184  		DSA * dsa = DSA_new ();
185  		DSA_set0_pqg (dsa, BN_dup (dsap), BN_dup (dsaq), BN_dup (dsag));
186  		DSA_set0_key (dsa, NULL, NULL);
187  		return dsa;
188  	}
189  #endif
190  	
191  // DH/ElGamal
192  
193  #if !IS_X86_64
194  	const int ELGAMAL_SHORT_EXPONENT_NUM_BITS = 226;
195  	const int ELGAMAL_SHORT_EXPONENT_NUM_BYTES = ELGAMAL_SHORT_EXPONENT_NUM_BITS/8+1;
196  #endif
197  	const int ELGAMAL_FULL_EXPONENT_NUM_BITS = 2048;
198  	const int ELGAMAL_FULL_EXPONENT_NUM_BYTES = ELGAMAL_FULL_EXPONENT_NUM_BITS/8;
199  
200  	#define elgp GetCryptoConstants ().elgp
201  	#define elgg GetCryptoConstants ().elgg
202  
203  	static BN_MONT_CTX * g_MontCtx = nullptr;
204  	static void PrecalculateElggTable (BIGNUM * table[][255], int len) // table is len's array of array of 255 bignums
205  	{
206  		if (len <= 0) return;
207  		BN_CTX * ctx = BN_CTX_new ();
208  		g_MontCtx = BN_MONT_CTX_new ();
209  		BN_MONT_CTX_set (g_MontCtx, elgp, ctx);
210  		auto montCtx = BN_MONT_CTX_new ();
211  		BN_MONT_CTX_copy (montCtx, g_MontCtx);
212  		for (int i = 0; i < len; i++)
213  		{
214  			table[i][0] = BN_new ();
215  			if (!i)
216  				BN_to_montgomery (table[0][0], elgg, montCtx, ctx);
217  			else
218  				BN_mod_mul_montgomery (table[i][0], table[i-1][254], table[i-1][0], montCtx, ctx);
219  			for (int j = 1; j < 255; j++)
220  			{
221  				table[i][j] = BN_new ();
222  				BN_mod_mul_montgomery (table[i][j], table[i][j-1], table[i][0], montCtx, ctx);
223  			}
224  		}
225  		BN_MONT_CTX_free (montCtx);
226  		BN_CTX_free (ctx);
227  	}
228  
229  	static void DestroyElggTable (BIGNUM * table[][255], int len)
230  	{
231  		for (int i = 0; i < len; i++)
232  			for (int j = 0; j < 255; j++)
233  			{
234  				BN_free (table[i][j]);
235  				table[i][j] = nullptr;
236  			}
237  		BN_MONT_CTX_free (g_MontCtx);
238  	}
239  
240  	static BIGNUM * ElggPow (const uint8_t * exp, int len, BIGNUM * table[][255], BN_CTX * ctx)
241  	// exp is in Big Endian
242  	{
243  		if (len <= 0) return nullptr;
244  		auto montCtx = BN_MONT_CTX_new ();
245  		BN_MONT_CTX_copy (montCtx, g_MontCtx);
246  		BIGNUM * res = nullptr;
247  		for (int i = 0; i < len; i++)
248  		{
249  			if (res)
250  			{
251  				if (exp[i])
252  					BN_mod_mul_montgomery (res, res, table[len-1-i][exp[i]-1], montCtx, ctx);
253  			}
254  			else if (exp[i])
255  				res = BN_dup (table[len-i-1][exp[i]-1]);
256  		}
257  		if (res)
258  			BN_from_montgomery (res, res, montCtx, ctx);
259  		BN_MONT_CTX_free (montCtx);
260  		return res;
261  	}
262  
263  	static BIGNUM * ElggPow (const BIGNUM * exp, BIGNUM * table[][255], BN_CTX * ctx)
264  	{
265  		auto len = BN_num_bytes (exp);
266  		uint8_t * buf = new uint8_t[len];
267  		BN_bn2bin (exp, buf);
268  		auto ret = ElggPow (buf, len, table, ctx);
269  		delete[] buf;
270  		return ret;
271  	}
272  
273  	static BIGNUM * (* g_ElggTable)[255] = nullptr;
274  
275  // x25519
276  	X25519Keys::X25519Keys ()
277  	{
278  		m_Ctx = EVP_PKEY_CTX_new_id (NID_X25519, NULL);
279  		m_Pkey = nullptr;
280  	}
281  
282  	X25519Keys::X25519Keys (const uint8_t * priv, const uint8_t * pub)
283  	{
284  		m_Pkey = EVP_PKEY_new_raw_private_key (EVP_PKEY_X25519, NULL, priv, 32);
285  		m_Ctx = EVP_PKEY_CTX_new (m_Pkey, NULL);
286  		if (pub)
287  			memcpy (m_PublicKey, pub, 32); // TODO: verify against m_Pkey
288  		else
289  		{
290  			size_t len = 32;
291  			EVP_PKEY_get_raw_public_key (m_Pkey, m_PublicKey, &len);
292  		}
293  	}
294  
295  	X25519Keys::~X25519Keys ()
296  	{
297  		EVP_PKEY_CTX_free (m_Ctx);
298  		if (m_Pkey) EVP_PKEY_free (m_Pkey);
299  	}
300  
301  	void X25519Keys::GenerateKeys ()
302  	{
303  		if (m_Pkey)
304  		{
305  			EVP_PKEY_free (m_Pkey);
306  			m_Pkey = nullptr;
307  		}
308  		EVP_PKEY_keygen_init (m_Ctx);
309  		EVP_PKEY_keygen (m_Ctx, &m_Pkey);
310  		EVP_PKEY_CTX_free (m_Ctx);
311  		m_Ctx = EVP_PKEY_CTX_new (m_Pkey, NULL); // TODO: do we really need to re-create m_Ctx?
312  		size_t len = 32;
313  		EVP_PKEY_get_raw_public_key (m_Pkey, m_PublicKey, &len);
314  	}
315  
316  	bool X25519Keys::Agree (const uint8_t * pub, uint8_t * shared)
317  	{
318  		if (!pub || (pub[31] & 0x80)) return false; // not x25519 key
319  		EVP_PKEY_derive_init (m_Ctx);
320  		auto pkey = EVP_PKEY_new_raw_public_key (EVP_PKEY_X25519, NULL, pub, 32);
321  		if (!pkey) return false;
322  		EVP_PKEY_derive_set_peer (m_Ctx, pkey);
323  		size_t len = 32;
324  		EVP_PKEY_derive (m_Ctx, shared, &len);
325  		EVP_PKEY_free (pkey);
326  		return true;
327  	}
328  
329  	void X25519Keys::GetPrivateKey (uint8_t * priv) const
330  	{
331  		size_t len = 32;
332  		EVP_PKEY_get_raw_private_key (m_Pkey, priv, &len);
333  	}
334  
335  	void X25519Keys::SetPrivateKey (const uint8_t * priv, bool calculatePublic)
336  	{
337  		if (m_Ctx) EVP_PKEY_CTX_free (m_Ctx);
338  		if (m_Pkey) EVP_PKEY_free (m_Pkey);
339  		m_Pkey = EVP_PKEY_new_raw_private_key (EVP_PKEY_X25519, NULL, priv, 32);
340  		m_Ctx = EVP_PKEY_CTX_new (m_Pkey, NULL);
341  		if (calculatePublic)
342  		{
343  			size_t len = 32;
344  			EVP_PKEY_get_raw_public_key (m_Pkey, m_PublicKey, &len);
345  		}
346  	}
347  
348  // ElGamal
349  	void ElGamalEncrypt (const uint8_t * key, const uint8_t * data, uint8_t * encrypted)
350  	{
351  		BN_CTX * ctx = BN_CTX_new ();
352  		BN_CTX_start (ctx);
353  		// everything, but a, because a might come from table
354  		BIGNUM * k = BN_CTX_get (ctx);
355  		BIGNUM * y = BN_CTX_get (ctx);
356  		BIGNUM * b1 = BN_CTX_get (ctx);
357  		BIGNUM * b = BN_CTX_get (ctx);
358  		// select random k
359  #if IS_X86_64
360  		BN_rand (k, ELGAMAL_FULL_EXPONENT_NUM_BITS, -1, 1); // full exponent for x64
361  #else
362  		BN_rand (k, ELGAMAL_SHORT_EXPONENT_NUM_BITS, -1, 1); // short exponent of 226 bits
363  #endif
364  		// calculate a
365  		BIGNUM * a;
366  		if (g_ElggTable)
367  			a = ElggPow (k, g_ElggTable, ctx);
368  		else
369  		{
370  			a = BN_new ();
371  			BN_mod_exp (a, elgg, k, elgp, ctx);
372  		}
373  
374  		// restore y from key
375  		BN_bin2bn (key, 256, y);
376  		// calculate b1
377  		BN_mod_exp (b1, y, k, elgp, ctx);
378  		// create m
379  		uint8_t m[255];
380  		m[0] = 0xFF;
381  		memcpy (m+33, data, 222);
382  		SHA256 (m+33, 222, m+1);
383  		// calculate b = b1*m mod p
384  		BN_bin2bn (m, 255, b);
385  		BN_mod_mul (b, b1, b, elgp, ctx);
386  		// copy a and b
387  		encrypted[0] = 0;
388  		bn2buf (a, encrypted + 1, 256);
389  		encrypted[257] = 0;
390  		bn2buf (b, encrypted + 258, 256);
391  
392  		BN_free (a);
393  		BN_CTX_end (ctx);
394  		BN_CTX_free (ctx);
395  	}
396  
397  	bool ElGamalDecrypt (const uint8_t * key, const uint8_t * encrypted, uint8_t * data)
398  	{
399  		BN_CTX * ctx = BN_CTX_new ();
400  		BN_CTX_start (ctx);
401  		BIGNUM * x = BN_CTX_get (ctx), * a = BN_CTX_get (ctx), * b = BN_CTX_get (ctx);
402  		BN_bin2bn (key, 256, x);
403  		BN_sub (x, elgp, x); BN_sub_word (x, 1); // x = elgp - x- 1
404  		BN_bin2bn (encrypted + 1, 256, a);
405  		BN_bin2bn (encrypted + 258, 256, b);
406  		// m = b*(a^x mod p) mod p
407  		BN_mod_exp (x, a, x, elgp, ctx);
408  		BN_mod_mul (b, b, x, elgp, ctx);
409  		uint8_t m[255];
410  		bn2buf (b, m, 255);
411  		BN_CTX_end (ctx);
412  		BN_CTX_free (ctx);
413  		uint8_t hash[32];
414  		SHA256 (m + 33, 222, hash);
415  		if (memcmp (m + 1, hash, 32))
416  		{
417  			LogPrint (eLogError, "ElGamal decrypt hash doesn't match");
418  			return false;
419  		}
420  		memcpy (data, m + 33, 222);
421  		return true;
422  	}
423  
424  	void GenerateElGamalKeyPair (uint8_t * priv, uint8_t * pub)
425  	{
426  #if IS_X86 || defined(_MSC_VER)
427  		RAND_bytes (priv, 256);
428  #else
429  		// lower 226 bits (28 bytes and 2 bits) only. short exponent
430  		auto numBytes = (ELGAMAL_SHORT_EXPONENT_NUM_BITS)/8 + 1; // 29
431  		auto numZeroBytes = 256 - numBytes;
432  		RAND_bytes (priv + numZeroBytes, numBytes);
433  		memset (priv, 0, numZeroBytes);
434  		priv[numZeroBytes] &= 0x03;
435  #endif
436  		BN_CTX * ctx = BN_CTX_new ();
437  		BIGNUM * p = BN_new ();
438  		BN_bin2bn (priv, 256, p);
439  		BN_mod_exp (p, elgg, p, elgp, ctx);
440  		bn2buf (p, pub, 256);
441  		BN_free (p);
442  		BN_CTX_free (ctx);
443  	}
444  
445  // ECIES
446  	void ECIESEncrypt (const EC_GROUP * curve, const EC_POINT * key, const uint8_t * data, uint8_t * encrypted)
447  	{
448  		BN_CTX * ctx = BN_CTX_new ();
449  		BN_CTX_start (ctx);
450  		BIGNUM * q = BN_CTX_get (ctx);
451  		EC_GROUP_get_order(curve, q, ctx);
452  		int len = BN_num_bytes (q);
453  		BIGNUM * k = BN_CTX_get (ctx);
454  		BN_rand_range (k, q); // 0 < k < q
455  		// point for shared secret
456  		auto p = EC_POINT_new (curve);
457  		EC_POINT_mul (curve, p, k, nullptr, nullptr, ctx);
458  		BIGNUM * x = BN_CTX_get (ctx), * y = BN_CTX_get (ctx);
459  		EC_POINT_get_affine_coordinates (curve, p, x, y, nullptr);
460  		encrypted[0] = 0;
461  		bn2buf (x, encrypted + 1, len);
462  		bn2buf (y, encrypted + 1 + len, len);
463  		RAND_bytes (encrypted + 1 + 2*len, 256 - 2*len);
464  		// encryption key and iv
465  		EC_POINT_mul (curve, p, nullptr, key, k, ctx);
466  		EC_POINT_get_affine_coordinates (curve, p, x, y, nullptr);
467  		uint8_t keyBuf[64], iv[64], shared[32];
468  		bn2buf (x, keyBuf, len);
469  		bn2buf (y, iv, len);
470  		SHA256 (keyBuf, len, shared);
471  		// create buffer
472  		uint8_t m[256];
473  		m[0] = 0xFF; m[255] = 0xFF;
474  		memcpy (m+33, data, 222);
475  		SHA256 (m+33, 222, m+1);
476  		// encrypt
477  		CBCEncryption encryption;
478  		encryption.SetKey (shared);
479  		encrypted[257] = 0;
480  		encryption.Encrypt (m, 256, iv, encrypted + 258);
481  		EC_POINT_free (p);
482  		BN_CTX_end (ctx);
483  		BN_CTX_free (ctx);
484  	}
485  
486  	bool ECIESDecrypt (const EC_GROUP * curve, const BIGNUM * key, const uint8_t * encrypted, uint8_t * data)
487  	{
488  		bool ret = true;
489  		BN_CTX * ctx = BN_CTX_new ();
490  		BN_CTX_start (ctx);
491  		BIGNUM * q = BN_CTX_get (ctx);
492  		EC_GROUP_get_order(curve, q, ctx);
493  		int len = BN_num_bytes (q);
494  		// point for shared secret
495  		BIGNUM * x = BN_CTX_get (ctx), * y = BN_CTX_get (ctx);
496  		BN_bin2bn (encrypted + 1, len, x);
497  		BN_bin2bn (encrypted + 1 + len, len, y);
498  		auto p = EC_POINT_new (curve);
499  		if (EC_POINT_set_affine_coordinates (curve, p, x, y, nullptr))
500  		{
501  			auto s = EC_POINT_new (curve);
502  			EC_POINT_mul (curve, s, nullptr, p, key, ctx);
503  			EC_POINT_get_affine_coordinates (curve, s, x, y, nullptr);
504  			EC_POINT_free (s);
505  			uint8_t keyBuf[64], iv[64], shared[32];
506  			bn2buf (x, keyBuf, len);
507  			bn2buf (y, iv, len);
508  			SHA256 (keyBuf, len, shared);
509  			// decrypt
510  			uint8_t m[256];
511  			CBCDecryption decryption;
512  			decryption.SetKey (shared);
513  			decryption.Decrypt (encrypted + 258, 256, iv, m);
514  			// verify and copy
515  			uint8_t hash[32];
516  			SHA256 (m + 33, 222, hash);
517  			if (!memcmp (m + 1, hash, 32))
518  				memcpy (data, m + 33, 222);
519  			else
520  			{
521  				LogPrint (eLogError, "ECIES decrypt hash doesn't match");
522  				ret = false;
523  			}
524  		}
525  		else
526  		{
527  			LogPrint (eLogError, "ECIES decrypt point is invalid");
528  			ret = false;
529  		}
530  
531  		EC_POINT_free (p);
532  		BN_CTX_end (ctx);
533  		BN_CTX_free (ctx);
534  		return ret;
535  	}
536  
537  	void GenerateECIESKeyPair (const EC_GROUP * curve, BIGNUM *& priv, EC_POINT *& pub)
538  	{
539  		BN_CTX * ctx = BN_CTX_new ();
540  		BIGNUM * q = BN_new ();
541  		EC_GROUP_get_order(curve, q, ctx);
542  		priv = BN_new ();
543  		BN_rand_range (priv, q);
544  		pub = EC_POINT_new (curve);
545  		EC_POINT_mul (curve, pub, priv, nullptr, nullptr, ctx);
546  		BN_free (q);
547  		BN_CTX_free (ctx);
548  	}
549  
550  // AES
551  	ECBEncryption::ECBEncryption ()
552  	{
553  		m_Ctx = EVP_CIPHER_CTX_new ();
554  	}
555  	
556  	ECBEncryption::~ECBEncryption ()
557  	{
558  		if (m_Ctx)
559  			EVP_CIPHER_CTX_free (m_Ctx);
560  	}	
561  	
562  	void ECBEncryption::Encrypt (const uint8_t * in, uint8_t * out)
563  	{
564  		EVP_EncryptInit_ex (m_Ctx, EVP_aes_256_ecb(), NULL, m_Key, NULL);
565  		EVP_CIPHER_CTX_set_padding (m_Ctx, 0);
566  		int len;
567  		EVP_EncryptUpdate (m_Ctx, out, &len, in, 16);
568  		EVP_EncryptFinal_ex (m_Ctx, out + len, &len);
569  	}
570  
571  	ECBDecryption::ECBDecryption ()
572  	{
573  		m_Ctx = EVP_CIPHER_CTX_new ();
574  	}
575  	
576  	ECBDecryption::~ECBDecryption ()
577  	{
578  		if (m_Ctx)
579  			EVP_CIPHER_CTX_free (m_Ctx);
580  	}	
581  	
582  	void ECBDecryption::Decrypt (const uint8_t * in, uint8_t * out)
583  	{
584  		EVP_DecryptInit_ex (m_Ctx, EVP_aes_256_ecb(), NULL, m_Key, NULL);
585  		EVP_CIPHER_CTX_set_padding (m_Ctx, 0);
586  		int len;
587  		EVP_DecryptUpdate (m_Ctx, out, &len, in, 16);
588  		EVP_DecryptFinal_ex (m_Ctx, out + len, &len);
589  	}
590  
591  
592  	CBCEncryption::CBCEncryption () 
593  	{ 
594  		m_Ctx = EVP_CIPHER_CTX_new ();
595  	}
596  	
597  	CBCEncryption::~CBCEncryption ()
598  	{
599  		if (m_Ctx)
600  			EVP_CIPHER_CTX_free (m_Ctx);
601  	}	
602  	
603  	void CBCEncryption::Encrypt (const uint8_t * in, size_t len, const uint8_t * iv, uint8_t * out)
604  	{
605  		// len/16
606  		EVP_EncryptInit_ex (m_Ctx, EVP_aes_256_cbc(), NULL, m_Key, iv);
607  		EVP_CIPHER_CTX_set_padding (m_Ctx, 0);
608  		int l;
609  		EVP_EncryptUpdate (m_Ctx, out, &l, in, len);
610  		EVP_EncryptFinal_ex (m_Ctx, out + l, &l);
611  	}
612  
613  	CBCDecryption::CBCDecryption () 
614  	{ 
615  		m_Ctx = EVP_CIPHER_CTX_new ();
616  	}
617  	
618  	CBCDecryption::~CBCDecryption ()
619  	{
620  		if (m_Ctx)
621  			EVP_CIPHER_CTX_free (m_Ctx);
622  	}	
623  	
624  	void CBCDecryption::Decrypt (const uint8_t * in, size_t len, const uint8_t * iv, uint8_t * out)
625  	{
626  		// len/16
627  		EVP_DecryptInit_ex (m_Ctx, EVP_aes_256_cbc(), NULL, m_Key, iv);
628  		EVP_CIPHER_CTX_set_padding (m_Ctx, 0);
629  		int l;
630  		EVP_DecryptUpdate (m_Ctx, out, &l, in, len);
631  		EVP_DecryptFinal_ex (m_Ctx, out + l, &l);
632  	}
633  
634  	void TunnelEncryption::Encrypt (const uint8_t * in, uint8_t * out)
635  	{
636  		uint8_t iv[16];
637  		m_IVEncryption.Encrypt (in, iv); // iv
638  		m_LayerEncryption.Encrypt (in + 16, i2p::tunnel::TUNNEL_DATA_ENCRYPTED_SIZE, iv, out + 16); // data
639  		m_IVEncryption.Encrypt (iv, out); // double iv
640  	}
641  
642  	void TunnelDecryption::Decrypt (const uint8_t * in, uint8_t * out)
643  	{
644  		uint8_t iv[16];
645  		m_IVDecryption.Decrypt (in, iv); // iv
646  		m_LayerDecryption.Decrypt (in + 16, i2p::tunnel::TUNNEL_DATA_ENCRYPTED_SIZE, iv, out + 16); // data
647  		m_IVDecryption.Decrypt (iv, out); // double iv
648  	}
649  
650  // AEAD/ChaCha20/Poly1305
651  
652  	static bool AEADChaCha20Poly1305 (EVP_CIPHER_CTX * ctx, const uint8_t * msg, size_t msgLen, 
653  		const uint8_t * ad, size_t adLen, const uint8_t * key, const uint8_t * nonce, uint8_t * buf, size_t len, bool encrypt)
654  	{
655  		if (!ctx || len < msgLen) return false;
656  		if (encrypt && len < msgLen + 16) return false;
657  		bool ret = true;
658  		int outlen = 0;
659  		if (encrypt)
660  		{
661  			EVP_EncryptInit_ex(ctx, EVP_chacha20_poly1305(), 0, 0, 0);
662  			EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_AEAD_SET_IVLEN, 12, 0);
663  			EVP_EncryptInit_ex(ctx, NULL, NULL, key, nonce);
664  			EVP_EncryptUpdate(ctx, NULL, &outlen, ad, adLen);
665  			EVP_EncryptUpdate(ctx, buf, &outlen, msg, msgLen);
666  			EVP_EncryptFinal_ex(ctx, buf + outlen, &outlen);
667  			EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_AEAD_GET_TAG, 16, buf + msgLen);
668  		}
669  		else
670  		{
671  #if defined(LIBRESSL_VERSION_NUMBER) && LIBRESSL_VERSION_NUMBER < 0x4000000fL
672  			std::vector<uint8_t> m(msgLen + 16);
673  			if (msg == buf)
674  			{	
675  				// we have to use different buffers otherwise verification fails
676  				memcpy (m.data (), msg, msgLen + 16);
677  				msg = m.data ();
678  			}	
679  #endif			
680  			EVP_DecryptInit_ex(ctx, EVP_chacha20_poly1305(), 0, 0, 0);
681  			EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_AEAD_SET_IVLEN, 12, 0);
682  			EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_AEAD_SET_TAG, 16, (uint8_t *)(msg + msgLen));
683  			EVP_DecryptInit_ex(ctx, NULL, NULL, key, nonce);
684  			EVP_DecryptUpdate(ctx, NULL, &outlen, ad, adLen);
685  			EVP_DecryptUpdate(ctx, buf, &outlen, msg, msgLen);
686  			ret = EVP_DecryptFinal_ex(ctx, buf + outlen, &outlen) > 0;
687  		}
688  		return ret;
689  	}
690  
691  	bool AEADChaCha20Poly1305 (const uint8_t * msg, size_t msgLen, const uint8_t * ad, size_t adLen, 
692  		const uint8_t * key, const uint8_t * nonce, uint8_t * buf, size_t len, bool encrypt)
693  	{
694  		EVP_CIPHER_CTX * ctx = EVP_CIPHER_CTX_new ();
695  		auto ret = AEADChaCha20Poly1305 (ctx, msg, msgLen, ad, adLen, key, nonce, buf, len, encrypt);
696  		EVP_CIPHER_CTX_free (ctx);
697  		return ret;
698  	}
699  
700  	AEADChaCha20Poly1305Encryptor::AEADChaCha20Poly1305Encryptor ()
701  	{
702  		m_Ctx = EVP_CIPHER_CTX_new ();
703  	}
704  	
705  	AEADChaCha20Poly1305Encryptor::~AEADChaCha20Poly1305Encryptor ()
706  	{
707  		if (m_Ctx)
708  			EVP_CIPHER_CTX_free (m_Ctx);
709  	}	
710  
711  	bool AEADChaCha20Poly1305Encryptor::Encrypt (const uint8_t * msg, size_t msgLen, const uint8_t * ad, size_t adLen,
712  		const uint8_t * key, const uint8_t * nonce, uint8_t * buf, size_t len)
713  	{
714  		return AEADChaCha20Poly1305 (m_Ctx, msg, msgLen, ad, adLen, key, nonce, buf, len, true);
715  	}	
716  
717  	void AEADChaCha20Poly1305Encryptor::Encrypt (const std::vector<std::pair<uint8_t *, size_t> >& bufs, 
718  		const uint8_t * key, const uint8_t * nonce, uint8_t * mac)
719  	{
720  		if (bufs.empty ()) return;
721  		int outlen = 0;
722  		EVP_EncryptInit_ex(m_Ctx, EVP_chacha20_poly1305(), 0, 0, 0);
723  		EVP_CIPHER_CTX_ctrl(m_Ctx, EVP_CTRL_AEAD_SET_IVLEN, 12, 0);
724  		EVP_EncryptInit_ex(m_Ctx, NULL, NULL, key, nonce);
725  		for (const auto& it: bufs)
726  			EVP_EncryptUpdate(m_Ctx, it.first, &outlen, it.first, it.second);
727  		EVP_EncryptFinal_ex(m_Ctx, NULL, &outlen);
728  		EVP_CIPHER_CTX_ctrl(m_Ctx, EVP_CTRL_AEAD_GET_TAG, 16, mac);
729  	}	
730  	
731  	AEADChaCha20Poly1305Decryptor::AEADChaCha20Poly1305Decryptor ()
732  	{
733  		m_Ctx = EVP_CIPHER_CTX_new ();
734  	}
735  	
736  	AEADChaCha20Poly1305Decryptor::~AEADChaCha20Poly1305Decryptor ()
737  	{
738  		if (m_Ctx)
739  			EVP_CIPHER_CTX_free (m_Ctx);
740  	}	
741  
742  	bool AEADChaCha20Poly1305Decryptor::Decrypt (const uint8_t * msg, size_t msgLen, const uint8_t * ad, size_t adLen,
743  		const uint8_t * key, const uint8_t * nonce, uint8_t * buf, size_t len)
744  	{
745  		return AEADChaCha20Poly1305 (m_Ctx, msg, msgLen, ad, adLen, key, nonce, buf, len, false);
746  	}
747  
748  	static void ChaCha20 (EVP_CIPHER_CTX *ctx, const uint8_t * msg, size_t msgLen, const uint8_t * key, const uint8_t * nonce, uint8_t * out)
749  	{
750  		uint32_t iv[4];
751  		iv[0] = htole32 (1); memcpy (iv + 1, nonce, 12); // counter | nonce
752  		EVP_EncryptInit_ex(ctx, EVP_chacha20 (), NULL, key, (const uint8_t *)iv);
753  		int outlen = 0;
754  		EVP_EncryptUpdate(ctx, out, &outlen, msg, msgLen);
755  		EVP_EncryptFinal_ex(ctx, NULL, &outlen);
756  	}
757  	
758  	void ChaCha20 (const uint8_t * msg, size_t msgLen, const uint8_t * key, const uint8_t * nonce, uint8_t * out)
759  	{
760  		EVP_CIPHER_CTX *ctx = EVP_CIPHER_CTX_new ();
761  		ChaCha20 (ctx, msg, msgLen, key, nonce, out);
762  		EVP_CIPHER_CTX_free (ctx);
763  	}
764  
765  	
766  	ChaCha20Context::ChaCha20Context ()
767  	{
768  		m_Ctx = EVP_CIPHER_CTX_new ();
769  	}
770  	
771  	ChaCha20Context::~ChaCha20Context ()
772  	{
773  		if (m_Ctx)
774  			EVP_CIPHER_CTX_free (m_Ctx);
775  	}
776  	
777  	void ChaCha20Context::operator ()(const uint8_t * msg, size_t msgLen, const uint8_t * key, const uint8_t * nonce, uint8_t * out)
778  	{
779  		ChaCha20 (m_Ctx, msg, msgLen, key, nonce, out);
780  	}	
781  	
782  	void HKDF (const uint8_t * salt, const uint8_t * key, size_t keyLen, std::string_view info,
783  		uint8_t * out, size_t outLen)
784  	{
785  		EVP_PKEY_CTX * pctx = EVP_PKEY_CTX_new_id (EVP_PKEY_HKDF, nullptr);
786  		EVP_PKEY_derive_init (pctx);
787  		EVP_PKEY_CTX_set_hkdf_md (pctx, EVP_sha256());
788  		if (key && keyLen)
789  		{
790  			EVP_PKEY_CTX_set1_hkdf_salt (pctx, salt, 32);
791  			EVP_PKEY_CTX_set1_hkdf_key (pctx, key, keyLen);
792  		}
793  		else
794  		{
795  			// zerolen
796  			EVP_PKEY_CTX_hkdf_mode (pctx, EVP_PKEY_HKDEF_MODE_EXPAND_ONLY);
797  			uint8_t tempKey[32]; unsigned int len;
798  			HMAC(EVP_sha256(), salt, 32, nullptr, 0, tempKey, &len);
799  			EVP_PKEY_CTX_set1_hkdf_key (pctx, tempKey, len);
800  		}
801  		if (info.length () > 0)
802  			EVP_PKEY_CTX_add1_hkdf_info (pctx, (const uint8_t *)info.data (), info.length ());
803  		EVP_PKEY_derive (pctx, out, &outLen);
804  		EVP_PKEY_CTX_free (pctx);
805  	}
806  
807  // Noise
808  
809  	void NoiseSymmetricState::Init (const uint8_t * ck, const uint8_t * hh, const uint8_t * pub)
810  	{
811  		// pub is Bob's public static key, hh = SHA256(h)
812  		memcpy (m_CK, ck, 32);
813  
814  		EVP_MD_CTX *ctx = EVP_MD_CTX_new ();
815  		EVP_DigestInit_ex(ctx, EVP_sha256 (), NULL);
816  		EVP_DigestUpdate (ctx, hh, 32);
817  		EVP_DigestUpdate (ctx, pub, 32);
818  		EVP_DigestFinal_ex (ctx, m_H, nullptr); // h = MixHash(pub) = SHA256(hh || pub)
819  		EVP_MD_CTX_free (ctx);
820  		m_N = 0;
821  	}	
822  	
823  	void NoiseSymmetricState::MixHash (const uint8_t * buf, size_t len)
824  	{
825  		EVP_MD_CTX *ctx = EVP_MD_CTX_new ();
826  		EVP_DigestInit_ex(ctx, EVP_sha256 (), NULL);
827  		EVP_DigestUpdate (ctx, m_H, 32);
828  		EVP_DigestUpdate (ctx, buf, len);
829  		EVP_DigestFinal_ex (ctx, m_H, nullptr);
830  		EVP_MD_CTX_free (ctx);
831  	}
832  
833  	void NoiseSymmetricState::MixHash (const std::vector<std::pair<uint8_t *, size_t> >& bufs)
834  	{
835  		EVP_MD_CTX *ctx = EVP_MD_CTX_new ();
836  		EVP_DigestInit_ex(ctx, EVP_sha256 (), NULL);
837  		EVP_DigestUpdate (ctx, m_H, 32);
838  		for (const auto& it: bufs)
839  			EVP_DigestUpdate (ctx, it.first, it.second);
840  		EVP_DigestFinal_ex (ctx, m_H, nullptr);
841  		EVP_MD_CTX_free (ctx);
842  	}
843  
844  	void NoiseSymmetricState::MixKey (const uint8_t * sharedSecret)
845  	{
846  		HKDF (m_CK, sharedSecret, 32, "", m_CK);
847  		// new ck is m_CK[0:31], key is m_CK[32:63]
848  		m_N = 0;
849  	}
850  
851  	bool NoiseSymmetricState::Encrypt (const uint8_t * in, uint8_t * out, size_t len)
852  	{
853  		uint8_t nonce[12];
854  		if (m_N)
855  		{	
856  			memset (nonce, 0, 4);
857  			htole64buf (nonce + 4, m_N);
858  		}	
859  		else
860  			memset (nonce, 0, 12);
861  		auto ret = AEADChaCha20Poly1305 (in, len, m_H, 32, m_CK + 32, nonce, out, len + 16, true);
862  		if (ret) m_N++;
863  		return ret;
864  	}
865  
866  	bool NoiseSymmetricState::Decrypt (const uint8_t * in, uint8_t * out, size_t len)
867  	{
868  		uint8_t nonce[12];
869  		if (m_N)
870  		{	
871  			memset (nonce, 0, 4);
872  			htole64buf (nonce + 4, m_N);
873  		}
874  		else
875  			memset (nonce, 0, 12);
876  		auto ret = AEADChaCha20Poly1305 (in, len, m_H, 32, m_CK + 32, nonce, out, len, false);
877  		if (ret) m_N++;
878  		return ret;
879  	}	
880  	
881  	void InitNoiseNState (NoiseSymmetricState& state, const uint8_t * pub)
882  	{
883  		static constexpr char protocolName[] = "Noise_N_25519_ChaChaPoly_SHA256"; // 31 chars
884  		static constexpr uint8_t hh[32] =
885  		{
886  			0x69, 0x4d, 0x52, 0x44, 0x5a, 0x27, 0xd9, 0xad, 0xfa, 0xd2, 0x9c, 0x76, 0x32, 0x39, 0x5d, 0xc1,
887  			0xe4, 0x35, 0x4c, 0x69, 0xb4, 0xf9, 0x2e, 0xac, 0x8a, 0x1e, 0xe4, 0x6a, 0x9e, 0xd2, 0x15, 0x54
888  		}; // hh = SHA256(protocol_name || 0)
889  		state.Init ((const uint8_t *)protocolName, hh, pub); // ck = protocol_name || 0
890  	}
891  
892  	void InitNoiseXKState (NoiseSymmetricState& state, const uint8_t * pub)
893  	{
894  		static constexpr uint8_t protocolNameHash[32] =
895  		{
896  			0x72, 0xe8, 0x42, 0xc5, 0x45, 0xe1, 0x80, 0x80, 0xd3, 0x9c, 0x44, 0x93, 0xbb, 0x91, 0xd7, 0xed,
897  			0xf2, 0x28, 0x98, 0x17, 0x71, 0x21, 0x8c, 0x1f, 0x62, 0x4e, 0x20, 0x6f, 0x28, 0xd3, 0x2f, 0x71
898  		}; // SHA256 ("Noise_XKaesobfse+hs2+hs3_25519_ChaChaPoly_SHA256")
899  		static constexpr uint8_t hh[32] =
900  		{
901  			0x49, 0xff, 0x48, 0x3f, 0xc4, 0x04, 0xb9, 0xb2, 0x6b, 0x11, 0x94, 0x36, 0x72, 0xff, 0x05, 0xb5,
902  			0x61, 0x27, 0x03, 0x31, 0xba, 0x89, 0xb8, 0xfc, 0x33, 0x15, 0x93, 0x87, 0x57, 0xdd, 0x3d, 0x1e
903  		}; // SHA256 (protocolNameHash)
904  		state.Init (protocolNameHash, hh, pub);
905  	}
906  
907  	void InitNoiseXKState1 (NoiseSymmetricState& state, const uint8_t * pub)
908  	{
909  		static constexpr uint8_t protocolNameHash[32] =
910  		{
911  			0xb1, 0x37, 0x22, 0x81, 0x74, 0x23, 0xa8, 0xfd, 0xf4, 0x2d, 0xf2, 0xe6, 0x0e, 0xd1, 0xed, 0xf4,
912  			0x1b, 0x93, 0x07, 0x1d, 0xb1, 0xec, 0x24, 0xa3, 0x67, 0xf7, 0x84, 0xec, 0x27, 0x0d, 0x81, 0x32
913  		}; // SHA256 ("Noise_XKchaobfse+hs1+hs2+hs3_25519_ChaChaPoly_SHA256")
914  		static constexpr uint8_t hh[32] =
915  		{
916  			0xdc, 0x85, 0xe6, 0xaf, 0x7b, 0x02, 0x65, 0x0c, 0xf1, 0xf9, 0x0d, 0x71, 0xfb, 0xc6, 0xd4, 0x53,
917  			0xa7, 0xcf, 0x6d, 0xbf, 0xbd, 0x52, 0x5e, 0xa5, 0xb5, 0x79, 0x1c, 0x47, 0xb3, 0x5e, 0xbc, 0x33
918  		}; // SHA256 (protocolNameHash)
919  		state.Init (protocolNameHash, hh, pub);
920  	}
921  
922  	void InitNoiseIKState (NoiseSymmetricState& state, const uint8_t * pub)
923  	{
924  		static constexpr uint8_t protocolNameHash[32] =
925  		{
926  			0x4c, 0xaf, 0x11, 0xef, 0x2c, 0x8e, 0x36, 0x56, 0x4c, 0x53, 0xe8, 0x88, 0x85, 0x06, 0x4d, 0xba,
927  			0xac, 0xbe, 0x00, 0x54, 0xad, 0x17, 0x8f, 0x80, 0x79, 0xa6, 0x46, 0x82, 0x7e, 0x6e, 0xe4, 0x0c
928  		}; // SHA256("Noise_IKelg2+hs2_25519_ChaChaPoly_SHA256"), 40 bytes
929  		static constexpr uint8_t hh[32] =
930  		{
931  			0x9c, 0xcf, 0x85, 0x2c, 0xc9, 0x3b, 0xb9, 0x50, 0x44, 0x41, 0xe9, 0x50, 0xe0, 0x1d, 0x52, 0x32,
932  			0x2e, 0x0d, 0x47, 0xad, 0xd1, 0xe9, 0xa5, 0x55, 0xf7, 0x55, 0xb5, 0x69, 0xae, 0x18, 0x3b, 0x5c
933  		}; // SHA256 (protocolNameHash)
934  		state.Init (protocolNameHash, hh, pub);
935  	}
936  		
937  // init and terminate
938  
939  /*	std::vector <std::unique_ptr<std::mutex> > m_OpenSSLMutexes;
940  	static void OpensslLockingCallback(int mode, int type, const char * file, int line)
941  	{
942  		if (type > 0 && (size_t)type < m_OpenSSLMutexes.size ())
943  		{
944  			if (mode & CRYPTO_LOCK)
945  				m_OpenSSLMutexes[type]->lock ();
946  			else
947  				m_OpenSSLMutexes[type]->unlock ();
948  		}
949  	}*/
950  
951  	void InitCrypto (bool precomputation)
952  	{
953  /*		auto numLocks = CRYPTO_num_locks();
954  		for (int i = 0; i < numLocks; i++)
955  			m_OpenSSLMutexes.emplace_back (new std::mutex);
956  		CRYPTO_set_locking_callback (OpensslLockingCallback);*/
957  		if (precomputation)
958  		{
959  #if IS_X86_64
960  			g_ElggTable = new BIGNUM * [ELGAMAL_FULL_EXPONENT_NUM_BYTES][255];
961  			PrecalculateElggTable (g_ElggTable, ELGAMAL_FULL_EXPONENT_NUM_BYTES);
962  #else
963  			g_ElggTable = new BIGNUM * [ELGAMAL_SHORT_EXPONENT_NUM_BYTES][255];
964  			PrecalculateElggTable (g_ElggTable, ELGAMAL_SHORT_EXPONENT_NUM_BYTES);
965  #endif
966  		}
967  	}
968  
969  	void TerminateCrypto ()
970  	{
971  		if (g_ElggTable)
972  		{
973  			DestroyElggTable (g_ElggTable,
974  #if IS_X86_64
975  				ELGAMAL_FULL_EXPONENT_NUM_BYTES
976  #else
977  				ELGAMAL_SHORT_EXPONENT_NUM_BYTES
978  #endif
979  			);
980  			delete[] g_ElggTable; g_ElggTable = nullptr;
981  		}
982  /*		CRYPTO_set_locking_callback (nullptr);
983  		m_OpenSSLMutexes.clear ();*/
984  	}
985  }
986  }