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

Generated by: LCOV version 1.14