Source code of Windows XP (NT5)
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.

910 lines
25 KiB

  1. /////////////////////////////////////////////////////////////////////////////
  2. // FILE : nt_sign.c //
  3. // DESCRIPTION : Crypto CP interfaces: //
  4. // CPSignHash //
  5. // CPVerifySignature //
  6. // AUTHOR : //
  7. // HISTORY : //
  8. // Jan 25 1995 larrys Changed from Nametag //
  9. // Feb 23 1995 larrys Changed NTag_SetLastError to SetLastError //
  10. // Mar 23 1995 larrys Added variable key length //
  11. // May 10 1995 larrys added private api calls //
  12. // Aug 03 1995 larrys Fix for bug 10 //
  13. // Aug 22 1995 larrys Added descriptions to sign and verify hash //
  14. // Aug 30 1995 larrys Changed Algid to dwKeySpec //
  15. // Aug 30 1995 larrys Removed RETURNASHVALUE from CryptGetHashValue //
  16. // Aug 31 1995 larrys Fixed CryptSignHash for pbSignature == NULL //
  17. // Aug 31 1995 larrys Fix for Bug 28 //
  18. // Sep 12 1995 Jeffspel/ramas Merged STT onto SCP //
  19. // Sep 12 1995 Jeffspel/ramas BUGS FIXED PKCS#1 Padding. //
  20. // Sep 18 1995 larrys Removed flag fro CryptSignHash //
  21. // Oct 13 1995 larrys Changed GetHashValue to GetHashParam //
  22. // Oct 23 1995 larrys Added MD2 //
  23. // Oct 25 1995 larrys Change length of sDescription string //
  24. // Nov 10 1995 DBarlow Bug #61 //
  25. // Dec 11 1995 larrys Added error return check //
  26. // May 15 1996 larrys Changed NTE_NO_MEMORY to ERROR_NOT_ENOUGHT... //
  27. // May 29 1996 larrys Bug 101 //
  28. // Jun 6 1996 a-johnb Added support for SSL 3.0 signatures //
  29. // May 23 1997 jeffspel Added provider type checking //
  30. // May 5 2000 dbarlow Clean up error return codes //
  31. // //
  32. // Copyright (C) 1993 - 2000, Microsoft Corporation //
  33. // All Rights Reserved //
  34. /////////////////////////////////////////////////////////////////////////////
  35. //#include <wtypes.h>
  36. #include "precomp.h"
  37. #include "ntagum.h"
  38. #include "nt_rsa.h"
  39. #include "protstor.h"
  40. #include "swnt_pk.h"
  41. extern CSP_STRINGS g_Strings;
  42. //
  43. // Reverse ASN.1 Encodings of possible hash identifiers. The leading byte is
  44. // the length of the remaining byte string. The lists of possible identifiers
  45. // is terminated with a '\x00' entry.
  46. //
  47. static const BYTE
  48. #ifdef CSP_USE_MD2
  49. *md2Encodings[]
  50. // 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
  51. = { (CONST BYTE *)"\x12\x10\x04\x00\x05\x02\x02\x0d\xf7\x86\x48\x86\x2a\x08\x06\x0c\x30\x20\x30",
  52. (CONST BYTE *)"\x10\x10\x04\x02\x02\x0d\xf7\x86\x48\x86\x2a\x08\x06\x0a\x30\x1e\x30",
  53. (CONST BYTE *)"\x00" },
  54. #endif
  55. #ifdef CSP_USE_MD4
  56. *md4Encodings[]
  57. = { (CONST BYTE *)"\x12\x10\x04\x00\x05\x04\x02\x0d\xf7\x86\x48\x86\x2a\x08\x06\x0c\x30\x20\x30",
  58. (CONST BYTE *)"\x10\x10\x04\x04\x02\x0d\xf7\x86\x48\x86\x2a\x08\x06\x0a\x30\x1e\x30",
  59. (CONST BYTE *)"\x00" },
  60. #endif
  61. #ifdef CSP_USE_MD5
  62. *md5Encodings[]
  63. = { (CONST BYTE *)"\x12\x10\x04\x00\x05\x05\x02\x0d\xf7\x86\x48\x86\x2a\x08\x06\x0c\x30\x20\x30",
  64. (CONST BYTE *)"\x10\x10\x04\x05\x02\x0d\xf7\x86\x48\x86\x2a\x08\x06\x0a\x30\x1e\x30",
  65. (CONST BYTE *)"\x00" },
  66. #endif
  67. #ifdef CSP_USE_SHA
  68. *shaEncodings[]
  69. = { (CONST BYTE *)"\x0f\x14\x04\x00\x05\x1a\x02\x03\x0e\x2b\x05\x06\x09\x30\x21\x30",
  70. (CONST BYTE *)"\x0d\x14\x04\x1a\x02\x03\x0e\x2b\x05\x06\x07\x30\x1f\x30",
  71. (CONST BYTE *)"\x00"},
  72. #endif
  73. *endEncodings[]
  74. = { (CONST BYTE *)"\x00" };
  75. /*
  76. - ApplyPKCS1SigningFormat
  77. -
  78. * Purpose:
  79. * Format a buffer with PKCS 1 for signing
  80. *
  81. */
  82. /*static*/ DWORD
  83. ApplyPKCS1SigningFormat(
  84. IN BSAFE_PUB_KEY *pPubKey,
  85. IN ALG_ID HashAlgid,
  86. IN BYTE *pbHash,
  87. IN DWORD cbHash,
  88. IN DWORD dwFlags,
  89. OUT BYTE *pbPKCS1Format)
  90. {
  91. DWORD dwReturn = ERROR_INTERNAL_ERROR;
  92. BYTE *pbStart;
  93. BYTE *pbEnd;
  94. BYTE bTmp;
  95. DWORD i;
  96. // insert the block type
  97. pbPKCS1Format[pPubKey->datalen - 1] = 0x01;
  98. // insert the type I padding
  99. memset(pbPKCS1Format, 0xff, pPubKey->datalen-1);
  100. // Reverse it
  101. for (i = 0; i < cbHash; i++)
  102. pbPKCS1Format[i] = pbHash[cbHash - (i + 1)];
  103. if ( 0 == (CRYPT_NOHASHOID & dwFlags))
  104. {
  105. switch (HashAlgid)
  106. {
  107. #ifdef CSP_USE_MD2
  108. case CALG_MD2:
  109. // PKCS delimit the hash value
  110. pbEnd = (LPBYTE)md2Encodings[0];
  111. pbStart = pbPKCS1Format + cbHash;
  112. bTmp = *pbEnd++;
  113. while (0 < bTmp--)
  114. *pbStart++ = *pbEnd++;
  115. *pbStart++ = 0;
  116. break;
  117. #endif
  118. #ifdef CSP_USE_MD4
  119. case CALG_MD4:
  120. // PKCS delimit the hash value
  121. pbEnd = (LPBYTE)md4Encodings[0];
  122. pbStart = pbPKCS1Format + cbHash;
  123. bTmp = *pbEnd++;
  124. while (0 < bTmp--)
  125. *pbStart++ = *pbEnd++;
  126. *pbStart++ = 0;
  127. break;
  128. #endif
  129. #ifdef CSP_USE_MD5
  130. case CALG_MD5:
  131. // PKCS delimit the hash value
  132. pbEnd = (LPBYTE)md5Encodings[0];
  133. pbStart = pbPKCS1Format + cbHash;
  134. bTmp = *pbEnd++;
  135. while (0 < bTmp--)
  136. *pbStart++ = *pbEnd++;
  137. *pbStart++ = 0;
  138. break;
  139. #endif
  140. #ifdef CSP_USE_SHA
  141. case CALG_SHA:
  142. // PKCS delimit the hash value
  143. pbEnd = (LPBYTE)shaEncodings[0];
  144. pbStart = pbPKCS1Format + cbHash;
  145. bTmp = *pbEnd++;
  146. while (0 < bTmp--)
  147. *pbStart++ = *pbEnd++;
  148. *pbStart++ = 0;
  149. break;
  150. #endif
  151. #ifdef CSP_USE_SSL3SHAMD5
  152. case CALG_SSL3_SHAMD5:
  153. // Don't put in any PKCS crud
  154. pbStart = pbPKCS1Format + cbHash;
  155. *pbStart++ = 0;
  156. break;
  157. #endif
  158. default:
  159. dwReturn = (DWORD)NTE_BAD_ALGID;
  160. goto ErrorExit;
  161. }
  162. }
  163. else
  164. {
  165. pbPKCS1Format[cbHash] = 0x00;
  166. }
  167. dwReturn = ERROR_SUCCESS;
  168. ErrorExit:
  169. return dwReturn;
  170. }
  171. /*
  172. - ApplyX931SigningFormat
  173. -
  174. * Purpose:
  175. * Format a buffer with X.9.31 for signing, assumes
  176. * the buffer to be formatted is at least the length
  177. * of the signature (cbSig).
  178. *
  179. */
  180. /*static*/ void
  181. ApplyX931SigningFormat(
  182. IN DWORD cbSig,
  183. IN BYTE *pbHash,
  184. IN DWORD cbHash,
  185. IN BOOL fDataInHash,
  186. OUT BYTE *pbFormatted)
  187. {
  188. DWORD i;
  189. // insert P3
  190. pbFormatted[0] = 0xcc;
  191. pbFormatted[1] = 0x33;
  192. // Reverse it
  193. for (i = 0; i < cbHash; i++)
  194. pbFormatted[i + 2] = pbHash[cbHash - (i + 1)];
  195. pbFormatted[22] = 0xba;
  196. // insert P2
  197. memset(pbFormatted + 23, 0xbb, cbSig - 24);
  198. // insert P1
  199. if (fDataInHash)
  200. pbFormatted[cbSig - 1] = 0x6b;
  201. else
  202. pbFormatted[cbSig - 1] = 0x4b;
  203. }
  204. /*
  205. - CPSignHash
  206. -
  207. * Purpose:
  208. * Create a digital signature from a hash
  209. *
  210. *
  211. * Parameters:
  212. * IN hUID - Handle to the user identifcation
  213. * IN hHash - Handle to hash object
  214. * IN dwKeySpec - Key pair that is used to sign with
  215. * algorithm to be used
  216. * IN sDescription - Description of data to be signed
  217. * IN dwFlags - Flags values
  218. * OUT pbSignture - Pointer to signature data
  219. * OUT dwHashLen - Pointer to the len of the signature data
  220. *
  221. * Returns:
  222. */
  223. BOOL WINAPI
  224. CPSignHash(
  225. IN HCRYPTPROV hUID,
  226. IN HCRYPTHASH hHash,
  227. IN DWORD dwKeySpec,
  228. IN LPCWSTR sDescription,
  229. IN DWORD dwFlags,
  230. OUT BYTE *pbSignature,
  231. OUT DWORD *pdwSigLen)
  232. {
  233. DWORD dwReturn = ERROR_INTERNAL_ERROR;
  234. PNTAGUserList pTmpUser = NULL;
  235. PNTAGHashList pTmpHash;
  236. BSAFE_PRV_KEY *pPrivKey = NULL;
  237. MD2_object *pMD2Hash;
  238. MD4_object *pMD4Hash;
  239. MD5_object *pMD5Hash;
  240. A_SHA_CTX *pSHAHash;
  241. BYTE rgbTmpHash[SSL3_SHAMD5_LEN];
  242. DWORD cbTmpHash = SSL3_SHAMD5_LEN;
  243. BYTE *pbInput = NULL;
  244. BYTE *pbSigT = NULL;
  245. DWORD cbSigLen;
  246. BOOL fSigKey;
  247. BSAFE_PUB_KEY *pPubKey;
  248. LPWSTR szPrompt;
  249. BOOL fDataInHash = FALSE;
  250. BOOL fRet;
  251. DWORD dwSts;
  252. EntryPoint
  253. if ((dwFlags & ~(CRYPT_NOHASHOID | CRYPT_X931_FORMAT)) != 0)
  254. {
  255. dwReturn = (DWORD)NTE_BAD_FLAGS;
  256. goto ErrorExit;
  257. }
  258. pTmpUser = (PNTAGUserList)NTLCheckList(hUID, USER_HANDLE);
  259. if (NULL == pTmpUser)
  260. {
  261. dwReturn = (DWORD)NTE_BAD_UID;
  262. goto ErrorExit;
  263. }
  264. // get the user's public key
  265. if (dwKeySpec == AT_KEYEXCHANGE)
  266. {
  267. fSigKey = FALSE;
  268. pPubKey = (BSAFE_PUB_KEY *)pTmpUser->ContInfo.pbExchPub;
  269. szPrompt = g_Strings.pwszSignWExch;
  270. }
  271. else if (dwKeySpec == AT_SIGNATURE)
  272. {
  273. if (PROV_RSA_SCHANNEL == pTmpUser->dwProvType)
  274. {
  275. dwReturn = (DWORD)NTE_BAD_ALGID;
  276. goto ErrorExit;
  277. }
  278. fSigKey = TRUE;
  279. pPubKey = (BSAFE_PUB_KEY *)pTmpUser->ContInfo.pbSigPub;
  280. szPrompt = g_Strings.pwszSigning;
  281. }
  282. else
  283. {
  284. dwReturn = (DWORD)NTE_BAD_ALGID;
  285. goto ErrorExit;
  286. }
  287. // check to make sure the key exists
  288. if (NULL == pPubKey)
  289. {
  290. dwReturn = (DWORD)NTE_BAD_KEYSET;
  291. goto ErrorExit;
  292. }
  293. cbSigLen = (pPubKey->bitlen + 7) / 8;
  294. if (pbSignature == NULL || *pdwSigLen < cbSigLen)
  295. {
  296. *pdwSigLen = cbSigLen;
  297. dwReturn = (pbSignature == NULL) ? ERROR_SUCCESS : ERROR_MORE_DATA;
  298. goto ErrorExit;
  299. }
  300. // check to see if the hash is in the hash list
  301. dwSts = NTLValidate(hHash, hUID, HASH_HANDLE, &pTmpHash);
  302. if (ERROR_SUCCESS != dwSts)
  303. {
  304. dwReturn = (dwSts == NTF_FAILED) ? (DWORD)NTE_BAD_HASH : dwSts;
  305. goto ErrorExit;
  306. }
  307. // zero the output buffer
  308. memset (pbSignature, 0, cbSigLen);
  309. switch (pTmpHash->Algid)
  310. {
  311. #ifdef CSP_USE_MD2
  312. case CALG_MD2:
  313. pMD2Hash = (MD2_object *)pTmpHash->pHashData;
  314. break;
  315. #endif
  316. #ifdef CSP_USE_MD4
  317. case CALG_MD4:
  318. pMD4Hash = (MD4_object *)pTmpHash->pHashData;
  319. break;
  320. #endif
  321. #ifdef CSP_USE_MD5
  322. case CALG_MD5:
  323. pMD5Hash = (MD5_object *)pTmpHash->pHashData;
  324. break;
  325. #endif
  326. #ifdef CSP_USE_SHA
  327. case CALG_SHA:
  328. pSHAHash = (A_SHA_CTX *)pTmpHash->pHashData;
  329. break;
  330. #endif
  331. #ifdef CSP_USE_SSL3SHAMD5
  332. case CALG_SSL3_SHAMD5:
  333. // Hash value must have already been set.
  334. if ((pTmpHash->HashFlags & HF_VALUE_SET) == 0)
  335. {
  336. dwReturn = (DWORD)NTE_BAD_HASH_STATE;
  337. goto ErrorExit;
  338. }
  339. break;
  340. #endif
  341. default:
  342. dwReturn = (DWORD)NTE_BAD_ALGID;
  343. goto ErrorExit;
  344. }
  345. // WARNING: due to vulnerabilities sDescription field is should NO longer
  346. // be used
  347. if (sDescription != NULL)
  348. {
  349. if (!CPHashData(hUID, hHash, (LPBYTE) sDescription,
  350. lstrlenW(sDescription) * sizeof(WCHAR), 0))
  351. {
  352. dwReturn = GetLastError(); // NTE_BAD_HASH
  353. goto ErrorExit;
  354. }
  355. }
  356. // check if this is a NULL hash (no data hashed) for X.9.31 format
  357. if (pTmpHash->dwHashState & DATA_IN_HASH)
  358. fDataInHash = TRUE;
  359. // now copy the hash into the input buffer
  360. cbTmpHash = pPubKey->keylen;
  361. if (!CPGetHashParam(hUID, hHash, HP_HASHVAL, rgbTmpHash, &cbTmpHash, 0))
  362. {
  363. dwReturn = GetLastError();
  364. goto ErrorExit;
  365. }
  366. pbInput = (BYTE *)_nt_malloc(pPubKey->keylen);
  367. if (pbInput == NULL)
  368. {
  369. dwReturn = ERROR_NOT_ENOUGH_MEMORY;
  370. goto ErrorExit;
  371. }
  372. if (dwFlags & CRYPT_X931_FORMAT)
  373. {
  374. // use X.9.31 padding for FIPS certification
  375. if (pTmpHash->Algid != CALG_SHA1)
  376. {
  377. dwReturn = (DWORD)NTE_BAD_ALGID;
  378. goto ErrorExit;
  379. }
  380. ApplyX931SigningFormat(cbSigLen,
  381. rgbTmpHash,
  382. cbTmpHash,
  383. fDataInHash,
  384. pbInput);
  385. }
  386. else
  387. {
  388. // use PKCS #1 padding
  389. dwSts = ApplyPKCS1SigningFormat(pPubKey, pTmpHash->Algid, rgbTmpHash,
  390. cbTmpHash, dwFlags, pbInput);
  391. if (ERROR_SUCCESS != dwSts)
  392. {
  393. dwReturn = dwSts;
  394. goto ErrorExit;
  395. }
  396. }
  397. // encrypt the hash value in input
  398. pbSigT = (BYTE *)_nt_malloc(pPubKey->keylen);
  399. if (NULL == pbSigT)
  400. {
  401. dwReturn = ERROR_NOT_ENOUGH_MEMORY;
  402. goto ErrorExit;
  403. }
  404. // load the appropriate key if necessary
  405. dwSts = UnprotectPrivKey(pTmpUser, szPrompt, fSigKey, FALSE);
  406. if (ERROR_SUCCESS != dwSts)
  407. {
  408. dwReturn = dwSts; // NTE_BAD_KEYSET
  409. goto ErrorExit;
  410. }
  411. // get the user's private key
  412. if (fSigKey)
  413. pPrivKey = (BSAFE_PRV_KEY *)pTmpUser->pSigPrivKey;
  414. else
  415. pPrivKey = (BSAFE_PRV_KEY *)pTmpUser->pExchPrivKey;
  416. if (pPrivKey == NULL)
  417. {
  418. dwReturn = (DWORD)NTE_NO_KEY;
  419. goto ErrorExit;
  420. }
  421. if (pPubKey->keylen != pPrivKey->keylen)
  422. {
  423. dwReturn = (DWORD)NTE_KEYSET_ENTRY_BAD;
  424. goto ErrorExit;
  425. }
  426. dwSts = RSAPrivateDecrypt(pTmpUser->pOffloadInfo, pPrivKey, pbInput,
  427. pbSigT);
  428. if (ERROR_SUCCESS != dwSts)
  429. {
  430. dwReturn = dwSts;
  431. goto ErrorExit;
  432. }
  433. memcpy(pbSignature, pbSigT, cbSigLen);
  434. *pdwSigLen = cbSigLen;
  435. dwReturn = ERROR_SUCCESS;
  436. ErrorExit:
  437. fRet = (ERROR_SUCCESS == dwReturn);
  438. if (pbSigT)
  439. _nt_free (pbSigT, pPubKey->keylen);
  440. if (pbInput)
  441. _nt_free(pbInput, pPubKey->keylen);
  442. if (!fRet)
  443. SetLastError(dwReturn);
  444. return fRet;
  445. }
  446. /*
  447. - VerifyPKCS1SigningFormat
  448. -
  449. * Purpose:
  450. * Check the format on a buffer to make sure the PKCS 1
  451. * formatting is correct.
  452. *
  453. */
  454. /*static*/ DWORD
  455. VerifyPKCS1SigningFormat(
  456. IN BSAFE_PUB_KEY *pKey,
  457. IN PNTAGHashList pTmpHash,
  458. IN BYTE *pbHash,
  459. IN DWORD cbHash,
  460. IN DWORD dwFlags,
  461. OUT BYTE *pbPKCS1Format)
  462. {
  463. DWORD dwReturn = ERROR_INTERNAL_ERROR;
  464. MD2_object *pMD2Hash;
  465. MD4_object *pMD4Hash;
  466. MD5_object *pMD5Hash;
  467. A_SHA_CTX *pSHAHash;
  468. BYTE *pbTmp;
  469. const BYTE **rgEncOptions;
  470. BYTE rgbTmpHash[SSL3_SHAMD5_LEN];
  471. DWORD i;
  472. DWORD cb;
  473. BYTE *pbStart;
  474. DWORD cbTmp;
  475. switch (pTmpHash->Algid)
  476. {
  477. #ifdef CSP_USE_MD2
  478. case CALG_MD2:
  479. pMD2Hash = (MD2_object *)pTmpHash->pHashData;
  480. pbTmp = (BYTE *) &(pMD2Hash->MD);
  481. rgEncOptions = md2Encodings;
  482. break;
  483. #endif
  484. #ifdef CSP_USE_MD4
  485. case CALG_MD4:
  486. pMD4Hash = (MD4_object *)pTmpHash->pHashData;
  487. pbTmp = (BYTE *) &(pMD4Hash->MD);
  488. rgEncOptions = md4Encodings;
  489. break;
  490. #endif
  491. #ifdef CSP_USE_MD5
  492. case CALG_MD5:
  493. pMD5Hash = (MD5_object *)pTmpHash->pHashData;
  494. pbTmp = (BYTE *)pMD5Hash->digest;
  495. rgEncOptions = md5Encodings;
  496. break;
  497. #endif
  498. #ifdef CSP_USE_SHA
  499. case CALG_SHA:
  500. pSHAHash = (A_SHA_CTX *)pTmpHash->pHashData;
  501. pbTmp = (BYTE *)pSHAHash->HashVal;
  502. rgEncOptions = shaEncodings;
  503. break;
  504. #endif
  505. #ifdef CSP_USE_SSL3SHAMD5
  506. case CALG_SSL3_SHAMD5:
  507. // Hash value must have already been set.
  508. if ((pTmpHash->HashFlags & HF_VALUE_SET) == 0)
  509. {
  510. dwReturn = (DWORD)NTE_BAD_HASH;
  511. goto ErrorExit;
  512. }
  513. pbTmp = pTmpHash->pHashData;
  514. rgEncOptions = NULL;
  515. break;
  516. #endif
  517. default:
  518. dwReturn = (DWORD)NTE_BAD_HASH;
  519. goto ErrorExit;
  520. }
  521. // Reverse the hash to match the signature.
  522. for (i = 0; i < cbHash; i++)
  523. rgbTmpHash[i] = pbHash[cbHash - (i + 1)];
  524. // See if it matches.
  525. if (0 != memcmp(rgbTmpHash, pbPKCS1Format, cbHash))
  526. {
  527. dwReturn = (DWORD)NTE_BAD_SIGNATURE;
  528. goto ErrorExit;
  529. }
  530. cb = cbHash;
  531. if (!(CRYPT_NOHASHOID & dwFlags))
  532. {
  533. // Check for any signature type identifiers
  534. if (rgEncOptions != NULL)
  535. {
  536. for (i = 0; 0 != *rgEncOptions[i]; i += 1)
  537. {
  538. pbStart = (LPBYTE)rgEncOptions[i];
  539. cbTmp = *pbStart++;
  540. if (0 == memcmp(&pbPKCS1Format[cb], pbStart, cbTmp))
  541. {
  542. cb += cbTmp; // Adjust the end of the hash data.
  543. break;
  544. }
  545. }
  546. }
  547. }
  548. // check to make sure the rest of the PKCS #1 padding is correct
  549. if ((0x00 != pbPKCS1Format[cb])
  550. || (0x00 != pbPKCS1Format[pKey->datalen])
  551. || (0x1 != pbPKCS1Format[pKey->datalen - 1]))
  552. {
  553. dwReturn = (DWORD)NTE_BAD_SIGNATURE;
  554. goto ErrorExit;
  555. }
  556. for (i = cb + 1; i < (DWORD)pKey->datalen - 1; i++)
  557. {
  558. if (0xff != pbPKCS1Format[i])
  559. {
  560. dwReturn = (DWORD)NTE_BAD_SIGNATURE;
  561. goto ErrorExit;
  562. }
  563. }
  564. dwReturn = ERROR_SUCCESS;
  565. ErrorExit:
  566. return dwReturn;
  567. }
  568. /*
  569. - VerifyX931SigningFormat
  570. -
  571. * Purpose:
  572. * Check the format on a buffer to make sure the X.9.31
  573. * formatting is correct.
  574. *
  575. */
  576. /*static*/ DWORD
  577. VerifyX931SigningFormat(
  578. IN BYTE *pbHash,
  579. IN DWORD cbHash,
  580. IN BOOL fDataInHash,
  581. IN BYTE *pbFormatted,
  582. IN DWORD cbFormatted)
  583. {
  584. DWORD dwReturn = ERROR_INTERNAL_ERROR;
  585. BYTE rgbTmpHash[SSL3_SHAMD5_LEN];
  586. DWORD i;
  587. // check P3
  588. if ((0xcc != pbFormatted[0]) || (0x33 != pbFormatted[1]) ||
  589. (0xba != pbFormatted[cbHash + 2]))
  590. {
  591. dwReturn = (DWORD)NTE_BAD_SIGNATURE;
  592. goto ErrorExit;
  593. }
  594. // Reverse the hash to match the signature and check if it matches.
  595. for (i = 0; i < cbHash; i++)
  596. rgbTmpHash[i] = pbHash[cbHash - (i + 1)];
  597. if (0 != memcmp(rgbTmpHash, pbFormatted + 2, cbHash))
  598. {
  599. dwReturn = (DWORD)NTE_BAD_SIGNATURE;
  600. goto ErrorExit;
  601. }
  602. // check P2
  603. for (i = 23; i < (cbFormatted - 24); i++)
  604. {
  605. if (0xbb != pbFormatted[i])
  606. {
  607. dwReturn = (DWORD)NTE_BAD_SIGNATURE;
  608. goto ErrorExit;
  609. }
  610. }
  611. // check P1
  612. if (fDataInHash)
  613. {
  614. if (0x6b != pbFormatted[cbFormatted - 1])
  615. {
  616. dwReturn = (DWORD)NTE_BAD_SIGNATURE;
  617. goto ErrorExit;
  618. }
  619. }
  620. else
  621. {
  622. if (0x4b != pbFormatted[cbFormatted - 1])
  623. {
  624. dwReturn = (DWORD)NTE_BAD_SIGNATURE;
  625. goto ErrorExit;
  626. }
  627. }
  628. dwReturn = ERROR_SUCCESS;
  629. ErrorExit:
  630. return dwReturn;
  631. }
  632. /*
  633. - CPVerifySignature
  634. -
  635. * Purpose:
  636. * Used to verify a signature against a hash object
  637. *
  638. *
  639. * Parameters:
  640. * IN hUID - Handle to the user identifcation
  641. * IN hHash - Handle to hash object
  642. * IN pbSignture - Pointer to signature data
  643. * IN dwSigLen - Length of the signature data
  644. * IN hPubKey - Handle to the public key for verifying
  645. * the signature
  646. * IN Algid - Algorithm identifier of the signature
  647. * algorithm to be used
  648. * IN sDescription - String describing the signed data
  649. * IN dwFlags - Flags values
  650. *
  651. * Returns:
  652. */
  653. BOOL WINAPI
  654. CPVerifySignature(
  655. IN HCRYPTPROV hUID,
  656. IN HCRYPTHASH hHash,
  657. IN CONST BYTE *pbSignature,
  658. IN DWORD dwSigLen,
  659. IN HCRYPTKEY hPubKey,
  660. IN LPCWSTR sDescription,
  661. IN DWORD dwFlags)
  662. {
  663. DWORD dwReturn = ERROR_INTERNAL_ERROR;
  664. PNTAGUserList pTmpUser;
  665. PNTAGHashList pTmpHash;
  666. PNTAGKeyList pPubKey;
  667. BSAFE_PUB_KEY *pKey;
  668. BYTE *pOutput = NULL;
  669. BSAFE_PUB_KEY *pBsafePubKey;
  670. BYTE *pbSigT = NULL;
  671. BYTE rgbTmpHash[SSL3_SHAMD5_LEN];
  672. DWORD cbTmpHash = SSL3_SHAMD5_LEN;
  673. DWORD cbLocalSigLen;
  674. BOOL fDataInHash = FALSE;
  675. BOOL fRet;
  676. DWORD dwSts;
  677. EntryPoint
  678. if ((dwFlags & ~(CRYPT_NOHASHOID | CRYPT_X931_FORMAT)) != 0)
  679. {
  680. dwReturn = (DWORD)NTE_BAD_FLAGS;
  681. goto ErrorExit;
  682. }
  683. // check the user identification
  684. pTmpUser = (PNTAGUserList)NTLCheckList(hUID, USER_HANDLE);
  685. if (NULL == pTmpUser)
  686. {
  687. dwReturn = (DWORD)NTE_BAD_UID;
  688. goto ErrorExit;
  689. }
  690. // check to see if the hash is in the hash list
  691. dwSts = NTLValidate(hHash, hUID, HASH_HANDLE, &pTmpHash);
  692. if (ERROR_SUCCESS != dwSts)
  693. {
  694. // NTLValidate doesn't know what error to set
  695. // so it set NTE_FAIL -- fix it up.
  696. dwReturn = (dwSts == NTE_FAIL) ? (DWORD)NTE_BAD_HASH : dwSts;
  697. goto ErrorExit;
  698. }
  699. if ((CALG_MD2 != pTmpHash->Algid) &&
  700. (CALG_MD4 != pTmpHash->Algid) &&
  701. (CALG_MD5 != pTmpHash->Algid) &&
  702. (CALG_SHA != pTmpHash->Algid) &&
  703. (CALG_SSL3_SHAMD5 != pTmpHash->Algid))
  704. {
  705. dwReturn = (DWORD)NTE_BAD_HASH;
  706. goto ErrorExit;
  707. }
  708. switch (HNTAG_TO_HTYPE((HNTAG)hPubKey))
  709. {
  710. case SIGPUBKEY_HANDLE:
  711. case EXCHPUBKEY_HANDLE:
  712. dwSts = NTLValidate((HNTAG)hPubKey,
  713. hUID, HNTAG_TO_HTYPE((HNTAG)hPubKey),
  714. &pPubKey);
  715. if (ERROR_SUCCESS != dwSts)
  716. {
  717. // NTLValidate doesn't know what error to set
  718. // so it set NTE_FAIL -- fix it up.
  719. dwReturn = (dwSts == NTE_FAIL) ? (DWORD)NTE_BAD_KEY : dwSts;
  720. goto ErrorExit;
  721. }
  722. break;
  723. default:
  724. dwReturn = (DWORD)NTE_BAD_KEY;
  725. goto ErrorExit;
  726. }
  727. pKey = (BSAFE_PUB_KEY *)pPubKey->pKeyValue;
  728. pBsafePubKey = (BSAFE_PUB_KEY *) pKey;
  729. cbLocalSigLen = (pBsafePubKey->bitlen+7)/8;
  730. if (dwSigLen != cbLocalSigLen)
  731. {
  732. dwReturn = (DWORD)NTE_BAD_SIGNATURE;
  733. goto ErrorExit;
  734. }
  735. pOutput = (BYTE *)_nt_malloc(pBsafePubKey->keylen);
  736. if (NULL == pOutput)
  737. {
  738. dwReturn = ERROR_NOT_ENOUGH_MEMORY;
  739. goto ErrorExit;
  740. }
  741. // encrypt the hash value in output
  742. pbSigT = (BYTE *)_nt_malloc(pBsafePubKey->keylen);
  743. if (NULL == pbSigT)
  744. {
  745. dwReturn = ERROR_NOT_ENOUGH_MEMORY;
  746. goto ErrorExit;
  747. }
  748. memset(pbSigT, 0, pBsafePubKey->keylen);
  749. memcpy(pbSigT, pbSignature, cbLocalSigLen);
  750. dwSts = RSAPublicEncrypt(pTmpUser->pOffloadInfo, pBsafePubKey,
  751. pbSigT, pOutput);
  752. if (ERROR_SUCCESS != dwSts)
  753. {
  754. dwReturn = dwSts; // NTE_BAD_SIGNATURE
  755. goto ErrorExit;
  756. }
  757. // WARNING: due to vulnerabilities sDescription field is should NO longer
  758. // be used
  759. if (sDescription != NULL)
  760. {
  761. if (!CPHashData(hUID, hHash, (LPBYTE) sDescription,
  762. lstrlenW(sDescription) * sizeof(WCHAR), 0))
  763. {
  764. dwReturn = GetLastError();
  765. goto ErrorExit;
  766. }
  767. }
  768. // check if this is a NULL hash (no data hashed) for X.9.31 format
  769. if (pTmpHash->dwHashState & DATA_IN_HASH)
  770. fDataInHash = TRUE;
  771. if (!CPGetHashParam(hUID, hHash, HP_HASHVAL, rgbTmpHash, &cbTmpHash, 0))
  772. {
  773. dwReturn = GetLastError();
  774. goto ErrorExit;
  775. }
  776. if (dwFlags & CRYPT_X931_FORMAT)
  777. {
  778. // use X.9.31 padding for FIPS certification
  779. dwSts = VerifyX931SigningFormat(rgbTmpHash, cbTmpHash,
  780. fDataInHash, pOutput,
  781. (pBsafePubKey->bitlen + 7) / 8);
  782. if (ERROR_SUCCESS != dwSts)
  783. {
  784. dwReturn = dwSts;
  785. goto ErrorExit;
  786. }
  787. }
  788. else
  789. {
  790. // use PKCS #1 padding
  791. dwSts = VerifyPKCS1SigningFormat(pKey, pTmpHash, rgbTmpHash,
  792. cbTmpHash, dwFlags, pOutput);
  793. if (ERROR_SUCCESS != dwSts)
  794. {
  795. dwReturn = dwSts;
  796. goto ErrorExit;
  797. }
  798. }
  799. dwReturn = ERROR_SUCCESS;
  800. ErrorExit:
  801. fRet = (ERROR_SUCCESS == dwReturn);
  802. if (pbSigT)
  803. _nt_free(pbSigT, pBsafePubKey->keylen);
  804. if (pOutput)
  805. _nt_free(pOutput, pBsafePubKey->keylen);
  806. if (!fRet)
  807. SetLastError(dwReturn);
  808. return fRet;
  809. }