Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

420 lines
13 KiB

  1. /////////////////////////////////////////////////////////////////////////////
  2. // FILE : fipslib.c //
  3. // DESCRIPTION : FIPS 140 support code. //
  4. // AUTHOR : //
  5. // HISTORY : //
  6. // Oct 20 1999 jeffspel/ramas Merge STT into default CSP //
  7. // //
  8. // Copyright (C) 2000 Microsoft Corporation All Rights Reserved //
  9. /////////////////////////////////////////////////////////////////////////////
  10. #include <nt.h>
  11. #include <ntrtl.h>
  12. #include <nturtl.h>
  13. #include <windows.h>
  14. #include <wincrypt.h>
  15. #ifdef KERNEL_MODE
  16. #if WINVER == 0x0500
  17. #include <ntos.h>
  18. #else
  19. #include <ntosp.h>
  20. #endif
  21. #endif
  22. #include <sha.h>
  23. #include <des.h>
  24. #include <tripldes.h>
  25. #include <modes.h>
  26. // known result of an SHA-1 hash on the above buffer
  27. static UCHAR rgbKnownSHA1[] =
  28. {
  29. 0xe8, 0x96, 0x82, 0x85, 0xeb, 0xae, 0x01, 0x14,
  30. 0x73, 0xf9, 0x08, 0x45, 0xc0, 0x6a, 0x6d, 0x3e,
  31. 0x69, 0x80, 0x6a, 0x0c
  32. };
  33. // IV for all block ciphers
  34. UCHAR rgbIV[] = {0x12, 0x34, 0x56, 0x78, 0x90, 0xAB, 0xCD, 0xEF};
  35. // known key, plaintext, and ciphertext for DES
  36. UCHAR rgbDESKey[] = {0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef};
  37. UCHAR rgbDESKnownPlaintext[] = {0x4E, 0x6F, 0x77, 0x20, 0x69, 0x73, 0x20, 0x74};
  38. UCHAR rgbDESKnownCiphertext[] = {0x3F, 0xA4, 0x0E, 0x8A, 0x98, 0x4D, 0x48, 0x15};
  39. UCHAR rgbDESCBCCiphertext[] = {0xE5, 0xC7, 0xCD, 0xDE, 0x87, 0x2B, 0xF2, 0x7C};
  40. // known key, plaintext, and ciphertext for 3 key 3DES
  41. UCHAR rgb3DESKey[] =
  42. {
  43. 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef,
  44. 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef, 0x01,
  45. 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef, 0x01, 0x23
  46. };
  47. UCHAR rgb3DESKnownPlaintext[] = {0x4E, 0x6F, 0x77, 0x20, 0x69, 0x73, 0x20, 0x74};
  48. UCHAR rgb3DESKnownCiphertext[] = {0x31, 0x4F, 0x83, 0x27, 0xFA, 0x7A, 0x09, 0xA8};
  49. UCHAR rgb3DESCBCCiphertext[] = {0xf3, 0xc0, 0xff, 0x02, 0x6c, 0x02, 0x30, 0x89};
  50. // known key, plaintext, and ciphertext for 2 key 3DES
  51. UCHAR rgb3DES112Key[] =
  52. {
  53. 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef,
  54. 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef, 0x01
  55. };
  56. UCHAR rgb3DES112KnownPlaintext[] = {0x4E, 0x6F, 0x77, 0x20, 0x69, 0x73, 0x20, 0x74};
  57. UCHAR rgb3DES112KnownCiphertext[] = {0xb7, 0x83, 0x57, 0x79, 0xee, 0x26, 0xac, 0xb7};
  58. UCHAR rgb3DES112CBCCiphertext[] = {0x13, 0x4b, 0x98, 0xf8, 0xee, 0xb3, 0xf6, 0x07};
  59. #define MAX_BLOCKLEN 8
  60. #define MAXKEYSTRUCTSIZE DES3_TABLESIZE // currently the max is a 3DES key structure
  61. // Known answer test for SHA HMAC from Fips draft
  62. UCHAR rgbHmacKey [] = {
  63. 0x01, 0x02, 0x03, 0x04, 0x05,
  64. 0x06, 0x07, 0x08, 0x09, 0x0a,
  65. 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
  66. 0x10, 0x11, 0x12, 0x13, 0x14,
  67. 0x15, 0x16, 0x17, 0x18, 0x19
  68. };
  69. UCHAR rgbHmacData [50]; // set bytes to 0xcd
  70. UCHAR rgbHmac [] = {
  71. 0x4c, 0x90, 0x07, 0xf4, 0x02,
  72. 0x62, 0x50, 0xc6, 0xbc, 0x84,
  73. 0x14, 0xf9, 0xbf, 0x50, 0xc8,
  74. 0x6c, 0x2d, 0x72, 0x35, 0xda
  75. };
  76. extern VOID FipsHmacSHAInit(
  77. OUT A_SHA_CTX *pShaCtx,
  78. IN UCHAR *pKey,
  79. IN unsigned int cbKey
  80. );
  81. extern VOID FipsHmacSHAUpdate(
  82. IN OUT A_SHA_CTX *pShaCtx,
  83. IN UCHAR *pb,
  84. IN unsigned int cb
  85. );
  86. extern VOID FipsHmacSHAFinal(
  87. IN A_SHA_CTX *pShaCtx,
  88. IN UCHAR *pKey,
  89. IN unsigned int cbKey,
  90. OUT UCHAR *pHash
  91. );
  92. //
  93. // Function : TestSHA1
  94. //
  95. // Description : This function hashes the passed in message with the SHA1 hash
  96. // algorithm and returns the resulting hash value.
  97. //
  98. void TestSHA1(
  99. UCHAR *pbMsg,
  100. ULONG cbMsg,
  101. UCHAR *pbHash
  102. )
  103. {
  104. A_SHA_CTX HashContext;
  105. // Initialize SHA
  106. A_SHAInit(&HashContext);
  107. // Compute SHA
  108. A_SHAUpdate(&HashContext, pbMsg, cbMsg);
  109. A_SHAFinal(&HashContext, pbHash);
  110. }
  111. //
  112. // Function : TestEncDec
  113. //
  114. // Description : This function expands the passed in key buffer for the appropriate
  115. // algorithm, and then either encryption or decryption is performed.
  116. // A comparison is then made to see if the ciphertext or plaintext
  117. // matches the expected value.
  118. // The function only uses ECB mode for block ciphers and the plaintext
  119. // buffer must be the same length as the ciphertext buffer. The length
  120. // of the plaintext must be either the block length of the cipher if it
  121. // is a block cipher or less than MAX_BLOCKLEN if a stream cipher is
  122. // being used.
  123. //
  124. NTSTATUS TestEncDec(
  125. IN ALG_ID Algid,
  126. IN UCHAR *pbKey,
  127. IN ULONG cbKey,
  128. IN UCHAR *pbPlaintext,
  129. IN ULONG cbPlaintext,
  130. IN UCHAR *pbCiphertext,
  131. IN UCHAR *pbIV,
  132. IN int iOperation
  133. )
  134. {
  135. UCHAR rgbExpandedKey[MAXKEYSTRUCTSIZE];
  136. UCHAR rgbBuffIn[MAX_BLOCKLEN];
  137. UCHAR rgbBuffOut[MAX_BLOCKLEN];
  138. ULONG i;
  139. NTSTATUS Status = STATUS_UNSUCCESSFUL;
  140. RtlZeroMemory(rgbExpandedKey, sizeof(rgbExpandedKey));
  141. RtlZeroMemory(rgbBuffIn, sizeof(rgbBuffIn));
  142. RtlZeroMemory(rgbBuffOut, sizeof(rgbBuffOut));
  143. // length of data to encrypt must be < MAX_BLOCKLEN
  144. if (cbPlaintext > MAX_BLOCKLEN)
  145. {
  146. goto Ret;
  147. }
  148. // alloc for and expand the key
  149. switch(Algid)
  150. {
  151. case (CALG_DES):
  152. {
  153. desparityonkey(pbKey, cbKey);
  154. deskey((DESTable*)rgbExpandedKey, pbKey);
  155. break;
  156. }
  157. case (CALG_3DES):
  158. {
  159. desparityonkey(pbKey, cbKey);
  160. tripledes3key((PDES3TABLE)rgbExpandedKey, pbKey);
  161. break;
  162. }
  163. case (CALG_3DES_112):
  164. {
  165. desparityonkey(pbKey, cbKey);
  166. tripledes2key((PDES3TABLE)rgbExpandedKey, pbKey);
  167. break;
  168. }
  169. }
  170. // if encrypting and there is an IV then use it
  171. if (ENCRYPT == iOperation)
  172. {
  173. memcpy(rgbBuffIn, pbPlaintext, cbPlaintext);
  174. if (NULL != pbIV)
  175. {
  176. for(i = 0; i < cbPlaintext; i++)
  177. {
  178. rgbBuffIn[i] = rgbBuffIn[i] ^ pbIV[i];
  179. }
  180. }
  181. }
  182. // encrypt the plaintext
  183. switch(Algid)
  184. {
  185. case (CALG_DES):
  186. {
  187. if (ENCRYPT == iOperation)
  188. {
  189. des(rgbBuffOut, rgbBuffIn, rgbExpandedKey, ENCRYPT);
  190. }
  191. else
  192. {
  193. des(rgbBuffOut, pbCiphertext, rgbExpandedKey, DECRYPT);
  194. }
  195. break;
  196. }
  197. case (CALG_3DES):
  198. case (CALG_3DES_112):
  199. {
  200. if (ENCRYPT == iOperation)
  201. {
  202. tripledes(rgbBuffOut, rgbBuffIn, rgbExpandedKey, ENCRYPT);
  203. }
  204. else
  205. {
  206. tripledes(rgbBuffOut, pbCiphertext, rgbExpandedKey, DECRYPT);
  207. }
  208. break;
  209. }
  210. }
  211. // compare the encrypted plaintext with the passed in ciphertext
  212. if (ENCRYPT == iOperation)
  213. {
  214. if (memcmp(pbCiphertext, rgbBuffOut, cbPlaintext))
  215. {
  216. goto Ret;
  217. }
  218. }
  219. // compare the decrypted ciphertext with the passed in plaintext
  220. else
  221. {
  222. // if there is an IV then use it
  223. if (NULL != pbIV)
  224. {
  225. for(i = 0; i < cbPlaintext; i++)
  226. {
  227. rgbBuffOut[i] = rgbBuffOut[i] ^ pbIV[i];
  228. }
  229. }
  230. if (memcmp(pbPlaintext, rgbBuffOut, cbPlaintext))
  231. {
  232. goto Ret;
  233. }
  234. }
  235. Status = STATUS_SUCCESS;
  236. Ret:
  237. return Status;
  238. }
  239. //
  240. // Function : TestSymmetricAlgorithm
  241. //
  242. // Description : This function expands the passed in key buffer for the appropriate algorithm,
  243. // encrypts the plaintext buffer with the same algorithm and key, and the
  244. // compares the passed in expected ciphertext with the calculated ciphertext
  245. // to make sure they are the same. The opposite is then done with decryption.
  246. // The function only uses ECB mode for block ciphers and the plaintext
  247. // buffer must be the same length as the ciphertext buffer. The length
  248. // of the plaintext must be either the block length of the cipher if it
  249. // is a block cipher or less than MAX_BLOCKLEN if a stream cipher is
  250. // being used.
  251. //
  252. NTSTATUS TestSymmetricAlgorithm(
  253. IN ALG_ID Algid,
  254. IN UCHAR *pbKey,
  255. IN ULONG cbKey,
  256. IN UCHAR *pbPlaintext,
  257. IN ULONG cbPlaintext,
  258. IN UCHAR *pbCiphertext,
  259. IN UCHAR *pbIV
  260. )
  261. {
  262. NTSTATUS Status = STATUS_UNSUCCESSFUL;
  263. Status = TestEncDec(Algid, pbKey, cbKey, pbPlaintext, cbPlaintext,
  264. pbCiphertext, pbIV, ENCRYPT);
  265. if (!NT_SUCCESS(Status))
  266. {
  267. goto Ret;
  268. }
  269. Status = TestEncDec(Algid, pbKey, cbKey, pbPlaintext, cbPlaintext,
  270. pbCiphertext, pbIV, DECRYPT);
  271. if (!NT_SUCCESS(Status))
  272. {
  273. goto Ret;
  274. }
  275. Ret:
  276. return Status;
  277. }
  278. // **********************************************************************
  279. // AlgorithmCheck performs known answer tests using the algorithms
  280. // supported by the provider.
  281. // **********************************************************************
  282. NTSTATUS AlgorithmCheck()
  283. {
  284. UCHAR rgbSHA1[A_SHA_DIGEST_LEN];
  285. NTSTATUS Status = STATUS_UNSUCCESSFUL;
  286. A_SHA_CTX ShaCtx;
  287. ULONG ul;
  288. RtlZeroMemory(rgbSHA1, sizeof(rgbSHA1));
  289. // known answer test with SHA-1 (this function is found in hash.c)
  290. TestSHA1("HashThis", 8, rgbSHA1);
  291. if (!RtlEqualMemory(rgbSHA1, rgbKnownSHA1, sizeof(rgbSHA1)))
  292. {
  293. goto Ret;
  294. }
  295. // known answer test with DES - ECB
  296. Status = TestSymmetricAlgorithm(CALG_DES, rgbDESKey, sizeof(rgbDESKey),
  297. rgbDESKnownPlaintext,
  298. sizeof(rgbDESKnownPlaintext),
  299. rgbDESKnownCiphertext,
  300. NULL);
  301. if (!NT_SUCCESS(Status))
  302. {
  303. goto Ret;
  304. }
  305. // known answer test with DES - CBC
  306. Status = TestSymmetricAlgorithm(CALG_DES, rgbDESKey, sizeof(rgbDESKey),
  307. rgbDESKnownPlaintext,
  308. sizeof(rgbDESKnownPlaintext),
  309. rgbDESCBCCiphertext,
  310. rgbIV);
  311. if (!NT_SUCCESS(Status))
  312. {
  313. goto Ret;
  314. }
  315. // known answer test with 3DES - ECB
  316. Status = TestSymmetricAlgorithm(CALG_3DES, rgb3DESKey, sizeof(rgb3DESKey),
  317. rgb3DESKnownPlaintext,
  318. sizeof(rgb3DESKnownPlaintext),
  319. rgb3DESKnownCiphertext,
  320. NULL);
  321. if (!NT_SUCCESS(Status))
  322. {
  323. goto Ret;
  324. }
  325. // known answer test with 3DES - CBC
  326. Status = TestSymmetricAlgorithm(CALG_3DES, rgb3DESKey, sizeof(rgb3DESKey),
  327. rgb3DESKnownPlaintext,
  328. sizeof(rgb3DESKnownPlaintext),
  329. rgb3DESCBCCiphertext,
  330. rgbIV);
  331. if (!NT_SUCCESS(Status))
  332. {
  333. goto Ret;
  334. }
  335. // known answer test with 3DES 112 - ECB
  336. Status = TestSymmetricAlgorithm(CALG_3DES_112, rgb3DES112Key,
  337. sizeof(rgb3DES112Key),
  338. rgb3DES112KnownPlaintext,
  339. sizeof(rgb3DES112KnownPlaintext),
  340. rgb3DES112KnownCiphertext,
  341. NULL);
  342. if (!NT_SUCCESS(Status))
  343. {
  344. goto Ret;
  345. }
  346. Status = TestSymmetricAlgorithm(CALG_3DES_112, rgb3DES112Key,
  347. sizeof(rgb3DES112Key),
  348. rgb3DES112KnownPlaintext,
  349. sizeof(rgb3DES112KnownPlaintext),
  350. rgb3DES112CBCCiphertext,
  351. rgbIV);
  352. if (!NT_SUCCESS(Status))
  353. {
  354. goto Ret;
  355. }
  356. // Known answer test for SHA-HMAC
  357. RtlZeroMemory(rgbSHA1, sizeof(rgbSHA1));
  358. RtlZeroMemory(&ShaCtx, sizeof(ShaCtx));
  359. for (ul = 0; ul < sizeof(rgbHmacData); ul++)
  360. rgbHmacData[ul] = 0xcd;
  361. FipsHmacSHAInit(&ShaCtx, rgbHmacKey, sizeof(rgbHmacKey));
  362. FipsHmacSHAUpdate(&ShaCtx, rgbHmacData, sizeof(rgbHmacData));
  363. FipsHmacSHAFinal(&ShaCtx, rgbHmacKey, sizeof(rgbHmacKey), rgbSHA1);
  364. if (! RtlEqualMemory(rgbSHA1, rgbHmac, sizeof(rgbHmac)))
  365. goto Ret;
  366. Status = STATUS_SUCCESS;
  367. Ret:
  368. return Status;
  369. }