diff options
Diffstat (limited to 'debian/patches/0003-CVE-2022-26306-add-Initialization-Vectors-to-passwor.patch')
-rw-r--r-- | debian/patches/0003-CVE-2022-26306-add-Initialization-Vectors-to-passwor.patch | 583 |
1 files changed, 583 insertions, 0 deletions
diff --git a/debian/patches/0003-CVE-2022-26306-add-Initialization-Vectors-to-passwor.patch b/debian/patches/0003-CVE-2022-26306-add-Initialization-Vectors-to-passwor.patch new file mode 100644 index 000000000..b65b3530c --- /dev/null +++ b/debian/patches/0003-CVE-2022-26306-add-Initialization-Vectors-to-passwor.patch @@ -0,0 +1,583 @@ +From e809625c2ca9f0c026aab9b5c2d13ced628c13e9 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Caol=C3=A1n=20McNamara?= <caolanm@redhat.com> +Date: Tue, 22 Mar 2022 17:22:22 +0000 +Subject: [PATCH 3/4] CVE-2022-26306 add Initialization Vectors to password + storage + +old ones default to the current all zero case and continue to work +as before + +Change-Id: I6fe3b02fafcce1b5e7133e77e76a5118177d77af +Reviewed-on: https://gerrit.libreoffice.org/c/core/+/131974 +Tested-by: Jenkins +Reviewed-by: Michael Stahl <michael.stahl@allotropia.de> +(cherry picked from commit 192fa1e3bfc6269f2ebb91716471485a56074aea) +Reviewed-on: https://gerrit.libreoffice.org/c/core/+/132306 +Reviewed-by: Thorsten Behrens <thorsten.behrens@allotropia.de> +(cherry picked from commit ab77587ec300f5c30084471000663c46ddf25dad) +--- + .../schema/org/openoffice/Office/Common.xcs | 10 ++ + .../passwordcontainer/passwordcontainer.cxx | 127 ++++++++++++------ + .../passwordcontainer/passwordcontainer.hxx | 63 +++++++-- + 3 files changed, 151 insertions(+), 49 deletions(-) + +diff --git a/officecfg/registry/schema/org/openoffice/Office/Common.xcs b/officecfg/registry/schema/org/openoffice/Office/Common.xcs +index 922efc33cca7..8d87d00d5369 100644 +--- a/officecfg/registry/schema/org/openoffice/Office/Common.xcs ++++ b/officecfg/registry/schema/org/openoffice/Office/Common.xcs +@@ -27,6 +27,11 @@ + <info> + <desc>Contains a container for passwords.</desc> + </info> ++ <prop oor:name="InitializationVector" oor:type="xs:string"> ++ <info> ++ <desc>Contains an initialization vector for the password encryption.</desc> ++ </info> ++ </prop> + <prop oor:name="Password" oor:type="xs:string" oor:localized="false"> + <info> + <desc>Contains a password encoded with the master password.</desc> +@@ -954,6 +959,11 @@ + </info> + <value>false</value> + </prop> ++ <prop oor:name="MasterInitializationVector" oor:type="xs:string"> ++ <info> ++ <desc>Contains an initialization vector for the master password encryption.</desc> ++ </info> ++ </prop> + <prop oor:name="Master" oor:type="xs:string" oor:nillable="false"> + <info> + <desc>Contains the master password encrypted by itself.</desc> +diff --git a/svl/source/passwordcontainer/passwordcontainer.cxx b/svl/source/passwordcontainer/passwordcontainer.cxx +index b674844f91d3..ef79470a2cb6 100644 +--- a/svl/source/passwordcontainer/passwordcontainer.cxx ++++ b/svl/source/passwordcontainer/passwordcontainer.cxx +@@ -181,15 +181,18 @@ PassMap StorageItem::getInfo() + + Sequence< OUString > aNodeNames = ConfigItem::GetNodeNames( "Store" ); + sal_Int32 aNodeCount = aNodeNames.getLength(); +- Sequence< OUString > aPropNames( aNodeCount ); ++ Sequence< OUString > aPropNames( aNodeCount * 2); + + std::transform(aNodeNames.begin(), aNodeNames.end(), aPropNames.begin(), + [](const OUString& rName) -> OUString { + return "Store/Passwordstorage['" + rName + "']/Password"; }); ++ std::transform(aNodeNames.begin(), aNodeNames.end(), aPropNames.getArray() + aNodeCount, ++ [](const OUString& rName) -> OUString { ++ return "Store/Passwordstorage['" + rName + "']/InitializationVector"; }); + + Sequence< Any > aPropertyValues = ConfigItem::GetProperties( aPropNames ); + +- if( aPropertyValues.getLength() != aNodeCount ) ++ if( aPropertyValues.getLength() != aNodeCount * 2) + { + OSL_FAIL( "Problems during reading" ); + return aResult; +@@ -205,14 +208,16 @@ PassMap StorageItem::getInfo() + OUString aName = aUrlUsr[1]; + + OUString aEPasswd; ++ OUString aIV; + aPropertyValues[aNodeInd] >>= aEPasswd; ++ aPropertyValues[aNodeInd + aNodeCount] >>= aIV; + + PassMap::iterator aIter = aResult.find( aUrl ); + if( aIter != aResult.end() ) +- aIter->second.emplace_back( aName, aEPasswd ); ++ aIter->second.emplace_back( aName, aEPasswd, aIV ); + else + { +- NamePassRecord aNewRecord( aName, aEPasswd ); ++ NamePassRecord aNewRecord( aName, aEPasswd, aIV ); + std::vector< NamePassRecord > listToAdd( 1, aNewRecord ); + + aResult.insert( PairUrlRecord( aUrl, listToAdd ) ); +@@ -276,17 +281,19 @@ sal_Int32 StorageItem::getStorageVersion() + return nResult; + } + +-bool StorageItem::getEncodedMP( OUString& aResult ) ++bool StorageItem::getEncodedMP( OUString& aResult, OUString& aResultIV ) + { + if( hasEncoded ) + { + aResult = mEncoded; ++ aResultIV = mEncodedIV; + return true; + } + +- Sequence< OUString > aNodeNames( 2 ); ++ Sequence< OUString > aNodeNames( 3 ); + aNodeNames[0] = "HasMaster"; + aNodeNames[1] = "Master"; ++ aNodeNames[2] = "MasterInitializationVector"; + + Sequence< Any > aPropertyValues = ConfigItem::GetProperties( aNodeNames ); + +@@ -298,32 +305,37 @@ bool StorageItem::getEncodedMP( OUString& aResult ) + + aPropertyValues[0] >>= hasEncoded; + aPropertyValues[1] >>= mEncoded; ++ aPropertyValues[2] >>= mEncodedIV; + + aResult = mEncoded; ++ aResultIV = mEncodedIV; + + return hasEncoded; + } + + +-void StorageItem::setEncodedMP( const OUString& aEncoded, bool bAcceptEmpty ) ++void StorageItem::setEncodedMP( const OUString& aEncoded, const OUString& aEncodedIV, bool bAcceptEmpty ) + { +- Sequence< OUString > sendNames(3); +- Sequence< uno::Any > sendVals(3); ++ Sequence< OUString > sendNames(4); ++ Sequence< uno::Any > sendVals(4); + + sendNames[0] = "HasMaster"; + sendNames[1] = "Master"; +- sendNames[2] = "StorageVersion"; ++ sendNames[2] = "MasterInitializationVector"; ++ sendNames[3] = "StorageVersion"; + + bool bHasMaster = ( !aEncoded.isEmpty() || bAcceptEmpty ); + sendVals[0] <<= bHasMaster; + sendVals[1] <<= aEncoded; +- sendVals[2] <<= nCurrentStorageVersion; ++ sendVals[2] <<= aEncodedIV; ++ sendVals[3] <<= nCurrentStorageVersion; + + ConfigItem::SetModified(); + ConfigItem::PutProperties( sendNames, sendVals ); + + hasEncoded = bHasMaster; + mEncoded = aEncoded; ++ mEncodedIV = aEncodedIV; + } + + +@@ -359,11 +371,13 @@ void StorageItem::update( const OUString& aURL, const NamePassRecord& aRecord ) + forIndex.push_back( aURL ); + forIndex.push_back( aRecord.GetUserName() ); + +- Sequence< beans::PropertyValue > sendSeq(1); ++ Sequence< beans::PropertyValue > sendSeq(2); + +- sendSeq[0].Name = "Store/Passwordstorage['" + createIndex( forIndex ) + "']/Password"; ++ sendSeq[0].Name = "Store/Passwordstorage['" + createIndex( forIndex ) + "']/InitializationVector"; ++ sendSeq[0].Value <<= aRecord.GetPersistentIV(); + +- sendSeq[0].Value <<= aRecord.GetPersPasswords(); ++ sendSeq[1].Name = "Store/Passwordstorage['" + createIndex( forIndex ) + "']/Password"; ++ sendSeq[1].Value <<= aRecord.GetPersPasswords(); + + ConfigItem::SetModified(); + ConfigItem::SetSetProperties( "Store", sendSeq ); +@@ -424,7 +438,7 @@ void SAL_CALL PasswordContainer::disposing( const EventObject& ) + } + } + +-std::vector< OUString > PasswordContainer::DecodePasswords( const OUString& aLine, const OUString& aMasterPasswd, css::task::PasswordRequestMode mode ) ++std::vector< OUString > PasswordContainer::DecodePasswords( const OUString& aLine, const OUString& aIV, const OUString& aMasterPasswd, css::task::PasswordRequestMode mode ) + { + if( !aMasterPasswd.isEmpty() ) + { +@@ -439,9 +453,16 @@ std::vector< OUString > PasswordContainer::DecodePasswords( const OUString& aLin + for( int ind = 0; ind < RTL_DIGEST_LENGTH_MD5; ind++ ) + code[ ind ] = static_cast<char>(aMasterPasswd.copy( ind*2, 2 ).toUInt32(16)); + ++ unsigned char iv[RTL_DIGEST_LENGTH_MD5] = {0}; ++ if (!aIV.isEmpty()) ++ { ++ for( int ind = 0; ind < RTL_DIGEST_LENGTH_MD5; ind++ ) ++ iv[ ind ] = static_cast<char>(aIV.copy( ind*2, 2 ).toUInt32(16)); ++ } ++ + rtlCipherError result = rtl_cipher_init ( + aDecoder, rtl_Cipher_DirectionDecode, +- code, RTL_DIGEST_LENGTH_MD5, nullptr, 0 ); ++ code, RTL_DIGEST_LENGTH_MD5, iv, RTL_DIGEST_LENGTH_MD5 ); + + if( result == rtl_Cipher_E_None ) + { +@@ -474,7 +495,7 @@ std::vector< OUString > PasswordContainer::DecodePasswords( const OUString& aLin + "Can't decode!", css::uno::Reference<css::uno::XInterface>(), mode); + } + +-OUString PasswordContainer::EncodePasswords(const std::vector< OUString >& lines, const OUString& aMasterPasswd ) ++OUString PasswordContainer::EncodePasswords(const std::vector< OUString >& lines, const OUString& aIV, const OUString& aMasterPasswd) + { + if( !aMasterPasswd.isEmpty() ) + { +@@ -491,9 +512,16 @@ OUString PasswordContainer::EncodePasswords(const std::vector< OUString >& lines + for( int ind = 0; ind < RTL_DIGEST_LENGTH_MD5; ind++ ) + code[ ind ] = static_cast<char>(aMasterPasswd.copy( ind*2, 2 ).toUInt32(16)); + ++ unsigned char iv[RTL_DIGEST_LENGTH_MD5] = {0}; ++ if (!aIV.isEmpty()) ++ { ++ for( int ind = 0; ind < RTL_DIGEST_LENGTH_MD5; ind++ ) ++ iv[ ind ] = static_cast<char>(aIV.copy( ind*2, 2 ).toUInt32(16)); ++ } ++ + rtlCipherError result = rtl_cipher_init ( + aEncoder, rtl_Cipher_DirectionEncode, +- code, RTL_DIGEST_LENGTH_MD5, nullptr, 0 ); ++ code, RTL_DIGEST_LENGTH_MD5, iv, RTL_DIGEST_LENGTH_MD5 ); + + if( result == rtl_Cipher_E_None ) + { +@@ -561,7 +589,7 @@ void PasswordContainer::UpdateVector( const OUString& aURL, std::vector< NamePas + + if( aRecord.HasPasswords( PERSISTENT_RECORD ) ) + { +- aNPIter.SetPersPasswords( aRecord.GetPersPasswords() ); ++ aNPIter.SetPersPasswords( aRecord.GetPersPasswords(), aRecord.GetPersistentIV() ); + + if( writeFile ) + { +@@ -594,7 +622,8 @@ UserRecord PasswordContainer::CopyToUserRecord( const NamePassRecord& aRecord, b + { + try + { +- ::std::vector< OUString > aDecodedPasswords = DecodePasswords( aRecord.GetPersPasswords(), GetMasterPassword( aHandler ), css::task::PasswordRequestMode_PASSWORD_ENTER ); ++ ::std::vector< OUString > aDecodedPasswords = DecodePasswords( aRecord.GetPersPasswords(), aRecord.GetPersistentIV(), ++ GetMasterPassword( aHandler ), css::task::PasswordRequestMode_PASSWORD_ENTER ); + aPasswords.insert( aPasswords.end(), aDecodedPasswords.begin(), aDecodedPasswords.end() ); + } + catch( NoMasterException& ) +@@ -639,6 +668,19 @@ void SAL_CALL PasswordContainer::addPersistent( const OUString& Url, const OUStr + PrivateAdd( Url, UserName, Passwords, PERSISTENT_RECORD, aHandler ); + } + ++OUString PasswordContainer::createIV() ++{ ++ rtlRandomPool randomPool = mRandomPool.get(); ++ unsigned char iv[RTL_DIGEST_LENGTH_MD5]; ++ rtl_random_getBytes(randomPool, iv, RTL_DIGEST_LENGTH_MD5); ++ OUStringBuffer aBuffer; ++ for (sal_uInt8 i : iv) ++ { ++ aBuffer.append(OUString::number(i >> 4, 16)); ++ aBuffer.append(OUString::number(i & 15, 16)); ++ } ++ return aBuffer.makeStringAndClear(); ++} + + void PasswordContainer::PrivateAdd( const OUString& Url, const OUString& UserName, const Sequence< OUString >& Passwords, char Mode, const Reference< XInteractionHandler >& aHandler ) + { +@@ -646,7 +688,11 @@ void PasswordContainer::PrivateAdd( const OUString& Url, const OUString& UserNam + ::std::vector< OUString > aStorePass = comphelper::sequenceToContainer< std::vector<OUString> >( Passwords ); + + if( Mode == PERSISTENT_RECORD ) +- aRecord.SetPersPasswords( EncodePasswords( aStorePass, GetMasterPassword( aHandler ) ) ); ++ { ++ OUString sIV = createIV(); ++ OUString sEncodedPasswords = EncodePasswords( aStorePass, sIV, GetMasterPassword( aHandler ) ); ++ aRecord.SetPersPasswords( sEncodedPasswords, sIV ); ++ } + else if( Mode == MEMORY_RECORD ) + aRecord.SetMemPasswords( aStorePass ); + else +@@ -839,10 +885,10 @@ OUString const & PasswordContainer::GetMasterPassword( const Reference< XInterac + + if( m_aMasterPasswd.isEmpty() && aHandler.is() ) + { +- OUString aEncodedMP; ++ OUString aEncodedMP, aEncodedMPIV; + bool bDefaultPassword = false; + +- if( !m_pStorageFile->getEncodedMP( aEncodedMP ) ) ++ if( !m_pStorageFile->getEncodedMP( aEncodedMP, aEncodedMPIV ) ) + aRMode = PasswordRequestMode_PASSWORD_CREATE; + else if ( aEncodedMP.isEmpty() ) + { +@@ -864,14 +910,15 @@ OUString const & PasswordContainer::GetMasterPassword( const Reference< XInterac + m_aMasterPasswd = aPass; + std::vector< OUString > aMaster( 1, m_aMasterPasswd ); + +- m_pStorageFile->setEncodedMP( EncodePasswords( aMaster, m_aMasterPasswd ) ); ++ OUString sIV = createIV(); ++ m_pStorageFile->setEncodedMP( EncodePasswords( aMaster, sIV, m_aMasterPasswd ), sIV ); + } + else + { + if (m_pStorageFile->getStorageVersion() == 0) + aPass = ReencodeAsOldHash(aPass); + +- std::vector< OUString > aRM( DecodePasswords( aEncodedMP, aPass, aRMode ) ); ++ std::vector< OUString > aRM( DecodePasswords( aEncodedMP, aEncodedMPIV, aPass, aRMode ) ); + if( aRM.empty() || aPass != aRM[0] ) + { + bAskAgain = true; +@@ -1028,7 +1075,8 @@ Sequence< UrlRecord > SAL_CALL PasswordContainer::getAllPersistent( const Refere + { + sal_Int32 oldLen = aUsers.getLength(); + aUsers.realloc( oldLen + 1 ); +- aUsers[ oldLen ] = UserRecord( aNP.GetUserName(), comphelper::containerToSequence( DecodePasswords( aNP.GetPersPasswords(), GetMasterPassword( xHandler ), css::task::PasswordRequestMode_PASSWORD_ENTER ) ) ); ++ aUsers[ oldLen ] = UserRecord( aNP.GetUserName(), comphelper::containerToSequence( DecodePasswords( aNP.GetPersPasswords(), aNP.GetPersistentIV(), ++ GetMasterPassword( xHandler ), css::task::PasswordRequestMode_PASSWORD_ENTER ) ) ); + } + + if( aUsers.hasElements() ) +@@ -1045,12 +1093,12 @@ Sequence< UrlRecord > SAL_CALL PasswordContainer::getAllPersistent( const Refere + sal_Bool SAL_CALL PasswordContainer::authorizateWithMasterPassword( const uno::Reference< task::XInteractionHandler >& xHandler ) + { + bool bResult = false; +- OUString aEncodedMP; ++ OUString aEncodedMP, aEncodedMPIV; + uno::Reference< task::XInteractionHandler > xTmpHandler = xHandler; + ::osl::MutexGuard aGuard( mMutex ); + + // the method should fail if there is no master password +- if( m_pStorageFile && m_pStorageFile->useStorage() && m_pStorageFile->getEncodedMP( aEncodedMP ) ) ++ if( m_pStorageFile && m_pStorageFile->useStorage() && m_pStorageFile->getEncodedMP( aEncodedMP, aEncodedMPIV ) ) + { + if ( aEncodedMP.isEmpty() ) + { +@@ -1118,8 +1166,8 @@ sal_Bool SAL_CALL PasswordContainer::changeMasterPassword( const uno::Reference< + + bool bCanChangePassword = true; + // if there is already a stored master password it should be entered by the user before the change happen +- OUString aEncodedMP; +- if( !m_aMasterPasswd.isEmpty() || m_pStorageFile->getEncodedMP( aEncodedMP ) ) ++ OUString aEncodedMP, aEncodedMPIV; ++ if( !m_aMasterPasswd.isEmpty() || m_pStorageFile->getEncodedMP( aEncodedMP, aEncodedMPIV ) ) + bCanChangePassword = authorizateWithMasterPassword( xTmpHandler ); + + if ( bCanChangePassword ) +@@ -1138,7 +1186,8 @@ sal_Bool SAL_CALL PasswordContainer::changeMasterPassword( const uno::Reference< + // store the new master password + m_aMasterPasswd = aPass; + std::vector< OUString > aMaster( 1, m_aMasterPasswd ); +- m_pStorageFile->setEncodedMP( EncodePasswords( aMaster, m_aMasterPasswd ) ); ++ OUString aIV = createIV(); ++ m_pStorageFile->setEncodedMP( EncodePasswords( aMaster, aIV, m_aMasterPasswd ), aIV ); + + // store all the entries with the new password + for ( const auto& rURL : aPersistent ) +@@ -1163,7 +1212,7 @@ void SAL_CALL PasswordContainer::removeMasterPassword() + if ( m_pStorageFile ) + { + m_aMasterPasswd.clear(); +- m_pStorageFile->setEncodedMP( OUString() ); // let the master password be removed from configuration ++ m_pStorageFile->setEncodedMP( OUString(), OUString() ); // let the master password be removed from configuration + } + } + +@@ -1174,8 +1223,8 @@ sal_Bool SAL_CALL PasswordContainer::hasMasterPassword( ) + if ( !m_pStorageFile ) + throw uno::RuntimeException(); + +- OUString aEncodedMP; +- return ( m_pStorageFile->useStorage() && m_pStorageFile->getEncodedMP( aEncodedMP ) ); ++ OUString aEncodedMP, aEncodedMPIV; ++ return ( m_pStorageFile->useStorage() && m_pStorageFile->getEncodedMP( aEncodedMP, aEncodedMPIV ) ); + } + + sal_Bool SAL_CALL PasswordContainer::allowPersistentStoring( sal_Bool bAllow ) +@@ -1222,8 +1271,8 @@ sal_Bool SAL_CALL PasswordContainer::useDefaultMasterPassword( const uno::Refere + + bool bCanChangePassword = true; + // if there is already a stored nondefault master password it should be entered by the user before the change happen +- OUString aEncodedMP; +- if( m_pStorageFile->getEncodedMP( aEncodedMP ) && !aEncodedMP.isEmpty() ) ++ OUString aEncodedMP, aEncodedMPIV; ++ if( m_pStorageFile->getEncodedMP( aEncodedMP, aEncodedMPIV ) && !aEncodedMP.isEmpty() ) + bCanChangePassword = authorizateWithMasterPassword( xTmpHandler ); + + if ( bCanChangePassword ) +@@ -1240,7 +1289,7 @@ sal_Bool SAL_CALL PasswordContainer::useDefaultMasterPassword( const uno::Refere + + // store the empty string to flag the default master password + m_aMasterPasswd = aPass; +- m_pStorageFile->setEncodedMP( OUString(), true ); ++ m_pStorageFile->setEncodedMP( OUString(), OUString(), true ); + + // store all the entries with the new password + for ( const auto& rURL : aPersistent ) +@@ -1264,8 +1313,8 @@ sal_Bool SAL_CALL PasswordContainer::isDefaultMasterPasswordUsed() + if ( !m_pStorageFile ) + throw uno::RuntimeException(); + +- OUString aEncodedMP; +- return ( m_pStorageFile->useStorage() && m_pStorageFile->getEncodedMP( aEncodedMP ) && aEncodedMP.isEmpty() ); ++ OUString aEncodedMP, aEncodedMPIV; ++ return ( m_pStorageFile->useStorage() && m_pStorageFile->getEncodedMP( aEncodedMP, aEncodedMPIV ) && aEncodedMP.isEmpty() ); + } + + +diff --git a/svl/source/passwordcontainer/passwordcontainer.hxx b/svl/source/passwordcontainer/passwordcontainer.hxx +index bf43b5903602..0454437b9dc2 100644 +--- a/svl/source/passwordcontainer/passwordcontainer.hxx ++++ b/svl/source/passwordcontainer/passwordcontainer.hxx +@@ -34,6 +34,7 @@ + #include <unotools/configitem.hxx> + #include <ucbhelper/interactionrequest.hxx> + ++#include <rtl/random.h> + #include <rtl/ref.hxx> + #include <osl/mutex.hxx> + +@@ -52,11 +53,12 @@ class NamePassRecord + ::std::vector< OUString > m_aMemPass; + + // persistent passwords are encrypted in one string +- bool m_bHasPersPass; ++ bool m_bHasPersPass; + OUString m_aPersPass; ++ OUString m_aPersistentIV; + + void InitArrays( bool bHasMemoryList, const ::std::vector< OUString >& aMemoryList, +- bool bHasPersistentList, const OUString& aPersistentList ) ++ bool bHasPersistentList, const OUString& aPersistentList, const OUString& aPersistentIV ) + { + m_bHasMemPass = bHasMemoryList; + if ( bHasMemoryList ) +@@ -64,7 +66,10 @@ class NamePassRecord + + m_bHasPersPass = bHasPersistentList; + if ( bHasPersistentList ) ++ { + m_aPersPass = aPersistentList; ++ m_aPersistentIV = aPersistentIV; ++ } + } + + public: +@@ -76,11 +81,12 @@ public: + { + } + +- NamePassRecord( const OUString& aName, const OUString& aPersistentList ) ++ NamePassRecord( const OUString& aName, const OUString& aPersistentList, const OUString& aPersistentIV ) + : m_aName( aName ) + , m_bHasMemPass( false ) + , m_bHasPersPass( true ) + , m_aPersPass( aPersistentList ) ++ , m_aPersistentIV( aPersistentIV ) + { + } + +@@ -89,7 +95,8 @@ public: + , m_bHasMemPass( false ) + , m_bHasPersPass( false ) + { +- InitArrays( aRecord.m_bHasMemPass, aRecord.m_aMemPass, aRecord.m_bHasPersPass, aRecord.m_aPersPass ); ++ InitArrays( aRecord.m_bHasMemPass, aRecord.m_aMemPass, ++ aRecord.m_bHasPersPass, aRecord.m_aPersPass, aRecord.m_aPersistentIV ); + } + + NamePassRecord& operator=( const NamePassRecord& aRecord ) +@@ -100,7 +107,9 @@ public: + + m_aMemPass.clear(); + m_aPersPass.clear(); +- InitArrays( aRecord.m_bHasMemPass, aRecord.m_aMemPass, aRecord.m_bHasPersPass, aRecord.m_aPersPass ); ++ m_aPersistentIV.clear(); ++ InitArrays( aRecord.m_bHasMemPass, aRecord.m_aMemPass, ++ aRecord.m_bHasPersPass, aRecord.m_aPersPass, aRecord.m_aPersistentIV ); + } + return *this; + } +@@ -136,15 +145,24 @@ public: + return OUString(); + } + ++ OUString GetPersistentIV() const ++ { ++ if ( m_bHasPersPass ) ++ return m_aPersistentIV; ++ ++ return OUString(); ++ } ++ + void SetMemPasswords( const ::std::vector< OUString >& aMemList ) + { + m_aMemPass = aMemList; + m_bHasMemPass = true; + } + +- void SetPersPasswords( const OUString& aPersList ) ++ void SetPersPasswords( const OUString& aPersList, const OUString& aPersIV ) + { + m_aPersPass = aPersList; ++ m_aPersistentIV = aPersIV; + m_bHasPersPass = true; + } + +@@ -159,6 +177,7 @@ public: + { + m_bHasPersPass = false; + m_aPersPass.clear(); ++ m_aPersistentIV.clear(); + } + } + +@@ -182,6 +201,7 @@ private: + PasswordContainer* mainCont; + bool hasEncoded; + OUString mEncoded; ++ OUString mEncodedIV; + + virtual void ImplCommit() override; + +@@ -201,8 +201,8 @@ + + sal_Int32 getStorageVersion(); + +- bool getEncodedMP( OUString& aResult ); +- void setEncodedMP( const OUString& aResult, bool bAcceptEnmpty = false ); ++ bool getEncodedMP( OUString& aResult, OUString& aResultIV ); ++ void setEncodedMP( const OUString& aResult, const OUString& aResultIV, bool bAcceptEmpty = false ); + void setUseStorage( bool bUse ); + bool useStorage(); + +@@ -224,6 +244,29 @@ private: + css::uno::Reference< css::lang::XComponent > mComponent; + SysCredentialsConfig mUrlContainer; + ++ class RandomPool ++ { ++ private: ++ rtlRandomPool m_aRandomPool; ++ public: ++ RandomPool() : m_aRandomPool(rtl_random_createPool()) ++ { ++ } ++ rtlRandomPool get() ++ { ++ return m_aRandomPool; ++ } ++ ~RandomPool() ++ { ++ // Clean up random pool memory ++ rtl_random_destroyPool(m_aRandomPool); ++ } ++ }; ++ ++ RandomPool mRandomPool; ++ ++ OUString createIV(); ++ + /// @throws css::uno::RuntimeException + css::uno::Sequence< css::task::UserRecord > CopyToUserRecordSequence( + const ::std::vector< NamePassRecord >& original, +@@ -274,10 +317,10 @@ css::task::UrlRecord find( + const css::uno::Reference< css::task::XInteractionHandler >& Handler ); + + /// @throws css::uno::RuntimeException +- static ::std::vector< OUString > DecodePasswords( const OUString& aLine, const OUString& aMasterPassword, css::task::PasswordRequestMode mode ); ++ static ::std::vector< OUString > DecodePasswords( const OUString& aLine, const OUString& aIV, const OUString& aMasterPassword, css::task::PasswordRequestMode mode ); + + /// @throws css::uno::RuntimeException +- static OUString EncodePasswords(const std::vector< OUString >& lines, const OUString& aMasterPassword ); ++ static OUString EncodePasswords(const std::vector< OUString >& lines, const OUString& aIV, const OUString& aMasterPassword ); + + public: + PasswordContainer( const css::uno::Reference< css::lang::XMultiServiceFactory >& ); +-- +2.37.1 + |