Bug 1832523 - Allow using NSS to sign and verify MAR signatures. r=application-update-reviewers,glandium,bytesized

Allow using NSS for checking MAR signatures also in platforms where
OS-native APIs are used by default, i.e., macOS and Windows.

Differential Revision: https://phabricator.services.mozilla.com/D177743
This commit is contained in:
Pier Angelo Vendrame 2023-06-14 16:36:04 +00:00
parent 92cede474d
commit 218d20a569
7 changed files with 93 additions and 39 deletions

View File

@ -54,6 +54,29 @@ set_config(
depends_if("--enable-unverified-updates")(lambda _: True), depends_if("--enable-unverified-updates")(lambda _: True),
) )
# Use NSS for MAR signatures even on platforms where system libraries are
# supported (currently Windows and macOS).
# ==============================================================
can_toggle_nss_mar = target_is_windows | target_is_osx
option(
"--enable-nss-mar",
when=can_toggle_nss_mar,
help="Enable using NSS to check MAR signatures instead of system crypto.",
)
@depends(
depends("--enable-nss-mar", when=can_toggle_nss_mar)(lambda x: x),
can_toggle_nss_mar,
)
def enable_nss_mar(enabled, can_toggle_nss_mar):
return enabled or not can_toggle_nss_mar
set_config("MOZ_USE_NSS_FOR_MAR", True, when=enable_nss_mar)
# Maintenance service (Windows only) # Maintenance service (Windows only)
# ============================================================== # ==============================================================

View File

@ -18,7 +18,7 @@
# include <unistd.h> # include <unistd.h>
#endif #endif
#if !defined(NO_SIGN_VERIFY) && (!defined(XP_WIN) || defined(MAR_NSS)) #if !defined(NO_SIGN_VERIFY) && defined(MAR_NSS)
# include "cert.h" # include "cert.h"
# include "nss.h" # include "nss.h"
# include "pk11pub.h" # include "pk11pub.h"
@ -65,7 +65,7 @@ static void print_usage() {
"signed_input_archive.mar base_64_encoded_signature_file " "signed_input_archive.mar base_64_encoded_signature_file "
"changed_signed_output.mar\n"); "changed_signed_output.mar\n");
printf("(i) is the index of the certificate to extract\n"); printf("(i) is the index of the certificate to extract\n");
# if defined(XP_MACOSX) || (defined(XP_WIN) && !defined(MAR_NSS)) # if !defined(MAR_NSS)
printf("Verify a MAR file:\n"); printf("Verify a MAR file:\n");
printf(" mar [-C workingDir] -D DERFilePath -v signed_archive.mar\n"); printf(" mar [-C workingDir] -D DERFilePath -v signed_archive.mar\n");
printf( printf(
@ -135,23 +135,22 @@ int main(int argc, char** argv) {
int32_t sigIndex = -1; int32_t sigIndex = -1;
uint32_t fileSizes[MAX_SIGNATURES]; uint32_t fileSizes[MAX_SIGNATURES];
const uint8_t* certBuffers[MAX_SIGNATURES]; const uint8_t* certBuffers[MAX_SIGNATURES];
# if ((!defined(MAR_NSS) && defined(XP_WIN)) || defined(XP_MACOSX)) || \ # if !defined(MAR_NSS)
((defined(XP_WIN) || defined(XP_MACOSX)) && !defined(MAR_NSS))
char* DERFilePaths[MAX_SIGNATURES]; char* DERFilePaths[MAX_SIGNATURES];
# endif # else
# if (!defined(XP_WIN) && !defined(XP_MACOSX)) || defined(MAR_NSS)
CERTCertificate* certs[MAX_SIGNATURES]; CERTCertificate* certs[MAX_SIGNATURES];
# endif # endif
#endif #endif
memset((void*)certNames, 0, sizeof(certNames)); memset((void*)certNames, 0, sizeof(certNames));
#if defined(XP_WIN) && !defined(MAR_NSS) && !defined(NO_SIGN_VERIFY) #if !defined(NO_SIGN_VERIFY)
memset((void*)certBuffers, 0, sizeof(certBuffers));
#endif
#if !defined(NO_SIGN_VERIFY) && \
((!defined(MAR_NSS) && defined(XP_WIN)) || defined(XP_MACOSX))
memset(DERFilePaths, 0, sizeof(DERFilePaths));
memset(fileSizes, 0, sizeof(fileSizes)); memset(fileSizes, 0, sizeof(fileSizes));
memset((void*)certBuffers, 0, sizeof(certBuffers));
# if !defined(MAR_NSS)
memset(DERFilePaths, 0, sizeof(DERFilePaths));
# else
memset(certs, 0, sizeof(certs));
# endif
#endif #endif
if (argc > 1 && 0 == strcmp(argv[1], "--version")) { if (argc > 1 && 0 == strcmp(argv[1], "--version")) {
@ -181,7 +180,7 @@ int main(int argc, char** argv) {
argc -= 2; argc -= 2;
} }
#if !defined(NO_SIGN_VERIFY) #if !defined(NO_SIGN_VERIFY)
# if (!defined(MAR_NSS) && defined(XP_WIN)) || defined(XP_MACOSX) # if !defined(MAR_NSS)
/* -D DERFilePath, also matches -D[index] DERFilePath /* -D DERFilePath, also matches -D[index] DERFilePath
We allow an index for verifying to be symmetric We allow an index for verifying to be symmetric
with the import and export command line arguments. */ with the import and export command line arguments. */
@ -348,7 +347,7 @@ int main(int argc, char** argv) {
return -1; return -1;
} }
# if (!defined(XP_WIN) && !defined(XP_MACOSX)) || defined(MAR_NSS) # if defined(MAR_NSS)
if (!NSSConfigDir || certCount == 0) { if (!NSSConfigDir || certCount == 0) {
print_usage(); print_usage();
return -1; return -1;
@ -362,7 +361,7 @@ int main(int argc, char** argv) {
rv = 0; rv = 0;
for (k = 0; k < certCount; ++k) { for (k = 0; k < certCount; ++k) {
# if (defined(XP_WIN) || defined(XP_MACOSX)) && !defined(MAR_NSS) # if !defined(MAR_NSS)
rv = mar_read_entire_file(DERFilePaths[k], MAR_MAX_CERT_SIZE, rv = mar_read_entire_file(DERFilePaths[k], MAR_MAX_CERT_SIZE,
&certBuffers[k], &fileSizes[k]); &certBuffers[k], &fileSizes[k]);
@ -404,7 +403,7 @@ int main(int argc, char** argv) {
} }
} }
for (k = 0; k < certCount; ++k) { for (k = 0; k < certCount; ++k) {
# if (defined(XP_WIN) || defined(XP_MACOSX)) && !defined(MAR_NSS) # if !defined(MAR_NSS)
free((void*)certBuffers[k]); free((void*)certBuffers[k]);
# else # else
/* certBuffers[k] is owned by certs[k] so don't free it */ /* certBuffers[k] is owned by certs[k] so don't free it */
@ -423,7 +422,7 @@ int main(int argc, char** argv) {
" no signature to verify.\n"); " no signature to verify.\n");
} }
} }
# if (!defined(XP_WIN) && !defined(XP_MACOSX)) || defined(MAR_NSS) # if defined(MAR_NSS)
(void)NSS_Shutdown(); (void)NSS_Shutdown();
# endif # endif
return rv ? -1 : 0; return rv ? -1 : 0;

View File

@ -43,15 +43,21 @@ if CONFIG["MOZ_BUILD_APP"] != "tools/update-packaging":
"verifymar", "verifymar",
] ]
if CONFIG["MOZ_USE_NSS_FOR_MAR"]:
DEFINES["MAR_NSS"] = True
if CONFIG["OS_ARCH"] == "WINNT": if CONFIG["OS_ARCH"] == "WINNT":
USE_STATIC_LIBS = True USE_STATIC_LIBS = True
OS_LIBS += [ OS_LIBS += [
"ws2_32", "ws2_32",
"crypt32",
"advapi32",
] ]
elif CONFIG["OS_ARCH"] == "Darwin": if not CONFIG["MOZ_USE_NSS_FOR_MAR"]:
OS_LIBS += [
"crypt32",
"advapi32",
]
elif CONFIG["OS_ARCH"] == "Darwin" and not CONFIG["MOZ_USE_NSS_FOR_MAR"]:
OS_LIBS += [ OS_LIBS += [
"-framework CoreFoundation", "-framework CoreFoundation",
"-framework Security", "-framework Security",

View File

@ -15,7 +15,7 @@ FORCE_STATIC_LIB = True
if CONFIG["OS_ARCH"] == "WINNT": if CONFIG["OS_ARCH"] == "WINNT":
USE_STATIC_LIBS = True USE_STATIC_LIBS = True
elif CONFIG["OS_ARCH"] == "Darwin": elif CONFIG["OS_ARCH"] == "Darwin" and not CONFIG["MOZ_USE_NSS_FOR_MAR"]:
UNIFIED_SOURCES += [ UNIFIED_SOURCES += [
"MacVerifyCrypto.cpp", "MacVerifyCrypto.cpp",
] ]
@ -23,25 +23,28 @@ elif CONFIG["OS_ARCH"] == "Darwin":
"-framework Security", "-framework Security",
] ]
else: else:
DEFINES["MAR_NSS"] = True
LOCAL_INCLUDES += ["../sign"]
USE_LIBS += [ USE_LIBS += [
"nspr", "nspr",
"nss", "nss",
"signmar", "signmar",
] ]
# Ideally, this would be '-Wl,-rpath=$ORIGIN', but the build system if CONFIG["OS_ARCH"] != "Darwin":
# doesn't do the right escaping yet. Even more ideally, this would # Ideally, this would be '-Wl,-rpath=$ORIGIN', but the build system
# be LDFLAGS, but the build system doesn't propagate those like USE_LIBS # doesn't do the right escaping yet. Even more ideally, this would
# and OS_LIBS. Bug #1041943. # be LDFLAGS, but the build system doesn't propagate those like
OS_LIBS += [ # USE_LIBS and OS_LIBS. Bug #1041943.
"-Wl,-rpath=\\$$ORIGIN", OS_LIBS += [
] "-Wl,-rpath=\\$$ORIGIN",
]
LOCAL_INCLUDES += [ LOCAL_INCLUDES += [
"../src", "../src",
] ]
if CONFIG["MOZ_USE_NSS_FOR_MAR"]:
LOCAL_INCLUDES += ["../sign"]
DEFINES["MAR_NSS"] = True
# C11 for static_assert # C11 for static_assert
c11_flags = ["-std=gnu11"] c11_flags = ["-std=gnu11"]
if CONFIG["CC_TYPE"] == "clang-cl": if CONFIG["CC_TYPE"] == "clang-cl":

View File

@ -4,6 +4,12 @@
# License, v. 2.0. If a copy of the MPL was not distributed with this # License, v. 2.0. If a copy of the MPL was not distributed with this
# file, You can obtain one at http://mozilla.org/MPL/2.0/. # file, You can obtain one at http://mozilla.org/MPL/2.0/.
link_with_nss = CONFIG["MOZ_USE_NSS_FOR_MAR"] or (
CONFIG["OS_ARCH"] == "Linux" and CONFIG["MOZ_VERIFY_MAR_SIGNATURE"]
)
if link_with_nss:
DEFINES["MAR_NSS"] = True
srcs = [ srcs = [
"archivereader.cpp", "archivereader.cpp",
"updater.cpp", "updater.cpp",
@ -36,14 +42,18 @@ if CONFIG["OS_ARCH"] == "WINNT":
"ws2_32", "ws2_32",
"shell32", "shell32",
"shlwapi", "shlwapi",
"crypt32",
"advapi32",
"gdi32", "gdi32",
"user32", "user32",
"userenv", "userenv",
"uuid", "uuid",
] ]
if not link_with_nss:
OS_LIBS += [
"crypt32",
"advapi32",
]
USE_LIBS += [ USE_LIBS += [
"bspatch", "bspatch",
"mar", "mar",
@ -51,6 +61,13 @@ USE_LIBS += [
"xz-embedded", "xz-embedded",
] ]
if link_with_nss:
USE_LIBS += [
"nspr",
"nss",
"signmar",
]
if CONFIG["MOZ_WIDGET_TOOLKIT"] == "gtk": if CONFIG["MOZ_WIDGET_TOOLKIT"] == "gtk":
have_progressui = 1 have_progressui = 1
srcs += [ srcs += [
@ -65,9 +82,14 @@ if CONFIG["MOZ_WIDGET_TOOLKIT"] == "cocoa":
] ]
OS_LIBS += [ OS_LIBS += [
"-framework Cocoa", "-framework Cocoa",
"-framework Security",
"-framework SystemConfiguration", "-framework SystemConfiguration",
] ]
if link_with_nss:
LDFLAGS += ["-Wl,-rpath,@executable_path/../../../"]
else:
OS_LIBS += [
"-framework Security",
]
UNIFIED_SOURCES += [ UNIFIED_SOURCES += [
"/toolkit/xre/updaterfileutils_osx.mm", "/toolkit/xre/updaterfileutils_osx.mm",
] ]

View File

@ -107,7 +107,7 @@ struct UpdateServerThreadArgs {
# define stat64 stat # define stat64 stat
#endif #endif
#if defined(MOZ_VERIFY_MAR_SIGNATURE) && !defined(XP_WIN) && !defined(XP_MACOSX) #if defined(MOZ_VERIFY_MAR_SIGNATURE) && defined(MAR_NSS)
# include "nss.h" # include "nss.h"
# include "prerror.h" # include "prerror.h"
#endif #endif
@ -2892,11 +2892,9 @@ int NS_main(int argc, NS_tchar** argv) {
if (!isDMGInstall) { if (!isDMGInstall) {
// Skip update-related code path for DMG installs. // Skip update-related code path for DMG installs.
#if defined(MOZ_VERIFY_MAR_SIGNATURE) && !defined(XP_WIN) && !defined(XP_MACOSX) #if defined(MOZ_VERIFY_MAR_SIGNATURE) && defined(MAR_NSS)
// On Windows and Mac we rely on native APIs to do verifications so we don't // If using NSS for signature verification, initialize NSS but minimize
// need to initialize NSS at all there. // the portion we depend on by avoiding all of the NSS databases.
// Otherwise, minimize the amount of NSS we depend on by avoiding all the
// NSS databases.
if (NSS_NoDB_Init(nullptr) != SECSuccess) { if (NSS_NoDB_Init(nullptr) != SECSuccess) {
PRErrorCode error = PR_GetError(); PRErrorCode error = PR_GetError();
fprintf(stderr, "Could not initialize NSS: %s (%d)", fprintf(stderr, "Could not initialize NSS: %s (%d)",

View File

@ -228,6 +228,9 @@ for var in ("APP_VERSION", "APP_ID"):
if CONFIG["MOZ_BUILD_APP"] == "browser": if CONFIG["MOZ_BUILD_APP"] == "browser":
DEFINES["MOZ_BUILD_APP_IS_BROWSER"] = True DEFINES["MOZ_BUILD_APP_IS_BROWSER"] = True
if CONFIG["MOZ_USE_NSS_FOR_MAR"]:
DEFINES["MAR_NSS"] = True
LOCAL_INCLUDES += [ LOCAL_INCLUDES += [
"../../other-licenses/nsis/Contrib/CityHash/cityhash", "../../other-licenses/nsis/Contrib/CityHash/cityhash",
"../components/find", "../components/find",