passhand.cpp 9.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362
  1. /* --- BEGIN COPYRIGHT BLOCK ---
  2. * This Program is free software; you can redistribute it and/or modify it under
  3. * the terms of the GNU General Public License as published by the Free Software
  4. * Foundation; version 2 of the License.
  5. *
  6. * This Program is distributed in the hope that it will be useful, but WITHOUT
  7. * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
  8. * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
  9. *
  10. * You should have received a copy of the GNU General Public License along with
  11. * this Program; if not, write to the Free Software Foundation, Inc., 59 Temple
  12. * Place, Suite 330, Boston, MA 02111-1307 USA.
  13. *
  14. * In addition, as a special exception, Red Hat, Inc. gives You the additional
  15. * right to link the code of this Program with code not covered under the GNU
  16. * General Public License ("Non-GPL Code") and to distribute linked combinations
  17. * including the two, subject to the limitations in this paragraph. Non-GPL Code
  18. * permitted under this exception must only link to the code of this Program
  19. * through those well defined interfaces identified in the file named EXCEPTION
  20. * found in the source code files (the "Approved Interfaces"). The files of
  21. * Non-GPL Code may instantiate templates or use macros or inline functions from
  22. * the Approved Interfaces without causing the resulting work to be covered by
  23. * the GNU General Public License. Only Red Hat, Inc. may make changes or
  24. * additions to the list of Approved Interfaces. You must obey the GNU General
  25. * Public License in all respects for all of the Program code and other code used
  26. * in conjunction with the Program except the Non-GPL Code covered by this
  27. * exception. If you modify this file, you may extend this exception to your
  28. * version of the file, but you are not obligated to do so. If you do not wish to
  29. * provide this exception without modification, you must delete this exception
  30. * statement from your version and license this file solely under the GPL without
  31. * exception.
  32. *
  33. *
  34. * Copyright (C) 2005 Red Hat, Inc.
  35. * All rights reserved.
  36. * --- END COPYRIGHT BLOCK --- */
  37. // Created: 2-8-2005
  38. // Author(s): Scott Bridges
  39. #include "passhand.h"
  40. #include <time.h>
  41. #define KEY {0xe8, 0xa7, 0x7c, 0xe2, 0x05, 0x63, 0x6a, 0x31}
  42. #define IV {0xe4, 0xbb, 0x3b, 0xd3, 0xc3, 0x71, 0x2e, 0x58}
  43. void timeStamp(fstream* outFile)
  44. {
  45. if(outFile->is_open())
  46. {
  47. char dateBuf[32];
  48. char timeBuf[32];
  49. _strdate(dateBuf);
  50. _strtime(timeBuf);
  51. *outFile << dateBuf << " " << timeBuf << ": ";
  52. }
  53. }
  54. int saveSet(PASS_INFO_LIST* passInfoList, char* filename)
  55. {
  56. int result = 0;
  57. fstream outFile;
  58. PASS_INFO_LIST_ITERATOR currentPair;
  59. strstream plainTextStream;
  60. char* cipherTextBuf;
  61. int usernameLen;
  62. int passwordLen;
  63. int plainTextLen;
  64. int cipherTextLen;
  65. int resultTextLen = 0;
  66. int pairCount = passInfoList->size();
  67. // Write usernames and passwords to a strstream
  68. plainTextStream.write((char*)&pairCount, sizeof(pairCount));
  69. for(currentPair = passInfoList->begin(); currentPair != passInfoList->end(); currentPair++)
  70. {
  71. // Usernames
  72. usernameLen = strlen(currentPair->username) + 1;
  73. plainTextStream.write((char*)&usernameLen, sizeof(usernameLen));
  74. plainTextStream.write(currentPair->username, usernameLen);
  75. // Passwords
  76. passwordLen = strlen(currentPair->password) + 1;
  77. plainTextStream.write((char*)&passwordLen, sizeof(passwordLen));
  78. plainTextStream.write(currentPair->password, passwordLen);
  79. }
  80. plainTextLen = plainTextStream.tellp() - plainTextStream.tellg();
  81. // cipherTextBuf length must be at least plainTextLen + 8
  82. cipherTextLen = plainTextLen + 8;
  83. cipherTextBuf = (char*)malloc(cipherTextLen);
  84. if(encrypt(plainTextStream.str(), plainTextLen, cipherTextBuf, cipherTextLen, &resultTextLen) != 0)
  85. {
  86. result = -1;
  87. goto exit;
  88. }
  89. // Write cipher text to file
  90. outFile.open(filename, ios::out | ios::binary);
  91. if(!outFile.is_open())
  92. {
  93. result = -1;
  94. goto exit;
  95. }
  96. outFile.write(cipherTextBuf, resultTextLen);
  97. outFile.close();
  98. exit:
  99. return result;
  100. }
  101. int loadSet(PASS_INFO_LIST* passInfoList, char* filename)
  102. {
  103. int result = 0;
  104. int i;
  105. fstream inFile;
  106. PASS_INFO newPair;
  107. strstream* plainTextStream;
  108. char* cipherTextBuf;
  109. char* plainTextBuf;
  110. int usernameLen;
  111. int passwordLen;
  112. int plainTextLen;
  113. int cipherTextLen;
  114. int resultTextLen = 0;
  115. int pairCount;
  116. // Read in cipher text from file
  117. inFile.open(filename, ios::in | ios::binary);
  118. if(!inFile.is_open())
  119. {
  120. result = -1;
  121. goto exit;
  122. }
  123. // Determine file size
  124. inFile.seekg(0, ios::end);
  125. cipherTextLen = inFile.tellg();
  126. inFile.seekg(0, ios::beg);
  127. // plainTextLen length must be at least cipherTextLen
  128. plainTextLen = cipherTextLen;
  129. cipherTextBuf = (char*)malloc(cipherTextLen);
  130. plainTextBuf = (char*)malloc(plainTextLen);
  131. inFile.read(cipherTextBuf, cipherTextLen);
  132. inFile.close();
  133. if(decrypt(cipherTextBuf, cipherTextLen, plainTextBuf, plainTextLen, &resultTextLen) != 0)
  134. {
  135. result = -1;
  136. goto exit;
  137. }
  138. plainTextStream = new strstream(plainTextBuf, resultTextLen);
  139. plainTextStream->read((char*)&pairCount, sizeof(pairCount));
  140. // Read usernames and passwords from a strstream
  141. for(i = 0; i < pairCount; i++)
  142. {
  143. // Username
  144. plainTextStream->read((char*)&usernameLen, sizeof(usernameLen));
  145. newPair.username = (char*)malloc(usernameLen);
  146. plainTextStream->read((char*)newPair.username, usernameLen);
  147. // Password
  148. plainTextStream->read((char*)&passwordLen, sizeof(passwordLen));
  149. newPair.password = (char*)malloc(passwordLen);
  150. plainTextStream->read((char*)newPair.password, passwordLen);
  151. // Backoff
  152. newPair.backoffCount = 0;
  153. // Load time
  154. time(&newPair.atTime);
  155. passInfoList->push_back(newPair);
  156. }
  157. delete plainTextStream;
  158. exit:
  159. return result;
  160. }
  161. int clearSet(PASS_INFO_LIST* passInfoList)
  162. {
  163. // ToDo: zero out memory
  164. passInfoList->clear();
  165. return -1;
  166. }
  167. int encrypt(char* plainTextBuf, int plainTextLen, char* cipherTextBuf, int cipherTextLen, int* resultTextLen)
  168. {
  169. int result = 0;
  170. SECStatus rv1, rv2, rv3;
  171. PK11SlotInfo* slot = NULL;
  172. PK11SymKey* SymKey = NULL;
  173. SECItem* SecParam = NULL;
  174. PK11Context* EncContext = NULL;
  175. unsigned char gKey[] = KEY;
  176. unsigned char gIV[] = IV;
  177. PK11SymKey* key = NULL;
  178. SECItem keyItem;
  179. SECItem ivItem;
  180. CK_MECHANISM_TYPE cipherMech = CKM_DES_CBC_PAD;
  181. int offset;
  182. int tempTextLen;
  183. // Initialize NSS
  184. rv1 = NSS_NoDB_Init(".");
  185. if(rv1 != SECSuccess)
  186. {
  187. result = PR_GetError();
  188. goto exit;
  189. }
  190. // Get a key slot
  191. slot = PK11_GetInternalKeySlot();
  192. if(slot == NULL)
  193. {
  194. result = PR_GetError();
  195. goto exit;
  196. }
  197. // Generate a symmetric key
  198. keyItem.data = gKey;
  199. keyItem.len = sizeof(gKey);
  200. SymKey = PK11_ImportSymKey(slot, cipherMech, PK11_OriginUnwrap, CKA_ENCRYPT, &keyItem, NULL);
  201. if(SymKey == NULL)
  202. {
  203. result = PR_GetError();
  204. goto exit;
  205. }
  206. // Set up the PKCS11 encryption paramters
  207. ivItem.data = gIV;
  208. ivItem.len = sizeof(gIV);
  209. SecParam = PK11_ParamFromIV(cipherMech, &ivItem);
  210. if(SecParam == NULL)
  211. {
  212. if(SymKey != NULL)
  213. {
  214. PK11_FreeSymKey(SymKey);
  215. }
  216. result = PR_GetError();
  217. goto exit;
  218. }
  219. // ToDo: check parameters
  220. // Encrypt
  221. tempTextLen = 0;
  222. EncContext = PK11_CreateContextBySymKey(cipherMech, CKA_ENCRYPT, SymKey, SecParam);
  223. rv2 = PK11_CipherOp(EncContext, (unsigned char*)cipherTextBuf, &tempTextLen, cipherTextLen, (unsigned char*)plainTextBuf, plainTextLen);
  224. offset = tempTextLen;
  225. rv3 = PK11_DigestFinal(EncContext, (unsigned char*)cipherTextBuf + offset, (unsigned int*)&tempTextLen, cipherTextLen - offset);
  226. *resultTextLen = offset + tempTextLen;
  227. // Clean up
  228. PK11_DestroyContext(EncContext, PR_TRUE);
  229. PK11_FreeSymKey(SymKey);
  230. SECITEM_FreeItem(SecParam, PR_TRUE);
  231. if((rv2 != SECSuccess) || (rv2 != SECSuccess))
  232. {
  233. result = PR_GetError();
  234. goto exit;
  235. }
  236. exit:
  237. return result;
  238. }
  239. int decrypt(char* cipherTextBuf, int cipherTextLen, char* plainTextBuf, int plainTextLen, int* resultTextLen)
  240. {
  241. int result = 0;
  242. SECStatus rv1, rv2, rv3;
  243. PK11SlotInfo* slot = NULL;
  244. PK11SymKey* SymKey = NULL;
  245. SECItem* SecParam = NULL;
  246. PK11Context* EncContext = NULL;
  247. unsigned char gKey[] = KEY;
  248. unsigned char gIV[] = IV;
  249. PK11SymKey* key = NULL;
  250. SECItem keyItem;
  251. SECItem ivItem;
  252. CK_MECHANISM_TYPE cipherMech = CKM_DES_CBC_PAD;
  253. int offset;
  254. int tempTextLen;
  255. // Initialize NSS
  256. rv1 = NSS_NoDB_Init(".");
  257. if(rv1 != SECSuccess)
  258. {
  259. result = PR_GetError();
  260. goto exit;
  261. }
  262. // Get a key slot
  263. slot = PK11_GetInternalKeySlot();
  264. if(slot == NULL)
  265. {
  266. result = PR_GetError();
  267. goto exit;
  268. }
  269. // Generate a symmetric key
  270. keyItem.data = gKey;
  271. keyItem.len = sizeof(gKey);
  272. SymKey = PK11_ImportSymKey(slot, cipherMech, PK11_OriginUnwrap, CKA_ENCRYPT, &keyItem, NULL);
  273. if(SymKey == NULL)
  274. {
  275. result = PR_GetError();
  276. goto exit;
  277. }
  278. // Set up the PKCS11 encryption paramters
  279. ivItem.data = gIV;
  280. ivItem.len = sizeof(gIV);
  281. SecParam = PK11_ParamFromIV(cipherMech, &ivItem);
  282. if(SecParam == NULL)
  283. {
  284. if(SymKey != NULL)
  285. {
  286. PK11_FreeSymKey(SymKey);
  287. }
  288. result = PR_GetError();
  289. goto exit;
  290. }
  291. // ToDo: check parameters
  292. // Decrypt
  293. tempTextLen = 0;
  294. EncContext = PK11_CreateContextBySymKey(cipherMech, CKA_DECRYPT, SymKey, SecParam);
  295. rv2 = PK11_CipherOp(EncContext, (unsigned char*)plainTextBuf, &tempTextLen, plainTextLen, (unsigned char*)cipherTextBuf, cipherTextLen);
  296. offset = tempTextLen;
  297. rv3 = PK11_DigestFinal(EncContext, (unsigned char*)plainTextBuf + offset, (unsigned int*)&tempTextLen, plainTextLen - offset);
  298. *resultTextLen = offset + tempTextLen;
  299. // Clean up
  300. PK11_DestroyContext(EncContext, PR_TRUE);
  301. PK11_FreeSymKey(SymKey);
  302. SECITEM_FreeItem(SecParam, PR_TRUE);
  303. if((rv2 != SECSuccess) || (rv2 != SECSuccess))
  304. {
  305. result = PR_GetError();
  306. goto exit;
  307. }
  308. exit:
  309. return result;
  310. }