office-gobmx/sal/rtl/digest.cxx
Stephan Bergmann f853ec317f Extend loplugin:external to warn about classes
...following up on 314f15bff0 "Extend
loplugin:external to warn about enums".

Cases where free functions were moved into an unnamed namespace along with a
class, to not break ADL, are in:

  filter/source/svg/svgexport.cxx
  sc/source/filter/excel/xelink.cxx
  sc/source/filter/excel/xilink.cxx
  svx/source/sdr/contact/viewobjectcontactofunocontrol.cxx

All other free functions mentioning moved classes appear to be harmless and not
give rise to (silent, even) ADL breakage.  (One remaining TODO in
compilerplugins/clang/external.cxx is that derived classes are not covered by
computeAffectedTypes, even though they could also be affected by ADL-breakage---
but don't seem to be in any acutal case across the code base.)

For friend declarations using elaborate type specifiers, like

  class C1 {};
  class C2 { friend class C1; };

* If C2 (but not C1) is moved into an unnamed namespace, the friend declaration
must be changed to not use an elaborate type specifier (i.e., "friend C1;"; see
C++17 [namespace.memdef]/3: "If the name in a friend declaration is neither
qualified nor a template-id and the declaration is a function or an
elaborated-type-specifier, the lookup to determine whether the entity has been
previously declared shall not consider any scopes outside the innermost
enclosing namespace.")

* If C1 (but not C2) is moved into an unnamed namespace, the friend declaration
must be changed too, see <https://gcc.gnu.org/bugzilla/show_bug.cgi?id=71882>
"elaborated-type-specifier friend not looked up in unnamed namespace".

Apart from that, to keep changes simple and mostly mechanical (which should help
avoid regressions), out-of-line definitions of class members have been left in
the enclosing (named) namespace.  But explicit specializations of class
templates had to be moved into the unnamed namespace to appease
<https://gcc.gnu.org/bugzilla/show_bug.cgi?id=92598> "explicit specialization of
template from unnamed namespace using unqualified-id in enclosing namespace".

Also, accompanying declarations (of e.g. typedefs or static variables) that
could arguably be moved into the unnamed namespace too have been left alone.

And in some cases, mention of affected types in blacklists in other loplugins
needed to be adapted.

And sc/qa/unit/mark_test.cxx uses a hack of including other .cxx, one of which
is sc/source/core/data/segmenttree.cxx where e.g. ScFlatUInt16SegmentsImpl is
not moved into an unnamed namespace (because it is declared in
sc/inc/segmenttree.hxx), but its base ScFlatSegmentsImpl is.  GCC warns about
such combinations with enabled-by-default -Wsubobject-linkage, but "The compiler
doesn’t give this warning for types defined in the main .C file, as those are
unlikely to have multiple definitions."
(<https://gcc.gnu.org/onlinedocs/gcc-9.2.0/gcc/Warning-Options.html>)  The
warned-about classes also don't have multiple definitions in the given test, so
disable the warning when including the .cxx.

Change-Id: Ib694094c0d8168be68f8fe90dfd0acbb66a3f1e4
Reviewed-on: https://gerrit.libreoffice.org/83239
Tested-by: Jenkins
Reviewed-by: Stephan Bergmann <sbergman@redhat.com>
2019-11-22 12:57:32 +01:00

1897 lines
50 KiB
C++

/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*
* This file is part of the LibreOffice project.
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*
* This file incorporates work covered by the following license notice:
*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed
* with this work for additional information regarding copyright
* ownership. The ASF licenses this file to you under the Apache
* License, Version 2.0 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.apache.org/licenses/LICENSE-2.0 .
*/
#include <string.h>
#include <stdlib.h>
#include <sal/types.h>
#include <osl/endian.h>
#include <rtl/alloc.h>
#include <rtl/digest.h>
#define RTL_DIGEST_CREATE(T) (static_cast<T*>(rtl_allocateZeroMemory(sizeof(T))))
#define RTL_DIGEST_ROTL(a,n) (((a) << (n)) | ((a) >> (32 - (n))))
#define RTL_DIGEST_HTONL(l,c) \
(*((c)++) = static_cast<sal_uInt8>(((l) >> 24) & 0xff), \
*((c)++) = static_cast<sal_uInt8>(((l) >> 16) & 0xff), \
*((c)++) = static_cast<sal_uInt8>(((l) >> 8) & 0xff), \
*((c)++) = static_cast<sal_uInt8>(((l) ) & 0xff))
#define RTL_DIGEST_LTOC(l,c) \
*((c)++) = static_cast<sal_uInt8>(((l) ) & 0xff); \
*((c)++) = static_cast<sal_uInt8>(((l) >> 8) & 0xff); \
*((c)++) = static_cast<sal_uInt8>(((l) >> 16) & 0xff); \
*((c)++) = static_cast<sal_uInt8>(((l) >> 24) & 0xff);
typedef rtlDigestError (Digest_init_t) (
void *ctx, const sal_uInt8 *Data, sal_uInt32 DatLen);
typedef void (Digest_delete_t) (void *ctx);
typedef rtlDigestError (Digest_update_t) (
void *ctx, const void *Data, sal_uInt32 DatLen);
typedef rtlDigestError (Digest_get_t) (
void *ctx, sal_uInt8 *Buffer, sal_uInt32 BufLen);
namespace {
struct Digest_Impl
{
rtlDigestAlgorithm m_algorithm;
sal_uInt32 m_length;
Digest_init_t *m_init;
Digest_delete_t *m_delete;
Digest_update_t *m_update;
Digest_get_t *m_get;
};
}
static void swapLong(sal_uInt32 *pData, sal_uInt32 nDatLen)
{
sal_uInt32 *X;
int i, n;
X = pData;
n = nDatLen;
for (i = 0; i < n; i++)
{
X[i] = OSL_SWAPDWORD(X[i]);
}
}
rtlDigest SAL_CALL rtl_digest_create(rtlDigestAlgorithm Algorithm)
SAL_THROW_EXTERN_C()
{
rtlDigest Digest = nullptr;
switch (Algorithm)
{
case rtl_Digest_AlgorithmMD2:
Digest = rtl_digest_createMD2();
break;
case rtl_Digest_AlgorithmMD5:
Digest = rtl_digest_createMD5();
break;
case rtl_Digest_AlgorithmSHA:
Digest = rtl_digest_createSHA();
break;
case rtl_Digest_AlgorithmSHA1:
Digest = rtl_digest_createSHA1();
break;
case rtl_Digest_AlgorithmHMAC_MD5:
Digest = rtl_digest_createHMAC_MD5();
break;
case rtl_Digest_AlgorithmHMAC_SHA1:
Digest = rtl_digest_createHMAC_SHA1();
break;
default: /* rtl_Digest_AlgorithmInvalid */
break;
}
return Digest;
}
rtlDigestAlgorithm SAL_CALL rtl_digest_queryAlgorithm(rtlDigest Digest)
SAL_THROW_EXTERN_C()
{
Digest_Impl *pImpl = static_cast<Digest_Impl *>(Digest);
if (pImpl)
return pImpl->m_algorithm;
return rtl_Digest_AlgorithmInvalid;
}
sal_uInt32 SAL_CALL rtl_digest_queryLength(rtlDigest Digest)
SAL_THROW_EXTERN_C()
{
Digest_Impl *pImpl = static_cast<Digest_Impl *>(Digest);
if (pImpl)
return pImpl->m_length;
return 0;
}
rtlDigestError SAL_CALL rtl_digest_init(
rtlDigest Digest, const sal_uInt8 *pData, sal_uInt32 nDatLen)
SAL_THROW_EXTERN_C()
{
Digest_Impl *pImpl = static_cast<Digest_Impl *>(Digest);
if (pImpl)
{
if (pImpl->m_init)
return pImpl->m_init (Digest, pData, nDatLen);
return rtl_Digest_E_None;
}
return rtl_Digest_E_Argument;
}
rtlDigestError SAL_CALL rtl_digest_update(
rtlDigest Digest, const void *pData, sal_uInt32 nDatLen)
SAL_THROW_EXTERN_C()
{
Digest_Impl *pImpl = static_cast<Digest_Impl *>(Digest);
if (pImpl && pImpl->m_update)
return pImpl->m_update(Digest, pData, nDatLen);
return rtl_Digest_E_Argument;
}
rtlDigestError SAL_CALL rtl_digest_get(
rtlDigest Digest, sal_uInt8 *pBuffer, sal_uInt32 nBufLen)
SAL_THROW_EXTERN_C()
{
Digest_Impl *pImpl = static_cast<Digest_Impl *>(Digest);
if (pImpl && pImpl->m_get)
return pImpl->m_get(Digest, pBuffer, nBufLen);
return rtl_Digest_E_Argument;
}
void SAL_CALL rtl_digest_destroy(rtlDigest Digest) SAL_THROW_EXTERN_C()
{
Digest_Impl *pImpl = static_cast<Digest_Impl *>(Digest);
if (pImpl && pImpl->m_delete)
pImpl->m_delete(Digest);
}
#define DIGEST_CBLOCK_MD2 16
#define DIGEST_LBLOCK_MD2 16
namespace {
struct DigestContextMD2
{
sal_uInt32 m_nDatLen;
sal_uInt8 m_pData[DIGEST_CBLOCK_MD2];
sal_uInt32 m_state[DIGEST_LBLOCK_MD2];
sal_uInt32 m_chksum[DIGEST_LBLOCK_MD2];
};
struct DigestMD2_Impl
{
Digest_Impl m_digest;
DigestContextMD2 m_context;
};
}
static void initMD2 (DigestContextMD2 *ctx);
static void updateMD2 (DigestContextMD2 *ctx);
static void endMD2 (DigestContextMD2 *ctx);
static const sal_uInt32 S[256] =
{
0x29, 0x2E, 0x43, 0xC9, 0xA2, 0xD8, 0x7C, 0x01,
0x3D, 0x36, 0x54, 0xA1, 0xEC, 0xF0, 0x06, 0x13,
0x62, 0xA7, 0x05, 0xF3, 0xC0, 0xC7, 0x73, 0x8C,
0x98, 0x93, 0x2B, 0xD9, 0xBC, 0x4C, 0x82, 0xCA,
0x1E, 0x9B, 0x57, 0x3C, 0xFD, 0xD4, 0xE0, 0x16,
0x67, 0x42, 0x6F, 0x18, 0x8A, 0x17, 0xE5, 0x12,
0xBE, 0x4E, 0xC4, 0xD6, 0xDA, 0x9E, 0xDE, 0x49,
0xA0, 0xFB, 0xF5, 0x8E, 0xBB, 0x2F, 0xEE, 0x7A,
0xA9, 0x68, 0x79, 0x91, 0x15, 0xB2, 0x07, 0x3F,
0x94, 0xC2, 0x10, 0x89, 0x0B, 0x22, 0x5F, 0x21,
0x80, 0x7F, 0x5D, 0x9A, 0x5A, 0x90, 0x32, 0x27,
0x35, 0x3E, 0xCC, 0xE7, 0xBF, 0xF7, 0x97, 0x03,
0xFF, 0x19, 0x30, 0xB3, 0x48, 0xA5, 0xB5, 0xD1,
0xD7, 0x5E, 0x92, 0x2A, 0xAC, 0x56, 0xAA, 0xC6,
0x4F, 0xB8, 0x38, 0xD2, 0x96, 0xA4, 0x7D, 0xB6,
0x76, 0xFC, 0x6B, 0xE2, 0x9C, 0x74, 0x04, 0xF1,
0x45, 0x9D, 0x70, 0x59, 0x64, 0x71, 0x87, 0x20,
0x86, 0x5B, 0xCF, 0x65, 0xE6, 0x2D, 0xA8, 0x02,
0x1B, 0x60, 0x25, 0xAD, 0xAE, 0xB0, 0xB9, 0xF6,
0x1C, 0x46, 0x61, 0x69, 0x34, 0x40, 0x7E, 0x0F,
0x55, 0x47, 0xA3, 0x23, 0xDD, 0x51, 0xAF, 0x3A,
0xC3, 0x5C, 0xF9, 0xCE, 0xBA, 0xC5, 0xEA, 0x26,
0x2C, 0x53, 0x0D, 0x6E, 0x85, 0x28, 0x84, 0x09,
0xD3, 0xDF, 0xCD, 0xF4, 0x41, 0x81, 0x4D, 0x52,
0x6A, 0xDC, 0x37, 0xC8, 0x6C, 0xC1, 0xAB, 0xFA,
0x24, 0xE1, 0x7B, 0x08, 0x0C, 0xBD, 0xB1, 0x4A,
0x78, 0x88, 0x95, 0x8B, 0xE3, 0x63, 0xE8, 0x6D,
0xE9, 0xCB, 0xD5, 0xFE, 0x3B, 0x00, 0x1D, 0x39,
0xF2, 0xEF, 0xB7, 0x0E, 0x66, 0x58, 0xD0, 0xE4,
0xA6, 0x77, 0x72, 0xF8, 0xEB, 0x75, 0x4B, 0x0A,
0x31, 0x44, 0x50, 0xB4, 0x8F, 0xED, 0x1F, 0x1A,
0xDB, 0x99, 0x8D, 0x33, 0x9F, 0x11, 0x83, 0x14,
};
static const Digest_Impl MD2 =
{
rtl_Digest_AlgorithmMD2,
RTL_DIGEST_LENGTH_MD2,
nullptr,
rtl_digest_destroyMD2,
rtl_digest_updateMD2,
rtl_digest_getMD2
};
static void initMD2(DigestContextMD2 *ctx)
{
memset(ctx, 0, sizeof(DigestContextMD2));
}
static void updateMD2(DigestContextMD2 *ctx)
{
sal_uInt8 *X;
sal_uInt32 *sp1, *sp2;
sal_uInt32 i, k, t;
sal_uInt32 state[48];
X = ctx->m_pData;
sp1 = ctx->m_state;
sp2 = ctx->m_chksum;
k = sp2[DIGEST_LBLOCK_MD2 - 1];
for (i = 0; i < 16; i++)
{
state[i + 0] = sp1[i];
state[i + 16] = t = X[i];
state[i + 32] = t ^ sp1[i];
k = sp2[i] ^= S[t^k];
}
t = 0;
for (i = 0; i < 18; i++)
{
for (k = 0; k < 48; k += 8)
{
t = state[k + 0] ^= S[t];
t = state[k + 1] ^= S[t];
t = state[k + 2] ^= S[t];
t = state[k + 3] ^= S[t];
t = state[k + 4] ^= S[t];
t = state[k + 5] ^= S[t];
t = state[k + 6] ^= S[t];
t = state[k + 7] ^= S[t];
}
t = ((t + i) & 0xff);
}
memcpy(sp1, state, 16 * sizeof(sal_uInt32));
rtl_secureZeroMemory(state, 48 * sizeof(sal_uInt32));
}
static void endMD2(DigestContextMD2 *ctx)
{
sal_uInt8 *X;
sal_uInt32 *C;
sal_uInt32 i, n;
X = ctx->m_pData;
C = ctx->m_chksum;
n = DIGEST_CBLOCK_MD2 - ctx->m_nDatLen;
for (i = ctx->m_nDatLen; i < DIGEST_CBLOCK_MD2; i++)
X[i] = static_cast<sal_uInt8>(n & 0xff);
updateMD2(ctx);
for (i = 0; i < DIGEST_CBLOCK_MD2; i++)
X[i] = static_cast<sal_uInt8>(C[i] & 0xff);
updateMD2(ctx);
}
rtlDigestError SAL_CALL rtl_digest_MD2(
const void *pData, sal_uInt32 nDatLen,
sal_uInt8 *pBuffer, sal_uInt32 nBufLen) SAL_THROW_EXTERN_C()
{
DigestMD2_Impl digest;
rtlDigestError result;
digest.m_digest = MD2;
initMD2(&(digest.m_context));
result = rtl_digest_updateMD2(&digest, pData, nDatLen);
if (result == rtl_Digest_E_None)
result = rtl_digest_getMD2(&digest, pBuffer, nBufLen);
rtl_secureZeroMemory(&digest, sizeof(digest));
return result;
}
rtlDigest SAL_CALL rtl_digest_createMD2() SAL_THROW_EXTERN_C()
{
DigestMD2_Impl *pImpl = RTL_DIGEST_CREATE(DigestMD2_Impl);
if (pImpl)
{
pImpl->m_digest = MD2;
initMD2(&(pImpl->m_context));
}
return static_cast<rtlDigest>(pImpl);
}
rtlDigestError SAL_CALL rtl_digest_updateMD2(
rtlDigest Digest, const void *pData, sal_uInt32 nDatLen)
SAL_THROW_EXTERN_C()
{
DigestMD2_Impl *pImpl = static_cast<DigestMD2_Impl *>(Digest);
const sal_uInt8 *d = static_cast<const sal_uInt8 *>(pData);
DigestContextMD2 *ctx;
if (!pImpl || !pData)
return rtl_Digest_E_Argument;
if (pImpl->m_digest.m_algorithm != rtl_Digest_AlgorithmMD2)
return rtl_Digest_E_Algorithm;
if (nDatLen == 0)
return rtl_Digest_E_None;
ctx = &(pImpl->m_context);
if (ctx->m_nDatLen)
{
sal_uInt8 *p = ctx->m_pData + ctx->m_nDatLen;
sal_uInt32 n = DIGEST_CBLOCK_MD2 - ctx->m_nDatLen;
if (nDatLen < n)
{
memcpy(p, d, nDatLen);
ctx->m_nDatLen += nDatLen;
return rtl_Digest_E_None;
}
memcpy(p, d, n);
d += n;
nDatLen -= n;
updateMD2(ctx);
ctx->m_nDatLen = 0;
}
while (nDatLen >= DIGEST_CBLOCK_MD2)
{
memcpy(ctx->m_pData, d, DIGEST_CBLOCK_MD2);
d += DIGEST_CBLOCK_MD2;
nDatLen -= DIGEST_CBLOCK_MD2;
updateMD2(ctx);
}
memcpy(ctx->m_pData, d, nDatLen);
ctx->m_nDatLen = nDatLen;
return rtl_Digest_E_None;
}
rtlDigestError SAL_CALL rtl_digest_getMD2(
rtlDigest Digest, sal_uInt8 *pBuffer, sal_uInt32 nBufLen)
SAL_THROW_EXTERN_C()
{
DigestMD2_Impl *pImpl = static_cast<DigestMD2_Impl *>(Digest);
sal_uInt32 i;
DigestContextMD2 *ctx;
if (!pImpl || !pBuffer)
return rtl_Digest_E_Argument;
if (pImpl->m_digest.m_algorithm != rtl_Digest_AlgorithmMD2)
return rtl_Digest_E_Algorithm;
if (pImpl->m_digest.m_length > nBufLen)
return rtl_Digest_E_BufferSize;
ctx = &(pImpl->m_context);
endMD2(ctx);
for (i = 0; i < DIGEST_CBLOCK_MD2; i++)
{
pBuffer[i] = static_cast<sal_uInt8>(ctx->m_state[i] & 0xff);
}
initMD2(ctx);
return rtl_Digest_E_None;
}
void SAL_CALL rtl_digest_destroyMD2(rtlDigest Digest) SAL_THROW_EXTERN_C()
{
DigestMD2_Impl *pImpl = static_cast<DigestMD2_Impl *>(Digest);
if (pImpl)
{
if (pImpl->m_digest.m_algorithm == rtl_Digest_AlgorithmMD2)
rtl_freeZeroMemory(pImpl, sizeof(DigestMD2_Impl));
else
free(pImpl);
}
}
#define DIGEST_CBLOCK_MD5 64
#define DIGEST_LBLOCK_MD5 16
namespace {
struct DigestContextMD5
{
sal_uInt32 m_nDatLen;
sal_uInt32 m_pData[DIGEST_LBLOCK_MD5];
sal_uInt32 m_nA, m_nB, m_nC, m_nD;
sal_uInt32 m_nL, m_nH;
};
struct DigestMD5_Impl
{
Digest_Impl m_digest;
DigestContextMD5 m_context;
};
}
static void initMD5 (DigestContextMD5 *ctx);
static void updateMD5 (DigestContextMD5 *ctx);
static void endMD5 (DigestContextMD5 *ctx);
#define F(x,y,z) ((((y) ^ (z)) & (x)) ^ (z))
#define G(x,y,z) ((((x) ^ (y)) & (z)) ^ (y))
#define H(x,y,z) ((x) ^ (y) ^ (z))
#define I(x,y,z) (((x) | (~(z))) ^ (y))
#define R0(a,b,c,d,k,s,t) { \
a += ((k) + (t) + F((b), (c), (d))); \
a = RTL_DIGEST_ROTL(a, s); \
a += b; }
#define R1(a,b,c,d,k,s,t) { \
a += ((k) + (t) + G((b), (c), (d))); \
a = RTL_DIGEST_ROTL(a, s); \
a += b; }
#define R2(a,b,c,d,k,s,t) { \
a += ((k) + (t) + H((b), (c), (d))); \
a = RTL_DIGEST_ROTL(a, s); \
a += b; }
#define R3(a,b,c,d,k,s,t) { \
a += ((k) + (t) + I((b), (c), (d))); \
a = RTL_DIGEST_ROTL(a, s); \
a += b; }
static const Digest_Impl MD5 =
{
rtl_Digest_AlgorithmMD5,
RTL_DIGEST_LENGTH_MD5,
nullptr,
rtl_digest_destroyMD5,
rtl_digest_updateMD5,
rtl_digest_getMD5
};
static void initMD5(DigestContextMD5 *ctx)
{
memset(ctx, 0, sizeof(DigestContextMD5));
ctx->m_nA = sal_uInt32(0x67452301L);
ctx->m_nB = sal_uInt32(0xefcdab89L);
ctx->m_nC = sal_uInt32(0x98badcfeL);
ctx->m_nD = sal_uInt32(0x10325476L);
}
static void updateMD5(DigestContextMD5 *ctx)
{
sal_uInt32 A, B, C, D;
sal_uInt32 *X;
A = ctx->m_nA;
B = ctx->m_nB;
C = ctx->m_nC;
D = ctx->m_nD;
X = ctx->m_pData;
R0 (A, B, C, D, X[ 0], 7, 0xd76aa478L);
R0 (D, A, B, C, X[ 1], 12, 0xe8c7b756L);
R0 (C, D, A, B, X[ 2], 17, 0x242070dbL);
R0 (B, C, D, A, X[ 3], 22, 0xc1bdceeeL);
R0 (A, B, C, D, X[ 4], 7, 0xf57c0fafL);
R0 (D, A, B, C, X[ 5], 12, 0x4787c62aL);
R0 (C, D, A, B, X[ 6], 17, 0xa8304613L);
R0 (B, C, D, A, X[ 7], 22, 0xfd469501L);
R0 (A, B, C, D, X[ 8], 7, 0x698098d8L);
R0 (D, A, B, C, X[ 9], 12, 0x8b44f7afL);
R0 (C, D, A, B, X[10], 17, 0xffff5bb1L);
R0 (B, C, D, A, X[11], 22, 0x895cd7beL);
R0 (A, B, C, D, X[12], 7, 0x6b901122L);
R0 (D, A, B, C, X[13], 12, 0xfd987193L);
R0 (C, D, A, B, X[14], 17, 0xa679438eL);
R0 (B, C, D, A, X[15], 22, 0x49b40821L);
R1 (A, B, C, D, X[ 1], 5, 0xf61e2562L);
R1 (D, A, B, C, X[ 6], 9, 0xc040b340L);
R1 (C, D, A, B, X[11], 14, 0x265e5a51L);
R1 (B, C, D, A, X[ 0], 20, 0xe9b6c7aaL);
R1 (A, B, C, D, X[ 5], 5, 0xd62f105dL);
R1 (D, A, B, C, X[10], 9, 0x02441453L);
R1 (C, D, A, B, X[15], 14, 0xd8a1e681L);
R1 (B, C, D, A, X[ 4], 20, 0xe7d3fbc8L);
R1 (A, B, C, D, X[ 9], 5, 0x21e1cde6L);
R1 (D, A, B, C, X[14], 9, 0xc33707d6L);
R1 (C, D, A, B, X[ 3], 14, 0xf4d50d87L);
R1 (B, C, D, A, X[ 8], 20, 0x455a14edL);
R1 (A, B, C, D, X[13], 5, 0xa9e3e905L);
R1 (D, A, B, C, X[ 2], 9, 0xfcefa3f8L);
R1 (C, D, A, B, X[ 7], 14, 0x676f02d9L);
R1 (B, C, D, A, X[12], 20, 0x8d2a4c8aL);
R2 (A, B, C, D, X[ 5], 4, 0xfffa3942L);
R2 (D, A, B, C, X[ 8], 11, 0x8771f681L);
R2 (C, D, A, B, X[11], 16, 0x6d9d6122L);
R2 (B, C, D, A, X[14], 23, 0xfde5380cL);
R2 (A, B, C, D, X[ 1], 4, 0xa4beea44L);
R2 (D, A, B, C, X[ 4], 11, 0x4bdecfa9L);
R2 (C, D, A, B, X[ 7], 16, 0xf6bb4b60L);
R2 (B, C, D, A, X[10], 23, 0xbebfbc70L);
R2 (A, B, C, D, X[13], 4, 0x289b7ec6L);
R2 (D, A, B, C, X[ 0], 11, 0xeaa127faL);
R2 (C, D, A, B, X[ 3], 16, 0xd4ef3085L);
R2 (B, C, D, A, X[ 6], 23, 0x04881d05L);
R2 (A, B, C, D, X[ 9], 4, 0xd9d4d039L);
R2 (D, A, B, C, X[12], 11, 0xe6db99e5L);
R2 (C, D, A, B, X[15], 16, 0x1fa27cf8L);
R2 (B, C, D, A, X[ 2], 23, 0xc4ac5665L);
R3 (A, B, C, D, X[ 0], 6, 0xf4292244L);
R3 (D, A, B, C, X[ 7], 10, 0x432aff97L);
R3 (C, D, A, B, X[14], 15, 0xab9423a7L);
R3 (B, C, D, A, X[ 5], 21, 0xfc93a039L);
R3 (A, B, C, D, X[12], 6, 0x655b59c3L);
R3 (D, A, B, C, X[ 3], 10, 0x8f0ccc92L);
R3 (C, D, A, B, X[10], 15, 0xffeff47dL);
R3 (B, C, D, A, X[ 1], 21, 0x85845dd1L);
R3 (A, B, C, D, X[ 8], 6, 0x6fa87e4fL);
R3 (D, A, B, C, X[15], 10, 0xfe2ce6e0L);
R3 (C, D, A, B, X[ 6], 15, 0xa3014314L);
R3 (B, C, D, A, X[13], 21, 0x4e0811a1L);
R3 (A, B, C, D, X[ 4], 6, 0xf7537e82L);
R3 (D, A, B, C, X[11], 10, 0xbd3af235L);
R3 (C, D, A, B, X[ 2], 15, 0x2ad7d2bbL);
R3 (B, C, D, A, X[ 9], 21, 0xeb86d391L);
ctx->m_nA += A;
ctx->m_nB += B;
ctx->m_nC += C;
ctx->m_nD += D;
}
static void endMD5(DigestContextMD5 *ctx)
{
static const sal_uInt8 end[4] =
{
0x80, 0x00, 0x00, 0x00
};
const sal_uInt8 *p = end;
sal_uInt32 *X;
int i;
X = ctx->m_pData;
i = (ctx->m_nDatLen >> 2);
#ifdef OSL_BIGENDIAN
swapLong(X, i + 1);
#endif /* OSL_BIGENDIAN */
switch (ctx->m_nDatLen & 0x03)
{
case 1: X[i] &= 0x000000ff; break;
case 2: X[i] &= 0x0000ffff; break;
case 3: X[i] &= 0x00ffffff; break;
}
switch (ctx->m_nDatLen & 0x03)
{
case 0: X[i] = static_cast<sal_uInt32>(*(p++)) << 0;
[[fallthrough]];
case 1: X[i] |= static_cast<sal_uInt32>(*(p++)) << 8;
[[fallthrough]];
case 2: X[i] |= static_cast<sal_uInt32>(*(p++)) << 16;
[[fallthrough]];
case 3: X[i] |= static_cast<sal_uInt32>(*p) << 24;
}
i += 1;
if (i > (DIGEST_LBLOCK_MD5 - 2))
{
for (; i < DIGEST_LBLOCK_MD5; i++)
{
X[i] = 0;
}
updateMD5(ctx);
i = 0;
}
for (; i < (DIGEST_LBLOCK_MD5 - 2); i++)
X[i] = 0;
X[DIGEST_LBLOCK_MD5 - 2] = ctx->m_nL;
X[DIGEST_LBLOCK_MD5 - 1] = ctx->m_nH;
updateMD5(ctx);
}
rtlDigestError SAL_CALL rtl_digest_MD5(
const void *pData, sal_uInt32 nDatLen,
sal_uInt8 *pBuffer, sal_uInt32 nBufLen) SAL_THROW_EXTERN_C()
{
DigestMD5_Impl digest;
rtlDigestError result;
digest.m_digest = MD5;
initMD5(&(digest.m_context));
result = rtl_digest_update(&digest, pData, nDatLen);
if (result == rtl_Digest_E_None)
result = rtl_digest_getMD5(&digest, pBuffer, nBufLen);
rtl_secureZeroMemory(&digest, sizeof(digest));
return result;
}
rtlDigest SAL_CALL rtl_digest_createMD5() SAL_THROW_EXTERN_C()
{
DigestMD5_Impl *pImpl = RTL_DIGEST_CREATE(DigestMD5_Impl);
if (pImpl)
{
pImpl->m_digest = MD5;
initMD5(&(pImpl->m_context));
}
return static_cast<rtlDigest>(pImpl);
}
rtlDigestError SAL_CALL rtl_digest_updateMD5(
rtlDigest Digest, const void *pData, sal_uInt32 nDatLen)
SAL_THROW_EXTERN_C()
{
DigestMD5_Impl *pImpl = static_cast<DigestMD5_Impl *>(Digest);
const sal_uInt8 *d = static_cast<const sal_uInt8 *>(pData);
DigestContextMD5 *ctx;
sal_uInt32 len;
if (!pImpl || !pData)
return rtl_Digest_E_Argument;
if (pImpl->m_digest.m_algorithm != rtl_Digest_AlgorithmMD5)
return rtl_Digest_E_Algorithm;
if (nDatLen == 0)
return rtl_Digest_E_None;
ctx = &(pImpl->m_context);
len = ctx->m_nL + (nDatLen << 3);
if (len < ctx->m_nL)
ctx->m_nH += 1;
ctx->m_nH += (nDatLen >> 29);
ctx->m_nL = len;
if (ctx->m_nDatLen)
{
sal_uInt8 *p = reinterpret_cast<sal_uInt8 *>(ctx->m_pData) + ctx->m_nDatLen;
sal_uInt32 n = DIGEST_CBLOCK_MD5 - ctx->m_nDatLen;
if (nDatLen < n)
{
memcpy(p, d, nDatLen);
ctx->m_nDatLen += nDatLen;
return rtl_Digest_E_None;
}
memcpy(p, d, n);
d += n;
nDatLen -= n;
#ifdef OSL_BIGENDIAN
swapLong(ctx->m_pData, DIGEST_LBLOCK_MD5);
#endif /* OSL_BIGENDIAN */
updateMD5(ctx);
ctx->m_nDatLen = 0;
}
while (nDatLen >= DIGEST_CBLOCK_MD5)
{
memcpy(ctx->m_pData, d, DIGEST_CBLOCK_MD5);
d += DIGEST_CBLOCK_MD5;
nDatLen -= DIGEST_CBLOCK_MD5;
#ifdef OSL_BIGENDIAN
swapLong(ctx->m_pData, DIGEST_LBLOCK_MD5);
#endif /* OSL_BIGENDIAN */
updateMD5(ctx);
}
memcpy(ctx->m_pData, d, nDatLen);
ctx->m_nDatLen = nDatLen;
return rtl_Digest_E_None;
}
rtlDigestError SAL_CALL rtl_digest_getMD5(
rtlDigest Digest, sal_uInt8 *pBuffer, sal_uInt32 nBufLen)
SAL_THROW_EXTERN_C()
{
DigestMD5_Impl *pImpl = static_cast<DigestMD5_Impl *>(Digest);
sal_uInt8 *p = pBuffer;
DigestContextMD5 *ctx;
if (!pImpl || !pBuffer)
return rtl_Digest_E_Argument;
if (pImpl->m_digest.m_algorithm != rtl_Digest_AlgorithmMD5)
return rtl_Digest_E_Algorithm;
if (pImpl->m_digest.m_length > nBufLen)
return rtl_Digest_E_BufferSize;
ctx = &(pImpl->m_context);
endMD5(ctx);
RTL_DIGEST_LTOC(ctx->m_nA, p);
RTL_DIGEST_LTOC(ctx->m_nB, p);
RTL_DIGEST_LTOC(ctx->m_nC, p);
RTL_DIGEST_LTOC(ctx->m_nD, p);
initMD5(ctx);
return rtl_Digest_E_None;
}
rtlDigestError SAL_CALL rtl_digest_rawMD5(
rtlDigest Digest, sal_uInt8 *pBuffer, sal_uInt32 nBufLen)
SAL_THROW_EXTERN_C()
{
DigestMD5_Impl *pImpl = static_cast<DigestMD5_Impl *>(Digest);
sal_uInt8 *p = pBuffer;
DigestContextMD5 *ctx;
if (!pImpl || !pBuffer)
return rtl_Digest_E_Argument;
if (pImpl->m_digest.m_algorithm != rtl_Digest_AlgorithmMD5)
return rtl_Digest_E_Algorithm;
if (pImpl->m_digest.m_length > nBufLen)
return rtl_Digest_E_BufferSize;
ctx = &(pImpl->m_context);
/* not finalized */
RTL_DIGEST_LTOC(ctx->m_nA, p);
RTL_DIGEST_LTOC(ctx->m_nB, p);
RTL_DIGEST_LTOC(ctx->m_nC, p);
RTL_DIGEST_LTOC(ctx->m_nD, p);
initMD5(ctx);
return rtl_Digest_E_None;
}
void SAL_CALL rtl_digest_destroyMD5(rtlDigest Digest) SAL_THROW_EXTERN_C()
{
DigestMD5_Impl *pImpl = static_cast<DigestMD5_Impl *>(Digest);
if (pImpl)
{
if (pImpl->m_digest.m_algorithm == rtl_Digest_AlgorithmMD5)
rtl_freeZeroMemory(pImpl, sizeof(DigestMD5_Impl));
else
free(pImpl);
}
}
#define DIGEST_CBLOCK_SHA 64
#define DIGEST_LBLOCK_SHA 16
typedef sal_uInt32 DigestSHA_update_t(sal_uInt32 x);
static sal_uInt32 updateSHA_0(sal_uInt32 x);
static sal_uInt32 updateSHA_1(sal_uInt32 x);
namespace {
struct DigestContextSHA
{
DigestSHA_update_t *m_update;
sal_uInt32 m_nDatLen;
sal_uInt32 m_pData[DIGEST_LBLOCK_SHA];
sal_uInt32 m_nA, m_nB, m_nC, m_nD, m_nE;
sal_uInt32 m_nL, m_nH;
};
struct DigestSHA_Impl
{
Digest_Impl m_digest;
DigestContextSHA m_context;
};
}
static void initSHA(
DigestContextSHA *ctx, DigestSHA_update_t *fct);
static void updateSHA(DigestContextSHA *ctx);
static void endSHA(DigestContextSHA *ctx);
#define K_00_19 sal_uInt32(0x5a827999L)
#define K_20_39 sal_uInt32(0x6ed9eba1L)
#define K_40_59 sal_uInt32(0x8f1bbcdcL)
#define K_60_79 sal_uInt32(0xca62c1d6L)
#define F_00_19(b,c,d) ((((c) ^ (d)) & (b)) ^ (d))
#define F_20_39(b,c,d) ((b) ^ (c) ^ (d))
#define F_40_59(b,c,d) (((b) & (c)) | ((b) & (d)) | ((c) & (d)))
#define F_60_79(b,c,d) F_20_39(b,c,d)
#define BODY_X(i) \
(X[(i)&0x0f] ^ X[((i)+2)&0x0f] ^ X[((i)+8)&0x0f] ^ X[((i)+13)&0x0f])
#define BODY_00_15(u,i,a,b,c,d,e,f) \
(f) = X[i]; \
(f) += (e) + K_00_19 + RTL_DIGEST_ROTL((a), 5) + F_00_19((b), (c), (d)); \
(b) = RTL_DIGEST_ROTL((b), 30);
#define BODY_16_19(u,i,a,b,c,d,e,f) \
(f) = BODY_X((i)); \
(f) = X[(i)&0x0f] = (u)((f)); \
(f) += (e) + K_00_19 + RTL_DIGEST_ROTL((a), 5) + F_00_19((b), (c), (d)); \
(b) = RTL_DIGEST_ROTL((b), 30);
#define BODY_20_39(u,i,a,b,c,d,e,f) \
(f) = BODY_X((i)); \
(f) = X[(i)&0x0f] = (u)((f)); \
(f) += (e) + K_20_39 + RTL_DIGEST_ROTL((a), 5) + F_20_39((b), (c), (d)); \
(b) = RTL_DIGEST_ROTL((b), 30);
#define BODY_40_59(u,i,a,b,c,d,e,f) \
(f) = BODY_X((i)); \
(f) = X[(i)&0x0f] = (u)((f)); \
(f) += (e) + K_40_59 + RTL_DIGEST_ROTL((a), 5) + F_40_59((b), (c), (d)); \
(b) = RTL_DIGEST_ROTL((b), 30);
#define BODY_60_79(u,i,a,b,c,d,e,f) \
(f) = BODY_X((i)); \
(f) = X[(i)&0x0f] = (u)((f)); \
(f) += (e) + K_60_79 + RTL_DIGEST_ROTL((a), 5) + F_60_79((b), (c), (d)); \
(b) = RTL_DIGEST_ROTL((b), 30);
static void initSHA(
DigestContextSHA *ctx, DigestSHA_update_t *fct)
{
memset(ctx, 0, sizeof(DigestContextSHA));
ctx->m_update = fct;
ctx->m_nA = sal_uInt32(0x67452301L);
ctx->m_nB = sal_uInt32(0xefcdab89L);
ctx->m_nC = sal_uInt32(0x98badcfeL);
ctx->m_nD = sal_uInt32(0x10325476L);
ctx->m_nE = sal_uInt32(0xc3d2e1f0L);
}
static void updateSHA(DigestContextSHA *ctx)
{
sal_uInt32 A, B, C, D, E, T;
sal_uInt32 *X;
DigestSHA_update_t *U;
U = ctx->m_update;
A = ctx->m_nA;
B = ctx->m_nB;
C = ctx->m_nC;
D = ctx->m_nD;
E = ctx->m_nE;
X = ctx->m_pData;
BODY_00_15 (U, 0, A, B, C, D, E, T);
BODY_00_15 (U, 1, T, A, B, C, D, E);
BODY_00_15 (U, 2, E, T, A, B, C, D);
BODY_00_15 (U, 3, D, E, T, A, B, C);
BODY_00_15 (U, 4, C, D, E, T, A, B);
BODY_00_15 (U, 5, B, C, D, E, T, A);
BODY_00_15 (U, 6, A, B, C, D, E, T);
BODY_00_15 (U, 7, T, A, B, C, D, E);
BODY_00_15 (U, 8, E, T, A, B, C, D);
BODY_00_15 (U, 9, D, E, T, A, B, C);
BODY_00_15 (U, 10, C, D, E, T, A, B);
BODY_00_15 (U, 11, B, C, D, E, T, A);
BODY_00_15 (U, 12, A, B, C, D, E, T);
BODY_00_15 (U, 13, T, A, B, C, D, E);
BODY_00_15 (U, 14, E, T, A, B, C, D);
BODY_00_15 (U, 15, D, E, T, A, B, C);
BODY_16_19 (U, 16, C, D, E, T, A, B);
BODY_16_19 (U, 17, B, C, D, E, T, A);
BODY_16_19 (U, 18, A, B, C, D, E, T);
BODY_16_19 (U, 19, T, A, B, C, D, E);
BODY_20_39 (U, 20, E, T, A, B, C, D);
BODY_20_39 (U, 21, D, E, T, A, B, C);
BODY_20_39 (U, 22, C, D, E, T, A, B);
BODY_20_39 (U, 23, B, C, D, E, T, A);
BODY_20_39 (U, 24, A, B, C, D, E, T);
BODY_20_39 (U, 25, T, A, B, C, D, E);
BODY_20_39 (U, 26, E, T, A, B, C, D);
BODY_20_39 (U, 27, D, E, T, A, B, C);
BODY_20_39 (U, 28, C, D, E, T, A, B);
BODY_20_39 (U, 29, B, C, D, E, T, A);
BODY_20_39 (U, 30, A, B, C, D, E, T);
BODY_20_39 (U, 31, T, A, B, C, D, E);
BODY_20_39 (U, 32, E, T, A, B, C, D);
BODY_20_39 (U, 33, D, E, T, A, B, C);
BODY_20_39 (U, 34, C, D, E, T, A, B);
BODY_20_39 (U, 35, B, C, D, E, T, A);
BODY_20_39 (U, 36, A, B, C, D, E, T);
BODY_20_39 (U, 37, T, A, B, C, D, E);
BODY_20_39 (U, 38, E, T, A, B, C, D);
BODY_20_39 (U, 39, D, E, T, A, B, C);
BODY_40_59 (U, 40, C, D, E, T, A, B);
BODY_40_59 (U, 41, B, C, D, E, T, A);
BODY_40_59 (U, 42, A, B, C, D, E, T);
BODY_40_59 (U, 43, T, A, B, C, D, E);
BODY_40_59 (U, 44, E, T, A, B, C, D);
BODY_40_59 (U, 45, D, E, T, A, B, C);
BODY_40_59 (U, 46, C, D, E, T, A, B);
BODY_40_59 (U, 47, B, C, D, E, T, A);
BODY_40_59 (U, 48, A, B, C, D, E, T);
BODY_40_59 (U, 49, T, A, B, C, D, E);
BODY_40_59 (U, 50, E, T, A, B, C, D);
BODY_40_59 (U, 51, D, E, T, A, B, C);
BODY_40_59 (U, 52, C, D, E, T, A, B);
BODY_40_59 (U, 53, B, C, D, E, T, A);
BODY_40_59 (U, 54, A, B, C, D, E, T);
BODY_40_59 (U, 55, T, A, B, C, D, E);
BODY_40_59 (U, 56, E, T, A, B, C, D);
BODY_40_59 (U, 57, D, E, T, A, B, C);
BODY_40_59 (U, 58, C, D, E, T, A, B);
BODY_40_59 (U, 59, B, C, D, E, T, A);
BODY_60_79 (U, 60, A, B, C, D, E, T);
BODY_60_79 (U, 61, T, A, B, C, D, E);
BODY_60_79 (U, 62, E, T, A, B, C, D);
BODY_60_79 (U, 63, D, E, T, A, B, C);
BODY_60_79 (U, 64, C, D, E, T, A, B);
BODY_60_79 (U, 65, B, C, D, E, T, A);
BODY_60_79 (U, 66, A, B, C, D, E, T);
BODY_60_79 (U, 67, T, A, B, C, D, E);
BODY_60_79 (U, 68, E, T, A, B, C, D);
BODY_60_79 (U, 69, D, E, T, A, B, C);
BODY_60_79 (U, 70, C, D, E, T, A, B);
BODY_60_79 (U, 71, B, C, D, E, T, A);
BODY_60_79 (U, 72, A, B, C, D, E, T);
BODY_60_79 (U, 73, T, A, B, C, D, E);
BODY_60_79 (U, 74, E, T, A, B, C, D);
BODY_60_79 (U, 75, D, E, T, A, B, C);
BODY_60_79 (U, 76, C, D, E, T, A, B);
BODY_60_79 (U, 77, B, C, D, E, T, A);
BODY_60_79 (U, 78, A, B, C, D, E, T);
BODY_60_79 (U, 79, T, A, B, C, D, E);
ctx->m_nA += E;
ctx->m_nB += T;
ctx->m_nC += A;
ctx->m_nD += B;
ctx->m_nE += C;
}
static void endSHA(DigestContextSHA *ctx)
{
static const sal_uInt8 end[4] =
{
0x80, 0x00, 0x00, 0x00
};
const sal_uInt8 *p = end;
sal_uInt32 *X;
int i;
X = ctx->m_pData;
i = (ctx->m_nDatLen >> 2);
#ifdef OSL_BIGENDIAN
swapLong(X, i + 1);
#endif /* OSL_BIGENDIAN */
switch (ctx->m_nDatLen & 0x03)
{
case 1: X[i] &= 0x000000ff; break;
case 2: X[i] &= 0x0000ffff; break;
case 3: X[i] &= 0x00ffffff; break;
}
switch (ctx->m_nDatLen & 0x03)
{
case 0: X[i] = static_cast<sal_uInt32>(*(p++)) << 0;
[[fallthrough]];
case 1: X[i] |= static_cast<sal_uInt32>(*(p++)) << 8;
[[fallthrough]];
case 2: X[i] |= static_cast<sal_uInt32>(*(p++)) << 16;
[[fallthrough]];
case 3: X[i] |= static_cast<sal_uInt32>(*(p++)) << 24;
}
swapLong(X, i + 1);
i += 1;
// tdf#114939 NB: this is WRONG and should be ">" not ">=" but is not
// fixed as this buggy SHA1 implementation is needed for compatibility
if (i >= (DIGEST_LBLOCK_SHA - 2))
{
for (; i < DIGEST_LBLOCK_SHA; i++)
{
X[i] = 0;
}
updateSHA(ctx);
i = 0;
}
for (; i < (DIGEST_LBLOCK_SHA - 2); i++)
{
X[i] = 0;
}
X[DIGEST_LBLOCK_SHA - 2] = ctx->m_nH;
X[DIGEST_LBLOCK_SHA - 1] = ctx->m_nL;
updateSHA(ctx);
}
static const Digest_Impl SHA_0 =
{
rtl_Digest_AlgorithmSHA,
RTL_DIGEST_LENGTH_SHA,
nullptr,
rtl_digest_destroySHA,
rtl_digest_updateSHA,
rtl_digest_getSHA
};
static sal_uInt32 updateSHA_0(sal_uInt32 x)
{
return x;
}
rtlDigestError SAL_CALL rtl_digest_SHA(
const void *pData, sal_uInt32 nDatLen,
sal_uInt8 *pBuffer, sal_uInt32 nBufLen) SAL_THROW_EXTERN_C()
{
DigestSHA_Impl digest;
rtlDigestError result;
digest.m_digest = SHA_0;
initSHA(&(digest.m_context), updateSHA_0);
result = rtl_digest_updateSHA(&digest, pData, nDatLen);
if (result == rtl_Digest_E_None)
result = rtl_digest_getSHA(&digest, pBuffer, nBufLen);
rtl_secureZeroMemory(&digest, sizeof(digest));
return result;
}
rtlDigest SAL_CALL rtl_digest_createSHA() SAL_THROW_EXTERN_C()
{
DigestSHA_Impl *pImpl = RTL_DIGEST_CREATE(DigestSHA_Impl);
if (pImpl)
{
pImpl->m_digest = SHA_0;
initSHA(&(pImpl->m_context), updateSHA_0);
}
return static_cast<rtlDigest>(pImpl);
}
rtlDigestError SAL_CALL rtl_digest_updateSHA(
rtlDigest Digest, const void *pData, sal_uInt32 nDatLen)
SAL_THROW_EXTERN_C()
{
DigestSHA_Impl *pImpl = static_cast<DigestSHA_Impl *>(Digest);
const sal_uInt8 *d = static_cast<const sal_uInt8 *>(pData);
DigestContextSHA *ctx;
sal_uInt32 len;
if (!pImpl || !pData)
return rtl_Digest_E_Argument;
if (pImpl->m_digest.m_algorithm != rtl_Digest_AlgorithmSHA)
return rtl_Digest_E_Algorithm;
if (nDatLen == 0)
return rtl_Digest_E_None;
ctx = &(pImpl->m_context);
len = ctx->m_nL + (nDatLen << 3);
if (len < ctx->m_nL)
ctx->m_nH += 1;
ctx->m_nH += (nDatLen >> 29);
ctx->m_nL = len;
if (ctx->m_nDatLen)
{
sal_uInt8 *p = reinterpret_cast<sal_uInt8 *>(ctx->m_pData) + ctx->m_nDatLen;
sal_uInt32 n = DIGEST_CBLOCK_SHA - ctx->m_nDatLen;
if (nDatLen < n)
{
memcpy(p, d, nDatLen);
ctx->m_nDatLen += nDatLen;
return rtl_Digest_E_None;
}
memcpy(p, d, n);
d += n;
nDatLen -= n;
#ifndef OSL_BIGENDIAN
swapLong(ctx->m_pData, DIGEST_LBLOCK_SHA);
#endif /* OSL_BIGENDIAN */
updateSHA(ctx);
ctx->m_nDatLen = 0;
}
while (nDatLen >= DIGEST_CBLOCK_SHA)
{
memcpy(ctx->m_pData, d, DIGEST_CBLOCK_SHA);
d += DIGEST_CBLOCK_SHA;
nDatLen -= DIGEST_CBLOCK_SHA;
#ifndef OSL_BIGENDIAN
swapLong(ctx->m_pData, DIGEST_LBLOCK_SHA);
#endif /* OSL_BIGENDIAN */
updateSHA(ctx);
}
memcpy(ctx->m_pData, d, nDatLen);
ctx->m_nDatLen = nDatLen;
return rtl_Digest_E_None;
}
rtlDigestError SAL_CALL rtl_digest_getSHA(
rtlDigest Digest, sal_uInt8 *pBuffer, sal_uInt32 nBufLen)
SAL_THROW_EXTERN_C()
{
DigestSHA_Impl *pImpl = static_cast<DigestSHA_Impl *>(Digest);
sal_uInt8 *p = pBuffer;
DigestContextSHA *ctx;
if (!pImpl || !pBuffer)
return rtl_Digest_E_Argument;
if (pImpl->m_digest.m_algorithm != rtl_Digest_AlgorithmSHA)
return rtl_Digest_E_Algorithm;
if (pImpl->m_digest.m_length > nBufLen)
return rtl_Digest_E_BufferSize;
ctx = &(pImpl->m_context);
endSHA(ctx);
RTL_DIGEST_HTONL(ctx->m_nA, p);
RTL_DIGEST_HTONL(ctx->m_nB, p);
RTL_DIGEST_HTONL(ctx->m_nC, p);
RTL_DIGEST_HTONL(ctx->m_nD, p);
RTL_DIGEST_HTONL(ctx->m_nE, p);
initSHA(ctx, updateSHA_0);
return rtl_Digest_E_None;
}
void SAL_CALL rtl_digest_destroySHA(rtlDigest Digest) SAL_THROW_EXTERN_C()
{
DigestSHA_Impl *pImpl = static_cast< DigestSHA_Impl * >(Digest);
if (pImpl)
{
if (pImpl->m_digest.m_algorithm == rtl_Digest_AlgorithmSHA)
rtl_freeZeroMemory(pImpl, sizeof(DigestSHA_Impl));
else
free(pImpl);
}
}
static const Digest_Impl SHA_1 =
{
rtl_Digest_AlgorithmSHA1,
RTL_DIGEST_LENGTH_SHA1,
nullptr,
rtl_digest_destroySHA1,
rtl_digest_updateSHA1,
rtl_digest_getSHA1
};
static sal_uInt32 updateSHA_1(sal_uInt32 x)
{
return RTL_DIGEST_ROTL(x, 1);
}
rtlDigestError SAL_CALL rtl_digest_SHA1(
const void *pData, sal_uInt32 nDatLen,
sal_uInt8 *pBuffer, sal_uInt32 nBufLen) SAL_THROW_EXTERN_C()
{
DigestSHA_Impl digest;
rtlDigestError result;
digest.m_digest = SHA_1;
initSHA(&(digest.m_context), updateSHA_1);
result = rtl_digest_updateSHA1(&digest, pData, nDatLen);
if (result == rtl_Digest_E_None)
result = rtl_digest_getSHA1(&digest, pBuffer, nBufLen);
rtl_secureZeroMemory(&digest, sizeof(digest));
return result;
}
rtlDigest SAL_CALL rtl_digest_createSHA1() SAL_THROW_EXTERN_C()
{
DigestSHA_Impl *pImpl = RTL_DIGEST_CREATE(DigestSHA_Impl);
if (pImpl)
{
pImpl->m_digest = SHA_1;
initSHA(&(pImpl->m_context), updateSHA_1);
}
return static_cast<rtlDigest>(pImpl);
}
rtlDigestError SAL_CALL rtl_digest_updateSHA1(
rtlDigest Digest, const void *pData, sal_uInt32 nDatLen)
SAL_THROW_EXTERN_C()
{
DigestSHA_Impl *pImpl = static_cast< DigestSHA_Impl * >(Digest);
const sal_uInt8 *d = static_cast< const sal_uInt8 * >(pData);
DigestContextSHA *ctx;
sal_uInt32 len;
if (!pImpl || !pData)
return rtl_Digest_E_Argument;
if (pImpl->m_digest.m_algorithm != rtl_Digest_AlgorithmSHA1)
return rtl_Digest_E_Algorithm;
if (nDatLen == 0)
return rtl_Digest_E_None;
ctx = &(pImpl->m_context);
len = ctx->m_nL + (nDatLen << 3);
if (len < ctx->m_nL)
ctx->m_nH += 1;
ctx->m_nH += (nDatLen >> 29);
ctx->m_nL = len;
if (ctx->m_nDatLen)
{
sal_uInt8 *p = reinterpret_cast<sal_uInt8 *>(ctx->m_pData) + ctx->m_nDatLen;
sal_uInt32 n = DIGEST_CBLOCK_SHA - ctx->m_nDatLen;
if (nDatLen < n)
{
memcpy(p, d, nDatLen);
ctx->m_nDatLen += nDatLen;
return rtl_Digest_E_None;
}
memcpy(p, d, n);
d += n;
nDatLen -= n;
#ifndef OSL_BIGENDIAN
swapLong(ctx->m_pData, DIGEST_LBLOCK_SHA);
#endif /* OSL_BIGENDIAN */
updateSHA(ctx);
ctx->m_nDatLen = 0;
}
while (nDatLen >= DIGEST_CBLOCK_SHA)
{
memcpy(ctx->m_pData, d, DIGEST_CBLOCK_SHA);
d += DIGEST_CBLOCK_SHA;
nDatLen -= DIGEST_CBLOCK_SHA;
#ifndef OSL_BIGENDIAN
swapLong(ctx->m_pData, DIGEST_LBLOCK_SHA);
#endif /* OSL_BIGENDIAN */
updateSHA(ctx);
}
memcpy(ctx->m_pData, d, nDatLen);
ctx->m_nDatLen = nDatLen;
return rtl_Digest_E_None;
}
rtlDigestError SAL_CALL rtl_digest_getSHA1 (
rtlDigest Digest, sal_uInt8 *pBuffer, sal_uInt32 nBufLen)
SAL_THROW_EXTERN_C()
{
DigestSHA_Impl *pImpl = static_cast<DigestSHA_Impl *>(Digest);
sal_uInt8 *p = pBuffer;
DigestContextSHA *ctx;
if (!pImpl || !pBuffer)
return rtl_Digest_E_Argument;
if (pImpl->m_digest.m_algorithm != rtl_Digest_AlgorithmSHA1)
return rtl_Digest_E_Algorithm;
if (pImpl->m_digest.m_length > nBufLen)
return rtl_Digest_E_BufferSize;
ctx = &(pImpl->m_context);
endSHA(ctx);
RTL_DIGEST_HTONL(ctx->m_nA, p);
RTL_DIGEST_HTONL(ctx->m_nB, p);
RTL_DIGEST_HTONL(ctx->m_nC, p);
RTL_DIGEST_HTONL(ctx->m_nD, p);
RTL_DIGEST_HTONL(ctx->m_nE, p);
initSHA(ctx, updateSHA_1);
return rtl_Digest_E_None;
}
void SAL_CALL rtl_digest_destroySHA1(rtlDigest Digest) SAL_THROW_EXTERN_C()
{
DigestSHA_Impl *pImpl = static_cast< DigestSHA_Impl * >(Digest);
if (pImpl)
{
if (pImpl->m_digest.m_algorithm == rtl_Digest_AlgorithmSHA1)
rtl_freeZeroMemory(pImpl, sizeof(DigestSHA_Impl));
else
free(pImpl);
}
}
#define DIGEST_CBLOCK_HMAC_MD5 64
namespace {
struct ContextHMAC_MD5
{
DigestMD5_Impl m_hash;
sal_uInt8 m_opad[DIGEST_CBLOCK_HMAC_MD5];
};
struct DigestHMAC_MD5_Impl
{
Digest_Impl m_digest;
ContextHMAC_MD5 m_context;
};
}
static void initHMAC_MD5(ContextHMAC_MD5 * ctx);
static void ipadHMAC_MD5(ContextHMAC_MD5 * ctx);
static void opadHMAC_MD5(ContextHMAC_MD5 * ctx);
static const Digest_Impl HMAC_MD5 =
{
rtl_Digest_AlgorithmHMAC_MD5,
RTL_DIGEST_LENGTH_MD5,
rtl_digest_initHMAC_MD5,
rtl_digest_destroyHMAC_MD5,
rtl_digest_updateHMAC_MD5,
rtl_digest_getHMAC_MD5
};
static void initHMAC_MD5(ContextHMAC_MD5 * ctx)
{
DigestMD5_Impl *pImpl = &(ctx->m_hash);
pImpl->m_digest = MD5;
initMD5(&(pImpl->m_context));
memset(ctx->m_opad, 0, DIGEST_CBLOCK_HMAC_MD5);
}
static void ipadHMAC_MD5(ContextHMAC_MD5 * ctx)
{
sal_uInt32 i;
for (i = 0; i < DIGEST_CBLOCK_HMAC_MD5; i++)
{
ctx->m_opad[i] ^= 0x36;
}
rtl_digest_updateMD5(&(ctx->m_hash), ctx->m_opad, DIGEST_CBLOCK_HMAC_MD5);
for (i = 0; i < DIGEST_CBLOCK_HMAC_MD5; i++)
{
ctx->m_opad[i] ^= 0x36;
}
}
static void opadHMAC_MD5(ContextHMAC_MD5 * ctx)
{
sal_uInt32 i;
for (i = 0; i < DIGEST_CBLOCK_HMAC_MD5; i++)
{
ctx->m_opad[i] ^= 0x5c;
}
}
rtlDigestError SAL_CALL rtl_digest_HMAC_MD5(
const sal_uInt8 *pKeyData, sal_uInt32 nKeyLen,
const void *pData, sal_uInt32 nDatLen,
sal_uInt8 *pBuffer, sal_uInt32 nBufLen) SAL_THROW_EXTERN_C()
{
DigestHMAC_MD5_Impl digest;
rtlDigestError result;
digest.m_digest = HMAC_MD5;
result = rtl_digest_initHMAC_MD5(&digest, pKeyData, nKeyLen);
if (result == rtl_Digest_E_None)
{
result = rtl_digest_updateHMAC_MD5(&digest, pData, nDatLen);
if (result == rtl_Digest_E_None)
result = rtl_digest_getHMAC_MD5(&digest, pBuffer, nBufLen);
}
rtl_secureZeroMemory(&digest, sizeof(digest));
return result;
}
rtlDigest SAL_CALL rtl_digest_createHMAC_MD5() SAL_THROW_EXTERN_C()
{
DigestHMAC_MD5_Impl *pImpl = RTL_DIGEST_CREATE(DigestHMAC_MD5_Impl);
if (pImpl)
{
pImpl->m_digest = HMAC_MD5;
initHMAC_MD5(&(pImpl->m_context));
}
return static_cast< rtlDigest >(pImpl);
}
rtlDigestError SAL_CALL rtl_digest_initHMAC_MD5(
rtlDigest Digest, const sal_uInt8 *pKeyData, sal_uInt32 nKeyLen)
SAL_THROW_EXTERN_C()
{
DigestHMAC_MD5_Impl *pImpl = static_cast< DigestHMAC_MD5_Impl* >(Digest);
ContextHMAC_MD5 *ctx;
if (!pImpl || !pKeyData)
return rtl_Digest_E_Argument;
if (pImpl->m_digest.m_algorithm != rtl_Digest_AlgorithmHMAC_MD5)
return rtl_Digest_E_Algorithm;
ctx = &(pImpl->m_context);
initHMAC_MD5(ctx);
if (nKeyLen > DIGEST_CBLOCK_HMAC_MD5)
{
/* Initialize 'opad' with hashed 'KeyData' */
rtl_digest_updateMD5(&(ctx->m_hash), pKeyData, nKeyLen);
rtl_digest_getMD5(&(ctx->m_hash), ctx->m_opad, RTL_DIGEST_LENGTH_MD5);
}
else
{
/* Initialize 'opad' with plain 'KeyData' */
memcpy(ctx->m_opad, pKeyData, nKeyLen);
}
ipadHMAC_MD5(ctx);
opadHMAC_MD5(ctx);
return rtl_Digest_E_None;
}
rtlDigestError SAL_CALL rtl_digest_updateHMAC_MD5(
rtlDigest Digest, const void *pData, sal_uInt32 nDatLen)
SAL_THROW_EXTERN_C()
{
DigestHMAC_MD5_Impl *pImpl = static_cast< DigestHMAC_MD5_Impl* >(Digest);
ContextHMAC_MD5 *ctx;
if (!pImpl || !pData)
return rtl_Digest_E_Argument;
if (pImpl->m_digest.m_algorithm != rtl_Digest_AlgorithmHMAC_MD5)
return rtl_Digest_E_Algorithm;
ctx = &(pImpl->m_context);
rtl_digest_updateMD5(&(ctx->m_hash), pData, nDatLen);
return rtl_Digest_E_None;
}
rtlDigestError SAL_CALL rtl_digest_getHMAC_MD5(
rtlDigest Digest, sal_uInt8 *pBuffer, sal_uInt32 nBufLen)
SAL_THROW_EXTERN_C()
{
DigestHMAC_MD5_Impl *pImpl = static_cast<DigestHMAC_MD5_Impl*>(Digest);
ContextHMAC_MD5 *ctx;
if (!pImpl || !pBuffer)
return rtl_Digest_E_Argument;
if (pImpl->m_digest.m_algorithm != rtl_Digest_AlgorithmHMAC_MD5)
return rtl_Digest_E_Algorithm;
if (pImpl->m_digest.m_length > nBufLen)
return rtl_Digest_E_BufferSize;
nBufLen = pImpl->m_digest.m_length;
ctx = &(pImpl->m_context);
rtl_digest_getMD5(&(ctx->m_hash), pBuffer, nBufLen);
rtl_digest_updateMD5(&(ctx->m_hash), ctx->m_opad, 64);
rtl_digest_updateMD5(&(ctx->m_hash), pBuffer, nBufLen);
rtl_digest_getMD5(&(ctx->m_hash), pBuffer, nBufLen);
opadHMAC_MD5(ctx);
ipadHMAC_MD5(ctx);
opadHMAC_MD5(ctx);
return rtl_Digest_E_None;
}
void SAL_CALL rtl_digest_destroyHMAC_MD5(rtlDigest Digest) SAL_THROW_EXTERN_C()
{
DigestHMAC_MD5_Impl *pImpl = static_cast< DigestHMAC_MD5_Impl* >(Digest);
if (pImpl)
{
if (pImpl->m_digest.m_algorithm == rtl_Digest_AlgorithmHMAC_MD5)
rtl_freeZeroMemory(pImpl, sizeof(DigestHMAC_MD5_Impl));
else
free(pImpl);
}
}
#define DIGEST_CBLOCK_HMAC_SHA1 64
namespace {
struct ContextHMAC_SHA1
{
DigestSHA_Impl m_hash;
sal_uInt8 m_opad[DIGEST_CBLOCK_HMAC_SHA1];
};
struct DigestHMAC_SHA1_Impl
{
Digest_Impl m_digest;
ContextHMAC_SHA1 m_context;
};
}
static void initHMAC_SHA1(ContextHMAC_SHA1 * ctx);
static void ipadHMAC_SHA1(ContextHMAC_SHA1 * ctx);
static void opadHMAC_SHA1(ContextHMAC_SHA1 * ctx);
static const Digest_Impl HMAC_SHA1 =
{
rtl_Digest_AlgorithmHMAC_SHA1,
RTL_DIGEST_LENGTH_SHA1,
rtl_digest_initHMAC_SHA1,
rtl_digest_destroyHMAC_SHA1,
rtl_digest_updateHMAC_SHA1,
rtl_digest_getHMAC_SHA1
};
static void initHMAC_SHA1(ContextHMAC_SHA1 * ctx)
{
DigestSHA_Impl *pImpl = &(ctx->m_hash);
pImpl->m_digest = SHA_1;
initSHA(&(pImpl->m_context), updateSHA_1);
memset(ctx->m_opad, 0, DIGEST_CBLOCK_HMAC_SHA1);
}
static void ipadHMAC_SHA1(ContextHMAC_SHA1 * ctx)
{
sal_uInt32 i;
for (i = 0; i < DIGEST_CBLOCK_HMAC_SHA1; i++)
{
ctx->m_opad[i] ^= 0x36;
}
rtl_digest_updateSHA1(&(ctx->m_hash), ctx->m_opad, DIGEST_CBLOCK_HMAC_SHA1);
for (i = 0; i < DIGEST_CBLOCK_HMAC_SHA1; i++)
{
ctx->m_opad[i] ^= 0x36;
}
}
static void opadHMAC_SHA1(ContextHMAC_SHA1 * ctx)
{
sal_uInt32 i;
for (i = 0; i < DIGEST_CBLOCK_HMAC_SHA1; i++)
{
ctx->m_opad[i] ^= 0x5c;
}
}
rtlDigestError SAL_CALL rtl_digest_HMAC_SHA1(
const sal_uInt8 *pKeyData, sal_uInt32 nKeyLen,
const void *pData, sal_uInt32 nDatLen,
sal_uInt8 *pBuffer, sal_uInt32 nBufLen) SAL_THROW_EXTERN_C()
{
DigestHMAC_SHA1_Impl digest;
rtlDigestError result;
digest.m_digest = HMAC_SHA1;
result = rtl_digest_initHMAC_SHA1(&digest, pKeyData, nKeyLen);
if (result == rtl_Digest_E_None)
{
result = rtl_digest_updateHMAC_SHA1(&digest, pData, nDatLen);
if (result == rtl_Digest_E_None)
result = rtl_digest_getHMAC_SHA1(&digest, pBuffer, nBufLen);
}
rtl_secureZeroMemory(&digest, sizeof(digest));
return result;
}
rtlDigest SAL_CALL rtl_digest_createHMAC_SHA1() SAL_THROW_EXTERN_C()
{
DigestHMAC_SHA1_Impl *pImpl = RTL_DIGEST_CREATE(DigestHMAC_SHA1_Impl);
if (pImpl)
{
pImpl->m_digest = HMAC_SHA1;
initHMAC_SHA1(&(pImpl->m_context));
}
return static_cast<rtlDigest>(pImpl);
}
rtlDigestError SAL_CALL rtl_digest_initHMAC_SHA1(
rtlDigest Digest, const sal_uInt8 *pKeyData, sal_uInt32 nKeyLen)
SAL_THROW_EXTERN_C()
{
DigestHMAC_SHA1_Impl *pImpl = static_cast<DigestHMAC_SHA1_Impl*>(Digest);
ContextHMAC_SHA1 *ctx;
if (!pImpl || !pKeyData)
return rtl_Digest_E_Argument;
if (pImpl->m_digest.m_algorithm != rtl_Digest_AlgorithmHMAC_SHA1)
return rtl_Digest_E_Algorithm;
ctx = &(pImpl->m_context);
initHMAC_SHA1(ctx);
if (nKeyLen > DIGEST_CBLOCK_HMAC_SHA1)
{
/* Initialize 'opad' with hashed 'KeyData' */
rtl_digest_updateSHA1(&(ctx->m_hash), pKeyData, nKeyLen);
rtl_digest_getSHA1(&(ctx->m_hash), ctx->m_opad, RTL_DIGEST_LENGTH_SHA1);
}
else
{
/* Initialize 'opad' with plain 'KeyData' */
memcpy(ctx->m_opad, pKeyData, nKeyLen);
}
ipadHMAC_SHA1(ctx);
opadHMAC_SHA1(ctx);
return rtl_Digest_E_None;
}
rtlDigestError SAL_CALL rtl_digest_updateHMAC_SHA1(
rtlDigest Digest, const void *pData, sal_uInt32 nDatLen)
SAL_THROW_EXTERN_C()
{
DigestHMAC_SHA1_Impl *pImpl = static_cast<DigestHMAC_SHA1_Impl*>(Digest);
ContextHMAC_SHA1 *ctx;
if (!pImpl || !pData)
return rtl_Digest_E_Argument;
if (pImpl->m_digest.m_algorithm != rtl_Digest_AlgorithmHMAC_SHA1)
return rtl_Digest_E_Algorithm;
ctx = &(pImpl->m_context);
rtl_digest_updateSHA1(&(ctx->m_hash), pData, nDatLen);
return rtl_Digest_E_None;
}
rtlDigestError SAL_CALL rtl_digest_getHMAC_SHA1(
rtlDigest Digest, sal_uInt8 *pBuffer, sal_uInt32 nBufLen)
SAL_THROW_EXTERN_C()
{
DigestHMAC_SHA1_Impl *pImpl = static_cast<DigestHMAC_SHA1_Impl*>(Digest);
ContextHMAC_SHA1 *ctx;
if (!pImpl || !pBuffer)
return rtl_Digest_E_Argument;
if (pImpl->m_digest.m_algorithm != rtl_Digest_AlgorithmHMAC_SHA1)
return rtl_Digest_E_Algorithm;
if (pImpl->m_digest.m_length > nBufLen)
return rtl_Digest_E_BufferSize;
nBufLen = pImpl->m_digest.m_length;
ctx = &(pImpl->m_context);
rtl_digest_getSHA1(&(ctx->m_hash), pBuffer, nBufLen);
rtl_digest_updateSHA1(&(ctx->m_hash), ctx->m_opad, sizeof(ctx->m_opad));
rtl_digest_updateSHA1(&(ctx->m_hash), pBuffer, nBufLen);
rtl_digest_getSHA1(&(ctx->m_hash), pBuffer, nBufLen);
opadHMAC_SHA1(ctx);
ipadHMAC_SHA1(ctx);
opadHMAC_SHA1(ctx);
return rtl_Digest_E_None;
}
void SAL_CALL rtl_digest_destroyHMAC_SHA1(rtlDigest Digest)
SAL_THROW_EXTERN_C()
{
DigestHMAC_SHA1_Impl *pImpl = static_cast<DigestHMAC_SHA1_Impl*>(Digest);
if (pImpl)
{
if (pImpl->m_digest.m_algorithm == rtl_Digest_AlgorithmHMAC_SHA1)
rtl_freeZeroMemory(pImpl, sizeof(DigestHMAC_SHA1_Impl));
else
free(pImpl);
}
}
#define DIGEST_CBLOCK_PBKDF2 RTL_DIGEST_LENGTH_HMAC_SHA1
static void updatePBKDF2(
rtlDigest hDigest,
sal_uInt8 T[DIGEST_CBLOCK_PBKDF2],
const sal_uInt8 *pSaltData, sal_uInt32 nSaltLen,
sal_uInt32 nCount, sal_uInt32 nIndex)
{
/* T_i = F (P, S, c, i) */
sal_uInt8 U[DIGEST_CBLOCK_PBKDF2];
sal_uInt32 i, k;
/* U_(1) = PRF (P, S || INDEX) */
rtl_digest_updateHMAC_SHA1(hDigest, pSaltData, nSaltLen);
rtl_digest_updateHMAC_SHA1(hDigest, &nIndex, sizeof(nIndex));
rtl_digest_getHMAC_SHA1(hDigest, U, DIGEST_CBLOCK_PBKDF2);
/* T = U_(1) */
for (k = 0; k < DIGEST_CBLOCK_PBKDF2; k++)
{
T[k] = U[k];
}
/* T ^= U_(2) ^ ... ^ U_(c) */
for (i = 1; i < nCount; i++)
{
/* U_(i) = PRF (P, U_(i-1)) */
rtl_digest_updateHMAC_SHA1(hDigest, U, DIGEST_CBLOCK_PBKDF2);
rtl_digest_getHMAC_SHA1(hDigest, U, DIGEST_CBLOCK_PBKDF2);
/* T ^= U_(i) */
for (k = 0; k < DIGEST_CBLOCK_PBKDF2; k++)
{
T[k] ^= U[k];
}
}
rtl_secureZeroMemory(U, DIGEST_CBLOCK_PBKDF2);
}
rtlDigestError SAL_CALL rtl_digest_PBKDF2(
sal_uInt8 *pKeyData , sal_uInt32 nKeyLen,
const sal_uInt8 *pPassData, sal_uInt32 nPassLen,
const sal_uInt8 *pSaltData, sal_uInt32 nSaltLen,
sal_uInt32 nCount) SAL_THROW_EXTERN_C()
{
DigestHMAC_SHA1_Impl digest;
sal_uInt32 i = 1;
if (!pKeyData || !pPassData || !pSaltData)
return rtl_Digest_E_Argument;
digest.m_digest = HMAC_SHA1;
rtl_digest_initHMAC_SHA1(&digest, pPassData, nPassLen);
/* DK = T_(1) || T_(2) || ... || T_(l) */
while (nKeyLen >= DIGEST_CBLOCK_PBKDF2)
{
/* T_(i) = F (P, S, c, i); DK ||= T_(i) */
updatePBKDF2(
&digest, pKeyData,
pSaltData, nSaltLen,
nCount, OSL_NETDWORD(i));
/* Next 'KeyData' block */
pKeyData += DIGEST_CBLOCK_PBKDF2;
nKeyLen -= DIGEST_CBLOCK_PBKDF2;
i += 1;
}
if (nKeyLen > 0)
{
/* Last 'KeyData' block */
sal_uInt8 T[DIGEST_CBLOCK_PBKDF2];
/* T_i = F (P, S, c, i) */
updatePBKDF2(
&digest, T,
pSaltData, nSaltLen,
nCount, OSL_NETDWORD(i));
/* DK ||= T_(i) */
memcpy(pKeyData, T, nKeyLen);
rtl_secureZeroMemory(T, DIGEST_CBLOCK_PBKDF2);
}
rtl_secureZeroMemory(&digest, sizeof(digest));
return rtl_Digest_E_None;
}
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */