Bug 903135 - Updates to libmar needed to support B2G MAR signature verification. r=bbondy
authorBrian Smith <bsmith@mozilla.com>
Wed, 22 Oct 2014 21:00:15 -0400
changeset 237758 144170110448647a591bb54572dc5e2979296027
parent 237688 4fe763cbe1961059f9051084afb6e300c6bf399f
child 237759 c19d11fe299702a7ef948b29e61b51b889c10b32
push id58022
push userryanvm@gmail.com
push dateMon, 06 Apr 2015 22:48:47 +0000
treeherdermozilla-inbound@0d4b7cd5b0cd [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersbbondy
bugs903135
milestone40.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 903135 - Updates to libmar needed to support B2G MAR signature verification. r=bbondy
modules/libmar/src/mar.h
modules/libmar/src/mar_cmdline.h
modules/libmar/tool/mar.c
modules/libmar/verify/cryptox.c
modules/libmar/verify/cryptox.h
modules/libmar/verify/mar_verify.c
--- a/modules/libmar/src/mar.h
+++ b/modules/libmar/src/mar.h
@@ -129,16 +129,36 @@ int mar_create(const char *dest,
 /**
  * Extract a MAR file to the current working directory.
  * @param path      The path to the MAR file to extract.  This path must be
  *                  compatible with fopen.
  * @return          A non-zero value if an error occurs.
  */
 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
  * 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.
  * We do not check that the certificate was issued by any trusted authority. 
  * We assume it to be self-signed.  We do not check whether the certificate 
@@ -149,22 +169,20 @@ int mar_extract(const char *path);
  *                       file data.
  * @param certDataSizes  Pointer to the first element in an array for size of
  *                       the cert data.
  * @param certCount      The number of elements in certData and certDataSizes
  * @return 0 on success
  *         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.
  * The caller is responsible for freeing the fields in infoBlock
  * if the return is successful.
  *
  * @param infoBlock Out parameter for where to store the result to
  * @return 0 on success, -1 on failure
--- a/modules/libmar/src/mar_cmdline.h
+++ b/modules/libmar/src/mar_cmdline.h
@@ -33,48 +33,16 @@ struct ProductInformationBlock;
  */
 int get_mar_file_info(const char *path, 
                       int *hasSignatureBlock,
                       uint32_t *numSignatures,
                       int *hasAdditionalBlocks,
                       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
  * if the return is successful.
  *
  * @param infoBlock Out parameter for where to store the result to
  * @return 0 on success, -1 on failure
 */
--- a/modules/libmar/tool/mar.c
+++ b/modules/libmar/tool/mar.c
@@ -14,16 +14,18 @@
 #include <windows.h>
 #include <direct.h>
 #define chdir _chdir
 #else
 #include <unistd.h>
 #endif
 
 #if !defined(NO_SIGN_VERIFY) && (!defined(XP_WIN) || defined(MAR_NSS))
+#include "cert.h"
+#include "pk11pub.h"
 int NSSInitCryptoContext(const char *NSSConfigDir);
 #endif
 
 int mar_repackage_and_sign(const char *NSSConfigDir,
                            const char * const *certNames,
                            uint32_t certCount,
                            const char *src, 
                            const char * dest);
@@ -115,25 +117,23 @@ int main(int argc, char **argv) {
   const char *certNames[MAX_SIGNATURES];
   char *MARChannelID = MAR_CHANNEL_ID;
   char *productVersion = MOZ_APP_VERSION;
   uint32_t i, k;
   int rv = -1;
   uint32_t certCount = 0;
   int32_t sigIndex = -1;
 
-#if defined(XP_WIN) && !defined(MAR_NSS) && !defined(NO_SIGN_VERIFY)
-  HANDLE certFile;
-  uint8_t *certBuffers[MAX_SIGNATURES];
+#if !defined(NO_SIGN_VERIFY)
+  uint32_t fileSizes[MAX_SIGNATURES];
+  uint8_t* certBuffers[MAX_SIGNATURES];
+  char* DERFilePaths[MAX_SIGNATURES];
+#if (!defined(XP_WIN) && !defined(XP_MACOSX)) || defined(MAR_NSS)
+  CERTCertificate* certs[MAX_SIGNATURES];
 #endif
-#if !defined(NO_SIGN_VERIFY) && ((!defined(MAR_NSS) && defined(XP_WIN)) || \
-                                 defined(XP_MACOSX))
-  char* DERFilePaths[MAX_SIGNATURES];
-  uint32_t fileSizes[MAX_SIGNATURES];
-  uint32_t read;
 #endif
 
   memset(certNames, 0, sizeof(certNames));
 #if defined(XP_WIN) && !defined(MAR_NSS) && !defined(NO_SIGN_VERIFY)
   memset(certBuffers, 0, sizeof(certBuffers));
 #endif
 #if !defined(NO_SIGN_VERIFY) && ((!defined(MAR_NSS) && defined(XP_WIN)) || \
                                  defined(XP_MACOSX))
@@ -314,86 +314,93 @@ int main(int argc, char **argv) {
     }
     if (argc < 5) {
       print_usage();
       return -1;
     }
     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;
     }
 
-    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;
-      }
-      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;
-      }
-      CloseHandle(certFile);
+#if (!defined(XP_WIN) && !defined(XP_MACOSX)) || defined(MAR_NSS)
+    if (!NSSConfigDir || certCount == 0) {
+      print_usage();
+      return -1;
     }
 
-    rv = mar_verify_signatures(argv[2], certBuffers, fileSizes,
-                               NULL, certCount);
+    if (NSSInitCryptoContext(NSSConfigDir)) {
+      fprintf(stderr, "ERROR: Could not initialize crypto library.\n");
+      return -1;
+    }
+#endif
+
+    rv = 0;
     for (k = 0; k < certCount; ++k) {
+#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;
+      }
+#endif
+      if (rv) {
+        fprintf(stderr, "ERROR: could not read file %s", DERFilePaths[k]);
+        break;
+      }
+    }
+
+    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 */
       int hasSignatureBlock;
       if (get_mar_file_info(argv[2], &hasSignatureBlock, 
                             NULL, NULL, NULL, NULL)) {
         fprintf(stderr, "ERROR: could not determine if MAR is old or new.\n");
       } else if (!hasSignatureBlock) {
         fprintf(stderr, "ERROR: The MAR file is in the old format so has"
                         " no signature to verify.\n");
       }
       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();
       return -1;
     }
     return mar_repackage_and_sign(NSSConfigDir, certNames, certCount,
                                   argv[2], argv[3]);
 
--- a/modules/libmar/verify/cryptox.c
+++ b/modules/libmar/verify/cryptox.c
@@ -11,39 +11,42 @@
 #include <stdlib.h>
 #include "cryptox.h"
 
 #if defined(MAR_NSS)
 
 /** 
  * 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;
 }
 
 CryptoX_Result
 NSS_VerifyBegin(VFYContext **ctx, 
                 SECKEYPublicKey * const *publicKey)
@@ -145,32 +148,31 @@ CyprtoAPI_VerifySignature(HCRYPTHASH *ha
  * @param sizeOfCertData The size of the certData buffer
  * @param certStore      Pointer to the handle of the certificate store to use
  * @param CryptoX_Success on success
 */
 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;
   }
 
   blob.cbData = sizeOfCertData;
   blob.pbData = certData;
   if (!CryptQueryObject(CERT_QUERY_OBJECT_BLOB, &blob, 
                         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;
   }
 
   if (!CryptImportPublicKeyInfo(provider, 
                                 PKCS_7_ASN_ENCODING | X509_ASN_ENCODING,
                                 &context->pCertInfo->SubjectPublicKeyInfo,
                                 publicKey)) {
     CertFreeCertificateContext(context);
--- a/modules/libmar/verify/cryptox.h
+++ b/modules/libmar/verify/cryptox.h
@@ -10,30 +10,32 @@
 #define CryptoX_Result int
 #define CryptoX_Success 0
 #define CryptoX_Error (-1)
 #define CryptoX_Succeeded(X) ((X) == CryptoX_Success)
 #define CryptoX_Failed(X) ((X) != CryptoX_Success)
 
 #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*
 #define CryptoX_SignatureHandle VFYContext *
 #define CryptoX_PublicKey SECKEYPublicKey *
 #define CryptoX_Certificate CERTCertificate *
 
 #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 ,
                                    const unsigned char *signature,
                                    unsigned int signatureLen);
 #ifdef __cplusplus
 } // extern "C"
 #endif
@@ -41,19 +43,18 @@ CryptoX_Result NSS_VerifySignature(VFYCo
 #define CryptoX_InitCryptoProvider(CryptoHandle) \
   CryptoX_Success
 #define CryptoX_VerifyBegin(CryptoHandle, SignatureHandle, PublicKey) \
   NSS_VerifyBegin(SignatureHandle, PublicKey)
 #define CryptoX_FreeSignatureHandle(SignatureHandle) \
   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) \
   SECKEY_DestroyPublicKey(*key)
 #define CryptoX_FreeCertificate(cert) \
   CERT_DestroyCertificate(*cert)
 
 #elif XP_MACOSX
@@ -86,17 +87,17 @@ void CryptoMac_FreePublicKey(CryptoX_Pub
 
 #define CryptoX_InitCryptoProvider(aProviderHandle) \
   CryptoMac_InitCryptoProvider()
 #define CryptoX_VerifyBegin(aCryptoHandle, aInputData, aPublicKey) \
   CryptoMac_VerifyBegin(aInputData)
 #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) \
   CryptoMac_VerifySignature(aInputData, aPublicKey, aSignature, aSignatureLen)
 #define CryptoX_FreeSignatureHandle(aInputData) \
   CryptoMac_FreeSignatureHandle(aInputData)
 #define CryptoX_FreePublicKey(aPublicKey) \
   CryptoMac_FreePublicKey(aPublicKey)
@@ -106,18 +107,17 @@ void CryptoMac_FreePublicKey(CryptoX_Pub
 
 #include <windows.h>
 #include <wincrypt.h>
 
 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);
 CryptoX_Result CyprtoAPI_VerifySignature(HCRYPTHASH *hash, 
                                          HCRYPTKEY *pubKey,
                                          const BYTE *signature, 
                                          DWORD signatureLen);
 
@@ -128,20 +128,18 @@ CryptoX_Result CyprtoAPI_VerifySignature
 #define CryptoX_Certificate HCERTSTORE
 #define CryptoX_InitCryptoProvider(CryptoHandle) \
   CryptoAPI_InitCryptoContext(CryptoHandle)
 #define CryptoX_VerifyBegin(CryptoHandle, SignatureHandle, PublicKey) \
   CryptoAPI_VerifyBegin(CryptoHandle, SignatureHandle)
 #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) \
   CryptDestroyKey(*(key))
 #define CryptoX_FreeCertificate(cert) \
   CertCloseStore(*(cert), CERT_CLOSE_STORE_FORCE_FLAG);
 
 #else
@@ -158,17 +156,16 @@ CryptoX_Result CyprtoAPI_VerifySignature
 #define CryptoX_PublicKey void*
 #define CryptoX_Certificate void*
 #define CryptoX_InitCryptoProvider(CryptoHandle) \
   CryptoX_Error
 #define CryptoX_VerifyBegin(CryptoHandle, SignatureHandle, PublicKey) \
   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
 
 #endif
 
 #endif
--- a/modules/libmar/verify/mar_verify.c
+++ b/modules/libmar/verify/mar_verify.c
@@ -12,16 +12,56 @@
 #include <sys/stat.h>
 #include <fcntl.h>
 #include <stdlib.h>
 #include <string.h>
 #include "mar_private.h"
 #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,
                                          uint32_t keyCount);
 int mar_verify_signatures_for_fp(FILE *fp,
                                  CryptoX_ProviderHandle provider,
                                  CryptoX_PublicKey *keys,
                                  const uint8_t * const *extractedSignatures,
@@ -76,121 +116,35 @@ ReadAndUpdateVerifyContext(FILE *fp,
 }
 
 /**
  * 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 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
  *                        the data stored
  * @param  certCount      The number of elements in certData and certDataSizes
  * @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) {
     fprintf(stderr, "ERROR: Invalid parameter specified.\n");
     goto failure;
   }
 
   if (!mar->fp) {
@@ -200,39 +154,34 @@ mar_verify_signaturesW(MarFile *mar,
 
   if (CryptoX_Failed(CryptoX_InitCryptoProvider(&provider))) { 
     fprintf(stderr, "ERROR: Could not init crytpo library.\n");
     goto failure;
   }
 
   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;
     }
   }
 
   rv = mar_extract_and_verify_signatures_fp(mar->fp, provider, keys, certCount);
 
 failure:
 
   for (k = 0; k < certCount; ++k) {
     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,
  * then calls mar_verify_signatures_for_fp to verify each signature.
  *
  * @param  fp       An opened MAR file handle
  * @param  provider A library provider
  * @param  keys     The public keys to use to verify the MAR