xref: /trunk/main/oox/source/core/encryption.cxx (revision 244f2bcc)
1 /**************************************************************
2  *
3  * Licensed to the Apache Software Foundation (ASF) under one
4  * or more contributor license agreements.  See the NOTICE file
5  * distributed with this work for additional information
6  * regarding copyright ownership.  The ASF licenses this file
7  * to you under the Apache License, Version 2.0 (the
8  * "License"); you may not use this file except in compliance
9  * with the License.  You may obtain a copy of the License at
10  *
11  *   http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing,
14  * software distributed under the License is distributed on an
15  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16  * KIND, either express or implied.  See the License for the
17  * specific language governing permissions and limitations
18  * under the License.
19  *
20  *************************************************************/
21 
22 
23 
24 #include "oox/core/encryption.hxx"
25 #include "oox/core/fastparser.hxx"
26 #include "oox/helper/attributelist.hxx"
27 #include "oox/helper/helper.hxx"
28 #include "oox/helper/openssl_wrapper.hxx"
29 
30 #include <rtl/digest.h>
31 #include <cppuhelper/implbase1.hxx>
32 #include <openssl/evp.h>
33 
34 #include <com/sun/star/io/XStream.hpp>
35 
36 
37 
38 namespace oox {
39 namespace core {
40 
41 // ============================================================================
42 
43 using namespace ::com::sun::star::beans;
44 using namespace ::com::sun::star::uno;
45 using namespace ::com::sun::star::xml::sax;
46 
47 using ::com::sun::star::io::XInputStream;
48 using ::comphelper::SequenceAsHashMap;
49 using ::rtl::OUString;
50 using ::std::vector;
51 
52 // ============================================================================
53 
54 
55 /* =========================================================================== */
56 /*  Kudos to Caolan McNamara who provided the core decryption implementation   */
57 /*  of Standard Encryption (MS-OFFCRYPTO section 2.3.4.5).                     */
58 /* =========================================================================== */
59 
60 #define ENCRYPTINFO_CRYPTOAPI        0x00000004U
61 #define ENCRYPTINFO_DOCPROPS         0x00000008U
62 #define ENCRYPTINFO_EXTERNAL         0x00000010U
63 #define ENCRYPTINFO_AES              0x00000020U
64 
65 #define ENCRYPT_ALGO_AES128          0x0000660EU
66 #define ENCRYPT_ALGO_AES192          0x0000660FU
67 #define ENCRYPT_ALGO_AES256          0x00006610U
68 #define ENCRYPT_ALGO_RC4             0x00006801U
69 
70 #define ENCRYPT_HASH_SHA1            0x00008004U
71 
72 class StandardEncryptionInfo : public EncryptionInfo
73 {
74 public:
75     StandardEncryptionInfo( BinaryInputStream& rStrm ) throw ( Exception );
~StandardEncryptionInfo()76     ~StandardEncryptionInfo() {}
77     bool isImplemented();
78     Sequence< NamedValue > verifyPassword( const OUString& rPassword ) throw ( Exception );
79     bool verifyEncryptionData( const Sequence< NamedValue >& rEncryptionData ) throw ( Exception );
80     bool checkEncryptionData( const sal_uInt8* pnKey, sal_uInt32 nKeySize, const sal_uInt8* pnVerifier, sal_uInt32 nVerifierSize, const sal_uInt8* pnVerifierHash, sal_uInt32 nVerifierHashSize ) throw ( Exception );
81     void decryptStream( BinaryXInputStream &aEncryptedPackage, BinaryXOutputStream &aDecryptedPackage ) throw ( Exception );
82 
83 private:
84     sal_uInt8           mpnSalt[ 16 ];
85     sal_uInt8           mpnEncrVerifier[ 16 ];
86     sal_uInt8           mpnEncrVerifierHash[ 32 ];
87     sal_uInt32          mnFlags;
88     sal_uInt32          mnAlgorithmId;
89     sal_uInt32          mnAlgorithmIdHash;
90     sal_uInt32          mnKeySize;
91     sal_uInt32          mnSaltSize;
92     sal_uInt32          mnVerifierHashSize;
93     vector< sal_uInt8>  encryptionKey;
94 };
95 
StandardEncryptionInfo(BinaryInputStream & rStrm)96 StandardEncryptionInfo::StandardEncryptionInfo( BinaryInputStream& rStrm ) throw ( Exception )
97 {
98     char msg[ 1024 ];
99     rStrm >> mnFlags;
100     if( getFlag( mnFlags, (sal_uInt32) ENCRYPTINFO_EXTERNAL ) )
101         throw Exception( OUString::createFromAscii( "EncryptionInfo::readEncryptionInfo() error: \"Extensible encryption\" is not currently supported, please report" ), Reference< XInterface >() );
102 
103     sal_uInt32 nHeaderSize, nRepeatedFlags;
104     rStrm >> nHeaderSize >> nRepeatedFlags;
105     if( nHeaderSize < 20 )
106     {
107         snprintf( msg, sizeof( msg ), "EncryptionInfo::readEncryptionInfo() error: header size %u is too short", nHeaderSize );
108         throw Exception( OUString::createFromAscii( msg ), Reference< XInterface >() );
109     }
110     if( nRepeatedFlags != mnFlags )
111         throw Exception( OUString::createFromAscii( "EncryptionInfo::readEncryptionInfo() error: flags don't match" ), Reference< XInterface>() );
112 
113     rStrm.skip( 4 );
114     rStrm >> mnAlgorithmId >> mnAlgorithmIdHash >> mnKeySize;
115     rStrm.skip( nHeaderSize - 20 );
116     rStrm >> mnSaltSize;
117     if( mnSaltSize != 16 )
118     {
119         snprintf( msg, sizeof( msg ), "EncryptionInfo::readEncryptionInfo() error: salt size is %u instead of 16", mnSaltSize );
120         throw Exception( OUString::createFromAscii( msg ), Reference< XInterface >() );
121     }
122 
123     rStrm.readMemory( mpnSalt, 16 );
124     rStrm.readMemory( mpnEncrVerifier, 16 );
125     rStrm >> mnVerifierHashSize;
126     rStrm.readMemory( mpnEncrVerifierHash, 32 );
127     if( rStrm.isEof() )
128         throw Exception( OUString::createFromAscii( "EncryptionInfo::readEncryptionInfo() error: standard encryption header too short" ), Reference< XInterface >() );
129 }
130 
isImplemented()131 bool StandardEncryptionInfo::isImplemented()
132 {
133     return getFlag( mnFlags, (sal_uInt32) ENCRYPTINFO_CRYPTOAPI ) &&
134         getFlag( mnFlags, (sal_uInt32) ENCRYPTINFO_AES ) &&
135         // algorithm ID 0 defaults to AES128 too, if ENCRYPTINFO_AES flag is set
136        ( ( mnAlgorithmId == 0 ) || ( mnAlgorithmId == ENCRYPT_ALGO_AES128 ) ) &&
137        // hash algorithm ID 0 defaults to SHA-1 too
138        ( ( mnAlgorithmIdHash == 0 ) || ( mnAlgorithmIdHash == ENCRYPT_HASH_SHA1 ) ) &&
139        ( mnVerifierHashSize == 20 );
140 }
141 
deriveKey(const sal_uInt8 * pnHash,sal_uInt32 nHashLen,sal_uInt8 * pnKeyDerived,sal_uInt32 nRequiredKeyLen)142 static void deriveKey( const sal_uInt8* pnHash, sal_uInt32 nHashLen, sal_uInt8* pnKeyDerived, sal_uInt32 nRequiredKeyLen )
143 {
144     sal_uInt8 pnBuffer[ 64 ];
145     memset( pnBuffer, 0x36, sizeof( pnBuffer ) );
146     for( sal_uInt32 i = 0; i < nHashLen; ++i )
147         pnBuffer[ i ] ^= pnHash[ i ];
148 
149     rtlDigest aDigest = rtl_digest_create( rtl_Digest_AlgorithmSHA1 );
150     rtlDigestError aError = rtl_digest_update( aDigest, pnBuffer, sizeof( pnBuffer ) );
151     sal_uInt8 pnX1[ RTL_DIGEST_LENGTH_SHA1 ];
152     aError = rtl_digest_get( aDigest, pnX1, RTL_DIGEST_LENGTH_SHA1 );
153     rtl_digest_destroy( aDigest );
154 
155     memset( pnBuffer, 0x5C, sizeof( pnBuffer ) );
156     for( sal_uInt32 i = 0; i < nHashLen; ++i )
157         pnBuffer[ i ] ^= pnHash[ i ];
158 
159     aDigest = rtl_digest_create( rtl_Digest_AlgorithmSHA1 );
160     aError = rtl_digest_update( aDigest, pnBuffer, sizeof( pnBuffer ) );
161     sal_uInt8 pnX2[ RTL_DIGEST_LENGTH_SHA1 ];
162     aError = rtl_digest_get( aDigest, pnX2, RTL_DIGEST_LENGTH_SHA1 );
163     rtl_digest_destroy( aDigest );
164 
165     if( nRequiredKeyLen > RTL_DIGEST_LENGTH_SHA1 )
166     {
167         memcpy( pnKeyDerived + RTL_DIGEST_LENGTH_SHA1, pnX2, nRequiredKeyLen - RTL_DIGEST_LENGTH_SHA1 );
168         nRequiredKeyLen = RTL_DIGEST_LENGTH_SHA1;
169     }
170     memcpy( pnKeyDerived, pnX1, nRequiredKeyLen );
171 }
172 
verifyPassword(const OUString & rPassword)173 Sequence< NamedValue > StandardEncryptionInfo::verifyPassword( const OUString& rPassword ) throw ( Exception )
174 {
175     size_t nBufferSize = mnSaltSize + 2 * rPassword.getLength();
176     sal_uInt8* pnBuffer = new sal_uInt8[ nBufferSize ];
177     memcpy( pnBuffer, mpnSalt, mnSaltSize );
178 
179     sal_uInt8* pnPasswordLoc = pnBuffer + mnSaltSize;
180     const sal_Unicode* pStr = rPassword.getStr();
181     for( sal_Int32 i = 0, nLen = rPassword.getLength(); i < nLen; ++i, ++pStr, pnPasswordLoc += 2 )
182         ByteOrderConverter::writeLittleEndian( pnPasswordLoc, static_cast< sal_uInt16 >( *pStr ) );
183 
184     rtlDigest aDigest = rtl_digest_create( rtl_Digest_AlgorithmSHA1 );
185     rtlDigestError aError = rtl_digest_update( aDigest, pnBuffer, nBufferSize );
186     delete[] pnBuffer;
187 
188     size_t nHashSize = RTL_DIGEST_LENGTH_SHA1 + 4;
189     sal_uInt8* pnHash = new sal_uInt8[ nHashSize ];
190     aError = rtl_digest_get( aDigest, pnHash + 4, RTL_DIGEST_LENGTH_SHA1 );
191     rtl_digest_destroy( aDigest );
192 
193     for( sal_uInt32 i = 0; i < 50000; ++i )
194     {
195         ByteOrderConverter::writeLittleEndian( pnHash, i );
196         aDigest = rtl_digest_create( rtl_Digest_AlgorithmSHA1 );
197         aError = rtl_digest_update( aDigest, pnHash, nHashSize );
198         aError = rtl_digest_get( aDigest, pnHash + 4, RTL_DIGEST_LENGTH_SHA1 );
199         rtl_digest_destroy( aDigest );
200     }
201 
202     memmove( pnHash, pnHash + 4, RTL_DIGEST_LENGTH_SHA1 );
203     memset( pnHash + RTL_DIGEST_LENGTH_SHA1, 0, 4 );
204     aDigest = rtl_digest_create( rtl_Digest_AlgorithmSHA1 );
205     aError = rtl_digest_update( aDigest, pnHash, nHashSize );
206     aError = rtl_digest_get( aDigest, pnHash, RTL_DIGEST_LENGTH_SHA1 );
207     rtl_digest_destroy( aDigest );
208 
209     vector< sal_uInt8 > key( mnKeySize / 8 );
210     deriveKey( pnHash, RTL_DIGEST_LENGTH_SHA1, &key[ 0 ], key.size() );
211     delete[] pnHash;
212 
213     Sequence< NamedValue > aResult;
214     if( checkEncryptionData( &key[ 0 ], key.size(), mpnEncrVerifier, sizeof( mpnEncrVerifier ), mpnEncrVerifierHash, sizeof( mpnEncrVerifierHash ) ) )
215     {
216         SequenceAsHashMap aEncryptionData;
217         aEncryptionData[ CREATE_OUSTRING( "AES128EncryptionKey" ) ] <<= Sequence< sal_Int8 >( reinterpret_cast< const sal_Int8* >( &key[ 0 ] ), key.size() );
218         aEncryptionData[ CREATE_OUSTRING( "AES128EncryptionSalt" ) ] <<= Sequence< sal_Int8 >( reinterpret_cast< const sal_Int8* >( mpnSalt ), mnSaltSize );
219         aEncryptionData[ CREATE_OUSTRING( "AES128EncryptionVerifier" ) ] <<= Sequence< sal_Int8 >( reinterpret_cast< const sal_Int8* >( mpnEncrVerifier ), sizeof( mpnEncrVerifier ) );
220         aEncryptionData[ CREATE_OUSTRING( "AES128EncryptionVerifierHash" ) ] <<= Sequence< sal_Int8 >( reinterpret_cast< const sal_Int8* >( mpnEncrVerifierHash ), sizeof( mpnEncrVerifierHash ) );
221         encryptionKey = key;
222         aResult = aEncryptionData.getAsConstNamedValueList();
223     }
224 
225     return aResult;
226 }
227 
verifyEncryptionData(const Sequence<NamedValue> & rEncryptionData)228 bool StandardEncryptionInfo::verifyEncryptionData( const Sequence< NamedValue >& rEncryptionData ) throw ( Exception )
229 {
230     SequenceAsHashMap aHashData( rEncryptionData );
231     Sequence< sal_Int8 > aKey = aHashData.getUnpackedValueOrDefault( CREATE_OUSTRING( "AES128EncryptionKey" ), Sequence< sal_Int8 >() );
232     Sequence< sal_Int8 > aVerifier = aHashData.getUnpackedValueOrDefault( CREATE_OUSTRING( "AES128EncryptionVerifier" ), Sequence< sal_Int8 >() );
233     Sequence< sal_Int8 > aVerifierHash = aHashData.getUnpackedValueOrDefault( CREATE_OUSTRING( "AES128EncryptionVerifierHash" ), Sequence< sal_Int8 >() );
234     const sal_uInt8 *pnKey = reinterpret_cast< const sal_uInt8* >( aKey.getConstArray() );
235     sal_uInt32 nKeySize = aKey.getLength();
236     const sal_uInt8 *pnVerifier = reinterpret_cast< const sal_uInt8* >( aVerifier.getConstArray() );
237     sal_uInt32 nVerifierSize = aVerifier.getLength();
238     const sal_uInt8 *pnVerifierHash = reinterpret_cast< const sal_uInt8* >( aVerifierHash.getConstArray() );
239     sal_uInt32 nVerifierHashSize = aVerifierHash.getLength();
240     if( checkEncryptionData( pnKey, nKeySize, pnVerifier, nVerifierSize, pnVerifierHash, nVerifierHashSize ) )
241     {
242         encryptionKey = vector< sal_uInt8 >( &pnKey[ 0 ], &pnKey[ nKeySize ] );
243         return true;
244     }
245     else
246         return false;
247 }
248 
checkEncryptionData(const sal_uInt8 * pnKey,sal_uInt32 nKeySize,const sal_uInt8 * pnVerifier,sal_uInt32 nVerifierSize,const sal_uInt8 * pnVerifierHash,sal_uInt32 nVerifierHashSize)249 bool StandardEncryptionInfo::checkEncryptionData( const sal_uInt8* pnKey, sal_uInt32 nKeySize, const sal_uInt8* pnVerifier, sal_uInt32 nVerifierSize, const sal_uInt8* pnVerifierHash, sal_uInt32 nVerifierHashSize ) throw ( Exception )
250 {
251     bool bResult = false;
252 
253     // the only currently supported algorithm needs key size 128
254     if ( nKeySize == 16 && nVerifierSize == 16 && nVerifierHashSize == 32 )
255     {
256         // check password
257         EVP_CIPHER_CTX *aes_ctx;
258         aes_ctx = EVP_CIPHER_CTX_new();
259         if ( aes_ctx == NULL )
260             return false;
261         EVP_DecryptInit_ex( aes_ctx, EVP_aes_128_ecb(), 0, pnKey, 0 );
262         EVP_CIPHER_CTX_set_padding( aes_ctx, 0 );
263         int nOutLen = 0;
264         sal_uInt8 pnTmpVerifier[ 16 ];
265         (void) memset( pnTmpVerifier, 0, sizeof(pnTmpVerifier) );
266 
267         /*int*/ EVP_DecryptUpdate( aes_ctx, pnTmpVerifier, &nOutLen, pnVerifier, nVerifierSize );
268         EVP_CIPHER_CTX_free( aes_ctx );
269 
270         aes_ctx = EVP_CIPHER_CTX_new();
271         if ( aes_ctx == NULL )
272             return false;
273         EVP_DecryptInit_ex( aes_ctx, EVP_aes_128_ecb(), 0, pnKey, 0 );
274         EVP_CIPHER_CTX_set_padding( aes_ctx, 0 );
275         sal_uInt8 pnTmpVerifierHash[ 32 ];
276         (void) memset( pnTmpVerifierHash, 0, sizeof(pnTmpVerifierHash) );
277 
278         /*int*/ EVP_DecryptUpdate( aes_ctx, pnTmpVerifierHash, &nOutLen, pnVerifierHash, nVerifierHashSize );
279         EVP_CIPHER_CTX_free( aes_ctx );
280 
281         rtlDigest aDigest = rtl_digest_create( rtl_Digest_AlgorithmSHA1 );
282         rtlDigestError aError = rtl_digest_update( aDigest, pnTmpVerifier, sizeof( pnTmpVerifier ) );
283         sal_uInt8 pnSha1Hash[ RTL_DIGEST_LENGTH_SHA1 ];
284         aError = rtl_digest_get( aDigest, pnSha1Hash, RTL_DIGEST_LENGTH_SHA1 );
285         rtl_digest_destroy( aDigest );
286 
287         bResult = ( memcmp( pnSha1Hash, pnTmpVerifierHash, RTL_DIGEST_LENGTH_SHA1 ) == 0 );
288     }
289 
290     return bResult;
291 }
292 
decryptStream(BinaryXInputStream & aEncryptedPackage,BinaryXOutputStream & aDecryptedPackage)293 void StandardEncryptionInfo::decryptStream( BinaryXInputStream &aEncryptedPackage, BinaryXOutputStream &aDecryptedPackage ) throw ( Exception )
294 {
295     EVP_CIPHER_CTX *aes_ctx;
296     aes_ctx = EVP_CIPHER_CTX_new();
297     if ( aes_ctx == NULL )
298         throw Exception();
299     EVP_DecryptInit_ex( aes_ctx, EVP_aes_128_ecb(), 0, &encryptionKey[ 0 ], 0 );
300     EVP_CIPHER_CTX_set_padding( aes_ctx, 0 );
301 
302     sal_uInt8 pnInBuffer[ 1024 ];
303     sal_uInt8 pnOutBuffer[ 1024 ];
304     sal_Int32 nInLen;
305     int nOutLen;
306     aEncryptedPackage.skip( 8 ); // decrypted size
307     while( (nInLen = aEncryptedPackage.readMemory( pnInBuffer, sizeof( pnInBuffer ) )) > 0 )
308     {
309         EVP_DecryptUpdate( aes_ctx, pnOutBuffer, &nOutLen, pnInBuffer, nInLen );
310         aDecryptedPackage.writeMemory( pnOutBuffer, nOutLen );
311     }
312     EVP_DecryptFinal_ex( aes_ctx, pnOutBuffer, &nOutLen );
313     aDecryptedPackage.writeMemory( pnOutBuffer, nOutLen );
314 
315     EVP_CIPHER_CTX_free( aes_ctx );
316     aDecryptedPackage.flush();
317 }
318 
319 // ============================================================================
320 // "Agile" encryption, 2.3.4.10 of MS-OFFCRYPTO
321 // ============================================================================
322 
323 struct AgileKeyData
324 {
325     sal_Int32 saltSize;
326     sal_Int32 blockSize;
327     sal_Int32 keyBits;
328     sal_Int32 hashSize;
329     OUString cipherAlgorithm;
330     OUString cipherChaining;
331     OUString hashAlgorithm;
332     vector< sal_uInt8 > saltValue;
333 };
334 
335 struct AgileDataIntegrity
336 {
337     vector< sal_uInt8 > encryptedHmacKey;
338     vector< sal_uInt8 > encryptedHmacValue;
339 };
340 
341 struct AgilePasswordKeyEncryptor
342 {
343     sal_Int32 saltSize;
344     sal_Int32 blockSize;
345     sal_Int32 keyBits;
346     sal_Int32 hashSize;
347     OUString cipherAlgorithm;
348     OUString cipherChaining;
349     OUString hashAlgorithm;
350     vector< sal_uInt8 > saltValue;
351     sal_Int32 spinCount;
352     vector< sal_uInt8 > encryptedVerifierHashInput;
353     vector< sal_uInt8 > encryptedVerifierHashValue;
354     vector< sal_uInt8 > encryptedKeyValue;
355 };
356 
decodeBase64(OUString & base64,vector<sal_uInt8> & bytes)357 static bool decodeBase64( OUString& base64, vector< sal_uInt8 >& bytes )
358 {
359     ::rtl::OString base64Ascii = ::rtl::OUStringToOString( base64, RTL_TEXTENCODING_UTF8 );
360     const sal_uInt32 len = base64Ascii.getLength();
361     bytes.resize( (len + 3) / 4 * 3 );
362     int decodedSize = EVP_DecodeBlock( &bytes[ 0 ], reinterpret_cast< sal_uInt8 const * >( base64Ascii.getStr() ), len );
363     if ( decodedSize < 0 )
364         return false;
365     if ( len >= 2 && base64Ascii[ len-1 ] == '=' && base64Ascii[ len-2 ] == '=' )
366         decodedSize -= 2;
367     else if ( len >= 1 && base64Ascii[ len-1] == '=' )
368         decodedSize--;
369     bytes.resize( decodedSize );
370     return true;
371 }
372 
373 class AgileEncryptionInfo : public EncryptionInfo
374 {
375 public:
376     AgileEncryptionInfo( const Reference< XComponentContext >& context, Reference< XInputStream >& inputStream ) throw ( Exception );
~AgileEncryptionInfo()377     ~AgileEncryptionInfo() {}
isImplemented()378     bool isImplemented() { return true; } // FIXME
379     Sequence< NamedValue > verifyPassword( const OUString& rPassword ) throw ( Exception );
380     bool verifyEncryptionData( const Sequence< NamedValue >& rEncryptionData ) throw ( Exception );
381     void decryptStream( BinaryXInputStream &aEncryptedPackage, BinaryXOutputStream &aDecryptedPackage ) throw ( Exception );
382 
383 private:
384     AgileKeyData keyData;
385     AgileDataIntegrity dataIntegrity;
386     AgilePasswordKeyEncryptor passwordKeyEncryptor;
387     vector< sal_uInt8> encryptionKey;
388     vector< sal_uInt8> hmacKey;
389     vector< sal_uInt8> hmacValue;
390 };
391 
392 // A SAX handler that parses the XML from the "XmlEncryptionDescriptor" in the EncryptionInfo stream.
393 class AgileEncryptionHandler : public ::cppu::WeakImplHelper1< XFastDocumentHandler >
394 {
395 public:
AgileEncryptionHandler(AgileKeyData & aKeyData,AgileDataIntegrity & aDataIntegrity,AgilePasswordKeyEncryptor & aPasswordKeyEncryptor)396     AgileEncryptionHandler( AgileKeyData &aKeyData, AgileDataIntegrity &aDataIntegrity, AgilePasswordKeyEncryptor &aPasswordKeyEncryptor )
397     : keyData( aKeyData ),
398       dataIntegrity( aDataIntegrity ),
399       passwordKeyEncryptor( aPasswordKeyEncryptor )
400     {
401     }
402 
403     // XFastDocumentHandler
404     virtual void SAL_CALL startDocument() throw (SAXException, RuntimeException);
405     virtual void SAL_CALL endDocument() throw (SAXException, RuntimeException);
406     virtual void SAL_CALL setDocumentLocator( const Reference< XLocator >& xLocator ) throw (SAXException, RuntimeException);
407 
408     // XFastContextHandler
409     virtual void SAL_CALL startFastElement( sal_Int32 nElement, const Reference< XFastAttributeList >& Attribs ) throw (SAXException, RuntimeException);
410     virtual void SAL_CALL startUnknownElement( const OUString& Namespace, const OUString& Name, const Reference< XFastAttributeList >& Attribs ) throw (SAXException, RuntimeException);
411     virtual void SAL_CALL endFastElement( sal_Int32 Element ) throw (SAXException, RuntimeException);
412     virtual void SAL_CALL endUnknownElement( const OUString& Namespace, const OUString& Name ) throw (SAXException, RuntimeException);
413     virtual Reference< XFastContextHandler > SAL_CALL createFastChildContext( sal_Int32 Element, const Reference< XFastAttributeList >& Attribs ) throw (SAXException, RuntimeException);
414     virtual Reference< XFastContextHandler > SAL_CALL createUnknownChildContext( const OUString& Namespace, const OUString& Name, const Reference< XFastAttributeList >& Attribs ) throw (SAXException, RuntimeException);
415     virtual void SAL_CALL characters( const OUString& aChars ) throw (SAXException, RuntimeException);
416     virtual void SAL_CALL ignorableWhitespace( const OUString& aWhitespaces ) throw (SAXException, RuntimeException);
417     virtual void SAL_CALL processingInstruction( const OUString& aTarget, const OUString& aData ) throw (SAXException, RuntimeException);
418 
getLastError()419     OUString& getLastError() { return lastError; }
420 
421 private:
422     void parseKeyData( const AttributeList& attribs ) throw (SAXException, RuntimeException);
423     void parseDataIntegrity( const AttributeList& attribs ) throw (SAXException, RuntimeException);
424     void parseEncryptedKey( const AttributeList& attribs ) throw (SAXException, RuntimeException);
425 
426     vector< sal_Int32 > stack;
427     OUString lastError;
428     AgileKeyData &keyData;
429     AgileDataIntegrity &dataIntegrity;
430     AgilePasswordKeyEncryptor &passwordKeyEncryptor;
431 };
432 
startDocument()433 void AgileEncryptionHandler::startDocument()
434     throw ( SAXException, RuntimeException )
435 {
436 }
437 
endDocument()438 void AgileEncryptionHandler::endDocument()
439     throw ( SAXException, RuntimeException )
440 {
441 }
442 
setDocumentLocator(const Reference<XLocator> &)443 void AgileEncryptionHandler::setDocumentLocator( const Reference< XLocator >& )
444     throw ( SAXException, RuntimeException )
445 {
446 }
447 
startFastElement(sal_Int32 nElement,const Reference<XFastAttributeList> & attribs)448 void AgileEncryptionHandler::startFastElement( sal_Int32 nElement, const Reference< XFastAttributeList >& attribs )
449     throw( SAXException, RuntimeException )
450 {
451     switch ( nElement )
452     {
453         case ENCRYPTION_TOKEN( encryption ):
454         break;
455 
456         case ENCRYPTION_TOKEN( keyData ):
457             if ( stack.size() == 1 && (stack[ 0 ] == ENCRYPTION_TOKEN( encryption )) )
458                 parseKeyData( AttributeList( attribs ) );
459         break;
460 
461         case ENCRYPTION_TOKEN( dataIntegrity ):
462             if ( stack.size() == 1 && (stack[ 0 ] == ENCRYPTION_TOKEN( encryption )) )
463                 parseDataIntegrity( AttributeList ( attribs ) );
464         break;
465 
466         case ENCRYPTION_TOKEN( keyEncryptors ):
467         break;
468 
469         case ENCRYPTION_TOKEN( keyEncryptor ):
470         break;
471 
472         case KEY_ENCRYPTOR_PASSWORD_TOKEN( encryptedKey ):
473             if ( stack.size() == 3
474                 && (stack[ 0 ] == ENCRYPTION_TOKEN( encryption ))
475                 && (stack[ 1 ] == ENCRYPTION_TOKEN( keyEncryptors ))
476                 && (stack[ 2 ] == ENCRYPTION_TOKEN( keyEncryptor )) )
477                 parseEncryptedKey( AttributeList ( attribs ) );
478         break;
479     }
480     stack.push_back( nElement );
481 }
482 
startUnknownElement(const OUString &,const OUString &,const Reference<XFastAttributeList> &)483 void AgileEncryptionHandler::startUnknownElement( const OUString&, const OUString&, const Reference< XFastAttributeList >& )
484     throw( SAXException, RuntimeException )
485 {
486     stack.push_back( -1 );
487 }
488 
endFastElement(sal_Int32 nElement)489 void AgileEncryptionHandler::endFastElement( sal_Int32 nElement )
490     throw( SAXException, RuntimeException )
491 {
492     stack.pop_back();
493 }
494 
endUnknownElement(const OUString &,const OUString &)495 void AgileEncryptionHandler::endUnknownElement( const OUString&, const OUString& )
496     throw( SAXException, RuntimeException )
497 {
498     stack.pop_back();
499 }
500 
createFastChildContext(sal_Int32,const Reference<XFastAttributeList> &)501 Reference< XFastContextHandler > AgileEncryptionHandler::createFastChildContext( sal_Int32, const Reference< XFastAttributeList >& )
502     throw (SAXException, RuntimeException)
503 {
504     return this;
505 }
506 
createUnknownChildContext(const OUString &,const OUString &,const Reference<XFastAttributeList> &)507 Reference< XFastContextHandler > AgileEncryptionHandler::createUnknownChildContext( const OUString&, const OUString&, const Reference< XFastAttributeList >& )
508     throw (SAXException, RuntimeException)
509 {
510     return this;
511 }
512 
characters(const::rtl::OUString & rStr)513 void AgileEncryptionHandler::characters( const ::rtl::OUString& rStr )
514     throw( SAXException, RuntimeException )
515 {
516 }
517 
ignorableWhitespace(const::rtl::OUString & str)518 void AgileEncryptionHandler::ignorableWhitespace( const ::rtl::OUString& str )
519     throw( SAXException, RuntimeException )
520 {
521 }
522 
processingInstruction(const::rtl::OUString & aTarget,const::rtl::OUString & aData)523 void AgileEncryptionHandler::processingInstruction( const ::rtl::OUString& aTarget, const ::rtl::OUString& aData )
524     throw( SAXException, RuntimeException )
525 {
526 }
527 
parseKeyData(const AttributeList & attribs)528 void AgileEncryptionHandler::parseKeyData( const AttributeList& attribs )
529     throw ( SAXException, RuntimeException )
530 {
531     keyData.saltSize = attribs.getInteger( XML_saltSize, 0 );
532     keyData.blockSize = attribs.getInteger( XML_blockSize, 0 );
533     keyData.keyBits = attribs.getInteger( XML_keyBits, 0 );
534     keyData.hashSize = attribs.getInteger( XML_hashSize, 0 );
535     keyData.cipherAlgorithm = attribs.getString( XML_cipherAlgorithm, OUString() );
536     keyData.cipherChaining = attribs.getString( XML_cipherChaining, OUString() );
537     keyData.hashAlgorithm = attribs.getString( XML_hashAlgorithm, OUString() );
538 
539     OUString saltValue = attribs.getString( XML_saltValue, OUString() );
540     if( !decodeBase64( saltValue, keyData.saltValue ) )
541         lastError = OUString::createFromAscii( "Failed to base64 decode the keyData.saltValue " ) + saltValue;
542 }
543 
parseDataIntegrity(const AttributeList & attribs)544 void AgileEncryptionHandler::parseDataIntegrity( const AttributeList& attribs )
545     throw ( SAXException, RuntimeException )
546 {
547     OUString encryptedHmacKey = attribs.getString( XML_encryptedHmacKey, OUString() );
548     if( !decodeBase64( encryptedHmacKey, dataIntegrity.encryptedHmacKey ) )
549         lastError = OUString::createFromAscii( "Failed to base64 decode the dataIntegrity.encryptedHmacKey " ) + encryptedHmacKey;
550     OUString encryptedHmacValue = attribs.getString( XML_encryptedHmacValue, OUString() );
551     if( !decodeBase64( encryptedHmacValue, dataIntegrity.encryptedHmacValue ) )
552         lastError = OUString::createFromAscii( "Failed to base64 decode the dataIntegrity.encryptedHmacValue " ) + encryptedHmacValue;
553 }
554 
parseEncryptedKey(const AttributeList & attribs)555 void AgileEncryptionHandler::parseEncryptedKey( const AttributeList& attribs )
556     throw ( SAXException, RuntimeException )
557 {
558     passwordKeyEncryptor.spinCount = attribs.getInteger( XML_spinCount, 0 );
559     passwordKeyEncryptor.saltSize = attribs.getInteger( XML_saltSize, 0 );
560     passwordKeyEncryptor.blockSize = attribs.getInteger( XML_blockSize, 0 );
561     passwordKeyEncryptor.keyBits = attribs.getInteger( XML_keyBits, 0 );
562     passwordKeyEncryptor.hashSize = attribs.getInteger( XML_hashSize, 0 );
563     passwordKeyEncryptor.cipherAlgorithm = attribs.getString( XML_cipherAlgorithm, OUString() );
564     passwordKeyEncryptor.cipherChaining = attribs.getString( XML_cipherChaining, OUString() );
565     passwordKeyEncryptor.hashAlgorithm = attribs.getString( XML_hashAlgorithm, OUString() );
566     OUString saltValue = attribs.getString( XML_saltValue, OUString() );
567     if( !decodeBase64( saltValue, passwordKeyEncryptor.saltValue ) )
568         lastError = OUString::createFromAscii( "Failed to base64 decode the passwordKeyEncryptor.saltValue " ) + saltValue;
569     OUString encryptedVerifierHashInput = attribs.getString( XML_encryptedVerifierHashInput, OUString() );
570     if( !decodeBase64( encryptedVerifierHashInput, passwordKeyEncryptor.encryptedVerifierHashInput ) )
571         lastError = OUString::createFromAscii( "Failed to base64 decode the passwordKeyEncryptor.encryptedVerifierHashInput " ) + encryptedVerifierHashInput;
572     OUString encryptedVerifierHashValue = attribs.getString( XML_encryptedVerifierHashValue, OUString() );
573     if( !decodeBase64( encryptedVerifierHashValue, passwordKeyEncryptor.encryptedVerifierHashValue ) )
574         lastError = OUString::createFromAscii( "Failed to base64 decode the passwordKeyEncryptor.encryptedVerifierHashValue " ) + encryptedVerifierHashValue;
575     OUString encryptedKeyValue = attribs.getString( XML_encryptedKeyValue, OUString() );
576     if( !decodeBase64( encryptedKeyValue, passwordKeyEncryptor.encryptedKeyValue ) )
577         lastError = OUString::createFromAscii( "Failed to base64 decode the passwordKeyEncryptor.encryptedKeyValue " ) + encryptedKeyValue;
578 }
579 
readUInt16LE(Reference<XInputStream> & inputStream)580 static sal_uInt16 readUInt16LE( Reference< XInputStream >& inputStream ) throw ( Exception )
581 {
582     Sequence< sal_Int8 > bytes( 2 );
583     sal_Int32 bytesRead = inputStream->readBytes( bytes, 2 );
584     if( bytesRead < 2 )
585         throw new Exception( OUString::createFromAscii( "EncryptionInfo::readEncryptionInfo() failed, early end of file" ), Reference< XInterface >() );
586     return (sal_uInt16) ( bytes[0] | (bytes[1] << 8) );
587 }
588 
readUInt32LE(Reference<XInputStream> & inputStream)589 static sal_uInt32 readUInt32LE( Reference< XInputStream >& inputStream ) throw ( Exception )
590 {
591     Sequence< sal_Int8 > bytes( 4 );
592     sal_Int32 bytesRead = inputStream->readBytes( bytes, 4 );
593     if( bytesRead < 4 )
594         throw new Exception( OUString::createFromAscii( "EncryptionInfo::readEncryptionInfo() failed, early end of file" ), Reference< XInterface >() );
595     return (sal_uInt32) ( bytes[0] | (bytes[1] << 8) | (bytes[2] << 16) | (bytes[3] << 24) );
596 }
597 
AgileEncryptionInfo(const Reference<XComponentContext> & context,Reference<XInputStream> & inputStream)598 AgileEncryptionInfo::AgileEncryptionInfo( const Reference< XComponentContext >& context, Reference< XInputStream >& inputStream ) throw ( Exception )
599 {
600     sal_uInt32 nReserved = readUInt32LE( inputStream );
601     if( nReserved != 0x40 )
602         throw new Exception( OUString::createFromAscii( "reserved field isn't 0x40" ), Reference< XInterface >() );
603     AgileEncryptionHandler *agileEncryptionHandler = new AgileEncryptionHandler( keyData, dataIntegrity, passwordKeyEncryptor );
604     Reference< XFastDocumentHandler > documentHandler( agileEncryptionHandler );
605     FastParser fastParser( context );
606     fastParser.registerNamespace( NMSP_encryption );
607     fastParser.registerNamespace( NMSP_keyEncryptorPassword );
608     fastParser.setDocumentHandler( documentHandler );
609     fastParser.parseStream( inputStream, OUString::createFromAscii( "EncryptionInfo" ), false );
610     if( !agileEncryptionHandler->getLastError().isEmpty() )
611         throw new Exception( agileEncryptionHandler->getLastError(), Reference< XInterface >() );
612 }
613 
toOpenSSLDigestAlgorithm(const OUString & hashAlgorithm)614 static const EVP_MD* toOpenSSLDigestAlgorithm( const OUString& hashAlgorithm  ) throw ( Exception )
615 {
616     if( hashAlgorithm.equalsAscii( "SHA-1" ) )
617         return EVP_sha1();
618     else if( hashAlgorithm.equalsAscii( "SHA1" ) ) // Typical Microsoft. The specification says "SHA-1", but documents use "SHA1".
619         return EVP_sha1();
620     else if( hashAlgorithm.equalsAscii( "SHA256" ) )
621         return EVP_sha256();
622     else if( hashAlgorithm.equalsAscii( "SHA384" ) )
623         return EVP_sha384();
624     else if( hashAlgorithm.equalsAscii( "SHA512" ) )
625         return EVP_sha512();
626     else if( hashAlgorithm.equalsAscii( "MD5" ) )
627         return EVP_md5();
628     else if( hashAlgorithm.equalsAscii( "MD4" ) )
629         return EVP_md4();
630 #if !defined(OPENSSL_NO_MD2)
631     else if( hashAlgorithm.equalsAscii( "MD2" ) )
632         return EVP_md2();
633 #endif
634     else if( hashAlgorithm.equalsAscii( "RIPEMD-160" ) )
635         return EVP_ripemd160();
636     else if( hashAlgorithm.equalsAscii( "WHIRLPOOL" ) )
637         return EVP_whirlpool();
638     char buffer[ 256 ];
639     ::rtl::OString str = ::rtl::OUStringToOString( hashAlgorithm, RTL_TEXTENCODING_UTF8 );
640     snprintf( buffer, sizeof( buffer ), "Unsupported digest algorithm %s", str.getStr() );
641     throw Exception( OUString::createFromAscii( buffer ), Reference< XInterface >() );
642 }
643 
toOpenSSLCipherAlgorithm(const OUString & cipherName,sal_uInt32 keyBits,const OUString & chainingMode)644 static const EVP_CIPHER* toOpenSSLCipherAlgorithm( const OUString& cipherName, sal_uInt32 keyBits, const OUString &chainingMode ) throw ( Exception )
645 {
646     if( cipherName.equalsAscii( "AES" ) && keyBits == 128 && chainingMode.equalsAscii( "ChainingModeCBC" ) )
647         return EVP_aes_128_cbc();
648     else if( cipherName.equalsAscii( "AES" ) && keyBits == 128 && chainingMode.equalsAscii( "ChainingModeCFB" ) )
649         return EVP_aes_128_cfb();
650     else if( cipherName.equalsAscii( "AES" ) && keyBits == 192 && chainingMode.equalsAscii( "ChainingModeCBC" ) )
651         return EVP_aes_192_cbc();
652     else if( cipherName.equalsAscii( "AES" ) && keyBits == 192 && chainingMode.equalsAscii( "ChainingModeCFB" ) )
653         return EVP_aes_192_cfb();
654     else if( cipherName.equalsAscii( "AES" ) && keyBits == 256 && chainingMode.equalsAscii( "ChainingModeCBC" ) )
655         return EVP_aes_256_cbc();
656     else if( cipherName.equalsAscii( "AES" ) && keyBits == 256 && chainingMode.equalsAscii( "ChainingModeCFB" ) )
657         return EVP_aes_256_cfb();
658 #if !defined(OPENSSL_NO_RC2)
659     else if( cipherName.equalsAscii( "RC2" ) && keyBits == 128 && chainingMode.equalsAscii( "ChainingModeCBC" ) )
660         return EVP_rc2_cbc();
661     else if( cipherName.equalsAscii( "RC2" ) && keyBits == 128 && chainingMode.equalsAscii( "ChainingModeCFB" ) )
662         return EVP_rc2_cfb();
663 #endif
664 #if !defined(OPENSSL_NO_DES)
665     else if( cipherName.equalsAscii( "DES" ) && keyBits == 56 && chainingMode.equalsAscii( "ChainingModeCBC" ) )
666         return EVP_des_cbc();
667     else if( cipherName.equalsAscii( "DES" ) && keyBits == 56 && chainingMode.equalsAscii( "ChainingModeCFB" ) )
668         return EVP_des_cfb();
669     else if( cipherName.equalsAscii( "DESX" ) && keyBits == 128 && chainingMode.equalsAscii( "ChainingModeCBC" ) )
670         return EVP_desx_cbc();
671     else if( cipherName.equalsAscii( "3DES" ) && keyBits == 168 && chainingMode.equalsAscii( "ChainingModeCBC" ) )
672         return EVP_des_ede3_cbc();
673     else if( cipherName.equalsAscii( "3DES" ) && keyBits == 168 && chainingMode.equalsAscii( "ChainingModeCFB" ) )
674         return EVP_des_ede3_cfb();
675     else if( cipherName.equalsAscii( "3DES_112" ) && keyBits == 112 && chainingMode.equalsAscii( "ChainingModeCBC" ) )
676         return EVP_des_ede_cbc();
677     else if( cipherName.equalsAscii( "3DES_112" ) && keyBits == 112 && chainingMode.equalsAscii( "ChainingModeCFB" ) )
678         return EVP_des_ede_cfb();
679 #endif
680     char buffer[ 256 ];
681     ::rtl::OString cipherNameUtf8 = ::rtl::OUStringToOString( cipherName, RTL_TEXTENCODING_UTF8 );
682     ::rtl::OString chainingModeUtf8 = ::rtl::OUStringToOString( chainingMode, RTL_TEXTENCODING_UTF8 );
683     snprintf( buffer, sizeof( buffer ), "Unsupported cipher with name=%s, keyBits=%u, chainingMode=%s", cipherNameUtf8.getStr(), keyBits, chainingModeUtf8.getStr() );
684     throw Exception( OUString::createFromAscii( buffer ), Reference< XInterface >() );
685 }
686 
687 // Ported from Apache POI's org.apache.poi.poifs.crypt.CryptoFunctions.hashPassword().
hashPassword(const OUString & password,const EVP_MD * digestAlgorithm,vector<sal_uInt8> & salt,sal_uInt32 spinCount)688 static vector< sal_uInt8 > hashPassword( const OUString& password, const EVP_MD *digestAlgorithm, vector< sal_uInt8 >& salt, sal_uInt32 spinCount ) throw ( Exception )
689 {
690     OpenSSLDigest digest;
691     digest.initialize( digestAlgorithm );
692     size_t digestSize = digest.digestSize();
693 
694     // Convert to little-endian UTF-16
695     vector< sal_uInt8 > passwordLE( 2 * password.getLength() );
696     for ( int i = 0; i < password.getLength(); i++ )
697         ByteOrderConverter::writeLittleEndian( &passwordLE[ 2 * i ], static_cast< sal_uInt16 >( password[ i ] ) );
698 
699     vector< sal_uInt8> digestBuffer( digestSize );
700     digest.update( &salt[ 0 ], salt.size() );
701     digest.update( &passwordLE[ 0 ], passwordLE.size() );
702     digest.final( &digestBuffer[ 0 ], NULL );
703 
704     char iteratorBuffer[ 4 ];
705     for (sal_uInt32 i = 0; i < spinCount; i++)
706     {
707         digest.initialize( digestAlgorithm );
708         ByteOrderConverter::writeLittleEndian( &iteratorBuffer, i );
709         digest.update( iteratorBuffer, sizeof( iteratorBuffer ) );
710         digest.update( &digestBuffer[ 0 ], digestSize );
711         digest.final( &digestBuffer[ 0 ], NULL );
712     }
713     return digestBuffer;
714 }
715 
716 // Ported from Apache POI's org.apache.poi.poifs.crypt.CryptoFunctions.getBlock36().
toBlock36(vector<sal_uInt8> & digest,sal_uInt32 size)717 static void toBlock36( vector< sal_uInt8 >& digest, sal_uInt32 size )
718 {
719     if( digest.size() < size )
720     {
721         sal_uInt32 i = digest.size();
722         digest.resize( size );
723         for (; i < size; i++)
724             digest[ i ] = 0x36;
725     }
726     else
727         digest.resize( size );
728 }
729 
730 // Ported from Apache POI's org.apache.poi.poifs.crypt.CryptoFunctions.getBlock0().
toBlock0(vector<sal_uInt8> & digest,sal_uInt32 size)731 static void toBlock0( vector< sal_uInt8 >& digest, sal_uInt32 size )
732 {
733     if( digest.size() < size )
734     {
735         sal_uInt32 i = digest.size();
736         digest.resize( size );
737         for (; i < size; i++)
738             digest[ i ] = 0;
739     }
740     else
741         digest.resize( size );
742 }
743 
744 // Ported from Apache POI's org.apache.poi.poifs.crypt.CryptoFunctions.generateKey().
generateKey(const vector<sal_uInt8> & passwordHash,const EVP_MD * digestAlgorithm,const vector<sal_uInt8> & blockKey,sal_uInt32 keySize)745 static vector< sal_uInt8 > generateKey( const vector< sal_uInt8 >& passwordHash,
746                                         const EVP_MD *digestAlgorithm,
747                                         const vector< sal_uInt8 >& blockKey,
748                                         sal_uInt32 keySize )
749     throw ( Exception )
750 {
751     OpenSSLDigest digest;
752     digest.initialize( digestAlgorithm );
753     digest.update( &passwordHash[ 0 ], passwordHash.size() );
754     digest.update( &blockKey[ 0 ], blockKey.size() );
755     vector< sal_uInt8> key( digest.digestSize() );
756     digest.final( &key[ 0 ], NULL );
757     toBlock36( key, keySize );
758     return key;
759 }
760 
761 // Ported from Apache POI's org.apache.poi.poifs.crypt.CryptoFunctions.generateIv().
generateIv(const vector<sal_uInt8> & salt,sal_uInt32 blockSize)762 static vector< sal_uInt8> generateIv( const vector< sal_uInt8 >& salt,
763                                       sal_uInt32 blockSize )
764     throw ( Exception )
765 {
766     vector< sal_uInt8> iv( salt );
767     toBlock36( iv, blockSize );
768     return iv;
769 }
770 
771 // Ported from Apache POI's org.apache.poi.poifs.crypt.CryptoFunctions.generateIv().
generateIv(const EVP_MD * digestAlgorithm,const vector<sal_uInt8> & salt,const vector<sal_uInt8> & blockKey,sal_uInt32 blockSize)772 static vector< sal_uInt8> generateIv( const EVP_MD *digestAlgorithm,
773                                       const vector< sal_uInt8 >& salt,
774                                       const vector< sal_uInt8 >& blockKey,
775                                       sal_uInt32 blockSize )
776     throw ( Exception )
777 {
778     OpenSSLDigest digest;
779     digest.initialize( digestAlgorithm );
780     digest.update( &salt[ 0 ], salt.size() );
781     digest.update( &blockKey[ 0 ], blockKey.size() );
782     vector< sal_uInt8> iv( digest.digestSize() );
783     digest.final( &iv[ 0 ], NULL );
784     toBlock36( iv, blockSize );
785     return iv;
786 }
787 
788 // Ported from Apache POI's org.apache.poi.poifs.crypt.agile.AgileDecryptor.getNextBlockSize().
getNextBlockSize(sal_uInt32 totalSize,sal_uInt32 blockSize)789 static sal_uInt32 getNextBlockSize( sal_uInt32 totalSize, sal_uInt32 blockSize )
790 {
791     sal_uInt32 numberOfBlocks = ( totalSize + ( blockSize - 1 ) ) / blockSize;
792     return numberOfBlocks * blockSize;
793 }
794 
decryptAll(const EVP_CIPHER * cipherAlgorithm,const sal_uInt8 * iv,const sal_uInt8 * key,const sal_uInt8 * encryptedData,sal_uInt32 encryptedDataLength)795 static vector< sal_uInt8 > decryptAll( const EVP_CIPHER* cipherAlgorithm,
796                                        const sal_uInt8* iv,
797                                        const sal_uInt8* key,
798                                        const sal_uInt8* encryptedData,
799                                        sal_uInt32 encryptedDataLength )
800     throw ( Exception )
801 {
802     OpenSSLCipher cipher;
803     cipher.initialize( cipherAlgorithm, key, iv, 0 );
804     cipher.setPadding( 0 );
805     const int blockSize = OpenSSLCipher::blockSize( cipherAlgorithm );
806     vector< sal_uInt8 > decryptedData( encryptedDataLength + 2*blockSize );
807 
808     int decryptedDataLength;
809     cipher.update( encryptedData, encryptedDataLength, &decryptedData[ 0 ], &decryptedDataLength );
810     int finalDataLength;
811     cipher.final( &decryptedData[ decryptedDataLength ], &finalDataLength );
812     decryptedDataLength += finalDataLength;
813     decryptedData.resize( decryptedDataLength );
814     return decryptedData;
815 }
816 
817 // Ported from Apache POI's org.apache.poi.poifs.crypt.agile.AgileDecryptor.hashInput().
hashInput(const vector<sal_uInt8> & passwordHash,const vector<sal_uInt8> & salt,const EVP_MD * digestAlgorithm,const vector<sal_uInt8> & blockKey,const vector<sal_uInt8> & inputKey,const EVP_CIPHER * decryptionAlgorithm,sal_uInt32 keySize,sal_uInt32 blockSize)818 static vector< sal_uInt8 > hashInput( const vector< sal_uInt8 >& passwordHash,
819                                       const vector< sal_uInt8 >& salt,
820                                       const EVP_MD *digestAlgorithm,
821                                       const vector< sal_uInt8 >& blockKey,
822                                       const vector< sal_uInt8 >& inputKey,
823                                       const EVP_CIPHER *decryptionAlgorithm,
824                                       sal_uInt32 keySize,
825                                       sal_uInt32 blockSize )
826     throw ( Exception )
827 {
828     vector< sal_uInt8 > intermediateKey = generateKey( passwordHash, digestAlgorithm, blockKey, keySize );
829     vector< sal_uInt8> iv = generateIv( salt, blockSize );
830     vector< sal_uInt8 > zeroedInput( inputKey.size() );
831     zeroedInput = inputKey;
832     toBlock0( zeroedInput, getNextBlockSize( zeroedInput.size(), blockSize ) );
833     return decryptAll( decryptionAlgorithm, &iv[ 0 ], &intermediateKey[ 0 ], &zeroedInput[ 0 ], zeroedInput.size() );
834 }
835 
836 // Ported from Apache POI's org.apache.poi.poifs.crypt.agile.AgileDecryptor.verifyPassword().
verifyPassword(const OUString & password)837 Sequence< NamedValue > AgileEncryptionInfo::verifyPassword( const OUString& password )
838     throw ( Exception )
839 {
840     const EVP_MD *digestAlgorithm = toOpenSSLDigestAlgorithm( passwordKeyEncryptor.hashAlgorithm );
841     vector< sal_uInt8 > passwordHash = hashPassword( password, digestAlgorithm, passwordKeyEncryptor.saltValue, passwordKeyEncryptor.spinCount );
842 
843     static const sal_uInt8 verifierInputBlockData[] = { 0xfe, 0xa7, 0xd2, 0x76, 0x3b, 0x4b, 0x9e, 0x79 };
844     vector< sal_uInt8 > verifierInputBlock( &verifierInputBlockData[ 0 ], &verifierInputBlockData[ sizeof( verifierInputBlockData ) ] );
845     const EVP_CIPHER* cipher = toOpenSSLCipherAlgorithm( passwordKeyEncryptor.cipherAlgorithm, passwordKeyEncryptor.keyBits, passwordKeyEncryptor.cipherChaining );
846     vector< sal_uInt8 > encryptedVerifierHash = hashInput( passwordHash, passwordKeyEncryptor.saltValue, digestAlgorithm, verifierInputBlock,
847                                                            passwordKeyEncryptor.encryptedVerifierHashInput, cipher, passwordKeyEncryptor.keyBits,
848                                                            passwordKeyEncryptor.blockSize );
849     const EVP_MD *verifierDigestAlgorithm = toOpenSSLDigestAlgorithm( keyData.hashAlgorithm );
850     OpenSSLDigest verifierDigest;
851     verifierDigest.initialize( verifierDigestAlgorithm );
852     verifierDigest.update( &encryptedVerifierHash[ 0 ], encryptedVerifierHash.size() );
853     encryptedVerifierHash.resize( verifierDigest.digestSize() );
854     verifierDigest.final( &encryptedVerifierHash[ 0 ], NULL );
855 
856     static const sal_uInt8 verifierHashBlockData[] = { 0xd7, 0xaa, 0x0f, 0x6d, 0x30, 0x61, 0x34, 0x4e };
857     vector< sal_uInt8 > verifierHashBlock( &verifierHashBlockData[ 0 ], &verifierHashBlockData[ sizeof( verifierHashBlockData ) ] );
858     vector< sal_uInt8 > verifierHashDec = hashInput( passwordHash, passwordKeyEncryptor.saltValue, digestAlgorithm, verifierHashBlock,
859                                                      passwordKeyEncryptor.encryptedVerifierHashValue, cipher, passwordKeyEncryptor.keyBits,
860                                                      passwordKeyEncryptor.blockSize );
861     toBlock0( verifierHashDec, verifierDigest.digestSize() );
862 
863     if( encryptedVerifierHash != verifierHashDec )
864         return Sequence< NamedValue >();
865 
866     // Password is correct. Decrypt and store the encryption key.
867     static const sal_uInt8 cryptoKeyBlockData[] = { 0x14, 0x6e, 0x0b, 0xe7, 0xab, 0xac, 0xd0, 0xd6 };
868     vector< sal_uInt8 > cryptoKeyBlock( &cryptoKeyBlockData[ 0 ], &cryptoKeyBlockData[ sizeof( cryptoKeyBlockData ) ] );
869     encryptionKey = hashInput( passwordHash, passwordKeyEncryptor.saltValue, digestAlgorithm, cryptoKeyBlock,
870                                passwordKeyEncryptor.encryptedKeyValue, cipher, passwordKeyEncryptor.keyBits,
871                                passwordKeyEncryptor.blockSize );
872     toBlock0( encryptionKey, passwordKeyEncryptor.keyBits / 8 );
873 
874     // Also decrypt the dataIntegrity fields for stream validation. Note that they are optional.
875     if( !dataIntegrity.encryptedHmacKey.empty() && !dataIntegrity.encryptedHmacValue.empty() )
876     {
877         const EVP_MD* keyDataDigestAlgorithm = toOpenSSLDigestAlgorithm( keyData.hashAlgorithm );
878         const EVP_CIPHER* keyDataCipher = toOpenSSLCipherAlgorithm( keyData.cipherAlgorithm, keyData.keyBits, keyData.cipherChaining );
879         static const sal_uInt8 integrityKeyBlockData[] = { 0x5f, 0xb2, 0xad, 0x01, 0x0c, 0xb9, 0xe1, 0xf6 };
880         vector< sal_uInt8 > integrityKeyBlock( &integrityKeyBlockData[ 0 ], &integrityKeyBlockData[ sizeof( integrityKeyBlockData ) ] );
881         vector< sal_uInt8 > integrityKeyIv = generateIv( keyDataDigestAlgorithm, keyData.saltValue, integrityKeyBlock, keyData.blockSize );
882         hmacKey = decryptAll( keyDataCipher, &integrityKeyIv[ 0 ], &encryptionKey[ 0 ], &dataIntegrity.encryptedHmacKey[ 0 ], dataIntegrity.encryptedHmacKey.size() );
883         toBlock0( hmacKey, OpenSSLDigest::digestSize( keyDataDigestAlgorithm ) );
884 
885         static const sal_uInt8 integrityValueBlockData[] = { 0xa0, 0x67, 0x7f, 0x02, 0xb2, 0x2c, 0x84, 0x33 };
886         vector< sal_uInt8 > integrityValueBlock( &integrityValueBlockData[ 0 ], &integrityValueBlockData[ sizeof( integrityValueBlockData ) ] );
887         vector< sal_uInt8 > integrityValueIv = generateIv( keyDataDigestAlgorithm, keyData.saltValue, integrityValueBlock, keyData.blockSize );
888         hmacValue = decryptAll( keyDataCipher, &integrityValueIv[ 0 ], &encryptionKey[ 0 ], &dataIntegrity.encryptedHmacValue[ 0 ], dataIntegrity.encryptedHmacValue.size() );
889         toBlock0( hmacValue, OpenSSLDigest::digestSize( keyDataDigestAlgorithm ) );
890     }
891 
892     // On success, MUST populate something into the encryption data, even though we'll never use it.
893     SequenceAsHashMap encryptionData;
894     encryptionData[ CREATE_OUSTRING( "OOXMLAgileEncryptionPasswordVerified" ) ] <<= sal_True;
895     return encryptionData.getAsConstNamedValueList();
896 }
897 
verifyEncryptionData(const Sequence<NamedValue> & rEncryptionData)898 bool AgileEncryptionInfo::verifyEncryptionData( const Sequence< NamedValue >& rEncryptionData )
899     throw ( Exception )
900 {
901     // OpenGrok shows how only main/comphelper/source/misc/docpasswordhelper.cxx calls IDocPasswordVerifier::verifyEncryptionData(),
902     // and only when the password is wrong and the rMediaEncData non-empty, which presumably allows other forms of encryption
903     // (eg. by certificate) to be used. We only support password for now.
904     return false;
905 }
906 
907 // Ported from Apache POI's org.apache.poi.poifs.crypt.agile.AgileDecryptor.initCipherForBlock().
decryptStream(BinaryXInputStream & aEncryptedPackage,BinaryXOutputStream & aDecryptedPackage)908 void AgileEncryptionInfo::decryptStream( BinaryXInputStream &aEncryptedPackage, BinaryXOutputStream &aDecryptedPackage )
909     throw ( Exception )
910 {
911     if( encryptionKey.empty() )
912         throw Exception( OUString::createFromAscii( "Encryption key not set, was the password wrong?" ), Reference< XInterface >() );
913     const EVP_CIPHER* cipherAlgorithm = toOpenSSLCipherAlgorithm( keyData.cipherAlgorithm, keyData.keyBits, keyData.cipherChaining );
914     const EVP_MD* digestAlgorithm = toOpenSSLDigestAlgorithm( keyData.hashAlgorithm );
915     OpenSSLCipher cipher;
916 
917     const sal_uInt64 decryptedSize = aEncryptedPackage.readuInt64();
918 
919     sal_uInt8 inputBuffer[ 4096 ];
920     vector< sal_uInt8 > outputBuffer( 4096 + 2*OpenSSLCipher::blockSize( cipherAlgorithm ) );
921     sal_Int32 bytesIn;
922     int bytesOut;
923     int finalBytesOut;
924     sal_uInt64 totalBytesWritten = 0;
925 
926     vector< sal_uInt8 > blockBytes( 4 );
927     bool done = false;
928     for ( sal_uInt32 block = 0; !done; block++ )
929     {
930         ByteOrderConverter::writeLittleEndian( &blockBytes[ 0 ], block );
931         vector< sal_uInt8 > iv = generateIv( digestAlgorithm, keyData.saltValue, blockBytes, keyData.blockSize );
932         cipher.initialize( cipherAlgorithm, &encryptionKey[ 0 ], &iv[ 0 ], 0 );
933         cipher.setPadding( 0 );
934 
935         bytesIn = aEncryptedPackage.readMemory( inputBuffer, sizeof( inputBuffer ) );
936         if( bytesIn > 0 )
937         {
938             cipher.update( inputBuffer, bytesIn, &outputBuffer[ 0 ], &bytesOut );
939             cipher.final( &outputBuffer[ bytesOut ], &finalBytesOut );
940             bytesOut += finalBytesOut;
941             if( decryptedSize < (totalBytesWritten + bytesOut) )
942             {
943                 bytesOut = decryptedSize % sizeof( inputBuffer );
944                 done = true;
945             }
946             aDecryptedPackage.writeMemory( &outputBuffer[ 0 ], bytesOut );
947             totalBytesWritten += bytesOut;
948         } else
949             done = true;
950     }
951 
952     aDecryptedPackage.flush();
953 }
954 
readEncryptionInfo(const Reference<XComponentContext> & context,Reference<XInputStream> & inputStream)955 EncryptionInfo* EncryptionInfo::readEncryptionInfo( const Reference< XComponentContext >& context, Reference< XInputStream >& inputStream )
956     throw ( Exception )
957 {
958     sal_uInt16 nVersionMajor = readUInt16LE( inputStream );
959     sal_uInt16 nVersionMinor = readUInt16LE( inputStream );
960     if( ( nVersionMajor == 2 && nVersionMinor == 2 ) ||
961         ( nVersionMajor == 3 && nVersionMinor == 2 ) ||
962         ( nVersionMajor == 4 && nVersionMinor == 2 ) )
963     {
964         // 2.3.4.5 Standard Encryption
965         BinaryXInputStream aInfoStrm( inputStream, false );
966         return new StandardEncryptionInfo( aInfoStrm );
967     }
968     else if ( nVersionMajor == 4 && nVersionMajor == 4 )
969     {
970         // 2.3.4.10 Agile Encryption
971         return new AgileEncryptionInfo( context, inputStream );
972     }
973     else
974     {
975         char msg[ 1024 ];
976         snprintf( msg, sizeof( msg ), "EncryptionInfo::readEncryptionInfo() error: unsupported EncryptionVersionInfo header with major=%hu minor=%hu",
977             nVersionMajor, nVersionMinor );
978         throw Exception( OUString::createFromAscii( msg ), Reference< XInterface >() );
979     }
980 }
981 
982 // ============================================================================
983 
984 } // namespace core
985 } // namespace oox
986