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 }