2 * Copyright 2001-2006 Internet2
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
20 * Methods for encrypting XMLObjects and other data.
24 #include "encryption/Decrypter.h"
26 #include <log4cpp/Category.hh>
27 #include <xsec/enc/XSECCryptoException.hpp>
28 #include <xsec/framework/XSECException.hpp>
29 #include <xsec/framework/XSECAlgorithmMapper.hpp>
30 #include <xsec/framework/XSECAlgorithmHandler.hpp>
31 #include <xsec/xenc/XENCEncryptedData.hpp>
32 #include <xsec/xenc/XENCEncryptedKey.hpp>
34 using namespace xmlencryption;
35 using namespace xmlsignature;
36 using namespace xmltooling;
39 Decrypter::~Decrypter()
41 XMLToolingInternalConfig::getInternalConfig().m_xsecProvider->releaseCipher(m_cipher);
46 DOMDocumentFragment* Decrypter::decryptData(EncryptedData* encryptedData)
48 if (encryptedData->getDOM()==NULL)
49 throw DecryptionException("The object must be marshalled before decryption.");
51 // We can reuse the cipher object if the document hasn't changed.
53 if (m_cipher && m_cipher->getDocument()!=encryptedData->getDOM()->getOwnerDocument()) {
54 XMLToolingInternalConfig::getInternalConfig().m_xsecProvider->releaseCipher(m_cipher);
59 m_cipher=XMLToolingInternalConfig::getInternalConfig().m_xsecProvider->newCipher(encryptedData->getDOM()->getOwnerDocument());
62 // Resolve decryption key.
63 XSECCryptoKey* key=NULL;
65 key=m_resolver->resolveKey(encryptedData->getKeyInfo());
67 // See if there's an encrypted key present. We'll need the algorithm...
68 const XMLCh* algorithm=
69 encryptedData->getEncryptionMethod() ? encryptedData->getEncryptionMethod()->getAlgorithm() : NULL;
71 throw DecryptionException("No EncryptionMethod/@Algorithm set, key decryption cannot proceed.");
73 if (encryptedData->getKeyInfo()) {
74 const vector<XMLObject*>& others=const_cast<const KeyInfo*>(encryptedData->getKeyInfo())->getOthers();
75 for (vector<XMLObject*>::const_iterator i=others.begin(); i!=others.end(); i++) {
76 EncryptedKey* encKey=dynamic_cast<EncryptedKey*>(*i);
79 key=decryptKey(encKey, algorithm);
81 catch (DecryptionException& e) {
82 log4cpp::Category::getInstance(XMLTOOLING_LOGCAT".Decrypter").warn(e.what());
89 throw DecryptionException("Unable to resolve a decryption key.");
92 m_cipher->setKey(key);
93 DOMNode* ret=m_cipher->decryptElementDetached(encryptedData->getDOM());
94 if (ret->getNodeType()!=DOMNode::DOCUMENT_FRAGMENT_NODE) {
96 throw DecryptionException("Decryption operation did not result in DocumentFragment.");
98 return static_cast<DOMDocumentFragment*>(ret);
100 catch(XSECException& e) {
101 auto_ptr_char temp(e.getMsg());
102 throw DecryptionException(string("XMLSecurity exception while decrypting: ") + temp.get());
104 catch(XSECCryptoException& e) {
105 throw DecryptionException(string("XMLSecurity exception while decrypting: ") + e.getMsg());
109 XSECCryptoKey* Decrypter::decryptKey(EncryptedKey* encryptedKey, const XMLCh* algorithm)
111 if (encryptedKey->getDOM()==NULL)
112 throw DecryptionException("The object must be marshalled before decryption.");
114 // We can reuse the cipher object if the document hasn't changed.
116 if (m_cipher && m_cipher->getDocument()!=encryptedKey->getDOM()->getOwnerDocument()) {
117 XMLToolingInternalConfig::getInternalConfig().m_xsecProvider->releaseCipher(m_cipher);
122 m_cipher=XMLToolingInternalConfig::getInternalConfig().m_xsecProvider->newCipher(encryptedKey->getDOM()->getOwnerDocument());
125 // Resolve key decryption key.
126 XSECCryptoKey* key=NULL;
128 key=m_KEKresolver->resolveKey(encryptedKey->getKeyInfo());
130 throw DecryptionException("Unable to resolve a key decryption key.");
131 m_cipher->setKEK(key);
133 XMLByte buffer[1024];
134 int keySize = m_cipher->decryptKey(encryptedKey->getDOM(), buffer, 1024);
136 // Try to map the key.
137 XSECAlgorithmHandler* handler = XSECPlatformUtils::g_algorithmMapper->mapURIToHandler(algorithm);
139 return handler->createKeyForURI(algorithm, buffer, keySize);
140 throw DecryptionException("Unrecognized algorithm, could not build object around decrypted key.");
142 throw DecryptionException("Unable to decrypt key.");
144 catch(XSECException& e) {
145 auto_ptr_char temp(e.getMsg());
146 throw DecryptionException(string("XMLSecurity exception while decrypting: ") + temp.get());
148 catch(XSECCryptoException& e) {
149 throw DecryptionException(string("XMLSecurity exception while decrypting: ") + e.getMsg());