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

