Allow selecting the tls backend to use in oox from configure

Change-Id: Ie82afb1f22caa0b02ddac256e2a0c2a49f19bb15
Reviewed-on: https://gerrit.libreoffice.org/3173
Reviewed-by: Miklos Vajna <vmiklos@suse.cz>
Tested-by: Miklos Vajna <vmiklos@suse.cz>
This commit is contained in:
Miguel Gomez 2013-04-02 15:36:12 +02:00 committed by Miklos Vajna
parent 7bcba4c910
commit 4be242ce6b
5 changed files with 152 additions and 0 deletions

View file

@ -568,6 +568,7 @@ export TDE_LIBS=$(gb_SPACE)@TDE_LIBS@
export TELEPATHY_CFLAGS=$(gb_SPACE)@TELEPATHY_CFLAGS@
export TELEPATHY_LIBS=$(gb_SPACE)@TELEPATHY_LIBS@
export THES_SYSTEM_DIR=@THES_SYSTEM_DIR@
export TLS=@TLS@
@x_Cygwin@ export TMP=@TMP_DIRECTORY@
export TMPDIR=@TEMP_DIRECTORY@
export TYPO_EXTENSION_PACK=@TYPO_EXTENSION_PACK@

View file

@ -0,0 +1,13 @@
#ifndef CONFIG_OOX_H
#define CONFIG_OOX_H
/*
Which TLS backend to use for cryptographic operations.
*/
#define USE_TLS_OPENSSL 0
#define USE_TLS_NSS 0
#endif

View file

@ -1271,6 +1271,17 @@ AC_ARG_WITH(package-format,
installed, msi. Example: --with-package-format="deb dmg"]),
,)
AC_ARG_WITH(tls,
AS_HELP_STRING([--with-tls],
[Decides which TLS/SSL and cryptographic implementations to use for
LibreOffice's code. Notice that this doesn't apply for depending
libraries like "neon", for example. Default is to use OpenSSL
although NSS is also possible. Notice that selecting NSS restricts
the usage of OpenSSL in LO's code but selecting OpenSSL doesn't
restrict by now the usage of NSS in LO's code. Possible values:
openssl, nss. Example: --with-tls="nss"]),
,)
AC_ARG_WITH(system-libs,
AS_HELP_STRING([--with-system-libs],
[Use libraries already on system -- enables all --with-system-* flags.]),
@ -8091,6 +8102,34 @@ AC_SUBST(WITH_MOZAB4WIN)
AC_SUBST(MSVC80_DLLS)
AC_SUBST(MSVC80_DLL_PATH)
dnl ===================================================================
dnl Check for TLS/SSL and cryptographic implementation to use
dnl ===================================================================
AC_MSG_CHECKING([which TLS/SSL and cryptographic implementation to use])
if test -n "$with_tls"; then
case $with_tls in
openssl)
AC_DEFINE(USE_TLS_OPENSSL)
TLS=OPENSSL
;;
nss)
AC_DEFINE(USE_TLS_NSS)
TLS=NSS
;;
*)
AC_MSG_ERROR([unsupported implementation $with_tls. Supported are:
openssl - OpenSSL
nss - Mozilla's Network Security Services (NSS)
])
;;
esac
else
AC_DEFINE(USE_TLS_OPENSSL)
TLS=OPENSSL
fi
AC_MSG_RESULT([$TLS])
AC_SUBST(TLS)
dnl ===================================================================
dnl Check for system NSS
dnl ===================================================================
@ -11805,6 +11844,7 @@ AC_CONFIG_HEADERS([config_host/config_global.h])
AC_CONFIG_HEADERS([config_host/config_graphite.h])
AC_CONFIG_HEADERS([config_host/config_kde4.h])
AC_CONFIG_HEADERS([config_host/config_mingw.h])
AC_CONFIG_HEADERS([config_host/config_oox.h])
AC_CONFIG_HEADERS([config_host/config_telepathy.h])
AC_CONFIG_HEADERS([config_host/config_typesizes.h])
AC_CONFIG_HEADERS([config_host/config_vclplug.h])

View file

@ -81,11 +81,21 @@ $(eval $(call gb_Library_use_libraries,oox,\
$(gb_UWINAPI) \
))
ifeq ($(TLS),OPENSSL)
$(eval $(call gb_Library_use_externals,oox,\
boost_headers \
openssl \
openssl_headers \
))
else
ifeq ($(TLS),NSS)
$(eval $(call gb_Library_use_externals,oox,\
boost_headers \
plc4 \
nss3 \
))
endif
endif
$(eval $(call gb_Library_set_componentfile,oox,oox/util/oox))

View file

@ -19,11 +19,18 @@
#include "oox/core/filterdetect.hxx"
#include <config_oox.h>
#include <com/sun/star/io/TempFile.hpp>
#include <com/sun/star/io/XStream.hpp>
#include <comphelper/docpasswordhelper.hxx>
#include <comphelper/mediadescriptor.hxx>
#if USE_TLS_OPENSSL
#include <openssl/evp.h>
#endif // USE_TLS_OPENSSL
#if USE_TLS_NSS
#include <nss.h>
#include <pk11pub.h>
#endif // USE_TLS_NSS
#include <rtl/digest.h>
#include "oox/core/fastparser.hxx"
#include "oox/helper/attributelist.hxx"
@ -373,6 +380,7 @@ bool lclCheckEncryptionData( const sal_uInt8* pnKey, sal_uInt32 nKeySize, const
if ( nKeySize == 16 && nVerifierSize == 16 && nVerifierHashSize == 32 )
{
// check password
#if USE_TLS_OPENSSL
EVP_CIPHER_CTX aes_ctx;
EVP_CIPHER_CTX_init( &aes_ctx );
EVP_DecryptInit_ex( &aes_ctx, EVP_aes_128_ecb(), 0, pnKey, 0 );
@ -392,6 +400,37 @@ bool lclCheckEncryptionData( const sal_uInt8* pnKey, sal_uInt32 nKeySize, const
/*int*/ EVP_DecryptUpdate( &aes_ctx, pnTmpVerifierHash, &nOutLen, pnVerifierHash, nVerifierHashSize );
EVP_CIPHER_CTX_cleanup( &aes_ctx );
#endif // USE_TLS_OPENSSL
#if USE_TLS_NSS
PK11SlotInfo *aSlot( PK11_GetBestSlot( CKM_AES_ECB, NULL ) );
sal_uInt8 *key( new sal_uInt8[ nKeySize ] );
(void) memcpy( key, pnKey, nKeySize * sizeof(sal_uInt8) );
SECItem keyItem;
keyItem.type = siBuffer;
keyItem.data = key;
keyItem.len = nKeySize;
PK11SymKey *symKey( PK11_ImportSymKey( aSlot, CKM_AES_ECB, PK11_OriginUnwrap, CKA_ENCRYPT, &keyItem, NULL ) );
SECItem *secParam( PK11_ParamFromIV( CKM_AES_ECB, NULL ) );
PK11Context *encContext( PK11_CreateContextBySymKey( CKM_AES_ECB, CKA_DECRYPT, symKey, secParam ) );
int nOutLen(0);
sal_uInt8 pnTmpVerifier[ 16 ];
(void) memset( pnTmpVerifier, 0, sizeof(pnTmpVerifier) );
PK11_CipherOp( encContext, pnTmpVerifier, &nOutLen, sizeof(pnTmpVerifier), const_cast<sal_uInt8*>(pnVerifier), nVerifierSize );
sal_uInt8 pnTmpVerifierHash[ 32 ];
(void) memset( pnTmpVerifierHash, 0, sizeof(pnTmpVerifierHash) );
PK11_CipherOp( encContext, pnTmpVerifierHash, &nOutLen, sizeof(pnTmpVerifierHash), const_cast<sal_uInt8*>(pnVerifierHash), nVerifierHashSize );
PK11_DestroyContext( encContext, PR_TRUE );
PK11_FreeSymKey( symKey );
SECITEM_FreeItem( secParam, PR_TRUE );
delete[] key;
#endif // USE_TLS_NSS
rtlDigest aDigest = rtl_digest_create( rtl_Digest_AlgorithmSHA1 );
rtl_digest_update( aDigest, pnTmpVerifier, sizeof( pnTmpVerifier ) );
@ -552,6 +591,11 @@ Reference< XInputStream > FilterDetect::extractUnencryptedPackage( MediaDescript
if( bImplemented )
{
#if USE_TLS_NSS
// Initialize NSS, database functions are not needed
NSS_NoDB_Init( NULL );
#endif // USE_TLS_NSS
/* "VelvetSweatshop" is the built-in default encryption
password used by MS Excel for the "workbook protection"
feature with password. Try this first before prompting the
@ -579,10 +623,31 @@ Reference< XInputStream > FilterDetect::extractUnencryptedPackage( MediaDescript
BinaryXOutputStream aDecryptedPackage( xDecryptedPackage, true );
BinaryXInputStream aEncryptedPackage( xEncryptedPackage, true );
#if USE_TLS_OPENSSL
EVP_CIPHER_CTX aes_ctx;
EVP_CIPHER_CTX_init( &aes_ctx );
EVP_DecryptInit_ex( &aes_ctx, EVP_aes_128_ecb(), 0, aVerifier.getKey(), 0 );
EVP_CIPHER_CTX_set_padding( &aes_ctx, 0 );
#endif // USE_TLS_OPENSSL
#if USE_TLS_NSS
// Retrieve the valid key so we can get its size later
SequenceAsHashMap aHashData( aEncryptionData );
Sequence<sal_Int8> validKey( aHashData.getUnpackedValueOrDefault( OUString("AES128EncryptionKey"), Sequence<sal_Int8>() ) );
PK11SlotInfo *aSlot( PK11_GetBestSlot( CKM_AES_ECB, NULL ) );
sal_uInt8 *key = new sal_uInt8[ validKey.getLength() ];
(void) memcpy( key, aVerifier.getKey(), validKey.getLength() );
SECItem keyItem;
keyItem.type = siBuffer;
keyItem.data = key;
keyItem.len = validKey.getLength();
PK11SymKey *symKey( PK11_ImportSymKey( aSlot, CKM_AES_ECB, PK11_OriginUnwrap, CKA_ENCRYPT, &keyItem, NULL ) );
SECItem *secParam( PK11_ParamFromIV( CKM_AES_ECB, NULL ) );
PK11Context *encContext( PK11_CreateContextBySymKey( CKM_AES_ECB, CKA_DECRYPT, symKey, secParam ) );
#endif // USE_TLS_NSS
sal_uInt8 pnInBuffer[ 1024 ];
sal_uInt8 pnOutBuffer[ 1024 ];
@ -591,13 +656,36 @@ Reference< XInputStream > FilterDetect::extractUnencryptedPackage( MediaDescript
aEncryptedPackage.skip( 8 ); // decrypted size
while( (nInLen = aEncryptedPackage.readMemory( pnInBuffer, sizeof( pnInBuffer ) )) > 0 )
{
#if USE_TLS_OPENSSL
EVP_DecryptUpdate( &aes_ctx, pnOutBuffer, &nOutLen, pnInBuffer, nInLen );
#endif // USE_TLS_OPENSSL
#if USE_TLS_NSS
PK11_CipherOp( encContext, pnOutBuffer, &nOutLen, sizeof(pnOutBuffer), pnInBuffer, nInLen );
#endif // USE_TLS_NSS
aDecryptedPackage.writeMemory( pnOutBuffer, nOutLen );
}
#if USE_TLS_OPENSSL
EVP_DecryptFinal_ex( &aes_ctx, pnOutBuffer, &nOutLen );
#endif // USE_TLS_OPENSSL
#if USE_TLS_NSS
uint final;
PK11_DigestFinal( encContext, pnOutBuffer, &final, nInLen - nOutLen );
nOutLen = final;
#endif // USE_TLS_NSS
aDecryptedPackage.writeMemory( pnOutBuffer, nOutLen );
#if USE_TLS_OPENSSL
EVP_CIPHER_CTX_cleanup( &aes_ctx );
#endif // USE_TLS_OPENSSL
#if USE_TLS_NSS
PK11_DestroyContext( encContext, PR_TRUE );
PK11_FreeSymKey( symKey );
SECITEM_FreeItem( secParam, PR_TRUE );
delete[] key;
#endif // USE_TLS_NSS
xDecryptedPackage->flush();
aDecryptedPackage.seekToStart();