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:
Robert Strong 2018-12-17 11:17:21 -08:00
parent 082c2acc6e
commit 6468b181f7
14 changed files with 758 additions and 932 deletions

View File

@ -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;

View File

@ -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__ */

View File

@ -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__ */

View File

@ -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;
}

View File

@ -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);

View File

@ -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__ */

View File

@ -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;

View File

@ -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;
}
}

View File

@ -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;
}

View File

@ -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;

View File

@ -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)

View File

@ -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");

View File

@ -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>

View File

@ -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;