mirror of
https://github.com/mozilla/gecko-dev.git
synced 2025-02-03 12:35:58 +00:00
Bug 1514532 - the modules/libmar directory isn't clang formatted and there are a few deprecation warnings in app update code. r=mhowell
Added defines to mar_extract.c, mar_read.c, bsdiff.c so they use the ISO C and C++ conformant name. Ran clang format on bspatch.cpp and the files under modules/libmar except for nss_secutil.c and nss_secutil.h since they are copies of nss code.
This commit is contained in:
parent
082c2acc6e
commit
6468b181f7
@ -30,12 +30,10 @@
|
||||
* @param NSSConfigDir The config dir containing the private key to use
|
||||
* @return 0 on success
|
||||
* -1 on error
|
||||
*/
|
||||
int
|
||||
NSSInitCryptoContext(const char *NSSConfigDir)
|
||||
{
|
||||
SECStatus status = NSS_Initialize(NSSConfigDir,
|
||||
"", "", SECMOD_DB, NSS_INIT_READONLY);
|
||||
*/
|
||||
int NSSInitCryptoContext(const char *NSSConfigDir) {
|
||||
SECStatus status =
|
||||
NSS_Initialize(NSSConfigDir, "", "", SECMOD_DB, NSS_INIT_READONLY);
|
||||
if (SECSuccess != status) {
|
||||
fprintf(stderr, "ERROR: Could not initialize NSS\n");
|
||||
return -1;
|
||||
@ -50,15 +48,11 @@ NSSInitCryptoContext(const char *NSSConfigDir)
|
||||
* @param ctx A pointer to the signing context to fill
|
||||
* @return 0 on success
|
||||
* -1 on error
|
||||
*/
|
||||
int
|
||||
NSSSignBegin(const char *certName,
|
||||
SGNContext **ctx,
|
||||
SECKEYPrivateKey **privKey,
|
||||
CERTCertificate **cert,
|
||||
uint32_t *signatureLength)
|
||||
{
|
||||
secuPWData pwdata = { PW_NONE, 0 };
|
||||
*/
|
||||
int NSSSignBegin(const char *certName, SGNContext **ctx,
|
||||
SECKEYPrivateKey **privKey, CERTCertificate **cert,
|
||||
uint32_t *signatureLength) {
|
||||
secuPWData pwdata = {PW_NONE, 0};
|
||||
if (!certName || !ctx || !privKey || !cert || !signatureLength) {
|
||||
fprintf(stderr, "ERROR: Invalid parameter passed to NSSSignBegin\n");
|
||||
return -1;
|
||||
@ -122,13 +116,10 @@ NSSSignBegin(const char *certName,
|
||||
* @return 0 on success
|
||||
* -2 on write error
|
||||
* -3 on signature update error
|
||||
*/
|
||||
int
|
||||
WriteAndUpdateSignatures(FILE *fpDest, void *buffer,
|
||||
uint32_t size, SGNContext **ctxs,
|
||||
uint32_t ctxCount,
|
||||
const char *err)
|
||||
{
|
||||
*/
|
||||
int WriteAndUpdateSignatures(FILE *fpDest, void *buffer, uint32_t size,
|
||||
SGNContext **ctxs, uint32_t ctxCount,
|
||||
const char *err) {
|
||||
uint32_t k;
|
||||
if (!size) {
|
||||
return 0;
|
||||
@ -141,7 +132,8 @@ WriteAndUpdateSignatures(FILE *fpDest, void *buffer,
|
||||
|
||||
for (k = 0; k < ctxCount; ++k) {
|
||||
if (SGN_Update(ctxs[k], buffer, size) != SECSuccess) {
|
||||
fprintf(stderr, "ERROR: Could not update signature context for %s\n", err);
|
||||
fprintf(stderr, "ERROR: Could not update signature context for %s\n",
|
||||
err);
|
||||
return -3;
|
||||
}
|
||||
}
|
||||
@ -155,10 +147,9 @@ WriteAndUpdateSignatures(FILE *fpDest, void *buffer,
|
||||
* @param indexBuf A buffer containing the MAR index
|
||||
* @param indexLength The length of the MAR index
|
||||
* @param offsetAmount The amount to adjust each index entry by
|
||||
*/
|
||||
void
|
||||
AdjustIndexContentOffsets(char *indexBuf, uint32_t indexLength, uint32_t offsetAmount)
|
||||
{
|
||||
*/
|
||||
void AdjustIndexContentOffsets(char *indexBuf, uint32_t indexLength,
|
||||
uint32_t offsetAmount) {
|
||||
uint32_t *offsetToContent;
|
||||
char *indexBufLoc = indexBuf;
|
||||
|
||||
@ -190,13 +181,10 @@ AdjustIndexContentOffsets(char *indexBuf, uint32_t indexLength, uint32_t offsetA
|
||||
* -1 on read error
|
||||
* -2 on write error
|
||||
* -3 on signature update error
|
||||
*/
|
||||
int
|
||||
ReadWriteAndUpdateSignatures(FILE *fpSrc, FILE *fpDest, void *buffer,
|
||||
uint32_t size, SGNContext **ctxs,
|
||||
uint32_t ctxCount,
|
||||
const char *err)
|
||||
{
|
||||
*/
|
||||
int ReadWriteAndUpdateSignatures(FILE *fpSrc, FILE *fpDest, void *buffer,
|
||||
uint32_t size, SGNContext **ctxs,
|
||||
uint32_t ctxCount, const char *err) {
|
||||
if (!size) {
|
||||
return 0;
|
||||
}
|
||||
@ -209,7 +197,6 @@ ReadWriteAndUpdateSignatures(FILE *fpSrc, FILE *fpDest, void *buffer,
|
||||
return WriteAndUpdateSignatures(fpDest, buffer, size, ctxs, ctxCount, err);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Reads from fpSrc, writes it to fpDest.
|
||||
*
|
||||
@ -221,11 +208,9 @@ ReadWriteAndUpdateSignatures(FILE *fpSrc, FILE *fpDest, void *buffer,
|
||||
* @return 0 on success
|
||||
* -1 on read error
|
||||
* -2 on write error
|
||||
*/
|
||||
int
|
||||
ReadAndWrite(FILE *fpSrc, FILE *fpDest, void *buffer,
|
||||
uint32_t size, const char *err)
|
||||
{
|
||||
*/
|
||||
int ReadAndWrite(FILE *fpSrc, FILE *fpDest, void *buffer, uint32_t size,
|
||||
const char *err) {
|
||||
if (!size) {
|
||||
return 0;
|
||||
}
|
||||
@ -252,14 +237,12 @@ ReadAndWrite(FILE *fpSrc, FILE *fpDest, void *buffer,
|
||||
* @return 0 on success
|
||||
* -1 on error
|
||||
*/
|
||||
int
|
||||
strip_signature_block(const char *src, const char * dest)
|
||||
{
|
||||
uint32_t offsetToIndex, dstOffsetToIndex, indexLength,
|
||||
numSignatures = 0, leftOver;
|
||||
int strip_signature_block(const char *src, const char *dest) {
|
||||
uint32_t offsetToIndex, dstOffsetToIndex, indexLength, numSignatures = 0,
|
||||
leftOver;
|
||||
int32_t stripAmount = 0;
|
||||
int64_t oldPos, sizeOfEntireMAR = 0, realSizeOfSrcMAR, numBytesToCopy,
|
||||
numChunks, i;
|
||||
int64_t oldPos, numChunks, i, realSizeOfSrcMAR, numBytesToCopy,
|
||||
sizeOfEntireMAR = 0;
|
||||
FILE *fpSrc = NULL, *fpDest = NULL;
|
||||
int rv = -1, hasSignatureBlock;
|
||||
char buf[BLOCKSIZE];
|
||||
@ -314,8 +297,7 @@ strip_signature_block(const char *src, const char * dest)
|
||||
|
||||
if (hasSignatureBlock) {
|
||||
/* Get the MAR length and adjust its size */
|
||||
if (fread(&sizeOfEntireMAR,
|
||||
sizeof(sizeOfEntireMAR), 1, fpSrc) != 1) {
|
||||
if (fread(&sizeOfEntireMAR, sizeof(sizeOfEntireMAR), 1, fpSrc) != 1) {
|
||||
fprintf(stderr, "ERROR: Could read mar size\n");
|
||||
goto failure;
|
||||
}
|
||||
@ -419,14 +401,13 @@ strip_signature_block(const char *src, const char * dest)
|
||||
}
|
||||
|
||||
/* Write out the left over */
|
||||
if (ReadAndWrite(fpSrc, fpDest, buf,
|
||||
leftOver, "left over content block")) {
|
||||
if (ReadAndWrite(fpSrc, fpDest, buf, leftOver, "left over content block")) {
|
||||
goto failure;
|
||||
}
|
||||
|
||||
/* Length of the index */
|
||||
if (ReadAndWrite(fpSrc, fpDest, &indexLength,
|
||||
sizeof(indexLength), "index length")) {
|
||||
if (ReadAndWrite(fpSrc, fpDest, &indexLength, sizeof(indexLength),
|
||||
"index length")) {
|
||||
goto failure;
|
||||
}
|
||||
indexLength = ntohl(indexLength);
|
||||
@ -442,10 +423,9 @@ strip_signature_block(const char *src, const char * dest)
|
||||
if (hasSignatureBlock) {
|
||||
AdjustIndexContentOffsets(indexBuf, indexLength, -stripAmount);
|
||||
} else {
|
||||
AdjustIndexContentOffsets(indexBuf, indexLength,
|
||||
sizeof(sizeOfEntireMAR) +
|
||||
sizeof(numSignatures) -
|
||||
stripAmount);
|
||||
AdjustIndexContentOffsets(
|
||||
indexBuf, indexLength,
|
||||
sizeof(sizeOfEntireMAR) + sizeof(numSignatures) - stripAmount);
|
||||
}
|
||||
|
||||
if (fwrite(indexBuf, indexLength, 1, fpDest) != 1) {
|
||||
@ -485,10 +465,8 @@ failure:
|
||||
* @param dest The path of file to write the signature to
|
||||
* @return 0 on success
|
||||
* -1 on error
|
||||
*/
|
||||
int
|
||||
extract_signature(const char *src, uint32_t sigIndex, const char * dest)
|
||||
{
|
||||
*/
|
||||
int extract_signature(const char *src, uint32_t sigIndex, const char *dest) {
|
||||
FILE *fpSrc = NULL, *fpDest = NULL;
|
||||
uint32_t i;
|
||||
uint32_t signatureCount;
|
||||
@ -599,21 +577,20 @@ failure:
|
||||
* @param src The path of the source MAR file
|
||||
* @param sigIndex The index of the signature to import
|
||||
* @param base64SigFile A file which contains the signature to import
|
||||
* @param dest The path of the destination MAR file with replaced signature
|
||||
* @param dest The path of the destination MAR file with replaced
|
||||
* signature
|
||||
* @return 0 on success
|
||||
* -1 on error
|
||||
*/
|
||||
int
|
||||
import_signature(const char *src, uint32_t sigIndex,
|
||||
const char *base64SigFile, const char *dest)
|
||||
{
|
||||
*/
|
||||
int import_signature(const char *src, uint32_t sigIndex,
|
||||
const char *base64SigFile, const char *dest) {
|
||||
int rv = -1;
|
||||
FILE *fpSrc = NULL;
|
||||
FILE *fpDest = NULL;
|
||||
FILE *fpSigFile = NULL;
|
||||
uint32_t i;
|
||||
uint32_t signatureCount, signatureLen, signatureAlgorithmID,
|
||||
numChunks, leftOver;
|
||||
uint32_t signatureCount, signatureLen, signatureAlgorithmID, numChunks,
|
||||
leftOver;
|
||||
char buf[BLOCKSIZE];
|
||||
uint64_t sizeOfSrcMAR, sizeOfBase64EncodedFile;
|
||||
char *passedInSignatureB64 = NULL;
|
||||
@ -638,7 +615,7 @@ import_signature(const char *src, uint32_t sigIndex,
|
||||
goto failure;
|
||||
}
|
||||
|
||||
fpSigFile = fopen(base64SigFile , "rb");
|
||||
fpSigFile = fopen(base64SigFile, "rb");
|
||||
if (!fpSigFile) {
|
||||
fprintf(stderr, "ERROR: could not open sig file: %s\n", base64SigFile);
|
||||
goto failure;
|
||||
@ -660,7 +637,7 @@ import_signature(const char *src, uint32_t sigIndex,
|
||||
fprintf(stderr, "ERROR: Could not seek to end of sig file.\n");
|
||||
goto failure;
|
||||
}
|
||||
sizeOfBase64EncodedFile= ftello(fpSigFile);
|
||||
sizeOfBase64EncodedFile = ftello(fpSigFile);
|
||||
if (fseeko(fpSigFile, 0, SEEK_SET)) {
|
||||
fprintf(stderr, "ERROR: Could not seek to start of sig file.\n");
|
||||
goto failure;
|
||||
@ -675,21 +652,22 @@ import_signature(const char *src, uint32_t sigIndex,
|
||||
}
|
||||
|
||||
/* Decode the base64 encoded data */
|
||||
passedInSignatureRaw = ATOB_AsciiToData(passedInSignatureB64, &passedInSignatureLenRaw);
|
||||
passedInSignatureRaw =
|
||||
ATOB_AsciiToData(passedInSignatureB64, &passedInSignatureLenRaw);
|
||||
if (!passedInSignatureRaw) {
|
||||
fprintf(stderr, "ERROR: could not obtain base64 decoded data\n");
|
||||
goto failure;
|
||||
}
|
||||
|
||||
/* Read everything up until the signature block offset and write it out */
|
||||
if (ReadAndWrite(fpSrc, fpDest, buf,
|
||||
SIGNATURE_BLOCK_OFFSET, "signature block offset")) {
|
||||
if (ReadAndWrite(fpSrc, fpDest, buf, SIGNATURE_BLOCK_OFFSET,
|
||||
"signature block offset")) {
|
||||
goto failure;
|
||||
}
|
||||
|
||||
/* Get the number of signatures */
|
||||
if (ReadAndWrite(fpSrc, fpDest, &signatureCount,
|
||||
sizeof(signatureCount), "signature count")) {
|
||||
if (ReadAndWrite(fpSrc, fpDest, &signatureCount, sizeof(signatureCount),
|
||||
"signature count")) {
|
||||
goto failure;
|
||||
}
|
||||
signatureCount = ntohl(signatureCount);
|
||||
@ -708,15 +686,14 @@ import_signature(const char *src, uint32_t sigIndex,
|
||||
base64 decoded signature */
|
||||
for (i = 0; i < signatureCount; i++) {
|
||||
/* Read/Write the signature algorithm ID */
|
||||
if (ReadAndWrite(fpSrc, fpDest,
|
||||
&signatureAlgorithmID,
|
||||
if (ReadAndWrite(fpSrc, fpDest, &signatureAlgorithmID,
|
||||
sizeof(signatureAlgorithmID), "sig algorithm ID")) {
|
||||
goto failure;
|
||||
}
|
||||
|
||||
/* Read/Write the signature length */
|
||||
if (ReadAndWrite(fpSrc, fpDest,
|
||||
&signatureLen, sizeof(signatureLen), "sig length")) {
|
||||
if (ReadAndWrite(fpSrc, fpDest, &signatureLen, sizeof(signatureLen),
|
||||
"sig length")) {
|
||||
goto failure;
|
||||
}
|
||||
signatureLen = ntohl(signatureLen);
|
||||
@ -738,14 +715,14 @@ import_signature(const char *src, uint32_t sigIndex,
|
||||
goto failure;
|
||||
}
|
||||
|
||||
if (fwrite(passedInSignatureRaw, passedInSignatureLenRaw,
|
||||
1, fpDest) != 1) {
|
||||
if (fwrite(passedInSignatureRaw, passedInSignatureLenRaw, 1, fpDest) !=
|
||||
1) {
|
||||
fprintf(stderr, "ERROR: Could not write signature\n");
|
||||
goto failure;
|
||||
}
|
||||
} else {
|
||||
if (ReadAndWrite(fpSrc, fpDest,
|
||||
extractedMARSignature, signatureLen, "signature")) {
|
||||
if (ReadAndWrite(fpSrc, fpDest, extractedMARSignature, signatureLen,
|
||||
"signature")) {
|
||||
goto failure;
|
||||
}
|
||||
}
|
||||
@ -807,7 +784,8 @@ failure:
|
||||
* The passed in MAR file must not already be signed or an error will
|
||||
* be returned.
|
||||
*
|
||||
* @param NSSConfigDir The NSS directory containing the private key for signing
|
||||
* @param NSSConfigDir The NSS directory containing the private key for
|
||||
* signing
|
||||
* @param certNames The nicknames of the certificate to use for signing
|
||||
* @param certCount The number of certificate names contained in certNames.
|
||||
* One signature will be produced for each certificate.
|
||||
@ -815,21 +793,15 @@ failure:
|
||||
* @param dest The path of the MAR file to write out that is signed
|
||||
* @return 0 on success
|
||||
* -1 on error
|
||||
*/
|
||||
int
|
||||
mar_repackage_and_sign(const char *NSSConfigDir,
|
||||
const char * const *certNames,
|
||||
uint32_t certCount,
|
||||
const char *src,
|
||||
const char *dest)
|
||||
{
|
||||
uint32_t offsetToIndex, dstOffsetToIndex, indexLength,
|
||||
numSignatures = 0, leftOver,
|
||||
signatureAlgorithmID, signatureSectionLength = 0;
|
||||
*/
|
||||
int mar_repackage_and_sign(const char *NSSConfigDir,
|
||||
const char *const *certNames, uint32_t certCount,
|
||||
const char *src, const char *dest) {
|
||||
uint32_t offsetToIndex, dstOffsetToIndex, indexLength, leftOver,
|
||||
signatureAlgorithmID, numSignatures = 0, signatureSectionLength = 0;
|
||||
uint32_t signatureLengths[MAX_SIGNATURES];
|
||||
int64_t oldPos, sizeOfEntireMAR = 0, realSizeOfSrcMAR,
|
||||
signaturePlaceholderOffset, numBytesToCopy,
|
||||
numChunks, i;
|
||||
int64_t oldPos, numChunks, i, realSizeOfSrcMAR, signaturePlaceholderOffset,
|
||||
numBytesToCopy, sizeOfEntireMAR = 0;
|
||||
FILE *fpSrc = NULL, *fpDest = NULL;
|
||||
int rv = -1, hasSignatureBlock;
|
||||
SGNContext *ctxs[MAX_SIGNATURES];
|
||||
@ -877,17 +849,16 @@ mar_repackage_and_sign(const char *NSSConfigDir,
|
||||
}
|
||||
|
||||
for (k = 0; k < certCount; k++) {
|
||||
if (NSSSignBegin(certNames[k], &ctxs[k], &privKeys[k],
|
||||
&certs[k], &signatureLengths[k])) {
|
||||
if (NSSSignBegin(certNames[k], &ctxs[k], &privKeys[k], &certs[k],
|
||||
&signatureLengths[k])) {
|
||||
fprintf(stderr, "ERROR: NSSSignBegin failed\n");
|
||||
goto failure;
|
||||
}
|
||||
}
|
||||
|
||||
/* MAR ID */
|
||||
if (ReadWriteAndUpdateSignatures(fpSrc, fpDest,
|
||||
buf, MAR_ID_SIZE,
|
||||
ctxs, certCount, "MAR ID")) {
|
||||
if (ReadWriteAndUpdateSignatures(fpSrc, fpDest, buf, MAR_ID_SIZE, ctxs,
|
||||
certCount, "MAR ID")) {
|
||||
goto failure;
|
||||
}
|
||||
|
||||
@ -912,8 +883,7 @@ mar_repackage_and_sign(const char *NSSConfigDir,
|
||||
|
||||
if (hasSignatureBlock) {
|
||||
/* Get the MAR length and adjust its size */
|
||||
if (fread(&sizeOfEntireMAR,
|
||||
sizeof(sizeOfEntireMAR), 1, fpSrc) != 1) {
|
||||
if (fread(&sizeOfEntireMAR, sizeof(sizeOfEntireMAR), 1, fpSrc) != 1) {
|
||||
fprintf(stderr, "ERROR: Could read mar size\n");
|
||||
goto failure;
|
||||
}
|
||||
@ -948,8 +918,7 @@ mar_repackage_and_sign(const char *NSSConfigDir,
|
||||
/* Calculate the total signature block length */
|
||||
for (k = 0; k < certCount; k++) {
|
||||
signatureSectionLength += sizeof(signatureAlgorithmID) +
|
||||
sizeof(signatureLengths[k]) +
|
||||
signatureLengths[k];
|
||||
sizeof(signatureLengths[k]) + signatureLengths[k];
|
||||
}
|
||||
dstOffsetToIndex = offsetToIndex;
|
||||
if (!hasSignatureBlock) {
|
||||
@ -984,9 +953,8 @@ mar_repackage_and_sign(const char *NSSConfigDir,
|
||||
/* Write out the number of signatures */
|
||||
numSignatures = certCount;
|
||||
numSignatures = htonl(numSignatures);
|
||||
if (WriteAndUpdateSignatures(fpDest, &numSignatures,
|
||||
sizeof(numSignatures), ctxs, certCount,
|
||||
"num signatures")) {
|
||||
if (WriteAndUpdateSignatures(fpDest, &numSignatures, sizeof(numSignatures),
|
||||
ctxs, certCount, "num signatures")) {
|
||||
goto failure;
|
||||
}
|
||||
numSignatures = ntohl(numSignatures);
|
||||
@ -997,8 +965,8 @@ mar_repackage_and_sign(const char *NSSConfigDir,
|
||||
/* Write out the signature algorithm ID, Only an ID of 2 is supported */
|
||||
signatureAlgorithmID = htonl(2);
|
||||
if (WriteAndUpdateSignatures(fpDest, &signatureAlgorithmID,
|
||||
sizeof(signatureAlgorithmID),
|
||||
ctxs, certCount, "num signatures")) {
|
||||
sizeof(signatureAlgorithmID), ctxs, certCount,
|
||||
"num signatures")) {
|
||||
goto failure;
|
||||
}
|
||||
signatureAlgorithmID = ntohl(signatureAlgorithmID);
|
||||
@ -1006,8 +974,8 @@ mar_repackage_and_sign(const char *NSSConfigDir,
|
||||
/* Write out the signature length */
|
||||
signatureLengths[k] = htonl(signatureLengths[k]);
|
||||
if (WriteAndUpdateSignatures(fpDest, &signatureLengths[k],
|
||||
sizeof(signatureLengths[k]),
|
||||
ctxs, certCount, "signature length")) {
|
||||
sizeof(signatureLengths[k]), ctxs, certCount,
|
||||
"signature length")) {
|
||||
goto failure;
|
||||
}
|
||||
signatureLengths[k] = ntohl(signatureLengths[k]);
|
||||
@ -1035,17 +1003,15 @@ mar_repackage_and_sign(const char *NSSConfigDir,
|
||||
|
||||
/* Read each file and write it to the MAR file */
|
||||
for (i = 0; i < numChunks; ++i) {
|
||||
if (ReadWriteAndUpdateSignatures(fpSrc, fpDest, buf,
|
||||
BLOCKSIZE, ctxs, certCount,
|
||||
"content block")) {
|
||||
if (ReadWriteAndUpdateSignatures(fpSrc, fpDest, buf, BLOCKSIZE, ctxs,
|
||||
certCount, "content block")) {
|
||||
goto failure;
|
||||
}
|
||||
}
|
||||
|
||||
/* Write out the left over */
|
||||
if (ReadWriteAndUpdateSignatures(fpSrc, fpDest, buf,
|
||||
leftOver, ctxs, certCount,
|
||||
"left over content block")) {
|
||||
if (ReadWriteAndUpdateSignatures(fpSrc, fpDest, buf, leftOver, ctxs,
|
||||
certCount, "left over content block")) {
|
||||
goto failure;
|
||||
}
|
||||
|
||||
@ -1069,13 +1035,12 @@ mar_repackage_and_sign(const char *NSSConfigDir,
|
||||
AdjustIndexContentOffsets(indexBuf, indexLength, signatureSectionLength);
|
||||
} else {
|
||||
AdjustIndexContentOffsets(indexBuf, indexLength,
|
||||
sizeof(sizeOfEntireMAR) +
|
||||
sizeof(numSignatures) +
|
||||
signatureSectionLength);
|
||||
sizeof(sizeOfEntireMAR) + sizeof(numSignatures) +
|
||||
signatureSectionLength);
|
||||
}
|
||||
|
||||
if (WriteAndUpdateSignatures(fpDest, indexBuf,
|
||||
indexLength, ctxs, certCount, "index")) {
|
||||
if (WriteAndUpdateSignatures(fpDest, indexBuf, indexLength, ctxs, certCount,
|
||||
"index")) {
|
||||
goto failure;
|
||||
}
|
||||
|
||||
@ -1105,14 +1070,15 @@ mar_repackage_and_sign(const char *NSSConfigDir,
|
||||
|
||||
for (k = 0; k < certCount; k++) {
|
||||
/* Skip to the position of the next signature */
|
||||
if (fseeko(fpDest, sizeof(signatureAlgorithmID) +
|
||||
sizeof(signatureLengths[k]), SEEK_CUR)) {
|
||||
if (fseeko(fpDest,
|
||||
sizeof(signatureAlgorithmID) + sizeof(signatureLengths[k]),
|
||||
SEEK_CUR)) {
|
||||
fprintf(stderr, "ERROR: Could not seek to signature offset\n");
|
||||
goto failure;
|
||||
}
|
||||
|
||||
/* Write out the calculated signature.
|
||||
*** THIS IS NOT SIGNED because it is the signature itself. *** */
|
||||
*** THIS IS NOT SIGNED because it is the signature itself. *** */
|
||||
if (fwrite(secItems[k].data, secItems[k].len, 1, fpDest) != 1) {
|
||||
fprintf(stderr, "ERROR: Could not write signature\n");
|
||||
goto failure;
|
||||
|
@ -19,7 +19,7 @@ extern "C" {
|
||||
* It is also used at various places internally and will affect memory usage.
|
||||
* If you want to increase this value above 9 then you need to adjust parsing
|
||||
* code in tool/mar.c.
|
||||
*/
|
||||
*/
|
||||
#define MAX_SIGNATURES 8
|
||||
#ifdef __cplusplus
|
||||
static_assert(MAX_SIGNATURES <= 9, "too many signatures");
|
||||
@ -27,8 +27,7 @@ static_assert(MAX_SIGNATURES <= 9, "too many signatures");
|
||||
MOZ_STATIC_ASSERT(MAX_SIGNATURES <= 9, "too many signatures");
|
||||
#endif
|
||||
|
||||
struct ProductInformationBlock
|
||||
{
|
||||
struct ProductInformationBlock {
|
||||
const char* MARChannelID;
|
||||
const char* productVersion;
|
||||
};
|
||||
@ -36,20 +35,18 @@ struct ProductInformationBlock
|
||||
/**
|
||||
* The MAR item data structure.
|
||||
*/
|
||||
typedef struct MarItem_
|
||||
{
|
||||
struct MarItem_* next; /* private field */
|
||||
uint32_t offset; /* offset into archive */
|
||||
uint32_t length; /* length of data in bytes */
|
||||
uint32_t flags; /* contains file mode bits */
|
||||
char name[1]; /* file path */
|
||||
typedef struct MarItem_ {
|
||||
struct MarItem_* next; /* private field */
|
||||
uint32_t offset; /* offset into archive */
|
||||
uint32_t length; /* length of data in bytes */
|
||||
uint32_t flags; /* contains file mode bits */
|
||||
char name[1]; /* file path */
|
||||
} MarItem;
|
||||
|
||||
/**
|
||||
* File offset and length for tracking access of byte indexes
|
||||
*/
|
||||
typedef struct SeenIndex_
|
||||
{
|
||||
typedef struct SeenIndex_ {
|
||||
struct SeenIndex_* next; /* private field */
|
||||
uint32_t offset; /* offset into archive */
|
||||
uint32_t length; /* length of the data in bytes */
|
||||
@ -60,8 +57,7 @@ typedef struct SeenIndex_
|
||||
/**
|
||||
* Mozilla ARchive (MAR) file data structure
|
||||
*/
|
||||
struct MarFile_
|
||||
{
|
||||
struct MarFile_ {
|
||||
FILE* fp; /* file pointer to the archive */
|
||||
MarItem* item_table[TABLESIZE]; /* hash table of files in the archive */
|
||||
SeenIndex* index_list; /* file indexes processed */
|
||||
@ -85,19 +81,17 @@ typedef int (*MarItemCallback)(MarFile* mar, const MarItem* item, void* data);
|
||||
* be compatible with fopen.
|
||||
* @return NULL if an error occurs.
|
||||
*/
|
||||
MarFile*
|
||||
mar_open(const char* path);
|
||||
MarFile* mar_open(const char* path);
|
||||
|
||||
#ifdef XP_WIN
|
||||
MarFile *mar_wopen(const wchar_t *path);
|
||||
MarFile* mar_wopen(const wchar_t* path);
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Close a MAR file that was opened using mar_open.
|
||||
* @param mar The MarFile object to close.
|
||||
*/
|
||||
void
|
||||
mar_close(MarFile* mar);
|
||||
void mar_close(MarFile* mar);
|
||||
|
||||
/**
|
||||
* Find an item in the MAR file by name.
|
||||
@ -105,8 +99,7 @@ mar_close(MarFile* mar);
|
||||
* @param item The name of the item to query.
|
||||
* @return A const reference to a MAR item or NULL if not found.
|
||||
*/
|
||||
const MarItem*
|
||||
mar_find_item(MarFile* mar, const char* item);
|
||||
const MarItem* mar_find_item(MarFile* mar, const char* item);
|
||||
|
||||
/**
|
||||
* Enumerate all MAR items via callback function.
|
||||
@ -117,8 +110,7 @@ mar_find_item(MarFile* mar, const char* item);
|
||||
* @return 0 if the enumeration ran to completion. Otherwise, any
|
||||
* non-zero return value from the callback is returned.
|
||||
*/
|
||||
int
|
||||
mar_enum_items(MarFile* mar, MarItemCallback callback, void* data);
|
||||
int mar_enum_items(MarFile* mar, MarItemCallback callback, void* data);
|
||||
|
||||
/**
|
||||
* Read from MAR item at given offset up to bufsize bytes.
|
||||
@ -130,12 +122,8 @@ mar_enum_items(MarFile* mar, MarItemCallback callback, void* data);
|
||||
* @return The number of bytes written or a negative value if an
|
||||
* error occurs.
|
||||
*/
|
||||
int
|
||||
mar_read(MarFile* mar,
|
||||
const MarItem* item,
|
||||
int offset,
|
||||
uint8_t* buf,
|
||||
int bufsize);
|
||||
int mar_read(MarFile* mar, const MarItem* item, int offset, uint8_t* buf,
|
||||
int bufsize);
|
||||
|
||||
/**
|
||||
* Create a MAR file from a set of files.
|
||||
@ -147,11 +135,8 @@ mar_read(MarFile* mar,
|
||||
* @param infoBlock The information to store in the product information block.
|
||||
* @return A non-zero value if an error occurs.
|
||||
*/
|
||||
int
|
||||
mar_create(const char* dest,
|
||||
int numfiles,
|
||||
char** files,
|
||||
struct ProductInformationBlock* infoBlock);
|
||||
int mar_create(const char* dest, int numfiles, char** files,
|
||||
struct ProductInformationBlock* infoBlock);
|
||||
|
||||
/**
|
||||
* Extract a MAR file to the current working directory.
|
||||
@ -159,10 +144,9 @@ mar_create(const char* dest,
|
||||
* compatible with fopen.
|
||||
* @return A non-zero value if an error occurs.
|
||||
*/
|
||||
int
|
||||
mar_extract(const char* path);
|
||||
int mar_extract(const char* path);
|
||||
|
||||
#define MAR_MAX_CERT_SIZE (16*1024) // Way larger than necessary
|
||||
#define MAR_MAX_CERT_SIZE (16 * 1024) // Way larger than necessary
|
||||
|
||||
/* Read the entire file (not a MAR file) into a newly-allocated buffer.
|
||||
* This function does not write to stderr. Instead, the caller should
|
||||
@ -177,11 +161,9 @@ mar_extract(const char* path);
|
||||
*
|
||||
* @return 0 on success, -1 on error
|
||||
*/
|
||||
int
|
||||
mar_read_entire_file(const char* filePath,
|
||||
uint32_t maxSize,
|
||||
/*out*/ const uint8_t** data,
|
||||
/*out*/ uint32_t* size);
|
||||
int mar_read_entire_file(const char* filePath, uint32_t maxSize,
|
||||
/*out*/ const uint8_t** data,
|
||||
/*out*/ uint32_t* size);
|
||||
|
||||
/**
|
||||
* Verifies a MAR file by verifying each signature with the corresponding
|
||||
@ -203,11 +185,8 @@ mar_read_entire_file(const char* filePath,
|
||||
* a negative number if there was an error
|
||||
* a positive number if the signature does not verify
|
||||
*/
|
||||
int
|
||||
mar_verify_signatures(MarFile* mar,
|
||||
const uint8_t* const* certData,
|
||||
const uint32_t* certDataSizes,
|
||||
uint32_t certCount);
|
||||
int mar_verify_signatures(MarFile* mar, const uint8_t* const* certData,
|
||||
const uint32_t* certDataSizes, uint32_t certCount);
|
||||
|
||||
/**
|
||||
* Reads the product info block from the MAR file's additional block section.
|
||||
@ -216,13 +195,12 @@ mar_verify_signatures(MarFile* mar,
|
||||
*
|
||||
* @param infoBlock Out parameter for where to store the result to
|
||||
* @return 0 on success, -1 on failure
|
||||
*/
|
||||
int
|
||||
mar_read_product_info_block(MarFile* mar,
|
||||
struct ProductInformationBlock* infoBlock);
|
||||
*/
|
||||
int mar_read_product_info_block(MarFile* mar,
|
||||
struct ProductInformationBlock* infoBlock);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* MAR_H__ */
|
||||
#endif /* MAR_H__ */
|
||||
|
@ -31,10 +31,8 @@ struct ProductInformationBlock;
|
||||
* has_additional_blocks is not equal to 0.
|
||||
* @return 0 on success and non-zero on failure.
|
||||
*/
|
||||
int get_mar_file_info(const char *path,
|
||||
int *hasSignatureBlock,
|
||||
uint32_t *numSignatures,
|
||||
int *hasAdditionalBlocks,
|
||||
int get_mar_file_info(const char *path, int *hasSignatureBlock,
|
||||
uint32_t *numSignatures, int *hasAdditionalBlocks,
|
||||
uint32_t *offsetAdditionalBlocks,
|
||||
uint32_t *numAdditionalBlocks);
|
||||
|
||||
@ -45,10 +43,9 @@ int get_mar_file_info(const char *path,
|
||||
*
|
||||
* @param infoBlock Out parameter for where to store the result to
|
||||
* @return 0 on success, -1 on failure
|
||||
*/
|
||||
int
|
||||
read_product_info_block(char *path,
|
||||
struct ProductInformationBlock *infoBlock);
|
||||
*/
|
||||
int read_product_info_block(char *path,
|
||||
struct ProductInformationBlock *infoBlock);
|
||||
|
||||
/**
|
||||
* Refreshes the product information block with the new information.
|
||||
@ -58,10 +55,9 @@ read_product_info_block(char *path,
|
||||
* should be refreshed.
|
||||
* @param infoBlock Out parameter for where to store the result to
|
||||
* @return 0 on success, -1 on failure
|
||||
*/
|
||||
int
|
||||
refresh_product_info_block(const char *path,
|
||||
struct ProductInformationBlock *infoBlock);
|
||||
*/
|
||||
int refresh_product_info_block(const char *path,
|
||||
struct ProductInformationBlock *infoBlock);
|
||||
|
||||
/**
|
||||
* Writes out a copy of the MAR at src but with the signature block stripped.
|
||||
@ -72,8 +68,7 @@ refresh_product_info_block(const char *path,
|
||||
* @return 0 on success
|
||||
* -1 on error
|
||||
*/
|
||||
int
|
||||
strip_signature_block(const char *src, const char * dest);
|
||||
int strip_signature_block(const char *src, const char *dest);
|
||||
|
||||
/**
|
||||
* Extracts a signature from a MAR file, base64 encodes it, and writes it out
|
||||
@ -83,9 +78,8 @@ strip_signature_block(const char *src, const char * dest);
|
||||
* @param dest The path of file to write the signature to
|
||||
* @return 0 on success
|
||||
* -1 on error
|
||||
*/
|
||||
int
|
||||
extract_signature(const char *src, uint32_t sigIndex, const char * dest);
|
||||
*/
|
||||
int extract_signature(const char *src, uint32_t sigIndex, const char *dest);
|
||||
|
||||
/**
|
||||
* Imports a base64 encoded signature into a MAR file
|
||||
@ -93,18 +87,16 @@ extract_signature(const char *src, uint32_t sigIndex, const char * dest);
|
||||
* @param src The path of the source MAR file
|
||||
* @param sigIndex The index of the signature to import
|
||||
* @param base64SigFile A file which contains the signature to import
|
||||
* @param dest The path of the destination MAR file with replaced signature
|
||||
* @param dest The path of the destination MAR file with replaced
|
||||
* signature
|
||||
* @return 0 on success
|
||||
* -1 on error
|
||||
*/
|
||||
int
|
||||
import_signature(const char *src,
|
||||
uint32_t sigIndex,
|
||||
const char * base64SigFile,
|
||||
const char *dest);
|
||||
*/
|
||||
int import_signature(const char *src, uint32_t sigIndex,
|
||||
const char *base64SigFile, const char *dest);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* MAR_CMDLINE_H__ */
|
||||
#endif /* MAR_CMDLINE_H__ */
|
||||
|
@ -45,12 +45,13 @@ static int mar_push(struct MarItemStack *stack, uint32_t length, uint32_t flags,
|
||||
/* increase size of stack */
|
||||
size_t size_needed = ROUND_UP(stack->size_used + size, BLOCKSIZE);
|
||||
stack->head = realloc(stack->head, size_needed);
|
||||
if (!stack->head)
|
||||
if (!stack->head) {
|
||||
return -1;
|
||||
}
|
||||
stack->size_allocated = size_needed;
|
||||
}
|
||||
|
||||
data = (((char *) stack->head) + stack->size_used);
|
||||
data = (((char *)stack->head) + stack->size_used);
|
||||
|
||||
n_offset = htonl(stack->last_offset);
|
||||
n_length = htonl(length);
|
||||
@ -104,16 +105,13 @@ static int mar_concat_file(FILE *fp, const char *path) {
|
||||
* the MAR
|
||||
* @param infoBlock The product info block to store in the file.
|
||||
* @return 0 on success.
|
||||
*/
|
||||
static int
|
||||
mar_concat_product_info_block(FILE *fp,
|
||||
struct MarItemStack *stack,
|
||||
struct ProductInformationBlock *infoBlock)
|
||||
{
|
||||
*/
|
||||
static int mar_concat_product_info_block(
|
||||
FILE *fp, struct MarItemStack *stack,
|
||||
struct ProductInformationBlock *infoBlock) {
|
||||
char buf[PIB_MAX_MAR_CHANNEL_ID_SIZE + PIB_MAX_PRODUCT_VERSION_SIZE];
|
||||
uint32_t additionalBlockID = 1, infoBlockSize, unused;
|
||||
if (!fp || !infoBlock ||
|
||||
!infoBlock->MARChannelID ||
|
||||
if (!fp || !infoBlock || !infoBlock->MARChannelID ||
|
||||
!infoBlock->productVersion) {
|
||||
return -1;
|
||||
}
|
||||
@ -132,45 +130,41 @@ mar_concat_product_info_block(FILE *fp,
|
||||
maximum MAR channel name and product version, we allocate the maximum
|
||||
amount to make it easier to modify the MAR file for repurposing MAR files
|
||||
to different MAR channels. + 2 is for the NULL terminators. */
|
||||
infoBlockSize = sizeof(infoBlockSize) +
|
||||
sizeof(additionalBlockID) +
|
||||
PIB_MAX_MAR_CHANNEL_ID_SIZE +
|
||||
PIB_MAX_PRODUCT_VERSION_SIZE + 2;
|
||||
infoBlockSize = sizeof(infoBlockSize) + sizeof(additionalBlockID) +
|
||||
PIB_MAX_MAR_CHANNEL_ID_SIZE + PIB_MAX_PRODUCT_VERSION_SIZE +
|
||||
2;
|
||||
if (stack) {
|
||||
stack->last_offset += infoBlockSize;
|
||||
}
|
||||
|
||||
/* Write out the product info block size */
|
||||
infoBlockSize = htonl(infoBlockSize);
|
||||
if (fwrite(&infoBlockSize,
|
||||
sizeof(infoBlockSize), 1, fp) != 1) {
|
||||
if (fwrite(&infoBlockSize, sizeof(infoBlockSize), 1, fp) != 1) {
|
||||
return -1;
|
||||
}
|
||||
infoBlockSize = ntohl(infoBlockSize);
|
||||
|
||||
/* Write out the product info block ID */
|
||||
additionalBlockID = htonl(additionalBlockID);
|
||||
if (fwrite(&additionalBlockID,
|
||||
sizeof(additionalBlockID), 1, fp) != 1) {
|
||||
if (fwrite(&additionalBlockID, sizeof(additionalBlockID), 1, fp) != 1) {
|
||||
return -1;
|
||||
}
|
||||
additionalBlockID = ntohl(additionalBlockID);
|
||||
|
||||
/* Write out the channel name and NULL terminator */
|
||||
if (fwrite(infoBlock->MARChannelID,
|
||||
strlen(infoBlock->MARChannelID) + 1, 1, fp) != 1) {
|
||||
if (fwrite(infoBlock->MARChannelID, strlen(infoBlock->MARChannelID) + 1, 1,
|
||||
fp) != 1) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Write out the product version string and NULL terminator */
|
||||
if (fwrite(infoBlock->productVersion,
|
||||
strlen(infoBlock->productVersion) + 1, 1, fp) != 1) {
|
||||
if (fwrite(infoBlock->productVersion, strlen(infoBlock->productVersion) + 1,
|
||||
1, fp) != 1) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Write out the rest of the block that is unused */
|
||||
unused = infoBlockSize - (sizeof(infoBlockSize) +
|
||||
sizeof(additionalBlockID) +
|
||||
unused = infoBlockSize - (sizeof(infoBlockSize) + sizeof(additionalBlockID) +
|
||||
strlen(infoBlock->MARChannelID) +
|
||||
strlen(infoBlock->productVersion) + 2);
|
||||
memset(buf, 0, sizeof(buf));
|
||||
@ -188,23 +182,18 @@ mar_concat_product_info_block(FILE *fp,
|
||||
* should be refreshed.
|
||||
* @param infoBlock Out parameter for where to store the result to
|
||||
* @return 0 on success, -1 on failure
|
||||
*/
|
||||
int
|
||||
refresh_product_info_block(const char *path,
|
||||
struct ProductInformationBlock *infoBlock)
|
||||
{
|
||||
FILE *fp ;
|
||||
*/
|
||||
int refresh_product_info_block(const char *path,
|
||||
struct ProductInformationBlock *infoBlock) {
|
||||
FILE *fp;
|
||||
int rv;
|
||||
uint32_t numSignatures, additionalBlockSize, additionalBlockID,
|
||||
offsetAdditionalBlocks, numAdditionalBlocks, i;
|
||||
offsetAdditionalBlocks, numAdditionalBlocks, i;
|
||||
int additionalBlocks, hasSignatureBlock;
|
||||
int64_t oldPos;
|
||||
|
||||
rv = get_mar_file_info(path,
|
||||
&hasSignatureBlock,
|
||||
&numSignatures,
|
||||
&additionalBlocks,
|
||||
&offsetAdditionalBlocks,
|
||||
rv = get_mar_file_info(path, &hasSignatureBlock, &numSignatures,
|
||||
&additionalBlocks, &offsetAdditionalBlocks,
|
||||
&numAdditionalBlocks);
|
||||
if (rv) {
|
||||
fprintf(stderr, "ERROR: Could not obtain MAR information.\n");
|
||||
@ -233,18 +222,14 @@ refresh_product_info_block(const char *path,
|
||||
oldPos = ftello(fp);
|
||||
|
||||
/* Read the additional block size */
|
||||
if (fread(&additionalBlockSize,
|
||||
sizeof(additionalBlockSize),
|
||||
1, fp) != 1) {
|
||||
if (fread(&additionalBlockSize, sizeof(additionalBlockSize), 1, fp) != 1) {
|
||||
fclose(fp);
|
||||
return -1;
|
||||
}
|
||||
additionalBlockSize = ntohl(additionalBlockSize);
|
||||
|
||||
/* Read the additional block ID */
|
||||
if (fread(&additionalBlockID,
|
||||
sizeof(additionalBlockID),
|
||||
1, fp) != 1) {
|
||||
if (fread(&additionalBlockID, sizeof(additionalBlockID), 1, fp) != 1) {
|
||||
fclose(fp);
|
||||
return -1;
|
||||
}
|
||||
@ -291,12 +276,11 @@ refresh_product_info_block(const char *path,
|
||||
* @param infoBlock The information to store in the product information block.
|
||||
* @return A non-zero value if an error occurs.
|
||||
*/
|
||||
int mar_create(const char *dest, int
|
||||
num_files, char **files,
|
||||
int mar_create(const char *dest, int num_files, char **files,
|
||||
struct ProductInformationBlock *infoBlock) {
|
||||
struct MarItemStack stack;
|
||||
uint32_t offset_to_index = 0, size_of_index,
|
||||
numSignatures, numAdditionalSections;
|
||||
uint32_t offset_to_index = 0, size_of_index, numSignatures,
|
||||
numAdditionalSections;
|
||||
uint64_t sizeOfEntireMAR = 0;
|
||||
struct stat st;
|
||||
FILE *fp;
|
||||
@ -310,15 +294,15 @@ int mar_create(const char *dest, int
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (fwrite(MAR_ID, MAR_ID_SIZE, 1, fp) != 1)
|
||||
if (fwrite(MAR_ID, MAR_ID_SIZE, 1, fp) != 1) {
|
||||
goto failure;
|
||||
if (fwrite(&offset_to_index, sizeof(uint32_t), 1, fp) != 1)
|
||||
}
|
||||
if (fwrite(&offset_to_index, sizeof(uint32_t), 1, fp) != 1) {
|
||||
goto failure;
|
||||
}
|
||||
|
||||
stack.last_offset = MAR_ID_SIZE +
|
||||
sizeof(offset_to_index) +
|
||||
sizeof(numSignatures) +
|
||||
sizeof(numAdditionalSections) +
|
||||
stack.last_offset = MAR_ID_SIZE + sizeof(offset_to_index) +
|
||||
sizeof(numSignatures) + sizeof(numAdditionalSections) +
|
||||
sizeof(sizeOfEntireMAR);
|
||||
|
||||
/* We will circle back on this at the end of the MAR creation to fill it */
|
||||
@ -335,8 +319,8 @@ int mar_create(const char *dest, int
|
||||
/* Write out the number of additional sections, for now just 1
|
||||
for the product info block */
|
||||
numAdditionalSections = htonl(1);
|
||||
if (fwrite(&numAdditionalSections,
|
||||
sizeof(numAdditionalSections), 1, fp) != 1) {
|
||||
if (fwrite(&numAdditionalSections, sizeof(numAdditionalSections), 1, fp) !=
|
||||
1) {
|
||||
goto failure;
|
||||
}
|
||||
numAdditionalSections = ntohl(numAdditionalSections);
|
||||
@ -351,20 +335,24 @@ int mar_create(const char *dest, int
|
||||
goto failure;
|
||||
}
|
||||
|
||||
if (mar_push(&stack, st.st_size, st.st_mode & 0777, files[i]))
|
||||
if (mar_push(&stack, st.st_size, st.st_mode & 0777, files[i])) {
|
||||
goto failure;
|
||||
}
|
||||
|
||||
/* concatenate input file to archive */
|
||||
if (mar_concat_file(fp, files[i]))
|
||||
if (mar_concat_file(fp, files[i])) {
|
||||
goto failure;
|
||||
}
|
||||
}
|
||||
|
||||
/* write out the index (prefixed with length of index) */
|
||||
size_of_index = htonl(stack.size_used);
|
||||
if (fwrite(&size_of_index, sizeof(size_of_index), 1, fp) != 1)
|
||||
if (fwrite(&size_of_index, sizeof(size_of_index), 1, fp) != 1) {
|
||||
goto failure;
|
||||
if (fwrite(stack.head, stack.size_used, 1, fp) != 1)
|
||||
}
|
||||
if (fwrite(stack.head, stack.size_used, 1, fp) != 1) {
|
||||
goto failure;
|
||||
}
|
||||
|
||||
/* To protect against invalid MAR files, we assumes that the MAR file
|
||||
size is less than or equal to MAX_SIZE_OF_MAR_FILE. */
|
||||
@ -374,26 +362,30 @@ int mar_create(const char *dest, int
|
||||
|
||||
/* write out offset to index file in network byte order */
|
||||
offset_to_index = htonl(stack.last_offset);
|
||||
if (fseek(fp, MAR_ID_SIZE, SEEK_SET))
|
||||
if (fseek(fp, MAR_ID_SIZE, SEEK_SET)) {
|
||||
goto failure;
|
||||
if (fwrite(&offset_to_index, sizeof(offset_to_index), 1, fp) != 1)
|
||||
}
|
||||
if (fwrite(&offset_to_index, sizeof(offset_to_index), 1, fp) != 1) {
|
||||
goto failure;
|
||||
}
|
||||
offset_to_index = ntohl(stack.last_offset);
|
||||
|
||||
sizeOfEntireMAR = ((uint64_t)stack.last_offset) +
|
||||
stack.size_used +
|
||||
sizeof(size_of_index);
|
||||
sizeOfEntireMAR =
|
||||
((uint64_t)stack.last_offset) + stack.size_used + sizeof(size_of_index);
|
||||
sizeOfEntireMAR = HOST_TO_NETWORK64(sizeOfEntireMAR);
|
||||
if (fwrite(&sizeOfEntireMAR, sizeof(sizeOfEntireMAR), 1, fp) != 1)
|
||||
if (fwrite(&sizeOfEntireMAR, sizeof(sizeOfEntireMAR), 1, fp) != 1) {
|
||||
goto failure;
|
||||
}
|
||||
sizeOfEntireMAR = NETWORK_TO_HOST64(sizeOfEntireMAR);
|
||||
|
||||
rv = 0;
|
||||
failure:
|
||||
if (stack.head)
|
||||
if (stack.head) {
|
||||
free(stack.head);
|
||||
}
|
||||
fclose(fp);
|
||||
if (rv)
|
||||
if (rv) {
|
||||
remove(dest);
|
||||
}
|
||||
return rv;
|
||||
}
|
||||
|
@ -15,14 +15,13 @@
|
||||
#ifdef XP_WIN
|
||||
#include <io.h>
|
||||
#include <direct.h>
|
||||
#define fdopen _fdopen
|
||||
#endif
|
||||
|
||||
/* Ensure that the directory containing this file exists */
|
||||
static int mar_ensure_parent_dir(const char *path)
|
||||
{
|
||||
static int mar_ensure_parent_dir(const char *path) {
|
||||
char *slash = strrchr(path, '/');
|
||||
if (slash)
|
||||
{
|
||||
if (slash) {
|
||||
*slash = '\0';
|
||||
mar_ensure_parent_dir(path);
|
||||
#ifdef XP_WIN
|
||||
@ -40,11 +39,13 @@ static int mar_test_callback(MarFile *mar, const MarItem *item, void *unused) {
|
||||
uint8_t buf[BLOCKSIZE];
|
||||
int fd, len, offset = 0;
|
||||
|
||||
if (mar_ensure_parent_dir(item->name))
|
||||
if (mar_ensure_parent_dir(item->name)) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
#ifdef XP_WIN
|
||||
fd = _open(item->name, _O_BINARY|_O_CREAT|_O_TRUNC|_O_WRONLY, item->flags);
|
||||
fd = _open(item->name, _O_BINARY | _O_CREAT | _O_TRUNC | _O_WRONLY,
|
||||
item->flags);
|
||||
#else
|
||||
fd = creat(item->name, item->flags);
|
||||
#endif
|
||||
@ -55,12 +56,14 @@ static int mar_test_callback(MarFile *mar, const MarItem *item, void *unused) {
|
||||
}
|
||||
|
||||
fp = fdopen(fd, "wb");
|
||||
if (!fp)
|
||||
if (!fp) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
while ((len = mar_read(mar, item, offset, buf, sizeof(buf))) > 0) {
|
||||
if (fwrite(buf, len, 1, fp) != 1)
|
||||
if (fwrite(buf, len, 1, fp) != 1) {
|
||||
break;
|
||||
}
|
||||
offset += len;
|
||||
}
|
||||
|
||||
@ -73,8 +76,9 @@ int mar_extract(const char *path) {
|
||||
int rv;
|
||||
|
||||
mar = mar_open(path);
|
||||
if (!mar)
|
||||
if (!mar) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
rv = mar_enum_items(mar, mar_test_callback, NULL);
|
||||
|
||||
|
@ -32,8 +32,8 @@ MOZ_STATIC_ASSERT(MAX_SIZE_OF_MAR_FILE < ((int64_t)LONG_MAX),
|
||||
|
||||
/* We store at most the size up to the signature block + 4
|
||||
bytes per BLOCKSIZE bytes */
|
||||
MOZ_STATIC_ASSERT(sizeof(BLOCKSIZE) < \
|
||||
(SIGNATURE_BLOCK_OFFSET + sizeof(uint32_t)),
|
||||
MOZ_STATIC_ASSERT(sizeof(BLOCKSIZE) <
|
||||
(SIGNATURE_BLOCK_OFFSET + sizeof(uint32_t)),
|
||||
"BLOCKSIZE is too big");
|
||||
|
||||
/* The maximum size of any signature supported by current and future
|
||||
@ -44,7 +44,7 @@ MOZ_STATIC_ASSERT(sizeof(BLOCKSIZE) < \
|
||||
The product information block has an ID of 1. */
|
||||
#define PRODUCT_INFO_BLOCK_ID 1
|
||||
|
||||
#define MAR_ITEM_SIZE(namelen) (3*sizeof(uint32_t) + (namelen) + 1)
|
||||
#define MAR_ITEM_SIZE(namelen) (3 * sizeof(uint32_t) + (namelen) + 1)
|
||||
|
||||
/* Product Information Block (PIB) constants */
|
||||
#define PIB_MAX_MAR_CHANNEL_ID_SIZE 63
|
||||
@ -65,15 +65,13 @@ MOZ_STATIC_ASSERT(sizeof(BLOCKSIZE) < \
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#define HOST_TO_NETWORK64(x) ( \
|
||||
((((uint64_t) x) & 0xFF) << 56) | \
|
||||
((((uint64_t) x) >> 8) & 0xFF) << 48) | \
|
||||
(((((uint64_t) x) >> 16) & 0xFF) << 40) | \
|
||||
(((((uint64_t) x) >> 24) & 0xFF) << 32) | \
|
||||
(((((uint64_t) x) >> 32) & 0xFF) << 24) | \
|
||||
(((((uint64_t) x) >> 40) & 0xFF) << 16) | \
|
||||
(((((uint64_t) x) >> 48) & 0xFF) << 8) | \
|
||||
(((uint64_t) x) >> 56)
|
||||
#define HOST_TO_NETWORK64(x) \
|
||||
(((((uint64_t)x) & 0xFF) << 56) | ((((uint64_t)x) >> 8) & 0xFF) << 48) | \
|
||||
(((((uint64_t)x) >> 16) & 0xFF) << 40) | \
|
||||
(((((uint64_t)x) >> 24) & 0xFF) << 32) | \
|
||||
(((((uint64_t)x) >> 32) & 0xFF) << 24) | \
|
||||
(((((uint64_t)x) >> 40) & 0xFF) << 16) | \
|
||||
(((((uint64_t)x) >> 48) & 0xFF) << 8) | (((uint64_t)x) >> 56)
|
||||
#define NETWORK_TO_HOST64 HOST_TO_NETWORK64
|
||||
|
||||
#endif /* MAR_PRIVATE_H__ */
|
||||
#endif /* MAR_PRIVATE_H__ */
|
||||
|
@ -11,6 +11,9 @@
|
||||
#include "city.h"
|
||||
#include "mar_private.h"
|
||||
#include "mar.h"
|
||||
#ifdef XP_WIN
|
||||
#define strdup _strdup
|
||||
#endif
|
||||
|
||||
/* This block must be at most 104 bytes.
|
||||
MAR channel name < 64 bytes, and product version < 32 bytes + 3 NULL
|
||||
@ -19,26 +22,19 @@
|
||||
sizeof(additionalBlockSize) and sizeof(additionalBlockID) */
|
||||
#define MAXADDITIONALBLOCKSIZE 96
|
||||
|
||||
static uint32_t
|
||||
mar_hash_name(const char* name)
|
||||
{
|
||||
static uint32_t mar_hash_name(const char* name) {
|
||||
return CityHash64(name, strlen(name)) % TABLESIZE;
|
||||
}
|
||||
|
||||
static int
|
||||
mar_insert_item(MarFile* mar,
|
||||
const char* name,
|
||||
int namelen,
|
||||
uint32_t offset,
|
||||
uint32_t length,
|
||||
uint32_t flags)
|
||||
{
|
||||
static int mar_insert_item(MarFile* mar, const char* name, int namelen,
|
||||
uint32_t offset, uint32_t length, uint32_t flags) {
|
||||
MarItem *item, *root;
|
||||
uint32_t hash;
|
||||
|
||||
item = (MarItem *) malloc(sizeof(MarItem) + namelen);
|
||||
if (!item)
|
||||
item = (MarItem*)malloc(sizeof(MarItem) + namelen);
|
||||
if (!item) {
|
||||
return -1;
|
||||
}
|
||||
item->next = NULL;
|
||||
item->offset = offset;
|
||||
item->length = length;
|
||||
@ -52,16 +48,13 @@ mar_insert_item(MarFile* mar,
|
||||
mar->item_table[hash] = item;
|
||||
} else {
|
||||
/* append item */
|
||||
while (root->next)
|
||||
root = root->next;
|
||||
while (root->next) root = root->next;
|
||||
root->next = item;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
mar_consume_index(MarFile* mar, char** buf, const char* buf_end)
|
||||
{
|
||||
static int mar_consume_index(MarFile* mar, char** buf, const char* buf_end) {
|
||||
/*
|
||||
* Each item has the following structure:
|
||||
* uint32_t offset (network byte order)
|
||||
@ -73,11 +66,12 @@ mar_consume_index(MarFile* mar, char** buf, const char* buf_end)
|
||||
uint32_t offset;
|
||||
uint32_t length;
|
||||
uint32_t flags;
|
||||
const char *name;
|
||||
const char* name;
|
||||
int namelen;
|
||||
|
||||
if ((buf_end - *buf) < (int)(3*sizeof(uint32_t) + 2))
|
||||
if ((buf_end - *buf) < (int)(3 * sizeof(uint32_t) + 2)) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
memcpy(&offset, *buf, sizeof(offset));
|
||||
*buf += sizeof(offset);
|
||||
@ -96,8 +90,9 @@ mar_consume_index(MarFile* mar, char** buf, const char* buf_end)
|
||||
/* find namelen; must take care not to read beyond buf_end */
|
||||
while (**buf) {
|
||||
/* buf_end points one byte past the end of buf's allocation */
|
||||
if (*buf == (buf_end - 1))
|
||||
if (*buf == (buf_end - 1)) {
|
||||
return -1;
|
||||
}
|
||||
++(*buf);
|
||||
}
|
||||
namelen = (*buf - name);
|
||||
@ -106,39 +101,44 @@ mar_consume_index(MarFile* mar, char** buf, const char* buf_end)
|
||||
return -1;
|
||||
}
|
||||
/* consume null byte */
|
||||
if (*buf == buf_end)
|
||||
if (*buf == buf_end) {
|
||||
return -1;
|
||||
}
|
||||
++(*buf);
|
||||
|
||||
return mar_insert_item(mar, name, namelen, offset, length, flags);
|
||||
}
|
||||
|
||||
static int
|
||||
mar_read_index(MarFile* mar)
|
||||
{
|
||||
static int mar_read_index(MarFile* mar) {
|
||||
char id[MAR_ID_SIZE], *buf, *bufptr, *bufend;
|
||||
uint32_t offset_to_index, size_of_index;
|
||||
|
||||
/* verify MAR ID */
|
||||
fseek(mar->fp, 0, SEEK_SET);
|
||||
if (fread(id, MAR_ID_SIZE, 1, mar->fp) != 1)
|
||||
if (fread(id, MAR_ID_SIZE, 1, mar->fp) != 1) {
|
||||
return -1;
|
||||
if (memcmp(id, MAR_ID, MAR_ID_SIZE) != 0)
|
||||
}
|
||||
if (memcmp(id, MAR_ID, MAR_ID_SIZE) != 0) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (fread(&offset_to_index, sizeof(uint32_t), 1, mar->fp) != 1)
|
||||
if (fread(&offset_to_index, sizeof(uint32_t), 1, mar->fp) != 1) {
|
||||
return -1;
|
||||
}
|
||||
offset_to_index = ntohl(offset_to_index);
|
||||
|
||||
if (fseek(mar->fp, offset_to_index, SEEK_SET))
|
||||
if (fseek(mar->fp, offset_to_index, SEEK_SET)) {
|
||||
return -1;
|
||||
if (fread(&size_of_index, sizeof(uint32_t), 1, mar->fp) != 1)
|
||||
}
|
||||
if (fread(&size_of_index, sizeof(uint32_t), 1, mar->fp) != 1) {
|
||||
return -1;
|
||||
}
|
||||
size_of_index = ntohl(size_of_index);
|
||||
|
||||
buf = (char *) malloc(size_of_index);
|
||||
if (!buf)
|
||||
buf = (char*)malloc(size_of_index);
|
||||
if (!buf) {
|
||||
return -1;
|
||||
}
|
||||
if (fread(buf, size_of_index, 1, mar->fp) != 1) {
|
||||
free(buf);
|
||||
return -1;
|
||||
@ -146,7 +146,8 @@ mar_read_index(MarFile* mar)
|
||||
|
||||
bufptr = buf;
|
||||
bufend = buf + size_of_index;
|
||||
while (bufptr < bufend && mar_consume_index(mar, &bufptr, bufend) == 0);
|
||||
while (bufptr < bufend && mar_consume_index(mar, &bufptr, bufend) == 0)
|
||||
;
|
||||
|
||||
free(buf);
|
||||
return (bufptr == bufend) ? 0 : -1;
|
||||
@ -160,9 +161,7 @@ mar_read_index(MarFile* mar)
|
||||
* @return int 1 on success, 0 if offset has been previously processed
|
||||
* -1 if unable to allocate space for the SeenIndexes
|
||||
*/
|
||||
static int
|
||||
mar_insert_offset(MarFile* mar, uint32_t offset, uint32_t length)
|
||||
{
|
||||
static int mar_insert_offset(MarFile* mar, uint32_t offset, uint32_t length) {
|
||||
/* Ignore files with no length */
|
||||
if (length == 0) {
|
||||
return 1;
|
||||
@ -213,9 +212,7 @@ mar_insert_offset(MarFile* mar, uint32_t offset, uint32_t length)
|
||||
* Internal shared code for mar_open and mar_wopen.
|
||||
* On failure, will fclose(fp).
|
||||
*/
|
||||
static MarFile*
|
||||
mar_fpopen(FILE* fp)
|
||||
{
|
||||
static MarFile* mar_fpopen(FILE* fp) {
|
||||
MarFile* mar;
|
||||
|
||||
mar = (MarFile*)malloc(sizeof(*mar));
|
||||
@ -232,10 +229,8 @@ mar_fpopen(FILE* fp)
|
||||
return mar;
|
||||
}
|
||||
|
||||
MarFile*
|
||||
mar_open(const char* path)
|
||||
{
|
||||
FILE *fp;
|
||||
MarFile* mar_open(const char* path) {
|
||||
FILE* fp;
|
||||
|
||||
fp = fopen(path, "rb");
|
||||
if (!fp) {
|
||||
@ -248,10 +243,8 @@ mar_open(const char* path)
|
||||
}
|
||||
|
||||
#ifdef XP_WIN
|
||||
MarFile*
|
||||
mar_wopen(const wchar_t* path)
|
||||
{
|
||||
FILE *fp;
|
||||
MarFile* mar_wopen(const wchar_t* path) {
|
||||
FILE* fp;
|
||||
|
||||
_wfopen_s(&fp, path, L"rb");
|
||||
if (!fp) {
|
||||
@ -264,9 +257,7 @@ mar_wopen(const wchar_t* path)
|
||||
}
|
||||
#endif
|
||||
|
||||
void
|
||||
mar_close(MarFile* mar)
|
||||
{
|
||||
void mar_close(MarFile* mar) {
|
||||
MarItem* item;
|
||||
SeenIndex* index;
|
||||
int i;
|
||||
@ -309,14 +300,10 @@ mar_close(MarFile* mar)
|
||||
* hasAdditionalBlocks is not equal to 0.
|
||||
* @return 0 on success and non-zero on failure.
|
||||
*/
|
||||
int
|
||||
get_mar_file_info_fp(FILE* fp,
|
||||
int* hasSignatureBlock,
|
||||
uint32_t* numSignatures,
|
||||
int* hasAdditionalBlocks,
|
||||
uint32_t* offsetAdditionalBlocks,
|
||||
uint32_t* numAdditionalBlocks)
|
||||
{
|
||||
int get_mar_file_info_fp(FILE* fp, int* hasSignatureBlock,
|
||||
uint32_t* numSignatures, int* hasAdditionalBlocks,
|
||||
uint32_t* offsetAdditionalBlocks,
|
||||
uint32_t* numAdditionalBlocks) {
|
||||
uint32_t offsetToIndex, offsetToContent, signatureCount, signatureLen, i;
|
||||
|
||||
/* One of hasSignatureBlock or hasAdditionalBlocks must be non NULL */
|
||||
@ -324,7 +311,6 @@ get_mar_file_info_fp(FILE* fp,
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
/* Skip to the start of the offset index */
|
||||
if (fseek(fp, MAR_ID_SIZE, SEEK_SET)) {
|
||||
return -1;
|
||||
@ -337,7 +323,7 @@ get_mar_file_info_fp(FILE* fp,
|
||||
offsetToIndex = ntohl(offsetToIndex);
|
||||
|
||||
if (numSignatures) {
|
||||
/* Skip past the MAR file size field */
|
||||
/* Skip past the MAR file size field */
|
||||
if (fseek(fp, sizeof(uint64_t), SEEK_CUR)) {
|
||||
return -1;
|
||||
}
|
||||
@ -381,7 +367,7 @@ get_mar_file_info_fp(FILE* fp,
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Skip to the start of the signature block */
|
||||
/* Skip to the start of the signature block */
|
||||
if (fseeko(fp, SIGNATURE_BLOCK_OFFSET, SEEK_SET)) {
|
||||
return -1;
|
||||
}
|
||||
@ -446,15 +432,15 @@ get_mar_file_info_fp(FILE* fp,
|
||||
*
|
||||
* @param infoBlock Out parameter for where to store the result to
|
||||
* @return 0 on success, -1 on failure
|
||||
*/
|
||||
int
|
||||
read_product_info_block(char* path, struct ProductInformationBlock* infoBlock)
|
||||
{
|
||||
*/
|
||||
int read_product_info_block(char* path,
|
||||
struct ProductInformationBlock* infoBlock) {
|
||||
int rv;
|
||||
MarFile mar;
|
||||
mar.fp = fopen(path, "rb");
|
||||
if (!mar.fp) {
|
||||
fprintf(stderr, "ERROR: could not open file in read_product_info_block()\n");
|
||||
fprintf(stderr,
|
||||
"ERROR: could not open file in read_product_info_block()\n");
|
||||
perror(path);
|
||||
return -1;
|
||||
}
|
||||
@ -470,20 +456,17 @@ read_product_info_block(char* path, struct ProductInformationBlock* infoBlock)
|
||||
*
|
||||
* @param infoBlock Out parameter for where to store the result to
|
||||
* @return 0 on success, -1 on failure
|
||||
*/
|
||||
int
|
||||
mar_read_product_info_block(MarFile* mar,
|
||||
struct ProductInformationBlock* infoBlock)
|
||||
{
|
||||
uint32_t offsetAdditionalBlocks, numAdditionalBlocks,
|
||||
additionalBlockSize, additionalBlockID;
|
||||
*/
|
||||
int mar_read_product_info_block(MarFile* mar,
|
||||
struct ProductInformationBlock* infoBlock) {
|
||||
uint32_t offsetAdditionalBlocks, numAdditionalBlocks, additionalBlockSize,
|
||||
additionalBlockID;
|
||||
int hasAdditionalBlocks;
|
||||
|
||||
/* The buffer size is 97 bytes because the MAR channel name < 64 bytes, and
|
||||
product version < 32 bytes + 3 NULL terminator bytes. */
|
||||
char buf[MAXADDITIONALBLOCKSIZE + 1] = { '\0' };
|
||||
if (get_mar_file_info_fp(mar->fp, NULL, NULL,
|
||||
&hasAdditionalBlocks,
|
||||
char buf[MAXADDITIONALBLOCKSIZE + 1] = {'\0'};
|
||||
if (get_mar_file_info_fp(mar->fp, NULL, NULL, &hasAdditionalBlocks,
|
||||
&offsetAdditionalBlocks,
|
||||
&numAdditionalBlocks) != 0) {
|
||||
return -1;
|
||||
@ -493,9 +476,8 @@ mar_read_product_info_block(MarFile* mar,
|
||||
in a MAR file so check if any exist and process the first found */
|
||||
if (numAdditionalBlocks > 0) {
|
||||
/* Read the additional block size */
|
||||
if (fread(&additionalBlockSize,
|
||||
sizeof(additionalBlockSize),
|
||||
1, mar->fp) != 1) {
|
||||
if (fread(&additionalBlockSize, sizeof(additionalBlockSize), 1, mar->fp) !=
|
||||
1) {
|
||||
return -1;
|
||||
}
|
||||
additionalBlockSize = ntohl(additionalBlockSize) -
|
||||
@ -508,15 +490,13 @@ mar_read_product_info_block(MarFile* mar,
|
||||
}
|
||||
|
||||
/* Read the additional block ID */
|
||||
if (fread(&additionalBlockID,
|
||||
sizeof(additionalBlockID),
|
||||
1, mar->fp) != 1) {
|
||||
if (fread(&additionalBlockID, sizeof(additionalBlockID), 1, mar->fp) != 1) {
|
||||
return -1;
|
||||
}
|
||||
additionalBlockID = ntohl(additionalBlockID);
|
||||
|
||||
if (PRODUCT_INFO_BLOCK_ID == additionalBlockID) {
|
||||
const char *location;
|
||||
const char* location;
|
||||
int len;
|
||||
|
||||
if (fread(buf, additionalBlockSize, 1, mar->fp) != 1) {
|
||||
@ -543,10 +523,8 @@ mar_read_product_info_block(MarFile* mar,
|
||||
infoBlock->productVersion = NULL;
|
||||
return -1;
|
||||
}
|
||||
infoBlock->MARChannelID =
|
||||
strdup(infoBlock->MARChannelID);
|
||||
infoBlock->productVersion =
|
||||
strdup(infoBlock->productVersion);
|
||||
infoBlock->MARChannelID = strdup(infoBlock->MARChannelID);
|
||||
infoBlock->productVersion = strdup(infoBlock->productVersion);
|
||||
return 0;
|
||||
} else {
|
||||
/* This is not the additional block you're looking for. Move along. */
|
||||
@ -560,9 +538,7 @@ mar_read_product_info_block(MarFile* mar,
|
||||
return -1;
|
||||
}
|
||||
|
||||
const MarItem*
|
||||
mar_find_item(MarFile* mar, const char* name)
|
||||
{
|
||||
const MarItem* mar_find_item(MarFile* mar, const char* name) {
|
||||
uint32_t hash;
|
||||
const MarItem* item;
|
||||
|
||||
@ -590,9 +566,7 @@ mar_find_item(MarFile* mar, const char* name)
|
||||
}
|
||||
}
|
||||
|
||||
int
|
||||
mar_enum_items(MarFile* mar, MarItemCallback callback, void* closure)
|
||||
{
|
||||
int mar_enum_items(MarFile* mar, MarItemCallback callback, void* closure) {
|
||||
MarItem* item;
|
||||
int i, rv;
|
||||
|
||||
@ -624,26 +598,25 @@ mar_enum_items(MarFile* mar, MarItemCallback callback, void* closure)
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
mar_read(MarFile* mar,
|
||||
const MarItem* item,
|
||||
int offset,
|
||||
uint8_t* buf,
|
||||
int bufsize)
|
||||
{
|
||||
int mar_read(MarFile* mar, const MarItem* item, int offset, uint8_t* buf,
|
||||
int bufsize) {
|
||||
int nr;
|
||||
|
||||
if (offset == (int) item->length)
|
||||
if (offset == (int)item->length) {
|
||||
return 0;
|
||||
if (offset > (int) item->length)
|
||||
}
|
||||
if (offset > (int)item->length) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
nr = item->length - offset;
|
||||
if (nr > bufsize)
|
||||
if (nr > bufsize) {
|
||||
nr = bufsize;
|
||||
}
|
||||
|
||||
if (fseek(mar->fp, item->offset + offset, SEEK_SET))
|
||||
if (fseek(mar->fp, item->offset + offset, SEEK_SET)) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
return fread(buf, 1, nr, mar->fp);
|
||||
}
|
||||
@ -666,25 +639,21 @@ mar_read(MarFile* mar,
|
||||
* has_additional_blocks is not equal to 0.
|
||||
* @return 0 on success and non-zero on failure.
|
||||
*/
|
||||
int
|
||||
get_mar_file_info(const char* path,
|
||||
int* hasSignatureBlock,
|
||||
uint32_t* numSignatures,
|
||||
int* hasAdditionalBlocks,
|
||||
uint32_t* offsetAdditionalBlocks,
|
||||
uint32_t* numAdditionalBlocks)
|
||||
{
|
||||
int get_mar_file_info(const char* path, int* hasSignatureBlock,
|
||||
uint32_t* numSignatures, int* hasAdditionalBlocks,
|
||||
uint32_t* offsetAdditionalBlocks,
|
||||
uint32_t* numAdditionalBlocks) {
|
||||
int rv;
|
||||
FILE *fp = fopen(path, "rb");
|
||||
FILE* fp = fopen(path, "rb");
|
||||
if (!fp) {
|
||||
fprintf(stderr, "ERROR: could not open file in get_mar_file_info()\n");
|
||||
perror(path);
|
||||
return -1;
|
||||
}
|
||||
|
||||
rv = get_mar_file_info_fp(fp, hasSignatureBlock,
|
||||
numSignatures, hasAdditionalBlocks,
|
||||
offsetAdditionalBlocks, numAdditionalBlocks);
|
||||
rv = get_mar_file_info_fp(fp, hasSignatureBlock, numSignatures,
|
||||
hasAdditionalBlocks, offsetAdditionalBlocks,
|
||||
numAdditionalBlocks);
|
||||
|
||||
fclose(fp);
|
||||
return rv;
|
||||
|
@ -26,10 +26,8 @@ int NSSInitCryptoContext(const char *NSSConfigDir);
|
||||
#endif
|
||||
|
||||
int mar_repackage_and_sign(const char *NSSConfigDir,
|
||||
const char * const *certNames,
|
||||
uint32_t certCount,
|
||||
const char *src,
|
||||
const char * dest);
|
||||
const char *const *certNames, uint32_t certCount,
|
||||
const char *src, const char *dest);
|
||||
|
||||
static void print_version() {
|
||||
printf("Version: %s\n", MOZ_APP_VERSION);
|
||||
@ -39,43 +37,55 @@ static void print_version() {
|
||||
static void print_usage() {
|
||||
printf("usage:\n");
|
||||
printf("Create a MAR file:\n");
|
||||
printf(" mar [-H MARChannelID] [-V ProductVersion] [-C workingDir] "
|
||||
"-c archive.mar [files...]\n");
|
||||
printf(
|
||||
" mar [-H MARChannelID] [-V ProductVersion] [-C workingDir] "
|
||||
"-c archive.mar [files...]\n");
|
||||
|
||||
printf("Extract a MAR file:\n");
|
||||
printf(" mar [-C workingDir] -x archive.mar\n");
|
||||
#ifndef NO_SIGN_VERIFY
|
||||
printf("Sign a MAR file:\n");
|
||||
printf(" mar [-C workingDir] -d NSSConfigDir -n certname -s "
|
||||
"archive.mar out_signed_archive.mar\n");
|
||||
printf(
|
||||
" mar [-C workingDir] -d NSSConfigDir -n certname -s "
|
||||
"archive.mar out_signed_archive.mar\n");
|
||||
|
||||
printf("Strip a MAR signature:\n");
|
||||
printf(" mar [-C workingDir] -r "
|
||||
"signed_input_archive.mar output_archive.mar\n");
|
||||
printf(
|
||||
" mar [-C workingDir] -r "
|
||||
"signed_input_archive.mar output_archive.mar\n");
|
||||
|
||||
printf("Extract a MAR signature:\n");
|
||||
printf(" mar [-C workingDir] -n(i) -X "
|
||||
"signed_input_archive.mar base_64_encoded_signature_file\n");
|
||||
printf(
|
||||
" mar [-C workingDir] -n(i) -X "
|
||||
"signed_input_archive.mar base_64_encoded_signature_file\n");
|
||||
|
||||
printf("Import a MAR signature:\n");
|
||||
printf(" mar [-C workingDir] -n(i) -I "
|
||||
"signed_input_archive.mar base_64_encoded_signature_file "
|
||||
"changed_signed_output.mar\n");
|
||||
printf(
|
||||
" mar [-C workingDir] -n(i) -I "
|
||||
"signed_input_archive.mar base_64_encoded_signature_file "
|
||||
"changed_signed_output.mar\n");
|
||||
printf("(i) is the index of the certificate to extract\n");
|
||||
#if defined(XP_MACOSX) || (defined(XP_WIN) && !defined(MAR_NSS))
|
||||
printf("Verify a MAR file:\n");
|
||||
printf(" mar [-C workingDir] -D DERFilePath -v signed_archive.mar\n");
|
||||
printf("At most %d signature certificate DER files are specified by "
|
||||
"-D0 DERFilePath1 -D1 DERFilePath2, ...\n", MAX_SIGNATURES);
|
||||
printf(
|
||||
"At most %d signature certificate DER files are specified by "
|
||||
"-D0 DERFilePath1 -D1 DERFilePath2, ...\n",
|
||||
MAX_SIGNATURES);
|
||||
#else
|
||||
printf("Verify a MAR file:\n");
|
||||
printf(" mar [-C workingDir] -d NSSConfigDir -n certname "
|
||||
"-v signed_archive.mar\n");
|
||||
printf("At most %d signature certificate names are specified by "
|
||||
"-n0 certName -n1 certName2, ...\n", MAX_SIGNATURES);
|
||||
printf(
|
||||
" mar [-C workingDir] -d NSSConfigDir -n certname "
|
||||
"-v signed_archive.mar\n");
|
||||
printf(
|
||||
"At most %d signature certificate names are specified by "
|
||||
"-n0 certName -n1 certName2, ...\n",
|
||||
MAX_SIGNATURES);
|
||||
#endif
|
||||
printf("At most %d verification certificate names are specified by "
|
||||
"-n0 certName -n1 certName2, ...\n", MAX_SIGNATURES);
|
||||
printf(
|
||||
"At most %d verification certificate names are specified by "
|
||||
"-n0 certName -n1 certName2, ...\n",
|
||||
MAX_SIGNATURES);
|
||||
#endif
|
||||
printf("Print information on a MAR file:\n");
|
||||
printf(" mar -t archive.mar\n");
|
||||
@ -84,17 +94,16 @@ static void print_usage() {
|
||||
printf(" mar -T archive.mar\n");
|
||||
|
||||
printf("Refresh the product information block of a MAR file:\n");
|
||||
printf(" mar [-H MARChannelID] [-V ProductVersion] [-C workingDir] "
|
||||
"-i unsigned_archive_to_refresh.mar\n");
|
||||
printf(
|
||||
" mar [-H MARChannelID] [-V ProductVersion] [-C workingDir] "
|
||||
"-i unsigned_archive_to_refresh.mar\n");
|
||||
|
||||
printf("Print executable version:\n");
|
||||
printf(" mar --version\n");
|
||||
printf("This program does not handle unicode file paths properly\n");
|
||||
}
|
||||
|
||||
static int mar_test_callback(MarFile *mar,
|
||||
const MarItem *item,
|
||||
void *unused) {
|
||||
static int mar_test_callback(MarFile *mar, const MarItem *item, void *unused) {
|
||||
printf("%u\t0%o\t%s\n", item->length, item->flags, item->name);
|
||||
return 0;
|
||||
}
|
||||
@ -103,8 +112,9 @@ static int mar_test(const char *path) {
|
||||
MarFile *mar;
|
||||
|
||||
mar = mar_open(path);
|
||||
if (!mar)
|
||||
if (!mar) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
printf("SIZE\tMODE\tNAME\n");
|
||||
mar_enum_items(mar, mar_test_callback, NULL);
|
||||
@ -125,22 +135,22 @@ int main(int argc, char **argv) {
|
||||
|
||||
#if !defined(NO_SIGN_VERIFY)
|
||||
uint32_t fileSizes[MAX_SIGNATURES];
|
||||
const uint8_t* certBuffers[MAX_SIGNATURES];
|
||||
const uint8_t *certBuffers[MAX_SIGNATURES];
|
||||
#if ((!defined(MAR_NSS) && defined(XP_WIN)) || defined(XP_MACOSX)) || \
|
||||
((defined(XP_WIN) || defined(XP_MACOSX)) && !defined(MAR_NSS))
|
||||
char* DERFilePaths[MAX_SIGNATURES];
|
||||
char *DERFilePaths[MAX_SIGNATURES];
|
||||
#endif
|
||||
#if (!defined(XP_WIN) && !defined(XP_MACOSX)) || defined(MAR_NSS)
|
||||
CERTCertificate* certs[MAX_SIGNATURES];
|
||||
CERTCertificate *certs[MAX_SIGNATURES];
|
||||
#endif
|
||||
#endif
|
||||
|
||||
memset((void*)certNames, 0, sizeof(certNames));
|
||||
memset((void *)certNames, 0, sizeof(certNames));
|
||||
#if defined(XP_WIN) && !defined(MAR_NSS) && !defined(NO_SIGN_VERIFY)
|
||||
memset((void*)certBuffers, 0, sizeof(certBuffers));
|
||||
memset((void *)certBuffers, 0, sizeof(certBuffers));
|
||||
#endif
|
||||
#if !defined(NO_SIGN_VERIFY) && ((!defined(MAR_NSS) && defined(XP_WIN)) || \
|
||||
defined(XP_MACOSX))
|
||||
#if !defined(NO_SIGN_VERIFY) && \
|
||||
((!defined(MAR_NSS) && defined(XP_WIN)) || defined(XP_MACOSX))
|
||||
memset(DERFilePaths, 0, sizeof(DERFilePaths));
|
||||
memset(fileSizes, 0, sizeof(fileSizes));
|
||||
#endif
|
||||
@ -156,14 +166,13 @@ int main(int argc, char **argv) {
|
||||
}
|
||||
|
||||
while (argc > 0) {
|
||||
if (argv[1][0] == '-' && (argv[1][1] == 'c' ||
|
||||
argv[1][1] == 't' || argv[1][1] == 'x' ||
|
||||
argv[1][1] == 'v' || argv[1][1] == 's' ||
|
||||
argv[1][1] == 'i' || argv[1][1] == 'T' ||
|
||||
argv[1][1] == 'r' || argv[1][1] == 'X' ||
|
||||
argv[1][1] == 'I')) {
|
||||
if (argv[1][0] == '-' &&
|
||||
(argv[1][1] == 'c' || argv[1][1] == 't' || argv[1][1] == 'x' ||
|
||||
argv[1][1] == 'v' || argv[1][1] == 's' || argv[1][1] == 'i' ||
|
||||
argv[1][1] == 'T' || argv[1][1] == 'r' || argv[1][1] == 'X' ||
|
||||
argv[1][1] == 'I')) {
|
||||
break;
|
||||
/* -C workingdirectory */
|
||||
/* -C workingdirectory */
|
||||
}
|
||||
if (argv[1][0] == '-' && argv[1][1] == 'C') {
|
||||
if (chdir(argv[2]) != 0) {
|
||||
@ -172,13 +181,12 @@ int main(int argc, char **argv) {
|
||||
argv += 2;
|
||||
argc -= 2;
|
||||
}
|
||||
#if !defined(NO_SIGN_VERIFY) && ((!defined(MAR_NSS) && defined(XP_WIN)) || \
|
||||
defined(XP_MACOSX))
|
||||
#if !defined(NO_SIGN_VERIFY) && \
|
||||
((!defined(MAR_NSS) && defined(XP_WIN)) || defined(XP_MACOSX))
|
||||
/* -D DERFilePath, also matches -D[index] DERFilePath
|
||||
We allow an index for verifying to be symmetric
|
||||
with the import and export command line arguments. */
|
||||
else if (argv[1][0] == '-' &&
|
||||
argv[1][1] == 'D' &&
|
||||
else if (argv[1][0] == '-' && argv[1][1] == 'D' &&
|
||||
(argv[1][2] == (char)('0' + certCount) || argv[1][2] == '\0')) {
|
||||
if (certCount >= MAX_SIGNATURES) {
|
||||
print_usage();
|
||||
@ -194,15 +202,12 @@ int main(int argc, char **argv) {
|
||||
NSSConfigDir = argv[2];
|
||||
argv += 2;
|
||||
argc -= 2;
|
||||
/* -n certName, also matches -n[index] certName
|
||||
We allow an index for verifying to be symmetric
|
||||
with the import and export command line arguments. */
|
||||
} else if (argv[1][0] == '-' &&
|
||||
argv[1][1] == 'n' &&
|
||||
(argv[1][2] == (char)('0' + certCount) ||
|
||||
argv[1][2] == '\0' ||
|
||||
!strcmp(argv[2], "-X") ||
|
||||
!strcmp(argv[2], "-I"))) {
|
||||
/* -n certName, also matches -n[index] certName
|
||||
We allow an index for verifying to be symmetric
|
||||
with the import and export command line arguments. */
|
||||
} else if (argv[1][0] == '-' && argv[1][1] == 'n' &&
|
||||
(argv[1][2] == (char)('0' + certCount) || argv[1][2] == '\0' ||
|
||||
!strcmp(argv[2], "-X") || !strcmp(argv[2], "-I"))) {
|
||||
if (certCount >= MAX_SIGNATURES) {
|
||||
print_usage();
|
||||
return -1;
|
||||
@ -218,18 +223,15 @@ int main(int argc, char **argv) {
|
||||
argv += 2;
|
||||
argc -= 2;
|
||||
}
|
||||
/* MAR channel ID */
|
||||
} else if (argv[1][0] == '-' && argv[1][1] == 'H') {
|
||||
} else if (argv[1][0] == '-' && argv[1][1] == 'H') { // MAR channel ID
|
||||
MARChannelID = argv[2];
|
||||
argv += 2;
|
||||
argc -= 2;
|
||||
/* Product Version */
|
||||
} else if (argv[1][0] == '-' && argv[1][1] == 'V') {
|
||||
} else if (argv[1][0] == '-' && argv[1][1] == 'V') { // Product Version
|
||||
productVersion = argv[2];
|
||||
argv += 2;
|
||||
argc -= 2;
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
print_usage();
|
||||
return -1;
|
||||
}
|
||||
@ -241,187 +243,181 @@ int main(int argc, char **argv) {
|
||||
}
|
||||
|
||||
switch (argv[1][1]) {
|
||||
case 'c': {
|
||||
struct ProductInformationBlock infoBlock;
|
||||
infoBlock.MARChannelID = MARChannelID;
|
||||
infoBlock.productVersion = productVersion;
|
||||
return mar_create(argv[2], argc - 3, argv + 3, &infoBlock);
|
||||
}
|
||||
case 'i': {
|
||||
struct ProductInformationBlock infoBlock;
|
||||
infoBlock.MARChannelID = MARChannelID;
|
||||
infoBlock.productVersion = productVersion;
|
||||
return refresh_product_info_block(argv[2], &infoBlock);
|
||||
}
|
||||
case 'T': {
|
||||
struct ProductInformationBlock infoBlock;
|
||||
uint32_t numSignatures, numAdditionalBlocks;
|
||||
int hasSignatureBlock, hasAdditionalBlock;
|
||||
if (!get_mar_file_info(argv[2],
|
||||
&hasSignatureBlock,
|
||||
&numSignatures,
|
||||
&hasAdditionalBlock,
|
||||
NULL, &numAdditionalBlocks)) {
|
||||
if (hasSignatureBlock) {
|
||||
printf("Signature block found with %d signature%s\n",
|
||||
numSignatures,
|
||||
numSignatures != 1 ? "s" : "");
|
||||
}
|
||||
if (hasAdditionalBlock) {
|
||||
printf("%d additional block%s found:\n",
|
||||
numAdditionalBlocks,
|
||||
numAdditionalBlocks != 1 ? "s" : "");
|
||||
}
|
||||
case 'c': {
|
||||
struct ProductInformationBlock infoBlock;
|
||||
infoBlock.MARChannelID = MARChannelID;
|
||||
infoBlock.productVersion = productVersion;
|
||||
return mar_create(argv[2], argc - 3, argv + 3, &infoBlock);
|
||||
}
|
||||
case 'i': {
|
||||
struct ProductInformationBlock infoBlock;
|
||||
infoBlock.MARChannelID = MARChannelID;
|
||||
infoBlock.productVersion = productVersion;
|
||||
return refresh_product_info_block(argv[2], &infoBlock);
|
||||
}
|
||||
case 'T': {
|
||||
struct ProductInformationBlock infoBlock;
|
||||
uint32_t numSignatures, numAdditionalBlocks;
|
||||
int hasSignatureBlock, hasAdditionalBlock;
|
||||
if (!get_mar_file_info(argv[2], &hasSignatureBlock, &numSignatures,
|
||||
&hasAdditionalBlock, NULL, &numAdditionalBlocks)) {
|
||||
if (hasSignatureBlock) {
|
||||
printf("Signature block found with %d signature%s\n", numSignatures,
|
||||
numSignatures != 1 ? "s" : "");
|
||||
}
|
||||
if (hasAdditionalBlock) {
|
||||
printf("%d additional block%s found:\n", numAdditionalBlocks,
|
||||
numAdditionalBlocks != 1 ? "s" : "");
|
||||
}
|
||||
|
||||
rv = read_product_info_block(argv[2], &infoBlock);
|
||||
if (!rv) {
|
||||
printf(" - Product Information Block:\n");
|
||||
printf(" - MAR channel name: %s\n"
|
||||
" - Product version: %s\n",
|
||||
infoBlock.MARChannelID,
|
||||
infoBlock.productVersion);
|
||||
free((void *)infoBlock.MARChannelID);
|
||||
free((void *)infoBlock.productVersion);
|
||||
rv = read_product_info_block(argv[2], &infoBlock);
|
||||
if (!rv) {
|
||||
printf(" - Product Information Block:\n");
|
||||
printf(
|
||||
" - MAR channel name: %s\n"
|
||||
" - Product version: %s\n",
|
||||
infoBlock.MARChannelID, infoBlock.productVersion);
|
||||
free((void *)infoBlock.MARChannelID);
|
||||
free((void *)infoBlock.productVersion);
|
||||
}
|
||||
}
|
||||
}
|
||||
printf("\n");
|
||||
/* The fall through from 'T' to 't' is intentional */
|
||||
}
|
||||
case 't':
|
||||
return mar_test(argv[2]);
|
||||
printf("\n");
|
||||
/* The fall through from 'T' to 't' is intentional */
|
||||
}
|
||||
case 't':
|
||||
return mar_test(argv[2]);
|
||||
|
||||
/* Extract a MAR file */
|
||||
case 'x':
|
||||
return mar_extract(argv[2]);
|
||||
case 'x': // Extract a MAR file
|
||||
return mar_extract(argv[2]);
|
||||
|
||||
#ifndef NO_SIGN_VERIFY
|
||||
/* Extract a MAR signature */
|
||||
case 'X':
|
||||
if (sigIndex == -1) {
|
||||
fprintf(stderr, "ERROR: Signature index was not passed.\n");
|
||||
return -1;
|
||||
}
|
||||
if (sigIndex >= MAX_SIGNATURES || sigIndex < -1) {
|
||||
fprintf(stderr, "ERROR: Signature index is out of range: %d.\n",
|
||||
sigIndex);
|
||||
return -1;
|
||||
}
|
||||
return extract_signature(argv[2], sigIndex, argv[3]);
|
||||
case 'X': // Extract a MAR signature
|
||||
if (sigIndex == -1) {
|
||||
fprintf(stderr, "ERROR: Signature index was not passed.\n");
|
||||
return -1;
|
||||
}
|
||||
if (sigIndex >= MAX_SIGNATURES || sigIndex < -1) {
|
||||
fprintf(stderr, "ERROR: Signature index is out of range: %d.\n",
|
||||
sigIndex);
|
||||
return -1;
|
||||
}
|
||||
return extract_signature(argv[2], sigIndex, argv[3]);
|
||||
|
||||
/* Import a MAR signature */
|
||||
case 'I':
|
||||
if (sigIndex == -1) {
|
||||
fprintf(stderr, "ERROR: signature index was not passed.\n");
|
||||
return -1;
|
||||
}
|
||||
if (sigIndex >= MAX_SIGNATURES || sigIndex < -1) {
|
||||
fprintf(stderr, "ERROR: Signature index is out of range: %d.\n",
|
||||
sigIndex);
|
||||
return -1;
|
||||
}
|
||||
if (argc < 5) {
|
||||
print_usage();
|
||||
return -1;
|
||||
}
|
||||
return import_signature(argv[2], sigIndex, argv[3], argv[4]);
|
||||
case 'I': // Import a MAR signature
|
||||
if (sigIndex == -1) {
|
||||
fprintf(stderr, "ERROR: signature index was not passed.\n");
|
||||
return -1;
|
||||
}
|
||||
if (sigIndex >= MAX_SIGNATURES || sigIndex < -1) {
|
||||
fprintf(stderr, "ERROR: Signature index is out of range: %d.\n",
|
||||
sigIndex);
|
||||
return -1;
|
||||
}
|
||||
if (argc < 5) {
|
||||
print_usage();
|
||||
return -1;
|
||||
}
|
||||
return import_signature(argv[2], sigIndex, argv[3], argv[4]);
|
||||
|
||||
case 'v':
|
||||
if (certCount == 0) {
|
||||
print_usage();
|
||||
return -1;
|
||||
}
|
||||
case 'v':
|
||||
if (certCount == 0) {
|
||||
print_usage();
|
||||
return -1;
|
||||
}
|
||||
|
||||
#if (!defined(XP_WIN) && !defined(XP_MACOSX)) || defined(MAR_NSS)
|
||||
if (!NSSConfigDir || certCount == 0) {
|
||||
print_usage();
|
||||
return -1;
|
||||
}
|
||||
if (!NSSConfigDir || certCount == 0) {
|
||||
print_usage();
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (NSSInitCryptoContext(NSSConfigDir)) {
|
||||
fprintf(stderr, "ERROR: Could not initialize crypto library.\n");
|
||||
return -1;
|
||||
}
|
||||
if (NSSInitCryptoContext(NSSConfigDir)) {
|
||||
fprintf(stderr, "ERROR: Could not initialize crypto library.\n");
|
||||
return -1;
|
||||
}
|
||||
#endif
|
||||
|
||||
rv = 0;
|
||||
for (k = 0; k < certCount; ++k) {
|
||||
rv = 0;
|
||||
for (k = 0; k < certCount; ++k) {
|
||||
#if (defined(XP_WIN) || defined(XP_MACOSX)) && !defined(MAR_NSS)
|
||||
rv = mar_read_entire_file(DERFilePaths[k], MAR_MAX_CERT_SIZE,
|
||||
&certBuffers[k], &fileSizes[k]);
|
||||
rv = mar_read_entire_file(DERFilePaths[k], MAR_MAX_CERT_SIZE,
|
||||
&certBuffers[k], &fileSizes[k]);
|
||||
|
||||
if (rv) {
|
||||
fprintf(stderr, "ERROR: could not read file %s", DERFilePaths[k]);
|
||||
break;
|
||||
}
|
||||
#else
|
||||
/* It is somewhat circuitous to look up a CERTCertificate and then pass
|
||||
* in its DER encoding just so we can later re-create that
|
||||
* CERTCertificate to extract the public key out of it. However, by
|
||||
* doing things this way, we maximize the reuse of the
|
||||
* mar_verify_signatures function and also we keep the control flow as
|
||||
* similar as possible between programs and operating systems, at least
|
||||
* for the functions that are critically important to security.
|
||||
*/
|
||||
certs[k] = PK11_FindCertFromNickname(certNames[k], NULL);
|
||||
if (certs[k]) {
|
||||
certBuffers[k] = certs[k]->derCert.data;
|
||||
fileSizes[k] = certs[k]->derCert.len;
|
||||
} else {
|
||||
rv = -1;
|
||||
fprintf(stderr, "ERROR: could not find cert from nickname %s",
|
||||
certNames[k]);
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
if (!rv) {
|
||||
MarFile *mar = mar_open(argv[2]);
|
||||
if (mar) {
|
||||
rv = mar_verify_signatures(mar, certBuffers, fileSizes, certCount);
|
||||
mar_close(mar);
|
||||
} else {
|
||||
fprintf(stderr, "ERROR: Could not open MAR file.\n");
|
||||
rv = -1;
|
||||
}
|
||||
}
|
||||
for (k = 0; k < certCount; ++k) {
|
||||
#if (defined(XP_WIN) || defined(XP_MACOSX)) && !defined(MAR_NSS)
|
||||
free((void *)certBuffers[k]);
|
||||
#else
|
||||
/* certBuffers[k] is owned by certs[k] so don't free it */
|
||||
CERT_DestroyCertificate(certs[k]);
|
||||
#endif
|
||||
}
|
||||
if (rv) {
|
||||
fprintf(stderr, "ERROR: could not read file %s", DERFilePaths[k]);
|
||||
break;
|
||||
/* Determine if the source MAR file has the new fields for signing */
|
||||
int hasSignatureBlock;
|
||||
if (get_mar_file_info(argv[2], &hasSignatureBlock, NULL, NULL, NULL,
|
||||
NULL)) {
|
||||
fprintf(stderr, "ERROR: could not determine if MAR is old or new.\n");
|
||||
} else if (!hasSignatureBlock) {
|
||||
fprintf(stderr,
|
||||
"ERROR: The MAR file is in the old format so has"
|
||||
" no signature to verify.\n");
|
||||
}
|
||||
}
|
||||
#else
|
||||
/* It is somewhat circuitous to look up a CERTCertificate and then pass
|
||||
* in its DER encoding just so we can later re-create that
|
||||
* CERTCertificate to extract the public key out of it. However, by doing
|
||||
* things this way, we maximize the reuse of the mar_verify_signatures
|
||||
* function and also we keep the control flow as similar as possible
|
||||
* between programs and operating systems, at least for the functions
|
||||
* that are critically important to security.
|
||||
*/
|
||||
certs[k] = PK11_FindCertFromNickname(certNames[k], NULL);
|
||||
if (certs[k]) {
|
||||
certBuffers[k] = certs[k]->derCert.data;
|
||||
fileSizes[k] = certs[k]->derCert.len;
|
||||
} else {
|
||||
rv = -1;
|
||||
fprintf(stderr, "ERROR: could not find cert from nickname %s", certNames[k]);
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
if (!rv) {
|
||||
MarFile *mar = mar_open(argv[2]);
|
||||
if (mar) {
|
||||
rv = mar_verify_signatures(mar, certBuffers, fileSizes, certCount);
|
||||
mar_close(mar);
|
||||
} else {
|
||||
fprintf(stderr, "ERROR: Could not open MAR file.\n");
|
||||
rv = -1;
|
||||
}
|
||||
}
|
||||
for (k = 0; k < certCount; ++k) {
|
||||
#if (defined(XP_WIN) || defined(XP_MACOSX)) && !defined(MAR_NSS)
|
||||
free((void*)certBuffers[k]);
|
||||
#else
|
||||
/* certBuffers[k] is owned by certs[k] so don't free it */
|
||||
CERT_DestroyCertificate(certs[k]);
|
||||
#endif
|
||||
}
|
||||
if (rv) {
|
||||
/* Determine if the source MAR file has the new fields for signing */
|
||||
int hasSignatureBlock;
|
||||
if (get_mar_file_info(argv[2], &hasSignatureBlock,
|
||||
NULL, NULL, NULL, NULL)) {
|
||||
fprintf(stderr, "ERROR: could not determine if MAR is old or new.\n");
|
||||
} else if (!hasSignatureBlock) {
|
||||
fprintf(stderr, "ERROR: The MAR file is in the old format so has"
|
||||
" no signature to verify.\n");
|
||||
}
|
||||
}
|
||||
#if (!defined(XP_WIN) && !defined(XP_MACOSX)) || defined(MAR_NSS)
|
||||
(void) NSS_Shutdown();
|
||||
(void)NSS_Shutdown();
|
||||
#endif
|
||||
return rv ? -1 : 0;
|
||||
return rv ? -1 : 0;
|
||||
|
||||
case 's':
|
||||
if (!NSSConfigDir || certCount == 0 || argc < 4) {
|
||||
print_usage();
|
||||
return -1;
|
||||
}
|
||||
return mar_repackage_and_sign(NSSConfigDir, certNames, certCount,
|
||||
argv[2], argv[3]);
|
||||
case 's':
|
||||
if (!NSSConfigDir || certCount == 0 || argc < 4) {
|
||||
print_usage();
|
||||
return -1;
|
||||
}
|
||||
return mar_repackage_and_sign(NSSConfigDir, certNames, certCount, argv[2],
|
||||
argv[3]);
|
||||
|
||||
case 'r':
|
||||
return strip_signature_block(argv[2], argv[3]);
|
||||
case 'r':
|
||||
return strip_signature_block(argv[2], argv[3]);
|
||||
#endif /* endif NO_SIGN_VERIFY disabled */
|
||||
|
||||
default:
|
||||
print_usage();
|
||||
return -1;
|
||||
default:
|
||||
print_usage();
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
@ -11,65 +11,60 @@
|
||||
// We declare the necessary parts of the Security Transforms API here since
|
||||
// we're building with the 10.6 SDK, which doesn't know about Security
|
||||
// Transforms.
|
||||
#ifdef __cplusplus
|
||||
#if defined(__cplusplus)
|
||||
extern "C" {
|
||||
#endif
|
||||
const CFStringRef kSecTransformInputAttributeName = CFSTR("INPUT");
|
||||
typedef CFTypeRef SecTransformRef;
|
||||
typedef struct OpaqueSecKeyRef* SecKeyRef;
|
||||
const CFStringRef kSecTransformInputAttributeName = CFSTR("INPUT");
|
||||
typedef CFTypeRef SecTransformRef;
|
||||
typedef struct OpaqueSecKeyRef* SecKeyRef;
|
||||
|
||||
typedef SecTransformRef (*SecTransformCreateReadTransformWithReadStreamFunc)
|
||||
(CFReadStreamRef inputStream);
|
||||
SecTransformCreateReadTransformWithReadStreamFunc
|
||||
typedef SecTransformRef (*SecTransformCreateReadTransformWithReadStreamFunc)(
|
||||
CFReadStreamRef inputStream);
|
||||
SecTransformCreateReadTransformWithReadStreamFunc
|
||||
SecTransformCreateReadTransformWithReadStreamPtr = NULL;
|
||||
typedef CFTypeRef (*SecTransformExecuteFunc)(SecTransformRef transform,
|
||||
CFErrorRef* error);
|
||||
SecTransformExecuteFunc SecTransformExecutePtr = NULL;
|
||||
typedef SecTransformRef (*SecVerifyTransformCreateFunc)(SecKeyRef key,
|
||||
CFDataRef signature,
|
||||
CFErrorRef* error);
|
||||
SecVerifyTransformCreateFunc SecVerifyTransformCreatePtr = NULL;
|
||||
typedef Boolean (*SecTransformSetAttributeFunc)(SecTransformRef transform,
|
||||
CFStringRef key,
|
||||
CFTypeRef value,
|
||||
CFErrorRef* error);
|
||||
SecTransformSetAttributeFunc SecTransformSetAttributePtr = NULL;
|
||||
#ifdef __cplusplus
|
||||
typedef CFTypeRef (*SecTransformExecuteFunc)(SecTransformRef transform,
|
||||
CFErrorRef* error);
|
||||
SecTransformExecuteFunc SecTransformExecutePtr = NULL;
|
||||
typedef SecTransformRef (*SecVerifyTransformCreateFunc)(SecKeyRef key,
|
||||
CFDataRef signature,
|
||||
CFErrorRef* error);
|
||||
SecVerifyTransformCreateFunc SecVerifyTransformCreatePtr = NULL;
|
||||
typedef Boolean (*SecTransformSetAttributeFunc)(SecTransformRef transform,
|
||||
CFStringRef key,
|
||||
CFTypeRef value,
|
||||
CFErrorRef* error);
|
||||
SecTransformSetAttributeFunc SecTransformSetAttributePtr = NULL;
|
||||
#if defined(__cplusplus)
|
||||
}
|
||||
#endif
|
||||
|
||||
CryptoX_Result
|
||||
CryptoMac_InitCryptoProvider()
|
||||
{
|
||||
CryptoX_Result CryptoMac_InitCryptoProvider() {
|
||||
if (!SecTransformCreateReadTransformWithReadStreamPtr) {
|
||||
SecTransformCreateReadTransformWithReadStreamPtr =
|
||||
(SecTransformCreateReadTransformWithReadStreamFunc)
|
||||
dlsym(RTLD_DEFAULT, "SecTransformCreateReadTransformWithReadStream");
|
||||
(SecTransformCreateReadTransformWithReadStreamFunc)dlsym(
|
||||
RTLD_DEFAULT, "SecTransformCreateReadTransformWithReadStream");
|
||||
}
|
||||
if (!SecTransformExecutePtr) {
|
||||
SecTransformExecutePtr = (SecTransformExecuteFunc)
|
||||
dlsym(RTLD_DEFAULT, "SecTransformExecute");
|
||||
SecTransformExecutePtr =
|
||||
(SecTransformExecuteFunc)dlsym(RTLD_DEFAULT, "SecTransformExecute");
|
||||
}
|
||||
if (!SecVerifyTransformCreatePtr) {
|
||||
SecVerifyTransformCreatePtr = (SecVerifyTransformCreateFunc)
|
||||
dlsym(RTLD_DEFAULT, "SecVerifyTransformCreate");
|
||||
SecVerifyTransformCreatePtr = (SecVerifyTransformCreateFunc)dlsym(
|
||||
RTLD_DEFAULT, "SecVerifyTransformCreate");
|
||||
}
|
||||
if (!SecTransformSetAttributePtr) {
|
||||
SecTransformSetAttributePtr = (SecTransformSetAttributeFunc)
|
||||
dlsym(RTLD_DEFAULT, "SecTransformSetAttribute");
|
||||
SecTransformSetAttributePtr = (SecTransformSetAttributeFunc)dlsym(
|
||||
RTLD_DEFAULT, "SecTransformSetAttribute");
|
||||
}
|
||||
if (!SecTransformCreateReadTransformWithReadStreamPtr ||
|
||||
!SecTransformExecutePtr ||
|
||||
!SecVerifyTransformCreatePtr ||
|
||||
!SecTransformExecutePtr || !SecVerifyTransformCreatePtr ||
|
||||
!SecTransformSetAttributePtr) {
|
||||
return CryptoX_Error;
|
||||
}
|
||||
return CryptoX_Success;
|
||||
}
|
||||
|
||||
CryptoX_Result
|
||||
CryptoMac_VerifyBegin(CryptoX_SignatureHandle* aInputData)
|
||||
{
|
||||
CryptoX_Result CryptoMac_VerifyBegin(CryptoX_SignatureHandle* aInputData) {
|
||||
if (!aInputData) {
|
||||
return CryptoX_Error;
|
||||
}
|
||||
@ -83,10 +78,8 @@ CryptoMac_VerifyBegin(CryptoX_SignatureHandle* aInputData)
|
||||
return CryptoX_Success;
|
||||
}
|
||||
|
||||
CryptoX_Result
|
||||
CryptoMac_VerifyUpdate(CryptoX_SignatureHandle* aInputData, void* aBuf,
|
||||
unsigned int aLen)
|
||||
{
|
||||
CryptoX_Result CryptoMac_VerifyUpdate(CryptoX_SignatureHandle* aInputData,
|
||||
void* aBuf, unsigned int aLen) {
|
||||
if (aLen == 0) {
|
||||
return CryptoX_Success;
|
||||
}
|
||||
@ -100,31 +93,26 @@ CryptoMac_VerifyUpdate(CryptoX_SignatureHandle* aInputData, void* aBuf,
|
||||
return CryptoX_Success;
|
||||
}
|
||||
|
||||
CryptoX_Result
|
||||
CryptoMac_LoadPublicKey(const unsigned char* aCertData,
|
||||
unsigned int aDataSize,
|
||||
CryptoX_PublicKey* aPublicKey)
|
||||
{
|
||||
CryptoX_Result CryptoMac_LoadPublicKey(const unsigned char* aCertData,
|
||||
unsigned int aDataSize,
|
||||
CryptoX_PublicKey* aPublicKey) {
|
||||
if (!aCertData || aDataSize == 0 || !aPublicKey) {
|
||||
return CryptoX_Error;
|
||||
}
|
||||
*aPublicKey = NULL;
|
||||
CFDataRef certData = CFDataCreate(kCFAllocatorDefault,
|
||||
aCertData,
|
||||
aDataSize);
|
||||
CFDataRef certData = CFDataCreate(kCFAllocatorDefault, aCertData, aDataSize);
|
||||
if (!certData) {
|
||||
return CryptoX_Error;
|
||||
}
|
||||
|
||||
SecCertificateRef cert = SecCertificateCreateWithData(kCFAllocatorDefault,
|
||||
certData);
|
||||
SecCertificateRef cert =
|
||||
SecCertificateCreateWithData(kCFAllocatorDefault, certData);
|
||||
CFRelease(certData);
|
||||
if (!cert) {
|
||||
return CryptoX_Error;
|
||||
}
|
||||
|
||||
OSStatus status = SecCertificateCopyPublicKey(cert,
|
||||
(SecKeyRef*)aPublicKey);
|
||||
OSStatus status = SecCertificateCopyPublicKey(cert, (SecKeyRef*)aPublicKey);
|
||||
CFRelease(cert);
|
||||
if (status != 0) {
|
||||
return CryptoX_Error;
|
||||
@ -133,28 +121,24 @@ CryptoMac_LoadPublicKey(const unsigned char* aCertData,
|
||||
return CryptoX_Success;
|
||||
}
|
||||
|
||||
CryptoX_Result
|
||||
CryptoMac_VerifySignature(CryptoX_SignatureHandle* aInputData,
|
||||
CryptoX_PublicKey* aPublicKey,
|
||||
const unsigned char* aSignature,
|
||||
unsigned int aSignatureLen)
|
||||
{
|
||||
CryptoX_Result CryptoMac_VerifySignature(CryptoX_SignatureHandle* aInputData,
|
||||
CryptoX_PublicKey* aPublicKey,
|
||||
const unsigned char* aSignature,
|
||||
unsigned int aSignatureLen) {
|
||||
if (!aInputData || !*aInputData || !aPublicKey || !*aPublicKey ||
|
||||
!aSignature || aSignatureLen == 0) {
|
||||
return CryptoX_Error;
|
||||
}
|
||||
|
||||
CFDataRef signatureData = CFDataCreate(kCFAllocatorDefault,
|
||||
aSignature, aSignatureLen);
|
||||
CFDataRef signatureData =
|
||||
CFDataCreate(kCFAllocatorDefault, aSignature, aSignatureLen);
|
||||
if (!signatureData) {
|
||||
return CryptoX_Error;
|
||||
}
|
||||
|
||||
CFErrorRef error;
|
||||
SecTransformRef verifier =
|
||||
SecVerifyTransformCreatePtr((SecKeyRef)*aPublicKey,
|
||||
signatureData,
|
||||
&error);
|
||||
SecTransformRef verifier = SecVerifyTransformCreatePtr((SecKeyRef)*aPublicKey,
|
||||
signatureData, &error);
|
||||
if (!verifier || error) {
|
||||
if (error) {
|
||||
CFRelease(error);
|
||||
@ -163,9 +147,7 @@ CryptoMac_VerifySignature(CryptoX_SignatureHandle* aInputData,
|
||||
return CryptoX_Error;
|
||||
}
|
||||
|
||||
SecTransformSetAttributePtr(verifier,
|
||||
kSecDigestTypeAttribute,
|
||||
kSecDigestSHA2,
|
||||
SecTransformSetAttributePtr(verifier, kSecDigestTypeAttribute, kSecDigestSHA2,
|
||||
&error);
|
||||
if (error) {
|
||||
CFRelease(error);
|
||||
@ -175,10 +157,9 @@ CryptoMac_VerifySignature(CryptoX_SignatureHandle* aInputData,
|
||||
}
|
||||
|
||||
int digestLength = 384;
|
||||
CFNumberRef dLen = CFNumberCreate(kCFAllocatorDefault, kCFNumberIntType, &digestLength);
|
||||
SecTransformSetAttributePtr(verifier,
|
||||
kSecDigestLengthAttribute,
|
||||
dLen,
|
||||
CFNumberRef dLen =
|
||||
CFNumberCreate(kCFAllocatorDefault, kCFNumberIntType, &digestLength);
|
||||
SecTransformSetAttributePtr(verifier, kSecDigestLengthAttribute, dLen,
|
||||
&error);
|
||||
CFRelease(dLen);
|
||||
if (error) {
|
||||
@ -188,10 +169,8 @@ CryptoMac_VerifySignature(CryptoX_SignatureHandle* aInputData,
|
||||
return CryptoX_Error;
|
||||
}
|
||||
|
||||
SecTransformSetAttributePtr(verifier,
|
||||
kSecTransformInputAttributeName,
|
||||
(CFDataRef)*aInputData,
|
||||
&error);
|
||||
SecTransformSetAttributePtr(verifier, kSecTransformInputAttributeName,
|
||||
(CFDataRef)*aInputData, &error);
|
||||
if (error) {
|
||||
CFRelease(error);
|
||||
CFRelease(signatureData);
|
||||
@ -219,9 +198,7 @@ CryptoMac_VerifySignature(CryptoX_SignatureHandle* aInputData,
|
||||
return result;
|
||||
}
|
||||
|
||||
void
|
||||
CryptoMac_FreeSignatureHandle(CryptoX_SignatureHandle* aInputData)
|
||||
{
|
||||
void CryptoMac_FreeSignatureHandle(CryptoX_SignatureHandle* aInputData) {
|
||||
if (!aInputData || !*aInputData) {
|
||||
return;
|
||||
}
|
||||
@ -232,9 +209,7 @@ CryptoMac_FreeSignatureHandle(CryptoX_SignatureHandle* aInputData)
|
||||
CFRelease(inputData);
|
||||
}
|
||||
|
||||
void
|
||||
CryptoMac_FreePublicKey(CryptoX_PublicKey* aPublicKey)
|
||||
{
|
||||
void CryptoMac_FreePublicKey(CryptoX_PublicKey* aPublicKey) {
|
||||
if (!aPublicKey || !*aPublicKey) {
|
||||
return;
|
||||
}
|
||||
|
@ -21,13 +21,12 @@
|
||||
* @param certDataSize The size of certData.
|
||||
* @param publicKey Out parameter for the public key to use.
|
||||
* @return CryptoX_Success on success, CryptoX_Error on error.
|
||||
*/
|
||||
CryptoX_Result
|
||||
NSS_LoadPublicKey(const unsigned char *certData, unsigned int certDataSize,
|
||||
SECKEYPublicKey **publicKey)
|
||||
{
|
||||
CERTCertificate * cert;
|
||||
SECItem certDataItem = { siBuffer, (unsigned char*) certData, certDataSize };
|
||||
*/
|
||||
CryptoX_Result NSS_LoadPublicKey(const unsigned char *certData,
|
||||
unsigned int certDataSize,
|
||||
SECKEYPublicKey **publicKey) {
|
||||
CERTCertificate *cert;
|
||||
SECItem certDataItem = {siBuffer, (unsigned char *)certData, certDataSize};
|
||||
|
||||
if (!certData || !publicKey) {
|
||||
return CryptoX_Error;
|
||||
@ -48,10 +47,8 @@ NSS_LoadPublicKey(const unsigned char *certData, unsigned int certDataSize,
|
||||
return CryptoX_Success;
|
||||
}
|
||||
|
||||
CryptoX_Result
|
||||
NSS_VerifyBegin(VFYContext **ctx,
|
||||
SECKEYPublicKey * const *publicKey)
|
||||
{
|
||||
CryptoX_Result NSS_VerifyBegin(VFYContext **ctx,
|
||||
SECKEYPublicKey *const *publicKey) {
|
||||
SECStatus status;
|
||||
if (!ctx || !publicKey || !*publicKey) {
|
||||
return CryptoX_Error;
|
||||
@ -82,12 +79,10 @@ NSS_VerifyBegin(VFYContext **ctx,
|
||||
* @param signature The signature to match.
|
||||
* @param signatureLen The length of the signature.
|
||||
* @return CryptoX_Success on success, CryptoX_Error on error.
|
||||
*/
|
||||
CryptoX_Result
|
||||
NSS_VerifySignature(VFYContext * const *ctx,
|
||||
const unsigned char *signature,
|
||||
unsigned int signatureLen)
|
||||
{
|
||||
*/
|
||||
CryptoX_Result NSS_VerifySignature(VFYContext *const *ctx,
|
||||
const unsigned char *signature,
|
||||
unsigned int signatureLen) {
|
||||
SECItem signedItem;
|
||||
SECStatus status;
|
||||
if (!ctx || !signature || !*ctx) {
|
||||
@ -95,7 +90,7 @@ NSS_VerifySignature(VFYContext * const *ctx,
|
||||
}
|
||||
|
||||
signedItem.len = signatureLen;
|
||||
signedItem.data = (unsigned char*)signature;
|
||||
signedItem.data = (unsigned char *)signature;
|
||||
status = VFY_EndWithSignature(*ctx, &signedItem);
|
||||
return SECSuccess == status ? CryptoX_Success : CryptoX_Error;
|
||||
}
|
||||
@ -109,19 +104,16 @@ NSS_VerifySignature(VFYContext * const *ctx,
|
||||
* @param signature The signature to check.
|
||||
* @param signatureLen The length of the signature.
|
||||
* @return CryptoX_Success on success, CryptoX_Error on error.
|
||||
*/
|
||||
CryptoX_Result
|
||||
CryptoAPI_VerifySignature(HCRYPTHASH *hash,
|
||||
HCRYPTKEY *pubKey,
|
||||
const BYTE *signature,
|
||||
DWORD signatureLen)
|
||||
{
|
||||
*/
|
||||
CryptoX_Result CryptoAPI_VerifySignature(HCRYPTHASH *hash, HCRYPTKEY *pubKey,
|
||||
const BYTE *signature,
|
||||
DWORD signatureLen) {
|
||||
DWORD i;
|
||||
BOOL result;
|
||||
/* Windows APIs expect the bytes in the signature to be in little-endian
|
||||
* order, but we write the signature in big-endian order. Other APIs like
|
||||
* NSS and OpenSSL expect big-endian order.
|
||||
*/
|
||||
/* Windows APIs expect the bytes in the signature to be in little-endian
|
||||
* order, but we write the signature in big-endian order. Other APIs like
|
||||
* NSS and OpenSSL expect big-endian order.
|
||||
*/
|
||||
BYTE *signatureReversed;
|
||||
if (!hash || !pubKey || !signature || signatureLen < 1) {
|
||||
return CryptoX_Error;
|
||||
@ -135,8 +127,8 @@ CryptoAPI_VerifySignature(HCRYPTHASH *hash,
|
||||
for (i = 0; i < signatureLen; i++) {
|
||||
signatureReversed[i] = signature[signatureLen - 1 - i];
|
||||
}
|
||||
result = CryptVerifySignature(*hash, signatureReversed,
|
||||
signatureLen, *pubKey, NULL, 0);
|
||||
result = CryptVerifySignature(*hash, signatureReversed, signatureLen, *pubKey,
|
||||
NULL, 0);
|
||||
free(signatureReversed);
|
||||
return result ? CryptoX_Success : CryptoX_Error;
|
||||
}
|
||||
@ -149,13 +141,10 @@ CryptoAPI_VerifySignature(HCRYPTHASH *hash,
|
||||
* @param sizeOfCertData The size of the certData buffer
|
||||
* @param certStore Pointer to the handle of the certificate store to use
|
||||
* @param CryptoX_Success on success
|
||||
*/
|
||||
CryptoX_Result
|
||||
CryptoAPI_LoadPublicKey(HCRYPTPROV provider,
|
||||
BYTE *certData,
|
||||
DWORD sizeOfCertData,
|
||||
HCRYPTKEY *publicKey)
|
||||
{
|
||||
*/
|
||||
CryptoX_Result CryptoAPI_LoadPublicKey(HCRYPTPROV provider, BYTE *certData,
|
||||
DWORD sizeOfCertData,
|
||||
HCRYPTKEY *publicKey) {
|
||||
CRYPT_DATA_BLOB blob;
|
||||
CERT_CONTEXT *context;
|
||||
if (!provider || !certData || !publicKey) {
|
||||
@ -166,16 +155,14 @@ CryptoAPI_LoadPublicKey(HCRYPTPROV provider,
|
||||
blob.pbData = certData;
|
||||
if (!CryptQueryObject(CERT_QUERY_OBJECT_BLOB, &blob,
|
||||
CERT_QUERY_CONTENT_FLAG_CERT,
|
||||
CERT_QUERY_FORMAT_FLAG_BINARY,
|
||||
0, NULL, NULL, NULL,
|
||||
CERT_QUERY_FORMAT_FLAG_BINARY, 0, NULL, NULL, NULL,
|
||||
NULL, NULL, (const void **)&context)) {
|
||||
return CryptoX_Error;
|
||||
}
|
||||
|
||||
if (!CryptImportPublicKeyInfo(provider,
|
||||
PKCS_7_ASN_ENCODING | X509_ASN_ENCODING,
|
||||
&context->pCertInfo->SubjectPublicKeyInfo,
|
||||
publicKey)) {
|
||||
if (!CryptImportPublicKeyInfo(
|
||||
provider, PKCS_7_ASN_ENCODING | X509_ASN_ENCODING,
|
||||
&context->pCertInfo->SubjectPublicKeyInfo, publicKey)) {
|
||||
CertFreeCertificateContext(context);
|
||||
return CryptoX_Error;
|
||||
}
|
||||
@ -185,38 +172,24 @@ CryptoAPI_LoadPublicKey(HCRYPTPROV provider,
|
||||
}
|
||||
|
||||
/* Try to acquire context in this way:
|
||||
* 1. Enhanced provider without creating a new key set
|
||||
* 2. Enhanced provider with creating a new key set
|
||||
* 3. Default provider without creating a new key set
|
||||
* 4. Default provider without creating a new key set
|
||||
* #2 and #4 should not be needed because of the CRYPT_VERIFYCONTEXT,
|
||||
* but we add it just in case.
|
||||
*
|
||||
* @param provider Out parameter containing the provider handle.
|
||||
* @return CryptoX_Success on success, CryptoX_Error on error.
|
||||
* 1. Enhanced provider without creating a new key set
|
||||
* 2. Enhanced provider with creating a new key set
|
||||
* 3. Default provider without creating a new key set
|
||||
* 4. Default provider without creating a new key set
|
||||
* #2 and #4 should not be needed because of the CRYPT_VERIFYCONTEXT,
|
||||
* but we add it just in case.
|
||||
*
|
||||
* @param provider Out parameter containing the provider handle.
|
||||
* @return CryptoX_Success on success, CryptoX_Error on error.
|
||||
*/
|
||||
CryptoX_Result
|
||||
CryptoAPI_InitCryptoContext(HCRYPTPROV *provider)
|
||||
{
|
||||
if (!CryptAcquireContext(provider,
|
||||
NULL,
|
||||
MS_ENH_RSA_AES_PROV,
|
||||
PROV_RSA_AES,
|
||||
CryptoX_Result CryptoAPI_InitCryptoContext(HCRYPTPROV *provider) {
|
||||
if (!CryptAcquireContext(provider, NULL, MS_ENH_RSA_AES_PROV, PROV_RSA_AES,
|
||||
CRYPT_VERIFYCONTEXT)) {
|
||||
if (!CryptAcquireContext(provider,
|
||||
NULL,
|
||||
MS_ENH_RSA_AES_PROV,
|
||||
PROV_RSA_AES,
|
||||
if (!CryptAcquireContext(provider, NULL, MS_ENH_RSA_AES_PROV, PROV_RSA_AES,
|
||||
CRYPT_NEWKEYSET | CRYPT_VERIFYCONTEXT)) {
|
||||
if (!CryptAcquireContext(provider,
|
||||
NULL,
|
||||
NULL,
|
||||
PROV_RSA_AES,
|
||||
if (!CryptAcquireContext(provider, NULL, NULL, PROV_RSA_AES,
|
||||
CRYPT_VERIFYCONTEXT)) {
|
||||
if (!CryptAcquireContext(provider,
|
||||
NULL,
|
||||
NULL,
|
||||
PROV_RSA_AES,
|
||||
if (!CryptAcquireContext(provider, NULL, NULL, PROV_RSA_AES,
|
||||
CRYPT_NEWKEYSET | CRYPT_VERIFYCONTEXT)) {
|
||||
*provider = CryptoX_InvalidHandleValue;
|
||||
return CryptoX_Error;
|
||||
@ -228,37 +201,32 @@ CryptoAPI_InitCryptoContext(HCRYPTPROV *provider)
|
||||
}
|
||||
|
||||
/**
|
||||
* Begins a signature verification hash context
|
||||
*
|
||||
* @param provider The crypt provider to use
|
||||
* @param hash Out parameter for a handle to the hash context
|
||||
* @return CryptoX_Success on success, CryptoX_Error on error.
|
||||
*/
|
||||
CryptoX_Result
|
||||
CryptoAPI_VerifyBegin(HCRYPTPROV provider, HCRYPTHASH* hash)
|
||||
{
|
||||
* Begins a signature verification hash context
|
||||
*
|
||||
* @param provider The crypt provider to use
|
||||
* @param hash Out parameter for a handle to the hash context
|
||||
* @return CryptoX_Success on success, CryptoX_Error on error.
|
||||
*/
|
||||
CryptoX_Result CryptoAPI_VerifyBegin(HCRYPTPROV provider, HCRYPTHASH *hash) {
|
||||
BOOL result;
|
||||
if (!provider || !hash) {
|
||||
return CryptoX_Error;
|
||||
}
|
||||
|
||||
*hash = (HCRYPTHASH)NULL;
|
||||
result = CryptCreateHash(provider, CALG_SHA_384,
|
||||
0, 0, hash);
|
||||
result = CryptCreateHash(provider, CALG_SHA_384, 0, 0, hash);
|
||||
return result ? CryptoX_Success : CryptoX_Error;
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates a signature verification hash context
|
||||
*
|
||||
* @param hash The hash context to udpate
|
||||
* @param buf The buffer to update the hash context with
|
||||
* @param len The size of the passed in buffer
|
||||
* @return CryptoX_Success on success, CryptoX_Error on error.
|
||||
*/
|
||||
CryptoX_Result
|
||||
CryptoAPI_VerifyUpdate(HCRYPTHASH* hash, BYTE *buf, DWORD len)
|
||||
{
|
||||
* Updates a signature verification hash context
|
||||
*
|
||||
* @param hash The hash context to udpate
|
||||
* @param buf The buffer to update the hash context with
|
||||
* @param len The size of the passed in buffer
|
||||
* @return CryptoX_Success on success, CryptoX_Error on error.
|
||||
*/
|
||||
CryptoX_Result CryptoAPI_VerifyUpdate(HCRYPTHASH *hash, BYTE *buf, DWORD len) {
|
||||
BOOL result;
|
||||
if (!hash || !buf) {
|
||||
return CryptoX_Error;
|
||||
|
@ -20,7 +20,7 @@
|
||||
#include "cryptohi.h"
|
||||
|
||||
#define CryptoX_InvalidHandleValue NULL
|
||||
#define CryptoX_ProviderHandle void*
|
||||
#define CryptoX_ProviderHandle void *
|
||||
#define CryptoX_SignatureHandle VFYContext *
|
||||
#define CryptoX_PublicKey SECKEYPublicKey *
|
||||
#define CryptoX_Certificate CERTCertificate *
|
||||
@ -28,42 +28,39 @@
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
CryptoX_Result NSS_LoadPublicKey(const unsigned char* certData,
|
||||
CryptoX_Result NSS_LoadPublicKey(const unsigned char *certData,
|
||||
unsigned int certDataSize,
|
||||
SECKEYPublicKey** publicKey);
|
||||
SECKEYPublicKey **publicKey);
|
||||
CryptoX_Result NSS_VerifyBegin(VFYContext **ctx,
|
||||
SECKEYPublicKey * const *publicKey);
|
||||
CryptoX_Result NSS_VerifySignature(VFYContext * const *ctx ,
|
||||
SECKEYPublicKey *const *publicKey);
|
||||
CryptoX_Result NSS_VerifySignature(VFYContext *const *ctx,
|
||||
const unsigned char *signature,
|
||||
unsigned int signatureLen);
|
||||
#ifdef __cplusplus
|
||||
} // extern "C"
|
||||
} // extern "C"
|
||||
#endif
|
||||
|
||||
#define CryptoX_InitCryptoProvider(CryptoHandle) \
|
||||
CryptoX_Success
|
||||
#define CryptoX_InitCryptoProvider(CryptoHandle) CryptoX_Success
|
||||
#define CryptoX_VerifyBegin(CryptoHandle, SignatureHandle, PublicKey) \
|
||||
NSS_VerifyBegin(SignatureHandle, PublicKey)
|
||||
#define CryptoX_FreeSignatureHandle(SignatureHandle) \
|
||||
VFY_DestroyContext(*SignatureHandle, PR_TRUE)
|
||||
#define CryptoX_VerifyUpdate(SignatureHandle, buf, len) \
|
||||
VFY_Update(*SignatureHandle, (const unsigned char*)(buf), len)
|
||||
VFY_Update(*SignatureHandle, (const unsigned char *)(buf), len)
|
||||
#define CryptoX_LoadPublicKey(CryptoHandle, certData, dataSize, publicKey) \
|
||||
NSS_LoadPublicKey(certData, dataSize, publicKey)
|
||||
#define CryptoX_VerifySignature(hash, publicKey, signedData, len) \
|
||||
NSS_VerifySignature(hash, (const unsigned char *)(signedData), len)
|
||||
#define CryptoX_FreePublicKey(key) \
|
||||
SECKEY_DestroyPublicKey(*key)
|
||||
#define CryptoX_FreeCertificate(cert) \
|
||||
CERT_DestroyCertificate(*cert)
|
||||
#define CryptoX_FreePublicKey(key) SECKEY_DestroyPublicKey(*key)
|
||||
#define CryptoX_FreeCertificate(cert) CERT_DestroyCertificate(*cert)
|
||||
|
||||
#elif XP_MACOSX
|
||||
|
||||
#define CryptoX_InvalidHandleValue NULL
|
||||
#define CryptoX_ProviderHandle void*
|
||||
#define CryptoX_SignatureHandle void*
|
||||
#define CryptoX_PublicKey void*
|
||||
#define CryptoX_Certificate void*
|
||||
#define CryptoX_ProviderHandle void *
|
||||
#define CryptoX_SignatureHandle void *
|
||||
#define CryptoX_PublicKey void *
|
||||
#define CryptoX_Certificate void *
|
||||
|
||||
// Forward-declare Objective-C functions implemented in MacVerifyCrypto.mm.
|
||||
#ifdef __cplusplus
|
||||
@ -83,7 +80,7 @@ CryptoX_Result CryptoMac_VerifySignature(CryptoX_SignatureHandle* aInputData,
|
||||
void CryptoMac_FreeSignatureHandle(CryptoX_SignatureHandle* aInputData);
|
||||
void CryptoMac_FreePublicKey(CryptoX_PublicKey* aPublicKey);
|
||||
#ifdef __cplusplus
|
||||
} // extern "C"
|
||||
} // extern "C"
|
||||
#endif
|
||||
|
||||
#define CryptoX_InitCryptoProvider(aProviderHandle) \
|
||||
@ -93,15 +90,14 @@ void CryptoMac_FreePublicKey(CryptoX_PublicKey* aPublicKey);
|
||||
#define CryptoX_VerifyUpdate(aInputData, aBuf, aLen) \
|
||||
CryptoMac_VerifyUpdate(aInputData, aBuf, aLen)
|
||||
#define CryptoX_LoadPublicKey(aProviderHandle, aCertData, aDataSize, \
|
||||
aPublicKey) \
|
||||
aPublicKey) \
|
||||
CryptoMac_LoadPublicKey(aCertData, aDataSize, aPublicKey)
|
||||
#define CryptoX_VerifySignature(aInputData, aPublicKey, aSignature, \
|
||||
aSignatureLen) \
|
||||
aSignatureLen) \
|
||||
CryptoMac_VerifySignature(aInputData, aPublicKey, aSignature, aSignatureLen)
|
||||
#define CryptoX_FreeSignatureHandle(aInputData) \
|
||||
CryptoMac_FreeSignatureHandle(aInputData)
|
||||
#define CryptoX_FreePublicKey(aPublicKey) \
|
||||
CryptoMac_FreePublicKey(aPublicKey)
|
||||
#define CryptoX_FreePublicKey(aPublicKey) CryptoMac_FreePublicKey(aPublicKey)
|
||||
#define CryptoX_FreeCertificate(aCertificate)
|
||||
|
||||
#elif defined(XP_WIN)
|
||||
@ -110,15 +106,12 @@ void CryptoMac_FreePublicKey(CryptoX_PublicKey* aPublicKey);
|
||||
#include <wincrypt.h>
|
||||
|
||||
CryptoX_Result CryptoAPI_InitCryptoContext(HCRYPTPROV *provider);
|
||||
CryptoX_Result CryptoAPI_LoadPublicKey(HCRYPTPROV hProv,
|
||||
BYTE *certData,
|
||||
CryptoX_Result CryptoAPI_LoadPublicKey(HCRYPTPROV hProv, BYTE *certData,
|
||||
DWORD sizeOfCertData,
|
||||
HCRYPTKEY *publicKey);
|
||||
CryptoX_Result CryptoAPI_VerifyBegin(HCRYPTPROV provider, HCRYPTHASH* hash);
|
||||
CryptoX_Result CryptoAPI_VerifyUpdate(HCRYPTHASH* hash,
|
||||
BYTE *buf, DWORD len);
|
||||
CryptoX_Result CryptoAPI_VerifySignature(HCRYPTHASH *hash,
|
||||
HCRYPTKEY *pubKey,
|
||||
CryptoX_Result CryptoAPI_VerifyBegin(HCRYPTPROV provider, HCRYPTHASH *hash);
|
||||
CryptoX_Result CryptoAPI_VerifyUpdate(HCRYPTHASH *hash, BYTE *buf, DWORD len);
|
||||
CryptoX_Result CryptoAPI_VerifySignature(HCRYPTHASH *hash, HCRYPTKEY *pubKey,
|
||||
const BYTE *signature,
|
||||
DWORD signatureLen);
|
||||
|
||||
@ -135,11 +128,10 @@ CryptoX_Result CryptoAPI_VerifySignature(HCRYPTHASH *hash,
|
||||
#define CryptoX_VerifyUpdate(SignatureHandle, buf, len) \
|
||||
CryptoAPI_VerifyUpdate(SignatureHandle, (BYTE *)(buf), len)
|
||||
#define CryptoX_LoadPublicKey(CryptoHandle, certData, dataSize, publicKey) \
|
||||
CryptoAPI_LoadPublicKey(CryptoHandle, (BYTE*)(certData), dataSize, publicKey)
|
||||
CryptoAPI_LoadPublicKey(CryptoHandle, (BYTE *)(certData), dataSize, publicKey)
|
||||
#define CryptoX_VerifySignature(hash, publicKey, signedData, len) \
|
||||
CryptoAPI_VerifySignature(hash, publicKey, signedData, len)
|
||||
#define CryptoX_FreePublicKey(key) \
|
||||
CryptDestroyKey(*(key))
|
||||
#define CryptoX_FreePublicKey(key) CryptDestroyKey(*(key))
|
||||
#define CryptoX_FreeCertificate(cert) \
|
||||
CertCloseStore(*(cert), CERT_CLOSE_STORE_FORCE_FLAG);
|
||||
|
||||
@ -152,12 +144,11 @@ CryptoX_Result CryptoAPI_VerifySignature(HCRYPTHASH *hash,
|
||||
*/
|
||||
|
||||
#define CryptoX_InvalidHandleValue NULL
|
||||
#define CryptoX_ProviderHandle void*
|
||||
#define CryptoX_SignatureHandle void*
|
||||
#define CryptoX_PublicKey void*
|
||||
#define CryptoX_Certificate void*
|
||||
#define CryptoX_InitCryptoProvider(CryptoHandle) \
|
||||
CryptoX_Error
|
||||
#define CryptoX_ProviderHandle void *
|
||||
#define CryptoX_SignatureHandle void *
|
||||
#define CryptoX_PublicKey void *
|
||||
#define CryptoX_Certificate void *
|
||||
#define CryptoX_InitCryptoProvider(CryptoHandle) CryptoX_Error
|
||||
#define CryptoX_VerifyBegin(CryptoHandle, SignatureHandle, PublicKey) \
|
||||
CryptoX_Error
|
||||
#define CryptoX_FreeSignatureHandle(SignatureHandle)
|
||||
|
@ -17,13 +17,11 @@
|
||||
#include "mar.h"
|
||||
#include "cryptox.h"
|
||||
|
||||
int
|
||||
mar_read_entire_file(const char * filePath, uint32_t maxSize,
|
||||
/*out*/ const uint8_t * *data,
|
||||
/*out*/ uint32_t *size)
|
||||
{
|
||||
int mar_read_entire_file(const char *filePath, uint32_t maxSize,
|
||||
/*out*/ const uint8_t **data,
|
||||
/*out*/ uint32_t *size) {
|
||||
int result;
|
||||
FILE * f;
|
||||
FILE *f;
|
||||
|
||||
if (!filePath || !data || !size) {
|
||||
return -1;
|
||||
@ -38,9 +36,9 @@ mar_read_entire_file(const char * filePath, uint32_t maxSize,
|
||||
if (!fseeko(f, 0, SEEK_END)) {
|
||||
int64_t fileSize = ftello(f);
|
||||
if (fileSize > 0 && fileSize <= maxSize && !fseeko(f, 0, SEEK_SET)) {
|
||||
unsigned char * fileData;
|
||||
unsigned char *fileData;
|
||||
|
||||
*size = (unsigned int) fileSize;
|
||||
*size = (unsigned int)fileSize;
|
||||
fileData = malloc(*size);
|
||||
if (fileData) {
|
||||
if (fread(fileData, *size, 1, f) == 1) {
|
||||
@ -62,12 +60,10 @@ int mar_extract_and_verify_signatures_fp(FILE *fp,
|
||||
CryptoX_ProviderHandle provider,
|
||||
CryptoX_PublicKey *keys,
|
||||
uint32_t keyCount);
|
||||
int mar_verify_signatures_for_fp(FILE *fp,
|
||||
CryptoX_ProviderHandle provider,
|
||||
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);
|
||||
const uint8_t *const *extractedSignatures,
|
||||
uint32_t keyCount, uint32_t *numVerified);
|
||||
|
||||
/**
|
||||
* Reads the specified number of bytes from the file pointer and
|
||||
@ -83,15 +79,10 @@ int mar_verify_signatures_for_fp(FILE *fp,
|
||||
* @return 0 on success
|
||||
* -1 on read error
|
||||
* -2 on verify update error
|
||||
*/
|
||||
int
|
||||
ReadAndUpdateVerifyContext(FILE *fp,
|
||||
void *buffer,
|
||||
uint32_t size,
|
||||
CryptoX_SignatureHandle *ctxs,
|
||||
uint32_t count,
|
||||
const char *err)
|
||||
{
|
||||
*/
|
||||
int ReadAndUpdateVerifyContext(FILE *fp, void *buffer, uint32_t size,
|
||||
CryptoX_SignatureHandle *ctxs, uint32_t count,
|
||||
const char *err) {
|
||||
uint32_t k;
|
||||
if (!fp || !buffer || !ctxs || count == 0 || !err) {
|
||||
fprintf(stderr, "ERROR: Invalid parameter specified.\n");
|
||||
@ -130,12 +121,9 @@ ReadAndUpdateVerifyContext(FILE *fp,
|
||||
* the data stored
|
||||
* @param certCount The number of elements in certData and certDataSizes
|
||||
* @return 0 on success
|
||||
*/
|
||||
int
|
||||
mar_verify_signatures(MarFile *mar,
|
||||
const uint8_t * const *certData,
|
||||
const uint32_t *certDataSizes,
|
||||
uint32_t certCount) {
|
||||
*/
|
||||
int mar_verify_signatures(MarFile *mar, const uint8_t *const *certData,
|
||||
const uint32_t *certDataSizes, uint32_t certCount) {
|
||||
int rv = -1;
|
||||
CryptoX_ProviderHandle provider = CryptoX_InvalidHandleValue;
|
||||
CryptoX_PublicKey keys[MAX_SIGNATURES];
|
||||
@ -159,8 +147,8 @@ mar_verify_signatures(MarFile *mar,
|
||||
}
|
||||
|
||||
for (k = 0; k < certCount; ++k) {
|
||||
if (CryptoX_Failed(CryptoX_LoadPublicKey(provider, certData[k], certDataSizes[k],
|
||||
&keys[k]))) {
|
||||
if (CryptoX_Failed(CryptoX_LoadPublicKey(provider, certData[k],
|
||||
certDataSizes[k], &keys[k]))) {
|
||||
fprintf(stderr, "ERROR: Could not load public key.\n");
|
||||
goto failure;
|
||||
}
|
||||
@ -188,12 +176,11 @@ failure:
|
||||
* @param keys The public keys to use to verify the MAR
|
||||
* @param keyCount The number of keys pointed to by keys
|
||||
* @return 0 on success
|
||||
*/
|
||||
int
|
||||
mar_extract_and_verify_signatures_fp(FILE *fp,
|
||||
CryptoX_ProviderHandle provider,
|
||||
CryptoX_PublicKey *keys,
|
||||
uint32_t keyCount) {
|
||||
*/
|
||||
int mar_extract_and_verify_signatures_fp(FILE *fp,
|
||||
CryptoX_ProviderHandle provider,
|
||||
CryptoX_PublicKey *keys,
|
||||
uint32_t keyCount) {
|
||||
uint32_t signatureCount, signatureLen, numVerified = 0;
|
||||
uint32_t signatureAlgorithmIDs[MAX_SIGNATURES];
|
||||
uint8_t *extractedSignatures[MAX_SIGNATURES];
|
||||
@ -286,12 +273,9 @@ mar_extract_and_verify_signatures_fp(FILE *fp,
|
||||
if (ftello(fp) == -1) {
|
||||
return CryptoX_Error;
|
||||
}
|
||||
if (mar_verify_signatures_for_fp(fp,
|
||||
provider,
|
||||
keys,
|
||||
(const uint8_t * const *)extractedSignatures,
|
||||
signatureCount,
|
||||
&numVerified) == CryptoX_Error) {
|
||||
if (mar_verify_signatures_for_fp(
|
||||
fp, provider, keys, (const uint8_t *const *)extractedSignatures,
|
||||
signatureCount, &numVerified) == CryptoX_Error) {
|
||||
return CryptoX_Error;
|
||||
}
|
||||
for (i = 0; i < signatureCount; ++i) {
|
||||
@ -332,15 +316,12 @@ mar_extract_and_verify_signatures_fp(FILE *fp,
|
||||
* This information can be useful for printing
|
||||
* error messages.
|
||||
* @return 0 on success, *numVerified == signatureCount.
|
||||
*/
|
||||
int
|
||||
mar_verify_signatures_for_fp(FILE *fp,
|
||||
CryptoX_ProviderHandle provider,
|
||||
CryptoX_PublicKey *keys,
|
||||
const uint8_t * const *extractedSignatures,
|
||||
uint32_t signatureCount,
|
||||
uint32_t *numVerified)
|
||||
{
|
||||
*/
|
||||
int mar_verify_signatures_for_fp(FILE *fp, CryptoX_ProviderHandle provider,
|
||||
CryptoX_PublicKey *keys,
|
||||
const uint8_t *const *extractedSignatures,
|
||||
uint32_t signatureCount,
|
||||
uint32_t *numVerified) {
|
||||
CryptoX_SignatureHandle signatureHandles[MAX_SIGNATURES];
|
||||
char buf[BLOCKSIZE];
|
||||
uint32_t signatureLengths[MAX_SIGNATURES];
|
||||
@ -367,8 +348,8 @@ mar_verify_signatures_for_fp(FILE *fp,
|
||||
}
|
||||
|
||||
for (i = 0; i < signatureCount; i++) {
|
||||
if (CryptoX_Failed(CryptoX_VerifyBegin(provider,
|
||||
&signatureHandles[i], &keys[i]))) {
|
||||
if (CryptoX_Failed(
|
||||
CryptoX_VerifyBegin(provider, &signatureHandles[i], &keys[i]))) {
|
||||
fprintf(stderr, "ERROR: Could not initialize signature handle.\n");
|
||||
goto failure;
|
||||
}
|
||||
@ -384,33 +365,24 @@ mar_verify_signatures_for_fp(FILE *fp,
|
||||
Bytes 4-7: index offset
|
||||
Bytes 8-15: size of entire MAR
|
||||
*/
|
||||
if (CryptoX_Failed(ReadAndUpdateVerifyContext(fp, buf,
|
||||
SIGNATURE_BLOCK_OFFSET +
|
||||
sizeof(uint32_t),
|
||||
signatureHandles,
|
||||
signatureCount,
|
||||
"signature block"))) {
|
||||
if (CryptoX_Failed(ReadAndUpdateVerifyContext(
|
||||
fp, buf, SIGNATURE_BLOCK_OFFSET + sizeof(uint32_t), signatureHandles,
|
||||
signatureCount, "signature block"))) {
|
||||
goto failure;
|
||||
}
|
||||
|
||||
/* Read the signature block */
|
||||
for (i = 0; i < signatureCount; i++) {
|
||||
/* Get the signature algorithm ID */
|
||||
if (CryptoX_Failed(ReadAndUpdateVerifyContext(fp,
|
||||
&buf,
|
||||
sizeof(uint32_t),
|
||||
signatureHandles,
|
||||
signatureCount,
|
||||
"signature algorithm ID"))) {
|
||||
if (CryptoX_Failed(ReadAndUpdateVerifyContext(
|
||||
fp, &buf, sizeof(uint32_t), signatureHandles, signatureCount,
|
||||
"signature algorithm ID"))) {
|
||||
goto failure;
|
||||
}
|
||||
|
||||
if (CryptoX_Failed(ReadAndUpdateVerifyContext(fp,
|
||||
&signatureLengths[i],
|
||||
sizeof(uint32_t),
|
||||
signatureHandles,
|
||||
signatureCount,
|
||||
"signature length"))) {
|
||||
if (CryptoX_Failed(ReadAndUpdateVerifyContext(
|
||||
fp, &signatureLengths[i], sizeof(uint32_t), signatureHandles,
|
||||
signatureCount, "signature length"))) {
|
||||
goto failure;
|
||||
}
|
||||
signatureLengths[i] = ntohl(signatureLengths[i]);
|
||||
@ -428,17 +400,18 @@ mar_verify_signatures_for_fp(FILE *fp,
|
||||
|
||||
/* Read the rest of the file after the signature block */
|
||||
while (!feof(fp)) {
|
||||
int numRead = fread(buf, 1, BLOCKSIZE , fp);
|
||||
int numRead = fread(buf, 1, BLOCKSIZE, fp);
|
||||
if (ferror(fp)) {
|
||||
fprintf(stderr, "ERROR: Error reading data block.\n");
|
||||
goto failure;
|
||||
}
|
||||
|
||||
for (i = 0; i < signatureCount; i++) {
|
||||
if (CryptoX_Failed(CryptoX_VerifyUpdate(&signatureHandles[i],
|
||||
buf, numRead))) {
|
||||
fprintf(stderr, "ERROR: Error updating verify context with"
|
||||
" data block.\n");
|
||||
if (CryptoX_Failed(
|
||||
CryptoX_VerifyUpdate(&signatureHandles[i], buf, numRead))) {
|
||||
fprintf(stderr,
|
||||
"ERROR: Error updating verify context with"
|
||||
" data block.\n");
|
||||
goto failure;
|
||||
}
|
||||
}
|
||||
@ -446,8 +419,7 @@ mar_verify_signatures_for_fp(FILE *fp,
|
||||
|
||||
/* Verify the signatures */
|
||||
for (i = 0; i < signatureCount; i++) {
|
||||
if (CryptoX_Failed(CryptoX_VerifySignature(&signatureHandles[i],
|
||||
&keys[i],
|
||||
if (CryptoX_Failed(CryptoX_VerifySignature(&signatureHandles[i], &keys[i],
|
||||
extractedSignatures[i],
|
||||
signatureLengths[i]))) {
|
||||
fprintf(stderr, "ERROR: Error verifying signature.\n");
|
||||
|
@ -26,6 +26,11 @@
|
||||
#ifdef XP_WIN
|
||||
#include <io.h>
|
||||
#include <winsock2.h>
|
||||
#define open _open
|
||||
#define close _close
|
||||
#define read _read
|
||||
#define lseek _lseek
|
||||
#define write _write
|
||||
#else
|
||||
#include <unistd.h>
|
||||
#include <arpa/inet.h>
|
||||
|
@ -57,7 +57,9 @@
|
||||
|
||||
int MBS_ReadHeader(FILE *file, MBSPatchHeader *header) {
|
||||
size_t s = fread(header, 1, sizeof(MBSPatchHeader), file);
|
||||
if (s != sizeof(MBSPatchHeader)) return READ_ERROR;
|
||||
if (s != sizeof(MBSPatchHeader)) {
|
||||
return READ_ERROR;
|
||||
}
|
||||
|
||||
header->slen = ntohl(header->slen);
|
||||
header->scrc32 = ntohl(header->scrc32);
|
||||
@ -68,26 +70,42 @@ int MBS_ReadHeader(FILE *file, MBSPatchHeader *header) {
|
||||
|
||||
struct stat hs;
|
||||
s = fstat(fileno(file), &hs);
|
||||
if (s != 0) return READ_ERROR;
|
||||
if (s != 0) {
|
||||
return READ_ERROR;
|
||||
}
|
||||
|
||||
if (memcmp(header->tag, "MBDIFF10", 8) != 0) return UNEXPECTED_BSPATCH_ERROR;
|
||||
if (memcmp(header->tag, "MBDIFF10", 8) != 0) {
|
||||
return UNEXPECTED_BSPATCH_ERROR;
|
||||
}
|
||||
|
||||
if (hs.st_size > INT_MAX) return UNEXPECTED_BSPATCH_ERROR;
|
||||
if (hs.st_size > INT_MAX) {
|
||||
return UNEXPECTED_BSPATCH_ERROR;
|
||||
}
|
||||
|
||||
size_t size = static_cast<size_t>(hs.st_size);
|
||||
if (size < sizeof(MBSPatchHeader)) return UNEXPECTED_BSPATCH_ERROR;
|
||||
if (size < sizeof(MBSPatchHeader)) {
|
||||
return UNEXPECTED_BSPATCH_ERROR;
|
||||
}
|
||||
size -= sizeof(MBSPatchHeader);
|
||||
|
||||
if (size < header->cblen) return UNEXPECTED_BSPATCH_ERROR;
|
||||
if (size < header->cblen) {
|
||||
return UNEXPECTED_BSPATCH_ERROR;
|
||||
}
|
||||
size -= header->cblen;
|
||||
|
||||
if (size < header->difflen) return UNEXPECTED_BSPATCH_ERROR;
|
||||
if (size < header->difflen) {
|
||||
return UNEXPECTED_BSPATCH_ERROR;
|
||||
}
|
||||
size -= header->difflen;
|
||||
|
||||
if (size < header->extralen) return UNEXPECTED_BSPATCH_ERROR;
|
||||
if (size < header->extralen) {
|
||||
return UNEXPECTED_BSPATCH_ERROR;
|
||||
}
|
||||
size -= header->extralen;
|
||||
|
||||
if (size != 0) return UNEXPECTED_BSPATCH_ERROR;
|
||||
if (size != 0) {
|
||||
return UNEXPECTED_BSPATCH_ERROR;
|
||||
}
|
||||
|
||||
return OK;
|
||||
}
|
||||
@ -99,7 +117,9 @@ int MBS_ApplyPatch(const MBSPatchHeader *header, FILE *patchFile,
|
||||
|
||||
unsigned char *buf = (unsigned char *)malloc(header->cblen + header->difflen +
|
||||
header->extralen);
|
||||
if (!buf) return BSPATCH_MEM_ERROR;
|
||||
if (!buf) {
|
||||
return BSPATCH_MEM_ERROR;
|
||||
}
|
||||
|
||||
int rv = OK;
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user