libsoliton/verify.sh
Kamal Tufekcic 3acaa0fa3f
CryptoVerif and Tamarin models, minor doc updates
Signed-off-by: Kamal Tufekcic <kamal@lo.sh>
2026-04-23 15:52:23 +03:00

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