source: trunk/src/crypt32/message.c@ 21311

Last change on this file since 21311 was 21311, checked in by vladest, 16 years ago

Added CRYPT32 and MSCMS APIs support

File size: 13.0 KB
Line 
1/*
2 * Copyright 2007 Juan Lang
3 *
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation; either
7 * version 2.1 of the License, or (at your option) any later version.
8 *
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Lesser General Public License for more details.
13 *
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with this library; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
17 */
18
19#include <stdarg.h>
20#include "windef.h"
21#include "winbase.h"
22#include "winerror.h"
23#include "wincrypt.h"
24
25#include "wine/debug.h"
26
27WINE_DEFAULT_DEBUG_CHANNEL(crypt);
28
29HCERTSTORE WINAPI CryptGetMessageCertificates(DWORD dwMsgAndCertEncodingType,
30 HCRYPTPROV_LEGACY hCryptProv, DWORD dwFlags, const BYTE* pbSignedBlob,
31 DWORD cbSignedBlob)
32{
33 CRYPT_DATA_BLOB blob = { cbSignedBlob, (LPBYTE)pbSignedBlob };
34
35 TRACE("(%08x, %ld, %d08x %p, %d)\n", dwMsgAndCertEncodingType, hCryptProv,
36 dwFlags, pbSignedBlob, cbSignedBlob);
37
38 return CertOpenStore(CERT_STORE_PROV_PKCS7, dwMsgAndCertEncodingType,
39 hCryptProv, dwFlags, &blob);
40}
41
42LONG WINAPI CryptGetMessageSignerCount(DWORD dwMsgEncodingType,
43 const BYTE *pbSignedBlob, DWORD cbSignedBlob)
44{
45 HCRYPTMSG msg;
46 LONG count = -1;
47
48 TRACE("(%08x, %p, %d)\n", dwMsgEncodingType, pbSignedBlob, cbSignedBlob);
49
50 msg = CryptMsgOpenToDecode(dwMsgEncodingType, 0, 0, 0, NULL, NULL);
51 if (msg)
52 {
53 if (CryptMsgUpdate(msg, pbSignedBlob, cbSignedBlob, TRUE))
54 {
55 DWORD size = sizeof(count);
56
57 CryptMsgGetParam(msg, CMSG_SIGNER_COUNT_PARAM, 0, &count, &size);
58 }
59 CryptMsgClose(msg);
60 }
61 return count;
62}
63
64static CERT_INFO *CRYPT_GetSignerCertInfoFromMsg(HCRYPTMSG msg,
65 DWORD dwSignerIndex)
66{
67 CERT_INFO *certInfo = NULL;
68 DWORD size;
69
70 if (CryptMsgGetParam(msg, CMSG_SIGNER_CERT_INFO_PARAM, dwSignerIndex, NULL,
71 &size))
72 {
73 certInfo = CryptMemAlloc(size);
74 if (certInfo)
75 {
76 if (!CryptMsgGetParam(msg, CMSG_SIGNER_CERT_INFO_PARAM,
77 dwSignerIndex, certInfo, &size))
78 {
79 CryptMemFree(certInfo);
80 certInfo = NULL;
81 }
82 }
83 }
84 else
85 SetLastError(CRYPT_E_UNEXPECTED_MSG_TYPE);
86 return certInfo;
87}
88
89static PCCERT_CONTEXT WINAPI CRYPT_DefaultGetSignerCertificate(void *pvGetArg,
90 DWORD dwCertEncodingType, PCERT_INFO pSignerId, HCERTSTORE hMsgCertStore)
91{
92 return CertFindCertificateInStore(hMsgCertStore, dwCertEncodingType, 0,
93 CERT_FIND_SUBJECT_CERT, pSignerId, NULL);
94}
95
96static inline PCCERT_CONTEXT CRYPT_GetSignerCertificate(HCRYPTMSG msg,
97 PCRYPT_VERIFY_MESSAGE_PARA pVerifyPara, PCERT_INFO certInfo, HCERTSTORE store)
98{
99 PFN_CRYPT_GET_SIGNER_CERTIFICATE getCert;
100
101 if (pVerifyPara->pfnGetSignerCertificate)
102 getCert = pVerifyPara->pfnGetSignerCertificate;
103 else
104 getCert = CRYPT_DefaultGetSignerCertificate;
105 return getCert(pVerifyPara->pvGetArg,
106 pVerifyPara->dwMsgAndCertEncodingType, certInfo, store);
107}
108
109BOOL WINAPI CryptVerifyDetachedMessageSignature(
110 PCRYPT_VERIFY_MESSAGE_PARA pVerifyPara, DWORD dwSignerIndex,
111 const BYTE *pbDetachedSignBlob, DWORD cbDetachedSignBlob, DWORD cToBeSigned,
112 const BYTE *rgpbToBeSigned[], DWORD rgcbToBeSigned[],
113 PCCERT_CONTEXT *ppSignerCert)
114{
115 BOOL ret = FALSE;
116 HCRYPTMSG msg;
117
118 TRACE("(%p, %d, %p, %d, %d, %p, %p, %p)\n", pVerifyPara, dwSignerIndex,
119 pbDetachedSignBlob, cbDetachedSignBlob, cToBeSigned, rgpbToBeSigned,
120 rgcbToBeSigned, ppSignerCert);
121
122 if (ppSignerCert)
123 *ppSignerCert = NULL;
124 if (!pVerifyPara ||
125 pVerifyPara->cbSize != sizeof(CRYPT_VERIFY_MESSAGE_PARA) ||
126 GET_CMSG_ENCODING_TYPE(pVerifyPara->dwMsgAndCertEncodingType) !=
127 PKCS_7_ASN_ENCODING)
128 {
129 SetLastError(E_INVALIDARG);
130 return FALSE;
131 }
132
133 msg = CryptMsgOpenToDecode(pVerifyPara->dwMsgAndCertEncodingType,
134 CMSG_DETACHED_FLAG, 0, pVerifyPara->hCryptProv, NULL, NULL);
135 if (msg)
136 {
137 ret = CryptMsgUpdate(msg, pbDetachedSignBlob, cbDetachedSignBlob, TRUE);
138 if (ret)
139 {
140 DWORD i;
141
142 for (i = 0; ret && i < cToBeSigned; i++)
143 ret = CryptMsgUpdate(msg, rgpbToBeSigned[i], rgcbToBeSigned[i],
144 i == cToBeSigned - 1 ? TRUE : FALSE);
145 }
146 if (ret)
147 {
148 CERT_INFO *certInfo = CRYPT_GetSignerCertInfoFromMsg(msg,
149 dwSignerIndex);
150
151 ret = FALSE;
152 if (certInfo)
153 {
154 HCERTSTORE store = CertOpenStore(CERT_STORE_PROV_MSG,
155 pVerifyPara->dwMsgAndCertEncodingType,
156 pVerifyPara->hCryptProv, 0, msg);
157
158 if (store)
159 {
160 PCCERT_CONTEXT cert = CRYPT_GetSignerCertificate(
161 msg, pVerifyPara, certInfo, store);
162
163 if (cert)
164 {
165 ret = CryptMsgControl(msg, 0,
166 CMSG_CTRL_VERIFY_SIGNATURE, cert->pCertInfo);
167 if (ret && ppSignerCert)
168 *ppSignerCert = cert;
169 else
170 CertFreeCertificateContext(cert);
171 }
172 else
173 SetLastError(CRYPT_E_NOT_FOUND);
174 CertCloseStore(store, 0);
175 }
176 CryptMemFree(certInfo);
177 }
178 }
179 CryptMsgClose(msg);
180 }
181 TRACE("returning %d\n", ret);
182 return ret;
183}
184
185BOOL WINAPI CryptVerifyMessageSignature(PCRYPT_VERIFY_MESSAGE_PARA pVerifyPara,
186 DWORD dwSignerIndex, const BYTE* pbSignedBlob, DWORD cbSignedBlob,
187 BYTE* pbDecoded, DWORD* pcbDecoded, PCCERT_CONTEXT* ppSignerCert)
188{
189 BOOL ret = FALSE;
190 HCRYPTMSG msg;
191
192 TRACE("(%p, %d, %p, %d, %p, %p, %p)\n",
193 pVerifyPara, dwSignerIndex, pbSignedBlob, cbSignedBlob,
194 pbDecoded, pcbDecoded, ppSignerCert);
195
196 if (ppSignerCert)
197 *ppSignerCert = NULL;
198 if (pcbDecoded)
199 *pcbDecoded = 0;
200 if (!pVerifyPara ||
201 pVerifyPara->cbSize != sizeof(CRYPT_VERIFY_MESSAGE_PARA) ||
202 GET_CMSG_ENCODING_TYPE(pVerifyPara->dwMsgAndCertEncodingType) !=
203 PKCS_7_ASN_ENCODING)
204 {
205 SetLastError(E_INVALIDARG);
206 return FALSE;
207 }
208
209 msg = CryptMsgOpenToDecode(pVerifyPara->dwMsgAndCertEncodingType, 0, 0,
210 pVerifyPara->hCryptProv, NULL, NULL);
211 if (msg)
212 {
213 ret = CryptMsgUpdate(msg, pbSignedBlob, cbSignedBlob, TRUE);
214 if (ret && pcbDecoded)
215 ret = CryptMsgGetParam(msg, CMSG_CONTENT_PARAM, 0, pbDecoded,
216 pcbDecoded);
217 if (ret)
218 {
219 CERT_INFO *certInfo = CRYPT_GetSignerCertInfoFromMsg(msg,
220 dwSignerIndex);
221
222 ret = FALSE;
223 if (certInfo)
224 {
225 HCERTSTORE store = CertOpenStore(CERT_STORE_PROV_MSG,
226 pVerifyPara->dwMsgAndCertEncodingType,
227 pVerifyPara->hCryptProv, 0, msg);
228
229 if (store)
230 {
231 PCCERT_CONTEXT cert = CRYPT_GetSignerCertificate(
232 msg, pVerifyPara, certInfo, store);
233
234 if (cert)
235 {
236 ret = CryptMsgControl(msg, 0,
237 CMSG_CTRL_VERIFY_SIGNATURE, cert->pCertInfo);
238 if (ret && ppSignerCert)
239 *ppSignerCert = cert;
240 else
241 CertFreeCertificateContext(cert);
242 }
243 CertCloseStore(store, 0);
244 }
245 }
246 CryptMemFree(certInfo);
247 }
248 CryptMsgClose(msg);
249 }
250 TRACE("returning %d\n", ret);
251 return ret;
252}
253
254BOOL WINAPI CryptHashMessage(PCRYPT_HASH_MESSAGE_PARA pHashPara,
255 BOOL fDetachedHash, DWORD cToBeHashed, const BYTE *rgpbToBeHashed[],
256 DWORD rgcbToBeHashed[], BYTE *pbHashedBlob, DWORD *pcbHashedBlob,
257 BYTE *pbComputedHash, DWORD *pcbComputedHash)
258{
259 DWORD i, flags;
260 BOOL ret = FALSE;
261 HCRYPTMSG msg;
262 CMSG_HASHED_ENCODE_INFO info;
263
264 TRACE("(%p, %d, %d, %p, %p, %p, %p, %p, %p)\n", pHashPara, fDetachedHash,
265 cToBeHashed, rgpbToBeHashed, rgcbToBeHashed, pbHashedBlob, pcbHashedBlob,
266 pbComputedHash, pcbComputedHash);
267
268 if (pHashPara->cbSize != sizeof(CRYPT_HASH_MESSAGE_PARA))
269 {
270 SetLastError(E_INVALIDARG);
271 return FALSE;
272 }
273 /* Native seems to ignore any encoding type other than the expected
274 * PKCS_7_ASN_ENCODING
275 */
276 if (GET_CMSG_ENCODING_TYPE(pHashPara->dwMsgEncodingType) !=
277 PKCS_7_ASN_ENCODING)
278 return TRUE;
279 /* Native also seems to do nothing if the output parameter isn't given */
280 if (!pcbHashedBlob)
281 return TRUE;
282
283 flags = fDetachedHash ? CMSG_DETACHED_FLAG : 0;
284 memset(&info, 0, sizeof(info));
285 info.cbSize = sizeof(info);
286 info.hCryptProv = pHashPara->hCryptProv;
287 memcpy(&info.HashAlgorithm, &pHashPara->HashAlgorithm,
288 sizeof(info.HashAlgorithm));
289 info.pvHashAuxInfo = pHashPara->pvHashAuxInfo;
290 msg = CryptMsgOpenToEncode(pHashPara->dwMsgEncodingType, flags, CMSG_HASHED,
291 &info, NULL, NULL);
292 if (msg)
293 {
294 for (i = 0, ret = TRUE; ret && i < cToBeHashed; i++)
295 ret = CryptMsgUpdate(msg, rgpbToBeHashed[i], rgcbToBeHashed[i],
296 i == cToBeHashed - 1 ? TRUE : FALSE);
297 if (ret)
298 {
299 ret = CryptMsgGetParam(msg, CMSG_CONTENT_PARAM, 0, pbHashedBlob,
300 pcbHashedBlob);
301 if (ret && pcbComputedHash)
302 ret = CryptMsgGetParam(msg, CMSG_COMPUTED_HASH_PARAM, 0,
303 pbComputedHash, pcbComputedHash);
304 }
305 CryptMsgClose(msg);
306 }
307 return ret;
308}
309
310BOOL WINAPI CryptVerifyDetachedMessageHash(PCRYPT_HASH_MESSAGE_PARA pHashPara,
311 BYTE *pbDetachedHashBlob, DWORD cbDetachedHashBlob, DWORD cToBeHashed,
312 const BYTE *rgpbToBeHashed[], DWORD rgcbToBeHashed[], BYTE *pbComputedHash,
313 DWORD *pcbComputedHash)
314{
315 HCRYPTMSG msg;
316 BOOL ret = FALSE;
317
318 TRACE("(%p, %p, %d, %d, %p, %p, %p, %p)\n", pHashPara, pbDetachedHashBlob,
319 cbDetachedHashBlob, cToBeHashed, rgpbToBeHashed, rgcbToBeHashed,
320 pbComputedHash, pcbComputedHash);
321
322 if (pHashPara->cbSize != sizeof(CRYPT_HASH_MESSAGE_PARA))
323 {
324 SetLastError(E_INVALIDARG);
325 return FALSE;
326 }
327 if (GET_CMSG_ENCODING_TYPE(pHashPara->dwMsgEncodingType) !=
328 PKCS_7_ASN_ENCODING)
329 {
330 SetLastError(E_INVALIDARG);
331 return FALSE;
332 }
333 msg = CryptMsgOpenToDecode(pHashPara->dwMsgEncodingType, CMSG_DETACHED_FLAG,
334 0, pHashPara->hCryptProv, NULL, NULL);
335 if (msg)
336 {
337 DWORD i;
338
339 ret = CryptMsgUpdate(msg, pbDetachedHashBlob, cbDetachedHashBlob, TRUE);
340 if (ret)
341 {
342 if (cToBeHashed)
343 {
344 for (i = 0; ret && i < cToBeHashed; i++)
345 {
346 ret = CryptMsgUpdate(msg, rgpbToBeHashed[i],
347 rgcbToBeHashed[i], i == cToBeHashed - 1 ? TRUE : FALSE);
348 }
349 }
350 else
351 ret = CryptMsgUpdate(msg, NULL, 0, TRUE);
352 }
353 if (ret)
354 {
355 ret = CryptMsgControl(msg, 0, CMSG_CTRL_VERIFY_HASH, NULL);
356 if (ret && pcbComputedHash)
357 ret = CryptMsgGetParam(msg, CMSG_COMPUTED_HASH_PARAM, 0,
358 pbComputedHash, pcbComputedHash);
359 }
360 CryptMsgClose(msg);
361 }
362 return ret;
363}
364
365BOOL WINAPI CryptVerifyMessageHash(PCRYPT_HASH_MESSAGE_PARA pHashPara,
366 BYTE *pbHashedBlob, DWORD cbHashedBlob, BYTE *pbToBeHashed,
367 DWORD *pcbToBeHashed, BYTE *pbComputedHash, DWORD *pcbComputedHash)
368{
369 HCRYPTMSG msg;
370 BOOL ret = FALSE;
371
372 TRACE("(%p, %p, %d, %p, %p, %p, %p)\n", pHashPara, pbHashedBlob,
373 cbHashedBlob, pbToBeHashed, pcbToBeHashed, pbComputedHash,
374 pcbComputedHash);
375
376 if (pHashPara->cbSize != sizeof(CRYPT_HASH_MESSAGE_PARA))
377 {
378 SetLastError(E_INVALIDARG);
379 return FALSE;
380 }
381 if (GET_CMSG_ENCODING_TYPE(pHashPara->dwMsgEncodingType) !=
382 PKCS_7_ASN_ENCODING)
383 {
384 SetLastError(E_INVALIDARG);
385 return FALSE;
386 }
387 msg = CryptMsgOpenToDecode(pHashPara->dwMsgEncodingType, 0, 0,
388 pHashPara->hCryptProv, NULL, NULL);
389 if (msg)
390 {
391 ret = CryptMsgUpdate(msg, pbHashedBlob, cbHashedBlob, TRUE);
392 if (ret)
393 {
394 ret = CryptMsgControl(msg, 0, CMSG_CTRL_VERIFY_HASH, NULL);
395 if (ret && pcbToBeHashed)
396 ret = CryptMsgGetParam(msg, CMSG_CONTENT_PARAM, 0,
397 pbToBeHashed, pcbToBeHashed);
398 if (ret && pcbComputedHash)
399 ret = CryptMsgGetParam(msg, CMSG_COMPUTED_HASH_PARAM, 0,
400 pbComputedHash, pcbComputedHash);
401 }
402 CryptMsgClose(msg);
403 }
404 return ret;
405}
Note: See TracBrowser for help on using the repository browser.