X-Git-Url: http://www.project-moonshot.org/gitweb/?a=blobdiff_plain;f=xmltooling%2Fencryption%2Fimpl%2FDecrypter.cpp;h=47ed588ea5f4c39fb64e2a1d8cdbc834ea395064;hb=64dcaec957e9befd960779498d7fe35bbb62141a;hp=5a34ab88b325659c909c41d208eb4a433c8be745;hpb=25a6bdaedbe29dedc179cf7497501aa53a5e7b04;p=shibboleth%2Fcpp-xmltooling.git diff --git a/xmltooling/encryption/impl/Decrypter.cpp b/xmltooling/encryption/impl/Decrypter.cpp index 5a34ab8..47ed588 100644 --- a/xmltooling/encryption/impl/Decrypter.cpp +++ b/xmltooling/encryption/impl/Decrypter.cpp @@ -21,17 +21,18 @@ */ #include "internal.h" +#include "logging.h" #include "encryption/Decrypter.h" #include "encryption/EncryptedKeyResolver.h" #include "security/Credential.h" #include "security/CredentialCriteria.h" #include "security/CredentialResolver.h" -#include #include #include #include #include +#include #include #include @@ -86,25 +87,25 @@ DOMDocumentFragment* Decrypter::decryptData(const EncryptedData& encryptedData, // Resolve a decryption key directly. vector creds; + int types = + CredentialCriteria::KEYINFO_EXTRACTION_KEY | + CredentialCriteria::KEYINFO_EXTRACTION_KEYNAMES | + CredentialCriteria::KEYINFO_EXTRACTION_IMPLICIT_KEYNAMES; if (m_criteria) { m_criteria->setUsage(CredentialCriteria::ENCRYPTION_CREDENTIAL); - m_criteria->setKeyInfo(encryptedData.getKeyInfo()); + m_criteria->setKeyInfo(encryptedData.getKeyInfo(), types); const EncryptionMethod* meth = encryptedData.getEncryptionMethod(); - if (meth) { - auto_ptr_char alg(meth->getAlgorithm()); - m_criteria->setKeyAlgorithm(alg.get()); - } + if (meth) + m_criteria->setXMLAlgorithm(meth->getAlgorithm()); m_credResolver->resolve(creds,m_criteria); } else { CredentialCriteria criteria; criteria.setUsage(CredentialCriteria::ENCRYPTION_CREDENTIAL); - criteria.setKeyInfo(encryptedData.getKeyInfo()); + criteria.setKeyInfo(encryptedData.getKeyInfo(), types); const EncryptionMethod* meth = encryptedData.getEncryptionMethod(); - if (meth) { - auto_ptr_char alg(meth->getAlgorithm()); - criteria.setKeyAlgorithm(alg.get()); - } + if (meth) + criteria.setXMLAlgorithm(meth->getAlgorithm()); m_credResolver->resolve(creds,&criteria); } @@ -118,7 +119,7 @@ DOMDocumentFragment* Decrypter::decryptData(const EncryptedData& encryptedData, return decryptData(encryptedData, key); } catch(DecryptionException& ex) { - log4cpp::Category::getInstance(XMLTOOLING_LOGCAT".Decrypter").warn(ex.what()); + logging::Category::getInstance(XMLTOOLING_LOGCAT".Decrypter").warn(ex.what()); } } @@ -146,6 +147,106 @@ DOMDocumentFragment* Decrypter::decryptData(const EncryptedData& encryptedData, return decryptData(encryptedData, keywrapper.get()); } +void Decrypter::decryptData(ostream& out, const EncryptedData& encryptedData, XSECCryptoKey* key) +{ + if (encryptedData.getDOM()==NULL) + throw DecryptionException("The object must be marshalled before decryption."); + + // We can reuse the cipher object if the document hasn't changed. + + if (m_cipher && m_cipher->getDocument()!=encryptedData.getDOM()->getOwnerDocument()) { + XMLToolingInternalConfig::getInternalConfig().m_xsecProvider->releaseCipher(m_cipher); + m_cipher=NULL; + } + + if (!m_cipher) + m_cipher=XMLToolingInternalConfig::getInternalConfig().m_xsecProvider->newCipher(encryptedData.getDOM()->getOwnerDocument()); + + try { + m_cipher->setKey(key->clone()); + auto_ptr in(m_cipher->decryptToBinInputStream(encryptedData.getDOM())); + + XMLByte buf[8192]; + unsigned int count = in->readBytes(buf, sizeof(buf)); + while (count > 0) + out.write(reinterpret_cast(buf),count); + } + catch(XSECException& e) { + auto_ptr_char temp(e.getMsg()); + throw DecryptionException(string("XMLSecurity exception while decrypting: ") + temp.get()); + } + catch(XSECCryptoException& e) { + throw DecryptionException(string("XMLSecurity exception while decrypting: ") + e.getMsg()); + } +} + +void Decrypter::decryptData(ostream& out, const EncryptedData& encryptedData, const XMLCh* recipient) +{ + if (!m_credResolver) + throw DecryptionException("No CredentialResolver supplied to provide decryption keys."); + + // Resolve a decryption key directly. + vector creds; + int types = + CredentialCriteria::KEYINFO_EXTRACTION_KEY | + CredentialCriteria::KEYINFO_EXTRACTION_KEYNAMES | + CredentialCriteria::KEYINFO_EXTRACTION_IMPLICIT_KEYNAMES; + if (m_criteria) { + m_criteria->setUsage(CredentialCriteria::ENCRYPTION_CREDENTIAL); + m_criteria->setKeyInfo(encryptedData.getKeyInfo(), types); + const EncryptionMethod* meth = encryptedData.getEncryptionMethod(); + if (meth) + m_criteria->setXMLAlgorithm(meth->getAlgorithm()); + m_credResolver->resolve(creds,m_criteria); + } + else { + CredentialCriteria criteria; + criteria.setUsage(CredentialCriteria::ENCRYPTION_CREDENTIAL); + criteria.setKeyInfo(encryptedData.getKeyInfo(), types); + const EncryptionMethod* meth = encryptedData.getEncryptionMethod(); + if (meth) + criteria.setXMLAlgorithm(meth->getAlgorithm()); + m_credResolver->resolve(creds,&criteria); + } + + // Loop over them and try each one. + XSECCryptoKey* key; + for (vector::const_iterator cred = creds.begin(); cred!=creds.end(); ++cred) { + try { + key = (*cred)->getPrivateKey(); + if (!key) + continue; + return decryptData(out, encryptedData, key); + } + catch(DecryptionException& ex) { + logging::Category::getInstance(XMLTOOLING_LOGCAT".Decrypter").warn(ex.what()); + } + } + + // We need to find an encrypted decryption key somewhere. We'll need the underlying algorithm... + const XMLCh* algorithm= + encryptedData.getEncryptionMethod() ? encryptedData.getEncryptionMethod()->getAlgorithm() : NULL; + if (!algorithm) + throw DecryptionException("No EncryptionMethod/@Algorithm set, key decryption cannot proceed."); + + // Check for external resolver. + const EncryptedKey* encKey=NULL; + if (m_EKResolver) + encKey = m_EKResolver->resolveKey(encryptedData, recipient); + else { + EncryptedKeyResolver ekr; + encKey = ekr.resolveKey(encryptedData, recipient); + } + + if (!encKey) + throw DecryptionException("Unable to locate an encrypted key."); + + auto_ptr keywrapper(decryptKey(*encKey, algorithm)); + if (!keywrapper.get()) + throw DecryptionException("Unable to decrypt the encrypted key."); + decryptData(out, encryptedData, keywrapper.get()); +} + XSECCryptoKey* Decrypter::decryptKey(const EncryptedKey& encryptedKey, const XMLCh* algorithm) { if (!m_credResolver) @@ -168,28 +269,27 @@ XSECCryptoKey* Decrypter::decryptKey(const EncryptedKey& encryptedKey, const XML if (!m_cipher) m_cipher=XMLToolingInternalConfig::getInternalConfig().m_xsecProvider->newCipher(encryptedKey.getDOM()->getOwnerDocument()); - // Resolve key decryption key. We can't loop over possible credentials because - // we can't tell a valid decrypt from an invalid one. + // Resolve key decryption keys. + int types = + CredentialCriteria::KEYINFO_EXTRACTION_KEY | + CredentialCriteria::KEYINFO_EXTRACTION_KEYNAMES | + CredentialCriteria::KEYINFO_EXTRACTION_IMPLICIT_KEYNAMES; vector creds; if (m_criteria) { m_criteria->setUsage(CredentialCriteria::ENCRYPTION_CREDENTIAL); - m_criteria->setKeyInfo(encryptedKey.getKeyInfo()); + m_criteria->setKeyInfo(encryptedKey.getKeyInfo(), types); const EncryptionMethod* meth = encryptedKey.getEncryptionMethod(); - if (meth) { - auto_ptr_char alg(meth->getAlgorithm()); - m_criteria->setKeyAlgorithm(alg.get()); - } + if (meth) + m_criteria->setXMLAlgorithm(meth->getAlgorithm()); m_credResolver->resolve(creds, m_criteria); } else { CredentialCriteria criteria; criteria.setUsage(CredentialCriteria::ENCRYPTION_CREDENTIAL); - criteria.setKeyInfo(encryptedKey.getKeyInfo()); + criteria.setKeyInfo(encryptedKey.getKeyInfo(), types); const EncryptionMethod* meth = encryptedKey.getEncryptionMethod(); - if (meth) { - auto_ptr_char alg(meth->getAlgorithm()); - criteria.setKeyAlgorithm(alg.get()); - } + if (meth) + criteria.setXMLAlgorithm(meth->getAlgorithm()); m_credResolver->resolve(creds, &criteria); } if (creds.empty()) @@ -220,7 +320,7 @@ XSECCryptoKey* Decrypter::decryptKey(const EncryptedKey& encryptedKey, const XML } } catch(DecryptionException& ex) { - log4cpp::Category::getInstance(XMLTOOLING_LOGCAT".Decrypter").warn(ex.what()); + logging::Category::getInstance(XMLTOOLING_LOGCAT".Decrypter").warn(ex.what()); } }