| 1 | /* |
| 2 | * The following code was taken directly from drivers/char/random.c |
| 3 | * in the Linux kernel. |
| 4 | */ |
| 5 | |
| 6 | #include "ssh.h" |
| 7 | |
| 8 | /* |
| 9 | * SHA transform algorithm, taken from code written by Peter Gutman, |
| 10 | * and apparently in the public domain. |
| 11 | */ |
| 12 | |
| 13 | /* The SHA f()-functions. */ |
| 14 | |
| 15 | #define f1(x,y,z) ( z ^ ( x & ( y ^ z ) ) ) /* Rounds 0-19 */ |
| 16 | #define f2(x,y,z) ( x ^ y ^ z ) /* Rounds 20-39 */ |
| 17 | #define f3(x,y,z) ( ( x & y ) | ( z & ( x | y ) ) ) /* Rounds 40-59 */ |
| 18 | #define f4(x,y,z) ( x ^ y ^ z ) /* Rounds 60-79 */ |
| 19 | |
| 20 | /* The SHA Mysterious Constants */ |
| 21 | |
| 22 | #define K1 0x5A827999L /* Rounds 0-19 */ |
| 23 | #define K2 0x6ED9EBA1L /* Rounds 20-39 */ |
| 24 | #define K3 0x8F1BBCDCL /* Rounds 40-59 */ |
| 25 | #define K4 0xCA62C1D6L /* Rounds 60-79 */ |
| 26 | |
| 27 | #define ROTL(n,X) ( ( ( X ) << n ) | ( ( X ) >> ( 32 - n ) ) ) |
| 28 | |
| 29 | #define expand(W,i) ( W[ i & 15 ] = \ |
| 30 | ROTL( 1, ( W[ i & 15 ] ^ W[ (i - 14) & 15 ] ^ \ |
| 31 | W[ (i - 8) & 15 ] ^ W[ (i - 3) & 15 ] ) ) ) |
| 32 | |
| 33 | #define subRound(a, b, c, d, e, f, k, data) \ |
| 34 | ( e += ROTL( 5, a ) + f( b, c, d ) + k + data, b = ROTL( 30, b ) ) |
| 35 | |
| 36 | |
| 37 | void SHATransform(word32 *digest, word32 *data) |
| 38 | { |
| 39 | word32 A, B, C, D, E; /* Local vars */ |
| 40 | word32 eData[ 16 ]; /* Expanded data */ |
| 41 | |
| 42 | /* Set up first buffer and local data buffer */ |
| 43 | A = digest[ 0 ]; |
| 44 | B = digest[ 1 ]; |
| 45 | C = digest[ 2 ]; |
| 46 | D = digest[ 3 ]; |
| 47 | E = digest[ 4 ]; |
| 48 | memcpy( eData, data, 16*sizeof(word32)); |
| 49 | |
| 50 | /* Heavy mangling, in 4 sub-rounds of 20 iterations each. */ |
| 51 | subRound( A, B, C, D, E, f1, K1, eData[ 0 ] ); |
| 52 | subRound( E, A, B, C, D, f1, K1, eData[ 1 ] ); |
| 53 | subRound( D, E, A, B, C, f1, K1, eData[ 2 ] ); |
| 54 | subRound( C, D, E, A, B, f1, K1, eData[ 3 ] ); |
| 55 | subRound( B, C, D, E, A, f1, K1, eData[ 4 ] ); |
| 56 | subRound( A, B, C, D, E, f1, K1, eData[ 5 ] ); |
| 57 | subRound( E, A, B, C, D, f1, K1, eData[ 6 ] ); |
| 58 | subRound( D, E, A, B, C, f1, K1, eData[ 7 ] ); |
| 59 | subRound( C, D, E, A, B, f1, K1, eData[ 8 ] ); |
| 60 | subRound( B, C, D, E, A, f1, K1, eData[ 9 ] ); |
| 61 | subRound( A, B, C, D, E, f1, K1, eData[ 10 ] ); |
| 62 | subRound( E, A, B, C, D, f1, K1, eData[ 11 ] ); |
| 63 | subRound( D, E, A, B, C, f1, K1, eData[ 12 ] ); |
| 64 | subRound( C, D, E, A, B, f1, K1, eData[ 13 ] ); |
| 65 | subRound( B, C, D, E, A, f1, K1, eData[ 14 ] ); |
| 66 | subRound( A, B, C, D, E, f1, K1, eData[ 15 ] ); |
| 67 | subRound( E, A, B, C, D, f1, K1, expand( eData, 16 ) ); |
| 68 | subRound( D, E, A, B, C, f1, K1, expand( eData, 17 ) ); |
| 69 | subRound( C, D, E, A, B, f1, K1, expand( eData, 18 ) ); |
| 70 | subRound( B, C, D, E, A, f1, K1, expand( eData, 19 ) ); |
| 71 | |
| 72 | subRound( A, B, C, D, E, f2, K2, expand( eData, 20 ) ); |
| 73 | subRound( E, A, B, C, D, f2, K2, expand( eData, 21 ) ); |
| 74 | subRound( D, E, A, B, C, f2, K2, expand( eData, 22 ) ); |
| 75 | subRound( C, D, E, A, B, f2, K2, expand( eData, 23 ) ); |
| 76 | subRound( B, C, D, E, A, f2, K2, expand( eData, 24 ) ); |
| 77 | subRound( A, B, C, D, E, f2, K2, expand( eData, 25 ) ); |
| 78 | subRound( E, A, B, C, D, f2, K2, expand( eData, 26 ) ); |
| 79 | subRound( D, E, A, B, C, f2, K2, expand( eData, 27 ) ); |
| 80 | subRound( C, D, E, A, B, f2, K2, expand( eData, 28 ) ); |
| 81 | subRound( B, C, D, E, A, f2, K2, expand( eData, 29 ) ); |
| 82 | subRound( A, B, C, D, E, f2, K2, expand( eData, 30 ) ); |
| 83 | subRound( E, A, B, C, D, f2, K2, expand( eData, 31 ) ); |
| 84 | subRound( D, E, A, B, C, f2, K2, expand( eData, 32 ) ); |
| 85 | subRound( C, D, E, A, B, f2, K2, expand( eData, 33 ) ); |
| 86 | subRound( B, C, D, E, A, f2, K2, expand( eData, 34 ) ); |
| 87 | subRound( A, B, C, D, E, f2, K2, expand( eData, 35 ) ); |
| 88 | subRound( E, A, B, C, D, f2, K2, expand( eData, 36 ) ); |
| 89 | subRound( D, E, A, B, C, f2, K2, expand( eData, 37 ) ); |
| 90 | subRound( C, D, E, A, B, f2, K2, expand( eData, 38 ) ); |
| 91 | subRound( B, C, D, E, A, f2, K2, expand( eData, 39 ) ); |
| 92 | |
| 93 | subRound( A, B, C, D, E, f3, K3, expand( eData, 40 ) ); |
| 94 | subRound( E, A, B, C, D, f3, K3, expand( eData, 41 ) ); |
| 95 | subRound( D, E, A, B, C, f3, K3, expand( eData, 42 ) ); |
| 96 | subRound( C, D, E, A, B, f3, K3, expand( eData, 43 ) ); |
| 97 | subRound( B, C, D, E, A, f3, K3, expand( eData, 44 ) ); |
| 98 | subRound( A, B, C, D, E, f3, K3, expand( eData, 45 ) ); |
| 99 | subRound( E, A, B, C, D, f3, K3, expand( eData, 46 ) ); |
| 100 | subRound( D, E, A, B, C, f3, K3, expand( eData, 47 ) ); |
| 101 | subRound( C, D, E, A, B, f3, K3, expand( eData, 48 ) ); |
| 102 | subRound( B, C, D, E, A, f3, K3, expand( eData, 49 ) ); |
| 103 | subRound( A, B, C, D, E, f3, K3, expand( eData, 50 ) ); |
| 104 | subRound( E, A, B, C, D, f3, K3, expand( eData, 51 ) ); |
| 105 | subRound( D, E, A, B, C, f3, K3, expand( eData, 52 ) ); |
| 106 | subRound( C, D, E, A, B, f3, K3, expand( eData, 53 ) ); |
| 107 | subRound( B, C, D, E, A, f3, K3, expand( eData, 54 ) ); |
| 108 | subRound( A, B, C, D, E, f3, K3, expand( eData, 55 ) ); |
| 109 | subRound( E, A, B, C, D, f3, K3, expand( eData, 56 ) ); |
| 110 | subRound( D, E, A, B, C, f3, K3, expand( eData, 57 ) ); |
| 111 | subRound( C, D, E, A, B, f3, K3, expand( eData, 58 ) ); |
| 112 | subRound( B, C, D, E, A, f3, K3, expand( eData, 59 ) ); |
| 113 | |
| 114 | subRound( A, B, C, D, E, f4, K4, expand( eData, 60 ) ); |
| 115 | subRound( E, A, B, C, D, f4, K4, expand( eData, 61 ) ); |
| 116 | subRound( D, E, A, B, C, f4, K4, expand( eData, 62 ) ); |
| 117 | subRound( C, D, E, A, B, f4, K4, expand( eData, 63 ) ); |
| 118 | subRound( B, C, D, E, A, f4, K4, expand( eData, 64 ) ); |
| 119 | subRound( A, B, C, D, E, f4, K4, expand( eData, 65 ) ); |
| 120 | subRound( E, A, B, C, D, f4, K4, expand( eData, 66 ) ); |
| 121 | subRound( D, E, A, B, C, f4, K4, expand( eData, 67 ) ); |
| 122 | subRound( C, D, E, A, B, f4, K4, expand( eData, 68 ) ); |
| 123 | subRound( B, C, D, E, A, f4, K4, expand( eData, 69 ) ); |
| 124 | subRound( A, B, C, D, E, f4, K4, expand( eData, 70 ) ); |
| 125 | subRound( E, A, B, C, D, f4, K4, expand( eData, 71 ) ); |
| 126 | subRound( D, E, A, B, C, f4, K4, expand( eData, 72 ) ); |
| 127 | subRound( C, D, E, A, B, f4, K4, expand( eData, 73 ) ); |
| 128 | subRound( B, C, D, E, A, f4, K4, expand( eData, 74 ) ); |
| 129 | subRound( A, B, C, D, E, f4, K4, expand( eData, 75 ) ); |
| 130 | subRound( E, A, B, C, D, f4, K4, expand( eData, 76 ) ); |
| 131 | subRound( D, E, A, B, C, f4, K4, expand( eData, 77 ) ); |
| 132 | subRound( C, D, E, A, B, f4, K4, expand( eData, 78 ) ); |
| 133 | subRound( B, C, D, E, A, f4, K4, expand( eData, 79 ) ); |
| 134 | |
| 135 | /* Build message digest */ |
| 136 | digest[ 0 ] += A; |
| 137 | digest[ 1 ] += B; |
| 138 | digest[ 2 ] += C; |
| 139 | digest[ 3 ] += D; |
| 140 | digest[ 4 ] += E; |
| 141 | } |