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 );
~StandardEncryptionInfo()76 ~StandardEncryptionInfo() {}
77 bool isImplemented();
78 Sequence< NamedValue > verifyPassword( const OUString& rPassword );
79 bool verifyEncryptionData( const Sequence< NamedValue >& rEncryptionData );
80 bool checkEncryptionData( const sal_uInt8* pnKey, sal_uInt32 nKeySize, const sal_uInt8* pnVerifier, sal_uInt32 nVerifierSize, const sal_uInt8* pnVerifierHash, sal_uInt32 nVerifierHashSize );
81 void decryptStream( BinaryXInputStream &aEncryptedPackage, BinaryXOutputStream &aDecryptedPackage );
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 )
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 )
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 )
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 )
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 )
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 );
~AgileEncryptionInfo()377 ~AgileEncryptionInfo() {}
isImplemented()378 bool isImplemented() { return true; } // FIXME
379 Sequence< NamedValue > verifyPassword( const OUString& rPassword );
380 bool verifyEncryptionData( const Sequence< NamedValue >& rEncryptionData );
381 void decryptStream( BinaryXInputStream &aEncryptedPackage, BinaryXOutputStream &aDecryptedPackage );
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();
405 virtual void SAL_CALL endDocument();
406 virtual void SAL_CALL setDocumentLocator( const Reference< XLocator >& xLocator );
407
408 // XFastContextHandler
409 virtual void SAL_CALL startFastElement( sal_Int32 nElement, const Reference< XFastAttributeList >& Attribs );
410 virtual void SAL_CALL startUnknownElement( const OUString& Namespace, const OUString& Name, const Reference< XFastAttributeList >& Attribs );
411 virtual void SAL_CALL endFastElement( sal_Int32 Element );
412 virtual void SAL_CALL endUnknownElement( const OUString& Namespace, const OUString& Name );
413 virtual Reference< XFastContextHandler > SAL_CALL createFastChildContext( sal_Int32 Element, const Reference< XFastAttributeList >& Attribs );
414 virtual Reference< XFastContextHandler > SAL_CALL createUnknownChildContext( const OUString& Namespace, const OUString& Name, const Reference< XFastAttributeList >& Attribs );
415 virtual void SAL_CALL characters( const OUString& aChars );
416 virtual void SAL_CALL ignorableWhitespace( const OUString& aWhitespaces );
417 virtual void SAL_CALL processingInstruction( const OUString& aTarget, const OUString& aData );
418
getLastError()419 OUString& getLastError() { return lastError; }
420
421 private:
422 void parseKeyData( const AttributeList& attribs );
423 void parseDataIntegrity( const AttributeList& attribs );
424 void parseEncryptedKey( const AttributeList& attribs );
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 {
435 }
436
endDocument()437 void AgileEncryptionHandler::endDocument()
438 {
439 }
440
setDocumentLocator(const Reference<XLocator> &)441 void AgileEncryptionHandler::setDocumentLocator( const Reference< XLocator >& )
442 {
443 }
444
startFastElement(sal_Int32 nElement,const Reference<XFastAttributeList> & attribs)445 void AgileEncryptionHandler::startFastElement( sal_Int32 nElement, const Reference< XFastAttributeList >& attribs )
446 {
447 switch ( nElement )
448 {
449 case ENCRYPTION_TOKEN( encryption ):
450 break;
451
452 case ENCRYPTION_TOKEN( keyData ):
453 if ( stack.size() == 1 && (stack[ 0 ] == ENCRYPTION_TOKEN( encryption )) )
454 parseKeyData( AttributeList( attribs ) );
455 break;
456
457 case ENCRYPTION_TOKEN( dataIntegrity ):
458 if ( stack.size() == 1 && (stack[ 0 ] == ENCRYPTION_TOKEN( encryption )) )
459 parseDataIntegrity( AttributeList ( attribs ) );
460 break;
461
462 case ENCRYPTION_TOKEN( keyEncryptors ):
463 break;
464
465 case ENCRYPTION_TOKEN( keyEncryptor ):
466 break;
467
468 case KEY_ENCRYPTOR_PASSWORD_TOKEN( encryptedKey ):
469 if ( stack.size() == 3
470 && (stack[ 0 ] == ENCRYPTION_TOKEN( encryption ))
471 && (stack[ 1 ] == ENCRYPTION_TOKEN( keyEncryptors ))
472 && (stack[ 2 ] == ENCRYPTION_TOKEN( keyEncryptor )) )
473 parseEncryptedKey( AttributeList ( attribs ) );
474 break;
475 }
476 stack.push_back( nElement );
477 }
478
startUnknownElement(const OUString &,const OUString &,const Reference<XFastAttributeList> &)479 void AgileEncryptionHandler::startUnknownElement( const OUString&, const OUString&, const Reference< XFastAttributeList >& )
480 {
481 stack.push_back( -1 );
482 }
483
endFastElement(sal_Int32 nElement)484 void AgileEncryptionHandler::endFastElement( sal_Int32 nElement )
485 {
486 stack.pop_back();
487 }
488
endUnknownElement(const OUString &,const OUString &)489 void AgileEncryptionHandler::endUnknownElement( const OUString&, const OUString& )
490 {
491 stack.pop_back();
492 }
493
createFastChildContext(sal_Int32,const Reference<XFastAttributeList> &)494 Reference< XFastContextHandler > AgileEncryptionHandler::createFastChildContext( sal_Int32, const Reference< XFastAttributeList >& )
495 {
496 return this;
497 }
498
createUnknownChildContext(const OUString &,const OUString &,const Reference<XFastAttributeList> &)499 Reference< XFastContextHandler > AgileEncryptionHandler::createUnknownChildContext( const OUString&, const OUString&, const Reference< XFastAttributeList >& )
500 {
501 return this;
502 }
503
characters(const::rtl::OUString & rStr)504 void AgileEncryptionHandler::characters( const ::rtl::OUString& rStr )
505 {
506 }
507
ignorableWhitespace(const::rtl::OUString & str)508 void AgileEncryptionHandler::ignorableWhitespace( const ::rtl::OUString& str )
509 {
510 }
511
processingInstruction(const::rtl::OUString & aTarget,const::rtl::OUString & aData)512 void AgileEncryptionHandler::processingInstruction( const ::rtl::OUString& aTarget, const ::rtl::OUString& aData )
513 {
514 }
515
parseKeyData(const AttributeList & attribs)516 void AgileEncryptionHandler::parseKeyData( const AttributeList& attribs )
517 {
518 keyData.saltSize = attribs.getInteger( XML_saltSize, 0 );
519 keyData.blockSize = attribs.getInteger( XML_blockSize, 0 );
520 keyData.keyBits = attribs.getInteger( XML_keyBits, 0 );
521 keyData.hashSize = attribs.getInteger( XML_hashSize, 0 );
522 keyData.cipherAlgorithm = attribs.getString( XML_cipherAlgorithm, OUString() );
523 keyData.cipherChaining = attribs.getString( XML_cipherChaining, OUString() );
524 keyData.hashAlgorithm = attribs.getString( XML_hashAlgorithm, OUString() );
525
526 OUString saltValue = attribs.getString( XML_saltValue, OUString() );
527 if( !decodeBase64( saltValue, keyData.saltValue ) )
528 lastError = OUString::createFromAscii( "Failed to base64 decode the keyData.saltValue " ) + saltValue;
529 }
530
parseDataIntegrity(const AttributeList & attribs)531 void AgileEncryptionHandler::parseDataIntegrity( const AttributeList& attribs )
532 {
533 OUString encryptedHmacKey = attribs.getString( XML_encryptedHmacKey, OUString() );
534 if( !decodeBase64( encryptedHmacKey, dataIntegrity.encryptedHmacKey ) )
535 lastError = OUString::createFromAscii( "Failed to base64 decode the dataIntegrity.encryptedHmacKey " ) + encryptedHmacKey;
536 OUString encryptedHmacValue = attribs.getString( XML_encryptedHmacValue, OUString() );
537 if( !decodeBase64( encryptedHmacValue, dataIntegrity.encryptedHmacValue ) )
538 lastError = OUString::createFromAscii( "Failed to base64 decode the dataIntegrity.encryptedHmacValue " ) + encryptedHmacValue;
539 }
540
parseEncryptedKey(const AttributeList & attribs)541 void AgileEncryptionHandler::parseEncryptedKey( const AttributeList& attribs )
542 {
543 passwordKeyEncryptor.spinCount = attribs.getInteger( XML_spinCount, 0 );
544 passwordKeyEncryptor.saltSize = attribs.getInteger( XML_saltSize, 0 );
545 passwordKeyEncryptor.blockSize = attribs.getInteger( XML_blockSize, 0 );
546 passwordKeyEncryptor.keyBits = attribs.getInteger( XML_keyBits, 0 );
547 passwordKeyEncryptor.hashSize = attribs.getInteger( XML_hashSize, 0 );
548 passwordKeyEncryptor.cipherAlgorithm = attribs.getString( XML_cipherAlgorithm, OUString() );
549 passwordKeyEncryptor.cipherChaining = attribs.getString( XML_cipherChaining, OUString() );
550 passwordKeyEncryptor.hashAlgorithm = attribs.getString( XML_hashAlgorithm, OUString() );
551 OUString saltValue = attribs.getString( XML_saltValue, OUString() );
552 if( !decodeBase64( saltValue, passwordKeyEncryptor.saltValue ) )
553 lastError = OUString::createFromAscii( "Failed to base64 decode the passwordKeyEncryptor.saltValue " ) + saltValue;
554 OUString encryptedVerifierHashInput = attribs.getString( XML_encryptedVerifierHashInput, OUString() );
555 if( !decodeBase64( encryptedVerifierHashInput, passwordKeyEncryptor.encryptedVerifierHashInput ) )
556 lastError = OUString::createFromAscii( "Failed to base64 decode the passwordKeyEncryptor.encryptedVerifierHashInput " ) + encryptedVerifierHashInput;
557 OUString encryptedVerifierHashValue = attribs.getString( XML_encryptedVerifierHashValue, OUString() );
558 if( !decodeBase64( encryptedVerifierHashValue, passwordKeyEncryptor.encryptedVerifierHashValue ) )
559 lastError = OUString::createFromAscii( "Failed to base64 decode the passwordKeyEncryptor.encryptedVerifierHashValue " ) + encryptedVerifierHashValue;
560 OUString encryptedKeyValue = attribs.getString( XML_encryptedKeyValue, OUString() );
561 if( !decodeBase64( encryptedKeyValue, passwordKeyEncryptor.encryptedKeyValue ) )
562 lastError = OUString::createFromAscii( "Failed to base64 decode the passwordKeyEncryptor.encryptedKeyValue " ) + encryptedKeyValue;
563 }
564
readUInt16LE(Reference<XInputStream> & inputStream)565 static sal_uInt16 readUInt16LE( Reference< XInputStream >& inputStream )
566 {
567 Sequence< sal_Int8 > bytes( 2 );
568 sal_Int32 bytesRead = inputStream->readBytes( bytes, 2 );
569 if( bytesRead < 2 )
570 throw new Exception( OUString::createFromAscii( "EncryptionInfo::readEncryptionInfo() failed, early end of file" ), Reference< XInterface >() );
571 return (sal_uInt16) ( bytes[0] | (bytes[1] << 8) );
572 }
573
readUInt32LE(Reference<XInputStream> & inputStream)574 static sal_uInt32 readUInt32LE( Reference< XInputStream >& inputStream )
575 {
576 Sequence< sal_Int8 > bytes( 4 );
577 sal_Int32 bytesRead = inputStream->readBytes( bytes, 4 );
578 if( bytesRead < 4 )
579 throw new Exception( OUString::createFromAscii( "EncryptionInfo::readEncryptionInfo() failed, early end of file" ), Reference< XInterface >() );
580 return (sal_uInt32) ( bytes[0] | (bytes[1] << 8) | (bytes[2] << 16) | (bytes[3] << 24) );
581 }
582
AgileEncryptionInfo(const Reference<XComponentContext> & context,Reference<XInputStream> & inputStream)583 AgileEncryptionInfo::AgileEncryptionInfo( const Reference< XComponentContext >& context, Reference< XInputStream >& inputStream )
584 {
585 sal_uInt32 nReserved = readUInt32LE( inputStream );
586 if( nReserved != 0x40 )
587 throw new Exception( OUString::createFromAscii( "reserved field isn't 0x40" ), Reference< XInterface >() );
588 AgileEncryptionHandler *agileEncryptionHandler = new AgileEncryptionHandler( keyData, dataIntegrity, passwordKeyEncryptor );
589 Reference< XFastDocumentHandler > documentHandler( agileEncryptionHandler );
590 FastParser fastParser( context );
591 fastParser.registerNamespace( NMSP_encryption );
592 fastParser.registerNamespace( NMSP_keyEncryptorPassword );
593 fastParser.setDocumentHandler( documentHandler );
594 fastParser.parseStream( inputStream, OUString::createFromAscii( "EncryptionInfo" ), false );
595 if( !agileEncryptionHandler->getLastError().isEmpty() )
596 throw new Exception( agileEncryptionHandler->getLastError(), Reference< XInterface >() );
597 }
598
toOpenSSLDigestAlgorithm(const OUString & hashAlgorithm)599 static const EVP_MD* toOpenSSLDigestAlgorithm( const OUString& hashAlgorithm )
600 {
601 if( hashAlgorithm.equalsAscii( "SHA-1" ) )
602 return EVP_sha1();
603 else if( hashAlgorithm.equalsAscii( "SHA1" ) ) // Typical Microsoft. The specification says "SHA-1", but documents use "SHA1".
604 return EVP_sha1();
605 else if( hashAlgorithm.equalsAscii( "SHA256" ) )
606 return EVP_sha256();
607 else if( hashAlgorithm.equalsAscii( "SHA384" ) )
608 return EVP_sha384();
609 else if( hashAlgorithm.equalsAscii( "SHA512" ) )
610 return EVP_sha512();
611 else if( hashAlgorithm.equalsAscii( "MD5" ) )
612 return EVP_md5();
613 else if( hashAlgorithm.equalsAscii( "MD4" ) )
614 return EVP_md4();
615 #if !defined(OPENSSL_NO_MD2)
616 else if( hashAlgorithm.equalsAscii( "MD2" ) )
617 return EVP_md2();
618 #endif
619 else if( hashAlgorithm.equalsAscii( "RIPEMD-160" ) )
620 return EVP_ripemd160();
621 else if( hashAlgorithm.equalsAscii( "WHIRLPOOL" ) )
622 return EVP_whirlpool();
623 char buffer[ 256 ];
624 ::rtl::OString str = ::rtl::OUStringToOString( hashAlgorithm, RTL_TEXTENCODING_UTF8 );
625 snprintf( buffer, sizeof( buffer ), "Unsupported digest algorithm %s", str.getStr() );
626 throw Exception( OUString::createFromAscii( buffer ), Reference< XInterface >() );
627 }
628
toOpenSSLCipherAlgorithm(const OUString & cipherName,sal_uInt32 keyBits,const OUString & chainingMode)629 static const EVP_CIPHER* toOpenSSLCipherAlgorithm( const OUString& cipherName, sal_uInt32 keyBits, const OUString &chainingMode )
630 {
631 if( cipherName.equalsAscii( "AES" ) && keyBits == 128 && chainingMode.equalsAscii( "ChainingModeCBC" ) )
632 return EVP_aes_128_cbc();
633 else if( cipherName.equalsAscii( "AES" ) && keyBits == 128 && chainingMode.equalsAscii( "ChainingModeCFB" ) )
634 return EVP_aes_128_cfb();
635 else if( cipherName.equalsAscii( "AES" ) && keyBits == 192 && chainingMode.equalsAscii( "ChainingModeCBC" ) )
636 return EVP_aes_192_cbc();
637 else if( cipherName.equalsAscii( "AES" ) && keyBits == 192 && chainingMode.equalsAscii( "ChainingModeCFB" ) )
638 return EVP_aes_192_cfb();
639 else if( cipherName.equalsAscii( "AES" ) && keyBits == 256 && chainingMode.equalsAscii( "ChainingModeCBC" ) )
640 return EVP_aes_256_cbc();
641 else if( cipherName.equalsAscii( "AES" ) && keyBits == 256 && chainingMode.equalsAscii( "ChainingModeCFB" ) )
642 return EVP_aes_256_cfb();
643 #if !defined(OPENSSL_NO_RC2)
644 else if( cipherName.equalsAscii( "RC2" ) && keyBits == 128 && chainingMode.equalsAscii( "ChainingModeCBC" ) )
645 return EVP_rc2_cbc();
646 else if( cipherName.equalsAscii( "RC2" ) && keyBits == 128 && chainingMode.equalsAscii( "ChainingModeCFB" ) )
647 return EVP_rc2_cfb();
648 #endif
649 #if !defined(OPENSSL_NO_DES)
650 else if( cipherName.equalsAscii( "DES" ) && keyBits == 56 && chainingMode.equalsAscii( "ChainingModeCBC" ) )
651 return EVP_des_cbc();
652 else if( cipherName.equalsAscii( "DES" ) && keyBits == 56 && chainingMode.equalsAscii( "ChainingModeCFB" ) )
653 return EVP_des_cfb();
654 else if( cipherName.equalsAscii( "DESX" ) && keyBits == 128 && chainingMode.equalsAscii( "ChainingModeCBC" ) )
655 return EVP_desx_cbc();
656 else if( cipherName.equalsAscii( "3DES" ) && keyBits == 168 && chainingMode.equalsAscii( "ChainingModeCBC" ) )
657 return EVP_des_ede3_cbc();
658 else if( cipherName.equalsAscii( "3DES" ) && keyBits == 168 && chainingMode.equalsAscii( "ChainingModeCFB" ) )
659 return EVP_des_ede3_cfb();
660 else if( cipherName.equalsAscii( "3DES_112" ) && keyBits == 112 && chainingMode.equalsAscii( "ChainingModeCBC" ) )
661 return EVP_des_ede_cbc();
662 else if( cipherName.equalsAscii( "3DES_112" ) && keyBits == 112 && chainingMode.equalsAscii( "ChainingModeCFB" ) )
663 return EVP_des_ede_cfb();
664 #endif
665 char buffer[ 256 ];
666 ::rtl::OString cipherNameUtf8 = ::rtl::OUStringToOString( cipherName, RTL_TEXTENCODING_UTF8 );
667 ::rtl::OString chainingModeUtf8 = ::rtl::OUStringToOString( chainingMode, RTL_TEXTENCODING_UTF8 );
668 snprintf( buffer, sizeof( buffer ), "Unsupported cipher with name=%s, keyBits=%u, chainingMode=%s", cipherNameUtf8.getStr(), keyBits, chainingModeUtf8.getStr() );
669 throw Exception( OUString::createFromAscii( buffer ), Reference< XInterface >() );
670 }
671
672 // 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)673 static vector< sal_uInt8 > hashPassword( const OUString& password, const EVP_MD *digestAlgorithm, vector< sal_uInt8 >& salt, sal_uInt32 spinCount )
674 {
675 OpenSSLDigest digest;
676 digest.initialize( digestAlgorithm );
677 size_t digestSize = digest.digestSize();
678
679 // Convert to little-endian UTF-16
680 vector< sal_uInt8 > passwordLE( 2 * password.getLength() );
681 for ( int i = 0; i < password.getLength(); i++ )
682 ByteOrderConverter::writeLittleEndian( &passwordLE[ 2 * i ], static_cast< sal_uInt16 >( password[ i ] ) );
683
684 vector< sal_uInt8> digestBuffer( digestSize );
685 digest.update( &salt[ 0 ], salt.size() );
686 digest.update( &passwordLE[ 0 ], passwordLE.size() );
687 digest.final( &digestBuffer[ 0 ], NULL );
688
689 char iteratorBuffer[ 4 ];
690 for (sal_uInt32 i = 0; i < spinCount; i++)
691 {
692 digest.initialize( digestAlgorithm );
693 ByteOrderConverter::writeLittleEndian( &iteratorBuffer, i );
694 digest.update( iteratorBuffer, sizeof( iteratorBuffer ) );
695 digest.update( &digestBuffer[ 0 ], digestSize );
696 digest.final( &digestBuffer[ 0 ], NULL );
697 }
698 return digestBuffer;
699 }
700
701 // Ported from Apache POI's org.apache.poi.poifs.crypt.CryptoFunctions.getBlock36().
toBlock36(vector<sal_uInt8> & digest,sal_uInt32 size)702 static void toBlock36( vector< sal_uInt8 >& digest, sal_uInt32 size )
703 {
704 if( digest.size() < size )
705 {
706 sal_uInt32 i = digest.size();
707 digest.resize( size );
708 for (; i < size; i++)
709 digest[ i ] = 0x36;
710 }
711 else
712 digest.resize( size );
713 }
714
715 // Ported from Apache POI's org.apache.poi.poifs.crypt.CryptoFunctions.getBlock0().
toBlock0(vector<sal_uInt8> & digest,sal_uInt32 size)716 static void toBlock0( vector< sal_uInt8 >& digest, sal_uInt32 size )
717 {
718 if( digest.size() < size )
719 {
720 sal_uInt32 i = digest.size();
721 digest.resize( size );
722 for (; i < size; i++)
723 digest[ i ] = 0;
724 }
725 else
726 digest.resize( size );
727 }
728
729 // 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)730 static vector< sal_uInt8 > generateKey( const vector< sal_uInt8 >& passwordHash,
731 const EVP_MD *digestAlgorithm,
732 const vector< sal_uInt8 >& blockKey,
733 sal_uInt32 keySize )
734 {
735 OpenSSLDigest digest;
736 digest.initialize( digestAlgorithm );
737 digest.update( &passwordHash[ 0 ], passwordHash.size() );
738 digest.update( &blockKey[ 0 ], blockKey.size() );
739 vector< sal_uInt8> key( digest.digestSize() );
740 digest.final( &key[ 0 ], NULL );
741 toBlock36( key, keySize );
742 return key;
743 }
744
745 // Ported from Apache POI's org.apache.poi.poifs.crypt.CryptoFunctions.generateIv().
generateIv(const vector<sal_uInt8> & salt,sal_uInt32 blockSize)746 static vector< sal_uInt8> generateIv( const vector< sal_uInt8 >& salt,
747 sal_uInt32 blockSize )
748 {
749 vector< sal_uInt8> iv( salt );
750 toBlock36( iv, blockSize );
751 return iv;
752 }
753
754 // 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)755 static vector< sal_uInt8> generateIv( const EVP_MD *digestAlgorithm,
756 const vector< sal_uInt8 >& salt,
757 const vector< sal_uInt8 >& blockKey,
758 sal_uInt32 blockSize )
759 {
760 OpenSSLDigest digest;
761 digest.initialize( digestAlgorithm );
762 digest.update( &salt[ 0 ], salt.size() );
763 digest.update( &blockKey[ 0 ], blockKey.size() );
764 vector< sal_uInt8> iv( digest.digestSize() );
765 digest.final( &iv[ 0 ], NULL );
766 toBlock36( iv, blockSize );
767 return iv;
768 }
769
770 // Ported from Apache POI's org.apache.poi.poifs.crypt.agile.AgileDecryptor.getNextBlockSize().
getNextBlockSize(sal_uInt32 totalSize,sal_uInt32 blockSize)771 static sal_uInt32 getNextBlockSize( sal_uInt32 totalSize, sal_uInt32 blockSize )
772 {
773 sal_uInt32 numberOfBlocks = ( totalSize + ( blockSize - 1 ) ) / blockSize;
774 return numberOfBlocks * blockSize;
775 }
776
decryptAll(const EVP_CIPHER * cipherAlgorithm,const sal_uInt8 * iv,const sal_uInt8 * key,const sal_uInt8 * encryptedData,sal_uInt32 encryptedDataLength)777 static vector< sal_uInt8 > decryptAll( const EVP_CIPHER* cipherAlgorithm,
778 const sal_uInt8* iv,
779 const sal_uInt8* key,
780 const sal_uInt8* encryptedData,
781 sal_uInt32 encryptedDataLength )
782 {
783 OpenSSLCipher cipher;
784 cipher.initialize( cipherAlgorithm, key, iv, 0 );
785 cipher.setPadding( 0 );
786 const int blockSize = OpenSSLCipher::blockSize( cipherAlgorithm );
787 vector< sal_uInt8 > decryptedData( encryptedDataLength + 2*blockSize );
788
789 int decryptedDataLength;
790 cipher.update( encryptedData, encryptedDataLength, &decryptedData[ 0 ], &decryptedDataLength );
791 int finalDataLength;
792 cipher.final( &decryptedData[ decryptedDataLength ], &finalDataLength );
793 decryptedDataLength += finalDataLength;
794 decryptedData.resize( decryptedDataLength );
795 return decryptedData;
796 }
797
798 // 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)799 static vector< sal_uInt8 > hashInput( const vector< sal_uInt8 >& passwordHash,
800 const vector< sal_uInt8 >& salt,
801 const EVP_MD *digestAlgorithm,
802 const vector< sal_uInt8 >& blockKey,
803 const vector< sal_uInt8 >& inputKey,
804 const EVP_CIPHER *decryptionAlgorithm,
805 sal_uInt32 keySize,
806 sal_uInt32 blockSize )
807 {
808 vector< sal_uInt8 > intermediateKey = generateKey( passwordHash, digestAlgorithm, blockKey, keySize );
809 vector< sal_uInt8> iv = generateIv( salt, blockSize );
810 vector< sal_uInt8 > zeroedInput( inputKey.size() );
811 zeroedInput = inputKey;
812 toBlock0( zeroedInput, getNextBlockSize( zeroedInput.size(), blockSize ) );
813 return decryptAll( decryptionAlgorithm, &iv[ 0 ], &intermediateKey[ 0 ], &zeroedInput[ 0 ], zeroedInput.size() );
814 }
815
816 // Ported from Apache POI's org.apache.poi.poifs.crypt.agile.AgileDecryptor.verifyPassword().
verifyPassword(const OUString & password)817 Sequence< NamedValue > AgileEncryptionInfo::verifyPassword( const OUString& password )
818 {
819 const EVP_MD *digestAlgorithm = toOpenSSLDigestAlgorithm( passwordKeyEncryptor.hashAlgorithm );
820 vector< sal_uInt8 > passwordHash = hashPassword( password, digestAlgorithm, passwordKeyEncryptor.saltValue, passwordKeyEncryptor.spinCount );
821
822 static const sal_uInt8 verifierInputBlockData[] = { 0xfe, 0xa7, 0xd2, 0x76, 0x3b, 0x4b, 0x9e, 0x79 };
823 vector< sal_uInt8 > verifierInputBlock( &verifierInputBlockData[ 0 ], &verifierInputBlockData[ sizeof( verifierInputBlockData ) ] );
824 const EVP_CIPHER* cipher = toOpenSSLCipherAlgorithm( passwordKeyEncryptor.cipherAlgorithm, passwordKeyEncryptor.keyBits, passwordKeyEncryptor.cipherChaining );
825 vector< sal_uInt8 > encryptedVerifierHash = hashInput( passwordHash, passwordKeyEncryptor.saltValue, digestAlgorithm, verifierInputBlock,
826 passwordKeyEncryptor.encryptedVerifierHashInput, cipher, passwordKeyEncryptor.keyBits,
827 passwordKeyEncryptor.blockSize );
828 const EVP_MD *verifierDigestAlgorithm = toOpenSSLDigestAlgorithm( keyData.hashAlgorithm );
829 OpenSSLDigest verifierDigest;
830 verifierDigest.initialize( verifierDigestAlgorithm );
831 verifierDigest.update( &encryptedVerifierHash[ 0 ], encryptedVerifierHash.size() );
832 encryptedVerifierHash.resize( verifierDigest.digestSize() );
833 verifierDigest.final( &encryptedVerifierHash[ 0 ], NULL );
834
835 static const sal_uInt8 verifierHashBlockData[] = { 0xd7, 0xaa, 0x0f, 0x6d, 0x30, 0x61, 0x34, 0x4e };
836 vector< sal_uInt8 > verifierHashBlock( &verifierHashBlockData[ 0 ], &verifierHashBlockData[ sizeof( verifierHashBlockData ) ] );
837 vector< sal_uInt8 > verifierHashDec = hashInput( passwordHash, passwordKeyEncryptor.saltValue, digestAlgorithm, verifierHashBlock,
838 passwordKeyEncryptor.encryptedVerifierHashValue, cipher, passwordKeyEncryptor.keyBits,
839 passwordKeyEncryptor.blockSize );
840 toBlock0( verifierHashDec, verifierDigest.digestSize() );
841
842 if( encryptedVerifierHash != verifierHashDec )
843 return Sequence< NamedValue >();
844
845 // Password is correct. Decrypt and store the encryption key.
846 static const sal_uInt8 cryptoKeyBlockData[] = { 0x14, 0x6e, 0x0b, 0xe7, 0xab, 0xac, 0xd0, 0xd6 };
847 vector< sal_uInt8 > cryptoKeyBlock( &cryptoKeyBlockData[ 0 ], &cryptoKeyBlockData[ sizeof( cryptoKeyBlockData ) ] );
848 encryptionKey = hashInput( passwordHash, passwordKeyEncryptor.saltValue, digestAlgorithm, cryptoKeyBlock,
849 passwordKeyEncryptor.encryptedKeyValue, cipher, passwordKeyEncryptor.keyBits,
850 passwordKeyEncryptor.blockSize );
851 toBlock0( encryptionKey, passwordKeyEncryptor.keyBits / 8 );
852
853 // Also decrypt the dataIntegrity fields for stream validation. Note that they are optional.
854 if( !dataIntegrity.encryptedHmacKey.empty() && !dataIntegrity.encryptedHmacValue.empty() )
855 {
856 const EVP_MD* keyDataDigestAlgorithm = toOpenSSLDigestAlgorithm( keyData.hashAlgorithm );
857 const EVP_CIPHER* keyDataCipher = toOpenSSLCipherAlgorithm( keyData.cipherAlgorithm, keyData.keyBits, keyData.cipherChaining );
858 static const sal_uInt8 integrityKeyBlockData[] = { 0x5f, 0xb2, 0xad, 0x01, 0x0c, 0xb9, 0xe1, 0xf6 };
859 vector< sal_uInt8 > integrityKeyBlock( &integrityKeyBlockData[ 0 ], &integrityKeyBlockData[ sizeof( integrityKeyBlockData ) ] );
860 vector< sal_uInt8 > integrityKeyIv = generateIv( keyDataDigestAlgorithm, keyData.saltValue, integrityKeyBlock, keyData.blockSize );
861 hmacKey = decryptAll( keyDataCipher, &integrityKeyIv[ 0 ], &encryptionKey[ 0 ], &dataIntegrity.encryptedHmacKey[ 0 ], dataIntegrity.encryptedHmacKey.size() );
862 toBlock0( hmacKey, OpenSSLDigest::digestSize( keyDataDigestAlgorithm ) );
863
864 static const sal_uInt8 integrityValueBlockData[] = { 0xa0, 0x67, 0x7f, 0x02, 0xb2, 0x2c, 0x84, 0x33 };
865 vector< sal_uInt8 > integrityValueBlock( &integrityValueBlockData[ 0 ], &integrityValueBlockData[ sizeof( integrityValueBlockData ) ] );
866 vector< sal_uInt8 > integrityValueIv = generateIv( keyDataDigestAlgorithm, keyData.saltValue, integrityValueBlock, keyData.blockSize );
867 hmacValue = decryptAll( keyDataCipher, &integrityValueIv[ 0 ], &encryptionKey[ 0 ], &dataIntegrity.encryptedHmacValue[ 0 ], dataIntegrity.encryptedHmacValue.size() );
868 toBlock0( hmacValue, OpenSSLDigest::digestSize( keyDataDigestAlgorithm ) );
869 }
870
871 // On success, MUST populate something into the encryption data, even though we'll never use it.
872 SequenceAsHashMap encryptionData;
873 encryptionData[ CREATE_OUSTRING( "OOXMLAgileEncryptionPasswordVerified" ) ] <<= sal_True;
874 return encryptionData.getAsConstNamedValueList();
875 }
876
verifyEncryptionData(const Sequence<NamedValue> & rEncryptionData)877 bool AgileEncryptionInfo::verifyEncryptionData( const Sequence< NamedValue >& rEncryptionData )
878 {
879 // OpenGrok shows how only main/comphelper/source/misc/docpasswordhelper.cxx calls IDocPasswordVerifier::verifyEncryptionData(),
880 // and only when the password is wrong and the rMediaEncData non-empty, which presumably allows other forms of encryption
881 // (eg. by certificate) to be used. We only support password for now.
882 return false;
883 }
884
885 // Ported from Apache POI's org.apache.poi.poifs.crypt.agile.AgileDecryptor.initCipherForBlock().
decryptStream(BinaryXInputStream & aEncryptedPackage,BinaryXOutputStream & aDecryptedPackage)886 void AgileEncryptionInfo::decryptStream( BinaryXInputStream &aEncryptedPackage, BinaryXOutputStream &aDecryptedPackage )
887 {
888 if( encryptionKey.empty() )
889 throw Exception( OUString::createFromAscii( "Encryption key not set, was the password wrong?" ), Reference< XInterface >() );
890 const EVP_CIPHER* cipherAlgorithm = toOpenSSLCipherAlgorithm( keyData.cipherAlgorithm, keyData.keyBits, keyData.cipherChaining );
891 const EVP_MD* digestAlgorithm = toOpenSSLDigestAlgorithm( keyData.hashAlgorithm );
892 OpenSSLCipher cipher;
893
894 const sal_uInt64 decryptedSize = aEncryptedPackage.readuInt64();
895
896 sal_uInt8 inputBuffer[ 4096 ];
897 vector< sal_uInt8 > outputBuffer( 4096 + 2*OpenSSLCipher::blockSize( cipherAlgorithm ) );
898 sal_Int32 bytesIn;
899 int bytesOut;
900 int finalBytesOut;
901 sal_uInt64 totalBytesWritten = 0;
902
903 vector< sal_uInt8 > blockBytes( 4 );
904 bool done = false;
905 for ( sal_uInt32 block = 0; !done; block++ )
906 {
907 ByteOrderConverter::writeLittleEndian( &blockBytes[ 0 ], block );
908 vector< sal_uInt8 > iv = generateIv( digestAlgorithm, keyData.saltValue, blockBytes, keyData.blockSize );
909 cipher.initialize( cipherAlgorithm, &encryptionKey[ 0 ], &iv[ 0 ], 0 );
910 cipher.setPadding( 0 );
911
912 bytesIn = aEncryptedPackage.readMemory( inputBuffer, sizeof( inputBuffer ) );
913 if( bytesIn > 0 )
914 {
915 cipher.update( inputBuffer, bytesIn, &outputBuffer[ 0 ], &bytesOut );
916 cipher.final( &outputBuffer[ bytesOut ], &finalBytesOut );
917 bytesOut += finalBytesOut;
918 if( decryptedSize < (totalBytesWritten + bytesOut) )
919 {
920 bytesOut = decryptedSize % sizeof( inputBuffer );
921 done = true;
922 }
923 aDecryptedPackage.writeMemory( &outputBuffer[ 0 ], bytesOut );
924 totalBytesWritten += bytesOut;
925 } else
926 done = true;
927 }
928
929 aDecryptedPackage.flush();
930 }
931
readEncryptionInfo(const Reference<XComponentContext> & context,Reference<XInputStream> & inputStream)932 EncryptionInfo* EncryptionInfo::readEncryptionInfo( const Reference< XComponentContext >& context, Reference< XInputStream >& inputStream )
933 {
934 sal_uInt16 nVersionMajor = readUInt16LE( inputStream );
935 sal_uInt16 nVersionMinor = readUInt16LE( inputStream );
936 if( ( nVersionMajor == 2 && nVersionMinor == 2 ) ||
937 ( nVersionMajor == 3 && nVersionMinor == 2 ) ||
938 ( nVersionMajor == 4 && nVersionMinor == 2 ) )
939 {
940 // 2.3.4.5 Standard Encryption
941 BinaryXInputStream aInfoStrm( inputStream, false );
942 return new StandardEncryptionInfo( aInfoStrm );
943 }
944 else if ( nVersionMajor == 4 && nVersionMajor == 4 )
945 {
946 // 2.3.4.10 Agile Encryption
947 return new AgileEncryptionInfo( context, inputStream );
948 }
949 else
950 {
951 char msg[ 1024 ];
952 snprintf( msg, sizeof( msg ), "EncryptionInfo::readEncryptionInfo() error: unsupported EncryptionVersionInfo header with major=%hu minor=%hu",
953 nVersionMajor, nVersionMinor );
954 throw Exception( OUString::createFromAscii( msg ), Reference< XInterface >() );
955 }
956 }
957
958 // ============================================================================
959
960 } // namespace core
961 } // namespace oox
962