des.c 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465
  1. /** BEGIN COPYRIGHT BLOCK
  2. * Copyright 2001 Sun Microsystems, Inc.
  3. * Portions copyright 1999, 2001-2003 Netscape Communications Corporation.
  4. * All rights reserved.
  5. * END COPYRIGHT BLOCK **/
  6. /* from /usr/project/iplanet/ws/ds5.ke/ns/svrcore/pkcs7/tstarchive.c */
  7. #include <string.h>
  8. #include <stdio.h>
  9. #include <ldap.h>
  10. #include <nspr.h>
  11. #include <nss.h>
  12. #include <secmod.h>
  13. /*
  14. #include <secasn1.h>
  15. #include <secpkcs7.h>
  16. */
  17. #include <key.h>
  18. #include <certdb.h>
  19. #include <cert.h>
  20. #include <svrcore.h>
  21. #include <secmodt.h>
  22. #include <prtypes.h>
  23. #include <seccomon.h>
  24. #include <pk11func.h>
  25. #include "rever.h"
  26. #include <slap.h>
  27. #include "slapi-plugin.h"
  28. #include <uuid.h>
  29. struct pk11MechItem
  30. {
  31. CK_MECHANISM_TYPE type;
  32. const char *mechName;
  33. };
  34. static const struct pk11MechItem mymech = { CKM_DES_CBC, "DES CBC encryption" };
  35. static Slapi_Mutex *mylock = NULL;
  36. struct pk11ContextStore
  37. {
  38. PK11SlotInfo *slot;
  39. const struct pk11MechItem *mech;
  40. PK11SymKey *key;
  41. SECItem *params;
  42. int length;
  43. unsigned char *crypt;
  44. };
  45. static int encode_path(char *inPlain, char **outCipher, char *path);
  46. static int decode_path(char *inCipher, char **outPlain, char *path);
  47. static SVRCOREError genKey(struct pk11ContextStore **out, const char *token, char *path);
  48. static SVRCOREError cryptPassword(struct pk11ContextStore *store, char * clear, unsigned char **out);
  49. static SVRCOREError decryptPassword(struct pk11ContextStore *store, unsigned char *cipher, char **out, int len);
  50. static void freeDes(struct pk11ContextStore *out);
  51. static int init = 0;
  52. void
  53. init_des_plugin()
  54. {
  55. mylock = slapi_new_mutex();
  56. }
  57. int
  58. encode(char *inPlain, char **outCipher)
  59. {
  60. return encode_path(inPlain, outCipher, NULL);
  61. }
  62. static int
  63. encode_path(char *inPlain, char **outCipher, char *path)
  64. {
  65. struct pk11ContextStore *context = NULL;
  66. int err;
  67. unsigned char *cipher = NULL;
  68. char *tmp = NULL;
  69. char *base = NULL;
  70. *outCipher = NULL;
  71. err = 1;
  72. if ( genKey(&context, tokDes, path) == SVRCORE_Success )
  73. {
  74. /* Try an encryption */
  75. if ( cryptPassword(context, inPlain, &cipher) == SVRCORE_Success )
  76. {
  77. base = BTOA_DataToAscii(cipher, context->length);
  78. if ( base != NULL )
  79. {
  80. tmp = slapi_ch_malloc( 3 + strlen(REVER_SCHEME_NAME) + strlen(base));
  81. if ( tmp != NULL )
  82. {
  83. sprintf( tmp, "%c%s%c%s", PWD_HASH_PREFIX_START, REVER_SCHEME_NAME, PWD_HASH_PREFIX_END, base);
  84. *outCipher = tmp;
  85. tmp = NULL;
  86. err = 0;
  87. }
  88. PORT_Free(base);
  89. }
  90. }
  91. }
  92. freeDes(context);
  93. slapi_ch_free((void **) &context);
  94. return(err);
  95. }
  96. int
  97. decode(char *inCipher, char **outPlain)
  98. {
  99. return decode_path(inCipher, outPlain, NULL);
  100. }
  101. static int
  102. decode_path(char *inCipher, char **outPlain, char *path)
  103. {
  104. struct pk11ContextStore *context = NULL;
  105. char *plain= NULL;
  106. int err;
  107. unsigned char *base = NULL;
  108. int len = 0;
  109. *outPlain = NULL;
  110. err = 1;
  111. if ( genKey(&context, tokDes, path) == SVRCORE_Success )
  112. {
  113. /* it seems that there is memory leak in that function: bug 400170 */
  114. base = ATOB_AsciiToData(inCipher, (unsigned int*)&len);
  115. if ( base != NULL )
  116. {
  117. if ( decryptPassword(context, base, &plain, len) == SVRCORE_Success )
  118. {
  119. *outPlain = plain;
  120. err = 0;
  121. }
  122. }
  123. }
  124. PORT_Free(base);
  125. freeDes(context);
  126. slapi_ch_free((void **) &context);
  127. return(err);
  128. }
  129. static void freeDes(struct pk11ContextStore *out)
  130. {
  131. if (out)
  132. {
  133. if (out->slot)
  134. slapd_pk11_freeSlot(out->slot);
  135. if (out->key)
  136. slapd_pk11_freeSymKey(out->key);
  137. if (out->params)
  138. SECITEM_FreeItem(out->params,PR_TRUE);
  139. if (out->crypt)
  140. free(out->crypt);
  141. }
  142. }
  143. static SVRCOREError genKey(struct pk11ContextStore **out, const char *token, char *path)
  144. {
  145. SVRCOREError err = SVRCORE_Success;
  146. struct pk11ContextStore *store = NULL;
  147. SECItem *pwitem = NULL;
  148. SECItem *result = NULL;
  149. SECAlgorithmID *algid = NULL;
  150. SECOidTag algoid;
  151. SECItem *salt = NULL;
  152. CK_MECHANISM pbeMech;
  153. CK_MECHANISM cryptoMech;
  154. char *instancedir = NULL;
  155. char *iv = NULL;
  156. store = (struct pk11ContextStore*)slapi_ch_malloc(sizeof(*store));
  157. if (store == NULL)
  158. {
  159. return (err = SVRCORE_NoMemory_Error);
  160. }
  161. *out = store;
  162. /* Low-level init */
  163. store->slot = NULL;
  164. store->key = NULL;
  165. store->params = NULL;
  166. store->crypt = NULL;
  167. /* Use the tokenName to find a PKCS11 slot */
  168. store->slot = slapd_pk11_findSlotByName((char *)token);
  169. if (store->slot == NULL)
  170. {
  171. return (err = SVRCORE_NoSuchToken_Error);
  172. }
  173. /* Generate a key and parameters to do the encryption */
  174. store->mech = &mymech;
  175. /* Generate a unique id, used as salt for the key generation */
  176. if ( path == NULL )
  177. {
  178. instancedir = config_get_instancedir();
  179. if ( instancedir == NULL )
  180. {
  181. return (err = SVRCORE_System_Error);
  182. }
  183. }
  184. else
  185. {
  186. instancedir = slapi_ch_strdup(path);
  187. }
  188. if ( slapi_uniqueIDGenerateFromNameString (&iv, NULL, instancedir, strlen(instancedir)) != UID_SUCCESS )
  189. {
  190. slapi_ch_free((void**)&instancedir);
  191. return (err = SVRCORE_System_Error);
  192. }
  193. slapi_ch_free((void**)&instancedir);
  194. pwitem = (SECItem *) PORT_Alloc(sizeof(SECItem));
  195. if (pwitem == NULL)
  196. {
  197. return (err = SVRCORE_NoMemory_Error);
  198. }
  199. pwitem->type = siBuffer;
  200. pwitem->data = (unsigned char *)PORT_Alloc(strlen(iv)+1);
  201. if (pwitem->data == NULL)
  202. {
  203. return (err = SVRCORE_NoMemory_Error);
  204. }
  205. strcpy((char*)pwitem->data, iv);
  206. pwitem->len = strlen(iv) + 1;
  207. algoid = SEC_OID_PKCS5_PBE_WITH_MD2_AND_DES_CBC;
  208. salt = (SECItem *) PORT_Alloc(sizeof(SECItem));
  209. if (salt == NULL)
  210. {
  211. return (err = SVRCORE_NoMemory_Error);
  212. }
  213. salt->type = siBuffer;
  214. salt->data = (unsigned char *)PORT_Alloc(strlen(iv)+1);
  215. if ( salt->data == NULL )
  216. {
  217. return (err = SVRCORE_NoMemory_Error);
  218. }
  219. strcpy((char*)salt->data, iv);
  220. salt->len = strlen(iv) + 1;
  221. slapi_ch_free((void**)&iv);
  222. algid = slapd_pk11_createPBEAlgorithmID(algoid, 2, salt);
  223. slapi_lock_mutex(mylock);
  224. store->key = slapd_pk11_pbeKeyGen(store->slot, algid, pwitem, 0, 0);
  225. if (store->key == 0)
  226. {
  227. slapi_unlock_mutex(mylock);
  228. return (err = SVRCORE_System_Error);
  229. }
  230. slapi_unlock_mutex(mylock);
  231. pbeMech.mechanism = slapd_pk11_algtagToMechanism(algoid);
  232. result = slapd_pk11_paramFromAlgid(algid);
  233. secoid_destroyAlgorithmID(algid, PR_TRUE);
  234. pbeMech.pParameter = result->data;
  235. pbeMech.ulParameterLen = result->len;
  236. if(slapd_pk11_mapPBEMechanismToCryptoMechanism(&pbeMech, &cryptoMech, pwitem,
  237. PR_FALSE) != CKR_OK)
  238. {
  239. SECITEM_FreeItem(result, PR_TRUE);
  240. return (err = SVRCORE_System_Error);
  241. }
  242. SECITEM_FreeItem(result, PR_TRUE);
  243. SECITEM_FreeItem(pwitem, PR_TRUE);
  244. SECITEM_FreeItem(salt, PR_TRUE);
  245. store->params = (SECItem *) PORT_Alloc(sizeof(SECItem));
  246. if (store->params == NULL)
  247. {
  248. return (err = SVRCORE_System_Error);
  249. }
  250. store->params->type = store->mech->type;
  251. store->params->data = (unsigned char *)PORT_Alloc(cryptoMech.ulParameterLen);
  252. if (store->params->data == NULL)
  253. {
  254. return (err = SVRCORE_System_Error);
  255. }
  256. memcpy(store->params->data, (unsigned char *)cryptoMech.pParameter, cryptoMech.ulParameterLen);
  257. store->params->len = cryptoMech.ulParameterLen;
  258. PORT_Free(cryptoMech.pParameter);
  259. return (err);
  260. }
  261. static SVRCOREError decryptPassword(struct pk11ContextStore *store, unsigned char *cipher, char **out, int len)
  262. {
  263. SVRCOREError err = SVRCORE_Success;
  264. unsigned char *plain = NULL;
  265. unsigned char *cipher_with_padding = NULL;
  266. SECStatus rv;
  267. PK11Context *ctx = 0;
  268. int outLen = 0;
  269. int blocksize = 0;
  270. blocksize = slapd_pk11_getBlockSize(store->mech->type, 0);
  271. store->length = len;
  272. /* store->length is the max. length of the returned clear text -
  273. must be >= length of crypted bytes - also must be a multiple
  274. of blocksize */
  275. if (blocksize != 0)
  276. {
  277. store->length += blocksize - (store->length % blocksize);
  278. }
  279. /* plain will hold the returned clear text */
  280. plain = (unsigned char *)slapi_ch_calloc(sizeof(unsigned char),
  281. store->length+1);
  282. if (!plain)
  283. {
  284. return (err = SVRCORE_NoMemory_Error);
  285. }
  286. /* create a buffer holding the original cipher bytes, padded with
  287. zeros to a multiple of blocksize - do not need +1 since buffer is not
  288. a string */
  289. cipher_with_padding = (unsigned char *)slapi_ch_calloc(sizeof(unsigned char),
  290. store->length);
  291. if (!cipher_with_padding)
  292. {
  293. return (err = SVRCORE_NoMemory_Error);
  294. }
  295. memcpy(cipher_with_padding, cipher, len);
  296. ctx = slapd_pk11_createContextBySymKey(store->mech->type, CKA_DECRYPT,
  297. store->key, store->params);
  298. if (!ctx)
  299. {
  300. return (err = SVRCORE_System_Error);
  301. }
  302. /* warning - there is a purify UMR in the NSS des code - you may see it when the
  303. password is not a multiple of 8 bytes long */
  304. rv = slapd_pk11_cipherOp(ctx, plain, &outLen, store->length,
  305. cipher_with_padding, store->length);
  306. if (rv)
  307. {
  308. err = SVRCORE_System_Error;
  309. }
  310. rv = slapd_pk11_finalize(ctx);
  311. /* we must do the finalize, but we only want to set the err return
  312. code if it is not already set */
  313. if (rv && (SVRCORE_Success == err))
  314. err = SVRCORE_System_Error;
  315. if (err == SVRCORE_Success)
  316. *out = (char *)plain;
  317. slapi_ch_free((void **)&cipher_with_padding);
  318. /* We should free the PK11Context... Something like : */
  319. slapd_pk11_destroyContext(ctx, PR_TRUE);
  320. return err;
  321. }
  322. static SVRCOREError cryptPassword(struct pk11ContextStore *store, char * clear, unsigned char **out)
  323. {
  324. SVRCOREError err = SVRCORE_Success;
  325. SECStatus rv;
  326. PK11Context *ctx = 0;
  327. int outLen = 0;
  328. int blocksize = 0;
  329. unsigned char *clear_with_padding = NULL; /* clear with padding up to blocksize */
  330. blocksize = slapd_pk11_getBlockSize(store->mech->type, 0);
  331. store->length = strlen(clear);
  332. /* the size of the clear text buffer passed to the des encryption functions
  333. must be a multiple of blocksize (usually 8 bytes) - we allocate a buffer
  334. of this size, copy the clear text password into it, and pad the rest with
  335. zeros */
  336. if (blocksize != 0)
  337. {
  338. store->length += blocksize - (store->length % blocksize);
  339. }
  340. /* store->crypt will hold the crypted password - it must be >= clear length */
  341. store->crypt = (unsigned char *)slapi_ch_calloc(sizeof(unsigned char),
  342. store->length+1);
  343. if (!store->crypt)
  344. {
  345. return (err = SVRCORE_NoMemory_Error);
  346. }
  347. /* create a buffer big enough to hold the clear text password and padding */
  348. clear_with_padding = (unsigned char *)slapi_ch_calloc(sizeof(unsigned char),
  349. store->length+1);
  350. if (!clear_with_padding)
  351. {
  352. return (err = SVRCORE_NoMemory_Error);
  353. }
  354. /* copy the clear text password into the buffer - the calloc insures the
  355. remainder is zero padded */
  356. strcpy((char *)clear_with_padding, clear);
  357. ctx = slapd_pk11_createContextBySymKey(store->mech->type, CKA_ENCRYPT,
  358. store->key, store->params);
  359. if (!ctx)
  360. {
  361. return (err = SVRCORE_System_Error);
  362. }
  363. rv = slapd_pk11_cipherOp(ctx, store->crypt, &outLen, store->length,
  364. clear_with_padding, store->length);
  365. if (rv)
  366. {
  367. err = SVRCORE_System_Error;
  368. }
  369. rv = slapd_pk11_finalize(ctx);
  370. /* we must do the finalize, but we only want to set the err return
  371. code if it is not already set */
  372. if (rv && (SVRCORE_Success == err))
  373. err = SVRCORE_System_Error;
  374. if (err == SVRCORE_Success)
  375. *out = store->crypt;
  376. slapi_ch_free((void **)&clear_with_padding);
  377. /* We should free the PK11Context... Something like : */
  378. slapd_pk11_destroyContext(ctx, PR_TRUE);
  379. return err;
  380. }
  381. char *
  382. migrateCredentials(char *oldpath, char *newpath, char *oldcred)
  383. {
  384. char *plain = NULL;
  385. char *cipher = NULL;
  386. init_des_plugin();
  387. slapd_pk11_configurePKCS11(NULL, NULL, tokDes, ptokDes, NULL, NULL, NULL, NULL, 0, 0 );
  388. NSS_NoDB_Init(NULL);
  389. if ( decode_path(oldcred, &plain, oldpath) == 0 )
  390. {
  391. if ( encode_path(plain, &cipher, newpath) != 0 )
  392. return(NULL);
  393. else
  394. return(cipher);
  395. }
  396. else
  397. return(NULL);
  398. }