зеркало из https://github.com/mozilla/gecko-dev.git
Bug 798413 - Export signature from MAR files implementation. r=bsmith
This commit is contained in:
Родитель
df5ae31148
Коммит
39483bb578
|
@ -22,6 +22,7 @@
|
|||
#endif
|
||||
|
||||
#include "nss_secutil.h"
|
||||
#include "base64.h"
|
||||
|
||||
/**
|
||||
* Initializes the NSS context.
|
||||
|
@ -477,6 +478,119 @@ failure:
|
|||
return rv;
|
||||
}
|
||||
|
||||
/**
|
||||
* Extracts a signature from a MAR file, base64 encodes it, and writes it out
|
||||
*
|
||||
* @param src The path of the source MAR file
|
||||
* @param sigIndex The index of the signature to extract
|
||||
* @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)
|
||||
{
|
||||
FILE *fpSrc = NULL, *fpDest = NULL;
|
||||
uint32_t i;
|
||||
uint32_t signatureCount;
|
||||
uint32_t signatureLen;
|
||||
uint8_t *extractedSignature = NULL;
|
||||
char *base64Encoded = NULL;
|
||||
int rv = -1;
|
||||
if (!src || !dest) {
|
||||
fprintf(stderr, "ERROR: Invalid parameter passed in.\n");
|
||||
goto failure;
|
||||
}
|
||||
|
||||
fpSrc = fopen(src, "rb");
|
||||
if (!fpSrc) {
|
||||
fprintf(stderr, "ERROR: could not open source file: %s\n", src);
|
||||
goto failure;
|
||||
}
|
||||
|
||||
fpDest = fopen(dest, "wb");
|
||||
if (!fpDest) {
|
||||
fprintf(stderr, "ERROR: could not create target file: %s\n", dest);
|
||||
goto failure;
|
||||
}
|
||||
|
||||
/* Skip to the start of the signature block */
|
||||
if (fseeko(fpSrc, SIGNATURE_BLOCK_OFFSET, SEEK_SET)) {
|
||||
fprintf(stderr, "ERROR: could not seek to signature block\n");
|
||||
goto failure;
|
||||
}
|
||||
|
||||
/* Get the number of signatures */
|
||||
if (fread(&signatureCount, sizeof(signatureCount), 1, fpSrc) != 1) {
|
||||
fprintf(stderr, "ERROR: could not read signature count\n");
|
||||
goto failure;
|
||||
}
|
||||
signatureCount = ntohl(signatureCount);
|
||||
if (sigIndex >= signatureCount) {
|
||||
fprintf(stderr, "ERROR: Signature index was out of range\n");
|
||||
goto failure;
|
||||
}
|
||||
|
||||
/* Skip to the correct signature */
|
||||
for (i = 0; i <= sigIndex; i++) {
|
||||
/* skip past the signature algorithm ID */
|
||||
if (fseeko(fpSrc, sizeof(uint32_t), SEEK_CUR)) {
|
||||
fprintf(stderr, "ERROR: Could not seek past sig algorithm ID.\n");
|
||||
goto failure;
|
||||
}
|
||||
|
||||
/* Get the signature length */
|
||||
if (fread(&signatureLen, sizeof(signatureLen), 1, fpSrc) != 1) {
|
||||
fprintf(stderr, "ERROR: could not read signature length\n");
|
||||
goto failure;
|
||||
}
|
||||
signatureLen = ntohl(signatureLen);
|
||||
|
||||
/* Get the signature */
|
||||
extractedSignature = malloc(signatureLen);
|
||||
if (fread(extractedSignature, signatureLen, 1, fpSrc) != 1) {
|
||||
fprintf(stderr, "ERROR: could not read signature\n");
|
||||
goto failure;
|
||||
}
|
||||
}
|
||||
|
||||
base64Encoded = BTOA_DataToAscii(extractedSignature, signatureLen);
|
||||
if (!base64Encoded) {
|
||||
fprintf(stderr, "ERROR: could not obtain base64 encoded data\n");
|
||||
goto failure;
|
||||
}
|
||||
|
||||
if (fwrite(base64Encoded, strlen(base64Encoded), 1, fpDest) != 1) {
|
||||
fprintf(stderr, "ERROR: Could not write base64 encoded string\n");
|
||||
goto failure;
|
||||
}
|
||||
|
||||
rv = 0;
|
||||
failure:
|
||||
if (base64Encoded) {
|
||||
PORT_Free(base64Encoded);
|
||||
}
|
||||
|
||||
if (extractedSignature) {
|
||||
free(extractedSignature);
|
||||
}
|
||||
|
||||
if (fpSrc) {
|
||||
fclose(fpSrc);
|
||||
}
|
||||
|
||||
if (fpDest) {
|
||||
fclose(fpDest);
|
||||
}
|
||||
|
||||
if (rv) {
|
||||
remove(dest);
|
||||
}
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Writes out a copy of the MAR at src but with embedded signatures.
|
||||
* The passed in MAR file must not already be signed or an error will
|
||||
|
|
|
@ -16,8 +16,11 @@ extern "C" {
|
|||
#endif
|
||||
|
||||
/* We have a MAX_SIGNATURES limit so that an invalid MAR will never
|
||||
waste too much of either updater's or signmar's time.
|
||||
It is also used at various places internally and will affect memory usage. */
|
||||
* waste too much of either updater's or signmar's time.
|
||||
* 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
|
||||
PR_STATIC_ASSERT(MAX_SIGNATURES <= 9);
|
||||
|
||||
|
|
|
@ -108,6 +108,18 @@ refresh_product_info_block(const char *path,
|
|||
int
|
||||
strip_signature_block(const char *src, const char * dest);
|
||||
|
||||
/**
|
||||
* Extracts a signature from a MAR file, base64 encodes it, and writes it out
|
||||
*
|
||||
* @param src The path of the source MAR file
|
||||
* @param sigIndex The index of the signature to extract
|
||||
* @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);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -30,18 +30,27 @@ int mar_repackage_and_sign(const char *NSSConfigDir,
|
|||
|
||||
static void print_usage() {
|
||||
printf("usage:\n");
|
||||
printf("Create a MAR file:\n");
|
||||
printf(" mar [-H MARChannelID] [-V ProductVersion] [-C workingDir] "
|
||||
"{-c|-x|-t|-T} archive.mar [files...]\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("Strip a MAR signature:\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("(i) is the index of the certificate to extract\n");
|
||||
#if 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);
|
||||
#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 "
|
||||
|
@ -50,6 +59,7 @@ static void print_usage() {
|
|||
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 [-H MARChannelID] [-V ProductVersion] [-C workingDir] "
|
||||
"-i unsigned_archive_to_refresh.mar\n");
|
||||
printf("This program does not handle unicode file paths properly\n");
|
||||
|
@ -84,6 +94,7 @@ int main(int argc, char **argv) {
|
|||
uint32_t i, k;
|
||||
int rv = -1;
|
||||
uint32_t certCount = 0;
|
||||
int32_t sigIndex = -1;
|
||||
#if defined(XP_WIN) && !defined(MAR_NSS) && !defined(NO_SIGN_VERIFY)
|
||||
HANDLE certFile;
|
||||
/* We use DWORD here instead of uint64_t because it simplifies code with
|
||||
|
@ -112,7 +123,7 @@ int main(int argc, char **argv) {
|
|||
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] == 'r' || argv[1][1] == 'X')) {
|
||||
break;
|
||||
/* -C workingdirectory */
|
||||
} else if (argv[1][0] == '-' && argv[1][1] == 'C') {
|
||||
|
@ -146,14 +157,24 @@ int main(int argc, char **argv) {
|
|||
with the import and export command line arguments. */
|
||||
} else if (argv[1][0] == '-' &&
|
||||
argv[1][1] == 'n' &&
|
||||
(argv[1][2] == '0' + certCount || argv[1][2] == '\0')) {
|
||||
(argv[1][2] == '0' + certCount ||
|
||||
argv[1][2] == '\0' ||
|
||||
!strcmp(argv[2], "-X"))) {
|
||||
if (certCount >= MAX_SIGNATURES) {
|
||||
print_usage();
|
||||
return -1;
|
||||
}
|
||||
certNames[certCount++] = argv[2];
|
||||
argv += 2;
|
||||
argc -= 2;
|
||||
if (strlen(argv[1]) > 2 &&
|
||||
!strcmp(argv[2], "-X") &&
|
||||
argv[1][2] >= '0' && argv[1][2] <= '9') {
|
||||
sigIndex = argv[1][2] - '0';
|
||||
argv++;
|
||||
argc--;
|
||||
} else {
|
||||
argv += 2;
|
||||
argc -= 2;
|
||||
}
|
||||
/* MAR channel ID */
|
||||
} else if (argv[1][0] == '-' && argv[1][1] == 'H') {
|
||||
MARChannelID = argv[2];
|
||||
|
@ -226,10 +247,24 @@ int main(int argc, char **argv) {
|
|||
case 't':
|
||||
return mar_test(argv[2]);
|
||||
|
||||
/* Extract a MAR file */
|
||||
case 'x':
|
||||
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 'v':
|
||||
|
||||
#if defined(XP_WIN) && !defined(MAR_NSS)
|
||||
|
|
Загрузка…
Ссылка в новой задаче