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-11-21 22:18:42 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     2080270 : static GUInt32 getu32(const unsigned char *addr)
      42             : {
      43     2080270 :     return ((((static_cast<GUInt32>(addr[3]) << 8) | addr[2]) << 8) | addr[1])
      44     2080270 :                << 8 |
      45     2080270 :            addr[0];
      46             : }
      47             : 
      48      339324 : static void putu32(GUInt32 data, unsigned char *addr)
      49             : {
      50      339324 :     addr[0] = static_cast<unsigned char>(data & 0xff);
      51      339324 :     addr[1] = static_cast<unsigned char>((data >> 8) & 0xff);
      52      339324 :     addr[2] = static_cast<unsigned char>((data >> 16) & 0xff);
      53      339324 :     addr[3] = static_cast<unsigned char>((data >> 24) & 0xff);
      54      339324 : }
      55             : 
      56             : /*
      57             :  * Start MD5 accumulation.  Set bit count to 0 and buffer to mysterious
      58             :  * initialization constants.
      59             :  */
      60       56554 : void CPLMD5Init(struct CPLMD5Context *context)
      61             : {
      62       56554 :     context->buf[0] = 0x67452301;
      63       56554 :     context->buf[1] = 0xefcdab89;
      64       56554 :     context->buf[2] = 0x98badcfe;
      65       56554 :     context->buf[3] = 0x10325476;
      66             : 
      67       56554 :     context->bits[0] = 0;
      68       56554 :     context->bits[1] = 0;
      69       56554 : }
      70             : 
      71             : /*
      72             :  * Update context to reflect the concatenation of another buffer full
      73             :  * of bytes.
      74             :  */
      75       56834 : void CPLMD5Update(struct CPLMD5Context *context, const void *buf, size_t len)
      76             : {
      77       56834 :     const GByte *pabyBuf = static_cast<const GByte *>(buf);
      78       56834 :     while (len > 0xffffffffU)
      79             :     {
      80           0 :         CPLMD5Update(context, pabyBuf, 0xffffffffU);
      81           0 :         pabyBuf += 0xffffffffU;
      82           0 :         len -= 0xffffffffU;
      83             :     }
      84             : 
      85             :     // Update bitcount
      86       56834 :     GUInt32 t = context->bits[0];
      87             :     // coverity[overflow_const]
      88       56834 :     if ((context->bits[0] =
      89       56834 :              (t + (static_cast<GUInt32>(len) << 3)) & 0xffffffff) < t)
      90           0 :         context->bits[1]++; /* Carry from low to high */
      91       56834 :     context->bits[1] += static_cast<GUInt32>(len >> 29);
      92             : 
      93       56834 :     t = (t >> 3) & 0x3f; /* Bytes already in shsInfo->data */
      94             : 
      95             :     /* Handle any leading odd-sized chunks */
      96             : 
      97       56834 :     if (t)
      98             :     {
      99         280 :         unsigned char *p = context->in + t;
     100             : 
     101         280 :         t = 64 - t;
     102         280 :         if (len < t)
     103             :         {
     104          24 :             memcpy(p, pabyBuf, len);
     105          24 :             return;
     106             :         }
     107         256 :         memcpy(p, pabyBuf, t);
     108         256 :         CPLMD5Transform(context->buf, context->in);
     109         256 :         pabyBuf += t;
     110         256 :         len -= t;
     111             :     }
     112             : 
     113             :     /* Process data in 64-byte chunks */
     114             : 
     115      126884 :     while (len >= 64)
     116             :     {
     117       70074 :         memcpy(context->in, pabyBuf, 64);
     118       70074 :         CPLMD5Transform(context->buf, context->in);
     119       70074 :         pabyBuf += 64;
     120       70074 :         len -= 64;
     121             :     }
     122             : 
     123             :     /* Handle any remaining bytes of data. */
     124             : 
     125       56810 :     memcpy(context->in, pabyBuf, len);
     126             : }
     127             : 
     128             : /*
     129             :  * Final wrapup - pad to 64-byte boundary with the bit pattern
     130             :  * 1 0* (64-bit count of bits processed, MSB-first)
     131             :  */
     132       56554 : void CPLMD5Final(unsigned char digest[16], struct CPLMD5Context *context)
     133             : {
     134             :     /* Compute number of bytes mod 64 */
     135       56554 :     unsigned count = static_cast<unsigned>((context->bits[0] >> 3) & 0x3F);
     136             : 
     137             :     /* Set the first char of padding to 0x80.  This is safe since there is
     138             :     always at least one byte free */
     139       56554 :     unsigned char *p = context->in + count;
     140       56554 :     *p++ = 0x80;
     141             : 
     142             :     /* Bytes of padding needed to make 64 bytes */
     143       56554 :     count = 64 - 1 - count;
     144             : 
     145             :     /* Pad out to 56 mod 64 */
     146       56554 :     if (count < 8)
     147             :     {
     148             :         /* Two lots of padding:  Pad the first block to 64 bytes */
     149        3133 :         memset(p, 0, count);
     150        3133 :         CPLMD5Transform(context->buf, context->in);
     151             : 
     152             :         /* Now fill the next block with 56 bytes */
     153        3133 :         memset(context->in, 0, 56);
     154             :     }
     155             :     else
     156             :     {
     157             :         /* Pad block to 56 bytes */
     158       53421 :         memset(p, 0, count - 8);
     159             :     }
     160             : 
     161             :     /* Append length in bits and transform */
     162       56554 :     putu32(context->bits[0], context->in + 56);
     163       56554 :     putu32(context->bits[1], context->in + 60);
     164             : 
     165       56554 :     CPLMD5Transform(context->buf, context->in);
     166       56554 :     putu32(context->buf[0], digest);
     167       56554 :     putu32(context->buf[1], digest + 4);
     168       56554 :     putu32(context->buf[2], digest + 8);
     169       56554 :     putu32(context->buf[3], digest + 12);
     170       56554 :     memset(context, 0, sizeof(*context)); /* In case it is sensitive */
     171       56554 : }
     172             : 
     173             : #ifndef ASM_MD5
     174             : 
     175             : /* The four core functions - F1 is optimized somewhat */
     176             : 
     177             : /* #define F1(x, y, z) (x & y | ~x & z) */
     178             : #define F1(x, y, z) (z ^ (x & (y ^ z)))
     179             : #define F2(x, y, z) F1(z, x, y)
     180             : #define F3(x, y, z) (x ^ y ^ z)
     181             : #define F4(x, y, z) (y ^ (x | ~z))
     182             : 
     183             : /* This is the central step in the MD5 algorithm. */
     184             : #define MD5STEP(f, w, x, y, z, data, s)                                        \
     185             :     (w += f(x, y, z) + data, w &= 0xffffffff, w = w << s | w >> (32 - s),      \
     186             :      w += x)
     187             : 
     188             : /*
     189             :  * The core of the MD5 algorithm, this alters an existing MD5 hash to
     190             :  * reflect the addition of 16 longwords of new data.  MD5Update blocks
     191             :  * the data and converts bytes into longwords for this routine.
     192             :  */
     193             : CPL_NOSANITIZE_UNSIGNED_INT_OVERFLOW
     194      130017 : void CPLMD5Transform(GUInt32 buf[4], const unsigned char inraw[64])
     195             : {
     196             :     GUInt32 in[16];
     197     2210290 :     for (int i = 0; i < 16; ++i)
     198     2080270 :         in[i] = getu32(inraw + 4 * i);
     199             : 
     200      130017 :     GUInt32 a = buf[0];
     201      130017 :     GUInt32 b = buf[1];
     202      130017 :     GUInt32 c = buf[2];
     203      130017 :     GUInt32 d = buf[3];
     204             : 
     205      130017 :     MD5STEP(F1, a, b, c, d, in[0] + 0xd76aa478, 7);
     206      130017 :     MD5STEP(F1, d, a, b, c, in[1] + 0xe8c7b756, 12);
     207      130017 :     MD5STEP(F1, c, d, a, b, in[2] + 0x242070db, 17);
     208      130017 :     MD5STEP(F1, b, c, d, a, in[3] + 0xc1bdceee, 22);
     209      130017 :     MD5STEP(F1, a, b, c, d, in[4] + 0xf57c0faf, 7);
     210      130017 :     MD5STEP(F1, d, a, b, c, in[5] + 0x4787c62a, 12);
     211      130017 :     MD5STEP(F1, c, d, a, b, in[6] + 0xa8304613, 17);
     212      130017 :     MD5STEP(F1, b, c, d, a, in[7] + 0xfd469501, 22);
     213      130017 :     MD5STEP(F1, a, b, c, d, in[8] + 0x698098d8, 7);
     214      130017 :     MD5STEP(F1, d, a, b, c, in[9] + 0x8b44f7af, 12);
     215      130017 :     MD5STEP(F1, c, d, a, b, in[10] + 0xffff5bb1, 17);
     216      130017 :     MD5STEP(F1, b, c, d, a, in[11] + 0x895cd7be, 22);
     217      130017 :     MD5STEP(F1, a, b, c, d, in[12] + 0x6b901122, 7);
     218      130017 :     MD5STEP(F1, d, a, b, c, in[13] + 0xfd987193, 12);
     219      130017 :     MD5STEP(F1, c, d, a, b, in[14] + 0xa679438e, 17);
     220      130017 :     MD5STEP(F1, b, c, d, a, in[15] + 0x49b40821, 22);
     221             : 
     222      130017 :     MD5STEP(F2, a, b, c, d, in[1] + 0xf61e2562, 5);
     223      130017 :     MD5STEP(F2, d, a, b, c, in[6] + 0xc040b340, 9);
     224      130017 :     MD5STEP(F2, c, d, a, b, in[11] + 0x265e5a51, 14);
     225      130017 :     MD5STEP(F2, b, c, d, a, in[0] + 0xe9b6c7aa, 20);
     226      130017 :     MD5STEP(F2, a, b, c, d, in[5] + 0xd62f105d, 5);
     227      130017 :     MD5STEP(F2, d, a, b, c, in[10] + 0x02441453, 9);
     228      130017 :     MD5STEP(F2, c, d, a, b, in[15] + 0xd8a1e681, 14);
     229      130017 :     MD5STEP(F2, b, c, d, a, in[4] + 0xe7d3fbc8, 20);
     230      130017 :     MD5STEP(F2, a, b, c, d, in[9] + 0x21e1cde6, 5);
     231      130017 :     MD5STEP(F2, d, a, b, c, in[14] + 0xc33707d6, 9);
     232      130017 :     MD5STEP(F2, c, d, a, b, in[3] + 0xf4d50d87, 14);
     233      130017 :     MD5STEP(F2, b, c, d, a, in[8] + 0x455a14ed, 20);
     234      130017 :     MD5STEP(F2, a, b, c, d, in[13] + 0xa9e3e905, 5);
     235      130017 :     MD5STEP(F2, d, a, b, c, in[2] + 0xfcefa3f8, 9);
     236      130017 :     MD5STEP(F2, c, d, a, b, in[7] + 0x676f02d9, 14);
     237      130017 :     MD5STEP(F2, b, c, d, a, in[12] + 0x8d2a4c8a, 20);
     238             : 
     239      130017 :     MD5STEP(F3, a, b, c, d, in[5] + 0xfffa3942, 4);
     240      130017 :     MD5STEP(F3, d, a, b, c, in[8] + 0x8771f681, 11);
     241      130017 :     MD5STEP(F3, c, d, a, b, in[11] + 0x6d9d6122, 16);
     242      130017 :     MD5STEP(F3, b, c, d, a, in[14] + 0xfde5380c, 23);
     243      130017 :     MD5STEP(F3, a, b, c, d, in[1] + 0xa4beea44, 4);
     244      130017 :     MD5STEP(F3, d, a, b, c, in[4] + 0x4bdecfa9, 11);
     245      130017 :     MD5STEP(F3, c, d, a, b, in[7] + 0xf6bb4b60, 16);
     246      130017 :     MD5STEP(F3, b, c, d, a, in[10] + 0xbebfbc70, 23);
     247      130017 :     MD5STEP(F3, a, b, c, d, in[13] + 0x289b7ec6, 4);
     248      130017 :     MD5STEP(F3, d, a, b, c, in[0] + 0xeaa127fa, 11);
     249      130017 :     MD5STEP(F3, c, d, a, b, in[3] + 0xd4ef3085, 16);
     250      130017 :     MD5STEP(F3, b, c, d, a, in[6] + 0x04881d05, 23);
     251      130017 :     MD5STEP(F3, a, b, c, d, in[9] + 0xd9d4d039, 4);
     252      130017 :     MD5STEP(F3, d, a, b, c, in[12] + 0xe6db99e5, 11);
     253      130017 :     MD5STEP(F3, c, d, a, b, in[15] + 0x1fa27cf8, 16);
     254      130017 :     MD5STEP(F3, b, c, d, a, in[2] + 0xc4ac5665, 23);
     255             : 
     256      130017 :     MD5STEP(F4, a, b, c, d, in[0] + 0xf4292244, 6);
     257      130017 :     MD5STEP(F4, d, a, b, c, in[7] + 0x432aff97, 10);
     258      130017 :     MD5STEP(F4, c, d, a, b, in[14] + 0xab9423a7, 15);
     259      130017 :     MD5STEP(F4, b, c, d, a, in[5] + 0xfc93a039, 21);
     260      130017 :     MD5STEP(F4, a, b, c, d, in[12] + 0x655b59c3, 6);
     261      130017 :     MD5STEP(F4, d, a, b, c, in[3] + 0x8f0ccc92, 10);
     262      130017 :     MD5STEP(F4, c, d, a, b, in[10] + 0xffeff47d, 15);
     263      130017 :     MD5STEP(F4, b, c, d, a, in[1] + 0x85845dd1, 21);
     264      130017 :     MD5STEP(F4, a, b, c, d, in[8] + 0x6fa87e4f, 6);
     265      130017 :     MD5STEP(F4, d, a, b, c, in[15] + 0xfe2ce6e0, 10);
     266      130017 :     MD5STEP(F4, c, d, a, b, in[6] + 0xa3014314, 15);
     267      130017 :     MD5STEP(F4, b, c, d, a, in[13] + 0x4e0811a1, 21);
     268      130017 :     MD5STEP(F4, a, b, c, d, in[4] + 0xf7537e82, 6);
     269      130017 :     MD5STEP(F4, d, a, b, c, in[11] + 0xbd3af235, 10);
     270      130017 :     MD5STEP(F4, c, d, a, b, in[2] + 0x2ad7d2bb, 15);
     271      130017 :     MD5STEP(F4, b, c, d, a, in[9] + 0xeb86d391, 21);
     272             : 
     273      130017 :     buf[0] += a;
     274      130017 :     buf[1] += b;
     275      130017 :     buf[2] += c;
     276      130017 :     buf[3] += d;
     277      130017 : }
     278             : #endif
     279             : 
     280             : /**
     281             :  * @brief CPLMD5String Transform string to MD5 hash
     282             :  * @param pszText Text to transform
     283             :  * @return MD5 hash string
     284             :  */
     285       55876 : const char *CPLMD5String(const char *pszText)
     286             : {
     287             :     struct CPLMD5Context context;
     288       55876 :     CPLMD5Init(&context);
     289       55876 :     CPLMD5Update(&context, pszText, strlen(pszText));
     290             :     unsigned char hash[16];
     291       55876 :     CPLMD5Final(hash, &context);
     292             : 
     293       55876 :     constexpr char tohex[] = "0123456789abcdef";
     294             :     char hhash[33];
     295      949892 :     for (int i = 0; i < 16; ++i)
     296             :     {
     297      894016 :         hhash[i * 2] = tohex[(hash[i] >> 4) & 0xf];
     298      894016 :         hhash[i * 2 + 1] = tohex[hash[i] & 0xf];
     299             :     }
     300       55876 :     hhash[32] = '\0';
     301      111752 :     return CPLSPrintf("%s", hhash);
     302             : }

Generated by: LCOV version 1.14