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.

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