summaryrefslogtreecommitdiff
path: root/vcl/source/gdi/pdfwriter_impl2.cxx
diff options
context:
space:
mode:
Diffstat (limited to 'vcl/source/gdi/pdfwriter_impl2.cxx')
-rw-r--r--vcl/source/gdi/pdfwriter_impl2.cxx507
1 files changed, 506 insertions, 1 deletions
diff --git a/vcl/source/gdi/pdfwriter_impl2.cxx b/vcl/source/gdi/pdfwriter_impl2.cxx
index c01b8a9771d8..ee1fe1cc6bc5 100644
--- a/vcl/source/gdi/pdfwriter_impl2.cxx
+++ b/vcl/source/gdi/pdfwriter_impl2.cxx
@@ -28,6 +28,7 @@
#include "precompiled_vcl.hxx"
#include "pdfwriter_impl.hxx"
+
#include "vcl/pdfextoutdevdata.hxx"
#include "vcl/virdev.hxx"
#include "vcl/gdimtf.hxx"
@@ -36,12 +37,16 @@
#include "vcl/svdata.hxx"
#include "unotools/streamwrap.hxx"
#include "unotools/processfactory.hxx"
-
#include "comphelper/processfactory.hxx"
+
#include "com/sun/star/beans/PropertyValue.hpp"
#include "com/sun/star/io/XSeekable.hpp"
#include "com/sun/star/graphic/XGraphicProvider.hpp"
+#include "cppuhelper/implbase1.hxx"
+
+#include <rtl/digest.h>
+
using namespace vcl;
using namespace rtl;
using namespace com::sun::star;
@@ -1032,4 +1037,504 @@ void PDFWriterImpl::playMetafile( const GDIMetaFile& i_rMtf, vcl::PDFExtOutDevDa
delete pPrivateDevice;
}
+// Encryption methods
+
+/* a crutch to transport an rtlDigest safely though UNO API
+ this is needed for the PDF export dialog, which otherwise would have to pass
+ clear text passwords down till they can be used in PDFWriter. Unfortunately
+ the MD5 sum of the password (which is needed to create the PDF encryption key)
+ is not sufficient, since an rtl MD5 digest cannot be created in an arbitrary state
+ which would be needed in PDFWriterImpl::computeEncryptionKey.
+*/
+class EncHashTransporter : public cppu::WeakImplHelper1 < com::sun::star::beans::XMaterialHolder >
+{
+ rtlDigest maUDigest;
+ sal_IntPtr maID;
+ std::vector< sal_uInt8 > maOValue;
+
+ static std::map< sal_IntPtr, EncHashTransporter* > sTransporters;
+public:
+ EncHashTransporter()
+ : maUDigest( rtl_digest_createMD5() )
+ {
+ maID = reinterpret_cast< sal_IntPtr >(this);
+ while( sTransporters.find( maID ) != sTransporters.end() ) // paranoia mode
+ maID++;
+ sTransporters[ maID ] = this;
+ }
+
+ virtual ~EncHashTransporter()
+ {
+ sTransporters.erase( maID );
+ if( maUDigest )
+ rtl_digest_destroyMD5( maUDigest );
+ OSL_TRACE( "EncHashTransporter freed\n" );
+ }
+
+ rtlDigest getUDigest() const { return maUDigest; };
+ std::vector< sal_uInt8 >& getOValue() { return maOValue; }
+ void invalidate()
+ {
+ if( maUDigest )
+ {
+ rtl_digest_destroyMD5( maUDigest );
+ maUDigest = NULL;
+ }
+ }
+
+ // XMaterialHolder
+ virtual uno::Any SAL_CALL getMaterial() throw()
+ {
+ return uno::makeAny( sal_Int64(maID) );
+ }
+
+ static EncHashTransporter* getEncHashTransporter( const uno::Reference< beans::XMaterialHolder >& );
+
+};
+
+std::map< sal_IntPtr, EncHashTransporter* > EncHashTransporter::sTransporters;
+
+EncHashTransporter* EncHashTransporter::getEncHashTransporter( const uno::Reference< beans::XMaterialHolder >& xRef )
+{
+ EncHashTransporter* pResult = NULL;
+ if( xRef.is() )
+ {
+ uno::Any aMat( xRef->getMaterial() );
+ sal_Int64 nMat = 0;
+ if( aMat >>= nMat )
+ {
+ std::map< sal_IntPtr, EncHashTransporter* >::iterator it = sTransporters.find( static_cast<sal_IntPtr>(nMat) );
+ if( it != sTransporters.end() )
+ pResult = it->second;
+ }
+ }
+ return pResult;
+}
+
+sal_Bool PDFWriterImpl::checkEncryptionBufferSize( register sal_Int32 newSize )
+{
+ if( m_nEncryptionBufferSize < newSize )
+ {
+ /* reallocate the buffer, the used function allocate as rtl_allocateMemory
+ if the pointer parameter is NULL */
+ m_pEncryptionBuffer = (sal_uInt8*)rtl_reallocateMemory( m_pEncryptionBuffer, newSize );
+ if( m_pEncryptionBuffer )
+ m_nEncryptionBufferSize = newSize;
+ else
+ m_nEncryptionBufferSize = 0;
+ }
+ return ( m_nEncryptionBufferSize != 0 );
+}
+
+void PDFWriterImpl::checkAndEnableStreamEncryption( register sal_Int32 nObject )
+{
+ if( m_aContext.Encryption.Encrypt() )
+ {
+ m_bEncryptThisStream = true;
+ sal_Int32 i = m_nKeyLength;
+ m_aContext.Encryption.EncryptionKey[i++] = (sal_uInt8)nObject;
+ m_aContext.Encryption.EncryptionKey[i++] = (sal_uInt8)( nObject >> 8 );
+ m_aContext.Encryption.EncryptionKey[i++] = (sal_uInt8)( nObject >> 16 );
+ //the other location of m_nEncryptionKey are already set to 0, our fixed generation number
+ // do the MD5 hash
+ sal_uInt8 nMD5Sum[ RTL_DIGEST_LENGTH_MD5 ];
+ // the i+2 to take into account the generation number, always zero
+ rtl_digest_MD5( &m_aContext.Encryption.EncryptionKey[0], i+2, nMD5Sum, sizeof(nMD5Sum) );
+ // initialize the RC4 with the key
+ // key legth: see algoritm 3.1, step 4: (N+5) max 16
+ rtl_cipher_initARCFOUR( m_aCipher, rtl_Cipher_DirectionEncode, nMD5Sum, m_nRC4KeyLength, NULL, 0 );
+ }
+}
+
+void PDFWriterImpl::enableStringEncryption( register sal_Int32 nObject )
+{
+ if( m_aContext.Encryption.Encrypt() )
+ {
+ sal_Int32 i = m_nKeyLength;
+ m_aContext.Encryption.EncryptionKey[i++] = (sal_uInt8)nObject;
+ m_aContext.Encryption.EncryptionKey[i++] = (sal_uInt8)( nObject >> 8 );
+ m_aContext.Encryption.EncryptionKey[i++] = (sal_uInt8)( nObject >> 16 );
+ //the other location of m_nEncryptionKey are already set to 0, our fixed generation number
+ // do the MD5 hash
+ sal_uInt8 nMD5Sum[ RTL_DIGEST_LENGTH_MD5 ];
+ // the i+2 to take into account the generation number, always zero
+ rtl_digest_MD5( &m_aContext.Encryption.EncryptionKey[0], i+2, nMD5Sum, sizeof(nMD5Sum) );
+ // initialize the RC4 with the key
+ // key legth: see algoritm 3.1, step 4: (N+5) max 16
+ rtl_cipher_initARCFOUR( m_aCipher, rtl_Cipher_DirectionEncode, nMD5Sum, m_nRC4KeyLength, NULL, 0 );
+ }
+}
+
+/* init the encryption engine
+1. init the document id, used both for building the document id and for building the encryption key(s)
+2. build the encryption key following algorithms described in the PDF specification
+ */
+uno::Reference< beans::XMaterialHolder > PDFWriterImpl::initEncryption( const rtl::OUString& i_rOwnerPassword,
+ const rtl::OUString& i_rUserPassword,
+ bool b128Bit
+ )
+{
+ uno::Reference< beans::XMaterialHolder > xResult;
+ if( i_rOwnerPassword.getLength() || i_rUserPassword.getLength() )
+ {
+ EncHashTransporter* pTransporter = new EncHashTransporter;
+ xResult = pTransporter;
+
+ // get padded passwords
+ sal_uInt8 aPadUPW[ENCRYPTED_PWD_SIZE], aPadOPW[ENCRYPTED_PWD_SIZE];
+ padPassword( i_rOwnerPassword.getLength() ? i_rOwnerPassword : i_rUserPassword, aPadOPW );
+ padPassword( i_rUserPassword, aPadUPW );
+ sal_Int32 nKeyLength = SECUR_40BIT_KEY;
+ if( b128Bit )
+ nKeyLength = SECUR_128BIT_KEY;
+
+ if( computeODictionaryValue( aPadOPW, aPadUPW, pTransporter->getOValue(), nKeyLength ) )
+ {
+ rtlDigest aDig = pTransporter->getUDigest();
+ if( rtl_digest_updateMD5( aDig, aPadUPW, ENCRYPTED_PWD_SIZE ) != rtl_Digest_E_None )
+ xResult.clear();
+ }
+ else
+ xResult.clear();
+
+ // trash temporary padded cleartext PWDs
+ rtl_zeroMemory( aPadOPW, sizeof(aPadOPW) );
+ rtl_zeroMemory( aPadUPW, sizeof(aPadUPW) );
+
+ }
+ return xResult;
+}
+
+bool PDFWriterImpl::prepareEncryption( const uno::Reference< beans::XMaterialHolder >& xEnc )
+{
+ bool bSuccess = false;
+ EncHashTransporter* pTransporter = EncHashTransporter::getEncHashTransporter( xEnc );
+ if( pTransporter )
+ {
+ sal_Int32 nKeyLength = 0, nRC4KeyLength = 0;
+ sal_Int32 nAccessPermissions = computeAccessPermissions( m_aContext.Encryption, nKeyLength, nRC4KeyLength );
+ m_aContext.Encryption.OValue = pTransporter->getOValue();
+ bSuccess = computeUDictionaryValue( pTransporter, m_aContext.Encryption, nKeyLength, nAccessPermissions );
+ }
+ if( ! bSuccess )
+ {
+ m_aContext.Encryption.OValue.clear();
+ m_aContext.Encryption.UValue.clear();
+ m_aContext.Encryption.EncryptionKey.clear();
+ }
+ return bSuccess;
+}
+
+sal_Int32 PDFWriterImpl::computeAccessPermissions( const vcl::PDFWriter::PDFEncryptionProperties& i_rProperties,
+ sal_Int32& o_rKeyLength, sal_Int32& o_rRC4KeyLength )
+{
+ /*
+ 2) compute the access permissions, in numerical form
+
+ the default value depends on the revision 2 (40 bit) or 3 (128 bit security):
+ - for 40 bit security the unused bit must be set to 1, since they are not used
+ - for 128 bit security the same bit must be preset to 0 and set later if needed
+ according to the table 3.15, pdf v 1.4 */
+ sal_Int32 nAccessPermissions = ( i_rProperties.Security128bit ) ? 0xfffff0c0 : 0xffffffc0 ;
+
+ /* check permissions for 40 bit security case */
+ nAccessPermissions |= ( i_rProperties.CanPrintTheDocument ) ? 1 << 2 : 0;
+ nAccessPermissions |= ( i_rProperties.CanModifyTheContent ) ? 1 << 3 : 0;
+ nAccessPermissions |= ( i_rProperties.CanCopyOrExtract ) ? 1 << 4 : 0;
+ nAccessPermissions |= ( i_rProperties.CanAddOrModify ) ? 1 << 5 : 0;
+ o_rKeyLength = SECUR_40BIT_KEY;
+ o_rRC4KeyLength = SECUR_40BIT_KEY+5; // for this value see PDF spec v 1.4, algorithm 3.1 step 4, where n is 5
+
+ if( i_rProperties.Security128bit )
+ {
+ o_rKeyLength = SECUR_128BIT_KEY;
+ o_rRC4KeyLength = 16; // for this value see PDF spec v 1.4, algorithm 3.1 step 4, where n is 16, thus maximum
+ // permitted value is 16
+ nAccessPermissions |= ( i_rProperties.CanFillInteractive ) ? 1 << 8 : 0;
+ nAccessPermissions |= ( i_rProperties.CanExtractForAccessibility ) ? 1 << 9 : 0;
+ nAccessPermissions |= ( i_rProperties.CanAssemble ) ? 1 << 10 : 0;
+ nAccessPermissions |= ( i_rProperties.CanPrintFull ) ? 1 << 11 : 0;
+ }
+ return nAccessPermissions;
+}
+
+/*************************************************************
+begin i12626 methods
+
+Implements Algorithm 3.2, step 1 only
+*/
+void PDFWriterImpl::padPassword( const rtl::OUString& i_rPassword, sal_uInt8* o_pPaddedPW )
+{
+ // get ansi-1252 version of the password string CHECKIT ! i12626
+ rtl::OString aString( rtl::OUStringToOString( i_rPassword, RTL_TEXTENCODING_MS_1252 ) );
+
+ //copy the string to the target
+ sal_Int32 nToCopy = ( aString.getLength() < ENCRYPTED_PWD_SIZE ) ? aString.getLength() : ENCRYPTED_PWD_SIZE;
+ sal_Int32 nCurrentChar;
+
+ for( nCurrentChar = 0; nCurrentChar < nToCopy; nCurrentChar++ )
+ o_pPaddedPW[nCurrentChar] = (sal_uInt8)( aString.getStr()[nCurrentChar] );
+
+ //pad it with standard byte string
+ sal_Int32 i,y;
+ for( i = nCurrentChar, y = 0 ; i < ENCRYPTED_PWD_SIZE; i++, y++ )
+ o_pPaddedPW[i] = s_nPadString[y];
+
+ // trash memory of temporary clear text password
+ rtl_zeroMemory( (sal_Char*)aString.getStr(), aString.getLength() );
+}
+
+/**********************************
+Algorithm 3.2 Compute the encryption key used
+
+step 1 should already be done before calling, the paThePaddedPassword parameter should contain
+the padded password and must be 32 byte long, the encryption key is returned into the paEncryptionKey parameter,
+it will be 16 byte long for 128 bit security; for 40 bit security only the first 5 bytes are used
+
+TODO: in pdf ver 1.5 and 1.6 the step 6 is different, should be implemented. See spec.
+
+*/
+bool PDFWriterImpl::computeEncryptionKey( EncHashTransporter* i_pTransporter, vcl::PDFWriter::PDFEncryptionProperties& io_rProperties, sal_Int32 i_nAccessPermissions )
+{
+ bool bSuccess = true;
+ sal_uInt8 nMD5Sum[ RTL_DIGEST_LENGTH_MD5 ];
+
+ // transporter contains an MD5 digest with the padded user password already
+ rtlDigest aDigest = i_pTransporter->getUDigest();
+ rtlDigestError nError = rtl_Digest_E_None;
+ if( aDigest )
+ {
+ //step 3
+ if( ! io_rProperties.OValue.empty() )
+ nError = rtl_digest_updateMD5( aDigest, &io_rProperties.OValue[0] , sal_Int32(io_rProperties.OValue.size()) );
+ else
+ bSuccess = false;
+ //Step 4
+ sal_uInt8 nPerm[4];
+
+ nPerm[0] = (sal_uInt8)i_nAccessPermissions;
+ nPerm[1] = (sal_uInt8)( i_nAccessPermissions >> 8 );
+ nPerm[2] = (sal_uInt8)( i_nAccessPermissions >> 16 );
+ nPerm[3] = (sal_uInt8)( i_nAccessPermissions >> 24 );
+
+ if( nError == rtl_Digest_E_None )
+ nError = rtl_digest_updateMD5( aDigest, nPerm , sizeof( nPerm ) );
+
+ //step 5, get the document ID, binary form
+ if( nError == rtl_Digest_E_None )
+ nError = rtl_digest_updateMD5( aDigest, &io_rProperties.DocumentIdentifier[0], sal_Int32(io_rProperties.DocumentIdentifier.size()) );
+ //get the digest
+ if( nError == rtl_Digest_E_None )
+ {
+ rtl_digest_getMD5( aDigest, nMD5Sum, sizeof( nMD5Sum ) );
+
+ //step 6, only if 128 bit
+ if( io_rProperties.Security128bit )
+ {
+ for( sal_Int32 i = 0; i < 50; i++ )
+ {
+ nError = rtl_digest_updateMD5( aDigest, &nMD5Sum, sizeof( nMD5Sum ) );
+ if( nError != rtl_Digest_E_None )
+ {
+ bSuccess = false;
+ break;
+ }
+ rtl_digest_getMD5( aDigest, nMD5Sum, sizeof( nMD5Sum ) );
+ }
+ }
+ }
+ }
+ else
+ bSuccess = false;
+
+ i_pTransporter->invalidate();
+
+ //Step 7
+ if( bSuccess )
+ {
+ io_rProperties.EncryptionKey.resize( MAXIMUM_RC4_KEY_LENGTH );
+ for( sal_Int32 i = 0; i < MD5_DIGEST_SIZE; i++ )
+ io_rProperties.EncryptionKey[i] = nMD5Sum[i];
+ }
+ else
+ io_rProperties.EncryptionKey.clear();
+
+ return bSuccess;
+}
+
+/**********************************
+Algorithm 3.3 Compute the encryption dictionary /O value, save into the class data member
+the step numbers down here correspond to the ones in PDF v.1.4 specfication
+*/
+bool PDFWriterImpl::computeODictionaryValue( const sal_uInt8* i_pPaddedOwnerPassword,
+ const sal_uInt8* i_pPaddedUserPassword,
+ std::vector< sal_uInt8 >& io_rOValue,
+ sal_Int32 i_nKeyLength
+ )
+{
+ bool bSuccess = true;
+
+ io_rOValue.resize( ENCRYPTED_PWD_SIZE );
+
+ rtlDigest aDigest = rtl_digest_createMD5();
+ rtlCipher aCipher = rtl_cipher_createARCFOUR( rtl_Cipher_ModeStream );
+ if( aDigest && aCipher)
+ {
+ //step 1 already done, data is in i_pPaddedOwnerPassword
+ //step 2
+
+ rtlDigestError nError = rtl_digest_updateMD5( aDigest, i_pPaddedOwnerPassword, ENCRYPTED_PWD_SIZE );
+ if( nError == rtl_Digest_E_None )
+ {
+ sal_uInt8 nMD5Sum[ RTL_DIGEST_LENGTH_MD5 ];
+
+ rtl_digest_getMD5( aDigest, nMD5Sum, sizeof(nMD5Sum) );
+//step 3, only if 128 bit
+ if( i_nKeyLength == SECUR_128BIT_KEY )
+ {
+ sal_Int32 i;
+ for( i = 0; i < 50; i++ )
+ {
+ nError = rtl_digest_updateMD5( aDigest, nMD5Sum, sizeof( nMD5Sum ) );
+ if( nError != rtl_Digest_E_None )
+ {
+ bSuccess = false;
+ break;
+ }
+ rtl_digest_getMD5( aDigest, nMD5Sum, sizeof( nMD5Sum ) );
+ }
+ }
+ //Step 4, the key is in nMD5Sum
+ //step 5 already done, data is in i_pPaddedUserPassword
+ //step 6
+ rtl_cipher_initARCFOUR( aCipher, rtl_Cipher_DirectionEncode,
+ nMD5Sum, i_nKeyLength , NULL, 0 );
+ // encrypt the user password using the key set above
+ rtl_cipher_encodeARCFOUR( aCipher, i_pPaddedUserPassword, ENCRYPTED_PWD_SIZE, // the data to be encrypted
+ &io_rOValue[0], sal_Int32(io_rOValue.size()) ); //encrypted data
+ //Step 7, only if 128 bit
+ if( i_nKeyLength == SECUR_128BIT_KEY )
+ {
+ sal_uInt32 i, y;
+ sal_uInt8 nLocalKey[ SECUR_128BIT_KEY ]; // 16 = 128 bit key
+
+ for( i = 1; i <= 19; i++ ) // do it 19 times, start with 1
+ {
+ for( y = 0; y < sizeof( nLocalKey ); y++ )
+ nLocalKey[y] = (sal_uInt8)( nMD5Sum[y] ^ i );
+
+ rtl_cipher_initARCFOUR( aCipher, rtl_Cipher_DirectionEncode,
+ nLocalKey, SECUR_128BIT_KEY, NULL, 0 ); //destination data area, on init can be NULL
+ rtl_cipher_encodeARCFOUR( aCipher, &io_rOValue[0], sal_Int32(io_rOValue.size()), // the data to be encrypted
+ &io_rOValue[0], sal_Int32(io_rOValue.size()) ); // encrypted data, can be the same as the input, encrypt "in place"
+ //step 8, store in class data member
+ }
+ }
+ }
+ else
+ bSuccess = false;
+ }
+ else
+ bSuccess = false;
+
+ if( aDigest )
+ rtl_digest_destroyMD5( aDigest );
+ if( aCipher )
+ rtl_cipher_destroyARCFOUR( aCipher );
+
+ if( ! bSuccess )
+ io_rOValue.clear();
+ return bSuccess;
+}
+
+/**********************************
+Algorithms 3.4 and 3.5 Compute the encryption dictionary /U value, save into the class data member, revision 2 (40 bit) or 3 (128 bit)
+*/
+bool PDFWriterImpl::computeUDictionaryValue( EncHashTransporter* i_pTransporter,
+ vcl::PDFWriter::PDFEncryptionProperties& io_rProperties,
+ sal_Int32 i_nKeyLength,
+ sal_Int32 i_nAccessPermissions
+ )
+{
+ bool bSuccess = true;
+
+ io_rProperties.UValue.resize( ENCRYPTED_PWD_SIZE );
+
+ rtlDigest aDigest = rtl_digest_createMD5();
+ rtlCipher aCipher = rtl_cipher_createARCFOUR( rtl_Cipher_ModeStream );
+ if( aDigest && aCipher )
+ {
+ //step 1, common to both 3.4 and 3.5
+ if( computeEncryptionKey( i_pTransporter, io_rProperties, i_nAccessPermissions ) )
+ {
+ // prepare encryption key for object
+ for( sal_Int32 i = i_nKeyLength, y = 0; y < 5 ; y++ )
+ io_rProperties.EncryptionKey[i++] = 0;
+
+ if( io_rProperties.Security128bit == false )
+ {
+ //3.4
+ //step 2 and 3
+ rtl_cipher_initARCFOUR( aCipher, rtl_Cipher_DirectionEncode,
+ &io_rProperties.EncryptionKey[0], 5 , // key and key length
+ NULL, 0 ); //destination data area
+ // encrypt the user password using the key set above, save for later use
+ rtl_cipher_encodeARCFOUR( aCipher, s_nPadString, sizeof( s_nPadString ), // the data to be encrypted
+ &io_rProperties.UValue[0], sal_Int32(io_rProperties.UValue.size()) ); //encrypted data, stored in class data member
+ }
+ else
+ {
+ //or 3.5, for 128 bit security
+ //step6, initilize the last 16 bytes of the encrypted user password to 0
+ for(sal_uInt32 i = MD5_DIGEST_SIZE; i < sal_uInt32(io_rProperties.UValue.size()); i++)
+ io_rProperties.UValue[i] = 0;
+ //step 2
+ rtlDigestError nError = rtl_digest_updateMD5( aDigest, s_nPadString, sizeof( s_nPadString ) );
+ //step 3
+ if( nError == rtl_Digest_E_None )
+ nError = rtl_digest_updateMD5( aDigest, &io_rProperties.DocumentIdentifier[0], sal_Int32(io_rProperties.DocumentIdentifier.size()) );
+ else
+ bSuccess = false;
+
+ sal_uInt8 nMD5Sum[ RTL_DIGEST_LENGTH_MD5 ];
+ rtl_digest_getMD5( aDigest, nMD5Sum, sizeof(nMD5Sum) );
+ //Step 4
+ rtl_cipher_initARCFOUR( aCipher, rtl_Cipher_DirectionEncode,
+ &io_rProperties.EncryptionKey[0], SECUR_128BIT_KEY, NULL, 0 ); //destination data area
+ rtl_cipher_encodeARCFOUR( aCipher, nMD5Sum, sizeof( nMD5Sum ), // the data to be encrypted
+ &io_rProperties.UValue[0], sizeof( nMD5Sum ) ); //encrypted data, stored in class data member
+ //step 5
+ sal_uInt32 i, y;
+ sal_uInt8 nLocalKey[SECUR_128BIT_KEY];
+
+ for( i = 1; i <= 19; i++ ) // do it 19 times, start with 1
+ {
+ for( y = 0; y < sizeof( nLocalKey ) ; y++ )
+ nLocalKey[y] = (sal_uInt8)( io_rProperties.EncryptionKey[y] ^ i );
+
+ rtl_cipher_initARCFOUR( aCipher, rtl_Cipher_DirectionEncode,
+ nLocalKey, SECUR_128BIT_KEY, // key and key length
+ NULL, 0 ); //destination data area, on init can be NULL
+ rtl_cipher_encodeARCFOUR( aCipher, &io_rProperties.UValue[0], SECUR_128BIT_KEY, // the data to be encrypted
+ &io_rProperties.UValue[0], SECUR_128BIT_KEY ); // encrypted data, can be the same as the input, encrypt "in place"
+ }
+ }
+ }
+ else
+ bSuccess = false;
+ }
+ else
+ bSuccess = false;
+
+ if( aDigest )
+ rtl_digest_destroyMD5( aDigest );
+ if( aCipher )
+ rtl_cipher_destroyARCFOUR( aCipher );
+
+ if( ! bSuccess )
+ io_rProperties.UValue.clear();
+ return bSuccess;
+}
+
+/* end i12626 methods */