diff --git a/docs/manual/adding-packages-directory.txt b/docs/manual/adding-packages-directory.txt
index 754a145..c5a92bd 100644
--- a/docs/manual/adding-packages-directory.txt
+++ b/docs/manual/adding-packages-directory.txt
@@ -325,3 +325,38 @@ different way, using different infrastructures:
 
 Further formatting details: see xref:writing-rules-mk[the writing
 rules].
+
+The +.hash+ file
+~~~~~~~~~~~~~~~~
+[[adding-packages-hash]]
+
+Optionally, you can add a third file, named +libfoo.hash+, that contains
+the https://en.wikipedia.org/wiki/Sha-1[SHA1] hashes of the downloaded
+files for the +libfoo+ package.
+
+The hashes stored in that file are used to validate the integrity of the
+downloaded files.
+
+The format for this file matches the output of +sha1sum+, that is, each
+line contains:
+
+* the SHA1 hash
+* two spaces
+* the name fo the file
+
+Specific to +Buildroot+, the filenames should not contain any directory
+component, such as:
+
+----
+486fb55c3efa71148fe07895fd713ea3a5ae343a  libfoo-1.2.3.tar.bz2
+a045ff9ecaf8d5342daa4cd23a4084da65af49e1  libfoo-fix-blabla.patch
+f729372d25deddd6191864a48484d4d268fd23ec  libfoo-data.bin
+----
+
+If the +.hash+ file is present, and there is an entry for a downloaded
+file, the hash of the downloaded file must match the hash stored in the
++.hash+ file. If it does not match, this is considered an error, and
+Buildroot aborts.
+
+If the +.hash+ file is present, but there is no entry for a downloaded
+file, or if the +.hash+ file is missing, then no check is done.
diff --git a/package/pkg-download.mk b/package/pkg-download.mk
index f3354d1..5627850 100644
--- a/package/pkg-download.mk
+++ b/package/pkg-download.mk
@@ -58,6 +58,14 @@ domainseparator=$(if $(1),$(1),/)
 # github(user,package,version): returns site of github repository
 github = https://github.com/$(1)/$(2)/tarball/$(3)
 
+# Helper for checking a tarball's checksum
+# $(1): the basename of the tarball to check
+# $(2): the full path to the file to check
+define VERIFY_SHA256
+	support/download/check-hash $(1) $(2) \
+		$($(PKG)_DIR_PREFIX)/$($(PKG)_NAME)/$($(PKG)_NAME).hash
+endef
+
 ################################################################################
 # The DOWNLOAD_* helpers are in charge of getting a working copy
 # of the source repository for their corresponding SCM,
@@ -153,7 +161,8 @@ endef
 # to prepend the path with a slash: scp://[user@]host:/absolutepath
 define DOWNLOAD_SCP
 	test -e $(DL_DIR)/$(2) || \
-	$(SCP) '$(call stripurischeme,$(call qstrip,$(1)))' $(DL_DIR)/$(2)
+	$(SCP) '$(call stripurischeme,$(call qstrip,$(1)))' $(DL_DIR)/$(2) && \
+	$(call VERIFY_SHA256,$(DL_DIR)/$(2))
 endef
 
 define SOURCE_CHECK_SCP
@@ -195,6 +204,7 @@ endef
 define DOWNLOAD_WGET
 	test -e $(DL_DIR)/$(2) || \
 	($(WGET) -O $(DL_DIR)/$(2).tmp '$(call qstrip,$(1))' && \
+	 $(call VERIFY_SHA256,$(2),$(DL_DIR)/$(2).tmp) && \
 	 mv $(DL_DIR)/$(2).tmp $(DL_DIR)/$(2)) || \
 	(rm -f $(DL_DIR)/$(2).tmp ; exit 1)
 endef
@@ -209,7 +219,8 @@ endef
 
 define DOWNLOAD_LOCALFILES
 	test -e $(DL_DIR)/$(2) || \
-		$(LOCALFILES) $(call stripurischeme,$(call qstrip,$(1))) $(DL_DIR)
+		$(LOCALFILES) $(call stripurischeme,$(call qstrip,$(1))) $(DL_DIR) && \
+	$(call VERIFY_SHA256,$(DL_DIR)/$(2))
 endef
 
 define SOURCE_CHECK_LOCALFILES
diff --git a/support/download/check-hash b/support/download/check-hash
new file mode 100755
index 0000000..5cf708f
--- /dev/null
+++ b/support/download/check-hash
@@ -0,0 +1,38 @@
+#!/bin/sh
+set -e
+
+# Helper to check a file matches its known hash
+# Call it with:
+#   $1: the basename of the package's tarball
+#   $2: the full path to the file to check
+#   $3: the path of the file containing all the the expected hashes
+
+tarball="${1}"
+file="${2}"
+h_file="${3}"
+
+# Does the hash-file exist?
+if [ ! -f "${h_file}" ]; then
+    exit 0
+fi
+
+# Do we know a hash for that tarball?
+known=$( grep -E '^[[:xdigit:]]+[[:space:]]{2}'"${tarball}"'$$' "${h_file}" \
+         |cut -d ' ' -f 1
+       )
+if [ -z "${known}" ]; then
+    exit 0
+fi
+
+# Do the hashes match?
+hash=$( sha1sum "${file}" |cut -d ' ' -f 1 )
+if [ "${hash}" = "${known}" ]; then
+    exit 0
+fi
+
+printf "ERROR: %s has wrong SHA256\n" "${tarball}"
+printf "ERROR: expected: %s\n" "${known}"
+printf "ERROR: got     : %s\n" "${hash}"
+printf "ERROR: Incomplete download, or MITM attack\n"
+
+exit 1
