commit 40b509e6d7408a73c5a81a3d971dfc6daf5f7510 Author: Kathy Brade brade@pearlcrescent.com Date: Fri Nov 14 11:24:14 2014 -0500
Bug 13379: Sign our MAR files (backport Mozilla patches).
Backport reviewed patches from these two Mozilla bugs: 903135 - Link updater to NSS and enable MAR verification on Linux and OSX 903126 - Implement a platform independent way to determine which cert to use for verifying mars Configure browser build with --enable-signmar and --enable-verify-mar. --- browser/confvars.sh | 5 + configure.in | 6 +- modules/libmar/moz.build | 6 +- modules/libmar/src/mar.h | 30 ++++- modules/libmar/src/mar_cmdline.h | 32 ----- modules/libmar/tool/mar.c | 109 +++++++++-------- modules/libmar/verify/cryptox.c | 32 ++--- modules/libmar/verify/cryptox.h | 29 ++--- modules/libmar/verify/mar_verify.c | 143 +++++++--------------- toolkit/mozapps/update/updater/Makefile.in | 12 +- toolkit/mozapps/update/updater/archivereader.cpp | 29 +---- toolkit/mozapps/update/updater/updater.cpp | 19 +++ 12 files changed, 197 insertions(+), 255 deletions(-)
diff --git a/browser/confvars.sh b/browser/confvars.sh index 8914379..8e7cf7e 100644 --- a/browser/confvars.sh +++ b/browser/confvars.sh @@ -8,6 +8,11 @@ MOZ_APP_VENDOR=Mozilla MOZ_UPDATER=1 MOZ_PHOENIX=1
+MOZ_VERIFY_MAR_SIGNATURE=1 + +# Enable building ./signmar and running libmar signature tests +MOZ_ENABLE_SIGNMAR=1 + MOZ_CHROME_FILE_FORMAT=omni MOZ_DISABLE_EXPORT_JS=1 MOZ_SAFE_BROWSING=1 diff --git a/configure.in b/configure.in index b97a1e6..3093a3f 100644 --- a/configure.in +++ b/configure.in @@ -6351,11 +6351,7 @@ MOZ_ARG_ENABLE_BOOL(verify-mar, MOZ_VERIFY_MAR_SIGNATURE= )
if test -n "$MOZ_VERIFY_MAR_SIGNATURE"; then - if test "$OS_ARCH" = "WINNT"; then - AC_DEFINE(MOZ_VERIFY_MAR_SIGNATURE) - else - AC_MSG_ERROR([Can only build with --enable-verify-mar with a Windows target]) - fi + AC_DEFINE(MOZ_VERIFY_MAR_SIGNATURE) fi
dnl ======================================================== diff --git a/modules/libmar/moz.build b/modules/libmar/moz.build index 44191c3..d9a8b34 100644 --- a/modules/libmar/moz.build +++ b/modules/libmar/moz.build @@ -9,11 +9,7 @@ DIRS += ['src'] if CONFIG['MOZ_ENABLE_SIGNMAR']: DIRS += ['sign', 'verify'] TEST_DIRS += ['tests'] -elif CONFIG['OS_ARCH'] == 'WINNT': - # On Windows we don't verify with NSS and updater needs to link to it - DIRS += ['verify'] -elif CONFIG['OS_ARCH'] == 'Darwin': - # On OSX we don't verify with NSS and updater needs to link to it. +elif CONFIG['MOZ_VERIFY_MAR_SIGNATURE']: DIRS += ['verify']
# If we are building ./sign and ./verify then ./tool must come after it diff --git a/modules/libmar/src/mar.h b/modules/libmar/src/mar.h index 4e53d2c..98b454d 100644 --- a/modules/libmar/src/mar.h +++ b/modules/libmar/src/mar.h @@ -134,6 +134,26 @@ int mar_create(const char *dest, */ int mar_extract(const char *path);
+#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 + * write whatever error messages it sees fit. The caller must free the returned + * buffer using free(). + * + * @param filePath The path to the file that should be read. + * @param maxSize The maximum valid file size. + * @param data On success, *data will point to a newly-allocated buffer + * with the file's contents in it. + * @param size On success, *size will be the size of the created buffer. + * + * @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); + /** * Verifies a MAR file by verifying each signature with the corresponding * certificate. That is, the first signature will be verified using the first @@ -154,12 +174,10 @@ int mar_extract(const char *path); * a negative number if there was an error * a positive number if the signature does not verify */ -#ifdef XP_WIN -int mar_verify_signaturesW(MarFile *mar, - const uint8_t * const *certData, - const uint32_t *certDataSizes, - uint32_t certCount); -#endif +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. diff --git a/modules/libmar/src/mar_cmdline.h b/modules/libmar/src/mar_cmdline.h index e8645ec..e2c9ed5 100644 --- a/modules/libmar/src/mar_cmdline.h +++ b/modules/libmar/src/mar_cmdline.h @@ -38,38 +38,6 @@ int get_mar_file_info(const char *path, uint32_t *offsetAdditionalBlocks, uint32_t *numAdditionalBlocks);
-/** - * Verifies a MAR file by verifying each signature with the corresponding - * certificate. That is, the first signature will be verified using the first - * certificate given, the second signature will be verified using the second - * certificate given, etc. The signature count must exactly match the number of - * certificates given, and all signature verifications must succeed. - * This is only used by the signmar program when used with arguments to verify - * a MAR. This should not be used to verify a MAR that will be extracted in the - * same operation by updater code. This function prints the error message if - * verification fails. - * - * @param pathToMAR The path of the MAR file whose signature should be - * checked - * @param certData Pointer to the first element in an array of certificate - * file data. - * @param certDataSizes Pointer to the first element in an array for size of - * the cert data. - * @param certNames Pointer to the first element in an array of certificate - * names. - * Used only if compiled with NSS support - * @param certCount The number of elements in certData, certDataSizes, - * and certNames - * @return 0 on success - * a negative number if there was an error - * a positive number if the signature does not verify - */ -int mar_verify_signatures(const char *pathToMAR, - const uint8_t * const *certData, - const uint32_t *certDataSizes, - const char * const *certNames, - uint32_t certCount); - /** * Reads the product info block from the MAR file's additional block section. * The caller is responsible for freeing the fields in infoBlock diff --git a/modules/libmar/tool/mar.c b/modules/libmar/tool/mar.c index 8abbac7..821813c 100644 --- a/modules/libmar/tool/mar.c +++ b/modules/libmar/tool/mar.c @@ -19,6 +19,8 @@ #endif
#if !defined(NO_SIGN_VERIFY) && (!defined(XP_WIN) || defined(MAR_NSS)) +#include "cert.h" +#include "pk11pub.h" int NSSInitCryptoContext(const char *NSSConfigDir); #endif
@@ -120,15 +122,13 @@ int main(int argc, char **argv) { uint32_t certCount = 0; int32_t sigIndex = -1;
-#if defined(XP_WIN) && !defined(MAR_NSS) && !defined(NO_SIGN_VERIFY) - HANDLE certFile; - uint8_t *certBuffers[MAX_SIGNATURES]; -#endif -#if !defined(NO_SIGN_VERIFY) && ((!defined(MAR_NSS) && defined(XP_WIN)) || \ - defined(XP_MACOSX)) - char* DERFilePaths[MAX_SIGNATURES]; +#if !defined(NO_SIGN_VERIFY) uint32_t fileSizes[MAX_SIGNATURES]; - uint32_t read; + uint8_t* certBuffers[MAX_SIGNATURES]; + char* DERFilePaths[MAX_SIGNATURES]; +#if (!defined(XP_WIN) && !defined(XP_MACOSX)) || defined(MAR_NSS) + CERTCertificate* certs[MAX_SIGNATURES]; +#endif #endif
memset(certNames, 0, sizeof(certNames)); @@ -319,43 +319,68 @@ int main(int argc, char **argv) { return import_signature(argv[2], sigIndex, argv[3], argv[4]);
case 'v': - -#if defined(XP_WIN) && !defined(MAR_NSS) 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 (NSSInitCryptoContext(NSSConfigDir)) { + fprintf(stderr, "ERROR: Could not initialize crypto library.\n"); + return -1; + } +#endif + + rv = 0; for (k = 0; k < certCount; ++k) { - /* If the mar program was built using CryptoAPI, then read in the buffer - containing the cert from disk. */ - certFile = CreateFileA(DERFilePaths[k], GENERIC_READ, - FILE_SHARE_READ | - FILE_SHARE_WRITE | - FILE_SHARE_DELETE, - NULL, - OPEN_EXISTING, - 0, NULL); - if (INVALID_HANDLE_VALUE == certFile) { - return -1; +#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]); +#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; } - fileSizes[k] = GetFileSize(certFile, NULL); - certBuffers[k] = malloc(fileSizes[k]); - if (!ReadFile(certFile, certBuffers[k], fileSizes[k], &read, NULL) || - fileSizes[k] != read) { - CloseHandle(certFile); - for (i = 0; i <= k; i++) { - free(certBuffers[i]); - } - return -1; +#endif + if (rv) { + fprintf(stderr, "ERROR: could not read file %s", DERFilePaths[k]); + break; } - CloseHandle(certFile); }
- rv = mar_verify_signatures(argv[2], certBuffers, fileSizes, - NULL, certCount); + 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(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 */ @@ -369,26 +394,8 @@ int main(int argc, char **argv) { } return -1; } - return 0;
-#elif defined(XP_MACOSX) - return mar_verify_signatures(argv[2], (const uint8_t* const*)DERFilePaths, - 0, NULL, certCount); -#else - if (!NSSConfigDir || certCount == 0) { - print_usage(); - return -1; - } - - if (NSSInitCryptoContext(NSSConfigDir)) { - fprintf(stderr, "ERROR: Could not initialize crypto library.\n"); - return -1; - } - - return mar_verify_signatures(argv[2], NULL, 0, certNames, certCount); - -#endif /* defined(XP_WIN) && !defined(MAR_NSS) */ case 's': if (!NSSConfigDir || certCount == 0 || argc < 4) { print_usage(); diff --git a/modules/libmar/verify/cryptox.c b/modules/libmar/verify/cryptox.c index 48fbecd..af34210 100644 --- a/modules/libmar/verify/cryptox.c +++ b/modules/libmar/verify/cryptox.c @@ -16,29 +16,32 @@ /** * Loads the public key for the specified cert name from the NSS store. * - * @param certName The cert name to find. + * @param certData The DER-encoded X509 certificate to extract the key from. + * @param certDataSize The size of certData. * @param publicKey Out parameter for the public key to use. - * @param cert Out parameter for the certificate to use. * @return CryptoX_Success on success, CryptoX_Error on error. */ CryptoX_Result -NSS_LoadPublicKey(const char *certNickname, - SECKEYPublicKey **publicKey, - CERTCertificate **cert) +NSS_LoadPublicKey(const unsigned char *certData, unsigned int certDataSize, + SECKEYPublicKey **publicKey) { - secuPWData pwdata = { PW_NONE, 0 }; - if (!cert || !publicKey || !cert) { + CERTCertificate * cert; + SECItem certDataItem = { siBuffer, (unsigned char*) certData, certDataSize }; + + if (!certData || !publicKey) { return CryptoX_Error; }
+ cert = CERT_NewTempCertificate(CERT_GetDefaultCertDB(), &certDataItem, NULL, + PR_FALSE, PR_TRUE); /* Get the cert and embedded public key out of the database */ - *cert = PK11_FindCertFromNickname(certNickname, &pwdata); - if (!*cert) { + if (!cert) { return CryptoX_Error; } - *publicKey = CERT_ExtractPublicKey(*cert); + *publicKey = CERT_ExtractPublicKey(cert); + CERT_DestroyCertificate(cert); + if (!*publicKey) { - CERT_DestroyCertificate(*cert); return CryptoX_Error; } return CryptoX_Success; @@ -150,12 +153,11 @@ CryptoX_Result CryptoAPI_LoadPublicKey(HCRYPTPROV provider, BYTE *certData, DWORD sizeOfCertData, - HCRYPTKEY *publicKey, - HCERTSTORE *certStore) + HCRYPTKEY *publicKey) { CRYPT_DATA_BLOB blob; CERT_CONTEXT *context; - if (!provider || !certData || !publicKey || !certStore) { + if (!provider || !certData || !publicKey) { return CryptoX_Error; }
@@ -165,7 +167,7 @@ CryptoAPI_LoadPublicKey(HCRYPTPROV provider, CERT_QUERY_CONTENT_FLAG_CERT, CERT_QUERY_FORMAT_FLAG_BINARY, 0, NULL, NULL, NULL, - certStore, NULL, (const void **)&context)) { + NULL, NULL, (const void **)&context)) { return CryptoX_Error; }
diff --git a/modules/libmar/verify/cryptox.h b/modules/libmar/verify/cryptox.h index 2dd93ef..ec8f5ac 100644 --- a/modules/libmar/verify/cryptox.h +++ b/modules/libmar/verify/cryptox.h @@ -15,7 +15,9 @@
#if defined(MAR_NSS)
-#include "nss_secutil.h" +#include "cert.h" +#include "keyhi.h" +#include "cryptohi.h"
#define CryptoX_InvalidHandleValue NULL #define CryptoX_ProviderHandle void* @@ -26,9 +28,9 @@ #ifdef __cplusplus extern "C" { #endif -CryptoX_Result NSS_LoadPublicKey(const char *certNickname, - SECKEYPublicKey **publicKey, - CERTCertificate **cert); +CryptoX_Result NSS_LoadPublicKey(const unsigned char* certData, + unsigned int certDataSize, + SECKEYPublicKey** publicKey); CryptoX_Result NSS_VerifyBegin(VFYContext **ctx, SECKEYPublicKey * const *publicKey); CryptoX_Result NSS_VerifySignature(VFYContext * const *ctx , @@ -46,9 +48,8 @@ CryptoX_Result NSS_VerifySignature(VFYContext * const *ctx , VFY_DestroyContext(*SignatureHandle, PR_TRUE) #define CryptoX_VerifyUpdate(SignatureHandle, buf, len) \ VFY_Update(*SignatureHandle, (const unsigned char*)(buf), len) -#define CryptoX_LoadPublicKey(CryptoHandle, certData, dataSize, \ - publicKey, certName, cert) \ - NSS_LoadPublicKey(certName, publicKey, cert) +#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) \ @@ -91,7 +92,7 @@ void CryptoMac_FreePublicKey(CryptoX_PublicKey* aPublicKey); #define CryptoX_VerifyUpdate(aInputData, aBuf, aLen) \ CryptoMac_VerifyUpdate(aInputData, aBuf, aLen) #define CryptoX_LoadPublicKey(aProviderHandle, aCertData, aDataSize, \ - aPublicKey, aCertName, aCert) \ + aPublicKey) \ CryptoMac_LoadPublicKey(aCertData, aPublicKey) #define CryptoX_VerifySignature(aInputData, aPublicKey, aSignature, \ aSignatureLen) \ @@ -111,8 +112,7 @@ CryptoX_Result CryptoAPI_InitCryptoContext(HCRYPTPROV *provider); CryptoX_Result CryptoAPI_LoadPublicKey(HCRYPTPROV hProv, BYTE *certData, DWORD sizeOfCertData, - HCRYPTKEY *publicKey, - HCERTSTORE *cert); + HCRYPTKEY *publicKey); CryptoX_Result CryptoAPI_VerifyBegin(HCRYPTPROV provider, HCRYPTHASH* hash); CryptoX_Result CryptoAPI_VerifyUpdate(HCRYPTHASH* hash, BYTE *buf, DWORD len); @@ -133,10 +133,8 @@ CryptoX_Result CyprtoAPI_VerifySignature(HCRYPTHASH *hash, #define CryptoX_FreeSignatureHandle(SignatureHandle) #define CryptoX_VerifyUpdate(SignatureHandle, buf, len) \ CryptoAPI_VerifyUpdate(SignatureHandle, (BYTE *)(buf), len) -#define CryptoX_LoadPublicKey(CryptoHandle, certData, dataSize, \ - publicKey, certName, cert) \ - CryptoAPI_LoadPublicKey(CryptoHandle, (BYTE*)(certData), \ - dataSize, publicKey, cert) +#define CryptoX_LoadPublicKey(CryptoHandle, certData, dataSize, publicKey) \ + CryptoAPI_LoadPublicKey(CryptoHandle, (BYTE*)(certData), dataSize, publicKey) #define CryptoX_VerifySignature(hash, publicKey, signedData, len) \ CyprtoAPI_VerifySignature(hash, publicKey, signedData, len) #define CryptoX_FreePublicKey(key) \ @@ -163,8 +161,7 @@ CryptoX_Result CyprtoAPI_VerifySignature(HCRYPTHASH *hash, CryptoX_Error #define CryptoX_FreeSignatureHandle(SignatureHandle) #define CryptoX_VerifyUpdate(SignatureHandle, buf, len) CryptoX_Error -#define CryptoX_LoadPublicKey(CryptoHandle, certData, dataSize, \ - publicKey, certName, cert) \ +#define CryptoX_LoadPublicKey(CryptoHandle, certData, dataSize, publicKey) \ CryptoX_Error #define CryptoX_VerifySignature(hash, publicKey, signedData, len) CryptoX_Error #define CryptoX_FreePublicKey(key) CryptoX_Error diff --git a/modules/libmar/verify/mar_verify.c b/modules/libmar/verify/mar_verify.c index 7578b62..165a802 100644 --- a/modules/libmar/verify/mar_verify.c +++ b/modules/libmar/verify/mar_verify.c @@ -17,6 +17,46 @@ #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 result; + FILE * f; + + if (!filePath || !data || !size) { + return -1; + } + + f = fopen(filePath, "rb"); + if (!f) { + return -1; + } + + result = -1; + if (!fseeko(f, 0, SEEK_END)) { + int64_t fileSize = ftello(f); + if (fileSize > 0 && fileSize <= maxSize && !fseeko(f, 0, SEEK_SET)) { + unsigned char * fileData; + + *size = (unsigned int) fileSize; + fileData = malloc(*size); + if (fileData) { + if (fread(fileData, *size, 1, f) == 1) { + *data = fileData; + result = 0; + } else { + free(fileData); + } + } + } + fclose(f); + } + + return result; +} + int mar_extract_and_verify_signatures_fp(FILE *fp, CryptoX_ProviderHandle provider, CryptoX_PublicKey *keys, @@ -81,92 +121,8 @@ ReadAndUpdateVerifyContext(FILE *fp, * certificate given, the second signature will be verified using the second * certificate given, etc. The signature count must exactly match the number of * certificates given, and all signature verifications must succeed. - * This is only used by the signmar program when used with arguments to verify - * a MAR. This should not be used to verify a MAR that will be extracted in the - * same operation by updater code. This function prints the error message if - * verification fails. * - * @param pathToMARFile The path of the MAR file to verify. - * @param certData Pointer to the first element in an array of certificate - * file data. - * @param certDataSizes Pointer to the first element in an array for size of the - * cert data. - * @param certNames Pointer to the first element in an array of certificate names. - * Used only if compiled as NSS, specifies the certificate names - * @param certCount The number of elements in certData, certDataSizes, and certNames - * @return 0 on success - * a negative number if there was an error - * a positive number if the signature does not verify - */ -int -mar_verify_signatures(const char *pathToMARFile, - const uint8_t * const *certData, - const uint32_t *certDataSizes, - const char * const *certNames, - uint32_t certCount) { - int rv; - CryptoX_ProviderHandle provider = CryptoX_InvalidHandleValue; - CryptoX_Certificate certs[MAX_SIGNATURES]; - CryptoX_PublicKey keys[MAX_SIGNATURES]; - FILE *fp; - uint32_t k; - - memset(certs, 0, sizeof(certs)); - memset(keys, 0, sizeof(keys)); - - if (!pathToMARFile || certCount == 0) { - fprintf(stderr, "ERROR: Invalid parameter specified.\n"); - return CryptoX_Error; - } - - fp = fopen(pathToMARFile, "rb"); - if (!fp) { - fprintf(stderr, "ERROR: Could not open MAR file.\n"); - return CryptoX_Error; - } - - if (CryptoX_Failed(CryptoX_InitCryptoProvider(&provider))) { - fclose(fp); - fprintf(stderr, "ERROR: Could not init crytpo library.\n"); - return CryptoX_Error; - } - - /* Load the certs and keys */ - for (k = 0; k < certCount; k++) { - if (CryptoX_Failed(CryptoX_LoadPublicKey(provider, certData[k], certDataSizes[k], - &keys[k], certNames[k], &certs[k]))) { - fclose(fp); - fprintf(stderr, "ERROR: Could not load public key.\n"); - return CryptoX_Error; - } - } - - rv = mar_extract_and_verify_signatures_fp(fp, provider, keys, certCount); - fclose(fp); - - /* Cleanup the allocated keys and certs */ - for (k = 0; k < certCount; k++) { - if (keys[k]) { - CryptoX_FreePublicKey(&keys[k]); - } - - if (certs[k]) { - CryptoX_FreeCertificate(&certs[k]); - } - } - return rv; -} - -#ifdef XP_WIN -/** - * Verifies a MAR file by verifying each signature with the corresponding - * certificate. That is, the first signature will be verified using the first - * certificate given, the second signature will be verified using the second - * certificate given, etc. The signature count must exactly match the number of - * certificates given, and all signature verifications must succeed. - * - * @param pathToMARFile The path of the MAR file who's signature - * should be calculated + * @param mar The file who's signature should be calculated * @param certData Pointer to the first element in an array of * certificate data * @param certDataSizes Pointer to the first element in an array for size of @@ -175,17 +131,15 @@ mar_verify_signatures(const char *pathToMARFile, * @return 0 on success */ int -mar_verify_signaturesW(MarFile *mar, - const uint8_t * const *certData, - const uint32_t *certDataSizes, - uint32_t certCount) { +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_Certificate certs[MAX_SIGNATURES]; CryptoX_PublicKey keys[MAX_SIGNATURES]; uint32_t k;
- memset(certs, 0, sizeof(certs)); memset(keys, 0, sizeof(keys));
if (!mar || !certData || !certDataSizes || certCount == 0) { @@ -205,7 +159,7 @@ mar_verify_signaturesW(MarFile *mar,
for (k = 0; k < certCount; ++k) { if (CryptoX_Failed(CryptoX_LoadPublicKey(provider, certData[k], certDataSizes[k], - &keys[k], "", &certs[k]))) { + &keys[k]))) { fprintf(stderr, "ERROR: Could not load public key.\n"); goto failure; } @@ -219,15 +173,10 @@ failure: if (keys[k]) { CryptoX_FreePublicKey(&keys[k]); } - - if (certs[k]) { - CryptoX_FreeCertificate(&certs[k]); - } }
return rv; } -#endif
/** * Extracts each signature from the specified MAR file, diff --git a/toolkit/mozapps/update/updater/Makefile.in b/toolkit/mozapps/update/updater/Makefile.in index bd6716b..52cdbeb 100644 --- a/toolkit/mozapps/update/updater/Makefile.in +++ b/toolkit/mozapps/update/updater/Makefile.in @@ -18,9 +18,14 @@ LIBS += \ $(MOZ_BZ2_LIBS) \ $(NULL)
-ifeq ($(OS_ARCH),WINNT) +LIBS += $(call EXPAND_LIBNAME_PATH,signmar,$(DEPTH)/modules/libmar/sign) LIBS += $(call EXPAND_LIBNAME_PATH,verifymar,$(DEPTH)/modules/libmar/verify) +ifeq ($(OS_ARCH),WINNT) OS_LIBS += $(call EXPAND_LIBNAME,comctl32 ws2_32 shell32 shlwapi) +else +LIBS += $(DIST)/lib/$(LIB_PREFIX)nss3.$(LIB_SUFFIX) \ + $(DIST)/lib/$(LIB_PREFIX)nssutil3.$(LIB_SUFFIX) \ + $(NSPR_LIBS) endif
ifdef MOZ_WIDGET_GTK @@ -51,14 +56,13 @@ else ifneq (,$(filter nightly aurora nightly-elm nightly-profiling nightly-oak n PRIMARY_CERT = nightly_aurora_level3_primary.der SECONDARY_CERT = nightly_aurora_level3_secondary.der else - PRIMARY_CERT = dep1.der - SECONDARY_CERT = dep2.der + PRIMARY_CERT = xpcshellCertificate.der + SECONDARY_CERT = xpcshellCertificate.der endif
export:: $(PYTHON) $(srcdir)/gen_cert_header.py primaryCertData $(srcdir)/$(PRIMARY_CERT) > primaryCert.h $(PYTHON) $(srcdir)/gen_cert_header.py secondaryCertData $(srcdir)/$(SECONDARY_CERT) > secondaryCert.h - $(PYTHON) $(srcdir)/gen_cert_header.py xpcshellCertData $(srcdir)/xpcshellCertificate.der > xpcshellCert.h
ifdef MOZ_WIDGET_GTK libs:: updater.png diff --git a/toolkit/mozapps/update/updater/archivereader.cpp b/toolkit/mozapps/update/updater/archivereader.cpp index f0e6ea3..aa9ccc4 100644 --- a/toolkit/mozapps/update/updater/archivereader.cpp +++ b/toolkit/mozapps/update/updater/archivereader.cpp @@ -15,13 +15,10 @@ #include "updatehelper.h" #endif
-#ifdef XP_WIN // These are generated at compile time based on the DER file for the channel // being used #include "primaryCert.h" #include "secondaryCert.h" -#include "xpcshellCert.h" -#endif
#define UPDATER_NO_STRING_GLUE_STL #include "nsVersionComparator.cpp" @@ -38,9 +35,6 @@ static int outbuf_size = 262144; static char *inbuf = nullptr; static char *outbuf = nullptr;
-#ifdef XP_WIN -#include "resource.h" - /** * Performs a verification on the opened MAR file with the passed in * certificate name ID and type ID. @@ -54,15 +48,13 @@ int VerifyLoadedCert(MarFile *archive, const uint8_t (&certData)[SIZE]) { const uint32_t size = SIZE; - const uint8_t * const data = &certData[0]; - if (mar_verify_signaturesW(archive, &data, &size, 1)) { + const uint8_t* const data = &certData[0]; + if (mar_verify_signatures(archive, &data, &size, 1)) { return CERT_VERIFY_ERROR; }
return OK; } -#endif -
/** * Performs a verification on the opened MAR file. Both the primary and backup @@ -79,22 +71,11 @@ ArchiveReader::VerifySignature() return ARCHIVE_NOT_OPEN; }
-#ifdef XP_WIN - // If the fallback key exists we're running an XPCShell test and we should - // use the XPCShell specific cert for the signed MAR. - int rv; - if (DoesFallbackKeyExist()) { - rv = VerifyLoadedCert(mArchive, xpcshellCertData); - } else { - rv = VerifyLoadedCert(mArchive, primaryCertData); - if (rv != OK) { - rv = VerifyLoadedCert(mArchive, secondaryCertData); - } + int rv = VerifyLoadedCert(mArchive, primaryCertData); + if (rv != OK) { + rv = VerifyLoadedCert(mArchive, secondaryCertData); } return rv; -#else - return OK; -#endif }
/** diff --git a/toolkit/mozapps/update/updater/updater.cpp b/toolkit/mozapps/update/updater/updater.cpp index 4cf24db..3a3968e 100644 --- a/toolkit/mozapps/update/updater/updater.cpp +++ b/toolkit/mozapps/update/updater/updater.cpp @@ -108,6 +108,11 @@ static bool sUseHardLinks = true; # define MAYBE_USE_HARD_LINKS 0 #endif
+#if defined(MOZ_VERIFY_MAR_SIGNATURE) && !defined(XP_WIN) +#include "nss.h" +#include "prerror.h" +#endif + #ifdef XP_WIN #include "updatehelper.h"
@@ -2520,6 +2525,20 @@ int NS_main(int argc, NS_tchar **argv) _exit(1); } #endif + +#if defined(MOZ_VERIFY_MAR_SIGNATURE) && !defined(XP_WIN) + // On Windows we rely on CyrptoAPI to do verifications so we don't need to + // initialize NSS at all there. + // Otherwise, minimize the amount of NSS we depend on by avoiding all the NSS + // databases. + if (NSS_NoDB_Init(NULL) != SECSuccess) { + PRErrorCode error = PR_GetError(); + fprintf(stderr, "Could not initialize NSS: %s (%d)", + PR_ErrorToName(error), (int) error); + _exit(1); + } +#endif + InitProgressUI(&argc, &argv);
// To process an update the updater command line must at a minimum have the