xsec/xkms/impl/XKMSRecoverResultImpl.cpp (207 lines of code) (raw):

/** * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ /* * XSEC * * XKMSRecoverResultImpl := Implementation of RecoverResult Messages * * $Id$ * */ #include <xsec/enc/XSECCryptoUtils.hpp> #include <xsec/enc/XSECCryptoKey.hpp> #include <xsec/framework/XSECDefs.hpp> #include <xsec/framework/XSECError.hpp> #include <xsec/framework/XSECEnv.hpp> #include <xsec/framework/XSECAlgorithmMapper.hpp> #include <xsec/framework/XSECAlgorithmHandler.hpp> #include <xsec/xenc/XENCEncryptedData.hpp> #include <xsec/xenc/XENCEncryptionMethod.hpp> #include <xsec/xenc/XENCCipher.hpp> #ifdef XSEC_XKMS_ENABLED #include "../../utils/XSECDOMUtils.hpp" #include "XKMSRecoverResultImpl.hpp" #include "XKMSKeyBindingImpl.hpp" #include "XKMSRSAKeyPairImpl.hpp" #include <xsec/xkms/XKMSConstants.hpp> #include <xercesc/dom/DOM.hpp> XERCES_CPP_NAMESPACE_USE // -------------------------------------------------------------------------------- // Construct/Destruct // -------------------------------------------------------------------------------- XKMSRecoverResultImpl::XKMSRecoverResultImpl( const XSECEnv * env) : m_result(env), m_msg(m_result.m_msg), mp_RSAKeyPair(NULL), mp_privateKeyElement(NULL) { } XKMSRecoverResultImpl::XKMSRecoverResultImpl( const XSECEnv * env, XERCES_CPP_NAMESPACE_QUALIFIER DOMElement * node) : m_result(env, node), m_msg(m_result.m_msg), mp_RSAKeyPair(NULL), mp_privateKeyElement(NULL) { } XKMSRecoverResultImpl::~XKMSRecoverResultImpl() { XKMSRecoverResultImpl::KeyBindingVectorType::iterator i; for (i = m_keyBindingList.begin() ; i != m_keyBindingList.end(); ++i) { delete (*i); } if (mp_RSAKeyPair != NULL) delete mp_RSAKeyPair; } // -------------------------------------------------------------------------------- // Load from DOM // -------------------------------------------------------------------------------- // Load elements void XKMSRecoverResultImpl::load() { if (m_msg.mp_messageAbstractTypeElement == NULL) { // Attempt to load an empty element throw XSECException(XSECException::XKMSError, "XKMSRecoverResult::load - called on empty DOM"); } if (!strEquals(getXKMSLocalName(m_msg.mp_messageAbstractTypeElement), XKMSConstants::s_tagRecoverResult)) { throw XSECException(XSECException::XKMSError, "XKMSRecoverResult::load - called incorrect node"); } // Get any UnverifiedKeyBinding elements DOMNodeList * nl = m_msg.mp_messageAbstractTypeElement->getElementsByTagNameNS( XKMSConstants::s_unicodeStrURIXKMS, XKMSConstants::s_tagKeyBinding); if (nl != NULL) { XKMSKeyBindingImpl * kb; for (unsigned int i = 0; i < nl->getLength() ; ++ i) { XSECnew(kb, XKMSKeyBindingImpl(m_msg.mp_env, (DOMElement *) nl->item(i))); m_keyBindingList.push_back(kb); kb->load(); } } nl = m_msg.mp_messageAbstractTypeElement->getElementsByTagNameNS( XKMSConstants::s_unicodeStrURIXKMS, XKMSConstants::s_tagPrivateKey); if (nl != NULL) mp_privateKeyElement = (DOMElement *) nl->item(0); // Load the base message m_result.load(); } // -------------------------------------------------------------------------------- // Create a blank one // -------------------------------------------------------------------------------- DOMElement * XKMSRecoverResultImpl::createBlankRecoverResult( const XMLCh * service, const XMLCh * id, ResultMajor rmaj, ResultMinor rmin) { return m_result.createBlankResultType( XKMSConstants::s_tagRecoverResult, service, id, rmaj, rmin); } // -------------------------------------------------------------------------------- // Get interface methods // -------------------------------------------------------------------------------- XKMSMessageAbstractType::messageType XKMSRecoverResultImpl::getMessageType(void) { return XKMSMessageAbstractTypeImpl::RecoverResult; } // -------------------------------------------------------------------------------- // UnverifiedKeyBinding handling // -------------------------------------------------------------------------------- int XKMSRecoverResultImpl::getKeyBindingSize(void) const { return (int) m_keyBindingList.size(); } XKMSKeyBinding * XKMSRecoverResultImpl::getKeyBindingItem(int item) const { if (item < 0 || item >= (int) m_keyBindingList.size()) { throw XSECException(XSECException::XKMSError, "XKMSRecoverResult::getKeyBindingItem - item out of range"); } return m_keyBindingList[item]; } XKMSKeyBinding * XKMSRecoverResultImpl::appendKeyBindingItem(XKMSStatus::StatusValue status) { XKMSKeyBindingImpl * u; XSECnew(u, XKMSKeyBindingImpl(m_msg.mp_env)); m_keyBindingList.push_back(u); DOMElement * e = u->createBlankKeyBinding(status); // Append the element DOMElement * c = findFirstElementChild(m_msg.mp_messageAbstractTypeElement); while (c != NULL) { if (strEquals(getXKMSLocalName(c), XKMSConstants::s_tagPrivateKey)) break; } if (c != NULL) { m_msg.mp_messageAbstractTypeElement->insertBefore(e, c); if (m_msg.mp_env->getPrettyPrintFlag()) { m_msg.mp_messageAbstractTypeElement->insertBefore( m_msg.mp_env->getParentDocument()->createTextNode(DSIGConstants::s_unicodeStrNL), c); } } else { m_msg.mp_messageAbstractTypeElement->appendChild(e); m_msg.mp_env->doPrettyPrint(m_msg.mp_messageAbstractTypeElement); } return u; } // -------------------------------------------------------------------------------- // RSAKeyPair handling // -------------------------------------------------------------------------------- XKMSRSAKeyPair * XKMSRecoverResultImpl::getRSAKeyPair(const char * passPhrase) { // Already done? if (mp_RSAKeyPair != NULL) return mp_RSAKeyPair; // Nope - can we do it? if (mp_privateKeyElement == NULL) return NULL; // Yep! Load the key unsigned char kbuf[XSEC_MAX_HASH_SIZE]; unsigned int len = CalculateXKMSKEK((unsigned char *) passPhrase, (int) strlen(passPhrase), kbuf, XSEC_MAX_HASH_SIZE); if (len == 0) { throw XSECException(XSECException::XKMSError, "XKMSRecoverResult::getRSAKeyPair - error deriving KEK"); } XSECProvider prov; XENCCipher * cipher = prov.newCipher(m_msg.mp_env->getParentDocument()); // Find the encrypted info DOMNode * n = findXENCNode(mp_privateKeyElement, "EncryptedData"); // Load into the Cipher class XENCEncryptedData * xed = cipher->loadEncryptedData((DOMElement *) n); if (xed == NULL) { throw XSECException(XSECException::XKMSError, "XKMSRecoverResult::getRSAKeyPair - error loading encrypted data"); } // Setup the appropriate key if (xed->getEncryptionMethod() == NULL) { throw XSECException(XSECException::XKMSError, "XKMSRecoverResult::getRSAKeyPair - no <EncryptionMethod> in EncryptedData"); } // Now find if we can get an algorithm for this URI const XSECAlgorithmHandler *handler = XSECPlatformUtils::g_algorithmMapper->mapURIToHandler( xed->getEncryptionMethod()->getAlgorithm()); if (handler == NULL) { throw XSECException(XSECException::XKMSError, "XKMSRecoverResult::getRSAKeyPair - unable to handle algorithm in EncryptedData"); } XSECCryptoKey * sk = handler->createKeyForURI( xed->getEncryptionMethod()->getAlgorithm(), (XMLByte *) kbuf, len); memset(kbuf, 0, XSEC_MAX_HASH_SIZE); cipher->setKey(sk); cipher->decryptElement(); // WooHoo - if we get this far things are looking good! DOMElement * kp = findFirstElementChild(mp_privateKeyElement); if (kp == NULL || !strEquals(getXKMSLocalName(kp), XKMSConstants::s_tagRSAKeyPair)) { throw XSECException(XSECException::XKMSError, "XKMSRecoverResult::getRSAKeyPair - private key did not decrypt to RSAKeyPair"); } XSECnew(mp_RSAKeyPair, XKMSRSAKeyPairImpl(m_msg.mp_env, kp)); mp_RSAKeyPair->load(); return mp_RSAKeyPair; } XENCEncryptedData * XKMSRecoverResultImpl::setRSAKeyPair(const char * passPhrase, XMLCh * Modulus, XMLCh * Exponent, XMLCh * P, XMLCh * Q, XMLCh * DP, XMLCh * DQ, XMLCh * InverseQ, XMLCh * D, const XMLCh * algorithmURI) { // Try to set up the key first - if this fails, don't want to have added the // XML // Find if we can get an algorithm for this URI const XSECAlgorithmHandler *handler = XSECPlatformUtils::g_algorithmMapper->mapURIToHandler(algorithmURI); if (handler == NULL) { throw XSECException(XSECException::XKMSError, "XKMSRecoverResult::setRSAKeyPair - unable to handle algorithm"); } unsigned char kbuf[XSEC_MAX_HASH_SIZE]; unsigned int len = CalculateXKMSKEK((unsigned char *) passPhrase, (int) strlen(passPhrase), kbuf, XSEC_MAX_HASH_SIZE); if (len == 0) { throw XSECException(XSECException::XKMSError, "XKMSRecoverResult::setRSAKeyPair - error deriving KEK"); } XSECCryptoKey * sk = handler->createKeyForURI( algorithmURI, (XMLByte *) kbuf, len); memset(kbuf, 0, XSEC_MAX_HASH_SIZE); // Get some setup values safeBuffer str; DOMDocument *doc = m_msg.mp_env->getParentDocument(); const XMLCh * prefix = m_msg.mp_env->getXKMSNSPrefix(); makeQName(str, prefix, XKMSConstants::s_tagPrivateKey); // Create a PrivateKey to add this to DOMElement * pk = doc->createElementNS(XKMSConstants::s_unicodeStrURIXKMS, str.rawXMLChBuffer()); m_msg.mp_env->doPrettyPrint(pk); // Add it to the request doc m_msg.mp_messageAbstractTypeElement->appendChild(pk); m_msg.mp_env->doPrettyPrint(m_msg.mp_messageAbstractTypeElement); // Now create the RSA structure XKMSRSAKeyPairImpl * rsa; XSECnew(rsa, XKMSRSAKeyPairImpl(m_msg.mp_env)); DOMElement * e = rsa->createBlankXKMSRSAKeyPairImpl(Modulus, Exponent, P, Q, DP, DQ, InverseQ, D); // Add it to the PrivateKey pk->appendChild(e); m_msg.mp_env->doPrettyPrint(pk); // Encrypt all of this for future use XENCCipher * cipher = m_prov.newCipher(m_msg.mp_env->getParentDocument()); cipher->setKey(sk); cipher->encryptElementContent(pk, algorithmURI); // Now load the encrypted data back in return cipher->loadEncryptedData(findFirstElementChild(pk)); } #endif /* XSEC_XKMS_ENABLED */