cryptolib.cpp 44 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026
  1. /*##############################################################################
  2. HPCC SYSTEMS software Copyright (C) 2019 HPCC Systems®.
  3. Licensed under the Apache License, Version 2.0 (the "License");
  4. you may not use this file except in compliance with the License.
  5. You may obtain a copy of the License at
  6. http://www.apache.org/licenses/LICENSE-2.0
  7. Unless required by applicable law or agreed to in writing, software
  8. distributed under the License is distributed on an "AS IS" BASIS,
  9. WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  10. See the License for the specific language governing permissions and
  11. limitations under the License.
  12. ############################################################################## */
  13. #include "jexcept.hpp"
  14. #include "digisign.hpp"
  15. #include "ske.hpp"
  16. #include "dadfs.hpp"
  17. #include "dautils.hpp"
  18. #include <openssl/rand.h>
  19. #include <unordered_map>
  20. #include "cryptolib.hpp"
  21. using namespace std;
  22. #define CRYPTOLIB_VERSION "CRYPTOLIB 1.0.00"
  23. using namespace cryptohelper;
  24. static const char * EclDefinition = nullptr;//Definitions specified in lib_cryptolib.ecllib
  25. CRYPTOLIB_API bool getECLPluginDefinition(ECLPluginDefinitionBlock *pb)
  26. {
  27. // Warning: This function may be called without the plugin being loaded fully.
  28. // It should not make any library calls or assume that dependent modules
  29. // have been loaded or that it has been initialized.
  30. //
  31. // Specifically: "The system does not call DllMain for process and thread
  32. // initialization and termination. Also, the system does not load
  33. // additional executable modules that are referenced by the specified module."
  34. if (pb->size != sizeof(ECLPluginDefinitionBlock))
  35. return false;
  36. pb->magicVersion = PLUGIN_VERSION;
  37. pb->version = CRYPTOLIB_VERSION;
  38. pb->moduleName = "lib_cryptolib";
  39. pb->ECL = EclDefinition;
  40. pb->flags = PLUGIN_IMPLICIT_MODULE;
  41. pb->description = "CryptoLib cryptography services library";
  42. return true;
  43. }
  44. namespace nsCryptolib {
  45. IPluginContext * parentCtx = nullptr;
  46. }
  47. using namespace nsCryptolib;
  48. CRYPTOLIB_API void setPluginContext(IPluginContext * _ctx) { parentCtx = _ctx; }
  49. //-------------------------------------------------------------------------------------------------------------------------------------------
  50. // C++ to ECL helpers
  51. //-------------------------------------------------------------------------------------------------------------------------------------------
  52. size32_t addToECLSetOfString(void * set, const char * str)
  53. {
  54. size32_t len = strlen(str);
  55. if (len)
  56. {
  57. memcpy(set, &len, sizeof(len));//copy 4 byte length. String Set memory buffer should already be allocated within the context
  58. memcpy((char *)set + sizeof(len), str, strlen(str));//followed by string
  59. }
  60. return len + sizeof(len);//return length copied to memory buffer
  61. }
  62. void stringArrayToECLSetOfString(const StringArray & arr, void * * set, size32_t * len)
  63. {
  64. //STRING is a variable length string stored as a 4 byte length, followed by the string. A set of strings has
  65. //the strings in this format repeated, and the total size returned in the __lenResult parameter. The __result value should be allocated
  66. //on the heap.
  67. size32_t currLen = 0;
  68. for (aindex_t idx = 0; idx < arr.length(); idx++)
  69. currLen += strlen(arr.item(idx)) + sizeof(size32_t);
  70. void * pSet = CTXMALLOC(parentCtx, currLen);
  71. assertex(set);
  72. *len = currLen;
  73. *set = pSet;
  74. currLen = 0;
  75. for (aindex_t idx = 0; idx < arr.length(); idx++)
  76. currLen += addToECLSetOfString((char*)pSet + currLen, arr.item(idx));
  77. }
  78. //-------------------------------------------------------------------------------------------------------------------------------------------
  79. // CIPHER SYMMETRIC SUPPORT
  80. //-------------------------------------------------------------------------------------------------------------------------------------------
  81. //NB: It should be noted that we count on the cryptohelper library to call OpenSSL_add_all_algorithms() at init time
  82. void my_clAlgorithmsCallback(const OBJ_NAME * _obj, void * _pRes)
  83. {
  84. ((StringArray*)_pRes)->append((const char*)_obj->name);//add this digest to string array
  85. }
  86. //NB: CRYPTOLIB call signatures can be gleaned from the generated workunit CPP file
  87. //Symmetric block/stream digest algorithms
  88. CRYPTOLIB_API void CRYPTOLIB_CALL clInstalledSymmetricCipherAlgorithms(bool & __isAllResult, size32_t & __lenResult, void * & __result)
  89. {
  90. __isAllResult = false;
  91. StringArray algorithms;
  92. OBJ_NAME_do_all_sorted(OBJ_NAME_TYPE_CIPHER_METH, my_clAlgorithmsCallback, (void*)&algorithms);
  93. stringArrayToECLSetOfString(algorithms, &__result, &__lenResult);
  94. }
  95. CRYPTOLIB_API void CRYPTOLIB_CALL clSupportedSymmetricCipherAlgorithms(bool & __isAllResult, size32_t & __lenResult, void * & __result)
  96. {
  97. __isAllResult = false;
  98. StringArray algorithms;
  99. algorithms.appendList("aes-256-cbc,aes-192-cbc,aes-128-cbc", ",");//make sure this list matches loadEVP_Cipher()
  100. stringArrayToECLSetOfString(algorithms, &__result, &__lenResult);
  101. }
  102. //-------------------------------------------------------------------------------------------------------------------------------------------
  103. //Helpers to build the DATA buffer returned from clSymmetricEncrypt, and sent to clSymmetricDecrypt
  104. //Buffer is structured as:
  105. // (size32_t)lenIV, IV excluding NULL, (size32_t)LenPlainText excluding NULL, (size32_t)LenCipher, Cipher
  106. static void symmDeserialize(const void * pBuffer, StringBuffer & sbIV, StringBuffer & sbCipher, size32_t * lenPlainText)
  107. {
  108. size32_t len;
  109. const char * finger = (const char *)pBuffer;
  110. memcpy(&len, finger, sizeof(size32_t));//extract IV
  111. finger += sizeof(size32_t);
  112. sbIV.append(len, finger);
  113. finger += len;
  114. memcpy(lenPlainText, finger, sizeof(size32_t));//extract length of plain text
  115. finger += sizeof(size32_t);
  116. memcpy(&len, finger, sizeof(size32_t));//extract cipher
  117. finger += sizeof(size32_t);
  118. sbCipher.append(len, finger);
  119. }
  120. static void symmSerialize(void * & result, size32_t & lenResult, const char * pIV, size32_t lenIV, size32_t lenPlainText, size32_t lenCipherBuff, const void * pCipherBuff)
  121. {
  122. //Allocate return DATA buffer
  123. lenResult = sizeof(size32_t) + lenIV + sizeof(size32_t) + sizeof(size32_t) + lenCipherBuff;
  124. result = CTXMALLOC(parentCtx, lenResult);
  125. //build result DATA buffer in the form:
  126. char * pRes = (char *)result;
  127. memcpy(pRes, &lenIV, sizeof(size32_t));//copy size of IV
  128. pRes += sizeof(size32_t);
  129. memcpy(pRes, pIV, lenIV);//copy the IV
  130. pRes += lenIV;
  131. memcpy(pRes, &lenPlainText, sizeof(size32_t));
  132. pRes += sizeof(size32_t);
  133. memcpy(pRes, &lenCipherBuff, sizeof(size32_t));
  134. pRes += sizeof(size32_t);
  135. memcpy(pRes, pCipherBuff, lenCipherBuff);
  136. }
  137. //-------------------------------------------------------------------------------------------------------------------------------------------
  138. void verifySymmetricAlgorithm(const char * algorithm, size32_t len)
  139. {
  140. if (strieq(algorithm, "aes-128-cbc"))
  141. {
  142. if (len != 16)
  143. throw makeStringExceptionV(-1, "Invalid Key Length %d specified for algorithm %s, try 16", len, algorithm);
  144. }
  145. else if (strieq(algorithm, "aes-192-cbc"))
  146. {
  147. if (len != 24)
  148. throw makeStringExceptionV(-1, "Invalid Key Length %d specified for algorithm %s, try 24", len, algorithm);
  149. }
  150. else if (strieq(algorithm, "aes-256-cbc"))
  151. {
  152. if (len != 32)
  153. throw makeStringExceptionV(-1, "Invalid Key Length %d specified for algorithm %s, try 32", len, algorithm);
  154. }
  155. else
  156. throw makeStringExceptionV(-1, "Unsupported symmetric algorithm (%s) specified", algorithm);
  157. }
  158. CRYPTOLIB_API void CRYPTOLIB_CALL clSymmEncrypt(size32_t & __lenResult, void * & __result,
  159. const char * algorithm,
  160. size32_t lenKey, const void * key,
  161. size32_t lenInputdata,const void * inputdata)
  162. {
  163. verifySymmetricAlgorithm(algorithm, lenKey );
  164. //Create a unique Initialization Vector
  165. unsigned char iv[EVP_MAX_IV_LENGTH];
  166. RAND_bytes(iv, EVP_MAX_IV_LENGTH);
  167. //temporary buffer for result
  168. MemoryBuffer out;
  169. aesEncrypt(out, lenInputdata, inputdata, lenKey, (const char *)key, (const char *)iv);
  170. //build result DATA buffer in the form:
  171. // (size32_t)EVP_MAX_IV_LENGTH, IV, (size32_t)LenPlainText excluding NULL, (size32_t)LenCipher, Cipher
  172. symmSerialize(__result, __lenResult, (const char *)iv, sizeof(iv), lenInputdata, out.length(), (const void *)out.bufferBase());
  173. }
  174. CRYPTOLIB_API void CRYPTOLIB_CALL clSymmDecrypt(size32_t & __lenResult,void * & __result,
  175. const char * algorithm,
  176. size32_t lenKey,const void * key,
  177. size32_t lenEncrypteddata,const void * encrypteddata)
  178. {
  179. verifySymmetricAlgorithm(algorithm, lenKey);
  180. //Decompose DATA buffer
  181. StringBuffer sbIV;
  182. StringBuffer sbCipher;
  183. size32_t lenPlainText;
  184. symmDeserialize(encrypteddata, sbIV, sbCipher, &lenPlainText);
  185. __result = (char *)CTXMALLOC(parentCtx, lenPlainText);
  186. __lenResult = lenPlainText;
  187. MemoryBuffer decrypted;
  188. size32_t len = aesDecrypt(decrypted, sbCipher.length(), sbCipher.str(), lenKey, (const char *)key, sbIV.str());
  189. memcpy(__result, decrypted.toByteArray(), __lenResult);
  190. }
  191. CRYPTOLIB_API void CRYPTOLIB_CALL clSymmetricEncrypt(size32_t & __lenResult, void * & __result,
  192. const char * algorithm,
  193. const char * key,
  194. size32_t lenInputdata,const void * inputdata)
  195. {
  196. return clSymmEncrypt(__lenResult, __result, algorithm, strlen(key), (const void *)key, lenInputdata, inputdata);
  197. }
  198. CRYPTOLIB_API void CRYPTOLIB_CALL clSymmetricDecrypt(size32_t & __lenResult,void * & __result,
  199. const char * algorithm,
  200. const char * key,
  201. size32_t lenEncrypteddata,const void * encrypteddata)
  202. {
  203. return clSymmDecrypt(__lenResult, __result, algorithm, strlen(key), (const void *)key, lenEncrypteddata, encrypteddata);
  204. }
  205. //-------------------------------------------------------------------------------------------------------------------------------------------
  206. // HASH SUPPORT
  207. //-------------------------------------------------------------------------------------------------------------------------------------------
  208. CRYPTOLIB_API void CRYPTOLIB_CALL clInstalledHashAlgorithms(bool & __isAllResult, size32_t & __lenResult, void * & __result)
  209. {
  210. __isAllResult = false;
  211. StringArray algorithms;
  212. OBJ_NAME_do_all_sorted(OBJ_NAME_TYPE_MD_METH, my_clAlgorithmsCallback, (void*)&algorithms);
  213. stringArrayToECLSetOfString(algorithms, &__result, &__lenResult);
  214. }
  215. CRYPTOLIB_API void CRYPTOLIB_CALL clSupportedHashAlgorithms(bool & __isAllResult, size32_t & __lenResult, void * & __result)
  216. {
  217. __isAllResult = false;
  218. StringArray algorithms;
  219. algorithms.appendList("SHA1,SHA224,SHA256,SHA384,SHA512", ",");//make sure these match algorithms in clHash()
  220. stringArrayToECLSetOfString(algorithms, &__result, &__lenResult);
  221. }
  222. void throwHashError(const char * str)
  223. {
  224. unsigned long err = ERR_get_error();
  225. char errStr[1024];
  226. ERR_error_string_n(err, errStr, sizeof(errStr));
  227. throw makeStringExceptionV(-1, "%s : ERROR %ld (0x%lX) : %s", str, err, err, errStr);
  228. }
  229. CRYPTOLIB_API void CRYPTOLIB_CALL clHash(size32_t & __lenResult, void * & __result,
  230. const char * algorithm,
  231. size32_t lenInputData, const void * inputData)
  232. {
  233. //Make sure each algorithm is included in clHashAlgorithms()
  234. if (strieq("SHA1", algorithm))
  235. {
  236. SHA_CTX context;
  237. if (!SHA1_Init(&context))
  238. throwHashError("OpenSSL ERROR calling SHA1_Init");
  239. if (!SHA1_Update(&context, (unsigned char*)inputData, lenInputData))
  240. throwHashError("OpenSSL ERROR calling SHA1_Update");
  241. __lenResult = SHA_DIGEST_LENGTH;//20 bytes
  242. __result = CTXMALLOC(parentCtx, __lenResult);
  243. if (!SHA1_Final((unsigned char *)__result, &context))
  244. {
  245. free(__result);
  246. throwHashError("OpenSSL ERROR calling SHA1_Final");
  247. }
  248. }
  249. else if (strieq("SHA224", algorithm))
  250. {
  251. SHA256_CTX context;//SHA224 uses the SHA256 context
  252. if (!SHA224_Init(&context))
  253. throwHashError("OpenSSL ERROR calling SHA224_Init");
  254. if (!SHA224_Update(&context, (unsigned char*)inputData, lenInputData))
  255. throwHashError("OpenSSL ERROR calling SHA224_Update");
  256. __lenResult = SHA224_DIGEST_LENGTH;//28 bytes
  257. __result = CTXMALLOC(parentCtx, __lenResult);
  258. if (!SHA224_Final((unsigned char *)__result, &context))
  259. {
  260. free(__result);
  261. throwHashError("OpenSSL ERROR calling SHA224_Final");
  262. }
  263. }
  264. else if (strieq("SHA256", algorithm))
  265. {
  266. SHA256_CTX context;
  267. if (!SHA256_Init(&context))
  268. throwHashError("OpenSSL ERROR calling SHA256_Init");
  269. if (!SHA256_Update(&context, (unsigned char*)inputData, lenInputData))
  270. throwHashError("OpenSSL ERROR calling SHA256_Update");
  271. __lenResult = SHA256_DIGEST_LENGTH;//32 bytes
  272. __result = CTXMALLOC(parentCtx, __lenResult);
  273. if (!SHA256_Final((unsigned char *)__result, &context))
  274. {
  275. free(__result);
  276. throwHashError("OpenSSL ERROR calling SHA256_Final");
  277. }
  278. }
  279. else if (strieq("SHA384", algorithm))
  280. {
  281. SHA512_CTX context;//SHA384 uses the SHA512 context
  282. if (!SHA384_Init(&context))
  283. throwHashError("OpenSSL ERROR calling SHA384_Init");
  284. if (!SHA384_Update(&context, (unsigned char*)inputData, lenInputData))
  285. throwHashError("OpenSSL ERROR calling SHA384_Update");
  286. __lenResult = SHA384_DIGEST_LENGTH;//48 bytes
  287. __result = CTXMALLOC(parentCtx, __lenResult);
  288. if (!SHA384_Final((unsigned char *)__result, &context))
  289. {
  290. free(__result);
  291. throwHashError("OpenSSL ERROR calling SHA384_Final");
  292. }
  293. }
  294. else if (strieq("SHA512", algorithm))
  295. {
  296. SHA512_CTX context;
  297. if (!SHA512_Init(&context))
  298. throwHashError("OpenSSL ERROR calling SHA512_Init");
  299. if (!SHA512_Update(&context, (unsigned char*)inputData, lenInputData))
  300. throwHashError("OpenSSL ERROR calling SHA512_Update");
  301. __lenResult = SHA512_DIGEST_LENGTH;//64 bytes
  302. __result = CTXMALLOC(parentCtx, __lenResult);
  303. if (!SHA512_Final((unsigned char *)__result, &context))
  304. {
  305. free(__result);
  306. throwHashError("OpenSSL ERROR calling SHA512_Final");
  307. }
  308. }
  309. else
  310. {
  311. throw makeStringExceptionV(-1, "Unsupported hash algorithm '%s' specified", algorithm);
  312. }
  313. }
  314. //-------------------------------------------------------------------------------------------------------------------------------------------
  315. // PUBLIC KEY SUPPORT
  316. //-------------------------------------------------------------------------------------------------------------------------------------------
  317. CRYPTOLIB_API void CRYPTOLIB_CALL clInstalledPublicKeyAlgorithms(bool & __isAllResult, size32_t & __lenResult, void * & __result)
  318. {
  319. __isAllResult = false;
  320. StringArray algorithms;
  321. OBJ_NAME_do_all_sorted(OBJ_NAME_TYPE_PKEY_METH, my_clAlgorithmsCallback, (void*)&algorithms);
  322. stringArrayToECLSetOfString(algorithms, &__result, &__lenResult);
  323. }
  324. CRYPTOLIB_API void CRYPTOLIB_CALL clSupportedPublicKeyAlgorithms(bool & __isAllResult, size32_t & __lenResult, void * & __result)
  325. {
  326. __isAllResult = false;
  327. StringArray algorithms;
  328. algorithms.appendList("RSA", ",");
  329. stringArrayToECLSetOfString(algorithms, &__result, &__lenResult);
  330. }
  331. //signature helper function
  332. void doPKISign(size32_t & __lenResult, void * & __result,
  333. IDigitalSignatureManager * pDSM,
  334. size32_t lenInputdata, const void * inputdata)
  335. {
  336. StringBuffer sbSig;
  337. if (pDSM->digiSign(sbSig, lenInputdata, inputdata))
  338. {
  339. __result = CTXMALLOC(parentCtx, sbSig.length());
  340. __lenResult = sbSig.length();
  341. memcpy(__result, sbSig.str(), __lenResult);
  342. }
  343. else
  344. {
  345. throw makeStringException(-1, "Unable to create Digital Signature");
  346. }
  347. }
  348. void verifyPKIAlgorithm(const char * pkAlgorithm)
  349. {
  350. if (!strieq(pkAlgorithm, "RSA"))
  351. throw makeStringExceptionV(-1, "Unsupported PKI algorithm (%s) specified", pkAlgorithm);
  352. }
  353. //---------------------------------------------------------
  354. // Helper that reads the given logical file into a string buffer
  355. // Throws if user does not have read permission or if FNF
  356. //---------------------------------------------------------
  357. void loadLFS(const char * lfs, IUserDescriptor * user, StringBuffer &sb)
  358. {
  359. CDfsLogicalFileName lfn;
  360. lfn.set(lfs);
  361. try
  362. {
  363. Owned<IDistributedFile> df = queryDistributedFileDirectory().lookup(lfn, user, AccessMode::tbdRead, false, false, nullptr, defaultPrivilegedUser);//scope checks
  364. if (!df)
  365. {
  366. throw makeStringExceptionV(-1, "File %s Not Found", lfs);
  367. }
  368. if (df->numParts() == 0)
  369. {
  370. throw makeStringExceptionV(-1, "File %s is Empty", lfs);
  371. }
  372. IDistributedFilePart &part = df->queryPart(0);
  373. RemoteFilename rfn;
  374. Owned<IFile> file = createIFile(part.getFilename(rfn));
  375. if (!file->exists())
  376. {
  377. throw makeStringExceptionV(-1, "File %s Not Found", lfs);
  378. }
  379. Owned<IFileIO> io = file->open(IFOread);
  380. offset_t len = file->size();
  381. char * buff = sb.reserveTruncate(len);
  382. size32_t read = io->read(0, len, buff);
  383. assertex(read == len);
  384. //IFileIO dtor closes the file
  385. }
  386. catch(IException * e)
  387. {
  388. StringBuffer s;
  389. VStringBuffer sb("Error accessing Key file '%s' : %s", lfs, e->errorMessage(s).str());
  390. e->Release();
  391. throw makeStringException(-1, sb.str());
  392. }
  393. }
  394. //-----------------------------------------------------------------
  395. // Simple cache for instances of Digital Signature Managers
  396. //-----------------------------------------------------------------
  397. class CDSMCache
  398. {
  399. private:
  400. CriticalSection csDSMCache;//guards modifications to the cache map
  401. typedef std::unordered_map<string, Owned<IDigitalSignatureManager>> DSMCache;
  402. DSMCache dsmCache;
  403. public:
  404. IDigitalSignatureManager * getInstance(const char * algo, const char * pubKeyFS, const char * pubKeyBuff, const char * privKeyFS, const char * privKeyBuff, size32_t lenPassphrase, const void * passphrase, bool isLFN, IUserDescriptor * user)
  405. {
  406. //Passphrase could be binary, so convert to string
  407. StringBuffer hexPwd;
  408. for (int i=0; i<lenPassphrase; i++)
  409. hexPwd.appendf("%02x", *((const unsigned char *)passphrase + i) );
  410. VStringBuffer searchKey("%s_%s_%s_%s_%s_%s", algo, isEmptyString(pubKeyFS) ? "" : pubKeyFS, isEmptyString(pubKeyBuff) ? "" : pubKeyBuff,
  411. isEmptyString(privKeyFS) ? "" : privKeyFS, isEmptyString(privKeyBuff) ? "" : privKeyBuff, hexPwd.str());
  412. CriticalBlock block(csDSMCache);
  413. DSMCache::iterator it = dsmCache.find(searchKey.str());
  414. IDigitalSignatureManager * ret = nullptr;
  415. if (it != dsmCache.end())//exists in cache
  416. {
  417. ret = (*it).second;
  418. }
  419. else
  420. {
  421. if (!isEmptyString(pubKeyFS) || !isEmptyString(privKeyFS))
  422. {
  423. bool isPublic = isEmptyString(privKeyFS);
  424. const char * fs = isPublic ? pubKeyFS : privKeyFS;;
  425. if (isLFN)
  426. {
  427. StringBuffer sb;
  428. loadLFS(fs, user, sb);//read key file into StringBuffer
  429. ret = createDigitalSignatureManagerInstanceFromKeys(isPublic ? sb.str() : nullptr, isPublic ? nullptr : sb.str(), lenPassphrase, passphrase);
  430. }
  431. else
  432. ret = createDigitalSignatureManagerInstanceFromFiles(pubKeyFS, privKeyFS, lenPassphrase, passphrase);
  433. }
  434. else
  435. ret = createDigitalSignatureManagerInstanceFromKeys(pubKeyBuff, privKeyBuff, lenPassphrase, passphrase);
  436. dsmCache.emplace(searchKey.str(), ret);
  437. }
  438. return LINK(ret);
  439. }
  440. };
  441. static CDSMCache g_DSMCache;
  442. //Sign given data using private key
  443. CRYPTOLIB_API void CRYPTOLIB_CALL clPKISign2(size32_t & __lenResult,void * & __result,
  444. const char * pkalgorithm,
  445. const char * privatekeyfile,
  446. size32_t lenPassPhrase,const void * passphrase,
  447. size32_t lenInputdata,const void * inputdata)
  448. {
  449. verifyPKIAlgorithm(pkalgorithm);//TODO extend cryptohelper to support more algorithms
  450. Owned<IDigitalSignatureManager> pDSM = g_DSMCache.getInstance(pkalgorithm, nullptr, nullptr, privatekeyfile, nullptr, lenPassPhrase, passphrase, false, nullptr);
  451. if (pDSM)
  452. {
  453. doPKISign(__lenResult, __result, pDSM, lenInputdata, inputdata);
  454. }
  455. else
  456. {
  457. throw makeStringException(-1, "Unable to create Digital Signature Manager");
  458. }
  459. }
  460. CRYPTOLIB_API void CRYPTOLIB_CALL clPKISignLFN2(ICodeContext * ctx,
  461. size32_t & __lenResult,void * & __result,
  462. const char * pkalgorithm,
  463. const char * privatekeyLFN,
  464. size32_t lenPassPhrase,const void * passphrase,
  465. size32_t lenInputdata,const void * inputdata)
  466. {
  467. verifyPKIAlgorithm(pkalgorithm);
  468. IUserDescriptor * udesc = ctx->queryUserDescriptor();
  469. Owned<IDigitalSignatureManager> pDSM = g_DSMCache.getInstance(pkalgorithm, nullptr, nullptr, privatekeyLFN, nullptr, lenPassPhrase, passphrase, true, udesc);
  470. if (pDSM)
  471. {
  472. doPKISign(__lenResult, __result, pDSM, lenInputdata, inputdata);
  473. }
  474. else
  475. {
  476. throw makeStringException(-1, "Unable to create Digital Signature Manager");
  477. }
  478. }
  479. CRYPTOLIB_API void CRYPTOLIB_CALL clPKISignBuff2(size32_t & __lenResult, void * & __result,
  480. const char * pkalgorithm,
  481. const char * privatekeybuff,
  482. size32_t lenPassPhrase,const void * passphrase,
  483. size32_t lenInputdata, const void * inputdata)
  484. {
  485. verifyPKIAlgorithm(pkalgorithm);
  486. Owned<IDigitalSignatureManager> pDSM = g_DSMCache.getInstance(pkalgorithm, nullptr, nullptr, nullptr, privatekeybuff, lenPassPhrase, passphrase, false, nullptr);
  487. if (pDSM)
  488. {
  489. doPKISign(__lenResult, __result, pDSM, lenInputdata, inputdata);
  490. }
  491. else
  492. {
  493. throw makeStringException(-1, "Unable to create Digital Signature Manager");
  494. }
  495. }
  496. CRYPTOLIB_API bool CRYPTOLIB_CALL clPKIVerifySignature2(const char * pkalgorithm,
  497. const char * publickeyfile,
  498. size32_t lenPassPhrase,const void * passphrase,
  499. size32_t lenSignature,const void * signature,
  500. size32_t lenSigneddata,const void * signeddata)
  501. {
  502. verifyPKIAlgorithm(pkalgorithm);
  503. Owned<IDigitalSignatureManager> pDSM = g_DSMCache.getInstance(pkalgorithm, publickeyfile, nullptr, nullptr, nullptr, lenPassPhrase, passphrase, false, nullptr);
  504. if (pDSM)
  505. {
  506. StringBuffer sbSig(lenSignature, (const char *)signature);
  507. bool rc = pDSM->digiVerify(sbSig.str(), lenSigneddata, signeddata);
  508. return rc;
  509. }
  510. else
  511. {
  512. throw makeStringException(-1, "Unable to create Digital Signature Manager");
  513. }
  514. }
  515. CRYPTOLIB_API bool CRYPTOLIB_CALL clPKIVerifySignatureLFN2(ICodeContext * ctx,
  516. const char * pkalgorithm,
  517. const char * publickeyLFN,
  518. size32_t lenPassPhrase,const void * passphrase,
  519. size32_t lenSignature,const void * signature,
  520. size32_t lenSigneddata,const void * signeddata)
  521. {
  522. verifyPKIAlgorithm(pkalgorithm);
  523. IUserDescriptor * udesc = ctx->queryUserDescriptor();
  524. Owned<IDigitalSignatureManager> pDSM = g_DSMCache.getInstance(pkalgorithm, publickeyLFN, nullptr, nullptr, nullptr, lenPassPhrase, passphrase, true, udesc);
  525. if (pDSM)
  526. {
  527. StringBuffer sbSig(lenSignature, (const char *)signature);
  528. bool rc = pDSM->digiVerify(sbSig.str(), lenSigneddata, signeddata);
  529. return rc;
  530. }
  531. else
  532. {
  533. throw makeStringException(-1, "Unable to create Digital Signature Manager");
  534. }
  535. }
  536. CRYPTOLIB_API bool CRYPTOLIB_CALL clPKIVerifySignatureBuff2(const char * pkalgorithm,
  537. const char * publicKeyBuff,
  538. size32_t lenPassPhrase,const void * passphrase,
  539. size32_t lenSignature, const void * signature,
  540. size32_t lenSigneddata, const void * signeddata)
  541. {
  542. verifyPKIAlgorithm(pkalgorithm);
  543. Owned<IDigitalSignatureManager> pDSM = g_DSMCache.getInstance(pkalgorithm, nullptr, publicKeyBuff, nullptr, nullptr, lenPassPhrase, passphrase, false, nullptr);
  544. if (pDSM)
  545. {
  546. StringBuffer sbSig(lenSignature, (const char *)signature);
  547. bool rc = pDSM->digiVerify(sbSig.str(), lenSigneddata, signeddata);
  548. return rc;
  549. }
  550. else
  551. {
  552. throw makeStringException(-1, "Unable to create Digital Signature Manager");
  553. }
  554. }
  555. CRYPTOLIB_API void CRYPTOLIB_CALL clPKISign(size32_t & __lenResult,void * & __result,
  556. const char * pkalgorithm,
  557. const char * privatekeyfile,
  558. const char * passphrase,
  559. size32_t lenInputdata,const void * inputdata)
  560. {
  561. return clPKISign2(__lenResult,__result, pkalgorithm, privatekeyfile, passphrase ? strlen(passphrase) : 0, (const void *)passphrase, lenInputdata, inputdata);
  562. }
  563. CRYPTOLIB_API void CRYPTOLIB_CALL clPKISignLFN(ICodeContext * ctx,
  564. size32_t & __lenResult,void * & __result,
  565. const char * pkalgorithm,
  566. const char * privatekeyLFN,
  567. const char * passphrase,
  568. size32_t lenInputdata,const void * inputdata)
  569. {
  570. return clPKISignLFN2(ctx, __lenResult,__result, pkalgorithm, privatekeyLFN, passphrase ? strlen(passphrase) : 0, (const void *)passphrase, lenInputdata, inputdata);
  571. }
  572. CRYPTOLIB_API void CRYPTOLIB_CALL clPKISignBuff(size32_t & __lenResult, void * & __result,
  573. const char * pkalgorithm,
  574. const char * privatekeybuff,
  575. const char * passphrase,
  576. size32_t lenInputdata, const void * inputdata)
  577. {
  578. return clPKISignBuff2(__lenResult,__result, pkalgorithm, privatekeybuff, passphrase ? strlen(passphrase) : 0, (const void *)passphrase, lenInputdata, inputdata);
  579. }
  580. CRYPTOLIB_API bool CRYPTOLIB_CALL clPKIVerifySignature(const char * pkalgorithm,
  581. const char * publickeyfile,
  582. const char * passphrase,
  583. size32_t lenSignature,const void * signature,
  584. size32_t lenSigneddata,const void * signeddata)
  585. {
  586. return clPKIVerifySignature2(pkalgorithm, publickeyfile, passphrase ? strlen(passphrase) : 0, (const void *)passphrase, lenSignature,signature, lenSigneddata, signeddata);
  587. }
  588. CRYPTOLIB_API bool CRYPTOLIB_CALL clPKIVerifySignatureLFN(ICodeContext * ctx,
  589. const char * pkalgorithm,
  590. const char * publickeyLFN,
  591. const char * passphrase,
  592. size32_t lenSignature,const void * signature,
  593. size32_t lenSigneddata,const void * signeddata)
  594. {
  595. return clPKIVerifySignatureLFN2(ctx, pkalgorithm, publickeyLFN, passphrase ? strlen(passphrase) : 0, (const void *)passphrase, lenSignature,signature, lenSigneddata, signeddata);
  596. }
  597. CRYPTOLIB_API bool CRYPTOLIB_CALL clPKIVerifySignatureBuff(const char * pkalgorithm,
  598. const char * publicKeyBuff,
  599. const char * passphrase,
  600. size32_t lenSignature, const void * signature,
  601. size32_t lenSigneddata, const void * signeddata)
  602. {
  603. return clPKIVerifySignatureBuff2(pkalgorithm, publicKeyBuff, passphrase ? strlen(passphrase) : 0, (const void *)passphrase, lenSignature,signature, lenSigneddata, signeddata);
  604. }
  605. //-----------------------------------------------------------------
  606. // Simple cache for loaded keys
  607. //
  608. //-----------------------------------------------------------------
  609. #ifdef _USE_HASHMAP
  610. class CKeyCache : public CInterface
  611. {
  612. private:
  613. typedef std::unordered_map<string, Owned<CLoadedKey>> KeyCache;
  614. KeyCache keyCache;
  615. public:
  616. CLoadedKey * getInstance(bool isPublic, const char * keyFS, const char * keyBuff, const char * passphrase)
  617. {
  618. if (isEmptyString(keyFS) && isEmptyString(keyBuff))
  619. throw makeStringExceptionV(-1, "Must specify a key filename or provide a key buffer");
  620. VStringBuffer searchKey("%s_%s_%s", isEmptyString(keyFS) ? "" : keyFS, isEmptyString(keyBuff) ? "" : keyBuff, isEmptyString(passphrase) ? "" : passphrase);
  621. KeyCache::iterator it = keyCache.find(searchKey.str());
  622. CLoadedKey * ret = nullptr;
  623. if (it != keyCache.end())//exists in cache?
  624. {
  625. ret = (*it).second;
  626. }
  627. else
  628. {
  629. if (!isEmptyString(keyFS))
  630. {
  631. //Create CLoadedKey from filespec
  632. if (isPublic)
  633. ret = loadPublicKeyFromFile(keyFS);
  634. else
  635. ret = loadPrivateKeyFromFile(keyFS, passphrase);
  636. }
  637. else
  638. {
  639. //Create CLoadedKey from key contents
  640. if (isPublic)
  641. ret = loadPublicKeyFromMemory(keyBuff);
  642. else
  643. ret = loadPrivateKeyFromMemory(keyBuff, passphrase);
  644. }
  645. keyCache.emplace(searchKey.str(), ret);
  646. }
  647. return LINK(ret);
  648. }
  649. };
  650. #else
  651. class CKeyCache : public CInterface
  652. {
  653. private:
  654. bool m_isPublic = false;
  655. StringAttr m_keyFS;
  656. StringAttr m_keyBuff;
  657. MemoryBuffer m_passphrase;
  658. Owned<CLoadedKey> m_loadedKey;
  659. //String compare that treats null ptr and ptr to empty string as matching
  660. inline bool sameString(const char * left, const char * right)
  661. {
  662. if (isEmptyString(left))
  663. return isEmptyString(right);
  664. else if (isEmptyString(right))
  665. return false;
  666. return strcmp(left, right) == 0;
  667. }
  668. //compare buffers
  669. inline bool sameBuff(size32_t lenLeft, const void * left, size32_t lenRight, const void * right)
  670. {
  671. if (lenLeft != lenRight)
  672. return false;
  673. if (lenLeft == 0)
  674. return true;
  675. return memcmp(left, right, lenLeft) == 0;
  676. }
  677. public:
  678. CLoadedKey * getInstance(bool isPublic, const char * keyFS, const char * keyBuff, size32_t lenPassphrase, const void * passphrase, bool isLFN, IUserDescriptor * user)
  679. {
  680. if (!m_loadedKey ||
  681. isPublic != m_isPublic ||
  682. !sameBuff(lenPassphrase, passphrase, m_passphrase.length(), m_passphrase.bufferBase()) ||
  683. !sameString(keyFS, m_keyFS.str()) ||
  684. !sameString(keyBuff, m_keyBuff.str()))
  685. {
  686. CLoadedKey *newKey;
  687. if (!isEmptyString(keyFS))
  688. {
  689. if (isLFN)
  690. {
  691. StringBuffer sb;
  692. loadLFS(keyFS, user, sb);//read key file into StringBuffer
  693. if (isPublic)
  694. newKey = loadPublicKeyFromMemory(sb.str());
  695. else
  696. newKey = loadPrivateKeyFromMemory(sb.str(), lenPassphrase, passphrase);
  697. }
  698. else if (isPublic)
  699. newKey = loadPublicKeyFromFile(keyFS);
  700. else
  701. newKey = loadPrivateKeyFromFile(keyFS, lenPassphrase, passphrase);
  702. }
  703. else if (!isEmptyString(keyBuff))
  704. {
  705. //Create CLoadedKey from key contents
  706. if (isPublic)
  707. newKey = loadPublicKeyFromMemory(keyBuff);
  708. else
  709. newKey = loadPrivateKeyFromMemory(keyBuff, lenPassphrase, passphrase);
  710. }
  711. else
  712. throw makeStringException(-1, "Must specify a key filename or provide a key buffer");
  713. m_loadedKey.setown(newKey);//releases previous ptr
  714. m_isPublic = isPublic;
  715. m_keyFS.set(keyFS);
  716. m_keyBuff.set(keyBuff);
  717. m_passphrase.clear().append(lenPassphrase, passphrase);
  718. }
  719. return LINK(m_loadedKey);
  720. }
  721. };
  722. #endif//_USE_HASHMAP
  723. //----------------------------------------------------------------------------
  724. // TLS storage of Key cache
  725. //----------------------------------------------------------------------------
  726. static thread_local CKeyCache *pKC = nullptr;
  727. static bool clearupKeyCache(bool isPooled)
  728. {
  729. delete pKC;
  730. pKC = nullptr;
  731. return false;
  732. }
  733. static CLoadedKey * getCachedKey(bool isPublic, const char * keyFS, const char * keyBuff, size32_t lenPassphrase, const void * passphrase, bool isLFN, IUserDescriptor * udesc)
  734. {
  735. if (!pKC)
  736. {
  737. pKC = new CKeyCache();
  738. addThreadTermFunc(clearupKeyCache);
  739. }
  740. return pKC->getInstance(isPublic, keyFS, keyBuff, lenPassphrase, passphrase, isLFN, udesc);
  741. }
  742. //------------------------------------
  743. //Encryption helper
  744. //------------------------------------
  745. static void doPKIEncrypt(size32_t & __lenResult,void * & __result,
  746. CLoadedKey * publicKey,
  747. size32_t lenInputdata,const void * inputdata)
  748. {
  749. MemoryBuffer pkeMb;
  750. __lenResult = publicKeyEncrypt(pkeMb, lenInputdata, inputdata, *publicKey);
  751. if (__lenResult)
  752. {
  753. __result = CTXMALLOC(parentCtx, __lenResult);
  754. memcpy(__result, pkeMb.bytes(), __lenResult);
  755. }
  756. }
  757. //------------------------------------
  758. //Decryption helper
  759. //------------------------------------
  760. static void doPKIDecrypt(size32_t & __lenResult,void * & __result,
  761. CLoadedKey * privateKey,
  762. size32_t lenInputdata,const void * inputdata)
  763. {
  764. MemoryBuffer pkeMb;
  765. __lenResult = privateKeyDecrypt(pkeMb, lenInputdata, inputdata, *privateKey);
  766. if (__lenResult)
  767. {
  768. __result = CTXMALLOC(parentCtx, __lenResult);
  769. memcpy(__result, pkeMb.bytes(), __lenResult);
  770. }
  771. }
  772. //encryption functions that take filespecs of key files
  773. CRYPTOLIB_API void CRYPTOLIB_CALL clPKIEncrypt2(size32_t & __lenResult,void * & __result,
  774. const char * pkalgorithm,
  775. const char * publickeyfile,
  776. size32_t lenPassPhrase,const void * passphrase,
  777. size32_t lenInputdata,const void * inputdata)
  778. {
  779. verifyPKIAlgorithm(pkalgorithm);
  780. Owned<CLoadedKey> publicKey = getCachedKey(true, publickeyfile, nullptr, lenPassPhrase, passphrase, false, nullptr);
  781. doPKIEncrypt(__lenResult, __result, publicKey, lenInputdata, inputdata);
  782. }
  783. CRYPTOLIB_API void CRYPTOLIB_CALL clPKIDecrypt2(size32_t & __lenResult,void * & __result,
  784. const char * pkalgorithm,
  785. const char * privatekeyfile,
  786. size32_t lenPassPhrase,const void * passphrase,
  787. size32_t lenEncrypteddata,const void * encrypteddata)
  788. {
  789. verifyPKIAlgorithm(pkalgorithm);
  790. Owned<CLoadedKey> privateKey = getCachedKey(false, privatekeyfile, nullptr, lenPassPhrase, passphrase, false, nullptr);
  791. doPKIDecrypt(__lenResult, __result, privateKey, lenEncrypteddata, encrypteddata);
  792. }
  793. CRYPTOLIB_API void CRYPTOLIB_CALL clPKIEncryptLFN2(ICodeContext * ctx,
  794. size32_t & __lenResult,void * & __result,
  795. const char * pkalgorithm,
  796. const char * publickeyLFN,
  797. size32_t lenPassPhrase,const void * passphrase,
  798. size32_t lenInputdata,const void * inputdata)
  799. {
  800. verifyPKIAlgorithm(pkalgorithm);
  801. IUserDescriptor * udesc = ctx->queryUserDescriptor();
  802. Owned<CLoadedKey> publicKey = getCachedKey(true, publickeyLFN, nullptr, lenPassPhrase, passphrase, true, udesc);
  803. doPKIEncrypt(__lenResult, __result, publicKey, lenInputdata, inputdata);
  804. }
  805. CRYPTOLIB_API void CRYPTOLIB_CALL clPKIDecryptLFN2(ICodeContext * ctx,
  806. size32_t & __lenResult,void * & __result,
  807. const char * pkalgorithm,
  808. const char * privatekeyLFN,
  809. size32_t lenPassPhrase,const void * passphrase,
  810. size32_t lenEncrypteddata,const void * encrypteddata)
  811. {
  812. verifyPKIAlgorithm(pkalgorithm);
  813. IUserDescriptor * udesc = ctx->queryUserDescriptor();
  814. Owned<CLoadedKey> privateKey = getCachedKey(false, privatekeyLFN, nullptr, lenPassPhrase, passphrase, true, udesc);
  815. doPKIDecrypt(__lenResult, __result, privateKey, lenEncrypteddata, encrypteddata);
  816. }
  817. //encryption functions that take keys in a buffer
  818. CRYPTOLIB_API void CRYPTOLIB_CALL clPKIEncryptBuff2(size32_t & __lenResult,void * & __result,
  819. const char * pkalgorithm,
  820. const char * publickeybuff,
  821. size32_t lenPassPhrase,const void * passphrase,
  822. size32_t lenInputdata,const void * inputdata)
  823. {
  824. verifyPKIAlgorithm(pkalgorithm);
  825. Owned<CLoadedKey> publicKey = getCachedKey(true, nullptr, publickeybuff, lenPassPhrase, passphrase, false, nullptr);
  826. doPKIEncrypt(__lenResult, __result, publicKey, lenInputdata, inputdata);
  827. }
  828. CRYPTOLIB_API void CRYPTOLIB_CALL clPKIDecryptBuff2(size32_t & __lenResult,void * & __result,
  829. const char * pkalgorithm,
  830. const char * privatekeybuff,
  831. size32_t lenPassPhrase,const void * passphrase,
  832. size32_t lenEncrypteddata,const void * encrypteddata)
  833. {
  834. verifyPKIAlgorithm(pkalgorithm);
  835. Owned<CLoadedKey> privateKey = getCachedKey(false, nullptr, privatekeybuff, lenPassPhrase, passphrase, false, nullptr);
  836. doPKIDecrypt(__lenResult, __result, privateKey, lenEncrypteddata, encrypteddata);
  837. }
  838. CRYPTOLIB_API void CRYPTOLIB_CALL clPKIEncrypt(size32_t & __lenResult,void * & __result,
  839. const char * pkalgorithm,
  840. const char * publickeyfile,
  841. const char * passphrase,
  842. size32_t lenInputdata,const void * inputdata)
  843. {
  844. return clPKIEncrypt2(__lenResult, __result, pkalgorithm, publickeyfile, passphrase ? strlen(passphrase) : 0, (const void *)passphrase, lenInputdata, inputdata);
  845. }
  846. CRYPTOLIB_API void CRYPTOLIB_CALL clPKIDecrypt(size32_t & __lenResult,void * & __result,
  847. const char * pkalgorithm,
  848. const char * privatekeyfile,
  849. const char * passphrase,
  850. size32_t lenEncrypteddata,const void * encrypteddata)
  851. {
  852. return clPKIDecrypt2(__lenResult, __result, pkalgorithm, privatekeyfile, passphrase ? strlen(passphrase) : 0, (const void *)passphrase, lenEncrypteddata, encrypteddata);
  853. }
  854. CRYPTOLIB_API void CRYPTOLIB_CALL clPKIEncryptLFN(ICodeContext * ctx,
  855. size32_t & __lenResult,void * & __result,
  856. const char * pkalgorithm,
  857. const char * publickeyLFN,
  858. const char * passphrase,
  859. size32_t lenInputdata,const void * inputdata)
  860. {
  861. return clPKIEncryptLFN2(ctx, __lenResult, __result, pkalgorithm, publickeyLFN, passphrase ? strlen(passphrase) : 0, (const void *)passphrase, lenInputdata, inputdata);
  862. }
  863. CRYPTOLIB_API void CRYPTOLIB_CALL clPKIDecryptLFN(ICodeContext * ctx,
  864. size32_t & __lenResult,void * & __result,
  865. const char * pkalgorithm,
  866. const char * privatekeyLFN,
  867. const char * passphrase,
  868. size32_t lenEncrypteddata,const void * encrypteddata)
  869. {
  870. return clPKIDecryptLFN2(ctx, __lenResult, __result, pkalgorithm, privatekeyLFN, passphrase ? strlen(passphrase) : 0, (const void *)passphrase, lenEncrypteddata, encrypteddata);
  871. }
  872. //encryption functions that take keys in a buffer
  873. CRYPTOLIB_API void CRYPTOLIB_CALL clPKIEncryptBuff(size32_t & __lenResult,void * & __result,
  874. const char * pkalgorithm,
  875. const char * publickeybuff,
  876. const char * passphrase,
  877. size32_t lenInputdata,const void * inputdata)
  878. {
  879. return clPKIEncryptBuff2(__lenResult, __result, pkalgorithm, publickeybuff, passphrase ? strlen(passphrase) : 0, (const void *)passphrase, lenInputdata, inputdata);
  880. }
  881. CRYPTOLIB_API void CRYPTOLIB_CALL clPKIDecryptBuff(size32_t & __lenResult,void * & __result,
  882. const char * pkalgorithm,
  883. const char * privatekeybuff,
  884. const char * passphrase,
  885. size32_t lenEncrypteddata,const void * encrypteddata)
  886. {
  887. return clPKIDecryptBuff2(__lenResult, __result, pkalgorithm, privatekeybuff, passphrase ? strlen(passphrase) : 0, (const void *)passphrase, lenEncrypteddata, encrypteddata);
  888. }