LCOV - code coverage report
Current view: top level - lunchbox/md5 - md5.cc (source / functions) Hit Total Coverage
Test: lcov2.info Lines: 169 229 73.8 %
Date: 2014-08-05 Functions: 21 31 67.7 %

          Line data    Source code
       1             : // MD5.CC - source code for the C++/object oriented translation and
       2             : //          modification of MD5.
       3             : 
       4             : // Translation and modification (c) 1995 by Mordechai T. Abzug
       5             : //                                  2012-2014, Stefan Eilemann <eile@eyescale.ch>
       6             : 
       7             : // This translation/ modification is provided "as is," without express or
       8             : // implied warranty of any kind.
       9             : 
      10             : // The translator/ modifier does not claim (1) that MD5 will do what you think
      11             : // it does; (2) that this translation/ modification is accurate; or (3) that
      12             : // this software is "merchantible."  (Language for this disclaimer partially
      13             : // copied from the disclaimer below).
      14             : 
      15             : /* based on:
      16             : 
      17             :    MD5C.C - RSA Data Security, Inc., MD5 message-digest algorithm
      18             :    MDDRIVER.C - test driver for MD2, MD4 and MD5
      19             : 
      20             : 
      21             :    Copyright (C) 1991-2, RSA Data Security, Inc. Created 1991. All
      22             : rights reserved.
      23             : 
      24             : License to copy and use this software is granted provided that it
      25             : is identified as the "RSA Data Security, Inc. MD5 Message-Digest
      26             : Algorithm" in all material mentioning or referencing this software
      27             : or this function.
      28             : 
      29             : License is also granted to make and use derivative works provided
      30             : that such works are identified as "derived from the RSA Data
      31             : Security, Inc. MD5 Message-Digest Algorithm" in all material
      32             : mentioning or referencing the derived work.
      33             : 
      34             : RSA Data Security, Inc. makes no representations concerning either
      35             : the merchantability of this software or the suitability of this
      36             : software for any particular purpose. It is provided "as is"
      37             : without express or implied warranty of any kind.
      38             : 
      39             : These notices must be retained in any copies of any part of this
      40             : documentation and/or software.
      41             : 
      42             :  */
      43             : 
      44             : #include "md5.hh"
      45             : #include <lunchbox/debug.h>
      46             : 
      47             : #include <assert.h>
      48             : #include <string.h>
      49             : #include <iostream>
      50             : 
      51             : 
      52             : 
      53             : 
      54             : // MD5 simple initialization method
      55             : 
      56             : // cppcheck-suppress uninitMemberVar
      57           0 : MD5::MD5(){
      58             : 
      59           0 :   init();
      60             : 
      61           0 : }
      62             : 
      63             : 
      64             : 
      65             : 
      66             : // MD5 block update operation. Continues an MD5 message-digest
      67             : // operation, processing another message block, and updating the
      68             : // context.
      69             : 
      70           9 : void MD5::update (uint1 *input, size_t input_length) {
      71             : 
      72             :   size_t input_index, buffer_index;
      73             :   size_t buffer_space;                // how much space is left in buffer
      74             : 
      75           9 :   if (finalized){  // so we can't update!
      76           0 :     LBERROR << "MD5::update:  Can't update a finalized digest!" << std::endl;
      77           9 :     return;
      78             :   }
      79             : 
      80             :   // Compute number of bytes mod 64
      81           9 :   buffer_index = (unsigned int)((count[0] >> 3) & 0x3F);
      82             : 
      83             :   // Update number of bits
      84           9 :   if (  (count[0] += ((uint4) input_length << 3))<((uint4) input_length << 3) )
      85           0 :     count[1]++;
      86             : 
      87           9 :   count[1] += ((uint4)input_length >> 29);
      88             : 
      89             : 
      90           9 :   buffer_space = 64 - buffer_index;  // how much space is left in buffer
      91             : 
      92             :   // Transform as many times as possible.
      93           9 :   if (input_length >= buffer_space) { // ie. we have enough to fill the buffer
      94             :     // fill the rest of the buffer and transform
      95           3 :     memcpy (buffer + buffer_index, input, buffer_space);
      96           3 :     transform (buffer);
      97             : 
      98             :     // now, transform each 64-byte piece of the input, bypassing the buffer
      99           3 :     for (input_index = buffer_space; input_index + 63 < input_length;
     100             :          input_index += 64)
     101           0 :       transform (input+input_index);
     102             : 
     103           3 :     buffer_index = 0;  // so we can buffer remaining
     104             :   }
     105             :   else
     106           6 :     input_index=0;     // so we can buffer the whole input
     107             : 
     108             : 
     109             :   // and here we do the buffering:
     110           9 :   memcpy(buffer+buffer_index, input+input_index, input_length-input_index);
     111             : }
     112             : 
     113             : 
     114             : 
     115             : // MD5 update for files.
     116             : // Like above, except that it works on files (and uses above as a primitive.)
     117             : 
     118           0 : void MD5::update(FILE *file){
     119             : 
     120             :   unsigned char buf[1024];
     121             :   size_t len;
     122             : 
     123           0 :   while ( (len=fread(buf, 1, 1024, file)) )
     124           0 :     update(buf, len);
     125             : 
     126           0 :   fclose (file);
     127             : 
     128           0 : }
     129             : 
     130             : 
     131             : 
     132             : 
     133             : 
     134             : 
     135             : // MD5 update for std::istreams.
     136             : // Like update for files; see above.
     137             : 
     138           0 : void MD5::update(std::istream& stream){
     139             : 
     140           0 :   while (stream.good()){
     141             :     unsigned char buf[1024];
     142           0 :     stream.read((char*)buf, 1024); // note that return value of read is unusable.
     143           0 :     const int len=stream.gcount();
     144           0 :     update(buf, len);
     145             :   }
     146             : 
     147           0 : }
     148             : 
     149             : 
     150             : 
     151             : 
     152             : 
     153             : 
     154             : // MD5 update for std::ifstreams.
     155             : // Like update for files; see above.
     156             : 
     157           0 : void MD5::update(std::ifstream& stream){
     158             : 
     159           0 :   while (stream.good()){
     160             :     unsigned char buf[1024];
     161           0 :     stream.read((char*)buf, 1024); // note that return value of read is unusable.
     162           0 :     const int len=stream.gcount();
     163           0 :     update(buf, len);
     164             :   }
     165             : 
     166           0 : }
     167             : 
     168             : 
     169             : 
     170             : 
     171             : 
     172             : 
     173             : // MD5 finalization. Ends an MD5 message-digest operation, writing the
     174             : // the message digest and zeroizing the context.
     175             : 
     176             : 
     177           3 : void MD5::finalize (){
     178             : 
     179             :   unsigned char bits[8];
     180             :   unsigned int index, padLen;
     181             :   static uint1 PADDING[64]={
     182             :     0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
     183             :     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
     184             :     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
     185             :     };
     186             : 
     187           3 :   if (finalized){
     188           0 :     LBERROR << "MD5::finalize:  Already finalized this digest!" << std::endl;
     189           3 :     return;
     190             :   }
     191             : 
     192             :   // Save number of bits
     193           3 :   encode (bits, count, 8);
     194             : 
     195             :   // Pad out to 56 mod 64.
     196           3 :   index = (uint4) ((count[0] >> 3) & 0x3f);
     197           3 :   padLen = (index < 56) ? (56 - index) : (120 - index);
     198           3 :   update (PADDING, padLen);
     199             : 
     200             :   // Append length (before padding)
     201           3 :   update (bits, 8);
     202             : 
     203             :   // Store state in digest
     204           3 :   encode (digest, state, 16);
     205             : 
     206             :   // Zeroize sensitive information
     207           3 :   memset (buffer, 0, sizeof(*buffer));
     208             : 
     209           3 :   finalized=1;
     210             : 
     211             : }
     212             : 
     213             : 
     214           3 : MD5::MD5(unsigned char* string){
     215             : 
     216           3 :   init();  // must be called be all constructors
     217           3 :   update(string, strlen( (const char*)string ));
     218           3 :   finalize ();
     219           3 : }
     220             : 
     221             : 
     222             : 
     223           0 : MD5::MD5(FILE *file){
     224             : 
     225           0 :   init();  // must be called be all constructors
     226           0 :   update(file);
     227           0 :   finalize ();
     228           0 : }
     229             : 
     230             : 
     231             : 
     232             : 
     233           0 : MD5::MD5(std::istream& stream){
     234             : 
     235           0 :   init();  // must called by all constructors
     236           0 :   update (stream);
     237           0 :   finalize();
     238           0 : }
     239             : 
     240             : 
     241             : 
     242           0 : MD5::MD5(std::ifstream& stream){
     243             : 
     244           0 :   init();  // must called by all constructors
     245           0 :   update (stream);
     246           0 :   finalize();
     247           0 : }
     248             : 
     249             : 
     250             : 
     251           0 : unsigned char *MD5::raw_digest(){
     252             : 
     253           0 :   if (!finalized){
     254           0 :     LBERROR << "MD5::raw_digest:  Can't get digest if you haven't "<<
     255           0 :       "finalized the digest!" <<std::endl;
     256           0 :     return ( (unsigned char*) "");
     257             :   }
     258             : 
     259           0 :   uint1 *s = new uint1[16];
     260           0 :   memcpy(s, digest, 16);
     261           0 :   return s;
     262             : }
     263             : 
     264           3 : void MD5::raw_digest( uint64_t& high, uint64_t& low) const
     265             : {
     266           6 :     high = (uint64_t( digest[7] )<<0) | (uint64_t( digest[6] )<<8) |
     267           9 :            (uint64_t( digest[5] )<<16) | (uint64_t( digest[4] )<<24) |
     268           9 :            (uint64_t( digest[3] )<<32) | (uint64_t( digest[2] )<<40) |
     269           6 :            (uint64_t( digest[1] )<<48) | (uint64_t( digest[0] )<<56);
     270           6 :     low = (uint64_t( digest[15] )<<0) | (uint64_t( digest[14] )<<8) |
     271           9 :           (uint64_t( digest[13] )<<16) | (uint64_t( digest[12] )<<24) |
     272           9 :           (uint64_t( digest[11] )<<32) | (uint64_t( digest[10] )<<40) |
     273           6 :           (uint64_t( digest[9] )<<48) | (uint64_t( digest[8] )<<56);
     274           3 : }
     275             : 
     276             : 
     277           0 : const char *MD5::hex_digest(){
     278             : 
     279           0 :   if (!finalized){
     280           0 :     LBERROR << "MD5::hex_digest:  Can't get digest if you haven't "<<
     281           0 :       "finalized the digest!" <<std::endl;
     282           0 :     return "";
     283             :   }
     284             : 
     285           0 :   char *s= new char[33];
     286           0 :   for (int i=0; i<16; i++)
     287           0 :     sprintf(s+i*2, "%02x", digest[i]);
     288             : 
     289           0 :   s[32]='\0';
     290             : 
     291           0 :   return s;
     292             : }
     293             : 
     294             : 
     295             : 
     296             : 
     297             : 
     298           0 : std::ostream& operator<<(std::ostream &stream, MD5 context){
     299             : 
     300           0 :   stream << context.hex_digest();
     301           0 :   return stream;
     302             : }
     303             : 
     304             : 
     305             : 
     306             : 
     307             : // PRIVATE METHODS:
     308             : 
     309             : 
     310             : 
     311           3 : void MD5::init(){
     312           3 :   finalized=0;  // we just started!
     313             : 
     314             :   // Nothing counted, so count=0
     315           3 :   count[0] = 0;
     316           3 :   count[1] = 0;
     317             : 
     318             :   // Load magic initialization constants.
     319           3 :   state[0] = 0x67452301;
     320           3 :   state[1] = 0xefcdab89;
     321           3 :   state[2] = 0x98badcfe;
     322           3 :   state[3] = 0x10325476;
     323           3 : }
     324             : 
     325             : 
     326             : 
     327             : // Constants for MD5Transform routine.
     328             : // Although we could use C++ style constants, defines are actually better,
     329             : // since they let us easily evade scope clashes.
     330             : 
     331             : #define S11 7
     332             : #define S12 12
     333             : #define S13 17
     334             : #define S14 22
     335             : #define S21 5
     336             : #define S22 9
     337             : #define S23 14
     338             : #define S24 20
     339             : #define S31 4
     340             : #define S32 11
     341             : #define S33 16
     342             : #define S34 23
     343             : #define S41 6
     344             : #define S42 10
     345             : #define S43 15
     346             : #define S44 21
     347             : 
     348             : 
     349             : 
     350             : 
     351             : // MD5 basic transformation. Transforms state based on block.
     352           3 : void MD5::transform (uint1 block[64]){
     353             : 
     354           3 :   uint4 a = state[0], b = state[1], c = state[2], d = state[3], x[16];
     355             : 
     356           3 :   decode (x, block, 64);
     357             : 
     358           3 :   assert(!finalized);  // not just a user error, since the method is private
     359             : 
     360             :   /* Round 1 */
     361           3 :   FF (a, b, c, d, x[ 0], S11, 0xd76aa478); /* 1 */
     362           3 :   FF (d, a, b, c, x[ 1], S12, 0xe8c7b756); /* 2 */
     363           3 :   FF (c, d, a, b, x[ 2], S13, 0x242070db); /* 3 */
     364           3 :   FF (b, c, d, a, x[ 3], S14, 0xc1bdceee); /* 4 */
     365           3 :   FF (a, b, c, d, x[ 4], S11, 0xf57c0faf); /* 5 */
     366           3 :   FF (d, a, b, c, x[ 5], S12, 0x4787c62a); /* 6 */
     367           3 :   FF (c, d, a, b, x[ 6], S13, 0xa8304613); /* 7 */
     368           3 :   FF (b, c, d, a, x[ 7], S14, 0xfd469501); /* 8 */
     369           3 :   FF (a, b, c, d, x[ 8], S11, 0x698098d8); /* 9 */
     370           3 :   FF (d, a, b, c, x[ 9], S12, 0x8b44f7af); /* 10 */
     371           3 :   FF (c, d, a, b, x[10], S13, 0xffff5bb1); /* 11 */
     372           3 :   FF (b, c, d, a, x[11], S14, 0x895cd7be); /* 12 */
     373           3 :   FF (a, b, c, d, x[12], S11, 0x6b901122); /* 13 */
     374           3 :   FF (d, a, b, c, x[13], S12, 0xfd987193); /* 14 */
     375           3 :   FF (c, d, a, b, x[14], S13, 0xa679438e); /* 15 */
     376           3 :   FF (b, c, d, a, x[15], S14, 0x49b40821); /* 16 */
     377             : 
     378             :  /* Round 2 */
     379           3 :   GG (a, b, c, d, x[ 1], S21, 0xf61e2562); /* 17 */
     380           3 :   GG (d, a, b, c, x[ 6], S22, 0xc040b340); /* 18 */
     381           3 :   GG (c, d, a, b, x[11], S23, 0x265e5a51); /* 19 */
     382           3 :   GG (b, c, d, a, x[ 0], S24, 0xe9b6c7aa); /* 20 */
     383           3 :   GG (a, b, c, d, x[ 5], S21, 0xd62f105d); /* 21 */
     384           3 :   GG (d, a, b, c, x[10], S22,  0x2441453); /* 22 */
     385           3 :   GG (c, d, a, b, x[15], S23, 0xd8a1e681); /* 23 */
     386           3 :   GG (b, c, d, a, x[ 4], S24, 0xe7d3fbc8); /* 24 */
     387           3 :   GG (a, b, c, d, x[ 9], S21, 0x21e1cde6); /* 25 */
     388           3 :   GG (d, a, b, c, x[14], S22, 0xc33707d6); /* 26 */
     389           3 :   GG (c, d, a, b, x[ 3], S23, 0xf4d50d87); /* 27 */
     390           3 :   GG (b, c, d, a, x[ 8], S24, 0x455a14ed); /* 28 */
     391           3 :   GG (a, b, c, d, x[13], S21, 0xa9e3e905); /* 29 */
     392           3 :   GG (d, a, b, c, x[ 2], S22, 0xfcefa3f8); /* 30 */
     393           3 :   GG (c, d, a, b, x[ 7], S23, 0x676f02d9); /* 31 */
     394           3 :   GG (b, c, d, a, x[12], S24, 0x8d2a4c8a); /* 32 */
     395             : 
     396             :   /* Round 3 */
     397           3 :   HH (a, b, c, d, x[ 5], S31, 0xfffa3942); /* 33 */
     398           3 :   HH (d, a, b, c, x[ 8], S32, 0x8771f681); /* 34 */
     399           3 :   HH (c, d, a, b, x[11], S33, 0x6d9d6122); /* 35 */
     400           3 :   HH (b, c, d, a, x[14], S34, 0xfde5380c); /* 36 */
     401           3 :   HH (a, b, c, d, x[ 1], S31, 0xa4beea44); /* 37 */
     402           3 :   HH (d, a, b, c, x[ 4], S32, 0x4bdecfa9); /* 38 */
     403           3 :   HH (c, d, a, b, x[ 7], S33, 0xf6bb4b60); /* 39 */
     404           3 :   HH (b, c, d, a, x[10], S34, 0xbebfbc70); /* 40 */
     405           3 :   HH (a, b, c, d, x[13], S31, 0x289b7ec6); /* 41 */
     406           3 :   HH (d, a, b, c, x[ 0], S32, 0xeaa127fa); /* 42 */
     407           3 :   HH (c, d, a, b, x[ 3], S33, 0xd4ef3085); /* 43 */
     408           3 :   HH (b, c, d, a, x[ 6], S34,  0x4881d05); /* 44 */
     409           3 :   HH (a, b, c, d, x[ 9], S31, 0xd9d4d039); /* 45 */
     410           3 :   HH (d, a, b, c, x[12], S32, 0xe6db99e5); /* 46 */
     411           3 :   HH (c, d, a, b, x[15], S33, 0x1fa27cf8); /* 47 */
     412           3 :   HH (b, c, d, a, x[ 2], S34, 0xc4ac5665); /* 48 */
     413             : 
     414             :   /* Round 4 */
     415           3 :   II (a, b, c, d, x[ 0], S41, 0xf4292244); /* 49 */
     416           3 :   II (d, a, b, c, x[ 7], S42, 0x432aff97); /* 50 */
     417           3 :   II (c, d, a, b, x[14], S43, 0xab9423a7); /* 51 */
     418           3 :   II (b, c, d, a, x[ 5], S44, 0xfc93a039); /* 52 */
     419           3 :   II (a, b, c, d, x[12], S41, 0x655b59c3); /* 53 */
     420           3 :   II (d, a, b, c, x[ 3], S42, 0x8f0ccc92); /* 54 */
     421           3 :   II (c, d, a, b, x[10], S43, 0xffeff47d); /* 55 */
     422           3 :   II (b, c, d, a, x[ 1], S44, 0x85845dd1); /* 56 */
     423           3 :   II (a, b, c, d, x[ 8], S41, 0x6fa87e4f); /* 57 */
     424           3 :   II (d, a, b, c, x[15], S42, 0xfe2ce6e0); /* 58 */
     425           3 :   II (c, d, a, b, x[ 6], S43, 0xa3014314); /* 59 */
     426           3 :   II (b, c, d, a, x[13], S44, 0x4e0811a1); /* 60 */
     427           3 :   II (a, b, c, d, x[ 4], S41, 0xf7537e82); /* 61 */
     428           3 :   II (d, a, b, c, x[11], S42, 0xbd3af235); /* 62 */
     429           3 :   II (c, d, a, b, x[ 2], S43, 0x2ad7d2bb); /* 63 */
     430           3 :   II (b, c, d, a, x[ 9], S44, 0xeb86d391); /* 64 */
     431             : 
     432           3 :   state[0] += a;
     433           3 :   state[1] += b;
     434           3 :   state[2] += c;
     435           3 :   state[3] += d;
     436             : 
     437             :   // Zeroize sensitive information.
     438           3 :   memset ( (uint1 *) x, 0, sizeof(x));
     439             : 
     440           3 : }
     441             : 
     442             : 
     443             : 
     444             : // Encodes input (UINT4) into output (unsigned char). Assumes len is
     445             : // a multiple of 4.
     446           6 : void MD5::encode (uint1 *output, uint4 *input, size_t len) {
     447             : 
     448             :   unsigned int i, j;
     449             : 
     450          24 :   for (i = 0, j = 0; j < len; i++, j += 4) {
     451          18 :     output[j]   = (uint1)  (input[i] & 0xff);
     452          18 :     output[j+1] = (uint1) ((input[i] >> 8) & 0xff);
     453          18 :     output[j+2] = (uint1) ((input[i] >> 16) & 0xff);
     454          18 :     output[j+3] = (uint1) ((input[i] >> 24) & 0xff);
     455             :   }
     456           6 : }
     457             : 
     458             : 
     459             : 
     460             : 
     461             : // Decodes input (unsigned char) into output (UINT4). Assumes len is
     462             : // a multiple of 4.
     463           3 : void MD5::decode (uint4 *output, uint1 *input, size_t len){
     464             : 
     465             :   unsigned int i, j;
     466             : 
     467          51 :   for (i = 0, j = 0; j < len; i++, j += 4)
     468          96 :     output[i] = ((uint4)input[j]) | (((uint4)input[j+1]) << 8) |
     469          96 :       (((uint4)input[j+2]) << 16) | (((uint4)input[j+3]) << 24);
     470           3 : }
     471             : 
     472             : 
     473             : 
     474             : 
     475             : 
     476             : // Note: Replace "for loop" with standard memcpy if possible.
     477          12 : void MD5::memcpy (uint1 *output, uint1 *input, size_t len){
     478             : 
     479             :   unsigned int i;
     480             : 
     481         204 :   for (i = 0; i < len; i++)
     482         192 :     output[i] = input[i];
     483          12 : }
     484             : 
     485             : 
     486             : 
     487             : // Note: Replace "for loop" with standard memset if possible.
     488           6 : void MD5::memset (uint1 *output, uint1 value, size_t len){
     489             : 
     490             :   unsigned int i;
     491             : 
     492         201 :   for (i = 0; i < len; i++)
     493         195 :     output[i] = value;
     494           6 : }
     495             : 
     496             : 
     497             : 
     498             : // ROTATE_LEFT rotates x left n bits.
     499             : 
     500         192 : inline unsigned int MD5::rotate_left  (uint4 x, uint4 n){
     501         192 :   return (x << n) | (x >> (32-n))  ;
     502             : }
     503             : 
     504             : 
     505             : 
     506             : 
     507             : // F, G, H and I are basic MD5 functions.
     508             : 
     509          48 : inline unsigned int MD5::F            (uint4 x, uint4 y, uint4 z){
     510          48 :   return (x & y) | (~x & z);
     511             : }
     512             : 
     513          48 : inline unsigned int MD5::G            (uint4 x, uint4 y, uint4 z){
     514          48 :   return (x & z) | (y & ~z);
     515             : }
     516             : 
     517          48 : inline unsigned int MD5::H            (uint4 x, uint4 y, uint4 z){
     518          48 :   return x ^ y ^ z;
     519             : }
     520             : 
     521          48 : inline unsigned int MD5::I            (uint4 x, uint4 y, uint4 z){
     522          48 :   return y ^ (x | ~z);
     523             : }
     524             : 
     525             : 
     526             : 
     527             : // FF, GG, HH, and II transformations for rounds 1, 2, 3, and 4.
     528             : // Rotation is separate from addition to prevent recomputation.
     529             : 
     530             : 
     531          48 : inline void MD5::FF(uint4& a, uint4 b, uint4 c, uint4 d, uint4 x,
     532             :                     uint4  s, uint4 ac){
     533          48 :  a += F(b, c, d) + x + ac;
     534          48 :  a = rotate_left (a, s) +b;
     535          48 : }
     536             : 
     537          48 : inline void MD5::GG(uint4& a, uint4 b, uint4 c, uint4 d, uint4 x,
     538             :                     uint4 s, uint4 ac){
     539          48 :  a += G(b, c, d) + x + ac;
     540          48 :  a = rotate_left (a, s) +b;
     541          48 : }
     542             : 
     543          48 : inline void MD5::HH(uint4& a, uint4 b, uint4 c, uint4 d, uint4 x,
     544             :                     uint4 s, uint4 ac){
     545          48 :  a += H(b, c, d) + x + ac;
     546          48 :  a = rotate_left (a, s) +b;
     547          48 : }
     548             : 
     549          48 : inline void MD5::II(uint4& a, uint4 b, uint4 c, uint4 d, uint4 x,
     550             :                              uint4 s, uint4 ac){
     551          48 :  a += I(b, c, d) + x + ac;
     552          48 :  a = rotate_left (a, s) +b;
     553         135 : }

Generated by: LCOV version 1.10