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),
)
# 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)
# ==============================================================

View File

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

View File

@ -43,15 +43,21 @@ if CONFIG["MOZ_BUILD_APP"] != "tools/update-packaging":
"verifymar",
]
if CONFIG["MOZ_USE_NSS_FOR_MAR"]:
DEFINES["MAR_NSS"] = True
if CONFIG["OS_ARCH"] == "WINNT":
USE_STATIC_LIBS = True
OS_LIBS += [
"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 += [
"-framework CoreFoundation",
"-framework Security",

View File

@ -15,7 +15,7 @@ FORCE_STATIC_LIB = True
if CONFIG["OS_ARCH"] == "WINNT":
USE_STATIC_LIBS = True
elif CONFIG["OS_ARCH"] == "Darwin":
elif CONFIG["OS_ARCH"] == "Darwin" and not CONFIG["MOZ_USE_NSS_FOR_MAR"]:
UNIFIED_SOURCES += [
"MacVerifyCrypto.cpp",
]
@ -23,25 +23,28 @@ elif CONFIG["OS_ARCH"] == "Darwin":
"-framework Security",
]
else:
DEFINES["MAR_NSS"] = True
LOCAL_INCLUDES += ["../sign"]
USE_LIBS += [
"nspr",
"nss",
"signmar",
]
# Ideally, this would be '-Wl,-rpath=$ORIGIN', but the build system
# doesn't do the right escaping yet. Even more ideally, this would
# be LDFLAGS, but the build system doesn't propagate those like USE_LIBS
# and OS_LIBS. Bug #1041943.
OS_LIBS += [
"-Wl,-rpath=\\$$ORIGIN",
]
if CONFIG["OS_ARCH"] != "Darwin":
# Ideally, this would be '-Wl,-rpath=$ORIGIN', but the build system
# doesn't do the right escaping yet. Even more ideally, this would
# be LDFLAGS, but the build system doesn't propagate those like
# USE_LIBS and OS_LIBS. Bug #1041943.
OS_LIBS += [
"-Wl,-rpath=\\$$ORIGIN",
]
LOCAL_INCLUDES += [
"../src",
]
if CONFIG["MOZ_USE_NSS_FOR_MAR"]:
LOCAL_INCLUDES += ["../sign"]
DEFINES["MAR_NSS"] = True
# C11 for static_assert
c11_flags = ["-std=gnu11"]
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
# 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 = [
"archivereader.cpp",
"updater.cpp",
@ -36,14 +42,18 @@ if CONFIG["OS_ARCH"] == "WINNT":
"ws2_32",
"shell32",
"shlwapi",
"crypt32",
"advapi32",
"gdi32",
"user32",
"userenv",
"uuid",
]
if not link_with_nss:
OS_LIBS += [
"crypt32",
"advapi32",
]
USE_LIBS += [
"bspatch",
"mar",
@ -51,6 +61,13 @@ USE_LIBS += [
"xz-embedded",
]
if link_with_nss:
USE_LIBS += [
"nspr",
"nss",
"signmar",
]
if CONFIG["MOZ_WIDGET_TOOLKIT"] == "gtk":
have_progressui = 1
srcs += [
@ -65,9 +82,14 @@ if CONFIG["MOZ_WIDGET_TOOLKIT"] == "cocoa":
]
OS_LIBS += [
"-framework Cocoa",
"-framework Security",
"-framework SystemConfiguration",
]
if link_with_nss:
LDFLAGS += ["-Wl,-rpath,@executable_path/../../../"]
else:
OS_LIBS += [
"-framework Security",
]
UNIFIED_SOURCES += [
"/toolkit/xre/updaterfileutils_osx.mm",
]

View File

@ -107,7 +107,7 @@ struct UpdateServerThreadArgs {
# define stat64 stat
#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 "prerror.h"
#endif
@ -2892,11 +2892,9 @@ int NS_main(int argc, NS_tchar** argv) {
if (!isDMGInstall) {
// Skip update-related code path for DMG installs.
#if defined(MOZ_VERIFY_MAR_SIGNATURE) && !defined(XP_WIN) && !defined(XP_MACOSX)
// On Windows and Mac we rely on native APIs 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 defined(MOZ_VERIFY_MAR_SIGNATURE) && defined(MAR_NSS)
// If using NSS for signature verification, initialize NSS but minimize
// the portion we depend on by avoiding all of the NSS databases.
if (NSS_NoDB_Init(nullptr) != SECSuccess) {
PRErrorCode error = PR_GetError();
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":
DEFINES["MOZ_BUILD_APP_IS_BROWSER"] = True
if CONFIG["MOZ_USE_NSS_FOR_MAR"]:
DEFINES["MAR_NSS"] = True
LOCAL_INCLUDES += [
"../../other-licenses/nsis/Contrib/CityHash/cityhash",
"../components/find",