This a quick hack to get some feedback regarding this change: Use
OpenSSL crypto library for hashing instead of libmd.
OpenSSL provides a slightly assembly optimized version for amd64 while
libmd is pure C. This passes the testsuite and I was able to perform an
upgrade so it can't be that bad ;) If I read this right, the checksum is
computed during package installation.
Would it be acceptable to to switch it?

While at it, why do we use md5? I'm asking because a small upgrade to
sha1 would improve the performance since sha1 performs better on
architectures that provide optimisation for it which includes a lot.
_If_ we are changing things here then we could decide if something like
checksum (e.g. xxhash) is enough to catch a bitflip or if a
cryptographic checksum is really required.

I don't know _why_ we have it: The .deb file was verified by apt after
the download, the decompressor has also a checksum.
The md5sum file isn't signed in any way, so whoever modified the binary
in the system could update md5sum file in case it is verified later.

Signed-off-by: Sebastian Andrzej Siewior <[email protected]>
---
 configure.ac      |   6 ++-
 debian/control    |   3 +-
 lib/dpkg/buffer.c | 110 ++++++++++++++++++++++++++++++++++++++++------
 3 files changed, 103 insertions(+), 16 deletions(-)

diff --git a/configure.ac b/configure.ac
index afc6d2bf7e0bc..72458d50586b8 100644
--- a/configure.ac
+++ b/configure.ac
@@ -96,7 +96,11 @@ AC_SYS_LARGEFILE
 
 # Checks for libraries.
 DPKG_LIB_RT
-DPKG_LIB_MD
+#DPKG_LIB_MD
+AC_ARG_VAR([MD_LIBS], [linker flags for md library])
+MD_LIBS=-lcrypto
+have_libmd=openssl
+AC_SEARCH_LIBS([EVP_MD_fetch], [crypto])
 DPKG_LIB_Z
 DPKG_LIB_BZ2
 DPKG_LIB_LZMA
diff --git a/debian/control b/debian/control
index d1b304546ef45..6fd7c29387bd2 100644
--- a/debian/control
+++ b/debian/control
@@ -16,7 +16,8 @@ Rules-Requires-Root: no
  gettext (>= 0.19.7),
 # Version needed for --porefs defaults, conditional addenda and mode=eof.
  po4a (>= 0.59),
- libmd-dev,
+# libmd-dev,
+ libssl-dev,
  zlib1g-dev,
  libbz2-dev,
 # Version needed for multi-threaded decompressor support.
diff --git a/lib/dpkg/buffer.c b/lib/dpkg/buffer.c
index ed05f4b4ab5cb..213268699bbd5 100644
--- a/lib/dpkg/buffer.c
+++ b/lib/dpkg/buffer.c
@@ -26,7 +26,6 @@
 #include <sys/types.h>
 
 #include <errno.h>
-#include <md5.h>
 #include <string.h>
 #include <unistd.h>
 #include <stdlib.h>
@@ -37,6 +36,13 @@
 #include <dpkg/fdio.h>
 #include <dpkg/buffer.h>
 
+#ifdef USE_LIB_MD
+#include <md5.h>
+#else
+#include <openssl/evp.h>
+#endif
+
+#ifdef USE_LIB_MD
 struct buffer_md5_ctx {
        MD5_CTX ctx;
        char *hash;
@@ -53,19 +59,6 @@ buffer_md5_init(struct buffer_data *data)
        MD5Init(&ctx->ctx);
 }
 
-static off_t
-buffer_digest_init(struct buffer_data *data)
-{
-       switch (data->type) {
-       case BUFFER_DIGEST_NULL:
-               break;
-       case BUFFER_DIGEST_MD5:
-               buffer_md5_init(data);
-               break;
-       }
-       return 0;
-}
-
 static off_t
 buffer_digest_update(struct buffer_data *digest, const void *buf, off_t length)
 {
@@ -104,6 +97,95 @@ buffer_md5_done(struct buffer_data *data)
        free(ctx);
 }
 
+
+#else
+struct buffer_md5_ctx {
+       EVP_MD_CTX *ctx;
+       char *hash;
+};
+
+static void
+buffer_md5_init(struct buffer_data *data)
+{
+       struct buffer_md5_ctx *ctx;
+       static EVP_MD *md_md5;
+
+       if (!md_md5) {
+               md_md5 = EVP_MD_fetch(NULL, "md5", NULL);
+               if (!md_md5)
+                       internerr("EVP_MD_fetch() failed.");
+       }
+       ctx = m_malloc(sizeof(*ctx));
+
+       ctx->ctx = EVP_MD_CTX_new();
+       if (ctx->ctx== NULL)
+               internerr("EVP_MD_CTX_new() failed.");
+
+       if (!EVP_DigestInit_ex(ctx->ctx, md_md5, NULL))
+               internerr("EVP_DigestInit_ex() failed.");
+
+       ctx->hash = data->arg.ptr;
+       data->arg.ptr = ctx;
+}
+
+static off_t
+buffer_digest_update(struct buffer_data *digest, const void *buf, off_t length)
+{
+       off_t ret = length;
+
+       switch (digest->type) {
+       case BUFFER_DIGEST_NULL:
+               break;
+       case BUFFER_DIGEST_MD5:
+               if (!EVP_DigestUpdate(((struct buffer_md5_ctx 
*)digest->arg.ptr)->ctx,
+                                     buf, length))
+                       internerr("Digest update failed %i", digest->type);
+               break;
+       default:
+               internerr("unknown data type %i", digest->type);
+       }
+
+       return ret;
+}
+
+static void
+buffer_md5_done(struct buffer_data *data)
+{
+       struct buffer_md5_ctx *ctx;
+       unsigned char digest[16], *p = digest;
+       char *hash;
+       int i;
+
+       ctx = (struct buffer_md5_ctx *)data->arg.ptr;
+       hash = ctx->hash;
+       if (!EVP_DigestFinal_ex(ctx->ctx, digest, NULL))
+               internerr("EVP_DigestFinal_ex() failed.");
+
+       for (i = 0; i < 16; ++i) {
+               sprintf(hash, "%02x", *p++);
+               hash += 2;
+       }
+       *hash = '\0';
+       EVP_MD_CTX_free(ctx->ctx);
+       free(ctx);
+}
+
+
+#endif
+
+static off_t
+buffer_digest_init(struct buffer_data *data)
+{
+       switch (data->type) {
+       case BUFFER_DIGEST_NULL:
+               break;
+       case BUFFER_DIGEST_MD5:
+               buffer_md5_init(data);
+               break;
+       }
+       return 0;
+}
+
 static off_t
 buffer_digest_done(struct buffer_data *data)
 {
-- 
2.40.1

Reply via email to