Esempio n. 1
0
static void md5_calc(const uint8_t *b64, md5_ctxt * ctxt)
{
	uint32_t A = ctxt->md5_sta;
	uint32_t B = ctxt->md5_stb;
	uint32_t C = ctxt->md5_stc;
	uint32_t D = ctxt->md5_std;
#if (BYTE_ORDER == LITTLE_ENDIAN)
	const uint32_t *X = (const uint32_t *)b64;
#elif (BYTE_ORDER == BIG_ENDIAN)
	uint32_t X[16];
#endif
	if (BYTE_ORDER == BIG_ENDIAN)
	  {
	    /* 4 byte words */
	    /* what a brute force but fast! */
	    uint8_t *y = (uint8_t *)X;
	    y[ 0] = b64[ 3]; y[ 1] = b64[ 2]; y[ 2] = b64[ 1]; y[ 3] = b64[ 0];
	    y[ 4] = b64[ 7]; y[ 5] = b64[ 6]; y[ 6] = b64[ 5]; y[ 7] = b64[ 4];
	    y[ 8] = b64[11]; y[ 9] = b64[10]; y[10] = b64[ 9]; y[11] = b64[ 8];
	    y[12] = b64[15]; y[13] = b64[14]; y[14] = b64[13]; y[15] = b64[12];
	    y[16] = b64[19]; y[17] = b64[18]; y[18] = b64[17]; y[19] = b64[16];
	    y[20] = b64[23]; y[21] = b64[22]; y[22] = b64[21]; y[23] = b64[20];
	    y[24] = b64[27]; y[25] = b64[26]; y[26] = b64[25]; y[27] = b64[24];
	    y[28] = b64[31]; y[29] = b64[30]; y[30] = b64[29]; y[31] = b64[28];
	    y[32] = b64[35]; y[33] = b64[34]; y[34] = b64[33]; y[35] = b64[32];
	    y[36] = b64[39]; y[37] = b64[38]; y[38] = b64[37]; y[39] = b64[36];
	    y[40] = b64[43]; y[41] = b64[42]; y[42] = b64[41]; y[43] = b64[40];
	    y[44] = b64[47]; y[45] = b64[46]; y[46] = b64[45]; y[47] = b64[44];
	    y[48] = b64[51]; y[49] = b64[50]; y[50] = b64[49]; y[51] = b64[48];
	    y[52] = b64[55]; y[53] = b64[54]; y[54] = b64[53]; y[55] = b64[52];
	    y[56] = b64[59]; y[57] = b64[58]; y[58] = b64[57]; y[59] = b64[56];
	    y[60] = b64[63]; y[61] = b64[62]; y[62] = b64[61]; y[63] = b64[60];
	  }

	ROUND1(A, B, C, D,  0, Sa,  1); ROUND1(D, A, B, C,  1, Sb,  2);
	ROUND1(C, D, A, B,  2, Sc,  3); ROUND1(B, C, D, A,  3, Sd,  4);
	ROUND1(A, B, C, D,  4, Sa,  5); ROUND1(D, A, B, C,  5, Sb,  6);
	ROUND1(C, D, A, B,  6, Sc,  7); ROUND1(B, C, D, A,  7, Sd,  8);
	ROUND1(A, B, C, D,  8, Sa,  9); ROUND1(D, A, B, C,  9, Sb, 10);
	ROUND1(C, D, A, B, 10, Sc, 11); ROUND1(B, C, D, A, 11, Sd, 12);
	ROUND1(A, B, C, D, 12, Sa, 13); ROUND1(D, A, B, C, 13, Sb, 14);
	ROUND1(C, D, A, B, 14, Sc, 15); ROUND1(B, C, D, A, 15, Sd, 16);
	
	ROUND2(A, B, C, D,  1, Se, 17); ROUND2(D, A, B, C,  6, Sf, 18);
	ROUND2(C, D, A, B, 11, Sg, 19); ROUND2(B, C, D, A,  0, Sh, 20);
	ROUND2(A, B, C, D,  5, Se, 21); ROUND2(D, A, B, C, 10, Sf, 22);
	ROUND2(C, D, A, B, 15, Sg, 23); ROUND2(B, C, D, A,  4, Sh, 24);
	ROUND2(A, B, C, D,  9, Se, 25); ROUND2(D, A, B, C, 14, Sf, 26);
	ROUND2(C, D, A, B,  3, Sg, 27); ROUND2(B, C, D, A,  8, Sh, 28);
	ROUND2(A, B, C, D, 13, Se, 29); ROUND2(D, A, B, C,  2, Sf, 30);
	ROUND2(C, D, A, B,  7, Sg, 31); ROUND2(B, C, D, A, 12, Sh, 32);

	ROUND3(A, B, C, D,  5, Si, 33); ROUND3(D, A, B, C,  8, Sj, 34);
	ROUND3(C, D, A, B, 11, Sk, 35); ROUND3(B, C, D, A, 14, Sl, 36);
	ROUND3(A, B, C, D,  1, Si, 37); ROUND3(D, A, B, C,  4, Sj, 38);
	ROUND3(C, D, A, B,  7, Sk, 39); ROUND3(B, C, D, A, 10, Sl, 40);
	ROUND3(A, B, C, D, 13, Si, 41); ROUND3(D, A, B, C,  0, Sj, 42);
	ROUND3(C, D, A, B,  3, Sk, 43); ROUND3(B, C, D, A,  6, Sl, 44);
	ROUND3(A, B, C, D,  9, Si, 45); ROUND3(D, A, B, C, 12, Sj, 46);
	ROUND3(C, D, A, B, 15, Sk, 47); ROUND3(B, C, D, A,  2, Sl, 48);
	
	ROUND4(A, B, C, D,  0, Sm, 49); ROUND4(D, A, B, C,  7, Sn, 50);	
	ROUND4(C, D, A, B, 14, So, 51); ROUND4(B, C, D, A,  5, Sp, 52);	
	ROUND4(A, B, C, D, 12, Sm, 53); ROUND4(D, A, B, C,  3, Sn, 54);	
	ROUND4(C, D, A, B, 10, So, 55); ROUND4(B, C, D, A,  1, Sp, 56);	
	ROUND4(A, B, C, D,  8, Sm, 57); ROUND4(D, A, B, C, 15, Sn, 58);	
	ROUND4(C, D, A, B,  6, So, 59); ROUND4(B, C, D, A, 13, Sp, 60);	
	ROUND4(A, B, C, D,  4, Sm, 61); ROUND4(D, A, B, C, 11, Sn, 62);	
	ROUND4(C, D, A, B,  2, So, 63); ROUND4(B, C, D, A,  9, Sp, 64);

	ctxt->md5_sta += A;
	ctxt->md5_stb += B;
	ctxt->md5_stc += C;
	ctxt->md5_std += D;
}
Esempio n. 2
0
void md5_context_hash(struct MD5_CONTEXT *c,
        const unsigned char blk[MD5_BLOCK_SIZE])
{
MD5_WORD        x[16];
unsigned        i, j;
MD5_WORD        A, B, C, D;
MD5_WORD        zz;

        for (i=j=0; i<16; i++)
        {
        MD5_WORD        w=(MD5_WORD)blk[j++];

                w |= (MD5_WORD)blk[j++] << 8;
                w |= (MD5_WORD)blk[j++] << 16;
                w |= (MD5_WORD)blk[j++] << 24;
                x[i]= w;
        }

#define F(X,Y,Z)        ( ((X) & (Y)) | ( (~(X)) & (Z)))
#define G(X,Y,Z)        ( ((X) & (Z)) | ( (Y) & (~(Z))))
#define H(X,Y,Z)        ( (X) ^ (Y) ^ (Z) )
#define I(X,Y,Z)        ( (Y) ^ ( (X) | (~(Z))))

        A=c->A;
        B=c->B;
        C=c->C;
        D=c->D;

#define ROUND1(a,b,c,d,k,s,i)   \
        { zz=(a + F(b,c,d) + x[k] + T[i]); a=b+MD5_ROL(zz,s); }

        ROUND1(A,B,C,D,0,7,0);
        ROUND1(D,A,B,C,1,12,1);
        ROUND1(C,D,A,B,2,17,2);
        ROUND1(B,C,D,A,3,22,3);
        ROUND1(A,B,C,D,4,7,4);
        ROUND1(D,A,B,C,5,12,5);
        ROUND1(C,D,A,B,6,17,6);
        ROUND1(B,C,D,A,7,22,7);
        ROUND1(A,B,C,D,8,7,8);
        ROUND1(D,A,B,C,9,12,9);
        ROUND1(C,D,A,B,10,17,10);
        ROUND1(B,C,D,A,11,22,11);
        ROUND1(A,B,C,D,12,7,12);
        ROUND1(D,A,B,C,13,12,13);
        ROUND1(C,D,A,B,14,17,14);
        ROUND1(B,C,D,A,15,22,15);

#define ROUND2(a,b,c,d,k,s,i)   \
        { zz=(a + G(b,c,d) + x[k] + T[i]); a = b + MD5_ROL(zz,s); }

        ROUND2(A,B,C,D,1,5,16);
        ROUND2(D,A,B,C,6,9,17);
        ROUND2(C,D,A,B,11,14,18);
        ROUND2(B,C,D,A,0,20,19);
        ROUND2(A,B,C,D,5,5,20);
        ROUND2(D,A,B,C,10,9,21);
        ROUND2(C,D,A,B,15,14,22);
        ROUND2(B,C,D,A,4,20,23);
        ROUND2(A,B,C,D,9,5,24);
        ROUND2(D,A,B,C,14,9,25);
        ROUND2(C,D,A,B,3,14,26);
        ROUND2(B,C,D,A,8,20,27);
        ROUND2(A,B,C,D,13,5,28);
        ROUND2(D,A,B,C,2,9,29);
        ROUND2(C,D,A,B,7,14,30);
        ROUND2(B,C,D,A,12,20,31);

#define ROUND3(a,b,c,d,k,s,i)   \
        { zz=(a + H(b,c,d) + x[k] + T[i]); a = b + MD5_ROL(zz,s); }

        ROUND3(A,B,C,D,5,4,32);
        ROUND3(D,A,B,C,8,11,33);
        ROUND3(C,D,A,B,11,16,34);
        ROUND3(B,C,D,A,14,23,35);
        ROUND3(A,B,C,D,1,4,36);
        ROUND3(D,A,B,C,4,11,37);
        ROUND3(C,D,A,B,7,16,38);
        ROUND3(B,C,D,A,10,23,39);
        ROUND3(A,B,C,D,13,4,40);
        ROUND3(D,A,B,C,0,11,41);
        ROUND3(C,D,A,B,3,16,42);
        ROUND3(B,C,D,A,6,23,43);
        ROUND3(A,B,C,D,9,4,44);
        ROUND3(D,A,B,C,12,11,45);
        ROUND3(C,D,A,B,15,16,46);
        ROUND3(B,C,D,A,2,23,47);

#define ROUND4(a,b,c,d,k,s,i)   \
        { zz=(a + I(b,c,d) + x[k] + T[i]); a = b + MD5_ROL(zz,s); }

        ROUND4(A,B,C,D,0,6,48);
        ROUND4(D,A,B,C,7,10,49);
        ROUND4(C,D,A,B,14,15,50);
        ROUND4(B,C,D,A,5,21,51);
        ROUND4(A,B,C,D,12,6,52);
        ROUND4(D,A,B,C,3,10,53);
        ROUND4(C,D,A,B,10,15,54);
        ROUND4(B,C,D,A,1,21,55);
        ROUND4(A,B,C,D,8,6,56);
        ROUND4(D,A,B,C,15,10,57);
        ROUND4(C,D,A,B,6,15,58);
        ROUND4(B,C,D,A,13,21,59);
        ROUND4(A,B,C,D,4,6,60);
        ROUND4(D,A,B,C,11,10,61);
        ROUND4(C,D,A,B,2,15,62);
        ROUND4(B,C,D,A,9,21,63);

        c->A += A;
        c->B += B;
        c->C += C;
        c->D += D;
}
Esempio n. 3
0
/* this applies md4 to 64 byte chunks */
static void
mdfour64(uint32 * M){
	int j;
	uint32 AA, BB, CC, DD;
	uint32 X[16];
	uint32 A, B, C, D;
	
	for(j = 0; j < 16; j++)
		X[j] = M[j];
		
	A = m->A;
	B = m->B;
	C = m->C;
	D = m->D;
	AA = A;
	BB = B;
	CC = C;
	DD = D;
	
	ROUND1(A, B, C, D, 0, 3);
	ROUND1(D, A, B, C, 1, 7);
	ROUND1(C, D, A, B, 2, 11);
	ROUND1(B, C, D, A, 3, 19);
	ROUND1(A, B, C, D, 4, 3);
	ROUND1(D, A, B, C, 5, 7);
	ROUND1(C, D, A, B, 6, 11);
	ROUND1(B, C, D, A, 7, 19);
	ROUND1(A, B, C, D, 8, 3);
	ROUND1(D, A, B, C, 9, 7);
	ROUND1(C, D, A, B, 10, 11);
	ROUND1(B, C, D, A, 11, 19);
	ROUND1(A, B, C, D, 12, 3);
	ROUND1(D, A, B, C, 13, 7);
	ROUND1(C, D, A, B, 14, 11);
	ROUND1(B, C, D, A, 15, 19);
	
	ROUND2(A, B, C, D, 0, 3);
	ROUND2(D, A, B, C, 4, 5);
	ROUND2(C, D, A, B, 8, 9);
	ROUND2(B, C, D, A, 12, 13);
	ROUND2(A, B, C, D, 1, 3);
	ROUND2(D, A, B, C, 5, 5);
	ROUND2(C, D, A, B, 9, 9);
	ROUND2(B, C, D, A, 13, 13);
	ROUND2(A, B, C, D, 2, 3);
	ROUND2(D, A, B, C, 6, 5);
	ROUND2(C, D, A, B, 10, 9);
	ROUND2(B, C, D, A, 14, 13);
	ROUND2(A, B, C, D, 3, 3);
	ROUND2(D, A, B, C, 7, 5);
	ROUND2(C, D, A, B, 11, 9);
	ROUND2(B, C, D, A, 15, 13);
	
	ROUND3(A, B, C, D, 0, 3);
	ROUND3(D, A, B, C, 8, 9);
	ROUND3(C, D, A, B, 4, 11);
	ROUND3(B, C, D, A, 12, 15);
	ROUND3(A, B, C, D, 2, 3);
	ROUND3(D, A, B, C, 10, 9);
	ROUND3(C, D, A, B, 6, 11);
	ROUND3(B, C, D, A, 14, 15);
	ROUND3(A, B, C, D, 1, 3);
	ROUND3(D, A, B, C, 9, 9);
	ROUND3(C, D, A, B, 5, 11);
	ROUND3(B, C, D, A, 13, 15);
	ROUND3(A, B, C, D, 3, 3);
	ROUND3(D, A, B, C, 11, 9);
	ROUND3(C, D, A, B, 7, 11);
	ROUND3(B, C, D, A, 15, 15);
	
	A += AA;
	B += BB;
	C += CC;
	D += DD;
	
#ifdef LARGE_INT32
	
	A &= 0xFFFFFFFF;
	B &= 0xFFFFFFFF;
	C &= 0xFFFFFFFF;
	D &= 0xFFFFFFFF;
#endif
	
	for(j = 0; j < 16; j++)
		X[j] = 0;
		
	m->A = A;
	m->B = B;
	m->C = C;
	m->D = D;
}
Esempio n. 4
0
/*
========================================================================
Routine Description:
    MD5 computation for one block (512 bits)

Arguments:
    pMD5_CTX        Pointer to Md5_CTX_STRUC

Return Value:
    None

Note:
    T[i] := floor(abs(sin(i + 1)) * (2 pow 32)), i is number of round
========================================================================
*/
VOID RT_MD5_Hash (
    IN  MD5_CTX_STRUC *pMD5_CTX)
{
    UINT32 X_i;
    UINT32 X[16];
    UINT32 a,b,c,d;
   
    /* Prepare the message schedule, {X_i} */
    NdisMoveMemory(X, pMD5_CTX->Block, MD5_BLOCK_SIZE);
    for (X_i = 0; X_i < 16; X_i++)
        X[X_i] = cpu2le32(X[X_i]); /* Endian Swap */
        /* End of for */
    
    /* MD5 hash computation */
    /* Initialize the working variables */
    a = pMD5_CTX->HashValue[0];
    b = pMD5_CTX->HashValue[1];
    c = pMD5_CTX->HashValue[2];
    d = pMD5_CTX->HashValue[3];

    /*
     *  Round 1
     *  Let [abcd k s i] denote the operation 
     *  a = b + ((a + F(b,c,d) + X[k] + T[i]) <<< s)
     */
    ROUND1(a, b, c, d, X[ 0],  7, 0xd76aa478); /* 1 */   
    ROUND1(d, a, b, c, X[ 1], 12, 0xe8c7b756); /* 2 */
    ROUND1(c, d, a, b, X[ 2], 17, 0x242070db); /* 3 */
    ROUND1(b, c, d, a, X[ 3], 22, 0xc1bdceee); /* 4 */
    ROUND1(a, b, c, d, X[ 4],  7, 0xf57c0faf); /* 5 */    
    ROUND1(d, a, b, c, X[ 5], 12, 0x4787c62a); /* 6 */
    ROUND1(c, d, a, b, X[ 6], 17, 0xa8304613); /* 7 */
    ROUND1(b, c, d, a, X[ 7], 22, 0xfd469501); /* 8 */
    ROUND1(a, b, c, d, X[ 8],  7, 0x698098d8); /* 9 */
    ROUND1(d, a, b, c, X[ 9], 12, 0x8b44f7af); /* 10 */
    ROUND1(c, d, a, b, X[10], 17, 0xffff5bb1); /* 11 */
    ROUND1(b, c, d, a, X[11], 22, 0x895cd7be); /* 12 */
    ROUND1(a, b, c, d, X[12],  7, 0x6b901122); /* 13 */
    ROUND1(d, a, b, c, X[13], 12, 0xfd987193); /* 14 */
    ROUND1(c, d, a, b, X[14], 17, 0xa679438e); /* 15 */
    ROUND1(b, c, d, a, X[15], 22, 0x49b40821); /* 16 */

    /*
     *  Round 2
     *  Let [abcd k s i] denote the operation 
     *  a = b + ((a + G(b,c,d) + X[k] + T[i]) <<< s)
     */
    ROUND2(a, b, c, d, X[ 1],  5, 0xf61e2562); /* 17 */
    ROUND2(d, a, b, c, X[ 6],  9, 0xc040b340); /* 18 */
    ROUND2(c, d, a, b, X[11], 14, 0x265e5a51); /* 19 */
    ROUND2(b, c, d, a, X[ 0], 20, 0xe9b6c7aa); /* 20 */
    ROUND2(a, b, c, d, X[ 5],  5, 0xd62f105d); /* 21 */
    ROUND2(d, a, b, c, X[10],  9,  0x2441453); /* 22 */
    ROUND2(c, d, a, b, X[15], 14, 0xd8a1e681); /* 23 */
    ROUND2(b, c, d, a, X[ 4], 20, 0xe7d3fbc8); /* 24 */
    ROUND2(a, b, c, d, X[ 9],  5, 0x21e1cde6); /* 25 */
    ROUND2(d, a, b, c, X[14],  9, 0xc33707d6); /* 26 */
    ROUND2(c, d, a, b, X[ 3], 14, 0xf4d50d87); /* 27 */ 
    ROUND2(b, c, d, a, X[ 8], 20, 0x455a14ed); /* 28 */
    ROUND2(a, b, c, d, X[13],  5, 0xa9e3e905); /* 29 */
    ROUND2(d, a, b, c, X[ 2],  9, 0xfcefa3f8); /* 30 */
    ROUND2(c, d, a, b, X[ 7], 14, 0x676f02d9); /* 31 */
    ROUND2(b, c, d, a, X[12], 20, 0x8d2a4c8a); /* 32 */ 

    /*
     *  Round 3
     *  Let [abcd k s t] denote the operation 
     *  a = b + ((a + H(b,c,d) + X[k] + T[i]) <<< s)
     */
    ROUND3(a, b, c, d, X[ 5],  4, 0xfffa3942); /* 33 */
    ROUND3(d, a, b, c, X[ 8], 11, 0x8771f681); /* 34 */
    ROUND3(c, d, a, b, X[11], 16, 0x6d9d6122); /* 35 */
    ROUND3(b, c, d, a, X[14], 23, 0xfde5380c); /* 36 */
    ROUND3(a, b, c, d, X[ 1],  4, 0xa4beea44); /* 37 */
    ROUND3(d, a, b, c, X[ 4], 11, 0x4bdecfa9); /* 38 */
    ROUND3(c, d, a, b, X[ 7], 16, 0xf6bb4b60); /* 39 */
    ROUND3(b, c, d, a, X[10], 23, 0xbebfbc70); /* 40 */
    ROUND3(a, b, c, d, X[13],  4, 0x289b7ec6); /* 41 */
    ROUND3(d, a, b, c, X[ 0], 11, 0xeaa127fa); /* 42 */
    ROUND3(c, d, a, b, X[ 3], 16, 0xd4ef3085); /* 43 */
    ROUND3(b, c, d, a, X[ 6], 23,  0x4881d05); /* 44 */
    ROUND3(a, b, c, d, X[ 9],  4, 0xd9d4d039); /* 45 */
    ROUND3(d, a, b, c, X[12], 11, 0xe6db99e5); /* 46 */
    ROUND3(c, d, a, b, X[15], 16, 0x1fa27cf8); /* 47 */
    ROUND3(b, c, d, a, X[ 2], 23, 0xc4ac5665); /* 48 */

    /*
     *  Round 4
     *  Let [abcd k s t] denote the operation 
     *  a = b + ((a + I(b,c,d) + X[k] + T[i]) <<< s)
     */
    ROUND4(a, b, c, d, X[ 0],  6, 0xf4292244); /* 49 */
    ROUND4(d, a, b, c, X[ 7], 10, 0x432aff97); /* 50 */
    ROUND4(c, d, a, b, X[14], 15, 0xab9423a7); /* 51 */
    ROUND4(b, c, d, a, X[ 5], 21, 0xfc93a039); /* 52 */
    ROUND4(a, b, c, d, X[12],  6, 0x655b59c3); /* 53 */
    ROUND4(d, a, b, c, X[ 3], 10, 0x8f0ccc92); /* 54 */
    ROUND4(c, d, a, b, X[10], 15, 0xffeff47d); /* 55 */
    ROUND4(b, c, d, a, X[ 1], 21, 0x85845dd1); /* 56 */
    ROUND4(a, b, c, d, X[ 8],  6, 0x6fa87e4f); /* 57 */
    ROUND4(d, a, b, c, X[15], 10, 0xfe2ce6e0); /* 58 */
    ROUND4(c, d, a, b, X[ 6], 15, 0xa3014314); /* 59 */
    ROUND4(b, c, d, a, X[13], 21, 0x4e0811a1); /* 60 */
    ROUND4(a, b, c, d, X[ 4],  6, 0xf7537e82); /* 61 */
    ROUND4(d, a, b, c, X[11], 10, 0xbd3af235); /* 62 */
    ROUND4(c, d, a, b, X[ 2], 15, 0x2ad7d2bb); /* 63 */
    ROUND4(b, c, d, a, X[ 9], 21, 0xeb86d391); /* 64 */  

    /* Compute the i^th intermediate hash value H^(i) */
    pMD5_CTX->HashValue[0] += a;
    pMD5_CTX->HashValue[1] += b;
    pMD5_CTX->HashValue[2] += c;
    pMD5_CTX->HashValue[3] += d;

    NdisZeroMemory(pMD5_CTX->Block, MD5_BLOCK_SIZE);
    pMD5_CTX->BlockLen = 0;
} /* End of RT_MD5_Hash */
Esempio n. 5
0
static void SHA1_block(SHA1_CTX *ctx)
/*
     Update the SHA-1 hash from a fresh 64 bytes of data.
*/
{ 
    static DWORDC sha1_round1 = 0x5A827999u; 
    static DWORDC sha1_round2 = 0x6ED9EBA1u;
    static DWORDC sha1_round3 = 0x8F1BBCDCu;
    static DWORDC sha1_round4 = 0xCA62C1D6u;
    
    DWORD a = ctx->partial_hash[0], b = ctx->partial_hash[1]; 
    DWORD c = ctx->partial_hash[2], d = ctx->partial_hash[3];
    DWORD e = ctx->partial_hash[4];
    DWORD  msg80[80]; 
    int i;
    BOOL OK = TRUE;

    for (i = 0; i != 16; i++) {   // Copy to local array, zero original
                                  // Extend length to 80
        DWORDC datval = ctx->awaiting_data[i];
        ctx->awaiting_data[i] = 0;
        msg80[i] = datval;
    }

    for (i = 16; i != 80; i += 2) {
        DWORDC temp1 =    msg80[i-3] ^ msg80[i-8] 
                        ^ msg80[i-14] ^ msg80[i-16];
        DWORDC temp2 =    msg80[i-2] ^ msg80[i-7] 
                        ^ msg80[i-13] ^ msg80[i-15];
        msg80[i  ] = ROTATE32L(temp1, 1);
        msg80[i+1] = ROTATE32L(temp2, 1);
    }
  
#define ROUND1(B, C, D) ((D ^ (B & (C ^ D))) + sha1_round1)
                        //  Equivalent to (B & C) | (~B & D).
                        //  (check cases B = 0 and B = 1)
#define ROUND2(B, C, D) ((B ^ C ^ D) + sha1_round2)

#define ROUND3(B, C, D) ((C & (B | D) | (B & D)) + sha1_round3)

#define ROUND4(B, C, D) ((B ^ C ^ D) + sha1_round4)

// Round 1
    for (i = 0; i != 20; i += 5) { 
        e += ROTATE32L(a, 5) + ROUND1(b, c, d) + msg80[i];
        b = ROTATE32L(b, 30);

        d += ROTATE32L(e, 5) + ROUND1(a, b, c) + msg80[i+1];
        a = ROTATE32L(a, 30);

        c += ROTATE32L(d, 5) + ROUND1(e, a, b) + msg80[i+2];
        e = ROTATE32L(e, 30);

        b += ROTATE32L(c, 5) + ROUND1(d, e, a) + msg80[i+3];
        d = ROTATE32L(d, 30);

        a += ROTATE32L(b, 5) + ROUND1(c, d, e) + msg80[i+4];
        c = ROTATE32L(c, 30);
#if 0
        printf("i = %ld %08lx %08lx %08lx %08lx %08lx\n", 
            i, a, b, c, d, e);
#endif
    } // for i

// Round 2
    for (i = 20; i != 40; i += 5) { 
        e += ROTATE32L(a, 5) + ROUND2(b, c, d) + msg80[i];
        b = ROTATE32L(b, 30);

        d += ROTATE32L(e, 5) + ROUND2(a, b, c) + msg80[i+1];
        a = ROTATE32L(a, 30);

        c += ROTATE32L(d, 5) + ROUND2(e, a, b) + msg80[i+2];
        e = ROTATE32L(e, 30);

        b += ROTATE32L(c, 5) + ROUND2(d, e, a) + msg80[i+3];
        d = ROTATE32L(d, 30);

        a += ROTATE32L(b, 5) + ROUND2(c, d, e) + msg80[i+4];
        c = ROTATE32L(c, 30);
    } // for i

// Round 3
    for (i = 40; i != 60; i += 5) { 
        e += ROTATE32L(a, 5) + ROUND3(b, c, d) + msg80[i];
        b = ROTATE32L(b, 30);

        d += ROTATE32L(e, 5) + ROUND3(a, b, c) + msg80[i+1];
        a = ROTATE32L(a, 30);

        c += ROTATE32L(d, 5) + ROUND3(e, a, b) + msg80[i+2];
        e = ROTATE32L(e, 30);

        b += ROTATE32L(c, 5) + ROUND3(d, e, a) + msg80[i+3];
        d = ROTATE32L(d, 30);

        a += ROTATE32L(b, 5) + ROUND3(c, d, e) + msg80[i+4];
        c = ROTATE32L(c, 30);
    } // for i

// Round 4
    for (i = 60; i != 80; i += 5) { 
        e += ROTATE32L(a, 5) + ROUND4(b, c, d) + msg80[i];
        b = ROTATE32L(b, 30);

        d += ROTATE32L(e, 5) + ROUND4(a, b, c) + msg80[i+1];
        a = ROTATE32L(a, 30);

        c += ROTATE32L(d, 5) + ROUND4(e, a, b) + msg80[i+2];
        e = ROTATE32L(e, 30);

        b += ROTATE32L(c, 5) + ROUND4(d, e, a) + msg80[i+3];
        d = ROTATE32L(d, 30);

        a += ROTATE32L(b, 5) + ROUND4(c, d, e) + msg80[i+4];
        c = ROTATE32L(c, 30);
    } // for i

#undef ROUND1
#undef ROUND2
#undef ROUND3
#undef ROUND4

    ctx->partial_hash[0] += a;
    ctx->partial_hash[1] += b;
    ctx->partial_hash[2] += c;
    ctx->partial_hash[3] += d;
    ctx->partial_hash[4] += e;
#if 0
    for (i = 0; i != 16; i++) {
        printf("%8lx ", msg16[i]);
        if ((i & 7) == 7) printf("\n");
    }
    printf("a, b, c, d, e = %08lx %08lx %08lx %08lx %08lx\n", 
        a, b, c, d, e);
    printf("Partial hash = %08lx %08lx %08lx %08lx %08lx\n",
        (long)ctx->partial_hash[0], (long)ctx->partial_hash[1],
        (long)ctx->partial_hash[2], (long)ctx->partial_hash[3],
        (long)ctx->partial_hash[4]);
#endif 
} // end SHA1_block