2 * Copyright 2001-2007 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 decrypting XMLObjects and other data.
24 #include "encryption/Decrypter.h"
25 #include "encryption/EncryptedKeyResolver.h"
26 #include "security/CredentialResolver.h"
28 #include <log4cpp/Category.hh>
29 #include <xsec/enc/XSECCryptoException.hpp>
30 #include <xsec/framework/XSECException.hpp>
31 #include <xsec/framework/XSECAlgorithmMapper.hpp>
32 #include <xsec/framework/XSECAlgorithmHandler.hpp>
33 #include <xsec/xenc/XENCEncryptedData.hpp>
34 #include <xsec/xenc/XENCEncryptedKey.hpp>
36 using namespace xmlencryption;
37 using namespace xmlsignature;
38 using namespace xmltooling;
41 Decrypter::~Decrypter()
44 XMLToolingInternalConfig::getInternalConfig().m_xsecProvider->releaseCipher(m_cipher);
47 DOMDocumentFragment* Decrypter::decryptData(EncryptedData& encryptedData)
49 if (encryptedData.getDOM()==NULL)
50 throw DecryptionException("The object must be marshalled before decryption.");
52 // We can reuse the cipher object if the document hasn't changed.
54 if (m_cipher && m_cipher->getDocument()!=encryptedData.getDOM()->getOwnerDocument()) {
55 XMLToolingInternalConfig::getInternalConfig().m_xsecProvider->releaseCipher(m_cipher);
60 m_cipher=XMLToolingInternalConfig::getInternalConfig().m_xsecProvider->newCipher(encryptedData.getDOM()->getOwnerDocument());
63 // Resolve decryption key.
64 XSECCryptoKey* key=NULL;
66 key=m_resolver->resolveKey(encryptedData.getKeyInfo());
68 if (!key && m_KEKresolver) {
69 // See if there's an encrypted key available. We'll need the algorithm...
70 const XMLCh* algorithm=
71 encryptedData.getEncryptionMethod() ? encryptedData.getEncryptionMethod()->getAlgorithm() : NULL;
73 throw DecryptionException("No EncryptionMethod/@Algorithm set, key decryption cannot proceed.");
75 if (encryptedData.getKeyInfo()) {
76 const vector<XMLObject*>& others=const_cast<const KeyInfo*>(encryptedData.getKeyInfo())->getUnknownXMLObjects();
77 for (vector<XMLObject*>::const_iterator i=others.begin(); i!=others.end(); i++) {
78 EncryptedKey* encKey=dynamic_cast<EncryptedKey*>(*i);
81 key=decryptKey(*encKey, algorithm);
83 catch (DecryptionException& e) {
84 log4cpp::Category::getInstance(XMLTOOLING_LOGCAT".Decrypter").warn(e.what());
91 // Check for a non-trivial resolver.
92 const EncryptedKeyResolver* ekr=dynamic_cast<const EncryptedKeyResolver*>(m_resolver);
94 EncryptedKey* encKey=ekr->resolveKey(encryptedData);
97 key=decryptKey(*encKey, algorithm);
99 catch (DecryptionException& e) {
100 log4cpp::Category::getInstance(XMLTOOLING_LOGCAT".Decrypter").warn(e.what());
108 throw DecryptionException("Unable to resolve a decryption key.");
110 m_cipher->setKey(key);
111 DOMNode* ret=m_cipher->decryptElementDetached(encryptedData.getDOM());
112 if (ret->getNodeType()!=DOMNode::DOCUMENT_FRAGMENT_NODE) {
114 throw DecryptionException("Decryption operation did not result in DocumentFragment.");
116 return static_cast<DOMDocumentFragment*>(ret);
118 catch(XSECException& e) {
119 auto_ptr_char temp(e.getMsg());
120 throw DecryptionException(string("XMLSecurity exception while decrypting: ") + temp.get());
122 catch(XSECCryptoException& e) {
123 throw DecryptionException(string("XMLSecurity exception while decrypting: ") + e.getMsg());
127 XSECCryptoKey* Decrypter::decryptKey(EncryptedKey& encryptedKey, const XMLCh* algorithm)
129 if (encryptedKey.getDOM()==NULL)
130 throw DecryptionException("The object must be marshalled before decryption.");
132 // We can reuse the cipher object if the document hasn't changed.
134 if (m_cipher && m_cipher->getDocument()!=encryptedKey.getDOM()->getOwnerDocument()) {
135 XMLToolingInternalConfig::getInternalConfig().m_xsecProvider->releaseCipher(m_cipher);
140 m_cipher=XMLToolingInternalConfig::getInternalConfig().m_xsecProvider->newCipher(encryptedKey.getDOM()->getOwnerDocument());
143 // Resolve key decryption key.
144 XSECCryptoKey* key=NULL;
146 key=m_KEKresolver->getKey(encryptedKey.getKeyInfo());
148 throw DecryptionException("Unable to resolve a key decryption key.");
149 m_cipher->setKEK(key);
151 XMLByte buffer[1024];
152 int keySize = m_cipher->decryptKey(encryptedKey.getDOM(), buffer, 1024);
154 // Try to map the key.
155 XSECAlgorithmHandler* handler = XSECPlatformUtils::g_algorithmMapper->mapURIToHandler(algorithm);
157 return handler->createKeyForURI(algorithm, buffer, keySize);
158 throw DecryptionException("Unrecognized algorithm, could not build object around decrypted key.");
160 throw DecryptionException("Unable to decrypt key.");
162 catch(XSECException& e) {
163 auto_ptr_char temp(e.getMsg());
164 throw DecryptionException(string("XMLSecurity exception while decrypting: ") + temp.get());
166 catch(XSECCryptoException& e) {
167 throw DecryptionException(string("XMLSecurity exception while decrypting: ") + e.getMsg());