| # Copyright (c) 2022, Google Inc. | 
 | # | 
 | # Permission to use, copy, modify, and/or distribute this software for any | 
 | # purpose with or without fee is hereby granted, provided that the above | 
 | # copyright notice and this permission notice appear in all copies. | 
 | # | 
 | # THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES | 
 | # WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF | 
 | # MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY | 
 | # SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES | 
 | # WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION | 
 | # OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN | 
 | # CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | 
 |  | 
 | # This script runs test_fips repeatedly with different FIPS tests broken. It is | 
 | # intended to be observed to demonstrate that the various tests are working and | 
 | # thus pauses for a keystroke between tests. | 
 | # | 
 | # Runs in either device mode (on an attached Android device) or in a locally built | 
 | # BoringSSL checkout. | 
 | # | 
 | # On Android static binaries are not built using FIPS mode, so in device mode each | 
 | # test makes changes to libcrypto.so rather than the test binary, test_fips. | 
 |  | 
 | set -e | 
 |  | 
 | die () { | 
 |   echo "ERROR: $@" | 
 |   exit 1 | 
 | } | 
 |  | 
 | usage() { | 
 |   echo "USAGE: $0 [local|device]" | 
 |   exit 1 | 
 | } | 
 |  | 
 | inferred_mode() { | 
 |   # Try and infer local or device mode based on makefiles and artifacts. | 
 |   if [ -f Android.bp -o -f external/boringssl/Android.bp ]; then | 
 |     echo device | 
 |   elif [ -f CMakeLists.txt -a -d build/crypto -a -d build/ssl ]; then | 
 |     echo local | 
 |   else | 
 |     echo "Unable to infer mode, please specify on the command line." | 
 |     usage | 
 |   fi | 
 | } | 
 |  | 
 | # Prefer mode from command line if present. | 
 | case "$1" in | 
 |   local|device) | 
 |     MODE=$1 | 
 |     ;; | 
 |  | 
 |   "") | 
 |     MODE=`inferred_mode` | 
 |     ;; | 
 |  | 
 |   *) | 
 |     usage | 
 |     ;; | 
 | esac | 
 |  | 
 | check_directory() { | 
 |   test -d "$1" || die "Directory $1 not found." | 
 | } | 
 |  | 
 | check_file() { | 
 |   test -f "$1" || die "File $1 not found." | 
 | } | 
 |  | 
 | run_test_locally() { | 
 |   eval "$1" || true | 
 | } | 
 |  | 
 | run_test_on_device() { | 
 |   EXECFILE="$1" | 
 |   LIBRARY="$2" | 
 |   adb shell rm -rf "$DEVICE_TMP" | 
 |   adb shell mkdir -p "$DEVICE_TMP" | 
 |   adb push "$EXECFILE" "$DEVICE_TMP" > /dev/null | 
 |   EXECPATH=$(basename "$EXECFILE") | 
 |   adb push "$LIBRARY" "$DEVICE_TMP" > /dev/null | 
 |   adb shell "LD_LIBRARY_PATH=$DEVICE_TMP" "$DEVICE_TMP/$EXECPATH" || true | 
 | } | 
 |  | 
 | device_integrity_break_test() { | 
 |   go run "$BORINGSSL/util/fipstools/break-hash.go" "$LIBCRYPTO_BIN" ./libcrypto.so | 
 |   $RUN "$TEST_FIPS_BIN" ./libcrypto.so | 
 |   rm ./libcrypto.so | 
 | } | 
 |  | 
 | local_integrity_break_test() { | 
 |   go run $BORINGSSL/util/fipstools/break-hash.go "$TEST_FIPS_BIN" ./break-bin | 
 |   chmod u+x ./break-bin | 
 |   $RUN ./break-bin | 
 |   rm ./break-bin | 
 | } | 
 |  | 
 | local_runtime_break_test() { | 
 |   BORINGSSL_FIPS_BREAK_TEST=$1 "$RUN" "$TEST_FIPS_BREAK_BIN" | 
 | } | 
 |  | 
 | # TODO(prb): make break-hash and break-kat take similar arguments to save having | 
 | # separate functions for each. | 
 | device_kat_break_test() { | 
 |   KAT="$1" | 
 |   go run "$BORINGSSL/util/fipstools/break-kat.go" "$LIBCRYPTO_BREAK_BIN" "$KAT" > ./libcrypto.so | 
 |   $RUN "$TEST_FIPS_BIN" ./libcrypto.so | 
 |   rm ./libcrypto.so | 
 | } | 
 |  | 
 | local_kat_break_test() { | 
 |   KAT="$1" | 
 |   go run "$BORINGSSL/util/fipstools/break-kat.go" "$TEST_FIPS_BREAK_BIN" "$KAT" > ./break-bin | 
 |   chmod u+x ./break-bin | 
 |   $RUN ./break-bin | 
 |   rm ./break-bin | 
 | } | 
 |  | 
 | pause () { | 
 |   echo -n "Press <Enter> " | 
 |   read | 
 | } | 
 |  | 
 | if [ "$MODE" = "local" ]; then | 
 |   TEST_FIPS_BIN=${TEST_FIPS_BIN:-build/util/fipstools/test_fips} | 
 |   TEST_FIPS_BREAK_BIN=${TEST_FIPS_BREAK_BIN:-./test_fips_break} | 
 |   check_file "$TEST_FIPS_BIN" | 
 |   check_file "$TEST_FIPS_BREAK_BIN" | 
 |  | 
 |   BORINGSSL=. | 
 |   RUN=run_test_locally | 
 |   BREAK_TEST=local_break_test | 
 |   INTEGRITY_BREAK_TEST=local_integrity_break_test | 
 |   KAT_BREAK_TEST=local_kat_break_test | 
 |   RUNTIME_BREAK_TEST=local_runtime_break_test | 
 |   if [ ! -f "$TEST_FIPS_BIN" ]; then | 
 |     echo "$TEST_FIPS_BIN is missing. Run this script from the top level of a" | 
 |     echo "BoringSSL checkout and ensure that BoringSSL has been built in" | 
 |     echo "build/ with -DFIPS_BREAK_TEST=TESTS passed to CMake." | 
 |     exit 1 | 
 |   fi | 
 | else # Device mode | 
 |   test "$ANDROID_BUILD_TOP" || die "'lunch aosp_arm64-eng' first" | 
 |   check_directory "$ANDROID_PRODUCT_OUT" | 
 |  | 
 |   TEST_FIPS_BIN="$ANDROID_PRODUCT_OUT/system/bin/test_fips" | 
 |   check_file "$TEST_FIPS_BIN" | 
 |   LIBCRYPTO_BIN="$ANDROID_PRODUCT_OUT/system/lib64/libcrypto.so" | 
 |   LIBCRYPTO_BREAK_BIN="libcrypto.so" | 
 |   check_file "$LIBCRYPTO_BIN" | 
 |   check_file "$LIBCRYPTO_BREAK_BIN" | 
 |  | 
 |   test "$ANDROID_SERIAL" || die "ANDROID_SERIAL not set" | 
 |   DEVICE_TMP=/data/local/tmp | 
 |  | 
 |   BORINGSSL="$ANDROID_BUILD_TOP/external/boringssl/src" | 
 |   RUN=run_test_on_device | 
 |   INTEGRITY_BREAK_TEST=device_integrity_break_test | 
 |   KAT_BREAK_TEST=device_kat_break_test | 
 | fi | 
 |  | 
 |  | 
 | KATS=$(go run "$BORINGSSL/util/fipstools/break-kat.go" --list-tests) | 
 |  | 
 | echo -e '\033[1mNormal output\033[0m' | 
 | $RUN "$TEST_FIPS_BIN" "$LIBCRYPTO_BIN" | 
 | pause | 
 |  | 
 | echo | 
 | echo -e '\033[1mIntegrity test failure\033[0m' | 
 | $INTEGRITY_BREAK_TEST | 
 | pause | 
 |  | 
 | for kat in $KATS; do | 
 |   echo | 
 |   echo -e "\033[1mKAT failure ${kat}\033[0m" | 
 |   $KAT_BREAK_TEST $kat | 
 |   pause | 
 | done | 
 |  | 
 | if [ "$MODE" = "local" ]; then | 
 |   # TODO(prb): add support for Android devices. | 
 |   for runtime_test in ECDSA_PWCT RSA_PWCT CRNG; do | 
 |     echo | 
 |     echo -e "\033[1m${runtime_test} failure\033[0m" | 
 |     $RUNTIME_BREAK_TEST ${runtime_test} | 
 |     pause | 
 |   done | 
 | fi |