Subject: Using multiple digest algorithms in pkgsrc
To: None <tech-pkg@netbsd.org>
From: Alistair Crooks <agc@pkgsrc.org>
List: tech-pkg
Date: 02/16/2005 14:06:55
--Dxnq1zWXvFF0Q93v
Content-Type: text/plain; charset=us-ascii
Content-Disposition: inline

Following on from

	http://www.schneier.com/blog/archives/2005/02/sha1_broken.html

I've made some modifications to bsd.pkg.mk so that a number of digest
algorithms can be specified for dist files and dist patches.  I have
kept the digests of our included patch files to be simply sha1 for
just now, since they are really meant to indicate whether a file has
changed, and are not used to guarantee file integrity - in short, if
someone can modify the patch file, they can modify the distinfo file
holding its information.

I have extended the DIGEST_ALGORITHM definition (which is set by ?=
in bsd.pkg.mk) to be a whitespace-separated list of algorithms which
are used in "makedistinfo" to generate the distinfo files.

The modifications produce distinfo files which look like this:

[14:00:06] agc@sys3 ...pkgsrc/misc/libutf 107 > cat distinfo 
$NetBSD: distinfo,v 1.3 2002/12/23 08:03:03 jmmv Exp $

SHA1 (libutf-2.10.tar.gz) = 8dd0f6873112deaa5b5bf2a0554e28f9d8d4ddda
RMD160 (libutf-2.10.tar.gz) = f7be9f311440fe68654ce0312e869dc6a94dc47f
Size (libutf-2.10.tar.gz) = 55099 bytes
SHA1 (patch-aa) = 13ed8cf7d011e10f207d0d95a9d033b41251be44
SHA1 (patch-ab) = 993fa48a26c1111fbbcd5464eae1b6ea07cb4ffc
[14:00:09] agc@sys3 ...pkgsrc/misc/libutf 108 >

and produce the following output:

[11:58:46] agc@sys3 ...pkgsrc/misc/libutf 25 > make checksum
===> do-fetch [libutf-2.10nb3] ===> Checking for vulnerabilities in libutf-2.10nb3
=> Checksum SHA1 OK for libutf-2.10.tar.gz.
=> Checksum RMD160 OK for libutf-2.10.tar.gz.
[11:59:32] agc@sys3 ...pkgsrc/misc/libutf 26 >

Existing distinfo files work just fine:

[12:00:14] agc@sys3 ...pkgsrc/editors/ssam 6 > make checksum
===> do-fetch [ssam-1.9nb1] ===> Checking for vulnerabilities in ssam-1.9nb1
=> Checksum SHA1 OK for ssam-1.9.tar.gz.
[12:01:01] agc@sys3 ...pkgsrc/editors/ssam 7 >

and modifying a single digit of one checksum will still detect
the fiddling:

[12:24:48] agc@sys3 ...pkgsrc/misc/libutf 44 > make
===> do-fetch [libutf-2.10nb2] ===> Checking for vulnerabilities in libutf-2.10nb2
=> Checksum SHA1 OK for libutf-2.10.tar.gz.
=> Checksum RMD160 mismatch for libutf-2.10.tar.gz.
Make sure the Makefile and checksum file (/usr/sandbox/current/usr/pkgsrc/misc/libutf/distinfo)
are up to date.  If you want to override this check, type

I'm just running a bulk build right now with the changes incorporated,
and some distinfo files updated to use multiple digests.

Regards,
Alistair

--Dxnq1zWXvFF0Q93v
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment; filename="multi-digest.diff"

Index: bsd.pkg.mk
===================================================================
RCS file: /cvsroot/pkgsrc/mk/bsd.pkg.mk,v
retrieving revision 1.1590
diff -u -r1.1590 bsd.pkg.mk
--- bsd.pkg.mk	16 Feb 2005 11:01:03 -0000	1.1590
+++ bsd.pkg.mk	16 Feb 2005 14:02:48 -0000
@@ -125,7 +125,7 @@
 CONFIGURE_SCRIPT?=	./configure
 DEPENDS?=		# empty
 DESCR_SRC?=		${PKGDIR}/DESCR
-DIGEST_ALGORITHM?=	SHA1
+DIGEST_ALGORITHM?=	SHA1 RMD160
 DISTFILES?=		${DISTNAME}${EXTRACT_SUFX}
 DISTINFO_FILE?=		${PKGDIR}/distinfo
 EXTRACT_ONLY?=		${DISTFILES}
@@ -137,6 +137,7 @@
 MAINTAINER?=		tech-pkg@NetBSD.org
 MAKE_FLAGS?=		# empty
 MAKEFILE?=		Makefile
+PATCH_DIGEST_ALGORITHM?=SHA1
 PKG_SUFX?=		.tgz
 PKGFILE?=		${PKGREPOSITORY}/${PKGNAME}${PKG_SUFX}
 PKGREPOSITORY?=		${PACKAGES}/${PKGREPOSITORYSUBDIR}
@@ -1271,7 +1272,7 @@
 				if [ -n "${FAILOVER_FETCH}" -a -f ${DISTINFO_FILE} -a -f ${_DISTDIR}/$$bfile ]; then \
 					alg=`${AWK} 'NF == 4 && $$2 == "('$$file')" && $$3 == "=" {print $$1;}' ${DISTINFO_FILE}`; \
 					if [ -z "$$alg" ]; then		\
-						alg=${DIGEST_ALGORITHM};\
+						alg=${PATCH_DIGEST_ALGORITHM};\
 					fi;				\
 					CKSUM=`${DIGEST} $$alg < ${_DISTDIR}/$$bfile`; \
 					CKSUM2=`${AWK} '$$1 == "'$$alg'" && $$2 == "('$$file')" {print $$4;}' <${DISTINFO_FILE}`; \
@@ -3687,12 +3688,18 @@
 	cd ${DISTDIR};							\
 	for sumfile in "" ${_CKSUMFILES}; do				\
 		if [ "X$$sumfile" = "X" ]; then continue; fi;		\
-		${DIGEST} ${DIGEST_ALGORITHM} $$sumfile >> $$newfile;	\
+		for a in "" ${DIGEST_ALGORITHM}; do			\
+			if [ "X$$a" = "X" ]; then continue; fi;		\
+			${DIGEST} $$a $$sumfile >> $$newfile;		\
+		done;							\
 		${WC} -c $$sumfile | ${AWK} '{ print "Size (" $$2 ") = " $$1 " bytes" }' >> $$newfile; \
 	done;								\
 	for ignore in "" ${_IGNOREFILES}; do				\
 		if [ "X$$ignore" = "X" ]; then continue; fi;		\
-		${ECHO} "${DIGEST_ALGORITHM} ($$ignore) = IGNORE" >> $$newfile; \
+		for a in "" ${DIGEST_ALGORITHM}; do			\
+			if [ "X$$a" = "X" ]; then continue; fi;		\
+			${ECHO} "$$a ($$ignore) = IGNORE" >> $$newfile; \
+		done;							\
 	done;								\
 	if [ -f ${DISTINFO_FILE} ]; then				\
 		${AWK} '$$2 ~ /\(patch-[a-z0-9]+\)/ { print $$0 }' < ${DISTINFO_FILE} >> $$newfile; \
@@ -3725,7 +3732,7 @@
 			case $$sumfile in				\
 				patch-local-*) ;;			\
 				*.orig|*.rej|*~) continue ;;		\
-				*)	${ECHO} "${DIGEST_ALGORITHM} ($$sumfile) = `${SED} -e '/\$$NetBSD.*/d' $$sumfile | ${DIGEST} ${DIGEST_ALGORITHM}`" >> $$newfile;; \
+				*)	${ECHO} "${PATCH_DIGEST_ALGORITHM} ($$sumfile) = `${SED} -e '/\$$NetBSD.*/d' $$sumfile | ${DIGEST} ${PATCH_DIGEST_ALGORITHM}`" >> $$newfile;; \
 			esac;						\
 		done);							\
 	fi;								\
@@ -3758,23 +3765,25 @@
 		  for file in "" ${_CKSUMFILES}; do			\
 		  	if [ "X$$file" = X"" ]; then continue; fi; 	\
 			alg=`${AWK} 'NF == 4 && $$2 == "('$$file')" && $$3 == "=" {print $$1;}' ${DISTINFO_FILE}`; \
-			if [ "X$$alg" = "X" ]; then			\
-				${ECHO_MSG} "=> No checksum recorded for $$file."; \
-				OK="false";				\
-			else						\
-				CKSUM=`${DIGEST} $$alg < $$file`;	\
-				CKSUM2=`${AWK} '$$1 == "'$$alg'" && $$2 == "('$$file')"{print $$4;}' ${DISTINFO_FILE}`; \
-				if [ "$$CKSUM2" = "IGNORE" ]; then	\
-					${ECHO_MSG} "=> Checksum for $$file is set to IGNORE in checksum file even though"; \
-					${ECHO_MSG} "   the file is not in the "'$$'"{IGNOREFILES} list."; \
+			for a in $$alg; do				\
+				if [ "X$$alg" = "X" ]; then		\
+					${ECHO_MSG} "=> No checksum recorded for $$file."; \
 					OK="false";			\
-				elif [ "$$CKSUM" = "$$CKSUM2" ]; then	\
-					${ECHO_MSG} "=> Checksum OK for $$file."; \
 				else					\
-					${ECHO_MSG} "=> Checksum mismatch for $$file."; \
-					OK="false";			\
+					CKSUM=`${DIGEST} $$a < $$file`;	\
+					CKSUM2=`${AWK} '$$1 == "'$$a'" && $$2 == "('$$file')"{print $$4;}' ${DISTINFO_FILE}`; \
+					if [ "$$CKSUM2" = "IGNORE" ]; then \
+						${ECHO_MSG} "=> Checksum for $$file is set to IGNORE in checksum file even though"; \
+						${ECHO_MSG} "   the file is not in the "'$$'"{IGNOREFILES} list."; \
+						OK="false";		\
+					elif [ "$$CKSUM" = "$$CKSUM2" ]; then	\
+						${ECHO_MSG} "=> Checksum $$a OK for $$file."; \
+					else				\
+						${ECHO_MSG} "=> Checksum $$a mismatch for $$file."; \
+						OK="false";		\
+					fi;				\
 				fi;					\
-			fi;						\
+			done;						\
 		  done;							\
 		  for file in "" ${_IGNOREFILES}; do			\
 		  	if [ "X$$file" = X"" ]; then continue; fi; 	\

--Dxnq1zWXvFF0Q93v--