#!/bin/bash # Copyright 2017 The Fuchsia Authors # # Use of this source code is governed by a MIT-style # license that can be found in the LICENSE file or at # https://opensource.org/licenses/MIT # Runs a single instance of the early boot entropy collection test. # # This script assumes that Zircon has already been built to support entropy quality tests (i.e with # the ENABLE_ENTROPY_COLLECTOR_TEST flag set at compile time). It handles starting Zircon either in # qemu or via netboot, then it extracts the entropy file once the boot-time test completes. Usually # you will call a "test driver" script that in turn calls this script, rather than calling this # script directly. # # Where sensible, the option flags agree with scripts/run-zircon. The -a, -m, and -s command line # options are mandatory; the rest are optional. The output directory must also be passed on the # command line, as a positional argument (i.e. without a '-?' type flag). # # This script saves the captured entropy in a file named 'entropy.#########.bin' (to facilitate # running repeated tests with the same output directory). It also saves a metadata file, named # 'entropy.#########.meta', recording certain test parameters. See the source below for more # details. # # BUGS: netboot isn't supported yet, only qemu. set -e -u CDPATH= ZIRCONDIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )/../.." && pwd )" function HELP { echo "$0 [options] output-dir/" >&2 echo "options:" >&2 echo "-a : arm64 or x86" >&2 echo "-c : add word to kernel cmdline" >&2 echo "-l : entropy test length (bytes to collect)" >&2 echo "-m : netboot or qemu" >&2 echo "-n : Zircon nodename to use" >&2 echo "-o : build directory" >&2 echo "-s : hwrng or jitterentropy" >&2 exit 1 } ARCH= BUILDDIR= CMDLINE="" LEN= METHOD= NODENAME= OUTDIR= SRC= while getopts "a:c:hl:m:n:o:s:" FLAG; do case "$FLAG" in a) ARCH="$OPTARG";; c) CMDLINE+="$OPTARG ";; h) HELP;; l) LEN="$OPTARG";; m) METHOD="$OPTARG";; n) NODENAME="$OPTARG";; o) BUILDDIR="$OPTARG";; s) SRC="$OPTARG";; \?) echo "unrecognized option" >&2 HELP ;; esac done shift $((OPTIND-1)) if [[ "$#" -ne "1" ]]; then echo "missing output dir" >&2 HELP fi OUTDIR="$1" shift # check required args if [[ -z $ARCH ]]; then echo "must specify arch" >&2 HELP fi if [[ -z $METHOD ]]; then echo "must specify method" >&2 HELP fi if [[ -z $SRC ]]; then echo "must specify source" >&2 HELP fi if [[ -z $OUTDIR ]]; then echo "must specify outdir" >&2 HELP fi # handle entropy-test specific cmdline args CMDLINE+="kernel.entropy-test.src=$SRC " if [[ -n $LEN ]]; then CMDLINE+="kernel.entropy-test.len=$LEN "; fi # find and read builddir PROJECT="$ARCH" if [[ -z "$BUILDDIR" ]]; then if [[ -n $PROJECT ]]; then BUILDDIR="$ZIRCONDIR/build-$PROJECT" else echo "could not autodetect builddir. use -o." >&2 HELP fi fi if [[ ! -d $BUILDDIR || ! -x $BUILDDIR/tools/netcp ]]; then echo "bad builddir: $BUILDDIR" >&2 HELP fi BUILDID="$(sed -n '/^#define\s\+BUILDID/{s/^[^"]*"//;s/".*$//;p;q}' "$BUILDDIR/config-buildid.h")" # set a few other variables if [[ -z $NODENAME ]]; then if [[ $METHOD = "qemu" ]]; then NODENAME="entropy-test-$(head -c16 /dev/urandom | xxd -p)"; elif [[ $METHOD = "netboot" ]]; then echo "missing nodename - required for netboot" >&2 HELP fi fi CMDLINE+="zircon.nodename=$NODENAME " NUM="$(cd "$OUTDIR"; find . \( -type f -name "entropy.*.bin" -print \) -o \( -type d ! -name . -prune \) | sed 's/^.*entropy\.0*//;s/\.bin$//;s/^$/0/;' | grep '^[0-9]\+$' | sort -nr | head -n 1)" if [[ -z $NUM ]]; then NUM=-1; fi NUM="$(printf "%09d" "$((NUM + 1))")" BINFILE="$OUTDIR/entropy.$NUM.bin" METAFILE="$OUTDIR/entropy.$NUM.meta" # launch zircon case "$METHOD" in qemu) "$ZIRCONDIR/scripts/run-zircon" -a "$ARCH" -c "$CMDLINE" -N -o "$BUILDDIR" /dev/null 2>/dev/null & BOOTSERVER_PID=$! ;; *) echo "unrecognized method: $METHOD" >&2 HELP ;; esac echo "launched zircon with nodename $NODENAME" >&2 # wait for zircon to send us the entropy file while true; do sleep 5; if "$BUILDDIR"/tools/netcp --nowait --timeout=1000 \ "$NODENAME:/boot/kernel/debug/entropy.bin" "$BINFILE" && [[ -z $LEN || $(wc -c <"$BINFILE") -eq $LEN ]] then echo "Finished test on nodename $NODENAME" >&2 break fi done # write the meta file { echo "entropy-test $METHOD" echo "date $(date +"%Y-%m-%d %H:%M:%S %Z")" echo "buildid $BUILDID" echo "arch $ARCH" echo "source $SRC" echo "len $LEN" echo "cmdline $CMDLINE" } >$METAFILE # reset the test device case "$METHOD" in qemu) while "$BUILDDIR"/tools/netaddr --nowait --timeout=1000 \ "$NODENAME" >/dev/null 2>/dev/null; do "$BUILDDIR"/tools/netruncmd --nowait --timeout=1000 "$NODENAME" dm shutdown sleep 2 done ;; netboot) kill "$BOOTSERVER_PID" sleep 1 # make sure bootserver actually has time to shut down while "$BUILDDIR"/tools/netaddr --nowait --timeout=1000 \ "$NODENAME" >/dev/null 2>/dev/null; do "$BUILDDIR"/tools/netruncmd --nowait --timeout=1000 "$NODENAME" dm reboot sleep 2 done ;; esac