Themis Core #1318
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
name: Themis Core | |
on: | |
pull_request: | |
paths: | |
- '.github/workflows/test-core.yaml' | |
- 'benches/themis/**' | |
- 'docs/examples/c/**' | |
- 'src/soter/**' | |
- 'src/themis/**' | |
- 'tests/common/**' | |
- 'tests/soter/**' | |
- 'tests/themis/**' | |
- '!tests/themis/wrappers/android/**' | |
- 'third_party/boringssl/src/**' | |
- 'tools/afl/**' | |
- '**/*.mk' | |
- 'Makefile' | |
- '!**/README*' | |
push: | |
branches: | |
- master | |
- stable | |
- release/* | |
schedule: | |
- cron: '20 6 * * 1' # every Monday at 6:20 UTC | |
env: | |
WITH_FATAL_WARNINGS: yes | |
# RNG tests tend to fail in virtualized environment due to /dev/random | |
# not behaving properly. Disable them to avoid spurious failures. | |
NO_NIST_STS: 1 | |
jobs: | |
unit-tests: | |
name: Unit tests | |
runs-on: ${{ matrix.os }} | |
env: | |
VERBOSE: 1 | |
SOTER_KDF_RUN_LONG_TESTS: yes | |
MATRIX_OS: ${{ matrix.os }} | |
strategy: | |
matrix: | |
os: [ubuntu-20.04, ubuntu-22.04, macos-12] | |
fail-fast: false | |
steps: | |
- name: Install system dependencies | |
run: | | |
if [[ "$(uname)" = "Darwin" ]] | |
then | |
brew install cmake ninja openssl@1.1 openssl@3 | |
else | |
sudo sh -c 'echo "DEBIAN_FRONTEND=noninteractive" >> /etc/environment' | |
sudo apt update | |
sudo apt install --yes gcc make libssl-dev cmake ninja-build | |
fi | |
- name: Check out code | |
uses: actions/checkout@v2 | |
with: | |
submodules: true | |
- name: Build Themis Core (OpenSSL) | |
run: make prepare_tests_basic ENGINE=openssl BUILD_PATH=build-openssl | |
- name: Build Themis Core (OpenSSL 3.0) | |
if: ${{ matrix.os != 'ubuntu-20.04' }} | |
run: | | |
export ENGINE=openssl | |
# macOS has both OpenSSL 1.1.1 and 3.0 installed, be specific. | |
if [[ "$MATRIX_OS" = "macos-12" ]]; then | |
openssl3="$(brew --prefix openssl@3)" | |
export ENGINE_INCLUDE_PATH="$openssl3/include" | |
export ENGINE_LIB_PATH="$openssl3/lib" | |
fi | |
make prepare_tests_basic BUILD_PATH=build-openssl-3.0 | |
- name: Build Themis Core (BoringSSL) | |
if: always() | |
run: make prepare_tests_basic ENGINE=boringssl BUILD_PATH=build-boringssl | |
- name: Build Themis Core (WITH_SCELL_COMPAT) | |
run: make prepare_tests_basic WITH_SCELL_COMPAT=yes BUILD_PATH=build-compat | |
- name: Run test suite (OpenSSL) | |
run: make test ENGINE=openssl BUILD_PATH=build-openssl | |
- name: Run test suite (OpenSSL, uncompressed keys) | |
env: | |
THEMIS_GEN_EC_KEY_PAIR_UNCOMPRESSED: "1" | |
run: make test ENGINE=openssl BUILD_PATH=build-openssl | |
- name: Run test suite (OpenSSL 3.0) | |
if: ${{ matrix.os != 'ubuntu-20.04' }} | |
run: | | |
export ENGINE=openssl | |
# macOS has both OpenSSL 1.1.1 and 3.0 installed, be specific. | |
if [[ "$MATRIX_OS" = "macos-12" ]]; then | |
openssl3="$(brew --prefix openssl@3)" | |
export ENGINE_INCLUDE_PATH="$openssl3/include" | |
export ENGINE_LIB_PATH="$openssl3/lib" | |
fi | |
make test BUILD_PATH=build-openssl-3.0 | |
- name: Run test suite (OpenSSL 3.0, uncompressed keys) | |
if: ${{ matrix.os != 'ubuntu-20.04' }} | |
env: | |
THEMIS_GEN_EC_KEY_PAIR_UNCOMPRESSED: "1" | |
run: | | |
export ENGINE=openssl | |
# macOS has both OpenSSL 1.1.1 and 3.0 installed, be specific. | |
if [[ "$MATRIX_OS" = "macos-12" ]]; then | |
openssl3="$(brew --prefix openssl@3)" | |
export ENGINE_INCLUDE_PATH="$openssl3/include" | |
export ENGINE_LIB_PATH="$openssl3/lib" | |
fi | |
make test BUILD_PATH=build-openssl-3.0 | |
- name: Run test suite (BoringSSL) | |
if: always() | |
run: make test ENGINE=boringssl BUILD_PATH=build-boringssl | |
- name: Run test suite (BoringSSL, uncompressed keys) | |
if: always() | |
env: | |
THEMIS_GEN_EC_KEY_PAIR_UNCOMPRESSED: "1" | |
run: make test ENGINE=boringssl BUILD_PATH=build-boringssl | |
- name: Run test suite (WITH_SCELL_COMPAT) | |
run: make test WITH_SCELL_COMPAT=yes BUILD_PATH=build-compat | |
examples: | |
name: Code examples | |
runs-on: ubuntu-20.04 | |
steps: | |
- name: Install system dependencies | |
run: | | |
sudo sh -c 'echo "DEBIAN_FRONTEND=noninteractive" >> /etc/environment' | |
sudo apt update | |
sudo apt install --yes gcc make libssl-dev | |
- name: Check out code | |
uses: actions/checkout@v2 | |
- name: Install Themis Core | |
run: | | |
make | |
sudo make install | |
- name: Run examples | |
run: | | |
cd $GITHUB_WORKSPACE/docs/examples/c/session_buffer_test | |
echo "Secure Session: buffer interface" | |
cc -o session_buffer_test session_buffer_test.c -lthemis | |
./session_buffer_test | |
cd $GITHUB_WORKSPACE/docs/examples/c/ssession_test | |
echo "Secure Session: socket interface" | |
cc -o session_test client.c server.c session_test.c -lthemis -pthread | |
./session_test | |
sanitizers: | |
name: Unit tests (with sanitizers) | |
runs-on: ubuntu-20.04 | |
env: | |
WITH_FATAL_SANITIZERS: yes | |
steps: | |
- name: Install system dependencies | |
run: | | |
sudo sh -c 'echo "DEBIAN_FRONTEND=noninteractive" >> /etc/environment' | |
sudo apt update | |
sudo apt install --yes gcc-10 libgcc-10-dev clang-8 make libssl-dev | |
- name: Check out code | |
uses: actions/checkout@v2 | |
# We test only OpenSSL flavor to not expand the testing matrix too much | |
# (rebuilding BoringSSL is not fun and takes much time) | |
- name: Check with GCC (ASan) | |
if: always() | |
run: make clean test CC=gcc-10 WITH_ASAN=1 | |
- name: Check with GCC (TSan) | |
if: always() | |
run: make clean test CC=gcc-10 WITH_TSAN=1 | |
- name: Check with GCC (UBSan) | |
if: always() | |
run: make clean test CC=gcc-10 WITH_UBSAN=1 | |
- name: Check with Clang (ASan) | |
if: always() | |
run: make clean test CC=clang-8 WITH_ASAN=1 | |
- name: Check with Clang (TSan) | |
if: always() | |
run: make clean test CC=clang-8 WITH_TSAN=1 | |
- name: Check with Clang (UBSan) | |
if: always() | |
run: make clean test CC=clang-8 WITH_UBSAN=1 | |
benchmarks: | |
name: Benchmarks | |
runs-on: ubuntu-20.04 | |
steps: | |
- name: Install system dependencies | |
run: | | |
sudo sh -c 'echo "DEBIAN_FRONTEND=noninteractive" >> /etc/environment' | |
sudo apt update | |
sudo apt install --yes gcc make libssl-dev gnuplot zip | |
- name: Install Rust toolchain (stable) | |
uses: actions-rs/toolchain@v1 | |
with: | |
toolchain: stable | |
profile: minimal | |
- name: Check out code | |
uses: actions/checkout@v2 | |
- name: Install Themis Core | |
run: | | |
make | |
sudo make install | |
# Cargo pulls in quite a few stuff from the Internet and Rust always | |
# (slowly) recompiles dependencies, so make heavy use of caching | |
- name: Cache Cargo registry | |
uses: actions/cache@v1 | |
with: | |
path: ~/.cargo/registry | |
key: ${{ runner.os }}-cargo-registry-${{ hashFiles('**/Cargo.toml') }} | |
restore-keys: ${{ runner.os }}-cargo-registry- | |
- name: Cache Cargo index | |
uses: actions/cache@v1 | |
with: | |
path: ~/.cargo/git | |
key: ${{ runner.os }}-cargo-index-${{ hashFiles('**/Cargo.toml') }} | |
restore-keys: ${{ runner.os }}-cargo-index- | |
- name: Cache Cargo build | |
uses: actions/cache@v1 | |
with: | |
path: target | |
key: ${{ runner.os }}-cargo-build-target-${{ hashFiles('**/Cargo.toml') }} | |
restore-keys: ${{ runner.os }}-cargo-build-target- | |
# This can take a while on the first run, it's better with caches | |
- name: Build benchmarks | |
run: | | |
cd benches/themis | |
cargo bench --no-run | |
# TODO: if building a pull request, compare base with updates | |
- name: Benchmark Secure Cell (master key) | |
run: | | |
cd benches/themis | |
cargo bench -- '^Secure Cell .* master key/4 KB' | |
- name: Benchmark Secure Cell (passphrase) | |
run: | | |
cd benches/themis | |
# These are awfully slow due to KDF | |
cargo bench -- '^Secure Cell .* passphrase/4 KB' --sample-size 10 | |
- name: Benchmark Secure Message (RSA) | |
run: | | |
cd benches/themis | |
cargo bench -- '^Secure Message .* - RSA/4 KB' | |
- name: Benchmark Secure Message (ECDSA) | |
run: | | |
cd benches/themis | |
cargo bench -- '^Secure Message .* - ECDSA/4 KB' | |
- name: Upload benchmark report | |
uses: actions/upload-artifact@v1 | |
with: | |
name: Criterion report | |
path: target/criterion | |
fuzzing: | |
name: AFL fuzzing | |
runs-on: ubuntu-20.04 | |
env: | |
FUZZ_TIMEOUT: 30s | |
THEMIS_DEFAULT_PBKDF2_ITERATIONS: 10 | |
WITH_FATAL_SANITIZERS: yes | |
steps: | |
- name: Install system dependencies | |
run: | | |
sudo sh -c 'echo "DEBIAN_FRONTEND=noninteractive" >> /etc/environment' | |
# 32-bit toolchain is required to run AFL with some sanitizers | |
sudo dpkg --add-architecture i386 | |
sudo apt update | |
sudo apt install --yes gcc make zip \ | |
afl++ gcc-multilib libc6-dev:i386 \ | |
libssl-dev:amd64 libssl-dev:i386 | |
# AFL needs proper core dumps to be available, write them to files | |
sudo sh -c 'echo core > /proc/sys/kernel/core_pattern' | |
- name: Check out code | |
uses: actions/checkout@v2 | |
- name: Build fuzzing framework (Clang) | |
if: always() | |
run: make clean fuzz AFL_CC=afl-clang | |
- name: Build fuzzing framework (GCC) | |
if: always() | |
run: make clean fuzz AFL_CC=afl-gcc | |
# Don't run them for too long, we aim for low-hanging fruit here. | |
# Ideally we'd like to wait for AFL to make one cycle and stop. | |
- name: Fuzzing with Address Sanitizer | |
if: always() | |
run: | | |
make clean fuzz AFL_CC=afl-gcc WITH_ASAN=1 | |
for tool in tools/afl/input/* | |
do | |
timeout -s INT "$FUZZ_TIMEOUT" \ | |
make fuzz AFL_CC=afl-gcc WITH_ASAN=1 \ | |
AFL_FUZZ="afl-fuzz -m 1024" \ | |
FUZZ_BIN=$(basename $tool) \ | |
| cat -u || true | |
done | |
# actions/upload-artifact cannot handle ":" in paths used by AFL, | |
# archive the report manually to prevent massive stalls | |
cd build/afl | |
zip -r results-asan.zip output | |
cd - | |
echo | |
echo Analyzing results... | |
echo | |
./tools/afl/analyze_crashes.sh --no-debugger | |
- name: Upload ASan results | |
if: always() | |
uses: actions/upload-artifact@v1 | |
with: | |
name: Core fuzzer report (ASan) | |
path: build/afl/results-asan.zip | |
- name: Fuzzing with Undefined Behavior Sanitizer | |
if: always() | |
run: | | |
make clean fuzz AFL_CC=afl-clang WITH_UBSAN=1 | |
for tool in tools/afl/input/* | |
do | |
timeout -s INT "$FUZZ_TIMEOUT" \ | |
make fuzz AFL_CC=afl-clang WITH_UBSAN=1 \ | |
FUZZ_BIN=$(basename $tool) \ | |
| cat -u || true | |
done | |
# actions/upload-artifact cannot handle ":" in paths used by AFL, | |
# archive the report manually to prevent massive stalls | |
cd build/afl | |
zip -r results-ubsan.zip output | |
cd - | |
echo | |
echo Analyzing results... | |
echo | |
./tools/afl/analyze_crashes.sh --no-debugger | |
- name: Upload UBSan results | |
if: always() | |
uses: actions/upload-artifact@v1 | |
with: | |
name: Core fuzzer report (UBSan) | |
path: build/afl/results-ubsan.zip | |
# TODO: 32-bit builds WITH_UBSAN=1 | |
leak-check: | |
name: Memory leaks | |
runs-on: ubuntu-20.04 | |
steps: | |
- name: Install system dependencies | |
run: | | |
sudo sh -c 'echo "DEBIAN_FRONTEND=noninteractive" >> /etc/environment' | |
sudo apt update | |
sudo apt install --yes gcc make libssl-dev valgrind ninja-build | |
- name: Check out code | |
uses: actions/checkout@v2 | |
with: | |
submodules: true | |
- name: Build Themis Core | |
run: | | |
make prepare_tests_basic ENGINE=openssl BUILD_PATH=build_openssl | |
make prepare_tests_basic ENGINE=boringssl BUILD_PATH=build_boringssl | |
- name: Check for leaks (OpenSSL) | |
if: always() | |
run: | | |
cd build_openssl | |
valgrind tests/soter_test 2>&1 | tee -a valgrind-report.txt | |
valgrind tests/themis_test 2>&1 | tee -a valgrind-report.txt | |
awk ' | |
/ERROR SUMMARY|(definitely|indirectly|possibly) lost/ { sum += $4 } | |
END { if (sum > 0) { exit 1 } } | |
' valgrind-report.txt | |
- name: Check for leaks (BoringSSL) | |
if: always() | |
run: | | |
cd build_boringssl | |
valgrind tests/soter_test 2>&1 | tee -a valgrind-report.txt | |
valgrind tests/themis_test 2>&1 | tee -a valgrind-report.txt | |
awk ' | |
/ERROR SUMMARY|(definitely|indirectly|possibly) lost/ { sum += $4 } | |
END { if (sum > 0) { exit 1 } } | |
' valgrind-report.txt | |
coverage: | |
name: Unit test coverage | |
runs-on: ubuntu-20.04 | |
steps: | |
- name: Install system dependencies | |
run: | | |
sudo sh -c 'echo "DEBIAN_FRONTEND=noninteractive" >> /etc/environment' | |
sudo apt update | |
sudo apt install --yes gcc make libssl-dev lcov | |
- name: Check out code | |
uses: actions/checkout@v2 | |
- name: Build Themis Core | |
run: make prepare_tests_basic COVERAGE=y | |
- name: Reset lcov counters | |
run: lcov --directory . --zerocounters | |
- name: Run test suite | |
run: make test COVERAGE=y | |
- name: Prepare lcov data | |
run: | | |
lcov --output-file coverage.info --directory . --capture | |
# Do not include tests themselves as well as system headers | |
lcov --output-file coverage.info --remove coverage.info '*/tests/*' '/usr/*' | |
lcov --list coverage.info | |
- name: Submit results to Coveralls | |
uses: coverallsapp/github-action@master | |
with: | |
github-token: ${{ secrets.GITHUB_TOKEN }} | |
path-to-lcov: ./coverage.info | |
msys2: | |
name: MSYS2 environment | |
runs-on: windows-2022 | |
env: | |
SOTER_KDF_RUN_LONG_TESTS: yes | |
# TODO: remove these two options when MSYS2 build issues are solved, | |
# because now PKGBUILD.MSYS2 just downloads latest release archive | |
# from GitHub instead of using checked out files | |
WITH_EXPERIMENTAL_OPENSSL_3_SUPPORT: yes | |
WITH_FATAL_WARNINGS: "no" # YAML :trollface: | |
defaults: | |
run: | |
shell: msys2 {0} | |
steps: | |
- name: Install MSYS2 | |
uses: msys2/setup-msys2@v2 | |
with: | |
install: >- | |
base-devel tar git gcc make | |
libopenssl>=3.0.0 | |
openssl-devel>=3.0.0 | |
mingw-w64-x86_64-nsis | |
# Git, I know you're only trying to help, but MSYS can work with | |
# UNIX line endings just fine. In fact, "makepkg" *requires* them. | |
# So don't be smart: just fetch the files as they are. | |
- name: Use UNIX line endings | |
shell: bash | |
run: git config --global core.autocrlf input | |
- name: Check out code | |
uses: actions/checkout@v2 | |
# TODO: if there are users of the BoringSSL flavor on Windows, | |
# we should be testing that one as well | |
- name: Build Themis Core | |
run: make prepare_tests_basic | |
- name: Run test suite | |
run: make test | |
# TODO: it would be nice to test the installer too | |
- name: Build Themis installer | |
run: make nsis_installer | |
- name: Build Themis packages | |
run: makepkg -p PKGBUILD.MSYS2 | |
- name: Install Themis packages | |
run: pacman -U --noconfirm themis-*.pkg.* | |
- name: Try building examples | |
run: | | |
cd $GITHUB_WORKSPACE/docs/examples/c/session_buffer_test | |
echo "Secure Session: buffer interface" | |
cc -o session_buffer_test session_buffer_test.c -lthemis | |
./session_buffer_test | |
cd $GITHUB_WORKSPACE/docs/examples/c/ssession_test | |
echo "Secure Session: socket interface" | |
cc -o session_test client.c server.c session_test.c -lthemis -pthread | |
./session_test | |
macos-cross-compile: | |
name: macOS cross toolchain | |
runs-on: macos-12 | |
steps: | |
- name: Install system dependencies | |
run: | | |
brew install cmake ninja | |
- name: Check out code | |
uses: actions/checkout@v2 | |
with: | |
submodules: true | |
# We can't test OpenSSL builds since this requires OpenSSL libraries | |
# built for the target architecture (and Homebrew doesn't have any). | |
# | |
# GitHub's virtual environemnts can change the default version of Xcode | |
# and that changes the available SDKs. Check the combinations here: | |
# https://github.com/actions/virtual-environments/blob/main/images/macos/macos-10.15-Readme.md#xcode | |
- name: Build Themis Core (BoringSSL, arm64) | |
run: make SDK=macosx13.1 ARCH=arm64 ENGINE=boringssl | |
# Of course we can't run unit tests either because there is no emulator. | |
# So I will be satisifed to see the build succeed and produce binaries | |
# with expected architecture. | |
- name: Check binary architecture | |
run: | | |
set -x | |
test $(lipo -archs build/libsoter.0.dylib) = arm64 | |
test $(lipo -archs build/libthemis.0.dylib) = arm64 |