]> glassweightruler.freedombox.rocks Git - Ventoy.git/blob - wimboot/wimboot-2.7.3/src/sha1.c
added Spanish (Latinoamérica) translation (#1865)
[Ventoy.git] / wimboot / wimboot-2.7.3 / src / sha1.c
1 /*
2 * Copyright (C) 2012 Michael Brown <mbrown@fensystems.co.uk>.
3 *
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.
8 *
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.
13 *
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
17 * 02110-1301, USA.
18 *
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.
22 */
23
24 /**
25 * @file
26 *
27 * SHA-1 algorithm
28 *
29 */
30
31 #include <stddef.h>
32 #include <stdint.h>
33 #include <string.h>
34 #include <byteswap.h>
35 #include <assert.h>
36 #include "rotate.h"
37 #include "sha1.h"
38
39 /** SHA-1 variables */
40 struct sha1_variables {
41 /* This layout matches that of struct sha1_digest_data,
42 * allowing for efficient endianness-conversion,
43 */
44 uint32_t a;
45 uint32_t b;
46 uint32_t c;
47 uint32_t d;
48 uint32_t e;
49 uint32_t w[80];
50 } __attribute__ (( packed ));
51
52 /**
53 * f(a,b,c,d) for steps 0 to 19
54 *
55 * @v v SHA-1 variables
56 * @ret f f(a,b,c,d)
57 */
58 static uint32_t sha1_f_0_19 ( struct sha1_variables *v ) {
59 return ( ( v->b & v->c ) | ( (~v->b) & v->d ) );
60 }
61
62 /**
63 * f(a,b,c,d) for steps 20 to 39 and 60 to 79
64 *
65 * @v v SHA-1 variables
66 * @ret f f(a,b,c,d)
67 */
68 static uint32_t sha1_f_20_39_60_79 ( struct sha1_variables *v ) {
69 return ( v->b ^ v->c ^ v->d );
70 }
71
72 /**
73 * f(a,b,c,d) for steps 40 to 59
74 *
75 * @v v SHA-1 variables
76 * @ret f f(a,b,c,d)
77 */
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 ) );
80 }
81
82 /** An SHA-1 step function */
83 struct sha1_step {
84 /**
85 * Calculate f(a,b,c,d)
86 *
87 * @v v SHA-1 variables
88 * @ret f f(a,b,c,d)
89 */
90 uint32_t ( * f ) ( struct sha1_variables *v );
91 /** Constant k */
92 uint32_t k;
93 };
94
95 /** SHA-1 steps */
96 static struct sha1_step sha1_steps[4] = {
97 /** 0 to 19 */
98 { .f = sha1_f_0_19, .k = 0x5a827999 },
99 /** 20 to 39 */
100 { .f = sha1_f_20_39_60_79, .k = 0x6ed9eba1 },
101 /** 40 to 59 */
102 { .f = sha1_f_40_59, .k = 0x8f1bbcdc },
103 /** 60 to 79 */
104 { .f = sha1_f_20_39_60_79, .k = 0xca62c1d6 },
105 };
106
107 /**
108 * Initialise SHA-1 algorithm
109 *
110 * @v ctx SHA-1 context
111 */
112 void sha1_init ( void *ctx ) {
113 struct sha1_context *context = ctx;
114
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 );
120 context->len = 0;
121 }
122
123 /**
124 * Calculate SHA-1 digest of accumulated data
125 *
126 * @v context SHA-1 context
127 */
128 static void sha1_digest ( struct sha1_context *context ) {
129 union {
130 union sha1_digest_data_dwords ddd;
131 struct sha1_variables v;
132 } u;
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;
138 uint32_t *w = u.v.w;
139 uint32_t f;
140 uint32_t k;
141 uint32_t temp;
142 struct sha1_step *step;
143 unsigned int i;
144
145 /* Convert h[0..4] to host-endian, and initialise a, b, c, d,
146 * e, and w[0..15]
147 */
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];
152 }
153
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 );
157
158 /* Main loop */
159 for ( i = 0 ; i < 80 ; i++ ) {
160 step = &sha1_steps[ i / 20 ];
161 f = step->f ( &u.v );
162 k = step->k;
163 temp = ( rol32 ( *a, 5 ) + f + *e + k + w[i] );
164 *e = *d;
165 *d = *c;
166 *c = rol32 ( *b, 30 );
167 *b = *a;
168 *a = temp;
169 }
170
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] );
176 }
177 }
178
179 /**
180 * Accumulate data with SHA-1 algorithm
181 *
182 * @v ctx SHA-1 context
183 * @v data Data
184 * @v len Length of data
185 */
186 void sha1_update ( void *ctx, const void *data, size_t len ) {
187 struct sha1_context *context = ctx;
188 const uint8_t *byte = data;
189 size_t offset;
190
191 /* Accumulate data a byte at a time, performing the digest
192 * whenever we fill the data buffer
193 */
194 while ( len-- ) {
195 offset = ( context->len % sizeof ( context->ddd.dd.data ) );
196 context->ddd.dd.data.byte[offset] = *(byte++);
197 context->len++;
198 if ( ( context->len % sizeof ( context->ddd.dd.data ) ) == 0 )
199 sha1_digest ( context );
200 }
201 }
202
203 /**
204 * Generate SHA-1 digest
205 *
206 * @v ctx SHA-1 context
207 * @v out Output buffer
208 */
209 void sha1_final ( void *ctx, void *out ) {
210 struct sha1_context *context = ctx;
211 uint64_t len_bits;
212 uint8_t pad;
213
214 /* Record length before pre-processing */
215 len_bits = cpu_to_be64 ( ( ( uint64_t ) context->len ) * 8 );
216
217 /* Pad with a single "1" bit followed by as many "0" bits as required */
218 pad = 0x80;
219 do {
220 sha1_update ( ctx, &pad, sizeof ( pad ) );
221 pad = 0x00;
222 } while ( ( context->len % sizeof ( context->ddd.dd.data ) ) !=
223 offsetof ( typeof ( context->ddd.dd.data ), final.len ) );
224
225 /* Append length (in bits) */
226 sha1_update ( ctx, &len_bits, sizeof ( len_bits ) );
227 assert ( ( context->len % sizeof ( context->ddd.dd.data ) ) == 0 );
228
229 /* Copy out final digest */
230 memcpy ( out, &context->ddd.dd.digest,
231 sizeof ( context->ddd.dd.digest ) );
232 }