diff --git a/util/crossgcc/buildgcc b/util/crossgcc/buildgcc
index 97c38b8d95..d6b11ed0a6 100755
--- a/util/crossgcc/buildgcc
+++ b/util/crossgcc/buildgcc
@@ -270,18 +270,6 @@ check_cc() {
 	fi
 }
 
-check_sum() {
-	test -z "$CHECKSUM" || \
-	test "$(cat sum/$1.cksum 2>/dev/null | sed -e 's@.*\([0-9a-f]\{40,\}\).*@\1@')" = \
-	"$($CHECKSUM tarballs/$1 2>/dev/null | sed -e 's@.*\([0-9a-f]\{40,\}\).*@\1@')"
-}
-
-compute_sum() {
-	test ! -f sum/$1.cksum && test -f tarballs/$1 && \
-	(test -z "$CHECKSUM" || $CHECKSUM tarballs/$1 > sum/$1.cksum ) && \
-	printf "(checksum created. ${RED}Note. Please upload sum/$1.cksum if the corresponding archive is upgraded.)${NC}"
-}
-
 download_showing_percentage() {
 	url=$1
 	printf " ..${red}  0%%"
@@ -293,12 +281,13 @@ download_showing_percentage() {
 
 download() {
 	package=$1
-	archive="$(eval echo \$$package"_ARCHIVE")"
+	archive="$package"_ARCHIVE
+	archive="${!archive}"
 
 	FILE=$(basename $archive)
 	printf " * $FILE "
 
-	if test -f tarballs/$FILE && check_sum $FILE ; then
+	if test -f tarballs/$FILE; then
 		printf "(cached)"
 	else
 		printf "(downloading from $archive)"
@@ -306,7 +295,6 @@ download() {
 		cd tarballs
 		download_showing_percentage $archive
 		cd ..
-		compute_sum $FILE
 	fi
 
 	if [ ! -f tarballs/$FILE ]; then
@@ -316,9 +304,100 @@ download() {
 	printf "\n"
 }
 
+# Compute the hash of the package given in $1, and print it raw (just the
+# hexadecimal hash).
+compute_hash() {
+	package=$1
+	archive="$package"_ARCHIVE
+	archive="${!archive}"
+	file="$(basename "$archive")"
+
+	if test -z "$CHECKSUM"; then
+		echo "${RED}\$CHECKSUM program missing. This is bad.${NC}" 1>&2
+		exit 1
+	fi
+
+	$CHECKSUM "tarballs/$file" 2>/dev/null | sed -e 's@.*\([0-9a-f]\{40,\}\).*@\1@'
+}
+
+error_hash_missing() {
+	package="$1"
+	archive="$package"_ARCHIVE
+	archive="${!archive}"
+	file="$(basename "$archive")"
+
+	fullhashfile="util/crossgcc/sum/$file.cksum"
+	printf "${RED}hash file missing:${NC}\n\n" 1>&2
+	printf "Please verify util/crossgcc/tarball/$file carefully\n" 1>&2
+	printf "(using PGP if possible), and then rename\n" 1>&2
+	printf "        ${CYAN}${fullhashfile}.calc${NC}\n" 1>&2
+	printf "     to ${CYAN}${fullhashfile}${NC}\n\n" 1>&2
+
+	exit 1
+}
+
+# Read the known hash file of the package given in $1, and print it raw.
+get_known_hash() {
+	package=$1
+	archive="$package"_ARCHIVE
+	archive="${!archive}"
+	file="$(basename "$archive")"
+	hashfile="sum/$file.cksum"
+
+	if [ ! -f "$hashfile" ]; then
+		calc_hash="$(compute_hash "$package")" || exit 1
+		echo "$calc_hash  tarballs/$file" > "${hashfile}.calc"
+
+		error_hash_missing "$package"
+		exit 1
+	fi
+
+	cat "$hashfile" | sed -e 's@.*\([0-9a-f]\{40,\}\).*@\1@'
+}
+
+error_hash_mismatch() {
+	package=$1
+	known_hash="$2"
+	computed_hash="$3"
+	archive="$package"_ARCHIVE
+	archive="${!archive}"
+	file="$(basename "$archive")"
+
+	printf "${RED}hash mismatch:${NC}\n\n"
+	printf "             expected (known) hash: $known_hash\n"
+	printf "calculated hash of downloaded file: $computed_hash\n\n"
+
+	printf "If you think this is due to a network error, please delete\n"
+	printf "  ${CYAN}util/crossgcc/tarballs/$file${NC}\n"
+	printf "and try again. If the problem persists, it may be due to an\n"
+	printf "administration error on the file server, or you might be\n"
+	printf "subject to a Man-in-the-Middle attack\n\n"
+
+	exit 1
+}
+
+# verify_hash - Check that the hash of the file given in $1 matches the known
+# hash; Bail out on mismatch or missing hash file.
+verify_hash() {
+	package=$1
+	archive="$package"_ARCHIVE
+	archive="${!archive}"
+
+	known_hash="$(get_known_hash "$package")" || exit "$?"
+	computed_hash="$(compute_hash "$package")" || exit "$?"
+
+	if [ "$known_hash" != "$computed_hash" ]; then
+		error_hash_mismatch "$package" "$known_hash" "$computed_hash"
+		exit 1
+	fi
+
+	printf "${GREEN}hash verified ("$known_hash")${NC}\n"
+}
+
 unpack_and_patch() {
 	package=$1
-	archive="$(eval echo \$$package"_ARCHIVE")"
+	archive="$package"_ARCHIVE
+	archive="${!archive}"
 	dir="$(eval echo \$$package"_DIR")"
 	test -d ${dir} && test -f ${dir}/.unpack_success || (
 		printf " * $(basename $archive)\n"
@@ -963,10 +1042,11 @@ export PATH=$DESTDIR$TARGETDIR/bin:$PATH
 
 # Download, unpack, patch and build all packages
 
-printf "Downloading tarballs ... \n"
+printf "Downloading and verifying tarballs... \n"
 mkdir -p tarballs
 for P in $PACKAGES; do
-	download $P
+	  download "$P" || exit "$?"
+    verify_hash "$P" || exit "$P"
 done
 printf "Downloaded tarballs ... ${green}ok${NC}\n"
 
