[tor-commits] [tor-browser/tor-browser-31.3.0esr-4.5-1] Bug 13379: Sign our MAR files (backport Mozilla patches).

brade at torproject.org brade at torproject.org
Wed Dec 17 22:06:24 UTC 2014


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





More information about the tor-commits mailing list