summaryrefslogtreecommitdiff
path: root/package
diff options
context:
space:
mode:
authorMichael Stahl <michael.stahl@allotropia.de>2023-12-08 21:16:31 +0100
committerMichael Stahl <michael.stahl@allotropia.de>2023-12-11 20:46:40 +0100
commitf0fda7ad2236f478fea396a23d4f982e5fc37e68 (patch)
treee6b0afbeb4874453aeb572c6e21240220667a36d /package
parent4bba7fbc22f13d579e57b36e8c8e302d987e01f0 (diff)
tdf#105844 offapi,package,sfx2,xmlsecurity: add AEAD w/ AES GCM
... and use it in the new experimental ODF encryption mode. https://www.w3.org/TR/xmlenc-core1/#sec-AES-GCM Unfortunately it turned out that NSS PK11_CipherOp() does not work with CKM_AES_GCM because it is initialized with "context->multi = PR_FALSE" in sftk_CryptInit(), so the one-step functions PK11_Encrypt() and PK11_Decrypt() have to be used. NSS 3.52 also changed a parameter struct definition - see https://fedoraproject.org/wiki/Changes/NssGCMParams - which is not a problem for RHEL or SUSE system NSS since those are rebased, but it is likely a problem for less well maintained Ubuntu LTS, so use the old struct definition which evidently still works with NSS 3.94. NSS 3.52 also added a new PK11_AEADOp() API but it looks like this doesn't support incremental encryption either. Change-Id: Ibd4a672db74b65b1218926ba35ff8d2f70444c7e Reviewed-on: https://gerrit.libreoffice.org/c/core/+/160505 Tested-by: Jenkins Reviewed-by: Michael Stahl <michael.stahl@allotropia.de>
Diffstat (limited to 'package')
-rw-r--r--package/inc/ZipPackage.hxx14
-rw-r--r--package/inc/ZipPackageStream.hxx2
-rw-r--r--package/source/manifest/ManifestDefines.hxx3
-rw-r--r--package/source/manifest/ManifestExport.cxx9
-rw-r--r--package/source/manifest/ManifestImport.cxx17
-rw-r--r--package/source/zipapi/XUnbufferedStream.cxx1
-rw-r--r--package/source/zipapi/ZipFile.cxx6
-rw-r--r--package/source/zippackage/ZipPackage.cxx16
-rw-r--r--package/source/zippackage/ZipPackageStream.cxx19
9 files changed, 77 insertions, 10 deletions
diff --git a/package/inc/ZipPackage.hxx b/package/inc/ZipPackage.hxx
index e83958241247..48067f39b6f7 100644
--- a/package/inc/ZipPackage.hxx
+++ b/package/inc/ZipPackage.hxx
@@ -31,6 +31,7 @@
#include <com/sun/star/xml/crypto/CipherID.hpp>
#include <comphelper/refcountedmutex.hxx>
#include <rtl/ref.hxx>
+#include <o3tl/unreachable.hxx>
#include "HashMaps.hxx"
#include "ZipFile.hxx"
@@ -124,7 +125,18 @@ public:
sal_Int32 GetStartKeyGenID() const { return m_nStartKeyGenerationID; }
sal_Int32 GetEncAlgID() const { return m_nCommonEncryptionID; }
sal_Int32 GetChecksumAlgID() const { return m_nChecksumDigestID; }
- sal_Int32 GetDefaultDerivedKeySize() const { return m_nCommonEncryptionID == css::xml::crypto::CipherID::AES_CBC_W3C_PADDING ? 32 : 16; }
+ sal_Int32 GetDefaultDerivedKeySize() const {
+ switch (m_nCommonEncryptionID)
+ {
+ case css::xml::crypto::CipherID::BLOWFISH_CFB_8:
+ return 16;
+ case css::xml::crypto::CipherID::AES_CBC_W3C_PADDING:
+ case css::xml::crypto::CipherID::AES_GCM_W3C:
+ return 32;
+ default:
+ O3TL_UNREACHABLE;
+ }
+ }
rtl::Reference<comphelper::RefCountedMutex>& GetSharedMutexRef() { return m_aMutexHolder; }
diff --git a/package/inc/ZipPackageStream.hxx b/package/inc/ZipPackageStream.hxx
index 194ff729adbe..91beaf276719 100644
--- a/package/inc/ZipPackageStream.hxx
+++ b/package/inc/ZipPackageStream.hxx
@@ -89,7 +89,7 @@ public:
sal_Int32 GetStartKeyGenID() const;
sal_Int32 GetEncryptionAlgorithm() const;
- sal_Int32 GetBlockSize() const;
+ sal_Int32 GetIVSize() const;
void SetToBeCompressed (bool bNewValue) { m_bToBeCompressed = bNewValue;}
void SetIsEncrypted (bool bNewValue) { m_bIsEncrypted = bNewValue;}
diff --git a/package/source/manifest/ManifestDefines.hxx b/package/source/manifest/ManifestDefines.hxx
index 48c06a362261..ae2095f5aab5 100644
--- a/package/source/manifest/ManifestDefines.hxx
+++ b/package/source/manifest/ManifestDefines.hxx
@@ -86,6 +86,9 @@ inline constexpr OUString BLOWFISH_URL = u"urn:oasis:names:tc:opendocument:xmlns
inline constexpr OUString AES128_URL = u"http://www.w3.org/2001/04/xmlenc#aes128-cbc"_ustr;
inline constexpr OUString AES192_URL = u"http://www.w3.org/2001/04/xmlenc#aes192-cbc"_ustr;
inline constexpr OUString AES256_URL = u"http://www.w3.org/2001/04/xmlenc#aes256-cbc"_ustr;
+inline constexpr OUString AESGCM128_URL = u"http://www.w3.org/2009/xmlenc11#aes128-gcm"_ustr;
+inline constexpr OUString AESGCM192_URL = u"http://www.w3.org/2009/xmlenc11#aes192-gcm"_ustr;
+inline constexpr OUString AESGCM256_URL = u"http://www.w3.org/2009/xmlenc11#aes256-gcm"_ustr;
inline constexpr OUString PBKDF2_NAME = u"PBKDF2"_ustr;
inline constexpr OUString PGP_NAME = u"PGP"_ustr;
diff --git a/package/source/manifest/ManifestExport.cxx b/package/source/manifest/ManifestExport.cxx
index be1d21114c1a..9921b1bad8c8 100644
--- a/package/source/manifest/ManifestExport.cxx
+++ b/package/source/manifest/ManifestExport.cxx
@@ -381,6 +381,15 @@ ManifestExport::ManifestExport( uno::Reference< xml::sax::XDocumentHandler > con
sEncAlgName = sAES256_URL;
}
+ else if (nEncAlgID == xml::crypto::CipherID::AES_GCM_W3C)
+ {
+ SAL_WARN_IF(nDerivedKeySize != 32, "package.manifest", "Unexpected key size is provided!");
+ if (nDerivedKeySize != 32)
+ {
+ throw uno::RuntimeException(THROW_WHERE "Unexpected key size is provided!");
+ }
+ sEncAlgName = AESGCM256_URL;
+ }
else if ( nEncAlgID == xml::crypto::CipherID::BLOWFISH_CFB_8 )
{
sEncAlgName = sBlowfish_Name;
diff --git a/package/source/manifest/ManifestImport.cxx b/package/source/manifest/ManifestImport.cxx
index 195324fdbe2a..b7aa57f99ff1 100644
--- a/package/source/manifest/ManifestImport.cxx
+++ b/package/source/manifest/ManifestImport.cxx
@@ -21,6 +21,7 @@
#include "ManifestDefines.hxx"
#include <PackageConstants.hxx>
#include <osl/diagnose.h>
+#include <sal/log.hxx>
#include <com/sun/star/xml/sax/XAttributeList.hpp>
#include <com/sun/star/xml/crypto/DigestID.hpp>
#include <com/sun/star/xml/crypto/CipherID.hpp>
@@ -184,6 +185,22 @@ void ManifestImport::doAlgorithm(StringHashMap &rConvertedAttribs)
if ( aString == BLOWFISH_NAME || aString == BLOWFISH_URL ) {
aSequence[PKG_MNFST_ENCALG].Name = gsEncryptionAlgProperty;
aSequence[PKG_MNFST_ENCALG].Value <<= xml::crypto::CipherID::BLOWFISH_CFB_8;
+ } else if (aString == AESGCM256_URL) {
+ aSequence[PKG_MNFST_ENCALG].Name = gsEncryptionAlgProperty;
+ aSequence[PKG_MNFST_ENCALG].Value <<= xml::crypto::CipherID::AES_GCM_W3C;
+ SAL_INFO_IF(nDerivedKeySize != 0 && nDerivedKeySize != 32, "package.manifest", "Unexpected derived key length!");
+ SAL_WARN_IF(nDerivedKeySize != 0 && nDerivedKeySize != 32, "package.manifest", "Unexpected derived key length!");
+ nDerivedKeySize = 32;
+ } else if (aString == AESGCM192_URL) {
+ aSequence[PKG_MNFST_ENCALG].Name = gsEncryptionAlgProperty;
+ aSequence[PKG_MNFST_ENCALG].Value <<= xml::crypto::CipherID::AES_GCM_W3C;
+ SAL_INFO_IF(nDerivedKeySize != 0 && nDerivedKeySize != 24, "package.manifest", "Unexpected derived key length!");
+ nDerivedKeySize = 24;
+ } else if (aString == AESGCM128_URL) {
+ aSequence[PKG_MNFST_ENCALG].Name = gsEncryptionAlgProperty;
+ aSequence[PKG_MNFST_ENCALG].Value <<= xml::crypto::CipherID::AES_GCM_W3C;
+ SAL_INFO_IF(nDerivedKeySize != 0 && nDerivedKeySize != 16, "package.manifest", "Unexpected derived key length!");
+ nDerivedKeySize = 16;
} else if ( aString == AES256_URL ) {
aSequence[PKG_MNFST_ENCALG].Name = gsEncryptionAlgProperty;
aSequence[PKG_MNFST_ENCALG].Value <<= xml::crypto::CipherID::AES_CBC_W3C_PADDING;
diff --git a/package/source/zipapi/XUnbufferedStream.cxx b/package/source/zipapi/XUnbufferedStream.cxx
index e3c31d5fca1c..bd2cf4d72d72 100644
--- a/package/source/zipapi/XUnbufferedStream.cxx
+++ b/package/source/zipapi/XUnbufferedStream.cxx
@@ -93,6 +93,7 @@ XUnbufferedStream::XUnbufferedStream(
if ( bMustDecrypt )
{
m_xCipherContext = ZipFile::StaticGetCipher( xContext, rData, false );
+ // this is only relevant when padding is used
mnBlockSize = ( rData->m_nEncAlg == xml::crypto::CipherID::AES_CBC_W3C_PADDING ? 16 : 1 );
}
diff --git a/package/source/zipapi/ZipFile.cxx b/package/source/zipapi/ZipFile.cxx
index 59bdcf8de891..f700b2722a71 100644
--- a/package/source/zipapi/ZipFile.cxx
+++ b/package/source/zipapi/ZipFile.cxx
@@ -187,7 +187,8 @@ uno::Reference< xml::crypto::XCipherContext > ZipFile::StaticGetCipher( const un
throw ZipIOException("Can not create derived key!" );
}
- if ( xEncryptionData->m_nEncAlg == xml::crypto::CipherID::AES_CBC_W3C_PADDING )
+ if (xEncryptionData->m_nEncAlg == xml::crypto::CipherID::AES_CBC_W3C_PADDING
+ || xEncryptionData->m_nEncAlg == xml::crypto::CipherID::AES_GCM_W3C)
{
uno::Reference< uno::XComponentContext > xContext = xArgContext;
if ( !xContext.is() )
@@ -450,6 +451,9 @@ void CheckSequence( const uno::Sequence< sal_Int8 >& aSequence )
bool ZipFile::StaticHasValidPassword( const uno::Reference< uno::XComponentContext >& rxContext, const Sequence< sal_Int8 > &aReadBuffer, const ::rtl::Reference< EncryptionData > &rData )
{
+ if (rData->m_nEncAlg == xml::crypto::CipherID::AES_GCM_W3C)
+ return true; /*TODO fails because of tag*/
+
if ( !rData.is() || !rData->m_aKey.hasElements() )
return false;
diff --git a/package/source/zippackage/ZipPackage.cxx b/package/source/zippackage/ZipPackage.cxx
index 46e87f437c7b..aacb5cd22a45 100644
--- a/package/source/zippackage/ZipPackage.cxx
+++ b/package/source/zippackage/ZipPackage.cxx
@@ -1714,7 +1714,9 @@ void SAL_CALL ZipPackage::setPropertyValue( const OUString& aPropertyName, const
sal_Int32 nID = 0;
if ( !( rAlgorithm.Value >>= nID )
|| ( nID != xml::crypto::DigestID::SHA256 && nID != xml::crypto::DigestID::SHA1 ) )
- throw IllegalArgumentException(THROW_WHERE "Unexpected start key generation algorithm is provided!", uno::Reference< uno::XInterface >(), 2 );
+ {
+ throw IllegalArgumentException(THROW_WHERE "Unexpected start key generation algorithm is provided!", uno::Reference<uno::XInterface>(), 2);
+ }
m_nStartKeyGenerationID = nID;
}
@@ -1722,8 +1724,12 @@ void SAL_CALL ZipPackage::setPropertyValue( const OUString& aPropertyName, const
{
sal_Int32 nID = 0;
if ( !( rAlgorithm.Value >>= nID )
- || ( nID != xml::crypto::CipherID::AES_CBC_W3C_PADDING && nID != xml::crypto::CipherID::BLOWFISH_CFB_8 ) )
- throw IllegalArgumentException(THROW_WHERE "Unexpected start key generation algorithm is provided!", uno::Reference< uno::XInterface >(), 2 );
+ || (nID != xml::crypto::CipherID::AES_GCM_W3C
+ && nID != xml::crypto::CipherID::AES_CBC_W3C_PADDING
+ && nID != xml::crypto::CipherID::BLOWFISH_CFB_8))
+ {
+ throw IllegalArgumentException(THROW_WHERE "Unexpected encryption algorithm is provided!", uno::Reference<uno::XInterface>(), 2);
+ }
m_nCommonEncryptionID = nID;
}
@@ -1732,7 +1738,9 @@ void SAL_CALL ZipPackage::setPropertyValue( const OUString& aPropertyName, const
sal_Int32 nID = 0;
if ( !( rAlgorithm.Value >>= nID )
|| ( nID != xml::crypto::DigestID::SHA1_1K && nID != xml::crypto::DigestID::SHA256_1K ) )
- throw IllegalArgumentException(THROW_WHERE "Unexpected start key generation algorithm is provided!", uno::Reference< uno::XInterface >(), 2 );
+ {
+ throw IllegalArgumentException(THROW_WHERE "Unexpected checksum algorithm is provided!", uno::Reference<uno::XInterface>(), 2);
+ }
m_nChecksumDigestID = nID;
}
diff --git a/package/source/zippackage/ZipPackageStream.cxx b/package/source/zippackage/ZipPackageStream.cxx
index d3c80cec2dce..494d8aaa6efc 100644
--- a/package/source/zippackage/ZipPackageStream.cxx
+++ b/package/source/zippackage/ZipPackageStream.cxx
@@ -53,6 +53,7 @@
#include <rtl/random.h>
#include <sal/log.hxx>
+#include <o3tl/unreachable.hxx>
#include <comphelper/diagnose_ex.hxx>
#include <PackageConstants.hxx>
@@ -184,9 +185,19 @@ sal_Int32 ZipPackageStream::GetEncryptionAlgorithm() const
return m_nImportedEncryptionAlgorithm ? m_nImportedEncryptionAlgorithm : m_rZipPackage.GetEncAlgID();
}
-sal_Int32 ZipPackageStream::GetBlockSize() const
+sal_Int32 ZipPackageStream::GetIVSize() const
{
- return GetEncryptionAlgorithm() == css::xml::crypto::CipherID::AES_CBC_W3C_PADDING ? 16 : 8;
+ switch (GetEncryptionAlgorithm())
+ {
+ case css::xml::crypto::CipherID::BLOWFISH_CFB_8:
+ return 8;
+ case css::xml::crypto::CipherID::AES_CBC_W3C_PADDING:
+ return 16;
+ case css::xml::crypto::CipherID::AES_GCM_W3C:
+ return 12;
+ default:
+ O3TL_UNREACHABLE;
+ }
}
::rtl::Reference<EncryptionData> ZipPackageStream::GetEncryptionData(Bugs const bugs)
@@ -567,7 +578,9 @@ bool ZipPackageStream::saveChild(
{
if ( bToBeEncrypted && !bTransportOwnEncrStreamAsRaw )
{
- uno::Sequence < sal_Int8 > aSalt( 16 ), aVector( GetBlockSize() );
+ uno::Sequence<sal_Int8> aSalt(16);
+ // note: for GCM it's particularly important that IV is unique
+ uno::Sequence<sal_Int8> aVector(GetIVSize());
rtl_random_getBytes ( rRandomPool, aSalt.getArray(), 16 );
rtl_random_getBytes ( rRandomPool, aVector.getArray(), aVector.getLength() );
if ( !m_bHaveOwnKey )