From patchwork Sun Jan 12 23:44:48 2014 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Yann E. MORIN" X-Patchwork-Id: 309660 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from fraxinus.osuosl.org (fraxinus.osuosl.org [140.211.166.137]) by ozlabs.org (Postfix) with ESMTP id 9542E2C0092 for ; Mon, 13 Jan 2014 10:45:09 +1100 (EST) Received: from localhost (localhost [127.0.0.1]) by fraxinus.osuosl.org (Postfix) with ESMTP id 17F9B8B7D9; Sun, 12 Jan 2014 23:45:07 +0000 (UTC) X-Virus-Scanned: amavisd-new at osuosl.org Received: from fraxinus.osuosl.org ([127.0.0.1]) by localhost (.osuosl.org [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id Spa5vYPjngfy; Sun, 12 Jan 2014 23:45:05 +0000 (UTC) Received: from ash.osuosl.org (ash.osuosl.org [140.211.166.34]) by fraxinus.osuosl.org (Postfix) with ESMTP id 6822E8B7B1; Sun, 12 Jan 2014 23:45:04 +0000 (UTC) X-Original-To: buildroot@lists.busybox.net Delivered-To: buildroot@osuosl.org Received: from whitealder.osuosl.org (whitealder.osuosl.org [140.211.166.138]) by ash.osuosl.org (Postfix) with ESMTP id A75131BF841 for ; Sun, 12 Jan 2014 23:44:59 +0000 (UTC) Received: from localhost (localhost [127.0.0.1]) by whitealder.osuosl.org (Postfix) with ESMTP id 9EEC38BA87 for ; Sun, 12 Jan 2014 23:44:59 +0000 (UTC) X-Virus-Scanned: amavisd-new at osuosl.org Received: from whitealder.osuosl.org ([127.0.0.1]) by localhost (.osuosl.org [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id 9Wr+MhlWte4o for ; Sun, 12 Jan 2014 23:44:58 +0000 (UTC) X-Greylist: domain auto-whitelisted by SQLgrey-1.7.6 Received: from mail-wg0-f41.google.com (mail-wg0-f41.google.com [74.125.82.41]) by whitealder.osuosl.org (Postfix) with ESMTPS id 6BB338BA54 for ; Sun, 12 Jan 2014 23:44:58 +0000 (UTC) Received: by mail-wg0-f41.google.com with SMTP id n12so2195761wgh.2 for ; Sun, 12 Jan 2014 15:44:57 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20120113; h=sender:from:to:cc:subject:date:message-id:in-reply-to:references; bh=UhZJMFRW232+cRnI6LL6vFRGlY7VothJl33bqflqI9k=; b=w1MiaZ6tYiZVitx94wUAmnOSb2ncxqI0p09exNDhcbO89XvquTksEg7+/Qxek8RSRs sNTjqAoEdzyyi/rFkdKRFFnjNAr4V0hiuPE1a1nfXRQbGKFUgWhZkOsvb13sqVieAK8s MAwEUO+Ex7utIWVRKPlaNVqDlkOdjEcaeN4nW0isNFxWPpc9tlvlU7nJRfXeYzboqU66 k8e2dlis1Ja87Z34rzJHcJ7tlsP3mPZ5k9KVkIldHdIUNfIaSkoImniPQAarHyIpUlHy FqUTR3ffQ2GdKAdgGPKXY4B4INDkqgYFJsvd9bvUcEExpAQS3s+kSo4MqE4xAOqyrQ3t xcWg== X-Received: by 10.180.73.196 with SMTP id n4mr12634912wiv.24.1389570297034; Sun, 12 Jan 2014 15:44:57 -0800 (PST) Received: from gourin.bzh.lan (ks3095497.kimsufi.com. [94.23.60.27]) by mx.google.com with ESMTPSA id z2sm14900365wiy.11.2014.01.12.15.44.55 for (version=TLSv1.1 cipher=ECDHE-RSA-RC4-SHA bits=128/128); Sun, 12 Jan 2014 15:44:56 -0800 (PST) From: "Yann E. MORIN" To: buildroot@busybox.net Date: Mon, 13 Jan 2014 00:44:48 +0100 Message-Id: X-Mailer: git-send-email 1.8.1.2 In-Reply-To: References: Cc: "Yann E. MORIN" Subject: [Buildroot] [PATCH 5/6] pkg-infra: add possiblity to check downloaded files against known hashes X-BeenThere: buildroot@busybox.net X-Mailman-Version: 2.1.14 Precedence: list List-Id: Discussion and development of buildroot List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Errors-To: buildroot-bounces@busybox.net Sender: buildroot-bounces@busybox.net From: "Yann E. MORIN" Some of the packages that Buildroot might build are sensitive pacakges, related to security: openssl, dropbear, ca-certificates... Some of those packages are download over plain http, because there is no way to get them over a secure channel, such as https. In these dark times of pervasive surveillance, the potential for harm that a tampered package could generate, we may want to check the integrity of those sensitive packages. So, each package may now provide a list of hashes for all files that needs to be downloaded, and Buildroot will just fail if any download file does not match its known hash. The choosen hash function is SHA1 since it is widely available, though theoretical attacks have been devised (but no known practical attack is known). Signed-off-by: "Yann E. MORIN" --- Note: this is not a bullet-proof solution, since Buildroot may itself be compromised. But if we eventually sign our releases, then we secure the list of hashes at the same time. Only random snapshots from the repository may be at risk of tampering, although this is highly doubtfull, given how git stores its data. Also, before we commit a list of hashes to the tree, we may want to setup a chain-of-trust to validate that thos hashes are correct. We may want to discuss this during our next developpers' day in Brussels in February. Note-2: The laternative to sha1 would be sha2 (256- or 512-bit), but oldish "enterprise-class" distributions may be missing them entirely. sha256sum and sha512sum were added to coreutils in 2005-10-23, and RHEL5 seems to have them. But better be safe than sorry. If sha2 should be considered instead of sha1, then it is very easy to switch now. Switching later would require that we revalidate all packages that have hashes, which could prove to be quite time-demanding if we have lots of packages using hashes. --- docs/manual/adding-packages-directory.txt | 35 ++++++++++++++++++++++++++++ package/pkg-download.mk | 15 ++++++++++-- support/download/check-hash | 38 +++++++++++++++++++++++++++++++ 3 files changed, 86 insertions(+), 2 deletions(-) create mode 100755 support/download/check-hash 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