/* -*- 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 ) & 0 xff), \
*((c)++) = static_cast <sal_uInt8>(((l) >> 16 ) & 0 xff), \
*((c)++) = static_cast <sal_uInt8>(((l) >> 8 ) & 0 xff), \
*((c)++) = static_cast <sal_uInt8>(((l) ) & 0 xff))
#define RTL_DIGEST_LTOC(l,c) \
*((c)++) = static_cast <sal_uInt8>(((l) ) & 0 xff); \
*((c)++) = static_cast <sal_uInt8>(((l) >> 8 ) & 0 xff); \
*((c)++) = static_cast <sal_uInt8>(((l) >> 16 ) & 0 xff); \
*((c)++) = static_cast <sal_uInt8>(((l) >> 24 ) & 0 xff);
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) noexcept
{
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) noexcept
{
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) noexcept
{
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) noexcept
{
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) noexcept
{
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) noexcept
{
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) noexcept
{
Digest_Impl *pImpl = static_cast <Digest_Impl *>(Digest);
if (pImpl && pImpl->m_delete)
pImpl->m_delete(Digest);
}
constexpr auto DIGEST_CBLOCK_MD2 = 16 ;
constexpr auto 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);
const sal_uInt32 S[256 ] =
{
0 x29, 0 x2E, 0 x43, 0 xC9, 0 xA2, 0 xD8, 0 x7C, 0 x01,
0 x3D, 0 x36, 0 x54, 0 xA1, 0 xEC, 0 xF0, 0 x06, 0 x13,
0 x62, 0 xA7, 0 x05, 0 xF3, 0 xC0, 0 xC7, 0 x73, 0 x8C,
0 x98, 0 x93, 0 x2B, 0 xD9, 0 xBC, 0 x4C, 0 x82, 0 xCA,
0 x1E, 0 x9B, 0 x57, 0 x3C, 0 xFD, 0 xD4, 0 xE0, 0 x16,
0 x67, 0 x42, 0 x6F, 0 x18, 0 x8A, 0 x17, 0 xE5, 0 x12,
0 xBE, 0 x4E, 0 xC4, 0 xD6, 0 xDA, 0 x9E, 0 xDE, 0 x49,
0 xA0, 0 xFB, 0 xF5, 0 x8E, 0 xBB, 0 x2F, 0 xEE, 0 x7A,
0 xA9, 0 x68, 0 x79, 0 x91, 0 x15, 0 xB2, 0 x07, 0 x3F,
0 x94, 0 xC2, 0 x10, 0 x89, 0 x0B, 0 x22, 0 x5F, 0 x21,
0 x80, 0 x7F, 0 x5D, 0 x9A, 0 x5A, 0 x90, 0 x32, 0 x27,
0 x35, 0 x3E, 0 xCC, 0 xE7, 0 xBF, 0 xF7, 0 x97, 0 x03,
0 xFF, 0 x19, 0 x30, 0 xB3, 0 x48, 0 xA5, 0 xB5, 0 xD1,
0 xD7, 0 x5E, 0 x92, 0 x2A, 0 xAC, 0 x56, 0 xAA, 0 xC6,
0 x4F, 0 xB8, 0 x38, 0 xD2, 0 x96, 0 xA4, 0 x7D, 0 xB6,
0 x76, 0 xFC, 0 x6B, 0 xE2, 0 x9C, 0 x74, 0 x04, 0 xF1,
0 x45, 0 x9D, 0 x70, 0 x59, 0 x64, 0 x71, 0 x87, 0 x20,
0 x86, 0 x5B, 0 xCF, 0 x65, 0 xE6, 0 x2D, 0 xA8, 0 x02,
0 x1B, 0 x60, 0 x25, 0 xAD, 0 xAE, 0 xB0, 0 xB9, 0 xF6,
0 x1C, 0 x46, 0 x61, 0 x69, 0 x34, 0 x40, 0 x7E, 0 x0F,
0 x55, 0 x47, 0 xA3, 0 x23, 0 xDD, 0 x51, 0 xAF, 0 x3A,
0 xC3, 0 x5C, 0 xF9, 0 xCE, 0 xBA, 0 xC5, 0 xEA, 0 x26,
0 x2C, 0 x53, 0 x0D, 0 x6E, 0 x85, 0 x28, 0 x84, 0 x09,
0 xD3, 0 xDF, 0 xCD, 0 xF4, 0 x41, 0 x81, 0 x4D, 0 x52,
0 x6A, 0 xDC, 0 x37, 0 xC8, 0 x6C, 0 xC1, 0 xAB, 0 xFA,
0 x24, 0 xE1, 0 x7B, 0 x08, 0 x0C, 0 xBD, 0 xB1, 0 x4A,
0 x78, 0 x88, 0 x95, 0 x8B, 0 xE3, 0 x63, 0 xE8, 0 x6D,
0 xE9, 0 xCB, 0 xD5, 0 xFE, 0 x3B, 0 x00, 0 x1D, 0 x39,
0 xF2, 0 xEF, 0 xB7, 0 x0E, 0 x66, 0 x58, 0 xD0, 0 xE4,
0 xA6, 0 x77, 0 x72, 0 xF8, 0 xEB, 0 x75, 0 x4B, 0 x0A,
0 x31, 0 x44, 0 x50, 0 xB4, 0 x8F, 0 xED, 0 x1F, 0 x1A,
0 xDB, 0 x99, 0 x8D, 0 x33, 0 x9F, 0 x11, 0 x83, 0 x14,
};
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) & 0 xff);
}
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 & 0 xff);
updateMD2(ctx);
for (i = 0 ; i < DIGEST_CBLOCK_MD2; i++)
X[i] = static_cast <sal_uInt8>(C[i] & 0 xff);
updateMD2(ctx);
}
rtlDigestError SAL_CALL rtl_digest_MD2(
const void *pData, sal_uInt32 nDatLen,
sal_uInt8 *pBuffer, sal_uInt32 nBufLen) noexcept
{
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() noexcept
{
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) noexcept
{
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) noexcept
{
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] & 0 xff);
}
initMD2(ctx);
return rtl_Digest_E_None;
}
void SAL_CALL rtl_digest_destroyMD2(rtlDigest Digest) noexcept
{
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; }
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(0 x67452301L);
ctx->m_nB = sal_uInt32(0 xefcdab89L);
ctx->m_nC = sal_uInt32(0 x98badcfeL);
ctx->m_nD = sal_uInt32(0 x10325476L);
}
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 , 0 xd76aa478L);
R0 (D, A, B, C, X[ 1 ], 12 , 0 xe8c7b756L);
R0 (C, D, A, B, X[ 2 ], 17 , 0 x242070dbL);
R0 (B, C, D, A, X[ 3 ], 22 , 0 xc1bdceeeL);
R0 (A, B, C, D, X[ 4 ], 7 , 0 xf57c0fafL);
R0 (D, A, B, C, X[ 5 ], 12 , 0 x4787c62aL);
R0 (C, D, A, B, X[ 6 ], 17 , 0 xa8304613L);
R0 (B, C, D, A, X[ 7 ], 22 , 0 xfd469501L);
R0 (A, B, C, D, X[ 8 ], 7 , 0 x698098d8L);
R0 (D, A, B, C, X[ 9 ], 12 , 0 x8b44f7afL);
R0 (C, D, A, B, X[10 ], 17 , 0 xffff5bb1L);
R0 (B, C, D, A, X[11 ], 22 , 0 x895cd7beL);
R0 (A, B, C, D, X[12 ], 7 , 0 x6b901122L);
R0 (D, A, B, C, X[13 ], 12 , 0 xfd987193L);
R0 (C, D, A, B, X[14 ], 17 , 0 xa679438eL);
R0 (B, C, D, A, X[15 ], 22 , 0 x49b40821L);
R1 (A, B, C, D, X[ 1 ], 5 , 0 xf61e2562L);
R1 (D, A, B, C, X[ 6 ], 9 , 0 xc040b340L);
R1 (C, D, A, B, X[11 ], 14 , 0 x265e5a51L);
R1 (B, C, D, A, X[ 0 ], 20 , 0 xe9b6c7aaL);
R1 (A, B, C, D, X[ 5 ], 5 , 0 xd62f105dL);
R1 (D, A, B, C, X[10 ], 9 , 0 x02441453L);
R1 (C, D, A, B, X[15 ], 14 , 0 xd8a1e681L);
R1 (B, C, D, A, X[ 4 ], 20 , 0 xe7d3fbc8L);
R1 (A, B, C, D, X[ 9 ], 5 , 0 x21e1cde6L);
R1 (D, A, B, C, X[14 ], 9 , 0 xc33707d6L);
R1 (C, D, A, B, X[ 3 ], 14 , 0 xf4d50d87L);
R1 (B, C, D, A, X[ 8 ], 20 , 0 x455a14edL);
R1 (A, B, C, D, X[13 ], 5 , 0 xa9e3e905L);
R1 (D, A, B, C, X[ 2 ], 9 , 0 xfcefa3f8L);
R1 (C, D, A, B, X[ 7 ], 14 , 0 x676f02d9L);
R1 (B, C, D, A, X[12 ], 20 , 0 x8d2a4c8aL);
R2 (A, B, C, D, X[ 5 ], 4 , 0 xfffa3942L);
R2 (D, A, B, C, X[ 8 ], 11 , 0 x8771f681L);
R2 (C, D, A, B, X[11 ], 16 , 0 x6d9d6122L);
R2 (B, C, D, A, X[14 ], 23 , 0 xfde5380cL);
R2 (A, B, C, D, X[ 1 ], 4 , 0 xa4beea44L);
R2 (D, A, B, C, X[ 4 ], 11 , 0 x4bdecfa9L);
R2 (C, D, A, B, X[ 7 ], 16 , 0 xf6bb4b60L);
R2 (B, C, D, A, X[10 ], 23 , 0 xbebfbc70L);
R2 (A, B, C, D, X[13 ], 4 , 0 x289b7ec6L);
R2 (D, A, B, C, X[ 0 ], 11 , 0 xeaa127faL);
R2 (C, D, A, B, X[ 3 ], 16 , 0 xd4ef3085L);
R2 (B, C, D, A, X[ 6 ], 23 , 0 x04881d05L);
R2 (A, B, C, D, X[ 9 ], 4 , 0 xd9d4d039L);
R2 (D, A, B, C, X[12 ], 11 , 0 xe6db99e5L);
R2 (C, D, A, B, X[15 ], 16 , 0 x1fa27cf8L);
R2 (B, C, D, A, X[ 2 ], 23 , 0 xc4ac5665L);
R3 (A, B, C, D, X[ 0 ], 6 , 0 xf4292244L);
R3 (D, A, B, C, X[ 7 ], 10 , 0 x432aff97L);
R3 (C, D, A, B, X[14 ], 15 , 0 xab9423a7L);
R3 (B, C, D, A, X[ 5 ], 21 , 0 xfc93a039L);
R3 (A, B, C, D, X[12 ], 6 , 0 x655b59c3L);
R3 (D, A, B, C, X[ 3 ], 10 , 0 x8f0ccc92L);
R3 (C, D, A, B, X[10 ], 15 , 0 xffeff47dL);
R3 (B, C, D, A, X[ 1 ], 21 , 0 x85845dd1L);
R3 (A, B, C, D, X[ 8 ], 6 , 0 x6fa87e4fL);
R3 (D, A, B, C, X[15 ], 10 , 0 xfe2ce6e0L);
R3 (C, D, A, B, X[ 6 ], 15 , 0 xa3014314L);
R3 (B, C, D, A, X[13 ], 21 , 0 x4e0811a1L);
R3 (A, B, C, D, X[ 4 ], 6 , 0 xf7537e82L);
R3 (D, A, B, C, X[11 ], 10 , 0 xbd3af235L);
R3 (C, D, A, B, X[ 2 ], 15 , 0 x2ad7d2bbL);
R3 (B, C, D, A, X[ 9 ], 21 , 0 xeb86d391L);
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 ] =
{
0 x80, 0 x00, 0 x00, 0 x00
};
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 & 0 x03)
{
case 1 : X[i] &= 0 x000000ff; break ;
case 2 : X[i] &= 0 x0000ffff; break ;
case 3 : X[i] &= 0 x00ffffff; break ;
}
switch (ctx->m_nDatLen & 0 x03)
{
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) noexcept
{
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() noexcept
{
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) noexcept
{
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) noexcept
{
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) noexcept
{
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) noexcept
{
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(0 x5a827999L)
#define K_20_39 sal_uInt32(0 x6ed9eba1L)
#define K_40_59 sal_uInt32(0 x8f1bbcdcL)
#define K_60_79 sal_uInt32(0 xca62c1d6L)
#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)&0 x0f] ^ X[((i)+2 )&0 x0f] ^ X[((i)+8 )&0 x0f] ^ X[((i)+13 )&0 x0f])
#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)&0 x0f] = (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)&0 x0f] = (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)&0 x0f] = (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)&0 x0f] = (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(0 x67452301L);
ctx->m_nB = sal_uInt32(0 xefcdab89L);
ctx->m_nC = sal_uInt32(0 x98badcfeL);
ctx->m_nD = sal_uInt32(0 x10325476L);
ctx->m_nE = sal_uInt32(0 xc3d2e1f0L);
}
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 ] =
{
0 x80, 0 x00, 0 x00, 0 x00
};
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 & 0 x03)
{
case 1 : X[i] &= 0 x000000ff; break ;
case 2 : X[i] &= 0 x0000ffff; break ;
case 3 : X[i] &= 0 x00ffffff; break ;
}
switch (ctx->m_nDatLen & 0 x03)
{
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);
}
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) noexcept
{
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() noexcept
{
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) noexcept
{
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) noexcept
{
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) noexcept
{
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);
}
}
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) noexcept
{
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() noexcept
{
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) noexcept
{
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) noexcept
{
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) noexcept
{
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);
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] ^= 0 x36;
}
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] ^= 0 x36;
}
}
static void opadHMAC_MD5(ContextHMAC_MD5 * ctx)
{
sal_uInt32 i;
for (i = 0 ; i < DIGEST_CBLOCK_HMAC_MD5; i++)
{
ctx->m_opad[i] ^= 0 x5c;
}
}
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) noexcept
{
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() noexcept
{
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) noexcept
{
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) noexcept
{
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) noexcept
{
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) noexcept
{
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);
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] ^= 0 x36;
}
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] ^= 0 x36;
}
}
static void opadHMAC_SHA1(ContextHMAC_SHA1 * ctx)
{
sal_uInt32 i;
for (i = 0 ; i < DIGEST_CBLOCK_HMAC_SHA1; i++)
{
ctx->m_opad[i] ^= 0 x5c;
}
}
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) noexcept
{
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() noexcept
{
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) noexcept
{
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) noexcept
{
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) noexcept
{
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) noexcept
{
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) noexcept
{
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: */
Messung V0.5 in Prozent C=99 H=90 G=94
¤ Dauer der Verarbeitung: 0.22 Sekunden
(vorverarbeitet am 2026-09-29)
¤
*© Formatika GbR, Deutschland