LCOV - code coverage report
Current view: top level - source/maths - MD5.cpp (source / functions) Hit Total Coverage
Test: 0 A.D. test coverage report Lines: 112 112 100.0 %
Date: 2023-01-19 00:18:29 Functions: 7 7 100.0 %

          Line data    Source code
       1             : /* Copyright (C) 2010 Wildfire Games.
       2             :  * This file is part of 0 A.D.
       3             :  *
       4             :  * 0 A.D. is free software: you can redistribute it and/or modify
       5             :  * it under the terms of the GNU General Public License as published by
       6             :  * the Free Software Foundation, either version 2 of the License, or
       7             :  * (at your option) any later version.
       8             :  *
       9             :  * 0 A.D. is distributed in the hope that it will be useful,
      10             :  * but WITHOUT ANY WARRANTY; without even the implied warranty of
      11             :  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      12             :  * GNU General Public License for more details.
      13             :  *
      14             :  * You should have received a copy of the GNU General Public License
      15             :  * along with 0 A.D.  If not, see <http://www.gnu.org/licenses/>.
      16             :  */
      17             : 
      18             : #include "precompiled.h"
      19             : 
      20             : // Based on md5.cpp from Crypto++ 5.6.0:
      21             : //   "md5.cpp - modified by Wei Dai from Colin Plumb's public domain md5.c"
      22             : //   "any modifications are placed in the public domain"
      23             : 
      24             : #include "MD5.h"
      25             : 
      26         722 : MD5::MD5()
      27             : {
      28         722 :     InitState();
      29         722 : }
      30             : 
      31        1217 : void MD5::InitState()
      32             : {
      33        1217 :     m_Digest[0] = 0x67452301L;
      34        1217 :     m_Digest[1] = 0xefcdab89L;
      35        1217 :     m_Digest[2] = 0x98badcfeL;
      36        1217 :     m_Digest[3] = 0x10325476L;
      37        1217 :     m_BufLen = 0;
      38        1217 :     m_InputLen = 0;
      39        1217 :     memset(m_Buf, 0xcc, sizeof(m_Buf));
      40        1217 : }
      41             : 
      42         633 : void MD5::UpdateRest(const u8* data, size_t len)
      43             : {
      44         633 :     const size_t CHUNK_SIZE = sizeof(m_Buf);
      45             : 
      46             :     // Add as much data as possible to the buffer
      47         633 :     size_t n = CHUNK_SIZE - m_BufLen;
      48             : //  ENSURE(len >= n);
      49         633 :     memcpy(m_Buf + m_BufLen, data, n);
      50         633 :     data += n;
      51         633 :     len -= n;
      52             : 
      53             :     // Flush the (now full) buffer
      54         633 :     Transform((const u32*)m_Buf); // assumes little-endian
      55             : 
      56             :     // Process whole chunks of the input
      57       12399 :     while (len >= CHUNK_SIZE)
      58             :     {
      59        5883 :         Transform((const u32*)data); // assumes little-endian; ignores alignment
      60        5883 :         data += CHUNK_SIZE;
      61        5883 :         len -= CHUNK_SIZE;
      62             :     }
      63             : 
      64             :     // Add the remainder to the buffer
      65         633 :     memcpy(m_Buf, data, len);
      66         633 :     m_BufLen = len;
      67         633 : }
      68             : 
      69         495 : void MD5::Final(u8* digest)
      70             : {
      71             :     // Compute the message length in bits (before padding)
      72         495 :     u64 len = m_InputLen * 8;
      73             : 
      74             :     // Pad with 1-bit
      75         495 :     const u8 pad = 0x80;
      76         495 :     Update(&pad, 1);
      77             : 
      78             :     // Fill with zeros until length % 64 = 56 (bytes)
      79       34845 :     while (m_BufLen % 64 != 56)
      80             :     {
      81       17175 :         const u8 zero = 0;
      82       17175 :         Update(&zero, 1);
      83             :     }
      84             : 
      85             :     // Append the length (assumes little-endian)
      86         495 :     Update((const u8*)&len, 8);
      87             : 
      88             :     // Return the digest (assumes little-endian)
      89         495 :     memcpy(digest, m_Digest, DIGESTSIZE);
      90             : 
      91             :     // Reset
      92         495 :     InitState();
      93         495 : }
      94             : 
      95             : // Use macro rather than inline function for significantly better debug-mode performance
      96             : #define rotlFixed(x, y) (((x) << (y)) | ((x) >> (32 - (y))))
      97             : // TODO: Crypto++ has an overload using _lrotl on MSVC - is that worthwhile?
      98             : 
      99        6516 : void MD5::Transform(const u32* in)
     100             : {
     101             : #define F1(x, y, z) (z ^ (x & (y ^ z)))
     102             : #define F2(x, y, z) F1(z, x, y)
     103             : #define F3(x, y, z) (x ^ y ^ z)
     104             : #define F4(x, y, z) (y ^ (x | ~z))
     105             : 
     106             : #define MD5STEP(f, w, x, y, z, data, s) \
     107             :     t = w + f(x, y, z) + data; w = rotlFixed(t, s) + x
     108             : 
     109        6516 :     u32* digest = m_Digest;
     110             : 
     111             :     u32 a, b, c, d;
     112             :     u32 t;
     113             : 
     114        6516 :     a = digest[0];
     115        6516 :     b = digest[1];
     116        6516 :     c = digest[2];
     117        6516 :     d = digest[3];
     118             : 
     119        6516 :     MD5STEP(F1, a, b, c, d, in[0] + 0xd76aa478, 7);
     120        6516 :     MD5STEP(F1, d, a, b, c, in[1] + 0xe8c7b756, 12);
     121        6516 :     MD5STEP(F1, c, d, a, b, in[2] + 0x242070db, 17);
     122        6516 :     MD5STEP(F1, b, c, d, a, in[3] + 0xc1bdceee, 22);
     123        6516 :     MD5STEP(F1, a, b, c, d, in[4] + 0xf57c0faf, 7);
     124        6516 :     MD5STEP(F1, d, a, b, c, in[5] + 0x4787c62a, 12);
     125        6516 :     MD5STEP(F1, c, d, a, b, in[6] + 0xa8304613, 17);
     126        6516 :     MD5STEP(F1, b, c, d, a, in[7] + 0xfd469501, 22);
     127        6516 :     MD5STEP(F1, a, b, c, d, in[8] + 0x698098d8, 7);
     128        6516 :     MD5STEP(F1, d, a, b, c, in[9] + 0x8b44f7af, 12);
     129        6516 :     MD5STEP(F1, c, d, a, b, in[10] + 0xffff5bb1, 17);
     130        6516 :     MD5STEP(F1, b, c, d, a, in[11] + 0x895cd7be, 22);
     131        6516 :     MD5STEP(F1, a, b, c, d, in[12] + 0x6b901122, 7);
     132        6516 :     MD5STEP(F1, d, a, b, c, in[13] + 0xfd987193, 12);
     133        6516 :     MD5STEP(F1, c, d, a, b, in[14] + 0xa679438e, 17);
     134        6516 :     MD5STEP(F1, b, c, d, a, in[15] + 0x49b40821, 22);
     135             : 
     136        6516 :     MD5STEP(F2, a, b, c, d, in[1] + 0xf61e2562, 5);
     137        6516 :     MD5STEP(F2, d, a, b, c, in[6] + 0xc040b340, 9);
     138        6516 :     MD5STEP(F2, c, d, a, b, in[11] + 0x265e5a51, 14);
     139        6516 :     MD5STEP(F2, b, c, d, a, in[0] + 0xe9b6c7aa, 20);
     140        6516 :     MD5STEP(F2, a, b, c, d, in[5] + 0xd62f105d, 5);
     141        6516 :     MD5STEP(F2, d, a, b, c, in[10] + 0x02441453, 9);
     142        6516 :     MD5STEP(F2, c, d, a, b, in[15] + 0xd8a1e681, 14);
     143        6516 :     MD5STEP(F2, b, c, d, a, in[4] + 0xe7d3fbc8, 20);
     144        6516 :     MD5STEP(F2, a, b, c, d, in[9] + 0x21e1cde6, 5);
     145        6516 :     MD5STEP(F2, d, a, b, c, in[14] + 0xc33707d6, 9);
     146        6516 :     MD5STEP(F2, c, d, a, b, in[3] + 0xf4d50d87, 14);
     147        6516 :     MD5STEP(F2, b, c, d, a, in[8] + 0x455a14ed, 20);
     148        6516 :     MD5STEP(F2, a, b, c, d, in[13] + 0xa9e3e905, 5);
     149        6516 :     MD5STEP(F2, d, a, b, c, in[2] + 0xfcefa3f8, 9);
     150        6516 :     MD5STEP(F2, c, d, a, b, in[7] + 0x676f02d9, 14);
     151        6516 :     MD5STEP(F2, b, c, d, a, in[12] + 0x8d2a4c8a, 20);
     152             : 
     153        6516 :     MD5STEP(F3, a, b, c, d, in[5] + 0xfffa3942, 4);
     154        6516 :     MD5STEP(F3, d, a, b, c, in[8] + 0x8771f681, 11);
     155        6516 :     MD5STEP(F3, c, d, a, b, in[11] + 0x6d9d6122, 16);
     156        6516 :     MD5STEP(F3, b, c, d, a, in[14] + 0xfde5380c, 23);
     157        6516 :     MD5STEP(F3, a, b, c, d, in[1] + 0xa4beea44, 4);
     158        6516 :     MD5STEP(F3, d, a, b, c, in[4] + 0x4bdecfa9, 11);
     159        6516 :     MD5STEP(F3, c, d, a, b, in[7] + 0xf6bb4b60, 16);
     160        6516 :     MD5STEP(F3, b, c, d, a, in[10] + 0xbebfbc70, 23);
     161        6516 :     MD5STEP(F3, a, b, c, d, in[13] + 0x289b7ec6, 4);
     162        6516 :     MD5STEP(F3, d, a, b, c, in[0] + 0xeaa127fa, 11);
     163        6516 :     MD5STEP(F3, c, d, a, b, in[3] + 0xd4ef3085, 16);
     164        6516 :     MD5STEP(F3, b, c, d, a, in[6] + 0x04881d05, 23);
     165        6516 :     MD5STEP(F3, a, b, c, d, in[9] + 0xd9d4d039, 4);
     166        6516 :     MD5STEP(F3, d, a, b, c, in[12] + 0xe6db99e5, 11);
     167        6516 :     MD5STEP(F3, c, d, a, b, in[15] + 0x1fa27cf8, 16);
     168        6516 :     MD5STEP(F3, b, c, d, a, in[2] + 0xc4ac5665, 23);
     169             : 
     170        6516 :     MD5STEP(F4, a, b, c, d, in[0] + 0xf4292244, 6);
     171        6516 :     MD5STEP(F4, d, a, b, c, in[7] + 0x432aff97, 10);
     172        6516 :     MD5STEP(F4, c, d, a, b, in[14] + 0xab9423a7, 15);
     173        6516 :     MD5STEP(F4, b, c, d, a, in[5] + 0xfc93a039, 21);
     174        6516 :     MD5STEP(F4, a, b, c, d, in[12] + 0x655b59c3, 6);
     175        6516 :     MD5STEP(F4, d, a, b, c, in[3] + 0x8f0ccc92, 10);
     176        6516 :     MD5STEP(F4, c, d, a, b, in[10] + 0xffeff47d, 15);
     177        6516 :     MD5STEP(F4, b, c, d, a, in[1] + 0x85845dd1, 21);
     178        6516 :     MD5STEP(F4, a, b, c, d, in[8] + 0x6fa87e4f, 6);
     179        6516 :     MD5STEP(F4, d, a, b, c, in[15] + 0xfe2ce6e0, 10);
     180        6516 :     MD5STEP(F4, c, d, a, b, in[6] + 0xa3014314, 15);
     181        6516 :     MD5STEP(F4, b, c, d, a, in[13] + 0x4e0811a1, 21);
     182        6516 :     MD5STEP(F4, a, b, c, d, in[4] + 0xf7537e82, 6);
     183        6516 :     MD5STEP(F4, d, a, b, c, in[11] + 0xbd3af235, 10);
     184        6516 :     MD5STEP(F4, c, d, a, b, in[2] + 0x2ad7d2bb, 15);
     185        6516 :     MD5STEP(F4, b, c, d, a, in[9] + 0xeb86d391, 21);
     186             : 
     187        6516 :     digest[0] += a;
     188        6516 :     digest[1] += b;
     189        6516 :     digest[2] += c;
     190        6516 :     digest[3] += d;
     191        6519 : }

Generated by: LCOV version 1.13