officecfg/registry/schema/org/openoffice/Office/Common.xcs |   10 +
 svl/source/passwordcontainer/passwordcontainer.cxx         |  115 +++++++++----
 svl/source/passwordcontainer/passwordcontainer.hxx         |   61 +++++-
 3 files changed, 143 insertions(+), 43 deletions(-)

New commits:
commit 192fa1e3bfc6269f2ebb91716471485a56074aea
Author:     Caolán McNamara <caol...@redhat.com>
AuthorDate: Tue Mar 22 17:22:22 2022 +0000
Commit:     Caolán McNamara <caol...@redhat.com>
CommitDate: Wed Mar 30 12:23:39 2022 +0200

    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.st...@allotropia.de>

diff --git a/officecfg/registry/schema/org/openoffice/Office/Common.xcs 
b/officecfg/registry/schema/org/openoffice/Office/Common.xcs
index 6e280eac2fc5..d1b16d62554b 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>
@@ -955,6 +960,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 e8f521c28014..4dd36e732108 100644
--- a/svl/source/passwordcontainer/passwordcontainer.cxx
+++ b/svl/source/passwordcontainer/passwordcontainer.cxx
@@ -186,15 +186,18 @@ PasswordMap StorageItem::getInfo()
 
     const 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.getArray(),
         [](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;
@@ -210,14 +213,16 @@ PasswordMap StorageItem::getInfo()
             OUString aName = aUrlUsr[1];
 
             OUString aEPasswd;
+            OUString aIV;
             aPropertyValues[aNodeInd] >>= aEPasswd;
+            aPropertyValues[aNodeInd + aNodeCount] >>= aIV;
 
             PasswordMap::iterator aIter = aResult.find( aUrl );
             if( aIter != aResult.end() )
-                aIter->second.emplace_back( aName, aEPasswd );
+                aIter->second.emplace_back( aName, aEPasswd, aIV );
             else
             {
-                NamePasswordRecord aNewRecord( aName, aEPasswd );
+                NamePasswordRecord aNewRecord( aName, aEPasswd, aIV );
                 std::vector< NamePasswordRecord > listToAdd( 1, aNewRecord );
 
                 aResult.insert( PairUrlRecord( aUrl, listToAdd ) );
@@ -275,15 +280,16 @@ sal_Int32 StorageItem::getStorageVersion()
     return nResult;
 }
 
-bool StorageItem::getEncodedMasterPassword( OUString& aResult )
+bool StorageItem::getEncodedMasterPassword( OUString& aResult, OUString& 
aResultIV )
 {
     if( hasEncoded )
     {
         aResult = mEncoded;
+        aResultIV = mEncodedIV;
         return true;
     }
 
-    Sequence< OUString > aNodeNames{ "HasMaster", "Master" };
+    Sequence< OUString > aNodeNames{ "HasMaster", "Master", 
"MasterInitializationVector" };
 
     Sequence< Any > aPropertyValues = ConfigItem::GetProperties( aNodeNames );
 
@@ -295,23 +301,27 @@ bool StorageItem::getEncodedMasterPassword( OUString& 
aResult )
 
     aPropertyValues[0] >>= hasEncoded;
     aPropertyValues[1] >>= mEncoded;
+    aPropertyValues[2] >>= mEncodedIV;
 
     aResult = mEncoded;
+    aResultIV = mEncodedIV;
 
     return hasEncoded;
 }
 
 
-void StorageItem::setEncodedMasterPassword( const OUString& aEncoded, bool 
bAcceptEmpty )
+void StorageItem::setEncodedMasterPassword( const OUString& aEncoded, const 
OUString& aEncodedIV, bool bAcceptEmpty )
 {
     bool bHasMaster = ( !aEncoded.isEmpty() || bAcceptEmpty );
 
     ConfigItem::SetModified();
-    ConfigItem::PutProperties( { "HasMaster", "Master", "StorageVersion" },
-                               { uno::Any(bHasMaster), uno::Any(aEncoded), 
uno::Any(nCurrentStorageVersion) } );
+    ConfigItem::PutProperties( { "HasMaster", "Master", 
"MasterInitializationVector", "StorageVersion" },
+                               { uno::Any(bHasMaster), uno::Any(aEncoded),
+                                 uno::Any(aEncodedIV), 
uno::Any(nCurrentStorageVersion) } );
 
     hasEncoded = bHasMaster;
     mEncoded = aEncoded;
+    mEncodedIV = aEncodedIV;
 }
 
 
@@ -338,6 +348,8 @@ void StorageItem::update( const OUString& aURL, const 
NamePasswordRecord& aRecor
     }
 
     Sequence< beans::PropertyValue > sendSeq{ comphelper::makePropertyValue(
+        "Store/Passwordstorage['" + createIndex( { aURL, aRecord.GetUserName() 
} ) + "']/InitializationVector",
+        aRecord.GetPersistentIV()), comphelper::makePropertyValue(
         "Store/Passwordstorage['" + createIndex( { aURL, aRecord.GetUserName() 
} ) + "']/Password",
         aRecord.GetPersistentPasswords()) };
 
@@ -400,7 +412,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() )
     {
@@ -415,9 +427,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 )
             {
@@ -450,7 +469,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() )
     {
@@ -467,9 +486,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 )
             {
@@ -537,7 +563,7 @@ void PasswordContainer::UpdateVector( const OUString& aURL, 
std::vector< NamePas
 
             if( aRecord.HasPasswords( PERSISTENT_RECORD ) )
             {
-                aNPIter.SetPersistentPasswords( 
aRecord.GetPersistentPasswords() );
+                aNPIter.SetPersistentPasswords( 
aRecord.GetPersistentPasswords(), aRecord.GetPersistentIV() );
 
                 if( writeFile )
                 {
@@ -570,7 +596,8 @@ UserRecord PasswordContainer::CopyToUserRecord( const 
NamePasswordRecord& aRecor
     {
         try
         {
-            ::std::vector< OUString > aDecodedPasswords = DecodePasswords( 
aRecord.GetPersistentPasswords(), GetMasterPassword( aHandler ), 
css::task::PasswordRequestMode_PASSWORD_ENTER );
+            ::std::vector< OUString > aDecodedPasswords = DecodePasswords( 
aRecord.GetPersistentPasswords(), aRecord.GetPersistentIV(),
+                                                                           
GetMasterPassword( aHandler ), css::task::PasswordRequestMode_PASSWORD_ENTER );
             aPasswords.insert( aPasswords.end(), aDecodedPasswords.begin(), 
aDecodedPasswords.end() );
         }
         catch( NoMasterException& )
@@ -616,6 +643,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 )
 {
@@ -623,7 +663,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.SetPersistentPasswords( EncodePasswords( aStorePass, 
GetMasterPassword( aHandler ) ) );
+    {
+        OUString sIV = createIV();
+        OUString sEncodedPasswords = EncodePasswords(aStorePass, sIV, 
GetMasterPassword(aHandler));
+        aRecord.SetPersistentPasswords(sEncodedPasswords, sIV);
+    }
     else if( Mode == MEMORY_RECORD )
         aRecord.SetMemoryPasswords( std::move(aStorePass) );
     else
@@ -813,10 +857,10 @@ OUString const & PasswordContainer::GetMasterPassword( 
const Reference< XInterac
 
     if( m_aMasterPassword.isEmpty() && aHandler.is() )
     {
-        OUString aEncodedMP;
+        OUString aEncodedMP, aEncodedMPIV;
         bool bDefaultPassword = false;
 
-        if( !m_xStorageFile->getEncodedMasterPassword( aEncodedMP ) )
+        if( !m_xStorageFile->getEncodedMasterPassword( aEncodedMP, 
aEncodedMPIV ) )
             aRMode = PasswordRequestMode_PASSWORD_CREATE;
         else if ( aEncodedMP.isEmpty() )
         {
@@ -838,14 +882,15 @@ OUString const & PasswordContainer::GetMasterPassword( 
const Reference< XInterac
                         m_aMasterPassword = aPass;
                         std::vector< OUString > aMaster( 1, m_aMasterPassword 
);
 
-                        m_xStorageFile->setEncodedMasterPassword( 
EncodePasswords( aMaster, m_aMasterPassword ) );
+                        OUString sIV = createIV();
+                        
m_xStorageFile->setEncodedMasterPassword(EncodePasswords(aMaster, sIV, 
m_aMasterPassword), sIV);
                     }
                     else
                     {
                         if (m_xStorageFile->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;
@@ -1002,7 +1047,8 @@ Sequence< UrlRecord > SAL_CALL 
PasswordContainer::getAllPersistent( const Refere
             {
                 sal_Int32 oldLen = aUsers.getLength();
                 aUsers.realloc( oldLen + 1 );
-                aUsers.getArray()[ oldLen ] = UserRecord( aNP.GetUserName(), 
comphelper::containerToSequence( DecodePasswords( aNP.GetPersistentPasswords(), 
GetMasterPassword( xHandler ), css::task::PasswordRequestMode_PASSWORD_ENTER ) 
) );
+                aUsers.getArray()[ oldLen ] = UserRecord( aNP.GetUserName(), 
comphelper::containerToSequence( DecodePasswords( aNP.GetPersistentPasswords(), 
aNP.GetPersistentIV(),
+                                                                               
                                                GetMasterPassword( xHandler ), 
css::task::PasswordRequestMode_PASSWORD_ENTER ) ) );
             }
 
         if( aUsers.hasElements() )
@@ -1019,12 +1065,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_xStorageFile && m_xStorageFile->useStorage() && 
m_xStorageFile->getEncodedMasterPassword( aEncodedMP ) )
+    if( m_xStorageFile && m_xStorageFile->useStorage() && 
m_xStorageFile->getEncodedMasterPassword( aEncodedMP, aEncodedMPIV ) )
     {
         if ( aEncodedMP.isEmpty() )
         {
@@ -1090,8 +1136,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_aMasterPassword.isEmpty() || 
m_xStorageFile->getEncodedMasterPassword( aEncodedMP ) )
+        OUString aEncodedMP, aEncodedMPIV;
+        if( !m_aMasterPassword.isEmpty() || 
m_xStorageFile->getEncodedMasterPassword( aEncodedMP, aEncodedMPIV ) )
             bCanChangePassword = authorizateWithMasterPassword( xTmpHandler );
 
         if ( bCanChangePassword )
@@ -1110,7 +1156,8 @@ sal_Bool SAL_CALL 
PasswordContainer::changeMasterPassword( const uno::Reference<
                 // store the new master password
                 m_aMasterPassword = aPass;
                 std::vector< OUString > aMaster( 1, m_aMasterPassword );
-                m_xStorageFile->setEncodedMasterPassword( EncodePasswords( 
aMaster, m_aMasterPassword ) );
+                OUString aIV = createIV();
+                
m_xStorageFile->setEncodedMasterPassword(EncodePasswords(aMaster, aIV, 
m_aMasterPassword), aIV);
 
                 // store all the entries with the new password
                 for ( const auto& rURL : aPersistent )
@@ -1135,7 +1182,7 @@ void SAL_CALL PasswordContainer::removeMasterPassword()
     if ( m_xStorageFile )
     {
         m_aMasterPassword.clear();
-        m_xStorageFile->setEncodedMasterPassword( OUString() ); // let the 
master password be removed from configuration
+        m_xStorageFile->setEncodedMasterPassword( OUString(), OUString() ); // 
let the master password be removed from configuration
     }
 }
 
@@ -1146,8 +1193,8 @@ sal_Bool SAL_CALL PasswordContainer::hasMasterPassword(  )
     if ( !m_xStorageFile )
         throw uno::RuntimeException();
 
-    OUString aEncodedMP;
-    return ( m_xStorageFile->useStorage() && 
m_xStorageFile->getEncodedMasterPassword( aEncodedMP ) );
+    OUString aEncodedMP, aEncodedMPIV;
+    return ( m_xStorageFile->useStorage() && 
m_xStorageFile->getEncodedMasterPassword( aEncodedMP, aEncodedMPIV ) );
 }
 
 sal_Bool SAL_CALL PasswordContainer::allowPersistentStoring( sal_Bool bAllow )
@@ -1194,8 +1241,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_xStorageFile->getEncodedMasterPassword( aEncodedMP ) && 
!aEncodedMP.isEmpty() )
+        OUString aEncodedMP, aEncodedMPIV;
+        if( m_xStorageFile->getEncodedMasterPassword( aEncodedMP, aEncodedMPIV 
) && !aEncodedMP.isEmpty() )
             bCanChangePassword = authorizateWithMasterPassword( xTmpHandler );
 
         if ( bCanChangePassword )
@@ -1212,7 +1259,7 @@ sal_Bool SAL_CALL 
PasswordContainer::useDefaultMasterPassword( const uno::Refere
 
                 // store the empty string to flag the default master password
                 m_aMasterPassword = aPass;
-                m_xStorageFile->setEncodedMasterPassword( OUString(), true );
+                m_xStorageFile->setEncodedMasterPassword( OUString(), 
OUString(), true );
 
                 // store all the entries with the new password
                 for ( const auto& rURL : aPersistent )
@@ -1236,8 +1283,8 @@ sal_Bool SAL_CALL 
PasswordContainer::isDefaultMasterPasswordUsed()
     if ( !m_xStorageFile )
         throw uno::RuntimeException();
 
-    OUString aEncodedMP;
-    return ( m_xStorageFile->useStorage() && 
m_xStorageFile->getEncodedMasterPassword( aEncodedMP ) && aEncodedMP.isEmpty() 
);
+    OUString aEncodedMP, aEncodedMPIV;
+    return ( m_xStorageFile->useStorage() && 
m_xStorageFile->getEncodedMasterPassword( aEncodedMP, aEncodedMPIV ) && 
aEncodedMP.isEmpty() );
 }
 
 
diff --git a/svl/source/passwordcontainer/passwordcontainer.hxx 
b/svl/source/passwordcontainer/passwordcontainer.hxx
index 52d185c9dc6f..8d77f0d2abf7 100644
--- a/svl/source/passwordcontainer/passwordcontainer.hxx
+++ b/svl/source/passwordcontainer/passwordcontainer.hxx
@@ -33,6 +33,7 @@
 #include <unotools/configitem.hxx>
 #include <ucbhelper/interactionrequest.hxx>
 
+#include <rtl/random.h>
 #include <rtl/ref.hxx>
 #include <osl/mutex.hxx>
 
@@ -53,9 +54,10 @@ class NamePasswordRecord
     // persistent passwords are encrypted in one string
     bool                        m_bHasPersistentPassword;
     OUString                    m_aPersistentPassword;
+    OUString                    m_aPersistentIV;
 
     void InitArrays( bool bHasMemoryList, ::std::vector< OUString >&& 
aMemoryList,
-                     bool bHasPersistentList, const OUString& aPersistentList )
+                     bool bHasPersistentList, const OUString& aPersistentList, 
const OUString& aPersistentIV )
     {
         m_bHasMemoryPasswords = bHasMemoryList;
         if ( bHasMemoryList )
@@ -63,7 +65,10 @@ class NamePasswordRecord
 
         m_bHasPersistentPassword = bHasPersistentList;
         if ( bHasPersistentList )
+        {
             m_aPersistentPassword = aPersistentList;
+            m_aPersistentIV = aPersistentIV;
+        }
     }
 
 public:
@@ -75,11 +80,12 @@ public:
     {
     }
 
-    NamePasswordRecord( const OUString& aName, const OUString& aPersistentList 
)
+    NamePasswordRecord( const OUString& aName, const OUString& 
aPersistentList, const OUString& aPersistentIV )
         : m_aName( aName )
         , m_bHasMemoryPasswords( false )
         , m_bHasPersistentPassword( true )
         , m_aPersistentPassword( aPersistentList )
+        , m_aPersistentIV( aPersistentIV )
     {
     }
 
@@ -88,7 +94,8 @@ public:
         , m_bHasMemoryPasswords( false )
         , m_bHasPersistentPassword( false )
     {
-        InitArrays( aRecord.m_bHasMemoryPasswords, 
std::vector(aRecord.m_aMemoryPasswords), aRecord.m_bHasPersistentPassword, 
aRecord.m_aPersistentPassword );
+        InitArrays( aRecord.m_bHasMemoryPasswords, 
std::vector(aRecord.m_aMemoryPasswords),
+                    aRecord.m_bHasPersistentPassword, 
aRecord.m_aPersistentPassword, aRecord.m_aPersistentIV );
     }
 
     NamePasswordRecord& operator=( const NamePasswordRecord& aRecord )
@@ -99,7 +106,9 @@ public:
 
             m_aMemoryPasswords.clear();
             m_aPersistentPassword.clear();
-            InitArrays( aRecord.m_bHasMemoryPasswords, 
std::vector(aRecord.m_aMemoryPasswords), aRecord.m_bHasPersistentPassword, 
aRecord.m_aPersistentPassword );
+            m_aPersistentIV.clear();
+            InitArrays( aRecord.m_bHasMemoryPasswords, 
std::vector(aRecord.m_aMemoryPasswords),
+                        aRecord.m_bHasPersistentPassword, 
aRecord.m_aPersistentPassword, aRecord.m_aPersistentIV );
         }
         return *this;
     }
@@ -135,15 +144,24 @@ public:
         return OUString();
     }
 
+    OUString GetPersistentIV() const
+    {
+        if ( m_bHasPersistentPassword )
+            return m_aPersistentIV;
+
+        return OUString();
+    }
+
     void SetMemoryPasswords( ::std::vector< OUString >&& aMemList )
     {
         m_aMemoryPasswords = std::move(aMemList);
         m_bHasMemoryPasswords = true;
     }
 
-    void SetPersistentPasswords( const OUString& aPersList )
+    void SetPersistentPasswords( const OUString& aPersList, const OUString& 
aPersIV )
     {
         m_aPersistentPassword = aPersList;
+        m_aPersistentIV = aPersIV;
         m_bHasPersistentPassword = true;
     }
 
@@ -158,6 +176,7 @@ public:
         {
             m_bHasPersistentPassword = false;
             m_aPersistentPassword.clear();
+            m_aPersistentIV.clear();
         }
     }
 
@@ -181,6 +200,7 @@ private:
     PasswordContainer*     mainCont;
     bool                   hasEncoded;
     OUString               mEncoded;
+    OUString               mEncodedIV;
 
     virtual void            ImplCommit() override;
 
@@ -201,8 +221,8 @@ public:
 
     sal_Int32 getStorageVersion();
 
-    bool getEncodedMasterPassword( OUString& aResult );
-    void setEncodedMasterPassword( const OUString& aResult, bool bAcceptEmpty 
= false );
+    bool getEncodedMasterPassword( OUString& aResult, OUString& aResultIV );
+    void setEncodedMasterPassword( const OUString& aResult, const OUString& 
aResultIV, bool bAcceptEmpty = false );
     void setUseStorage( bool bUse );
     bool useStorage();
 
@@ -223,6 +243,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< 
NamePasswordRecord >& original,
@@ -273,10 +316,10 @@ private:
                               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::uno::XComponentContext 
>& );

Reply via email to