Version 7.6.3.2-android, tag libreoffice-7.6.3.2-android
[LibreOffice.git] / onlineupdate / source / libmar / verify / cryptox.c
blob7cce8bf036fd5cc10a81d1845445975013d8de03
1 /* This Source Code Form is subject to the terms of the Mozilla Public
2 * License, v. 2.0. If a copy of the MPL was not distributed with this
3 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
5 #ifdef _WIN32
6 #ifndef WIN32_LEAN_AND_MEAN
7 #define WIN32_LEAN_AND_MEAN
8 #endif
9 #endif
11 #include <stdlib.h>
12 #include "cryptox.h"
14 #ifdef _WIN32
15 #pragma warning(push)
16 #pragma warning(disable: 4204)
17 #endif
19 #if defined(MAR_NSS)
21 /**
22 * Loads the public key for the specified cert name from the NSS store.
24 * @param certData The DER-encoded X509 certificate to extract the key from.
25 * @param certDataSize The size of certData.
26 * @param publicKey Out parameter for the public key to use.
27 * @return CryptoX_Success on success, CryptoX_Error on error.
29 CryptoX_Result
30 NSS_LoadPublicKey(const unsigned char *certData, unsigned int certDataSize,
31 SECKEYPublicKey **publicKey)
33 CERTCertificate * cert;
34 SECItem certDataItem = { siBuffer, (unsigned char*) certData, certDataSize };
36 if (!certData || !publicKey) {
37 return CryptoX_Error;
40 cert = CERT_NewTempCertificate(CERT_GetDefaultCertDB(), &certDataItem, NULL,
41 PR_FALSE, PR_TRUE);
42 /* Get the cert and embedded public key out of the database */
43 if (!cert) {
44 return CryptoX_Error;
46 *publicKey = CERT_ExtractPublicKey(cert);
47 CERT_DestroyCertificate(cert);
49 if (!*publicKey) {
50 return CryptoX_Error;
52 return CryptoX_Success;
55 CryptoX_Result
56 NSS_VerifyBegin(VFYContext **ctx,
57 SECKEYPublicKey * const *publicKey)
59 SECStatus status;
60 if (!ctx || !publicKey || !*publicKey) {
61 return CryptoX_Error;
64 /* Check that the key length is large enough for our requirements */
65 if ((SECKEY_PublicKeyStrength(*publicKey) * 8) <
66 XP_MIN_SIGNATURE_LEN_IN_BYTES) {
67 fprintf(stderr, "ERROR: Key length must be >= %d bytes\n",
68 XP_MIN_SIGNATURE_LEN_IN_BYTES);
69 return CryptoX_Error;
72 *ctx = VFY_CreateContext(*publicKey, NULL,
73 SEC_OID_ISO_SHA1_WITH_RSA_SIGNATURE, NULL);
74 if (*ctx == NULL) {
75 return CryptoX_Error;
78 status = VFY_Begin(*ctx);
79 return SECSuccess == status ? CryptoX_Success : CryptoX_Error;
82 /**
83 * Verifies if a verify context matches the passed in signature.
85 * @param ctx The verify context that the signature should match.
86 * @param signature The signature to match.
87 * @param signatureLen The length of the signature.
88 * @return CryptoX_Success on success, CryptoX_Error on error.
90 CryptoX_Result
91 NSS_VerifySignature(VFYContext * const *ctx,
92 const unsigned char *signature,
93 unsigned int signatureLen)
95 SECItem signedItem;
96 SECStatus status;
97 if (!ctx || !signature || !*ctx) {
98 return CryptoX_Error;
101 signedItem.len = signatureLen;
102 signedItem.data = (unsigned char*)signature;
103 status = VFY_EndWithSignature(*ctx, &signedItem);
104 return SECSuccess == status ? CryptoX_Success : CryptoX_Error;
107 #elif defined(WNT)
109 * Verifies if a signature + public key matches a hash context.
111 * @param hash The hash context that the signature should match.
112 * @param pubKey The public key to use on the signature.
113 * @param signature The signature to check.
114 * @param signatureLen The length of the signature.
115 * @return CryptoX_Success on success, CryptoX_Error on error.
117 CryptoX_Result
118 CryptoAPI_VerifySignature(HCRYPTHASH *hash,
119 HCRYPTKEY *pubKey,
120 const BYTE *signature,
121 DWORD signatureLen)
123 DWORD i;
124 BOOL result;
125 /* Windows APIs expect the bytes in the signature to be in little-endian
126 * order, but we write the signature in big-endian order. Other APIs like
127 * NSS and OpenSSL expect big-endian order.
129 BYTE *signatureReversed;
130 if (!hash || !pubKey || !signature || signatureLen < 1) {
131 return CryptoX_Error;
134 signatureReversed = malloc(signatureLen);
135 if (!signatureReversed) {
136 return CryptoX_Error;
139 for (i = 0; i < signatureLen; i++) {
140 signatureReversed[i] = signature[signatureLen - 1 - i];
142 result = CryptVerifySignature(*hash, signatureReversed,
143 signatureLen, *pubKey, NULL, 0);
144 free(signatureReversed);
145 return result ? CryptoX_Success : CryptoX_Error;
149 * Obtains the public key for the passed in cert data
151 * @param provider The crypto provider
152 * @param certData Data of the certificate to extract the public key from
153 * @param sizeOfCertData The size of the certData buffer
154 * @param certStore Pointer to the handle of the certificate store to use
155 * @param CryptoX_Success on success
157 CryptoX_Result
158 CryptoAPI_LoadPublicKey(HCRYPTPROV provider,
159 BYTE *certData,
160 DWORD sizeOfCertData,
161 HCRYPTKEY *publicKey)
163 CRYPT_DATA_BLOB blob;
164 CERT_CONTEXT *context;
165 if (!provider || !certData || !publicKey) {
166 return CryptoX_Error;
169 blob.cbData = sizeOfCertData;
170 blob.pbData = certData;
171 if (!CryptQueryObject(CERT_QUERY_OBJECT_BLOB, &blob,
172 CERT_QUERY_CONTENT_FLAG_CERT,
173 CERT_QUERY_FORMAT_FLAG_BINARY,
174 0, NULL, NULL, NULL,
175 NULL, NULL, (const void **)&context)) {
176 return CryptoX_Error;
179 if (!CryptImportPublicKeyInfo(provider,
180 PKCS_7_ASN_ENCODING | X509_ASN_ENCODING,
181 &context->pCertInfo->SubjectPublicKeyInfo,
182 publicKey)) {
183 CertFreeCertificateContext(context);
184 return CryptoX_Error;
187 CertFreeCertificateContext(context);
188 return CryptoX_Success;
191 /* Try to acquire context in this way:
192 * 1. Enhanced provider without creating a new key set
193 * 2. Enhanced provider with creating a new key set
194 * 3. Default provider without creating a new key set
195 * 4. Default provider without creating a new key set
196 * #2 and #4 should not be needed because of the CRYPT_VERIFYCONTEXT,
197 * but we add it just in case.
199 * @param provider Out parameter containing the provider handle.
200 * @return CryptoX_Success on success, CryptoX_Error on error.
202 CryptoX_Result
203 CryptoAPI_InitCryptoContext(HCRYPTPROV *provider)
205 if (!CryptAcquireContext(provider,
206 NULL,
207 MS_ENHANCED_PROV,
208 PROV_RSA_FULL,
209 CRYPT_VERIFYCONTEXT)) {
210 if (!CryptAcquireContext(provider,
211 NULL,
212 MS_ENHANCED_PROV,
213 PROV_RSA_FULL,
214 CRYPT_NEWKEYSET | CRYPT_VERIFYCONTEXT)) {
215 if (!CryptAcquireContext(provider,
216 NULL,
217 NULL,
218 PROV_RSA_FULL,
219 CRYPT_VERIFYCONTEXT)) {
220 if (!CryptAcquireContext(provider,
221 NULL,
222 NULL,
223 PROV_RSA_FULL,
224 CRYPT_NEWKEYSET | CRYPT_VERIFYCONTEXT)) {
225 *provider = CryptoX_InvalidHandleValue;
226 return CryptoX_Error;
231 return CryptoX_Success;
235 * Begins a signature verification hash context
237 * @param provider The crypt provider to use
238 * @param hash Out parameter for a handle to the hash context
239 * @return CryptoX_Success on success, CryptoX_Error on error.
241 CryptoX_Result
242 CryptoAPI_VerifyBegin(HCRYPTPROV provider, HCRYPTHASH* hash)
244 BOOL result;
245 if (!provider || !hash) {
246 return CryptoX_Error;
249 *hash = (HCRYPTHASH)NULL;
250 result = CryptCreateHash(provider, CALG_SHA1,
251 0, 0, hash);
252 return result ? CryptoX_Success : CryptoX_Error;
256 * Updates a signature verification hash context
258 * @param hash The hash context to update
259 * @param buf The buffer to update the hash context with
260 * @param len The size of the passed in buffer
261 * @return CryptoX_Success on success, CryptoX_Error on error.
263 CryptoX_Result
264 CryptoAPI_VerifyUpdate(HCRYPTHASH* hash, BYTE *buf, DWORD len)
266 BOOL result;
267 if (!hash || !buf) {
268 return CryptoX_Error;
271 result = CryptHashData(*hash, buf, len, 0);
272 return result ? CryptoX_Success : CryptoX_Error;
275 #ifdef _WIN32
276 #pragma warning(pop)
277 #endif
279 #endif