pbe.c 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592
  1. /** BEGIN COPYRIGHT BLOCK
  2. * Copyright (C) 2001 Sun Microsystems, Inc. Used by permission.
  3. * Copyright (C) 2015 Red Hat, Inc.
  4. * All rights reserved.
  5. *
  6. * License: GPL (version 3 or any later version).
  7. * See LICENSE for details.
  8. * END COPYRIGHT BLOCK **/
  9. #ifdef HAVE_CONFIG_H
  10. # include <config.h>
  11. #endif
  12. #include <string.h>
  13. #include <stdio.h>
  14. #include <ldap.h>
  15. #include <nspr.h>
  16. #include <nss.h>
  17. #include <secmod.h>
  18. /*
  19. #include <secasn1.h>
  20. #include <secpkcs7.h>
  21. */
  22. #include <key.h>
  23. #include <certdb.h>
  24. #include <cert.h>
  25. #include <svrcore.h>
  26. #include <secmodt.h>
  27. #include <prtypes.h>
  28. #include <seccomon.h>
  29. #include <pk11func.h>
  30. #define NEED_TOK_PBE /* see slap.h - defines tokPBE and ptokPBE */
  31. #include "rever.h"
  32. #include <slap.h>
  33. #include "slapi-plugin.h"
  34. #include <uuid.h>
  35. #include <plbase64.h>
  36. struct pk11MechItem
  37. {
  38. CK_MECHANISM_TYPE type;
  39. const char *mechName;
  40. };
  41. static const struct pk11MechItem DESmech = { CKM_DES_CBC, "DES CBC encryption" };
  42. static const struct pk11MechItem AESmech = { CKM_AES_CBC, "AES CBC encryption" };
  43. static Slapi_Mutex *pbe_lock = NULL;
  44. struct pk11ContextStore
  45. {
  46. PK11SlotInfo *slot;
  47. const struct pk11MechItem *mech;
  48. PK11SymKey *key;
  49. SECItem *params;
  50. int length;
  51. unsigned char *crypt;
  52. char *algid_base64;
  53. };
  54. /*
  55. * der_algid converting functions:
  56. *
  57. * SECStatus ATOB_ConvertAsciiToItem(SECItem *binary_item, const char *ascii);
  58. * char * BTOA_ConvertItemToAscii(SECItem *binary_item);
  59. *
  60. */
  61. static int encode_path(char *inPlain, char **outCipher, char *path, int mech);
  62. static int decode_path(char *inCipher, char **outPlain, char *path, int mech, char *algid);
  63. static SVRCOREError genKey(struct pk11ContextStore **out, const char *token, char *path, int mech, PRArenaPool *arena, char *algid);
  64. static SVRCOREError cryptPassword(struct pk11ContextStore *store, char * clear, unsigned char **out);
  65. static SVRCOREError decryptPassword(struct pk11ContextStore *store, unsigned char *cipher, char **out, int len);
  66. static void freePBE(struct pk11ContextStore *store);
  67. void
  68. init_pbe_plugin()
  69. {
  70. if(!pbe_lock){
  71. pbe_lock = slapi_new_mutex();
  72. }
  73. }
  74. int
  75. encode(char *inPlain, char **outCipher, int mech)
  76. {
  77. return encode_path(inPlain, outCipher, NULL, mech);
  78. }
  79. static int
  80. encode_path(char *inPlain, char **outCipher, char *path, int mech)
  81. {
  82. struct pk11ContextStore *context = NULL;
  83. PRArenaPool *arena = NULL;
  84. unsigned char *cipher = NULL;
  85. char *tmp = NULL;
  86. char *base = NULL;
  87. int len = 0;
  88. int err;
  89. *outCipher = NULL;
  90. err = 1;
  91. if ( genKey(&context, tokPBE, path, mech, arena, NULL) == SVRCORE_Success ){
  92. /* Try an encryption */
  93. if ( cryptPassword(context, inPlain, &cipher) == SVRCORE_Success ){
  94. base = BTOA_DataToAscii(cipher, context->length);
  95. if ( base != NULL ){
  96. const char *scheme;
  97. if (mech == AES_MECH){
  98. scheme = AES_REVER_SCHEME_NAME;
  99. len = 3 + strlen(scheme)+ strlen(context->algid_base64) + strlen(base) + 1;
  100. if( (tmp = slapi_ch_malloc( len )) ){
  101. /*
  102. * {AES-<BASE64_ALG_ID>}<ENCODED PASSWORD>
  103. */
  104. sprintf( tmp, "%c%s-%s%c%s", PWD_HASH_PREFIX_START, scheme,
  105. context->algid_base64,PWD_HASH_PREFIX_END, base);
  106. }
  107. } else {
  108. /* Old school DES */
  109. scheme = DES_REVER_SCHEME_NAME;
  110. if((tmp = slapi_ch_malloc( 3 + strlen(scheme) + strlen(base)))){
  111. sprintf( tmp, "%c%s%c%s", PWD_HASH_PREFIX_START, scheme,
  112. PWD_HASH_PREFIX_END, base);
  113. }
  114. }
  115. if ( tmp != NULL ){
  116. *outCipher = tmp;
  117. tmp = NULL;
  118. err = 0;
  119. }
  120. PORT_Free(base);
  121. }
  122. }
  123. }
  124. freePBE(context);
  125. return(err);
  126. }
  127. int
  128. decode(char *inCipher, char **outPlain, int mech, char *algid)
  129. {
  130. return decode_path(inCipher, outPlain, NULL, mech, algid);
  131. }
  132. static int
  133. decode_path(char *inCipher, char **outPlain, char *path, int mech, char *algid)
  134. {
  135. struct pk11ContextStore *context = NULL;
  136. PRArenaPool *arena = NULL;
  137. unsigned char *base = NULL;
  138. char *plain = NULL;
  139. int err;
  140. int len = 0;
  141. *outPlain = NULL;
  142. err = 1;
  143. if ( genKey(&context, tokPBE, path, mech, arena, algid) == SVRCORE_Success ){
  144. /* it seems that there is memory leak in that function: bug 400170 */
  145. base = ATOB_AsciiToData(inCipher, (unsigned int*)&len);
  146. if ( base != NULL ){
  147. if ( decryptPassword(context, base, &plain, len) == SVRCORE_Success ){
  148. *outPlain = plain;
  149. err = 0;
  150. }
  151. }
  152. }
  153. slapi_ch_free_string(&algid);
  154. PORT_Free(base);
  155. PORT_FreeArena(arena, PR_TRUE);
  156. freePBE(context);
  157. return(err);
  158. }
  159. static void
  160. freePBE(struct pk11ContextStore *store)
  161. {
  162. if (store){
  163. if (store->slot)
  164. slapd_pk11_freeSlot(store->slot);
  165. if (store->key)
  166. slapd_pk11_freeSymKey(store->key);
  167. if (store->params)
  168. SECITEM_FreeItem(store->params, PR_TRUE);
  169. slapi_ch_free((void **)&store->crypt);
  170. slapi_ch_free_string(&store->algid_base64);
  171. slapi_ch_free((void **)&store);
  172. }
  173. }
  174. static SVRCOREError
  175. genKey(struct pk11ContextStore **out, const char *token, char *path, int mech, PRArenaPool *arena, char *alg)
  176. {
  177. SVRCOREError err = SVRCORE_Success;
  178. struct pk11ContextStore *store = NULL;
  179. SECItem *pwitem = NULL;
  180. SECItem *result = NULL;
  181. SECItem *salt = NULL;
  182. SECItem der_algid;
  183. SECAlgorithmID *algid = NULL;
  184. SECOidTag algoid;
  185. CK_MECHANISM pbeMech;
  186. CK_MECHANISM cryptoMech;
  187. SECAlgorithmID my_algid;
  188. char *configdir = NULL;
  189. char *der_ascii = NULL;
  190. char *iv = NULL;
  191. int free_it = 0;
  192. arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
  193. store = (struct pk11ContextStore*)slapi_ch_calloc(1, sizeof(*store));
  194. if (store == NULL){
  195. err = SVRCORE_NoMemory_Error;
  196. goto done;
  197. }
  198. *out = store;
  199. /* Use the tokenName to find a PKCS11 slot */
  200. store->slot = slapd_pk11_findSlotByName((char *)token);
  201. if (store->slot == NULL){
  202. err = SVRCORE_NoSuchToken_Error;
  203. goto done;
  204. }
  205. /* Generate a key and parameters to do the encryption */
  206. if(mech == AES_MECH){
  207. store->mech = &AESmech;
  208. algoid = SEC_OID_AES_256_CBC;
  209. } else {
  210. store->mech = &DESmech;
  211. algoid = SEC_OID_PKCS5_PBE_WITH_MD2_AND_DES_CBC;
  212. }
  213. /* Generate a unique id, used as salt for the key generation */
  214. if ( path == NULL ){
  215. configdir = config_get_configdir();
  216. if ( configdir == NULL ){
  217. err = SVRCORE_System_Error;
  218. goto done;
  219. }
  220. } else {
  221. configdir = slapi_ch_strdup(path);
  222. }
  223. if ( slapi_uniqueIDGenerateFromNameString (&iv, NULL, configdir, strlen(configdir)) != UID_SUCCESS ){
  224. err = SVRCORE_System_Error;
  225. goto done;
  226. }
  227. pwitem = (SECItem *) PORT_Alloc(sizeof(SECItem));
  228. if (pwitem == NULL){
  229. err = SVRCORE_NoMemory_Error;
  230. goto done;
  231. }
  232. pwitem->type = siBuffer;
  233. pwitem->data = (unsigned char *)PORT_Alloc(strlen(iv)+1);
  234. if (pwitem->data == NULL){
  235. err = SVRCORE_NoMemory_Error;
  236. goto done;
  237. }
  238. strcpy((char*)pwitem->data, iv);
  239. pwitem->len = strlen(iv) + 1;
  240. salt = (SECItem *) PORT_Alloc(sizeof(SECItem));
  241. if (salt == NULL){
  242. err = SVRCORE_NoMemory_Error;
  243. goto done;
  244. }
  245. salt->type = siBuffer;
  246. salt->data = (unsigned char *)PORT_Alloc(strlen(iv)+1);
  247. if ( salt->data == NULL ){
  248. err = SVRCORE_NoMemory_Error;
  249. goto done;
  250. }
  251. strcpy((char*)salt->data, iv);
  252. salt->len = strlen(iv) + 1;
  253. PORT_Memset(&der_algid, 0, sizeof(der_algid));
  254. if(!alg){
  255. /*
  256. * This is DES, or we are encoding AES - the process is the same.
  257. */
  258. algid = slapd_pk11_createPBEAlgorithmID(algoid, 2, salt);
  259. free_it = 1; /* we need to free this algid */
  260. /*
  261. * The following is only need for AES - we need to store
  262. * algid for future decodings(unlike with DES). So convert
  263. * algid to its DER encoding. Then convert the DER to ascii,
  264. * and finally convert the DER ascii to base64 so we can store
  265. * it in the cipher prefix.
  266. */
  267. SEC_ASN1EncodeItem(arena, &der_algid, algid, SEC_ASN1_GET(SECOID_AlgorithmIDTemplate));
  268. der_ascii = BTOA_ConvertItemToAscii(&der_algid);
  269. store->algid_base64 = PL_Base64Encode(der_ascii,strlen(der_ascii), NULL);
  270. slapi_ch_free_string(&der_ascii);
  271. } else {
  272. /*
  273. * We are decoding AES - use the supplied algid
  274. */
  275. PORT_Memset(&my_algid, 0, sizeof(my_algid));
  276. /* Decode the base64 der encoding */
  277. der_ascii = PL_Base64Decode(alg, strlen(alg), NULL);
  278. /* convert the der ascii to the SEC item */
  279. ATOB_ConvertAsciiToItem(&der_algid, der_ascii);
  280. SEC_ASN1DecodeItem(arena, &my_algid, SEC_ASN1_GET(SECOID_AlgorithmIDTemplate), &der_algid);
  281. SECITEM_FreeItem(&der_algid, PR_FALSE);
  282. algid = &my_algid;
  283. slapi_ch_free_string(&der_ascii);
  284. }
  285. slapi_lock_mutex(pbe_lock);
  286. store->key = slapd_pk11_pbeKeyGen(store->slot, algid, pwitem, 0, 0);
  287. if (store->key == 0){
  288. slapi_unlock_mutex(pbe_lock);
  289. err = SVRCORE_System_Error;
  290. goto done;
  291. }
  292. slapi_unlock_mutex(pbe_lock);
  293. if(mech == AES_MECH)
  294. {
  295. cryptoMech.mechanism = PK11_GetPBECryptoMechanism(algid, &store->params, pwitem);
  296. if (cryptoMech.mechanism == CKM_INVALID_MECHANISM) {
  297. err = SVRCORE_System_Error;
  298. goto done;
  299. }
  300. }
  301. else
  302. {
  303. /* DES */
  304. pbeMech.mechanism = slapd_pk11_algtagToMechanism(algoid);
  305. result = slapd_pk11_paramFromAlgid(algid);
  306. if(result){
  307. pbeMech.pParameter = result->data;
  308. pbeMech.ulParameterLen = result->len;
  309. }
  310. if(slapd_pk11_mapPBEMechanismToCryptoMechanism(&pbeMech, &cryptoMech, pwitem,
  311. PR_FALSE) != CKR_OK){
  312. err = SVRCORE_System_Error;
  313. goto done;
  314. }
  315. store->params = (SECItem *) PORT_Alloc(sizeof(SECItem));
  316. if (store->params == NULL){
  317. err = SVRCORE_System_Error;
  318. goto done;
  319. }
  320. store->params->type = store->mech->type;
  321. store->params->data = (unsigned char *)PORT_Alloc(cryptoMech.ulParameterLen);
  322. if (store->params->data == NULL){
  323. err = SVRCORE_System_Error;
  324. goto done;
  325. }
  326. memcpy(store->params->data, (unsigned char *)cryptoMech.pParameter, cryptoMech.ulParameterLen);
  327. store->params->len = cryptoMech.ulParameterLen;
  328. PORT_Free(cryptoMech.pParameter);
  329. }
  330. done:
  331. SECITEM_FreeItem(result, PR_TRUE);
  332. SECITEM_FreeItem(pwitem, PR_TRUE);
  333. SECITEM_FreeItem(salt, PR_TRUE);
  334. if(free_it){
  335. secoid_destroyAlgorithmID(algid, PR_TRUE);
  336. }
  337. slapi_ch_free_string(&configdir);
  338. slapi_ch_free_string(&iv);
  339. if (arena) {
  340. PORT_FreeArena(arena, PR_TRUE);
  341. }
  342. return (err);
  343. }
  344. static SVRCOREError
  345. decryptPassword(struct pk11ContextStore *store, unsigned char *cipher, char **out, int len)
  346. {
  347. SVRCOREError err = SVRCORE_Success;
  348. unsigned char *plain = NULL;
  349. unsigned char *cipher_with_padding = NULL;
  350. SECStatus rv;
  351. PK11Context *ctx = NULL;
  352. int outLen = 0;
  353. int blocksize = 0;
  354. blocksize = slapd_pk11_getBlockSize(store->mech->type, 0);
  355. store->length = len;
  356. /*
  357. * store->length is the max. length of the returned clear text -
  358. * must be >= length of crypted bytes - also must be a multiple
  359. * of blocksize
  360. */
  361. if (blocksize != 0){
  362. store->length += blocksize - (store->length % blocksize);
  363. }
  364. /* plain will hold the returned clear text */
  365. plain = (unsigned char *)slapi_ch_calloc(sizeof(unsigned char),
  366. store->length+1);
  367. if (!plain){
  368. err = SVRCORE_NoMemory_Error;
  369. goto done;
  370. }
  371. /*
  372. * create a buffer holding the original cipher bytes, padded with
  373. * zeros to a multiple of blocksize - do not need +1 since buffer is not
  374. * a string
  375. */
  376. cipher_with_padding = (unsigned char *)slapi_ch_calloc(sizeof(unsigned char),
  377. store->length);
  378. if (!cipher_with_padding){
  379. err = SVRCORE_NoMemory_Error;
  380. goto done;
  381. }
  382. memcpy(cipher_with_padding, cipher, len);
  383. ctx = slapd_pk11_createContextBySymKey(store->mech->type, CKA_DECRYPT,
  384. store->key, store->params);
  385. if (!ctx) {
  386. err = SVRCORE_System_Error;
  387. goto done;
  388. }
  389. /*
  390. * Warning - there is a purify UMR in the NSS des code - you may see it when the
  391. * password is not a multiple of 8 bytes long
  392. */
  393. rv = slapd_pk11_cipherOp(ctx, plain, &outLen, store->length,
  394. cipher_with_padding, store->length);
  395. if (rv){
  396. err = SVRCORE_System_Error;
  397. }
  398. rv = slapd_pk11_finalize(ctx);
  399. /*
  400. * We must do the finalize, but we only want to set the err return
  401. * code if it is not already set
  402. */
  403. if (rv && (SVRCORE_Success == err))
  404. err = SVRCORE_System_Error;
  405. done:
  406. if (err == SVRCORE_Success){
  407. *out = (char *)plain;
  408. } else {
  409. slapi_ch_free((void **)&plain);
  410. }
  411. slapi_ch_free((void **)&cipher_with_padding);
  412. /* We should free the PK11Context... Something like : */
  413. if (ctx){
  414. slapd_pk11_destroyContext(ctx, PR_TRUE);
  415. }
  416. return err;
  417. }
  418. static SVRCOREError
  419. cryptPassword(struct pk11ContextStore *store, char * clear, unsigned char **out)
  420. {
  421. SVRCOREError err = SVRCORE_Success;
  422. SECStatus rv;
  423. PK11Context *ctx = NULL;
  424. unsigned char *clear_with_padding = NULL; /* clear with padding up to blocksize */
  425. int blocksize = 0;
  426. int outLen = 0;
  427. blocksize = slapd_pk11_getBlockSize(store->mech->type, 0);
  428. store->length = strlen(clear);
  429. /*
  430. * The size of the clear text buffer passed to the encryption functions
  431. * must be a multiple of blocksize (usually 8 bytes) - we allocate a buffer
  432. * of this size, copy the clear text password into it, and pad the rest with
  433. * zeros.
  434. */
  435. if (blocksize != 0){
  436. store->length += blocksize - (store->length % blocksize);
  437. }
  438. /*
  439. * store->crypt will hold the crypted password - it must be >= clear length
  440. * store->crypt is freed in NSS; let's not use slapi_ch_calloc
  441. */
  442. store->crypt = (unsigned char *)calloc(sizeof(unsigned char),
  443. store->length+1);
  444. if (!store->crypt) {
  445. err = SVRCORE_NoMemory_Error;
  446. goto done;
  447. }
  448. /* Create a buffer big enough to hold the clear text password and padding */
  449. clear_with_padding = (unsigned char *)slapi_ch_calloc(sizeof(unsigned char),
  450. store->length+1);
  451. if (!clear_with_padding){
  452. err = SVRCORE_NoMemory_Error;
  453. goto done;
  454. }
  455. /*
  456. * Copy the clear text password into the buffer - the calloc insures the
  457. * remainder is zero padded .
  458. */
  459. strcpy((char *)clear_with_padding, clear);
  460. ctx = slapd_pk11_createContextBySymKey(store->mech->type, CKA_ENCRYPT,
  461. store->key, store->params);
  462. if (!ctx) {
  463. err = SVRCORE_System_Error;
  464. goto done;
  465. }
  466. rv = slapd_pk11_cipherOp(ctx, store->crypt, &outLen, store->length,
  467. clear_with_padding, store->length);
  468. if (rv) {
  469. err = SVRCORE_System_Error;
  470. }
  471. rv = slapd_pk11_finalize(ctx);
  472. /*
  473. * We must do the finalize, but we only want to set the err return
  474. * code if it is not already set
  475. */
  476. if (rv && (SVRCORE_Success == err)){
  477. err = SVRCORE_System_Error;
  478. }
  479. done:
  480. if (err == SVRCORE_Success){
  481. *out = store->crypt;
  482. }
  483. slapi_ch_free((void **)&clear_with_padding);
  484. /* We should free the PK11Context... Something like : */
  485. if (ctx){
  486. slapd_pk11_destroyContext(ctx, PR_TRUE);
  487. }
  488. return err;
  489. }
  490. /*
  491. * The UUID name based generator was broken on x86 platforms. We use
  492. * this to generate the password encryption key. During migration,
  493. * we have to fix this so we can use the fixed generator. The env.
  494. * var USE_BROKEN_UUID tells the uuid generator to use the old
  495. * broken method to create the UUID. That will allow us to decrypt
  496. * the password to the correct clear text, then we can turn off
  497. * the broken method and use the fixed method to encrypt the
  498. * password.
  499. */
  500. char *
  501. migrateCredentials(char *oldpath, char *newpath, char *oldcred)
  502. {
  503. static char *useBrokenUUID = "USE_BROKEN_UUID=1";
  504. static char *disableBrokenUUID = "USE_BROKEN_UUID=0";
  505. char *plain = NULL;
  506. char *cipher = NULL;
  507. init_pbe_plugin();
  508. slapd_pk11_configurePKCS11(NULL, NULL, tokPBE, ptokPBE, NULL, NULL, NULL, NULL, 0, 0 );
  509. NSS_NoDB_Init(NULL);
  510. if (getenv("MIGRATE_BROKEN_PWD")) {
  511. putenv(useBrokenUUID);
  512. }
  513. if ( decode_path(oldcred, &plain, oldpath, DES_MECH, NULL) == 0 ){
  514. if (getenv("MIGRATE_BROKEN_PWD")) {
  515. putenv(disableBrokenUUID);
  516. }
  517. if ( encode_path(plain, &cipher, newpath, AES_MECH) != 0 ){
  518. return(NULL);
  519. } else {
  520. return(cipher);
  521. }
  522. } else {
  523. return(NULL);
  524. }
  525. }