LCOV - code coverage report
Current view: top level - src/util - sha1.cpp (source / functions) Hit Total Coverage
Test: report Lines: 87 93 93.5 %
Date: 2015-07-11 18:23:49 Functions: 7 8 87.5 %

          Line data    Source code
       1             : /* sha1.cpp
       2             : 
       3             : Copyright (c) 2005 Michael D. Leonhard
       4             : 
       5             : http://tamale.net/
       6             : 
       7             : Permission is hereby granted, free of charge, to any person obtaining a copy of
       8             : this software and associated documentation files (the "Software"), to deal in
       9             : the Software without restriction, including without limitation the rights to
      10             : use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
      11             : of the Software, and to permit persons to whom the Software is furnished to do
      12             : so, subject to the following conditions:
      13             : 
      14             : The above copyright notice and this permission notice shall be included in all
      15             : copies or substantial portions of the Software.
      16             : 
      17             : THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
      18             : IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
      19             : FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
      20             : AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
      21             : LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
      22             : OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
      23             : SOFTWARE.
      24             : 
      25             : */
      26             : 
      27             : #include <stdio.h>
      28             : #include <string.h>
      29             : #include <stdlib.h>
      30             : #include <assert.h>
      31             : 
      32             : #include "sha1.h"
      33             : 
      34             : // print out memory in hexadecimal
      35           0 : void SHA1::hexPrinter( unsigned char* c, int l )
      36             : {
      37             :         assert( c );
      38             :         assert( l > 0 );
      39           0 :         while( l > 0 )
      40             :         {
      41           0 :                 printf( " %02x", *c );
      42           0 :                 l--;
      43           0 :                 c++;
      44             :         }
      45           0 : }
      46             : 
      47             : // circular left bit rotation.  MSB wraps around to LSB
      48    45799712 : Uint32 SHA1::lrot( Uint32 x, int bits )
      49             : {
      50    45799712 :         return (x<<bits) | (x>>(32 - bits));
      51             : };
      52             : 
      53             : // Save a 32-bit unsigned integer to memory, in big-endian order
      54       18445 : void SHA1::storeBigEndianUint32( unsigned char* byte, Uint32 num )
      55             : {
      56             :         assert( byte );
      57       18445 :         byte[0] = (unsigned char)(num>>24);
      58       18445 :         byte[1] = (unsigned char)(num>>16);
      59       18445 :         byte[2] = (unsigned char)(num>>8);
      60       18445 :         byte[3] = (unsigned char)num;
      61       18445 : }
      62             : 
      63             : 
      64             : // Constructor *******************************************************
      65        2635 : SHA1::SHA1()
      66             : {
      67             :         // make sure that the data type is the right size
      68             :         assert( sizeof( Uint32 ) * 5 == 20 );
      69             :         
      70             :         // initialize
      71        2635 :         H0 = 0x67452301;
      72        2635 :         H1 = 0xefcdab89;
      73        2635 :         H2 = 0x98badcfe;
      74        2635 :         H3 = 0x10325476;
      75        2635 :         H4 = 0xc3d2e1f0;
      76        2635 :         unprocessedBytes = 0;
      77        2635 :         size = 0;
      78        2635 : }
      79             : 
      80             : // Destructor ********************************************************
      81        5270 : SHA1::~SHA1()
      82             : {
      83             :         // erase data
      84        2635 :         H0 = H1 = H2 = H3 = H4 = 0;
      85        2635 :         for( int c = 0; c < 64; c++ ) bytes[c] = 0;
      86        2635 :         unprocessedBytes = size = 0;
      87        2635 : }
      88             : 
      89             : // process ***********************************************************
      90      204463 : void SHA1::process()
      91             : {
      92             :         assert( unprocessedBytes == 64 );
      93             :         //printf( "process: " ); hexPrinter( bytes, 64 ); printf( "\n" );
      94             :         int t;
      95             :         Uint32 a, b, c, d, e, K, f, W[80];
      96             :         // starting values
      97      204463 :         a = H0;
      98      204463 :         b = H1;
      99      204463 :         c = H2;
     100      204463 :         d = H3;
     101      204463 :         e = H4;
     102             :         // copy and expand the message block
     103     3475871 :         for( t = 0; t < 16; t++ ) W[t] = (bytes[t*4] << 24)
     104     3271408 :                                                                         +(bytes[t*4 + 1] << 16)
     105     3271408 :                                                                         +(bytes[t*4 + 2] << 8)
     106     3271408 :                                                                         + bytes[t*4 + 3];
     107    13290095 :         for(; t< 80; t++ ) W[t] = lrot( W[t-3]^W[t-8]^W[t-14]^W[t-16], 1 );
     108             :         
     109             :         /* main loop */
     110             :         Uint32 temp;
     111    16561503 :         for( t = 0; t < 80; t++ )
     112             :         {
     113    16357040 :                 if( t < 20 ) {
     114     4089260 :                         K = 0x5a827999;
     115     4089260 :                         f = (b & c) | ((b ^ 0xFFFFFFFF) & d);//TODO: try using ~
     116    12267780 :                 } else if( t < 40 ) {
     117     4089260 :                         K = 0x6ed9eba1;
     118     4089260 :                         f = b ^ c ^ d;
     119     8178520 :                 } else if( t < 60 ) {
     120     4089260 :                         K = 0x8f1bbcdc;
     121     4089260 :                         f = (b & c) | (b & d) | (c & d);
     122             :                 } else {
     123     4089260 :                         K = 0xca62c1d6;
     124     4089260 :                         f = b ^ c ^ d;
     125             :                 }
     126    16357040 :                 temp = lrot(a,5) + f + e + W[t] + K;
     127    16357040 :                 e = d;
     128    16357040 :                 d = c;
     129    16357040 :                 c = lrot(b,30);
     130    16357040 :                 b = a;
     131    16357040 :                 a = temp;
     132             :                 //printf( "t=%d %08x %08x %08x %08x %08x\n",t,a,b,c,d,e );
     133             :         }
     134             :         /* add variables */
     135      204463 :         H0 += a;
     136      204463 :         H1 += b;
     137      204463 :         H2 += c;
     138      204463 :         H3 += d;
     139      204463 :         H4 += e;
     140             :         //printf( "Current: %08x %08x %08x %08x %08x\n",H0,H1,H2,H3,H4 );
     141             :         /* all bytes have been processed */
     142      204463 :         unprocessedBytes = 0;
     143      204463 : }
     144             : 
     145             : // addBytes **********************************************************
     146        8150 : void SHA1::addBytes( const char* data, int num )
     147             : {
     148             :         assert( data );
     149             :         assert( num >= 0 );
     150             :         // add these bytes to the running total
     151        8150 :         size += num;
     152             :         // repeat until all data is processed
     153      427474 :         while( num > 0 )
     154             :         {
     155             :                 // number of bytes required to complete block
     156      209662 :                 int needed = 64 - unprocessedBytes;
     157             :                 assert( needed > 0 );
     158             :                 // number of bytes to copy (use smaller of two)
     159      209662 :                 int toCopy = (num < needed) ? num : needed;
     160             :                 // Copy the bytes
     161      209662 :                 memcpy( bytes + unprocessedBytes, data, toCopy );
     162             :                 // Bytes have been copied
     163      209662 :                 num -= toCopy;
     164      209662 :                 data += toCopy;
     165      209662 :                 unprocessedBytes += toCopy;
     166             :                 
     167             :                 // there is a full block
     168      209662 :                 if( unprocessedBytes == 64 ) process();
     169             :         }
     170        8150 : }
     171             : 
     172             : // digest ************************************************************
     173        2635 : unsigned char* SHA1::getDigest()
     174             : {
     175             :         // save the message size
     176        2635 :         Uint32 totalBitsL = size << 3;
     177        2635 :         Uint32 totalBitsH = size >> 29;
     178             :         // add 0x80 to the message
     179        2635 :         addBytes( "\x80", 1 );
     180             :         
     181             :         unsigned char footer[64] = {
     182             :                 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,
     184             :                 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
     185        2635 :                 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
     186             :         // block has no room for 8-byte filesize, so finish it
     187        2635 :         if( unprocessedBytes > 56 )
     188         245 :                 addBytes( (char*)footer, 64 - unprocessedBytes);
     189             :         assert( unprocessedBytes <= 56 );
     190             :         // how many zeros do we need
     191        2635 :         int neededZeros = 56 - unprocessedBytes;
     192             :         // store file size (in bits) in big-endian format
     193        2635 :         storeBigEndianUint32( footer + neededZeros    , totalBitsH );
     194        2635 :         storeBigEndianUint32( footer + neededZeros + 4, totalBitsL );
     195             :         // finish the final block
     196        2635 :         addBytes( (char*)footer, neededZeros + 8 );
     197             :         // allocate memory for the digest bytes
     198        2635 :         unsigned char* digest = (unsigned char*)malloc( 20 );
     199             :         // copy the digest bytes
     200        2635 :         storeBigEndianUint32( digest, H0 );
     201        2635 :         storeBigEndianUint32( digest + 4, H1 );
     202        2635 :         storeBigEndianUint32( digest + 8, H2 );
     203        2635 :         storeBigEndianUint32( digest + 12, H3 );
     204        2635 :         storeBigEndianUint32( digest + 16, H4 );
     205             :         // return the digest
     206        2635 :         return digest;
     207             : }

Generated by: LCOV version 1.11