LCOV - code coverage report
Current view: top level - port - cpl_md5.cpp (source / functions) Hit Total Coverage
Test: gdal_filtered.info Lines: 147 151 97.4 %
Date: 2024-04-29 01:40:10 Functions: 7 7 100.0 %

          Line data    Source code
       1             : /*
       2             :  * This code implements the MD5 message-digest algorithm.
       3             :  * The algorithm is due to Ron Rivest.  This code was
       4             :  * written by Colin Plumb in 1993, no copyright is claimed.
       5             :  * This code is in the public domain; do with it what you wish.
       6             :  *
       7             :  * Equivalent code is available from RSA Data Security, Inc.
       8             :  * This code has been tested against that, and is equivalent,
       9             :  * except that you don't need to include two pages of legalese
      10             :  * with every copy.
      11             :  *
      12             :  * To compute the message digest of a chunk of bytes, declare an
      13             :  * MD5Context structure, pass it to MD5Init, call MD5Update as
      14             :  * needed on buffers full of bytes, and then call MD5Final, which
      15             :  * will fill a supplied 16-byte array with the digest.
      16             :  */
      17             : 
      18             : /* This code was modified in 1997 by Jim Kingdon of Cyclic Software to
      19             : not require an integer type which is exactly 32 bits.  This work
      20             : draws on the changes for the same purpose by Tatu Ylonen
      21             : <ylo@cs.hut.fi> as part of SSH, but since I didn't actually use
      22             : that code, there is no copyright issue.  I hereby disclaim
      23             : copyright in any changes I have made; this code remains in the
      24             : public domain.  */
      25             : 
      26             : /* Note regarding cvs_* namespace: this avoids potential conflicts
      27             : with libraries such as some versions of Kerberos.  No particular
      28             : need to worry about whether the system supplies an MD5 library, as
      29             : this file is only about 3k of object code.  */
      30             : 
      31             : /* Modified by E. Rouault, to fix :
      32             :    warning: argument to 'sizeof' in 'memset' call is the same expression as
      33             :    the destination; did you mean to dereference it? [-Wsizeof-pointer-memaccess]
      34             :         memset(ctx, 0, sizeof(ctx)); */   /* In case it is sensitive */
      35             : /* at the end of cvs_MD5Final */
      36             : 
      37             : #include "cpl_md5.h"
      38             : 
      39             : #include "cpl_string.h"
      40             : 
      41       33856 : static GUInt32 getu32(const unsigned char *addr)
      42             : {
      43       33856 :     return ((((static_cast<GUInt32>(addr[3]) << 8) | addr[2]) << 8) | addr[1])
      44       33856 :                << 8 |
      45       33856 :            addr[0];
      46             : }
      47             : 
      48        5424 : static void putu32(GUInt32 data, unsigned char *addr)
      49             : {
      50        5424 :     addr[0] = static_cast<unsigned char>(data & 0xff);
      51        5424 :     addr[1] = static_cast<unsigned char>((data >> 8) & 0xff);
      52        5424 :     addr[2] = static_cast<unsigned char>((data >> 16) & 0xff);
      53        5424 :     addr[3] = static_cast<unsigned char>((data >> 24) & 0xff);
      54        5424 : }
      55             : 
      56             : /*
      57             :  * Start MD5 accumulation.  Set bit count to 0 and buffer to mysterious
      58             :  * initialization constants.
      59             :  */
      60         904 : void CPLMD5Init(struct CPLMD5Context *context)
      61             : {
      62         904 :     context->buf[0] = 0x67452301;
      63         904 :     context->buf[1] = 0xefcdab89;
      64         904 :     context->buf[2] = 0x98badcfe;
      65         904 :     context->buf[3] = 0x10325476;
      66             : 
      67         904 :     context->bits[0] = 0;
      68         904 :     context->bits[1] = 0;
      69         904 : }
      70             : 
      71             : /*
      72             :  * Update context to reflect the concatenation of another buffer full
      73             :  * of bytes.
      74             :  */
      75        1184 : void CPLMD5Update(struct CPLMD5Context *context, const void *buf, size_t len)
      76             : {
      77        1184 :     const GByte *pabyBuf = static_cast<const GByte *>(buf);
      78        1184 :     while (len > 0xffffffffU)
      79             :     {
      80           0 :         CPLMD5Update(context, pabyBuf, 0xffffffffU);
      81           0 :         pabyBuf += 0xffffffffU;
      82           0 :         len -= 0xffffffffU;
      83             :     }
      84             : 
      85             :     // Update bitcount
      86        1184 :     GUInt32 t = context->bits[0];
      87        1184 :     if ((context->bits[0] =
      88        1184 :              (t + (static_cast<GUInt32>(len) << 3)) & 0xffffffff) < t)
      89           0 :         context->bits[1]++; /* Carry from low to high */
      90        1184 :     context->bits[1] += static_cast<GUInt32>(len >> 29);
      91             : 
      92        1184 :     t = (t >> 3) & 0x3f; /* Bytes already in shsInfo->data */
      93             : 
      94             :     /* Handle any leading odd-sized chunks */
      95             : 
      96        1184 :     if (t)
      97             :     {
      98         280 :         unsigned char *p = context->in + t;
      99             : 
     100         280 :         t = 64 - t;
     101         280 :         if (len < t)
     102             :         {
     103          24 :             memcpy(p, pabyBuf, len);
     104          24 :             return;
     105             :         }
     106         256 :         memcpy(p, pabyBuf, t);
     107         256 :         CPLMD5Transform(context->buf, context->in);
     108         256 :         pabyBuf += t;
     109         256 :         len -= t;
     110             :     }
     111             : 
     112             :     /* Process data in 64-byte chunks */
     113             : 
     114        2096 :     while (len >= 64)
     115             :     {
     116         936 :         memcpy(context->in, pabyBuf, 64);
     117         936 :         CPLMD5Transform(context->buf, context->in);
     118         936 :         pabyBuf += 64;
     119         936 :         len -= 64;
     120             :     }
     121             : 
     122             :     /* Handle any remaining bytes of data. */
     123             : 
     124        1160 :     memcpy(context->in, pabyBuf, len);
     125             : }
     126             : 
     127             : /*
     128             :  * Final wrapup - pad to 64-byte boundary with the bit pattern
     129             :  * 1 0* (64-bit count of bits processed, MSB-first)
     130             :  */
     131         904 : void CPLMD5Final(unsigned char digest[16], struct CPLMD5Context *context)
     132             : {
     133             :     /* Compute number of bytes mod 64 */
     134         904 :     unsigned count = static_cast<unsigned>((context->bits[0] >> 3) & 0x3F);
     135             : 
     136             :     /* Set the first char of padding to 0x80.  This is safe since there is
     137             :     always at least one byte free */
     138         904 :     unsigned char *p = context->in + count;
     139         904 :     *p++ = 0x80;
     140             : 
     141             :     /* Bytes of padding needed to make 64 bytes */
     142         904 :     count = 64 - 1 - count;
     143             : 
     144             :     /* Pad out to 56 mod 64 */
     145         904 :     if (count < 8)
     146             :     {
     147             :         /* Two lots of padding:  Pad the first block to 64 bytes */
     148          20 :         memset(p, 0, count);
     149          20 :         CPLMD5Transform(context->buf, context->in);
     150             : 
     151             :         /* Now fill the next block with 56 bytes */
     152          20 :         memset(context->in, 0, 56);
     153             :     }
     154             :     else
     155             :     {
     156             :         /* Pad block to 56 bytes */
     157         884 :         memset(p, 0, count - 8);
     158             :     }
     159             : 
     160             :     /* Append length in bits and transform */
     161         904 :     putu32(context->bits[0], context->in + 56);
     162         904 :     putu32(context->bits[1], context->in + 60);
     163             : 
     164         904 :     CPLMD5Transform(context->buf, context->in);
     165         904 :     putu32(context->buf[0], digest);
     166         904 :     putu32(context->buf[1], digest + 4);
     167         904 :     putu32(context->buf[2], digest + 8);
     168         904 :     putu32(context->buf[3], digest + 12);
     169         904 :     memset(context, 0, sizeof(*context)); /* In case it is sensitive */
     170         904 : }
     171             : 
     172             : #ifndef ASM_MD5
     173             : 
     174             : /* The four core functions - F1 is optimized somewhat */
     175             : 
     176             : /* #define F1(x, y, z) (x & y | ~x & z) */
     177             : #define F1(x, y, z) (z ^ (x & (y ^ z)))
     178             : #define F2(x, y, z) F1(z, x, y)
     179             : #define F3(x, y, z) (x ^ y ^ z)
     180             : #define F4(x, y, z) (y ^ (x | ~z))
     181             : 
     182             : /* This is the central step in the MD5 algorithm. */
     183             : #define MD5STEP(f, w, x, y, z, data, s)                                        \
     184             :     (w += f(x, y, z) + data, w &= 0xffffffff, w = w << s | w >> (32 - s),      \
     185             :      w += x)
     186             : 
     187             : /*
     188             :  * The core of the MD5 algorithm, this alters an existing MD5 hash to
     189             :  * reflect the addition of 16 longwords of new data.  MD5Update blocks
     190             :  * the data and converts bytes into longwords for this routine.
     191             :  */
     192             : CPL_NOSANITIZE_UNSIGNED_INT_OVERFLOW
     193        2116 : void CPLMD5Transform(GUInt32 buf[4], const unsigned char inraw[64])
     194             : {
     195             :     GUInt32 in[16];
     196       35972 :     for (int i = 0; i < 16; ++i)
     197       33856 :         in[i] = getu32(inraw + 4 * i);
     198             : 
     199        2116 :     GUInt32 a = buf[0];
     200        2116 :     GUInt32 b = buf[1];
     201        2116 :     GUInt32 c = buf[2];
     202        2116 :     GUInt32 d = buf[3];
     203             : 
     204        2116 :     MD5STEP(F1, a, b, c, d, in[0] + 0xd76aa478, 7);
     205        2116 :     MD5STEP(F1, d, a, b, c, in[1] + 0xe8c7b756, 12);
     206        2116 :     MD5STEP(F1, c, d, a, b, in[2] + 0x242070db, 17);
     207        2116 :     MD5STEP(F1, b, c, d, a, in[3] + 0xc1bdceee, 22);
     208        2116 :     MD5STEP(F1, a, b, c, d, in[4] + 0xf57c0faf, 7);
     209        2116 :     MD5STEP(F1, d, a, b, c, in[5] + 0x4787c62a, 12);
     210        2116 :     MD5STEP(F1, c, d, a, b, in[6] + 0xa8304613, 17);
     211        2116 :     MD5STEP(F1, b, c, d, a, in[7] + 0xfd469501, 22);
     212        2116 :     MD5STEP(F1, a, b, c, d, in[8] + 0x698098d8, 7);
     213        2116 :     MD5STEP(F1, d, a, b, c, in[9] + 0x8b44f7af, 12);
     214        2116 :     MD5STEP(F1, c, d, a, b, in[10] + 0xffff5bb1, 17);
     215        2116 :     MD5STEP(F1, b, c, d, a, in[11] + 0x895cd7be, 22);
     216        2116 :     MD5STEP(F1, a, b, c, d, in[12] + 0x6b901122, 7);
     217        2116 :     MD5STEP(F1, d, a, b, c, in[13] + 0xfd987193, 12);
     218        2116 :     MD5STEP(F1, c, d, a, b, in[14] + 0xa679438e, 17);
     219        2116 :     MD5STEP(F1, b, c, d, a, in[15] + 0x49b40821, 22);
     220             : 
     221        2116 :     MD5STEP(F2, a, b, c, d, in[1] + 0xf61e2562, 5);
     222        2116 :     MD5STEP(F2, d, a, b, c, in[6] + 0xc040b340, 9);
     223        2116 :     MD5STEP(F2, c, d, a, b, in[11] + 0x265e5a51, 14);
     224        2116 :     MD5STEP(F2, b, c, d, a, in[0] + 0xe9b6c7aa, 20);
     225        2116 :     MD5STEP(F2, a, b, c, d, in[5] + 0xd62f105d, 5);
     226        2116 :     MD5STEP(F2, d, a, b, c, in[10] + 0x02441453, 9);
     227        2116 :     MD5STEP(F2, c, d, a, b, in[15] + 0xd8a1e681, 14);
     228        2116 :     MD5STEP(F2, b, c, d, a, in[4] + 0xe7d3fbc8, 20);
     229        2116 :     MD5STEP(F2, a, b, c, d, in[9] + 0x21e1cde6, 5);
     230        2116 :     MD5STEP(F2, d, a, b, c, in[14] + 0xc33707d6, 9);
     231        2116 :     MD5STEP(F2, c, d, a, b, in[3] + 0xf4d50d87, 14);
     232        2116 :     MD5STEP(F2, b, c, d, a, in[8] + 0x455a14ed, 20);
     233        2116 :     MD5STEP(F2, a, b, c, d, in[13] + 0xa9e3e905, 5);
     234        2116 :     MD5STEP(F2, d, a, b, c, in[2] + 0xfcefa3f8, 9);
     235        2116 :     MD5STEP(F2, c, d, a, b, in[7] + 0x676f02d9, 14);
     236        2116 :     MD5STEP(F2, b, c, d, a, in[12] + 0x8d2a4c8a, 20);
     237             : 
     238        2116 :     MD5STEP(F3, a, b, c, d, in[5] + 0xfffa3942, 4);
     239        2116 :     MD5STEP(F3, d, a, b, c, in[8] + 0x8771f681, 11);
     240        2116 :     MD5STEP(F3, c, d, a, b, in[11] + 0x6d9d6122, 16);
     241        2116 :     MD5STEP(F3, b, c, d, a, in[14] + 0xfde5380c, 23);
     242        2116 :     MD5STEP(F3, a, b, c, d, in[1] + 0xa4beea44, 4);
     243        2116 :     MD5STEP(F3, d, a, b, c, in[4] + 0x4bdecfa9, 11);
     244        2116 :     MD5STEP(F3, c, d, a, b, in[7] + 0xf6bb4b60, 16);
     245        2116 :     MD5STEP(F3, b, c, d, a, in[10] + 0xbebfbc70, 23);
     246        2116 :     MD5STEP(F3, a, b, c, d, in[13] + 0x289b7ec6, 4);
     247        2116 :     MD5STEP(F3, d, a, b, c, in[0] + 0xeaa127fa, 11);
     248        2116 :     MD5STEP(F3, c, d, a, b, in[3] + 0xd4ef3085, 16);
     249        2116 :     MD5STEP(F3, b, c, d, a, in[6] + 0x04881d05, 23);
     250        2116 :     MD5STEP(F3, a, b, c, d, in[9] + 0xd9d4d039, 4);
     251        2116 :     MD5STEP(F3, d, a, b, c, in[12] + 0xe6db99e5, 11);
     252        2116 :     MD5STEP(F3, c, d, a, b, in[15] + 0x1fa27cf8, 16);
     253        2116 :     MD5STEP(F3, b, c, d, a, in[2] + 0xc4ac5665, 23);
     254             : 
     255        2116 :     MD5STEP(F4, a, b, c, d, in[0] + 0xf4292244, 6);
     256        2116 :     MD5STEP(F4, d, a, b, c, in[7] + 0x432aff97, 10);
     257        2116 :     MD5STEP(F4, c, d, a, b, in[14] + 0xab9423a7, 15);
     258        2116 :     MD5STEP(F4, b, c, d, a, in[5] + 0xfc93a039, 21);
     259        2116 :     MD5STEP(F4, a, b, c, d, in[12] + 0x655b59c3, 6);
     260        2116 :     MD5STEP(F4, d, a, b, c, in[3] + 0x8f0ccc92, 10);
     261        2116 :     MD5STEP(F4, c, d, a, b, in[10] + 0xffeff47d, 15);
     262        2116 :     MD5STEP(F4, b, c, d, a, in[1] + 0x85845dd1, 21);
     263        2116 :     MD5STEP(F4, a, b, c, d, in[8] + 0x6fa87e4f, 6);
     264        2116 :     MD5STEP(F4, d, a, b, c, in[15] + 0xfe2ce6e0, 10);
     265        2116 :     MD5STEP(F4, c, d, a, b, in[6] + 0xa3014314, 15);
     266        2116 :     MD5STEP(F4, b, c, d, a, in[13] + 0x4e0811a1, 21);
     267        2116 :     MD5STEP(F4, a, b, c, d, in[4] + 0xf7537e82, 6);
     268        2116 :     MD5STEP(F4, d, a, b, c, in[11] + 0xbd3af235, 10);
     269        2116 :     MD5STEP(F4, c, d, a, b, in[2] + 0x2ad7d2bb, 15);
     270        2116 :     MD5STEP(F4, b, c, d, a, in[9] + 0xeb86d391, 21);
     271             : 
     272        2116 :     buf[0] += a;
     273        2116 :     buf[1] += b;
     274        2116 :     buf[2] += c;
     275        2116 :     buf[3] += d;
     276        2116 : }
     277             : #endif
     278             : 
     279             : /**
     280             :  * @brief CPLMD5String Transform string to MD5 hash
     281             :  * @param pszText Text to transform
     282             :  * @return MD5 hash string
     283             :  */
     284         226 : const char *CPLMD5String(const char *pszText)
     285             : {
     286             :     struct CPLMD5Context context;
     287         226 :     CPLMD5Init(&context);
     288         226 :     CPLMD5Update(&context, pszText, strlen(pszText));
     289             :     unsigned char hash[16];
     290         226 :     CPLMD5Final(hash, &context);
     291             : 
     292         226 :     constexpr char tohex[] = "0123456789abcdef";
     293             :     char hhash[33];
     294        3842 :     for (int i = 0; i < 16; ++i)
     295             :     {
     296        3616 :         hhash[i * 2] = tohex[(hash[i] >> 4) & 0xf];
     297        3616 :         hhash[i * 2 + 1] = tohex[hash[i] & 0xf];
     298             :     }
     299         226 :     hhash[32] = '\0';
     300         452 :     return CPLSPrintf("%s", hhash);
     301             : }

Generated by: LCOV version 1.14