LibreOffice Module onlineupdate (master) 1
mar_verify.c
Go to the documentation of this file.
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/. */
4
5#ifdef _WIN32
6#ifndef WIN32_LEAN_AND_MEAN
7#define WIN32_LEAN_AND_MEAN
8#endif
9#endif
10
11#include <sys/types.h>
12#include <sys/stat.h>
13#include <fcntl.h>
14#include <stdlib.h>
15#include <string.h>
16#include <assert.h>
18#include <onlineupdate/mar.h>
19#include "cryptox.h"
20
21int
22mar_read_entire_file(const char * filePath, uint32_t maxSize,
23 /*out*/ const uint8_t * *data,
24 /*out*/ uint32_t *size)
25{
26 int result;
27 FILE * f;
28
29 if (!filePath || !data || !size) {
30 return -1;
31 }
32
33 f = fopen(filePath, "rb");
34 if (!f) {
35 return -1;
36 }
37
38 result = -1;
39 if (!fseeko(f, 0, SEEK_END)) {
40 int64_t fileSize = ftello(f);
41 if (fileSize > 0 && fileSize <= maxSize && !fseeko(f, 0, SEEK_SET)) {
42 unsigned char * fileData;
43
44 *size = (unsigned int) fileSize;
45 fileData = malloc(*size);
46 if (fileData) {
47 if (fread(fileData, *size, 1, f) == 1) {
48 *data = fileData;
49 result = 0;
50 } else {
51 free(fileData);
52 }
53 }
54 }
55 }
56
57 fclose(f);
58
59 return result;
60}
61
65 uint32_t keyCount);
69 const uint8_t * const *extractedSignatures,
70 uint32_t keyCount,
71 uint32_t *numVerified);
72
88int
90 void *buffer,
91 uint32_t size,
93 uint32_t count,
94 const char *err)
95{
96 uint32_t k;
97 if (!fp || !buffer || !ctxs || count == 0 || !err) {
98 fprintf(stderr, "ERROR: Invalid parameter specified.\n");
99 return CryptoX_Error;
100 }
101
102 if (!size) {
103 return CryptoX_Success;
104 }
105
106 if (fread(buffer, size, 1, fp) != 1) {
107 fprintf(stderr, "ERROR: Could not read %s\n", err);
108 return CryptoX_Error;
109 }
110
111 for (k = 0; k < count; k++) {
112 if (CryptoX_Failed(CryptoX_VerifyUpdate(&ctxs[k], buffer, size))) {
113 fprintf(stderr, "ERROR: Could not update verify context for %s\n", err);
114 return -2;
115 }
116 }
117 return CryptoX_Success;
118}
119
135int
137 const uint8_t * const *certData,
138 const uint32_t *certDataSizes,
139 uint32_t certCount) {
140 int rv = -1;
143 uint32_t k;
144
145 memset(keys, 0, sizeof(keys));
146
147 if (!mar || !certData || !certDataSizes || certCount == 0) {
148 fprintf(stderr, "ERROR: Invalid parameter specified.\n");
149 goto failure;
150 }
151
152 if (!mar->fp) {
153 fprintf(stderr, "ERROR: MAR file is not open.\n");
154 goto failure;
155 }
156
158 fprintf(stderr, "ERROR: Could not init crypto library.\n");
159 goto failure;
160 }
161
162 for (k = 0; k < certCount; ++k) {
163 if (CryptoX_Failed(CryptoX_LoadPublicKey(provider, certData[k], certDataSizes[k],
164 &keys[k]))) {
165 fprintf(stderr, "ERROR: Could not load public key.\n");
166 goto failure;
167 }
168 }
169
170 rv = mar_extract_and_verify_signatures_fp(mar->fp, provider, keys, certCount);
171
172failure:
173
174 for (k = 0; k < certCount; ++k) {
175 if (keys[k]) {
176 CryptoX_FreePublicKey(&keys[k]);
177 }
178 }
179
180 return rv;
181}
182
193int
195 CryptoX_ProviderHandle provider,
196 CryptoX_PublicKey *keys,
197 uint32_t keyCount) {
198 uint32_t signatureCount, signatureLen, numVerified = 0;
199 uint32_t signatureAlgorithmIDs[MAX_SIGNATURES];
200 int rv = -1;
201 uint8_t *extractedSignatures[MAX_SIGNATURES];
202 uint32_t i;
203
204 memset(signatureAlgorithmIDs, 0, sizeof(signatureAlgorithmIDs));
205 memset(extractedSignatures, 0, sizeof(extractedSignatures));
206
207 if (!fp) {
208 fprintf(stderr, "ERROR: Invalid file pointer passed.\n");
209 return CryptoX_Error;
210 }
211
212 /* To protect against invalid MAR files, we assume that the MAR file
213 size is less than or equal to MAX_SIZE_OF_MAR_FILE. */
214 if (fseeko(fp, 0, SEEK_END)) {
215 fprintf(stderr, "ERROR: Could not seek to the end of the MAR file.\n");
216 return CryptoX_Error;
217 }
218 if (ftello(fp) > MAX_SIZE_OF_MAR_FILE) {
219 fprintf(stderr, "ERROR: MAR file is too large to be verified.\n");
220 return CryptoX_Error;
221 }
222
223 /* Skip to the start of the signature block */
224 if (fseeko(fp, SIGNATURE_BLOCK_OFFSET, SEEK_SET)) {
225 fprintf(stderr, "ERROR: Could not seek to the signature block.\n");
226 return CryptoX_Error;
227 }
228
229 /* Get the number of signatures */
230 if (fread(&signatureCount, sizeof(signatureCount), 1, fp) != 1) {
231 fprintf(stderr, "ERROR: Could not read number of signatures.\n");
232 return CryptoX_Error;
233 }
234 signatureCount = ntohl(signatureCount);
235
236 /* Check that we have less than the max amount of signatures so we don't
237 waste too much of either updater's or signmar's time. */
238 if (signatureCount > MAX_SIGNATURES) {
239 fprintf(stderr, "ERROR: At most %d signatures can be specified.\n",
241 return CryptoX_Error;
242 }
243
244 for (i = 0; i < signatureCount; i++) {
245 /* Get the signature algorithm ID */
246 if (fread(&signatureAlgorithmIDs[i], sizeof(uint32_t), 1, fp) != 1) {
247 fprintf(stderr, "ERROR: Could not read signatures algorithm ID.\n");
248 return CryptoX_Error;
249 }
250 signatureAlgorithmIDs[i] = ntohl(signatureAlgorithmIDs[i]);
251
252 if (fread(&signatureLen, sizeof(uint32_t), 1, fp) != 1) {
253 fprintf(stderr, "ERROR: Could not read signatures length.\n");
254 return CryptoX_Error;
255 }
256 signatureLen = ntohl(signatureLen);
257
258 /* To protected against invalid input make sure the signature length
259 isn't too big. */
260 if (signatureLen > MAX_SIGNATURE_LENGTH) {
261 fprintf(stderr, "ERROR: Signature length is too large to verify.\n");
262 return CryptoX_Error;
263 }
264
265 extractedSignatures[i] = malloc(signatureLen);
266 if (!extractedSignatures[i]) {
267 fprintf(stderr, "ERROR: Could allocate buffer for signature.\n");
268 return CryptoX_Error;
269 }
270 if (fread(extractedSignatures[i], signatureLen, 1, fp) != 1) {
271 fprintf(stderr, "ERROR: Could not read extracted signature.\n");
272 for (i = 0; i < signatureCount; ++i) {
273 free(extractedSignatures[i]);
274 }
275 return CryptoX_Error;
276 }
277
278 /* We don't try to verify signatures we don't know about */
279 if (signatureAlgorithmIDs[i] != 1) {
280 fprintf(stderr, "ERROR: Unknown signature algorithm ID.\n");
281 for (i = 0; i < signatureCount; ++i) {
282 free(extractedSignatures[i]);
283 }
284 return CryptoX_Error;
285 }
286 }
287
289 provider,
290 keys,
291 (const uint8_t * const *)extractedSignatures,
292 signatureCount,
293 &numVerified);
294 for (i = 0; i < signatureCount; ++i) {
295 free(extractedSignatures[i]);
296 }
297
298 /* If we reached here and we verified every
299 signature, return success. */
300 if (numVerified == signatureCount && keyCount == numVerified) {
301 assert(rv == 0); (void) rv;
302 return CryptoX_Success;
303 }
304
305 if (numVerified == 0) {
306 fprintf(stderr, "ERROR: Not all signatures were verified.\n");
307 } else {
308 fprintf(stderr, "ERROR: Only %d of %d signatures were verified.\n",
309 numVerified, signatureCount);
310 }
311 return CryptoX_Error;
312}
313
334int
336 CryptoX_ProviderHandle provider,
337 CryptoX_PublicKey *keys,
338 const uint8_t * const *extractedSignatures,
339 uint32_t signatureCount,
340 uint32_t *numVerified)
341{
342 CryptoX_SignatureHandle signatureHandles[MAX_SIGNATURES];
343 char buf[BLOCKSIZE];
344 uint32_t signatureLengths[MAX_SIGNATURES];
345 uint32_t i;
346 int rv = CryptoX_Error;
347
348 (void) provider; (void) keys; // avoid warnings
349
350 memset(signatureHandles, 0, sizeof(signatureHandles));
351 memset(signatureLengths, 0, sizeof(signatureLengths));
352
353 if (!extractedSignatures || !numVerified) {
354 fprintf(stderr, "ERROR: Invalid parameter specified.\n");
355 goto failure;
356 }
357
358 *numVerified = 0;
359
360 /* This function is only called when we have at least one signature,
361 but to protected against future people who call this function we
362 make sure a non zero value is passed in.
363 */
364 if (!signatureCount) {
365 fprintf(stderr, "ERROR: There must be at least one signature.\n");
366 goto failure;
367 }
368
369 for (i = 0; i < signatureCount; i++) {
371 &signatureHandles[i], &keys[i]))) {
372 fprintf(stderr, "ERROR: Could not initialize signature handle.\n");
373 goto failure;
374 }
375 }
376
377 /* Skip to the start of the file */
378 if (fseeko(fp, 0, SEEK_SET)) {
379 fprintf(stderr, "ERROR: Could not seek to start of the file\n");
380 goto failure;
381 }
382
383 /* Bytes 0-3: MAR1
384 Bytes 4-7: index offset
385 Bytes 8-15: size of entire MAR
386 */
389 sizeof(uint32_t),
390 signatureHandles,
391 signatureCount,
392 "signature block"))) {
393 goto failure;
394 }
395
396 /* Read the signature block */
397 for (i = 0; i < signatureCount; i++) {
398 /* Get the signature algorithm ID */
400 &buf,
401 sizeof(uint32_t),
402 signatureHandles,
403 signatureCount,
404 "signature algorithm ID"))) {
405 goto failure;
406 }
407
409 &signatureLengths[i],
410 sizeof(uint32_t),
411 signatureHandles,
412 signatureCount,
413 "signature length"))) {
414 goto failure;
415 }
416 signatureLengths[i] = ntohl(signatureLengths[i]);
417 if (signatureLengths[i] > MAX_SIGNATURE_LENGTH) {
418 fprintf(stderr, "ERROR: Embedded signature length is too large.\n");
419 goto failure;
420 }
421
422 /* Skip past the signature itself as those are not included */
423 if (fseeko(fp, signatureLengths[i], SEEK_CUR)) {
424 fprintf(stderr, "ERROR: Could not seek past signature.\n");
425 goto failure;
426 }
427 }
428
429 /* Read the rest of the file after the signature block */
430 while (!feof(fp)) {
431 int numRead = fread(buf, 1, BLOCKSIZE , fp);
432 if (ferror(fp)) {
433 fprintf(stderr, "ERROR: Error reading data block.\n");
434 goto failure;
435 }
436
437 for (i = 0; i < signatureCount; i++) {
438 if (CryptoX_Failed(CryptoX_VerifyUpdate(&signatureHandles[i],
439 buf, numRead))) {
440 fprintf(stderr, "ERROR: Error updating verify context with"
441 " data block.\n");
442 goto failure;
443 }
444 }
445 }
446
447 /* Verify the signatures */
448 for (i = 0; i < signatureCount; i++) {
449 if (CryptoX_Failed(CryptoX_VerifySignature(&signatureHandles[i],
450 &keys[i],
451 extractedSignatures[i],
452 signatureLengths[i]))) {
453 fprintf(stderr, "ERROR: Error verifying signature.\n");
454 goto failure;
455 }
456 ++*numVerified;
457 }
458
459 rv = CryptoX_Success;
460failure:
461 for (i = 0; i < signatureCount; i++) {
462 CryptoX_FreeSignatureHandle(&signatureHandles[i]);
463 }
464
465 return rv;
466}
#define CryptoX_LoadPublicKey(CryptoHandle, certData, dataSize, publicKey)
Definition: cryptox.h:165
#define CryptoX_ProviderHandle
Definition: cryptox.h:155
#define CryptoX_InvalidHandleValue
Definition: cryptox.h:154
#define CryptoX_Error
Definition: cryptox.h:12
#define CryptoX_InitCryptoProvider(CryptoHandle)
Definition: cryptox.h:159
#define CryptoX_Failed(X)
Definition: cryptox.h:14
#define CryptoX_VerifyBegin(CryptoHandle, SignatureHandle, PublicKey)
Definition: cryptox.h:161
#define CryptoX_FreeSignatureHandle(SignatureHandle)
Definition: cryptox.h:163
#define CryptoX_Success
Definition: cryptox.h:11
#define CryptoX_VerifyUpdate(SignatureHandle, buf, len)
Definition: cryptox.h:164
#define CryptoX_VerifySignature(hash, publicKey, signedData, len)
Definition: cryptox.h:167
#define CryptoX_FreePublicKey(key)
Definition: cryptox.h:168
#define CryptoX_PublicKey
Definition: cryptox.h:157
#define CryptoX_SignatureHandle
Definition: cryptox.h:156
#define MAX_SIGNATURES
Definition: mar.h:23
#define MAX_SIZE_OF_MAR_FILE
Definition: mar_private.h:26
#define SIGNATURE_BLOCK_OFFSET
Definition: mar_private.h:22
#define MAX_SIGNATURE_LENGTH
Definition: mar_private.h:41
#define BLOCKSIZE
Definition: mar_private.h:14
int mar_verify_signatures_for_fp(FILE *fp, CryptoX_ProviderHandle provider, CryptoX_PublicKey *keys, const uint8_t *const *extractedSignatures, uint32_t keyCount, uint32_t *numVerified)
Verifies a MAR file by verifying each signature with the corresponding certificate.
Definition: mar_verify.c:335
int ReadAndUpdateVerifyContext(FILE *fp, void *buffer, uint32_t size, CryptoX_SignatureHandle *ctxs, uint32_t count, const char *err)
Reads the specified number of bytes from the file pointer and stores them in the passed buffer.
Definition: mar_verify.c:89
int mar_extract_and_verify_signatures_fp(FILE *fp, CryptoX_ProviderHandle provider, CryptoX_PublicKey *keys, uint32_t keyCount)
Extracts each signature from the specified MAR file, then calls mar_verify_signatures_for_fp to verif...
Definition: mar_verify.c:194
int mar_read_entire_file(const char *filePath, uint32_t maxSize, const uint8_t **data, uint32_t *size)
Definition: mar_verify.c:22
int mar_verify_signatures(MarFile *mar, const uint8_t *const *certData, const uint32_t *certDataSizes, uint32_t certCount)
Verifies a MAR file by verifying each signature with the corresponding certificate.
Definition: mar_verify.c:136
err
size
filePath
int i
sal_uInt32 ntohl(sal_uInt32 n)
const wchar_t *typedef int(__stdcall *DllNativeUnregProc)(int
Definition: mar.h:48
FILE * fp
Definition: mar.h:49
Any result