/**
 * 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
 *
 * XKMSRegisterResultImpl := Implementation of RegisterResult Messages
 *
 * $Id$
 *
 */

#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/utils/XSECDOMUtils.hpp>
#include <xsec/xkms/XKMSConstants.hpp>
#include <xsec/enc/XSECCryptoUtils.hpp>
#include <xsec/enc/XSECCryptoKey.hpp>
#include <xsec/xenc/XENCEncryptedData.hpp>
#include <xsec/xenc/XENCEncryptionMethod.hpp>
#include <xsec/xenc/XENCCipher.hpp>

#include "XKMSRegisterResultImpl.hpp"
#include "XKMSKeyBindingImpl.hpp"
#include "XKMSRSAKeyPairImpl.hpp"

#include <xercesc/dom/DOM.hpp>

XERCES_CPP_NAMESPACE_USE

// --------------------------------------------------------------------------------
//           Construct/Destruct
// --------------------------------------------------------------------------------

XKMSRegisterResultImpl::XKMSRegisterResultImpl(
		const XSECEnv * env) :
m_result(env),
m_msg(m_result.m_msg),
mp_RSAKeyPair(NULL),
mp_privateKeyElement(NULL) {

}

XKMSRegisterResultImpl::XKMSRegisterResultImpl(
		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) {

}

XKMSRegisterResultImpl::~XKMSRegisterResultImpl() {

	XKMSRegisterResultImpl::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 XKMSRegisterResultImpl::load() {

	if (m_msg.mp_messageAbstractTypeElement == NULL) {

		// Attempt to load an empty element
		throw XSECException(XSECException::XKMSError,
			"XKMSRegisterResult::load - called on empty DOM");

	}

	if (!strEquals(getXKMSLocalName(m_msg.mp_messageAbstractTypeElement), 
									XKMSConstants::s_tagRegisterResult)) {
	
		throw XSECException(XSECException::XKMSError,
			"XKMSRegisterResult::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 * XKMSRegisterResultImpl::createBlankRegisterResult(
		const XMLCh * service,
		const XMLCh * id,
		ResultMajor rmaj,
		ResultMinor rmin) {

	return m_result.createBlankResultType(
		XKMSConstants::s_tagRegisterResult, service, id, rmaj, rmin);

}

// --------------------------------------------------------------------------------
//           Get interface methods
// --------------------------------------------------------------------------------

XKMSMessageAbstractType::messageType XKMSRegisterResultImpl::getMessageType(void) {

	return XKMSMessageAbstractTypeImpl::RegisterResult;

}

// --------------------------------------------------------------------------------
//           UnverifiedKeyBinding handling
// --------------------------------------------------------------------------------


int XKMSRegisterResultImpl::getKeyBindingSize(void) const {

	return (int) m_keyBindingList.size();

}

XKMSKeyBinding * XKMSRegisterResultImpl::getKeyBindingItem(int item) const {

	if (item < 0 || item >= (int) m_keyBindingList.size()) {
		throw XSECException(XSECException::XKMSError,
			"XKMSRegisterResult::getKeyBindingItem - item out of range");
	}

	return m_keyBindingList[item];

}

XKMSKeyBinding * XKMSRegisterResultImpl::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 * XKMSRegisterResultImpl::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,
			"XKMSRegisterResult::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,
			"XKMSRegisterResult::getRSAKeyPair - error loading encrypted data");
	}

	// Setup the appropriate key
	if (xed->getEncryptionMethod() == NULL) {
		throw XSECException(XSECException::XKMSError,
			"XKMSRegisterResult::getRSAKeyPair - no <EncryptionMethod> in EncryptedData");
	}

	// Now find if we can get an algorithm for this URI
	XSECAlgorithmHandler *handler;

	handler = 
		XSECPlatformUtils::g_algorithmMapper->mapURIToHandler(
			xed->getEncryptionMethod()->getAlgorithm());

	if (handler == NULL) {
		throw XSECException(XSECException::XKMSError,
			"XKMSRegisterResult::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,
			"XKMSRegisterResult::getRSAKeyPair - private key did not decrypt to RSAKeyPair");
	
	}

	XSECnew(mp_RSAKeyPair, XKMSRSAKeyPairImpl(m_msg.mp_env, kp));
	mp_RSAKeyPair->load();

	return mp_RSAKeyPair;
}

XENCEncryptedData * XKMSRegisterResultImpl::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
	XSECAlgorithmHandler *handler =
		XSECPlatformUtils::g_algorithmMapper->mapURIToHandler(
			algorithmURI);

	if (handler == NULL) {
		throw XSECException(XSECException::XKMSError,
			"XKMSRegisterResult::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,
			"XKMSRegisterResult::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));

}	

