mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-11-25 05:41:12 +00:00
Bug 1317947 - land NSS ee21c9892907, r=me
This commit is contained in:
parent
59f6549539
commit
3594725777
1
security/nss/.gitignore
vendored
1
security/nss/.gitignore
vendored
@ -17,3 +17,4 @@ GTAGS
|
||||
.ycm_extra_conf.py*
|
||||
fuzz/libFuzzer/*
|
||||
fuzz/corpus
|
||||
fuzz/out
|
||||
|
@ -1 +1 @@
|
||||
6353ce63e18f
|
||||
ee21c9892907
|
||||
|
@ -0,0 +1,27 @@
|
||||
FROM aarch64/ubuntu:xenial-20161213
|
||||
MAINTAINER Franziskus Kiefer <franziskuskiefer@gmail.com>
|
||||
|
||||
RUN useradd -d /home/worker -s /bin/bash -m worker
|
||||
WORKDIR /home/worker
|
||||
|
||||
# Add build and test scripts.
|
||||
ADD bin /home/worker/bin
|
||||
RUN chmod +x /home/worker/bin/*
|
||||
|
||||
# Install dependencies.
|
||||
ADD setup.sh /tmp/setup.sh
|
||||
RUN bash /tmp/setup.sh
|
||||
|
||||
# Env variables.
|
||||
ENV HOME /home/worker
|
||||
ENV SHELL /bin/bash
|
||||
ENV USER worker
|
||||
ENV LOGNAME worker
|
||||
ENV HOSTNAME taskcluster-worker
|
||||
ENV LANG en_US.UTF-8
|
||||
ENV LC_ALL en_US.UTF-8
|
||||
ENV HOST localhost
|
||||
ENV DOMSUF localdomain
|
||||
|
||||
# Set a default command for debugging.
|
||||
CMD ["/bin/bash", "--login"]
|
20
security/nss/automation/taskcluster/docker-aarch64/bin/checkout.sh
Executable file
20
security/nss/automation/taskcluster/docker-aarch64/bin/checkout.sh
Executable file
@ -0,0 +1,20 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
set -v -e -x
|
||||
|
||||
if [ $(id -u) = 0 ]; then
|
||||
# Drop privileges by re-running this script.
|
||||
exec su worker $0
|
||||
fi
|
||||
|
||||
# Default values for testing.
|
||||
REVISION=${NSS_HEAD_REVISION:-default}
|
||||
REPOSITORY=${NSS_HEAD_REPOSITORY:-https://hg.mozilla.org/projects/nss}
|
||||
|
||||
# Clone NSS.
|
||||
for i in 0 2 5; do
|
||||
sleep $i
|
||||
hg clone -r $REVISION $REPOSITORY nss && exit 0
|
||||
rm -rf nss
|
||||
done
|
||||
exit 1
|
31
security/nss/automation/taskcluster/docker-aarch64/setup.sh
Executable file
31
security/nss/automation/taskcluster/docker-aarch64/setup.sh
Executable file
@ -0,0 +1,31 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
set -v -e -x
|
||||
|
||||
export DEBIAN_FRONTEND=noninteractive
|
||||
|
||||
# Update.
|
||||
apt-get -y update
|
||||
apt-get -y dist-upgrade
|
||||
|
||||
apt_packages=()
|
||||
apt_packages+=('build-essential')
|
||||
apt_packages+=('ca-certificates')
|
||||
apt_packages+=('curl')
|
||||
apt_packages+=('zlib1g-dev')
|
||||
apt_packages+=('gyp')
|
||||
apt_packages+=('ninja-build')
|
||||
apt_packages+=('mercurial')
|
||||
|
||||
# Install packages.
|
||||
apt-get install -y --no-install-recommends ${apt_packages[@]}
|
||||
|
||||
locale-gen en_US.UTF-8
|
||||
dpkg-reconfigure locales
|
||||
|
||||
# Cleanup.
|
||||
rm -rf ~/.ccache ~/.cache
|
||||
apt-get autoremove -y
|
||||
apt-get clean
|
||||
apt-get autoclean
|
||||
rm $0
|
@ -12,6 +12,9 @@ RUN chmod +x /home/worker/bin/*
|
||||
ADD setup.sh /tmp/setup.sh
|
||||
RUN bash /tmp/setup.sh
|
||||
|
||||
# Change user.
|
||||
USER worker
|
||||
|
||||
# Env variables.
|
||||
ENV HOME /home/worker
|
||||
ENV SHELL /bin/bash
|
||||
@ -23,5 +26,8 @@ ENV LC_ALL en_US.UTF-8
|
||||
ENV HOST localhost
|
||||
ENV DOMSUF localdomain
|
||||
|
||||
# LLVM 4.0
|
||||
ENV PATH "${PATH}:/home/worker/third_party/llvm-build/Release+Asserts/bin/"
|
||||
|
||||
# Set a default command for debugging.
|
||||
CMD ["/bin/bash", "--login"]
|
||||
|
@ -19,9 +19,6 @@ apt_packages+=('ninja-build')
|
||||
apt_packages+=('pkg-config')
|
||||
apt_packages+=('zlib1g-dev')
|
||||
|
||||
# ct-verif and sanitizers
|
||||
apt_packages+=('valgrind')
|
||||
|
||||
# Latest Mercurial.
|
||||
apt_packages+=('mercurial')
|
||||
apt-key adv --keyserver keyserver.ubuntu.com --recv-keys 41BD8711B1F0EC2B0D85B91CF59CE3A8323293EE
|
||||
@ -38,11 +35,6 @@ git -C clang-tmp/clang checkout HEAD scripts/update.py
|
||||
clang-tmp/clang/scripts/update.py
|
||||
rm -fr clang-tmp
|
||||
|
||||
# Link to LLVM binaries.
|
||||
for b in clang clang++ llvm-symbolizer; do
|
||||
ln -s /home/worker/third_party/llvm-build/Release+Asserts/bin/$b /usr/local/bin/$b
|
||||
done
|
||||
|
||||
locale-gen en_US.UTF-8
|
||||
dpkg-reconfigure locales
|
||||
|
||||
|
@ -12,6 +12,9 @@ RUN chmod +x /home/worker/bin/*
|
||||
ADD setup.sh /tmp/setup.sh
|
||||
RUN bash /tmp/setup.sh
|
||||
|
||||
# Change user.
|
||||
USER worker
|
||||
|
||||
# Env variables.
|
||||
ENV HOME /home/worker
|
||||
ENV SHELL /bin/bash
|
||||
@ -23,5 +26,8 @@ ENV LC_ALL en_US.UTF-8
|
||||
ENV HOST localhost
|
||||
ENV DOMSUF localdomain
|
||||
|
||||
# Rust + Go
|
||||
ENV PATH "${PATH}:/home/worker/.cargo/bin/:/usr/lib/go-1.6/bin"
|
||||
|
||||
# Set a default command for debugging.
|
||||
CMD ["/bin/bash", "--login"]
|
||||
|
@ -49,7 +49,11 @@ apt-get install -y --no-install-recommends ${apt_packages[@]}
|
||||
ln -s /usr/include/x86_64-linux-gnu/zconf.h /usr/include
|
||||
|
||||
# Install clang-3.9 into /usr/local/.
|
||||
curl http://llvm.org/releases/3.9.0/clang+llvm-3.9.0-x86_64-linux-gnu-ubuntu-16.04.tar.xz | tar xJv -C /usr/local --strip-components=1
|
||||
# FIXME: verify signature
|
||||
curl -L http://releases.llvm.org/3.9.0/clang+llvm-3.9.0-x86_64-linux-gnu-ubuntu-16.04.tar.xz | tar xJv -C /usr/local --strip-components=1
|
||||
|
||||
# Install latest Rust (stable).
|
||||
su worker -c "curl https://sh.rustup.rs -sSf | sh -s -- -y"
|
||||
|
||||
locale-gen en_US.UTF-8
|
||||
dpkg-reconfigure locales
|
||||
|
@ -30,18 +30,23 @@ queue.filter(task => {
|
||||
}
|
||||
}
|
||||
|
||||
if (task.tests == "bogo") {
|
||||
// No BoGo tests on Windows.
|
||||
if (task.tests == "bogo" || task.tests == "interop") {
|
||||
// No windows
|
||||
if (task.platform == "windows2012-64") {
|
||||
return false;
|
||||
}
|
||||
|
||||
// No BoGo tests on ARM.
|
||||
// No ARM
|
||||
if (task.collection == "arm-debug") {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// Temporarily disable SSL tests on ARM.
|
||||
if (task.tests == "ssl" && task.collection == "arm-debug") {
|
||||
return false;
|
||||
}
|
||||
|
||||
// GYP builds with -Ddisable_libpkix=1 by default.
|
||||
if ((task.collection == "gyp" || task.collection == "gyp-asan") &&
|
||||
task.tests == "chains") {
|
||||
@ -280,7 +285,7 @@ async function scheduleFuzzing() {
|
||||
"/bin/bash",
|
||||
"-c",
|
||||
"bin/checkout.sh && " +
|
||||
"nss/automation/taskcluster/scripts/build_gyp.sh -g -v --fuzz"
|
||||
"nss/automation/taskcluster/scripts/build_gyp.sh -g -v --fuzz=tls"
|
||||
],
|
||||
artifacts: {
|
||||
public: {
|
||||
@ -316,31 +321,16 @@ async function scheduleFuzzing() {
|
||||
|
||||
queue.scheduleTask(merge(base, {
|
||||
parent: task_build,
|
||||
name: "Cert",
|
||||
name: "QuickDER",
|
||||
command: [
|
||||
"/bin/bash",
|
||||
"-c",
|
||||
"bin/checkout.sh && nss/automation/taskcluster/scripts/fuzz.sh " +
|
||||
"cert nss/fuzz/corpus/cert -max_total_time=300"
|
||||
"quickder nss/fuzz/corpus/quickder -max_total_time=300"
|
||||
],
|
||||
// Need a privileged docker container to remove this.
|
||||
env: {ASAN_OPTIONS: "detect_leaks=0"},
|
||||
symbol: "SCert",
|
||||
kind: "test"
|
||||
}));
|
||||
|
||||
queue.scheduleTask(merge(base, {
|
||||
parent: task_build,
|
||||
name: "SPKI",
|
||||
command: [
|
||||
"/bin/bash",
|
||||
"-c",
|
||||
"bin/checkout.sh && nss/automation/taskcluster/scripts/fuzz.sh " +
|
||||
"spki nss/fuzz/corpus/spki -max_total_time=300"
|
||||
],
|
||||
// Need a privileged docker container to remove this.
|
||||
env: {ASAN_OPTIONS: "detect_leaks=0"},
|
||||
symbol: "SPKI",
|
||||
symbol: "QuickDER",
|
||||
kind: "test"
|
||||
}));
|
||||
|
||||
@ -363,7 +353,7 @@ async function scheduleTestBuilds() {
|
||||
"/bin/bash",
|
||||
"-c",
|
||||
"bin/checkout.sh && " +
|
||||
"nss/automation/taskcluster/scripts/build_gyp.sh -g -v --test"
|
||||
"nss/automation/taskcluster/scripts/build_gyp.sh -g -v --test --ct-verif"
|
||||
],
|
||||
artifacts: {
|
||||
public: {
|
||||
@ -471,6 +461,9 @@ function scheduleTests(task_build, task_cert, test_base) {
|
||||
queue.scheduleTask(merge(no_cert_base, {
|
||||
name: "Bogo tests", symbol: "Bogo", tests: "bogo", cycle: "standard"
|
||||
}));
|
||||
queue.scheduleTask(merge(no_cert_base, {
|
||||
name: "Interop tests", symbol: "Interop", tests: "interop", cycle: "standard"
|
||||
}));
|
||||
queue.scheduleTask(merge(no_cert_base, {
|
||||
name: "Chains tests", symbol: "Chains", tests: "chains"
|
||||
}));
|
||||
|
@ -34,7 +34,7 @@ function parseOptions(opts) {
|
||||
// Parse unit tests.
|
||||
let aliases = {"gtests": "gtest"};
|
||||
let allUnitTests = ["bogo", "crmf", "chains", "cipher", "db", "ec", "fips",
|
||||
"gtest", "lowhash", "merge", "sdr", "smime", "tools",
|
||||
"gtest", "interop", "lowhash", "merge", "sdr", "smime", "tools",
|
||||
"ssl", "mpi", "scert", "spki"];
|
||||
let unittests = intersect(opts.unittests.split(/\s*,\s*/).map(t => {
|
||||
return aliases[t] || t;
|
||||
|
@ -1,14 +1,9 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
source $(dirname $0)/tools.sh
|
||||
|
||||
if [[ $(id -u) -eq 0 ]]; then
|
||||
# Drop privileges by re-running this script.
|
||||
exec su worker $0
|
||||
fi
|
||||
source $(dirname "$0")/tools.sh
|
||||
|
||||
# Clone NSPR if needed.
|
||||
hg_clone https://hg.mozilla.org/projects/nspr nspr default
|
||||
hg_clone https://hg.mozilla.org/projects/nspr ./nspr default
|
||||
|
||||
# Build.
|
||||
make -C nss nss_build_all
|
||||
|
@ -1,17 +1,12 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
source $(dirname $0)/tools.sh
|
||||
|
||||
if [[ $(id -u) -eq 0 ]]; then
|
||||
# Drop privileges by re-running this script.
|
||||
exec su worker -c "$0 $*"
|
||||
fi
|
||||
source $(dirname "$0")/tools.sh
|
||||
|
||||
# Clone NSPR if needed.
|
||||
hg_clone https://hg.mozilla.org/projects/nspr nspr default
|
||||
hg_clone https://hg.mozilla.org/projects/nspr ./nspr default
|
||||
|
||||
# Build.
|
||||
nss/build.sh ${*--g -v}
|
||||
nss/build.sh -g -v "$@"
|
||||
|
||||
# Package.
|
||||
mkdir artifacts
|
||||
|
@ -1,11 +1,6 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
set -v -e -x
|
||||
|
||||
if [ $(id -u) = 0 ]; then
|
||||
# Drop privileges by re-running this script.
|
||||
exec su worker $0
|
||||
fi
|
||||
source $(dirname "$0")/tools.sh
|
||||
|
||||
mkdir -p /home/worker/artifacts
|
||||
|
||||
|
@ -1,11 +1,9 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
source $(dirname $0)/tools.sh
|
||||
source $(dirname "$0")/tools.sh
|
||||
|
||||
if [ $(id -u) = 0 ]; then
|
||||
# Drop privileges by re-running this script.
|
||||
exec su worker -c "$0 $*"
|
||||
fi
|
||||
type="$1"
|
||||
shift
|
||||
|
||||
# Fetch artifact if needed.
|
||||
fetch_dist
|
||||
@ -13,8 +11,11 @@ fetch_dist
|
||||
# Clone corpus.
|
||||
./nss/fuzz/clone_corpus.sh
|
||||
|
||||
# Ensure we have a directory.
|
||||
mkdir -p nss/fuzz/corpus/$type
|
||||
|
||||
# Fetch objdir name.
|
||||
objdir=$(cat dist/latest)
|
||||
|
||||
# Run nssfuzz.
|
||||
LD_LIBRARY_PATH=$LD_LIBRARY_PATH:dist/$objdir/lib dist/$objdir/bin/nssfuzz $*
|
||||
dist/$objdir/bin/nssfuzz-"$type" "$@"
|
||||
|
@ -1,16 +1,6 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
set -v -e -x
|
||||
|
||||
source $(dirname $0)/tools.sh
|
||||
|
||||
if [ $(id -u) = 0 ]; then
|
||||
# Stupid Docker.
|
||||
echo "127.0.0.1 localhost.localdomain" >> /etc/hosts
|
||||
|
||||
# Drop privileges by re-running this script.
|
||||
exec su worker $0
|
||||
fi
|
||||
source $(dirname "$0")/tools.sh
|
||||
|
||||
# Fetch artifact if needed.
|
||||
fetch_dist
|
||||
|
@ -1,11 +1,6 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
set -v -e -x
|
||||
|
||||
if [ $(id -u) -eq 0 ]; then
|
||||
# Drop privileges by re-running this script.
|
||||
exec su worker $0 "$@"
|
||||
fi
|
||||
source $(dirname "$0")/tools.sh
|
||||
|
||||
# Apply clang-format on the provided folder and verify that this doesn't change any file.
|
||||
# If any file differs after formatting, the script eventually exits with 1.
|
||||
@ -46,6 +41,7 @@ else
|
||||
"$top/gtests/pk11_gtest" \
|
||||
"$top/gtests/ssl_gtest" \
|
||||
"$top/gtests/util_gtest" \
|
||||
"$top/nss-tool" \
|
||||
)
|
||||
fi
|
||||
|
||||
|
@ -1,15 +1,10 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
source $(dirname $0)/tools.sh
|
||||
|
||||
if [ $(id -u) = 0 ]; then
|
||||
# Drop privileges by re-running this script.
|
||||
exec su worker $0 $@
|
||||
fi
|
||||
source $(dirname "$0")/tools.sh
|
||||
|
||||
# Clone NSPR if needed.
|
||||
if [ ! -d "nspr" ]; then
|
||||
hg_clone https://hg.mozilla.org/projects/nspr nspr default
|
||||
hg_clone https://hg.mozilla.org/projects/nspr ./nspr default
|
||||
fi
|
||||
|
||||
# Build.
|
||||
|
@ -1,14 +1,6 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
source $(dirname $0)/tools.sh
|
||||
|
||||
if [ $(id -u) = 0 ]; then
|
||||
# Stupid Docker.
|
||||
echo "127.0.0.1 localhost.localdomain" >> /etc/hosts
|
||||
|
||||
# Drop privileges by re-running this script.
|
||||
exec su worker $0
|
||||
fi
|
||||
source $(dirname "$0")/tools.sh
|
||||
|
||||
# Fetch artifact if needed.
|
||||
fetch_dist
|
||||
|
@ -2,11 +2,21 @@
|
||||
|
||||
set -v -e -x
|
||||
|
||||
if [[ $(id -u) -eq 0 ]]; then
|
||||
# Drop privileges by re-running this script.
|
||||
# Note: this mangles arguments, better to avoid running scripts as root.
|
||||
exec su worker -c "$0 $*"
|
||||
fi
|
||||
|
||||
# Usage: hg_clone repo dir [revision=@]
|
||||
hg_clone() {
|
||||
repo=$1
|
||||
dir=$2
|
||||
rev=${3:-@}
|
||||
if [ -d "$dir" ]; then
|
||||
hg pull -R "$dir" -ur "$rev" "$repo" && return
|
||||
rm -rf "$dir"
|
||||
fi
|
||||
for i in 0 2 5; do
|
||||
sleep $i
|
||||
hg clone -r "$rev" "$repo" "$dir" && return
|
||||
|
@ -6,15 +6,18 @@
|
||||
|
||||
set -e
|
||||
|
||||
source $(dirname $0)/coreconf/nspr.sh
|
||||
cwd=$(cd $(dirname $0); pwd -P)
|
||||
source "$cwd"/coreconf/nspr.sh
|
||||
source "$cwd"/coreconf/sanitizers.sh
|
||||
|
||||
# Usage info
|
||||
show_help() {
|
||||
cat << EOF
|
||||
|
||||
Usage: ${0##*/} [-hcgv] [-j <n>] [--test] [--fuzz] [--scan-build[=output]]
|
||||
[-m32] [--opt|-o] [--asan] [--ubsan] [--sancov[=edge|bb|func|...]]
|
||||
[--pprof] [--msan]
|
||||
show_help()
|
||||
{
|
||||
cat << EOF
|
||||
Usage: ${0##*/} [-hcv] [-j <n>] [--nspr] [--gyp|-g] [--opt|-o] [-m32]
|
||||
[--test] [--pprof] [--scan-build[=output]] [--ct-verif]
|
||||
[--asan] [--ubsan] [--msan] [--sancov[=edge|bb|func|...]]
|
||||
[--disable-tests] [--fuzz[=tls|oss]]
|
||||
|
||||
This script builds NSS with gyp and ninja.
|
||||
|
||||
@ -23,27 +26,44 @@ the features or platforms that NSS supports.
|
||||
|
||||
NSS build tool options:
|
||||
|
||||
-h display this help and exit
|
||||
-c clean before build
|
||||
-g force a rebuild of gyp (and NSPR, because why not)
|
||||
-j <n> run at most <n> concurrent jobs
|
||||
-v verbose build
|
||||
-m32 do a 32-bit build on a 64-bit system
|
||||
--test ignore map files and export everything we have
|
||||
--fuzz enable fuzzing mode. this always enables test builds
|
||||
--scan-build run the build with scan-build (scan-build has to be in the path)
|
||||
--scan-build=/out/path sets the output path for scan-build
|
||||
--opt|-o do an opt build
|
||||
--asan do an asan build
|
||||
--ubsan do an ubsan build
|
||||
--ubsan=bool,shift,... sets specific UB sanitizers
|
||||
--msan do an msan build
|
||||
--sancov do sanitize coverage builds
|
||||
--sancov=func sets coverage to function level for example
|
||||
--pprof build with gperftool support
|
||||
-h display this help and exit
|
||||
-c clean before build
|
||||
-v verbose build
|
||||
-j <n> run at most <n> concurrent jobs
|
||||
--nspr force a rebuild of NSPR
|
||||
--gyp|-g force a rerun of gyp
|
||||
--opt|-o do an opt build
|
||||
-m32 do a 32-bit build on a 64-bit system
|
||||
--test ignore map files and export everything we have
|
||||
--fuzz build fuzzing targets (this always enables test builds)
|
||||
--fuzz=tls to enable TLS fuzzing mode
|
||||
--fuzz=oss to build for OSS-Fuzz
|
||||
--pprof build with gperftool support
|
||||
--ct-verif build with valgrind for ct-verif
|
||||
--scan-build run the build with scan-build (scan-build has to be in the path)
|
||||
--scan-build=/out/path sets the output path for scan-build
|
||||
--asan do an asan build
|
||||
--ubsan do an ubsan build
|
||||
--ubsan=bool,shift,... sets specific UB sanitizers
|
||||
--msan do an msan build
|
||||
--sancov do sanitize coverage builds
|
||||
--sancov=func sets coverage to function level for example
|
||||
--disable-tests don't build tests and corresponding cmdline utils
|
||||
EOF
|
||||
}
|
||||
|
||||
run_verbose()
|
||||
{
|
||||
if [ "$verbose" = 1 ]; then
|
||||
echo "$@"
|
||||
exec 3>&1
|
||||
else
|
||||
exec 3>/dev/null
|
||||
fi
|
||||
"$@" 1>&3 2>&3
|
||||
exec 3>&-
|
||||
}
|
||||
|
||||
if [ -n "$CCC" ] && [ -z "$CXX" ]; then
|
||||
export CXX="$CCC"
|
||||
fi
|
||||
@ -52,170 +72,159 @@ opt_build=0
|
||||
build_64=0
|
||||
clean=0
|
||||
rebuild_gyp=0
|
||||
rebuild_nspr=0
|
||||
target=Debug
|
||||
verbose=0
|
||||
fuzz=0
|
||||
ubsan_default=bool,signed-integer-overflow,shift,vptr
|
||||
fuzz_tls=0
|
||||
fuzz_oss=0
|
||||
|
||||
# parse parameters to store in config
|
||||
params=$(echo "$*" | perl -pe 's/-c|-v|-g|-j [0-9]*|-h//g' | perl -pe 's/^\s*(.*?)\s*$/\1/')
|
||||
params=$(echo "$params $CC $CCC" | tr " " "\n" | perl -pe 's/^\s*$//')
|
||||
params=$(echo "${params[*]}" | sort)
|
||||
|
||||
cwd=$(cd $(dirname $0); pwd -P)
|
||||
dist_dir="$cwd/../dist"
|
||||
gyp_params=(--depth="$cwd" --generator-output=".")
|
||||
nspr_params=()
|
||||
ninja_params=()
|
||||
|
||||
# try to guess sensible defaults
|
||||
arch=$(python "$cwd/coreconf/detect_host_arch.py")
|
||||
arch=$(python "$cwd"/coreconf/detect_host_arch.py)
|
||||
if [ "$arch" = "x64" -o "$arch" = "aarch64" ]; then
|
||||
build_64=1
|
||||
fi
|
||||
|
||||
gyp_params=()
|
||||
ninja_params=()
|
||||
scanbuild=()
|
||||
|
||||
sancov_default()
|
||||
{
|
||||
clang_version=$($CC --version | grep -oE 'clang version (3\.9\.|4\.)')
|
||||
if [ -z "$clang_version" ]; then
|
||||
echo "Need at least clang-3.9 (better 4.0) for sancov." 1>&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [ "$clang_version" = "clang version 3.9." ]; then
|
||||
echo edge,indirect-calls,8bit-counters
|
||||
else
|
||||
echo trace-pc-guard
|
||||
fi
|
||||
}
|
||||
|
||||
enable_fuzz()
|
||||
{
|
||||
fuzz=1
|
||||
nspr_sanitizer asan
|
||||
nspr_sanitizer ubsan $ubsan_default
|
||||
nspr_sanitizer sancov $(sancov_default)
|
||||
gyp_params+=(-Duse_asan=1)
|
||||
gyp_params+=(-Duse_ubsan=$ubsan_default)
|
||||
gyp_params+=(-Duse_sancov=$(sancov_default))
|
||||
|
||||
# Adding debug symbols even for opt builds.
|
||||
nspr_opt+=(--enable-debug-symbols)
|
||||
}
|
||||
|
||||
# parse command line arguments
|
||||
while [ $# -gt 0 ]; do
|
||||
case $1 in
|
||||
-c) clean=1 ;;
|
||||
-g) rebuild_gyp=1 ;;
|
||||
--gyp|-g) rebuild_gyp=1 ;;
|
||||
--nspr) nspr_clean; rebuild_nspr=1 ;;
|
||||
-j) ninja_params+=(-j "$2"); shift ;;
|
||||
-v) ninja_params+=(-v); verbose=1 ;;
|
||||
--test) gyp_params+=(-Dtest_build=1) ;;
|
||||
--fuzz) gyp_params+=(-Dtest_build=1 -Dfuzz=1); enable_fuzz ;;
|
||||
--scan-build) scanbuild=(scan-build) ;;
|
||||
--scan-build=?*) scanbuild=(scan-build -o "${1#*=}") ;;
|
||||
--fuzz) fuzz=1 ;;
|
||||
--fuzz=oss) fuzz=1; fuzz_oss=1 ;;
|
||||
--fuzz=tls) fuzz=1; fuzz_tls=1 ;;
|
||||
--scan-build) enable_scanbuild ;;
|
||||
--scan-build=?*) enable_scanbuild "${1#*=}" ;;
|
||||
--opt|-o) opt_build=1 ;;
|
||||
-m32|--m32) build_64=0 ;;
|
||||
--asan) gyp_params+=(-Duse_asan=1); nspr_sanitizer asan ;;
|
||||
--ubsan) gyp_params+=(-Duse_ubsan=$ubsan_default); nspr_sanitizer ubsan $ubsan_default ;;
|
||||
--ubsan=?*) gyp_params+=(-Duse_ubsan="${1#*=}"); nspr_sanitizer ubsan "${1#*=}" ;;
|
||||
--sancov) gyp_params+=(-Duse_sancov=$(sancov_default)); nspr_sanitizer sancov $(sancov_default) ;;
|
||||
--sancov=?*) gyp_params+=(-Duse_sancov="${1#*=}"); nspr_sanitizer sancov "${1#*=}" ;;
|
||||
--asan) enable_sanitizer asan ;;
|
||||
--msan) enable_sanitizer msan ;;
|
||||
--ubsan) enable_ubsan ;;
|
||||
--ubsan=?*) enable_ubsan "${1#*=}" ;;
|
||||
--sancov) enable_sancov ;;
|
||||
--sancov=?*) enable_sancov "${1#*=}" ;;
|
||||
--pprof) gyp_params+=(-Duse_pprof=1) ;;
|
||||
--msan) gyp_params+=(-Duse_msan=1); nspr_sanitizer msan ;;
|
||||
*) show_help; exit ;;
|
||||
--ct-verif) gyp_params+=(-Dct_verif=1) ;;
|
||||
--disable-tests) gyp_params+=(-Ddisable_tests=1) ;;
|
||||
--no-zdefs) gyp_params+=(-Dno_zdefs=1) ;;
|
||||
*) show_help; exit 2 ;;
|
||||
esac
|
||||
shift
|
||||
done
|
||||
|
||||
if [ "$opt_build" = "1" ]; then
|
||||
if [ "$opt_build" = 1 ]; then
|
||||
target=Release
|
||||
nspr_opt+=(--disable-debug --enable-optimize)
|
||||
else
|
||||
target=Debug
|
||||
fi
|
||||
if [ "$build_64" == "1" ]; then
|
||||
nspr_opt+=(--enable-64bit)
|
||||
if [ "$build_64" = 1 ]; then
|
||||
nspr_params+=(--enable-64bit)
|
||||
else
|
||||
gyp_params+=(-Dtarget_arch=ia32)
|
||||
fi
|
||||
|
||||
# clone fuzzing stuff
|
||||
if [ "$fuzz" = "1" ]; then
|
||||
[ $verbose = 0 ] && exec 3>/dev/null || exec 3>&1
|
||||
|
||||
echo "[1/2] Cloning libFuzzer files ..."
|
||||
$cwd/fuzz/clone_libfuzzer.sh 1>&3 2>&3
|
||||
|
||||
echo "[2/2] Cloning fuzzing corpus ..."
|
||||
$cwd/fuzz/clone_corpus.sh 1>&3 2>&3
|
||||
|
||||
exec 3>&-
|
||||
fi
|
||||
|
||||
# check if we have to rebuild gyp
|
||||
if [ "$params" != "$(cat $cwd/out/config 2>/dev/null)" -o "$rebuild_gyp" == 1 -o "$clean" == 1 ]; then
|
||||
rebuild_gyp=1
|
||||
rm -rf "$cwd/../nspr/$target" # force NSPR to rebuild
|
||||
if [ "$fuzz" = 1 ]; then
|
||||
source "$cwd"/coreconf/fuzz.sh
|
||||
fi
|
||||
|
||||
# set paths
|
||||
target_dir="$cwd/out/$target"
|
||||
|
||||
# get the realpath of $dist_dir
|
||||
dist_dir=$(mkdir -p $dist_dir; cd $dist_dir; pwd -P)
|
||||
|
||||
# get object directory
|
||||
obj_dir="$dist_dir/$target"
|
||||
gyp_params+=(-Dnss_dist_dir=$dist_dir)
|
||||
gyp_params+=(-Dnss_dist_obj_dir=$obj_dir)
|
||||
gyp_params+=(-Dnspr_lib_dir=$obj_dir/lib)
|
||||
gyp_params+=(-Dnspr_include_dir=$obj_dir/include/nspr)
|
||||
target_dir="$cwd"/out/$target
|
||||
mkdir -p "$target_dir"
|
||||
dist_dir="$cwd"/../dist
|
||||
dist_dir=$(mkdir -p "$dist_dir"; cd "$dist_dir"; pwd -P)
|
||||
gyp_params+=(-Dnss_dist_dir="$dist_dir")
|
||||
|
||||
# -c = clean first
|
||||
if [ "$clean" = 1 ]; then
|
||||
rm -rf "$cwd/out"
|
||||
rm -rf "$cwd/../nspr/$target"
|
||||
nspr_clean
|
||||
rm -rf "$cwd"/out
|
||||
rm -rf "$dist_dir"
|
||||
fi
|
||||
|
||||
# This saves a canonical representation of arguments that we are passing to gyp
|
||||
# or the NSPR build so that we can work out if a rebuild is needed.
|
||||
# Caveat: This can fail for arguments that are position-dependent.
|
||||
# e.g., "-e 2 -f 1" and "-e 1 -f 2" canonicalize the same.
|
||||
check_config()
|
||||
{
|
||||
local newconf="$1".new oldconf="$1"
|
||||
shift
|
||||
mkdir -p $(dirname "$newconf")
|
||||
echo CC="$CC" >"$newconf"
|
||||
echo CCC="$CCC" >>"$newconf"
|
||||
echo CXX="$CXX" >>"$newconf"
|
||||
for i in "$@"; do echo $i; done | sort >>"$newconf"
|
||||
|
||||
# Note: The following diff fails if $oldconf isn't there as well, which
|
||||
# happens if we don't have a previous successful build.
|
||||
! diff -q "$newconf" "$oldconf" >/dev/null 2>&1
|
||||
}
|
||||
|
||||
gyp_config="$cwd"/out/gyp_config
|
||||
nspr_config="$cwd"/out/$target/nspr_config
|
||||
|
||||
# If we don't have a build directory make sure that we rebuild.
|
||||
if [ ! -d "$target_dir" ]; then
|
||||
rebuild_nspr=1
|
||||
rebuild_gyp=1
|
||||
elif [ ! -d "$dist_dir"/$target ]; then
|
||||
rebuild_nspr=1
|
||||
fi
|
||||
|
||||
# Update NSPR ${C,CXX,LD}FLAGS.
|
||||
nspr_set_flags $sanitizer_flags
|
||||
|
||||
if check_config "$nspr_config" "${nspr_params[@]}" \
|
||||
nspr_cflags="$nspr_cflags" \
|
||||
nspr_cxxflags="$nspr_cxxflags" \
|
||||
nspr_ldflags="$nspr_ldflags"; then
|
||||
rebuild_nspr=1
|
||||
fi
|
||||
|
||||
# Forward sanitizer flags.
|
||||
if [ ! -z "$sanitizer_flags" ]; then
|
||||
gyp_params+=(-Dsanitizer_flags="$sanitizer_flags")
|
||||
fi
|
||||
|
||||
if check_config "$gyp_config" "${gyp_params[@]}"; then
|
||||
rebuild_gyp=1
|
||||
fi
|
||||
|
||||
# save the chosen target
|
||||
mkdir -p $dist_dir
|
||||
echo $target > $dist_dir/latest
|
||||
mkdir -p "$dist_dir"
|
||||
echo $target > "$dist_dir"/latest
|
||||
|
||||
# pass on CC and CCC
|
||||
if [ "${#scanbuild[@]}" -gt 0 ]; then
|
||||
if [ -n "$CC" ]; then
|
||||
scanbuild+=(--use-cc="$CC")
|
||||
fi
|
||||
if [ -n "$CCC" ]; then
|
||||
scanbuild+=(--use-c++="$CCC")
|
||||
fi
|
||||
fi
|
||||
if [ "$rebuild_nspr" = 1 ]; then
|
||||
nspr_build "${nspr_params[@]}"
|
||||
mv -f "$nspr_config".new "$nspr_config"
|
||||
fi
|
||||
if [ "$rebuild_gyp" = 1 ]; then
|
||||
|
||||
# These steps can take a while, so don't overdo them.
|
||||
# Force a redo with -g.
|
||||
if [ "$rebuild_gyp" = 1 -o ! -d "$target_dir" ]; then
|
||||
build_nspr $verbose
|
||||
# These extra arguments aren't used in determining whether to rebuild.
|
||||
obj_dir="$dist_dir"/$target
|
||||
gyp_params+=(-Dnss_dist_obj_dir=$obj_dir)
|
||||
gyp_params+=(-Dnspr_lib_dir=$obj_dir/lib)
|
||||
gyp_params+=(-Dnspr_include_dir=$obj_dir/include/nspr)
|
||||
|
||||
# Run gyp.
|
||||
[ $verbose = 1 ] && set -v -x
|
||||
"${scanbuild[@]}" gyp -f ninja "${gyp_params[@]}" --depth="$cwd" \
|
||||
--generator-output="." "$cwd/nss.gyp"
|
||||
[ $verbose = 1 ] && set +v +x
|
||||
run_verbose run_scanbuild gyp -f ninja "${gyp_params[@]}" "$cwd"/nss.gyp
|
||||
|
||||
# Store used parameters for next run.
|
||||
echo "$params" > "$cwd/out/config"
|
||||
mv -f "$gyp_config".new "$gyp_config"
|
||||
fi
|
||||
|
||||
# Run ninja.
|
||||
if which ninja >/dev/null 2>&1; then
|
||||
ninja=(ninja)
|
||||
elif which ninja-build >/dev/null 2>&1; then
|
||||
ninja=(ninja-build)
|
||||
if hash ninja 2>/dev/null; then
|
||||
ninja=ninja
|
||||
elif hash ninja-build 2>/dev/null; then
|
||||
ninja=ninja-build
|
||||
else
|
||||
echo "Please install ninja" 1>&2
|
||||
exit 1
|
||||
fi
|
||||
"${scanbuild[@]}" $ninja -C "$target_dir" "${ninja_params[@]}"
|
||||
run_scanbuild $ninja -C "$target_dir" "${ninja_params[@]}"
|
||||
|
@ -32,8 +32,6 @@
|
||||
'<(DEPTH)/lib/dev/dev.gyp:nssdev',
|
||||
'<(DEPTH)/lib/base/base.gyp:nssb',
|
||||
'<(DEPTH)/lib/freebl/freebl.gyp:freebl',
|
||||
'<(DEPTH)/lib/pk11wrap/pk11wrap.gyp:pk11wrap',
|
||||
'<(DEPTH)/lib/certhigh/certhigh.gyp:certhi',
|
||||
'<(DEPTH)/lib/sqlite/sqlite.gyp:sqlite3',
|
||||
],
|
||||
'conditions': [
|
||||
|
@ -52,7 +52,6 @@
|
||||
'use_system_zlib%': 1,
|
||||
'nspr_libs%': ['-lplds4', '-lplc4', '-lnspr4'],
|
||||
'zlib_libs%': ['-lz'],
|
||||
'optimize_flags%': '-O2',
|
||||
'dll_prefix': 'lib',
|
||||
'conditions': [
|
||||
['OS=="mac"', {
|
||||
@ -98,14 +97,14 @@
|
||||
'moz_fold_libs%': 0,
|
||||
'moz_folded_library_name%': '',
|
||||
'ssl_enable_zlib%': 1,
|
||||
'use_asan%': 0,
|
||||
'use_ubsan%': 0,
|
||||
'use_msan%': 0,
|
||||
'use_sancov%': 0,
|
||||
'sanitizer_flags%': 0,
|
||||
'test_build%': 0,
|
||||
'no_zdefs%': 0,
|
||||
'fuzz%': 0,
|
||||
'fuzz_tls%': 0,
|
||||
'sign_libs%': 1,
|
||||
'use_pprof%': 0,
|
||||
'ct_verif%': 0,
|
||||
'nss_public_dist_dir%': '<(nss_dist_dir)/public',
|
||||
'nss_private_dist_dir%': '<(nss_dist_dir)/private',
|
||||
},
|
||||
@ -115,6 +114,8 @@
|
||||
'variables': {
|
||||
'mapfile%': '',
|
||||
'test_build%': 0,
|
||||
'debug_optimization_level%': '0',
|
||||
'release_optimization_level%': '2',
|
||||
},
|
||||
'standalone_static_library': 0,
|
||||
'include_dirs': [
|
||||
@ -133,6 +134,11 @@
|
||||
'-lc',
|
||||
],
|
||||
}],
|
||||
[ 'fuzz==1', {
|
||||
'variables': {
|
||||
'debug_optimization_level%': '1',
|
||||
},
|
||||
}],
|
||||
],
|
||||
'target_conditions': [
|
||||
# If we want to properly export a static library, and copy it to lib,
|
||||
@ -209,7 +215,6 @@
|
||||
[ 'cc_use_gnu_ld==1', {
|
||||
'ldflags': [
|
||||
'-Wl,--gc-sections',
|
||||
'-Wl,-z,defs',
|
||||
],
|
||||
'conditions': [
|
||||
['OS=="dragonfly" or OS=="freebsd" or OS=="netbsd" or OS=="openbsd"', {
|
||||
@ -218,6 +223,11 @@
|
||||
'-Wl,--warn-unresolved-symbols',
|
||||
],
|
||||
}],
|
||||
['no_zdefs==0', {
|
||||
'ldflags': [
|
||||
'-Wl,-z,defs',
|
||||
],
|
||||
}],
|
||||
],
|
||||
}],
|
||||
],
|
||||
@ -341,79 +351,22 @@
|
||||
'<!@(<(python) <(DEPTH)/coreconf/werror.py)',
|
||||
],
|
||||
}],
|
||||
[ 'fuzz==1', {
|
||||
[ 'fuzz_tls==1', {
|
||||
'cflags': [
|
||||
'-Wno-unused-function',
|
||||
]
|
||||
],
|
||||
}],
|
||||
[ 'fuzz==1 or use_asan==1 or use_ubsan!=0', {
|
||||
'cflags': ['-O1'],
|
||||
[ 'sanitizer_flags!=0', {
|
||||
'cflags': ['<@(sanitizer_flags)'],
|
||||
'ldflags': ['<@(sanitizer_flags)'],
|
||||
'xcode_settings': {
|
||||
'GCC_OPTIMIZATION_LEVEL': '1', # -O1
|
||||
}
|
||||
}],
|
||||
[ 'use_asan==1', {
|
||||
'variables': {
|
||||
'asan_flags': '<!(<(python) <(DEPTH)/coreconf/sanitizers.py asan)',
|
||||
'no_ldflags': '<!(<(python) <(DEPTH)/coreconf/sanitizers.py ld)',
|
||||
},
|
||||
'cflags': ['<@(asan_flags)'],
|
||||
'ldflags': ['<@(asan_flags)'],
|
||||
'ldflags!': ['<@(no_ldflags)'],
|
||||
'xcode_settings': {
|
||||
'OTHER_CFLAGS': ['<@(asan_flags)'],
|
||||
'OTHER_LDFLAGS!': ['<@(no_ldflags)'],
|
||||
'OTHER_CFLAGS': ['<@(sanitizer_flags)'],
|
||||
# We want to pass -fsanitize=... to our final link call,
|
||||
# but not to libtool. OTHER_LDFLAGS is passed to both.
|
||||
# To trick GYP into doing what we want, we'll piggyback on
|
||||
# LIBRARY_SEARCH_PATHS, producing "-L/usr/lib -fsanitize=...".
|
||||
# The -L/usr/lib is redundant but innocuous: it's a default path.
|
||||
'LIBRARY_SEARCH_PATHS': ['/usr/lib <(asan_flags)'],
|
||||
},
|
||||
}],
|
||||
[ 'use_ubsan!=0', {
|
||||
'variables': {
|
||||
'ubsan_flags': '<!(<(python) <(DEPTH)/coreconf/sanitizers.py ubsan <(use_ubsan))',
|
||||
'no_ldflags': '<!(<(python) <(DEPTH)/coreconf/sanitizers.py ld)',
|
||||
},
|
||||
'cflags': ['<@(ubsan_flags)'],
|
||||
'ldflags': ['<@(ubsan_flags)'],
|
||||
'ldflags!': ['<@(no_ldflags)'],
|
||||
'xcode_settings': {
|
||||
'OTHER_CFLAGS': ['<@(ubsan_flags)'],
|
||||
'OTHER_LDFLAGS!': ['<@(no_ldflags)'],
|
||||
# See comment above.
|
||||
'LIBRARY_SEARCH_PATHS': ['/usr/lib <(ubsan_flags)'],
|
||||
},
|
||||
}],
|
||||
[ 'use_msan==1', {
|
||||
'variables': {
|
||||
'msan_flags': '<!(<(python) <(DEPTH)/coreconf/sanitizers.py msan)',
|
||||
'no_ldflags': '<!(<(python) <(DEPTH)/coreconf/sanitizers.py ld)',
|
||||
},
|
||||
'cflags': ['<@(msan_flags)'],
|
||||
'ldflags': ['<@(msan_flags)'],
|
||||
'ldflags!': ['<@(no_ldflags)'],
|
||||
'xcode_settings': {
|
||||
'OTHER_CFLAGS': ['<@(msan_flags)'],
|
||||
'OTHER_LDFLAGS!': ['<@(no_ldflags)'],
|
||||
# See comment above.
|
||||
'LIBRARY_SEARCH_PATHS': ['/usr/lib <(msan_flags)'],
|
||||
},
|
||||
}],
|
||||
[ 'use_sancov!=0', {
|
||||
'variables': {
|
||||
'sancov_flags': '<!(<(python) <(DEPTH)/coreconf/sanitizers.py sancov <(use_sancov))',
|
||||
'no_ldflags': '<!(<(python) <(DEPTH)/coreconf/sanitizers.py ld)',
|
||||
},
|
||||
'cflags': ['<@(sancov_flags)'],
|
||||
'ldflags': ['<@(sancov_flags)'],
|
||||
'ldflags!': ['<@(no_ldflags)'],
|
||||
'xcode_settings': {
|
||||
'OTHER_CFLAGS': ['<@(sancov_flags)'],
|
||||
'OTHER_LDFLAGS!': ['<@(no_ldflags)'],
|
||||
# See comment above.
|
||||
'LIBRARY_SEARCH_PATHS': ['/usr/lib <(sancov_flags)'],
|
||||
'LIBRARY_SEARCH_PATHS': ['/usr/lib <(sanitizer_flags)'],
|
||||
},
|
||||
}],
|
||||
[ 'OS=="android" and mozilla_client==0', {
|
||||
@ -472,7 +425,6 @@
|
||||
],
|
||||
},
|
||||
},
|
||||
|
||||
}],
|
||||
[ 'target_arch=="x64"', {
|
||||
'msvs_configuration_platform': 'x64',
|
||||
@ -515,14 +467,15 @@
|
||||
],
|
||||
#TODO: DEBUG_$USER
|
||||
'defines': ['DEBUG'],
|
||||
'cflags': [ '-O<(debug_optimization_level)' ],
|
||||
'xcode_settings': {
|
||||
'COPY_PHASE_STRIP': 'NO',
|
||||
'GCC_OPTIMIZATION_LEVEL': '0',
|
||||
'GCC_OPTIMIZATION_LEVEL': '<(debug_optimization_level)',
|
||||
'GCC_GENERATE_DEBUGGING_SYMBOLS': 'YES',
|
||||
},
|
||||
'msvs_settings': {
|
||||
'VCCLCompilerTool': {
|
||||
'Optimization': '0',
|
||||
'Optimization': '<(debug_optimization_level)',
|
||||
'BasicRuntimeChecks': '3',
|
||||
'RuntimeLibrary': '2', # /MD
|
||||
},
|
||||
@ -537,16 +490,15 @@
|
||||
# Common settings for release should go here.
|
||||
'Release': {
|
||||
'inherit_from': ['Common'],
|
||||
'defines': [
|
||||
'NDEBUG',
|
||||
],
|
||||
'defines': ['NDEBUG'],
|
||||
'cflags': [ '-O<(release_optimization_level)' ],
|
||||
'xcode_settings': {
|
||||
'DEAD_CODE_STRIPPING': 'YES', # -Wl,-dead_strip
|
||||
'GCC_OPTIMIZATION_LEVEL': '2', # -O2
|
||||
'GCC_OPTIMIZATION_LEVEL': '<(release_optimization_level)',
|
||||
},
|
||||
'msvs_settings': {
|
||||
'VCCLCompilerTool': {
|
||||
'Optimization': '2', # /Os
|
||||
'Optimization': '<(release_optimization_level)',
|
||||
'RuntimeLibrary': '2', # /MD
|
||||
},
|
||||
'VCLinkerTool': {
|
||||
|
@ -10,3 +10,4 @@
|
||||
*/
|
||||
|
||||
#error "Do not include this header file."
|
||||
|
||||
|
38
security/nss/coreconf/fuzz.sh
Normal file
38
security/nss/coreconf/fuzz.sh
Normal file
@ -0,0 +1,38 @@
|
||||
#!/usr/bin/env bash
|
||||
# This file is used by build.sh to setup fuzzing.
|
||||
|
||||
set +e
|
||||
|
||||
# Default to clang if CC is not set.
|
||||
if [ -z "$CC" ]; then
|
||||
command -v clang &> /dev/null 2>&1
|
||||
if [ $? != 0 ]; then
|
||||
echo "Fuzzing requires clang!"
|
||||
exit 1
|
||||
fi
|
||||
export CC=clang
|
||||
export CCC=clang++
|
||||
export CXX=clang++
|
||||
fi
|
||||
|
||||
gyp_params+=(-Dtest_build=1 -Dfuzz=1)
|
||||
|
||||
# Add debug symbols even for opt builds.
|
||||
nspr_params+=(--enable-debug-symbols)
|
||||
|
||||
if [ "$fuzz_oss" = 1 ]; then
|
||||
gyp_params+=(-Dno_zdefs=1)
|
||||
else
|
||||
enable_sanitizer asan
|
||||
enable_ubsan
|
||||
enable_sancov
|
||||
fi
|
||||
|
||||
if [ "$fuzz_tls" = 1 ]; then
|
||||
gyp_params+=(-Dfuzz_tls=1)
|
||||
fi
|
||||
|
||||
if [ ! -f "/usr/lib/libFuzzingEngine.a" ]; then
|
||||
echo "Cloning libFuzzer files ..."
|
||||
run_verbose "$cwd"/fuzz/clone_libfuzzer.sh
|
||||
fi
|
@ -5,7 +5,6 @@
|
||||
# the features or platforms that the regular NSPR build supports.
|
||||
|
||||
# variables
|
||||
nspr_opt=()
|
||||
nspr_cflags=
|
||||
nspr_cxxflags=
|
||||
nspr_ldflags=
|
||||
@ -15,39 +14,38 @@ if hash gmake 2>/dev/null; then
|
||||
make() { command gmake "$@"; }
|
||||
fi
|
||||
|
||||
nspr_sanitizer()
|
||||
nspr_set_flags()
|
||||
{
|
||||
nspr_cflags="$nspr_cflags $(python $cwd/coreconf/sanitizers.py $1 $2)"
|
||||
nspr_cxxflags="$nspr_cxxflags $(python $cwd/coreconf/sanitizers.py $1 $2)"
|
||||
nspr_ldflags="$nspr_ldflags $(python $cwd/coreconf/sanitizers.py $1 $2)"
|
||||
nspr_cflags="$CFLAGS $@"
|
||||
nspr_cxxflags="$CXXFLAGS $@"
|
||||
nspr_ldflags="$LDFLAGS $@"
|
||||
}
|
||||
|
||||
verbose()
|
||||
nspr_build()
|
||||
{
|
||||
CFLAGS=$nspr_cflags CXXFLAGS=$nspr_cxxflags LDFLAGS=$nspr_ldflags \
|
||||
CC=$CC CXX=$CCC ../configure "${nspr_opt[@]}" --prefix="$obj_dir"
|
||||
make -C "$cwd/../nspr/$target"
|
||||
make -C "$cwd/../nspr/$target" install
|
||||
}
|
||||
local nspr_dir="$cwd"/../nspr/$target
|
||||
mkdir -p "$nspr_dir"
|
||||
|
||||
silent()
|
||||
{
|
||||
echo "[1/3] configure NSPR ..."
|
||||
CFLAGS=$nspr_cflags CXXFLAGS=$nspr_cxxflags LDFLAGS=$nspr_ldflags \
|
||||
CC=$CC CXX=$CCC ../configure "${nspr_opt[@]}" --prefix="$obj_dir" 1> /dev/null
|
||||
echo "[2/3] make NSPR ..."
|
||||
make -C "$cwd/../nspr/$target" 1> /dev/null
|
||||
echo "[3/3] install NSPR ..."
|
||||
make -C "$cwd/../nspr/$target" install 1> /dev/null
|
||||
}
|
||||
|
||||
build_nspr()
|
||||
{
|
||||
mkdir -p "$cwd/../nspr/$target"
|
||||
cd "$cwd/../nspr/$target"
|
||||
if [ "$1" == 1 ]; then
|
||||
verbose
|
||||
else
|
||||
silent
|
||||
# These NSPR options are directory-specific, so they don't need to be
|
||||
# included in nspr_opt and changing them doesn't force a rebuild of NSPR.
|
||||
extra_params=(--prefix="$dist_dir"/$target)
|
||||
if [ "$opt_build" = 1 ]; then
|
||||
extra_params+=(--disable-debug --enable-optimize)
|
||||
fi
|
||||
|
||||
echo "NSPR [1/3] configure ..."
|
||||
pushd "$nspr_dir" >/dev/null
|
||||
CFLAGS="$nspr_cflags" CXXFLAGS="$nspr_cxxflags" \
|
||||
LDFLAGS="$nspr_ldflags" CC="$CC" CXX="$CCC" \
|
||||
run_verbose ../configure "${extra_params[@]}" "$@"
|
||||
popd >/dev/null
|
||||
echo "NSPR [2/3] make ..."
|
||||
run_verbose make -C "$nspr_dir"
|
||||
echo "NSPR [3/3] install ..."
|
||||
run_verbose make -C "$nspr_dir" install
|
||||
}
|
||||
|
||||
nspr_clean()
|
||||
{
|
||||
rm -rf "$cwd"/../nspr/$target
|
||||
}
|
||||
|
@ -5,7 +5,7 @@ import sys
|
||||
|
||||
def main():
|
||||
if len(sys.argv) < 2:
|
||||
raise Exception('Specify either "ld", asan", "msan", "sancov" or "ubsan" as argument.')
|
||||
raise Exception('Specify either "asan", "msan", "sancov" or "ubsan" as argument.')
|
||||
|
||||
sanitizer = sys.argv[1]
|
||||
if sanitizer == "ubsan":
|
||||
@ -27,12 +27,7 @@ def main():
|
||||
print('-fsanitize-coverage='+sys.argv[2]+' ', end='')
|
||||
return
|
||||
|
||||
# We have to remove this from the ld flags when building asan.
|
||||
if sanitizer == "ld":
|
||||
print('-Wl,-z,defs ', end='')
|
||||
return
|
||||
|
||||
raise Exception('Specify either "ld", asan", "msan", "sancov" or "ubsan" as argument.')
|
||||
raise Exception('Specify either "asan", "msan", "sancov" or "ubsan" as argument.')
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
|
74
security/nss/coreconf/sanitizers.sh
Normal file
74
security/nss/coreconf/sanitizers.sh
Normal file
@ -0,0 +1,74 @@
|
||||
#!/usr/bin/env bash
|
||||
# This file is used by build.sh to setup sanitizers.
|
||||
|
||||
sanitizer_flags=""
|
||||
|
||||
# This tracks what sanitizers are enabled, and their options.
|
||||
declare -A sanitizers
|
||||
enable_sanitizer()
|
||||
{
|
||||
local san="$1"
|
||||
[ -n "${sanitizers[$san]}" ] && return
|
||||
sanitizers[$san]="${2:-1}"
|
||||
|
||||
if [ -z "$sanitizer_flags" ]; then
|
||||
gyp_params+=(-Dno_zdefs=1)
|
||||
fi
|
||||
|
||||
local cflags=$(python $cwd/coreconf/sanitizers.py "$@")
|
||||
sanitizer_flags="$sanitizer_flags $cflags"
|
||||
}
|
||||
|
||||
enable_sancov()
|
||||
{
|
||||
local clang_version=$($CC --version | grep -oE 'clang version (3\.9\.|4\.)')
|
||||
if [ -z "$clang_version" ]; then
|
||||
echo "Need at least clang-3.9 (better 4.0) for sancov." 1>&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
local sancov
|
||||
if [ -n "$1" ]; then
|
||||
sancov="$1"
|
||||
elif [ "$clang_version" = "clang version 3.9." ]; then
|
||||
sancov=edge,indirect-calls,8bit-counters
|
||||
else
|
||||
sancov=trace-pc-guard,trace-cmp
|
||||
fi
|
||||
enable_sanitizer sancov "$sancov"
|
||||
}
|
||||
|
||||
enable_ubsan()
|
||||
{
|
||||
local ubsan
|
||||
if [ -n "$1" ]; then
|
||||
ubsan="$1"
|
||||
else
|
||||
ubsan=bool,signed-integer-overflow,shift,vptr
|
||||
fi
|
||||
enable_sanitizer ubsan "$ubsan"
|
||||
}
|
||||
|
||||
# Not strictly a sanitizer, but the pattern fits
|
||||
scanbuild=()
|
||||
enable_scanbuild()
|
||||
{
|
||||
[ "${#scanbuild[@]}" -gt 0 ] && return
|
||||
|
||||
scanbuild=(scan-build)
|
||||
if [ -n "$1" ]; then
|
||||
scanbuild+=(-o "$1")
|
||||
fi
|
||||
# pass on CC and CCC to scanbuild
|
||||
if [ -n "$CC" ]; then
|
||||
scanbuild+=(--use-cc="$CC")
|
||||
fi
|
||||
if [ -n "$CCC" ]; then
|
||||
scanbuild+=(--use-c++="$CCC")
|
||||
fi
|
||||
}
|
||||
|
||||
run_scanbuild()
|
||||
{
|
||||
"${scanbuild[@]}" "$@"
|
||||
}
|
17
security/nss/fuzz/cert_target.cc
Normal file
17
security/nss/fuzz/cert_target.cc
Normal file
@ -0,0 +1,17 @@
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* 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/. */
|
||||
|
||||
#include "FuzzerInternal.h"
|
||||
#include "asn1_mutators.h"
|
||||
#include "shared.h"
|
||||
|
||||
extern const uint16_t DEFAULT_MAX_LENGTH = 3072U;
|
||||
|
||||
extern "C" int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) {
|
||||
CERTCertificate cert;
|
||||
QuickDERDecode(&cert, SEC_SignedCertificateTemplate, Data, Size);
|
||||
return 0;
|
||||
}
|
||||
|
||||
ADD_CUSTOM_MUTATORS({&ASN1MutatorFlipConstructed, &ASN1MutatorChangeType})
|
@ -1,22 +1,46 @@
|
||||
#!/bin/sh
|
||||
|
||||
d=$(dirname $0)
|
||||
$d/git-copy.sh https://chromium.googlesource.com/chromium/llvm-project/llvm/lib/Fuzzer 1b543d6e5073b56be214394890c9193979a3d7e1 $d/libFuzzer
|
||||
$d/git-copy.sh https://chromium.googlesource.com/chromium/llvm-project/llvm/lib/Fuzzer 33c20f597a2e312611d52677ff0fdd9335b485b7 $d/libFuzzer
|
||||
|
||||
# [https://llvm.org/bugs/show_bug.cgi?id=31318]
|
||||
# This prevents a known buffer overrun that won't be fixed as the affected code
|
||||
# will go away in the near future. Until that is we have to patch it as we seem
|
||||
# to constantly run into it.
|
||||
cat <<EOF | patch -p0 -d $d
|
||||
diff --git libFuzzer/FuzzerMutate.cpp libFuzzer/FuzzerMutate.cpp
|
||||
--- libFuzzer/FuzzerMutate.cpp
|
||||
+++ libFuzzer/FuzzerMutate.cpp
|
||||
@@ -53,10 +53,9 @@
|
||||
DefaultMutators.push_back(
|
||||
{&MutationDispatcher::Mutate_AddWordFromTORC, "CMP"});
|
||||
diff --git libFuzzer/FuzzerLoop.cpp libFuzzer/FuzzerLoop.cpp
|
||||
--- libFuzzer/FuzzerLoop.cpp
|
||||
+++ libFuzzer/FuzzerLoop.cpp
|
||||
@@ -472,6 +472,9 @@
|
||||
uint8_t dummy;
|
||||
ExecuteCallback(&dummy, 0);
|
||||
|
||||
+ Mutators = DefaultMutators;
|
||||
if (EF->LLVMFuzzerCustomMutator)
|
||||
Mutators.push_back({&MutationDispatcher::Mutate_Custom, "Custom"});
|
||||
- else
|
||||
- Mutators = DefaultMutators;
|
||||
|
||||
if (EF->LLVMFuzzerCustomCrossOver)
|
||||
Mutators.push_back(
|
||||
+ // Number of counters might have changed.
|
||||
+ PrepareCounters(&MaxCoverage);
|
||||
+
|
||||
for (const auto &U : *InitialCorpus) {
|
||||
if (size_t NumFeatures = RunOne(U)) {
|
||||
CheckExitOnSrcPosOrItem();
|
||||
EOF
|
||||
|
||||
# Latest Libfuzzer uses __sanitizer_dump_coverage(), a symbol to be introduced
|
||||
# with LLVM 4.0. To keep our code working with LLVM 3.x to simplify development
|
||||
# of fuzzers we'll just provide it ourselves.
|
||||
cat <<EOF | patch -p0 -d $d
|
||||
diff --git libFuzzer/FuzzerTracePC.cpp libFuzzer/FuzzerTracePC.cpp
|
||||
--- libFuzzer/FuzzerTracePC.cpp
|
||||
+++ libFuzzer/FuzzerTracePC.cpp
|
||||
@@ -24,6 +24,12 @@
|
||||
#include <set>
|
||||
#include <sstream>
|
||||
|
||||
+#if defined(__clang_major__) && (__clang_major__ == 3)
|
||||
+void __sanitizer_dump_coverage(const uintptr_t *pcs, uintptr_t len) {
|
||||
+ // SanCov in LLVM 4.x will provide this symbol. Make 3.x work.
|
||||
+}
|
||||
+#endif
|
||||
+
|
||||
namespace fuzzer {
|
||||
|
||||
TracePC TPC;
|
||||
EOF
|
||||
|
@ -4,79 +4,134 @@
|
||||
{
|
||||
'includes': [
|
||||
'../coreconf/config.gypi',
|
||||
'../cmd/platlibs.gypi'
|
||||
],
|
||||
'variables': {
|
||||
'use_fuzzing_engine': '<!(test -f /usr/lib/libFuzzingEngine.a && echo 1 || echo 0)',
|
||||
},
|
||||
'target_defaults': {
|
||||
'variables': {
|
||||
'debug_optimization_level': '2',
|
||||
},
|
||||
'target_conditions': [
|
||||
[ '_type=="executable"', {
|
||||
'libraries!': [
|
||||
'<@(nspr_libs)',
|
||||
],
|
||||
'libraries': [
|
||||
'<(nss_dist_obj_dir)/lib/libplds4.a',
|
||||
'<(nss_dist_obj_dir)/lib/libnspr4.a',
|
||||
'<(nss_dist_obj_dir)/lib/libplc4.a',
|
||||
],
|
||||
}],
|
||||
],
|
||||
},
|
||||
'targets': [
|
||||
{
|
||||
'target_name': 'libFuzzer',
|
||||
'type': 'static_library',
|
||||
'sources': [
|
||||
'libFuzzer/FuzzerCrossOver.cpp',
|
||||
'libFuzzer/FuzzerDriver.cpp',
|
||||
'libFuzzer/FuzzerExtFunctionsDlsym.cpp',
|
||||
'libFuzzer/FuzzerExtFunctionsWeak.cpp',
|
||||
'libFuzzer/FuzzerIO.cpp',
|
||||
'libFuzzer/FuzzerLoop.cpp',
|
||||
'libFuzzer/FuzzerMutate.cpp',
|
||||
'libFuzzer/FuzzerSHA1.cpp',
|
||||
'libFuzzer/FuzzerTracePC.cpp',
|
||||
'libFuzzer/FuzzerTraceState.cpp',
|
||||
'libFuzzer/FuzzerUtil.cpp',
|
||||
'libFuzzer/FuzzerUtilDarwin.cpp',
|
||||
'libFuzzer/FuzzerUtilLinux.cpp',
|
||||
'target_name': 'fuzz_base',
|
||||
'dependencies': [
|
||||
'<(DEPTH)/lib/certdb/certdb.gyp:certdb',
|
||||
'<(DEPTH)/lib/certhigh/certhigh.gyp:certhi',
|
||||
'<(DEPTH)/lib/cryptohi/cryptohi.gyp:cryptohi',
|
||||
'<(DEPTH)/lib/base/base.gyp:nssb',
|
||||
'<(DEPTH)/lib/dev/dev.gyp:nssdev',
|
||||
'<(DEPTH)/lib/pki/pki.gyp:nsspki',
|
||||
'<(DEPTH)/lib/util/util.gyp:nssutil',
|
||||
'<(DEPTH)/lib/nss/nss.gyp:nss_static',
|
||||
'<(DEPTH)/lib/pk11wrap/pk11wrap.gyp:pk11wrap',
|
||||
'<(DEPTH)/lib/pkcs7/pkcs7.gyp:pkcs7',
|
||||
],
|
||||
'cflags': [
|
||||
'-O2',
|
||||
'conditions': [
|
||||
['use_fuzzing_engine==0', {
|
||||
'type': 'static_library',
|
||||
'sources': [
|
||||
'libFuzzer/FuzzerCrossOver.cpp',
|
||||
'libFuzzer/FuzzerDriver.cpp',
|
||||
'libFuzzer/FuzzerExtFunctionsDlsym.cpp',
|
||||
'libFuzzer/FuzzerExtFunctionsWeak.cpp',
|
||||
'libFuzzer/FuzzerExtFunctionsWeakAlias.cpp',
|
||||
'libFuzzer/FuzzerIO.cpp',
|
||||
'libFuzzer/FuzzerIOPosix.cpp',
|
||||
'libFuzzer/FuzzerIOWindows.cpp',
|
||||
'libFuzzer/FuzzerLoop.cpp',
|
||||
'libFuzzer/FuzzerMain.cpp',
|
||||
'libFuzzer/FuzzerMerge.cpp',
|
||||
'libFuzzer/FuzzerMutate.cpp',
|
||||
'libFuzzer/FuzzerSHA1.cpp',
|
||||
'libFuzzer/FuzzerTracePC.cpp',
|
||||
'libFuzzer/FuzzerTraceState.cpp',
|
||||
'libFuzzer/FuzzerUtil.cpp',
|
||||
'libFuzzer/FuzzerUtilDarwin.cpp',
|
||||
'libFuzzer/FuzzerUtilLinux.cpp',
|
||||
'libFuzzer/FuzzerUtilPosix.cpp',
|
||||
'libFuzzer/FuzzerUtilWindows.cpp',
|
||||
],
|
||||
'cflags/': [
|
||||
['exclude', '-fsanitize-coverage'],
|
||||
],
|
||||
'xcode_settings': {
|
||||
'OTHER_CFLAGS/': [
|
||||
['exclude', '-fsanitize-coverage'],
|
||||
],
|
||||
},
|
||||
'direct_dependent_settings': {
|
||||
'include_dirs': [
|
||||
'libFuzzer',
|
||||
],
|
||||
},
|
||||
}, {
|
||||
'type': 'none',
|
||||
'direct_dependent_settings': {
|
||||
'libraries': ['-lFuzzingEngine'],
|
||||
}
|
||||
}]
|
||||
],
|
||||
'cflags!': [
|
||||
'-O1',
|
||||
],
|
||||
'cflags/': [
|
||||
['exclude', '-fsanitize'],
|
||||
],
|
||||
'xcode_settings': {
|
||||
'GCC_OPTIMIZATION_LEVEL': '2', # -O2
|
||||
'OTHER_CFLAGS/': [
|
||||
['exclude', '-fsanitize'],
|
||||
],
|
||||
},
|
||||
},
|
||||
{
|
||||
'target_name': 'nssfuzz',
|
||||
'target_name': 'nssfuzz-pkcs8',
|
||||
'type': 'executable',
|
||||
'sources': [
|
||||
'asn1_mutators.cc',
|
||||
'nssfuzz.cc',
|
||||
'initialize.cc',
|
||||
'pkcs8_target.cc',
|
||||
'quickder_targets.cc',
|
||||
],
|
||||
'dependencies': [
|
||||
'<(DEPTH)/exports.gyp:nss_exports',
|
||||
'libFuzzer',
|
||||
'fuzz_base',
|
||||
],
|
||||
'cflags': [
|
||||
'-O2',
|
||||
},
|
||||
{
|
||||
'target_name': 'nssfuzz-quickder',
|
||||
'type': 'executable',
|
||||
'sources': [
|
||||
'asn1_mutators.cc',
|
||||
'initialize.cc',
|
||||
'quickder_target.cc',
|
||||
],
|
||||
'cflags!': [
|
||||
'-O1',
|
||||
'dependencies': [
|
||||
'<(DEPTH)/exports.gyp:nss_exports',
|
||||
'fuzz_base',
|
||||
],
|
||||
'cflags/': [
|
||||
['exclude', '-fsanitize-coverage'],
|
||||
},
|
||||
{
|
||||
'target_name': 'nssfuzz-hash',
|
||||
'type': 'executable',
|
||||
'sources': [
|
||||
'hash_target.cc',
|
||||
'initialize.cc',
|
||||
],
|
||||
'dependencies': [
|
||||
'<(DEPTH)/exports.gyp:nss_exports',
|
||||
'fuzz_base',
|
||||
],
|
||||
},
|
||||
{
|
||||
'target_name': 'nssfuzz',
|
||||
'type': 'none',
|
||||
'dependencies': [
|
||||
'nssfuzz-hash',
|
||||
'nssfuzz-pkcs8',
|
||||
'nssfuzz-quickder',
|
||||
],
|
||||
'xcode_settings': {
|
||||
'GCC_OPTIMIZATION_LEVEL': '2', # -O2
|
||||
'OTHER_CFLAGS/': [
|
||||
['exclude', '-fsanitize-coverage'],
|
||||
],
|
||||
},
|
||||
}
|
||||
],
|
||||
'target_defaults': {
|
||||
'include_dirs': [
|
||||
'libFuzzer',
|
||||
],
|
||||
},
|
||||
'variables': {
|
||||
'module': 'nss',
|
||||
}
|
||||
}
|
||||
|
42
security/nss/fuzz/hash_target.cc
Normal file
42
security/nss/fuzz/hash_target.cc
Normal file
@ -0,0 +1,42 @@
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* 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/. */
|
||||
|
||||
#include <memory>
|
||||
#include <vector>
|
||||
|
||||
#include "FuzzerInternal.h"
|
||||
#include "hasht.h"
|
||||
#include "pk11pub.h"
|
||||
#include "secoidt.h"
|
||||
#include "shared.h"
|
||||
|
||||
extern const uint16_t DEFAULT_MAX_LENGTH = 4096U;
|
||||
|
||||
const std::vector<SECOidTag> algos = {SEC_OID_MD5, SEC_OID_SHA1, SEC_OID_SHA256,
|
||||
SEC_OID_SHA384, SEC_OID_SHA512};
|
||||
|
||||
extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
|
||||
uint8_t hashOut[HASH_LENGTH_MAX];
|
||||
|
||||
static std::unique_ptr<NSSDatabase> db(new NSSDatabase());
|
||||
assert(db != nullptr);
|
||||
|
||||
// simple hashing.
|
||||
for (auto algo : algos) {
|
||||
assert(PK11_HashBuf(algo, hashOut, data, size) == SECSuccess);
|
||||
}
|
||||
|
||||
// hashing with context.
|
||||
for (auto algo : algos) {
|
||||
unsigned int len = 0;
|
||||
PK11Context *context = PK11_CreateDigestContext(algo);
|
||||
assert(context != nullptr);
|
||||
assert(PK11_DigestBegin(context) == SECSuccess);
|
||||
assert(PK11_DigestFinal(context, hashOut, &len, HASH_LENGTH_MAX) ==
|
||||
SECSuccess);
|
||||
PK11_DestroyContext(context, PR_TRUE);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
54
security/nss/fuzz/initialize.cc
Normal file
54
security/nss/fuzz/initialize.cc
Normal file
@ -0,0 +1,54 @@
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* 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/. */
|
||||
|
||||
#include <string.h>
|
||||
#include <algorithm>
|
||||
#include <iostream>
|
||||
#include <vector>
|
||||
|
||||
#include "assert.h"
|
||||
|
||||
extern const uint16_t DEFAULT_MAX_LENGTH;
|
||||
|
||||
const uint16_t MERGE_MAX_LENGTH = 50000U;
|
||||
|
||||
extern "C" int LLVMFuzzerInitialize(int *argc, char ***argv) {
|
||||
std::vector<std::string> args(*argv, *argv + *argc);
|
||||
|
||||
auto hasMaxLenArg = [](std::string &a) { return a.find("-max_len=") == 0; };
|
||||
|
||||
// Nothing to do if a max_len argument is given.
|
||||
if (any_of(args.begin(), args.end(), hasMaxLenArg)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
auto hasMergeArg = [](std::string &a) { return a.find("-merge=1") == 0; };
|
||||
|
||||
uint16_t max_length = DEFAULT_MAX_LENGTH;
|
||||
|
||||
// Set specific max_len when merging.
|
||||
if (any_of(args.begin(), args.end(), hasMergeArg)) {
|
||||
max_length = MERGE_MAX_LENGTH;
|
||||
}
|
||||
|
||||
std::cerr << "INFO: MaxLen: " << max_length << std::endl;
|
||||
std::string param = "-max_len=" + std::to_string(max_length);
|
||||
|
||||
// Copy original arguments.
|
||||
char **new_args = new char *[*argc + 1];
|
||||
for (int i = 0; i < *argc; i++) {
|
||||
new_args[i] = (*argv)[i];
|
||||
}
|
||||
|
||||
// Append corpus max length.
|
||||
size_t param_len = param.size() + 1;
|
||||
new_args[*argc] = new char[param_len];
|
||||
memcpy(new_args[*argc], param.c_str(), param_len);
|
||||
|
||||
// Update arguments.
|
||||
(*argc)++;
|
||||
*argv = new_args;
|
||||
|
||||
return 0;
|
||||
}
|
@ -1,163 +0,0 @@
|
||||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim: set ts=2 et sw=2 tw=80: */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* 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/. */
|
||||
|
||||
#include <iomanip>
|
||||
#include <iostream>
|
||||
|
||||
#include "FuzzerInternal.h"
|
||||
#include "FuzzerMutate.h"
|
||||
#include "FuzzerRandom.h"
|
||||
#include "registry.h"
|
||||
#include "shared.h"
|
||||
|
||||
using namespace std;
|
||||
|
||||
static vector<Mutator> gMutators;
|
||||
|
||||
class Args {
|
||||
public:
|
||||
Args(int argc, char **argv) : args_(argv, argv + argc) {}
|
||||
|
||||
string &operator[](const int idx) { return args_[idx]; }
|
||||
|
||||
bool Has(const string &arg) {
|
||||
return any_of(args_.begin(), args_.end(),
|
||||
[&arg](string &a) { return a.find(arg) == 0; });
|
||||
}
|
||||
|
||||
void Append(const string &arg) { args_.push_back(arg); }
|
||||
|
||||
void Remove(const int index) {
|
||||
assert(index < count());
|
||||
args_.erase(args_.begin() + index);
|
||||
}
|
||||
|
||||
vector<char *> argv() {
|
||||
vector<char *> out;
|
||||
out.resize(count());
|
||||
|
||||
transform(args_.begin(), args_.end(), out.begin(),
|
||||
[](string &a) { return const_cast<char *>(a.c_str()); });
|
||||
|
||||
return out;
|
||||
}
|
||||
|
||||
size_t count() { return args_.size(); }
|
||||
|
||||
private:
|
||||
vector<string> args_;
|
||||
};
|
||||
|
||||
void printUsage(Args &args) {
|
||||
size_t sep = args[0].rfind("/") + 1;
|
||||
string progName = args[0].substr(sep);
|
||||
|
||||
cerr << progName << " - Various libFuzzer targets for NSS" << endl << endl;
|
||||
cerr << "Usage: " << progName << " <target> <libFuzzer options>" << endl
|
||||
<< endl;
|
||||
cerr << "Valid targets:" << endl;
|
||||
|
||||
vector<string> names = Registry::Names();
|
||||
|
||||
// Find length of the longest name.
|
||||
size_t name_w =
|
||||
max_element(names.begin(), names.end(), [](string &a, string &b) {
|
||||
return a.size() < b.size();
|
||||
})->size();
|
||||
|
||||
// Find length of the longest description.
|
||||
auto max = max_element(names.begin(), names.end(), [](string &a, string &b) {
|
||||
return Registry::Desc(a).size() < Registry::Desc(b).size();
|
||||
});
|
||||
size_t desc_w = Registry::Desc(*max).size();
|
||||
|
||||
// Print list of targets.
|
||||
for (string name : names) {
|
||||
cerr << " " << left << setw(name_w) << name << " - " << setw(desc_w)
|
||||
<< Registry::Desc(name)
|
||||
<< " [default max_len=" << Registry::MaxLen(name) << "]" << endl;
|
||||
}
|
||||
|
||||
// Some usage examples.
|
||||
cerr << endl << "Run fuzzer with a given corpus directory:" << endl;
|
||||
cerr << " " << progName << " <target> /path/to/corpus" << endl;
|
||||
|
||||
cerr << endl << "Run fuzzer with a single test input:" << endl;
|
||||
cerr << " " << progName
|
||||
<< " <target> ./crash-14d4355b971092e39572bc306a135ddf9f923e19" << endl;
|
||||
|
||||
cerr << endl
|
||||
<< "Specify the number of cores you wish to dedicate to fuzzing:"
|
||||
<< endl;
|
||||
cerr << " " << progName << " <target> -jobs=8 -workers=8 /path/to/corpus"
|
||||
<< endl;
|
||||
|
||||
cerr << endl << "Override the maximum length of a test input:" << endl;
|
||||
cerr << " " << progName << " <target> -max_len=2048 /path/to/corpus" << endl;
|
||||
|
||||
cerr << endl
|
||||
<< "Minimize a given corpus and put the result into 'new_corpus':"
|
||||
<< endl;
|
||||
cerr << " " << progName
|
||||
<< " <target> -merge=1 -max_len=50000 ./new_corpus /path/to/corpus"
|
||||
<< endl;
|
||||
|
||||
cerr << endl << "Merge new test inputs into a corpus:" << endl;
|
||||
cerr
|
||||
<< " " << progName
|
||||
<< " <target> -merge=1 -max_len=50000 /path/to/corpus ./inputs1 ./inputs2"
|
||||
<< endl;
|
||||
|
||||
cerr << endl << "Print libFuzzer usage information:" << endl;
|
||||
cerr << " " << progName << " <target> -help=1" << endl << endl;
|
||||
|
||||
cerr << "Check out the docs at http://llvm.org/docs/LibFuzzer.html" << endl;
|
||||
}
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
Args args(argc, argv);
|
||||
|
||||
if (args.count() < 2 || !Registry::Has(args[1])) {
|
||||
printUsage(args);
|
||||
return 1;
|
||||
}
|
||||
|
||||
string targetName(args[1]);
|
||||
|
||||
// Add target mutators.
|
||||
auto mutators = Registry::Mutators(targetName);
|
||||
gMutators.insert(gMutators.end(), mutators.begin(), mutators.end());
|
||||
|
||||
// Remove the target argument when -workers=x or -jobs=y is NOT given.
|
||||
// If both are given, libFuzzer will spawn multiple processes for the target.
|
||||
if (!args.Has("-workers=") || !args.Has("-jobs=")) {
|
||||
args.Remove(1);
|
||||
}
|
||||
|
||||
// Set default max_len arg, if none given and we're not merging.
|
||||
if (!args.Has("-max_len=") && !args.Has("-merge=1")) {
|
||||
uint16_t maxLen = Registry::MaxLen(targetName);
|
||||
args.Append("-max_len=" + to_string(maxLen));
|
||||
}
|
||||
|
||||
// Hand control to the libFuzzer driver.
|
||||
vector<char *> args_new(args.argv());
|
||||
argc = args_new.size();
|
||||
argv = args_new.data();
|
||||
|
||||
return fuzzer::FuzzerDriver(&argc, &argv, Registry::Func(targetName));
|
||||
}
|
||||
|
||||
extern "C" size_t LLVMFuzzerCustomMutator(uint8_t *Data, size_t Size,
|
||||
size_t MaxSize, unsigned int Seed) {
|
||||
if (gMutators.empty()) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Forward to a pseudorandom mutator.
|
||||
fuzzer::Random R(Seed);
|
||||
return gMutators.at(R(gMutators.size()))(Data, Size, MaxSize, Seed);
|
||||
}
|
@ -1,20 +1,21 @@
|
||||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim: set ts=2 et sw=2 tw=80: */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* 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/. */
|
||||
|
||||
#include <assert.h>
|
||||
#include <stdint.h>
|
||||
#include <memory>
|
||||
#include <vector>
|
||||
|
||||
#include "keyhi.h"
|
||||
#include "pk11pub.h"
|
||||
|
||||
#include "registry.h"
|
||||
#include "FuzzerInternal.h"
|
||||
#include "asn1_mutators.h"
|
||||
#include "assert.h"
|
||||
#include "shared.h"
|
||||
|
||||
extern "C" int pkcs8_fuzzing_target(const uint8_t *Data, size_t Size) {
|
||||
extern const uint16_t DEFAULT_MAX_LENGTH = 2048U;
|
||||
|
||||
extern "C" int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) {
|
||||
SECItem data = {siBuffer, (unsigned char *)Data, (unsigned int)Size};
|
||||
|
||||
static std::unique_ptr<NSSDatabase> db(new NSSDatabase());
|
||||
@ -34,5 +35,4 @@ extern "C" int pkcs8_fuzzing_target(const uint8_t *Data, size_t Size) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
REGISTER_FUZZING_TARGET("pkcs8", pkcs8_fuzzing_target, 2048, "PKCS#8 Import",
|
||||
{})
|
||||
ADD_CUSTOM_MUTATORS({&ASN1MutatorFlipConstructed, &ASN1MutatorChangeType})
|
||||
|
83
security/nss/fuzz/quickder_target.cc
Normal file
83
security/nss/fuzz/quickder_target.cc
Normal file
@ -0,0 +1,83 @@
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* 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/. */
|
||||
|
||||
#include "FuzzerInternal.h"
|
||||
#include "asn1_mutators.h"
|
||||
#include "shared.h"
|
||||
|
||||
const std::vector<const SEC_ASN1Template *> templates = {
|
||||
CERT_AttributeTemplate,
|
||||
CERT_CertExtensionTemplate,
|
||||
CERT_CertificateRequestTemplate,
|
||||
CERT_CertificateTemplate,
|
||||
CERT_CrlTemplate,
|
||||
CERT_IssuerAndSNTemplate,
|
||||
CERT_NameTemplate,
|
||||
CERT_PublicKeyAndChallengeTemplate,
|
||||
CERT_RDNTemplate,
|
||||
CERT_SequenceOfCertExtensionTemplate,
|
||||
CERT_SetOfAttributeTemplate,
|
||||
CERT_SetOfSignedCrlTemplate,
|
||||
CERT_SignedCrlTemplate,
|
||||
CERT_SignedDataTemplate,
|
||||
CERT_SubjectPublicKeyInfoTemplate,
|
||||
CERT_TimeChoiceTemplate,
|
||||
CERT_ValidityTemplate,
|
||||
SEC_AnyTemplate,
|
||||
SEC_BitStringTemplate,
|
||||
SEC_BMPStringTemplate,
|
||||
SEC_BooleanTemplate,
|
||||
SEC_CertSequenceTemplate,
|
||||
SEC_EnumeratedTemplate,
|
||||
SEC_GeneralizedTimeTemplate,
|
||||
SEC_IA5StringTemplate,
|
||||
SEC_IntegerTemplate,
|
||||
SEC_NullTemplate,
|
||||
SEC_ObjectIDTemplate,
|
||||
SEC_OctetStringTemplate,
|
||||
SEC_PointerToAnyTemplate,
|
||||
SEC_PointerToEnumeratedTemplate,
|
||||
SEC_PointerToGeneralizedTimeTemplate,
|
||||
SEC_PointerToOctetStringTemplate,
|
||||
SEC_PrintableStringTemplate,
|
||||
SEC_SetOfAnyTemplate,
|
||||
SEC_SetOfEnumeratedTemplate,
|
||||
SEC_SequenceOfAnyTemplate,
|
||||
SEC_SequenceOfObjectIDTemplate,
|
||||
SEC_SignedCertificateTemplate,
|
||||
SEC_SkipTemplate,
|
||||
SEC_T61StringTemplate,
|
||||
SEC_UniversalStringTemplate,
|
||||
SEC_UTCTimeTemplate,
|
||||
SEC_UTF8StringTemplate,
|
||||
SEC_VisibleStringTemplate,
|
||||
SECKEY_DHParamKeyTemplate,
|
||||
SECKEY_DHPublicKeyTemplate,
|
||||
SECKEY_DSAPrivateKeyExportTemplate,
|
||||
SECKEY_DSAPublicKeyTemplate,
|
||||
SECKEY_PQGParamsTemplate,
|
||||
SECKEY_PrivateKeyInfoTemplate,
|
||||
SECKEY_RSAPSSParamsTemplate,
|
||||
SECKEY_RSAPublicKeyTemplate,
|
||||
SECOID_AlgorithmIDTemplate};
|
||||
|
||||
extern const uint16_t DEFAULT_MAX_LENGTH = 10000U;
|
||||
|
||||
extern "C" int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) {
|
||||
char *dest[2048];
|
||||
|
||||
for (auto tpl : templates) {
|
||||
PORTCheapArenaPool pool;
|
||||
SECItem buf = {siBuffer, const_cast<unsigned char *>(Data),
|
||||
static_cast<unsigned int>(Size)};
|
||||
|
||||
PORT_InitCheapArena(&pool, DER_DEFAULT_CHUNKSIZE);
|
||||
(void)SEC_QuickDERDecodeItem(&pool.arena, dest, tpl, &buf);
|
||||
PORT_DestroyCheapArena(&pool);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
ADD_CUSTOM_MUTATORS({&ASN1MutatorFlipConstructed, &ASN1MutatorChangeType})
|
@ -1,38 +0,0 @@
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* 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/. */
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#include "asn1_mutators.h"
|
||||
#include "cert.h"
|
||||
#include "registry.h"
|
||||
|
||||
void QuickDERDecode(void *dst, const SEC_ASN1Template *tpl, const uint8_t *buf,
|
||||
size_t len) {
|
||||
PORTCheapArenaPool pool;
|
||||
SECItem data = {siBuffer, const_cast<unsigned char *>(buf),
|
||||
static_cast<unsigned int>(len)};
|
||||
|
||||
PORT_InitCheapArena(&pool, DER_DEFAULT_CHUNKSIZE);
|
||||
(void)SEC_QuickDERDecodeItem(&pool.arena, dst, tpl, &data);
|
||||
PORT_DestroyCheapArena(&pool);
|
||||
}
|
||||
|
||||
extern "C" int cert_fuzzing_target(const uint8_t *Data, size_t Size) {
|
||||
CERTCertificate cert;
|
||||
QuickDERDecode(&cert, SEC_SignedCertificateTemplate, Data, Size);
|
||||
return 0;
|
||||
}
|
||||
|
||||
REGISTER_FUZZING_TARGET("cert", cert_fuzzing_target, 3072, "Certificate Import",
|
||||
{&ASN1MutatorFlipConstructed, &ASN1MutatorChangeType})
|
||||
|
||||
extern "C" int spki_fuzzing_target(const uint8_t *Data, size_t Size) {
|
||||
CERTSubjectPublicKeyInfo spki;
|
||||
QuickDERDecode(&spki, CERT_SubjectPublicKeyInfoTemplate, Data, Size);
|
||||
return 0;
|
||||
}
|
||||
|
||||
REGISTER_FUZZING_TARGET("spki", spki_fuzzing_target, 1024, "SPKI Import",
|
||||
{&ASN1MutatorFlipConstructed, &ASN1MutatorChangeType})
|
@ -1,79 +0,0 @@
|
||||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim: set ts=2 et sw=2 tw=80: */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* 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/. */
|
||||
|
||||
#ifndef registry_h__
|
||||
#define registry_h__
|
||||
|
||||
#include <map>
|
||||
#include "FuzzerInternal.h"
|
||||
#include "nss.h"
|
||||
|
||||
using namespace fuzzer;
|
||||
using namespace std;
|
||||
|
||||
typedef decltype(LLVMFuzzerCustomMutator)* Mutator;
|
||||
|
||||
class Registry {
|
||||
public:
|
||||
static void Add(string name, UserCallback func, uint16_t max_len, string desc,
|
||||
vector<Mutator> mutators = {}) {
|
||||
assert(!Has(name));
|
||||
GetInstance().targets_[name] = TargetData(func, max_len, desc, mutators);
|
||||
}
|
||||
|
||||
static bool Has(string name) {
|
||||
return GetInstance().targets_.count(name) > 0;
|
||||
}
|
||||
|
||||
static UserCallback Func(string name) {
|
||||
assert(Has(name));
|
||||
return get<0>(Get(name));
|
||||
}
|
||||
|
||||
static uint16_t MaxLen(string name) {
|
||||
assert(Has(name));
|
||||
return get<1>(Get(name));
|
||||
}
|
||||
|
||||
static string& Desc(string name) {
|
||||
assert(Has(name));
|
||||
return get<2>(Get(name));
|
||||
}
|
||||
|
||||
static vector<Mutator>& Mutators(string name) {
|
||||
assert(Has(name));
|
||||
return get<3>(Get(name));
|
||||
}
|
||||
|
||||
static vector<string> Names() {
|
||||
vector<string> names;
|
||||
for (auto& it : GetInstance().targets_) {
|
||||
names.push_back(it.first);
|
||||
}
|
||||
return names;
|
||||
}
|
||||
|
||||
private:
|
||||
typedef tuple<UserCallback, uint16_t, string, vector<Mutator>> TargetData;
|
||||
|
||||
static Registry& GetInstance() {
|
||||
static Registry registry;
|
||||
return registry;
|
||||
}
|
||||
|
||||
static TargetData& Get(string name) { return GetInstance().targets_[name]; }
|
||||
|
||||
Registry() {}
|
||||
|
||||
map<string, TargetData> targets_;
|
||||
};
|
||||
|
||||
#define REGISTER_FUZZING_TARGET(name, func, max_len, desc, ...) \
|
||||
static void __attribute__((constructor)) Register_##func() { \
|
||||
Registry::Add(name, func, max_len, desc, __VA_ARGS__); \
|
||||
}
|
||||
|
||||
#endif // registry_h__
|
@ -7,6 +7,8 @@
|
||||
#ifndef shared_h__
|
||||
#define shared_h__
|
||||
|
||||
#include "FuzzerRandom.h"
|
||||
#include "cert.h"
|
||||
#include "nss.h"
|
||||
|
||||
class NSSDatabase {
|
||||
@ -15,4 +17,23 @@ class NSSDatabase {
|
||||
~NSSDatabase() { NSS_Shutdown(); }
|
||||
};
|
||||
|
||||
size_t CustomMutate(std::vector<decltype(LLVMFuzzerCustomMutator) *> mutators,
|
||||
uint8_t *Data, size_t Size, size_t MaxSize,
|
||||
unsigned int Seed) {
|
||||
fuzzer::Random R(Seed);
|
||||
|
||||
if (R.RandBool()) {
|
||||
auto idx = R(mutators.size());
|
||||
return mutators.at(idx)(Data, Size, MaxSize, Seed);
|
||||
}
|
||||
|
||||
return LLVMFuzzerMutate(Data, Size, MaxSize);
|
||||
}
|
||||
|
||||
#define ADD_CUSTOM_MUTATORS(...) \
|
||||
extern "C" size_t LLVMFuzzerCustomMutator( \
|
||||
uint8_t *Data, size_t Size, size_t MaxSize, unsigned int Seed) { \
|
||||
return CustomMutate(__VA_ARGS__, Data, Size, MaxSize, Seed); \
|
||||
}
|
||||
|
||||
#endif // shared_h__
|
||||
|
17
security/nss/fuzz/spki_target.cc
Normal file
17
security/nss/fuzz/spki_target.cc
Normal file
@ -0,0 +1,17 @@
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* 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/. */
|
||||
|
||||
#include "FuzzerInternal.h"
|
||||
#include "asn1_mutators.h"
|
||||
#include "shared.h"
|
||||
|
||||
extern const uint16_t DEFAULT_MAX_LENGTH = 1024U;
|
||||
|
||||
extern "C" int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) {
|
||||
CERTSubjectPublicKeyInfo spki;
|
||||
QuickDERDecode(&spki, CERT_SubjectPublicKeyInfoTemplate, Data, Size);
|
||||
return 0;
|
||||
}
|
||||
|
||||
ADD_CUSTOM_MUTATORS({&ASN1MutatorFlipConstructed, &ASN1MutatorChangeType})
|
@ -1,15 +1,16 @@
|
||||
|
||||
##############################################
|
||||
## ##
|
||||
## WARNING: You're building with -Dfuzz=1 ##
|
||||
## ##
|
||||
## This means: ##
|
||||
## ##
|
||||
## * Your PRNG is DETERMINISTIC. ##
|
||||
## * TLS transcripts are PLAINTEXT. ##
|
||||
## * TLS signature checks are DISABLED. ##
|
||||
## ##
|
||||
## Thank you for fuzzing! ##
|
||||
## ##
|
||||
##############################################
|
||||
##################################################
|
||||
## ##
|
||||
## WARNING: You're building with -Dfuzz_tls=1 ##
|
||||
## ##
|
||||
## This means: ##
|
||||
## ##
|
||||
## * Your PRNG is DETERMINISTIC. ##
|
||||
## * TLS transcripts are PLAINTEXT. ##
|
||||
## * Session tickets are NOT encrypted. ##
|
||||
## * TLS signature/MAC checks are DISABLED. ##
|
||||
## ##
|
||||
## Thank you for fuzzing! ##
|
||||
## ##
|
||||
##################################################
|
||||
|
||||
|
@ -1,35 +0,0 @@
|
||||
# This Source Code Form is subject to the terms of the Mozilla Public
|
||||
# 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/.
|
||||
{
|
||||
'includes': [
|
||||
'../../coreconf/config.gypi',
|
||||
'gtest.gypi',
|
||||
],
|
||||
'targets': [
|
||||
{
|
||||
'target_name': 'gtests',
|
||||
'type': 'executable',
|
||||
'sources': [
|
||||
'gtests.cc'
|
||||
],
|
||||
'dependencies': [
|
||||
'<(DEPTH)/exports.gyp:nss_exports',
|
||||
'<(DEPTH)/lib/nss/nss.gyp:nss3',
|
||||
'<(DEPTH)/lib/util/util.gyp:nssutil3',
|
||||
'<(DEPTH)/lib/smime/smime.gyp:smime3',
|
||||
'<(DEPTH)/gtests/google_test/google_test.gyp:gtest',
|
||||
'<(DEPTH)/cmd/lib/lib.gyp:sectool'
|
||||
]
|
||||
}
|
||||
],
|
||||
'target_defaults': {
|
||||
'include_dirs': [
|
||||
'../../gtests/google_test/gtest/include',
|
||||
'../../gtests/common'
|
||||
],
|
||||
},
|
||||
'variables': {
|
||||
'module': 'nss'
|
||||
}
|
||||
}
|
@ -2,9 +2,6 @@
|
||||
# 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/.
|
||||
{
|
||||
'includes': [
|
||||
'../../coreconf/config.gypi'
|
||||
],
|
||||
'target_defaults': {
|
||||
'conditions': [
|
||||
['OS=="win"', {
|
||||
@ -17,7 +14,7 @@
|
||||
'-lstdc++',
|
||||
],
|
||||
}],
|
||||
[ 'fuzz==1', {
|
||||
[ 'fuzz_tls==1', {
|
||||
'defines': [
|
||||
'UNSAFE_FUZZER_MODE',
|
||||
],
|
||||
|
@ -19,8 +19,12 @@
|
||||
'<(DEPTH)/lib/freebl/freebl.gyp:<(freebl_name)',
|
||||
'<(DEPTH)/gtests/google_test/google_test.gyp:gtest',
|
||||
],
|
||||
'defines': [
|
||||
'CT_VERIF',
|
||||
'conditions': [
|
||||
[ 'ct_verif==1', {
|
||||
'defines': [
|
||||
'CT_VERIF',
|
||||
],
|
||||
}],
|
||||
],
|
||||
}
|
||||
],
|
||||
|
@ -83,8 +83,10 @@ TEST_F(MPITest, MpiCmpConstTest) {
|
||||
"FFFFFFFF00000000FFFFFFFFFFFFFFFFBCE6FAADA7179E84F3B9CAC2FC632550"),
|
||||
16);
|
||||
|
||||
#ifdef CT_VERIF
|
||||
mp_taint(&b);
|
||||
mp_taint(&c);
|
||||
#endif
|
||||
|
||||
uint32_t runs = 5000000;
|
||||
uint32_t time_b = 0, time_c = 0;
|
||||
|
@ -12,20 +12,16 @@
|
||||
#include "nss.h"
|
||||
#include "prio.h"
|
||||
#include "prnetdb.h"
|
||||
#include "secerr.h"
|
||||
#include "ssl.h"
|
||||
#include "ssl3prot.h"
|
||||
#include "sslerr.h"
|
||||
#include "sslproto.h"
|
||||
#include "ssl3prot.h"
|
||||
|
||||
#include "nsskeys.h"
|
||||
|
||||
static const char* kVersionDisableFlags[] = {
|
||||
"no-ssl3",
|
||||
"no-tls1",
|
||||
"no-tls11",
|
||||
"no-tls12",
|
||||
"no-tls13"
|
||||
};
|
||||
static const char* kVersionDisableFlags[] = {"no-ssl3", "no-tls1", "no-tls11",
|
||||
"no-tls12", "no-tls13"};
|
||||
|
||||
bool exitCodeUnimplemented = false;
|
||||
|
||||
@ -154,8 +150,7 @@ class TestAgent {
|
||||
}
|
||||
|
||||
static bool ConvertFromWireVersion(SSLProtocolVariant variant,
|
||||
int wire_version,
|
||||
uint16_t* lib_version) {
|
||||
int wire_version, uint16_t* lib_version) {
|
||||
// These default values are used when {min,max}-version isn't given.
|
||||
if (wire_version == 0 || wire_version == 0xffff) {
|
||||
*lib_version = static_cast<uint16_t>(wire_version);
|
||||
@ -171,18 +166,18 @@ class TestAgent {
|
||||
|
||||
if (variant == ssl_variant_datagram) {
|
||||
switch (wire_version) {
|
||||
case SSL_LIBRARY_VERSION_DTLS_1_0_WIRE:
|
||||
*lib_version = SSL_LIBRARY_VERSION_DTLS_1_0;
|
||||
break;
|
||||
case SSL_LIBRARY_VERSION_DTLS_1_2_WIRE:
|
||||
*lib_version = SSL_LIBRARY_VERSION_DTLS_1_2;
|
||||
break;
|
||||
case SSL_LIBRARY_VERSION_DTLS_1_3_WIRE:
|
||||
*lib_version = SSL_LIBRARY_VERSION_DTLS_1_3;
|
||||
break;
|
||||
default:
|
||||
std::cerr << "Unrecognized DTLS version " << wire_version << ".\n";
|
||||
return false;
|
||||
case SSL_LIBRARY_VERSION_DTLS_1_0_WIRE:
|
||||
*lib_version = SSL_LIBRARY_VERSION_DTLS_1_0;
|
||||
break;
|
||||
case SSL_LIBRARY_VERSION_DTLS_1_2_WIRE:
|
||||
*lib_version = SSL_LIBRARY_VERSION_DTLS_1_2;
|
||||
break;
|
||||
case SSL_LIBRARY_VERSION_DTLS_1_3_WIRE:
|
||||
*lib_version = SSL_LIBRARY_VERSION_DTLS_1_3;
|
||||
break;
|
||||
default:
|
||||
std::cerr << "Unrecognized DTLS version " << wire_version << ".\n";
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
if (wire_version < SSL_LIBRARY_VERSION_3_0 ||
|
||||
@ -220,7 +215,7 @@ class TestAgent {
|
||||
// Ignore -no-ssl3, because SSLv3 is never supported.
|
||||
for (size_t i = 1; i < PR_ARRAY_SIZE(kVersionDisableFlags); ++i) {
|
||||
auto version =
|
||||
static_cast<uint16_t>(SSL_LIBRARY_VERSION_TLS_1_0 + (i - 1));
|
||||
static_cast<uint16_t>(SSL_LIBRARY_VERSION_TLS_1_0 + (i - 1));
|
||||
if (variant == ssl_variant_datagram) {
|
||||
// In DTLS mode, the -no-tlsN flags refer to DTLS versions,
|
||||
// but NSS wants the corresponding TLS versions.
|
||||
@ -348,12 +343,53 @@ class TestAgent {
|
||||
rv = PR_Write(ssl_fd_, block, len);
|
||||
if (rv != len) {
|
||||
std::cerr << "Write failure\n";
|
||||
PORT_SetError(SEC_ERROR_OUTPUT_LEN);
|
||||
return SECFailure;
|
||||
}
|
||||
}
|
||||
return SECSuccess;
|
||||
}
|
||||
|
||||
// Write bytes to the other side then read them back and check
|
||||
// that they were correctly XORed as in ReadWrite.
|
||||
SECStatus WriteRead() {
|
||||
static const uint8_t ch = 'E';
|
||||
|
||||
// We do 600-byte blocks to provide mis-alignment of the
|
||||
// reader and writer.
|
||||
uint8_t block[600];
|
||||
memset(block, ch, sizeof(block));
|
||||
int32_t rv = PR_Write(ssl_fd_, block, sizeof(block));
|
||||
if (rv != sizeof(block)) {
|
||||
std::cerr << "Write failure\n";
|
||||
PORT_SetError(SEC_ERROR_OUTPUT_LEN);
|
||||
return SECFailure;
|
||||
}
|
||||
|
||||
size_t left = sizeof(block);
|
||||
while (left) {
|
||||
int32_t rv = PR_Read(ssl_fd_, block, left);
|
||||
if (rv < 0) {
|
||||
std::cerr << "Failure reading\n";
|
||||
return SECFailure;
|
||||
}
|
||||
if (rv == 0) {
|
||||
PORT_SetError(SEC_ERROR_INPUT_LEN);
|
||||
return SECFailure;
|
||||
}
|
||||
|
||||
int32_t len = rv;
|
||||
for (int32_t i = 0; i < len; ++i) {
|
||||
if (block[i] != (ch ^ 0xff)) {
|
||||
PORT_SetError(SEC_ERROR_BAD_DATA);
|
||||
return SECFailure;
|
||||
}
|
||||
}
|
||||
left -= len;
|
||||
}
|
||||
return SECSuccess;
|
||||
}
|
||||
|
||||
SECStatus DoExchange() {
|
||||
SECStatus rv = Handshake();
|
||||
if (rv != SECSuccess) {
|
||||
@ -363,12 +399,22 @@ class TestAgent {
|
||||
return SECFailure;
|
||||
}
|
||||
|
||||
rv = ReadWrite();
|
||||
if (rv != SECSuccess) {
|
||||
PRErrorCode err = PR_GetError();
|
||||
std::cerr << "ReadWrite failed with error=" << FormatError(err)
|
||||
<< std::endl;
|
||||
return SECFailure;
|
||||
if (cfg_.get<bool>("write-then-read")) {
|
||||
rv = WriteRead();
|
||||
if (rv != SECSuccess) {
|
||||
PRErrorCode err = PR_GetError();
|
||||
std::cerr << "WriteRead failed with error=" << FormatError(err)
|
||||
<< std::endl;
|
||||
return SECFailure;
|
||||
}
|
||||
} else {
|
||||
rv = ReadWrite();
|
||||
if (rv != SECSuccess) {
|
||||
PRErrorCode err = PR_GetError();
|
||||
std::cerr << "ReadWrite failed with error=" << FormatError(err)
|
||||
<< std::endl;
|
||||
return SECFailure;
|
||||
}
|
||||
}
|
||||
|
||||
return SECSuccess;
|
||||
@ -395,6 +441,7 @@ std::unique_ptr<const Config> ReadConfig(int argc, char** argv) {
|
||||
for (auto flag : kVersionDisableFlags) {
|
||||
cfg->AddEntry<bool>(flag, false);
|
||||
}
|
||||
cfg->AddEntry<bool>("write-then-read", false);
|
||||
|
||||
auto rv = cfg->ParseArgs(argc, argv);
|
||||
switch (rv) {
|
||||
@ -410,7 +457,6 @@ std::unique_ptr<const Config> ReadConfig(int argc, char** argv) {
|
||||
return std::move(cfg);
|
||||
}
|
||||
|
||||
|
||||
bool RunCycle(std::unique_ptr<const Config>& cfg) {
|
||||
std::unique_ptr<TestAgent> agent(TestAgent::Create(*cfg));
|
||||
return agent && agent->DoExchange() == SECSuccess;
|
||||
|
@ -35,9 +35,6 @@
|
||||
'<(DEPTH)/lib/dev/dev.gyp:nssdev',
|
||||
'<(DEPTH)/lib/base/base.gyp:nssb',
|
||||
'<(DEPTH)/lib/freebl/freebl.gyp:freebl',
|
||||
'<(DEPTH)/lib/nss/nss.gyp:nss_static',
|
||||
'<(DEPTH)/lib/pk11wrap/pk11wrap.gyp:pk11wrap',
|
||||
'<(DEPTH)/lib/certhigh/certhigh.gyp:certhi',
|
||||
'<(DEPTH)/lib/zlib/zlib.gyp:nss_zlib'
|
||||
],
|
||||
'conditions': [
|
||||
|
@ -26,6 +26,7 @@ CPPSRCS = \
|
||||
ssl_extension_unittest.cc \
|
||||
ssl_fragment_unittest.cc \
|
||||
ssl_fuzz_unittest.cc \
|
||||
ssl_gather_unittest.cc \
|
||||
ssl_gtest.cc \
|
||||
ssl_hrr_unittest.cc \
|
||||
ssl_loopback_unittest.cc \
|
||||
|
@ -227,7 +227,7 @@ TEST_P(TlsConnectTls13, TestTls13ZeroRttDowngrade) {
|
||||
client_->Handshake();
|
||||
server_->Handshake();
|
||||
ASSERT_TRUE_WAIT(
|
||||
(client_->error_code() == SSL_ERROR_RX_MALFORMED_SERVER_HELLO), 2000);
|
||||
(client_->error_code() == SSL_ERROR_DOWNGRADE_WITH_EARLY_DATA), 2000);
|
||||
|
||||
// DTLS will timeout as we bump the epoch when installing the early app data
|
||||
// cipher suite. Thus the encrypted alert will be ignored.
|
||||
@ -266,7 +266,7 @@ TEST_P(TlsConnectTls13, TestTls13ZeroRttDowngradeEarlyData) {
|
||||
client_->Handshake();
|
||||
server_->Handshake();
|
||||
ASSERT_TRUE_WAIT(
|
||||
(client_->error_code() == SSL_ERROR_RX_MALFORMED_SERVER_HELLO), 2000);
|
||||
(client_->error_code() == SSL_ERROR_DOWNGRADE_WITH_EARLY_DATA), 2000);
|
||||
|
||||
// DTLS will timeout as we bump the epoch when installing the early app data
|
||||
// cipher suite. Thus the encrypted alert will be ignored.
|
||||
|
@ -191,6 +191,58 @@ TEST_P(TlsConnectGenericPre13, P384PriorityFromModelSocket) {
|
||||
ssl_sig_rsa_pss_sha256);
|
||||
}
|
||||
|
||||
class TlsKeyExchangeGroupCapture : public TlsHandshakeFilter {
|
||||
public:
|
||||
TlsKeyExchangeGroupCapture() : group_(ssl_grp_none) {}
|
||||
|
||||
SSLNamedGroup group() const { return group_; }
|
||||
|
||||
protected:
|
||||
virtual PacketFilter::Action FilterHandshake(const HandshakeHeader &header,
|
||||
const DataBuffer &input,
|
||||
DataBuffer *output) {
|
||||
if (header.handshake_type() != kTlsHandshakeServerKeyExchange) {
|
||||
return KEEP;
|
||||
}
|
||||
|
||||
uint32_t value = 0;
|
||||
EXPECT_TRUE(input.Read(0, 1, &value));
|
||||
EXPECT_EQ(3U, value) << "curve type has to be 3";
|
||||
|
||||
EXPECT_TRUE(input.Read(1, 2, &value));
|
||||
group_ = static_cast<SSLNamedGroup>(value);
|
||||
|
||||
return KEEP;
|
||||
}
|
||||
|
||||
private:
|
||||
SSLNamedGroup group_;
|
||||
};
|
||||
|
||||
// If we strip the client's supported groups extension, the server should assume
|
||||
// P-256 is supported by the client (<= 1.2 only).
|
||||
TEST_P(TlsConnectGenericPre13, DropSupportedGroupExtensionP256) {
|
||||
EnsureTlsSetup();
|
||||
client_->SetPacketFilter(new TlsExtensionDropper(ssl_supported_groups_xtn));
|
||||
auto group_capture = new TlsKeyExchangeGroupCapture();
|
||||
server_->SetPacketFilter(group_capture);
|
||||
|
||||
ConnectExpectFail();
|
||||
client_->CheckErrorCode(SSL_ERROR_DECRYPT_ERROR_ALERT);
|
||||
server_->CheckErrorCode(SSL_ERROR_BAD_HANDSHAKE_HASH_VALUE);
|
||||
|
||||
EXPECT_EQ(ssl_grp_ec_secp256r1, group_capture->group());
|
||||
}
|
||||
|
||||
// Supported groups is mandatory in TLS 1.3.
|
||||
TEST_P(TlsConnectTls13, DropSupportedGroupExtension) {
|
||||
EnsureTlsSetup();
|
||||
client_->SetPacketFilter(new TlsExtensionDropper(ssl_supported_groups_xtn));
|
||||
ConnectExpectFail();
|
||||
client_->CheckErrorCode(SSL_ERROR_MISSING_EXTENSION_ALERT);
|
||||
server_->CheckErrorCode(SSL_ERROR_MISSING_SUPPORTED_GROUPS_EXTENSION);
|
||||
}
|
||||
|
||||
// If we only have a lame group, we fall back to static RSA.
|
||||
TEST_P(TlsConnectGenericPre13, UseLameGroup) {
|
||||
const std::vector<SSLNamedGroup> groups = {ssl_grp_ec_secp192r1};
|
||||
|
153
security/nss/gtests/ssl_gtest/ssl_gather_unittest.cc
Normal file
153
security/nss/gtests/ssl_gtest/ssl_gather_unittest.cc
Normal file
@ -0,0 +1,153 @@
|
||||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim: set ts=2 et sw=2 tw=80: */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* 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/. */
|
||||
|
||||
#include "gtest_utils.h"
|
||||
#include "tls_connect.h"
|
||||
|
||||
namespace nss_test {
|
||||
|
||||
class GatherV2ClientHelloTest : public TlsConnectTestBase {
|
||||
public:
|
||||
GatherV2ClientHelloTest() : TlsConnectTestBase(STREAM, 0) {}
|
||||
|
||||
void ConnectExpectMalformedClientHello(const DataBuffer &data) {
|
||||
EnsureTlsSetup();
|
||||
|
||||
auto alert_recorder = new TlsAlertRecorder();
|
||||
server_->SetPacketFilter(alert_recorder);
|
||||
|
||||
client_->SendDirect(data);
|
||||
server_->StartConnect();
|
||||
server_->Handshake();
|
||||
ASSERT_TRUE_WAIT(
|
||||
(server_->error_code() == SSL_ERROR_RX_MALFORMED_CLIENT_HELLO), 2000);
|
||||
|
||||
EXPECT_EQ(kTlsAlertFatal, alert_recorder->level());
|
||||
EXPECT_EQ(illegal_parameter, alert_recorder->description());
|
||||
}
|
||||
};
|
||||
|
||||
// Gather a 5-byte v3 record, with a zero fragment length. The empty handshake
|
||||
// message should be ignored, and the connection will succeed afterwards.
|
||||
TEST_F(TlsConnectTest, GatherEmptyV3Record) {
|
||||
DataBuffer buffer;
|
||||
|
||||
size_t idx = 0;
|
||||
idx = buffer.Write(idx, 0x16, 1); // handshake
|
||||
idx = buffer.Write(idx, 0x0301, 2); // record_version
|
||||
(void)buffer.Write(idx, 0U, 2); // length=0
|
||||
|
||||
EnsureTlsSetup();
|
||||
client_->SendDirect(buffer);
|
||||
Connect();
|
||||
}
|
||||
|
||||
// Gather a 5-byte v3 record, with a fragment length exceeding the maximum.
|
||||
TEST_F(TlsConnectTest, GatherExcessiveV3Record) {
|
||||
DataBuffer buffer;
|
||||
|
||||
size_t idx = 0;
|
||||
idx = buffer.Write(idx, 0x16, 1); // handshake
|
||||
idx = buffer.Write(idx, 0x0301, 2); // record_version
|
||||
(void)buffer.Write(idx, MAX_FRAGMENT_LENGTH + 2048 + 1, 2); // length=max+1
|
||||
|
||||
EnsureTlsSetup();
|
||||
auto alert_recorder = new TlsAlertRecorder();
|
||||
server_->SetPacketFilter(alert_recorder);
|
||||
client_->SendDirect(buffer);
|
||||
server_->StartConnect();
|
||||
server_->Handshake();
|
||||
ASSERT_TRUE_WAIT((server_->error_code() == SSL_ERROR_RX_RECORD_TOO_LONG),
|
||||
2000);
|
||||
|
||||
EXPECT_EQ(kTlsAlertFatal, alert_recorder->level());
|
||||
EXPECT_EQ(record_overflow, alert_recorder->description());
|
||||
}
|
||||
|
||||
// Gather a 3-byte v2 header, with a fragment length of 2.
|
||||
TEST_F(GatherV2ClientHelloTest, GatherV2RecordLongHeader) {
|
||||
DataBuffer buffer;
|
||||
|
||||
size_t idx = 0;
|
||||
idx = buffer.Write(idx, 0x0002, 2); // length=2 (long header)
|
||||
idx = buffer.Write(idx, 0U, 1); // padding=0
|
||||
(void)buffer.Write(idx, 0U, 2); // data
|
||||
|
||||
ConnectExpectMalformedClientHello(buffer);
|
||||
}
|
||||
|
||||
// Gather a 3-byte v2 header, with a fragment length of 1.
|
||||
TEST_F(GatherV2ClientHelloTest, GatherV2RecordLongHeader2) {
|
||||
DataBuffer buffer;
|
||||
|
||||
size_t idx = 0;
|
||||
idx = buffer.Write(idx, 0x0001, 2); // length=1 (long header)
|
||||
idx = buffer.Write(idx, 0U, 1); // padding=0
|
||||
idx = buffer.Write(idx, 0U, 1); // data
|
||||
(void)buffer.Write(idx, 0U, 1); // surplus (need 5 bytes total)
|
||||
|
||||
ConnectExpectMalformedClientHello(buffer);
|
||||
}
|
||||
|
||||
// Gather a 3-byte v2 header, with a zero fragment length.
|
||||
TEST_F(GatherV2ClientHelloTest, GatherEmptyV2RecordLongHeader) {
|
||||
DataBuffer buffer;
|
||||
|
||||
size_t idx = 0;
|
||||
idx = buffer.Write(idx, 0U, 2); // length=0 (long header)
|
||||
idx = buffer.Write(idx, 0U, 1); // padding=0
|
||||
(void)buffer.Write(idx, 0U, 2); // surplus (need 5 bytes total)
|
||||
|
||||
ConnectExpectMalformedClientHello(buffer);
|
||||
}
|
||||
|
||||
// Gather a 2-byte v2 header, with a fragment length of 3.
|
||||
TEST_F(GatherV2ClientHelloTest, GatherV2RecordShortHeader) {
|
||||
DataBuffer buffer;
|
||||
|
||||
size_t idx = 0;
|
||||
idx = buffer.Write(idx, 0x8003, 2); // length=3 (short header)
|
||||
(void)buffer.Write(idx, 0U, 3); // data
|
||||
|
||||
ConnectExpectMalformedClientHello(buffer);
|
||||
}
|
||||
|
||||
// Gather a 2-byte v2 header, with a fragment length of 2.
|
||||
TEST_F(GatherV2ClientHelloTest, GatherEmptyV2RecordShortHeader2) {
|
||||
DataBuffer buffer;
|
||||
|
||||
size_t idx = 0;
|
||||
idx = buffer.Write(idx, 0x8002, 2); // length=2 (short header)
|
||||
idx = buffer.Write(idx, 0U, 2); // data
|
||||
(void)buffer.Write(idx, 0U, 1); // surplus (need 5 bytes total)
|
||||
|
||||
ConnectExpectMalformedClientHello(buffer);
|
||||
}
|
||||
|
||||
// Gather a 2-byte v2 header, with a fragment length of 1.
|
||||
TEST_F(GatherV2ClientHelloTest, GatherEmptyV2RecordShortHeader3) {
|
||||
DataBuffer buffer;
|
||||
|
||||
size_t idx = 0;
|
||||
idx = buffer.Write(idx, 0x8001, 2); // length=1 (short header)
|
||||
idx = buffer.Write(idx, 0U, 1); // data
|
||||
(void)buffer.Write(idx, 0U, 2); // surplus (need 5 bytes total)
|
||||
|
||||
ConnectExpectMalformedClientHello(buffer);
|
||||
}
|
||||
|
||||
// Gather a 2-byte v2 header, with a zero fragment length.
|
||||
TEST_F(GatherV2ClientHelloTest, GatherEmptyV2RecordShortHeader) {
|
||||
DataBuffer buffer;
|
||||
|
||||
size_t idx = 0;
|
||||
idx = buffer.Write(idx, 0x8000, 2); // length=0 (short header)
|
||||
(void)buffer.Write(idx, 0U, 3); // surplus (need 5 bytes total)
|
||||
|
||||
ConnectExpectMalformedClientHello(buffer);
|
||||
}
|
||||
|
||||
} // namespace nss_test
|
@ -26,6 +26,7 @@
|
||||
'ssl_extension_unittest.cc',
|
||||
'ssl_fuzz_unittest.cc',
|
||||
'ssl_fragment_unittest.cc',
|
||||
'ssl_gather_unittest.cc',
|
||||
'ssl_gtest.cc',
|
||||
'ssl_hrr_unittest.cc',
|
||||
'ssl_loopback_unittest.cc',
|
||||
|
@ -202,6 +202,28 @@ TEST_P(SSLv2ClientHelloTest, Connect) {
|
||||
Connect();
|
||||
}
|
||||
|
||||
// Sending a v2 ClientHello after a no-op v3 record must fail.
|
||||
TEST_P(SSLv2ClientHelloTest, ConnectAfterEmptyV3Record) {
|
||||
DataBuffer buffer;
|
||||
|
||||
size_t idx = 0;
|
||||
idx = buffer.Write(idx, 0x16, 1); // handshake
|
||||
idx = buffer.Write(idx, 0x0301, 2); // record_version
|
||||
(void)buffer.Write(idx, 0U, 2); // length=0
|
||||
|
||||
SetAvailableCipherSuite(TLS_DHE_RSA_WITH_AES_128_CBC_SHA);
|
||||
EnsureTlsSetup();
|
||||
client_->SendDirect(buffer);
|
||||
|
||||
// Need padding so the connection doesn't just time out. With a v2
|
||||
// ClientHello parsed as a v3 record we will use the record version
|
||||
// as the record length.
|
||||
SetPadding(255);
|
||||
|
||||
ConnectExpectFail();
|
||||
EXPECT_EQ(SSL_ERROR_BAD_CLIENT, server_->error_code());
|
||||
}
|
||||
|
||||
// Test negotiating TLS 1.3.
|
||||
TEST_F(SSLv2ClientHelloTestF, Connect13) {
|
||||
EnsureTlsSetup();
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -45,8 +45,8 @@
|
||||
* of the comment in the CK_VERSION type definition.
|
||||
*/
|
||||
#define NSS_BUILTINS_LIBRARY_VERSION_MAJOR 2
|
||||
#define NSS_BUILTINS_LIBRARY_VERSION_MINOR 10
|
||||
#define NSS_BUILTINS_LIBRARY_VERSION "2.10"
|
||||
#define NSS_BUILTINS_LIBRARY_VERSION_MINOR 11
|
||||
#define NSS_BUILTINS_LIBRARY_VERSION "2.11"
|
||||
|
||||
/* These version numbers detail the semantic changes to the ckfw engine. */
|
||||
#define NSS_BUILTINS_HARDWARE_VERSION_MAJOR 1
|
||||
|
@ -166,12 +166,16 @@ static SECItem *
|
||||
common_DecodeDerSig(const SECItem *item, unsigned int len)
|
||||
{
|
||||
SECItem *result = NULL;
|
||||
PORTCheapArenaPool arena;
|
||||
SECStatus status;
|
||||
DSA_ASN1Signature sig;
|
||||
SECItem dst;
|
||||
|
||||
PORT_Memset(&sig, 0, sizeof(sig));
|
||||
|
||||
/* Make enough room for r + s. */
|
||||
PORT_InitCheapArena(&arena, PR_MAX(2 * MAX_ECKEY_LEN, DSA_MAX_SIGNATURE_LEN));
|
||||
|
||||
result = PORT_ZNew(SECItem);
|
||||
if (result == NULL)
|
||||
goto loser;
|
||||
@ -183,7 +187,7 @@ common_DecodeDerSig(const SECItem *item, unsigned int len)
|
||||
|
||||
sig.r.type = siUnsignedInteger;
|
||||
sig.s.type = siUnsignedInteger;
|
||||
status = SEC_ASN1DecodeItem(NULL, &sig, DSA_SignatureTemplate, item);
|
||||
status = SEC_QuickDERDecodeItem(&arena.arena, &sig, DSA_SignatureTemplate, item);
|
||||
if (status != SECSuccess)
|
||||
goto loser;
|
||||
|
||||
@ -202,10 +206,7 @@ common_DecodeDerSig(const SECItem *item, unsigned int len)
|
||||
goto loser;
|
||||
|
||||
done:
|
||||
if (sig.r.data != NULL)
|
||||
PORT_Free(sig.r.data);
|
||||
if (sig.s.data != NULL)
|
||||
PORT_Free(sig.s.data);
|
||||
PORT_DestroyCheapArena(&arena);
|
||||
|
||||
return result;
|
||||
|
||||
|
@ -91,7 +91,7 @@ nssSlot_ResetDelay(
|
||||
}
|
||||
|
||||
static PRBool
|
||||
within_token_delay_period(NSSSlot *slot)
|
||||
within_token_delay_period(const NSSSlot *slot)
|
||||
{
|
||||
PRIntervalTime time, lastTime;
|
||||
/* Set the delay time for checking the token presence */
|
||||
@ -103,7 +103,6 @@ within_token_delay_period(NSSSlot *slot)
|
||||
if ((lastTime) && ((time - lastTime) < s_token_delay_time)) {
|
||||
return PR_TRUE;
|
||||
}
|
||||
slot->lastTokenPing = time;
|
||||
return PR_FALSE;
|
||||
}
|
||||
|
||||
@ -136,6 +135,7 @@ nssSlot_IsTokenPresent(
|
||||
nssSlot_ExitMonitor(slot);
|
||||
if (ckrv != CKR_OK) {
|
||||
slot->token->base.name[0] = 0; /* XXX */
|
||||
slot->lastTokenPing = PR_IntervalNow();
|
||||
return PR_FALSE;
|
||||
}
|
||||
slot->ckFlags = slotInfo.flags;
|
||||
@ -143,6 +143,7 @@ nssSlot_IsTokenPresent(
|
||||
if ((slot->ckFlags & CKF_TOKEN_PRESENT) == 0) {
|
||||
if (!slot->token) {
|
||||
/* token was never present */
|
||||
slot->lastTokenPing = PR_IntervalNow();
|
||||
return PR_FALSE;
|
||||
}
|
||||
session = nssToken_GetDefaultSession(slot->token);
|
||||
@ -165,6 +166,7 @@ nssSlot_IsTokenPresent(
|
||||
slot->token->base.name[0] = 0; /* XXX */
|
||||
/* clear the token cache */
|
||||
nssToken_Remove(slot->token);
|
||||
slot->lastTokenPing = PR_IntervalNow();
|
||||
return PR_FALSE;
|
||||
}
|
||||
/* token is present, use the session info to determine if the card
|
||||
@ -187,8 +189,10 @@ nssSlot_IsTokenPresent(
|
||||
isPresent = session->handle != CK_INVALID_SESSION;
|
||||
nssSession_ExitMonitor(session);
|
||||
/* token not removed, finished */
|
||||
if (isPresent)
|
||||
if (isPresent) {
|
||||
slot->lastTokenPing = PR_IntervalNow();
|
||||
return PR_TRUE;
|
||||
}
|
||||
}
|
||||
/* the token has been removed, and reinserted, or the slot contains
|
||||
* a token it doesn't recognize. invalidate all the old
|
||||
@ -201,8 +205,11 @@ nssSlot_IsTokenPresent(
|
||||
if (nssrv != PR_SUCCESS) {
|
||||
slot->token->base.name[0] = 0; /* XXX */
|
||||
slot->ckFlags &= ~CKF_TOKEN_PRESENT;
|
||||
/* TODO: insert a barrier here to avoid reordering of the assingments */
|
||||
slot->lastTokenPing = PR_IntervalNow();
|
||||
return PR_FALSE;
|
||||
}
|
||||
slot->lastTokenPing = PR_IntervalNow();
|
||||
return PR_TRUE;
|
||||
}
|
||||
|
||||
|
@ -601,7 +601,7 @@ $(ECL_OBJS): $(ECL_HDRS)
|
||||
|
||||
|
||||
|
||||
$(OBJDIR)/sysrand$(OBJ_SUFFIX): sysrand.c unix_rand.c win_rand.c os2_rand.c
|
||||
$(OBJDIR)/sysrand$(OBJ_SUFFIX): sysrand.c unix_rand.c win_rand.c
|
||||
|
||||
$(OBJDIR)/$(PROG_PREFIX)mpprime$(OBJ_SUFFIX): primes.c
|
||||
|
||||
|
@ -566,6 +566,15 @@ ECDH_Derive(SECItem *publicValue,
|
||||
return SECFailure;
|
||||
}
|
||||
|
||||
/*
|
||||
* Make sure the point is on the requested curve to avoid
|
||||
* certain small subgroup attacks.
|
||||
*/
|
||||
if (EC_ValidatePublicKey(ecParams, publicValue) != SECSuccess) {
|
||||
PORT_SetError(SEC_ERROR_BAD_KEY);
|
||||
return SECFailure;
|
||||
}
|
||||
|
||||
/* Perform curve specific multiplication using ECMethod */
|
||||
if (ecParams->fieldID.type == ec_field_plain) {
|
||||
const ECMethod *method;
|
||||
@ -581,10 +590,6 @@ ECDH_Derive(SECItem *publicValue,
|
||||
PORT_SetError(SEC_ERROR_UNSUPPORTED_ELLIPTIC_CURVE);
|
||||
return SECFailure;
|
||||
}
|
||||
if (method->validate(publicValue) != SECSuccess) {
|
||||
PORT_SetError(SEC_ERROR_BAD_KEY);
|
||||
return SECFailure;
|
||||
}
|
||||
return method->mul(derivedSecret, privateValue, publicValue);
|
||||
}
|
||||
|
||||
@ -1002,9 +1007,14 @@ ECDSA_VerifyDigest(ECPublicKey *key, const SECItem *signature,
|
||||
}
|
||||
slen = signature->len / 2;
|
||||
|
||||
/*
|
||||
* The incoming point has been verified in sftk_handlePublicKeyObject.
|
||||
*/
|
||||
|
||||
SECITEM_AllocItem(NULL, &pointC, ecParams->pointSize);
|
||||
if (pointC.data == NULL)
|
||||
if (pointC.data == NULL) {
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
CHECK_MPI_OK(mp_init(&r_));
|
||||
CHECK_MPI_OK(mp_init(&s_));
|
||||
|
@ -90,20 +90,6 @@ the linear coefficient in the curve defining equation).
|
||||
|
||||
ecp_192.c and ecp_224.c provide optimized field arithmetic.
|
||||
|
||||
Point Arithmetic over Binary Polynomial Fields
|
||||
----------------------------------------------
|
||||
|
||||
ec2_aff.c provides point arithmetic using affine coordinates.
|
||||
|
||||
ec2_proj.c provides point arithmetic using projective coordinates.
|
||||
(Projective coordinates represent a point (x, y) as (X, Y, Z), where
|
||||
x=X/Z, y=Y/Z^2).
|
||||
|
||||
ec2_mont.c provides point multiplication using Montgomery projective
|
||||
coordinates.
|
||||
|
||||
ec2_163.c, ec2_193.c, and ec2_233.c provide optimized field arithmetic.
|
||||
|
||||
Field Arithmetic
|
||||
----------------
|
||||
|
||||
@ -126,18 +112,6 @@ fields defined by nistp192 and nistp224 primes.
|
||||
|
||||
ecl_gf.c provides wrappers around the basic field operations.
|
||||
|
||||
Binary Polynomial Field Arithmetic
|
||||
----------------------------------
|
||||
|
||||
../mpi/mp_gf2m.c provides basic binary polynomial field arithmetic,
|
||||
including addition, multiplication, squaring, mod, and division, as well
|
||||
as conversion ob polynomial representations between bitstring and int[].
|
||||
|
||||
ec2_163.c, ec2_193.c, and ec2_233.c provide optimized field mod, mul,
|
||||
and sqr operations.
|
||||
|
||||
ecl_gf.c provides wrappers around the basic field operations.
|
||||
|
||||
Field Encoding
|
||||
--------------
|
||||
|
||||
@ -187,81 +161,3 @@ arithmetic. Instead, they use basic field arithmetic with their
|
||||
optimized reduction (as in ecp_192.c and ecp_224.c). They
|
||||
use the same point multiplication and simultaneous point multiplication
|
||||
algorithms as other curves over prime fields.
|
||||
|
||||
Curves over binary polynomial fields by default use generic field
|
||||
arithmetic with montgomery point multiplication and basic kP + lQ
|
||||
computation (multiply, multiply, and add). (Wiring in function
|
||||
ECGroup_cons_GF2m in ecl.c.)
|
||||
|
||||
Curves over binary polynomial fields that have optimized field
|
||||
arithmetic (i.e., any 163-, 193, or 233-bit field) use their optimized
|
||||
field arithmetic. They use the same point multiplication and
|
||||
simultaneous point multiplication algorithms as other curves over binary
|
||||
fields.
|
||||
|
||||
Example
|
||||
-------
|
||||
|
||||
We provide an example for plugging in an optimized implementation for
|
||||
the Koblitz curve nistk163.
|
||||
|
||||
Suppose the file ec2_k163.c contains the optimized implementation. In
|
||||
particular it contains a point multiplication function:
|
||||
|
||||
mp_err ec_GF2m_nistk163_pt_mul(const mp_int *n, const mp_int *px,
|
||||
const mp_int *py, mp_int *rx, mp_int *ry, const ECGroup *group);
|
||||
|
||||
Since only a pt_mul function is provided, the generic pt_add function
|
||||
will be used.
|
||||
|
||||
There are two options for handling the optimized field arithmetic used
|
||||
by the ..._pt_mul function. Say the optimized field arithmetic includes
|
||||
the following functions:
|
||||
|
||||
mp_err ec_GF2m_nistk163_add(const mp_int *a, const mp_int *b,
|
||||
mp_int *r, const GFMethod *meth);
|
||||
mp_err ec_GF2m_nistk163_mul(const mp_int *a, const mp_int *b,
|
||||
mp_int *r, const GFMethod *meth);
|
||||
mp_err ec_GF2m_nistk163_sqr(const mp_int *a, const mp_int *b,
|
||||
mp_int *r, const GFMethod *meth);
|
||||
mp_err ec_GF2m_nistk163_div(const mp_int *a, const mp_int *b,
|
||||
mp_int *r, const GFMethod *meth);
|
||||
|
||||
First, the optimized field arithmetic could simply be called directly
|
||||
by the ..._pt_mul function. This would be accomplished by changing
|
||||
the ecgroup_fromNameAndHex function in ecl.c to include the following
|
||||
statements:
|
||||
|
||||
if (name == ECCurve_NIST_K163) {
|
||||
group = ECGroup_consGF2m(&irr, NULL, &curvea, &curveb, &genx,
|
||||
&geny, &order, params->cofactor);
|
||||
if (group == NULL) { res = MP_UNDEF; goto CLEANUP; }
|
||||
MP_CHECKOK( ec_group_set_nistk163(group) );
|
||||
}
|
||||
|
||||
and including in ec2_k163.c the following function:
|
||||
|
||||
mp_err ec_group_set_nistk163(ECGroup *group) {
|
||||
group->point_mul = &ec_GF2m_nistk163_pt_mul;
|
||||
return MP_OKAY;
|
||||
}
|
||||
|
||||
As a result, ec_GF2m_pt_add and similar functions would use the
|
||||
basic binary polynomial field arithmetic ec_GF2m_add, ec_GF2m_mul,
|
||||
ec_GF2m_sqr, and ec_GF2m_div.
|
||||
|
||||
Alternatively, the optimized field arithmetic could be wired into the
|
||||
group's GFMethod. This would be accomplished by putting the following
|
||||
function in ec2_k163.c:
|
||||
|
||||
mp_err ec_group_set_nistk163(ECGroup *group) {
|
||||
group->meth->field_add = &ec_GF2m_nistk163_add;
|
||||
group->meth->field_mul = &ec_GF2m_nistk163_mul;
|
||||
group->meth->field_sqr = &ec_GF2m_nistk163_sqr;
|
||||
group->meth->field_div = &ec_GF2m_nistk163_div;
|
||||
group->point_mul = &ec_GF2m_nistk163_pt_mul;
|
||||
return MP_OKAY;
|
||||
}
|
||||
|
||||
For an example of functions that use special field encodings, take a
|
||||
look at ecp_mont.c.
|
||||
|
@ -1,121 +0,0 @@
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* 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/. */
|
||||
|
||||
#include "mpi.h"
|
||||
#include "mplogic.h"
|
||||
#include "ecl.h"
|
||||
#include "ecp.h"
|
||||
#include "ecl-priv.h"
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <stdio.h>
|
||||
#include <time.h>
|
||||
#include <sys/time.h>
|
||||
#include <sys/resource.h>
|
||||
|
||||
/* Returns 2^e as an integer. This is meant to be used for small powers of
|
||||
* two. */
|
||||
int ec_twoTo(int e);
|
||||
|
||||
/* Number of bits of scalar to test */
|
||||
#define BITSIZE 160
|
||||
|
||||
/* Time k repetitions of operation op. */
|
||||
#define M_TimeOperation(op, k) \
|
||||
{ \
|
||||
double dStart, dNow, dUserTime; \
|
||||
struct rusage ru; \
|
||||
int i; \
|
||||
getrusage(RUSAGE_SELF, &ru); \
|
||||
dStart = (double)ru.ru_utime.tv_sec + (double)ru.ru_utime.tv_usec * 0.000001; \
|
||||
for (i = 0; i < k; i++) { \
|
||||
{ \
|
||||
op; \
|
||||
} \
|
||||
}; \
|
||||
getrusage(RUSAGE_SELF, &ru); \
|
||||
dNow = (double)ru.ru_utime.tv_sec + (double)ru.ru_utime.tv_usec * 0.000001; \
|
||||
dUserTime = dNow - dStart; \
|
||||
if (dUserTime) \
|
||||
printf(" %-45s\n k: %6i, t: %6.2f sec\n", #op, k, dUserTime); \
|
||||
}
|
||||
|
||||
/* Tests wNAF computation. Non-adjacent-form is discussed in the paper: D.
|
||||
* Hankerson, J. Hernandez and A. Menezes, "Software implementation of
|
||||
* elliptic curve cryptography over binary fields", Proc. CHES 2000. */
|
||||
|
||||
mp_err
|
||||
main(void)
|
||||
{
|
||||
signed char naf[BITSIZE + 1];
|
||||
ECGroup *group = NULL;
|
||||
mp_int k;
|
||||
mp_int *scalar;
|
||||
int i, count;
|
||||
int res;
|
||||
int w = 5;
|
||||
char s[1000];
|
||||
|
||||
/* Get a 160 bit scalar to compute wNAF from */
|
||||
group = ECGroup_fromName(ECCurve_SECG_PRIME_160R1);
|
||||
scalar = &group->genx;
|
||||
|
||||
/* Compute wNAF representation of scalar */
|
||||
ec_compute_wNAF(naf, BITSIZE, scalar, w);
|
||||
|
||||
/* Verify correctness of representation */
|
||||
mp_init(&k); /* init k to 0 */
|
||||
|
||||
for (i = BITSIZE; i >= 0; i--) {
|
||||
mp_add(&k, &k, &k);
|
||||
/* digits in mp_???_d are unsigned */
|
||||
if (naf[i] >= 0) {
|
||||
mp_add_d(&k, naf[i], &k);
|
||||
} else {
|
||||
mp_sub_d(&k, -naf[i], &k);
|
||||
}
|
||||
}
|
||||
|
||||
if (mp_cmp(&k, scalar) != 0) {
|
||||
printf("Error: incorrect NAF value.\n");
|
||||
MP_CHECKOK(mp_toradix(&k, s, 16));
|
||||
printf("NAF value %s\n", s);
|
||||
MP_CHECKOK(mp_toradix(scalar, s, 16));
|
||||
printf("original value %s\n", s);
|
||||
goto CLEANUP;
|
||||
}
|
||||
|
||||
/* Verify digits of representation are valid */
|
||||
for (i = 0; i <= BITSIZE; i++) {
|
||||
if (naf[i] % 2 == 0 && naf[i] != 0) {
|
||||
printf("Error: Even non-zero digit found.\n");
|
||||
goto CLEANUP;
|
||||
}
|
||||
if (naf[i] < -(ec_twoTo(w - 1)) || naf[i] >= ec_twoTo(w - 1)) {
|
||||
printf("Error: Magnitude of naf digit too large.\n");
|
||||
goto CLEANUP;
|
||||
}
|
||||
}
|
||||
|
||||
/* Verify sparsity of representation */
|
||||
count = w - 1;
|
||||
for (i = 0; i <= BITSIZE; i++) {
|
||||
if (naf[i] != 0) {
|
||||
if (count < w - 1) {
|
||||
printf("Error: Sparsity failed.\n");
|
||||
goto CLEANUP;
|
||||
}
|
||||
count = 0;
|
||||
} else
|
||||
count++;
|
||||
}
|
||||
|
||||
/* Check timing */
|
||||
M_TimeOperation(ec_compute_wNAF(naf, BITSIZE, scalar, w), 10000);
|
||||
|
||||
printf("Test passed.\n");
|
||||
CLEANUP:
|
||||
ECGroup_free(group);
|
||||
return MP_OKAY;
|
||||
}
|
@ -1,409 +0,0 @@
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* 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/. */
|
||||
|
||||
#include "mpi.h"
|
||||
#include "mplogic.h"
|
||||
#include "mpprime.h"
|
||||
#include "ecl.h"
|
||||
#include "ecl-curve.h"
|
||||
#include "ecp.h"
|
||||
#include <stdio.h>
|
||||
#include <strings.h>
|
||||
#include <assert.h>
|
||||
|
||||
#include <time.h>
|
||||
#include <sys/time.h>
|
||||
#include <sys/resource.h>
|
||||
|
||||
/* Time k repetitions of operation op. */
|
||||
#define M_TimeOperation(op, k) \
|
||||
{ \
|
||||
double dStart, dNow, dUserTime; \
|
||||
struct rusage ru; \
|
||||
int i; \
|
||||
getrusage(RUSAGE_SELF, &ru); \
|
||||
dStart = (double)ru.ru_utime.tv_sec + (double)ru.ru_utime.tv_usec * 0.000001; \
|
||||
for (i = 0; i < k; i++) { \
|
||||
{ \
|
||||
op; \
|
||||
} \
|
||||
}; \
|
||||
getrusage(RUSAGE_SELF, &ru); \
|
||||
dNow = (double)ru.ru_utime.tv_sec + (double)ru.ru_utime.tv_usec * 0.000001; \
|
||||
dUserTime = dNow - dStart; \
|
||||
if (dUserTime) \
|
||||
printf(" %-45s k: %6i, t: %6.2f sec\n", #op, k, dUserTime); \
|
||||
}
|
||||
|
||||
/* Test curve using generic field arithmetic. */
|
||||
#define ECTEST_GENERIC_GFP(name_c, name) \
|
||||
printf("Testing %s using generic implementation...\n", name_c); \
|
||||
params = EC_GetNamedCurveParams(name); \
|
||||
if (params == NULL) { \
|
||||
printf(" Error: could not construct params.\n"); \
|
||||
res = MP_NO; \
|
||||
goto CLEANUP; \
|
||||
} \
|
||||
ECGroup_free(group); \
|
||||
group = ECGroup_fromHex(params); \
|
||||
if (group == NULL) { \
|
||||
printf(" Error: could not construct group.\n"); \
|
||||
res = MP_NO; \
|
||||
goto CLEANUP; \
|
||||
} \
|
||||
MP_CHECKOK(ectest_curve_GFp(group, ectestPrint, ectestTime, 1)); \
|
||||
printf("... okay.\n");
|
||||
|
||||
/* Test curve using specific field arithmetic. */
|
||||
#define ECTEST_NAMED_GFP(name_c, name) \
|
||||
printf("Testing %s using specific implementation...\n", name_c); \
|
||||
ECGroup_free(group); \
|
||||
group = ECGroup_fromName(name); \
|
||||
if (group == NULL) { \
|
||||
printf(" Warning: could not construct group.\n"); \
|
||||
printf("... failed; continuing with remaining tests.\n"); \
|
||||
} else { \
|
||||
MP_CHECKOK(ectest_curve_GFp(group, ectestPrint, ectestTime, 0)); \
|
||||
printf("... okay.\n"); \
|
||||
}
|
||||
|
||||
/* Performs basic tests of elliptic curve cryptography over prime fields.
|
||||
* If tests fail, then it prints an error message, aborts, and returns an
|
||||
* error code. Otherwise, returns 0. */
|
||||
int
|
||||
ectest_curve_GFp(ECGroup *group, int ectestPrint, int ectestTime,
|
||||
int generic)
|
||||
{
|
||||
|
||||
mp_int one, order_1, gx, gy, rx, ry, n;
|
||||
int size;
|
||||
mp_err res;
|
||||
char s[1000];
|
||||
|
||||
/* initialize values */
|
||||
MP_CHECKOK(mp_init(&one));
|
||||
MP_CHECKOK(mp_init(&order_1));
|
||||
MP_CHECKOK(mp_init(&gx));
|
||||
MP_CHECKOK(mp_init(&gy));
|
||||
MP_CHECKOK(mp_init(&rx));
|
||||
MP_CHECKOK(mp_init(&ry));
|
||||
MP_CHECKOK(mp_init(&n));
|
||||
|
||||
MP_CHECKOK(mp_set_int(&one, 1));
|
||||
MP_CHECKOK(mp_sub(&group->order, &one, &order_1));
|
||||
|
||||
/* encode base point */
|
||||
if (group->meth->field_dec) {
|
||||
MP_CHECKOK(group->meth->field_dec(&group->genx, &gx, group->meth));
|
||||
MP_CHECKOK(group->meth->field_dec(&group->geny, &gy, group->meth));
|
||||
} else {
|
||||
MP_CHECKOK(mp_copy(&group->genx, &gx));
|
||||
MP_CHECKOK(mp_copy(&group->geny, &gy));
|
||||
}
|
||||
if (ectestPrint) {
|
||||
/* output base point */
|
||||
printf(" base point P:\n");
|
||||
MP_CHECKOK(mp_toradix(&gx, s, 16));
|
||||
printf(" %s\n", s);
|
||||
MP_CHECKOK(mp_toradix(&gy, s, 16));
|
||||
printf(" %s\n", s);
|
||||
if (group->meth->field_enc) {
|
||||
printf(" base point P (encoded):\n");
|
||||
MP_CHECKOK(mp_toradix(&group->genx, s, 16));
|
||||
printf(" %s\n", s);
|
||||
MP_CHECKOK(mp_toradix(&group->geny, s, 16));
|
||||
printf(" %s\n", s);
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef ECL_ENABLE_GFP_PT_MUL_AFF
|
||||
/* multiply base point by order - 1 and check for negative of base
|
||||
* point */
|
||||
MP_CHECKOK(ec_GFp_pt_mul_aff(&order_1, &group->genx, &group->geny, &rx, &ry, group));
|
||||
if (ectestPrint) {
|
||||
printf(" (order-1)*P (affine):\n");
|
||||
MP_CHECKOK(mp_toradix(&rx, s, 16));
|
||||
printf(" %s\n", s);
|
||||
MP_CHECKOK(mp_toradix(&ry, s, 16));
|
||||
printf(" %s\n", s);
|
||||
}
|
||||
MP_CHECKOK(group->meth->field_neg(&ry, &ry, group->meth));
|
||||
if ((mp_cmp(&rx, &group->genx) != 0) || (mp_cmp(&ry, &group->geny) != 0)) {
|
||||
printf(" Error: invalid result (expected (- base point)).\n");
|
||||
res = MP_NO;
|
||||
goto CLEANUP;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef ECL_ENABLE_GFP_PT_MUL_AFF
|
||||
/* multiply base point by order - 1 and check for negative of base
|
||||
* point */
|
||||
MP_CHECKOK(ec_GFp_pt_mul_jac(&order_1, &group->genx, &group->geny, &rx, &ry, group));
|
||||
if (ectestPrint) {
|
||||
printf(" (order-1)*P (jacobian):\n");
|
||||
MP_CHECKOK(mp_toradix(&rx, s, 16));
|
||||
printf(" %s\n", s);
|
||||
MP_CHECKOK(mp_toradix(&ry, s, 16));
|
||||
printf(" %s\n", s);
|
||||
}
|
||||
MP_CHECKOK(group->meth->field_neg(&ry, &ry, group->meth));
|
||||
if ((mp_cmp(&rx, &group->genx) != 0) || (mp_cmp(&ry, &group->geny) != 0)) {
|
||||
printf(" Error: invalid result (expected (- base point)).\n");
|
||||
res = MP_NO;
|
||||
goto CLEANUP;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* multiply base point by order - 1 and check for negative of base
|
||||
* point */
|
||||
MP_CHECKOK(ECPoint_mul(group, &order_1, NULL, NULL, &rx, &ry));
|
||||
if (ectestPrint) {
|
||||
printf(" (order-1)*P (ECPoint_mul):\n");
|
||||
MP_CHECKOK(mp_toradix(&rx, s, 16));
|
||||
printf(" %s\n", s);
|
||||
MP_CHECKOK(mp_toradix(&ry, s, 16));
|
||||
printf(" %s\n", s);
|
||||
}
|
||||
MP_CHECKOK(mp_submod(&group->meth->irr, &ry, &group->meth->irr, &ry));
|
||||
if ((mp_cmp(&rx, &gx) != 0) || (mp_cmp(&ry, &gy) != 0)) {
|
||||
printf(" Error: invalid result (expected (- base point)).\n");
|
||||
res = MP_NO;
|
||||
goto CLEANUP;
|
||||
}
|
||||
|
||||
/* multiply base point by order - 1 and check for negative of base
|
||||
* point */
|
||||
MP_CHECKOK(ECPoint_mul(group, &order_1, &gx, &gy, &rx, &ry));
|
||||
if (ectestPrint) {
|
||||
printf(" (order-1)*P (ECPoint_mul):\n");
|
||||
MP_CHECKOK(mp_toradix(&rx, s, 16));
|
||||
printf(" %s\n", s);
|
||||
MP_CHECKOK(mp_toradix(&ry, s, 16));
|
||||
printf(" %s\n", s);
|
||||
}
|
||||
MP_CHECKOK(mp_submod(&group->meth->irr, &ry, &group->meth->irr, &ry));
|
||||
if ((mp_cmp(&rx, &gx) != 0) || (mp_cmp(&ry, &gy) != 0)) {
|
||||
printf(" Error: invalid result (expected (- base point)).\n");
|
||||
res = MP_NO;
|
||||
goto CLEANUP;
|
||||
}
|
||||
|
||||
#ifdef ECL_ENABLE_GFP_PT_MUL_AFF
|
||||
/* multiply base point by order and check for point at infinity */
|
||||
MP_CHECKOK(ec_GFp_pt_mul_aff(&group->order, &group->genx, &group->geny, &rx, &ry,
|
||||
group));
|
||||
if (ectestPrint) {
|
||||
printf(" (order)*P (affine):\n");
|
||||
MP_CHECKOK(mp_toradix(&rx, s, 16));
|
||||
printf(" %s\n", s);
|
||||
MP_CHECKOK(mp_toradix(&ry, s, 16));
|
||||
printf(" %s\n", s);
|
||||
}
|
||||
if (ec_GFp_pt_is_inf_aff(&rx, &ry) != MP_YES) {
|
||||
printf(" Error: invalid result (expected point at infinity).\n");
|
||||
res = MP_NO;
|
||||
goto CLEANUP;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef ECL_ENABLE_GFP_PT_MUL_JAC
|
||||
/* multiply base point by order and check for point at infinity */
|
||||
MP_CHECKOK(ec_GFp_pt_mul_jac(&group->order, &group->genx, &group->geny, &rx, &ry,
|
||||
group));
|
||||
if (ectestPrint) {
|
||||
printf(" (order)*P (jacobian):\n");
|
||||
MP_CHECKOK(mp_toradix(&rx, s, 16));
|
||||
printf(" %s\n", s);
|
||||
MP_CHECKOK(mp_toradix(&ry, s, 16));
|
||||
printf(" %s\n", s);
|
||||
}
|
||||
if (ec_GFp_pt_is_inf_aff(&rx, &ry) != MP_YES) {
|
||||
printf(" Error: invalid result (expected point at infinity).\n");
|
||||
res = MP_NO;
|
||||
goto CLEANUP;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* multiply base point by order and check for point at infinity */
|
||||
MP_CHECKOK(ECPoint_mul(group, &group->order, NULL, NULL, &rx, &ry));
|
||||
if (ectestPrint) {
|
||||
printf(" (order)*P (ECPoint_mul):\n");
|
||||
MP_CHECKOK(mp_toradix(&rx, s, 16));
|
||||
printf(" %s\n", s);
|
||||
MP_CHECKOK(mp_toradix(&ry, s, 16));
|
||||
printf(" %s\n", s);
|
||||
}
|
||||
if (ec_GFp_pt_is_inf_aff(&rx, &ry) != MP_YES) {
|
||||
printf(" Error: invalid result (expected point at infinity).\n");
|
||||
res = MP_NO;
|
||||
goto CLEANUP;
|
||||
}
|
||||
|
||||
/* multiply base point by order and check for point at infinity */
|
||||
MP_CHECKOK(ECPoint_mul(group, &group->order, &gx, &gy, &rx, &ry));
|
||||
if (ectestPrint) {
|
||||
printf(" (order)*P (ECPoint_mul):\n");
|
||||
MP_CHECKOK(mp_toradix(&rx, s, 16));
|
||||
printf(" %s\n", s);
|
||||
MP_CHECKOK(mp_toradix(&ry, s, 16));
|
||||
printf(" %s\n", s);
|
||||
}
|
||||
if (ec_GFp_pt_is_inf_aff(&rx, &ry) != MP_YES) {
|
||||
printf(" Error: invalid result (expected point at infinity).\n");
|
||||
res = MP_NO;
|
||||
goto CLEANUP;
|
||||
}
|
||||
|
||||
/* check that (order-1)P + (order-1)P + P == (order-1)P */
|
||||
MP_CHECKOK(ECPoints_mul(group, &order_1, &order_1, &gx, &gy, &rx, &ry));
|
||||
MP_CHECKOK(ECPoints_mul(group, &one, &one, &rx, &ry, &rx, &ry));
|
||||
if (ectestPrint) {
|
||||
printf(" (order-1)*P + (order-1)*P + P == (order-1)*P (ECPoints_mul):\n");
|
||||
MP_CHECKOK(mp_toradix(&rx, s, 16));
|
||||
printf(" %s\n", s);
|
||||
MP_CHECKOK(mp_toradix(&ry, s, 16));
|
||||
printf(" %s\n", s);
|
||||
}
|
||||
MP_CHECKOK(mp_submod(&group->meth->irr, &ry, &group->meth->irr, &ry));
|
||||
if ((mp_cmp(&rx, &gx) != 0) || (mp_cmp(&ry, &gy) != 0)) {
|
||||
printf(" Error: invalid result (expected (- base point)).\n");
|
||||
res = MP_NO;
|
||||
goto CLEANUP;
|
||||
}
|
||||
|
||||
/* test validate_point function */
|
||||
if (ECPoint_validate(group, &gx, &gy) != MP_YES) {
|
||||
printf(" Error: validate point on base point failed.\n");
|
||||
res = MP_NO;
|
||||
goto CLEANUP;
|
||||
}
|
||||
MP_CHECKOK(mp_add_d(&gy, 1, &ry));
|
||||
if (ECPoint_validate(group, &gx, &ry) != MP_NO) {
|
||||
printf(" Error: validate point on invalid point passed.\n");
|
||||
res = MP_NO;
|
||||
goto CLEANUP;
|
||||
}
|
||||
|
||||
if (ectestTime) {
|
||||
/* compute random scalar */
|
||||
size = mpl_significant_bits(&group->meth->irr);
|
||||
if (size < MP_OKAY) {
|
||||
goto CLEANUP;
|
||||
}
|
||||
MP_CHECKOK(mpp_random_size(&n, (size + ECL_BITS - 1) / ECL_BITS));
|
||||
MP_CHECKOK(group->meth->field_mod(&n, &n, group->meth));
|
||||
/* timed test */
|
||||
if (generic) {
|
||||
#ifdef ECL_ENABLE_GFP_PT_MUL_AFF
|
||||
M_TimeOperation(MP_CHECKOK(ec_GFp_pt_mul_aff(&n, &group->genx, &group->geny, &rx, &ry,
|
||||
group)),
|
||||
100);
|
||||
#endif
|
||||
M_TimeOperation(MP_CHECKOK(ECPoint_mul(group, &n, NULL, NULL, &rx, &ry)),
|
||||
100);
|
||||
M_TimeOperation(MP_CHECKOK(ECPoints_mul(group, &n, &n, &gx, &gy, &rx, &ry)), 100);
|
||||
} else {
|
||||
M_TimeOperation(MP_CHECKOK(ECPoint_mul(group, &n, NULL, NULL, &rx, &ry)),
|
||||
100);
|
||||
M_TimeOperation(MP_CHECKOK(ECPoint_mul(group, &n, &gx, &gy, &rx, &ry)),
|
||||
100);
|
||||
M_TimeOperation(MP_CHECKOK(ECPoints_mul(group, &n, &n, &gx, &gy, &rx, &ry)), 100);
|
||||
}
|
||||
}
|
||||
|
||||
CLEANUP:
|
||||
mp_clear(&one);
|
||||
mp_clear(&order_1);
|
||||
mp_clear(&gx);
|
||||
mp_clear(&gy);
|
||||
mp_clear(&rx);
|
||||
mp_clear(&ry);
|
||||
mp_clear(&n);
|
||||
if (res != MP_OKAY) {
|
||||
printf(" Error: exiting with error value %i\n", res);
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
/* Prints help information. */
|
||||
void
|
||||
printUsage()
|
||||
{
|
||||
printf("Usage: ecp_test [--print] [--time]\n");
|
||||
printf(" --print Print out results of each point arithmetic test.\n");
|
||||
printf(" --time Benchmark point operations and print results.\n");
|
||||
}
|
||||
|
||||
/* Performs tests of elliptic curve cryptography over prime fields If
|
||||
* tests fail, then it prints an error message, aborts, and returns an
|
||||
* error code. Otherwise, returns 0. */
|
||||
int
|
||||
main(int argv, char **argc)
|
||||
{
|
||||
|
||||
int ectestTime = 0;
|
||||
int ectestPrint = 0;
|
||||
int i;
|
||||
ECGroup *group = NULL;
|
||||
ECCurveParams *params = NULL;
|
||||
mp_err res;
|
||||
|
||||
/* read command-line arguments */
|
||||
for (i = 1; i < argv; i++) {
|
||||
if ((strcasecmp(argc[i], "time") == 0) || (strcasecmp(argc[i], "-time") == 0) || (strcasecmp(argc[i], "--time") == 0)) {
|
||||
ectestTime = 1;
|
||||
} else if ((strcasecmp(argc[i], "print") == 0) || (strcasecmp(argc[i], "-print") == 0) || (strcasecmp(argc[i], "--print") == 0)) {
|
||||
ectestPrint = 1;
|
||||
} else {
|
||||
printUsage();
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
/* generic arithmetic tests */
|
||||
ECTEST_GENERIC_GFP("SECP-160R1", ECCurve_SECG_PRIME_160R1);
|
||||
|
||||
/* specific arithmetic tests */
|
||||
ECTEST_NAMED_GFP("NIST-P192", ECCurve_NIST_P192);
|
||||
ECTEST_NAMED_GFP("NIST-P224", ECCurve_NIST_P224);
|
||||
ECTEST_NAMED_GFP("NIST-P256", ECCurve_NIST_P256);
|
||||
ECTEST_NAMED_GFP("NIST-P384", ECCurve_NIST_P384);
|
||||
ECTEST_NAMED_GFP("NIST-P521", ECCurve_NIST_P521);
|
||||
ECTEST_NAMED_GFP("ANSI X9.62 PRIME192v1", ECCurve_X9_62_PRIME_192V1);
|
||||
ECTEST_NAMED_GFP("ANSI X9.62 PRIME192v2", ECCurve_X9_62_PRIME_192V2);
|
||||
ECTEST_NAMED_GFP("ANSI X9.62 PRIME192v3", ECCurve_X9_62_PRIME_192V3);
|
||||
ECTEST_NAMED_GFP("ANSI X9.62 PRIME239v1", ECCurve_X9_62_PRIME_239V1);
|
||||
ECTEST_NAMED_GFP("ANSI X9.62 PRIME239v2", ECCurve_X9_62_PRIME_239V2);
|
||||
ECTEST_NAMED_GFP("ANSI X9.62 PRIME239v3", ECCurve_X9_62_PRIME_239V3);
|
||||
ECTEST_NAMED_GFP("ANSI X9.62 PRIME256v1", ECCurve_X9_62_PRIME_256V1);
|
||||
ECTEST_NAMED_GFP("SECP-112R1", ECCurve_SECG_PRIME_112R1);
|
||||
ECTEST_NAMED_GFP("SECP-112R2", ECCurve_SECG_PRIME_112R2);
|
||||
ECTEST_NAMED_GFP("SECP-128R1", ECCurve_SECG_PRIME_128R1);
|
||||
ECTEST_NAMED_GFP("SECP-128R2", ECCurve_SECG_PRIME_128R2);
|
||||
ECTEST_NAMED_GFP("SECP-160K1", ECCurve_SECG_PRIME_160K1);
|
||||
ECTEST_NAMED_GFP("SECP-160R1", ECCurve_SECG_PRIME_160R1);
|
||||
ECTEST_NAMED_GFP("SECP-160R2", ECCurve_SECG_PRIME_160R2);
|
||||
ECTEST_NAMED_GFP("SECP-192K1", ECCurve_SECG_PRIME_192K1);
|
||||
ECTEST_NAMED_GFP("SECP-192R1", ECCurve_SECG_PRIME_192R1);
|
||||
ECTEST_NAMED_GFP("SECP-224K1", ECCurve_SECG_PRIME_224K1);
|
||||
ECTEST_NAMED_GFP("SECP-224R1", ECCurve_SECG_PRIME_224R1);
|
||||
ECTEST_NAMED_GFP("SECP-256K1", ECCurve_SECG_PRIME_256K1);
|
||||
ECTEST_NAMED_GFP("SECP-256R1", ECCurve_SECG_PRIME_256R1);
|
||||
ECTEST_NAMED_GFP("SECP-384R1", ECCurve_SECG_PRIME_384R1);
|
||||
ECTEST_NAMED_GFP("SECP-521R1", ECCurve_SECG_PRIME_521R1);
|
||||
ECTEST_NAMED_GFP("WTLS-6 (112)", ECCurve_WTLS_6);
|
||||
ECTEST_NAMED_GFP("WTLS-7 (160)", ECCurve_WTLS_7);
|
||||
ECTEST_NAMED_GFP("WTLS-8 (112)", ECCurve_WTLS_8);
|
||||
ECTEST_NAMED_GFP("WTLS-9 (160)", ECCurve_WTLS_9);
|
||||
ECTEST_NAMED_GFP("WTLS-12 (224)", ECCurve_WTLS_12);
|
||||
ECTEST_NAMED_GFP("Curve25519", ECCurve25519);
|
||||
|
||||
CLEANUP:
|
||||
EC_FreeCurveParams(params);
|
||||
ECGroup_free(group);
|
||||
if (res != MP_OKAY) {
|
||||
printf("Error: exiting with error value %i\n", res);
|
||||
}
|
||||
return res;
|
||||
}
|
@ -104,6 +104,10 @@
|
||||
'<(DEPTH)/lib/util/util.gyp:nssutil3',
|
||||
],
|
||||
}],
|
||||
]
|
||||
}],
|
||||
[ 'OS=="linux" or OS=="android"', {
|
||||
'conditions': [
|
||||
[ 'target_arch=="x64"', {
|
||||
'sources': [
|
||||
'arcfour-amd64-gas.s',
|
||||
@ -142,7 +146,7 @@
|
||||
}],
|
||||
],
|
||||
}, {
|
||||
# not Linux
|
||||
# not Linux or Android
|
||||
'conditions': [
|
||||
[ 'moz_fold_libs==0', {
|
||||
'dependencies': [
|
||||
@ -221,7 +225,7 @@
|
||||
}],
|
||||
],
|
||||
}],
|
||||
[ 'fuzz==1', {
|
||||
[ 'fuzz_tls==1', {
|
||||
'sources': [
|
||||
'det_rng.c',
|
||||
],
|
||||
@ -229,7 +233,7 @@
|
||||
'UNSAFE_FUZZER_MODE',
|
||||
],
|
||||
}],
|
||||
[ 'test_build==1', {
|
||||
[ 'ct_verif==1', {
|
||||
'defines': [
|
||||
'CT_VERIF',
|
||||
],
|
||||
@ -374,6 +378,10 @@
|
||||
'FREEBL_NO_DEPEND',
|
||||
],
|
||||
}],
|
||||
],
|
||||
}],
|
||||
[ 'OS=="linux" or OS=="android"', {
|
||||
'conditions': [
|
||||
[ 'target_arch=="x64"', {
|
||||
'defines': [
|
||||
'MP_IS_LITTLE_ENDIAN',
|
||||
@ -383,7 +391,7 @@
|
||||
'NSS_USE_COMBA',
|
||||
],
|
||||
}],
|
||||
[ 'target_arch=="x64" and use_msan==0', {
|
||||
[ 'target_arch=="x64"', {
|
||||
'defines': [
|
||||
'USE_HW_AES',
|
||||
'INTEL_GCM',
|
||||
@ -406,7 +414,7 @@
|
||||
'SHA_NO_LONG_LONG',
|
||||
],
|
||||
}],
|
||||
[ 'target_arch=="arm64"', {
|
||||
[ 'target_arch=="arm64" or target_arch=="aarch64"', {
|
||||
'defines': [
|
||||
'NSS_USE_64',
|
||||
],
|
||||
|
@ -1,334 +0,0 @@
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* 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/. */
|
||||
|
||||
#define INCL_DOS
|
||||
#define INCL_DOSERRORS
|
||||
#include <os2.h>
|
||||
#include "secrng.h"
|
||||
#include "prerror.h"
|
||||
#include <stdlib.h>
|
||||
#include <time.h>
|
||||
#include <stdio.h>
|
||||
#include <sys/stat.h>
|
||||
|
||||
static BOOL
|
||||
clockTickTime(unsigned long *phigh, unsigned long *plow)
|
||||
{
|
||||
APIRET rc = NO_ERROR;
|
||||
QWORD qword = { 0, 0 };
|
||||
|
||||
rc = DosTmrQueryTime(&qword);
|
||||
if (rc != NO_ERROR)
|
||||
return FALSE;
|
||||
|
||||
*phigh = qword.ulHi;
|
||||
*plow = qword.ulLo;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
size_t
|
||||
RNG_GetNoise(void *buf, size_t maxbuf)
|
||||
{
|
||||
unsigned long high = 0;
|
||||
unsigned long low = 0;
|
||||
clock_t val = 0;
|
||||
int n = 0;
|
||||
int nBytes = 0;
|
||||
time_t sTime;
|
||||
|
||||
if (maxbuf <= 0)
|
||||
return 0;
|
||||
|
||||
clockTickTime(&high, &low);
|
||||
|
||||
/* get the maximally changing bits first */
|
||||
nBytes = sizeof(low) > maxbuf ? maxbuf : sizeof(low);
|
||||
memcpy(buf, &low, nBytes);
|
||||
n += nBytes;
|
||||
maxbuf -= nBytes;
|
||||
|
||||
if (maxbuf <= 0)
|
||||
return n;
|
||||
|
||||
nBytes = sizeof(high) > maxbuf ? maxbuf : sizeof(high);
|
||||
memcpy(((char *)buf) + n, &high, nBytes);
|
||||
n += nBytes;
|
||||
maxbuf -= nBytes;
|
||||
|
||||
if (maxbuf <= 0)
|
||||
return n;
|
||||
|
||||
/* get the number of milliseconds that have elapsed since application started */
|
||||
val = clock();
|
||||
|
||||
nBytes = sizeof(val) > maxbuf ? maxbuf : sizeof(val);
|
||||
memcpy(((char *)buf) + n, &val, nBytes);
|
||||
n += nBytes;
|
||||
maxbuf -= nBytes;
|
||||
|
||||
if (maxbuf <= 0)
|
||||
return n;
|
||||
|
||||
/* get the time in seconds since midnight Jan 1, 1970 */
|
||||
time(&sTime);
|
||||
nBytes = sizeof(sTime) > maxbuf ? maxbuf : sizeof(sTime);
|
||||
memcpy(((char *)buf) + n, &sTime, nBytes);
|
||||
n += nBytes;
|
||||
|
||||
return n;
|
||||
}
|
||||
|
||||
static BOOL
|
||||
EnumSystemFiles(void (*func)(const char *))
|
||||
{
|
||||
APIRET rc;
|
||||
ULONG sysInfo = 0;
|
||||
char bootLetter[2];
|
||||
char sysDir[_MAX_PATH] = "";
|
||||
char filename[_MAX_PATH];
|
||||
HDIR hdir = HDIR_CREATE;
|
||||
ULONG numFiles = 1;
|
||||
FILEFINDBUF3 fileBuf = { 0 };
|
||||
ULONG buflen = sizeof(FILEFINDBUF3);
|
||||
|
||||
if (DosQuerySysInfo(QSV_BOOT_DRIVE, QSV_BOOT_DRIVE, (PVOID)&sysInfo,
|
||||
sizeof(ULONG)) == NO_ERROR) {
|
||||
bootLetter[0] = sysInfo + 'A' - 1;
|
||||
bootLetter[1] = '\0';
|
||||
strcpy(sysDir, bootLetter);
|
||||
strcpy(sysDir + 1, ":\\OS2\\");
|
||||
|
||||
strcpy(filename, sysDir);
|
||||
strcat(filename, "*.*");
|
||||
}
|
||||
|
||||
rc = DosFindFirst(filename, &hdir, FILE_NORMAL, &fileBuf, buflen,
|
||||
&numFiles, FIL_STANDARD);
|
||||
if (rc == NO_ERROR) {
|
||||
do {
|
||||
// pass the full pathname to the callback
|
||||
sprintf(filename, "%s%s", sysDir, fileBuf.achName);
|
||||
(*func)(filename);
|
||||
|
||||
numFiles = 1;
|
||||
rc = DosFindNext(hdir, &fileBuf, buflen, &numFiles);
|
||||
if (rc != NO_ERROR && rc != ERROR_NO_MORE_FILES)
|
||||
printf("DosFindNext errod code = %d\n", rc);
|
||||
} while (rc == NO_ERROR);
|
||||
|
||||
rc = DosFindClose(hdir);
|
||||
if (rc != NO_ERROR)
|
||||
printf("DosFindClose error code = %d", rc);
|
||||
} else
|
||||
printf("DosFindFirst error code = %d", rc);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static int dwNumFiles, dwReadEvery, dwFileToRead = 0;
|
||||
|
||||
static void
|
||||
CountFiles(const char *file)
|
||||
{
|
||||
dwNumFiles++;
|
||||
}
|
||||
|
||||
static void
|
||||
ReadFiles(const char *file)
|
||||
{
|
||||
if ((dwNumFiles % dwReadEvery) == 0)
|
||||
RNG_FileForRNG(file);
|
||||
|
||||
dwNumFiles++;
|
||||
}
|
||||
|
||||
static void
|
||||
ReadSingleFile(const char *filename)
|
||||
{
|
||||
unsigned char buffer[1024];
|
||||
FILE *file;
|
||||
|
||||
file = fopen((char *)filename, "rb");
|
||||
if (file != NULL) {
|
||||
while (fread(buffer, 1, sizeof(buffer), file) > 0)
|
||||
;
|
||||
fclose(file);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
ReadOneFile(const char *file)
|
||||
{
|
||||
if (dwNumFiles == dwFileToRead) {
|
||||
ReadSingleFile(file);
|
||||
}
|
||||
|
||||
dwNumFiles++;
|
||||
}
|
||||
|
||||
static void
|
||||
ReadSystemFiles(void)
|
||||
{
|
||||
// first count the number of files
|
||||
dwNumFiles = 0;
|
||||
if (!EnumSystemFiles(CountFiles))
|
||||
return;
|
||||
|
||||
RNG_RandomUpdate(&dwNumFiles, sizeof(dwNumFiles));
|
||||
|
||||
// now read 10 files
|
||||
if (dwNumFiles == 0)
|
||||
return;
|
||||
|
||||
dwReadEvery = dwNumFiles / 10;
|
||||
if (dwReadEvery == 0)
|
||||
dwReadEvery = 1; // less than 10 files
|
||||
|
||||
dwNumFiles = 0;
|
||||
EnumSystemFiles(ReadFiles);
|
||||
}
|
||||
|
||||
void
|
||||
RNG_SystemInfoForRNG(void)
|
||||
{
|
||||
unsigned long *plong = 0;
|
||||
PTIB ptib;
|
||||
PPIB ppib;
|
||||
APIRET rc = NO_ERROR;
|
||||
DATETIME dt;
|
||||
COUNTRYCODE cc = { 0 };
|
||||
COUNTRYINFO ci = { 0 };
|
||||
unsigned long actual = 0;
|
||||
char path[_MAX_PATH] = "";
|
||||
char fullpath[_MAX_PATH] = "";
|
||||
unsigned long pathlength = sizeof(path);
|
||||
FSALLOCATE fsallocate;
|
||||
FILESTATUS3 fstatus;
|
||||
unsigned long defaultdrive = 0;
|
||||
unsigned long logicaldrives = 0;
|
||||
unsigned long sysInfo[QSV_MAX] = { 0 };
|
||||
char buffer[20];
|
||||
int nBytes = 0;
|
||||
|
||||
nBytes = RNG_GetNoise(buffer, sizeof(buffer));
|
||||
RNG_RandomUpdate(buffer, nBytes);
|
||||
|
||||
/* allocate memory and use address and memory */
|
||||
plong = (unsigned long *)malloc(sizeof(*plong));
|
||||
RNG_RandomUpdate(&plong, sizeof(plong));
|
||||
RNG_RandomUpdate(plong, sizeof(*plong));
|
||||
free(plong);
|
||||
|
||||
/* process info */
|
||||
rc = DosGetInfoBlocks(&ptib, &ppib);
|
||||
if (rc == NO_ERROR) {
|
||||
RNG_RandomUpdate(ptib, sizeof(*ptib));
|
||||
RNG_RandomUpdate(ppib, sizeof(*ppib));
|
||||
}
|
||||
|
||||
/* time */
|
||||
rc = DosGetDateTime(&dt);
|
||||
if (rc == NO_ERROR) {
|
||||
RNG_RandomUpdate(&dt, sizeof(dt));
|
||||
}
|
||||
|
||||
/* country */
|
||||
rc = DosQueryCtryInfo(sizeof(ci), &cc, &ci, &actual);
|
||||
if (rc == NO_ERROR) {
|
||||
RNG_RandomUpdate(&cc, sizeof(cc));
|
||||
RNG_RandomUpdate(&ci, sizeof(ci));
|
||||
RNG_RandomUpdate(&actual, sizeof(actual));
|
||||
}
|
||||
|
||||
/* current directory */
|
||||
rc = DosQueryCurrentDir(0, path, &pathlength);
|
||||
strcat(fullpath, "\\");
|
||||
strcat(fullpath, path);
|
||||
if (rc == NO_ERROR) {
|
||||
RNG_RandomUpdate(fullpath, strlen(fullpath));
|
||||
// path info
|
||||
rc = DosQueryPathInfo(fullpath, FIL_STANDARD, &fstatus, sizeof(fstatus));
|
||||
if (rc == NO_ERROR) {
|
||||
RNG_RandomUpdate(&fstatus, sizeof(fstatus));
|
||||
}
|
||||
}
|
||||
|
||||
/* file system info */
|
||||
rc = DosQueryFSInfo(0, FSIL_ALLOC, &fsallocate, sizeof(fsallocate));
|
||||
if (rc == NO_ERROR) {
|
||||
RNG_RandomUpdate(&fsallocate, sizeof(fsallocate));
|
||||
}
|
||||
|
||||
/* drive info */
|
||||
rc = DosQueryCurrentDisk(&defaultdrive, &logicaldrives);
|
||||
if (rc == NO_ERROR) {
|
||||
RNG_RandomUpdate(&defaultdrive, sizeof(defaultdrive));
|
||||
RNG_RandomUpdate(&logicaldrives, sizeof(logicaldrives));
|
||||
}
|
||||
|
||||
/* system info */
|
||||
rc = DosQuerySysInfo(1L, QSV_MAX, (PVOID)&sysInfo, sizeof(ULONG) * QSV_MAX);
|
||||
if (rc == NO_ERROR) {
|
||||
RNG_RandomUpdate(&sysInfo, sizeof(sysInfo));
|
||||
}
|
||||
|
||||
// now let's do some files
|
||||
ReadSystemFiles();
|
||||
|
||||
/* more noise */
|
||||
nBytes = RNG_GetNoise(buffer, sizeof(buffer));
|
||||
RNG_RandomUpdate(buffer, nBytes);
|
||||
}
|
||||
|
||||
void
|
||||
RNG_FileForRNG(const char *filename)
|
||||
{
|
||||
struct stat stat_buf;
|
||||
unsigned char buffer[1024];
|
||||
FILE *file = 0;
|
||||
int nBytes = 0;
|
||||
static int totalFileBytes = 0;
|
||||
|
||||
if (stat((char *)filename, &stat_buf) < 0)
|
||||
return;
|
||||
|
||||
RNG_RandomUpdate((unsigned char *)&stat_buf, sizeof(stat_buf));
|
||||
|
||||
file = fopen((char *)filename, "r");
|
||||
if (file != NULL) {
|
||||
for (;;) {
|
||||
size_t bytes = fread(buffer, 1, sizeof(buffer), file);
|
||||
|
||||
if (bytes == 0)
|
||||
break;
|
||||
|
||||
RNG_RandomUpdate(buffer, bytes);
|
||||
totalFileBytes += bytes;
|
||||
if (totalFileBytes > 250000)
|
||||
break;
|
||||
}
|
||||
fclose(file);
|
||||
}
|
||||
|
||||
nBytes = RNG_GetNoise(buffer, 20);
|
||||
RNG_RandomUpdate(buffer, nBytes);
|
||||
}
|
||||
|
||||
static void
|
||||
rng_systemJitter(void)
|
||||
{
|
||||
dwNumFiles = 0;
|
||||
EnumSystemFiles(ReadOneFile);
|
||||
dwFileToRead++;
|
||||
if (dwFileToRead >= dwNumFiles) {
|
||||
dwFileToRead = 0;
|
||||
}
|
||||
}
|
||||
|
||||
size_t
|
||||
RNG_SystemRNG(void *dest, size_t maxLen)
|
||||
{
|
||||
return rng_systemFromNoise(dest, maxLen);
|
||||
}
|
@ -8,42 +8,9 @@
|
||||
|
||||
#include "seccomon.h"
|
||||
|
||||
#ifndef XP_WIN
|
||||
static size_t rng_systemFromNoise(unsigned char *dest, size_t maxLen);
|
||||
#endif
|
||||
|
||||
#if defined(XP_UNIX) || defined(XP_BEOS)
|
||||
#include "unix_rand.c"
|
||||
#endif
|
||||
#ifdef XP_WIN
|
||||
#include "win_rand.c"
|
||||
#endif
|
||||
#ifdef XP_OS2
|
||||
#include "os2_rand.c"
|
||||
#endif
|
||||
|
||||
#ifndef XP_WIN
|
||||
/*
|
||||
* Normal RNG_SystemRNG() isn't available, use the system noise to collect
|
||||
* the required amount of entropy.
|
||||
*/
|
||||
static size_t
|
||||
rng_systemFromNoise(unsigned char *dest, size_t maxLen)
|
||||
{
|
||||
size_t retBytes = maxLen;
|
||||
|
||||
while (maxLen) {
|
||||
size_t nbytes = RNG_GetNoise(dest, maxLen);
|
||||
|
||||
PORT_Assert(nbytes != 0);
|
||||
|
||||
dest += nbytes;
|
||||
maxLen -= nbytes;
|
||||
|
||||
/* some hw op to try to introduce more entropy into the next
|
||||
* RNG_GetNoise call */
|
||||
rng_systemJitter();
|
||||
}
|
||||
return retBytes;
|
||||
}
|
||||
#endif
|
||||
|
@ -894,6 +894,9 @@ RNG_SystemInfoForRNG(void)
|
||||
|
||||
/* grab some data from system's PRNG before any other files. */
|
||||
bytes = RNG_FileUpdate("/dev/urandom", SYSTEM_RNG_SEED_COUNT);
|
||||
if (!bytes) {
|
||||
PORT_SetError(SEC_ERROR_NEED_RANDOM);
|
||||
}
|
||||
|
||||
/* If the user points us to a random file, pass it through the rng */
|
||||
randfile = PR_GetEnvSecure("NSRANDFILE");
|
||||
@ -1022,20 +1025,6 @@ RNG_FileForRNG(const char *fileName)
|
||||
RNG_FileUpdate(fileName, TOTAL_FILE_LIMIT);
|
||||
}
|
||||
|
||||
void
|
||||
ReadSingleFile(const char *fileName)
|
||||
{
|
||||
FILE *file;
|
||||
unsigned char buffer[BUFSIZ];
|
||||
|
||||
file = fopen(fileName, "rb");
|
||||
if (file != NULL) {
|
||||
while (fread(buffer, 1, sizeof(buffer), file) > 0)
|
||||
;
|
||||
fclose(file);
|
||||
}
|
||||
}
|
||||
|
||||
#define _POSIX_PTHREAD_SEMANTICS
|
||||
#include <dirent.h>
|
||||
|
||||
@ -1055,89 +1044,6 @@ ReadFileOK(char *dir, char *file)
|
||||
return S_ISREG(stat_buf.st_mode) ? PR_TRUE : PR_FALSE;
|
||||
}
|
||||
|
||||
/*
|
||||
* read one file out of either /etc or the user's home directory.
|
||||
* fileToRead tells which file to read.
|
||||
*
|
||||
* return 1 if it's time to reset the fileToRead (no more files to read).
|
||||
*/
|
||||
static int
|
||||
ReadOneFile(int fileToRead)
|
||||
{
|
||||
char *dir = "/etc";
|
||||
DIR *fd = opendir(dir);
|
||||
int resetCount = 0;
|
||||
struct dirent *entry;
|
||||
#if defined(__sun)
|
||||
char firstName[256];
|
||||
#else
|
||||
char firstName[NAME_MAX + 1];
|
||||
#endif
|
||||
const char *name = NULL;
|
||||
int i;
|
||||
|
||||
if (fd == NULL) {
|
||||
dir = PR_GetEnvSecure("HOME");
|
||||
if (dir) {
|
||||
fd = opendir(dir);
|
||||
}
|
||||
}
|
||||
if (fd == NULL) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
firstName[0] = '\0';
|
||||
for (i = 0; i <= fileToRead; i++) {
|
||||
do {
|
||||
/* readdir() isn't guaranteed to be thread safe on every platform;
|
||||
* this code assumes the same directory isn't read concurrently.
|
||||
* This usage is confirmed safe on Linux, see bug 1254334. */
|
||||
entry = readdir(fd);
|
||||
} while (entry != NULL && !ReadFileOK(dir, &entry->d_name[0]));
|
||||
if (entry == NULL) {
|
||||
resetCount = 1; /* read to the end, start again at the beginning */
|
||||
if (firstName[0]) {
|
||||
/* ran out of entries in the directory, use the first one */
|
||||
name = firstName;
|
||||
}
|
||||
break;
|
||||
}
|
||||
name = entry->d_name;
|
||||
if (i == 0) {
|
||||
/* copy the name of the first in case we run out of entries */
|
||||
PORT_Assert(PORT_Strlen(name) < sizeof(firstName));
|
||||
PORT_Strncpy(firstName, name, sizeof(firstName) - 1);
|
||||
firstName[sizeof(firstName) - 1] = '\0';
|
||||
}
|
||||
}
|
||||
|
||||
if (name) {
|
||||
char filename[PATH_MAX];
|
||||
int count = snprintf(filename, sizeof(filename), "%s/%s", dir, name);
|
||||
if (count >= 1) {
|
||||
ReadSingleFile(filename);
|
||||
}
|
||||
}
|
||||
|
||||
closedir(fd);
|
||||
return resetCount;
|
||||
}
|
||||
|
||||
/*
|
||||
* do something to try to introduce more noise into the 'GetNoise' call
|
||||
*/
|
||||
static void
|
||||
rng_systemJitter(void)
|
||||
{
|
||||
static int fileToRead = 1;
|
||||
|
||||
if (ReadOneFile(fileToRead)) {
|
||||
fileToRead = 1;
|
||||
} else {
|
||||
fileToRead++;
|
||||
}
|
||||
}
|
||||
|
||||
size_t
|
||||
RNG_SystemRNG(void *dest, size_t maxLen)
|
||||
{
|
||||
@ -1149,7 +1055,8 @@ RNG_SystemRNG(void *dest, size_t maxLen)
|
||||
|
||||
file = fopen("/dev/urandom", "r");
|
||||
if (file == NULL) {
|
||||
return rng_systemFromNoise(dest, maxLen);
|
||||
PORT_SetError(SEC_ERROR_NEED_RANDOM);
|
||||
return 0;
|
||||
}
|
||||
/* Read from the underlying file descriptor directly to bypass stdio
|
||||
* buffering and avoid reading more bytes than we need from /dev/urandom.
|
||||
|
@ -47,7 +47,10 @@ NSS_IMPLEMENT PRStatus
|
||||
NSSCryptoContext_Destroy(NSSCryptoContext *cc)
|
||||
{
|
||||
PRStatus status = PR_SUCCESS;
|
||||
PORT_Assert(cc->certStore);
|
||||
PORT_Assert(cc && cc->certStore);
|
||||
if (!cc) {
|
||||
return PR_FAILURE;
|
||||
}
|
||||
if (cc->certStore) {
|
||||
status = nssCertificateStore_Destroy(cc->certStore);
|
||||
if (status == PR_FAILURE) {
|
||||
@ -93,8 +96,8 @@ NSSCryptoContext_FindOrImportCertificate(
|
||||
{
|
||||
NSSCertificate *rvCert = NULL;
|
||||
|
||||
PORT_Assert(cc->certStore);
|
||||
if (!cc->certStore) {
|
||||
PORT_Assert(cc && cc->certStore);
|
||||
if (!cc || !cc->certStore) {
|
||||
nss_SetError(NSS_ERROR_INVALID_ARGUMENT);
|
||||
return rvCert;
|
||||
}
|
||||
@ -146,8 +149,8 @@ nssCryptoContext_ImportTrust(
|
||||
NSSTrust *trust)
|
||||
{
|
||||
PRStatus nssrv;
|
||||
PORT_Assert(cc->certStore);
|
||||
if (!cc->certStore) {
|
||||
PORT_Assert(cc && cc->certStore);
|
||||
if (!cc || !cc->certStore) {
|
||||
return PR_FAILURE;
|
||||
}
|
||||
nssrv = nssCertificateStore_AddTrust(cc->certStore, trust);
|
||||
@ -165,8 +168,8 @@ nssCryptoContext_ImportSMIMEProfile(
|
||||
nssSMIMEProfile *profile)
|
||||
{
|
||||
PRStatus nssrv;
|
||||
PORT_Assert(cc->certStore);
|
||||
if (!cc->certStore) {
|
||||
PORT_Assert(cc && cc->certStore);
|
||||
if (!cc || !cc->certStore) {
|
||||
return PR_FAILURE;
|
||||
}
|
||||
nssrv = nssCertificateStore_AddSMIMEProfile(cc->certStore, profile);
|
||||
@ -189,8 +192,8 @@ NSSCryptoContext_FindBestCertificateByNickname(
|
||||
{
|
||||
NSSCertificate **certs;
|
||||
NSSCertificate *rvCert = NULL;
|
||||
PORT_Assert(cc->certStore);
|
||||
if (!cc->certStore) {
|
||||
PORT_Assert(cc && cc->certStore);
|
||||
if (!cc || !cc->certStore) {
|
||||
return NULL;
|
||||
}
|
||||
certs = nssCertificateStore_FindCertificatesByNickname(cc->certStore,
|
||||
@ -215,8 +218,8 @@ NSSCryptoContext_FindCertificatesByNickname(
|
||||
NSSArena *arenaOpt)
|
||||
{
|
||||
NSSCertificate **rvCerts;
|
||||
PORT_Assert(cc->certStore);
|
||||
if (!cc->certStore) {
|
||||
PORT_Assert(cc && cc->certStore);
|
||||
if (!cc || !cc->certStore) {
|
||||
return NULL;
|
||||
}
|
||||
rvCerts = nssCertificateStore_FindCertificatesByNickname(cc->certStore,
|
||||
@ -233,8 +236,8 @@ NSSCryptoContext_FindCertificateByIssuerAndSerialNumber(
|
||||
NSSDER *issuer,
|
||||
NSSDER *serialNumber)
|
||||
{
|
||||
PORT_Assert(cc->certStore);
|
||||
if (!cc->certStore) {
|
||||
PORT_Assert(cc && cc->certStore);
|
||||
if (!cc || !cc->certStore) {
|
||||
return NULL;
|
||||
}
|
||||
return nssCertificateStore_FindCertificateByIssuerAndSerialNumber(
|
||||
@ -253,8 +256,8 @@ NSSCryptoContext_FindBestCertificateBySubject(
|
||||
{
|
||||
NSSCertificate **certs;
|
||||
NSSCertificate *rvCert = NULL;
|
||||
PORT_Assert(cc->certStore);
|
||||
if (!cc->certStore) {
|
||||
PORT_Assert(cc && cc->certStore);
|
||||
if (!cc || !cc->certStore) {
|
||||
return NULL;
|
||||
}
|
||||
certs = nssCertificateStore_FindCertificatesBySubject(cc->certStore,
|
||||
@ -279,8 +282,8 @@ nssCryptoContext_FindCertificatesBySubject(
|
||||
NSSArena *arenaOpt)
|
||||
{
|
||||
NSSCertificate **rvCerts;
|
||||
PORT_Assert(cc->certStore);
|
||||
if (!cc->certStore) {
|
||||
PORT_Assert(cc && cc->certStore);
|
||||
if (!cc || !cc->certStore) {
|
||||
return NULL;
|
||||
}
|
||||
rvCerts = nssCertificateStore_FindCertificatesBySubject(cc->certStore,
|
||||
@ -333,8 +336,8 @@ NSSCryptoContext_FindCertificateByEncodedCertificate(
|
||||
NSSCryptoContext *cc,
|
||||
NSSBER *encodedCertificate)
|
||||
{
|
||||
PORT_Assert(cc->certStore);
|
||||
if (!cc->certStore) {
|
||||
PORT_Assert(cc && cc->certStore);
|
||||
if (!cc || !cc->certStore) {
|
||||
return NULL;
|
||||
}
|
||||
return nssCertificateStore_FindCertificateByEncodedCertificate(
|
||||
@ -353,8 +356,8 @@ NSSCryptoContext_FindBestCertificateByEmail(
|
||||
NSSCertificate **certs;
|
||||
NSSCertificate *rvCert = NULL;
|
||||
|
||||
PORT_Assert(cc->certStore);
|
||||
if (!cc->certStore) {
|
||||
PORT_Assert(cc && cc->certStore);
|
||||
if (!cc || !cc->certStore) {
|
||||
return NULL;
|
||||
}
|
||||
certs = nssCertificateStore_FindCertificatesByEmail(cc->certStore,
|
||||
@ -379,8 +382,8 @@ NSSCryptoContext_FindCertificatesByEmail(
|
||||
NSSArena *arenaOpt)
|
||||
{
|
||||
NSSCertificate **rvCerts;
|
||||
PORT_Assert(cc->certStore);
|
||||
if (!cc->certStore) {
|
||||
PORT_Assert(cc && cc->certStore);
|
||||
if (!cc || !cc->certStore) {
|
||||
return NULL;
|
||||
}
|
||||
rvCerts = nssCertificateStore_FindCertificatesByEmail(cc->certStore,
|
||||
@ -488,8 +491,8 @@ nssCryptoContext_FindTrustForCertificate(
|
||||
NSSCryptoContext *cc,
|
||||
NSSCertificate *cert)
|
||||
{
|
||||
PORT_Assert(cc->certStore);
|
||||
if (!cc->certStore) {
|
||||
PORT_Assert(cc && cc->certStore);
|
||||
if (!cc || !cc->certStore) {
|
||||
return NULL;
|
||||
}
|
||||
return nssCertificateStore_FindTrustForCertificate(cc->certStore, cert);
|
||||
@ -500,8 +503,8 @@ nssCryptoContext_FindSMIMEProfileForCertificate(
|
||||
NSSCryptoContext *cc,
|
||||
NSSCertificate *cert)
|
||||
{
|
||||
PORT_Assert(cc->certStore);
|
||||
if (!cc->certStore) {
|
||||
PORT_Assert(cc && cc->certStore);
|
||||
if (!cc || !cc->certStore) {
|
||||
return NULL;
|
||||
}
|
||||
return nssCertificateStore_FindSMIMEProfileForCertificate(cc->certStore,
|
||||
|
@ -334,18 +334,12 @@ dbs_readBlob(DBS *dbsp, DBT *data)
|
||||
}
|
||||
|
||||
len = dbs_getBlobSize(data);
|
||||
mapfile = PR_CreateFileMap(filed, len, PR_PROT_READONLY);
|
||||
if (mapfile == NULL) {
|
||||
/* USE PR_GetError instead of PORT_GetError here
|
||||
* because we are getting the error from PR_xxx
|
||||
* function */
|
||||
if (PR_GetError() != PR_NOT_IMPLEMENTED_ERROR) {
|
||||
goto loser;
|
||||
}
|
||||
addr = dbs_EmulateMap(filed, len);
|
||||
} else {
|
||||
addr = PR_MemMap(mapfile, 0, len);
|
||||
}
|
||||
/* Bug 1323150
|
||||
* PR_MemMap fails on Windows for larger certificates.
|
||||
* https://msdn.microsoft.com/en-us/library/windows/desktop/aa366761(v=vs.85).aspx
|
||||
* Let's always use the emulated map, i.e. read the file.
|
||||
*/
|
||||
addr = dbs_EmulateMap(filed, len);
|
||||
if (addr == NULL) {
|
||||
goto loser;
|
||||
}
|
||||
|
@ -7267,14 +7267,6 @@ NSC_DeriveKey(CK_SESSION_HANDLE hSession,
|
||||
|
||||
if (mechanism == CKM_ECDH1_COFACTOR_DERIVE) {
|
||||
withCofactor = PR_TRUE;
|
||||
} else {
|
||||
/* When not using cofactor derivation, one should
|
||||
* validate the public key to avoid small subgroup
|
||||
* attacks.
|
||||
*/
|
||||
if (EC_ValidatePublicKey(&privKey->u.ec.ecParams, &ecPoint) != SECSuccess) {
|
||||
goto ec_loser;
|
||||
}
|
||||
}
|
||||
|
||||
rv = ECDH_Derive(&ecPoint, &privKey->u.ec.ecParams, &ecScalar,
|
||||
|
@ -505,3 +505,6 @@ ER3(SSL_ERROR_MALFORMED_PSK_KEY_EXCHANGE_MODES, (SSL_ERROR_BASE + 158),
|
||||
|
||||
ER3(SSL_ERROR_MISSING_PSK_KEY_EXCHANGE_MODES, (SSL_ERROR_BASE + 159),
|
||||
"SSL expected a PSK key exchange modes extension.")
|
||||
|
||||
ER3(SSL_ERROR_DOWNGRADE_WITH_EARLY_DATA, (SSL_ERROR_BASE + 160),
|
||||
"SSL got a pre-TLS 1.3 version even though we sent early data.")
|
||||
|
@ -63,7 +63,7 @@
|
||||
'NSS_SSL_ENABLE_ZLIB',
|
||||
],
|
||||
}],
|
||||
[ 'fuzz==1', {
|
||||
[ 'fuzz_tls==1', {
|
||||
'defines': [
|
||||
'UNSAFE_FUZZER_MODE',
|
||||
],
|
||||
|
@ -1044,8 +1044,9 @@ Null_Cipher(void *ctx, unsigned char *output, int *outputLen, int maxOutputLen,
|
||||
return SECFailure;
|
||||
}
|
||||
*outputLen = inputLen;
|
||||
if (input != output)
|
||||
if (inputLen > 0 && input != output) {
|
||||
PORT_Memcpy(output, input, inputLen);
|
||||
}
|
||||
return SECSuccess;
|
||||
}
|
||||
|
||||
@ -3121,6 +3122,10 @@ SSL3_SendAlert(sslSocket *ss, SSL3AlertLevel level, SSL3AlertDescription desc)
|
||||
{
|
||||
PRUint8 bytes[2];
|
||||
SECStatus rv;
|
||||
PRBool needHsLock = !ssl_HaveSSL3HandshakeLock(ss);
|
||||
|
||||
/* Check that if I need the HS lock I also need the Xmit lock */
|
||||
PORT_Assert(!needHsLock || !ssl_HaveXmitBufLock(ss));
|
||||
|
||||
SSL_TRC(3, ("%d: SSL3[%d]: send alert record, level=%d desc=%d",
|
||||
SSL_GETPID(), ss->fd, level, desc));
|
||||
@ -3128,7 +3133,9 @@ SSL3_SendAlert(sslSocket *ss, SSL3AlertLevel level, SSL3AlertDescription desc)
|
||||
bytes[0] = level;
|
||||
bytes[1] = desc;
|
||||
|
||||
ssl_GetSSL3HandshakeLock(ss);
|
||||
if (needHsLock) {
|
||||
ssl_GetSSL3HandshakeLock(ss);
|
||||
}
|
||||
if (level == alert_fatal) {
|
||||
if (!ss->opt.noCache && ss->sec.ci.sid) {
|
||||
ss->sec.uncache(ss->sec.ci.sid);
|
||||
@ -3146,7 +3153,9 @@ SSL3_SendAlert(sslSocket *ss, SSL3AlertLevel level, SSL3AlertDescription desc)
|
||||
ss->ssl3.fatalAlertSent = PR_TRUE;
|
||||
}
|
||||
ssl_ReleaseXmitBufLock(ss);
|
||||
ssl_ReleaseSSL3HandshakeLock(ss);
|
||||
if (needHsLock) {
|
||||
ssl_ReleaseSSL3HandshakeLock(ss);
|
||||
}
|
||||
return rv; /* error set by ssl3_FlushHandshake or ssl3_SendRecord */
|
||||
}
|
||||
|
||||
@ -6646,12 +6655,19 @@ ssl3_HandleServerHello(sslSocket *ss, SSL3Opaque *b, PRUint32 length)
|
||||
|
||||
/* The server didn't pick 1.3 although we either received a
|
||||
* HelloRetryRequest, or we prepared to send early app data. */
|
||||
if (ss->version < SSL_LIBRARY_VERSION_TLS_1_3 &&
|
||||
(ss->ssl3.hs.helloRetry || ss->ssl3.hs.zeroRttState == ssl_0rtt_sent)) {
|
||||
/* SSL3_SendAlert() will uncache the SID. */
|
||||
desc = illegal_parameter;
|
||||
errCode = SSL_ERROR_RX_MALFORMED_SERVER_HELLO;
|
||||
goto alert_loser;
|
||||
if (ss->version < SSL_LIBRARY_VERSION_TLS_1_3) {
|
||||
if (ss->ssl3.hs.helloRetry) {
|
||||
/* SSL3_SendAlert() will uncache the SID. */
|
||||
desc = illegal_parameter;
|
||||
errCode = SSL_ERROR_RX_MALFORMED_SERVER_HELLO;
|
||||
goto alert_loser;
|
||||
}
|
||||
if (ss->ssl3.hs.zeroRttState == ssl_0rtt_sent) {
|
||||
/* SSL3_SendAlert() will uncache the SID. */
|
||||
desc = illegal_parameter;
|
||||
errCode = SSL_ERROR_DOWNGRADE_WITH_EARLY_DATA;
|
||||
goto alert_loser;
|
||||
}
|
||||
}
|
||||
|
||||
/* Check that the server negotiated the same version as it did
|
||||
@ -8215,6 +8231,20 @@ ssl3_SelectServerCert(sslSocket *ss)
|
||||
const ssl3KEADef *kea_def = ss->ssl3.hs.kea_def;
|
||||
PRCList *cursor;
|
||||
|
||||
/* If the client didn't include the supported groups extension, assume just
|
||||
* P-256 support and disable all the other ECDHE groups. This also affects
|
||||
* ECDHE group selection, but this function is called first. */
|
||||
if (!ssl3_ExtensionNegotiated(ss, ssl_supported_groups_xtn)) {
|
||||
unsigned int i;
|
||||
for (i = 0; i < SSL_NAMED_GROUP_COUNT; ++i) {
|
||||
if (ss->namedGroupPreferences[i] &&
|
||||
ss->namedGroupPreferences[i]->keaType == ssl_kea_ecdh &&
|
||||
ss->namedGroupPreferences[i]->name != ssl_grp_ec_secp256r1) {
|
||||
ss->namedGroupPreferences[i] = NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* This picks the first certificate that has:
|
||||
* a) the right authentication method, and
|
||||
* b) the right named curve (EC only)
|
||||
|
@ -32,6 +32,7 @@ ssl3_InitGather(sslGather *gs)
|
||||
gs->readOffset = 0;
|
||||
gs->dtlsPacketOffset = 0;
|
||||
gs->dtlsPacket.len = 0;
|
||||
gs->rejectV2Records = PR_FALSE;
|
||||
status = sslBuffer_Grow(&gs->buf, 4096);
|
||||
return status;
|
||||
}
|
||||
@ -147,8 +148,11 @@ ssl3_GatherData(sslSocket *ss, sslGather *gs, int flags, ssl2Gather *ssl2gs)
|
||||
switch (gs->state) {
|
||||
case GS_HEADER:
|
||||
/* Check for SSLv2 handshakes. Always assume SSLv3 on clients,
|
||||
* support SSLv2 handshakes only when ssl2gs != NULL. */
|
||||
if (!ssl2gs || ssl3_isLikelyV3Hello(gs->hdr)) {
|
||||
* support SSLv2 handshakes only when ssl2gs != NULL.
|
||||
* Always assume v3 after we received the first record. */
|
||||
if (!ssl2gs ||
|
||||
ss->gs.rejectV2Records ||
|
||||
ssl3_isLikelyV3Hello(gs->hdr)) {
|
||||
/* Should have a non-SSLv2 record header in gs->hdr. Extract
|
||||
* the length of the following encrypted data, and then
|
||||
* read in the rest of the record into gs->inbuf. */
|
||||
@ -183,7 +187,7 @@ ssl3_GatherData(sslSocket *ss, sslGather *gs, int flags, ssl2Gather *ssl2gs)
|
||||
/* This is the max length for an encrypted SSLv3+ fragment. */
|
||||
if (!v2HdrLength &&
|
||||
gs->remainder > (MAX_FRAGMENT_LENGTH + 2048)) {
|
||||
SSL3_SendAlert(ss, alert_fatal, unexpected_message);
|
||||
SSL3_SendAlert(ss, alert_fatal, record_overflow);
|
||||
gs->state = GS_INIT;
|
||||
PORT_SetError(SSL_ERROR_RX_RECORD_TOO_LONG);
|
||||
return SECFailure;
|
||||
@ -205,13 +209,28 @@ ssl3_GatherData(sslSocket *ss, sslGather *gs, int flags, ssl2Gather *ssl2gs)
|
||||
* many into the gs->hdr[] buffer. Copy them over into inbuf so
|
||||
* that we can properly process the hello record later. */
|
||||
if (v2HdrLength) {
|
||||
/* Reject v2 records that don't even carry enough data to
|
||||
* resemble a valid ClientHello header. */
|
||||
if (gs->remainder < SSL_HL_CLIENT_HELLO_HBYTES) {
|
||||
SSL3_SendAlert(ss, alert_fatal, illegal_parameter);
|
||||
PORT_SetError(SSL_ERROR_RX_MALFORMED_CLIENT_HELLO);
|
||||
return SECFailure;
|
||||
}
|
||||
|
||||
PORT_Assert(lbp);
|
||||
gs->inbuf.len = 5 - v2HdrLength;
|
||||
PORT_Memcpy(lbp, gs->hdr + v2HdrLength, gs->inbuf.len);
|
||||
gs->remainder -= gs->inbuf.len;
|
||||
lbp += gs->inbuf.len;
|
||||
}
|
||||
|
||||
break; /* End this case. Continue around the loop. */
|
||||
if (gs->remainder > 0) {
|
||||
break; /* End this case. Continue around the loop. */
|
||||
}
|
||||
|
||||
/* FALL THROUGH if (gs->remainder == 0) as we just received
|
||||
* an empty record and there's really no point in calling
|
||||
* ssl_DefRecv() with buf=NULL and len=0. */
|
||||
|
||||
case GS_DATA:
|
||||
/*
|
||||
@ -219,6 +238,10 @@ ssl3_GatherData(sslSocket *ss, sslGather *gs, int flags, ssl2Gather *ssl2gs)
|
||||
*/
|
||||
SSL_TRC(10, ("%d: SSL[%d]: got record of %d bytes",
|
||||
SSL_GETPID(), ss->fd, gs->inbuf.len));
|
||||
|
||||
/* reject any v2 records from now on */
|
||||
ss->gs.rejectV2Records = PR_TRUE;
|
||||
|
||||
gs->state = GS_INIT;
|
||||
return 1;
|
||||
}
|
||||
|
@ -66,6 +66,8 @@ ssl_DefRecv(sslSocket *ss, unsigned char *buf, int len, int flags)
|
||||
PRFileDesc *lower = ss->fd->lower;
|
||||
int rv;
|
||||
|
||||
PORT_Assert(buf && len > 0);
|
||||
|
||||
rv = lower->methods->recv(lower, (void *)buf, len, flags, ss->rTimeout);
|
||||
if (rv < 0) {
|
||||
DEFINE_ERROR
|
||||
|
@ -244,6 +244,7 @@ typedef enum {
|
||||
SSL_ERROR_MISSING_SIGNATURE_ALGORITHMS_EXTENSION = (SSL_ERROR_BASE + 157),
|
||||
SSL_ERROR_MALFORMED_PSK_KEY_EXCHANGE_MODES = (SSL_ERROR_BASE + 158),
|
||||
SSL_ERROR_MISSING_PSK_KEY_EXCHANGE_MODES = (SSL_ERROR_BASE + 159),
|
||||
SSL_ERROR_DOWNGRADE_WITH_EARLY_DATA = (SSL_ERROR_BASE + 160),
|
||||
SSL_ERROR_END_OF_LIST /* let the c compiler determine the value of this. */
|
||||
} SSLErrorCodes;
|
||||
#endif /* NO_SECURITY_ERROR_ENUM */
|
||||
|
@ -370,6 +370,10 @@ struct sslGatherStr {
|
||||
|
||||
/* the start of the buffered DTLS record in dtlsPacket */
|
||||
unsigned int dtlsPacketOffset;
|
||||
|
||||
/* tracks whether we've seen a v3-type record before and must reject
|
||||
* any further v2-type records. */
|
||||
PRBool rejectV2Records;
|
||||
};
|
||||
|
||||
/* sslGather.state */
|
||||
|
@ -132,7 +132,7 @@ const SSL3ProtocolVersion kDtlsRecordVersion = SSL_LIBRARY_VERSION_TLS_1_1;
|
||||
PR_STATIC_ASSERT(SSL_LIBRARY_VERSION_MAX_SUPPORTED <=
|
||||
SSL_LIBRARY_VERSION_TLS_1_3);
|
||||
|
||||
/* Use this instead of FATAL_ERROR when an alert isn't possible. */
|
||||
/* Use this instead of FATAL_ERROR when no alert shall be sent. */
|
||||
#define LOG_ERROR(ss, prError) \
|
||||
do { \
|
||||
SSL_TRC(3, ("%d: TLS13[%d]: fatal error %d in %s (%s:%d)", \
|
||||
|
@ -256,11 +256,10 @@ tls13_ClientHandleKeyShareXtn(const sslSocket *ss, TLSExtensionData *xtnData, PR
|
||||
PORT_Assert(PR_CLIST_IS_EMPTY(&xtnData->remoteKeyShares));
|
||||
|
||||
PORT_Assert(!ss->sec.isServer);
|
||||
|
||||
/* The server must not send this extension when negotiating < TLS 1.3. */
|
||||
if (ss->version < SSL_LIBRARY_VERSION_TLS_1_3) {
|
||||
/* This can't happen because the extension processing
|
||||
* code filters out TLS 1.3 extensions when not in
|
||||
* TLS 1.3 mode. */
|
||||
PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
|
||||
PORT_SetError(SSL_ERROR_EXTENSION_DISALLOWED_FOR_VERSION);
|
||||
return SECFailure;
|
||||
}
|
||||
|
||||
@ -691,9 +690,10 @@ tls13_ClientHandlePreSharedKeyXtn(const sslSocket *ss, TLSExtensionData *xtnData
|
||||
SSL_TRC(3, ("%d: SSL3[%d]: handle pre_shared_key extension",
|
||||
SSL_GETPID(), ss->fd));
|
||||
|
||||
/* If we are doing < TLS 1.3, then ignore this. */
|
||||
/* The server must not send this extension when negotiating < TLS 1.3. */
|
||||
if (ss->version < SSL_LIBRARY_VERSION_TLS_1_3) {
|
||||
return SECSuccess;
|
||||
PORT_SetError(SSL_ERROR_EXTENSION_DISALLOWED_FOR_VERSION);
|
||||
return SECFailure;
|
||||
}
|
||||
|
||||
rv = ssl3_ExtConsumeHandshakeNumber(ss, &index, 2, &data->data, &data->len);
|
||||
@ -816,7 +816,7 @@ tls13_ClientHandleEarlyDataXtn(const sslSocket *ss, TLSExtensionData *xtnData, P
|
||||
SSL_TRC(3, ("%d: TLS13[%d]: handle early_data extension",
|
||||
SSL_GETPID(), ss->fd));
|
||||
|
||||
/* If we are doing < TLS 1.3, then ignore this. */
|
||||
/* The server must not send this extension when negotiating < TLS 1.3. */
|
||||
if (ss->version < SSL_LIBRARY_VERSION_TLS_1_3) {
|
||||
PORT_SetError(SSL_ERROR_EXTENSION_DISALLOWED_FOR_VERSION);
|
||||
return SECFailure;
|
||||
@ -843,7 +843,7 @@ tls13_ClientHandleTicketEarlyDataInfoXtn(const sslSocket *ss, TLSExtensionData *
|
||||
SSL_TRC(3, ("%d: TLS13[%d]: handle early_data_info extension",
|
||||
SSL_GETPID(), ss->fd));
|
||||
|
||||
/* If we are doing < TLS 1.3, then ignore this. */
|
||||
/* The server must not send this extension when negotiating < TLS 1.3. */
|
||||
if (ss->version < SSL_LIBRARY_VERSION_TLS_1_3) {
|
||||
PORT_SetError(SSL_ERROR_EXTENSION_DISALLOWED_FOR_VERSION);
|
||||
return SECFailure;
|
||||
@ -1093,6 +1093,13 @@ tls13_SendShortHeaderXtn(const sslSocket *ss,
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Don't send this if TLS 1.3 isn't at least possible. */
|
||||
if (ss->vrange.max < SSL_LIBRARY_VERSION_TLS_1_3) {
|
||||
/* This should only happen on the client. */
|
||||
PORT_Assert(!ss->sec.isServer);
|
||||
return 0;
|
||||
}
|
||||
|
||||
SSL_TRC(3, ("%d: TLS13[%d]: send short_header extension",
|
||||
SSL_GETPID(), ss->fd));
|
||||
|
||||
@ -1124,10 +1131,10 @@ tls13_HandleShortHeaderXtn(
|
||||
const sslSocket *ss, TLSExtensionData *xtnData, PRUint16 ex_type,
|
||||
SECItem *data)
|
||||
{
|
||||
SSL_TRC(3, ("%d: TLS13[%d]: handle early_data extension",
|
||||
SSL_TRC(3, ("%d: TLS13[%d]: handle short_header extension",
|
||||
SSL_GETPID(), ss->fd));
|
||||
|
||||
/* If we are doing < TLS 1.3, then ignore this. */
|
||||
/* The client might have asked for this, but we didn't negotiate TLS 1.3. */
|
||||
if (ss->version < SSL_LIBRARY_VERSION_TLS_1_3) {
|
||||
return SECSuccess;
|
||||
}
|
||||
|
@ -290,3 +290,9 @@ PORT_DestroyCheapArena;
|
||||
;+ local:
|
||||
;+ *;
|
||||
;+};
|
||||
;+NSSUTIL_3.25 { # NSS Utilities 3.25 release
|
||||
;+ global:
|
||||
SEC_ASN1DecoderSetMaximumElementSize;
|
||||
;+ local:
|
||||
;+ *;
|
||||
;+};
|
||||
|
@ -54,6 +54,18 @@ extern void SEC_ASN1DecoderSetNotifyProc(SEC_ASN1DecoderContext *cx,
|
||||
|
||||
extern void SEC_ASN1DecoderClearNotifyProc(SEC_ASN1DecoderContext *cx);
|
||||
|
||||
/* Sets the maximum size that should be allocated for a single ASN.1
|
||||
* element. Set to 0 to indicate there is no limit.
|
||||
*
|
||||
* Note: This does not set the maximum size overall that may be allocated
|
||||
* while parsing, nor does it guarantee that the decoder won't allocate
|
||||
* more than |max_size| while parsing an individual element; rather, it
|
||||
* merely guarantees that any individual allocation for returned data
|
||||
* should not exceed |max_size|.
|
||||
*/
|
||||
extern void SEC_ASN1DecoderSetMaximumElementSize(SEC_ASN1DecoderContext *cx,
|
||||
unsigned long max_size);
|
||||
|
||||
extern SECStatus SEC_ASN1Decode(PLArenaPool *pool, void *dest,
|
||||
const SEC_ASN1Template *t,
|
||||
const char *buf, long len);
|
||||
|
@ -292,6 +292,17 @@ struct sec_DecoderContext_struct {
|
||||
sec_asn1d_state *current;
|
||||
sec_asn1d_parse_status status;
|
||||
|
||||
/* The maximum size the caller is willing to allow a single element
|
||||
* to be before returning an error.
|
||||
*
|
||||
* In the case of an indefinite length element, this is the sum total
|
||||
* of all child elements.
|
||||
*
|
||||
* In the case of a definite length element, this represents the maximum
|
||||
* size of the top-level element.
|
||||
*/
|
||||
unsigned long max_element_size;
|
||||
|
||||
SEC_ASN1NotifyProc notify_proc; /* call before/after handling field */
|
||||
void *notify_arg; /* argument to notify_proc */
|
||||
PRBool during_notify; /* true during call to notify_proc */
|
||||
@ -1288,6 +1299,13 @@ sec_asn1d_prepare_for_contents(sec_asn1d_state *state)
|
||||
alloc_len += subitem->len;
|
||||
}
|
||||
|
||||
if (state->top->max_element_size > 0 &&
|
||||
alloc_len > state->top->max_element_size) {
|
||||
PORT_SetError(SEC_ERROR_OUTPUT_LEN);
|
||||
state->top->status = decodeError;
|
||||
return;
|
||||
}
|
||||
|
||||
item->data = (unsigned char *)sec_asn1d_zalloc(poolp, alloc_len);
|
||||
if (item->data == NULL) {
|
||||
state->top->status = decodeError;
|
||||
@ -1396,6 +1414,13 @@ sec_asn1d_prepare_for_contents(sec_asn1d_state *state)
|
||||
if (state->dest != NULL) {
|
||||
item = (SECItem *)(state->dest);
|
||||
item->len = 0;
|
||||
if (state->top->max_element_size > 0 &&
|
||||
state->contents_length > state->top->max_element_size) {
|
||||
PORT_SetError(SEC_ERROR_OUTPUT_LEN);
|
||||
state->top->status = decodeError;
|
||||
return;
|
||||
}
|
||||
|
||||
if (state->top->filter_only) {
|
||||
item->data = NULL;
|
||||
} else {
|
||||
@ -2223,6 +2248,13 @@ sec_asn1d_concat_substrings(sec_asn1d_state *state)
|
||||
alloc_len = item_len;
|
||||
}
|
||||
|
||||
if (state->top->max_element_size > 0 &&
|
||||
alloc_len > state->top->max_element_size) {
|
||||
PORT_SetError(SEC_ERROR_OUTPUT_LEN);
|
||||
state->top->status = decodeError;
|
||||
return;
|
||||
}
|
||||
|
||||
item = (SECItem *)(state->dest);
|
||||
PORT_Assert(item != NULL);
|
||||
PORT_Assert(item->data == NULL);
|
||||
@ -2726,7 +2758,7 @@ SEC_ASN1DecoderUpdate(SEC_ASN1DecoderContext *cx,
|
||||
#ifdef DEBUG_ASN1D_STATES
|
||||
printf("\nPLACE = %s, next byte = 0x%02x, %08x[%d]\n",
|
||||
(state->place >= 0 && state->place <= notInUse) ? place_names[state->place] : "(undefined)",
|
||||
(unsigned int)((unsigned char *)buf)[consumed],
|
||||
len ? (unsigned int)((unsigned char *)buf)[consumed] : 0,
|
||||
buf, consumed);
|
||||
dump_states(cx);
|
||||
#endif /* DEBUG_ASN1D_STATES */
|
||||
@ -3041,6 +3073,13 @@ SEC_ASN1DecoderClearNotifyProc(SEC_ASN1DecoderContext *cx)
|
||||
cx->notify_arg = NULL; /* not necessary; just being clean */
|
||||
}
|
||||
|
||||
void
|
||||
SEC_ASN1DecoderSetMaximumElementSize(SEC_ASN1DecoderContext *cx,
|
||||
unsigned long max_size)
|
||||
{
|
||||
cx->max_element_size = max_size;
|
||||
}
|
||||
|
||||
void
|
||||
SEC_ASN1DecoderAbort(SEC_ASN1DecoderContext *cx, int error)
|
||||
{
|
||||
@ -3061,6 +3100,10 @@ SEC_ASN1Decode(PLArenaPool *poolp, void *dest,
|
||||
if (dcx == NULL)
|
||||
return SECFailure;
|
||||
|
||||
/* In one-shot mode, there's no possibility of streaming data beyond the
|
||||
* length of len */
|
||||
SEC_ASN1DecoderSetMaximumElementSize(dcx, len);
|
||||
|
||||
urv = SEC_ASN1DecoderUpdate(dcx, buf, len);
|
||||
frv = SEC_ASN1DecoderFinish(dcx);
|
||||
|
||||
|
4
security/nss/nss-tool/.clang-format
Normal file
4
security/nss/nss-tool/.clang-format
Normal file
@ -0,0 +1,4 @@
|
||||
---
|
||||
Language: Cpp
|
||||
BasedOnStyle: Google
|
||||
...
|
23
security/nss/nss-tool/common/argparse.cc
Normal file
23
security/nss/nss-tool/common/argparse.cc
Normal file
@ -0,0 +1,23 @@
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* 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/. */
|
||||
|
||||
#include "argparse.h"
|
||||
|
||||
ArgParser::ArgParser(const std::vector<std::string>& arguments) {
|
||||
for (size_t i = 0; i < arguments.size(); i++) {
|
||||
std::string arg = arguments.at(i);
|
||||
if (arg.find("--") == 0) {
|
||||
// look for an option argument
|
||||
if (i + 1 < arguments.size() && arguments.at(i + 1).find("--") != 0) {
|
||||
programArgs_[arg] = arguments.at(i + 1);
|
||||
i++;
|
||||
} else {
|
||||
programArgs_[arg] = "";
|
||||
}
|
||||
} else {
|
||||
// positional argument (e.g. required argument)
|
||||
positionalArgs_.push_back(arg);
|
||||
}
|
||||
}
|
||||
}
|
30
security/nss/nss-tool/common/argparse.h
Normal file
30
security/nss/nss-tool/common/argparse.h
Normal file
@ -0,0 +1,30 @@
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* 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/. */
|
||||
|
||||
#ifndef argparse_h__
|
||||
#define argparse_h__
|
||||
|
||||
#include <string>
|
||||
#include <unordered_map>
|
||||
#include <vector>
|
||||
|
||||
class ArgParser {
|
||||
public:
|
||||
ArgParser(const std::vector<std::string>& arguments);
|
||||
|
||||
bool Has(std::string arg) { return programArgs_.count(arg) > 0; }
|
||||
|
||||
std::string Get(std::string arg) { return programArgs_[arg]; }
|
||||
|
||||
size_t GetPositionalArgumentCount() { return positionalArgs_.size(); }
|
||||
std::string GetPositionalArgument(size_t pos) {
|
||||
return positionalArgs_.at(pos);
|
||||
}
|
||||
|
||||
private:
|
||||
std::unordered_map<std::string, std::string> programArgs_;
|
||||
std::vector<std::string> positionalArgs_;
|
||||
};
|
||||
|
||||
#endif // argparse_h__
|
57
security/nss/nss-tool/common/scoped_ptrs.h
Normal file
57
security/nss/nss-tool/common/scoped_ptrs.h
Normal file
@ -0,0 +1,57 @@
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* 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/. */
|
||||
|
||||
#ifndef scoped_ptrs_h__
|
||||
#define scoped_ptrs_h__
|
||||
|
||||
#include <memory>
|
||||
#include "cert.h"
|
||||
#include "keyhi.h"
|
||||
#include "pk11pub.h"
|
||||
|
||||
struct ScopedDelete {
|
||||
void operator()(CERTCertificate* cert) { CERT_DestroyCertificate(cert); }
|
||||
void operator()(CERTCertificateList* list) {
|
||||
CERT_DestroyCertificateList(list);
|
||||
}
|
||||
void operator()(CERTSubjectPublicKeyInfo* spki) {
|
||||
SECKEY_DestroySubjectPublicKeyInfo(spki);
|
||||
}
|
||||
void operator()(PK11SlotInfo* slot) { PK11_FreeSlot(slot); }
|
||||
void operator()(PK11SymKey* key) { PK11_FreeSymKey(key); }
|
||||
void operator()(SECAlgorithmID* id) { SECOID_DestroyAlgorithmID(id, true); }
|
||||
void operator()(SECItem* item) { SECITEM_FreeItem(item, true); }
|
||||
void operator()(SECKEYPublicKey* key) { SECKEY_DestroyPublicKey(key); }
|
||||
void operator()(SECKEYPrivateKey* key) { SECKEY_DestroyPrivateKey(key); }
|
||||
|
||||
void operator()(CERTCertList* list) { CERT_DestroyCertList(list); }
|
||||
};
|
||||
|
||||
template <class T>
|
||||
struct ScopedMaybeDelete {
|
||||
void operator()(T* ptr) {
|
||||
if (ptr) {
|
||||
ScopedDelete del;
|
||||
del(ptr);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
#define SCOPED(x) typedef std::unique_ptr<x, ScopedMaybeDelete<x> > Scoped##x
|
||||
|
||||
SCOPED(CERTCertificate);
|
||||
SCOPED(CERTCertificateList);
|
||||
SCOPED(CERTSubjectPublicKeyInfo);
|
||||
SCOPED(PK11SlotInfo);
|
||||
SCOPED(PK11SymKey);
|
||||
SCOPED(SECAlgorithmID);
|
||||
SCOPED(SECItem);
|
||||
SCOPED(SECKEYPublicKey);
|
||||
SCOPED(SECKEYPrivateKey);
|
||||
|
||||
SCOPED(CERTCertList);
|
||||
|
||||
#undef SCOPED
|
||||
|
||||
#endif
|
138
security/nss/nss-tool/db/dbtool.cc
Normal file
138
security/nss/nss-tool/db/dbtool.cc
Normal file
@ -0,0 +1,138 @@
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* 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/. */
|
||||
|
||||
#include "dbtool.h"
|
||||
#include "argparse.h"
|
||||
#include "scoped_ptrs.h"
|
||||
|
||||
#include <iomanip>
|
||||
#include <iostream>
|
||||
#include <memory>
|
||||
#include <sstream>
|
||||
|
||||
#include <cert.h>
|
||||
#include <certdb.h>
|
||||
#include <nss.h>
|
||||
#include <prio.h>
|
||||
|
||||
static std::string PrintFlags(unsigned int flags) {
|
||||
std::stringstream ss;
|
||||
if ((flags & CERTDB_VALID_CA) && !(flags & CERTDB_TRUSTED_CA) &&
|
||||
!(flags & CERTDB_TRUSTED_CLIENT_CA)) {
|
||||
ss << "c";
|
||||
}
|
||||
if ((flags & CERTDB_TERMINAL_RECORD) && !(flags & CERTDB_TRUSTED)) {
|
||||
ss << "p";
|
||||
}
|
||||
if (flags & CERTDB_TRUSTED_CA) {
|
||||
ss << "C";
|
||||
}
|
||||
if (flags & CERTDB_TRUSTED_CLIENT_CA) {
|
||||
ss << "T";
|
||||
}
|
||||
if (flags & CERTDB_TRUSTED) {
|
||||
ss << "P";
|
||||
}
|
||||
if (flags & CERTDB_USER) {
|
||||
ss << "u";
|
||||
}
|
||||
if (flags & CERTDB_SEND_WARN) {
|
||||
ss << "w";
|
||||
}
|
||||
if (flags & CERTDB_INVISIBLE_CA) {
|
||||
ss << "I";
|
||||
}
|
||||
if (flags & CERTDB_GOVT_APPROVED_CA) {
|
||||
ss << "G";
|
||||
}
|
||||
return ss.str();
|
||||
}
|
||||
|
||||
void DBTool::Usage() {
|
||||
std::cerr << "Usage: nss db [--path <directory>] --list-certs" << std::endl;
|
||||
}
|
||||
|
||||
bool DBTool::Run(const std::vector<std::string> &arguments) {
|
||||
ArgParser parser(arguments);
|
||||
|
||||
std::string initDir(".");
|
||||
if (parser.Has("--path")) {
|
||||
initDir = parser.Get("--path");
|
||||
if (PR_Access(initDir.c_str(), PR_ACCESS_READ_OK) != PR_SUCCESS) {
|
||||
std::cerr << "Directory '" << initDir
|
||||
<< "' does not exists or you don't have permissions!"
|
||||
<< std::endl;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (!parser.Has("--list-certs")) {
|
||||
return false;
|
||||
}
|
||||
std::cout << "Using database directory: " << initDir << std::endl
|
||||
<< std::endl;
|
||||
|
||||
// init NSS
|
||||
const char *certPrefix = ""; // certutil -P option --- can leave this empty
|
||||
SECStatus rv =
|
||||
NSS_Initialize(initDir.c_str(), certPrefix, certPrefix, "secmod.db", 0);
|
||||
if (rv != SECSuccess) {
|
||||
std::cerr << "NSS init failed!" << std::endl;
|
||||
return false;
|
||||
}
|
||||
|
||||
ListCertificates();
|
||||
|
||||
// shutdown nss
|
||||
if (NSS_Shutdown() != SECSuccess) {
|
||||
std::cerr << "NSS Shutdown failed!" << std::endl;
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void DBTool::ListCertificates() {
|
||||
ScopedCERTCertList list(PK11_ListCerts(PK11CertListAll, nullptr));
|
||||
CERTCertListNode *node;
|
||||
|
||||
std::cout << std::setw(60) << std::left << "Certificate Nickname"
|
||||
<< " "
|
||||
<< "Trust Attributes" << std::endl;
|
||||
std::cout << std::setw(60) << std::left << ""
|
||||
<< " "
|
||||
<< "SSL,S/MIME,JAR/XPI" << std::endl
|
||||
<< std::endl;
|
||||
|
||||
for (node = CERT_LIST_HEAD(list); !CERT_LIST_END(node, list);
|
||||
node = CERT_LIST_NEXT(node)) {
|
||||
CERTCertificate *cert = node->cert;
|
||||
|
||||
std::string name("(unknown)");
|
||||
char *appData = static_cast<char *>(node->appData);
|
||||
if (appData && strlen(appData) > 0) {
|
||||
name = appData;
|
||||
} else if (cert->nickname && strlen(cert->nickname) > 0) {
|
||||
name = cert->nickname;
|
||||
} else if (cert->emailAddr && strlen(cert->emailAddr) > 0) {
|
||||
name = cert->emailAddr;
|
||||
}
|
||||
|
||||
CERTCertTrust trust;
|
||||
std::string trusts;
|
||||
if (CERT_GetCertTrust(cert, &trust) == SECSuccess) {
|
||||
std::stringstream ss;
|
||||
ss << PrintFlags(trust.sslFlags);
|
||||
ss << ",";
|
||||
ss << PrintFlags(trust.emailFlags);
|
||||
ss << ",";
|
||||
ss << PrintFlags(trust.objectSigningFlags);
|
||||
trusts = ss.str();
|
||||
} else {
|
||||
trusts = ",,";
|
||||
}
|
||||
std::cout << std::setw(60) << std::left << name << " " << trusts
|
||||
<< std::endl;
|
||||
}
|
||||
}
|
21
security/nss/nss-tool/db/dbtool.h
Normal file
21
security/nss/nss-tool/db/dbtool.h
Normal file
@ -0,0 +1,21 @@
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* 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/. */
|
||||
|
||||
#ifndef dbtool_h__
|
||||
#define dbtool_h__
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
class DBTool {
|
||||
public:
|
||||
bool Run(const std::vector<std::string>& arguments);
|
||||
|
||||
void Usage();
|
||||
|
||||
private:
|
||||
void ListCertificates();
|
||||
};
|
||||
|
||||
#endif // dbtool_h__
|
43
security/nss/nss-tool/nss_tool.cc
Normal file
43
security/nss/nss-tool/nss_tool.cc
Normal file
@ -0,0 +1,43 @@
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* 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/. */
|
||||
|
||||
#include <iostream>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include <prinit.h>
|
||||
|
||||
#include "argparse.h"
|
||||
#include "db/dbtool.h"
|
||||
|
||||
static void Usage() {
|
||||
std::cerr << "Usage: nss <command> <subcommand> [options]" << std::endl;
|
||||
std::cerr << " nss db [--path <directory>] --list-certs" << std::endl;
|
||||
}
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
if (argc < 2) {
|
||||
Usage();
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (std::string(argv[1]) != "db") {
|
||||
Usage();
|
||||
return 1;
|
||||
}
|
||||
|
||||
int exit_code = 0;
|
||||
PR_Init(PR_SYSTEM_THREAD, PR_PRIORITY_NORMAL, 1);
|
||||
|
||||
std::vector<std::string> arguments(argv + 2, argv + argc);
|
||||
DBTool tool;
|
||||
if (!tool.Run(arguments)) {
|
||||
tool.Usage();
|
||||
exit_code = 1;
|
||||
}
|
||||
|
||||
PR_Cleanup();
|
||||
|
||||
return exit_code;
|
||||
}
|
27
security/nss/nss-tool/nss_tool.gyp
Normal file
27
security/nss/nss-tool/nss_tool.gyp
Normal file
@ -0,0 +1,27 @@
|
||||
# This Source Code Form is subject to the terms of the Mozilla Public
|
||||
# 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/.
|
||||
{
|
||||
'includes' : [
|
||||
'../coreconf/config.gypi',
|
||||
'../cmd/platlibs.gypi',
|
||||
],
|
||||
'targets' : [
|
||||
{
|
||||
'target_name' : 'nss',
|
||||
'type' : 'executable',
|
||||
'sources' : [
|
||||
'nss_tool.cc',
|
||||
'common/argparse.cc',
|
||||
'db/dbtool.cc',
|
||||
],
|
||||
'include_dirs': [
|
||||
'common',
|
||||
],
|
||||
'dependencies' : [
|
||||
'<(DEPTH)/exports.gyp:dbm_exports',
|
||||
'<(DEPTH)/exports.gyp:nss_exports'
|
||||
],
|
||||
}
|
||||
],
|
||||
}
|
@ -120,6 +120,7 @@
|
||||
'cmd/smimetools/smimetools.gyp:cmsutil',
|
||||
'cmd/ssltap/ssltap.gyp:ssltap',
|
||||
'cmd/symkeyutil/symkeyutil.gyp:symkeyutil',
|
||||
'nss-tool/nss_tool.gyp:nss',
|
||||
],
|
||||
}],
|
||||
],
|
||||
@ -177,7 +178,6 @@
|
||||
'cmd/vfychain/vfychain.gyp:vfychain',
|
||||
'cmd/vfyserv/vfyserv.gyp:vfyserv',
|
||||
'gtests/google_test/google_test.gyp:gtest1',
|
||||
'gtests/common/common.gyp:gtests',
|
||||
'gtests/der_gtest/der_gtest.gyp:der_gtest',
|
||||
'gtests/pk11_gtest/pk11_gtest.gyp:pk11_gtest',
|
||||
'gtests/ssl_gtest/ssl_gtest.gyp:ssl_gtest',
|
||||
@ -241,7 +241,7 @@
|
||||
},
|
||||
],
|
||||
}],
|
||||
[ 'fuzz==1', {
|
||||
[ 'fuzz_tls==1', {
|
||||
'targets': [
|
||||
{
|
||||
'target_name': 'fuzz_warning',
|
||||
@ -256,12 +256,16 @@
|
||||
}
|
||||
],
|
||||
},
|
||||
],
|
||||
}],
|
||||
[ 'fuzz==1', {
|
||||
'targets': [
|
||||
{
|
||||
'target_name': 'fuzz',
|
||||
'type': 'none',
|
||||
'dependencies': [
|
||||
'fuzz/fuzz.gyp:nssfuzz',
|
||||
]
|
||||
],
|
||||
},
|
||||
],
|
||||
}],
|
||||
|
@ -2,8 +2,8 @@
|
||||
|
||||
Network Security Services (NSS) is a set of libraries designed to support
|
||||
cross-platform development of security-enabled client and server
|
||||
applications. NSS supports SSL v3-TLS 1.2 (experimental TLS 1.3), PKCS #5, PKCS
|
||||
#7, PKCS #11, PKCS #12, S/MIME, X.509 v3 certificates, and other security
|
||||
applications. NSS supports SSL v3-TLS 1.2 (experimental TLS 1.3), PKCS #5, PKCS#7,
|
||||
PKCS #11, PKCS #12, S/MIME, X.509 v3 certificates, and other security
|
||||
standards.
|
||||
|
||||
## Getting started
|
||||
@ -34,15 +34,16 @@ After changing into the NSS directory a typical build is done as follows
|
||||
./build.sh
|
||||
|
||||
Once the build is done the build output is found in the directory
|
||||
`../dist/*.OBJ`, where `*` will be a name dynamically derived from your system's
|
||||
architecture. Exported header files can be found in the `include` directory,
|
||||
library files in directory `lib`, and tools in directory `bin`. In order to run
|
||||
the tools, set your system environment to use the libraries of your build from
|
||||
the "lib" directory, e.g., using the `LD_LIBRARY_PATH` or `DYLD_LIBRARY_PATH`.
|
||||
`../dist/Debug` for debug builds and `../dist/Release` for opt builds.
|
||||
Exported header files can be found in the `include` directory, library files in
|
||||
directory `lib`, and tools in directory `bin`. In order to run the tools, set
|
||||
your system environment to use the libraries of your build from the "lib"
|
||||
directory, e.g., using the `LD_LIBRARY_PATH` or `DYLD_LIBRARY_PATH`.
|
||||
|
||||
Usage: build.sh [-hcgv] [-j <n>] [--test] [--fuzz] [--scan-build[=output]]
|
||||
[-m32] [--opt|-o] [--asan] [--ubsan] [--sancov[=edge|bb|func]]
|
||||
[--pprof] [--msan]
|
||||
Usage: build.sh [-hcv] [-j <n>] [--nspr] [--gyp|-g] [--opt|-o] [-m32]
|
||||
[--test] [--fuzz] [--pprof] [--scan-build[=output]]
|
||||
[--asan] [--ubsan] [--msan] [--sancov[=edge|bb|func|...]]
|
||||
[--ct-verif] [--disable-tests]
|
||||
|
||||
This script builds NSS with gyp and ninja.
|
||||
|
||||
@ -51,24 +52,27 @@ the "lib" directory, e.g., using the `LD_LIBRARY_PATH` or `DYLD_LIBRARY_PATH`.
|
||||
|
||||
NSS build tool options:
|
||||
|
||||
-h display this help and exit
|
||||
-c clean before build
|
||||
-g force a rebuild of gyp (and NSPR, because why not)
|
||||
-j <n> run at most <n> concurrent jobs
|
||||
-v verbose build
|
||||
-m32 do a 32-bit build on a 64-bit system
|
||||
--test ignore map files and export everything we have
|
||||
--fuzz enable fuzzing mode. this always enables test builds
|
||||
--scan-build run the build with scan-build (scan-build has to be in the path)
|
||||
--scan-build=/out/path sets the output path for scan-build
|
||||
--opt|-o do an opt build
|
||||
--asan do an asan build
|
||||
--ubsan do an ubsan build
|
||||
--msan do an msan build
|
||||
--sancov do sanitize coverage builds
|
||||
--sancov=func sets coverage to function level for example
|
||||
--pprof build with gperftool support
|
||||
|
||||
-h display this help and exit
|
||||
-c clean before build
|
||||
-v verbose build
|
||||
-j <n> run at most <n> concurrent jobs
|
||||
--nspr force a rebuild of NSPR
|
||||
--gyp|-g force a rerun of gyp
|
||||
--opt|-o do an opt build
|
||||
-m32 do a 32-bit build on a 64-bit system
|
||||
--test ignore map files and export everything we have
|
||||
--fuzz enable fuzzing mode. this always enables test builds
|
||||
--pprof build with gperftool support
|
||||
--ct-verif build with valgrind for ct-verif
|
||||
--scan-build run the build with scan-build (scan-build has to be in the path)
|
||||
--scan-build=/out/path sets the output path for scan-build
|
||||
--asan do an asan build
|
||||
--ubsan do an ubsan build
|
||||
--ubsan=bool,shift,... sets specific UB sanitizers
|
||||
--msan do an msan build
|
||||
--sancov do sanitize coverage builds
|
||||
--sancov=func sets coverage to function level for example
|
||||
--disable-tests don't build tests and corresponding cmdline utils
|
||||
|
||||
## Building NSS (legacy build system)
|
||||
|
||||
|
@ -39,6 +39,8 @@
|
||||
# gtests.sh - Gtest based unit tests for everything else
|
||||
# bogo.sh - Bogo interop tests (disabled by default)
|
||||
# https://boringssl.googlesource.com/boringssl/+/master/ssl/test/PORTING.md
|
||||
# interop.sh - Interoperability tests (disabled by default)
|
||||
# https://github.com/ekr/tls_interop
|
||||
#
|
||||
# NSS testing is now devided to 4 cycles:
|
||||
# ---------------------------------------
|
||||
|
@ -39,9 +39,6 @@ bogo_cleanup()
|
||||
. common/cleanup.sh
|
||||
}
|
||||
|
||||
# Need to add go to the PATH.
|
||||
export PATH=$PATH:/usr/lib/go-1.6/bin
|
||||
|
||||
cd "$(dirname "$0")"
|
||||
SOURCE_DIR="$PWD"/../..
|
||||
bogo_init
|
||||
|
68
security/nss/tests/interop/interop.sh
Executable file
68
security/nss/tests/interop/interop.sh
Executable file
@ -0,0 +1,68 @@
|
||||
#!/bin/bash
|
||||
#
|
||||
# This Source Code Form is subject to the terms of the Mozilla Public
|
||||
# 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/.
|
||||
|
||||
########################################################################
|
||||
#
|
||||
# tests/interop/interop.sh
|
||||
#
|
||||
# Script to drive our cross-stack interop tests
|
||||
#
|
||||
########################################################################
|
||||
|
||||
interop_init()
|
||||
{
|
||||
SCRIPTNAME="interop.sh"
|
||||
if [ -z "${INIT_SOURCED}" -o "${INIT_SOURCED}" != "TRUE" ] ; then
|
||||
cd ../common
|
||||
. ./init.sh
|
||||
fi
|
||||
|
||||
mkdir -p "${HOSTDIR}/interop"
|
||||
cd "${HOSTDIR}/interop"
|
||||
INTEROP=${INTEROP:=tls_interop}
|
||||
if [ ! -d "$INTEROP" ]; then
|
||||
git clone -q https://github.com/mozilla/tls-interop "$INTEROP"
|
||||
fi
|
||||
|
||||
# We use the BoringSSL keyfiles
|
||||
BORING=${BORING:=boringssl}
|
||||
if [ ! -d "$BORING" ]; then
|
||||
git clone -q https://boringssl.googlesource.com/boringssl "$BORING"
|
||||
git -C "$BORING" checkout -q ea80f9d5df4c302de391e999395e1c87f9c786b3
|
||||
fi
|
||||
|
||||
SCRIPTNAME="interop.sh"
|
||||
html_head "interop test"
|
||||
}
|
||||
|
||||
interop_cleanup()
|
||||
{
|
||||
html "</TABLE><BR>"
|
||||
cd ${QADIR}
|
||||
. common/cleanup.sh
|
||||
}
|
||||
|
||||
# Function so we can easily add other stacks
|
||||
interop_run()
|
||||
{
|
||||
test_name=$1
|
||||
client=$2
|
||||
server=$3
|
||||
|
||||
(cd "$INTEROP";
|
||||
cargo run -- --client ${client} --server ${server} --rootdir ../${BORING}/ssl/test/runner/ --test-cases cases.json) 2>interop-${test_name}.errors | tee interop-${test_name}.log
|
||||
html_msg "${PIPESTATUS[0]}" 0 "Interop" "Run successfully"
|
||||
grep -i 'FAILED\|Assertion failure' interop-${test_name}.errors
|
||||
html_msg $? 1 "Interop" "No failures"
|
||||
}
|
||||
|
||||
cd "$(dirname "$0")"
|
||||
SOURCE_DIR="$PWD"/../..
|
||||
interop_init
|
||||
NSS_SHIM="${BINDIR}"/nss_bogo_shim
|
||||
BORING_SHIM="../${BORING}"/build/ssl/test/bssl_shim
|
||||
interop_run "nss_nss" ${NSS_SHIM} ${NSS_SHIM}
|
||||
interop_cleanup
|
Loading…
Reference in New Issue
Block a user