1 #!/usr/bin/env bash
2 export LC_ALL=C
3 set -e -o pipefail
4 5 # Source the common prelude, which:
6 # 1. Checks if we're at the top directory of the Bitcoin Core repository
7 # 2. Defines a few common functions and variables
8 #
9 # shellcheck source=libexec/prelude.bash
10 source "$(dirname "${BASH_SOURCE[0]}")/libexec/prelude.bash"
11 12 13 ###################
14 ## Sanity Checks ##
15 ###################
16 17 ################
18 # Required non-builtin commands should be invokable
19 ################
20 21 check_tools cat diff gpg
22 23 ################
24 # Required env vars should be non-empty
25 ################
26 27 cmd_usage() {
28 cat <<EOF
29 Synopsis:
30 31 env GUIX_SIGS_REPO=<path/to/guix.sigs> [ SIGNER=<signer> ] ./contrib/guix/guix-verify
32 33 Example overriding signer's manifest to use as base
34 35 env GUIX_SIGS_REPO=/home/dongcarl/guix.sigs SIGNER=achow101 ./contrib/guix/guix-verify
36 37 EOF
38 }
39 40 if [ -z "$GUIX_SIGS_REPO" ]; then
41 cmd_usage
42 exit 1
43 fi
44 45 ################
46 # GUIX_SIGS_REPO should exist as a directory
47 ################
48 49 if [ ! -d "$GUIX_SIGS_REPO" ]; then
50 cat << EOF
51 ERR: The specified GUIX_SIGS_REPO is not an existent directory:
52 53 '$GUIX_SIGS_REPO'
54 55 Hint: Please clone the guix.sigs repository and point to it with the
56 GUIX_SIGS_REPO environment variable.
57 58 EOF
59 cmd_usage
60 exit 1
61 fi
62 63 ##############
64 ## Verify ##
65 ##############
66 67 OUTSIGDIR_BASE="${GUIX_SIGS_REPO}/${VERSION}"
68 echo "Looking for signature directories in '${OUTSIGDIR_BASE}'"
69 echo ""
70 71 # Usage: verify compare_manifest current_manifest
72 verify() {
73 local compare_manifest="$1"
74 local current_manifest="$2"
75 if ! gpg --quiet --batch --verify "$current_manifest".asc "$current_manifest" 1>&2; then
76 echo "ERR: Failed to verify GPG signature in '${current_manifest}'"
77 echo ""
78 echo "Hint: Either the signature is invalid or the public key is missing"
79 echo ""
80 failure=1
81 elif ! diff --report-identical "$compare_manifest" "$current_manifest" 1>&2; then
82 echo "ERR: The SHA256SUMS attestation in these two directories differ:"
83 echo " '${compare_manifest}'"
84 echo " '${current_manifest}'"
85 echo ""
86 failure=1
87 else
88 echo "Verified: '${current_manifest}'"
89 echo ""
90 fi
91 }
92 93 shopt -s nullglob
94 all_noncodesigned=( "$OUTSIGDIR_BASE"/*/noncodesigned.SHA256SUMS )
95 shopt -u nullglob
96 97 echo "--------------------"
98 echo ""
99 if (( ${#all_noncodesigned[@]} )); then
100 compare_noncodesigned="${all_noncodesigned[0]}"
101 if [[ -n "$SIGNER" ]]; then
102 signer_noncodesigned="$OUTSIGDIR_BASE/$SIGNER/noncodesigned.SHA256SUMS"
103 if [[ -f "$signer_noncodesigned" ]]; then
104 echo "Using $SIGNER's manifest as the base to compare against"
105 compare_noncodesigned="$signer_noncodesigned"
106 else
107 echo "Unable to find $SIGNER's manifest, using the first one found"
108 fi
109 else
110 echo "No SIGNER provided, using the first manifest found"
111 fi
112 113 for current_manifest in "${all_noncodesigned[@]}"; do
114 verify "$compare_noncodesigned" "$current_manifest"
115 done
116 117 echo "DONE: Checking output signatures for noncodesigned.SHA256SUMS"
118 echo ""
119 else
120 echo "WARN: No signature directories with noncodesigned.SHA256SUMS found"
121 echo ""
122 fi
123 124 shopt -s nullglob
125 all_all=( "$OUTSIGDIR_BASE"/*/all.SHA256SUMS )
126 shopt -u nullglob
127 128 echo "--------------------"
129 echo ""
130 if (( ${#all_all[@]} )); then
131 compare_all="${all_all[0]}"
132 if [[ -n "$SIGNER" ]]; then
133 signer_all="$OUTSIGDIR_BASE/$SIGNER/all.SHA256SUMS"
134 if [[ -f "$signer_all" ]]; then
135 echo "Using $SIGNER's manifest as the base to compare against"
136 compare_all="$signer_all"
137 else
138 echo "Unable to find $SIGNER's manifest, using the first one found"
139 fi
140 else
141 echo "No SIGNER provided, using the first manifest found"
142 fi
143 144 for current_manifest in "${all_all[@]}"; do
145 verify "$compare_all" "$current_manifest"
146 done
147 148 # Sanity check: there should be no entries that exist in
149 # noncodesigned.SHA256SUMS that doesn't exist in all.SHA256SUMS
150 if [[ "$(comm -23 <(sort "$compare_noncodesigned") <(sort "$compare_all") | wc -c)" -ne 0 ]]; then
151 echo "ERR: There are unique lines in noncodesigned.SHA256SUMS which"
152 echo " do not exist in all.SHA256SUMS, something went very wrong."
153 exit 1
154 fi
155 156 echo "DONE: Checking output signatures for all.SHA256SUMS"
157 echo ""
158 else
159 echo "WARN: No signature directories with all.SHA256SUMS found"
160 echo ""
161 fi
162 163 echo "===================="
164 echo ""
165 if (( ${#all_noncodesigned[@]} + ${#all_all[@]} == 0 )); then
166 echo "ERR: Unable to perform any verifications as no signature directories"
167 echo " were found"
168 echo ""
169 exit 1
170 fi
171 172 if [ -n "$failure" ]; then
173 exit 1
174 fi
175