/src/libreoffice/sal/rtl/digest.cxx
Line | Count | Source |
1 | | /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ |
2 | | /* |
3 | | * This file is part of the LibreOffice project. |
4 | | * |
5 | | * This Source Code Form is subject to the terms of the Mozilla Public |
6 | | * License, v. 2.0. If a copy of the MPL was not distributed with this |
7 | | * file, You can obtain one at http://mozilla.org/MPL/2.0/. |
8 | | * |
9 | | * This file incorporates work covered by the following license notice: |
10 | | * |
11 | | * Licensed to the Apache Software Foundation (ASF) under one or more |
12 | | * contributor license agreements. See the NOTICE file distributed |
13 | | * with this work for additional information regarding copyright |
14 | | * ownership. The ASF licenses this file to you under the Apache |
15 | | * License, Version 2.0 (the "License"); you may not use this file |
16 | | * except in compliance with the License. You may obtain a copy of |
17 | | * the License at http://www.apache.org/licenses/LICENSE-2.0 . |
18 | | */ |
19 | | |
20 | | #include <string.h> |
21 | | #include <stdlib.h> |
22 | | |
23 | | #include <sal/types.h> |
24 | | #include <osl/endian.h> |
25 | | #include <rtl/alloc.h> |
26 | | #include <rtl/digest.h> |
27 | | |
28 | 779 | #define RTL_DIGEST_CREATE(T) (static_cast<T*>(rtl_allocateZeroMemory(sizeof(T)))) |
29 | | |
30 | 43.5k | #define RTL_DIGEST_ROTL(a,n) (((a) << (n)) | ((a) >> (32 - (n)))) |
31 | | |
32 | | #define RTL_DIGEST_HTONL(l,c) \ |
33 | 510 | (*((c)++) = static_cast<sal_uInt8>(((l) >> 24) & 0xff), \ |
34 | 510 | *((c)++) = static_cast<sal_uInt8>(((l) >> 16) & 0xff), \ |
35 | 510 | *((c)++) = static_cast<sal_uInt8>(((l) >> 8) & 0xff), \ |
36 | 510 | *((c)++) = static_cast<sal_uInt8>(((l) ) & 0xff)) |
37 | | |
38 | | #define RTL_DIGEST_LTOC(l,c) \ |
39 | 836 | *((c)++) = static_cast<sal_uInt8>(((l) ) & 0xff); \ |
40 | 836 | *((c)++) = static_cast<sal_uInt8>(((l) >> 8) & 0xff); \ |
41 | 836 | *((c)++) = static_cast<sal_uInt8>(((l) >> 16) & 0xff); \ |
42 | 836 | *((c)++) = static_cast<sal_uInt8>(((l) >> 24) & 0xff); |
43 | | |
44 | | typedef rtlDigestError (Digest_init_t) ( |
45 | | void *ctx, const sal_uInt8 *Data, sal_uInt32 DatLen); |
46 | | |
47 | | typedef void (Digest_delete_t) (void *ctx); |
48 | | |
49 | | typedef rtlDigestError (Digest_update_t) ( |
50 | | void *ctx, const void *Data, sal_uInt32 DatLen); |
51 | | |
52 | | typedef rtlDigestError (Digest_get_t) ( |
53 | | void *ctx, sal_uInt8 *Buffer, sal_uInt32 BufLen); |
54 | | |
55 | | namespace { |
56 | | |
57 | | struct Digest_Impl |
58 | | { |
59 | | rtlDigestAlgorithm m_algorithm; |
60 | | sal_uInt32 m_length; |
61 | | |
62 | | Digest_init_t *m_init; |
63 | | Digest_delete_t *m_delete; |
64 | | Digest_update_t *m_update; |
65 | | Digest_get_t *m_get; |
66 | | }; |
67 | | |
68 | | } |
69 | | |
70 | | static void swapLong(sal_uInt32 *pData, sal_uInt32 nDatLen) |
71 | 102 | { |
72 | 102 | sal_uInt32 *X; |
73 | 102 | int i, n; |
74 | | |
75 | 102 | X = pData; |
76 | 102 | n = nDatLen; |
77 | | |
78 | 510 | for (i = 0; i < n; i++) |
79 | 408 | { |
80 | 408 | X[i] = OSL_SWAPDWORD(X[i]); |
81 | 408 | } |
82 | 102 | } |
83 | | |
84 | | rtlDigest SAL_CALL rtl_digest_create(rtlDigestAlgorithm Algorithm) noexcept |
85 | 779 | { |
86 | 779 | rtlDigest Digest = nullptr; |
87 | 779 | switch (Algorithm) |
88 | 779 | { |
89 | 0 | case rtl_Digest_AlgorithmMD2: |
90 | 0 | Digest = rtl_digest_createMD2(); |
91 | 0 | break; |
92 | | |
93 | 779 | case rtl_Digest_AlgorithmMD5: |
94 | 779 | Digest = rtl_digest_createMD5(); |
95 | 779 | break; |
96 | | |
97 | 0 | case rtl_Digest_AlgorithmSHA: |
98 | 0 | Digest = rtl_digest_createSHA(); |
99 | 0 | break; |
100 | | |
101 | 0 | case rtl_Digest_AlgorithmSHA1: |
102 | 0 | Digest = rtl_digest_createSHA1(); |
103 | 0 | break; |
104 | | |
105 | 0 | case rtl_Digest_AlgorithmHMAC_MD5: |
106 | 0 | Digest = rtl_digest_createHMAC_MD5(); |
107 | 0 | break; |
108 | | |
109 | 0 | case rtl_Digest_AlgorithmHMAC_SHA1: |
110 | 0 | Digest = rtl_digest_createHMAC_SHA1(); |
111 | 0 | break; |
112 | | |
113 | 0 | default: /* rtl_Digest_AlgorithmInvalid */ |
114 | 0 | break; |
115 | 779 | } |
116 | 779 | return Digest; |
117 | 779 | } |
118 | | |
119 | | rtlDigestAlgorithm SAL_CALL rtl_digest_queryAlgorithm(rtlDigest Digest) noexcept |
120 | 0 | { |
121 | 0 | Digest_Impl *pImpl = static_cast<Digest_Impl *>(Digest); |
122 | 0 | if (pImpl) |
123 | 0 | return pImpl->m_algorithm; |
124 | 0 | return rtl_Digest_AlgorithmInvalid; |
125 | 0 | } |
126 | | |
127 | | sal_uInt32 SAL_CALL rtl_digest_queryLength(rtlDigest Digest) noexcept |
128 | 0 | { |
129 | 0 | Digest_Impl *pImpl = static_cast<Digest_Impl *>(Digest); |
130 | 0 | if (pImpl) |
131 | 0 | return pImpl->m_length; |
132 | 0 | return 0; |
133 | 0 | } |
134 | | |
135 | | rtlDigestError SAL_CALL rtl_digest_init( |
136 | | rtlDigest Digest, const sal_uInt8 *pData, sal_uInt32 nDatLen) noexcept |
137 | 0 | { |
138 | 0 | Digest_Impl *pImpl = static_cast<Digest_Impl *>(Digest); |
139 | 0 | if (pImpl) |
140 | 0 | { |
141 | 0 | if (pImpl->m_init) |
142 | 0 | return pImpl->m_init (Digest, pData, nDatLen); |
143 | 0 | return rtl_Digest_E_None; |
144 | 0 | } |
145 | 0 | return rtl_Digest_E_Argument; |
146 | 0 | } |
147 | | |
148 | | rtlDigestError SAL_CALL rtl_digest_update( |
149 | | rtlDigest Digest, const void *pData, sal_uInt32 nDatLen) noexcept |
150 | 0 | { |
151 | 0 | Digest_Impl *pImpl = static_cast<Digest_Impl *>(Digest); |
152 | 0 | if (pImpl && pImpl->m_update) |
153 | 0 | return pImpl->m_update(Digest, pData, nDatLen); |
154 | 0 | return rtl_Digest_E_Argument; |
155 | 0 | } |
156 | | |
157 | | rtlDigestError SAL_CALL rtl_digest_get( |
158 | | rtlDigest Digest, sal_uInt8 *pBuffer, sal_uInt32 nBufLen) noexcept |
159 | 0 | { |
160 | 0 | Digest_Impl *pImpl = static_cast<Digest_Impl *>(Digest); |
161 | 0 | if (pImpl && pImpl->m_get) |
162 | 0 | return pImpl->m_get(Digest, pBuffer, nBufLen); |
163 | 0 | return rtl_Digest_E_Argument; |
164 | 0 | } |
165 | | |
166 | | void SAL_CALL rtl_digest_destroy(rtlDigest Digest) noexcept |
167 | 779 | { |
168 | 779 | Digest_Impl *pImpl = static_cast<Digest_Impl *>(Digest); |
169 | 779 | if (pImpl && pImpl->m_delete) |
170 | 779 | pImpl->m_delete(Digest); |
171 | 779 | } |
172 | | |
173 | | constexpr auto DIGEST_CBLOCK_MD2 = 16; |
174 | | constexpr auto DIGEST_LBLOCK_MD2 = 16; |
175 | | |
176 | | namespace { |
177 | | |
178 | | struct DigestContextMD2 |
179 | | { |
180 | | sal_uInt32 m_nDatLen; |
181 | | sal_uInt8 m_pData[DIGEST_CBLOCK_MD2]; |
182 | | sal_uInt32 m_state[DIGEST_LBLOCK_MD2]; |
183 | | sal_uInt32 m_chksum[DIGEST_LBLOCK_MD2]; |
184 | | }; |
185 | | |
186 | | struct DigestMD2_Impl |
187 | | { |
188 | | Digest_Impl m_digest; |
189 | | DigestContextMD2 m_context; |
190 | | }; |
191 | | |
192 | | } |
193 | | |
194 | | static void initMD2 (DigestContextMD2 *ctx); |
195 | | static void updateMD2 (DigestContextMD2 *ctx); |
196 | | static void endMD2 (DigestContextMD2 *ctx); |
197 | | |
198 | | const sal_uInt32 S[256] = |
199 | | { |
200 | | 0x29, 0x2E, 0x43, 0xC9, 0xA2, 0xD8, 0x7C, 0x01, |
201 | | 0x3D, 0x36, 0x54, 0xA1, 0xEC, 0xF0, 0x06, 0x13, |
202 | | 0x62, 0xA7, 0x05, 0xF3, 0xC0, 0xC7, 0x73, 0x8C, |
203 | | 0x98, 0x93, 0x2B, 0xD9, 0xBC, 0x4C, 0x82, 0xCA, |
204 | | 0x1E, 0x9B, 0x57, 0x3C, 0xFD, 0xD4, 0xE0, 0x16, |
205 | | 0x67, 0x42, 0x6F, 0x18, 0x8A, 0x17, 0xE5, 0x12, |
206 | | 0xBE, 0x4E, 0xC4, 0xD6, 0xDA, 0x9E, 0xDE, 0x49, |
207 | | 0xA0, 0xFB, 0xF5, 0x8E, 0xBB, 0x2F, 0xEE, 0x7A, |
208 | | 0xA9, 0x68, 0x79, 0x91, 0x15, 0xB2, 0x07, 0x3F, |
209 | | 0x94, 0xC2, 0x10, 0x89, 0x0B, 0x22, 0x5F, 0x21, |
210 | | 0x80, 0x7F, 0x5D, 0x9A, 0x5A, 0x90, 0x32, 0x27, |
211 | | 0x35, 0x3E, 0xCC, 0xE7, 0xBF, 0xF7, 0x97, 0x03, |
212 | | 0xFF, 0x19, 0x30, 0xB3, 0x48, 0xA5, 0xB5, 0xD1, |
213 | | 0xD7, 0x5E, 0x92, 0x2A, 0xAC, 0x56, 0xAA, 0xC6, |
214 | | 0x4F, 0xB8, 0x38, 0xD2, 0x96, 0xA4, 0x7D, 0xB6, |
215 | | 0x76, 0xFC, 0x6B, 0xE2, 0x9C, 0x74, 0x04, 0xF1, |
216 | | 0x45, 0x9D, 0x70, 0x59, 0x64, 0x71, 0x87, 0x20, |
217 | | 0x86, 0x5B, 0xCF, 0x65, 0xE6, 0x2D, 0xA8, 0x02, |
218 | | 0x1B, 0x60, 0x25, 0xAD, 0xAE, 0xB0, 0xB9, 0xF6, |
219 | | 0x1C, 0x46, 0x61, 0x69, 0x34, 0x40, 0x7E, 0x0F, |
220 | | 0x55, 0x47, 0xA3, 0x23, 0xDD, 0x51, 0xAF, 0x3A, |
221 | | 0xC3, 0x5C, 0xF9, 0xCE, 0xBA, 0xC5, 0xEA, 0x26, |
222 | | 0x2C, 0x53, 0x0D, 0x6E, 0x85, 0x28, 0x84, 0x09, |
223 | | 0xD3, 0xDF, 0xCD, 0xF4, 0x41, 0x81, 0x4D, 0x52, |
224 | | 0x6A, 0xDC, 0x37, 0xC8, 0x6C, 0xC1, 0xAB, 0xFA, |
225 | | 0x24, 0xE1, 0x7B, 0x08, 0x0C, 0xBD, 0xB1, 0x4A, |
226 | | 0x78, 0x88, 0x95, 0x8B, 0xE3, 0x63, 0xE8, 0x6D, |
227 | | 0xE9, 0xCB, 0xD5, 0xFE, 0x3B, 0x00, 0x1D, 0x39, |
228 | | 0xF2, 0xEF, 0xB7, 0x0E, 0x66, 0x58, 0xD0, 0xE4, |
229 | | 0xA6, 0x77, 0x72, 0xF8, 0xEB, 0x75, 0x4B, 0x0A, |
230 | | 0x31, 0x44, 0x50, 0xB4, 0x8F, 0xED, 0x1F, 0x1A, |
231 | | 0xDB, 0x99, 0x8D, 0x33, 0x9F, 0x11, 0x83, 0x14, |
232 | | }; |
233 | | |
234 | | const Digest_Impl MD2 = |
235 | | { |
236 | | rtl_Digest_AlgorithmMD2, |
237 | | RTL_DIGEST_LENGTH_MD2, |
238 | | nullptr, |
239 | | rtl_digest_destroyMD2, |
240 | | rtl_digest_updateMD2, |
241 | | rtl_digest_getMD2 |
242 | | }; |
243 | | |
244 | | static void initMD2(DigestContextMD2 *ctx) |
245 | 0 | { |
246 | 0 | memset(ctx, 0, sizeof(DigestContextMD2)); |
247 | 0 | } |
248 | | |
249 | | static void updateMD2(DigestContextMD2 *ctx) |
250 | 0 | { |
251 | 0 | sal_uInt8 *X; |
252 | 0 | sal_uInt32 *sp1, *sp2; |
253 | 0 | sal_uInt32 i, k, t; |
254 | |
|
255 | 0 | sal_uInt32 state[48]; |
256 | |
|
257 | 0 | X = ctx->m_pData; |
258 | 0 | sp1 = ctx->m_state; |
259 | 0 | sp2 = ctx->m_chksum; |
260 | |
|
261 | 0 | k = sp2[DIGEST_LBLOCK_MD2 - 1]; |
262 | 0 | for (i = 0; i < 16; i++) |
263 | 0 | { |
264 | 0 | state[i + 0] = sp1[i]; |
265 | 0 | state[i + 16] = t = X[i]; |
266 | 0 | state[i + 32] = t ^ sp1[i]; |
267 | 0 | k = sp2[i] ^= S[t^k]; |
268 | 0 | } |
269 | |
|
270 | 0 | t = 0; |
271 | 0 | for (i = 0; i < 18; i++) |
272 | 0 | { |
273 | 0 | for (k = 0; k < 48; k += 8) |
274 | 0 | { |
275 | 0 | t = state[k + 0] ^= S[t]; |
276 | 0 | t = state[k + 1] ^= S[t]; |
277 | 0 | t = state[k + 2] ^= S[t]; |
278 | 0 | t = state[k + 3] ^= S[t]; |
279 | 0 | t = state[k + 4] ^= S[t]; |
280 | 0 | t = state[k + 5] ^= S[t]; |
281 | 0 | t = state[k + 6] ^= S[t]; |
282 | 0 | t = state[k + 7] ^= S[t]; |
283 | 0 | } |
284 | 0 | t = ((t + i) & 0xff); |
285 | 0 | } |
286 | |
|
287 | 0 | memcpy(sp1, state, 16 * sizeof(sal_uInt32)); |
288 | 0 | rtl_secureZeroMemory(state, 48 * sizeof(sal_uInt32)); |
289 | 0 | } |
290 | | |
291 | | static void endMD2(DigestContextMD2 *ctx) |
292 | 0 | { |
293 | 0 | sal_uInt8 *X; |
294 | 0 | sal_uInt32 *C; |
295 | 0 | sal_uInt32 i, n; |
296 | |
|
297 | 0 | X = ctx->m_pData; |
298 | 0 | C = ctx->m_chksum; |
299 | 0 | n = DIGEST_CBLOCK_MD2 - ctx->m_nDatLen; |
300 | |
|
301 | 0 | for (i = ctx->m_nDatLen; i < DIGEST_CBLOCK_MD2; i++) |
302 | 0 | X[i] = static_cast<sal_uInt8>(n & 0xff); |
303 | |
|
304 | 0 | updateMD2(ctx); |
305 | |
|
306 | 0 | for (i = 0; i < DIGEST_CBLOCK_MD2; i++) |
307 | 0 | X[i] = static_cast<sal_uInt8>(C[i] & 0xff); |
308 | 0 | updateMD2(ctx); |
309 | 0 | } |
310 | | |
311 | | rtlDigestError SAL_CALL rtl_digest_MD2( |
312 | | const void *pData, sal_uInt32 nDatLen, |
313 | | sal_uInt8 *pBuffer, sal_uInt32 nBufLen) noexcept |
314 | 0 | { |
315 | 0 | DigestMD2_Impl digest; |
316 | 0 | rtlDigestError result; |
317 | |
|
318 | 0 | digest.m_digest = MD2; |
319 | 0 | initMD2(&(digest.m_context)); |
320 | |
|
321 | 0 | result = rtl_digest_updateMD2(&digest, pData, nDatLen); |
322 | 0 | if (result == rtl_Digest_E_None) |
323 | 0 | result = rtl_digest_getMD2(&digest, pBuffer, nBufLen); |
324 | |
|
325 | 0 | rtl_secureZeroMemory(&digest, sizeof(digest)); |
326 | 0 | return result; |
327 | 0 | } |
328 | | |
329 | | rtlDigest SAL_CALL rtl_digest_createMD2() noexcept |
330 | 0 | { |
331 | 0 | DigestMD2_Impl *pImpl = RTL_DIGEST_CREATE(DigestMD2_Impl); |
332 | 0 | if (pImpl) |
333 | 0 | { |
334 | 0 | pImpl->m_digest = MD2; |
335 | 0 | initMD2(&(pImpl->m_context)); |
336 | 0 | } |
337 | 0 | return static_cast<rtlDigest>(pImpl); |
338 | 0 | } |
339 | | |
340 | | rtlDigestError SAL_CALL rtl_digest_updateMD2( |
341 | | rtlDigest Digest, const void *pData, sal_uInt32 nDatLen) noexcept |
342 | 0 | { |
343 | 0 | DigestMD2_Impl *pImpl = static_cast<DigestMD2_Impl *>(Digest); |
344 | 0 | const sal_uInt8 *d = static_cast<const sal_uInt8 *>(pData); |
345 | |
|
346 | 0 | DigestContextMD2 *ctx; |
347 | |
|
348 | 0 | if (!pImpl || !pData) |
349 | 0 | return rtl_Digest_E_Argument; |
350 | | |
351 | 0 | if (pImpl->m_digest.m_algorithm != rtl_Digest_AlgorithmMD2) |
352 | 0 | return rtl_Digest_E_Algorithm; |
353 | | |
354 | 0 | if (nDatLen == 0) |
355 | 0 | return rtl_Digest_E_None; |
356 | | |
357 | 0 | ctx = &(pImpl->m_context); |
358 | |
|
359 | 0 | if (ctx->m_nDatLen) |
360 | 0 | { |
361 | 0 | sal_uInt8 *p = ctx->m_pData + ctx->m_nDatLen; |
362 | 0 | sal_uInt32 n = DIGEST_CBLOCK_MD2 - ctx->m_nDatLen; |
363 | |
|
364 | 0 | if (nDatLen < n) |
365 | 0 | { |
366 | 0 | memcpy(p, d, nDatLen); |
367 | 0 | ctx->m_nDatLen += nDatLen; |
368 | |
|
369 | 0 | return rtl_Digest_E_None; |
370 | 0 | } |
371 | | |
372 | 0 | memcpy(p, d, n); |
373 | 0 | d += n; |
374 | 0 | nDatLen -= n; |
375 | |
|
376 | 0 | updateMD2(ctx); |
377 | 0 | ctx->m_nDatLen = 0; |
378 | 0 | } |
379 | | |
380 | 0 | while (nDatLen >= DIGEST_CBLOCK_MD2) |
381 | 0 | { |
382 | 0 | memcpy(ctx->m_pData, d, DIGEST_CBLOCK_MD2); |
383 | 0 | d += DIGEST_CBLOCK_MD2; |
384 | 0 | nDatLen -= DIGEST_CBLOCK_MD2; |
385 | |
|
386 | 0 | updateMD2(ctx); |
387 | 0 | } |
388 | |
|
389 | 0 | memcpy(ctx->m_pData, d, nDatLen); |
390 | 0 | ctx->m_nDatLen = nDatLen; |
391 | |
|
392 | 0 | return rtl_Digest_E_None; |
393 | 0 | } |
394 | | |
395 | | rtlDigestError SAL_CALL rtl_digest_getMD2( |
396 | | rtlDigest Digest, sal_uInt8 *pBuffer, sal_uInt32 nBufLen) noexcept |
397 | 0 | { |
398 | 0 | DigestMD2_Impl *pImpl = static_cast<DigestMD2_Impl *>(Digest); |
399 | 0 | sal_uInt32 i; |
400 | |
|
401 | 0 | DigestContextMD2 *ctx; |
402 | |
|
403 | 0 | if (!pImpl || !pBuffer) |
404 | 0 | return rtl_Digest_E_Argument; |
405 | | |
406 | 0 | if (pImpl->m_digest.m_algorithm != rtl_Digest_AlgorithmMD2) |
407 | 0 | return rtl_Digest_E_Algorithm; |
408 | | |
409 | 0 | if (pImpl->m_digest.m_length > nBufLen) |
410 | 0 | return rtl_Digest_E_BufferSize; |
411 | | |
412 | 0 | ctx = &(pImpl->m_context); |
413 | |
|
414 | 0 | endMD2(ctx); |
415 | 0 | for (i = 0; i < DIGEST_CBLOCK_MD2; i++) |
416 | 0 | { |
417 | 0 | pBuffer[i] = static_cast<sal_uInt8>(ctx->m_state[i] & 0xff); |
418 | 0 | } |
419 | |
|
420 | 0 | initMD2(ctx); |
421 | |
|
422 | 0 | return rtl_Digest_E_None; |
423 | 0 | } |
424 | | |
425 | | void SAL_CALL rtl_digest_destroyMD2(rtlDigest Digest) noexcept |
426 | 0 | { |
427 | 0 | DigestMD2_Impl *pImpl = static_cast<DigestMD2_Impl *>(Digest); |
428 | 0 | if (pImpl) |
429 | 0 | { |
430 | 0 | if (pImpl->m_digest.m_algorithm == rtl_Digest_AlgorithmMD2) |
431 | 0 | rtl_freeZeroMemory(pImpl, sizeof(DigestMD2_Impl)); |
432 | 0 | else |
433 | 0 | free(pImpl); |
434 | 0 | } |
435 | 0 | } |
436 | | |
437 | 1.82k | #define DIGEST_CBLOCK_MD5 64 |
438 | 0 | #define DIGEST_LBLOCK_MD5 16 |
439 | | |
440 | | namespace { |
441 | | |
442 | | struct DigestContextMD5 |
443 | | { |
444 | | sal_uInt32 m_nDatLen; |
445 | | sal_uInt32 m_pData[DIGEST_LBLOCK_MD5]; |
446 | | sal_uInt32 m_nA, m_nB, m_nC, m_nD; |
447 | | sal_uInt32 m_nL, m_nH; |
448 | | }; |
449 | | |
450 | | struct DigestMD5_Impl |
451 | | { |
452 | | Digest_Impl m_digest; |
453 | | DigestContextMD5 m_context; |
454 | | }; |
455 | | |
456 | | } |
457 | | |
458 | | static void initMD5 (DigestContextMD5 *ctx); |
459 | | static void updateMD5 (DigestContextMD5 *ctx); |
460 | | static void endMD5 (DigestContextMD5 *ctx); |
461 | | |
462 | 5.18k | #define F(x,y,z) ((((y) ^ (z)) & (x)) ^ (z)) |
463 | 5.18k | #define G(x,y,z) ((((x) ^ (y)) & (z)) ^ (y)) |
464 | 5.18k | #define H(x,y,z) ((x) ^ (y) ^ (z)) |
465 | 5.18k | #define I(x,y,z) (((x) | (~(z))) ^ (y)) |
466 | | |
467 | 5.18k | #define R0(a,b,c,d,k,s,t) { \ |
468 | 5.18k | a += ((k) + (t) + F((b), (c), (d))); \ |
469 | 5.18k | a = RTL_DIGEST_ROTL(a, s); \ |
470 | 5.18k | a += b; } |
471 | | |
472 | 5.18k | #define R1(a,b,c,d,k,s,t) { \ |
473 | 5.18k | a += ((k) + (t) + G((b), (c), (d))); \ |
474 | 5.18k | a = RTL_DIGEST_ROTL(a, s); \ |
475 | 5.18k | a += b; } |
476 | | |
477 | 5.18k | #define R2(a,b,c,d,k,s,t) { \ |
478 | 5.18k | a += ((k) + (t) + H((b), (c), (d))); \ |
479 | 5.18k | a = RTL_DIGEST_ROTL(a, s); \ |
480 | 5.18k | a += b; } |
481 | | |
482 | 5.18k | #define R3(a,b,c,d,k,s,t) { \ |
483 | 5.18k | a += ((k) + (t) + I((b), (c), (d))); \ |
484 | 5.18k | a = RTL_DIGEST_ROTL(a, s); \ |
485 | 5.18k | a += b; } |
486 | | |
487 | | const Digest_Impl MD5 = |
488 | | { |
489 | | rtl_Digest_AlgorithmMD5, |
490 | | RTL_DIGEST_LENGTH_MD5, |
491 | | nullptr, |
492 | | rtl_digest_destroyMD5, |
493 | | rtl_digest_updateMD5, |
494 | | rtl_digest_getMD5 |
495 | | }; |
496 | | |
497 | | static void initMD5(DigestContextMD5 *ctx) |
498 | 988 | { |
499 | 988 | memset(ctx, 0, sizeof(DigestContextMD5)); |
500 | | |
501 | 988 | ctx->m_nA = sal_uInt32(0x67452301L); |
502 | 988 | ctx->m_nB = sal_uInt32(0xefcdab89L); |
503 | 988 | ctx->m_nC = sal_uInt32(0x98badcfeL); |
504 | 988 | ctx->m_nD = sal_uInt32(0x10325476L); |
505 | 988 | } |
506 | | |
507 | | static void updateMD5(DigestContextMD5 *ctx) |
508 | 324 | { |
509 | 324 | sal_uInt32 A, B, C, D; |
510 | 324 | sal_uInt32 *X; |
511 | | |
512 | 324 | A = ctx->m_nA; |
513 | 324 | B = ctx->m_nB; |
514 | 324 | C = ctx->m_nC; |
515 | 324 | D = ctx->m_nD; |
516 | 324 | X = ctx->m_pData; |
517 | | |
518 | 324 | R0 (A, B, C, D, X[ 0], 7, 0xd76aa478L); |
519 | 324 | R0 (D, A, B, C, X[ 1], 12, 0xe8c7b756L); |
520 | 324 | R0 (C, D, A, B, X[ 2], 17, 0x242070dbL); |
521 | 324 | R0 (B, C, D, A, X[ 3], 22, 0xc1bdceeeL); |
522 | 324 | R0 (A, B, C, D, X[ 4], 7, 0xf57c0fafL); |
523 | 324 | R0 (D, A, B, C, X[ 5], 12, 0x4787c62aL); |
524 | 324 | R0 (C, D, A, B, X[ 6], 17, 0xa8304613L); |
525 | 324 | R0 (B, C, D, A, X[ 7], 22, 0xfd469501L); |
526 | 324 | R0 (A, B, C, D, X[ 8], 7, 0x698098d8L); |
527 | 324 | R0 (D, A, B, C, X[ 9], 12, 0x8b44f7afL); |
528 | 324 | R0 (C, D, A, B, X[10], 17, 0xffff5bb1L); |
529 | 324 | R0 (B, C, D, A, X[11], 22, 0x895cd7beL); |
530 | 324 | R0 (A, B, C, D, X[12], 7, 0x6b901122L); |
531 | 324 | R0 (D, A, B, C, X[13], 12, 0xfd987193L); |
532 | 324 | R0 (C, D, A, B, X[14], 17, 0xa679438eL); |
533 | 324 | R0 (B, C, D, A, X[15], 22, 0x49b40821L); |
534 | | |
535 | 324 | R1 (A, B, C, D, X[ 1], 5, 0xf61e2562L); |
536 | 324 | R1 (D, A, B, C, X[ 6], 9, 0xc040b340L); |
537 | 324 | R1 (C, D, A, B, X[11], 14, 0x265e5a51L); |
538 | 324 | R1 (B, C, D, A, X[ 0], 20, 0xe9b6c7aaL); |
539 | 324 | R1 (A, B, C, D, X[ 5], 5, 0xd62f105dL); |
540 | 324 | R1 (D, A, B, C, X[10], 9, 0x02441453L); |
541 | 324 | R1 (C, D, A, B, X[15], 14, 0xd8a1e681L); |
542 | 324 | R1 (B, C, D, A, X[ 4], 20, 0xe7d3fbc8L); |
543 | 324 | R1 (A, B, C, D, X[ 9], 5, 0x21e1cde6L); |
544 | 324 | R1 (D, A, B, C, X[14], 9, 0xc33707d6L); |
545 | 324 | R1 (C, D, A, B, X[ 3], 14, 0xf4d50d87L); |
546 | 324 | R1 (B, C, D, A, X[ 8], 20, 0x455a14edL); |
547 | 324 | R1 (A, B, C, D, X[13], 5, 0xa9e3e905L); |
548 | 324 | R1 (D, A, B, C, X[ 2], 9, 0xfcefa3f8L); |
549 | 324 | R1 (C, D, A, B, X[ 7], 14, 0x676f02d9L); |
550 | 324 | R1 (B, C, D, A, X[12], 20, 0x8d2a4c8aL); |
551 | | |
552 | 324 | R2 (A, B, C, D, X[ 5], 4, 0xfffa3942L); |
553 | 324 | R2 (D, A, B, C, X[ 8], 11, 0x8771f681L); |
554 | 324 | R2 (C, D, A, B, X[11], 16, 0x6d9d6122L); |
555 | 324 | R2 (B, C, D, A, X[14], 23, 0xfde5380cL); |
556 | 324 | R2 (A, B, C, D, X[ 1], 4, 0xa4beea44L); |
557 | 324 | R2 (D, A, B, C, X[ 4], 11, 0x4bdecfa9L); |
558 | 324 | R2 (C, D, A, B, X[ 7], 16, 0xf6bb4b60L); |
559 | 324 | R2 (B, C, D, A, X[10], 23, 0xbebfbc70L); |
560 | 324 | R2 (A, B, C, D, X[13], 4, 0x289b7ec6L); |
561 | 324 | R2 (D, A, B, C, X[ 0], 11, 0xeaa127faL); |
562 | 324 | R2 (C, D, A, B, X[ 3], 16, 0xd4ef3085L); |
563 | 324 | R2 (B, C, D, A, X[ 6], 23, 0x04881d05L); |
564 | 324 | R2 (A, B, C, D, X[ 9], 4, 0xd9d4d039L); |
565 | 324 | R2 (D, A, B, C, X[12], 11, 0xe6db99e5L); |
566 | 324 | R2 (C, D, A, B, X[15], 16, 0x1fa27cf8L); |
567 | 324 | R2 (B, C, D, A, X[ 2], 23, 0xc4ac5665L); |
568 | | |
569 | 324 | R3 (A, B, C, D, X[ 0], 6, 0xf4292244L); |
570 | 324 | R3 (D, A, B, C, X[ 7], 10, 0x432aff97L); |
571 | 324 | R3 (C, D, A, B, X[14], 15, 0xab9423a7L); |
572 | 324 | R3 (B, C, D, A, X[ 5], 21, 0xfc93a039L); |
573 | 324 | R3 (A, B, C, D, X[12], 6, 0x655b59c3L); |
574 | 324 | R3 (D, A, B, C, X[ 3], 10, 0x8f0ccc92L); |
575 | 324 | R3 (C, D, A, B, X[10], 15, 0xffeff47dL); |
576 | 324 | R3 (B, C, D, A, X[ 1], 21, 0x85845dd1L); |
577 | 324 | R3 (A, B, C, D, X[ 8], 6, 0x6fa87e4fL); |
578 | 324 | R3 (D, A, B, C, X[15], 10, 0xfe2ce6e0L); |
579 | 324 | R3 (C, D, A, B, X[ 6], 15, 0xa3014314L); |
580 | 324 | R3 (B, C, D, A, X[13], 21, 0x4e0811a1L); |
581 | 324 | R3 (A, B, C, D, X[ 4], 6, 0xf7537e82L); |
582 | 324 | R3 (D, A, B, C, X[11], 10, 0xbd3af235L); |
583 | 324 | R3 (C, D, A, B, X[ 2], 15, 0x2ad7d2bbL); |
584 | 324 | R3 (B, C, D, A, X[ 9], 21, 0xeb86d391L); |
585 | | |
586 | 324 | ctx->m_nA += A; |
587 | 324 | ctx->m_nB += B; |
588 | 324 | ctx->m_nC += C; |
589 | 324 | ctx->m_nD += D; |
590 | 324 | } |
591 | | |
592 | | static void endMD5(DigestContextMD5 *ctx) |
593 | 0 | { |
594 | 0 | static const sal_uInt8 end[4] = |
595 | 0 | { |
596 | 0 | 0x80, 0x00, 0x00, 0x00 |
597 | 0 | }; |
598 | 0 | const sal_uInt8 *p = end; |
599 | |
|
600 | 0 | sal_uInt32 *X; |
601 | 0 | int i; |
602 | |
|
603 | 0 | X = ctx->m_pData; |
604 | 0 | i = (ctx->m_nDatLen >> 2); |
605 | |
|
606 | | #ifdef OSL_BIGENDIAN |
607 | | swapLong(X, i + 1); |
608 | | #endif /* OSL_BIGENDIAN */ |
609 | |
|
610 | 0 | switch (ctx->m_nDatLen & 0x03) |
611 | 0 | { |
612 | 0 | case 1: X[i] &= 0x000000ff; break; |
613 | 0 | case 2: X[i] &= 0x0000ffff; break; |
614 | 0 | case 3: X[i] &= 0x00ffffff; break; |
615 | 0 | } |
616 | | |
617 | 0 | switch (ctx->m_nDatLen & 0x03) |
618 | 0 | { |
619 | 0 | case 0: X[i] = static_cast<sal_uInt32>(*(p++)) << 0; |
620 | 0 | [[fallthrough]]; |
621 | 0 | case 1: X[i] |= static_cast<sal_uInt32>(*(p++)) << 8; |
622 | 0 | [[fallthrough]]; |
623 | 0 | case 2: X[i] |= static_cast<sal_uInt32>(*(p++)) << 16; |
624 | 0 | [[fallthrough]]; |
625 | 0 | case 3: X[i] |= static_cast<sal_uInt32>(*p) << 24; |
626 | 0 | } |
627 | |
|
628 | 0 | i += 1; |
629 | |
|
630 | 0 | if (i > (DIGEST_LBLOCK_MD5 - 2)) |
631 | 0 | { |
632 | 0 | for (; i < DIGEST_LBLOCK_MD5; i++) |
633 | 0 | { |
634 | 0 | X[i] = 0; |
635 | 0 | } |
636 | |
|
637 | 0 | updateMD5(ctx); |
638 | 0 | i = 0; |
639 | 0 | } |
640 | |
|
641 | 0 | for (; i < (DIGEST_LBLOCK_MD5 - 2); i++) |
642 | 0 | X[i] = 0; |
643 | |
|
644 | 0 | X[DIGEST_LBLOCK_MD5 - 2] = ctx->m_nL; |
645 | 0 | X[DIGEST_LBLOCK_MD5 - 1] = ctx->m_nH; |
646 | |
|
647 | 0 | updateMD5(ctx); |
648 | 0 | } |
649 | | |
650 | | rtlDigestError SAL_CALL rtl_digest_MD5( |
651 | | const void *pData, sal_uInt32 nDatLen, |
652 | | sal_uInt8 *pBuffer, sal_uInt32 nBufLen) noexcept |
653 | 0 | { |
654 | 0 | DigestMD5_Impl digest; |
655 | 0 | rtlDigestError result; |
656 | |
|
657 | 0 | digest.m_digest = MD5; |
658 | 0 | initMD5(&(digest.m_context)); |
659 | |
|
660 | 0 | result = rtl_digest_update(&digest, pData, nDatLen); |
661 | 0 | if (result == rtl_Digest_E_None) |
662 | 0 | result = rtl_digest_getMD5(&digest, pBuffer, nBufLen); |
663 | |
|
664 | 0 | rtl_secureZeroMemory(&digest, sizeof(digest)); |
665 | 0 | return result; |
666 | 0 | } |
667 | | |
668 | | rtlDigest SAL_CALL rtl_digest_createMD5() noexcept |
669 | 779 | { |
670 | 779 | DigestMD5_Impl *pImpl = RTL_DIGEST_CREATE(DigestMD5_Impl); |
671 | 779 | if (pImpl) |
672 | 779 | { |
673 | 779 | pImpl->m_digest = MD5; |
674 | 779 | initMD5(&(pImpl->m_context)); |
675 | 779 | } |
676 | 779 | return static_cast<rtlDigest>(pImpl); |
677 | 779 | } |
678 | | |
679 | | rtlDigestError SAL_CALL rtl_digest_updateMD5( |
680 | | rtlDigest Digest, const void *pData, sal_uInt32 nDatLen) noexcept |
681 | 945 | { |
682 | 945 | DigestMD5_Impl *pImpl = static_cast<DigestMD5_Impl *>(Digest); |
683 | 945 | const sal_uInt8 *d = static_cast<const sal_uInt8 *>(pData); |
684 | | |
685 | 945 | DigestContextMD5 *ctx; |
686 | 945 | sal_uInt32 len; |
687 | | |
688 | 945 | if (!pImpl || !pData) |
689 | 0 | return rtl_Digest_E_Argument; |
690 | | |
691 | 945 | if (pImpl->m_digest.m_algorithm != rtl_Digest_AlgorithmMD5) |
692 | 0 | return rtl_Digest_E_Algorithm; |
693 | | |
694 | 945 | if (nDatLen == 0) |
695 | 0 | return rtl_Digest_E_None; |
696 | | |
697 | 945 | ctx = &(pImpl->m_context); |
698 | | |
699 | 945 | len = ctx->m_nL + (nDatLen << 3); |
700 | 945 | if (len < ctx->m_nL) |
701 | 0 | ctx->m_nH += 1; |
702 | | |
703 | 945 | ctx->m_nH += (nDatLen >> 29); |
704 | 945 | ctx->m_nL = len; |
705 | | |
706 | 945 | if (ctx->m_nDatLen) |
707 | 713 | { |
708 | 713 | sal_uInt8 *p = reinterpret_cast<sal_uInt8 *>(ctx->m_pData) + ctx->m_nDatLen; |
709 | 713 | sal_uInt32 n = DIGEST_CBLOCK_MD5 - ctx->m_nDatLen; |
710 | | |
711 | 713 | if (nDatLen < n) |
712 | 575 | { |
713 | 575 | memcpy(p, d, nDatLen); |
714 | 575 | ctx->m_nDatLen += nDatLen; |
715 | | |
716 | 575 | return rtl_Digest_E_None; |
717 | 575 | } |
718 | | |
719 | 138 | memcpy(p, d, n); |
720 | 138 | d += n; |
721 | 138 | nDatLen -= n; |
722 | | |
723 | | #ifdef OSL_BIGENDIAN |
724 | | swapLong(ctx->m_pData, DIGEST_LBLOCK_MD5); |
725 | | #endif /* OSL_BIGENDIAN */ |
726 | | |
727 | 138 | updateMD5(ctx); |
728 | 138 | ctx->m_nDatLen = 0; |
729 | 138 | } |
730 | | |
731 | 556 | while (nDatLen >= DIGEST_CBLOCK_MD5) |
732 | 186 | { |
733 | 186 | memcpy(ctx->m_pData, d, DIGEST_CBLOCK_MD5); |
734 | 186 | d += DIGEST_CBLOCK_MD5; |
735 | 186 | nDatLen -= DIGEST_CBLOCK_MD5; |
736 | | |
737 | | #ifdef OSL_BIGENDIAN |
738 | | swapLong(ctx->m_pData, DIGEST_LBLOCK_MD5); |
739 | | #endif /* OSL_BIGENDIAN */ |
740 | | |
741 | 186 | updateMD5(ctx); |
742 | 186 | } |
743 | | |
744 | 370 | memcpy(ctx->m_pData, d, nDatLen); |
745 | 370 | ctx->m_nDatLen = nDatLen; |
746 | | |
747 | 370 | return rtl_Digest_E_None; |
748 | 945 | } |
749 | | |
750 | | rtlDigestError SAL_CALL rtl_digest_getMD5( |
751 | | rtlDigest Digest, sal_uInt8 *pBuffer, sal_uInt32 nBufLen) noexcept |
752 | 0 | { |
753 | 0 | DigestMD5_Impl *pImpl = static_cast<DigestMD5_Impl *>(Digest); |
754 | 0 | sal_uInt8 *p = pBuffer; |
755 | |
|
756 | 0 | DigestContextMD5 *ctx; |
757 | |
|
758 | 0 | if (!pImpl || !pBuffer) |
759 | 0 | return rtl_Digest_E_Argument; |
760 | | |
761 | 0 | if (pImpl->m_digest.m_algorithm != rtl_Digest_AlgorithmMD5) |
762 | 0 | return rtl_Digest_E_Algorithm; |
763 | | |
764 | 0 | if (pImpl->m_digest.m_length > nBufLen) |
765 | 0 | return rtl_Digest_E_BufferSize; |
766 | | |
767 | 0 | ctx = &(pImpl->m_context); |
768 | |
|
769 | 0 | endMD5(ctx); |
770 | 0 | RTL_DIGEST_LTOC(ctx->m_nA, p); |
771 | 0 | RTL_DIGEST_LTOC(ctx->m_nB, p); |
772 | 0 | RTL_DIGEST_LTOC(ctx->m_nC, p); |
773 | 0 | RTL_DIGEST_LTOC(ctx->m_nD, p); |
774 | 0 | initMD5(ctx); |
775 | |
|
776 | 0 | return rtl_Digest_E_None; |
777 | 0 | } |
778 | | |
779 | | rtlDigestError SAL_CALL rtl_digest_rawMD5( |
780 | | rtlDigest Digest, sal_uInt8 *pBuffer, sal_uInt32 nBufLen) noexcept |
781 | 209 | { |
782 | 209 | DigestMD5_Impl *pImpl = static_cast<DigestMD5_Impl *>(Digest); |
783 | 209 | sal_uInt8 *p = pBuffer; |
784 | | |
785 | 209 | DigestContextMD5 *ctx; |
786 | | |
787 | 209 | if (!pImpl || !pBuffer) |
788 | 0 | return rtl_Digest_E_Argument; |
789 | | |
790 | 209 | if (pImpl->m_digest.m_algorithm != rtl_Digest_AlgorithmMD5) |
791 | 0 | return rtl_Digest_E_Algorithm; |
792 | | |
793 | 209 | if (pImpl->m_digest.m_length > nBufLen) |
794 | 0 | return rtl_Digest_E_BufferSize; |
795 | | |
796 | 209 | ctx = &(pImpl->m_context); |
797 | | |
798 | | /* not finalized */ |
799 | 209 | RTL_DIGEST_LTOC(ctx->m_nA, p); |
800 | 209 | RTL_DIGEST_LTOC(ctx->m_nB, p); |
801 | 209 | RTL_DIGEST_LTOC(ctx->m_nC, p); |
802 | 209 | RTL_DIGEST_LTOC(ctx->m_nD, p); |
803 | 209 | initMD5(ctx); |
804 | | |
805 | 209 | return rtl_Digest_E_None; |
806 | 209 | } |
807 | | |
808 | | void SAL_CALL rtl_digest_destroyMD5(rtlDigest Digest) noexcept |
809 | 779 | { |
810 | 779 | DigestMD5_Impl *pImpl = static_cast<DigestMD5_Impl *>(Digest); |
811 | 779 | if (pImpl) |
812 | 779 | { |
813 | 779 | if (pImpl->m_digest.m_algorithm == rtl_Digest_AlgorithmMD5) |
814 | 779 | rtl_freeZeroMemory(pImpl, sizeof(DigestMD5_Impl)); |
815 | 0 | else |
816 | 0 | free(pImpl); |
817 | 779 | } |
818 | 779 | } |
819 | | |
820 | 102 | #define DIGEST_CBLOCK_SHA 64 |
821 | 1.42k | #define DIGEST_LBLOCK_SHA 16 |
822 | | |
823 | | typedef sal_uInt32 DigestSHA_update_t(sal_uInt32 x); |
824 | | |
825 | | static sal_uInt32 updateSHA_0(sal_uInt32 x); |
826 | | static sal_uInt32 updateSHA_1(sal_uInt32 x); |
827 | | |
828 | | namespace { |
829 | | |
830 | | struct DigestContextSHA |
831 | | { |
832 | | DigestSHA_update_t *m_update; |
833 | | sal_uInt32 m_nDatLen; |
834 | | sal_uInt32 m_pData[DIGEST_LBLOCK_SHA]; |
835 | | sal_uInt32 m_nA, m_nB, m_nC, m_nD, m_nE; |
836 | | sal_uInt32 m_nL, m_nH; |
837 | | }; |
838 | | |
839 | | struct DigestSHA_Impl |
840 | | { |
841 | | Digest_Impl m_digest; |
842 | | DigestContextSHA m_context; |
843 | | }; |
844 | | |
845 | | } |
846 | | |
847 | | static void initSHA( |
848 | | DigestContextSHA *ctx, DigestSHA_update_t *fct); |
849 | | |
850 | | static void updateSHA(DigestContextSHA *ctx); |
851 | | static void endSHA(DigestContextSHA *ctx); |
852 | | |
853 | 2.04k | #define K_00_19 sal_uInt32(0x5a827999L) |
854 | 2.04k | #define K_20_39 sal_uInt32(0x6ed9eba1L) |
855 | 2.04k | #define K_40_59 sal_uInt32(0x8f1bbcdcL) |
856 | 2.04k | #define K_60_79 sal_uInt32(0xca62c1d6L) |
857 | | |
858 | 2.04k | #define F_00_19(b,c,d) ((((c) ^ (d)) & (b)) ^ (d)) |
859 | 4.08k | #define F_20_39(b,c,d) ((b) ^ (c) ^ (d)) |
860 | 2.04k | #define F_40_59(b,c,d) (((b) & (c)) | ((b) & (d)) | ((c) & (d))) |
861 | 2.04k | #define F_60_79(b,c,d) F_20_39(b,c,d) |
862 | | |
863 | | #define BODY_X(i) \ |
864 | 6.52k | (X[(i)&0x0f] ^ X[((i)+2)&0x0f] ^ X[((i)+8)&0x0f] ^ X[((i)+13)&0x0f]) |
865 | | |
866 | | #define BODY_00_15(u,i,a,b,c,d,e,f) \ |
867 | 1.63k | (f) = X[i]; \ |
868 | 1.63k | (f) += (e) + K_00_19 + RTL_DIGEST_ROTL((a), 5) + F_00_19((b), (c), (d)); \ |
869 | 1.63k | (b) = RTL_DIGEST_ROTL((b), 30); |
870 | | |
871 | | #define BODY_16_19(u,i,a,b,c,d,e,f) \ |
872 | 408 | (f) = BODY_X((i)); \ |
873 | 408 | (f) = X[(i)&0x0f] = (u)((f)); \ |
874 | 408 | (f) += (e) + K_00_19 + RTL_DIGEST_ROTL((a), 5) + F_00_19((b), (c), (d)); \ |
875 | 408 | (b) = RTL_DIGEST_ROTL((b), 30); |
876 | | |
877 | | #define BODY_20_39(u,i,a,b,c,d,e,f) \ |
878 | 2.04k | (f) = BODY_X((i)); \ |
879 | 2.04k | (f) = X[(i)&0x0f] = (u)((f)); \ |
880 | 2.04k | (f) += (e) + K_20_39 + RTL_DIGEST_ROTL((a), 5) + F_20_39((b), (c), (d)); \ |
881 | 2.04k | (b) = RTL_DIGEST_ROTL((b), 30); |
882 | | |
883 | | #define BODY_40_59(u,i,a,b,c,d,e,f) \ |
884 | 2.04k | (f) = BODY_X((i)); \ |
885 | 2.04k | (f) = X[(i)&0x0f] = (u)((f)); \ |
886 | 2.04k | (f) += (e) + K_40_59 + RTL_DIGEST_ROTL((a), 5) + F_40_59((b), (c), (d)); \ |
887 | 2.04k | (b) = RTL_DIGEST_ROTL((b), 30); |
888 | | |
889 | | #define BODY_60_79(u,i,a,b,c,d,e,f) \ |
890 | 2.04k | (f) = BODY_X((i)); \ |
891 | 2.04k | (f) = X[(i)&0x0f] = (u)((f)); \ |
892 | 2.04k | (f) += (e) + K_60_79 + RTL_DIGEST_ROTL((a), 5) + F_60_79((b), (c), (d)); \ |
893 | 2.04k | (b) = RTL_DIGEST_ROTL((b), 30); |
894 | | |
895 | | static void initSHA( |
896 | | DigestContextSHA *ctx, DigestSHA_update_t *fct) |
897 | 204 | { |
898 | 204 | memset(ctx, 0, sizeof(DigestContextSHA)); |
899 | 204 | ctx->m_update = fct; |
900 | | |
901 | 204 | ctx->m_nA = sal_uInt32(0x67452301L); |
902 | 204 | ctx->m_nB = sal_uInt32(0xefcdab89L); |
903 | 204 | ctx->m_nC = sal_uInt32(0x98badcfeL); |
904 | 204 | ctx->m_nD = sal_uInt32(0x10325476L); |
905 | 204 | ctx->m_nE = sal_uInt32(0xc3d2e1f0L); |
906 | 204 | } |
907 | | |
908 | | static void updateSHA(DigestContextSHA *ctx) |
909 | 102 | { |
910 | 102 | sal_uInt32 A, B, C, D, E, T; |
911 | 102 | sal_uInt32 *X; |
912 | | |
913 | 102 | DigestSHA_update_t *U; |
914 | 102 | U = ctx->m_update; |
915 | | |
916 | 102 | A = ctx->m_nA; |
917 | 102 | B = ctx->m_nB; |
918 | 102 | C = ctx->m_nC; |
919 | 102 | D = ctx->m_nD; |
920 | 102 | E = ctx->m_nE; |
921 | 102 | X = ctx->m_pData; |
922 | | |
923 | 102 | BODY_00_15 (U, 0, A, B, C, D, E, T); |
924 | 102 | BODY_00_15 (U, 1, T, A, B, C, D, E); |
925 | 102 | BODY_00_15 (U, 2, E, T, A, B, C, D); |
926 | 102 | BODY_00_15 (U, 3, D, E, T, A, B, C); |
927 | 102 | BODY_00_15 (U, 4, C, D, E, T, A, B); |
928 | 102 | BODY_00_15 (U, 5, B, C, D, E, T, A); |
929 | 102 | BODY_00_15 (U, 6, A, B, C, D, E, T); |
930 | 102 | BODY_00_15 (U, 7, T, A, B, C, D, E); |
931 | 102 | BODY_00_15 (U, 8, E, T, A, B, C, D); |
932 | 102 | BODY_00_15 (U, 9, D, E, T, A, B, C); |
933 | 102 | BODY_00_15 (U, 10, C, D, E, T, A, B); |
934 | 102 | BODY_00_15 (U, 11, B, C, D, E, T, A); |
935 | 102 | BODY_00_15 (U, 12, A, B, C, D, E, T); |
936 | 102 | BODY_00_15 (U, 13, T, A, B, C, D, E); |
937 | 102 | BODY_00_15 (U, 14, E, T, A, B, C, D); |
938 | 102 | BODY_00_15 (U, 15, D, E, T, A, B, C); |
939 | 102 | BODY_16_19 (U, 16, C, D, E, T, A, B); |
940 | 102 | BODY_16_19 (U, 17, B, C, D, E, T, A); |
941 | 102 | BODY_16_19 (U, 18, A, B, C, D, E, T); |
942 | 102 | BODY_16_19 (U, 19, T, A, B, C, D, E); |
943 | | |
944 | 102 | BODY_20_39 (U, 20, E, T, A, B, C, D); |
945 | 102 | BODY_20_39 (U, 21, D, E, T, A, B, C); |
946 | 102 | BODY_20_39 (U, 22, C, D, E, T, A, B); |
947 | 102 | BODY_20_39 (U, 23, B, C, D, E, T, A); |
948 | 102 | BODY_20_39 (U, 24, A, B, C, D, E, T); |
949 | 102 | BODY_20_39 (U, 25, T, A, B, C, D, E); |
950 | 102 | BODY_20_39 (U, 26, E, T, A, B, C, D); |
951 | 102 | BODY_20_39 (U, 27, D, E, T, A, B, C); |
952 | 102 | BODY_20_39 (U, 28, C, D, E, T, A, B); |
953 | 102 | BODY_20_39 (U, 29, B, C, D, E, T, A); |
954 | 102 | BODY_20_39 (U, 30, A, B, C, D, E, T); |
955 | 102 | BODY_20_39 (U, 31, T, A, B, C, D, E); |
956 | 102 | BODY_20_39 (U, 32, E, T, A, B, C, D); |
957 | 102 | BODY_20_39 (U, 33, D, E, T, A, B, C); |
958 | 102 | BODY_20_39 (U, 34, C, D, E, T, A, B); |
959 | 102 | BODY_20_39 (U, 35, B, C, D, E, T, A); |
960 | 102 | BODY_20_39 (U, 36, A, B, C, D, E, T); |
961 | 102 | BODY_20_39 (U, 37, T, A, B, C, D, E); |
962 | 102 | BODY_20_39 (U, 38, E, T, A, B, C, D); |
963 | 102 | BODY_20_39 (U, 39, D, E, T, A, B, C); |
964 | | |
965 | 102 | BODY_40_59 (U, 40, C, D, E, T, A, B); |
966 | 102 | BODY_40_59 (U, 41, B, C, D, E, T, A); |
967 | 102 | BODY_40_59 (U, 42, A, B, C, D, E, T); |
968 | 102 | BODY_40_59 (U, 43, T, A, B, C, D, E); |
969 | 102 | BODY_40_59 (U, 44, E, T, A, B, C, D); |
970 | 102 | BODY_40_59 (U, 45, D, E, T, A, B, C); |
971 | 102 | BODY_40_59 (U, 46, C, D, E, T, A, B); |
972 | 102 | BODY_40_59 (U, 47, B, C, D, E, T, A); |
973 | 102 | BODY_40_59 (U, 48, A, B, C, D, E, T); |
974 | 102 | BODY_40_59 (U, 49, T, A, B, C, D, E); |
975 | 102 | BODY_40_59 (U, 50, E, T, A, B, C, D); |
976 | 102 | BODY_40_59 (U, 51, D, E, T, A, B, C); |
977 | 102 | BODY_40_59 (U, 52, C, D, E, T, A, B); |
978 | 102 | BODY_40_59 (U, 53, B, C, D, E, T, A); |
979 | 102 | BODY_40_59 (U, 54, A, B, C, D, E, T); |
980 | 102 | BODY_40_59 (U, 55, T, A, B, C, D, E); |
981 | 102 | BODY_40_59 (U, 56, E, T, A, B, C, D); |
982 | 102 | BODY_40_59 (U, 57, D, E, T, A, B, C); |
983 | 102 | BODY_40_59 (U, 58, C, D, E, T, A, B); |
984 | 102 | BODY_40_59 (U, 59, B, C, D, E, T, A); |
985 | | |
986 | 102 | BODY_60_79 (U, 60, A, B, C, D, E, T); |
987 | 102 | BODY_60_79 (U, 61, T, A, B, C, D, E); |
988 | 102 | BODY_60_79 (U, 62, E, T, A, B, C, D); |
989 | 102 | BODY_60_79 (U, 63, D, E, T, A, B, C); |
990 | 102 | BODY_60_79 (U, 64, C, D, E, T, A, B); |
991 | 102 | BODY_60_79 (U, 65, B, C, D, E, T, A); |
992 | 102 | BODY_60_79 (U, 66, A, B, C, D, E, T); |
993 | 102 | BODY_60_79 (U, 67, T, A, B, C, D, E); |
994 | 102 | BODY_60_79 (U, 68, E, T, A, B, C, D); |
995 | 102 | BODY_60_79 (U, 69, D, E, T, A, B, C); |
996 | 102 | BODY_60_79 (U, 70, C, D, E, T, A, B); |
997 | 102 | BODY_60_79 (U, 71, B, C, D, E, T, A); |
998 | 102 | BODY_60_79 (U, 72, A, B, C, D, E, T); |
999 | 102 | BODY_60_79 (U, 73, T, A, B, C, D, E); |
1000 | 102 | BODY_60_79 (U, 74, E, T, A, B, C, D); |
1001 | 102 | BODY_60_79 (U, 75, D, E, T, A, B, C); |
1002 | 102 | BODY_60_79 (U, 76, C, D, E, T, A, B); |
1003 | 102 | BODY_60_79 (U, 77, B, C, D, E, T, A); |
1004 | 102 | BODY_60_79 (U, 78, A, B, C, D, E, T); |
1005 | 102 | BODY_60_79 (U, 79, T, A, B, C, D, E); |
1006 | | |
1007 | 102 | ctx->m_nA += E; |
1008 | 102 | ctx->m_nB += T; |
1009 | 102 | ctx->m_nC += A; |
1010 | 102 | ctx->m_nD += B; |
1011 | 102 | ctx->m_nE += C; |
1012 | 102 | } |
1013 | | |
1014 | | static void endSHA(DigestContextSHA *ctx) |
1015 | 102 | { |
1016 | 102 | static const sal_uInt8 end[4] = |
1017 | 102 | { |
1018 | 102 | 0x80, 0x00, 0x00, 0x00 |
1019 | 102 | }; |
1020 | 102 | const sal_uInt8 *p = end; |
1021 | | |
1022 | 102 | sal_uInt32 *X; |
1023 | 102 | int i; |
1024 | | |
1025 | 102 | X = ctx->m_pData; |
1026 | 102 | i = (ctx->m_nDatLen >> 2); |
1027 | | |
1028 | | #ifdef OSL_BIGENDIAN |
1029 | | swapLong(X, i + 1); |
1030 | | #endif /* OSL_BIGENDIAN */ |
1031 | | |
1032 | 102 | switch (ctx->m_nDatLen & 0x03) |
1033 | 102 | { |
1034 | 0 | case 1: X[i] &= 0x000000ff; break; |
1035 | 0 | case 2: X[i] &= 0x0000ffff; break; |
1036 | 102 | case 3: X[i] &= 0x00ffffff; break; |
1037 | 102 | } |
1038 | | |
1039 | 102 | switch (ctx->m_nDatLen & 0x03) |
1040 | 102 | { |
1041 | 0 | case 0: X[i] = static_cast<sal_uInt32>(*(p++)) << 0; |
1042 | 0 | [[fallthrough]]; |
1043 | 0 | case 1: X[i] |= static_cast<sal_uInt32>(*(p++)) << 8; |
1044 | 0 | [[fallthrough]]; |
1045 | 0 | case 2: X[i] |= static_cast<sal_uInt32>(*(p++)) << 16; |
1046 | 0 | [[fallthrough]]; |
1047 | 102 | case 3: X[i] |= static_cast<sal_uInt32>(*(p++)) << 24; |
1048 | 102 | } |
1049 | | |
1050 | 102 | swapLong(X, i + 1); |
1051 | | |
1052 | 102 | i += 1; |
1053 | | |
1054 | | // tdf#114939 NB: this is WRONG and should be ">" not ">=" but is not |
1055 | | // fixed as this buggy SHA1 implementation is needed for compatibility |
1056 | 102 | if (i >= (DIGEST_LBLOCK_SHA - 2)) |
1057 | 0 | { |
1058 | 0 | for (; i < DIGEST_LBLOCK_SHA; i++) |
1059 | 0 | { |
1060 | 0 | X[i] = 0; |
1061 | 0 | } |
1062 | |
|
1063 | 0 | updateSHA(ctx); |
1064 | 0 | i = 0; |
1065 | 0 | } |
1066 | | |
1067 | 1.12k | for (; i < (DIGEST_LBLOCK_SHA - 2); i++) |
1068 | 1.02k | { |
1069 | 1.02k | X[i] = 0; |
1070 | 1.02k | } |
1071 | | |
1072 | 102 | X[DIGEST_LBLOCK_SHA - 2] = ctx->m_nH; |
1073 | 102 | X[DIGEST_LBLOCK_SHA - 1] = ctx->m_nL; |
1074 | | |
1075 | 102 | updateSHA(ctx); |
1076 | 102 | } |
1077 | | |
1078 | | const Digest_Impl SHA_0 = |
1079 | | { |
1080 | | rtl_Digest_AlgorithmSHA, |
1081 | | RTL_DIGEST_LENGTH_SHA, |
1082 | | nullptr, |
1083 | | rtl_digest_destroySHA, |
1084 | | rtl_digest_updateSHA, |
1085 | | rtl_digest_getSHA |
1086 | | }; |
1087 | | |
1088 | | static sal_uInt32 updateSHA_0(sal_uInt32 x) |
1089 | 0 | { |
1090 | 0 | return x; |
1091 | 0 | } |
1092 | | |
1093 | | rtlDigestError SAL_CALL rtl_digest_SHA( |
1094 | | const void *pData, sal_uInt32 nDatLen, |
1095 | | sal_uInt8 *pBuffer, sal_uInt32 nBufLen) noexcept |
1096 | 0 | { |
1097 | 0 | DigestSHA_Impl digest; |
1098 | 0 | rtlDigestError result; |
1099 | |
|
1100 | 0 | digest.m_digest = SHA_0; |
1101 | 0 | initSHA(&(digest.m_context), updateSHA_0); |
1102 | |
|
1103 | 0 | result = rtl_digest_updateSHA(&digest, pData, nDatLen); |
1104 | 0 | if (result == rtl_Digest_E_None) |
1105 | 0 | result = rtl_digest_getSHA(&digest, pBuffer, nBufLen); |
1106 | |
|
1107 | 0 | rtl_secureZeroMemory(&digest, sizeof(digest)); |
1108 | 0 | return result; |
1109 | 0 | } |
1110 | | |
1111 | | rtlDigest SAL_CALL rtl_digest_createSHA() noexcept |
1112 | 0 | { |
1113 | 0 | DigestSHA_Impl *pImpl = RTL_DIGEST_CREATE(DigestSHA_Impl); |
1114 | 0 | if (pImpl) |
1115 | 0 | { |
1116 | 0 | pImpl->m_digest = SHA_0; |
1117 | 0 | initSHA(&(pImpl->m_context), updateSHA_0); |
1118 | 0 | } |
1119 | 0 | return static_cast<rtlDigest>(pImpl); |
1120 | 0 | } |
1121 | | |
1122 | | rtlDigestError SAL_CALL rtl_digest_updateSHA( |
1123 | | rtlDigest Digest, const void *pData, sal_uInt32 nDatLen) noexcept |
1124 | 0 | { |
1125 | 0 | DigestSHA_Impl *pImpl = static_cast<DigestSHA_Impl *>(Digest); |
1126 | 0 | const sal_uInt8 *d = static_cast<const sal_uInt8 *>(pData); |
1127 | |
|
1128 | 0 | DigestContextSHA *ctx; |
1129 | 0 | sal_uInt32 len; |
1130 | |
|
1131 | 0 | if (!pImpl || !pData) |
1132 | 0 | return rtl_Digest_E_Argument; |
1133 | | |
1134 | 0 | if (pImpl->m_digest.m_algorithm != rtl_Digest_AlgorithmSHA) |
1135 | 0 | return rtl_Digest_E_Algorithm; |
1136 | | |
1137 | 0 | if (nDatLen == 0) |
1138 | 0 | return rtl_Digest_E_None; |
1139 | | |
1140 | 0 | ctx = &(pImpl->m_context); |
1141 | |
|
1142 | 0 | len = ctx->m_nL + (nDatLen << 3); |
1143 | 0 | if (len < ctx->m_nL) |
1144 | 0 | ctx->m_nH += 1; |
1145 | |
|
1146 | 0 | ctx->m_nH += (nDatLen >> 29); |
1147 | 0 | ctx->m_nL = len; |
1148 | |
|
1149 | 0 | if (ctx->m_nDatLen) |
1150 | 0 | { |
1151 | 0 | sal_uInt8 *p = reinterpret_cast<sal_uInt8 *>(ctx->m_pData) + ctx->m_nDatLen; |
1152 | 0 | sal_uInt32 n = DIGEST_CBLOCK_SHA - ctx->m_nDatLen; |
1153 | |
|
1154 | 0 | if (nDatLen < n) |
1155 | 0 | { |
1156 | 0 | memcpy(p, d, nDatLen); |
1157 | 0 | ctx->m_nDatLen += nDatLen; |
1158 | |
|
1159 | 0 | return rtl_Digest_E_None; |
1160 | 0 | } |
1161 | | |
1162 | 0 | memcpy(p, d, n); |
1163 | 0 | d += n; |
1164 | 0 | nDatLen -= n; |
1165 | |
|
1166 | 0 | #ifndef OSL_BIGENDIAN |
1167 | 0 | swapLong(ctx->m_pData, DIGEST_LBLOCK_SHA); |
1168 | 0 | #endif /* OSL_BIGENDIAN */ |
1169 | |
|
1170 | 0 | updateSHA(ctx); |
1171 | 0 | ctx->m_nDatLen = 0; |
1172 | 0 | } |
1173 | | |
1174 | 0 | while (nDatLen >= DIGEST_CBLOCK_SHA) |
1175 | 0 | { |
1176 | 0 | memcpy(ctx->m_pData, d, DIGEST_CBLOCK_SHA); |
1177 | 0 | d += DIGEST_CBLOCK_SHA; |
1178 | 0 | nDatLen -= DIGEST_CBLOCK_SHA; |
1179 | |
|
1180 | 0 | #ifndef OSL_BIGENDIAN |
1181 | 0 | swapLong(ctx->m_pData, DIGEST_LBLOCK_SHA); |
1182 | 0 | #endif /* OSL_BIGENDIAN */ |
1183 | |
|
1184 | 0 | updateSHA(ctx); |
1185 | 0 | } |
1186 | |
|
1187 | 0 | memcpy(ctx->m_pData, d, nDatLen); |
1188 | 0 | ctx->m_nDatLen = nDatLen; |
1189 | |
|
1190 | 0 | return rtl_Digest_E_None; |
1191 | 0 | } |
1192 | | |
1193 | | rtlDigestError SAL_CALL rtl_digest_getSHA( |
1194 | | rtlDigest Digest, sal_uInt8 *pBuffer, sal_uInt32 nBufLen) noexcept |
1195 | 0 | { |
1196 | 0 | DigestSHA_Impl *pImpl = static_cast<DigestSHA_Impl *>(Digest); |
1197 | 0 | sal_uInt8 *p = pBuffer; |
1198 | |
|
1199 | 0 | DigestContextSHA *ctx; |
1200 | |
|
1201 | 0 | if (!pImpl || !pBuffer) |
1202 | 0 | return rtl_Digest_E_Argument; |
1203 | | |
1204 | 0 | if (pImpl->m_digest.m_algorithm != rtl_Digest_AlgorithmSHA) |
1205 | 0 | return rtl_Digest_E_Algorithm; |
1206 | | |
1207 | 0 | if (pImpl->m_digest.m_length > nBufLen) |
1208 | 0 | return rtl_Digest_E_BufferSize; |
1209 | | |
1210 | 0 | ctx = &(pImpl->m_context); |
1211 | |
|
1212 | 0 | endSHA(ctx); |
1213 | 0 | RTL_DIGEST_HTONL(ctx->m_nA, p); |
1214 | 0 | RTL_DIGEST_HTONL(ctx->m_nB, p); |
1215 | 0 | RTL_DIGEST_HTONL(ctx->m_nC, p); |
1216 | 0 | RTL_DIGEST_HTONL(ctx->m_nD, p); |
1217 | 0 | RTL_DIGEST_HTONL(ctx->m_nE, p); |
1218 | 0 | initSHA(ctx, updateSHA_0); |
1219 | |
|
1220 | 0 | return rtl_Digest_E_None; |
1221 | 0 | } |
1222 | | |
1223 | | void SAL_CALL rtl_digest_destroySHA(rtlDigest Digest) noexcept |
1224 | 0 | { |
1225 | 0 | DigestSHA_Impl *pImpl = static_cast< DigestSHA_Impl * >(Digest); |
1226 | 0 | if (pImpl) |
1227 | 0 | { |
1228 | 0 | if (pImpl->m_digest.m_algorithm == rtl_Digest_AlgorithmSHA) |
1229 | 0 | rtl_freeZeroMemory(pImpl, sizeof(DigestSHA_Impl)); |
1230 | 0 | else |
1231 | 0 | free(pImpl); |
1232 | 0 | } |
1233 | 0 | } |
1234 | | |
1235 | | const Digest_Impl SHA_1 = |
1236 | | { |
1237 | | rtl_Digest_AlgorithmSHA1, |
1238 | | RTL_DIGEST_LENGTH_SHA1, |
1239 | | nullptr, |
1240 | | rtl_digest_destroySHA1, |
1241 | | rtl_digest_updateSHA1, |
1242 | | rtl_digest_getSHA1 |
1243 | | }; |
1244 | | |
1245 | | static sal_uInt32 updateSHA_1(sal_uInt32 x) |
1246 | 6.52k | { |
1247 | 6.52k | return RTL_DIGEST_ROTL(x, 1); |
1248 | 6.52k | } |
1249 | | |
1250 | | rtlDigestError SAL_CALL rtl_digest_SHA1( |
1251 | | const void *pData, sal_uInt32 nDatLen, |
1252 | | sal_uInt8 *pBuffer, sal_uInt32 nBufLen) noexcept |
1253 | 102 | { |
1254 | 102 | DigestSHA_Impl digest; |
1255 | 102 | rtlDigestError result; |
1256 | | |
1257 | 102 | digest.m_digest = SHA_1; |
1258 | 102 | initSHA(&(digest.m_context), updateSHA_1); |
1259 | | |
1260 | 102 | result = rtl_digest_updateSHA1(&digest, pData, nDatLen); |
1261 | 102 | if (result == rtl_Digest_E_None) |
1262 | 102 | result = rtl_digest_getSHA1(&digest, pBuffer, nBufLen); |
1263 | | |
1264 | 102 | rtl_secureZeroMemory(&digest, sizeof(digest)); |
1265 | 102 | return result; |
1266 | 102 | } |
1267 | | |
1268 | | rtlDigest SAL_CALL rtl_digest_createSHA1() noexcept |
1269 | 0 | { |
1270 | 0 | DigestSHA_Impl *pImpl = RTL_DIGEST_CREATE(DigestSHA_Impl); |
1271 | 0 | if (pImpl) |
1272 | 0 | { |
1273 | 0 | pImpl->m_digest = SHA_1; |
1274 | 0 | initSHA(&(pImpl->m_context), updateSHA_1); |
1275 | 0 | } |
1276 | 0 | return static_cast<rtlDigest>(pImpl); |
1277 | 0 | } |
1278 | | |
1279 | | rtlDigestError SAL_CALL rtl_digest_updateSHA1( |
1280 | | rtlDigest Digest, const void *pData, sal_uInt32 nDatLen) noexcept |
1281 | 102 | { |
1282 | 102 | DigestSHA_Impl *pImpl = static_cast< DigestSHA_Impl * >(Digest); |
1283 | 102 | const sal_uInt8 *d = static_cast< const sal_uInt8 * >(pData); |
1284 | | |
1285 | 102 | DigestContextSHA *ctx; |
1286 | 102 | sal_uInt32 len; |
1287 | | |
1288 | 102 | if (!pImpl || !pData) |
1289 | 0 | return rtl_Digest_E_Argument; |
1290 | | |
1291 | 102 | if (pImpl->m_digest.m_algorithm != rtl_Digest_AlgorithmSHA1) |
1292 | 0 | return rtl_Digest_E_Algorithm; |
1293 | | |
1294 | 102 | if (nDatLen == 0) |
1295 | 0 | return rtl_Digest_E_None; |
1296 | | |
1297 | 102 | ctx = &(pImpl->m_context); |
1298 | | |
1299 | 102 | len = ctx->m_nL + (nDatLen << 3); |
1300 | 102 | if (len < ctx->m_nL) |
1301 | 0 | ctx->m_nH += 1; |
1302 | | |
1303 | 102 | ctx->m_nH += (nDatLen >> 29); |
1304 | 102 | ctx->m_nL = len; |
1305 | | |
1306 | 102 | if (ctx->m_nDatLen) |
1307 | 0 | { |
1308 | 0 | sal_uInt8 *p = reinterpret_cast<sal_uInt8 *>(ctx->m_pData) + ctx->m_nDatLen; |
1309 | 0 | sal_uInt32 n = DIGEST_CBLOCK_SHA - ctx->m_nDatLen; |
1310 | |
|
1311 | 0 | if (nDatLen < n) |
1312 | 0 | { |
1313 | 0 | memcpy(p, d, nDatLen); |
1314 | 0 | ctx->m_nDatLen += nDatLen; |
1315 | |
|
1316 | 0 | return rtl_Digest_E_None; |
1317 | 0 | } |
1318 | | |
1319 | 0 | memcpy(p, d, n); |
1320 | 0 | d += n; |
1321 | 0 | nDatLen -= n; |
1322 | |
|
1323 | 0 | #ifndef OSL_BIGENDIAN |
1324 | 0 | swapLong(ctx->m_pData, DIGEST_LBLOCK_SHA); |
1325 | 0 | #endif /* OSL_BIGENDIAN */ |
1326 | |
|
1327 | 0 | updateSHA(ctx); |
1328 | 0 | ctx->m_nDatLen = 0; |
1329 | 0 | } |
1330 | | |
1331 | 102 | while (nDatLen >= DIGEST_CBLOCK_SHA) |
1332 | 0 | { |
1333 | 0 | memcpy(ctx->m_pData, d, DIGEST_CBLOCK_SHA); |
1334 | 0 | d += DIGEST_CBLOCK_SHA; |
1335 | 0 | nDatLen -= DIGEST_CBLOCK_SHA; |
1336 | |
|
1337 | 0 | #ifndef OSL_BIGENDIAN |
1338 | 0 | swapLong(ctx->m_pData, DIGEST_LBLOCK_SHA); |
1339 | 0 | #endif /* OSL_BIGENDIAN */ |
1340 | |
|
1341 | 0 | updateSHA(ctx); |
1342 | 0 | } |
1343 | | |
1344 | 102 | memcpy(ctx->m_pData, d, nDatLen); |
1345 | 102 | ctx->m_nDatLen = nDatLen; |
1346 | | |
1347 | 102 | return rtl_Digest_E_None; |
1348 | 102 | } |
1349 | | |
1350 | | rtlDigestError SAL_CALL rtl_digest_getSHA1 ( |
1351 | | rtlDigest Digest, sal_uInt8 *pBuffer, sal_uInt32 nBufLen) noexcept |
1352 | 102 | { |
1353 | 102 | DigestSHA_Impl *pImpl = static_cast<DigestSHA_Impl *>(Digest); |
1354 | 102 | sal_uInt8 *p = pBuffer; |
1355 | | |
1356 | 102 | DigestContextSHA *ctx; |
1357 | | |
1358 | 102 | if (!pImpl || !pBuffer) |
1359 | 0 | return rtl_Digest_E_Argument; |
1360 | | |
1361 | 102 | if (pImpl->m_digest.m_algorithm != rtl_Digest_AlgorithmSHA1) |
1362 | 0 | return rtl_Digest_E_Algorithm; |
1363 | | |
1364 | 102 | if (pImpl->m_digest.m_length > nBufLen) |
1365 | 0 | return rtl_Digest_E_BufferSize; |
1366 | | |
1367 | 102 | ctx = &(pImpl->m_context); |
1368 | | |
1369 | 102 | endSHA(ctx); |
1370 | 102 | RTL_DIGEST_HTONL(ctx->m_nA, p); |
1371 | 102 | RTL_DIGEST_HTONL(ctx->m_nB, p); |
1372 | 102 | RTL_DIGEST_HTONL(ctx->m_nC, p); |
1373 | 102 | RTL_DIGEST_HTONL(ctx->m_nD, p); |
1374 | 102 | RTL_DIGEST_HTONL(ctx->m_nE, p); |
1375 | 102 | initSHA(ctx, updateSHA_1); |
1376 | | |
1377 | 102 | return rtl_Digest_E_None; |
1378 | 102 | } |
1379 | | |
1380 | | void SAL_CALL rtl_digest_destroySHA1(rtlDigest Digest) noexcept |
1381 | 0 | { |
1382 | 0 | DigestSHA_Impl *pImpl = static_cast< DigestSHA_Impl * >(Digest); |
1383 | 0 | if (pImpl) |
1384 | 0 | { |
1385 | 0 | if (pImpl->m_digest.m_algorithm == rtl_Digest_AlgorithmSHA1) |
1386 | 0 | rtl_freeZeroMemory(pImpl, sizeof(DigestSHA_Impl)); |
1387 | 0 | else |
1388 | 0 | free(pImpl); |
1389 | 0 | } |
1390 | 0 | } |
1391 | | |
1392 | 0 | #define DIGEST_CBLOCK_HMAC_MD5 64 |
1393 | | |
1394 | | namespace { |
1395 | | |
1396 | | struct ContextHMAC_MD5 |
1397 | | { |
1398 | | DigestMD5_Impl m_hash; |
1399 | | sal_uInt8 m_opad[DIGEST_CBLOCK_HMAC_MD5]; |
1400 | | }; |
1401 | | |
1402 | | struct DigestHMAC_MD5_Impl |
1403 | | { |
1404 | | Digest_Impl m_digest; |
1405 | | ContextHMAC_MD5 m_context; |
1406 | | }; |
1407 | | |
1408 | | } |
1409 | | |
1410 | | static void initHMAC_MD5(ContextHMAC_MD5 * ctx); |
1411 | | static void ipadHMAC_MD5(ContextHMAC_MD5 * ctx); |
1412 | | static void opadHMAC_MD5(ContextHMAC_MD5 * ctx); |
1413 | | |
1414 | | const Digest_Impl HMAC_MD5 = |
1415 | | { |
1416 | | rtl_Digest_AlgorithmHMAC_MD5, |
1417 | | RTL_DIGEST_LENGTH_MD5, |
1418 | | |
1419 | | rtl_digest_initHMAC_MD5, |
1420 | | rtl_digest_destroyHMAC_MD5, |
1421 | | rtl_digest_updateHMAC_MD5, |
1422 | | rtl_digest_getHMAC_MD5 |
1423 | | }; |
1424 | | |
1425 | | static void initHMAC_MD5(ContextHMAC_MD5 * ctx) |
1426 | 0 | { |
1427 | 0 | DigestMD5_Impl *pImpl = &(ctx->m_hash); |
1428 | |
|
1429 | 0 | pImpl->m_digest = MD5; |
1430 | 0 | initMD5(&(pImpl->m_context)); |
1431 | |
|
1432 | 0 | memset(ctx->m_opad, 0, DIGEST_CBLOCK_HMAC_MD5); |
1433 | 0 | } |
1434 | | |
1435 | | static void ipadHMAC_MD5(ContextHMAC_MD5 * ctx) |
1436 | 0 | { |
1437 | 0 | sal_uInt32 i; |
1438 | |
|
1439 | 0 | for (i = 0; i < DIGEST_CBLOCK_HMAC_MD5; i++) |
1440 | 0 | { |
1441 | 0 | ctx->m_opad[i] ^= 0x36; |
1442 | 0 | } |
1443 | |
|
1444 | 0 | rtl_digest_updateMD5(&(ctx->m_hash), ctx->m_opad, DIGEST_CBLOCK_HMAC_MD5); |
1445 | |
|
1446 | 0 | for (i = 0; i < DIGEST_CBLOCK_HMAC_MD5; i++) |
1447 | 0 | { |
1448 | 0 | ctx->m_opad[i] ^= 0x36; |
1449 | 0 | } |
1450 | 0 | } |
1451 | | |
1452 | | static void opadHMAC_MD5(ContextHMAC_MD5 * ctx) |
1453 | 0 | { |
1454 | 0 | sal_uInt32 i; |
1455 | |
|
1456 | 0 | for (i = 0; i < DIGEST_CBLOCK_HMAC_MD5; i++) |
1457 | 0 | { |
1458 | 0 | ctx->m_opad[i] ^= 0x5c; |
1459 | 0 | } |
1460 | 0 | } |
1461 | | |
1462 | | rtlDigestError SAL_CALL rtl_digest_HMAC_MD5( |
1463 | | const sal_uInt8 *pKeyData, sal_uInt32 nKeyLen, |
1464 | | const void *pData, sal_uInt32 nDatLen, |
1465 | | sal_uInt8 *pBuffer, sal_uInt32 nBufLen) noexcept |
1466 | 0 | { |
1467 | 0 | DigestHMAC_MD5_Impl digest; |
1468 | 0 | rtlDigestError result; |
1469 | |
|
1470 | 0 | digest.m_digest = HMAC_MD5; |
1471 | |
|
1472 | 0 | result = rtl_digest_initHMAC_MD5(&digest, pKeyData, nKeyLen); |
1473 | 0 | if (result == rtl_Digest_E_None) |
1474 | 0 | { |
1475 | 0 | result = rtl_digest_updateHMAC_MD5(&digest, pData, nDatLen); |
1476 | 0 | if (result == rtl_Digest_E_None) |
1477 | 0 | result = rtl_digest_getHMAC_MD5(&digest, pBuffer, nBufLen); |
1478 | 0 | } |
1479 | |
|
1480 | 0 | rtl_secureZeroMemory(&digest, sizeof(digest)); |
1481 | 0 | return result; |
1482 | 0 | } |
1483 | | |
1484 | | rtlDigest SAL_CALL rtl_digest_createHMAC_MD5() noexcept |
1485 | 0 | { |
1486 | 0 | DigestHMAC_MD5_Impl *pImpl = RTL_DIGEST_CREATE(DigestHMAC_MD5_Impl); |
1487 | 0 | if (pImpl) |
1488 | 0 | { |
1489 | 0 | pImpl->m_digest = HMAC_MD5; |
1490 | 0 | initHMAC_MD5(&(pImpl->m_context)); |
1491 | 0 | } |
1492 | 0 | return static_cast< rtlDigest >(pImpl); |
1493 | 0 | } |
1494 | | |
1495 | | rtlDigestError SAL_CALL rtl_digest_initHMAC_MD5( |
1496 | | rtlDigest Digest, const sal_uInt8 *pKeyData, sal_uInt32 nKeyLen) noexcept |
1497 | 0 | { |
1498 | 0 | DigestHMAC_MD5_Impl *pImpl = static_cast< DigestHMAC_MD5_Impl* >(Digest); |
1499 | 0 | ContextHMAC_MD5 *ctx; |
1500 | |
|
1501 | 0 | if (!pImpl || !pKeyData) |
1502 | 0 | return rtl_Digest_E_Argument; |
1503 | | |
1504 | 0 | if (pImpl->m_digest.m_algorithm != rtl_Digest_AlgorithmHMAC_MD5) |
1505 | 0 | return rtl_Digest_E_Algorithm; |
1506 | | |
1507 | 0 | ctx = &(pImpl->m_context); |
1508 | 0 | initHMAC_MD5(ctx); |
1509 | |
|
1510 | 0 | if (nKeyLen > DIGEST_CBLOCK_HMAC_MD5) |
1511 | 0 | { |
1512 | | /* Initialize 'opad' with hashed 'KeyData' */ |
1513 | 0 | rtl_digest_updateMD5(&(ctx->m_hash), pKeyData, nKeyLen); |
1514 | 0 | rtl_digest_getMD5(&(ctx->m_hash), ctx->m_opad, RTL_DIGEST_LENGTH_MD5); |
1515 | 0 | } |
1516 | 0 | else |
1517 | 0 | { |
1518 | | /* Initialize 'opad' with plain 'KeyData' */ |
1519 | 0 | memcpy(ctx->m_opad, pKeyData, nKeyLen); |
1520 | 0 | } |
1521 | |
|
1522 | 0 | ipadHMAC_MD5(ctx); |
1523 | 0 | opadHMAC_MD5(ctx); |
1524 | |
|
1525 | 0 | return rtl_Digest_E_None; |
1526 | 0 | } |
1527 | | |
1528 | | rtlDigestError SAL_CALL rtl_digest_updateHMAC_MD5( |
1529 | | rtlDigest Digest, const void *pData, sal_uInt32 nDatLen) noexcept |
1530 | 0 | { |
1531 | 0 | DigestHMAC_MD5_Impl *pImpl = static_cast< DigestHMAC_MD5_Impl* >(Digest); |
1532 | 0 | ContextHMAC_MD5 *ctx; |
1533 | |
|
1534 | 0 | if (!pImpl || !pData) |
1535 | 0 | return rtl_Digest_E_Argument; |
1536 | | |
1537 | 0 | if (pImpl->m_digest.m_algorithm != rtl_Digest_AlgorithmHMAC_MD5) |
1538 | 0 | return rtl_Digest_E_Algorithm; |
1539 | | |
1540 | 0 | ctx = &(pImpl->m_context); |
1541 | 0 | rtl_digest_updateMD5(&(ctx->m_hash), pData, nDatLen); |
1542 | |
|
1543 | 0 | return rtl_Digest_E_None; |
1544 | 0 | } |
1545 | | |
1546 | | rtlDigestError SAL_CALL rtl_digest_getHMAC_MD5( |
1547 | | rtlDigest Digest, sal_uInt8 *pBuffer, sal_uInt32 nBufLen) noexcept |
1548 | 0 | { |
1549 | 0 | DigestHMAC_MD5_Impl *pImpl = static_cast<DigestHMAC_MD5_Impl*>(Digest); |
1550 | 0 | ContextHMAC_MD5 *ctx; |
1551 | |
|
1552 | 0 | if (!pImpl || !pBuffer) |
1553 | 0 | return rtl_Digest_E_Argument; |
1554 | | |
1555 | 0 | if (pImpl->m_digest.m_algorithm != rtl_Digest_AlgorithmHMAC_MD5) |
1556 | 0 | return rtl_Digest_E_Algorithm; |
1557 | | |
1558 | 0 | if (pImpl->m_digest.m_length > nBufLen) |
1559 | 0 | return rtl_Digest_E_BufferSize; |
1560 | | |
1561 | 0 | nBufLen = pImpl->m_digest.m_length; |
1562 | |
|
1563 | 0 | ctx = &(pImpl->m_context); |
1564 | 0 | rtl_digest_getMD5(&(ctx->m_hash), pBuffer, nBufLen); |
1565 | |
|
1566 | 0 | rtl_digest_updateMD5(&(ctx->m_hash), ctx->m_opad, 64); |
1567 | 0 | rtl_digest_updateMD5(&(ctx->m_hash), pBuffer, nBufLen); |
1568 | 0 | rtl_digest_getMD5(&(ctx->m_hash), pBuffer, nBufLen); |
1569 | |
|
1570 | 0 | opadHMAC_MD5(ctx); |
1571 | 0 | ipadHMAC_MD5(ctx); |
1572 | 0 | opadHMAC_MD5(ctx); |
1573 | |
|
1574 | 0 | return rtl_Digest_E_None; |
1575 | 0 | } |
1576 | | |
1577 | | void SAL_CALL rtl_digest_destroyHMAC_MD5(rtlDigest Digest) noexcept |
1578 | 0 | { |
1579 | 0 | DigestHMAC_MD5_Impl *pImpl = static_cast< DigestHMAC_MD5_Impl* >(Digest); |
1580 | 0 | if (pImpl) |
1581 | 0 | { |
1582 | 0 | if (pImpl->m_digest.m_algorithm == rtl_Digest_AlgorithmHMAC_MD5) |
1583 | 0 | rtl_freeZeroMemory(pImpl, sizeof(DigestHMAC_MD5_Impl)); |
1584 | 0 | else |
1585 | 0 | free(pImpl); |
1586 | 0 | } |
1587 | 0 | } |
1588 | | |
1589 | 0 | #define DIGEST_CBLOCK_HMAC_SHA1 64 |
1590 | | |
1591 | | namespace { |
1592 | | |
1593 | | struct ContextHMAC_SHA1 |
1594 | | { |
1595 | | DigestSHA_Impl m_hash; |
1596 | | sal_uInt8 m_opad[DIGEST_CBLOCK_HMAC_SHA1]; |
1597 | | }; |
1598 | | |
1599 | | struct DigestHMAC_SHA1_Impl |
1600 | | { |
1601 | | Digest_Impl m_digest; |
1602 | | ContextHMAC_SHA1 m_context; |
1603 | | }; |
1604 | | |
1605 | | } |
1606 | | |
1607 | | static void initHMAC_SHA1(ContextHMAC_SHA1 * ctx); |
1608 | | static void ipadHMAC_SHA1(ContextHMAC_SHA1 * ctx); |
1609 | | static void opadHMAC_SHA1(ContextHMAC_SHA1 * ctx); |
1610 | | |
1611 | | const Digest_Impl HMAC_SHA1 = |
1612 | | { |
1613 | | rtl_Digest_AlgorithmHMAC_SHA1, |
1614 | | RTL_DIGEST_LENGTH_SHA1, |
1615 | | rtl_digest_initHMAC_SHA1, |
1616 | | rtl_digest_destroyHMAC_SHA1, |
1617 | | rtl_digest_updateHMAC_SHA1, |
1618 | | rtl_digest_getHMAC_SHA1 |
1619 | | }; |
1620 | | |
1621 | | static void initHMAC_SHA1(ContextHMAC_SHA1 * ctx) |
1622 | 0 | { |
1623 | 0 | DigestSHA_Impl *pImpl = &(ctx->m_hash); |
1624 | |
|
1625 | 0 | pImpl->m_digest = SHA_1; |
1626 | 0 | initSHA(&(pImpl->m_context), updateSHA_1); |
1627 | |
|
1628 | 0 | memset(ctx->m_opad, 0, DIGEST_CBLOCK_HMAC_SHA1); |
1629 | 0 | } |
1630 | | |
1631 | | static void ipadHMAC_SHA1(ContextHMAC_SHA1 * ctx) |
1632 | 0 | { |
1633 | 0 | sal_uInt32 i; |
1634 | |
|
1635 | 0 | for (i = 0; i < DIGEST_CBLOCK_HMAC_SHA1; i++) |
1636 | 0 | { |
1637 | 0 | ctx->m_opad[i] ^= 0x36; |
1638 | 0 | } |
1639 | |
|
1640 | 0 | rtl_digest_updateSHA1(&(ctx->m_hash), ctx->m_opad, DIGEST_CBLOCK_HMAC_SHA1); |
1641 | |
|
1642 | 0 | for (i = 0; i < DIGEST_CBLOCK_HMAC_SHA1; i++) |
1643 | 0 | { |
1644 | 0 | ctx->m_opad[i] ^= 0x36; |
1645 | 0 | } |
1646 | 0 | } |
1647 | | |
1648 | | static void opadHMAC_SHA1(ContextHMAC_SHA1 * ctx) |
1649 | 0 | { |
1650 | 0 | sal_uInt32 i; |
1651 | |
|
1652 | 0 | for (i = 0; i < DIGEST_CBLOCK_HMAC_SHA1; i++) |
1653 | 0 | { |
1654 | 0 | ctx->m_opad[i] ^= 0x5c; |
1655 | 0 | } |
1656 | 0 | } |
1657 | | |
1658 | | rtlDigestError SAL_CALL rtl_digest_HMAC_SHA1( |
1659 | | const sal_uInt8 *pKeyData, sal_uInt32 nKeyLen, |
1660 | | const void *pData, sal_uInt32 nDatLen, |
1661 | | sal_uInt8 *pBuffer, sal_uInt32 nBufLen) noexcept |
1662 | 0 | { |
1663 | 0 | DigestHMAC_SHA1_Impl digest; |
1664 | 0 | rtlDigestError result; |
1665 | |
|
1666 | 0 | digest.m_digest = HMAC_SHA1; |
1667 | |
|
1668 | 0 | result = rtl_digest_initHMAC_SHA1(&digest, pKeyData, nKeyLen); |
1669 | 0 | if (result == rtl_Digest_E_None) |
1670 | 0 | { |
1671 | 0 | result = rtl_digest_updateHMAC_SHA1(&digest, pData, nDatLen); |
1672 | 0 | if (result == rtl_Digest_E_None) |
1673 | 0 | result = rtl_digest_getHMAC_SHA1(&digest, pBuffer, nBufLen); |
1674 | 0 | } |
1675 | |
|
1676 | 0 | rtl_secureZeroMemory(&digest, sizeof(digest)); |
1677 | 0 | return result; |
1678 | 0 | } |
1679 | | |
1680 | | rtlDigest SAL_CALL rtl_digest_createHMAC_SHA1() noexcept |
1681 | 0 | { |
1682 | 0 | DigestHMAC_SHA1_Impl *pImpl = RTL_DIGEST_CREATE(DigestHMAC_SHA1_Impl); |
1683 | 0 | if (pImpl) |
1684 | 0 | { |
1685 | 0 | pImpl->m_digest = HMAC_SHA1; |
1686 | 0 | initHMAC_SHA1(&(pImpl->m_context)); |
1687 | 0 | } |
1688 | 0 | return static_cast<rtlDigest>(pImpl); |
1689 | 0 | } |
1690 | | |
1691 | | rtlDigestError SAL_CALL rtl_digest_initHMAC_SHA1( |
1692 | | rtlDigest Digest, const sal_uInt8 *pKeyData, sal_uInt32 nKeyLen) noexcept |
1693 | 0 | { |
1694 | 0 | DigestHMAC_SHA1_Impl *pImpl = static_cast<DigestHMAC_SHA1_Impl*>(Digest); |
1695 | 0 | ContextHMAC_SHA1 *ctx; |
1696 | |
|
1697 | 0 | if (!pImpl || !pKeyData) |
1698 | 0 | return rtl_Digest_E_Argument; |
1699 | | |
1700 | 0 | if (pImpl->m_digest.m_algorithm != rtl_Digest_AlgorithmHMAC_SHA1) |
1701 | 0 | return rtl_Digest_E_Algorithm; |
1702 | | |
1703 | 0 | ctx = &(pImpl->m_context); |
1704 | 0 | initHMAC_SHA1(ctx); |
1705 | |
|
1706 | 0 | if (nKeyLen > DIGEST_CBLOCK_HMAC_SHA1) |
1707 | 0 | { |
1708 | | /* Initialize 'opad' with hashed 'KeyData' */ |
1709 | 0 | rtl_digest_updateSHA1(&(ctx->m_hash), pKeyData, nKeyLen); |
1710 | 0 | rtl_digest_getSHA1(&(ctx->m_hash), ctx->m_opad, RTL_DIGEST_LENGTH_SHA1); |
1711 | 0 | } |
1712 | 0 | else |
1713 | 0 | { |
1714 | | /* Initialize 'opad' with plain 'KeyData' */ |
1715 | 0 | memcpy(ctx->m_opad, pKeyData, nKeyLen); |
1716 | 0 | } |
1717 | |
|
1718 | 0 | ipadHMAC_SHA1(ctx); |
1719 | 0 | opadHMAC_SHA1(ctx); |
1720 | |
|
1721 | 0 | return rtl_Digest_E_None; |
1722 | 0 | } |
1723 | | |
1724 | | rtlDigestError SAL_CALL rtl_digest_updateHMAC_SHA1( |
1725 | | rtlDigest Digest, const void *pData, sal_uInt32 nDatLen) noexcept |
1726 | 0 | { |
1727 | 0 | DigestHMAC_SHA1_Impl *pImpl = static_cast<DigestHMAC_SHA1_Impl*>(Digest); |
1728 | 0 | ContextHMAC_SHA1 *ctx; |
1729 | |
|
1730 | 0 | if (!pImpl || !pData) |
1731 | 0 | return rtl_Digest_E_Argument; |
1732 | | |
1733 | 0 | if (pImpl->m_digest.m_algorithm != rtl_Digest_AlgorithmHMAC_SHA1) |
1734 | 0 | return rtl_Digest_E_Algorithm; |
1735 | | |
1736 | 0 | ctx = &(pImpl->m_context); |
1737 | 0 | rtl_digest_updateSHA1(&(ctx->m_hash), pData, nDatLen); |
1738 | |
|
1739 | 0 | return rtl_Digest_E_None; |
1740 | 0 | } |
1741 | | |
1742 | | rtlDigestError SAL_CALL rtl_digest_getHMAC_SHA1( |
1743 | | rtlDigest Digest, sal_uInt8 *pBuffer, sal_uInt32 nBufLen) noexcept |
1744 | 0 | { |
1745 | 0 | DigestHMAC_SHA1_Impl *pImpl = static_cast<DigestHMAC_SHA1_Impl*>(Digest); |
1746 | 0 | ContextHMAC_SHA1 *ctx; |
1747 | |
|
1748 | 0 | if (!pImpl || !pBuffer) |
1749 | 0 | return rtl_Digest_E_Argument; |
1750 | | |
1751 | 0 | if (pImpl->m_digest.m_algorithm != rtl_Digest_AlgorithmHMAC_SHA1) |
1752 | 0 | return rtl_Digest_E_Algorithm; |
1753 | | |
1754 | 0 | if (pImpl->m_digest.m_length > nBufLen) |
1755 | 0 | return rtl_Digest_E_BufferSize; |
1756 | | |
1757 | 0 | nBufLen = pImpl->m_digest.m_length; |
1758 | |
|
1759 | 0 | ctx = &(pImpl->m_context); |
1760 | 0 | rtl_digest_getSHA1(&(ctx->m_hash), pBuffer, nBufLen); |
1761 | |
|
1762 | 0 | rtl_digest_updateSHA1(&(ctx->m_hash), ctx->m_opad, sizeof(ctx->m_opad)); |
1763 | 0 | rtl_digest_updateSHA1(&(ctx->m_hash), pBuffer, nBufLen); |
1764 | 0 | rtl_digest_getSHA1(&(ctx->m_hash), pBuffer, nBufLen); |
1765 | |
|
1766 | 0 | opadHMAC_SHA1(ctx); |
1767 | 0 | ipadHMAC_SHA1(ctx); |
1768 | 0 | opadHMAC_SHA1(ctx); |
1769 | |
|
1770 | 0 | return rtl_Digest_E_None; |
1771 | 0 | } |
1772 | | |
1773 | | void SAL_CALL rtl_digest_destroyHMAC_SHA1(rtlDigest Digest) noexcept |
1774 | 0 | { |
1775 | 0 | DigestHMAC_SHA1_Impl *pImpl = static_cast<DigestHMAC_SHA1_Impl*>(Digest); |
1776 | 0 | if (pImpl) |
1777 | 0 | { |
1778 | 0 | if (pImpl->m_digest.m_algorithm == rtl_Digest_AlgorithmHMAC_SHA1) |
1779 | 0 | rtl_freeZeroMemory(pImpl, sizeof(DigestHMAC_SHA1_Impl)); |
1780 | 0 | else |
1781 | 0 | free(pImpl); |
1782 | 0 | } |
1783 | 0 | } |
1784 | | |
1785 | 0 | #define DIGEST_CBLOCK_PBKDF2 RTL_DIGEST_LENGTH_HMAC_SHA1 |
1786 | | |
1787 | | static void updatePBKDF2( |
1788 | | rtlDigest hDigest, |
1789 | | sal_uInt8 T[DIGEST_CBLOCK_PBKDF2], |
1790 | | const sal_uInt8 *pSaltData, sal_uInt32 nSaltLen, |
1791 | | sal_uInt32 nCount, sal_uInt32 nIndex) |
1792 | 0 | { |
1793 | | /* T_i = F (P, S, c, i) */ |
1794 | 0 | sal_uInt8 U[DIGEST_CBLOCK_PBKDF2]; |
1795 | 0 | sal_uInt32 i, k; |
1796 | | |
1797 | | /* U_(1) = PRF (P, S || INDEX) */ |
1798 | 0 | rtl_digest_updateHMAC_SHA1(hDigest, pSaltData, nSaltLen); |
1799 | 0 | rtl_digest_updateHMAC_SHA1(hDigest, &nIndex, sizeof(nIndex)); |
1800 | 0 | rtl_digest_getHMAC_SHA1(hDigest, U, DIGEST_CBLOCK_PBKDF2); |
1801 | | |
1802 | | /* T = U_(1) */ |
1803 | 0 | for (k = 0; k < DIGEST_CBLOCK_PBKDF2; k++) |
1804 | 0 | { |
1805 | 0 | T[k] = U[k]; |
1806 | 0 | } |
1807 | | |
1808 | | /* T ^= U_(2) ^ ... ^ U_(c) */ |
1809 | 0 | for (i = 1; i < nCount; i++) |
1810 | 0 | { |
1811 | | /* U_(i) = PRF (P, U_(i-1)) */ |
1812 | 0 | rtl_digest_updateHMAC_SHA1(hDigest, U, DIGEST_CBLOCK_PBKDF2); |
1813 | 0 | rtl_digest_getHMAC_SHA1(hDigest, U, DIGEST_CBLOCK_PBKDF2); |
1814 | | |
1815 | | /* T ^= U_(i) */ |
1816 | 0 | for (k = 0; k < DIGEST_CBLOCK_PBKDF2; k++) |
1817 | 0 | { |
1818 | 0 | T[k] ^= U[k]; |
1819 | 0 | } |
1820 | 0 | } |
1821 | |
|
1822 | 0 | rtl_secureZeroMemory(U, DIGEST_CBLOCK_PBKDF2); |
1823 | 0 | } |
1824 | | |
1825 | | rtlDigestError SAL_CALL rtl_digest_PBKDF2( |
1826 | | sal_uInt8 *pKeyData , sal_uInt32 nKeyLen, |
1827 | | const sal_uInt8 *pPassData, sal_uInt32 nPassLen, |
1828 | | const sal_uInt8 *pSaltData, sal_uInt32 nSaltLen, |
1829 | | sal_uInt32 nCount) noexcept |
1830 | 0 | { |
1831 | 0 | DigestHMAC_SHA1_Impl digest; |
1832 | 0 | sal_uInt32 i = 1; |
1833 | |
|
1834 | 0 | if (!pKeyData || !pPassData || !pSaltData) |
1835 | 0 | return rtl_Digest_E_Argument; |
1836 | | |
1837 | 0 | digest.m_digest = HMAC_SHA1; |
1838 | 0 | rtl_digest_initHMAC_SHA1(&digest, pPassData, nPassLen); |
1839 | | |
1840 | | /* DK = T_(1) || T_(2) || ... || T_(l) */ |
1841 | 0 | while (nKeyLen >= DIGEST_CBLOCK_PBKDF2) |
1842 | 0 | { |
1843 | | /* T_(i) = F (P, S, c, i); DK ||= T_(i) */ |
1844 | 0 | updatePBKDF2( |
1845 | 0 | &digest, pKeyData, |
1846 | 0 | pSaltData, nSaltLen, |
1847 | 0 | nCount, OSL_NETDWORD(i)); |
1848 | | |
1849 | | /* Next 'KeyData' block */ |
1850 | 0 | pKeyData += DIGEST_CBLOCK_PBKDF2; |
1851 | 0 | nKeyLen -= DIGEST_CBLOCK_PBKDF2; |
1852 | 0 | i += 1; |
1853 | 0 | } |
1854 | |
|
1855 | 0 | if (nKeyLen > 0) |
1856 | 0 | { |
1857 | | /* Last 'KeyData' block */ |
1858 | 0 | sal_uInt8 T[DIGEST_CBLOCK_PBKDF2]; |
1859 | | |
1860 | | /* T_i = F (P, S, c, i) */ |
1861 | 0 | updatePBKDF2( |
1862 | 0 | &digest, T, |
1863 | 0 | pSaltData, nSaltLen, |
1864 | 0 | nCount, OSL_NETDWORD(i)); |
1865 | | |
1866 | | /* DK ||= T_(i) */ |
1867 | 0 | memcpy(pKeyData, T, nKeyLen); |
1868 | 0 | rtl_secureZeroMemory(T, DIGEST_CBLOCK_PBKDF2); |
1869 | 0 | } |
1870 | |
|
1871 | 0 | rtl_secureZeroMemory(&digest, sizeof(digest)); |
1872 | 0 | return rtl_Digest_E_None; |
1873 | 0 | } |
1874 | | |
1875 | | /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ |