commit 40b509e6d7408a73c5a81a3d971dfc6daf5f7510
Author: Kathy Brade <brade(a)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