xref: /reactos/dll/win32/crypt32/message.c (revision a6e10342)
1c2c66affSColin Finck /*
2c2c66affSColin Finck  * Copyright 2007 Juan Lang
3c2c66affSColin Finck  *
4c2c66affSColin Finck  * This library is free software; you can redistribute it and/or
5c2c66affSColin Finck  * modify it under the terms of the GNU Lesser General Public
6c2c66affSColin Finck  * License as published by the Free Software Foundation; either
7c2c66affSColin Finck  * version 2.1 of the License, or (at your option) any later version.
8c2c66affSColin Finck  *
9c2c66affSColin Finck  * This library is distributed in the hope that it will be useful,
10c2c66affSColin Finck  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11c2c66affSColin Finck  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12c2c66affSColin Finck  * Lesser General Public License for more details.
13c2c66affSColin Finck  *
14c2c66affSColin Finck  * You should have received a copy of the GNU Lesser General Public
15c2c66affSColin Finck  * License along with this library; if not, write to the Free Software
16c2c66affSColin Finck  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
17c2c66affSColin Finck  */
18c2c66affSColin Finck 
19*a6e10342SAmine Khaldi #include <stdarg.h>
20*a6e10342SAmine Khaldi #include "windef.h"
21*a6e10342SAmine Khaldi #include "winbase.h"
22*a6e10342SAmine Khaldi #include "wincrypt.h"
23*a6e10342SAmine Khaldi 
24*a6e10342SAmine Khaldi #include "wine/debug.h"
25c2c66affSColin Finck 
26c2c66affSColin Finck WINE_DEFAULT_DEBUG_CHANNEL(crypt);
27c2c66affSColin Finck 
CryptGetMessageCertificates(DWORD dwMsgAndCertEncodingType,HCRYPTPROV_LEGACY hCryptProv,DWORD dwFlags,const BYTE * pbSignedBlob,DWORD cbSignedBlob)28c2c66affSColin Finck HCERTSTORE WINAPI CryptGetMessageCertificates(DWORD dwMsgAndCertEncodingType,
29c2c66affSColin Finck  HCRYPTPROV_LEGACY hCryptProv, DWORD dwFlags, const BYTE* pbSignedBlob,
30c2c66affSColin Finck  DWORD cbSignedBlob)
31c2c66affSColin Finck {
32c2c66affSColin Finck     CRYPT_DATA_BLOB blob = { cbSignedBlob, (LPBYTE)pbSignedBlob };
33c2c66affSColin Finck 
34c2c66affSColin Finck     TRACE("(%08x, %ld, %d08x %p, %d)\n", dwMsgAndCertEncodingType, hCryptProv,
35c2c66affSColin Finck      dwFlags, pbSignedBlob, cbSignedBlob);
36c2c66affSColin Finck 
37c2c66affSColin Finck     return CertOpenStore(CERT_STORE_PROV_PKCS7, dwMsgAndCertEncodingType,
38c2c66affSColin Finck      hCryptProv, dwFlags, &blob);
39c2c66affSColin Finck }
40c2c66affSColin Finck 
CryptGetMessageSignerCount(DWORD dwMsgEncodingType,const BYTE * pbSignedBlob,DWORD cbSignedBlob)41c2c66affSColin Finck LONG WINAPI CryptGetMessageSignerCount(DWORD dwMsgEncodingType,
42c2c66affSColin Finck  const BYTE *pbSignedBlob, DWORD cbSignedBlob)
43c2c66affSColin Finck {
44c2c66affSColin Finck     HCRYPTMSG msg;
45c2c66affSColin Finck     LONG count = -1;
46c2c66affSColin Finck 
47c2c66affSColin Finck     TRACE("(%08x, %p, %d)\n", dwMsgEncodingType, pbSignedBlob, cbSignedBlob);
48c2c66affSColin Finck 
49c2c66affSColin Finck     msg = CryptMsgOpenToDecode(dwMsgEncodingType, 0, 0, 0, NULL, NULL);
50c2c66affSColin Finck     if (msg)
51c2c66affSColin Finck     {
52c2c66affSColin Finck         if (CryptMsgUpdate(msg, pbSignedBlob, cbSignedBlob, TRUE))
53c2c66affSColin Finck         {
54c2c66affSColin Finck             DWORD size = sizeof(count);
55c2c66affSColin Finck 
56c2c66affSColin Finck             CryptMsgGetParam(msg, CMSG_SIGNER_COUNT_PARAM, 0, &count, &size);
57c2c66affSColin Finck         }
58c2c66affSColin Finck         CryptMsgClose(msg);
59c2c66affSColin Finck     }
60c2c66affSColin Finck     return count;
61c2c66affSColin Finck }
62c2c66affSColin Finck 
CRYPT_GetSignerCertInfoFromMsg(HCRYPTMSG msg,DWORD dwSignerIndex)63c2c66affSColin Finck static CERT_INFO *CRYPT_GetSignerCertInfoFromMsg(HCRYPTMSG msg,
64c2c66affSColin Finck  DWORD dwSignerIndex)
65c2c66affSColin Finck {
66c2c66affSColin Finck     CERT_INFO *certInfo = NULL;
67c2c66affSColin Finck     DWORD size;
68c2c66affSColin Finck 
69c2c66affSColin Finck     if (CryptMsgGetParam(msg, CMSG_SIGNER_CERT_INFO_PARAM, dwSignerIndex, NULL,
70c2c66affSColin Finck      &size))
71c2c66affSColin Finck     {
72c2c66affSColin Finck         certInfo = CryptMemAlloc(size);
73c2c66affSColin Finck         if (certInfo)
74c2c66affSColin Finck         {
75c2c66affSColin Finck             if (!CryptMsgGetParam(msg, CMSG_SIGNER_CERT_INFO_PARAM,
76c2c66affSColin Finck              dwSignerIndex, certInfo, &size))
77c2c66affSColin Finck             {
78c2c66affSColin Finck                 CryptMemFree(certInfo);
79c2c66affSColin Finck                 certInfo = NULL;
80c2c66affSColin Finck             }
81c2c66affSColin Finck         }
82c2c66affSColin Finck     }
83c2c66affSColin Finck     else
84c2c66affSColin Finck         SetLastError(CRYPT_E_UNEXPECTED_MSG_TYPE);
85c2c66affSColin Finck     return certInfo;
86c2c66affSColin Finck }
87c2c66affSColin Finck 
CRYPT_DefaultGetSignerCertificate(void * pvGetArg,DWORD dwCertEncodingType,PCERT_INFO pSignerId,HCERTSTORE hMsgCertStore)88c2c66affSColin Finck static PCCERT_CONTEXT WINAPI CRYPT_DefaultGetSignerCertificate(void *pvGetArg,
89c2c66affSColin Finck  DWORD dwCertEncodingType, PCERT_INFO pSignerId, HCERTSTORE hMsgCertStore)
90c2c66affSColin Finck {
91c2c66affSColin Finck     return CertFindCertificateInStore(hMsgCertStore, dwCertEncodingType, 0,
92c2c66affSColin Finck      CERT_FIND_SUBJECT_CERT, pSignerId, NULL);
93c2c66affSColin Finck }
94c2c66affSColin Finck 
CRYPT_GetSignerCertificate(HCRYPTMSG msg,PCRYPT_VERIFY_MESSAGE_PARA pVerifyPara,PCERT_INFO certInfo,HCERTSTORE store)95c2c66affSColin Finck static inline PCCERT_CONTEXT CRYPT_GetSignerCertificate(HCRYPTMSG msg,
96c2c66affSColin Finck  PCRYPT_VERIFY_MESSAGE_PARA pVerifyPara, PCERT_INFO certInfo, HCERTSTORE store)
97c2c66affSColin Finck {
98c2c66affSColin Finck     PFN_CRYPT_GET_SIGNER_CERTIFICATE getCert;
99c2c66affSColin Finck 
100c2c66affSColin Finck     if (pVerifyPara->pfnGetSignerCertificate)
101c2c66affSColin Finck         getCert = pVerifyPara->pfnGetSignerCertificate;
102c2c66affSColin Finck     else
103c2c66affSColin Finck         getCert = CRYPT_DefaultGetSignerCertificate;
104c2c66affSColin Finck     return getCert(pVerifyPara->pvGetArg,
105c2c66affSColin Finck      pVerifyPara->dwMsgAndCertEncodingType, certInfo, store);
106c2c66affSColin Finck }
107c2c66affSColin Finck 
CryptVerifyDetachedMessageSignature(PCRYPT_VERIFY_MESSAGE_PARA pVerifyPara,DWORD dwSignerIndex,const BYTE * pbDetachedSignBlob,DWORD cbDetachedSignBlob,DWORD cToBeSigned,const BYTE * rgpbToBeSigned[],DWORD rgcbToBeSigned[],PCCERT_CONTEXT * ppSignerCert)108c2c66affSColin Finck BOOL WINAPI CryptVerifyDetachedMessageSignature(
109c2c66affSColin Finck  PCRYPT_VERIFY_MESSAGE_PARA pVerifyPara, DWORD dwSignerIndex,
110c2c66affSColin Finck  const BYTE *pbDetachedSignBlob, DWORD cbDetachedSignBlob, DWORD cToBeSigned,
111c2c66affSColin Finck  const BYTE *rgpbToBeSigned[], DWORD rgcbToBeSigned[],
112c2c66affSColin Finck  PCCERT_CONTEXT *ppSignerCert)
113c2c66affSColin Finck {
114c2c66affSColin Finck     BOOL ret = FALSE;
115c2c66affSColin Finck     HCRYPTMSG msg;
116c2c66affSColin Finck 
117c2c66affSColin Finck     TRACE("(%p, %d, %p, %d, %d, %p, %p, %p)\n", pVerifyPara, dwSignerIndex,
118c2c66affSColin Finck      pbDetachedSignBlob, cbDetachedSignBlob, cToBeSigned, rgpbToBeSigned,
119c2c66affSColin Finck      rgcbToBeSigned, ppSignerCert);
120c2c66affSColin Finck 
121c2c66affSColin Finck     if (ppSignerCert)
122c2c66affSColin Finck         *ppSignerCert = NULL;
123c2c66affSColin Finck     if (!pVerifyPara ||
124c2c66affSColin Finck      pVerifyPara->cbSize != sizeof(CRYPT_VERIFY_MESSAGE_PARA) ||
125c2c66affSColin Finck      GET_CMSG_ENCODING_TYPE(pVerifyPara->dwMsgAndCertEncodingType) !=
126c2c66affSColin Finck      PKCS_7_ASN_ENCODING)
127c2c66affSColin Finck     {
128c2c66affSColin Finck         SetLastError(E_INVALIDARG);
129c2c66affSColin Finck         return FALSE;
130c2c66affSColin Finck     }
131c2c66affSColin Finck 
132c2c66affSColin Finck     msg = CryptMsgOpenToDecode(pVerifyPara->dwMsgAndCertEncodingType,
133c2c66affSColin Finck      CMSG_DETACHED_FLAG, 0, pVerifyPara->hCryptProv, NULL, NULL);
134c2c66affSColin Finck     if (msg)
135c2c66affSColin Finck     {
136c2c66affSColin Finck         ret = CryptMsgUpdate(msg, pbDetachedSignBlob, cbDetachedSignBlob, TRUE);
137c2c66affSColin Finck         if (ret)
138c2c66affSColin Finck         {
139c2c66affSColin Finck             DWORD i;
140c2c66affSColin Finck 
141c2c66affSColin Finck             for (i = 0; ret && i < cToBeSigned; i++)
142c2c66affSColin Finck                 ret = CryptMsgUpdate(msg, rgpbToBeSigned[i], rgcbToBeSigned[i],
143c2c66affSColin Finck                  i == cToBeSigned - 1);
144c2c66affSColin Finck         }
145c2c66affSColin Finck         if (ret)
146c2c66affSColin Finck         {
147c2c66affSColin Finck             CERT_INFO *certInfo = CRYPT_GetSignerCertInfoFromMsg(msg,
148c2c66affSColin Finck              dwSignerIndex);
149c2c66affSColin Finck 
150c2c66affSColin Finck             ret = FALSE;
151c2c66affSColin Finck             if (certInfo)
152c2c66affSColin Finck             {
153c2c66affSColin Finck                 HCERTSTORE store = CertOpenStore(CERT_STORE_PROV_MSG,
154c2c66affSColin Finck                  pVerifyPara->dwMsgAndCertEncodingType,
155c2c66affSColin Finck                  pVerifyPara->hCryptProv, 0, msg);
156c2c66affSColin Finck 
157c2c66affSColin Finck                 if (store)
158c2c66affSColin Finck                 {
159c2c66affSColin Finck                     PCCERT_CONTEXT cert = CRYPT_GetSignerCertificate(
160c2c66affSColin Finck                      msg, pVerifyPara, certInfo, store);
161c2c66affSColin Finck 
162c2c66affSColin Finck                     if (cert)
163c2c66affSColin Finck                     {
164c2c66affSColin Finck                         ret = CryptMsgControl(msg, 0,
165c2c66affSColin Finck                          CMSG_CTRL_VERIFY_SIGNATURE, cert->pCertInfo);
166c2c66affSColin Finck                         if (ret && ppSignerCert)
167c2c66affSColin Finck                             *ppSignerCert = cert;
168c2c66affSColin Finck                         else
169c2c66affSColin Finck                             CertFreeCertificateContext(cert);
170c2c66affSColin Finck                     }
171c2c66affSColin Finck                     else
172c2c66affSColin Finck                         SetLastError(CRYPT_E_NOT_FOUND);
173c2c66affSColin Finck                     CertCloseStore(store, 0);
174c2c66affSColin Finck                 }
175c2c66affSColin Finck                 CryptMemFree(certInfo);
176c2c66affSColin Finck             }
177c2c66affSColin Finck         }
178c2c66affSColin Finck         CryptMsgClose(msg);
179c2c66affSColin Finck     }
180c2c66affSColin Finck     TRACE("returning %d\n", ret);
181c2c66affSColin Finck     return ret;
182c2c66affSColin Finck }
183c2c66affSColin Finck 
CryptVerifyMessageSignature(PCRYPT_VERIFY_MESSAGE_PARA pVerifyPara,DWORD dwSignerIndex,const BYTE * pbSignedBlob,DWORD cbSignedBlob,BYTE * pbDecoded,DWORD * pcbDecoded,PCCERT_CONTEXT * ppSignerCert)184c2c66affSColin Finck BOOL WINAPI CryptVerifyMessageSignature(PCRYPT_VERIFY_MESSAGE_PARA pVerifyPara,
185c2c66affSColin Finck  DWORD dwSignerIndex, const BYTE* pbSignedBlob, DWORD cbSignedBlob,
186c2c66affSColin Finck  BYTE* pbDecoded, DWORD* pcbDecoded, PCCERT_CONTEXT* ppSignerCert)
187c2c66affSColin Finck {
188c2c66affSColin Finck     BOOL ret = FALSE;
189c2c66affSColin Finck     HCRYPTMSG msg;
190c2c66affSColin Finck 
191c2c66affSColin Finck     TRACE("(%p, %d, %p, %d, %p, %p, %p)\n",
192c2c66affSColin Finck      pVerifyPara, dwSignerIndex, pbSignedBlob, cbSignedBlob,
193c2c66affSColin Finck      pbDecoded, pcbDecoded, ppSignerCert);
194c2c66affSColin Finck 
195c2c66affSColin Finck     if (ppSignerCert)
196c2c66affSColin Finck         *ppSignerCert = NULL;
197c2c66affSColin Finck     if (!pVerifyPara ||
198c2c66affSColin Finck      pVerifyPara->cbSize != sizeof(CRYPT_VERIFY_MESSAGE_PARA) ||
199c2c66affSColin Finck      GET_CMSG_ENCODING_TYPE(pVerifyPara->dwMsgAndCertEncodingType) !=
200c2c66affSColin Finck      PKCS_7_ASN_ENCODING)
201c2c66affSColin Finck     {
202c2c66affSColin Finck         if(pcbDecoded)
203c2c66affSColin Finck             *pcbDecoded = 0;
204c2c66affSColin Finck         SetLastError(E_INVALIDARG);
205c2c66affSColin Finck         return FALSE;
206c2c66affSColin Finck     }
207c2c66affSColin Finck 
208c2c66affSColin Finck     msg = CryptMsgOpenToDecode(pVerifyPara->dwMsgAndCertEncodingType, 0, 0,
209c2c66affSColin Finck      pVerifyPara->hCryptProv, NULL, NULL);
210c2c66affSColin Finck     if (msg)
211c2c66affSColin Finck     {
212c2c66affSColin Finck         ret = CryptMsgUpdate(msg, pbSignedBlob, cbSignedBlob, TRUE);
213c2c66affSColin Finck         if (ret && pcbDecoded)
214c2c66affSColin Finck             ret = CryptMsgGetParam(msg, CMSG_CONTENT_PARAM, 0, pbDecoded,
215c2c66affSColin Finck              pcbDecoded);
216c2c66affSColin Finck         if (ret)
217c2c66affSColin Finck         {
218c2c66affSColin Finck             CERT_INFO *certInfo = CRYPT_GetSignerCertInfoFromMsg(msg,
219c2c66affSColin Finck              dwSignerIndex);
220c2c66affSColin Finck 
221c2c66affSColin Finck             ret = FALSE;
222c2c66affSColin Finck             if (certInfo)
223c2c66affSColin Finck             {
224c2c66affSColin Finck                 HCERTSTORE store = CertOpenStore(CERT_STORE_PROV_MSG,
225c2c66affSColin Finck                  pVerifyPara->dwMsgAndCertEncodingType,
226c2c66affSColin Finck                  pVerifyPara->hCryptProv, 0, msg);
227c2c66affSColin Finck 
228c2c66affSColin Finck                 if (store)
229c2c66affSColin Finck                 {
230c2c66affSColin Finck                     PCCERT_CONTEXT cert = CRYPT_GetSignerCertificate(
231c2c66affSColin Finck                      msg, pVerifyPara, certInfo, store);
232c2c66affSColin Finck 
233c2c66affSColin Finck                     if (cert)
234c2c66affSColin Finck                     {
235c2c66affSColin Finck                         ret = CryptMsgControl(msg, 0,
236c2c66affSColin Finck                          CMSG_CTRL_VERIFY_SIGNATURE, cert->pCertInfo);
237c2c66affSColin Finck                         if (ret && ppSignerCert)
238c2c66affSColin Finck                             *ppSignerCert = cert;
239c2c66affSColin Finck                         else
240c2c66affSColin Finck                             CertFreeCertificateContext(cert);
241c2c66affSColin Finck                     }
242c2c66affSColin Finck                     CertCloseStore(store, 0);
243c2c66affSColin Finck                 }
244c2c66affSColin Finck             }
245c2c66affSColin Finck             CryptMemFree(certInfo);
246c2c66affSColin Finck         }
247c2c66affSColin Finck         CryptMsgClose(msg);
248c2c66affSColin Finck     }
249c2c66affSColin Finck     if(!ret && pcbDecoded)
250c2c66affSColin Finck         *pcbDecoded = 0;
251c2c66affSColin Finck     TRACE("returning %d\n", ret);
252c2c66affSColin Finck     return ret;
253c2c66affSColin Finck }
254c2c66affSColin Finck 
CryptHashMessage(PCRYPT_HASH_MESSAGE_PARA pHashPara,BOOL fDetachedHash,DWORD cToBeHashed,const BYTE * rgpbToBeHashed[],DWORD rgcbToBeHashed[],BYTE * pbHashedBlob,DWORD * pcbHashedBlob,BYTE * pbComputedHash,DWORD * pcbComputedHash)255c2c66affSColin Finck BOOL WINAPI CryptHashMessage(PCRYPT_HASH_MESSAGE_PARA pHashPara,
256c2c66affSColin Finck  BOOL fDetachedHash, DWORD cToBeHashed, const BYTE *rgpbToBeHashed[],
257c2c66affSColin Finck  DWORD rgcbToBeHashed[], BYTE *pbHashedBlob, DWORD *pcbHashedBlob,
258c2c66affSColin Finck  BYTE *pbComputedHash, DWORD *pcbComputedHash)
259c2c66affSColin Finck {
260c2c66affSColin Finck     DWORD i, flags;
261c2c66affSColin Finck     BOOL ret = FALSE;
262c2c66affSColin Finck     HCRYPTMSG msg;
263c2c66affSColin Finck     CMSG_HASHED_ENCODE_INFO info;
264c2c66affSColin Finck 
265c2c66affSColin Finck     TRACE("(%p, %d, %d, %p, %p, %p, %p, %p, %p)\n", pHashPara, fDetachedHash,
266c2c66affSColin Finck      cToBeHashed, rgpbToBeHashed, rgcbToBeHashed, pbHashedBlob, pcbHashedBlob,
267c2c66affSColin Finck      pbComputedHash, pcbComputedHash);
268c2c66affSColin Finck 
269c2c66affSColin Finck     if (pHashPara->cbSize != sizeof(CRYPT_HASH_MESSAGE_PARA))
270c2c66affSColin Finck     {
271c2c66affSColin Finck         SetLastError(E_INVALIDARG);
272c2c66affSColin Finck         return FALSE;
273c2c66affSColin Finck     }
274c2c66affSColin Finck     /* Native seems to ignore any encoding type other than the expected
275c2c66affSColin Finck      * PKCS_7_ASN_ENCODING
276c2c66affSColin Finck      */
277c2c66affSColin Finck     if (GET_CMSG_ENCODING_TYPE(pHashPara->dwMsgEncodingType) !=
278c2c66affSColin Finck      PKCS_7_ASN_ENCODING)
279c2c66affSColin Finck         return TRUE;
280c2c66affSColin Finck     /* Native also seems to do nothing if the output parameter isn't given */
281c2c66affSColin Finck     if (!pcbHashedBlob)
282c2c66affSColin Finck         return TRUE;
283c2c66affSColin Finck 
284c2c66affSColin Finck     flags = fDetachedHash ? CMSG_DETACHED_FLAG : 0;
285c2c66affSColin Finck     memset(&info, 0, sizeof(info));
286c2c66affSColin Finck     info.cbSize = sizeof(info);
287c2c66affSColin Finck     info.hCryptProv = pHashPara->hCryptProv;
288c2c66affSColin Finck     info.HashAlgorithm = pHashPara->HashAlgorithm;
289c2c66affSColin Finck     info.pvHashAuxInfo = pHashPara->pvHashAuxInfo;
290c2c66affSColin Finck     msg = CryptMsgOpenToEncode(pHashPara->dwMsgEncodingType, flags, CMSG_HASHED,
291c2c66affSColin Finck      &info, NULL, NULL);
292c2c66affSColin Finck     if (msg)
293c2c66affSColin Finck     {
294c2c66affSColin Finck         for (i = 0, ret = TRUE; ret && i < cToBeHashed; i++)
295c2c66affSColin Finck             ret = CryptMsgUpdate(msg, rgpbToBeHashed[i], rgcbToBeHashed[i], i == cToBeHashed - 1);
296c2c66affSColin Finck         if (ret)
297c2c66affSColin Finck         {
298c2c66affSColin Finck             ret = CryptMsgGetParam(msg, CMSG_CONTENT_PARAM, 0, pbHashedBlob,
299c2c66affSColin Finck              pcbHashedBlob);
300c2c66affSColin Finck             if (ret && pcbComputedHash)
301c2c66affSColin Finck                 ret = CryptMsgGetParam(msg, CMSG_COMPUTED_HASH_PARAM, 0,
302c2c66affSColin Finck                  pbComputedHash, pcbComputedHash);
303c2c66affSColin Finck         }
304c2c66affSColin Finck         CryptMsgClose(msg);
305c2c66affSColin Finck     }
306c2c66affSColin Finck     return ret;
307c2c66affSColin Finck }
308c2c66affSColin Finck 
CryptVerifyDetachedMessageHash(PCRYPT_HASH_MESSAGE_PARA pHashPara,BYTE * pbDetachedHashBlob,DWORD cbDetachedHashBlob,DWORD cToBeHashed,const BYTE * rgpbToBeHashed[],DWORD rgcbToBeHashed[],BYTE * pbComputedHash,DWORD * pcbComputedHash)309c2c66affSColin Finck BOOL WINAPI CryptVerifyDetachedMessageHash(PCRYPT_HASH_MESSAGE_PARA pHashPara,
310c2c66affSColin Finck  BYTE *pbDetachedHashBlob, DWORD cbDetachedHashBlob, DWORD cToBeHashed,
311c2c66affSColin Finck  const BYTE *rgpbToBeHashed[], DWORD rgcbToBeHashed[], BYTE *pbComputedHash,
312c2c66affSColin Finck  DWORD *pcbComputedHash)
313c2c66affSColin Finck {
314c2c66affSColin Finck     HCRYPTMSG msg;
315c2c66affSColin Finck     BOOL ret = FALSE;
316c2c66affSColin Finck 
317c2c66affSColin Finck     TRACE("(%p, %p, %d, %d, %p, %p, %p, %p)\n", pHashPara, pbDetachedHashBlob,
318c2c66affSColin Finck      cbDetachedHashBlob, cToBeHashed, rgpbToBeHashed, rgcbToBeHashed,
319c2c66affSColin Finck      pbComputedHash, pcbComputedHash);
320c2c66affSColin Finck 
321c2c66affSColin Finck     if (pHashPara->cbSize != sizeof(CRYPT_HASH_MESSAGE_PARA))
322c2c66affSColin Finck     {
323c2c66affSColin Finck         SetLastError(E_INVALIDARG);
324c2c66affSColin Finck         return FALSE;
325c2c66affSColin Finck     }
326c2c66affSColin Finck     if (GET_CMSG_ENCODING_TYPE(pHashPara->dwMsgEncodingType) !=
327c2c66affSColin Finck      PKCS_7_ASN_ENCODING)
328c2c66affSColin Finck     {
329c2c66affSColin Finck         SetLastError(E_INVALIDARG);
330c2c66affSColin Finck         return FALSE;
331c2c66affSColin Finck     }
332c2c66affSColin Finck     msg = CryptMsgOpenToDecode(pHashPara->dwMsgEncodingType, CMSG_DETACHED_FLAG,
333c2c66affSColin Finck      0, pHashPara->hCryptProv, NULL, NULL);
334c2c66affSColin Finck     if (msg)
335c2c66affSColin Finck     {
336c2c66affSColin Finck         DWORD i;
337c2c66affSColin Finck 
338c2c66affSColin Finck         ret = CryptMsgUpdate(msg, pbDetachedHashBlob, cbDetachedHashBlob, TRUE);
339c2c66affSColin Finck         if (ret)
340c2c66affSColin Finck         {
341c2c66affSColin Finck             if (cToBeHashed)
342c2c66affSColin Finck             {
343c2c66affSColin Finck                 for (i = 0; ret && i < cToBeHashed; i++)
344c2c66affSColin Finck                 {
345c2c66affSColin Finck                     ret = CryptMsgUpdate(msg, rgpbToBeHashed[i],
346c2c66affSColin Finck                      rgcbToBeHashed[i], i == cToBeHashed - 1);
347c2c66affSColin Finck                 }
348c2c66affSColin Finck             }
349c2c66affSColin Finck             else
350c2c66affSColin Finck                 ret = CryptMsgUpdate(msg, NULL, 0, TRUE);
351c2c66affSColin Finck         }
352c2c66affSColin Finck         if (ret)
353c2c66affSColin Finck         {
354c2c66affSColin Finck             ret = CryptMsgControl(msg, 0, CMSG_CTRL_VERIFY_HASH, NULL);
355c2c66affSColin Finck             if (ret && pcbComputedHash)
356c2c66affSColin Finck                 ret = CryptMsgGetParam(msg, CMSG_COMPUTED_HASH_PARAM, 0,
357c2c66affSColin Finck                  pbComputedHash, pcbComputedHash);
358c2c66affSColin Finck         }
359c2c66affSColin Finck         CryptMsgClose(msg);
360c2c66affSColin Finck     }
361c2c66affSColin Finck     return ret;
362c2c66affSColin Finck }
363c2c66affSColin Finck 
CryptVerifyMessageHash(PCRYPT_HASH_MESSAGE_PARA pHashPara,BYTE * pbHashedBlob,DWORD cbHashedBlob,BYTE * pbToBeHashed,DWORD * pcbToBeHashed,BYTE * pbComputedHash,DWORD * pcbComputedHash)364c2c66affSColin Finck BOOL WINAPI CryptVerifyMessageHash(PCRYPT_HASH_MESSAGE_PARA pHashPara,
365c2c66affSColin Finck  BYTE *pbHashedBlob, DWORD cbHashedBlob, BYTE *pbToBeHashed,
366c2c66affSColin Finck  DWORD *pcbToBeHashed, BYTE *pbComputedHash, DWORD *pcbComputedHash)
367c2c66affSColin Finck {
368c2c66affSColin Finck     HCRYPTMSG msg;
369c2c66affSColin Finck     BOOL ret = FALSE;
370c2c66affSColin Finck 
371c2c66affSColin Finck     TRACE("(%p, %p, %d, %p, %p, %p, %p)\n", pHashPara, pbHashedBlob,
372c2c66affSColin Finck      cbHashedBlob, pbToBeHashed, pcbToBeHashed, pbComputedHash,
373c2c66affSColin Finck      pcbComputedHash);
374c2c66affSColin Finck 
375c2c66affSColin Finck     if (pHashPara->cbSize != sizeof(CRYPT_HASH_MESSAGE_PARA))
376c2c66affSColin Finck     {
377c2c66affSColin Finck         SetLastError(E_INVALIDARG);
378c2c66affSColin Finck         return FALSE;
379c2c66affSColin Finck     }
380c2c66affSColin Finck     if (GET_CMSG_ENCODING_TYPE(pHashPara->dwMsgEncodingType) !=
381c2c66affSColin Finck      PKCS_7_ASN_ENCODING)
382c2c66affSColin Finck     {
383c2c66affSColin Finck         SetLastError(E_INVALIDARG);
384c2c66affSColin Finck         return FALSE;
385c2c66affSColin Finck     }
386c2c66affSColin Finck     msg = CryptMsgOpenToDecode(pHashPara->dwMsgEncodingType, 0, 0,
387c2c66affSColin Finck      pHashPara->hCryptProv, NULL, NULL);
388c2c66affSColin Finck     if (msg)
389c2c66affSColin Finck     {
390c2c66affSColin Finck         ret = CryptMsgUpdate(msg, pbHashedBlob, cbHashedBlob, TRUE);
391c2c66affSColin Finck         if (ret)
392c2c66affSColin Finck         {
393c2c66affSColin Finck             ret = CryptMsgControl(msg, 0, CMSG_CTRL_VERIFY_HASH, NULL);
394c2c66affSColin Finck             if (ret && pcbToBeHashed)
395c2c66affSColin Finck                 ret = CryptMsgGetParam(msg, CMSG_CONTENT_PARAM, 0,
396c2c66affSColin Finck                  pbToBeHashed, pcbToBeHashed);
397c2c66affSColin Finck             if (ret && pcbComputedHash)
398c2c66affSColin Finck                 ret = CryptMsgGetParam(msg, CMSG_COMPUTED_HASH_PARAM, 0,
399c2c66affSColin Finck                  pbComputedHash, pcbComputedHash);
400c2c66affSColin Finck         }
401c2c66affSColin Finck         CryptMsgClose(msg);
402c2c66affSColin Finck     }
403c2c66affSColin Finck     return ret;
404c2c66affSColin Finck }
405c2c66affSColin Finck 
CryptSignMessage(PCRYPT_SIGN_MESSAGE_PARA pSignPara,BOOL fDetachedSignature,DWORD cToBeSigned,const BYTE * rgpbToBeSigned[],DWORD rgcbToBeSigned[],BYTE * pbSignedBlob,DWORD * pcbSignedBlob)406c2c66affSColin Finck BOOL WINAPI CryptSignMessage(PCRYPT_SIGN_MESSAGE_PARA pSignPara,
407c2c66affSColin Finck  BOOL fDetachedSignature, DWORD cToBeSigned, const BYTE *rgpbToBeSigned[],
408c2c66affSColin Finck  DWORD rgcbToBeSigned[], BYTE *pbSignedBlob, DWORD *pcbSignedBlob)
409c2c66affSColin Finck {
410c2c66affSColin Finck     HCRYPTPROV hCryptProv;
411c2c66affSColin Finck     BOOL ret, freeProv = FALSE;
412c2c66affSColin Finck     DWORD i, keySpec;
413c2c66affSColin Finck     PCERT_BLOB certBlob = NULL;
414c2c66affSColin Finck     PCRL_BLOB crlBlob = NULL;
415c2c66affSColin Finck     CMSG_SIGNED_ENCODE_INFO signInfo;
416c2c66affSColin Finck     CMSG_SIGNER_ENCODE_INFO signer;
417c2c66affSColin Finck     HCRYPTMSG msg = 0;
418c2c66affSColin Finck 
419c2c66affSColin Finck     TRACE("(%p, %d, %d, %p, %p, %p, %p)\n", pSignPara, fDetachedSignature,
420c2c66affSColin Finck      cToBeSigned, rgpbToBeSigned, rgcbToBeSigned, pbSignedBlob, pcbSignedBlob);
421c2c66affSColin Finck 
422c2c66affSColin Finck     if (pSignPara->cbSize != sizeof(CRYPT_SIGN_MESSAGE_PARA) ||
423c2c66affSColin Finck      GET_CMSG_ENCODING_TYPE(pSignPara->dwMsgEncodingType) !=
424c2c66affSColin Finck      PKCS_7_ASN_ENCODING)
425c2c66affSColin Finck     {
426c2c66affSColin Finck         *pcbSignedBlob = 0;
427c2c66affSColin Finck         SetLastError(E_INVALIDARG);
428c2c66affSColin Finck         return FALSE;
429c2c66affSColin Finck     }
430c2c66affSColin Finck     if (!pSignPara->pSigningCert)
431c2c66affSColin Finck         return TRUE;
432c2c66affSColin Finck 
433c2c66affSColin Finck     ret = CryptAcquireCertificatePrivateKey(pSignPara->pSigningCert,
434c2c66affSColin Finck      CRYPT_ACQUIRE_CACHE_FLAG, NULL, &hCryptProv, &keySpec, &freeProv);
435c2c66affSColin Finck     if (!ret)
436c2c66affSColin Finck         return FALSE;
437c2c66affSColin Finck 
438c2c66affSColin Finck     memset(&signer, 0, sizeof(signer));
439c2c66affSColin Finck     signer.cbSize = sizeof(signer);
440c2c66affSColin Finck     signer.pCertInfo = pSignPara->pSigningCert->pCertInfo;
441c2c66affSColin Finck     signer.hCryptProv = hCryptProv;
442c2c66affSColin Finck     signer.dwKeySpec = keySpec;
443c2c66affSColin Finck     signer.HashAlgorithm = pSignPara->HashAlgorithm;
444c2c66affSColin Finck     signer.pvHashAuxInfo = pSignPara->pvHashAuxInfo;
445c2c66affSColin Finck     signer.cAuthAttr = pSignPara->cAuthAttr;
446c2c66affSColin Finck     signer.rgAuthAttr = pSignPara->rgAuthAttr;
447c2c66affSColin Finck     signer.cUnauthAttr = pSignPara->cUnauthAttr;
448c2c66affSColin Finck     signer.rgUnauthAttr = pSignPara->rgUnauthAttr;
449c2c66affSColin Finck 
450c2c66affSColin Finck     memset(&signInfo, 0, sizeof(signInfo));
451c2c66affSColin Finck     signInfo.cbSize = sizeof(signInfo);
452c2c66affSColin Finck     signInfo.cSigners = 1;
453c2c66affSColin Finck     signInfo.rgSigners = &signer;
454c2c66affSColin Finck 
455c2c66affSColin Finck     if (pSignPara->cMsgCert)
456c2c66affSColin Finck     {
457c2c66affSColin Finck         certBlob = CryptMemAlloc(sizeof(CERT_BLOB) * pSignPara->cMsgCert);
458c2c66affSColin Finck         if (certBlob)
459c2c66affSColin Finck         {
460c2c66affSColin Finck             for (i = 0; i < pSignPara->cMsgCert; ++i)
461c2c66affSColin Finck             {
462c2c66affSColin Finck                 certBlob[i].cbData = pSignPara->rgpMsgCert[i]->cbCertEncoded;
463c2c66affSColin Finck                 certBlob[i].pbData = pSignPara->rgpMsgCert[i]->pbCertEncoded;
464c2c66affSColin Finck             }
465c2c66affSColin Finck             signInfo.cCertEncoded = pSignPara->cMsgCert;
466c2c66affSColin Finck             signInfo.rgCertEncoded = certBlob;
467c2c66affSColin Finck         }
468c2c66affSColin Finck         else
469c2c66affSColin Finck             ret = FALSE;
470c2c66affSColin Finck     }
471c2c66affSColin Finck     if (pSignPara->cMsgCrl)
472c2c66affSColin Finck     {
473c2c66affSColin Finck         crlBlob = CryptMemAlloc(sizeof(CRL_BLOB) * pSignPara->cMsgCrl);
474c2c66affSColin Finck         if (crlBlob)
475c2c66affSColin Finck         {
476c2c66affSColin Finck             for (i = 0; i < pSignPara->cMsgCrl; ++i)
477c2c66affSColin Finck             {
478c2c66affSColin Finck                 crlBlob[i].cbData = pSignPara->rgpMsgCrl[i]->cbCrlEncoded;
479c2c66affSColin Finck                 crlBlob[i].pbData = pSignPara->rgpMsgCrl[i]->pbCrlEncoded;
480c2c66affSColin Finck             }
481c2c66affSColin Finck             signInfo.cCrlEncoded = pSignPara->cMsgCrl;
482c2c66affSColin Finck             signInfo.rgCrlEncoded = crlBlob;
483c2c66affSColin Finck         }
484c2c66affSColin Finck         else
485c2c66affSColin Finck             ret = FALSE;
486c2c66affSColin Finck     }
487c2c66affSColin Finck     if (pSignPara->dwFlags || pSignPara->dwInnerContentType)
488c2c66affSColin Finck         FIXME("unimplemented feature\n");
489c2c66affSColin Finck 
490c2c66affSColin Finck     if (ret)
491c2c66affSColin Finck         msg = CryptMsgOpenToEncode(pSignPara->dwMsgEncodingType,
492c2c66affSColin Finck          fDetachedSignature ? CMSG_DETACHED_FLAG : 0, CMSG_SIGNED, &signInfo,
493c2c66affSColin Finck          NULL, NULL);
494c2c66affSColin Finck     if (msg)
495c2c66affSColin Finck     {
496c2c66affSColin Finck         if (cToBeSigned)
497c2c66affSColin Finck         {
498c2c66affSColin Finck             for (i = 0; ret && i < cToBeSigned; ++i)
499c2c66affSColin Finck             {
500c2c66affSColin Finck                 ret = CryptMsgUpdate(msg, rgpbToBeSigned[i], rgcbToBeSigned[i],
501c2c66affSColin Finck                  i == cToBeSigned - 1);
502c2c66affSColin Finck             }
503c2c66affSColin Finck         }
504c2c66affSColin Finck         else
505c2c66affSColin Finck             ret = CryptMsgUpdate(msg, NULL, 0, TRUE);
506c2c66affSColin Finck         if (ret)
507c2c66affSColin Finck             ret = CryptMsgGetParam(msg, CMSG_CONTENT_PARAM, 0, pbSignedBlob,
508c2c66affSColin Finck              pcbSignedBlob);
509c2c66affSColin Finck         CryptMsgClose(msg);
510c2c66affSColin Finck     }
511c2c66affSColin Finck     else
512c2c66affSColin Finck         ret = FALSE;
513c2c66affSColin Finck 
514c2c66affSColin Finck     CryptMemFree(crlBlob);
515c2c66affSColin Finck     CryptMemFree(certBlob);
516c2c66affSColin Finck     if (freeProv)
517c2c66affSColin Finck         CryptReleaseContext(hCryptProv, 0);
518c2c66affSColin Finck     return ret;
519c2c66affSColin Finck }
520c2c66affSColin Finck 
CryptEncryptMessage(PCRYPT_ENCRYPT_MESSAGE_PARA pEncryptPara,DWORD cRecipientCert,PCCERT_CONTEXT rgpRecipientCert[],const BYTE * pbToBeEncrypted,DWORD cbToBeEncrypted,BYTE * pbEncryptedBlob,DWORD * pcbEncryptedBlob)521c2c66affSColin Finck BOOL WINAPI CryptEncryptMessage(PCRYPT_ENCRYPT_MESSAGE_PARA pEncryptPara,
522c2c66affSColin Finck  DWORD cRecipientCert, PCCERT_CONTEXT rgpRecipientCert[],
523c2c66affSColin Finck  const BYTE *pbToBeEncrypted, DWORD cbToBeEncrypted, BYTE *pbEncryptedBlob,
524c2c66affSColin Finck  DWORD *pcbEncryptedBlob)
525c2c66affSColin Finck {
526c2c66affSColin Finck     BOOL ret = TRUE;
527c2c66affSColin Finck     DWORD i;
528c2c66affSColin Finck     PCERT_INFO *certInfo = NULL;
529c2c66affSColin Finck     CMSG_ENVELOPED_ENCODE_INFO envelopedInfo;
530c2c66affSColin Finck     HCRYPTMSG msg = 0;
531c2c66affSColin Finck 
532c2c66affSColin Finck     TRACE("(%p, %d, %p, %p, %d, %p, %p)\n", pEncryptPara, cRecipientCert,
533c2c66affSColin Finck      rgpRecipientCert, pbToBeEncrypted, cbToBeEncrypted, pbEncryptedBlob,
534c2c66affSColin Finck      pcbEncryptedBlob);
535c2c66affSColin Finck 
536c2c66affSColin Finck     if (pEncryptPara->cbSize != sizeof(CRYPT_ENCRYPT_MESSAGE_PARA) ||
537c2c66affSColin Finck      GET_CMSG_ENCODING_TYPE(pEncryptPara->dwMsgEncodingType) !=
538c2c66affSColin Finck      PKCS_7_ASN_ENCODING)
539c2c66affSColin Finck     {
540c2c66affSColin Finck         *pcbEncryptedBlob = 0;
541c2c66affSColin Finck         SetLastError(E_INVALIDARG);
542c2c66affSColin Finck         return FALSE;
543c2c66affSColin Finck     }
544c2c66affSColin Finck 
545c2c66affSColin Finck     memset(&envelopedInfo, 0, sizeof(envelopedInfo));
546c2c66affSColin Finck     envelopedInfo.cbSize = sizeof(envelopedInfo);
547c2c66affSColin Finck     envelopedInfo.hCryptProv = pEncryptPara->hCryptProv;
548c2c66affSColin Finck     envelopedInfo.ContentEncryptionAlgorithm =
549c2c66affSColin Finck      pEncryptPara->ContentEncryptionAlgorithm;
550c2c66affSColin Finck     envelopedInfo.pvEncryptionAuxInfo = pEncryptPara->pvEncryptionAuxInfo;
551c2c66affSColin Finck 
552c2c66affSColin Finck     if (cRecipientCert)
553c2c66affSColin Finck     {
554c2c66affSColin Finck         certInfo = CryptMemAlloc(sizeof(PCERT_INFO) * cRecipientCert);
555c2c66affSColin Finck         if (certInfo)
556c2c66affSColin Finck         {
557c2c66affSColin Finck             for (i = 0; i < cRecipientCert; ++i)
558c2c66affSColin Finck                 certInfo[i] = rgpRecipientCert[i]->pCertInfo;
559c2c66affSColin Finck             envelopedInfo.cRecipients = cRecipientCert;
560c2c66affSColin Finck             envelopedInfo.rgpRecipientCert = certInfo;
561c2c66affSColin Finck         }
562c2c66affSColin Finck         else
563c2c66affSColin Finck             ret = FALSE;
564c2c66affSColin Finck     }
565c2c66affSColin Finck 
566c2c66affSColin Finck     if (ret)
567c2c66affSColin Finck         msg = CryptMsgOpenToEncode(pEncryptPara->dwMsgEncodingType, 0,
568c2c66affSColin Finck          CMSG_ENVELOPED, &envelopedInfo, NULL, NULL);
569c2c66affSColin Finck     if (msg)
570c2c66affSColin Finck     {
571c2c66affSColin Finck         ret = CryptMsgUpdate(msg, pbToBeEncrypted, cbToBeEncrypted, TRUE);
572c2c66affSColin Finck         if (ret)
573c2c66affSColin Finck             ret = CryptMsgGetParam(msg, CMSG_CONTENT_PARAM, 0, pbEncryptedBlob,
574c2c66affSColin Finck              pcbEncryptedBlob);
575c2c66affSColin Finck         CryptMsgClose(msg);
576c2c66affSColin Finck     }
577c2c66affSColin Finck     else
578c2c66affSColin Finck         ret = FALSE;
579c2c66affSColin Finck 
580c2c66affSColin Finck     CryptMemFree(certInfo);
581c2c66affSColin Finck     if (!ret) *pcbEncryptedBlob = 0;
582c2c66affSColin Finck     return ret;
583c2c66affSColin Finck }
584