Coverage Report

Created: 2025-12-31 10:39

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/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: */