1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/modules/libmar/sign/mar_sign.c Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,1160 @@ 1.4 +/* This Source Code Form is subject to the terms of the Mozilla Public 1.5 + * License, v. 2.0. If a copy of the MPL was not distributed with this 1.6 + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 1.7 + 1.8 +#ifdef XP_WIN 1.9 +#ifndef WIN32_LEAN_AND_MEAN 1.10 +#define WIN32_LEAN_AND_MEAN 1.11 +#endif 1.12 +#endif 1.13 + 1.14 +#include <sys/types.h> 1.15 +#include <sys/stat.h> 1.16 +#include <fcntl.h> 1.17 +#include <stdlib.h> 1.18 +#include <string.h> 1.19 +#include "mar_private.h" 1.20 +#include "mar_cmdline.h" 1.21 +#include "mar.h" 1.22 +#include "cryptox.h" 1.23 +#ifndef XP_WIN 1.24 +#include <unistd.h> 1.25 +#endif 1.26 + 1.27 +#include "nss_secutil.h" 1.28 +#include "base64.h" 1.29 + 1.30 +/** 1.31 + * Initializes the NSS context. 1.32 + * 1.33 + * @param NSSConfigDir The config dir containing the private key to use 1.34 + * @return 0 on success 1.35 + * -1 on error 1.36 +*/ 1.37 +int 1.38 +NSSInitCryptoContext(const char *NSSConfigDir) 1.39 +{ 1.40 + SECStatus status = NSS_Initialize(NSSConfigDir, 1.41 + "", "", SECMOD_DB, NSS_INIT_READONLY); 1.42 + if (SECSuccess != status) { 1.43 + fprintf(stderr, "ERROR: Could not initialize NSS\n"); 1.44 + return -1; 1.45 + } 1.46 + 1.47 + return 0; 1.48 +} 1.49 + 1.50 +/** 1.51 + * Obtains a signing context. 1.52 + * 1.53 + * @param ctx A pointer to the signing context to fill 1.54 + * @return 0 on success 1.55 + * -1 on error 1.56 +*/ 1.57 +int 1.58 +NSSSignBegin(const char *certName, 1.59 + SGNContext **ctx, 1.60 + SECKEYPrivateKey **privKey, 1.61 + CERTCertificate **cert, 1.62 + uint32_t *signatureLength) 1.63 +{ 1.64 + secuPWData pwdata = { PW_NONE, 0 }; 1.65 + if (!certName || !ctx || !privKey || !cert || !signatureLength) { 1.66 + fprintf(stderr, "ERROR: Invalid parameter passed to NSSSignBegin\n"); 1.67 + return -1; 1.68 + } 1.69 + 1.70 + /* Get the cert and embedded public key out of the database */ 1.71 + *cert = PK11_FindCertFromNickname(certName, &pwdata); 1.72 + if (!*cert) { 1.73 + fprintf(stderr, "ERROR: Could not find cert from nickname\n"); 1.74 + return -1; 1.75 + } 1.76 + 1.77 + /* Get the private key out of the database */ 1.78 + *privKey = PK11_FindKeyByAnyCert(*cert, &pwdata); 1.79 + if (!*privKey) { 1.80 + fprintf(stderr, "ERROR: Could not find private key\n"); 1.81 + return -1; 1.82 + } 1.83 + 1.84 + *signatureLength = PK11_SignatureLen(*privKey); 1.85 + 1.86 + if (*signatureLength > BLOCKSIZE) { 1.87 + fprintf(stderr, 1.88 + "ERROR: Program must be compiled with a larger block size" 1.89 + " to support signing with signatures this large: %u.\n", 1.90 + *signatureLength); 1.91 + return -1; 1.92 + } 1.93 + 1.94 + /* Check that the key length is large enough for our requirements */ 1.95 + if (*signatureLength < XP_MIN_SIGNATURE_LEN_IN_BYTES) { 1.96 + fprintf(stderr, "ERROR: Key length must be >= %d bytes\n", 1.97 + XP_MIN_SIGNATURE_LEN_IN_BYTES); 1.98 + return -1; 1.99 + } 1.100 + 1.101 + *ctx = SGN_NewContext (SEC_OID_ISO_SHA1_WITH_RSA_SIGNATURE, *privKey); 1.102 + if (!*ctx) { 1.103 + fprintf(stderr, "ERROR: Could not create signature context\n"); 1.104 + return -1; 1.105 + } 1.106 + 1.107 + if (SGN_Begin(*ctx) != SECSuccess) { 1.108 + fprintf(stderr, "ERROR: Could not begin signature\n"); 1.109 + return -1; 1.110 + } 1.111 + 1.112 + return 0; 1.113 +} 1.114 + 1.115 +/** 1.116 + * Writes the passed buffer to the file fp and updates the signature contexts. 1.117 + * 1.118 + * @param fpDest The file pointer to write to. 1.119 + * @param buffer The buffer to write. 1.120 + * @param size The size of the buffer to write. 1.121 + * @param ctxs Pointer to the first element in an array of signature 1.122 + * contexts to update. 1.123 + * @param ctxCount The number of signature contexts pointed to by ctxs 1.124 + * @param err The name of what is being written to in case of error. 1.125 + * @return 0 on success 1.126 + * -2 on write error 1.127 + * -3 on signature update error 1.128 +*/ 1.129 +int 1.130 +WriteAndUpdateSignatures(FILE *fpDest, void *buffer, 1.131 + uint32_t size, SGNContext **ctxs, 1.132 + uint32_t ctxCount, 1.133 + const char *err) 1.134 +{ 1.135 + uint32_t k; 1.136 + if (!size) { 1.137 + return 0; 1.138 + } 1.139 + 1.140 + if (fwrite(buffer, size, 1, fpDest) != 1) { 1.141 + fprintf(stderr, "ERROR: Could not write %s\n", err); 1.142 + return -2; 1.143 + } 1.144 + 1.145 + for (k = 0; k < ctxCount; ++k) { 1.146 + if (SGN_Update(ctxs[k], buffer, size) != SECSuccess) { 1.147 + fprintf(stderr, "ERROR: Could not update signature context for %s\n", err); 1.148 + return -3; 1.149 + } 1.150 + } 1.151 + return 0; 1.152 +} 1.153 + 1.154 +/** 1.155 + * Adjusts each entry's content offset in the the passed in index by the 1.156 + * specified amount. 1.157 + * 1.158 + * @param indexBuf A buffer containing the MAR index 1.159 + * @param indexLength The length of the MAR index 1.160 + * @param offsetAmount The amount to adjust each index entry by 1.161 +*/ 1.162 +void 1.163 +AdjustIndexContentOffsets(char *indexBuf, uint32_t indexLength, uint32_t offsetAmount) 1.164 +{ 1.165 + uint32_t *offsetToContent; 1.166 + char *indexBufLoc = indexBuf; 1.167 + 1.168 + /* Consume the index and adjust each index by the specified amount */ 1.169 + while (indexBufLoc != (indexBuf + indexLength)) { 1.170 + /* Adjust the offset */ 1.171 + offsetToContent = (uint32_t *)indexBufLoc; 1.172 + *offsetToContent = ntohl(*offsetToContent); 1.173 + *offsetToContent += offsetAmount; 1.174 + *offsetToContent = htonl(*offsetToContent); 1.175 + /* Skip past the offset, length, and flags */ 1.176 + indexBufLoc += 3 * sizeof(uint32_t); 1.177 + indexBufLoc += strlen(indexBufLoc) + 1; 1.178 + } 1.179 +} 1.180 + 1.181 +/** 1.182 + * Reads from fpSrc, writes it to fpDest, and updates the signature contexts. 1.183 + * 1.184 + * @param fpSrc The file pointer to read from. 1.185 + * @param fpDest The file pointer to write to. 1.186 + * @param buffer The buffer to write. 1.187 + * @param size The size of the buffer to write. 1.188 + * @param ctxs Pointer to the first element in an array of signature 1.189 + * contexts to update. 1.190 + * @param ctxCount The number of signature contexts pointed to by ctxs 1.191 + * @param err The name of what is being written to in case of error. 1.192 + * @return 0 on success 1.193 + * -1 on read error 1.194 + * -2 on write error 1.195 + * -3 on signature update error 1.196 +*/ 1.197 +int 1.198 +ReadWriteAndUpdateSignatures(FILE *fpSrc, FILE *fpDest, void *buffer, 1.199 + uint32_t size, SGNContext **ctxs, 1.200 + uint32_t ctxCount, 1.201 + const char *err) 1.202 +{ 1.203 + if (!size) { 1.204 + return 0; 1.205 + } 1.206 + 1.207 + if (fread(buffer, size, 1, fpSrc) != 1) { 1.208 + fprintf(stderr, "ERROR: Could not read %s\n", err); 1.209 + return -1; 1.210 + } 1.211 + 1.212 + return WriteAndUpdateSignatures(fpDest, buffer, size, ctxs, ctxCount, err); 1.213 +} 1.214 + 1.215 + 1.216 +/** 1.217 + * Reads from fpSrc, writes it to fpDest. 1.218 + * 1.219 + * @param fpSrc The file pointer to read from. 1.220 + * @param fpDest The file pointer to write to. 1.221 + * @param buffer The buffer to write. 1.222 + * @param size The size of the buffer to write. 1.223 + * @param err The name of what is being written to in case of error. 1.224 + * @return 0 on success 1.225 + * -1 on read error 1.226 + * -2 on write error 1.227 +*/ 1.228 +int 1.229 +ReadAndWrite(FILE *fpSrc, FILE *fpDest, void *buffer, 1.230 + uint32_t size, const char *err) 1.231 +{ 1.232 + if (!size) { 1.233 + return 0; 1.234 + } 1.235 + 1.236 + if (fread(buffer, size, 1, fpSrc) != 1) { 1.237 + fprintf(stderr, "ERROR: Could not read %s\n", err); 1.238 + return -1; 1.239 + } 1.240 + 1.241 + if (fwrite(buffer, size, 1, fpDest) != 1) { 1.242 + fprintf(stderr, "ERROR: Could not write %s\n", err); 1.243 + return -2; 1.244 + } 1.245 + 1.246 + return 0; 1.247 +} 1.248 + 1.249 +/** 1.250 + * Writes out a copy of the MAR at src but with the signature block stripped. 1.251 + * 1.252 + * @param src The path of the source MAR file 1.253 + * @param dest The path of the MAR file to write out that 1.254 + has no signature block 1.255 + * @return 0 on success 1.256 + * -1 on error 1.257 +*/ 1.258 +int 1.259 +strip_signature_block(const char *src, const char * dest) 1.260 +{ 1.261 + uint32_t offsetToIndex, dstOffsetToIndex, indexLength, 1.262 + numSignatures = 0, leftOver; 1.263 + int32_t stripAmount = 0; 1.264 + int64_t oldPos, sizeOfEntireMAR = 0, realSizeOfSrcMAR, numBytesToCopy, 1.265 + numChunks, i; 1.266 + FILE *fpSrc = NULL, *fpDest = NULL; 1.267 + int rv = -1, hasSignatureBlock; 1.268 + char buf[BLOCKSIZE]; 1.269 + char *indexBuf = NULL, *indexBufLoc; 1.270 + 1.271 + if (!src || !dest) { 1.272 + fprintf(stderr, "ERROR: Invalid parameter passed in.\n"); 1.273 + return -1; 1.274 + } 1.275 + 1.276 + fpSrc = fopen(src, "rb"); 1.277 + if (!fpSrc) { 1.278 + fprintf(stderr, "ERROR: could not open source file: %s\n", src); 1.279 + goto failure; 1.280 + } 1.281 + 1.282 + fpDest = fopen(dest, "wb"); 1.283 + if (!fpDest) { 1.284 + fprintf(stderr, "ERROR: could not create target file: %s\n", dest); 1.285 + goto failure; 1.286 + } 1.287 + 1.288 + /* Determine if the source MAR file has the new fields for signing or not */ 1.289 + if (get_mar_file_info(src, &hasSignatureBlock, NULL, NULL, NULL, NULL)) { 1.290 + fprintf(stderr, "ERROR: could not determine if MAR is old or new.\n"); 1.291 + goto failure; 1.292 + } 1.293 + 1.294 + /* MAR ID */ 1.295 + if (ReadAndWrite(fpSrc, fpDest, buf, MAR_ID_SIZE, "MAR ID")) { 1.296 + goto failure; 1.297 + } 1.298 + 1.299 + /* Offset to index */ 1.300 + if (fread(&offsetToIndex, sizeof(offsetToIndex), 1, fpSrc) != 1) { 1.301 + fprintf(stderr, "ERROR: Could not read offset\n"); 1.302 + goto failure; 1.303 + } 1.304 + offsetToIndex = ntohl(offsetToIndex); 1.305 + 1.306 + /* Get the real size of the MAR */ 1.307 + oldPos = ftello(fpSrc); 1.308 + if (fseeko(fpSrc, 0, SEEK_END)) { 1.309 + fprintf(stderr, "ERROR: Could not seek to end of file.\n"); 1.310 + goto failure; 1.311 + } 1.312 + realSizeOfSrcMAR = ftello(fpSrc); 1.313 + if (fseeko(fpSrc, oldPos, SEEK_SET)) { 1.314 + fprintf(stderr, "ERROR: Could not seek back to current location.\n"); 1.315 + goto failure; 1.316 + } 1.317 + 1.318 + if (hasSignatureBlock) { 1.319 + /* Get the MAR length and adjust its size */ 1.320 + if (fread(&sizeOfEntireMAR, 1.321 + sizeof(sizeOfEntireMAR), 1, fpSrc) != 1) { 1.322 + fprintf(stderr, "ERROR: Could read mar size\n"); 1.323 + goto failure; 1.324 + } 1.325 + sizeOfEntireMAR = NETWORK_TO_HOST64(sizeOfEntireMAR); 1.326 + if (sizeOfEntireMAR != realSizeOfSrcMAR) { 1.327 + fprintf(stderr, "ERROR: Source MAR is not of the right size\n"); 1.328 + goto failure; 1.329 + } 1.330 + 1.331 + /* Get the num signatures in the source file so we know what to strip */ 1.332 + if (fread(&numSignatures, sizeof(numSignatures), 1, fpSrc) != 1) { 1.333 + fprintf(stderr, "ERROR: Could read num signatures\n"); 1.334 + goto failure; 1.335 + } 1.336 + numSignatures = ntohl(numSignatures); 1.337 + 1.338 + for (i = 0; i < numSignatures; i++) { 1.339 + uint32_t signatureLen; 1.340 + 1.341 + /* Skip past the signature algorithm ID */ 1.342 + if (fseeko(fpSrc, sizeof(uint32_t), SEEK_CUR)) { 1.343 + fprintf(stderr, "ERROR: Could not skip past signature algorithm ID\n"); 1.344 + } 1.345 + 1.346 + /* Read in the length of the signature so we know how far to skip */ 1.347 + if (fread(&signatureLen, sizeof(uint32_t), 1, fpSrc) != 1) { 1.348 + fprintf(stderr, "ERROR: Could not read signatures length.\n"); 1.349 + return CryptoX_Error; 1.350 + } 1.351 + signatureLen = ntohl(signatureLen); 1.352 + 1.353 + /* Skip past the signature */ 1.354 + if (fseeko(fpSrc, signatureLen, SEEK_CUR)) { 1.355 + fprintf(stderr, "ERROR: Could not skip past signature algorithm ID\n"); 1.356 + } 1.357 + 1.358 + stripAmount += sizeof(uint32_t) + sizeof(uint32_t) + signatureLen; 1.359 + } 1.360 + 1.361 + } else { 1.362 + sizeOfEntireMAR = realSizeOfSrcMAR; 1.363 + numSignatures = 0; 1.364 + } 1.365 + 1.366 + if (((int64_t)offsetToIndex) > sizeOfEntireMAR) { 1.367 + fprintf(stderr, "ERROR: Offset to index is larger than the file size.\n"); 1.368 + goto failure; 1.369 + } 1.370 + 1.371 + dstOffsetToIndex = offsetToIndex; 1.372 + if (!hasSignatureBlock) { 1.373 + dstOffsetToIndex += sizeof(sizeOfEntireMAR) + sizeof(numSignatures); 1.374 + } 1.375 + dstOffsetToIndex -= stripAmount; 1.376 + 1.377 + /* Write out the index offset */ 1.378 + dstOffsetToIndex = htonl(dstOffsetToIndex); 1.379 + if (fwrite(&dstOffsetToIndex, sizeof(dstOffsetToIndex), 1, fpDest) != 1) { 1.380 + fprintf(stderr, "ERROR: Could not write offset to index\n"); 1.381 + goto failure; 1.382 + } 1.383 + dstOffsetToIndex = ntohl(dstOffsetToIndex); 1.384 + 1.385 + /* Write out the new MAR file size */ 1.386 + if (!hasSignatureBlock) { 1.387 + sizeOfEntireMAR += sizeof(sizeOfEntireMAR) + sizeof(numSignatures); 1.388 + } 1.389 + sizeOfEntireMAR -= stripAmount; 1.390 + 1.391 + /* Write out the MAR size */ 1.392 + sizeOfEntireMAR = HOST_TO_NETWORK64(sizeOfEntireMAR); 1.393 + if (fwrite(&sizeOfEntireMAR, sizeof(sizeOfEntireMAR), 1, fpDest) != 1) { 1.394 + fprintf(stderr, "ERROR: Could not write size of MAR\n"); 1.395 + goto failure; 1.396 + } 1.397 + sizeOfEntireMAR = NETWORK_TO_HOST64(sizeOfEntireMAR); 1.398 + 1.399 + /* Write out the number of signatures, which is 0 */ 1.400 + numSignatures = 0; 1.401 + if (fwrite(&numSignatures, sizeof(numSignatures), 1, fpDest) != 1) { 1.402 + fprintf(stderr, "ERROR: Could not write out num signatures\n"); 1.403 + goto failure; 1.404 + } 1.405 + 1.406 + /* Write out the rest of the MAR excluding the index header and index 1.407 + offsetToIndex unfortunately has to remain 32-bit because for backwards 1.408 + compatibility with the old MAR file format. */ 1.409 + if (ftello(fpSrc) > ((int64_t)offsetToIndex)) { 1.410 + fprintf(stderr, "ERROR: Index offset is too small.\n"); 1.411 + goto failure; 1.412 + } 1.413 + numBytesToCopy = ((int64_t)offsetToIndex) - ftello(fpSrc); 1.414 + numChunks = numBytesToCopy / BLOCKSIZE; 1.415 + leftOver = numBytesToCopy % BLOCKSIZE; 1.416 + 1.417 + /* Read each file and write it to the MAR file */ 1.418 + for (i = 0; i < numChunks; ++i) { 1.419 + if (ReadAndWrite(fpSrc, fpDest, buf, BLOCKSIZE, "content block")) { 1.420 + goto failure; 1.421 + } 1.422 + } 1.423 + 1.424 + /* Write out the left over */ 1.425 + if (ReadAndWrite(fpSrc, fpDest, buf, 1.426 + leftOver, "left over content block")) { 1.427 + goto failure; 1.428 + } 1.429 + 1.430 + /* Length of the index */ 1.431 + if (ReadAndWrite(fpSrc, fpDest, &indexLength, 1.432 + sizeof(indexLength), "index length")) { 1.433 + goto failure; 1.434 + } 1.435 + indexLength = ntohl(indexLength); 1.436 + 1.437 + /* Consume the index and adjust each index by the difference */ 1.438 + indexBuf = malloc(indexLength); 1.439 + indexBufLoc = indexBuf; 1.440 + if (fread(indexBuf, indexLength, 1, fpSrc) != 1) { 1.441 + fprintf(stderr, "ERROR: Could not read index\n"); 1.442 + goto failure; 1.443 + } 1.444 + 1.445 + /* Adjust each entry in the index */ 1.446 + if (hasSignatureBlock) { 1.447 + AdjustIndexContentOffsets(indexBuf, indexLength, -stripAmount); 1.448 + } else { 1.449 + AdjustIndexContentOffsets(indexBuf, indexLength, 1.450 + sizeof(sizeOfEntireMAR) + 1.451 + sizeof(numSignatures) - 1.452 + stripAmount); 1.453 + } 1.454 + 1.455 + if (fwrite(indexBuf, indexLength, 1, fpDest) != 1) { 1.456 + fprintf(stderr, "ERROR: Could not write index\n"); 1.457 + goto failure; 1.458 + } 1.459 + 1.460 + rv = 0; 1.461 +failure: 1.462 + if (fpSrc) { 1.463 + fclose(fpSrc); 1.464 + } 1.465 + 1.466 + if (fpDest) { 1.467 + fclose(fpDest); 1.468 + } 1.469 + 1.470 + if (rv) { 1.471 + remove(dest); 1.472 + } 1.473 + 1.474 + if (indexBuf) { 1.475 + free(indexBuf); 1.476 + } 1.477 + 1.478 + if (rv) { 1.479 + remove(dest); 1.480 + } 1.481 + return rv; 1.482 +} 1.483 + 1.484 +/** 1.485 + * Extracts a signature from a MAR file, base64 encodes it, and writes it out 1.486 + * 1.487 + * @param src The path of the source MAR file 1.488 + * @param sigIndex The index of the signature to extract 1.489 + * @param dest The path of file to write the signature to 1.490 + * @return 0 on success 1.491 + * -1 on error 1.492 +*/ 1.493 +int 1.494 +extract_signature(const char *src, uint32_t sigIndex, const char * dest) 1.495 +{ 1.496 + FILE *fpSrc = NULL, *fpDest = NULL; 1.497 + uint32_t i; 1.498 + uint32_t signatureCount; 1.499 + uint32_t signatureLen; 1.500 + uint8_t *extractedSignature = NULL; 1.501 + char *base64Encoded = NULL; 1.502 + int rv = -1; 1.503 + if (!src || !dest) { 1.504 + fprintf(stderr, "ERROR: Invalid parameter passed in.\n"); 1.505 + goto failure; 1.506 + } 1.507 + 1.508 + fpSrc = fopen(src, "rb"); 1.509 + if (!fpSrc) { 1.510 + fprintf(stderr, "ERROR: could not open source file: %s\n", src); 1.511 + goto failure; 1.512 + } 1.513 + 1.514 + fpDest = fopen(dest, "wb"); 1.515 + if (!fpDest) { 1.516 + fprintf(stderr, "ERROR: could not create target file: %s\n", dest); 1.517 + goto failure; 1.518 + } 1.519 + 1.520 + /* Skip to the start of the signature block */ 1.521 + if (fseeko(fpSrc, SIGNATURE_BLOCK_OFFSET, SEEK_SET)) { 1.522 + fprintf(stderr, "ERROR: could not seek to signature block\n"); 1.523 + goto failure; 1.524 + } 1.525 + 1.526 + /* Get the number of signatures */ 1.527 + if (fread(&signatureCount, sizeof(signatureCount), 1, fpSrc) != 1) { 1.528 + fprintf(stderr, "ERROR: could not read signature count\n"); 1.529 + goto failure; 1.530 + } 1.531 + signatureCount = ntohl(signatureCount); 1.532 + if (sigIndex >= signatureCount) { 1.533 + fprintf(stderr, "ERROR: Signature index was out of range\n"); 1.534 + goto failure; 1.535 + } 1.536 + 1.537 + /* Skip to the correct signature */ 1.538 + for (i = 0; i <= sigIndex; i++) { 1.539 + /* skip past the signature algorithm ID */ 1.540 + if (fseeko(fpSrc, sizeof(uint32_t), SEEK_CUR)) { 1.541 + fprintf(stderr, "ERROR: Could not seek past sig algorithm ID.\n"); 1.542 + goto failure; 1.543 + } 1.544 + 1.545 + /* Get the signature length */ 1.546 + if (fread(&signatureLen, sizeof(signatureLen), 1, fpSrc) != 1) { 1.547 + fprintf(stderr, "ERROR: could not read signature length\n"); 1.548 + goto failure; 1.549 + } 1.550 + signatureLen = ntohl(signatureLen); 1.551 + 1.552 + /* Get the signature */ 1.553 + extractedSignature = malloc(signatureLen); 1.554 + if (fread(extractedSignature, signatureLen, 1, fpSrc) != 1) { 1.555 + fprintf(stderr, "ERROR: could not read signature\n"); 1.556 + goto failure; 1.557 + } 1.558 + } 1.559 + 1.560 + base64Encoded = BTOA_DataToAscii(extractedSignature, signatureLen); 1.561 + if (!base64Encoded) { 1.562 + fprintf(stderr, "ERROR: could not obtain base64 encoded data\n"); 1.563 + goto failure; 1.564 + } 1.565 + 1.566 + if (fwrite(base64Encoded, strlen(base64Encoded), 1, fpDest) != 1) { 1.567 + fprintf(stderr, "ERROR: Could not write base64 encoded string\n"); 1.568 + goto failure; 1.569 + } 1.570 + 1.571 + rv = 0; 1.572 +failure: 1.573 + if (base64Encoded) { 1.574 + PORT_Free(base64Encoded); 1.575 + } 1.576 + 1.577 + if (extractedSignature) { 1.578 + free(extractedSignature); 1.579 + } 1.580 + 1.581 + if (fpSrc) { 1.582 + fclose(fpSrc); 1.583 + } 1.584 + 1.585 + if (fpDest) { 1.586 + fclose(fpDest); 1.587 + } 1.588 + 1.589 + if (rv) { 1.590 + remove(dest); 1.591 + } 1.592 + 1.593 + return rv; 1.594 +} 1.595 + 1.596 +/** 1.597 + * Imports a base64 encoded signature into a MAR file 1.598 + * 1.599 + * @param src The path of the source MAR file 1.600 + * @param sigIndex The index of the signature to import 1.601 + * @param base64SigFile A file which contains the signature to import 1.602 + * @param dest The path of the destination MAR file with replaced signature 1.603 + * @return 0 on success 1.604 + * -1 on error 1.605 +*/ 1.606 +int 1.607 +import_signature(const char *src, uint32_t sigIndex, 1.608 + const char *base64SigFile, const char *dest) 1.609 +{ 1.610 + int rv = -1; 1.611 + FILE *fpSrc = NULL; 1.612 + FILE *fpDest = NULL; 1.613 + FILE *fpSigFile = NULL; 1.614 + uint32_t i; 1.615 + uint32_t signatureCount, signatureLen, signatureAlgorithmID, 1.616 + numChunks, leftOver; 1.617 + char buf[BLOCKSIZE]; 1.618 + uint64_t sizeOfSrcMAR, sizeOfBase64EncodedFile; 1.619 + char *passedInSignatureB64 = NULL; 1.620 + uint8_t *passedInSignatureRaw = NULL; 1.621 + uint8_t *extractedMARSignature = NULL; 1.622 + unsigned int passedInSignatureLenRaw; 1.623 + 1.624 + if (!src || !dest) { 1.625 + fprintf(stderr, "ERROR: Invalid parameter passed in.\n"); 1.626 + goto failure; 1.627 + } 1.628 + 1.629 + fpSrc = fopen(src, "rb"); 1.630 + if (!fpSrc) { 1.631 + fprintf(stderr, "ERROR: could not open source file: %s\n", src); 1.632 + goto failure; 1.633 + } 1.634 + 1.635 + fpDest = fopen(dest, "wb"); 1.636 + if (!fpDest) { 1.637 + fprintf(stderr, "ERROR: could not open dest file: %s\n", dest); 1.638 + goto failure; 1.639 + } 1.640 + 1.641 + fpSigFile = fopen(base64SigFile , "rb"); 1.642 + if (!fpSigFile) { 1.643 + fprintf(stderr, "ERROR: could not open sig file: %s\n", base64SigFile); 1.644 + goto failure; 1.645 + } 1.646 + 1.647 + /* Get the src file size */ 1.648 + if (fseeko(fpSrc, 0, SEEK_END)) { 1.649 + fprintf(stderr, "ERROR: Could not seek to end of src file.\n"); 1.650 + goto failure; 1.651 + } 1.652 + sizeOfSrcMAR = ftello(fpSrc); 1.653 + if (fseeko(fpSrc, 0, SEEK_SET)) { 1.654 + fprintf(stderr, "ERROR: Could not seek to start of src file.\n"); 1.655 + goto failure; 1.656 + } 1.657 + 1.658 + /* Get the sig file size */ 1.659 + if (fseeko(fpSigFile, 0, SEEK_END)) { 1.660 + fprintf(stderr, "ERROR: Could not seek to end of sig file.\n"); 1.661 + goto failure; 1.662 + } 1.663 + sizeOfBase64EncodedFile= ftello(fpSigFile); 1.664 + if (fseeko(fpSigFile, 0, SEEK_SET)) { 1.665 + fprintf(stderr, "ERROR: Could not seek to start of sig file.\n"); 1.666 + goto failure; 1.667 + } 1.668 + 1.669 + /* Read in the base64 encoded signature to import */ 1.670 + passedInSignatureB64 = malloc(sizeOfBase64EncodedFile + 1); 1.671 + passedInSignatureB64[sizeOfBase64EncodedFile] = '\0'; 1.672 + if (fread(passedInSignatureB64, sizeOfBase64EncodedFile, 1, fpSigFile) != 1) { 1.673 + fprintf(stderr, "ERROR: Could read b64 sig file.\n"); 1.674 + goto failure; 1.675 + } 1.676 + 1.677 + /* Decode the base64 encoded data */ 1.678 + passedInSignatureRaw = ATOB_AsciiToData(passedInSignatureB64, &passedInSignatureLenRaw); 1.679 + if (!passedInSignatureRaw) { 1.680 + fprintf(stderr, "ERROR: could not obtain base64 decoded data\n"); 1.681 + goto failure; 1.682 + } 1.683 + 1.684 + /* Read everything up until the signature block offset and write it out */ 1.685 + if (ReadAndWrite(fpSrc, fpDest, buf, 1.686 + SIGNATURE_BLOCK_OFFSET, "signature block offset")) { 1.687 + goto failure; 1.688 + } 1.689 + 1.690 + /* Get the number of signatures */ 1.691 + if (ReadAndWrite(fpSrc, fpDest, &signatureCount, 1.692 + sizeof(signatureCount), "signature count")) { 1.693 + goto failure; 1.694 + } 1.695 + signatureCount = ntohl(signatureCount); 1.696 + if (signatureCount > MAX_SIGNATURES) { 1.697 + fprintf(stderr, "ERROR: Signature count was out of range\n"); 1.698 + goto failure; 1.699 + } 1.700 + 1.701 + if (sigIndex >= signatureCount) { 1.702 + fprintf(stderr, "ERROR: Signature index was out of range\n"); 1.703 + goto failure; 1.704 + } 1.705 + 1.706 + /* Read and write the whole signature block, but if we reach the 1.707 + signature offset, then we should replace it with the specified 1.708 + base64 decoded signature */ 1.709 + for (i = 0; i < signatureCount; i++) { 1.710 + /* Read/Write the signature algorithm ID */ 1.711 + if (ReadAndWrite(fpSrc, fpDest, 1.712 + &signatureAlgorithmID, 1.713 + sizeof(signatureAlgorithmID), "sig algorithm ID")) { 1.714 + goto failure; 1.715 + } 1.716 + 1.717 + /* Read/Write the signature length */ 1.718 + if (ReadAndWrite(fpSrc, fpDest, 1.719 + &signatureLen, sizeof(signatureLen), "sig length")) { 1.720 + goto failure; 1.721 + } 1.722 + signatureLen = ntohl(signatureLen); 1.723 + 1.724 + /* Get the signature */ 1.725 + if (extractedMARSignature) { 1.726 + free(extractedMARSignature); 1.727 + } 1.728 + extractedMARSignature = malloc(signatureLen); 1.729 + 1.730 + if (sigIndex == i) { 1.731 + if (passedInSignatureLenRaw != signatureLen) { 1.732 + fprintf(stderr, "ERROR: Signature length must be the same\n"); 1.733 + goto failure; 1.734 + } 1.735 + 1.736 + if (fread(extractedMARSignature, signatureLen, 1, fpSrc) != 1) { 1.737 + fprintf(stderr, "ERROR: Could not read signature\n"); 1.738 + goto failure; 1.739 + } 1.740 + 1.741 + if (fwrite(passedInSignatureRaw, passedInSignatureLenRaw, 1.742 + 1, fpDest) != 1) { 1.743 + fprintf(stderr, "ERROR: Could not write signature\n"); 1.744 + goto failure; 1.745 + } 1.746 + } else { 1.747 + if (ReadAndWrite(fpSrc, fpDest, 1.748 + extractedMARSignature, signatureLen, "signature")) { 1.749 + goto failure; 1.750 + } 1.751 + } 1.752 + } 1.753 + 1.754 + /* We replaced the signature so let's just skip past the rest o the 1.755 + file. */ 1.756 + numChunks = (sizeOfSrcMAR - ftello(fpSrc)) / BLOCKSIZE; 1.757 + leftOver = (sizeOfSrcMAR - ftello(fpSrc)) % BLOCKSIZE; 1.758 + 1.759 + /* Read each file and write it to the MAR file */ 1.760 + for (i = 0; i < numChunks; ++i) { 1.761 + if (ReadAndWrite(fpSrc, fpDest, buf, BLOCKSIZE, "content block")) { 1.762 + goto failure; 1.763 + } 1.764 + } 1.765 + 1.766 + if (ReadAndWrite(fpSrc, fpDest, buf, leftOver, "left over content block")) { 1.767 + goto failure; 1.768 + } 1.769 + 1.770 + rv = 0; 1.771 + 1.772 +failure: 1.773 + 1.774 + if (fpSrc) { 1.775 + fclose(fpSrc); 1.776 + } 1.777 + 1.778 + if (fpDest) { 1.779 + fclose(fpDest); 1.780 + } 1.781 + 1.782 + if (fpSigFile) { 1.783 + fclose(fpSigFile); 1.784 + } 1.785 + 1.786 + if (rv) { 1.787 + remove(dest); 1.788 + } 1.789 + 1.790 + if (extractedMARSignature) { 1.791 + free(extractedMARSignature); 1.792 + } 1.793 + 1.794 + if (passedInSignatureB64) { 1.795 + free(passedInSignatureB64); 1.796 + } 1.797 + 1.798 + if (passedInSignatureRaw) { 1.799 + PORT_Free(passedInSignatureRaw); 1.800 + } 1.801 + 1.802 + return rv; 1.803 +} 1.804 + 1.805 +/** 1.806 + * Writes out a copy of the MAR at src but with embedded signatures. 1.807 + * The passed in MAR file must not already be signed or an error will 1.808 + * be returned. 1.809 + * 1.810 + * @param NSSConfigDir The NSS directory containing the private key for signing 1.811 + * @param certNames The nicknames of the certificate to use for signing 1.812 + * @param certCount The number of certificate names contained in certNames. 1.813 + * One signature will be produced for each certificate. 1.814 + * @param src The path of the source MAR file to sign 1.815 + * @param dest The path of the MAR file to write out that is signed 1.816 + * @return 0 on success 1.817 + * -1 on error 1.818 +*/ 1.819 +int 1.820 +mar_repackage_and_sign(const char *NSSConfigDir, 1.821 + const char * const *certNames, 1.822 + uint32_t certCount, 1.823 + const char *src, 1.824 + const char *dest) 1.825 +{ 1.826 + uint32_t offsetToIndex, dstOffsetToIndex, indexLength, 1.827 + numSignatures = 0, leftOver, 1.828 + signatureAlgorithmID, signatureSectionLength = 0; 1.829 + uint32_t signatureLengths[MAX_SIGNATURES]; 1.830 + int64_t oldPos, sizeOfEntireMAR = 0, realSizeOfSrcMAR, 1.831 + signaturePlaceholderOffset, numBytesToCopy, 1.832 + numChunks, i; 1.833 + FILE *fpSrc = NULL, *fpDest = NULL; 1.834 + int rv = -1, hasSignatureBlock; 1.835 + SGNContext *ctxs[MAX_SIGNATURES]; 1.836 + SECItem secItems[MAX_SIGNATURES]; 1.837 + char buf[BLOCKSIZE]; 1.838 + SECKEYPrivateKey *privKeys[MAX_SIGNATURES]; 1.839 + CERTCertificate *certs[MAX_SIGNATURES]; 1.840 + char *indexBuf = NULL, *indexBufLoc; 1.841 + uint32_t k; 1.842 + 1.843 + memset(signatureLengths, 0, sizeof(signatureLengths)); 1.844 + memset(ctxs, 0, sizeof(ctxs)); 1.845 + memset(secItems, 0, sizeof(secItems)); 1.846 + memset(privKeys, 0, sizeof(privKeys)); 1.847 + memset(certs, 0, sizeof(certs)); 1.848 + 1.849 + if (!NSSConfigDir || !certNames || certCount == 0 || !src || !dest) { 1.850 + fprintf(stderr, "ERROR: Invalid parameter passed in.\n"); 1.851 + return -1; 1.852 + } 1.853 + 1.854 + if (NSSInitCryptoContext(NSSConfigDir)) { 1.855 + fprintf(stderr, "ERROR: Could not init config dir: %s\n", NSSConfigDir); 1.856 + goto failure; 1.857 + } 1.858 + 1.859 + PK11_SetPasswordFunc(SECU_GetModulePassword); 1.860 + 1.861 + fpSrc = fopen(src, "rb"); 1.862 + if (!fpSrc) { 1.863 + fprintf(stderr, "ERROR: could not open source file: %s\n", src); 1.864 + goto failure; 1.865 + } 1.866 + 1.867 + fpDest = fopen(dest, "wb"); 1.868 + if (!fpDest) { 1.869 + fprintf(stderr, "ERROR: could not create target file: %s\n", dest); 1.870 + goto failure; 1.871 + } 1.872 + 1.873 + /* Determine if the source MAR file has the new fields for signing or not */ 1.874 + if (get_mar_file_info(src, &hasSignatureBlock, NULL, NULL, NULL, NULL)) { 1.875 + fprintf(stderr, "ERROR: could not determine if MAR is old or new.\n"); 1.876 + goto failure; 1.877 + } 1.878 + 1.879 + for (k = 0; k < certCount; k++) { 1.880 + if (NSSSignBegin(certNames[k], &ctxs[k], &privKeys[k], 1.881 + &certs[k], &signatureLengths[k])) { 1.882 + fprintf(stderr, "ERROR: NSSSignBegin failed\n"); 1.883 + goto failure; 1.884 + } 1.885 + } 1.886 + 1.887 + /* MAR ID */ 1.888 + if (ReadWriteAndUpdateSignatures(fpSrc, fpDest, 1.889 + buf, MAR_ID_SIZE, 1.890 + ctxs, certCount, "MAR ID")) { 1.891 + goto failure; 1.892 + } 1.893 + 1.894 + /* Offset to index */ 1.895 + if (fread(&offsetToIndex, sizeof(offsetToIndex), 1, fpSrc) != 1) { 1.896 + fprintf(stderr, "ERROR: Could not read offset\n"); 1.897 + goto failure; 1.898 + } 1.899 + offsetToIndex = ntohl(offsetToIndex); 1.900 + 1.901 + /* Get the real size of the MAR */ 1.902 + oldPos = ftello(fpSrc); 1.903 + if (fseeko(fpSrc, 0, SEEK_END)) { 1.904 + fprintf(stderr, "ERROR: Could not seek to end of file.\n"); 1.905 + goto failure; 1.906 + } 1.907 + realSizeOfSrcMAR = ftello(fpSrc); 1.908 + if (fseeko(fpSrc, oldPos, SEEK_SET)) { 1.909 + fprintf(stderr, "ERROR: Could not seek back to current location.\n"); 1.910 + goto failure; 1.911 + } 1.912 + 1.913 + if (hasSignatureBlock) { 1.914 + /* Get the MAR length and adjust its size */ 1.915 + if (fread(&sizeOfEntireMAR, 1.916 + sizeof(sizeOfEntireMAR), 1, fpSrc) != 1) { 1.917 + fprintf(stderr, "ERROR: Could read mar size\n"); 1.918 + goto failure; 1.919 + } 1.920 + sizeOfEntireMAR = NETWORK_TO_HOST64(sizeOfEntireMAR); 1.921 + if (sizeOfEntireMAR != realSizeOfSrcMAR) { 1.922 + fprintf(stderr, "ERROR: Source MAR is not of the right size\n"); 1.923 + goto failure; 1.924 + } 1.925 + 1.926 + /* Get the num signatures in the source file */ 1.927 + if (fread(&numSignatures, sizeof(numSignatures), 1, fpSrc) != 1) { 1.928 + fprintf(stderr, "ERROR: Could read num signatures\n"); 1.929 + goto failure; 1.930 + } 1.931 + numSignatures = ntohl(numSignatures); 1.932 + 1.933 + /* We do not support resigning, if you have multiple signatures, 1.934 + you must add them all at the same time. */ 1.935 + if (numSignatures) { 1.936 + fprintf(stderr, "ERROR: MAR is already signed\n"); 1.937 + goto failure; 1.938 + } 1.939 + } else { 1.940 + sizeOfEntireMAR = realSizeOfSrcMAR; 1.941 + } 1.942 + 1.943 + if (((int64_t)offsetToIndex) > sizeOfEntireMAR) { 1.944 + fprintf(stderr, "ERROR: Offset to index is larger than the file size.\n"); 1.945 + goto failure; 1.946 + } 1.947 + 1.948 + /* Calculate the total signature block length */ 1.949 + for (k = 0; k < certCount; k++) { 1.950 + signatureSectionLength += sizeof(signatureAlgorithmID) + 1.951 + sizeof(signatureLengths[k]) + 1.952 + signatureLengths[k]; 1.953 + } 1.954 + dstOffsetToIndex = offsetToIndex; 1.955 + if (!hasSignatureBlock) { 1.956 + dstOffsetToIndex += sizeof(sizeOfEntireMAR) + sizeof(numSignatures); 1.957 + } 1.958 + dstOffsetToIndex += signatureSectionLength; 1.959 + 1.960 + /* Write out the index offset */ 1.961 + dstOffsetToIndex = htonl(dstOffsetToIndex); 1.962 + if (WriteAndUpdateSignatures(fpDest, &dstOffsetToIndex, 1.963 + sizeof(dstOffsetToIndex), ctxs, certCount, 1.964 + "index offset")) { 1.965 + goto failure; 1.966 + } 1.967 + dstOffsetToIndex = ntohl(dstOffsetToIndex); 1.968 + 1.969 + /* Write out the new MAR file size */ 1.970 + sizeOfEntireMAR += signatureSectionLength; 1.971 + if (!hasSignatureBlock) { 1.972 + sizeOfEntireMAR += sizeof(sizeOfEntireMAR) + sizeof(numSignatures); 1.973 + } 1.974 + 1.975 + /* Write out the MAR size */ 1.976 + sizeOfEntireMAR = HOST_TO_NETWORK64(sizeOfEntireMAR); 1.977 + if (WriteAndUpdateSignatures(fpDest, &sizeOfEntireMAR, 1.978 + sizeof(sizeOfEntireMAR), ctxs, certCount, 1.979 + "size of MAR")) { 1.980 + goto failure; 1.981 + } 1.982 + sizeOfEntireMAR = NETWORK_TO_HOST64(sizeOfEntireMAR); 1.983 + 1.984 + /* Write out the number of signatures */ 1.985 + numSignatures = certCount; 1.986 + numSignatures = htonl(numSignatures); 1.987 + if (WriteAndUpdateSignatures(fpDest, &numSignatures, 1.988 + sizeof(numSignatures), ctxs, certCount, 1.989 + "num signatures")) { 1.990 + goto failure; 1.991 + } 1.992 + numSignatures = ntohl(numSignatures); 1.993 + 1.994 + signaturePlaceholderOffset = ftello(fpDest); 1.995 + 1.996 + for (k = 0; k < certCount; k++) { 1.997 + /* Write out the signature algorithm ID, Only an ID of 1 is supported */ 1.998 + signatureAlgorithmID = htonl(1); 1.999 + if (WriteAndUpdateSignatures(fpDest, &signatureAlgorithmID, 1.1000 + sizeof(signatureAlgorithmID), 1.1001 + ctxs, certCount, "num signatures")) { 1.1002 + goto failure; 1.1003 + } 1.1004 + signatureAlgorithmID = ntohl(signatureAlgorithmID); 1.1005 + 1.1006 + /* Write out the signature length */ 1.1007 + signatureLengths[k] = htonl(signatureLengths[k]); 1.1008 + if (WriteAndUpdateSignatures(fpDest, &signatureLengths[k], 1.1009 + sizeof(signatureLengths[k]), 1.1010 + ctxs, certCount, "signature length")) { 1.1011 + goto failure; 1.1012 + } 1.1013 + signatureLengths[k] = ntohl(signatureLengths[k]); 1.1014 + 1.1015 + /* Write out a placeholder for the signature, we'll come back to this later 1.1016 + *** THIS IS NOT SIGNED because it is a placeholder that will be replaced 1.1017 + below, plus it is going to be the signature itself. *** */ 1.1018 + memset(buf, 0, sizeof(buf)); 1.1019 + if (fwrite(buf, signatureLengths[k], 1, fpDest) != 1) { 1.1020 + fprintf(stderr, "ERROR: Could not write signature length\n"); 1.1021 + goto failure; 1.1022 + } 1.1023 + } 1.1024 + 1.1025 + /* Write out the rest of the MAR excluding the index header and index 1.1026 + offsetToIndex unfortunately has to remain 32-bit because for backwards 1.1027 + compatibility with the old MAR file format. */ 1.1028 + if (ftello(fpSrc) > ((int64_t)offsetToIndex)) { 1.1029 + fprintf(stderr, "ERROR: Index offset is too small.\n"); 1.1030 + goto failure; 1.1031 + } 1.1032 + numBytesToCopy = ((int64_t)offsetToIndex) - ftello(fpSrc); 1.1033 + numChunks = numBytesToCopy / BLOCKSIZE; 1.1034 + leftOver = numBytesToCopy % BLOCKSIZE; 1.1035 + 1.1036 + /* Read each file and write it to the MAR file */ 1.1037 + for (i = 0; i < numChunks; ++i) { 1.1038 + if (ReadWriteAndUpdateSignatures(fpSrc, fpDest, buf, 1.1039 + BLOCKSIZE, ctxs, certCount, 1.1040 + "content block")) { 1.1041 + goto failure; 1.1042 + } 1.1043 + } 1.1044 + 1.1045 + /* Write out the left over */ 1.1046 + if (ReadWriteAndUpdateSignatures(fpSrc, fpDest, buf, 1.1047 + leftOver, ctxs, certCount, 1.1048 + "left over content block")) { 1.1049 + goto failure; 1.1050 + } 1.1051 + 1.1052 + /* Length of the index */ 1.1053 + if (ReadWriteAndUpdateSignatures(fpSrc, fpDest, &indexLength, 1.1054 + sizeof(indexLength), ctxs, certCount, 1.1055 + "index length")) { 1.1056 + goto failure; 1.1057 + } 1.1058 + indexLength = ntohl(indexLength); 1.1059 + 1.1060 + /* Consume the index and adjust each index by signatureSectionLength */ 1.1061 + indexBuf = malloc(indexLength); 1.1062 + indexBufLoc = indexBuf; 1.1063 + if (fread(indexBuf, indexLength, 1, fpSrc) != 1) { 1.1064 + fprintf(stderr, "ERROR: Could not read index\n"); 1.1065 + goto failure; 1.1066 + } 1.1067 + 1.1068 + /* Adjust each entry in the index */ 1.1069 + if (hasSignatureBlock) { 1.1070 + AdjustIndexContentOffsets(indexBuf, indexLength, signatureSectionLength); 1.1071 + } else { 1.1072 + AdjustIndexContentOffsets(indexBuf, indexLength, 1.1073 + sizeof(sizeOfEntireMAR) + 1.1074 + sizeof(numSignatures) + 1.1075 + signatureSectionLength); 1.1076 + } 1.1077 + 1.1078 + if (WriteAndUpdateSignatures(fpDest, indexBuf, 1.1079 + indexLength, ctxs, certCount, "index")) { 1.1080 + goto failure; 1.1081 + } 1.1082 + 1.1083 + /* Ensure that we don't sign a file that is too large to be accepted by 1.1084 + the verification function. */ 1.1085 + if (ftello(fpDest) > MAX_SIZE_OF_MAR_FILE) { 1.1086 + goto failure; 1.1087 + } 1.1088 + 1.1089 + for (k = 0; k < certCount; k++) { 1.1090 + /* Get the signature */ 1.1091 + if (SGN_End(ctxs[k], &secItems[k]) != SECSuccess) { 1.1092 + fprintf(stderr, "ERROR: Could not end signature context\n"); 1.1093 + goto failure; 1.1094 + } 1.1095 + if (signatureLengths[k] != secItems[k].len) { 1.1096 + fprintf(stderr, "ERROR: Signature is not the expected length\n"); 1.1097 + goto failure; 1.1098 + } 1.1099 + } 1.1100 + 1.1101 + /* Get back to the location of the signature placeholder */ 1.1102 + if (fseeko(fpDest, signaturePlaceholderOffset, SEEK_SET)) { 1.1103 + fprintf(stderr, "ERROR: Could not seek to signature offset\n"); 1.1104 + goto failure; 1.1105 + } 1.1106 + 1.1107 + for (k = 0; k < certCount; k++) { 1.1108 + /* Skip to the position of the next signature */ 1.1109 + if (fseeko(fpDest, sizeof(signatureAlgorithmID) + 1.1110 + sizeof(signatureLengths[k]), SEEK_CUR)) { 1.1111 + fprintf(stderr, "ERROR: Could not seek to signature offset\n"); 1.1112 + goto failure; 1.1113 + } 1.1114 + 1.1115 + /* Write out the calculated signature. 1.1116 + *** THIS IS NOT SIGNED because it is the signature itself. *** */ 1.1117 + if (fwrite(secItems[k].data, secItems[k].len, 1, fpDest) != 1) { 1.1118 + fprintf(stderr, "ERROR: Could not write signature\n"); 1.1119 + goto failure; 1.1120 + } 1.1121 + } 1.1122 + 1.1123 + rv = 0; 1.1124 +failure: 1.1125 + if (fpSrc) { 1.1126 + fclose(fpSrc); 1.1127 + } 1.1128 + 1.1129 + if (fpDest) { 1.1130 + fclose(fpDest); 1.1131 + } 1.1132 + 1.1133 + if (rv) { 1.1134 + remove(dest); 1.1135 + } 1.1136 + 1.1137 + if (indexBuf) { 1.1138 + free(indexBuf); 1.1139 + } 1.1140 + 1.1141 + /* Cleanup */ 1.1142 + for (k = 0; k < certCount; k++) { 1.1143 + if (ctxs[k]) { 1.1144 + SGN_DestroyContext(ctxs[k], PR_TRUE); 1.1145 + } 1.1146 + 1.1147 + if (certs[k]) { 1.1148 + CERT_DestroyCertificate(certs[k]); 1.1149 + } 1.1150 + 1.1151 + if (privKeys[k]) { 1.1152 + SECKEY_DestroyPrivateKey(privKeys[k]); 1.1153 + } 1.1154 + 1.1155 + SECITEM_FreeItem(&secItems[k], PR_FALSE); 1.1156 + } 1.1157 + 1.1158 + if (rv) { 1.1159 + remove(dest); 1.1160 + } 1.1161 + 1.1162 + return rv; 1.1163 +}