1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ 2 /* 3 * This file is part of the LibreOffice project. 4 * 5 * This Source Code Form is subject to the terms of the Mozilla Public 6 * License, v. 2.0. If a copy of the MPL was not distributed with this 7 * file, You can obtain one at http://mozilla.org/MPL/2.0/. 8 * 9 * This file incorporates work covered by the following license notice: 10 * 11 * Licensed to the Apache Software Foundation (ASF) under one or more 12 * contributor license agreements. See the NOTICE file distributed 13 * with this work for additional information regarding copyright 14 * ownership. The ASF licenses this file to you under the Apache 15 * License, Version 2.0 (the "License"); you may not use this file 16 * except in compliance with the License. You may obtain a copy of 17 * the License at http://www.apache.org/licenses/LICENSE-2.0 . 18 */ 19 20 #include <com/sun/star/xml/sax/XExtendedDocumentHandler.hpp> 21 #include <com/sun/star/xml/sax/XDocumentHandler.hpp> 22 #include <com/sun/star/xml/sax/XAttributeList.hpp> 23 #include <com/sun/star/xml/crypto/DigestID.hpp> 24 #include <com/sun/star/xml/crypto/CipherID.hpp> 25 #include <com/sun/star/beans/PropertyValue.hpp> 26 #include <com/sun/star/beans/NamedValue.hpp> 27 #include <com/sun/star/uno/RuntimeException.hpp> 28 29 #include "ManifestDefines.hxx" 30 #include "ManifestExport.hxx" 31 #include <sax/tools/converter.hxx> 32 33 #include <osl/diagnose.h> 34 #include <rtl/ustrbuf.hxx> 35 #include <comphelper/base64.hxx> 36 #include <comphelper/documentconstants.hxx> 37 #include <comphelper/attributelist.hxx> 38 39 using namespace ::com::sun::star; 40 41 #if OSL_DEBUG_LEVEL > 0 42 #define THROW_WHERE SAL_WHERE 43 #else 44 #define THROW_WHERE "" 45 #endif 46 47 ManifestExport::ManifestExport( uno::Reference< xml::sax::XDocumentHandler > const & xHandler, const uno::Sequence< uno::Sequence < beans::PropertyValue > >& rManList ) 48 { 49 const OUString sFileEntryElement ( ELEMENT_FILE_ENTRY ); 50 const OUString sManifestElement ( ELEMENT_MANIFEST ); 51 const OUString sEncryptionDataElement( ELEMENT_ENCRYPTION_DATA ); 52 const OUString sAlgorithmElement ( ELEMENT_ALGORITHM ); 53 const OUString sStartKeyGenerationElement ( ELEMENT_START_KEY_GENERATION ); 54 const OUString sKeyDerivationElement ( ELEMENT_KEY_DERIVATION ); 55 56 const OUString sCdataAttribute ( ATTRIBUTE_CDATA ); 57 const OUString sMediaTypeAttribute ( ATTRIBUTE_MEDIA_TYPE ); 58 const OUString sVersionAttribute ( ATTRIBUTE_VERSION ); 59 const OUString sFullPathAttribute ( ATTRIBUTE_FULL_PATH ); 60 const OUString sSizeAttribute ( ATTRIBUTE_SIZE ); 61 const OUString sKeySizeAttribute ( ATTRIBUTE_KEY_SIZE ); 62 const OUString sSaltAttribute ( ATTRIBUTE_SALT ); 63 const OUString sInitialisationVectorAttribute ( ATTRIBUTE_INITIALISATION_VECTOR ); 64 const OUString sIterationCountAttribute ( ATTRIBUTE_ITERATION_COUNT ); 65 const OUString sAlgorithmNameAttribute ( ATTRIBUTE_ALGORITHM_NAME ); 66 const OUString sStartKeyGenerationNameAttribute ( ATTRIBUTE_START_KEY_GENERATION_NAME ); 67 const OUString sKeyDerivationNameAttribute ( ATTRIBUTE_KEY_DERIVATION_NAME ); 68 const OUString sChecksumTypeAttribute ( ATTRIBUTE_CHECKSUM_TYPE ); 69 const OUString sChecksumAttribute ( ATTRIBUTE_CHECKSUM); 70 71 const OUString sKeyInfoElement ( ELEMENT_ENCRYPTED_KEYINFO ); 72 const OUString sManifestKeyInfoElement ( ELEMENT_MANIFEST_KEYINFO ); 73 const OUString sEncryptedKeyElement ( ELEMENT_ENCRYPTEDKEY ); 74 const OUString sEncryptionMethodElement ( ELEMENT_ENCRYPTIONMETHOD ); 75 const OUString sPgpDataElement ( ELEMENT_PGPDATA ); 76 const OUString sPgpKeyIDElement ( ELEMENT_PGPKEYID ); 77 const OUString sPGPKeyPacketElement ( ELEMENT_PGPKEYPACKET ); 78 const OUString sAlgorithmAttribute ( ATTRIBUTE_ALGORITHM ); 79 const OUString sCipherDataElement ( ELEMENT_CIPHERDATA ); 80 const OUString sCipherValueElement ( ELEMENT_CIPHERVALUE ); 81 const OUString sKeyInfo ( "KeyInfo" ); 82 const OUString sPgpKeyIDProperty ( "KeyId" ); 83 const OUString sPgpKeyPacketProperty ( "KeyPacket" ); 84 const OUString sCipherValueProperty ( "CipherValue" ); 85 const OUString sFullPathProperty ( "FullPath" ); 86 const OUString sVersionProperty ( "Version" ); 87 const OUString sMediaTypeProperty ( "MediaType" ); 88 const OUString sIterationCountProperty ( "IterationCount" ); 89 const OUString sDerivedKeySizeProperty ( "DerivedKeySize" ); 90 const OUString sSaltProperty ( "Salt" ); 91 const OUString sInitialisationVectorProperty( "InitialisationVector" ); 92 const OUString sSizeProperty ( "Size" ); 93 const OUString sDigestProperty ( "Digest" ); 94 const OUString sEncryptionAlgProperty ( "EncryptionAlgorithm" ); 95 const OUString sStartKeyAlgProperty ( "StartKeyAlgorithm" ); 96 const OUString sDigestAlgProperty ( "DigestAlgorithm" ); 97 98 const OUString sWhiteSpace ( " " ); 99 100 const OUString sSHA256_URL_ODF12 ( SHA256_URL_ODF12 ); 101 const OUString sSHA256_URL ( SHA256_URL ); 102 const OUString sSHA1_Name ( SHA1_NAME ); 103 104 const OUString sSHA1_1k_Name ( SHA1_1K_NAME ); 105 const OUString sSHA256_1k_URL ( SHA256_1K_URL ); 106 107 const OUString sBlowfish_Name ( BLOWFISH_NAME ); 108 const OUString sAES256_URL ( AES256_URL ); 109 110 const OUString sPBKDF2_Name ( PBKDF2_NAME ); 111 const OUString sPGP_Name ( PGP_NAME ); 112 113 ::comphelper::AttributeList * pRootAttrList = new ::comphelper::AttributeList; 114 const uno::Sequence < beans::PropertyValue > *pSequence = rManList.getConstArray(); 115 const sal_uInt32 nManLength = rManList.getLength(); 116 117 // find the mediatype of the document if any 118 OUString aDocMediaType; 119 OUString aDocVersion; 120 sal_Int32 nRootFolderPropIndex=-1; 121 for (sal_uInt32 nInd = 0; nInd < nManLength ; nInd++ ) 122 { 123 OUString aMediaType; 124 OUString aPath; 125 OUString aVersion; 126 127 const beans::PropertyValue *pValue = pSequence[nInd].getConstArray(); 128 for (sal_uInt32 j = 0, nNum = pSequence[nInd].getLength(); j < nNum; j++, pValue++) 129 { 130 if (pValue->Name == sMediaTypeProperty ) 131 { 132 pValue->Value >>= aMediaType; 133 } 134 else if (pValue->Name == sFullPathProperty ) 135 { 136 pValue->Value >>= aPath; 137 } 138 else if (pValue->Name == sVersionProperty ) 139 { 140 pValue->Value >>= aVersion; 141 } 142 143 if ( !aPath.isEmpty() && !aMediaType.isEmpty() && !aVersion.isEmpty() ) 144 break; 145 } 146 147 if ( aPath == "/" ) 148 { 149 aDocMediaType = aMediaType; 150 aDocVersion = aVersion; 151 nRootFolderPropIndex = nInd; 152 break; 153 } 154 } 155 156 bool bProvideDTD = false; 157 bool bAcceptNonemptyVersion = false; 158 bool bStoreStartKeyGeneration = false; 159 if ( !aDocMediaType.isEmpty() ) 160 { 161 if ( aDocMediaType == MIMETYPE_OASIS_OPENDOCUMENT_TEXT_ASCII 162 || aDocMediaType == MIMETYPE_OASIS_OPENDOCUMENT_TEXT_WEB_ASCII 163 || aDocMediaType == MIMETYPE_OASIS_OPENDOCUMENT_TEXT_GLOBAL_ASCII 164 || aDocMediaType == MIMETYPE_OASIS_OPENDOCUMENT_DRAWING_ASCII 165 || aDocMediaType == MIMETYPE_OASIS_OPENDOCUMENT_PRESENTATION_ASCII 166 || aDocMediaType == MIMETYPE_OASIS_OPENDOCUMENT_SPREADSHEET_ASCII 167 || aDocMediaType == MIMETYPE_OASIS_OPENDOCUMENT_CHART_ASCII 168 || aDocMediaType == MIMETYPE_OASIS_OPENDOCUMENT_DATABASE_ASCII 169 || aDocMediaType == MIMETYPE_OASIS_OPENDOCUMENT_FORMULA_ASCII 170 || aDocMediaType == MIMETYPE_OASIS_OPENDOCUMENT_TEXT_TEMPLATE_ASCII 171 || aDocMediaType == MIMETYPE_OASIS_OPENDOCUMENT_TEXT_GLOBAL_TEMPLATE_ASCII 172 || aDocMediaType == MIMETYPE_OASIS_OPENDOCUMENT_DRAWING_TEMPLATE_ASCII 173 || aDocMediaType == MIMETYPE_OASIS_OPENDOCUMENT_PRESENTATION_TEMPLATE_ASCII 174 || aDocMediaType == MIMETYPE_OASIS_OPENDOCUMENT_SPREADSHEET_TEMPLATE_ASCII 175 || aDocMediaType == MIMETYPE_OASIS_OPENDOCUMENT_CHART_TEMPLATE_ASCII 176 || aDocMediaType == MIMETYPE_OASIS_OPENDOCUMENT_FORMULA_TEMPLATE_ASCII ) 177 178 { 179 // oasis format 180 pRootAttrList->AddAttribute ( ATTRIBUTE_XMLNS, 181 sCdataAttribute, 182 MANIFEST_OASIS_NAMESPACE ); 183 bAcceptNonemptyVersion = true; 184 if ( aDocVersion.compareTo( ODFVER_012_TEXT ) >= 0 ) 185 { 186 // this is ODF12 or later generation, let encrypted 187 // streams contain start-key-generation entry 188 bStoreStartKeyGeneration = true; 189 pRootAttrList->AddAttribute ( sVersionAttribute, sCdataAttribute, aDocVersion ); 190 // plus gpg4libre extensions - loext NS for that 191 pRootAttrList->AddAttribute ( ATTRIBUTE_XMLNS_LOEXT, 192 sCdataAttribute, 193 MANIFEST_LOEXT_NAMESPACE ); 194 } 195 } 196 else 197 { 198 // even if it is no SO6 format the namespace must be specified 199 // thus SO6 format is used as default one 200 pRootAttrList->AddAttribute ( ATTRIBUTE_XMLNS, 201 sCdataAttribute, 202 MANIFEST_NAMESPACE ); 203 204 bProvideDTD = true; 205 } 206 } 207 208 uno::Reference < xml::sax::XAttributeList > xRootAttrList (pRootAttrList); 209 210 xHandler->startDocument(); 211 uno::Reference < xml::sax::XExtendedDocumentHandler > xExtHandler ( xHandler, uno::UNO_QUERY ); 212 if ( xExtHandler.is() && bProvideDTD ) 213 { 214 xExtHandler->unknown ( MANIFEST_DOCTYPE ); 215 xHandler->ignorableWhitespace ( sWhiteSpace ); 216 } 217 xHandler->startElement( sManifestElement, xRootAttrList ); 218 219 const uno::Any *pKeyInfoProperty = nullptr; 220 if ( nRootFolderPropIndex >= 0 ) 221 { 222 // do we have package-wide encryption info? 223 const beans::PropertyValue *pValue = 224 pSequence[nRootFolderPropIndex].getConstArray(); 225 for (sal_uInt32 j = 0, nNum = pSequence[nRootFolderPropIndex].getLength(); j < nNum; j++, pValue++) 226 { 227 if (pValue->Name == sKeyInfo ) 228 pKeyInfoProperty = &pValue->Value; 229 } 230 231 if ( pKeyInfoProperty ) 232 { 233 // yeah, so that goes directly below the manifest:manifest 234 // element 235 ::comphelper::AttributeList * pNewAttrList = new ::comphelper::AttributeList; 236 uno::Reference < xml::sax::XAttributeList > xNewAttrList (pNewAttrList); 237 OUStringBuffer aBuffer; 238 239 xHandler->ignorableWhitespace ( sWhiteSpace ); 240 241 // ==== manifest:keyinfo & children 242 xHandler->startElement( sManifestKeyInfoElement, nullptr ); 243 xHandler->ignorableWhitespace ( sWhiteSpace ); 244 245 uno::Sequence< uno::Sequence < beans::NamedValue > > aKeyInfoSequence; 246 *pKeyInfoProperty >>= aKeyInfoSequence; 247 const uno::Sequence < beans::NamedValue > *pKeyInfoSequence = aKeyInfoSequence.getConstArray(); 248 const sal_uInt32 nKeyInfoLength = aKeyInfoSequence.getLength(); 249 for (sal_uInt32 nInd = 0; nInd < nKeyInfoLength ; nInd++ ) 250 { 251 uno::Sequence < sal_Int8 > aPgpKeyID; 252 uno::Sequence < sal_Int8 > aPgpKeyPacket; 253 uno::Sequence < sal_Int8 > aCipherValue; 254 const beans::NamedValue *pNValue = pKeyInfoSequence[nInd].getConstArray(); 255 for (sal_uInt32 j = 0, nNum = pKeyInfoSequence[nInd].getLength(); j < nNum; j++, pNValue++) 256 { 257 if (pNValue->Name == sPgpKeyIDProperty ) 258 pNValue->Value >>= aPgpKeyID; 259 else if (pNValue->Name == sPgpKeyPacketProperty ) 260 pNValue->Value >>= aPgpKeyPacket; 261 else if (pNValue->Name == sCipherValueProperty ) 262 pNValue->Value >>= aCipherValue; 263 } 264 265 if (aPgpKeyID.hasElements() && aCipherValue.hasElements() ) 266 { 267 // ==== manifest:encrypted-key & children - one for each recipient 268 xHandler->startElement( sEncryptedKeyElement, nullptr ); 269 xHandler->ignorableWhitespace ( sWhiteSpace ); 270 271 // TODO: the algorithm should rather be configurable 272 pNewAttrList->AddAttribute ( sAlgorithmAttribute, sCdataAttribute, 273 "http://www.w3.org/2001/04/xmlenc#rsa-oaep-mgf1p" ); 274 xHandler->startElement( sEncryptionMethodElement, xNewAttrList ); 275 xHandler->ignorableWhitespace ( sWhiteSpace ); 276 xHandler->endElement( sEncryptionMethodElement ); 277 278 xHandler->startElement( sKeyInfoElement, nullptr ); 279 xHandler->ignorableWhitespace ( sWhiteSpace ); 280 281 xHandler->startElement( sPgpDataElement, nullptr ); 282 xHandler->ignorableWhitespace ( sWhiteSpace ); 283 284 xHandler->startElement( sPgpKeyIDElement, nullptr ); 285 ::comphelper::Base64::encode(aBuffer, aPgpKeyID); 286 xHandler->characters( aBuffer.makeStringAndClear() ); 287 xHandler->endElement( sPgpKeyIDElement ); 288 xHandler->ignorableWhitespace ( sWhiteSpace ); 289 290 // key packet is optional 291 if (aPgpKeyPacket.hasElements()) 292 { 293 xHandler->startElement( sPGPKeyPacketElement, nullptr ); 294 ::comphelper::Base64::encode(aBuffer, aPgpKeyPacket); 295 xHandler->characters( aBuffer.makeStringAndClear() ); 296 xHandler->endElement( sPGPKeyPacketElement ); 297 xHandler->ignorableWhitespace ( sWhiteSpace ); 298 } 299 300 xHandler->endElement( sPgpDataElement ); 301 xHandler->ignorableWhitespace ( sWhiteSpace ); 302 303 xHandler->endElement( sKeyInfoElement ); 304 xHandler->ignorableWhitespace ( sWhiteSpace ); 305 306 xHandler->startElement( sCipherDataElement, nullptr ); 307 xHandler->ignorableWhitespace ( sWhiteSpace ); 308 309 xHandler->startElement( sCipherValueElement, nullptr ); 310 ::comphelper::Base64::encode(aBuffer, aCipherValue); 311 xHandler->characters( aBuffer.makeStringAndClear() ); 312 xHandler->endElement( sCipherValueElement ); 313 xHandler->ignorableWhitespace ( sWhiteSpace ); 314 315 xHandler->endElement( sCipherDataElement ); 316 xHandler->ignorableWhitespace ( sWhiteSpace ); 317 318 xHandler->endElement( sEncryptedKeyElement ); 319 xHandler->ignorableWhitespace ( sWhiteSpace ); 320 } 321 } 322 323 xHandler->endElement( sManifestKeyInfoElement ); 324 xHandler->ignorableWhitespace ( sWhiteSpace ); 325 } 326 } 327 328 // now write individual file entries 329 for (sal_uInt32 i = 0 ; i < nManLength ; i++) 330 { 331 ::comphelper::AttributeList *pAttrList = new ::comphelper::AttributeList; 332 const beans::PropertyValue *pValue = pSequence[i].getConstArray(); 333 OUString aString; 334 const uno::Any *pVector = nullptr, *pSalt = nullptr, *pIterationCount = nullptr, *pDigest = nullptr, *pDigestAlg = nullptr, *pEncryptAlg = nullptr, *pStartKeyAlg = nullptr, *pDerivedKeySize = nullptr; 335 for (sal_uInt32 j = 0, nNum = pSequence[i].getLength(); j < nNum; j++, pValue++) 336 { 337 if (pValue->Name == sMediaTypeProperty ) 338 { 339 pValue->Value >>= aString; 340 pAttrList->AddAttribute ( sMediaTypeAttribute, sCdataAttribute, aString ); 341 } 342 else if (pValue->Name == sVersionProperty ) 343 { 344 pValue->Value >>= aString; 345 // the version is stored only if it is not empty 346 if ( bAcceptNonemptyVersion && !aString.isEmpty() ) 347 pAttrList->AddAttribute ( sVersionAttribute, sCdataAttribute, aString ); 348 } 349 else if (pValue->Name == sFullPathProperty ) 350 { 351 pValue->Value >>= aString; 352 pAttrList->AddAttribute ( sFullPathAttribute, sCdataAttribute, aString ); 353 } 354 else if (pValue->Name == sSizeProperty ) 355 { 356 sal_Int64 nSize = 0; 357 pValue->Value >>= nSize; 358 OUStringBuffer aBuffer; 359 aBuffer.append ( nSize ); 360 pAttrList->AddAttribute ( sSizeAttribute, sCdataAttribute, aBuffer.makeStringAndClear() ); 361 } 362 else if (pValue->Name == sInitialisationVectorProperty ) 363 pVector = &pValue->Value; 364 else if (pValue->Name == sSaltProperty ) 365 pSalt = &pValue->Value; 366 else if (pValue->Name == sIterationCountProperty ) 367 pIterationCount = &pValue->Value; 368 else if (pValue->Name == sDigestProperty ) 369 pDigest = &pValue->Value; 370 else if (pValue->Name == sDigestAlgProperty ) 371 pDigestAlg = &pValue->Value; 372 else if (pValue->Name == sEncryptionAlgProperty ) 373 pEncryptAlg = &pValue->Value; 374 else if (pValue->Name == sStartKeyAlgProperty ) 375 pStartKeyAlg = &pValue->Value; 376 else if (pValue->Name == sDerivedKeySizeProperty ) 377 pDerivedKeySize = &pValue->Value; 378 } 379 380 xHandler->ignorableWhitespace ( sWhiteSpace ); 381 uno::Reference < xml::sax::XAttributeList > xAttrList ( pAttrList ); 382 xHandler->startElement( sFileEntryElement , xAttrList); 383 if ( pVector && pSalt && pIterationCount && pDigest && pDigestAlg && pEncryptAlg && pStartKeyAlg && pDerivedKeySize ) 384 { 385 // ==== Encryption Data 386 ::comphelper::AttributeList * pNewAttrList = new ::comphelper::AttributeList; 387 uno::Reference < xml::sax::XAttributeList > xNewAttrList (pNewAttrList); 388 OUStringBuffer aBuffer; 389 uno::Sequence < sal_Int8 > aSequence; 390 391 xHandler->ignorableWhitespace ( sWhiteSpace ); 392 393 // ==== Digest 394 OUString sChecksumType; 395 sal_Int32 nDigestAlgID = 0; 396 *pDigestAlg >>= nDigestAlgID; 397 if ( nDigestAlgID == xml::crypto::DigestID::SHA256_1K ) 398 sChecksumType = sSHA256_1k_URL; 399 else if ( nDigestAlgID == xml::crypto::DigestID::SHA1_1K ) 400 sChecksumType = sSHA1_1k_Name; 401 else 402 throw uno::RuntimeException( THROW_WHERE "Unexpected digest algorithm is provided!" ); 403 404 pNewAttrList->AddAttribute ( sChecksumTypeAttribute, sCdataAttribute, sChecksumType ); 405 *pDigest >>= aSequence; 406 ::comphelper::Base64::encode(aBuffer, aSequence); 407 pNewAttrList->AddAttribute ( sChecksumAttribute, sCdataAttribute, aBuffer.makeStringAndClear() ); 408 409 xHandler->startElement( sEncryptionDataElement , xNewAttrList); 410 411 // ==== Algorithm 412 pNewAttrList = new ::comphelper::AttributeList; 413 xNewAttrList = pNewAttrList; 414 415 sal_Int32 nEncAlgID = 0; 416 sal_Int32 nDerivedKeySize = 0; 417 *pEncryptAlg >>= nEncAlgID; 418 *pDerivedKeySize >>= nDerivedKeySize; 419 420 OUString sEncAlgName; 421 if ( nEncAlgID == xml::crypto::CipherID::AES_CBC_W3C_PADDING ) 422 { 423 OSL_ENSURE( nDerivedKeySize, "Unexpected key size is provided!" ); 424 if ( nDerivedKeySize != 32 ) 425 throw uno::RuntimeException( THROW_WHERE "Unexpected key size is provided!" ); 426 427 sEncAlgName = sAES256_URL; 428 } 429 else if ( nEncAlgID == xml::crypto::CipherID::BLOWFISH_CFB_8 ) 430 { 431 sEncAlgName = sBlowfish_Name; 432 } 433 else 434 throw uno::RuntimeException( THROW_WHERE "Unexpected encryption algorithm is provided!" ); 435 436 pNewAttrList->AddAttribute ( sAlgorithmNameAttribute, sCdataAttribute, sEncAlgName ); 437 438 *pVector >>= aSequence; 439 ::comphelper::Base64::encode(aBuffer, aSequence); 440 pNewAttrList->AddAttribute ( sInitialisationVectorAttribute, sCdataAttribute, aBuffer.makeStringAndClear() ); 441 442 xHandler->ignorableWhitespace ( sWhiteSpace ); 443 xHandler->startElement( sAlgorithmElement , xNewAttrList); 444 xHandler->ignorableWhitespace ( sWhiteSpace ); 445 xHandler->endElement( sAlgorithmElement ); 446 447 // ==== Key Derivation 448 pNewAttrList = new ::comphelper::AttributeList; 449 xNewAttrList = pNewAttrList; 450 451 if ( pKeyInfoProperty ) 452 { 453 pNewAttrList->AddAttribute ( sKeyDerivationNameAttribute, 454 sCdataAttribute, 455 sPGP_Name ); 456 // no start-key-generation needed, our session key has 457 // max size already 458 bStoreStartKeyGeneration = false; 459 } 460 else 461 { 462 pNewAttrList->AddAttribute ( sKeyDerivationNameAttribute, 463 sCdataAttribute, 464 sPBKDF2_Name ); 465 466 if ( bStoreStartKeyGeneration ) 467 { 468 aBuffer.append( nDerivedKeySize ); 469 pNewAttrList->AddAttribute ( sKeySizeAttribute, sCdataAttribute, aBuffer.makeStringAndClear() ); 470 } 471 472 sal_Int32 nCount = 0; 473 *pIterationCount >>= nCount; 474 aBuffer.append (nCount); 475 pNewAttrList->AddAttribute ( sIterationCountAttribute, sCdataAttribute, aBuffer.makeStringAndClear() ); 476 477 *pSalt >>= aSequence; 478 ::comphelper::Base64::encode(aBuffer, aSequence); 479 pNewAttrList->AddAttribute ( sSaltAttribute, sCdataAttribute, aBuffer.makeStringAndClear() ); 480 } 481 482 xHandler->ignorableWhitespace ( sWhiteSpace ); 483 xHandler->startElement( sKeyDerivationElement , xNewAttrList); 484 xHandler->ignorableWhitespace ( sWhiteSpace ); 485 xHandler->endElement( sKeyDerivationElement ); 486 487 // we have to store start-key-generation element as the last one to workaround the parsing problem 488 // in OOo3.1 and older versions 489 if ( bStoreStartKeyGeneration ) 490 { 491 // ==== Start Key Generation 492 pNewAttrList = new ::comphelper::AttributeList; 493 xNewAttrList = pNewAttrList; 494 495 OUString sStartKeyAlg; 496 OUString sStartKeySize; 497 sal_Int32 nStartKeyAlgID = 0; 498 *pStartKeyAlg >>= nStartKeyAlgID; 499 if ( nStartKeyAlgID == xml::crypto::DigestID::SHA256 ) 500 { 501 sStartKeyAlg = sSHA256_URL_ODF12; // TODO use sSHA256_URL 502 (void) sSHA256_URL; 503 aBuffer.append( sal_Int32(32) ); 504 sStartKeySize = aBuffer.makeStringAndClear(); 505 } 506 else if ( nStartKeyAlgID == xml::crypto::DigestID::SHA1 ) 507 { 508 sStartKeyAlg = sSHA1_Name; 509 aBuffer.append( sal_Int32(20) ); 510 sStartKeySize = aBuffer.makeStringAndClear(); 511 } 512 else 513 throw uno::RuntimeException( THROW_WHERE "Unexpected start key algorithm is provided!" ); 514 515 pNewAttrList->AddAttribute ( sStartKeyGenerationNameAttribute, sCdataAttribute, sStartKeyAlg ); 516 pNewAttrList->AddAttribute ( sKeySizeAttribute, sCdataAttribute, sStartKeySize ); 517 518 xHandler->ignorableWhitespace ( sWhiteSpace ); 519 xHandler->startElement( sStartKeyGenerationElement , xNewAttrList); 520 xHandler->ignorableWhitespace ( sWhiteSpace ); 521 xHandler->endElement( sStartKeyGenerationElement ); 522 } 523 524 xHandler->ignorableWhitespace ( sWhiteSpace ); 525 xHandler->endElement( sEncryptionDataElement ); 526 } 527 xHandler->ignorableWhitespace ( sWhiteSpace ); 528 xHandler->endElement( sFileEntryElement ); 529 } 530 xHandler->ignorableWhitespace ( sWhiteSpace ); 531 xHandler->endElement( sManifestElement ); 532 xHandler->endDocument(); 533 } 534 535 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ 536
