pbe.c 17 KB

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