2 * Copyright 2007 Juan Lang
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.
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.
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
24 #include "wine/debug.h"
26 WINE_DEFAULT_DEBUG_CHANNEL(crypt
);
28 HCERTSTORE WINAPI
CryptGetMessageCertificates(DWORD dwMsgAndCertEncodingType
,
29 HCRYPTPROV_LEGACY hCryptProv
, DWORD dwFlags
, const BYTE
* pbSignedBlob
,
32 CRYPT_DATA_BLOB blob
= { cbSignedBlob
, (LPBYTE
)pbSignedBlob
};
34 TRACE("(%08x, %ld, %d08x %p, %d)\n", dwMsgAndCertEncodingType
, hCryptProv
,
35 dwFlags
, pbSignedBlob
, cbSignedBlob
);
37 return CertOpenStore(CERT_STORE_PROV_PKCS7
, dwMsgAndCertEncodingType
,
38 hCryptProv
, dwFlags
, &blob
);
41 LONG WINAPI
CryptGetMessageSignerCount(DWORD dwMsgEncodingType
,
42 const BYTE
*pbSignedBlob
, DWORD cbSignedBlob
)
47 TRACE("(%08x, %p, %d)\n", dwMsgEncodingType
, pbSignedBlob
, cbSignedBlob
);
49 msg
= CryptMsgOpenToDecode(dwMsgEncodingType
, 0, 0, 0, NULL
, NULL
);
52 if (CryptMsgUpdate(msg
, pbSignedBlob
, cbSignedBlob
, TRUE
))
54 DWORD size
= sizeof(count
);
56 CryptMsgGetParam(msg
, CMSG_SIGNER_COUNT_PARAM
, 0, &count
, &size
);
63 static BOOL
CRYPT_CopyParam(void *pvData
, DWORD
*pcbData
, const void *src
,
70 else if (*pcbData
< len
)
73 SetLastError(ERROR_MORE_DATA
);
79 memcpy(pvData
, src
, len
);
84 static CERT_INFO
*CRYPT_GetSignerCertInfoFromMsg(HCRYPTMSG msg
,
87 CERT_INFO
*certInfo
= NULL
;
90 if (CryptMsgGetParam(msg
, CMSG_SIGNER_CERT_INFO_PARAM
, dwSignerIndex
, NULL
,
93 certInfo
= CryptMemAlloc(size
);
96 if (!CryptMsgGetParam(msg
, CMSG_SIGNER_CERT_INFO_PARAM
,
97 dwSignerIndex
, certInfo
, &size
))
99 CryptMemFree(certInfo
);
107 static PCCERT_CONTEXT WINAPI
CRYPT_DefaultGetSignerCertificate(void *pvGetArg
,
108 DWORD dwCertEncodingType
, PCERT_INFO pSignerId
, HCERTSTORE hMsgCertStore
)
110 return CertFindCertificateInStore(hMsgCertStore
, dwCertEncodingType
, 0,
111 CERT_FIND_SUBJECT_CERT
, pSignerId
, NULL
);
114 static inline PCCERT_CONTEXT
CRYPT_GetSignerCertificate(HCRYPTMSG msg
,
115 PCRYPT_VERIFY_MESSAGE_PARA pVerifyPara
, PCERT_INFO certInfo
, HCERTSTORE store
)
117 PFN_CRYPT_GET_SIGNER_CERTIFICATE getCert
;
119 if (pVerifyPara
->pfnGetSignerCertificate
)
120 getCert
= pVerifyPara
->pfnGetSignerCertificate
;
122 getCert
= CRYPT_DefaultGetSignerCertificate
;
123 return getCert(pVerifyPara
->pvGetArg
,
124 pVerifyPara
->dwMsgAndCertEncodingType
, certInfo
, store
);
127 BOOL WINAPI
CryptVerifyMessageSignature(PCRYPT_VERIFY_MESSAGE_PARA pVerifyPara
,
128 DWORD dwSignerIndex
, const BYTE
* pbSignedBlob
, DWORD cbSignedBlob
,
129 BYTE
* pbDecoded
, DWORD
* pcbDecoded
, PCCERT_CONTEXT
* ppSignerCert
)
133 CRYPT_CONTENT_INFO
*contentInfo
;
136 TRACE("(%p, %d, %p, %d, %p, %p, %p)\n",
137 pVerifyPara
, dwSignerIndex
, pbSignedBlob
, cbSignedBlob
,
138 pbDecoded
, pcbDecoded
, ppSignerCert
);
141 *ppSignerCert
= NULL
;
145 pVerifyPara
->cbSize
!= sizeof(CRYPT_VERIFY_MESSAGE_PARA
) ||
146 GET_CMSG_ENCODING_TYPE(pVerifyPara
->dwMsgAndCertEncodingType
) !=
149 SetLastError(E_INVALIDARG
);
153 if (!CryptDecodeObjectEx(pVerifyPara
->dwMsgAndCertEncodingType
,
154 PKCS_CONTENT_INFO
, pbSignedBlob
, cbSignedBlob
,
155 CRYPT_DECODE_ALLOC_FLAG
| CRYPT_DECODE_NOCOPY_FLAG
, NULL
,
156 (LPBYTE
)&contentInfo
, &size
))
158 if (strcmp(contentInfo
->pszObjId
, szOID_RSA_signedData
))
160 LocalFree(contentInfo
);
161 SetLastError(CRYPT_E_UNEXPECTED_MSG_TYPE
);
164 msg
= CryptMsgOpenToDecode(pVerifyPara
->dwMsgAndCertEncodingType
, 0,
165 CMSG_SIGNED
, pVerifyPara
->hCryptProv
, NULL
, NULL
);
168 ret
= CryptMsgUpdate(msg
, contentInfo
->Content
.pbData
,
169 contentInfo
->Content
.cbData
, TRUE
);
170 if (ret
&& pcbDecoded
)
171 ret
= CRYPT_CopyParam(pbDecoded
, pcbDecoded
,
172 contentInfo
->Content
.pbData
, contentInfo
->Content
.cbData
);
175 CERT_INFO
*certInfo
= CRYPT_GetSignerCertInfoFromMsg(msg
,
181 HCERTSTORE store
= CertOpenStore(CERT_STORE_PROV_MSG
,
182 pVerifyPara
->dwMsgAndCertEncodingType
,
183 pVerifyPara
->hCryptProv
, 0, msg
);
187 PCCERT_CONTEXT cert
= CRYPT_GetSignerCertificate(
188 msg
, pVerifyPara
, certInfo
, store
);
192 ret
= CryptMsgControl(msg
, 0,
193 CMSG_CTRL_VERIFY_SIGNATURE
, cert
->pCertInfo
);
194 if (ret
&& ppSignerCert
)
195 *ppSignerCert
= cert
;
197 CertFreeCertificateContext(cert
);
199 CertCloseStore(store
, 0);
202 CryptMemFree(certInfo
);
206 LocalFree(contentInfo
);
207 TRACE("returning %d\n", ret
);
211 BOOL WINAPI
CryptHashMessage(PCRYPT_HASH_MESSAGE_PARA pHashPara
,
212 BOOL fDetachedHash
, DWORD cToBeHashed
, const BYTE
*rgpbToBeHashed
[],
213 DWORD rgcbToBeHashed
[], BYTE
*pbHashedBlob
, DWORD
*pcbHashedBlob
,
214 BYTE
*pbComputedHash
, DWORD
*pcbComputedHash
)
219 CMSG_HASHED_ENCODE_INFO info
;
221 TRACE("(%p, %d, %d, %p, %p, %p, %p, %p, %p)\n", pHashPara
, fDetachedHash
,
222 cToBeHashed
, rgpbToBeHashed
, rgcbToBeHashed
, pbHashedBlob
, pcbHashedBlob
,
223 pbComputedHash
, pcbComputedHash
);
225 if (pHashPara
->cbSize
!= sizeof(CRYPT_HASH_MESSAGE_PARA
))
227 SetLastError(E_INVALIDARG
);
230 /* Native seems to ignore any encoding type other than the expected
231 * PKCS_7_ASN_ENCODING
233 if (GET_CMSG_ENCODING_TYPE(pHashPara
->dwMsgEncodingType
) !=
236 /* Native also seems to do nothing if the output parameter isn't given */
240 flags
= fDetachedHash
? CMSG_DETACHED_FLAG
: 0;
241 memset(&info
, 0, sizeof(info
));
242 info
.cbSize
= sizeof(info
);
243 info
.hCryptProv
= pHashPara
->hCryptProv
;
244 memcpy(&info
.HashAlgorithm
, &pHashPara
->HashAlgorithm
,
245 sizeof(info
.HashAlgorithm
));
246 info
.pvHashAuxInfo
= pHashPara
->pvHashAuxInfo
;
247 msg
= CryptMsgOpenToEncode(pHashPara
->dwMsgEncodingType
, flags
, CMSG_HASHED
,
251 for (i
= 0, ret
= TRUE
; ret
&& i
< cToBeHashed
; i
++)
252 ret
= CryptMsgUpdate(msg
, rgpbToBeHashed
[i
], rgcbToBeHashed
[i
],
253 i
== cToBeHashed
- 1 ? TRUE
: FALSE
);
256 ret
= CryptMsgGetParam(msg
, CMSG_CONTENT_PARAM
, 0, pbHashedBlob
,
258 if (ret
&& pcbComputedHash
)
259 ret
= CryptMsgGetParam(msg
, CMSG_COMPUTED_HASH_PARAM
, 0,
260 pbComputedHash
, pcbComputedHash
);
267 BOOL WINAPI
CryptVerifyDetachedMessageHash(PCRYPT_HASH_MESSAGE_PARA pHashPara
,
268 BYTE
*pbDetachedHashBlob
, DWORD cbDetachedHashBlob
, DWORD cToBeHashed
,
269 const BYTE
*rgpbToBeHashed
[], DWORD rgcbToBeHashed
[], BYTE
*pbComputedHash
,
270 DWORD
*pcbComputedHash
)
275 TRACE("(%p, %p, %d, %d, %p, %p, %p, %p)\n", pHashPara
, pbDetachedHashBlob
,
276 cbDetachedHashBlob
, cToBeHashed
, rgpbToBeHashed
, rgcbToBeHashed
,
277 pbComputedHash
, pcbComputedHash
);
279 if (pHashPara
->cbSize
!= sizeof(CRYPT_HASH_MESSAGE_PARA
))
281 SetLastError(E_INVALIDARG
);
284 if (GET_CMSG_ENCODING_TYPE(pHashPara
->dwMsgEncodingType
) !=
287 SetLastError(E_INVALIDARG
);
290 msg
= CryptMsgOpenToDecode(pHashPara
->dwMsgEncodingType
, CMSG_DETACHED_FLAG
,
291 0, pHashPara
->hCryptProv
, NULL
, NULL
);
296 ret
= CryptMsgUpdate(msg
, pbDetachedHashBlob
, cbDetachedHashBlob
, TRUE
);
301 for (i
= 0; ret
&& i
< cToBeHashed
; i
++)
303 ret
= CryptMsgUpdate(msg
, rgpbToBeHashed
[i
],
304 rgcbToBeHashed
[i
], i
== cToBeHashed
- 1 ? TRUE
: FALSE
);
308 ret
= CryptMsgUpdate(msg
, NULL
, 0, TRUE
);
312 ret
= CryptMsgControl(msg
, 0, CMSG_CTRL_VERIFY_HASH
, NULL
);
313 if (ret
&& pcbComputedHash
)
314 ret
= CryptMsgGetParam(msg
, CMSG_COMPUTED_HASH_PARAM
, 0,
315 pbComputedHash
, pcbComputedHash
);