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 491336 901956eef6c9bf29f54c96ed811474089cfa0ee4
parent 491335 02550df602110228ea56505b532ceddbc250c5a6
child 491337 64255585a5b787d2cc86b3be79aa20ff468f7fdc
push id47343
push userbmo:dothayer@mozilla.com
push dateWed, 01 Mar 2017 22:58:58 +0000
reviewersbbondy
bugs903135
milestone36.0a1
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