182 lines
5.3 KiB
Bash
Executable file
182 lines
5.3 KiB
Bash
Executable file
#!/bin/bash
|
|
# Formal verification runner for libsoliton.
|
|
# Run after editing any .spthy or .cv file. Results should match the
|
|
# expected outcomes in tamarin/README.md and cryptoverif/README.md.
|
|
#
|
|
# Requirements:
|
|
# tamarin-prover 1.12.0+ with maude 3.5.1+ on PATH
|
|
# cryptoverif 2.12+ on PATH
|
|
#
|
|
# Usage:
|
|
# ./verify.sh # run everything
|
|
# ./verify.sh tamarin # tamarin only
|
|
# ./verify.sh cryptoverif # cryptoverif only
|
|
# ./verify.sh tamarin/LO_Auth.spthy # single file
|
|
#
|
|
# Environment:
|
|
# CV_LIB Path to CryptoVerif pq library (without .cvl extension).
|
|
# Example: CV_LIB=/usr/share/cryptoverif/pq ./verify.sh
|
|
|
|
set -euo pipefail
|
|
|
|
SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
|
|
TAMARIN_DIR="$SCRIPT_DIR/tamarin"
|
|
CV_DIR="$SCRIPT_DIR/cryptoverif"
|
|
CV_LIB="${CV_LIB:-}"
|
|
|
|
if [ -t 1 ]; then
|
|
GREEN='\033[0;32m'; RED='\033[0;31m'; YELLOW='\033[0;33m'
|
|
BOLD='\033[1m'; RESET='\033[0m'
|
|
else
|
|
GREEN=''; RED=''; YELLOW=''; BOLD=''; RESET=''
|
|
fi
|
|
|
|
# Global counters
|
|
T_VERIFIED=0; T_FALSIFIED=0; T_ERRORS=0; T_FILES=0
|
|
CV_PROVED=0; CV_FAILED=0; CV_FILES=0
|
|
|
|
print_header() {
|
|
echo ""
|
|
echo -e "${BOLD}=== $1 ===${RESET}"
|
|
echo ""
|
|
}
|
|
|
|
run_tamarin() {
|
|
local file="$1"
|
|
local name
|
|
name="$(basename "$file" .spthy)"
|
|
T_FILES=$((T_FILES + 1))
|
|
|
|
echo -e "${BOLD}--- $name ---${RESET}"
|
|
|
|
local output
|
|
if ! output=$(tamarin-prover "$file" --prove 2>&1); then
|
|
echo -e " ${RED}ERROR: tamarin-prover failed${RESET}"
|
|
echo "$output" | tail -5 | sed 's/^/ /'
|
|
T_ERRORS=$((T_ERRORS + 1))
|
|
return
|
|
fi
|
|
|
|
# Check for wellformedness warnings
|
|
if echo "$output" | grep -q "WARNING"; then
|
|
echo -e " ${RED}WARNING: wellformedness check failed${RESET}"
|
|
T_ERRORS=$((T_ERRORS + 1))
|
|
fi
|
|
|
|
local time
|
|
time=$(echo "$output" | grep "processing time:" | sed 's/.*processing time: //')
|
|
|
|
# Parse each result line — avoid subshell pipe by using process substitution
|
|
while IFS= read -r line; do
|
|
local lemma steps
|
|
lemma=$(echo "$line" | sed 's/ (.*//')
|
|
steps=$(echo "$line" | grep -oP '\d+ steps' || echo "? steps")
|
|
|
|
if echo "$line" | grep -q "verified"; then
|
|
echo -e " ${GREEN}PASS${RESET} $lemma ($steps)"
|
|
T_VERIFIED=$((T_VERIFIED + 1))
|
|
elif echo "$line" | grep -q "falsified"; then
|
|
echo -e " ${YELLOW}FALSE${RESET} $lemma ($steps)"
|
|
T_FALSIFIED=$((T_FALSIFIED + 1))
|
|
fi
|
|
done < <(echo "$output" | grep -E "verified|falsified")
|
|
|
|
echo " ($time)"
|
|
}
|
|
|
|
run_cryptoverif() {
|
|
local file="$1"
|
|
local name
|
|
name="$(basename "$file" .cv)"
|
|
CV_FILES=$((CV_FILES + 1))
|
|
|
|
echo -e "${BOLD}--- $name ---${RESET}"
|
|
|
|
if [ -z "$CV_LIB" ]; then
|
|
echo -e " ${YELLOW}SKIP${RESET} CV_LIB not set. Run: CV_LIB=/path/to/pq $0 cryptoverif"
|
|
CV_FILES=$((CV_FILES - 1))
|
|
return
|
|
fi
|
|
|
|
local output
|
|
output=$(cryptoverif -lib "$CV_LIB" "$file" 2>&1) || true
|
|
|
|
if echo "$output" | grep -q "^File.*Error:"; then
|
|
echo -e " ${RED}ERROR${RESET}"
|
|
echo "$output" | grep "Error:" | sed 's/^/ /'
|
|
CV_FAILED=$((CV_FAILED + 1))
|
|
return
|
|
fi
|
|
|
|
while IFS= read -r line; do
|
|
if echo "$line" | grep -q "Proved"; then
|
|
local prop bound
|
|
prop=$(echo "$line" | sed 's/RESULT Proved //' | sed 's/ up to.*//')
|
|
bound=$(echo "$line" | grep -oP 'up to probability .*' || echo "")
|
|
echo -e " ${GREEN}PROVED${RESET} $prop"
|
|
[ -n "$bound" ] && echo " $bound"
|
|
CV_PROVED=$((CV_PROVED + 1))
|
|
elif echo "$line" | grep -q "Could not prove"; then
|
|
local prop
|
|
prop=$(echo "$line" | sed 's/RESULT Could not prove //')
|
|
echo -e " ${RED}FAILED${RESET} $prop"
|
|
CV_FAILED=$((CV_FAILED + 1))
|
|
fi
|
|
done < <(echo "$output" | grep "^RESULT" | grep -v "^RESULT time")
|
|
|
|
if echo "$output" | grep -q "All queries proved"; then
|
|
echo -e " ${GREEN}All queries proved.${RESET}"
|
|
fi
|
|
}
|
|
|
|
run_all_tamarin() {
|
|
print_header "Tamarin Prover"
|
|
for f in "$TAMARIN_DIR"/*.spthy; do
|
|
run_tamarin "$f"
|
|
echo ""
|
|
done
|
|
}
|
|
|
|
run_all_cryptoverif() {
|
|
print_header "CryptoVerif"
|
|
for f in "$CV_DIR"/*.cv; do
|
|
run_cryptoverif "$f"
|
|
echo ""
|
|
done
|
|
}
|
|
|
|
case "${1:-all}" in
|
|
tamarin) run_all_tamarin ;;
|
|
cryptoverif) run_all_cryptoverif ;;
|
|
*.spthy) run_tamarin "$1" ;;
|
|
*.cv) run_cryptoverif "$1" ;;
|
|
all) run_all_tamarin; run_all_cryptoverif ;;
|
|
*) echo "Usage: $0 [all|tamarin|cryptoverif|<file>]"; exit 1 ;;
|
|
esac
|
|
|
|
# Summary
|
|
echo ""
|
|
echo -e "${BOLD}=== Summary ===${RESET}"
|
|
|
|
T_TOTAL=$((T_VERIFIED + T_FALSIFIED))
|
|
if [ "$T_FILES" -gt 0 ]; then
|
|
echo -e " Tamarin: ${T_FILES} files, ${T_TOTAL} lemmas (${T_VERIFIED} verified, ${T_FALSIFIED} falsified, ${T_ERRORS} errors)"
|
|
fi
|
|
|
|
CV_TOTAL=$((CV_PROVED + CV_FAILED))
|
|
if [ "$CV_FILES" -gt 0 ]; then
|
|
echo -e " CryptoVerif: ${CV_FILES} files, ${CV_TOTAL} queries (${CV_PROVED} proved, ${CV_FAILED} failed)"
|
|
fi
|
|
|
|
GRAND_TOTAL=$((T_TOTAL + CV_TOTAL))
|
|
GRAND_PASS=$((T_VERIFIED + T_FALSIFIED + CV_PROVED))
|
|
GRAND_FAIL=$((T_ERRORS + CV_FAILED))
|
|
|
|
echo -e " Total: ${GRAND_TOTAL} checks, ${GRAND_FAIL} failures"
|
|
|
|
if [ "$GRAND_FAIL" -gt 0 ]; then
|
|
echo -e " ${RED}Some checks failed.${RESET}"
|
|
exit 1
|
|
else
|
|
echo -e " ${GREEN}All checks passed.${RESET}"
|
|
fi
|