[PATCH] libdpkg: Use OpenSSL for hashing.
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 <sebastian@breakpoint.cc>
---
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 to: