2 * Copyright (C) 2012 Michael Brown <mbrown@fensystems.co.uk>.
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License as
6 * published by the Free Software Foundation; either version 2 of the
7 * License, or any later version.
9 * This program is distributed in the hope that it will be useful, but
10 * WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * General Public License for more details.
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
19 * You can also choose to distribute this program under the terms of
20 * the Unmodified Binary Distribution Licence (as given in the file
21 * COPYING.UBDL), provided that you have satisfied its requirements.
39 /** SHA-1 variables */
40 struct sha1_variables
{
41 /* This layout matches that of struct sha1_digest_data,
42 * allowing for efficient endianness-conversion,
50 } __attribute__ (( packed
));
53 * f(a,b,c,d) for steps 0 to 19
55 * @v v SHA-1 variables
58 static uint32_t sha1_f_0_19 ( struct sha1_variables
*v
) {
59 return ( ( v
->b
& v
->c
) | ( (~v
->b
) & v
->d
) );
63 * f(a,b,c,d) for steps 20 to 39 and 60 to 79
65 * @v v SHA-1 variables
68 static uint32_t sha1_f_20_39_60_79 ( struct sha1_variables
*v
) {
69 return ( v
->b
^ v
->c
^ v
->d
);
73 * f(a,b,c,d) for steps 40 to 59
75 * @v v SHA-1 variables
78 static uint32_t sha1_f_40_59 ( struct sha1_variables
*v
) {
79 return ( ( v
->b
& v
->c
) | ( v
->b
& v
->d
) | ( v
->c
& v
->d
) );
82 /** An SHA-1 step function */
85 * Calculate f(a,b,c,d)
87 * @v v SHA-1 variables
90 uint32_t ( * f
) ( struct sha1_variables
*v
);
96 static struct sha1_step sha1_steps
[4] = {
98 { .f
= sha1_f_0_19
, .k
= 0x5a827999 },
100 { .f
= sha1_f_20_39_60_79
, .k
= 0x6ed9eba1 },
102 { .f
= sha1_f_40_59
, .k
= 0x8f1bbcdc },
104 { .f
= sha1_f_20_39_60_79
, .k
= 0xca62c1d6 },
108 * Initialise SHA-1 algorithm
110 * @v ctx SHA-1 context
112 void sha1_init ( void *ctx
) {
113 struct sha1_context
*context
= ctx
;
115 context
->ddd
.dd
.digest
.h
[0] = cpu_to_be32 ( 0x67452301 );
116 context
->ddd
.dd
.digest
.h
[1] = cpu_to_be32 ( 0xefcdab89 );
117 context
->ddd
.dd
.digest
.h
[2] = cpu_to_be32 ( 0x98badcfe );
118 context
->ddd
.dd
.digest
.h
[3] = cpu_to_be32 ( 0x10325476 );
119 context
->ddd
.dd
.digest
.h
[4] = cpu_to_be32 ( 0xc3d2e1f0 );
124 * Calculate SHA-1 digest of accumulated data
126 * @v context SHA-1 context
128 static void sha1_digest ( struct sha1_context
*context
) {
130 union sha1_digest_data_dwords ddd
;
131 struct sha1_variables v
;
133 uint32_t *a
= &u
.v
.a
;
134 uint32_t *b
= &u
.v
.b
;
135 uint32_t *c
= &u
.v
.c
;
136 uint32_t *d
= &u
.v
.d
;
137 uint32_t *e
= &u
.v
.e
;
142 struct sha1_step
*step
;
145 /* Convert h[0..4] to host-endian, and initialise a, b, c, d,
148 for ( i
= 0 ; i
< ( sizeof ( u
.ddd
.dword
) /
149 sizeof ( u
.ddd
.dword
[0] ) ) ; i
++ ) {
150 be32_to_cpus ( &context
->ddd
.dword
[i
] );
151 u
.ddd
.dword
[i
] = context
->ddd
.dword
[i
];
154 /* Initialise w[16..79] */
155 for ( i
= 16 ; i
< 80 ; i
++ )
156 w
[i
] = rol32 ( ( w
[i
-3] ^ w
[i
-8] ^ w
[i
-14] ^ w
[i
-16] ), 1 );
159 for ( i
= 0 ; i
< 80 ; i
++ ) {
160 step
= &sha1_steps
[ i
/ 20 ];
161 f
= step
->f ( &u
.v
);
163 temp
= ( rol32 ( *a
, 5 ) + f
+ *e
+ k
+ w
[i
] );
166 *c
= rol32 ( *b
, 30 );
171 /* Add chunk to hash and convert back to big-endian */
172 for ( i
= 0 ; i
< 5 ; i
++ ) {
173 context
->ddd
.dd
.digest
.h
[i
] =
174 cpu_to_be32 ( context
->ddd
.dd
.digest
.h
[i
] +
175 u
.ddd
.dd
.digest
.h
[i
] );
180 * Accumulate data with SHA-1 algorithm
182 * @v ctx SHA-1 context
184 * @v len Length of data
186 void sha1_update ( void *ctx
, const void *data
, size_t len
) {
187 struct sha1_context
*context
= ctx
;
188 const uint8_t *byte
= data
;
191 /* Accumulate data a byte at a time, performing the digest
192 * whenever we fill the data buffer
195 offset
= ( context
->len
% sizeof ( context
->ddd
.dd
.data
) );
196 context
->ddd
.dd
.data
.byte
[offset
] = *(byte
++);
198 if ( ( context
->len
% sizeof ( context
->ddd
.dd
.data
) ) == 0 )
199 sha1_digest ( context
);
204 * Generate SHA-1 digest
206 * @v ctx SHA-1 context
207 * @v out Output buffer
209 void sha1_final ( void *ctx
, void *out
) {
210 struct sha1_context
*context
= ctx
;
214 /* Record length before pre-processing */
215 len_bits
= cpu_to_be64 ( ( ( uint64_t ) context
->len
) * 8 );
217 /* Pad with a single "1" bit followed by as many "0" bits as required */
220 sha1_update ( ctx
, &pad
, sizeof ( pad
) );
222 } while ( ( context
->len
% sizeof ( context
->ddd
.dd
.data
) ) !=
223 offsetof ( typeof ( context
->ddd
.dd
.data
), final
.len
) );
225 /* Append length (in bits) */
226 sha1_update ( ctx
, &len_bits
, sizeof ( len_bits
) );
227 assert ( ( context
->len
% sizeof ( context
->ddd
.dd
.data
) ) == 0 );
229 /* Copy out final digest */
230 memcpy ( out
, &context
->ddd
.dd
.digest
,
231 sizeof ( context
->ddd
.dd
.digest
) );