blob: 8e666b96b5c007a4ae4bdea76cd3e96cff438479 [file] [log] [blame]
/**
* 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
*
* XENCEncryptedTypeImpl := Implementation of the EncryptedType interface
* element
*
* $Id$
*
*/
#include <xsec/dsig/DSIGReference.hpp>
#include <xsec/framework/XSECDefs.hpp>
#include <xsec/framework/XSECEnv.hpp>
#include <xsec/framework/XSECError.hpp>
#include <xsec/transformers/TXFMBase64.hpp>
#include <xsec/transformers/TXFMChain.hpp>
#include <xsec/transformers/TXFMSB.hpp>
#include <xsec/transformers/TXFMC14n.hpp>
#include <xsec/xenc/XENCEncryptedKey.hpp>
#include "XENCCipherImpl.hpp"
#include "XENCCipherDataImpl.hpp"
#include "XENCEncryptedTypeImpl.hpp"
#include "XENCEncryptionMethodImpl.hpp"
#include "../../utils/XSECAutoPtr.hpp"
#include "../../utils/XSECDOMUtils.hpp"
#include <xercesc/util/XMLUniDefs.hpp>
#include <xercesc/util/Janitor.hpp>
XERCES_CPP_NAMESPACE_USE
// --------------------------------------------------------------------------------
// UNICODE Strings
// --------------------------------------------------------------------------------
static XMLCh s_EncryptionMethod[] = {
chLatin_E,
chLatin_n,
chLatin_c,
chLatin_r,
chLatin_y,
chLatin_p,
chLatin_t,
chLatin_i,
chLatin_o,
chLatin_n,
chLatin_M,
chLatin_e,
chLatin_t,
chLatin_h,
chLatin_o,
chLatin_d,
chNull,
};
static XMLCh s_KeyInfo[] = {
chLatin_K,
chLatin_e,
chLatin_y,
chLatin_I,
chLatin_n,
chLatin_f,
chLatin_o,
chNull,
};
static XMLCh s_CipherData[] = {
chLatin_C,
chLatin_i,
chLatin_p,
chLatin_h,
chLatin_e,
chLatin_r,
chLatin_D,
chLatin_a,
chLatin_t,
chLatin_a,
chNull,
};
static XMLCh s_Type[] = {
chLatin_T,
chLatin_y,
chLatin_p,
chLatin_e,
chNull
};
static XMLCh s_MimeType[] = {
chLatin_M,
chLatin_i,
chLatin_m,
chLatin_e,
chLatin_T,
chLatin_y,
chLatin_p,
chLatin_e,
chNull
};
static XMLCh s_Encoding[] = {
chLatin_E,
chLatin_n,
chLatin_c,
chLatin_o,
chLatin_d,
chLatin_i,
chLatin_n,
chLatin_g,
chNull
};
// --------------------------------------------------------------------------------
// Constructors and Destructors
// --------------------------------------------------------------------------------
XENCEncryptedTypeImpl::XENCEncryptedTypeImpl(const XSECEnv * env) :
mp_env(env),
mp_encryptedTypeElement(NULL),
mp_keyInfoElement(NULL),
mp_cipherDataElement(NULL),
mp_cipherData(NULL),
mp_encryptionMethod(NULL),
m_keyInfoList(env),
mp_typeAttr(NULL),
mp_mimeTypeAttr(NULL),
mp_encodingAttr(NULL) {
}
XENCEncryptedTypeImpl::XENCEncryptedTypeImpl(const XSECEnv * env, DOMElement * node) :
mp_env(env),
mp_encryptedTypeElement(node),
mp_keyInfoElement(NULL),
mp_cipherDataElement(NULL),
mp_cipherData(NULL),
mp_encryptionMethod(NULL),
m_keyInfoList(env),
mp_typeAttr(NULL),
mp_mimeTypeAttr(NULL),
mp_encodingAttr(NULL) {
}
XENCEncryptedTypeImpl::~XENCEncryptedTypeImpl() {
if (mp_cipherData != NULL)
delete mp_cipherData;
if (mp_encryptionMethod != NULL)
delete mp_encryptionMethod;
}
// --------------------------------------------------------------------------------
// Load DOM Structures
// --------------------------------------------------------------------------------
void XENCEncryptedTypeImpl::load() {
if (mp_encryptedTypeElement == NULL) {
// Attempt to load an empty encryptedType element
throw XSECException(XSECException::EncryptedTypeError,
"XENCEncryptedType::load - called on empty DOM");
}
// Type
mp_typeAttr = mp_encryptedTypeElement->getAttributeNodeNS(NULL, s_Type);
// MimeType
mp_mimeTypeAttr = mp_encryptedTypeElement->getAttributeNodeNS(NULL, s_MimeType);
// Encoding
mp_encodingAttr = mp_encryptedTypeElement->getAttributeNodeNS(NULL, s_Encoding);
// Don't know what the node name should be (held by super class),
// so go straight to the children
DOMElement *tmpElt = (DOMElement *) findFirstChildOfType(mp_encryptedTypeElement, DOMNode::ELEMENT_NODE);
if (tmpElt != NULL && strEquals(getXENCLocalName(tmpElt), s_EncryptionMethod)) {
XSECnew(mp_encryptionMethod, XENCEncryptionMethodImpl(mp_env, tmpElt));
mp_encryptionMethod->load();
tmpElt = findNextElementChild(tmpElt);
}
if (tmpElt != NULL && strEquals(getDSIGLocalName(tmpElt), s_KeyInfo)) {
// Load
mp_keyInfoElement = tmpElt;
m_keyInfoList.loadListFromXML(tmpElt);
// Find the next node
tmpElt = findNextElementChild(tmpElt);
}
if (tmpElt != NULL && strEquals(getXENCLocalName(tmpElt), s_CipherData)) {
mp_cipherDataElement = tmpElt;
XSECnew(mp_cipherData, XENCCipherDataImpl(mp_env, tmpElt));
mp_cipherData->load();
tmpElt = findNextElementChild(tmpElt);
}
else {
throw XSECException(XSECException::ExpectedXENCChildNotFound,
"Expected <CipherData> child of <EncryptedType>");
}
// Should check for EncryptionProperties
}
// --------------------------------------------------------------------------------
// Create a blank structure
// --------------------------------------------------------------------------------
DOMElement * XENCEncryptedTypeImpl::createBlankEncryptedType(
XMLCh * localName,
XENCCipherData::XENCCipherDataType type,
const XMLCh * algorithm,
const XMLCh * value) {
// Reset
mp_cipherData = NULL;
mp_encryptionMethod = NULL;
// Get some setup values
safeBuffer str;
DOMDocument *doc = mp_env->getParentDocument();
const XMLCh * prefix = mp_env->getXENCNSPrefix();
makeQName(str, prefix, localName);
mp_encryptedTypeElement = doc->createElementNS(DSIGConstants::s_unicodeStrURIXENC, str.rawXMLChBuffer());
// Set namespace
if (prefix[0] == XERCES_CPP_NAMESPACE_QUALIFIER chNull) {
str.sbTranscodeIn("xmlns");
}
else {
str.sbTranscodeIn("xmlns:");
str.sbXMLChCat(prefix);
}
mp_encryptedTypeElement->setAttributeNS(DSIGConstants::s_unicodeStrURIXMLNS,
str.rawXMLChBuffer(),
DSIGConstants::s_unicodeStrURIXENC);
mp_env->doPrettyPrint(mp_encryptedTypeElement);
// Create the EncryptionMethod
if (algorithm != NULL) {
XSECnew(mp_encryptionMethod, XENCEncryptionMethodImpl(mp_env));
DOMNode * encryptionMethodNode =
mp_encryptionMethod->createBlankEncryptionMethod(algorithm);
mp_encryptedTypeElement->appendChild(encryptionMethodNode);
mp_env->doPrettyPrint(mp_encryptedTypeElement);
}
// Create the cipher Data
XSECnew(mp_cipherData, XENCCipherDataImpl(mp_env));
mp_cipherDataElement = mp_cipherData->createBlankCipherData(type, value);
// Add to EncryptedType
mp_encryptedTypeElement->appendChild(mp_cipherDataElement);
mp_env->doPrettyPrint(mp_encryptedTypeElement);
return mp_encryptedTypeElement;
}
// --------------------------------------------------------------------------------
// Create a txfm chain for this transform list
// --------------------------------------------------------------------------------
TXFMChain * XENCEncryptedTypeImpl::createCipherTXFMChain(void) {
if (mp_cipherData->getCipherDataType() == XENCCipherData::VALUE_TYPE) {
TXFMChain * chain;
// Given we already have this in memory, we transcode to
// local code page and then transform
XSECAutoPtrChar b64(mp_cipherData->getCipherValue()->getCipherString());
try {
TXFMSB *sb;
XSECnew(sb, TXFMSB(mp_env->getParentDocument()));
safeBuffer temp(b64.get());
sb->setInput(temp);
// Create a chain
XSECnew(chain, TXFMChain(sb));
// Create a base64 decoder
TXFMBase64 * tb64;
XSECnew(tb64, TXFMBase64(mp_env->getParentDocument()));
chain->appendTxfm(tb64);
return chain;
}
catch (...) {
throw;
}
}
else if (mp_cipherData->getCipherDataType() == XENCCipherData::REFERENCE_TYPE) {
TXFMChain * chain;
TXFMBase * b = DSIGReference::getURIBaseTXFM(mp_env->getParentDocument(), mp_cipherData->getCipherReference()->getURI(), mp_env);
chain = DSIGReference::createTXFMChainFromList(b, mp_cipherData->getCipherReference()->getTransforms());
Janitor<TXFMChain> j_chain(chain);
if (chain->getLastTxfm()->getOutputType() == TXFMBase::DOM_NODES) {
TXFMC14n * c14n;
XSECnew(c14n, TXFMC14n(mp_env->getParentDocument()));
chain->appendTxfm(c14n);
}
j_chain.release();
return chain;
}
else {
throw XSECException(XSECException::EncryptedTypeError,
"XENCEncryptedType::createDecryptionTXFMChain - Unknown type of CipherData");
}
}
// --------------------------------------------------------------------------------
// Get Methods
// --------------------------------------------------------------------------------
XENCCipherData * XENCEncryptedTypeImpl::getCipherData() const {
return mp_cipherData;
}
XENCEncryptionMethod * XENCEncryptedTypeImpl::getEncryptionMethod() const {
return mp_encryptionMethod;
}
// --------------------------------------------------------------------------------
// KeyInfo elements
// --------------------------------------------------------------------------------
const DSIGKeyInfoList * XENCEncryptedTypeImpl::getKeyInfoList() const {
return &m_keyInfoList;
}
DSIGKeyInfoList * XENCEncryptedTypeImpl::getKeyInfoList() {
return &m_keyInfoList;
}
void XENCEncryptedTypeImpl::clearKeyInfo() {
if (mp_keyInfoElement == NULL)
return;
if (mp_encryptedTypeElement->removeChild(mp_keyInfoElement) != mp_keyInfoElement) {
throw XSECException(XSECException::ExpectedDSIGChildNotFound,
"Attempted to remove KeyInfo node but it is no longer a child of <EncryptedType>");
}
mp_keyInfoElement->release(); // No longer required
mp_keyInfoElement = NULL;
// Clear out the list
m_keyInfoList.empty();
}
void XENCEncryptedTypeImpl::createKeyInfoElement() {
if (mp_keyInfoElement != NULL)
return;
safeBuffer str;
const XMLCh * prefixNS = mp_env->getDSIGNSPrefix();
makeQName(str, prefixNS, "KeyInfo");
mp_keyInfoElement = m_keyInfoList.createKeyInfo();
// Place the node before the CipherData node
if (mp_cipherDataElement == NULL) {
throw XSECException(XSECException::EncryptedTypeError,
"XENCEncryptedTypeImpl::createKeyInfoElement - unable to find CipherData node");
}
mp_encryptedTypeElement->insertBefore(mp_keyInfoElement, mp_cipherDataElement);
if (mp_env->getPrettyPrintFlag() == true)
mp_encryptedTypeElement->insertBefore(mp_env->getParentDocument()->createTextNode(DSIGConstants::s_unicodeStrNL), mp_cipherDataElement);
// Need to add the DS namespace
if (prefixNS[0] == '\0') {
str.sbTranscodeIn("xmlns");
}
else {
str.sbTranscodeIn("xmlns:");
str.sbXMLChCat(prefixNS);
}
mp_keyInfoElement->setAttributeNS(DSIGConstants::s_unicodeStrURIXMLNS,
str.rawXMLChBuffer(),
DSIGConstants::s_unicodeStrURIDSIG);
}
DSIGKeyInfoValue * XENCEncryptedTypeImpl::appendDSAKeyValue(const XMLCh * P,
const XMLCh * Q,
const XMLCh * G,
const XMLCh * Y) {
createKeyInfoElement();
return m_keyInfoList.appendDSAKeyValue(P, Q, G, Y);
}
DSIGKeyInfoValue * XENCEncryptedTypeImpl::appendRSAKeyValue(const XMLCh * modulus,
const XMLCh * exponent) {
createKeyInfoElement();
return m_keyInfoList.appendRSAKeyValue(modulus, exponent);
}
DSIGKeyInfoX509 * XENCEncryptedTypeImpl::appendX509Data() {
createKeyInfoElement();
return m_keyInfoList.appendX509Data();
}
DSIGKeyInfoName * XENCEncryptedTypeImpl::appendKeyName(const XMLCh * name, bool isDName) {
createKeyInfoElement();
return m_keyInfoList.appendKeyName(name, isDName);
}
DSIGKeyInfoPGPData * XENCEncryptedTypeImpl::appendPGPData(const XMLCh * id, const XMLCh * packet) {
createKeyInfoElement();
return m_keyInfoList.appendPGPData(id, packet);
}
DSIGKeyInfoSPKIData * XENCEncryptedTypeImpl::appendSPKIData(const XMLCh * sexp) {
createKeyInfoElement();
return m_keyInfoList.appendSPKIData(sexp);
}
DSIGKeyInfoMgmtData * XENCEncryptedTypeImpl::appendMgmtData(const XMLCh * data) {
createKeyInfoElement();
return m_keyInfoList.appendMgmtData(data);
}
void XENCEncryptedTypeImpl::appendEncryptedKey(XENCEncryptedKey * encryptedKey) {
createKeyInfoElement();
m_keyInfoList.addAndInsertKeyInfo(encryptedKey);
}
// --------------------------------------------------------------------------------
// Type URI handling
// --------------------------------------------------------------------------------
const XMLCh * XENCEncryptedTypeImpl::getType() const {
if (mp_typeAttr != NULL)
return mp_typeAttr->getNodeValue();
return NULL;
}
void XENCEncryptedTypeImpl::setType(const XMLCh * uri) {
if (mp_typeAttr != NULL) {
mp_typeAttr->setNodeValue(uri);
}
else {
// Need to create the node
mp_encryptedTypeElement->setAttributeNS(NULL, s_Type, uri);
mp_typeAttr = mp_encryptedTypeElement->getAttributeNodeNS(NULL, s_Type);
if (mp_typeAttr == NULL) {
throw XSECException(XSECException::InternalError,
"XENCEncryptedTypeImpl::setTypeURI - Cannot find the attribute I just added");
}
}
}
// --------------------------------------------------------------------------------
// MimeType handling
// --------------------------------------------------------------------------------
const XMLCh * XENCEncryptedTypeImpl::getMimeType() const {
if (mp_mimeTypeAttr != NULL)
return mp_mimeTypeAttr->getNodeValue();
return NULL;
}
void XENCEncryptedTypeImpl::setMimeType(const XMLCh * mimeType) {
if (mp_mimeTypeAttr != NULL) {
mp_mimeTypeAttr->setNodeValue(mimeType);
}
else {
// Need to create the node
mp_encryptedTypeElement->setAttributeNS(NULL, s_MimeType, mimeType);
mp_mimeTypeAttr = mp_encryptedTypeElement->getAttributeNodeNS(NULL, s_MimeType);
if (mp_mimeTypeAttr == NULL) {
throw XSECException(XSECException::InternalError,
"XENCEncryptedTypeImpl::setMimeType - Cannot find the attribute I just added");
}
}
}
// --------------------------------------------------------------------------------
// Encoding handling
// --------------------------------------------------------------------------------
const XMLCh * XENCEncryptedTypeImpl::getEncoding() const {
if (mp_encodingAttr != NULL)
return mp_encodingAttr->getNodeValue();
return NULL;
}
void XENCEncryptedTypeImpl::setEncoding(const XMLCh * uri) {
if (mp_encodingAttr != NULL) {
mp_encodingAttr->setNodeValue(uri);
}
else {
// Need to create the node
mp_encryptedTypeElement->setAttributeNS(NULL, s_Encoding, uri);
mp_encodingAttr = mp_encryptedTypeElement->getAttributeNodeNS(NULL, s_Encoding);
if (mp_encodingAttr == NULL) {
throw XSECException(XSECException::InternalError,
"XENCEncryptedTypeImpl::setEncodingURI - Cannot find the attribute I just added");
}
}
}