[vlc-devel] [PATCH 1/4] src: replace MD5 implementation with BearSSLs one

Marvin Scholz epirat07 at gmail.com
Thu Jul 23 15:03:44 CEST 2020


Sorry, forgot rationale for the change, added locally:

The BearSSL implementation is a bit more readable than
the old one and it will make it easier to add BearSSLs
SHA1 after that, as both share common helper functions.

On 23 Jul 2020, at 14:51, Marvin Scholz wrote:

> ---
>  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