[pacman-dev] [PATCH 2/3] Use OpenSSL MD5 crypto functions if available

Dan McGee dan at archlinux.org
Thu Sep 2 13:30:53 EDT 2010


I've noticed my Atom-powered laptop is dog-slow when doing integrity checks
on packages, and it turns out our MD5 implementation isn't near as good as
that provided by OpenSSL. Using their routines instead provided anywhere
from a 1.4x up to a 1.8x performance benefit over our built-in MD5 function.

This does not remove the MD5 code from our codebase, but it does enable
linking against OpenSSL to get their much faster implementation if it is
available on whatever platform you are using. At configure-time, we will
default to using it if it is available, but this can be easily changed by
using the `--with-openssl` or `--without-openssl` arguments to configure.

Signed-off-by: Dan McGee <dan at archlinux.org>
---
 configure.ac            |   19 ++++++++++++++++++-
 lib/libalpm/Makefile.am |    6 +++++-
 lib/libalpm/util.c      |   44 +++++++++++++++++++++++++++++++++++++++++++-
 3 files changed, 66 insertions(+), 3 deletions(-)

diff --git a/configure.ac b/configure.ac
index b845f9c..e0aafba 100644
--- a/configure.ac
+++ b/configure.ac
@@ -70,7 +70,7 @@ AC_DEFINE_UNQUOTED([LIB_VERSION], ["$LIB_VERSION"], [libalpm version number])
 
 # Help line for root directory
 AC_ARG_WITH(root-dir,
-	AS_HELP_STRING([--with-root-dir=path], [set the location of pacman's root operating directory]),
+	AS_HELP_STRING([--with-root-dir=path], [set the location of the root operating directory]),
 	[ROOTDIR=$withval], [ROOTDIR=/])
 
 # Help line for package extension
@@ -88,6 +88,11 @@ AC_ARG_WITH(buildscript,
 	AS_HELP_STRING([--with-buildscript=name], [set the build script name used by makepkg]),
 	[BUILDSCRIPT=$withval], [BUILDSCRIPT=PKGBUILD])
 
+# Help line for using OpenSSL
+AC_ARG_WITH(openssl,
+	AS_HELP_STRING([--with-openssl], [use OpenSSL crypto implementations instead of internal routines]),
+	[], [with_openssl=check])
+
 # Help line for libfetch
 AC_ARG_ENABLE(internal-download,
 	AS_HELP_STRING([--disable-internal-download], [do not build with libfetch support]),
@@ -131,6 +136,18 @@ AM_GNU_GETTEXT_VERSION(0.13.1)
 AC_CHECK_LIB([archive], [archive_read_data], ,
 	AC_MSG_ERROR([libarchive is needed to compile pacman!]))
 
+# Check for OpenSSL
+AC_MSG_CHECKING(whether to link with libssl)
+AS_IF([test "x$with_openssl" != "xno"],
+	[AC_MSG_RESULT(yes)
+	AC_CHECK_LIB([ssl], [MD5_Final], ,
+	[if test "x$with_openssl" != "xcheck"; then
+		AC_MSG_FAILURE([--with-openssl was given, but -lssl was not found])
+	fi],
+	[-lcrypto])],
+	AC_MSG_RESULT(no))
+AM_CONDITIONAL([HAVE_LIBSSL], [test "x$ac_cv_lib_ssl_MD5_Final" = "xyes"])
+
 # Enable or disable usage of libfetch
 AC_MSG_CHECKING(whether to link with libfetch)
 if test "x$internaldownload" = "xyes" ; then
diff --git a/lib/libalpm/Makefile.am b/lib/libalpm/Makefile.am
index 3473a73..e136b54 100644
--- a/lib/libalpm/Makefile.am
+++ b/lib/libalpm/Makefile.am
@@ -38,7 +38,6 @@ libalpm_la_SOURCES = \
 	group.h group.c \
 	handle.h handle.c \
 	log.h log.c \
-	md5.h md5.c \
 	package.h package.c \
 	remove.h remove.c \
 	sync.h sync.c \
@@ -46,6 +45,11 @@ libalpm_la_SOURCES = \
 	util.h util.c \
 	version.c
 
+if !HAVE_LIBSSL
+libalpm_la_SOURCES += \
+	md5.h md5.c
+endif
+
 libalpm_la_LDFLAGS = -no-undefined -version-info $(LIB_VERSION_INFO)
 libalpm_la_LIBADD = $(LTLIBINTL)
 
diff --git a/lib/libalpm/util.c b/lib/libalpm/util.c
index 8a1f392..5bf4ef1 100644
--- a/lib/libalpm/util.c
+++ b/lib/libalpm/util.c
@@ -43,13 +43,18 @@
 #include <archive.h>
 #include <archive_entry.h>
 
+#ifdef HAVE_LIBSSL
+#include <openssl/md5.h>
+#else
+#include "md5.h"
+#endif
+
 /* libalpm */
 #include "util.h"
 #include "log.h"
 #include "package.h"
 #include "alpm.h"
 #include "alpm_list.h"
-#include "md5.h"
 #include "handle.h"
 
 #ifndef HAVE_STRSEP
@@ -676,6 +681,42 @@ int _alpm_lstat(const char *path, struct stat *buf)
 	return(ret);
 }
 
+#ifdef HAVE_LIBSSL
+static int md5_file(const char *path, unsigned char output[16])
+{
+    FILE *f;
+    size_t n;
+    MD5_CTX ctx;
+    unsigned char *buf;
+
+		CALLOC(buf, 8192, sizeof(unsigned char), return(1));
+
+    if((f = fopen(path, "rb")) == NULL) {
+        free(buf);
+        return(1);
+    }
+
+    MD5_Init(&ctx);
+
+    while((n = fread(buf, 1, sizeof(buf), f)) > 0) {
+        MD5_Update(&ctx, buf, n);
+		}
+
+    MD5_Final(output, &ctx);
+
+    memset(&ctx, 0, sizeof(MD5_CTX));
+    free(buf);
+
+    if(ferror(f) != 0) {
+        fclose(f);
+        return(2);
+    }
+
+    fclose(f);
+    return(0);
+}
+#endif
+
 /** Get the md5 sum of file.
  * @param filename name of the file
  * @return the checksum on success, NULL on error
@@ -693,6 +734,7 @@ char SYMEXPORT *alpm_compute_md5sum(const char *filename)
 
 	/* allocate 32 chars plus 1 for null */
 	md5sum = calloc(33, sizeof(char));
+	/* defined above for OpenSSL, otherwise defined in md5.h */
 	ret = md5_file(filename, output);
 
 	if (ret > 0) {
-- 
1.7.2.2



More information about the pacman-dev mailing list