/* -*- 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 <stdlib.h>
#include <string.h>
#include <sal/types.h>
#include <rtl/alloc.h>
#include <rtl/cipher.h>
#include <algorithm>
#if defined LIBO_CIPHER_OPENSSL_BACKEND
#include <o3tl/safeint.hxx>
#include <cassert>
#include <cstring>
#include <limits>
#include <openssl/evp.h>
#endif
#if !
defined LIBO_CIPHER_OPENSSL_BACKEND
#define RTL_CIPHER_NTOHL(c, l) \
((l) = (
static_cast <sal_uInt32>(*((c)++))) <<
24 , \
(l) |= (
static_cast <sal_uInt32>(*((c)++))) <<
16 , \
(l) |= (
static_cast <sal_uInt32>(*((c)++))) <<
8 , \
(l) |= (
static_cast <sal_uInt32>(*((c)++))))
#define RTL_CIPHER_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_CIPHER_NTOHL64(c, xl, xr, n) \
{ \
(xl) = (xr) =
0 ; \
(c) += (n); \
switch ((n)) \
{ \
case 8 : (xr) = (
static_cast <sal_uInt32>(*(--(c)))); \
[[fallthrough]]; \
case 7 : (xr) |= (
static_cast <sal_uInt32>(*(--(c)))) <<
8 ; \
[[fallthrough]]; \
case 6 : (xr) |= (
static_cast <sal_uInt32>(*(--(c)))) <<
16 ; \
[[fallthrough]]; \
case 5 : (xr) |= (
static_cast <sal_uInt32>(*(--(c)))) <<
24 ; \
[[fallthrough]]; \
case 4 : (xl) = (
static_cast <sal_uInt32>(*(--(c)))); \
[[fallthrough]]; \
case 3 : (xl) |= (
static_cast <sal_uInt32>(*(--(c)))) <<
8 ; \
[[fallthrough]]; \
case 2 : (xl) |= (
static_cast <sal_uInt32>(*(--(c)))) <<
16 ; \
[[fallthrough]]; \
case 1 : (xl) |= (
static_cast <sal_uInt32>(*(--(c)))) <<
24 ; \
} \
}
#define RTL_CIPHER_HTONL64(xl, xr, c, n) \
{ \
(c) += (n); \
switch ((n)) \
{ \
case 8 : *(--(c)) =
static_cast <sal_uInt8>(((xr) ) &
0 xff); \
[[fallthrough]]; \
case 7 : *(--(c)) =
static_cast <sal_uInt8>(((xr) >>
8 ) &
0 xff); \
[[fallthrough]]; \
case 6 : *(--(c)) =
static_cast <sal_uInt8>(((xr) >>
16 ) &
0 xff); \
[[fallthrough]]; \
case 5 : *(--(c)) =
static_cast <sal_uInt8>(((xr) >>
24 ) &
0 xff); \
[[fallthrough]]; \
case 4 : *(--(c)) =
static_cast <sal_uInt8>(((xl) ) &
0 xff); \
[[fallthrough]]; \
case 3 : *(--(c)) =
static_cast <sal_uInt8>(((xl) >>
8 ) &
0 xff); \
[[fallthrough]]; \
case 2 : *(--(c)) =
static_cast <sal_uInt8>(((xl) >>
16 ) &
0 xff); \
[[fallthrough]]; \
case 1 : *(--(c)) =
static_cast <sal_uInt8>(((xl) >>
24 ) &
0 xff); \
} \
}
#endif
typedef rtlCipherError(cipher_init_t) (
rtlCipher Cipher,
rtlCipherDirection Direction,
const sal_uInt8 *pKeyData, sal_Size nKeyLen,
const sal_uInt8 *pArgData, sal_Size nArgLen);
typedef rtlCipherError(cipher_update_t) (
rtlCipher Cipher,
const void *pData, sal_Size nDatLen,
sal_uInt8 *pBuffer, sal_Size nBufLen);
typedef void (cipher_delete_t) (rtlCipher Cipher);
namespace {
struct Cipher_Impl
{
rtlCipherAlgorithm m_algorithm;
rtlCipherDirection m_direction;
rtlCipherMode m_mode;
cipher_init_t *m_init;
cipher_update_t *m_encode;
cipher_update_t *m_decode;
cipher_delete_t *m_delete;
};
}
rtlCipher SAL_CALL rtl_cipher_create(
rtlCipherAlgorithm Algorithm,
rtlCipherMode Mode) noexcept
{
rtlCipher Cipher = nullptr;
switch (Algorithm)
{
case rtl_Cipher_AlgorithmBF:
Cipher = rtl_cipher_createBF (Mode);
break ;
case rtl_Cipher_AlgorithmARCFOUR:
Cipher = rtl_cipher_createARCFOUR (Mode);
break ;
default :
/* rtl_Cipher_AlgorithmInvalid */
break ;
}
return Cipher;
}
rtlCipherError SAL_CALL rtl_cipher_init(
rtlCipher Cipher,
rtlCipherDirection Direction,
const sal_uInt8 *pKeyData, sal_Size nKeyLen,
const sal_uInt8 *pArgData, sal_Size nArgLen) noexcept
{
Cipher_Impl *pImpl =
static_cast <Cipher_Impl*>(Cipher);
if (!pImpl)
return rtl_Cipher_E_Argument;
if (!pImpl->m_init)
return rtl_Cipher_E_Unknown;
return (pImpl->m_init)(
Cipher, Direction, pKeyData, nKeyLen, pArgData, nArgLen);
}
rtlCipherError SAL_CALL rtl_cipher_encode(
rtlCipher Cipher,
const void *pData, sal_Size nDatLen,
sal_uInt8 *pBuffer, sal_Size nBufLen) noexcept
{
Cipher_Impl *pImpl =
static_cast <Cipher_Impl*>(Cipher);
if (!pImpl)
return rtl_Cipher_E_Argument;
if (!pImpl->m_encode)
return rtl_Cipher_E_Unknown;
return (pImpl->m_encode)(Cipher, pData, nDatLen, pBuffer, nBufLen);
}
rtlCipherError SAL_CALL rtl_cipher_decode(
rtlCipher Cipher,
const void *pData, sal_Size nDatLen,
sal_uInt8 *pBuffer, sal_Size nBufLen) noexcept
{
Cipher_Impl *pImpl =
static_cast <Cipher_Impl*>(Cipher);
if (!pImpl)
return rtl_Cipher_E_Argument;
if (!pImpl->m_decode)
return rtl_Cipher_E_Unknown;
return (pImpl->m_decode)(Cipher, pData, nDatLen, pBuffer, nBufLen);
}
void SAL_CALL rtl_cipher_destroy(rtlCipher Cipher) noexcept
{
Cipher_Impl *pImpl =
static_cast <Cipher_Impl*>(Cipher);
if (pImpl && pImpl->m_delete)
pImpl->m_delete(Cipher);
}
namespace {
#if !
defined LIBO_CIPHER_OPENSSL_BACKEND
#define CIPHER_ROUNDS_BF
16
struct CipherKeyBF
{
sal_uInt32 m_S[
4 ][
256 ];
sal_uInt32 m_P[CIPHER_ROUNDS_BF +
2 ];
};
#endif
struct CipherContextBF
{
#if defined LIBO_CIPHER_OPENSSL_BACKEND
EVP_CIPHER_CTX * m_context;
#else
CipherKeyBF m_key;
union
{
sal_uInt32 m_long[
2 ];
sal_uInt8 m_byte[
8 ];
} m_iv;
sal_uInt32 m_offset;
#endif
};
struct CipherBF_Impl
{
Cipher_Impl m_cipher;
CipherContextBF m_context;
};
}
#if !
defined LIBO_CIPHER_OPENSSL_BACKEND
static rtlCipherError BF_init(
CipherContextBF *ctx,
rtlCipherMode eMode,
const sal_uInt8 *pKeyData, sal_Size nKeyLen,
const sal_uInt8 *pArgData, sal_Size nArgLen);
#endif
static rtlCipherError BF_update(
CipherContextBF *ctx,
rtlCipherMode eMode,
rtlCipherDirection eDirection,
const sal_uInt8 *pData, sal_Size nDatLen,
sal_uInt8 *pBuffer, sal_Size nBufLen);
#if !
defined LIBO_CIPHER_OPENSSL_BACKEND
static void BF_updateECB(
CipherContextBF *ctx,
rtlCipherDirection direction,
const sal_uInt8 *pData,
sal_uInt8 *pBuffer,
sal_Size nLength);
static void BF_updateCBC(
CipherContextBF *ctx,
rtlCipherDirection direction,
const sal_uInt8 *pData,
sal_uInt8 *pBuffer,
sal_Size nLength);
static void BF_updateCFB(
CipherContextBF *ctx,
rtlCipherDirection direction,
const sal_uInt8 *pData,
sal_uInt8 *pBuffer);
static void BF_encode(CipherKeyBF *key, sal_uInt32 *xl, sal_uInt32 *xr);
static void BF_decode(CipherKeyBF *key, sal_uInt32 *xl, sal_uInt32 *xr);
static sal_uInt32 BF(CipherKeyBF *key, sal_uInt32 x);
const CipherKeyBF BF_key =
{
/* S */
{
/* S[0] */
{
/* 0 */
0 xD1310BA6L,
0 x98DFB5ACL,
0 x2FFD72DBL,
0 xD01ADFB7L,
0 xB8E1AFEDL,
0 x6A267E96L,
0 xBA7C9045L,
0 xF12C7F99L,
0 x24A19947L,
0 xB3916CF7L,
0 x0801F2E2L,
0 x858EFC16L,
0 x636920D8L,
0 x71574E69L,
0 xA458FEA3L,
0 xF4933D7EL,
/* 1 */
0 x0D95748FL,
0 x728EB658L,
0 x718BCD58L,
0 x82154AEEL,
0 x7B54A41DL,
0 xC25A59B5L,
0 x9C30D539L,
0 x2AF26013L,
0 xC5D1B023L,
0 x286085F0L,
0 xCA417918L,
0 xB8DB38EFL,
0 x8E79DCB0L,
0 x603A180EL,
0 x6C9E0E8BL,
0 xB01E8A3EL,
/* 2 */
0 xD71577C1L,
0 xBD314B27L,
0 x78AF2FDAL,
0 x55605C60L,
0 xE65525F3L,
0 xAA55AB94L,
0 x57489862L,
0 x63E81440L,
0 x55CA396AL,
0 x2AAB10B6L,
0 xB4CC5C34L,
0 x1141E8CEL,
0 xA15486AFL,
0 x7C72E993L,
0 xB3EE1411L,
0 x636FBC2AL,
/* 3 */
0 x2BA9C55DL,
0 x741831F6L,
0 xCE5C3E16L,
0 x9B87931EL,
0 xAFD6BA33L,
0 x6C24CF5CL,
0 x7A325381L,
0 x28958677L,
0 x3B8F4898L,
0 x6B4BB9AFL,
0 xC4BFE81BL,
0 x66282193L,
0 x61D809CCL,
0 xFB21A991L,
0 x487CAC60L,
0 x5DEC8032L,
/* 4 */
0 xEF845D5DL,
0 xE98575B1L,
0 xDC262302L,
0 xEB651B88L,
0 x23893E81L,
0 xD396ACC5L,
0 x0F6D6FF3L,
0 x83F44239L,
0 x2E0B4482L,
0 xA4842004L,
0 x69C8F04AL,
0 x9E1F9B5EL,
0 x21C66842L,
0 xF6E96C9AL,
0 x670C9C61L,
0 xABD388F0L,
/* 5 */
0 x6A51A0D2L,
0 xD8542F68L,
0 x960FA728L,
0 xAB5133A3L,
0 x6EEF0B6CL,
0 x137A3BE4L,
0 xBA3BF050L,
0 x7EFB2A98L,
0 xA1F1651DL,
0 x39AF0176L,
0 x66CA593EL,
0 x82430E88L,
0 x8CEE8619L,
0 x456F9FB4L,
0 x7D84A5C3L,
0 x3B8B5EBEL,
/* 6 */
0 xE06F75D8L,
0 x85C12073L,
0 x401A449FL,
0 x56C16AA6L,
0 x4ED3AA62L,
0 x363F7706L,
0 x1BFEDF72L,
0 x429B023DL,
0 x37D0D724L,
0 xD00A1248L,
0 xDB0FEAD3L,
0 x49F1C09BL,
0 x075372C9L,
0 x80991B7BL,
0 x25D479D8L,
0 xF6E8DEF7L,
/* 7 */
0 xE3FE501AL,
0 xB6794C3BL,
0 x976CE0BDL,
0 x04C006BAL,
0 xC1A94FB6L,
0 x409F60C4L,
0 x5E5C9EC2L,
0 x196A2463L,
0 x68FB6FAFL,
0 x3E6C53B5L,
0 x1339B2EBL,
0 x3B52EC6FL,
0 x6DFC511FL,
0 x9B30952CL,
0 xCC814544L,
0 xAF5EBD09L,
/* 8 */
0 xBEE3D004L,
0 xDE334AFDL,
0 x660F2807L,
0 x192E4BB3L,
0 xC0CBA857L,
0 x45C8740FL,
0 xD20B5F39L,
0 xB9D3FBDBL,
0 x5579C0BDL,
0 x1A60320AL,
0 xD6A100C6L,
0 x402C7279L,
0 x679F25FEL,
0 xFB1FA3CCL,
0 x8EA5E9F8L,
0 xDB3222F8L,
/* 9 */
0 x3C7516DFL,
0 xFD616B15L,
0 x2F501EC8L,
0 xAD0552ABL,
0 x323DB5FAL,
0 xFD238760L,
0 x53317B48L,
0 x3E00DF82L,
0 x9E5C57BBL,
0 xCA6F8CA0L,
0 x1A87562EL,
0 xDF1769DBL,
0 xD542A8F6L,
0 x287EFFC3L,
0 xAC6732C6L,
0 x8C4F5573L,
/* A */
0 x695B27B0L,
0 xBBCA58C8L,
0 xE1FFA35DL,
0 xB8F011A0L,
0 x10FA3D98L,
0 xFD2183B8L,
0 x4AFCB56CL,
0 x2DD1D35BL,
0 x9A53E479L,
0 xB6F84565L,
0 xD28E49BCL,
0 x4BFB9790L,
0 xE1DDF2DAL,
0 xA4CB7E33L,
0 x62FB1341L,
0 xCEE4C6E8L,
/* B */
0 xEF20CADAL,
0 x36774C01L,
0 xD07E9EFEL,
0 x2BF11FB4L,
0 x95DBDA4DL,
0 xAE909198L,
0 xEAAD8E71L,
0 x6B93D5A0L,
0 xD08ED1D0L,
0 xAFC725E0L,
0 x8E3C5B2FL,
0 x8E7594B7L,
0 x8FF6E2FBL,
0 xF2122B64L,
0 x8888B812L,
0 x900DF01CL,
/* C */
0 x4FAD5EA0L,
0 x688FC31CL,
0 xD1CFF191L,
0 xB3A8C1ADL,
0 x2F2F2218L,
0 xBE0E1777L,
0 xEA752DFEL,
0 x8B021FA1L,
0 xE5A0CC0FL,
0 xB56F74E8L,
0 x18ACF3D6L,
0 xCE89E299L,
0 xB4A84FE0L,
0 xFD13E0B7L,
0 x7CC43B81L,
0 xD2ADA8D9L,
/* D */
0 x165FA266L,
0 x80957705L,
0 x93CC7314L,
0 x211A1477L,
0 xE6AD2065L,
0 x77B5FA86L,
0 xC75442F5L,
0 xFB9D35CFL,
0 xEBCDAF0CL,
0 x7B3E89A0L,
0 xD6411BD3L,
0 xAE1E7E49L,
0 x00250E2DL,
0 x2071B35EL,
0 x226800BBL,
0 x57B8E0AFL,
/* E */
0 x2464369BL,
0 xF009B91EL,
0 x5563911DL,
0 x59DFA6AAL,
0 x78C14389L,
0 xD95A537FL,
0 x207D5BA2L,
0 x02E5B9C5L,
0 x83260376L,
0 x6295CFA9L,
0 x11C81968L,
0 x4E734A41L,
0 xB3472DCAL,
0 x7B14A94AL,
0 x1B510052L,
0 x9A532915L,
/* F */
0 xD60F573FL,
0 xBC9BC6E4L,
0 x2B60A476L,
0 x81E67400L,
0 x08BA6FB5L,
0 x571BE91FL,
0 xF296EC6BL,
0 x2A0DD915L,
0 xB6636521L,
0 xE7B9F9B6L,
0 xFF34052EL,
0 xC5855664L,
0 x53B02D5DL,
0 xA99F8FA1L,
0 x08BA4799L,
0 x6E85076AL
},
/* S[1] */
{
0 x4B7A70E9L,
0 xB5B32944L,
0 xDB75092EL,
0 xC4192623L,
0 xAD6EA6B0L,
0 x49A7DF7DL,
0 x9CEE60B8L,
0 x8FEDB266L,
0 xECAA8C71L,
0 x699A17FFL,
0 x5664526CL,
0 xC2B19EE1L,
0 x193602A5L,
0 x75094C29L,
0 xA0591340L,
0 xE4183A3EL,
0 x3F54989AL,
0 x5B429D65L,
0 x6B8FE4D6L,
0 x99F73FD6L,
0 xA1D29C07L,
0 xEFE830F5L,
0 x4D2D38E6L,
0 xF0255DC1L,
0 x4CDD2086L,
0 x8470EB26L,
0 x6382E9C6L,
0 x021ECC5EL,
0 x09686B3FL,
0 x3EBAEFC9L,
0 x3C971814L,
0 x6B6A70A1L,
0 x687F3584L,
0 x52A0E286L,
0 xB79C5305L,
0 xAA500737L,
0 x3E07841CL,
0 x7FDEAE5CL,
0 x8E7D44ECL,
0 x5716F2B8L,
0 xB03ADA37L,
0 xF0500C0DL,
0 xF01C1F04L,
0 x0200B3FFL,
0 xAE0CF51AL,
0 x3CB574B2L,
0 x25837A58L,
0 xDC0921BDL,
0 xD19113F9L,
0 x7CA92FF6L,
0 x94324773L,
0 x22F54701L,
0 x3AE5E581L,
0 x37C2DADCL,
0 xC8B57634L,
0 x9AF3DDA7L,
0 xA9446146L,
0 x0FD0030EL,
0 xECC8C73EL,
0 xA4751E41L,
0 xE238CD99L,
0 x3BEA0E2FL,
0 x3280BBA1L,
0 x183EB331L,
0 x4E548B38L,
0 x4F6DB908L,
0 x6F420D03L,
0 xF60A04BFL,
0 x2CB81290L,
0 x24977C79L,
0 x5679B072L,
0 xBCAF89AFL,
0 xDE9A771FL,
0 xD9930810L,
0 xB38BAE12L,
0 xDCCF3F2EL,
0 x5512721FL,
0 x2E6B7124L,
0 x501ADDE6L,
0 x9F84CD87L,
0 x7A584718L,
0 x7408DA17L,
0 xBC9F9ABCL,
0 xE94B7D8CL,
0 xEC7AEC3AL,
0 xDB851DFAL,
0 x63094366L,
0 xC464C3D2L,
0 xEF1C1847L,
0 x3215D908L,
0 xDD433B37L,
0 x24C2BA16L,
0 x12A14D43L,
0 x2A65C451L,
0 x50940002L,
0 x133AE4DDL,
0 x71DFF89EL,
0 x10314E55L,
0 x81AC77D6L,
0 x5F11199BL,
0 x043556F1L,
0 xD7A3C76BL,
0 x3C11183BL,
0 x5924A509L,
0 xF28FE6EDL,
0 x97F1FBFAL,
0 x9EBABF2CL,
0 x1E153C6EL,
0 x86E34570L,
0 xEAE96FB1L,
0 x860E5E0AL,
0 x5A3E2AB3L,
0 x771FE71CL,
0 x4E3D06FAL,
0 x2965DCB9L,
0 x99E71D0FL,
0 x803E89D6L,
0 x5266C825L,
0 x2E4CC978L,
0 x9C10B36AL,
0 xC6150EBAL,
0 x94E2EA78L,
0 xA5FC3C53L,
0 x1E0A2DF4L,
0 xF2F74EA7L,
0 x361D2B3DL,
0 x1939260FL,
0 x19C27960L,
0 x5223A708L,
0 xF71312B6L,
0 xEBADFE6EL,
0 xEAC31F66L,
0 xE3BC4595L,
0 xA67BC883L,
0 xB17F37D1L,
0 x018CFF28L,
0 xC332DDEFL,
0 xBE6C5AA5L,
0 x65582185L,
0 x68AB9802L,
0 xEECEA50FL,
0 xDB2F953BL,
0 x2AEF7DADL,
0 x5B6E2F84L,
0 x1521B628L,
0 x29076170L,
0 xECDD4775L,
0 x619F1510L,
0 x13CCA830L,
0 xEB61BD96L,
0 x0334FE1EL,
0 xAA0363CFL,
0 xB5735C90L,
0 x4C70A239L,
0 xD59E9E0BL,
0 xCBAADE14L,
0 xEECC86BCL,
0 x60622CA7L,
0 x9CAB5CABL,
0 xB2F3846EL,
0 x648B1EAFL,
0 x19BDF0CAL,
0 xA02369B9L,
0 x655ABB50L,
0 x40685A32L,
0 x3C2AB4B3L,
0 x319EE9D5L,
0 xC021B8F7L,
0 x9B540B19L,
0 x875FA099L,
0 x95F7997EL,
0 x623D7DA8L,
0 xF837889AL,
0 x97E32D77L,
0 x11ED935FL,
0 x16681281L,
0 x0E358829L,
0 xC7E61FD6L,
0 x96DEDFA1L,
0 x7858BA99L,
0 x57F584A5L,
0 x1B227263L,
0 x9B83C3FFL,
0 x1AC24696L,
0 xCDB30AEBL,
0 x532E3054L,
0 x8FD948E4L,
0 x6DBC3128L,
0 x58EBF2EFL,
0 x34C6FFEAL,
0 xFE28ED61L,
0 xEE7C3C73L,
0 x5D4A14D9L,
0 xE864B7E3L,
0 x42105D14L,
0 x203E13E0L,
0 x45EEE2B6L,
0 xA3AAABEAL,
0 xDB6C4F15L,
0 xFACB4FD0L,
0 xC742F442L,
0 xEF6ABBB5L,
0 x654F3B1DL,
0 x41CD2105L,
0 xD81E799EL,
0 x86854DC7L,
0 xE44B476AL,
0 x3D816250L,
0 xCF62A1F2L,
0 x5B8D2646L,
0 xFC8883A0L,
0 xC1C7B6A3L,
0 x7F1524C3L,
0 x69CB7492L,
0 x47848A0BL,
0 x5692B285L,
0 x095BBF00L,
0 xAD19489DL,
0 x1462B174L,
0 x23820E00L,
0 x58428D2AL,
0 x0C55F5EAL,
0 x1DADF43EL,
0 x233F7061L,
0 x3372F092L,
0 x8D937E41L,
0 xD65FECF1L,
0 x6C223BDBL,
0 x7CDE3759L,
0 xCBEE7460L,
0 x4085F2A7L,
0 xCE77326EL,
0 xA6078084L,
0 x19F8509EL,
0 xE8EFD855L,
0 x61D99735L,
0 xA969A7AAL,
0 xC50C06C2L,
0 x5A04ABFCL,
0 x800BCADCL,
0 x9E447A2EL,
0 xC3453484L,
0 xFDD56705L,
0 x0E1E9EC9L,
0 xDB73DBD3L,
0 x105588CDL,
0 x675FDA79L,
0 xE3674340L,
0 xC5C43465L,
0 x713E38D8L,
0 x3D28F89EL,
0 xF16DFF20L,
0 x153E21E7L,
0 x8FB03D4AL,
0 xE6E39F2BL,
0 xDB83ADF7L
},
/* S[2] */
{
0 xE93D5A68L,
0 x948140F7L,
0 xF64C261CL,
0 x94692934L,
0 x411520F7L,
0 x7602D4F7L,
0 xBCF46B2EL,
0 xD4A20068L,
0 xD4082471L,
0 x3320F46AL,
0 x43B7D4B7L,
0 x500061AFL,
0 x1E39F62EL,
0 x97244546L,
0 x14214F74L,
0 xBF8B8840L,
0 x4D95FC1DL,
0 x96B591AFL,
0 x70F4DDD3L,
0 x66A02F45L,
0 xBFBC09ECL,
0 x03BD9785L,
0 x7FAC6DD0L,
0 x31CB8504L,
0 x96EB27B3L,
0 x55FD3941L,
0 xDA2547E6L,
0 xABCA0A9AL,
0 x28507825L,
0 x530429F4L,
0 x0A2C86DAL,
0 xE9B66DFBL,
0 x68DC1462L,
0 xD7486900L,
0 x680EC0A4L,
0 x27A18DEEL,
0 x4F3FFEA2L,
0 xE887AD8CL,
0 xB58CE006L,
0 x7AF4D6B6L,
0 xAACE1E7CL,
0 xD3375FECL,
0 xCE78A399L,
0 x406B2A42L,
0 x20FE9E35L,
0 xD9F385B9L,
0 xEE39D7ABL,
0 x3B124E8BL,
0 x1DC9FAF7L,
0 x4B6D1856L,
0 x26A36631L,
0 xEAE397B2L,
0 x3A6EFA74L,
0 xDD5B4332L,
0 x6841E7F7L,
0 xCA7820FBL,
0 xFB0AF54EL,
0 xD8FEB397L,
0 x454056ACL,
0 xBA489527L,
0 x55533A3AL,
0 x20838D87L,
0 xFE6BA9B7L,
0 xD096954BL,
0 x55A867BCL,
0 xA1159A58L,
0 xCCA92963L,
0 x99E1DB33L,
0 xA62A4A56L,
0 x3F3125F9L,
0 x5EF47E1CL,
0 x9029317CL,
0 xFDF8E802L,
0 x04272F70L,
0 x80BB155CL,
0 x05282CE3L,
0 x95C11548L,
0 xE4C66D22L,
0 x48C1133FL,
0 xC70F86DCL,
0 x07F9C9EEL,
0 x41041F0FL,
0 x404779A4L,
0 x5D886E17L,
0 x325F51EBL,
0 xD59BC0D1L,
0 xF2BCC18FL,
0 x41113564L,
0 x257B7834L,
0 x602A9C60L,
0 xDFF8E8A3L,
0 x1F636C1BL,
0 x0E12B4C2L,
0 x02E1329EL,
0 xAF664FD1L,
0 xCAD18115L,
0 x6B2395E0L,
0 x333E92E1L,
0 x3B240B62L,
0 xEEBEB922L,
0 x85B2A20EL,
0 xE6BA0D99L,
0 xDE720C8CL,
0 x2DA2F728L,
0 xD0127845L,
0 x95B794FDL,
0 x647D0862L,
0 xE7CCF5F0L,
0 x5449A36FL,
0 x877D48FAL,
0 xC39DFD27L,
0 xF33E8D1EL,
0 x0A476341L,
0 x992EFF74L,
0 x3A6F6EABL,
0 xF4F8FD37L,
0 xA812DC60L,
0 xA1EBDDF8L,
0 x991BE14CL,
0 xDB6E6B0DL,
0 xC67B5510L,
0 x6D672C37L,
0 x2765D43BL,
0 xDCD0E804L,
0 xF1290DC7L,
0 xCC00FFA3L,
0 xB5390F92L,
0 x690FED0BL,
0 x667B9FFBL,
0 xCEDB7D9CL,
0 xA091CF0BL,
0 xD9155EA3L,
0 xBB132F88L,
0 x515BAD24L,
0 x7B9479BFL,
0 x763BD6EBL,
0 x37392EB3L,
0 xCC115979L,
0 x8026E297L,
0 xF42E312DL,
0 x6842ADA7L,
0 xC66A2B3BL,
0 x12754CCCL,
0 x782EF11CL,
0 x6A124237L,
0 xB79251E7L,
0 x06A1BBE6L,
0 x4BFB6350L,
0 x1A6B1018L,
0 x11CAEDFAL,
0 x3D25BDD8L,
0 xE2E1C3C9L,
0 x44421659L,
0 x0A121386L,
0 xD90CEC6EL,
0 xD5ABEA2AL,
0 x64AF674EL,
0 xDA86A85FL,
0 xBEBFE988L,
0 x64E4C3FEL,
0 x9DBC8057L,
0 xF0F7C086L,
0 x60787BF8L,
0 x6003604DL,
0 xD1FD8346L,
0 xF6381FB0L,
0 x7745AE04L,
0 xD736FCCCL,
0 x83426B33L,
0 xF01EAB71L,
0 xB0804187L,
0 x3C005E5FL,
0 x77A057BEL,
0 xBDE8AE24L,
0 x55464299L,
0 xBF582E61L,
0 x4E58F48FL,
0 xF2DDFDA2L,
0 xF474EF38L,
0 x8789BDC2L,
0 x5366F9C3L,
0 xC8B38E74L,
0 xB475F255L,
0 x46FCD9B9L,
0 x7AEB2661L,
0 x8B1DDF84L,
0 x846A0E79L,
0 x915F95E2L,
0 x466E598EL,
0 x20B45770L,
0 x8CD55591L,
0 xC902DE4CL,
0 xB90BACE1L,
0 xBB8205D0L,
0 x11A86248L,
0 x7574A99EL,
0 xB77F19B6L,
0 xE0A9DC09L,
0 x662D09A1L,
0 xC4324633L,
0 xE85A1F02L,
0 x09F0BE8CL,
0 x4A99A025L,
0 x1D6EFE10L,
0 x1AB93D1DL,
0 x0BA5A4DFL,
0 xA186F20FL,
0 x2868F169L,
0 xDCB7DA83L,
0 x573906FEL,
0 xA1E2CE9BL,
0 x4FCD7F52L,
0 x50115E01L,
0 xA70683FAL,
0 xA002B5C4L,
0 x0DE6D027L,
0 x9AF88C27L,
0 x773F8641L,
0 xC3604C06L,
0 x61A806B5L,
0 xF0177A28L,
0 xC0F586E0L,
0 x006058AAL,
0 x30DC7D62L,
0 x11E69ED7L,
0 x2338EA63L,
0 x53C2DD94L,
0 xC2C21634L,
0 xBBCBEE56L,
0 x90BCB6DEL,
0 xEBFC7DA1L,
0 xCE591D76L,
0 x6F05E409L,
0 x4B7C0188L,
0 x39720A3DL,
0 x7C927C24L,
0 x86E3725FL,
0 x724D9DB9L,
0 x1AC15BB4L,
0 xD39EB8FCL,
0 xED545578L,
0 x08FCA5B5L,
0 xD83D7CD3L,
0 x4DAD0FC4L,
0 x1E50EF5EL,
0 xB161E6F8L,
0 xA28514D9L,
0 x6C51133CL,
0 x6FD5C7E7L,
0 x56E14EC4L,
0 x362ABFCEL,
0 xDDC6C837L,
0 xD79A3234L,
0 x92638212L,
0 x670EFA8EL,
0 x406000E0L
},
/* S[3] */
{
0 x3A39CE37L,
0 xD3FAF5CFL,
0 xABC27737L,
0 x5AC52D1BL,
0 x5CB0679EL,
0 x4FA33742L,
0 xD3822740L,
0 x99BC9BBEL,
0 xD5118E9DL,
0 xBF0F7315L,
0 xD62D1C7EL,
0 xC700C47BL,
0 xB78C1B6BL,
0 x21A19045L,
0 xB26EB1BEL,
0 x6A366EB4L,
0 x5748AB2FL,
0 xBC946E79L,
0 xC6A376D2L,
0 x6549C2C8L,
0 x530FF8EEL,
0 x468DDE7DL,
0 xD5730A1DL,
0 x4CD04DC6L,
0 x2939BBDBL,
0 xA9BA4650L,
0 xAC9526E8L,
0 xBE5EE304L,
0 xA1FAD5F0L,
0 x6A2D519AL,
0 x63EF8CE2L,
0 x9A86EE22L,
0 xC089C2B8L,
0 x43242EF6L,
0 xA51E03AAL,
0 x9CF2D0A4L,
0 x83C061BAL,
0 x9BE96A4DL,
0 x8FE51550L,
0 xBA645BD6L,
0 x2826A2F9L,
0 xA73A3AE1L,
0 x4BA99586L,
0 xEF5562E9L,
0 xC72FEFD3L,
0 xF752F7DAL,
0 x3F046F69L,
0 x77FA0A59L,
0 x80E4A915L,
0 x87B08601L,
0 x9B09E6ADL,
0 x3B3EE593L,
0 xE990FD5AL,
0 x9E34D797L,
0 x2CF0B7D9L,
0 x022B8B51L,
0 x96D5AC3AL,
0 x017DA67DL,
0 xD1CF3ED6L,
0 x7C7D2D28L,
0 x1F9F25CFL,
0 xADF2B89BL,
0 x5AD6B472L,
0 x5A88F54CL,
0 xE029AC71L,
0 xE019A5E6L,
0 x47B0ACFDL,
0 xED93FA9BL,
0 xE8D3C48DL,
0 x283B57CCL,
0 xF8D56629L,
0 x79132E28L,
0 x785F0191L,
0 xED756055L,
0 xF7960E44L,
0 xE3D35E8CL,
0 x15056DD4L,
0 x88F46DBAL,
0 x03A16125L,
0 x0564F0BDL,
0 xC3EB9E15L,
0 x3C9057A2L,
0 x97271AECL,
0 xA93A072AL,
0 x1B3F6D9BL,
0 x1E6321F5L,
0 xF59C66FBL,
0 x26DCF319L,
0 x7533D928L,
0 xB155FDF5L,
0 x03563482L,
0 x8ABA3CBBL,
0 x28517711L,
0 xC20AD9F8L,
0 xABCC5167L,
0 xCCAD925FL,
0 x4DE81751L,
0 x3830DC8EL,
0 x379D5862L,
0 x9320F991L,
0 xEA7A90C2L,
0 xFB3E7BCEL,
0 x5121CE64L,
0 x774FBE32L,
0 xA8B6E37EL,
0 xC3293D46L,
0 x48DE5369L,
0 x6413E680L,
0 xA2AE0810L,
0 xDD6DB224L,
0 x69852DFDL,
0 x09072166L,
0 xB39A460AL,
0 x6445C0DDL,
0 x586CDECFL,
0 x1C20C8AEL,
0 x5BBEF7DDL,
0 x1B588D40L,
0 xCCD2017FL,
0 x6BB4E3BBL,
0 xDDA26A7EL,
0 x3A59FF45L,
0 x3E350A44L,
0 xBCB4CDD5L,
0 x72EACEA8L,
0 xFA6484BBL,
0 x8D6612AEL,
0 xBF3C6F47L,
0 xD29BE463L,
0 x542F5D9EL,
0 xAEC2771BL,
0 xF64E6370L,
0 x740E0D8DL,
0 xE75B1357L,
0 xF8721671L,
0 xAF537D5DL,
0 x4040CB08L,
0 x4EB4E2CCL,
0 x34D2466AL,
0 x0115AF84L,
0 xE1B00428L,
0 x95983A1DL,
0 x06B89FB4L,
0 xCE6EA048L,
0 x6F3F3B82L,
0 x3520AB82L,
0 x011A1D4BL,
0 x277227F8L,
0 x611560B1L,
0 xE7933FDCL,
0 xBB3A792BL,
0 x344525BDL,
0 xA08839E1L,
0 x51CE794BL,
0 x2F32C9B7L,
0 xA01FBAC9L,
0 xE01CC87EL,
0 xBCC7D1F6L,
0 xCF0111C3L,
0 xA1E8AAC7L,
0 x1A908749L,
0 xD44FBD9AL,
0 xD0DADECBL,
0 xD50ADA38L,
0 x0339C32AL,
0 xC6913667L,
0 x8DF9317CL,
0 xE0B12B4FL,
0 xF79E59B7L,
0 x43F5BB3AL,
0 xF2D519FFL,
0 x27D9459CL,
0 xBF97222CL,
0 x15E6FC2AL,
0 x0F91FC71L,
0 x9B941525L,
0 xFAE59361L,
0 xCEB69CEBL,
0 xC2A86459L,
0 x12BAA8D1L,
0 xB6C1075EL,
0 xE3056A0CL,
0 x10D25065L,
0 xCB03A442L,
0 xE0EC6E0EL,
0 x1698DB3BL,
0 x4C98A0BEL,
0 x3278E964L,
0 x9F1F9532L,
0 xE0D392DFL,
0 xD3A0342BL,
0 x8971F21EL,
0 x1B0A7441L,
0 x4BA3348CL,
0 xC5BE7120L,
0 xC37632D8L,
0 xDF359F8DL,
0 x9B992F2EL,
0 xE60B6F47L,
0 x0FE3F11DL,
0 xE54CDA54L,
0 x1EDAD891L,
0 xCE6279CFL,
0 xCD3E7E6FL,
0 x1618B166L,
0 xFD2C1D05L,
0 x848FD2C5L,
0 xF6FB2299L,
0 xF523F357L,
0 xA6327623L,
0 x93A83531L,
0 x56CCCD02L,
0 xACF08162L,
0 x5A75EBB5L,
0 x6E163697L,
0 x88D273CCL,
0 xDE966292L,
0 x81B949D0L,
0 x4C50901BL,
0 x71C65614L,
0 xE6C6C7BDL,
0 x327A140AL,
0 x45E1D006L,
0 xC3F27B9AL,
0 xC9AA53FDL,
0 x62A80F00L,
0 xBB25BFE2L,
0 x35BDD2F6L,
0 x71126905L,
0 xB2040222L,
0 xB6CBCF7CL,
0 xCD769C2BL,
0 x53113EC0L,
0 x1640E3D3L,
0 x38ABBD60L,
0 x2547ADF0L,
0 xBA38209CL,
0 xF746CE76L,
0 x77AFA1C5L,
0 x20756060L,
0 x85CBFE4EL,
0 x8AE88DD8L,
0 x7AAAF9B0L,
0 x4CF9AA7EL,
0 x1948C25CL,
0 x02FB8A8CL,
0 x01C36AE4L,
0 xD6EBE1F9L,
0 x90D4F869L,
0 xA65CDEA0L,
0 x3F09252DL,
0 xC208E69FL,
0 xB74E6132L,
0 xCE77E25BL,
0 x578FDFE3L,
0 x3AC372E6L
}
},
/* P */
{
0 x243F6A88L,
0 x85A308D3L,
0 x13198A2EL,
0 x03707344L,
0 xA4093822L,
0 x299F31D0L,
0 x082EFA98L,
0 xEC4E6C89L,
0 x452821E6L,
0 x38D01377L,
0 xBE5466CFL,
0 x34E90C6CL,
0 xC0AC29B7L,
0 xC97C50DDL,
0 x3F84D5B5L,
0 xB5470917L,
0 x9216D5D9L,
0 x8979FB1BL
}
};
#endif
#if !
defined LIBO_CIPHER_OPENSSL_BACKEND
static rtlCipherError BF_init(
CipherContextBF *ctx,
rtlCipherMode eMode,
const sal_uInt8 *pKeyData, sal_Size nKeyLen,
const sal_uInt8 *pArgData, sal_Size nArgLen)
{
CipherKeyBF *key;
sal_uInt32 D, DL, DR;
sal_uInt16 i, j, k;
key = &(ctx->m_key);
memcpy(key, &BF_key,
sizeof (CipherKeyBF));
memset(&(ctx->m_iv),
0 ,
sizeof (ctx->m_iv));
ctx->m_offset =
0 ;
for (i =
0 , k =
0 ; i < CIPHER_ROUNDS_BF +
2 ; ++i)
{
D =
0 ;
for (j =
0 ; j <
4 ; ++j)
{
D = ((D <<
8 ) | pKeyData[k]);
k++;
if (k >= nKeyLen)
k =
0 ;
}
key->m_P[i] ^= D;
}
rtl_secureZeroMemory(&DL,
sizeof (DL));
rtl_secureZeroMemory(&DR,
sizeof (DR));
for (i =
0 ; i < CIPHER_ROUNDS_BF +
2 ; i +=
2 )
{
BF_encode(key, &DL, &DR);
key->m_P[i ] = DL;
key->m_P[i +
1 ] = DR;
}
for (i =
0 ; i <
4 ; ++i)
{
for (k =
0 ; k <
256 ; k +=
2 )
{
BF_encode(key, &DL, &DR);
key->m_S[i][k ] = DL;
key->m_S[i][k +
1 ] = DR;
}
}
if (pArgData && nArgLen)
{
nArgLen = std::min<sal_Size>(nArgLen,
8 );
if (eMode == rtl_Cipher_ModeStream)
{
memcpy(ctx->m_iv.m_byte, pArgData, nArgLen);
}
else
{
RTL_CIPHER_NTOHL64 (pArgData, DL, DR, nArgLen);
ctx->m_iv.m_long[
0 ] = DL;
ctx->m_iv.m_long[
1 ] = DR;
}
}
return rtl_Cipher_E_None;
}
#endif
static rtlCipherError BF_update(
CipherContextBF *ctx,
rtlCipherMode eMode,
rtlCipherDirection eDirection,
const sal_uInt8 *pData, sal_Size nDatLen,
sal_uInt8 *pBuffer, sal_Size nBufLen)
{
/* Check arguments. */
if (!pData || !pBuffer)
return rtl_Cipher_E_Argument;
if ((nDatLen <=
0 ) || (nDatLen > nBufLen))
return rtl_Cipher_E_BufferSize;
/* Update. */
#if defined LIBO_CIPHER_OPENSSL_BACKEND
assert(eMode == rtl_Cipher_ModeStream);
(
void ) eMode;
(
void ) eDirection;
while (nDatLen > o3tl::make_unsigned(std::numeric_limits<
int >::max())) {
int outl;
if (EVP_CipherUpdate(ctx->m_context, pBuffer, &outl, pData, std::numeric_limits<
int >::max
())
== 0 )
{
return rtl_Cipher_E_Unknown;
}
assert(outl == std::numeric_limits<int >::max());
pData += std::numeric_limits<int >::max();
nDatLen -= std::numeric_limits<int >::max();
pBuffer += std::numeric_limits<int >::max();
}
int outl;
if (EVP_CipherUpdate(ctx->m_context, pBuffer, &outl, pData, static_cast <int >(nDatLen)) == 0 )
{
return rtl_Cipher_E_Unknown;
}
assert(outl == static_cast <int >(nDatLen));
// A final call to EVP_CipherFinal_ex is intentionally missing; it wouldn't fit the rtl/cipher.h
// interface, and is hopefully not needed, as each individual Blowfish CFB update step doesn't
// hold back any data that would need to be finally flushed.
#else
if (eMode == rtl_Cipher_ModeECB)
{
/* Block mode. */
while (nDatLen > 8 )
{
BF_updateECB(ctx, eDirection, pData, pBuffer, 8 );
nDatLen -= 8 ;
pData += 8 ;
pBuffer += 8 ;
}
BF_updateECB(ctx, eDirection, pData, pBuffer, nDatLen);
}
else if (eMode == rtl_Cipher_ModeCBC)
{
/* Block mode. */
while (nDatLen > 8 )
{
BF_updateCBC (ctx, eDirection, pData, pBuffer, 8 );
nDatLen -= 8 ;
pData += 8 ;
pBuffer += 8 ;
}
BF_updateCBC (ctx, eDirection, pData, pBuffer, nDatLen);
}
else
{
/* Stream mode. */
while (nDatLen > 0 )
{
BF_updateCFB (ctx, eDirection, pData, pBuffer);
nDatLen -= 1 ;
pData += 1 ;
pBuffer += 1 ;
}
}
#endif
return rtl_Cipher_E_None;
}
#if !defined LIBO_CIPHER_OPENSSL_BACKEND
static void BF_updateECB(
CipherContextBF *ctx,
rtlCipherDirection direction,
const sal_uInt8 *pData,
sal_uInt8 *pBuffer,
sal_Size nLength)
{
CipherKeyBF *key;
sal_uInt32 DL, DR;
key = &(ctx->m_key);
if (direction == rtl_Cipher_DirectionEncode)
{
RTL_CIPHER_NTOHL64(pData, DL, DR, nLength);
BF_encode(key, &DL, &DR);
RTL_CIPHER_HTONL(DL, pBuffer);
RTL_CIPHER_HTONL(DR, pBuffer);
}
else
{
RTL_CIPHER_NTOHL(pData, DL);
RTL_CIPHER_NTOHL(pData, DR);
BF_decode(key, &DL, &DR);
RTL_CIPHER_HTONL64(DL, DR, pBuffer, nLength);
}
rtl_secureZeroMemory(&DL, sizeof (DL));
rtl_secureZeroMemory(&DR, sizeof (DR));
}
static void BF_updateCBC(
CipherContextBF *ctx,
rtlCipherDirection direction,
const sal_uInt8 *pData,
sal_uInt8 *pBuffer,
sal_Size nLength)
{
CipherKeyBF *key;
sal_uInt32 DL, DR;
key = &(ctx->m_key);
if (direction == rtl_Cipher_DirectionEncode)
{
RTL_CIPHER_NTOHL64(pData, DL, DR, nLength);
DL ^= ctx->m_iv.m_long[0 ];
DR ^= ctx->m_iv.m_long[1 ];
BF_encode(key, &DL, &DR);
ctx->m_iv.m_long[0 ] = DL;
ctx->m_iv.m_long[1 ] = DR;
RTL_CIPHER_HTONL(DL, pBuffer);
RTL_CIPHER_HTONL(DR, pBuffer);
}
else
{
sal_uInt32 IVL, IVR;
RTL_CIPHER_NTOHL(pData, DL);
RTL_CIPHER_NTOHL(pData, DR);
IVL = DL;
IVR = DR;
BF_decode(key, &DL, &DR);
DL ^= ctx->m_iv.m_long[0 ];
DR ^= ctx->m_iv.m_long[1 ];
ctx->m_iv.m_long[0 ] = IVL;
ctx->m_iv.m_long[1 ] = IVR;
RTL_CIPHER_HTONL64(DL, DR, pBuffer, nLength);
}
rtl_secureZeroMemory(&DL, sizeof (DL));
rtl_secureZeroMemory(&DR, sizeof (DR));
}
static void BF_updateCFB(
CipherContextBF *ctx,
rtlCipherDirection direction,
const sal_uInt8 *pData,
sal_uInt8 *pBuffer)
{
sal_uInt8 *iv;
sal_uInt32 k;
iv = ctx->m_iv.m_byte;
k = ctx->m_offset;
if (k == 0 )
{
sal_uInt32 IVL, IVR;
RTL_CIPHER_NTOHL64(iv, IVL, IVR, 8 );
BF_encode(&(ctx->m_key), &IVL, &IVR);
RTL_CIPHER_HTONL64(IVL, IVR, iv, 8 );
rtl_secureZeroMemory(&IVL, sizeof (IVL));
rtl_secureZeroMemory(&IVR, sizeof (IVR));
}
if (direction == rtl_Cipher_DirectionEncode)
{
iv[k] ^= *pData;
*pBuffer = iv[k];
}
else
{
sal_uInt8 c = iv[k];
iv[k] = *pData;
*pBuffer = *pData ^ c;
}
ctx->m_offset = ((k + 1 ) & 0 x07);
iv = nullptr;
}
static void BF_encode(
CipherKeyBF *key, sal_uInt32 *xl, sal_uInt32 *xr)
{
sal_uInt32 t, XL, XR;
sal_uInt16 i;
XL = *xl;
XR = *xr;
for (i = 0 ; i < CIPHER_ROUNDS_BF; ++i)
{
XL ^= key->m_P[i];
XR ^= BF (key, XL);
t = XL;
XL = XR;
XR = t;
}
t = XL;
XL = XR;
XR = t;
XR ^= key->m_P[CIPHER_ROUNDS_BF ];
XL ^= key->m_P[CIPHER_ROUNDS_BF + 1 ];
*xl = XL;
*xr = XR;
}
static void BF_decode(
CipherKeyBF *key, sal_uInt32 *xl, sal_uInt32 *xr)
{
sal_uInt32 t, XL, XR;
sal_uInt16 i;
XL = *xl;
XR = *xr;
for (i = CIPHER_ROUNDS_BF + 1 ; i > 1 ; --i)
{
XL ^= key->m_P[i];
XR ^= BF (key, XL);
t = XL;
XL = XR;
XR = t;
}
t = XL;
XL = XR;
XR = t;
XR ^= key->m_P[1 ];
XL ^= key->m_P[0 ];
*xl = XL;
*xr = XR;
}
static sal_uInt32 BF(CipherKeyBF *key, sal_uInt32 x)
{
sal_uInt16 a, b, c, d;
sal_uInt32 y;
d = static_cast <sal_uInt16>(x & 0 x00ff);
x >>= 8 ;
c = static_cast <sal_uInt16>(x & 0 x00ff);
x >>= 8 ;
b = static_cast <sal_uInt16>(x & 0 x00ff);
x >>= 8 ;
a = static_cast <sal_uInt16>(x & 0 x00ff);
y = key->m_S[0 ][a];
y += key->m_S[1 ][b];
y ^= key->m_S[2 ][c];
y += key->m_S[3 ][d];
return y;
}
#endif
/**
rtl_cipherBF (Blowfish) implementation.
Reference: Bruce Schneier: Applied Cryptography, 2nd edition, ch. 14.3
*/
rtlCipher SAL_CALL rtl_cipher_createBF(rtlCipherMode Mode) noexcept
{
CipherBF_Impl *pImpl = nullptr;
if (Mode == rtl_Cipher_ModeInvalid)
return nullptr;
#if defined LIBO_CIPHER_OPENSSL_BACKEND
if (Mode != rtl_Cipher_ModeStream) {
// Cannot easily support ModeECB and ModeCBC, and they aren't used in the LO code at least:
return nullptr;
}
#endif
pImpl = static_cast <CipherBF_Impl*>(rtl_allocateZeroMemory(sizeof (CipherBF_Impl)));
if (pImpl)
{
pImpl->m_cipher.m_algorithm = rtl_Cipher_AlgorithmBF;
pImpl->m_cipher.m_direction = rtl_Cipher_DirectionInvalid;
pImpl->m_cipher.m_mode = Mode;
pImpl->m_cipher.m_init = rtl_cipher_initBF;
pImpl->m_cipher.m_encode = rtl_cipher_encodeBF;
pImpl->m_cipher.m_decode = rtl_cipher_decodeBF;
pImpl->m_cipher.m_delete = rtl_cipher_destroyBF;
}
return static_cast <rtlCipher>(pImpl);
}
rtlCipherError SAL_CALL rtl_cipher_initBF(
rtlCipher Cipher,
rtlCipherDirection Direction,
const sal_uInt8 *pKeyData, sal_Size nKeyLen,
const sal_uInt8 *pArgData, sal_Size nArgLen) noexcept
{
CipherBF_Impl *pImpl = static_cast <CipherBF_Impl*>(Cipher);
if (!pImpl || !pKeyData)
return rtl_Cipher_E_Argument;
if (pImpl->m_cipher.m_algorithm != rtl_Cipher_AlgorithmBF)
return rtl_Cipher_E_Algorithm;
if (Direction != rtl_Cipher_DirectionInvalid)
pImpl->m_cipher.m_direction = Direction;
else
return rtl_Cipher_E_Direction;
#if defined LIBO_CIPHER_OPENSSL_BACKEND
if (pImpl->m_cipher.m_direction == rtl_Cipher_DirectionBoth) {
// Cannot easily support DirectionBoth, and it isn't used in the LO code at least:
return rtl_Cipher_E_Direction;
}
if (nKeyLen > o3tl::make_unsigned(std::numeric_limits<int >::max())) {
return rtl_Cipher_E_BufferSize;
}
if (pImpl->m_context.m_context != nullptr) {
EVP_CIPHER_CTX_free(pImpl->m_context.m_context);
}
pImpl->m_context.m_context = EVP_CIPHER_CTX_new();
if (pImpl->m_context.m_context == nullptr) {
return rtl_Cipher_E_Memory;
}
unsigned char iv[8 ];
auto const n = std::min(nArgLen, sal_Size(8 ));
std::memcpy(iv, pArgData, n);
std::memset(iv + n, 0 , 8 - n);
if (EVP_CipherInit_ex(
pImpl->m_context.m_context, EVP_bf_cfb(), nullptr, nullptr, iv,
pImpl->m_cipher.m_direction == rtl_Cipher_DirectionDecode ? 0 : 1 )
== 0 )
{
return rtl_Cipher_E_Unknown;
}
if (EVP_CIPHER_CTX_set_key_length(pImpl->m_context.m_context, static_cast <int >(nKeyLen)) == 0 ) {
return rtl_Cipher_E_Unknown;
}
if (EVP_CipherInit_ex(pImpl->m_context.m_context, nullptr, nullptr, pKeyData, nullptr, -1 ) == 0 )
{
return rtl_Cipher_E_Unknown;
}
return rtl_Cipher_E_None;
#else
return BF_init(
&(pImpl->m_context), pImpl->m_cipher.m_mode,
pKeyData, nKeyLen, pArgData, nArgLen);
#endif
}
rtlCipherError SAL_CALL rtl_cipher_encodeBF(
rtlCipher Cipher,
const void *pData, sal_Size nDatLen,
sal_uInt8 *pBuffer, sal_Size nBufLen) noexcept
{
CipherBF_Impl *pImpl = static_cast <CipherBF_Impl*>(Cipher);
if (!pImpl)
return rtl_Cipher_E_Argument;
if (pImpl->m_cipher.m_algorithm != rtl_Cipher_AlgorithmBF)
return rtl_Cipher_E_Algorithm;
if (pImpl->m_cipher.m_direction == rtl_Cipher_DirectionInvalid)
return rtl_Cipher_E_Direction;
if (pImpl->m_cipher.m_direction == rtl_Cipher_DirectionDecode)
return rtl_Cipher_E_Direction;
return BF_update(
&(pImpl->m_context), pImpl->m_cipher.m_mode,
rtl_Cipher_DirectionEncode,
static_cast <const sal_uInt8*>(pData), nDatLen, pBuffer, nBufLen);
}
rtlCipherError SAL_CALL rtl_cipher_decodeBF(
rtlCipher Cipher,
const void *pData, sal_Size nDatLen,
sal_uInt8 *pBuffer, sal_Size nBufLen) noexcept
{
CipherBF_Impl *pImpl = static_cast <CipherBF_Impl*>(Cipher);
if (!pImpl)
return rtl_Cipher_E_Argument;
if (pImpl->m_cipher.m_algorithm != rtl_Cipher_AlgorithmBF)
return rtl_Cipher_E_Algorithm;
if (pImpl->m_cipher.m_direction == rtl_Cipher_DirectionInvalid)
return rtl_Cipher_E_Direction;
if (pImpl->m_cipher.m_direction == rtl_Cipher_DirectionEncode)
return rtl_Cipher_E_Direction;
return BF_update(
&(pImpl->m_context), pImpl->m_cipher.m_mode,
rtl_Cipher_DirectionDecode,
static_cast <const sal_uInt8*>(pData), nDatLen, pBuffer, nBufLen);
}
void SAL_CALL rtl_cipher_destroyBF(rtlCipher Cipher) noexcept
{
CipherBF_Impl *pImpl = static_cast <CipherBF_Impl*>(Cipher);
if (!pImpl)
return ;
if (pImpl->m_cipher.m_algorithm == rtl_Cipher_AlgorithmBF)
{
#if defined LIBO_CIPHER_OPENSSL_BACKEND
if (pImpl->m_context.m_context != nullptr) {
EVP_CIPHER_CTX_free(pImpl->m_context.m_context);
}
#endif
rtl_freeZeroMemory(pImpl, sizeof (CipherBF_Impl));
}
else
free(pImpl);
}
#if !defined LIBO_CIPHER_OPENSSL_BACKEND
#define CIPHER_CBLOCK_ARCFOUR 256
#endif
namespace {
struct ContextARCFOUR_Impl
{
#if defined LIBO_CIPHER_OPENSSL_BACKEND
EVP_CIPHER_CTX * m_context;
#else
unsigned int m_S[CIPHER_CBLOCK_ARCFOUR];
unsigned int m_X, m_Y;
#endif
};
struct CipherARCFOUR_Impl
{
Cipher_Impl m_cipher;
ContextARCFOUR_Impl m_context;
};
}
static rtlCipherError rtl_cipherARCFOUR_update_Impl(
ContextARCFOUR_Impl *ctx,
const sal_uInt8 *pData, sal_Size nDatLen,
sal_uInt8 *pBuffer, sal_Size nBufLen);
static rtlCipherError rtl_cipherARCFOUR_init_Impl(
ContextARCFOUR_Impl *ctx,
const sal_uInt8 *pKeyData, sal_Size nKeyLen)
{
#if defined LIBO_CIPHER_OPENSSL_BACKEND
if (nKeyLen > o3tl::make_unsigned(std::numeric_limits<int >::max())) {
return rtl_Cipher_E_BufferSize;
}
if (ctx->m_context != nullptr) {
EVP_CIPHER_CTX_free(ctx->m_context);
}
ctx->m_context = EVP_CIPHER_CTX_new();
if (ctx->m_context == nullptr) {
return rtl_Cipher_E_Memory;
}
if (EVP_CipherInit_ex(ctx->m_context, EVP_rc4(), nullptr, nullptr, nullptr, 0 ) == 0 ) {
// RC4 en- and decryption is identical, so we can use 0=decrypt regardless of direction,
// and thus also support rtl_Cipher_DirectionBoth
return rtl_Cipher_E_Unknown;
}
if (EVP_CIPHER_CTX_set_key_length(ctx->m_context, static_cast <int >(nKeyLen)) == 0 ) {
return rtl_Cipher_E_Unknown;
}
if (EVP_CipherInit_ex(ctx->m_context, nullptr, nullptr, pKeyData, nullptr, -1 ) == 0 ) {
return rtl_Cipher_E_Unknown;
}
#else
unsigned int K[CIPHER_CBLOCK_ARCFOUR];
unsigned int *L, *S;
unsigned int x, y;
sal_Size n, k;
S = &(ctx->m_S[0 ]);
/* Initialize S linearly. */
for (x = 0 ; x < CIPHER_CBLOCK_ARCFOUR; x++)
S[x] = x;
/* Initialize K with key, repeat key as necessary. */
for (L = K, n = CIPHER_CBLOCK_ARCFOUR; n > nKeyLen; n -= nKeyLen)
{
for (k = 0 ; k < nKeyLen; k++)
{
L[k] = pKeyData[k];
}
L += nKeyLen;
}
for (k = 0 ; k < n; k++)
{
L[k] = pKeyData[k];
}
/* Initialize S with K. */
for (x = 0 , y = 0 ; x < CIPHER_CBLOCK_ARCFOUR; x++)
{
y = (y + S[x] + K[x]) % CIPHER_CBLOCK_ARCFOUR;
/* swap S[x] and S[y] */
unsigned int t = S[x];
S[x] = S[y];
S[y] = t;
}
/* Initialize counters X and Y. */
ctx->m_X = 0 ;
ctx->m_Y = 0 ;
#endif
return rtl_Cipher_E_None;
}
static rtlCipherError rtl_cipherARCFOUR_update_Impl(
ContextARCFOUR_Impl *ctx,
const sal_uInt8 *pData, sal_Size nDatLen,
sal_uInt8 *pBuffer, sal_Size nBufLen)
{
/* Check arguments. */
if (!pData || !pBuffer)
return rtl_Cipher_E_Argument;
if ((0 >= nDatLen) || (nDatLen > nBufLen))
return rtl_Cipher_E_BufferSize;
#if defined LIBO_CIPHER_OPENSSL_BACKEND
while (nDatLen > o3tl::make_unsigned(std::numeric_limits<int >::max())) {
int outl;
if (EVP_CipherUpdate(ctx->m_context, pBuffer, &outl, pData, std::numeric_limits<int >::max())
== 0 )
{
return rtl_Cipher_E_Unknown;
}
assert(outl == std::numeric_limits<int >::max());
pData += std::numeric_limits<int >::max();
nDatLen -= std::numeric_limits<int >::max();
pBuffer += std::numeric_limits<int >::max();
}
int outl;
if (EVP_CipherUpdate(ctx->m_context, pBuffer, &outl, pData, static_cast <int >(nDatLen)) == 0 ) {
return rtl_Cipher_E_Unknown;
}
assert(outl == static_cast <int >(nDatLen));
// A final call to EVP_CipherFinal_ex is intentionally missing; it wouldn't fit the rtl/cipher.h
// interface, and is hopefully not needed, as each individual RC4 update step doesn't hold back
// any data that would need to be finally flushed.
#else
unsigned int *S;
sal_Size k;
/* Update. */
S = &(ctx->m_S[0 ]);
for (k = 0 ; k < nDatLen; k++)
{
/* Update counters X and Y. */
unsigned int x = ctx->m_X;
unsigned int y = ctx->m_Y;
x = (x + 1 ) % CIPHER_CBLOCK_ARCFOUR;
y = (y + S[x]) % CIPHER_CBLOCK_ARCFOUR;
ctx->m_X = x;
ctx->m_Y = y;
/* Swap S[x] and S[y]. */
unsigned int t = S[x];
S[x] = S[y];
S[y] = t;
/* Evaluate next key byte S[t]. */
t = (S[x] + S[y]) % CIPHER_CBLOCK_ARCFOUR;
pBuffer[k] = pData[k] ^ static_cast <sal_uInt8>(S[t] & 0 xff);
}
#endif
return rtl_Cipher_E_None;
}
/**
rtl_cipher_ARCFOUR (RC4) implementation.
Reference: Bruce Schneier: Applied Cryptography, 2nd edition, ch. 17.1
*/
rtlCipher SAL_CALL rtl_cipher_createARCFOUR(rtlCipherMode Mode) noexcept
{
CipherARCFOUR_Impl *pImpl = nullptr;
if (Mode != rtl_Cipher_ModeStream)
return nullptr;
pImpl = static_cast <CipherARCFOUR_Impl*>(rtl_allocateZeroMemory(sizeof (CipherARCFOUR_Impl)));
if (pImpl)
{
pImpl->m_cipher.m_algorithm = rtl_Cipher_AlgorithmARCFOUR;
pImpl->m_cipher.m_direction = rtl_Cipher_DirectionInvalid;
pImpl->m_cipher.m_mode = rtl_Cipher_ModeStream;
pImpl->m_cipher.m_init = rtl_cipher_initARCFOUR;
pImpl->m_cipher.m_encode = rtl_cipher_encodeARCFOUR;
pImpl->m_cipher.m_decode = rtl_cipher_decodeARCFOUR;
pImpl->m_cipher.m_delete = rtl_cipher_destroyARCFOUR;
}
return static_cast <rtlCipher>(pImpl);
}
rtlCipherError SAL_CALL rtl_cipher_initARCFOUR(
rtlCipher Cipher,
rtlCipherDirection Direction,
const sal_uInt8 *pKeyData, sal_Size nKeyLen,
SAL_UNUSED_PARAMETER const sal_uInt8 *, SAL_UNUSED_PARAMETER sal_Size) noexcept
{
CipherARCFOUR_Impl *pImpl = static_cast <CipherARCFOUR_Impl*>(Cipher);
if (!pImpl || !pKeyData)
return rtl_Cipher_E_Argument;
if (pImpl->m_cipher.m_algorithm != rtl_Cipher_AlgorithmARCFOUR)
return rtl_Cipher_E_Algorithm;
if (Direction != rtl_Cipher_DirectionInvalid)
pImpl->m_cipher.m_direction = Direction;
else
return rtl_Cipher_E_Direction;
return rtl_cipherARCFOUR_init_Impl(&(pImpl->m_context), pKeyData, nKeyLen);
}
rtlCipherError SAL_CALL rtl_cipher_encodeARCFOUR(
rtlCipher Cipher,
const void *pData, sal_Size nDatLen,
sal_uInt8 *pBuffer, sal_Size nBufLen) noexcept
{
CipherARCFOUR_Impl *pImpl = static_cast <CipherARCFOUR_Impl*>(Cipher);
if (!pImpl)
return rtl_Cipher_E_Argument;
if (pImpl->m_cipher.m_algorithm != rtl_Cipher_AlgorithmARCFOUR)
return rtl_Cipher_E_Algorithm;
if (pImpl->m_cipher.m_direction == rtl_Cipher_DirectionInvalid)
return rtl_Cipher_E_Direction;
return rtl_cipherARCFOUR_update_Impl(
&(pImpl->m_context),
static_cast <const sal_uInt8*>(pData), nDatLen, pBuffer, nBufLen);
}
rtlCipherError SAL_CALL rtl_cipher_decodeARCFOUR(
rtlCipher Cipher,
const void *pData, sal_Size nDatLen,
sal_uInt8 *pBuffer, sal_Size nBufLen) noexcept
{
CipherARCFOUR_Impl *pImpl = static_cast <CipherARCFOUR_Impl*>(Cipher);
if (!pImpl)
return rtl_Cipher_E_Argument;
if (pImpl->m_cipher.m_algorithm != rtl_Cipher_AlgorithmARCFOUR)
return rtl_Cipher_E_Algorithm;
if (pImpl->m_cipher.m_direction == rtl_Cipher_DirectionInvalid)
return rtl_Cipher_E_Direction;
return rtl_cipherARCFOUR_update_Impl(
&(pImpl->m_context),
static_cast <const sal_uInt8*>(pData), nDatLen, pBuffer, nBufLen);
}
void SAL_CALL rtl_cipher_destroyARCFOUR(rtlCipher Cipher) noexcept
{
CipherARCFOUR_Impl *pImpl = static_cast <CipherARCFOUR_Impl*>(Cipher);
if (!pImpl)
return ;
if (pImpl->m_cipher.m_algorithm == rtl_Cipher_AlgorithmARCFOUR)
{
#if defined LIBO_CIPHER_OPENSSL_BACKEND
if (pImpl->m_context.m_context != nullptr) {
EVP_CIPHER_CTX_free(pImpl->m_context.m_context);
}
#endif
rtl_freeZeroMemory(pImpl, sizeof (CipherARCFOUR_Impl));
}
else
free(pImpl);
}
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
Messung V0.5 in Prozent C=93 H=92 G=92
¤ Dauer der Verarbeitung: 0.21 Sekunden
(vorverarbeitet am 2026-06-06)
¤
*© Formatika GbR, Deutschland