/**************************************************************
 *
 * 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
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied.  See the License for the
 * specific language governing permissions and limitations
 * under the License.
 *
 *************************************************************/



#include "oox/core/binarycodec.hxx"

#include <algorithm>
#include <string.h>
#include "oox/helper/attributelist.hxx"

#include <comphelper/sequenceashashmap.hxx>
#include <comphelper/docpasswordhelper.hxx>

using namespace ::com::sun::star;

namespace oox {
namespace core {

// ============================================================================

namespace {

/** Rotates rnValue left by nBits bits. */
template< typename Type >
inline void lclRotateLeft( Type& rnValue, size_t nBits )
{
    OSL_ENSURE( nBits < sizeof( Type ) * 8, "lclRotateLeft - rotation count overflow" );
    rnValue = static_cast< Type >( (rnValue << nBits) | (rnValue >> (sizeof( Type ) * 8 - nBits)) );
}

/** Rotates the lower nWidth bits of rnValue left by nBits bits. */
template< typename Type >
inline void lclRotateLeft( Type& rnValue, size_t nBits, size_t nWidth )
{
    OSL_ENSURE( (nBits < nWidth) && (nWidth < sizeof( Type ) * 8), "lclRotateLeft - rotation count overflow" );
    Type nMask = static_cast< Type >( (1UL << nWidth) - 1 );
    rnValue = static_cast< Type >(
        ((rnValue << nBits) | ((rnValue & nMask) >> (nWidth - nBits))) & nMask );
}

sal_Int32 lclGetLen( const sal_uInt8* pnPassData, sal_Int32 nBufferSize )
{
    sal_Int32 nLen = 0;
    while( (nLen < nBufferSize) && pnPassData[ nLen ] ) ++nLen;
    return nLen;
}

sal_uInt16 lclGetKey( const sal_uInt8* pnPassData, sal_Int32 nBufferSize )
{
    sal_Int32 nLen = lclGetLen( pnPassData, nBufferSize );
    if( nLen <= 0 ) return 0;

    sal_uInt16 nKey = 0;
    sal_uInt16 nKeyBase = 0x8000;
    sal_uInt16 nKeyEnd = 0xFFFF;
    const sal_uInt8* pnChar = pnPassData + nLen - 1;
    for( sal_Int32 nIndex = 0; nIndex < nLen; ++nIndex, --pnChar )
    {
        sal_uInt8 cChar = *pnChar & 0x7F;
        for( size_t nBit = 0; nBit < 8; ++nBit )
        {
            lclRotateLeft( nKeyBase, 1 );
            if( nKeyBase & 1 ) nKeyBase ^= 0x1020;
            if( cChar & 1 ) nKey ^= nKeyBase;
            cChar >>= 1;
            lclRotateLeft( nKeyEnd, 1 );
            if( nKeyEnd & 1 ) nKeyEnd ^= 0x1020;
        }
    }
    return nKey ^ nKeyEnd;
}

sal_uInt16 lclGetHash( const sal_uInt8* pnPassData, sal_Int32 nBufferSize )
{
    sal_Int32 nLen = lclGetLen( pnPassData, nBufferSize );

    sal_uInt16 nHash = static_cast< sal_uInt16 >( nLen );
    if( nLen > 0 )
        nHash ^= 0xCE4B;

    const sal_uInt8* pnChar = pnPassData;
    for( sal_Int32 nIndex = 0; nIndex < nLen; ++nIndex, ++pnChar )
    {
        sal_uInt16 cChar = *pnChar;
        size_t nRot = static_cast< size_t >( (nIndex + 1) % 15 );
        lclRotateLeft( cChar, nRot, 15 );
        nHash ^= cChar;
    }
    return nHash;
}

} // namespace

// ============================================================================

/*static*/ sal_uInt16 CodecHelper::getPasswordHash( const AttributeList& rAttribs, sal_Int32 nElement )
{
    sal_Int32 nPasswordHash = rAttribs.getIntegerHex( nElement, 0 );
    OSL_ENSURE( (0 <= nPasswordHash) && (nPasswordHash <= SAL_MAX_UINT16), "CodecHelper::getPasswordHash - invalid password hash" );
    return static_cast< sal_uInt16 >( ((0 <= nPasswordHash) && (nPasswordHash <= SAL_MAX_UINT16)) ? nPasswordHash : 0 );
}

// ============================================================================

BinaryCodec_XOR::BinaryCodec_XOR( CodecType eCodecType ) :
    meCodecType( eCodecType ),
    mnOffset( 0 ),
    mnBaseKey( 0 ),
    mnHash( 0 )
{
    (void)memset( mpnKey, 0, sizeof( mpnKey ) );
}

BinaryCodec_XOR::~BinaryCodec_XOR()
{
    (void)memset( mpnKey, 0, sizeof( mpnKey ) );
    mnBaseKey = mnHash = 0;
}

void BinaryCodec_XOR::initKey( const sal_uInt8 pnPassData[ 16 ] )
{
    // calculate base key and hash from passed password
    mnBaseKey = lclGetKey( pnPassData, 16 );
    mnHash = lclGetHash( pnPassData, 16 );

     static const sal_uInt8 spnFillChars[] =
    {
        0xBB, 0xFF, 0xFF, 0xBA,
        0xFF, 0xFF, 0xB9, 0x80,
        0x00, 0xBE, 0x0F, 0x00,
        0xBF, 0x0F, 0x00
    };

    (void)memcpy( mpnKey, pnPassData, 16 );
    sal_Int32 nIndex;
    sal_Int32 nLen = lclGetLen( pnPassData, 16 );
    const sal_uInt8* pnFillChar = spnFillChars;
    for( nIndex = nLen; nIndex < static_cast< sal_Int32 >( sizeof( mpnKey ) ); ++nIndex, ++pnFillChar )
        mpnKey[ nIndex ] = *pnFillChar;

    // rotation of key values is application dependent
    size_t nRotateSize = 0;
    switch( meCodecType )
    {
        case CODEC_WORD:    nRotateSize = 7;    break;
        case CODEC_EXCEL:   nRotateSize = 2;    break;
        // compiler will warn, if new codec type is introduced and not handled here
    }

    // use little-endian base key to create key array
    sal_uInt8 pnBaseKeyLE[ 2 ];
    pnBaseKeyLE[ 0 ] = static_cast< sal_uInt8 >( mnBaseKey );
    pnBaseKeyLE[ 1 ] = static_cast< sal_uInt8 >( mnBaseKey >> 8 );
    sal_uInt8* pnKeyChar = mpnKey;
    for( nIndex = 0; nIndex < static_cast< sal_Int32 >( sizeof( mpnKey ) ); ++nIndex, ++pnKeyChar )
    {
        *pnKeyChar ^= pnBaseKeyLE[ nIndex & 1 ];
        lclRotateLeft( *pnKeyChar, nRotateSize );
    }
}

bool BinaryCodec_XOR::initCodec( const uno::Sequence< beans::NamedValue >& aData )
{
    bool bResult = sal_False;

    ::comphelper::SequenceAsHashMap aHashData( aData );
    uno::Sequence< sal_Int8 > aKey = aHashData.getUnpackedValueOrDefault( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "XOR95EncryptionKey" ) ), uno::Sequence< sal_Int8 >() );

    if ( aKey.getLength() == 16 )
    {
        (void)memcpy( mpnKey, aKey.getConstArray(), 16 );
        bResult = sal_True;

        mnBaseKey = (sal_uInt16)aHashData.getUnpackedValueOrDefault( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "XOR95BaseKey" ) ), (sal_Int16)0 );
        mnHash = (sal_uInt16)aHashData.getUnpackedValueOrDefault( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "XOR95PasswordHash" ) ), (sal_Int16)0 );
    }
    else
        OSL_ENSURE( sal_False, "Unexpected key size!\n" );

    return bResult;
}

uno::Sequence< beans::NamedValue > BinaryCodec_XOR::getEncryptionData()
{
    ::comphelper::SequenceAsHashMap aHashData;
    aHashData[ ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "XOR95EncryptionKey" ) ) ] <<= uno::Sequence<sal_Int8>( (sal_Int8*)mpnKey, 16 );
    aHashData[ ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "XOR95BaseKey" ) ) ] <<= (sal_Int16)mnBaseKey;
    aHashData[ ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "XOR95PasswordHash" ) ) ] <<= (sal_Int16)mnHash;

    return aHashData.getAsConstNamedValueList();
}

bool BinaryCodec_XOR::verifyKey( sal_uInt16 nKey, sal_uInt16 nHash ) const
{
    return (nKey == mnBaseKey) && (nHash == mnHash);
}

void BinaryCodec_XOR::startBlock()
{
    mnOffset = 0;
}

bool BinaryCodec_XOR::decode( sal_uInt8* pnDestData, const sal_uInt8* pnSrcData, sal_Int32 nBytes )
{
    const sal_uInt8* pnCurrKey = mpnKey + mnOffset;
    const sal_uInt8* pnKeyLast = mpnKey + 0x0F;

    // switch/case outside of the for loop (performance)
    const sal_uInt8* pnSrcDataEnd = pnSrcData + nBytes;
    switch( meCodecType )
    {
        case CODEC_WORD:
        {
            for( ; pnSrcData < pnSrcDataEnd; ++pnSrcData, ++pnDestData )
            {
                sal_uInt8 nData = *pnSrcData ^ *pnCurrKey;
                if( (*pnSrcData != 0) && (nData != 0) )
                    *pnDestData = nData;
                if( pnCurrKey < pnKeyLast ) ++pnCurrKey; else pnCurrKey = mpnKey;
            }
        }
        break;
        case CODEC_EXCEL:
        {
            for( ; pnSrcData < pnSrcDataEnd; ++pnSrcData, ++pnDestData )
            {
                *pnDestData = *pnSrcData;
                lclRotateLeft( *pnDestData, 3 );
                *pnDestData ^= *pnCurrKey;
                if( pnCurrKey < pnKeyLast ) ++pnCurrKey; else pnCurrKey = mpnKey;
            }
        }
        break;
        // compiler will warn, if new codec type is introduced and not handled here
    }

    // update offset and leave
    return skip( nBytes );
}

bool BinaryCodec_XOR::skip( sal_Int32 nBytes )
{
    mnOffset = static_cast< sal_Int32 >( (mnOffset + nBytes) & 0x0F );
    return true;
}

// ============================================================================

BinaryCodec_RCF::BinaryCodec_RCF()
{
    mhCipher = rtl_cipher_create( rtl_Cipher_AlgorithmARCFOUR, rtl_Cipher_ModeStream );
    OSL_ENSURE( mhCipher != 0, "BinaryCodec_RCF::BinaryCodec_RCF - cannot create cipher" );

    mhDigest = rtl_digest_create( rtl_Digest_AlgorithmMD5 );
    OSL_ENSURE( mhDigest != 0, "BinaryCodec_RCF::BinaryCodec_RCF - cannot create digest" );

    (void)memset( mpnDigestValue, 0, sizeof( mpnDigestValue ) );
    (void)memset (mpnUnique, 0, sizeof(mpnUnique));
}

BinaryCodec_RCF::~BinaryCodec_RCF()
{
    (void)memset( mpnDigestValue, 0, sizeof( mpnDigestValue ) );
    (void)memset (mpnUnique, 0, sizeof(mpnUnique));
    rtl_digest_destroy( mhDigest );
    rtl_cipher_destroy( mhCipher );
}

bool BinaryCodec_RCF::initCodec( const uno::Sequence< beans::NamedValue >& aData )
{
    bool bResult = sal_False;

    ::comphelper::SequenceAsHashMap aHashData( aData );
    uno::Sequence< sal_Int8 > aKey = aHashData.getUnpackedValueOrDefault( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "STD97EncryptionKey" ) ), uno::Sequence< sal_Int8 >() );

    if ( aKey.getLength() == RTL_DIGEST_LENGTH_MD5 )
    {
        (void)memcpy( mpnDigestValue, aKey.getConstArray(), RTL_DIGEST_LENGTH_MD5 );
        uno::Sequence< sal_Int8 > aUniqueID = aHashData.getUnpackedValueOrDefault( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "STD97UniqueID" ) ), uno::Sequence< sal_Int8 >() );
        if ( aUniqueID.getLength() == 16 )
        {
            (void)memcpy( mpnUnique, aUniqueID.getConstArray(), 16 );
            bResult = sal_False;
        }
        else
            OSL_ENSURE( sal_False, "Unexpected document ID!\n" );
    }
    else
        OSL_ENSURE( sal_False, "Unexpected key size!\n" );

    return bResult;
}

uno::Sequence< beans::NamedValue > BinaryCodec_RCF::getEncryptionData()
{
    ::comphelper::SequenceAsHashMap aHashData;
    aHashData[ ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "STD97EncryptionKey" ) ) ] <<= uno::Sequence< sal_Int8 >( (sal_Int8*)mpnDigestValue, RTL_DIGEST_LENGTH_MD5 );
    aHashData[ ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "STD97UniqueID" ) ) ] <<= uno::Sequence< sal_Int8 >( (sal_Int8*)mpnUnique, 16 );

    return aHashData.getAsConstNamedValueList();
}

void BinaryCodec_RCF::initKey( const sal_uInt16 pnPassData[ 16 ], const sal_uInt8 pnSalt[ 16 ] )
{
    uno::Sequence< sal_Int8 > aKey = ::comphelper::DocPasswordHelper::GenerateStd97Key( pnPassData, uno::Sequence< sal_Int8 >( (sal_Int8*)pnSalt, 16 ) );
    // Fill raw digest of above updates into DigestValue.

    if ( aKey.getLength() == sizeof(mpnDigestValue) )
        (void)memcpy ( mpnDigestValue, (const sal_uInt8*)aKey.getConstArray(), sizeof(mpnDigestValue) );
    else
        memset( mpnDigestValue, 0, sizeof(mpnDigestValue) );

    (void)memcpy( mpnUnique, pnSalt, 16 );
}

bool BinaryCodec_RCF::verifyKey( const sal_uInt8 pnVerifier[ 16 ], const sal_uInt8 pnVerifierHash[ 16 ] )
{
    if( !startBlock( 0 ) )
        return false;

    sal_uInt8 pnDigest[ RTL_DIGEST_LENGTH_MD5 ];
    sal_uInt8 pnBuffer[ 64 ];

    // decode salt data into buffer
    rtl_cipher_decode( mhCipher, pnVerifier, 16, pnBuffer, sizeof( pnBuffer ) );

    pnBuffer[ 16 ] = 0x80;
    (void)memset( pnBuffer + 17, 0, sizeof( pnBuffer ) - 17 );
    pnBuffer[ 56 ] = 0x80;

    // fill raw digest of buffer into digest
    rtl_digest_updateMD5( mhDigest, pnBuffer, sizeof( pnBuffer ) );
    rtl_digest_rawMD5( mhDigest, pnDigest, sizeof( pnDigest ) );

    // decode original salt digest into buffer
    rtl_cipher_decode( mhCipher, pnVerifierHash, 16, pnBuffer, sizeof( pnBuffer ) );

    // compare buffer with computed digest
    bool bResult = memcmp( pnBuffer, pnDigest, sizeof( pnDigest ) ) == 0;

    // erase buffer and digest arrays and leave
    (void)memset( pnBuffer, 0, sizeof( pnBuffer ) );
    (void)memset( pnDigest, 0, sizeof( pnDigest ) );
    return bResult;
}

bool BinaryCodec_RCF::startBlock( sal_Int32 nCounter )
{
    // initialize key data array
    sal_uInt8 pnKeyData[ 64 ];
    (void)memset( pnKeyData, 0, sizeof( pnKeyData ) );

    // fill 40 bit of digest value into [0..4]
    (void)memcpy( pnKeyData, mpnDigestValue, 5 );

    // fill little-endian counter into [5..8], static_cast masks out unneeded bits
    pnKeyData[ 5 ] = static_cast< sal_uInt8 >( nCounter );
    pnKeyData[ 6 ] = static_cast< sal_uInt8 >( nCounter >> 8 );
    pnKeyData[ 7 ] = static_cast< sal_uInt8 >( nCounter >> 16 );
    pnKeyData[ 8 ] = static_cast< sal_uInt8 >( nCounter >> 24 );

    pnKeyData[ 9 ] = 0x80;
    pnKeyData[ 56 ] = 0x48;

    // fill raw digest of key data into key data
    (void)rtl_digest_updateMD5( mhDigest, pnKeyData, sizeof( pnKeyData ) );
    (void)rtl_digest_rawMD5( mhDigest, pnKeyData, RTL_DIGEST_LENGTH_MD5 );

    // initialize cipher with key data (for decoding)
    rtlCipherError eResult =
        rtl_cipher_init( mhCipher, rtl_Cipher_DirectionDecode, pnKeyData, RTL_DIGEST_LENGTH_MD5, 0, 0 );

    // rrase key data array and leave
    (void)memset( pnKeyData, 0, sizeof( pnKeyData ) );
    return eResult == rtl_Cipher_E_None;
}

bool BinaryCodec_RCF::decode( sal_uInt8* pnDestData, const sal_uInt8* pnSrcData, sal_Int32 nBytes )
{
    rtlCipherError eResult = rtl_cipher_decode( mhCipher,
        pnSrcData, static_cast< sal_Size >( nBytes ),
        pnDestData, static_cast< sal_Size >( nBytes ) );
    return eResult == rtl_Cipher_E_None;
}

bool BinaryCodec_RCF::skip( sal_Int32 nBytes )
{
    // decode dummy data in memory to update internal state of RC4 cipher
    sal_uInt8 pnDummy[ 1024 ];
    sal_Int32 nBytesLeft = nBytes;
    bool bResult = true;
    while( bResult && (nBytesLeft > 0) )
    {
        sal_Int32 nBlockLen = ::std::min( nBytesLeft, static_cast< sal_Int32 >( sizeof( pnDummy ) ) );
        bResult = decode( pnDummy, pnDummy, nBlockLen );
        nBytesLeft -= nBlockLen;
    }
    return bResult;
}

// ============================================================================

} // namespace core
} // namespace oox
