[vlc-devel] [PATCH 1/4] src: replace MD5 implementation with BearSSLs one
Marvin Scholz
epirat07 at gmail.com
Thu Jul 23 14:51:56 CEST 2020
---
include/vlc_hash.h | 11 +-
src/misc/md5.c | 479 ++++++++++++++++++---------------------------
2 files changed, 194 insertions(+), 296 deletions(-)
diff --git a/include/vlc_hash.h b/include/vlc_hash.h
index 0a853d5ad3..fae6125735 100644
--- a/include/vlc_hash.h
+++ b/include/vlc_hash.h
@@ -83,11 +83,10 @@
*/
typedef struct vlc_hash_md5_ctx
{
- struct md5_s {
- uint32_t A, B, C, D; /* chaining variables */
- uint32_t nblocks;
- uint8_t buf[64];
- int count;
+ struct {
+ unsigned char buf[64];
+ uint64_t count;
+ uint32_t val[4];
} priv; /**< \internal Private */
} vlc_hash_md5_t;
@@ -136,7 +135,7 @@ VLC_API void vlc_hash_md5_Update(vlc_hash_md5_t *ctx, const void *data, size_t s
* \param[out] output Output buffer to write to
* \param size Output buffer size
*/
-VLC_API void vlc_hash_md5_Finish(vlc_hash_md5_t *ctx, void *output, size_t size);
+VLC_API void vlc_hash_md5_Finish(const vlc_hash_md5_t *ctx, void *output, size_t size);
/**
* @}
diff --git a/src/misc/md5.c b/src/misc/md5.c
index 68657a4f0a..f5678ac6e9 100644
--- a/src/misc/md5.c
+++ b/src/misc/md5.c
@@ -1,30 +1,34 @@
-/*****************************************************************************
- * md5.c: not so strong MD5 hashing
- *****************************************************************************
- * Copyright (C) 1995,1996,1998,1999,2001,2002,
- * 2003 Free Software Foundation, Inc.
+/**
+ * MD5 hashing implementation
+ * \file md5.h
+ */
+
+/*
+ * Nearly all of this code was copied from BearSSL and adapted to
+ * VLCs usecase and API.
*
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU Lesser General Public License as published by
- * the Free Software Foundation; either version 2.1 of the License, or
- * (at your option) any later version.
*
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU Lesser General Public License for more details.
+ * Copyright (c) 2016 Thomas Pornin <pornin at bolet.org>
*
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
- *****************************************************************************/
-
-/* md5.c - MD5 Message-Digest Algorithm
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
*
- * According to the definition of MD5 in RFC 1321 from April 1992.
- * NOTE: This is *not* the same file as the one from glibc.
- * Written by Ulrich Drepper <drepper at gnu.ai.mit.edu>, 1995.
- * heavily modified for GnuPG by Werner Koch <wk at gnupg.org>
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
*/
/* Test values:
@@ -45,309 +49,204 @@
#include <vlc_common.h>
#include <vlc_hash.h>
-typedef uint32_t u32;
-typedef uint8_t byte;
-#define rol(x,n) ( ((x) << (n)) | ((x) >> (32-(n))) )
+/* Begin common helpers */
-typedef struct md5_s MD5_CONTEXT;
+static inline uint32_t
+br_dec32le(const void *src)
+{
+ const unsigned char *buf;
+ buf = src;
+ return (uint32_t)buf[0]
+ | ((uint32_t)buf[1] << 8)
+ | ((uint32_t)buf[2] << 16)
+ | ((uint32_t)buf[3] << 24);
+}
static void
-md5_init( void *context )
+br_range_dec32le(uint32_t *v, size_t num, const void *src)
{
- MD5_CONTEXT *ctx = context;
-
- ctx->A = 0x67452301;
- ctx->B = 0xefcdab89;
- ctx->C = 0x98badcfe;
- ctx->D = 0x10325476;
+ const unsigned char *buf;
- ctx->nblocks = 0;
- ctx->count = 0;
+ buf = src;
+ while (num -- > 0) {
+ *v ++ = br_dec32le(buf);
+ buf += 4;
+ }
}
+static inline void
+br_enc32le(void *dst, uint32_t x)
+{
+ unsigned char *buf;
-/* These are the four functions used in the four steps of the MD5 algorithm
- and defined in the RFC 1321. The first function is a little bit optimized
- (as found in Colin Plumbs public domain implementation). */
-/* #define FF(b, c, d) ((b & c) | (~b & d)) */
-#define FF(b, c, d) (d ^ (b & (c ^ d)))
-#define FG(b, c, d) FF (d, b, c)
-#define FH(b, c, d) (b ^ c ^ d)
-#define FI(b, c, d) (c ^ (b | ~d))
-
+ buf = dst;
+ buf[0] = (unsigned char)x;
+ buf[1] = (unsigned char)(x >> 8);
+ buf[2] = (unsigned char)(x >> 16);
+ buf[3] = (unsigned char)(x >> 24);
+}
-/****************
- * transform n*64 bytes
- */
static void
-transform ( MD5_CONTEXT *ctx, const unsigned char *data )
+br_range_enc32le(void *dst, const uint32_t *v, size_t num)
{
- u32 correct_words[16];
- register u32 A = ctx->A;
- register u32 B = ctx->B;
- register u32 C = ctx->C;
- register u32 D = ctx->D;
- u32 *cwp = correct_words;
-
-#ifdef WORDS_BIGENDIAN
- {
- int i;
- byte *p2, *p1;
- for(i=0, p1=data, p2=(byte*)correct_words; i < 16; i++, p2 += 4 )
- {
- p2[3] = *p1++;
- p2[2] = *p1++;
- p2[1] = *p1++;
- p2[0] = *p1++;
- }
- }
-#else
- memcpy( correct_words, data, 64 );
-#endif
+ unsigned char *buf;
+
+ buf = dst;
+ while (num -- > 0) {
+ br_enc32le(buf, *v ++);
+ buf += 4;
+ }
+}
+static inline void
+br_enc64le(void *dst, uint64_t x)
+{
+ unsigned char *buf;
-#define OP(a, b, c, d, s, T) \
- do \
- { \
- a += FF (b, c, d) + (*cwp++) + T; \
- a = rol(a, s); \
- a += b; \
- } \
- while (0)
-
- /* Before we start, one word about the strange constants.
- They are defined in RFC 1321 as
-
- T[i] = (int) (4294967296.0 * fabs (sin (i))), i=1..64
- */
-
- /* Round 1. */
- OP (A, B, C, D, 7, 0xd76aa478);
- OP (D, A, B, C, 12, 0xe8c7b756);
- OP (C, D, A, B, 17, 0x242070db);
- OP (B, C, D, A, 22, 0xc1bdceee);
- OP (A, B, C, D, 7, 0xf57c0faf);
- OP (D, A, B, C, 12, 0x4787c62a);
- OP (C, D, A, B, 17, 0xa8304613);
- OP (B, C, D, A, 22, 0xfd469501);
- OP (A, B, C, D, 7, 0x698098d8);
- OP (D, A, B, C, 12, 0x8b44f7af);
- OP (C, D, A, B, 17, 0xffff5bb1);
- OP (B, C, D, A, 22, 0x895cd7be);
- OP (A, B, C, D, 7, 0x6b901122);
- OP (D, A, B, C, 12, 0xfd987193);
- OP (C, D, A, B, 17, 0xa679438e);
- OP (B, C, D, A, 22, 0x49b40821);
-
-#undef OP
-#define OP(f, a, b, c, d, k, s, T) \
- do \
- { \
- a += f (b, c, d) + correct_words[k] + T; \
- a = rol(a, s); \
- a += b; \
- } \
- while (0)
-
- /* Round 2. */
- OP (FG, A, B, C, D, 1, 5, 0xf61e2562);
- OP (FG, D, A, B, C, 6, 9, 0xc040b340);
- OP (FG, C, D, A, B, 11, 14, 0x265e5a51);
- OP (FG, B, C, D, A, 0, 20, 0xe9b6c7aa);
- OP (FG, A, B, C, D, 5, 5, 0xd62f105d);
- OP (FG, D, A, B, C, 10, 9, 0x02441453);
- OP (FG, C, D, A, B, 15, 14, 0xd8a1e681);
- OP (FG, B, C, D, A, 4, 20, 0xe7d3fbc8);
- OP (FG, A, B, C, D, 9, 5, 0x21e1cde6);
- OP (FG, D, A, B, C, 14, 9, 0xc33707d6);
- OP (FG, C, D, A, B, 3, 14, 0xf4d50d87);
- OP (FG, B, C, D, A, 8, 20, 0x455a14ed);
- OP (FG, A, B, C, D, 13, 5, 0xa9e3e905);
- OP (FG, D, A, B, C, 2, 9, 0xfcefa3f8);
- OP (FG, C, D, A, B, 7, 14, 0x676f02d9);
- OP (FG, B, C, D, A, 12, 20, 0x8d2a4c8a);
-
- /* Round 3. */
- OP (FH, A, B, C, D, 5, 4, 0xfffa3942);
- OP (FH, D, A, B, C, 8, 11, 0x8771f681);
- OP (FH, C, D, A, B, 11, 16, 0x6d9d6122);
- OP (FH, B, C, D, A, 14, 23, 0xfde5380c);
- OP (FH, A, B, C, D, 1, 4, 0xa4beea44);
- OP (FH, D, A, B, C, 4, 11, 0x4bdecfa9);
- OP (FH, C, D, A, B, 7, 16, 0xf6bb4b60);
- OP (FH, B, C, D, A, 10, 23, 0xbebfbc70);
- OP (FH, A, B, C, D, 13, 4, 0x289b7ec6);
- OP (FH, D, A, B, C, 0, 11, 0xeaa127fa);
- OP (FH, C, D, A, B, 3, 16, 0xd4ef3085);
- OP (FH, B, C, D, A, 6, 23, 0x04881d05);
- OP (FH, A, B, C, D, 9, 4, 0xd9d4d039);
- OP (FH, D, A, B, C, 12, 11, 0xe6db99e5);
- OP (FH, C, D, A, B, 15, 16, 0x1fa27cf8);
- OP (FH, B, C, D, A, 2, 23, 0xc4ac5665);
-
- /* Round 4. */
- OP (FI, A, B, C, D, 0, 6, 0xf4292244);
- OP (FI, D, A, B, C, 7, 10, 0x432aff97);
- OP (FI, C, D, A, B, 14, 15, 0xab9423a7);
- OP (FI, B, C, D, A, 5, 21, 0xfc93a039);
- OP (FI, A, B, C, D, 12, 6, 0x655b59c3);
- OP (FI, D, A, B, C, 3, 10, 0x8f0ccc92);
- OP (FI, C, D, A, B, 10, 15, 0xffeff47d);
- OP (FI, B, C, D, A, 1, 21, 0x85845dd1);
- OP (FI, A, B, C, D, 8, 6, 0x6fa87e4f);
- OP (FI, D, A, B, C, 15, 10, 0xfe2ce6e0);
- OP (FI, C, D, A, B, 6, 15, 0xa3014314);
- OP (FI, B, C, D, A, 13, 21, 0x4e0811a1);
- OP (FI, A, B, C, D, 4, 6, 0xf7537e82);
- OP (FI, D, A, B, C, 11, 10, 0xbd3af235);
- OP (FI, C, D, A, B, 2, 15, 0x2ad7d2bb);
- OP (FI, B, C, D, A, 9, 21, 0xeb86d391);
-
- /* Put checksum in context given as argument. */
- ctx->A += A;
- ctx->B += B;
- ctx->C += C;
- ctx->D += D;
+ buf = dst;
+ br_enc32le(buf, (uint32_t)x);
+ br_enc32le(buf + 4, (uint32_t)(x >> 32));
}
+/* End common helpers */
+#define F(B, C, D) ((((C) ^ (D)) & (B)) ^ (D))
+#define G(B, C, D) ((((C) ^ (B)) & (D)) ^ (C))
+#define H(B, C, D) ((B) ^ (C) ^ (D))
+#define I(B, C, D) ((C) ^ ((B) | ~(D)))
-/* The routine updates the message-digest context to
- * account for the presence of each of the characters inBuf[0..inLen-1]
- * in the message whose digest is being computed.
- */
-static void
-md5_write( void *context, const void *inbuf_arg , size_t inlen)
-{
- const unsigned char *inbuf = inbuf_arg;
- MD5_CONTEXT *hd = context;
-
- if( hd->count == 64 ) /* flush the buffer */
- {
- transform( hd, hd->buf );
- hd->count = 0;
- hd->nblocks++;
- }
- if( !inbuf )
- return;
-
- if( hd->count )
- {
- for( ; inlen && hd->count < 64; inlen-- )
- hd->buf[hd->count++] = *inbuf++;
- md5_write( hd, NULL, 0 );
- if( !inlen )
- return;
- }
+#define ROTL(x, n) (((x) << (n)) | ((x) >> (32 - (n))))
- while( inlen >= 64 )
- {
- transform( hd, inbuf );
- hd->count = 0;
- hd->nblocks++;
- inlen -= 64;
- inbuf += 64;
- }
- for( ; inlen && hd->count < 64; inlen-- )
- hd->buf[hd->count++] = *inbuf++;
+const uint32_t br_md5_IV[4] = {
+ 0x67452301, 0xEFCDAB89, 0x98BADCFE, 0x10325476
+};
-}
+static const uint32_t K[64] = {
+ 0xD76AA478, 0xE8C7B756, 0x242070DB, 0xC1BDCEEE,
+ 0xF57C0FAF, 0x4787C62A, 0xA8304613, 0xFD469501,
+ 0x698098D8, 0x8B44F7AF, 0xFFFF5BB1, 0x895CD7BE,
+ 0x6B901122, 0xFD987193, 0xA679438E, 0x49B40821,
+ 0xF61E2562, 0xC040B340, 0x265E5A51, 0xE9B6C7AA,
+ 0xD62F105D, 0x02441453, 0xD8A1E681, 0xE7D3FBC8,
+ 0x21E1CDE6, 0xC33707D6, 0xF4D50D87, 0x455A14ED,
+ 0xA9E3E905, 0xFCEFA3F8, 0x676F02D9, 0x8D2A4C8A,
+ 0xFFFA3942, 0x8771F681, 0x6D9D6122, 0xFDE5380C,
+ 0xA4BEEA44, 0x4BDECFA9, 0xF6BB4B60, 0xBEBFBC70,
+ 0x289B7EC6, 0xEAA127FA, 0xD4EF3085, 0x04881D05,
+ 0xD9D4D039, 0xE6DB99E5, 0x1FA27CF8, 0xC4AC5665,
-/* The routine final terminates the message-digest computation and
- * ends with the desired message digest in mdContext->digest[0...15].
- * The handle is prepared for a new MD5 cycle.
- * Returns 16 bytes representing the digest.
- */
+ 0xF4292244, 0x432AFF97, 0xAB9423A7, 0xFC93A039,
+ 0x655B59C3, 0x8F0CCC92, 0xFFEFF47D, 0x85845DD1,
+ 0x6FA87E4F, 0xFE2CE6E0, 0xA3014314, 0x4E0811A1,
+ 0xF7537E82, 0xBD3AF235, 0x2AD7D2BB, 0xEB86D391
+};
+
+static const unsigned char MP[48] = {
+ 1, 6, 11, 0, 5, 10, 15, 4, 9, 14, 3, 8, 13, 2, 7, 12,
+ 5, 8, 11, 14, 1, 4, 7, 10, 13, 0, 3, 6, 9, 12, 15, 2,
+ 0, 7, 14, 5, 12, 3, 10, 1, 8, 15, 6, 13, 4, 11, 2, 9
+};
static void
-md5_final( void *context)
+br_md5_round(const unsigned char *buf, uint32_t *val)
{
- MD5_CONTEXT *hd = context;
- u32 t, msb, lsb;
- byte *p;
-
- md5_write(hd, NULL, 0); /* flush */;
-
- t = hd->nblocks;
- /* multiply by 64 to make a byte count */
- lsb = t << 6;
- msb = t >> 26;
- /* add the count */
- t = lsb;
- if( (lsb += hd->count) < t )
- msb++;
- /* multiply by 8 to make a bit count */
- t = lsb;
- lsb <<= 3;
- msb <<= 3;
- msb |= t >> 29;
-
- if( hd->count < 56 ) /* enough room */
- {
- hd->buf[hd->count++] = 0x80; /* pad */
- while( hd->count < 56 )
- hd->buf[hd->count++] = 0; /* pad */
+ uint32_t m[16];
+ uint32_t a, b, c, d;
+ int i;
+
+ a = val[0];
+ b = val[1];
+ c = val[2];
+ d = val[3];
+
+ br_range_dec32le(m, 16, buf);
+
+ for (i = 0; i < 16; i += 4) {
+ a = b + ROTL(a + F(b, c, d) + m[i + 0] + K[i + 0], 7);
+ d = a + ROTL(d + F(a, b, c) + m[i + 1] + K[i + 1], 12);
+ c = d + ROTL(c + F(d, a, b) + m[i + 2] + K[i + 2], 17);
+ b = c + ROTL(b + F(c, d, a) + m[i + 3] + K[i + 3], 22);
}
- else /* need one extra block */
- {
- hd->buf[hd->count++] = 0x80; /* pad character */
- while( hd->count < 64 )
- hd->buf[hd->count++] = 0;
- md5_write(hd, NULL, 0); /* flush */;
- memset(hd->buf, 0, 56 ); /* fill next block with zeroes */
+ for (i = 16; i < 32; i += 4) {
+ a = b + ROTL(a + G(b, c, d) + m[MP[i - 16]] + K[i + 0], 5);
+ d = a + ROTL(d + G(a, b, c) + m[MP[i - 15]] + K[i + 1], 9);
+ c = d + ROTL(c + G(d, a, b) + m[MP[i - 14]] + K[i + 2], 14);
+ b = c + ROTL(b + G(c, d, a) + m[MP[i - 13]] + K[i + 3], 20);
+ }
+ for (i = 32; i < 48; i += 4) {
+ a = b + ROTL(a + H(b, c, d) + m[MP[i - 16]] + K[i + 0], 4);
+ d = a + ROTL(d + H(a, b, c) + m[MP[i - 15]] + K[i + 1], 11);
+ c = d + ROTL(c + H(d, a, b) + m[MP[i - 14]] + K[i + 2], 16);
+ b = c + ROTL(b + H(c, d, a) + m[MP[i - 13]] + K[i + 3], 23);
+ }
+ for (i = 48; i < 64; i += 4) {
+ a = b + ROTL(a + I(b, c, d) + m[MP[i - 16]] + K[i + 0], 6);
+ d = a + ROTL(d + I(a, b, c) + m[MP[i - 15]] + K[i + 1], 10);
+ c = d + ROTL(c + I(d, a, b) + m[MP[i - 14]] + K[i + 2], 15);
+ b = c + ROTL(b + I(c, d, a) + m[MP[i - 13]] + K[i + 3], 21);
}
- /* append the 64 bit count */
- hd->buf[56] = lsb ;
- hd->buf[57] = lsb >> 8;
- hd->buf[58] = lsb >> 16;
- hd->buf[59] = lsb >> 24;
- hd->buf[60] = msb ;
- hd->buf[61] = msb >> 8;
- hd->buf[62] = msb >> 16;
- hd->buf[63] = msb >> 24;
- transform( hd, hd->buf );
-
- p = hd->buf;
-#ifdef WORDS_BIGENDIAN
-#define X(a) do { *p++ = hd->a ; *p++ = hd->a >> 8; \
- *p++ = hd->a >> 16; *p++ = hd->a >> 24; } while(0)
-#else /* little endian */
-#define X(a) do { *(u32*)p = (*hd).a ; p += 4; } while(0)
-#endif
- X(A);
- X(B);
- X(C);
- X(D);
-#undef X
-
-}
-#if 0
-static byte *
-md5_read( void *context )
-{
- MD5_CONTEXT *hd = (MD5_CONTEXT *) context;
- return hd->buf;
+ val[0] += a;
+ val[1] += b;
+ val[2] += c;
+ val[3] += d;
}
-#endif
-/* Public API */
-void vlc_hash_md5_Init(vlc_hash_md5_t *ctx)
+void vlc_hash_md5_Init(vlc_hash_md5_t *c)
{
- md5_init(&ctx->priv);
+ memcpy(c->priv.val, br_md5_IV, sizeof c->priv.val);
+ c->priv.count = 0;
}
-void vlc_hash_md5_Update(vlc_hash_md5_t *ctx, const void *data, size_t length)
+void vlc_hash_md5_Update(vlc_hash_md5_t *c, const void *data, size_t len)
{
- md5_write(&ctx->priv, data, length);
+ const unsigned char *buf;
+ size_t ptr;
+
+ buf = data;
+ ptr = (size_t)c->priv.count & 63;
+ while (len > 0) {
+ size_t clen;
+
+ clen = 64 - ptr;
+ if (clen > len) {
+ clen = len;
+ }
+ memcpy(c->priv.buf + ptr, buf, clen);
+ ptr += clen;
+ buf += clen;
+ len -= clen;
+ c->priv.count += (uint64_t)clen;
+ if (ptr == 64) {
+ br_md5_round(c->priv.buf, c->priv.val);
+ ptr = 0;
+ }
+ }
}
-void vlc_hash_md5_Finish(vlc_hash_md5_t *ctx, void *output, size_t size)
+void vlc_hash_md5_Finish(const vlc_hash_md5_t *c, void *dst, size_t len)
{
- assert(size >= VLC_HASH_MD5_DIGEST_SIZE);
- md5_final(&ctx->priv);
- memcpy(output, ctx->priv.buf, VLC_HASH_MD5_DIGEST_SIZE);
+ unsigned char buf[64];
+ uint32_t val[4];
+ size_t ptr;
+
+ assert(len >= VLC_HASH_MD5_DIGEST_SIZE);
+
+ ptr = (size_t)c->priv.count & 63;
+ memcpy(buf, c->priv.buf, ptr);
+ memcpy(val, c->priv.val, sizeof val);
+ buf[ptr ++] = 0x80;
+ if (ptr > 56) {
+ memset(buf + ptr, 0, 64 - ptr);
+ br_md5_round(buf, val);
+ memset(buf, 0, 56);
+ } else {
+ memset(buf + ptr, 0, 56 - ptr);
+ }
+ br_enc64le(buf + 56, c->priv.count << 3);
+ br_md5_round(buf, val);
+ br_range_enc32le(dst, val, 4);
}
--
2.24.3 (Apple Git-128)
More information about the vlc-devel
mailing list