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.

263 lines
6.5 KiB

  1. //+---------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. // Copyright (C) Microsoft Corporation, 1992 - 1995.
  5. //
  6. // File: sigsys.c
  7. //
  8. // Contents:
  9. //
  10. // Classes:
  11. //
  12. // Functions:
  13. //
  14. // History: 09-23-97 jbanes LSA integration stuff.
  15. //
  16. //----------------------------------------------------------------------------
  17. #include <spbase.h>
  18. #include <wincrypt.h>
  19. #include <ssl2msg.h>
  20. #include <ssl3msg.h>
  21. SP_STATUS
  22. SPVerifySignature(
  23. HCRYPTPROV hProv,
  24. DWORD dwCapiFlags,
  25. PPUBLICKEY pPublic,
  26. ALG_ID aiHash,
  27. PBYTE pbData,
  28. DWORD cbData,
  29. PBYTE pbSig,
  30. DWORD cbSig,
  31. BOOL fHashData)
  32. {
  33. HCRYPTKEY hPublicKey = 0;
  34. HCRYPTHASH hHash = 0;
  35. PBYTE pbSigBuff = NULL;
  36. SP_STATUS pctRet;
  37. if(hProv == 0 || pPublic == NULL)
  38. {
  39. pctRet = SP_LOG_RESULT(PCT_INT_INTERNAL_ERROR);
  40. goto cleanup;
  41. }
  42. pbSigBuff = SPExternalAlloc(cbSig);
  43. if(pbSigBuff == NULL)
  44. {
  45. pctRet = SP_LOG_RESULT(SEC_E_INSUFFICIENT_MEMORY);
  46. goto cleanup;
  47. }
  48. //
  49. // Create public key.
  50. //
  51. if(!SchCryptImportKey(hProv,
  52. (PBYTE)pPublic->pPublic,
  53. pPublic->cbPublic,
  54. 0, 0,
  55. &hPublicKey,
  56. dwCapiFlags))
  57. {
  58. SP_LOG_RESULT(GetLastError());
  59. pctRet = PCT_ERR_ILLEGAL_MESSAGE;
  60. goto cleanup;
  61. }
  62. //
  63. // Hash data.
  64. //
  65. if(!SchCryptCreateHash(hProv, aiHash, 0, 0, &hHash, dwCapiFlags))
  66. {
  67. SP_LOG_RESULT(GetLastError());
  68. pctRet = PCT_ERR_ILLEGAL_MESSAGE;
  69. goto cleanup;
  70. }
  71. if(!fHashData)
  72. {
  73. // set hash value
  74. if(!SchCryptSetHashParam(hHash, HP_HASHVAL, pbData, 0, dwCapiFlags))
  75. {
  76. SP_LOG_RESULT(GetLastError());
  77. pctRet = PCT_ERR_ILLEGAL_MESSAGE;
  78. goto cleanup;
  79. }
  80. }
  81. else
  82. {
  83. if(!SchCryptHashData(hHash, pbData, cbData, 0, dwCapiFlags))
  84. {
  85. SP_LOG_RESULT(GetLastError());
  86. pctRet = PCT_ERR_ILLEGAL_MESSAGE;
  87. goto cleanup;
  88. }
  89. }
  90. if(pPublic->pPublic->aiKeyAlg == CALG_DSS_SIGN)
  91. {
  92. BYTE rgbTempSig[DSA_SIGNATURE_SIZE];
  93. DWORD cbTempSig;
  94. // Remove DSS ASN1 goo around signature and convert it to
  95. // little endian.
  96. cbTempSig = sizeof(rgbTempSig);
  97. if(!CryptDecodeObject(X509_ASN_ENCODING,
  98. X509_DSS_SIGNATURE,
  99. pbSig,
  100. cbSig,
  101. 0,
  102. rgbTempSig,
  103. &cbTempSig))
  104. {
  105. SP_LOG_RESULT(GetLastError());
  106. pctRet = PCT_ERR_ILLEGAL_MESSAGE;
  107. goto cleanup;
  108. }
  109. memcpy(pbSigBuff, rgbTempSig, cbTempSig);
  110. cbSig = cbTempSig;
  111. }
  112. else
  113. {
  114. // Convert signature to little endian.
  115. ReverseMemCopy(pbSigBuff, pbSig, cbSig);
  116. }
  117. if(!SchCryptVerifySignature(hHash,
  118. pbSigBuff,
  119. cbSig,
  120. hPublicKey,
  121. NULL, 0,
  122. dwCapiFlags))
  123. {
  124. DebugLog((DEB_WARN, "Signature Verify Failed: %x\n", GetLastError()));
  125. pctRet = SP_LOG_RESULT(PCT_INT_MSG_ALTERED);
  126. goto cleanup;
  127. }
  128. pctRet = PCT_ERR_OK;
  129. cleanup:
  130. if(hPublicKey)
  131. {
  132. SchCryptDestroyKey(hPublicKey, dwCapiFlags);
  133. }
  134. if(hHash)
  135. {
  136. SchCryptDestroyHash(hHash, dwCapiFlags);
  137. }
  138. if(pbSigBuff != NULL)
  139. {
  140. SPExternalFree(pbSigBuff);
  141. }
  142. return pctRet;
  143. }
  144. SP_STATUS
  145. SignHashUsingCred(
  146. PSPCredential pCred,
  147. ALG_ID aiHash,
  148. PBYTE pbHash,
  149. DWORD cbHash,
  150. PBYTE pbSignature,
  151. PDWORD pcbSignature)
  152. {
  153. HCRYPTHASH hHash;
  154. DWORD cbSignatureBuffer;
  155. SP_STATUS pctRet;
  156. if(pCred == NULL)
  157. {
  158. return SP_LOG_RESULT(PCT_INT_INTERNAL_ERROR);
  159. }
  160. cbSignatureBuffer = *pcbSignature;
  161. if(pCred->hProv)
  162. {
  163. // Sign hash using local CSP handle.
  164. if(!CryptCreateHash(pCred->hProv, aiHash, 0, 0, &hHash))
  165. {
  166. SP_LOG_RESULT(GetLastError());
  167. return PCT_ERR_ILLEGAL_MESSAGE;
  168. }
  169. if(!CryptSetHashParam(hHash, HP_HASHVAL, pbHash, 0))
  170. {
  171. SP_LOG_RESULT(GetLastError());
  172. CryptDestroyHash(hHash);
  173. return PCT_ERR_ILLEGAL_MESSAGE;
  174. }
  175. if(!CryptSignHash(hHash, pCred->dwKeySpec, NULL, 0, pbSignature, pcbSignature))
  176. {
  177. SP_LOG_RESULT(GetLastError());
  178. CryptDestroyHash(hHash);
  179. return PCT_ERR_ILLEGAL_MESSAGE;
  180. }
  181. CryptDestroyHash(hHash);
  182. }
  183. else if(pCred->hRemoteProv)
  184. {
  185. // Sign hash via a call to the application process.
  186. pctRet = SignHashUsingCallback(pCred->hRemoteProv,
  187. pCred->dwKeySpec,
  188. aiHash,
  189. pbHash,
  190. cbHash,
  191. pbSignature,
  192. pcbSignature,
  193. FALSE);
  194. if(pctRet != PCT_ERR_OK)
  195. {
  196. return SP_LOG_RESULT(pctRet);
  197. }
  198. }
  199. else
  200. {
  201. DebugLog((DEB_ERROR, "We have no key with which to sign!\n"));
  202. return SP_LOG_RESULT(PCT_INT_INTERNAL_ERROR);
  203. }
  204. if(pCred->dwExchSpec == SP_EXCH_DH_PKCS3)
  205. {
  206. BYTE rgbTempSig[DSA_SIGNATURE_SIZE];
  207. // Add DSS ASN1 goo around signature.
  208. if(*pcbSignature != DSA_SIGNATURE_SIZE)
  209. {
  210. return SP_LOG_RESULT(PCT_ERR_ILLEGAL_MESSAGE);
  211. }
  212. memcpy(rgbTempSig, pbSignature, DSA_SIGNATURE_SIZE);
  213. *pcbSignature = cbSignatureBuffer;
  214. if(!CryptEncodeObject(X509_ASN_ENCODING,
  215. X509_DSS_SIGNATURE,
  216. rgbTempSig,
  217. pbSignature,
  218. pcbSignature))
  219. {
  220. SP_LOG_RESULT(GetLastError());
  221. return PCT_ERR_ILLEGAL_MESSAGE;
  222. }
  223. }
  224. else
  225. {
  226. // Convert signature to big endian.
  227. ReverseInPlace(pbSignature, *pcbSignature);
  228. }
  229. return PCT_ERR_OK;
  230. }