Line | Count | Source |
1 | | /* rmd160.c - RIPE-MD160 |
2 | | * Copyright (C) 1998, 1999, 2000, 2001, 2008 Free Software Foundation, Inc. |
3 | | * |
4 | | * This file is part of GnuPG. |
5 | | * |
6 | | * GnuPG is free software; you can redistribute it and/or modify |
7 | | * it under the terms of the GNU General Public License as published by |
8 | | * the Free Software Foundation; either version 3 of the License, or |
9 | | * (at your option) any later version. |
10 | | * |
11 | | * GnuPG is distributed in the hope that it will be useful, |
12 | | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
13 | | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
14 | | * GNU General Public License for more details. |
15 | | * |
16 | | * You should have received a copy of the GNU General Public License |
17 | | * along with this program; if not, see <https://www.gnu.org/licenses/>. |
18 | | */ |
19 | | |
20 | | /* For historic reasons gpg uses RIPE-MD160 to identify names in |
21 | | the trustdb. It would be better to change that to SHA-1, to take |
22 | | advantage of a SHA-1 hardware operation provided by some CPUs. |
23 | | This would break trustdb compatibility and thus we don't want to do |
24 | | it now. |
25 | | |
26 | | We do not use the libgcrypt provided implementation of RMD160 |
27 | | because that is not available in FIPS mode, thus for the sake of |
28 | | gpg internal non-cryptographic, purposes, we use this separate |
29 | | implementation. |
30 | | */ |
31 | | |
32 | | #include <config.h> |
33 | | |
34 | | #include <stdio.h> |
35 | | #include <stdlib.h> |
36 | | #include <string.h> |
37 | | |
38 | | #include "../common/types.h" |
39 | | #include "rmd160.h" |
40 | | |
41 | | /* |
42 | | * Rotate the 32 bit integer X by N bytes. |
43 | | */ |
44 | | #if defined(__GNUC__) && defined(__i386__) |
45 | | static inline u32 |
46 | | rol (u32 x, int n) |
47 | | { |
48 | | __asm__("roll %%cl,%0" |
49 | | :"=r" (x) |
50 | | :"0" (x),"c" (n)); |
51 | | return x; |
52 | | } |
53 | | #else |
54 | 0 | #define rol(x,n) ( ((x) << (n)) | ((x) >> (32-(n))) ) |
55 | | #endif |
56 | | |
57 | | /* Structure holding the context for the RIPE-MD160 computation. */ |
58 | | typedef struct |
59 | | { |
60 | | u32 h0, h1, h2, h3, h4; |
61 | | u32 nblocks; |
62 | | unsigned char buf[64]; |
63 | | int count; |
64 | | } rmd160_context_t; |
65 | | |
66 | | |
67 | | |
68 | | static void |
69 | | rmd160_init (rmd160_context_t *hd) |
70 | 0 | { |
71 | 0 | hd->h0 = 0x67452301; |
72 | 0 | hd->h1 = 0xEFCDAB89; |
73 | 0 | hd->h2 = 0x98BADCFE; |
74 | 0 | hd->h3 = 0x10325476; |
75 | 0 | hd->h4 = 0xC3D2E1F0; |
76 | 0 | hd->nblocks = 0; |
77 | 0 | hd->count = 0; |
78 | 0 | } |
79 | | |
80 | | |
81 | | |
82 | | /* |
83 | | * Transform the message X which consists of 16 32-bit-words. |
84 | | */ |
85 | | static void |
86 | | transform (rmd160_context_t *hd, const unsigned char *data) |
87 | 0 | { |
88 | 0 | u32 a,b,c,d,e,aa,bb,cc,dd,ee,t; |
89 | | #ifdef WORDS_BIGENDIAN |
90 | | u32 x[16]; |
91 | | { |
92 | | int i; |
93 | | unsigned char *p2, *p1; |
94 | | for (i=0, p1=data, p2=(unsigned char*)x; i < 16; i++, p2 += 4 ) |
95 | | { |
96 | | p2[3] = *p1++; |
97 | | p2[2] = *p1++; |
98 | | p2[1] = *p1++; |
99 | | p2[0] = *p1++; |
100 | | } |
101 | | } |
102 | | #else |
103 | 0 | u32 x[16]; |
104 | 0 | memcpy (x, data, 64); |
105 | 0 | #endif |
106 | | |
107 | |
|
108 | 0 | #define K0 0x00000000 |
109 | 0 | #define K1 0x5A827999 |
110 | 0 | #define K2 0x6ED9EBA1 |
111 | 0 | #define K3 0x8F1BBCDC |
112 | 0 | #define K4 0xA953FD4E |
113 | 0 | #define KK0 0x50A28BE6 |
114 | 0 | #define KK1 0x5C4DD124 |
115 | 0 | #define KK2 0x6D703EF3 |
116 | 0 | #define KK3 0x7A6D76E9 |
117 | 0 | #define KK4 0x00000000 |
118 | 0 | #define F0(x,y,z) ( (x) ^ (y) ^ (z) ) |
119 | 0 | #define F1(x,y,z) ( ((x) & (y)) | (~(x) & (z)) ) |
120 | 0 | #define F2(x,y,z) ( ((x) | ~(y)) ^ (z) ) |
121 | 0 | #define F3(x,y,z) ( ((x) & (z)) | ((y) & ~(z)) ) |
122 | 0 | #define F4(x,y,z) ( (x) ^ ((y) | ~(z)) ) |
123 | 0 | #define R(a,b,c,d,e,f,k,r,s) do { t = a + f(b,c,d) + k + x[r]; \ |
124 | 0 | a = rol(t,s) + e; \ |
125 | 0 | c = rol(c,10); \ |
126 | 0 | } while(0) |
127 | | |
128 | | /* Left lane. */ |
129 | 0 | a = hd->h0; |
130 | 0 | b = hd->h1; |
131 | 0 | c = hd->h2; |
132 | 0 | d = hd->h3; |
133 | 0 | e = hd->h4; |
134 | 0 | R( a, b, c, d, e, F0, K0, 0, 11 ); |
135 | 0 | R( e, a, b, c, d, F0, K0, 1, 14 ); |
136 | 0 | R( d, e, a, b, c, F0, K0, 2, 15 ); |
137 | 0 | R( c, d, e, a, b, F0, K0, 3, 12 ); |
138 | 0 | R( b, c, d, e, a, F0, K0, 4, 5 ); |
139 | 0 | R( a, b, c, d, e, F0, K0, 5, 8 ); |
140 | 0 | R( e, a, b, c, d, F0, K0, 6, 7 ); |
141 | 0 | R( d, e, a, b, c, F0, K0, 7, 9 ); |
142 | 0 | R( c, d, e, a, b, F0, K0, 8, 11 ); |
143 | 0 | R( b, c, d, e, a, F0, K0, 9, 13 ); |
144 | 0 | R( a, b, c, d, e, F0, K0, 10, 14 ); |
145 | 0 | R( e, a, b, c, d, F0, K0, 11, 15 ); |
146 | 0 | R( d, e, a, b, c, F0, K0, 12, 6 ); |
147 | 0 | R( c, d, e, a, b, F0, K0, 13, 7 ); |
148 | 0 | R( b, c, d, e, a, F0, K0, 14, 9 ); |
149 | 0 | R( a, b, c, d, e, F0, K0, 15, 8 ); |
150 | 0 | R( e, a, b, c, d, F1, K1, 7, 7 ); |
151 | 0 | R( d, e, a, b, c, F1, K1, 4, 6 ); |
152 | 0 | R( c, d, e, a, b, F1, K1, 13, 8 ); |
153 | 0 | R( b, c, d, e, a, F1, K1, 1, 13 ); |
154 | 0 | R( a, b, c, d, e, F1, K1, 10, 11 ); |
155 | 0 | R( e, a, b, c, d, F1, K1, 6, 9 ); |
156 | 0 | R( d, e, a, b, c, F1, K1, 15, 7 ); |
157 | 0 | R( c, d, e, a, b, F1, K1, 3, 15 ); |
158 | 0 | R( b, c, d, e, a, F1, K1, 12, 7 ); |
159 | 0 | R( a, b, c, d, e, F1, K1, 0, 12 ); |
160 | 0 | R( e, a, b, c, d, F1, K1, 9, 15 ); |
161 | 0 | R( d, e, a, b, c, F1, K1, 5, 9 ); |
162 | 0 | R( c, d, e, a, b, F1, K1, 2, 11 ); |
163 | 0 | R( b, c, d, e, a, F1, K1, 14, 7 ); |
164 | 0 | R( a, b, c, d, e, F1, K1, 11, 13 ); |
165 | 0 | R( e, a, b, c, d, F1, K1, 8, 12 ); |
166 | 0 | R( d, e, a, b, c, F2, K2, 3, 11 ); |
167 | 0 | R( c, d, e, a, b, F2, K2, 10, 13 ); |
168 | 0 | R( b, c, d, e, a, F2, K2, 14, 6 ); |
169 | 0 | R( a, b, c, d, e, F2, K2, 4, 7 ); |
170 | 0 | R( e, a, b, c, d, F2, K2, 9, 14 ); |
171 | 0 | R( d, e, a, b, c, F2, K2, 15, 9 ); |
172 | 0 | R( c, d, e, a, b, F2, K2, 8, 13 ); |
173 | 0 | R( b, c, d, e, a, F2, K2, 1, 15 ); |
174 | 0 | R( a, b, c, d, e, F2, K2, 2, 14 ); |
175 | 0 | R( e, a, b, c, d, F2, K2, 7, 8 ); |
176 | 0 | R( d, e, a, b, c, F2, K2, 0, 13 ); |
177 | 0 | R( c, d, e, a, b, F2, K2, 6, 6 ); |
178 | 0 | R( b, c, d, e, a, F2, K2, 13, 5 ); |
179 | 0 | R( a, b, c, d, e, F2, K2, 11, 12 ); |
180 | 0 | R( e, a, b, c, d, F2, K2, 5, 7 ); |
181 | 0 | R( d, e, a, b, c, F2, K2, 12, 5 ); |
182 | 0 | R( c, d, e, a, b, F3, K3, 1, 11 ); |
183 | 0 | R( b, c, d, e, a, F3, K3, 9, 12 ); |
184 | 0 | R( a, b, c, d, e, F3, K3, 11, 14 ); |
185 | 0 | R( e, a, b, c, d, F3, K3, 10, 15 ); |
186 | 0 | R( d, e, a, b, c, F3, K3, 0, 14 ); |
187 | 0 | R( c, d, e, a, b, F3, K3, 8, 15 ); |
188 | 0 | R( b, c, d, e, a, F3, K3, 12, 9 ); |
189 | 0 | R( a, b, c, d, e, F3, K3, 4, 8 ); |
190 | 0 | R( e, a, b, c, d, F3, K3, 13, 9 ); |
191 | 0 | R( d, e, a, b, c, F3, K3, 3, 14 ); |
192 | 0 | R( c, d, e, a, b, F3, K3, 7, 5 ); |
193 | 0 | R( b, c, d, e, a, F3, K3, 15, 6 ); |
194 | 0 | R( a, b, c, d, e, F3, K3, 14, 8 ); |
195 | 0 | R( e, a, b, c, d, F3, K3, 5, 6 ); |
196 | 0 | R( d, e, a, b, c, F3, K3, 6, 5 ); |
197 | 0 | R( c, d, e, a, b, F3, K3, 2, 12 ); |
198 | 0 | R( b, c, d, e, a, F4, K4, 4, 9 ); |
199 | 0 | R( a, b, c, d, e, F4, K4, 0, 15 ); |
200 | 0 | R( e, a, b, c, d, F4, K4, 5, 5 ); |
201 | 0 | R( d, e, a, b, c, F4, K4, 9, 11 ); |
202 | 0 | R( c, d, e, a, b, F4, K4, 7, 6 ); |
203 | 0 | R( b, c, d, e, a, F4, K4, 12, 8 ); |
204 | 0 | R( a, b, c, d, e, F4, K4, 2, 13 ); |
205 | 0 | R( e, a, b, c, d, F4, K4, 10, 12 ); |
206 | 0 | R( d, e, a, b, c, F4, K4, 14, 5 ); |
207 | 0 | R( c, d, e, a, b, F4, K4, 1, 12 ); |
208 | 0 | R( b, c, d, e, a, F4, K4, 3, 13 ); |
209 | 0 | R( a, b, c, d, e, F4, K4, 8, 14 ); |
210 | 0 | R( e, a, b, c, d, F4, K4, 11, 11 ); |
211 | 0 | R( d, e, a, b, c, F4, K4, 6, 8 ); |
212 | 0 | R( c, d, e, a, b, F4, K4, 15, 5 ); |
213 | 0 | R( b, c, d, e, a, F4, K4, 13, 6 ); |
214 | |
|
215 | 0 | aa = a; bb = b; cc = c; dd = d; ee = e; |
216 | | |
217 | | /* Right lane. */ |
218 | 0 | a = hd->h0; |
219 | 0 | b = hd->h1; |
220 | 0 | c = hd->h2; |
221 | 0 | d = hd->h3; |
222 | 0 | e = hd->h4; |
223 | 0 | R( a, b, c, d, e, F4, KK0, 5, 8); |
224 | 0 | R( e, a, b, c, d, F4, KK0, 14, 9); |
225 | 0 | R( d, e, a, b, c, F4, KK0, 7, 9); |
226 | 0 | R( c, d, e, a, b, F4, KK0, 0, 11); |
227 | 0 | R( b, c, d, e, a, F4, KK0, 9, 13); |
228 | 0 | R( a, b, c, d, e, F4, KK0, 2, 15); |
229 | 0 | R( e, a, b, c, d, F4, KK0, 11, 15); |
230 | 0 | R( d, e, a, b, c, F4, KK0, 4, 5); |
231 | 0 | R( c, d, e, a, b, F4, KK0, 13, 7); |
232 | 0 | R( b, c, d, e, a, F4, KK0, 6, 7); |
233 | 0 | R( a, b, c, d, e, F4, KK0, 15, 8); |
234 | 0 | R( e, a, b, c, d, F4, KK0, 8, 11); |
235 | 0 | R( d, e, a, b, c, F4, KK0, 1, 14); |
236 | 0 | R( c, d, e, a, b, F4, KK0, 10, 14); |
237 | 0 | R( b, c, d, e, a, F4, KK0, 3, 12); |
238 | 0 | R( a, b, c, d, e, F4, KK0, 12, 6); |
239 | 0 | R( e, a, b, c, d, F3, KK1, 6, 9); |
240 | 0 | R( d, e, a, b, c, F3, KK1, 11, 13); |
241 | 0 | R( c, d, e, a, b, F3, KK1, 3, 15); |
242 | 0 | R( b, c, d, e, a, F3, KK1, 7, 7); |
243 | 0 | R( a, b, c, d, e, F3, KK1, 0, 12); |
244 | 0 | R( e, a, b, c, d, F3, KK1, 13, 8); |
245 | 0 | R( d, e, a, b, c, F3, KK1, 5, 9); |
246 | 0 | R( c, d, e, a, b, F3, KK1, 10, 11); |
247 | 0 | R( b, c, d, e, a, F3, KK1, 14, 7); |
248 | 0 | R( a, b, c, d, e, F3, KK1, 15, 7); |
249 | 0 | R( e, a, b, c, d, F3, KK1, 8, 12); |
250 | 0 | R( d, e, a, b, c, F3, KK1, 12, 7); |
251 | 0 | R( c, d, e, a, b, F3, KK1, 4, 6); |
252 | 0 | R( b, c, d, e, a, F3, KK1, 9, 15); |
253 | 0 | R( a, b, c, d, e, F3, KK1, 1, 13); |
254 | 0 | R( e, a, b, c, d, F3, KK1, 2, 11); |
255 | 0 | R( d, e, a, b, c, F2, KK2, 15, 9); |
256 | 0 | R( c, d, e, a, b, F2, KK2, 5, 7); |
257 | 0 | R( b, c, d, e, a, F2, KK2, 1, 15); |
258 | 0 | R( a, b, c, d, e, F2, KK2, 3, 11); |
259 | 0 | R( e, a, b, c, d, F2, KK2, 7, 8); |
260 | 0 | R( d, e, a, b, c, F2, KK2, 14, 6); |
261 | 0 | R( c, d, e, a, b, F2, KK2, 6, 6); |
262 | 0 | R( b, c, d, e, a, F2, KK2, 9, 14); |
263 | 0 | R( a, b, c, d, e, F2, KK2, 11, 12); |
264 | 0 | R( e, a, b, c, d, F2, KK2, 8, 13); |
265 | 0 | R( d, e, a, b, c, F2, KK2, 12, 5); |
266 | 0 | R( c, d, e, a, b, F2, KK2, 2, 14); |
267 | 0 | R( b, c, d, e, a, F2, KK2, 10, 13); |
268 | 0 | R( a, b, c, d, e, F2, KK2, 0, 13); |
269 | 0 | R( e, a, b, c, d, F2, KK2, 4, 7); |
270 | 0 | R( d, e, a, b, c, F2, KK2, 13, 5); |
271 | 0 | R( c, d, e, a, b, F1, KK3, 8, 15); |
272 | 0 | R( b, c, d, e, a, F1, KK3, 6, 5); |
273 | 0 | R( a, b, c, d, e, F1, KK3, 4, 8); |
274 | 0 | R( e, a, b, c, d, F1, KK3, 1, 11); |
275 | 0 | R( d, e, a, b, c, F1, KK3, 3, 14); |
276 | 0 | R( c, d, e, a, b, F1, KK3, 11, 14); |
277 | 0 | R( b, c, d, e, a, F1, KK3, 15, 6); |
278 | 0 | R( a, b, c, d, e, F1, KK3, 0, 14); |
279 | 0 | R( e, a, b, c, d, F1, KK3, 5, 6); |
280 | 0 | R( d, e, a, b, c, F1, KK3, 12, 9); |
281 | 0 | R( c, d, e, a, b, F1, KK3, 2, 12); |
282 | 0 | R( b, c, d, e, a, F1, KK3, 13, 9); |
283 | 0 | R( a, b, c, d, e, F1, KK3, 9, 12); |
284 | 0 | R( e, a, b, c, d, F1, KK3, 7, 5); |
285 | 0 | R( d, e, a, b, c, F1, KK3, 10, 15); |
286 | 0 | R( c, d, e, a, b, F1, KK3, 14, 8); |
287 | 0 | R( b, c, d, e, a, F0, KK4, 12, 8); |
288 | 0 | R( a, b, c, d, e, F0, KK4, 15, 5); |
289 | 0 | R( e, a, b, c, d, F0, KK4, 10, 12); |
290 | 0 | R( d, e, a, b, c, F0, KK4, 4, 9); |
291 | 0 | R( c, d, e, a, b, F0, KK4, 1, 12); |
292 | 0 | R( b, c, d, e, a, F0, KK4, 5, 5); |
293 | 0 | R( a, b, c, d, e, F0, KK4, 8, 14); |
294 | 0 | R( e, a, b, c, d, F0, KK4, 7, 6); |
295 | 0 | R( d, e, a, b, c, F0, KK4, 6, 8); |
296 | 0 | R( c, d, e, a, b, F0, KK4, 2, 13); |
297 | 0 | R( b, c, d, e, a, F0, KK4, 13, 6); |
298 | 0 | R( a, b, c, d, e, F0, KK4, 14, 5); |
299 | 0 | R( e, a, b, c, d, F0, KK4, 0, 15); |
300 | 0 | R( d, e, a, b, c, F0, KK4, 3, 13); |
301 | 0 | R( c, d, e, a, b, F0, KK4, 9, 11); |
302 | 0 | R( b, c, d, e, a, F0, KK4, 11, 11); |
303 | | |
304 | |
|
305 | 0 | t = hd->h1 + d + cc; |
306 | 0 | hd->h1 = hd->h2 + e + dd; |
307 | 0 | hd->h2 = hd->h3 + a + ee; |
308 | 0 | hd->h3 = hd->h4 + b + aa; |
309 | 0 | hd->h4 = hd->h0 + c + bb; |
310 | 0 | hd->h0 = t; |
311 | 0 | } |
312 | | |
313 | | |
314 | | /* Update the message digest with the content of (INBUF,INLEN). */ |
315 | | static void |
316 | | rmd160_write (rmd160_context_t *hd, const unsigned char *inbuf, size_t inlen) |
317 | 0 | { |
318 | 0 | if( hd->count == 64 ) |
319 | 0 | { |
320 | | /* Flush the buffer. */ |
321 | 0 | transform (hd, hd->buf); |
322 | 0 | hd->count = 0; |
323 | 0 | hd->nblocks++; |
324 | 0 | } |
325 | 0 | if (!inbuf) |
326 | 0 | return; |
327 | | |
328 | 0 | if (hd->count) |
329 | 0 | { |
330 | 0 | for (; inlen && hd->count < 64; inlen--) |
331 | 0 | hd->buf[hd->count++] = *inbuf++; |
332 | 0 | rmd160_write (hd, NULL, 0); |
333 | 0 | if (!inlen) |
334 | 0 | return; |
335 | 0 | } |
336 | | |
337 | 0 | while (inlen >= 64) |
338 | 0 | { |
339 | 0 | transform (hd, inbuf); |
340 | 0 | hd->count = 0; |
341 | 0 | hd->nblocks++; |
342 | 0 | inlen -= 64; |
343 | 0 | inbuf += 64; |
344 | 0 | } |
345 | 0 | for (; inlen && hd->count < 64; inlen--) |
346 | 0 | hd->buf[hd->count++] = *inbuf++; |
347 | 0 | } |
348 | | |
349 | | |
350 | | /* Complete the message computation. */ |
351 | | static void |
352 | | rmd160_final( rmd160_context_t *hd ) |
353 | 0 | { |
354 | 0 | u32 t, msb, lsb; |
355 | 0 | unsigned char *p; |
356 | |
|
357 | 0 | rmd160_write (hd, NULL, 0); /* Flush buffer. */ |
358 | |
|
359 | 0 | t = hd->nblocks; |
360 | | /* Multiply by 64 to make a byte count. */ |
361 | 0 | lsb = t << 6; |
362 | 0 | msb = t >> 26; |
363 | | /* Add the count. */ |
364 | 0 | t = lsb; |
365 | 0 | if ((lsb += hd->count) < t) |
366 | 0 | msb++; |
367 | | /* Multiply by 8 to make a bit count. */ |
368 | 0 | t = lsb; |
369 | 0 | lsb <<= 3; |
370 | 0 | msb <<= 3; |
371 | 0 | msb |= t >> 29; |
372 | |
|
373 | 0 | if (hd->count < 56) |
374 | 0 | { |
375 | | /* Enough room. */ |
376 | 0 | hd->buf[hd->count++] = 0x80; /* Pad character. */ |
377 | 0 | while (hd->count < 56) |
378 | 0 | hd->buf[hd->count++] = 0; |
379 | 0 | } |
380 | 0 | else |
381 | 0 | { |
382 | | /* Need one extra block. */ |
383 | 0 | hd->buf[hd->count++] = 0x80; /* Pad character. */ |
384 | 0 | while (hd->count < 64) |
385 | 0 | hd->buf[hd->count++] = 0; |
386 | 0 | rmd160_write (hd, NULL, 0); /* Flush buffer. */ |
387 | 0 | memset (hd->buf, 0, 56); /* Fill next block with zeroes. */ |
388 | 0 | } |
389 | | /* Append the 64 bit count. */ |
390 | 0 | hd->buf[56] = lsb; |
391 | 0 | hd->buf[57] = lsb >> 8; |
392 | 0 | hd->buf[58] = lsb >> 16; |
393 | 0 | hd->buf[59] = lsb >> 24; |
394 | 0 | hd->buf[60] = msb; |
395 | 0 | hd->buf[61] = msb >> 8; |
396 | 0 | hd->buf[62] = msb >> 16; |
397 | 0 | hd->buf[63] = msb >> 24; |
398 | 0 | transform (hd, hd->buf); |
399 | |
|
400 | 0 | p = hd->buf; |
401 | 0 | #define X(a) do { *p++ = hd->h##a; *p++ = hd->h##a >> 8; \ |
402 | 0 | *p++ = hd->h##a >> 16; *p++ = hd->h##a >> 24; } while(0) |
403 | 0 | X(0); |
404 | 0 | X(1); |
405 | 0 | X(2); |
406 | 0 | X(3); |
407 | 0 | X(4); |
408 | 0 | #undef X |
409 | 0 | } |
410 | | |
411 | | |
412 | | /* |
413 | | * Compines function to put the hash value of the supplied BUFFER into |
414 | | * OUTBUF which must have a size of 20 bytes. |
415 | | */ |
416 | | void |
417 | | rmd160_hash_buffer (void *outbuf, const void *buffer, size_t length) |
418 | 0 | { |
419 | 0 | rmd160_context_t hd; |
420 | |
|
421 | 0 | rmd160_init (&hd); |
422 | 0 | rmd160_write (&hd, buffer, length); |
423 | 0 | rmd160_final (&hd); |
424 | 0 | memcpy (outbuf, hd.buf, 20); |
425 | 0 | } |