Revert "sal: remove MD2, SHA, HMAC_MD5 digests"

it breaks the published API

This reverts commit e4892750c3.

Change-Id: Id072882efc432cdbc3c20a6bcece1369f9a78bf4
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/209385
Tested-by: Jenkins
Reviewed-by: Xisco Fauli <xiscofauli@libreoffice.org>
This commit is contained in:
Xisco Fauli
2026-08-20 15:43:22 +02:00
parent aac090211d
commit e1f9e8beb4
3 changed files with 876 additions and 26 deletions
+207
View File
@@ -43,9 +43,12 @@ typedef void* rtlDigest;
*/
enum __rtl_DigestAlgorithm
{
rtl_Digest_AlgorithmMD2,
rtl_Digest_AlgorithmMD5,
rtl_Digest_AlgorithmSHA,
rtl_Digest_AlgorithmSHA1,
rtl_Digest_AlgorithmHMAC_MD5,
rtl_Digest_AlgorithmHMAC_SHA1,
rtl_Digest_AlgorithmInvalid,
@@ -156,6 +159,62 @@ SAL_DLLPUBLIC rtlDigestError SAL_CALL rtl_digest_get (
sal_uInt8 *pBuffer, sal_uInt32 nBufLen
) SAL_THROW_EXTERN_C();
#define RTL_DIGEST_LENGTH_MD2 16
/** Create a MD2 digest handle.
The MD2 digest algorithm is specified in
RFC 1319 (Informational)
The MD2 Message-Digest Algorithm
@see rtl_digest_create()
*/
SAL_DLLPUBLIC rtlDigest SAL_CALL rtl_digest_createMD2 (void) SAL_THROW_EXTERN_C();
/** Destroy a MD2 digest handle.
@see rtl_digest_destroy()
*/
SAL_DLLPUBLIC void SAL_CALL rtl_digest_destroyMD2 (
rtlDigest Digest
) SAL_THROW_EXTERN_C();
/** Update a MD2 digest with given data.
@see rtl_digest_update()
*/
SAL_DLLPUBLIC rtlDigestError SAL_CALL rtl_digest_updateMD2 (
rtlDigest Digest,
const void *pData, sal_uInt32 nDatLen
) SAL_THROW_EXTERN_C();
/** Finalize a MD2 digest and retrieve the digest value.
@see rtl_digest_get()
*/
SAL_DLLPUBLIC rtlDigestError SAL_CALL rtl_digest_getMD2 (
rtlDigest Digest,
sal_uInt8 *pBuffer, sal_uInt32 nBufLen
) SAL_THROW_EXTERN_C();
/** Evaluate a MD2 digest value from given data.
This function performs an optimized call sequence on a
single data buffer, avoiding digest creation and destruction.
@see rtl_digest_updateMD2()
@see rtl_digest_getMD2()
@param[in] pData data buffer.
@param[in] nDatLen data length.
@param[in] pBuffer digest value buffer.
@param[in] nBufLen digest value length.
@retval rtl_Digest_E_None upon success.
*/
SAL_DLLPUBLIC rtlDigestError SAL_CALL rtl_digest_MD2 (
const void *pData, sal_uInt32 nDatLen,
sal_uInt8 *pBuffer, sal_uInt32 nBufLen
) SAL_THROW_EXTERN_C();
#define RTL_DIGEST_LENGTH_MD5 16
/** Create a MD5 digest handle.
@@ -224,6 +283,80 @@ SAL_DLLPUBLIC rtlDigestError SAL_CALL rtl_digest_MD5 (
sal_uInt8 *pBuffer, sal_uInt32 nBufLen
) SAL_THROW_EXTERN_C();
#define RTL_DIGEST_LENGTH_SHA 20
/** Create a SHA digest handle.
The SHA digest algorithm is specified in
FIPS PUB 180 (Superseded by FIPS PUB 180-1)
Secure Hash Standard
@deprecated The implementation is buggy and generates incorrect results
for 52 <= (len % 64) <= 55; use only for bug-compatibility.
@see rtl_digest_create()
*/
SAL_DLLPUBLIC rtlDigest SAL_CALL rtl_digest_createSHA (void) SAL_THROW_EXTERN_C();
/** Destroy a SHA digest handle.
@deprecated The implementation is buggy and generates incorrect results
for 52 <= (len % 64) <= 55; use only for bug-compatibility.
@see rtl_digest_destroy()
*/
SAL_DLLPUBLIC void SAL_CALL rtl_digest_destroySHA (
rtlDigest Digest
) SAL_THROW_EXTERN_C();
/** Update a SHA digest with given data.
@deprecated The implementation is buggy and generates incorrect results
for 52 <= (len % 64) <= 55; use only for bug-compatibility.
@see rtl_digest_update()
*/
SAL_DLLPUBLIC rtlDigestError SAL_CALL rtl_digest_updateSHA (
rtlDigest Digest,
const void *pData, sal_uInt32 nDatLen
) SAL_THROW_EXTERN_C();
/** Finalize a SHA digest and retrieve the digest value.
@deprecated The implementation is buggy and generates incorrect results
for 52 <= (len % 64) <= 55; use only for bug-compatibility.
@see rtl_digest_get()
*/
SAL_DLLPUBLIC rtlDigestError SAL_CALL rtl_digest_getSHA (
rtlDigest Digest,
sal_uInt8 *pBuffer, sal_uInt32 nBufLen
) SAL_THROW_EXTERN_C();
/** Evaluate a SHA digest value from given data.
This function performs an optimized call sequence on a
single data buffer, avoiding digest creation and destruction.
@deprecated The implementation is buggy and generates incorrect results
for 52 <= (len % 64) <= 55; use only for bug-compatibility.
@see rtl_digest_updateSHA()
@see rtl_digest_getSHA()
@param[in] pData data buffer.
@param[in] nDatLen data length.
@param[in] pBuffer digest value buffer.
@param[in] nBufLen digest value length.
@retval rtl_Digest_E_None upon success.
*/
SAL_DLLPUBLIC rtlDigestError SAL_CALL rtl_digest_SHA (
const void *pData, sal_uInt32 nDatLen,
sal_uInt8 *pBuffer, sal_uInt32 nBufLen
) SAL_THROW_EXTERN_C();
/*========================================================================
*
* rtl_digest_SHA1 interface.
@@ -302,6 +435,80 @@ SAL_DLLPUBLIC rtlDigestError SAL_CALL rtl_digest_SHA1 (
sal_uInt8 *pBuffer, sal_uInt32 nBufLen
) SAL_THROW_EXTERN_C();
#define RTL_DIGEST_LENGTH_HMAC_MD5 RTL_DIGEST_LENGTH_MD5
/** Create a HMAC_MD5 digest handle.
The HMAC_MD5 digest algorithm is specified in
RFC 2104 (Informational)
HMAC: Keyed-Hashing for Message Authentication
@see rtl_digest_create()
*/
SAL_DLLPUBLIC rtlDigest SAL_CALL rtl_digest_createHMAC_MD5 (void) SAL_THROW_EXTERN_C();
/** Destroy a HMAC_MD5 digest handle.
@see rtl_digest_destroy()
*/
SAL_DLLPUBLIC void SAL_CALL rtl_digest_destroyHMAC_MD5 (
rtlDigest Digest
) SAL_THROW_EXTERN_C();
/** Initialize a HMAC_MD5 digest.
@see rtl_digest_init()
@param[in] Digest digest handle.
@param[in] pKeyData key material buffer.
@param[in] nKeyLen key material length.
@retval rtl_Digest_E_None upon success.
*/
SAL_DLLPUBLIC rtlDigestError SAL_CALL rtl_digest_initHMAC_MD5 (
rtlDigest Digest,
const sal_uInt8 *pKeyData, sal_uInt32 nKeyLen
) SAL_THROW_EXTERN_C();
/** Update a HMAC_MD5 digest with given data.
@see rtl_digest_update()
*/
SAL_DLLPUBLIC rtlDigestError SAL_CALL rtl_digest_updateHMAC_MD5 (
rtlDigest Digest,
const void *pData, sal_uInt32 nDatLen
) SAL_THROW_EXTERN_C();
/** Finalize a HMAC_MD5 digest and retrieve the digest value.
@see rtl_digest_get()
*/
SAL_DLLPUBLIC rtlDigestError SAL_CALL rtl_digest_getHMAC_MD5 (
rtlDigest Digest,
sal_uInt8 *pBuffer, sal_uInt32 nBufLen
) SAL_THROW_EXTERN_C();
/** Evaluate a HMAC_MD5 digest value from given data.
This function performs an optimized call sequence on a
single data buffer, avoiding digest creation and destruction.
@see rtl_digest_initHMAC_MD5()
@see rtl_digest_updateHMAC_MD5()
@see rtl_digest_getHMAC_MD5()
@param[in] pKeyData key material buffer.
@param[in] nKeyLen key material length.
@param[in] pData data buffer.
@param[in] nDatLen data length.
@param[in] pBuffer digest value buffer.
@param[in] nBufLen digest value length.
@retval rtl_Digest_E_None upon success.
*/
SAL_DLLPUBLIC 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();
#define RTL_DIGEST_LENGTH_HMAC_SHA1 RTL_DIGEST_LENGTH_SHA1
/** Create a HMAC_SHA1 digest handle.
+38 -26
View File
@@ -41,22 +41,31 @@ constexpr OStringLiteral sSampleString_only_one_diff ("This is a sample sentence
const rtlDigestAlgorithm constDigestAlgorithms[] =
{
rtl_Digest_AlgorithmMD2,
rtl_Digest_AlgorithmMD5,
rtl_Digest_AlgorithmSHA,
rtl_Digest_AlgorithmSHA1,
rtl_Digest_AlgorithmHMAC_MD5,
rtl_Digest_AlgorithmHMAC_SHA1,
};
const sal_uInt32 constDigestAlgorithmLengths[] =
{
RTL_DIGEST_LENGTH_MD2,
RTL_DIGEST_LENGTH_MD5,
RTL_DIGEST_LENGTH_SHA,
RTL_DIGEST_LENGTH_SHA1,
RTL_DIGEST_LENGTH_HMAC_MD5,
RTL_DIGEST_LENGTH_HMAC_SHA1,
};
const std::string_view constSampleStringSums[] =
{
std::string_view("647ee6c9d4aa5fdd374ed9d7a156acbf"),
std::string_view("b16b903e6fc0b62ae389013ed93fe531"),
std::string_view("eab2814429b2613301c8a077b806af3680548914"),
std::string_view("2bc5bdb7506a2cdc2fd27fc8b9889343012d5008"),
std::string_view("0b1b0e1a6f2e4420326354b031063605"),
std::string_view("1998c6a556915be76451bfb587fa7c34d849936e")
};
@@ -271,42 +280,45 @@ public:
CPPUNIT_ASSERT_EQUAL_MESSAGE("does not handle wrong parameter", rtl_Digest_E_Argument, aError);
aHandle = nullptr;
aError = rtl_digest_updateSHA1(aHandle, nullptr, 0);
aError = rtl_digest_updateMD2(aHandle, nullptr, 0);
CPPUNIT_ASSERT_EQUAL_MESSAGE("does not handle wrong parameter", rtl_Digest_E_Argument, aError);
aHandle = rtl_digest_create( rtl_Digest_AlgorithmSHA1 );
CPPUNIT_ASSERT(aHandle != nullptr);
aError = rtl_digest_updateMD5(aHandle, nullptr, 0);
CPPUNIT_ASSERT_EQUAL_MESSAGE("does not handle wrong parameter", rtl_Digest_E_Argument, aError);
aHandle = rtl_digest_create( rtl_Digest_AlgorithmMD2 );
CPPUNIT_ASSERT_MESSAGE("create with rtl_Digest_AlgorithmMD2", aHandle != nullptr);
const sal_uInt8* pData = reinterpret_cast<const sal_uInt8*>(sSampleString.getStr());
sal_uInt32 nSize = sSampleString.getLength();
aError = rtl_digest_updateSHA1(aHandle, nullptr, 0);
aError = rtl_digest_updateMD2(aHandle, nullptr, 0);
CPPUNIT_ASSERT_EQUAL_MESSAGE("handle parameter 'pData' wrong", rtl_Digest_E_Argument, aError);
aError = rtl_digest_updateSHA1(aHandle, pData, 0);
aError = rtl_digest_updateMD2(aHandle, pData, 0);
CPPUNIT_ASSERT_EQUAL_MESSAGE("handle parameter 'nSize' wrong", rtl_Digest_E_None, aError);
rtl_digest_destroySHA1(aHandle);
rtl_digest_destroyMD2(aHandle);
// use wrong Algorithm!!! This is volitional!
aHandle = rtl_digest_create(rtl_Digest_AlgorithmHMAC_SHA1);
CPPUNIT_ASSERT(aHandle != nullptr);
aHandle = rtl_digest_create(rtl_Digest_AlgorithmMD2);
CPPUNIT_ASSERT_MESSAGE("create with rtl_Digest_AlgorithmMD2", aHandle != nullptr);
aError = rtl_digest_updateSHA1(aHandle, pData, nSize);
aError = rtl_digest_updateMD5(aHandle, pData, nSize);
CPPUNIT_ASSERT_EQUAL_MESSAGE("handle parameter 'handle' wrong", rtl_Digest_E_Algorithm, aError);
rtl_digest_destroyHMAC_SHA1(aHandle);
rtl_digest_destroyMD5(aHandle);
aHandle = rtl_digest_create( rtl_Digest_AlgorithmHMAC_SHA1 );
CPPUNIT_ASSERT(aHandle != nullptr);
aHandle = rtl_digest_create( rtl_Digest_AlgorithmMD5 );
CPPUNIT_ASSERT_MESSAGE("create with rtl_Digest_AlgorithmMD5", aHandle != nullptr);
aError = rtl_digest_updateHMAC_SHA1(aHandle, nullptr, 0);
aError = rtl_digest_updateMD5(aHandle, nullptr, 0);
CPPUNIT_ASSERT_EQUAL_MESSAGE("handle parameter 'pData' wrong", rtl_Digest_E_Argument, aError);
aError = rtl_digest_updateHMAC_SHA1(aHandle, pData, 0);
aError = rtl_digest_updateMD5(aHandle, pData, 0);
CPPUNIT_ASSERT_EQUAL_MESSAGE("handle parameter 'nSize' wrong", rtl_Digest_E_None, aError);
rtl_digest_destroyHMAC_SHA1(aHandle);
rtl_digest_destroyMD5(aHandle);
}
void testGet()
@@ -319,34 +331,34 @@ public:
CPPUNIT_ASSERT_EQUAL_MESSAGE("does not handle wrong parameter", rtl_Digest_E_Argument, aError);
aHandle = nullptr;
aError = rtl_digest_getSHA1(aHandle, nullptr, 0);
aError = rtl_digest_getMD5(aHandle, nullptr, 0);
CPPUNIT_ASSERT_EQUAL_MESSAGE("does not handle wrong parameter", rtl_Digest_E_Argument, aError);
// test with wrong algorithm
aHandle = rtl_digest_create(rtl_Digest_AlgorithmHMAC_SHA1);
CPPUNIT_ASSERT(aHandle != nullptr);
aHandle = rtl_digest_create(rtl_Digest_AlgorithmMD2);
CPPUNIT_ASSERT_MESSAGE("create with rtl_Digest_AlgorithmMD2", aHandle != nullptr);
sal_uInt32 nKeyLen = rtl_digest_queryLength(aHandle);
std::unique_ptr<sal_uInt8[]> pKeyBuffer(new sal_uInt8[nKeyLen]);
aError = rtl_digest_getSHA1(aHandle, nullptr, 0);
aError = rtl_digest_getMD5(aHandle, nullptr, 0);
CPPUNIT_ASSERT_EQUAL_MESSAGE("handle 2. parameter wrong", rtl_Digest_E_Argument, aError);
aError = rtl_digest_getSHA1(aHandle, pKeyBuffer.get(), 0);
aError = rtl_digest_getMD5(aHandle, pKeyBuffer.get(), 0);
CPPUNIT_ASSERT_EQUAL_MESSAGE("handle parameter 'handle' wrong", rtl_Digest_E_Algorithm, aError);
rtl_digest_destroyHMAC_SHA1(aHandle);
rtl_digest_destroyMD2(aHandle);
aHandle = rtl_digest_create(rtl_Digest_AlgorithmSHA1);
CPPUNIT_ASSERT(aHandle != nullptr);
aHandle = rtl_digest_create(rtl_Digest_AlgorithmMD5);
CPPUNIT_ASSERT_MESSAGE("create with rtl_Digest_AlgorithmMD5", aHandle != nullptr);
aError = rtl_digest_getSHA1(aHandle, nullptr, nKeyLen);
aError = rtl_digest_getMD5(aHandle, nullptr, nKeyLen);
CPPUNIT_ASSERT_EQUAL_MESSAGE("handle parameter 'pData' wrong", rtl_Digest_E_Argument, aError);
aError = rtl_digest_getSHA1(aHandle, pKeyBuffer.get(), 0);
aError = rtl_digest_getMD5(aHandle, pKeyBuffer.get(), 0);
CPPUNIT_ASSERT_EQUAL_MESSAGE("handle parameter 'nSize' wrong", rtl_Digest_E_BufferSize, aError);
rtl_digest_destroySHA1(aHandle);
rtl_digest_destroyMD5(aHandle);
}
void testSHA1SumForBiggerInputData()
+631
View File
@@ -86,14 +86,26 @@ 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;
@@ -158,6 +170,270 @@ void SAL_CALL rtl_digest_destroy(rtlDigest Digest) noexcept
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] =
{
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,
};
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) 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] & 0xff);
}
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
@@ -546,6 +822,7 @@ void SAL_CALL rtl_digest_destroyMD5(rtlDigest Digest) noexcept
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 {
@@ -798,6 +1075,163 @@ static void endSHA(DigestContextSHA *ctx)
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,
@@ -955,6 +1389,203 @@ void SAL_CALL rtl_digest_destroySHA1(rtlDigest Digest) noexcept
}
}
#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] ^= 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) 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 {