зеркало из https://github.com/mozilla/gecko-dev.git
Bug 798413 - Export signature from MAR files implementation. r=bsmith, a=blocking-basecamp
This commit is contained in:
Родитель
766128af2d
Коммит
73f5fc7a03
|
@ -22,6 +22,7 @@
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include "nss_secutil.h"
|
#include "nss_secutil.h"
|
||||||
|
#include "base64.h"
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Initializes the NSS context.
|
* Initializes the NSS context.
|
||||||
|
@ -477,6 +478,119 @@ failure:
|
||||||
return rv;
|
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.
|
* 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
|
* The passed in MAR file must not already be signed or an error will
|
||||||
|
|
|
@ -16,8 +16,11 @@ extern "C" {
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* We have a MAX_SIGNATURES limit so that an invalid MAR will never
|
/* We have a MAX_SIGNATURES limit so that an invalid MAR will never
|
||||||
waste too much of either updater's or signmar's time.
|
* waste too much of either updater's or signmar's time.
|
||||||
It is also used at various places internally and will affect memory usage. */
|
* 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
|
#define MAX_SIGNATURES 8
|
||||||
PR_STATIC_ASSERT(MAX_SIGNATURES <= 9);
|
PR_STATIC_ASSERT(MAX_SIGNATURES <= 9);
|
||||||
|
|
||||||
|
|
|
@ -108,6 +108,18 @@ refresh_product_info_block(const char *path,
|
||||||
int
|
int
|
||||||
strip_signature_block(const char *src, const char * dest);
|
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
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -30,18 +30,27 @@ int mar_repackage_and_sign(const char *NSSConfigDir,
|
||||||
|
|
||||||
static void print_usage() {
|
static void print_usage() {
|
||||||
printf("usage:\n");
|
printf("usage:\n");
|
||||||
|
printf("Create a MAR file:\n");
|
||||||
printf(" mar [-H MARChannelID] [-V ProductVersion] [-C workingDir] "
|
printf(" mar [-H MARChannelID] [-V ProductVersion] [-C workingDir] "
|
||||||
"{-c|-x|-t|-T} archive.mar [files...]\n");
|
"{-c|-x|-t|-T} archive.mar [files...]\n");
|
||||||
#ifndef NO_SIGN_VERIFY
|
#ifndef NO_SIGN_VERIFY
|
||||||
|
printf("Sign a MAR file:\n");
|
||||||
printf(" mar [-C workingDir] -d NSSConfigDir -n certname -s "
|
printf(" mar [-C workingDir] -d NSSConfigDir -n certname -s "
|
||||||
"archive.mar out_signed_archive.mar\n");
|
"archive.mar out_signed_archive.mar\n");
|
||||||
|
printf("Strip a MAR signature:\n");
|
||||||
printf(" mar [-C workingDir] -r "
|
printf(" mar [-C workingDir] -r "
|
||||||
"signed_input_archive.mar output_archive.mar\n");
|
"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)
|
#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(" mar [-C workingDir] -D DERFilePath -v signed_archive.mar\n");
|
||||||
printf("At most %d signature certificate DER files are specified by "
|
printf("At most %d signature certificate DER files are specified by "
|
||||||
"-D0 DERFilePath1 -D1 DERFilePath2, ...\n", MAX_SIGNATURES);
|
"-D0 DERFilePath1 -D1 DERFilePath2, ...\n", MAX_SIGNATURES);
|
||||||
#else
|
#else
|
||||||
|
printf("Verify a MAR file:\n");
|
||||||
printf(" mar [-C workingDir] -d NSSConfigDir -n certname "
|
printf(" mar [-C workingDir] -d NSSConfigDir -n certname "
|
||||||
"-v signed_archive.mar\n");
|
"-v signed_archive.mar\n");
|
||||||
printf("At most %d signature certificate names are specified by "
|
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 "
|
printf("At most %d verification certificate names are specified by "
|
||||||
"-n0 certName -n1 certName2, ...\n", MAX_SIGNATURES);
|
"-n0 certName -n1 certName2, ...\n", MAX_SIGNATURES);
|
||||||
#endif
|
#endif
|
||||||
|
printf("Print information on a MAR file:\n");
|
||||||
printf(" mar [-H MARChannelID] [-V ProductVersion] [-C workingDir] "
|
printf(" mar [-H MARChannelID] [-V ProductVersion] [-C workingDir] "
|
||||||
"-i unsigned_archive_to_refresh.mar\n");
|
"-i unsigned_archive_to_refresh.mar\n");
|
||||||
printf("This program does not handle unicode file paths properly\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;
|
uint32_t i, k;
|
||||||
int rv = -1;
|
int rv = -1;
|
||||||
uint32_t certCount = 0;
|
uint32_t certCount = 0;
|
||||||
|
int32_t sigIndex = -1;
|
||||||
#if defined(XP_WIN) && !defined(MAR_NSS) && !defined(NO_SIGN_VERIFY)
|
#if defined(XP_WIN) && !defined(MAR_NSS) && !defined(NO_SIGN_VERIFY)
|
||||||
HANDLE certFile;
|
HANDLE certFile;
|
||||||
/* We use DWORD here instead of uint64_t because it simplifies code with
|
/* 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] == 't' || argv[1][1] == 'x' ||
|
||||||
argv[1][1] == 'v' || argv[1][1] == 's' ||
|
argv[1][1] == 'v' || argv[1][1] == 's' ||
|
||||||
argv[1][1] == 'i' || argv[1][1] == 'T' ||
|
argv[1][1] == 'i' || argv[1][1] == 'T' ||
|
||||||
argv[1][1] == 'r')) {
|
argv[1][1] == 'r' || argv[1][1] == 'X')) {
|
||||||
break;
|
break;
|
||||||
/* -C workingdirectory */
|
/* -C workingdirectory */
|
||||||
} else if (argv[1][0] == '-' && argv[1][1] == 'C') {
|
} 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. */
|
with the import and export command line arguments. */
|
||||||
} else if (argv[1][0] == '-' &&
|
} else if (argv[1][0] == '-' &&
|
||||||
argv[1][1] == 'n' &&
|
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) {
|
if (certCount >= MAX_SIGNATURES) {
|
||||||
print_usage();
|
print_usage();
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
certNames[certCount++] = argv[2];
|
certNames[certCount++] = argv[2];
|
||||||
argv += 2;
|
if (strlen(argv[1]) > 2 &&
|
||||||
argc -= 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 */
|
/* MAR channel ID */
|
||||||
} else if (argv[1][0] == '-' && argv[1][1] == 'H') {
|
} else if (argv[1][0] == '-' && argv[1][1] == 'H') {
|
||||||
MARChannelID = argv[2];
|
MARChannelID = argv[2];
|
||||||
|
@ -226,10 +247,24 @@ int main(int argc, char **argv) {
|
||||||
case 't':
|
case 't':
|
||||||
return mar_test(argv[2]);
|
return mar_test(argv[2]);
|
||||||
|
|
||||||
|
/* Extract a MAR file */
|
||||||
case 'x':
|
case 'x':
|
||||||
return mar_extract(argv[2]);
|
return mar_extract(argv[2]);
|
||||||
|
|
||||||
#ifndef NO_SIGN_VERIFY
|
#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':
|
case 'v':
|
||||||
|
|
||||||
#if defined(XP_WIN) && !defined(MAR_NSS)
|
#if defined(XP_WIN) && !defined(MAR_NSS)
|
||||||
|
|
Загрузка…
Ссылка в новой задаче