xmlsecurityengine/xmlsec/src/xmlsec_xkms.c
changeset 0 e35f40988205
child 8 e65204f75c47
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/xmlsecurityengine/xmlsec/src/xmlsec_xkms.c	Thu Dec 17 09:29:21 2009 +0200
@@ -0,0 +1,5016 @@
+/** 
+ * XML Security Library (http://www.aleksey.com/xmlsec).
+ *
+ * "XML Key Management Specification v 2.0" implementation
+ *  http://www.w3.org/TR/xkms2/
+ * 
+ * This is free software; see Copyright file in the source
+ * distribution for preciese wording.
+ * 
+ * Copyright (C) 2002-2003 Aleksey Sanin <aleksey@aleksey.com>
+ * Portion Copyright © 2009 Nokia Corporation and/or its subsidiary(-ies). All rights reserved. 
+ */
+
+#include "xmlsec_config.h"
+#ifndef XMLSEC_NO_XKMS
+#include "xmlsec_globals.h"
+ 
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+
+#include <libxml2_tree.h>
+#include <libxml2_parser.h>
+#include <libxml2_globals.h>
+
+#include "xmlsec_xmlsec.h"
+#include "xmlsec_buffer.h"
+#include "xmlsec_xmltree.h"
+#include "xmlsec_keys.h"
+#include "xmlsec_keysmngr.h"
+#include "xmlsec_transforms.h"
+#include "xmlsec_keyinfo.h"
+#include "xmlsec_soap.h"
+#include "xmlsec_xkms.h"
+#include "xmlsec_private.h"
+#include "xmlsec_privatexkms.h"
+#include "xmlsec_errors.h"
+
+#define XMLSEC_XKMS_ID_ATTRIBUTE_LEN		32
+
+/* The ID attribute in XKMS is 'Id' */
+static const xmlChar* xmlSecXkmsServerIds[] = { BAD_CAST "Id", NULL };
+
+#ifndef XMLSEC_NO_SOAP
+static int      xmlSecXkmsServerCtxWriteSoap11FatalError	(xmlSecXkmsServerCtxPtr ctx,
+							         xmlNodePtr envNode);
+static int      xmlSecXkmsServerCtxWriteSoap12FatalError	(xmlSecXkmsServerCtxPtr ctx,
+							         xmlNodePtr envNode);
+#endif /* XMLSEC_NO_SOAP */
+
+static int	xmlSecXkmsServerCtxRequestAbstractTypeNodeRead	(xmlSecXkmsServerCtxPtr ctx,
+							         xmlNodePtr* node);
+static int	xmlSecXkmsServerCtxSignatureNodeRead		(xmlSecXkmsServerCtxPtr ctx, 
+								 xmlNodePtr node);
+static int	xmlSecXkmsServerCtxMessageExtensionNodesRead	(xmlSecXkmsServerCtxPtr ctx, 
+								 xmlNodePtr* node);
+static int	xmlSecXkmsServerCtxOpaqueClientDataNodeRead	(xmlSecXkmsServerCtxPtr ctx, 
+								 xmlNodePtr node);
+static int	xmlSecXkmsServerCtxPendingNotificationNodeRead	(xmlSecXkmsServerCtxPtr ctx, 
+								 xmlNodePtr node);
+static int	xmlSecXkmsServerCtxRespondWithNodesRead		(xmlSecXkmsServerCtxPtr ctx, 
+								 xmlNodePtr* node);
+static int	xmlSecXkmsServerCtxPendingRequestNodeRead	(xmlSecXkmsServerCtxPtr ctx,
+							         xmlNodePtr* node);
+static int	xmlSecXkmsServerCtxQueryKeyBindingNodeRead	(xmlSecXkmsServerCtxPtr ctx,
+								 xmlNodePtr node);
+static int	xmlSecXkmsServerCtxKeyBindingAbstractTypeNodeRead(xmlSecXkmsServerCtxPtr ctx,
+							         xmlNodePtr* node);
+static int	xmlSecXkmsServerCtxKeyBindingAbstractTypeNodeWrite(xmlSecXkmsServerCtxPtr ctx,
+							         xmlNodePtr node,
+								 xmlSecKeyPtr key);
+static int	xmlSecXkmsServerCtxKeyInfoNodeWrite		(xmlSecXkmsServerCtxPtr ctx,
+							    	 xmlNodePtr node,
+								 xmlSecKeyPtr key);
+static int	xmlSecXkmsServerCtxUseKeyWithNodesRead		(xmlSecXkmsServerCtxPtr ctx, 
+								 xmlNodePtr* node);
+static int	xmlSecXkmsServerCtxUseKeyWithNodesWrite		(xmlSecXkmsServerCtxPtr ctx, 
+								 xmlNodePtr node,
+								 xmlSecKeyPtr key);
+static int	xmlSecXkmsServerCtxTimeInstantNodeRead		(xmlSecXkmsServerCtxPtr ctx,
+								 xmlNodePtr node);
+static int	xmlSecXkmsServerCtxResultTypeNodeWrite		(xmlSecXkmsServerCtxPtr ctx, 
+								 xmlNodePtr node);
+static int	xmlSecXkmsServerCtxRequestSignatureValueNodeWrite(xmlSecXkmsServerCtxPtr ctx, 
+								 xmlNodePtr node);
+static int	xmlSecXkmsServerCtxUnverifiedKeyBindingNodeWrite(xmlSecXkmsServerCtxPtr ctx,
+							    	 xmlNodePtr node,
+								 xmlSecKeyPtr key);
+static int	xmlSecXkmsServerCtxKeyBindingNodeWrite		(xmlSecXkmsServerCtxPtr ctx,
+							    	 xmlNodePtr node,
+								 xmlSecKeyPtr key);
+static int 	xmlSecXkmsServerCtxValidityIntervalNodeWrite	(xmlSecXkmsServerCtxPtr ctx,
+								 xmlNodePtr node, 
+								 xmlSecKeyPtr key);
+static int	xmlSecXkmsServerCtxKeyBindingStatusNodeWrite	(xmlSecXkmsServerCtxPtr ctx,
+							    	 xmlNodePtr node,
+								 xmlSecKeyPtr key);
+
+
+static const xmlSecQName2IntegerInfo gXmlSecXkmsResultMajorInfo[] = 
+{
+  { xmlSecXkmsNs, xmlSecResultMajorCodeSuccess,
+    xmlSecXkmsResultMajorSuccess },
+  { xmlSecXkmsNs, xmlSecResultMajorCodeVersionMismatch,
+    xmlSecXkmsResultMajorVersionMismatch },
+  { xmlSecXkmsNs, xmlSecResultMajorCodeSender, 
+    xmlSecXkmsResultMajorSender },
+  { xmlSecXkmsNs, xmlSecResultMajorCodeReceiver,
+    xmlSecXkmsResultMajorReceiver },
+  { xmlSecXkmsNs, xmlSecResultMajorCodeRepresent,     
+    xmlSecXkmsResultMajorRepresent },
+  { xmlSecXkmsNs, xmlSecResultMajorCodePending, 
+    xmlSecXkmsResultMajorPending, },
+  { NULL , NULL, 0 }	/* MUST be last in the list */
+};
+
+static const xmlSecQName2IntegerInfo gXmlSecXkmsMinorErrorInfo[] = 
+{
+  { xmlSecXkmsNs, xmlSecResultMinorCodeNoMatch,
+    xmlSecXkmsResultMinorNoMatch },
+  { xmlSecXkmsNs, xmlSecResultMinorCodeTooManyResponses, 
+    xmlSecXkmsResultMinorTooManyResponses },
+  { xmlSecXkmsNs, xmlSecResultMinorCodeIncomplete,
+    xmlSecXkmsResultMinorIncomplete },
+  { xmlSecXkmsNs, xmlSecResultMinorCodeFailure, 
+    xmlSecXkmsResultMinorFailure },
+  { xmlSecXkmsNs, xmlSecResultMinorCodeRefused, 
+    xmlSecXkmsResultMinorRefused },
+  { xmlSecXkmsNs, xmlSecResultMinorCodeNoAuthentication, 
+    xmlSecXkmsResultMinorNoAuthentication },
+  { xmlSecXkmsNs, xmlSecResultMinorCodeMessageNotSupported, 
+    xmlSecXkmsResultMinorMessageNotSupported },
+  { xmlSecXkmsNs, xmlSecResultMinorCodeUnknownResponseId, 
+    xmlSecXkmsResultMinorUnknownResponseId },
+  { xmlSecXkmsNs, xmlSecResultMinorCodeNotSynchronous, 
+    xmlSecXkmsResultMinorSynchronous },
+  { NULL, NULL, 0 }	/* MUST be last in the list */
+};
+
+static const xmlSecQName2IntegerInfo gXmlSecXkmsKeyBindingStatusInfo[] = 
+{
+  { xmlSecXkmsNs, xmlSecKeyBindingStatusValid, 
+    xmlSecXkmsKeyBindingStatusValid },
+  { xmlSecXkmsNs, xmlSecKeyBindingStatusInvalid,
+    xmlSecXkmsKeyBindingStatusInvalid },
+  { xmlSecXkmsNs, xmlSecKeyBindingStatusIndeterminate, 
+    xmlSecXkmsKeyBindingStatusIndeterminate },
+  { NULL, NULL, 0 }	/* MUST be last in the list */
+};
+
+static const xmlSecQName2BitMaskInfo gXmlSecXkmsKeyUsageInfo[] = 
+{
+  { xmlSecXkmsNs, xmlSecKeyUsageEncryption,
+    xmlSecKeyUsageEncrypt | xmlSecKeyUsageDecrypt },
+  { xmlSecXkmsNs, xmlSecKeyUsageSignature,
+    xmlSecKeyUsageSign | xmlSecKeyUsageVerify },
+  { xmlSecXkmsNs, xmlSecKeyUsageExchange,
+    xmlSecKeyUsageKeyExchange},
+  { NULL, NULL, 0 }	/* MUST be last in the list */
+};
+
+static const xmlSecQName2BitMaskInfo gXmlSecXkmsKeyBindingReasonInfo[] = 
+{
+    { xmlSecXkmsNs, xmlSecKeyBindingReasonIssuerTrust,
+      XMLSEC_XKMS_KEY_BINDING_REASON_MASK_ISSUER_TRAST },
+    { xmlSecXkmsNs, xmlSecKeyBindingReasonRevocationStatus,
+      XMLSEC_XKMS_KEY_BINDING_REASON_MASK_REVOCATION_STATUS },
+    { xmlSecXkmsNs, xmlSecKeyBindingReasonValidityInterval,
+      XMLSEC_XKMS_KEY_BINDING_REASON_MASK_VALIDITY_INTERVAL },
+    { xmlSecXkmsNs, xmlSecKeyBindingReasonSignature,
+      XMLSEC_XKMS_KEY_BINDING_REASON_MASK_SIGNATURE },
+    { NULL, NULL, 0 }	/* MUST be last in the list */
+};
+
+static const xmlSecQName2BitMaskInfo gXmlSecXkmsResponseMechanismInfo[] = 
+{
+    { xmlSecXkmsNs, xmlSecResponseMechanismRepresent,
+      XMLSEC_XKMS_RESPONSE_MECHANISM_MASK_REPRESENT },
+    { xmlSecXkmsNs, xmlSecResponseMechanismPending,
+      XMLSEC_XKMS_RESPONSE_MECHANISM_MASK_PENDING },
+    { xmlSecXkmsNs, xmlSecResponseMechanismRequestSignatureValue,
+      XMLSEC_XKMS_RESPONSE_MECHANISM_MASK_REQUEST_SIGNATURE_VALUE },
+    { NULL, NULL, 0 }	/* MUST be last in the list */
+};
+
+static const xmlSecQName2IntegerInfo gXmlSecXkmsFormatInfo[] = 
+{
+  { NULL, xmlSecXkmsFormatStrPlain, 
+    xmlSecXkmsServerFormatPlain },
+#ifndef XMLSEC_NO_SOAP
+  { NULL, xmlSecXkmsFormatStrSoap11,
+    xmlSecXkmsServerFormatSoap11 },
+  { NULL, xmlSecXkmsFormatStrSoap12, 
+    xmlSecXkmsServerFormatSoap12 },
+#endif /* XMLSEC_NO_SOAP */
+  { NULL, NULL, 0 }	/* MUST be last in the list */
+};
+
+/**
+ * xmlSecXkmsServerFormatFromString:
+ * @str         the string.
+ *  
+ * Gets xmlSecXkmsServerFormat from string @str.
+ * 
+ * Returns corresponding format or xmlSecXkmsServerFormatUnknown
+ * if format could not be recognized.
+ */
+EXPORT_C 
+xmlSecXkmsServerFormat 
+xmlSecXkmsServerFormatFromString(const xmlChar* str) {
+    int res;
+    int ret;
+
+    xmlSecAssert2(str != NULL, xmlSecXkmsServerFormatUnknown);
+    
+    ret = xmlSecQName2IntegerGetInteger(gXmlSecXkmsFormatInfo, NULL, str, &res);
+    if(ret < 0) {
+	xmlSecError(XMLSEC_ERRORS_HERE,
+		    NULL,
+		    "xmlSecQName2IntegerGetInteger",
+		    XMLSEC_ERRORS_R_XMLSEC_FAILED,
+		    XMLSEC_ERRORS_NO_MESSAGE);
+	return(xmlSecXkmsServerFormatUnknown);   
+    }
+
+    return((xmlSecXkmsServerFormat)res);
+}
+
+/**
+ * xmlSecXkmsServerFormatToString:
+ * @format:     the format.
+ *
+ * Gets string from @format.
+ *
+ * Returns string corresponding to @format or NULL if an error occurs.
+ */
+EXPORT_C
+const xmlChar* 
+xmlSecXkmsServerFormatToString (xmlSecXkmsServerFormat format) {
+    xmlSecQName2IntegerInfoConstPtr info;
+    
+    xmlSecAssert2(format != xmlSecXkmsServerFormatUnknown, NULL);
+
+    info = xmlSecQName2IntegerGetInfo(gXmlSecXkmsFormatInfo, format);
+    if(info == NULL) {
+	xmlSecError(XMLSEC_ERRORS_HERE,
+		    NULL,
+		    "xmlSecQName2IntegerGetInfo",
+		    XMLSEC_ERRORS_R_XMLSEC_FAILED,
+		    XMLSEC_ERRORS_NO_MESSAGE);
+        return(NULL);
+    }
+    return(info->qnameLocalPart);
+}
+
+/**
+ * xmlSecXkmsServerCtxCreate:
+ * @keysMngr: 	the pointer to keys manager.
+ *
+ * Creates XKMS request server side processing context.
+ * The caller is responsible for destroying returend object by calling 
+ * #xmlSecXkmsServerCtxDestroy function.
+ *
+ * Returns pointer to newly allocated context object or NULL if an error
+ * occurs.
+ */
+EXPORT_C
+xmlSecXkmsServerCtxPtr	
+xmlSecXkmsServerCtxCreate(xmlSecKeysMngrPtr keysMngr) {
+    xmlSecXkmsServerCtxPtr ctx;
+    int ret;
+    
+    ctx = (xmlSecXkmsServerCtxPtr) xmlMalloc(sizeof(xmlSecXkmsServerCtx));
+    if(ctx == NULL) {
+	xmlSecError(XMLSEC_ERRORS_HERE,
+		    NULL,
+		    NULL,
+		    XMLSEC_ERRORS_R_MALLOC_FAILED,
+		    "sizeof(xmlSecXkmsServerCtx)=%d", 
+		    sizeof(xmlSecXkmsServerCtx));
+	return(NULL);
+    }
+    
+    ret = xmlSecXkmsServerCtxInitialize(ctx, keysMngr);
+    if(ret < 0) {
+	xmlSecError(XMLSEC_ERRORS_HERE,
+		    NULL,
+		    "xmlSecXkmsServerCtxInitialize",
+		    XMLSEC_ERRORS_R_XMLSEC_FAILED,
+		    XMLSEC_ERRORS_NO_MESSAGE);
+	xmlSecXkmsServerCtxDestroy(ctx);
+	return(NULL);   
+    }
+    return(ctx);    
+}
+
+/**
+ * xmlSecXkmsServerCtxDestroy:
+ * @ctx:	the pointer to XKMS processing context.
+ *
+ * Destroy context object created with #xmlSecXkmsServerCtxCreate function.
+ */
+EXPORT_C
+void  
+xmlSecXkmsServerCtxDestroy(xmlSecXkmsServerCtxPtr ctx) {
+    xmlSecAssert(ctx != NULL);
+    
+    xmlSecXkmsServerCtxFinalize(ctx);
+    xmlFree(ctx);
+}
+
+/**
+ * xmlSecXkmsServerCtxInitialize:
+ * @ctx:	the pointer to XKMS processing context.
+ * @keysMngr: 	the pointer to keys manager.
+ *
+ * Initializes XKMS element processing context.
+ * The caller is responsible for cleaing up returend object by calling 
+ * #xmlSecXkmsServerCtxFinalize function.
+ *
+ * Returns 0 on success or a negative value if an error occurs.
+ */
+EXPORT_C
+int 
+xmlSecXkmsServerCtxInitialize(xmlSecXkmsServerCtxPtr ctx, xmlSecKeysMngrPtr keysMngr) {
+    int ret;
+    
+    xmlSecAssert2(ctx != NULL, -1);
+    
+    memset(ctx, 0, sizeof(xmlSecXkmsServerCtx));
+
+    ctx->resultMajor 	= xmlSecXkmsResultMajorSuccess;
+    ctx->resultMinor 	= xmlSecXkmsResultMinorNone;
+    ctx->responseLimit  = XMLSEC_XKMS_NO_RESPONSE_LIMIT;
+    ctx->idLen		= XMLSEC_XKMS_ID_ATTRIBUTE_LEN;
+
+    /* initialize key info */
+    ret = xmlSecKeyInfoCtxInitialize(&(ctx->keyInfoReadCtx), keysMngr);
+    if(ret < 0) {
+	xmlSecError(XMLSEC_ERRORS_HERE,
+		    NULL,
+		    "xmlSecKeyInfoCtxInitialize",
+		    XMLSEC_ERRORS_R_XMLSEC_FAILED,
+		    XMLSEC_ERRORS_NO_MESSAGE);
+	return(-1);   
+    }
+    ctx->keyInfoReadCtx.mode = xmlSecKeyInfoModeRead;
+    
+    ret = xmlSecKeyInfoCtxInitialize(&(ctx->keyInfoWriteCtx), keysMngr);
+    if(ret < 0) {
+	xmlSecError(XMLSEC_ERRORS_HERE,
+		    NULL,
+		    "xmlSecKeyInfoCtxInitialize",
+		    XMLSEC_ERRORS_R_XMLSEC_FAILED,
+		    XMLSEC_ERRORS_NO_MESSAGE);
+	return(-1);   
+    }
+    ctx->keyInfoWriteCtx.mode = xmlSecKeyInfoModeWrite;
+
+    /* enabled RespondWith */
+    ret = xmlSecPtrListInitialize(&(ctx->enabledRespondWithIds), xmlSecXkmsRespondWithIdListId);
+    if(ret < 0) { 
+	xmlSecError(XMLSEC_ERRORS_HERE,
+		    NULL,
+		    "xmlSecPtrListInitialize",
+		    XMLSEC_ERRORS_R_XMLSEC_FAILED,
+		    XMLSEC_ERRORS_NO_MESSAGE);
+	return(-1);
+    }
+
+    /* enabled ServerRequest */
+    ret = xmlSecPtrListInitialize(&(ctx->enabledServerRequestIds), xmlSecXkmsServerRequestIdListId);
+    if(ret < 0) { 
+	xmlSecError(XMLSEC_ERRORS_HERE,
+		    NULL,
+		    "xmlSecPtrListInitialize",
+		    XMLSEC_ERRORS_R_XMLSEC_FAILED,
+		    XMLSEC_ERRORS_NO_MESSAGE);
+	return(-1);
+    }
+
+
+
+    /* initialize keys list */
+    ret = xmlSecPtrListInitialize(&(ctx->keys), xmlSecKeyPtrListId);
+    if(ret < 0) {
+	xmlSecError(XMLSEC_ERRORS_HERE,
+		    NULL,
+		    "xmlSecPtrListInitialize",
+		    XMLSEC_ERRORS_R_XMLSEC_FAILED,
+		    XMLSEC_ERRORS_NO_MESSAGE);
+	return(-1);   
+    }
+
+    /* initialize RespondWith list */
+    ret = xmlSecPtrListInitialize(&(ctx->respWithList), xmlSecXkmsRespondWithIdListId);
+    if(ret < 0) {
+	xmlSecError(XMLSEC_ERRORS_HERE,
+		    NULL,
+		    "xmlSecPtrListInitialize",
+		    XMLSEC_ERRORS_R_XMLSEC_FAILED,
+		    XMLSEC_ERRORS_NO_MESSAGE);
+	return(-1);   
+    }
+
+    return(0);
+}
+
+/**
+ * xmlSecXkmsServerCtxFinalize:
+ * @ctx:	the pointer to XKMS processing context.
+ *
+ * Cleans up @ctx object.
+ */
+EXPORT_C
+void 
+xmlSecXkmsServerCtxFinalize(xmlSecXkmsServerCtxPtr ctx) {
+    xmlSecAssert(ctx != NULL);
+
+    xmlSecXkmsServerCtxReset(ctx);
+    
+    if(ctx->expectedService != NULL) {
+	xmlFree(ctx->expectedService);
+    }
+    if(ctx->idPrefix != NULL) {
+	xmlFree(ctx->idPrefix);
+    }
+
+    xmlSecKeyInfoCtxFinalize(&(ctx->keyInfoReadCtx));
+    xmlSecKeyInfoCtxFinalize(&(ctx->keyInfoWriteCtx));
+    xmlSecPtrListFinalize(&(ctx->enabledRespondWithIds));
+    xmlSecPtrListFinalize(&(ctx->enabledServerRequestIds));
+    xmlSecPtrListFinalize(&(ctx->keys));
+    xmlSecPtrListFinalize(&(ctx->respWithList));
+    memset(ctx, 0, sizeof(xmlSecXkmsServerCtx));
+}
+
+/**
+ * xmlSecXkmsServerCtxReset:
+ * @ctx:	the pointer to XKMS processing context.
+ *
+ * Resets @ctx object, user settings are not touched.
+ */
+EXPORT_C
+void 
+xmlSecXkmsServerCtxReset(xmlSecXkmsServerCtxPtr ctx) {
+    xmlSecAssert(ctx != NULL);
+    
+    ctx->resultMajor = xmlSecXkmsResultMajorSuccess;
+    ctx->resultMinor = xmlSecXkmsResultMinorNone;
+    xmlSecKeyInfoCtxReset(&(ctx->keyInfoReadCtx));
+    xmlSecKeyInfoCtxReset(&(ctx->keyInfoWriteCtx));
+    xmlSecPtrListEmpty(&(ctx->keys));
+    xmlSecPtrListEmpty(&(ctx->respWithList));
+
+    ctx->requestNode            = NULL;    
+    ctx->opaqueClientDataNode   = NULL;    
+    ctx->firtsMsgExtNode 	= NULL;
+    ctx->keyInfoNode		= NULL;
+    ctx->requestId		= xmlSecXkmsServerRequestIdUnknown;
+    
+    if(ctx->id != NULL) {
+	xmlFree(ctx->id); ctx->id = NULL;
+    }
+    if(ctx->service != NULL) {
+	xmlFree(ctx->service); ctx->service = NULL;
+    }
+    if(ctx->nonce != NULL) {
+	xmlFree(ctx->nonce); ctx->nonce = NULL;
+    }
+    if(ctx->originalRequestId != NULL) {
+	xmlFree(ctx->originalRequestId); ctx->originalRequestId = NULL;
+    }
+    if(ctx->pendingNotificationMechanism != NULL) {
+	xmlFree(ctx->pendingNotificationMechanism); 
+	ctx->pendingNotificationMechanism = NULL;
+    }
+    if(ctx->pendingNotificationIdentifier != NULL) {
+	xmlFree(ctx->pendingNotificationIdentifier); 
+	ctx->pendingNotificationIdentifier = NULL;
+    }
+    if(ctx->compoundRequestContexts != NULL) {
+        xmlSecPtrListDestroy(ctx->compoundRequestContexts);
+        ctx->compoundRequestContexts = NULL;
+    }
+    
+    ctx->responseLimit 		= XMLSEC_XKMS_NO_RESPONSE_LIMIT;
+    ctx->responseMechanismMask  = 0;
+}
+
+/**
+ * xmlSecXkmsServerCtxCopyUserPref:
+ * @dst:	the pointer to destination context.
+ * @src:	the pointer to source context.
+ * 
+ * Copies user preference from @src context to @dst.
+ *
+ * Returns 0 on success or a negative value if an error occurs.
+ */
+EXPORT_C
+int 
+xmlSecXkmsServerCtxCopyUserPref(xmlSecXkmsServerCtxPtr dst, xmlSecXkmsServerCtxPtr src) {
+    int ret;
+    
+    xmlSecAssert2(dst != NULL, -1);
+    xmlSecAssert2(src != NULL, -1);
+
+    dst->userData 	= src->userData;
+    dst->flags		= src->flags;
+    dst->flags2		= src->flags2;
+
+    ret = xmlSecKeyInfoCtxCopyUserPref(&(dst->keyInfoReadCtx), &(src->keyInfoReadCtx));
+    if(ret < 0) {
+    	xmlSecError(XMLSEC_ERRORS_HERE,
+		    NULL,
+		    "xmlSecKeyInfoCtxCopyUserPref",
+		    XMLSEC_ERRORS_R_XMLSEC_FAILED,
+		    XMLSEC_ERRORS_NO_MESSAGE);
+	return(-1);
+    }
+
+    ret = xmlSecKeyInfoCtxCopyUserPref(&(dst->keyInfoWriteCtx), &(src->keyInfoWriteCtx));
+    if(ret < 0) {
+    	xmlSecError(XMLSEC_ERRORS_HERE,
+		    NULL,
+		    "xmlSecKeyInfoCtxCopyUserPref",
+		    XMLSEC_ERRORS_R_XMLSEC_FAILED,
+		    XMLSEC_ERRORS_NO_MESSAGE);
+	return(-1);
+    }
+    
+    if(src->expectedService != NULL) {
+	dst->expectedService = xmlStrdup(src->expectedService);
+	if(dst->expectedService == NULL) {
+	    xmlSecError(XMLSEC_ERRORS_HERE,
+			NULL,
+			"xmlStrdup",
+		        XMLSEC_ERRORS_R_MALLOC_FAILED,
+			XMLSEC_ERRORS_NO_MESSAGE);
+	    return(-1);
+	}
+    }
+
+    if(src->idPrefix != NULL) {
+	dst->idPrefix = xmlStrdup(src->idPrefix);
+	if(dst->idPrefix == NULL) {
+	    xmlSecError(XMLSEC_ERRORS_HERE,
+			NULL,
+			"xmlStrdup",
+		        XMLSEC_ERRORS_R_MALLOC_FAILED,
+			XMLSEC_ERRORS_NO_MESSAGE);
+	    return(-1);
+	}
+    }
+    src->idLen = dst->idLen;
+
+
+    ret = xmlSecPtrListCopy(&(dst->enabledRespondWithIds), &(src->enabledRespondWithIds));
+    if(ret < 0) { 
+	xmlSecError(XMLSEC_ERRORS_HERE,
+		    NULL,
+		    "xmlSecPtrListCopy",
+		    XMLSEC_ERRORS_R_XMLSEC_FAILED,
+		    XMLSEC_ERRORS_NO_MESSAGE);
+	return(-1);
+    }
+
+    ret = xmlSecPtrListCopy(&(dst->enabledServerRequestIds), &(src->enabledServerRequestIds));
+    if(ret < 0) { 
+	xmlSecError(XMLSEC_ERRORS_HERE,
+		    NULL,
+		    "xmlSecPtrListCopy",
+		    XMLSEC_ERRORS_R_XMLSEC_FAILED,
+		    XMLSEC_ERRORS_NO_MESSAGE);
+	return(-1);
+    }
+
+    return(0);
+} 
+
+/** 
+ * xmlSecXkmsServerCtxProcess: 
+ * @ctx:	the pointer to XKMS processing context.
+ * @node:	the pointer to request node.
+ * @format:     the request/response format.
+ * @doc:	the pointer to response parent XML document (might be NULL).
+ * 
+ * Reads XKMS request from @node and creates response to a newly created node. 
+ * Caller is responsible for adding the returned node to the XML document.
+ *
+ * Returns pointer to newly created XKMS response node or NULL
+ * if an error occurs.
+ */
+EXPORT_C
+xmlNodePtr 
+xmlSecXkmsServerCtxProcess(xmlSecXkmsServerCtxPtr ctx, xmlNodePtr node, 
+                              xmlSecXkmsServerFormat format, xmlDocPtr doc) {
+    int ret;
+
+    xmlSecAssert2(ctx != NULL, NULL);
+    xmlSecAssert2(ctx->requestId == NULL, NULL);
+    xmlSecAssert2(ctx->requestNode == NULL, NULL);
+    xmlSecAssert2(node != NULL, NULL);
+
+    ctx->requestNode = xmlSecXkmsServerCtxRequestUnwrap(ctx, node, format);
+    if(ctx->requestNode == NULL) {
+    	xmlSecError(XMLSEC_ERRORS_HERE,
+		    NULL,
+		    "xmlSecXkmsServerCtxRequestUnwrap",
+		    XMLSEC_ERRORS_R_XMLSEC_FAILED,
+		    "node=%s",
+		    xmlSecErrorsSafeString(node->name));
+	xmlSecXkmsServerCtxSetResult(ctx, xmlSecXkmsResultMajorReceiver, xmlSecXkmsResultMinorFailure);
+	goto done;
+    }    
+        
+    ret = xmlSecXkmsServerCtxRequestRead(ctx, ctx->requestNode);
+    if(ret < 0) {
+    	xmlSecError(XMLSEC_ERRORS_HERE,
+		    NULL,
+		    "xmlSecXkmsServerRequestIdListFindByNode",
+		    XMLSEC_ERRORS_R_XMLSEC_FAILED,
+		    "ctx->requestNode=%s",
+		    xmlSecErrorsSafeString(ctx->requestNode->name));
+	xmlSecXkmsServerCtxSetResult(ctx, xmlSecXkmsResultMajorReceiver, xmlSecXkmsResultMinorFailure);
+	goto done;
+    }    
+
+    ret = xmlSecXkmsServerRequestExecute(ctx->requestId, ctx);
+    if(ret < 0) {
+    	xmlSecError(XMLSEC_ERRORS_HERE,
+		    NULL,
+		    "xmlSecXkmsServerRequestExecute",
+		    XMLSEC_ERRORS_R_XMLSEC_FAILED,
+		    "ctx->requestNode=%s",
+		    xmlSecErrorsSafeString(ctx->requestNode->name));
+	xmlSecXkmsServerCtxSetResult(ctx, xmlSecXkmsResultMajorReceiver, xmlSecXkmsResultMinorFailure);
+	goto done;
+    }
+
+done:
+    /* always try to write response back */    
+    if(ctx->requestId != NULL) {
+        xmlNodePtr respNode;
+        xmlNodePtr wrappedRespNode;
+        
+        respNode = xmlSecXkmsServerCtxResponseWrite(ctx, doc);
+        if(respNode == NULL) {
+    	    xmlSecError(XMLSEC_ERRORS_HERE,
+		        NULL,
+		        "xmlSecXkmsServerCtxResponseWrite",
+		        XMLSEC_ERRORS_R_XMLSEC_FAILED,
+		        "ctx->requestNode=%s",
+		        xmlSecErrorsSafeString(ctx->requestNode->name));
+	    xmlSecXkmsServerCtxSetResult(ctx, xmlSecXkmsResultMajorReceiver, xmlSecXkmsResultMinorFailure);
+            goto error;    
+        }
+    
+
+        wrappedRespNode = xmlSecXkmsServerCtxResponseWrap(ctx, respNode, format, doc);
+        if(wrappedRespNode == NULL) {
+    	    xmlSecError(XMLSEC_ERRORS_HERE,
+		        NULL,
+		        "xmlSecXkmsServerCtxResponseWrite",
+		        XMLSEC_ERRORS_R_XMLSEC_FAILED,
+		        "ctx->requestNode=%s",
+		        xmlSecErrorsSafeString(ctx->requestNode->name));
+	    xmlSecXkmsServerCtxSetResult(ctx, xmlSecXkmsResultMajorReceiver, xmlSecXkmsResultMinorFailure);
+            xmlFreeNode(respNode);
+            goto error;    
+        }
+
+        return(wrappedRespNode);
+    }
+    
+error:
+    /* last attempt: create fatatl error response */
+    return(xmlSecXkmsServerCtxFatalErrorResponseCreate(ctx, format, doc));
+}
+
+/** 
+ * xmlSecXkmsServerCtxRequestRead: 
+ * @ctx:	the pointer to XKMS processing context.
+ * @node:	the pointer to request node.
+ *
+ * Reads XKMS request from @node and stores data in @ctx.
+ *
+ * Returns 0 on success or a negative value if an error occurs.
+ */
+EXPORT_C
+int 
+xmlSecXkmsServerCtxRequestRead(xmlSecXkmsServerCtxPtr ctx, xmlNodePtr node) {
+    int ret;
+    
+    xmlSecAssert2(ctx != NULL, -1);
+    xmlSecAssert2(ctx->requestId == NULL, -1);
+    xmlSecAssert2(node != NULL, -1);
+
+    /* find out what the request is */
+    if(xmlSecPtrListGetSize(&(ctx->enabledServerRequestIds)) > 0) {
+	ctx->requestId = xmlSecXkmsServerRequestIdListFindByNode(&(ctx->enabledServerRequestIds), node);
+    } else {
+	ctx->requestId = xmlSecXkmsServerRequestIdListFindByNode(xmlSecXkmsServerRequestIdsGet(), node);
+    }
+    if(ctx->requestId == xmlSecXkmsServerRequestIdUnknown) {
+    	xmlSecError(XMLSEC_ERRORS_HERE,
+		    NULL,
+		    "xmlSecXkmsServerRequestIdListFindByNode",
+		    XMLSEC_ERRORS_R_XMLSEC_FAILED,
+		    "node=%s",
+		    xmlSecErrorsSafeString(node->name));
+	xmlSecXkmsServerCtxSetResult(ctx, xmlSecXkmsResultMajorSender, xmlSecXkmsResultMinorMessageNotSupported);
+	return(-1);
+    }
+
+    xmlSecAddIDs(node->doc, node, xmlSecXkmsServerIds);
+    ret = xmlSecXkmsServerRequestNodeRead(ctx->requestId, ctx, node);
+    if(ret < 0) {
+    	xmlSecError(XMLSEC_ERRORS_HERE,
+		    NULL,
+		    "xmlSecXkmsServerRequestNodeRead",
+		    XMLSEC_ERRORS_R_XMLSEC_FAILED,
+		    "request=%s",
+		    xmlSecErrorsSafeString(xmlSecXkmsServerRequestKlassGetName(ctx->requestId)));
+	xmlSecXkmsServerCtxSetResult(ctx, xmlSecXkmsResultMajorSender, xmlSecXkmsResultMinorFailure);
+	return(-1);
+    }
+        
+    return(0);
+}
+
+/** 
+ * xmlSecXkmsServerCtxResponseWrite: 
+ * @ctx:	the pointer to XKMS processing context.
+ * @doc:	the pointer to response parent XML document (might be NULL).
+ *
+ * Writes XKMS response from context to a newly created node. Caller is 
+ * responsible for adding the returned node to the XML document.
+ *
+ * Returns pointer to newly created XKMS response node or NULL
+ * if an error occurs.
+ */
+EXPORT_C
+xmlNodePtr
+xmlSecXkmsServerCtxResponseWrite(xmlSecXkmsServerCtxPtr ctx, xmlDocPtr doc) {
+    xmlNodePtr respNode;
+    
+    xmlSecAssert2(ctx != NULL, NULL);
+    xmlSecAssert2(ctx->requestId != NULL, NULL);
+
+    /* now write results */
+    respNode = xmlSecXkmsServerRequestNodeWrite(ctx->requestId, ctx, doc, NULL);
+    if(respNode == NULL) {
+    	xmlSecError(XMLSEC_ERRORS_HERE,
+		    NULL,
+		    "xmlSecXkmsServerRequestNodeWrite",
+		    XMLSEC_ERRORS_R_XMLSEC_FAILED,
+		    "request=%s",
+		    xmlSecErrorsSafeString(xmlSecXkmsServerRequestKlassGetName(ctx->requestId)));
+	xmlSecXkmsServerCtxSetResult(ctx, xmlSecXkmsResultMajorReceiver, xmlSecXkmsResultMinorFailure);
+        return(NULL);
+    }
+    
+    return(respNode);
+}
+
+/**
+ * xmlSecXkmsServerCtxRequestUnwrap:
+ * @ctx:	the pointer to XKMS processing context.
+ * @node:	the pointer to request node.
+ * @format:     the request/response format.
+ * 
+ * Removes SOAP or other envelope from XKMS request.
+ *
+ * Returns pointer to "real" XKMS request node or NULL if an error occurs. 
+ */
+EXPORT_C
+xmlNodePtr 
+xmlSecXkmsServerCtxRequestUnwrap(xmlSecXkmsServerCtxPtr ctx, xmlNodePtr node,  xmlSecXkmsServerFormat format) {
+    xmlNodePtr result = NULL;
+        
+    xmlSecAssert2(ctx != NULL, NULL);
+    xmlSecAssert2(node != NULL, NULL);
+    
+    switch(format) {
+    case xmlSecXkmsServerFormatPlain:
+        result = node;
+        break;
+#ifndef XMLSEC_NO_SOAP
+    case xmlSecXkmsServerFormatSoap11:
+        /* verify that it is actually soap Envelope node */
+        if(xmlSecSoap11CheckEnvelope(node) != 1) {
+            xmlSecError(XMLSEC_ERRORS_HERE,
+		        NULL,
+		        "xmlSecSoap11CheckEnvelope",
+		        XMLSEC_ERRORS_R_XMLSEC_FAILED,
+		        XMLSEC_ERRORS_NO_MESSAGE);
+	    xmlSecXkmsServerCtxSetResult(ctx, xmlSecXkmsResultMajorSender, xmlSecXkmsResultMinorFailure);
+	    return(NULL);
+        }   
+        
+        /* check that Body has exactly one entry */
+        if(xmlSecSoap11GetBodyEntriesNumber(node) != 1) {
+            xmlSecError(XMLSEC_ERRORS_HERE,
+		        NULL,
+		        "xmlSecSoap11GetBodyEntriesNumber",
+		        XMLSEC_ERRORS_R_INVALID_DATA,
+		        XMLSEC_ERRORS_NO_MESSAGE);
+	    xmlSecXkmsServerCtxSetResult(ctx, xmlSecXkmsResultMajorSender, xmlSecXkmsResultMinorFailure);
+	    return(NULL);
+        }
+        
+        /* this one enntry is our xkms request */
+        result = xmlSecSoap11GetBodyEntry(node, 0);
+        if(result == NULL) {
+            xmlSecError(XMLSEC_ERRORS_HERE,
+		        NULL,
+		        "xmlSecSoap11GetBodyEntry",
+		        XMLSEC_ERRORS_R_INVALID_DATA,
+		        XMLSEC_ERRORS_NO_MESSAGE);
+	    xmlSecXkmsServerCtxSetResult(ctx, xmlSecXkmsResultMajorSender, xmlSecXkmsResultMinorFailure);
+	    return(NULL);
+        }
+        
+        break;
+    case xmlSecXkmsServerFormatSoap12:
+        /* verify that it is actually soap Envelope node */
+        if(xmlSecSoap12CheckEnvelope(node) != 1) {
+            xmlSecError(XMLSEC_ERRORS_HERE,
+		        NULL,
+		        "xmlSecSoap12CheckEnvelope",
+		        XMLSEC_ERRORS_R_XMLSEC_FAILED,
+		        XMLSEC_ERRORS_NO_MESSAGE);
+	    xmlSecXkmsServerCtxSetResult(ctx, xmlSecXkmsResultMajorSender, xmlSecXkmsResultMinorFailure);
+	    return(NULL);
+        }   
+        
+        /* check that Body has exactly one entry */
+        if(xmlSecSoap12GetBodyEntriesNumber(node) != 1) {
+            xmlSecError(XMLSEC_ERRORS_HERE,
+		        NULL,
+		        "xmlSecSoap12GetBodyEntriesNumber",
+		        XMLSEC_ERRORS_R_INVALID_DATA,
+		        XMLSEC_ERRORS_NO_MESSAGE);
+	    xmlSecXkmsServerCtxSetResult(ctx, xmlSecXkmsResultMajorSender, xmlSecXkmsResultMinorFailure);
+	    return(NULL);
+        }
+        
+        /* this one enntry is our xkms request */
+        result = xmlSecSoap12GetBodyEntry(node, 0);
+        if(result == NULL) {
+            xmlSecError(XMLSEC_ERRORS_HERE,
+		        NULL,
+		        "xmlSecSoap12GetBodyEntry",
+		        XMLSEC_ERRORS_R_INVALID_DATA,
+		        XMLSEC_ERRORS_NO_MESSAGE);
+	    xmlSecXkmsServerCtxSetResult(ctx, xmlSecXkmsResultMajorSender, xmlSecXkmsResultMinorFailure);
+	    return(NULL);
+        }
+        
+        break;
+#endif /* XMLSEC_NO_SOAP */
+    default:
+    	xmlSecError(XMLSEC_ERRORS_HERE,
+		    NULL,
+		    NULL,
+		    XMLSEC_ERRORS_R_NOT_IMPLEMENTED,
+		    "format=%d",
+                    format);
+	xmlSecXkmsServerCtxSetResult(ctx, xmlSecXkmsResultMajorSender, xmlSecXkmsResultMinorFailure);
+	return(NULL);
+    }
+    
+    return(result);
+}
+
+/** 
+ * xmlSecXkmsServerCtxResponseWrap: 
+ * @ctx:	the pointer to XKMS processing context.
+ * @node:	the pointer to response node.
+ * @format:     the request/response format.
+ * @doc:	the pointer to response parent XML document (might be NULL).
+ *
+ * Creates SOAP or other envelope around XKMS response.
+ * Caller is responsible for adding the returned node to the XML document.
+ *
+ * Returns pointer to newly created response envelope node or NULL
+ * if an error occurs.
+ */
+EXPORT_C
+xmlNodePtr 
+xmlSecXkmsServerCtxResponseWrap(xmlSecXkmsServerCtxPtr ctx, xmlNodePtr node, xmlSecXkmsServerFormat format, xmlDocPtr doc) {
+    xmlNodePtr result = NULL;
+    
+    xmlSecAssert2(ctx != NULL, NULL);
+    xmlSecAssert2(node != NULL, NULL);
+    
+    switch(format) {
+    case xmlSecXkmsServerFormatPlain:
+        result = node; /* do nothing */
+        break;
+#ifndef XMLSEC_NO_SOAP
+    case xmlSecXkmsServerFormatSoap11:
+        result = xmlSecSoap11CreateEnvelope(doc);
+        if(result == NULL) {
+            xmlSecError(XMLSEC_ERRORS_HERE,
+		        NULL,
+		        "xmlSecSoap11CreateEnvelope",
+		        XMLSEC_ERRORS_R_INVALID_DATA,
+		        XMLSEC_ERRORS_NO_MESSAGE);
+	    xmlSecXkmsServerCtxSetResult(ctx, xmlSecXkmsResultMajorReceiver, xmlSecXkmsResultMinorFailure);
+	    return(NULL);
+        }
+        
+        if(xmlSecSoap11AddBodyEntry(result, node) == NULL) {
+            xmlSecError(XMLSEC_ERRORS_HERE,
+		        NULL,
+		        "xmlSecSoap11AddBodyEntry",
+		        XMLSEC_ERRORS_R_INVALID_DATA,
+		        XMLSEC_ERRORS_NO_MESSAGE);
+	    xmlSecXkmsServerCtxSetResult(ctx, xmlSecXkmsResultMajorReceiver, xmlSecXkmsResultMinorFailure);
+	    return(NULL);
+        }
+        break;
+    case xmlSecXkmsServerFormatSoap12:
+        result = xmlSecSoap12CreateEnvelope(doc);
+        if(result == NULL) {
+            xmlSecError(XMLSEC_ERRORS_HERE,
+		        NULL,
+		        "xmlSecSoap12CreateEnvelope",
+		        XMLSEC_ERRORS_R_INVALID_DATA,
+		        XMLSEC_ERRORS_NO_MESSAGE);
+	    xmlSecXkmsServerCtxSetResult(ctx, xmlSecXkmsResultMajorReceiver, xmlSecXkmsResultMinorFailure);
+	    return(NULL);
+        }
+        
+        if(xmlSecSoap12AddBodyEntry(result, node) == NULL) {
+            xmlSecError(XMLSEC_ERRORS_HERE,
+		        NULL,
+		        "xmlSecSoap12AddBodyEntry",
+		        XMLSEC_ERRORS_R_INVALID_DATA,
+		        XMLSEC_ERRORS_NO_MESSAGE);
+	    xmlSecXkmsServerCtxSetResult(ctx, xmlSecXkmsResultMajorReceiver, xmlSecXkmsResultMinorFailure);
+	    return(NULL);
+        }
+        break;
+#endif /* XMLSEC_NO_SOAP */
+    default:
+    	xmlSecError(XMLSEC_ERRORS_HERE,
+		    NULL,
+		    NULL,
+		    XMLSEC_ERRORS_R_NOT_IMPLEMENTED,
+		    "format=%d",
+                    format);
+	xmlSecXkmsServerCtxSetResult(ctx, xmlSecXkmsResultMajorSender, xmlSecXkmsResultMinorFailure);
+	return(NULL);
+    }
+    
+    return(result);
+}
+
+/** 
+ * xmlSecXkmsServerCtxFatalErrorResponseCreate: 
+ * @ctx:	the pointer to XKMS processing context.
+ * @format:     the request/response format.
+ * @doc:	the pointer to response parent XML document (might be NULL).
+ *
+ * Creates a "fatal error" SOAP or other envelope respons. Caller is 
+ * responsible for adding the returned node to the XML document.
+ *
+ * Returns pointer to newly created fatal error response (it might be NULL).
+ */
+EXPORT_C
+xmlNodePtr 
+xmlSecXkmsServerCtxFatalErrorResponseCreate(xmlSecXkmsServerCtxPtr ctx, xmlSecXkmsServerFormat format, xmlDocPtr doc) {
+    xmlNodePtr result = NULL;
+    int ret;
+    
+    xmlSecAssert2(ctx != NULL, NULL);
+
+    /* make sure that we have an error */
+    if(ctx->resultMajor == xmlSecXkmsResultMajorSuccess) {
+	xmlSecXkmsServerCtxSetResult(ctx, xmlSecXkmsResultMajorReceiver, xmlSecXkmsResultMinorFailure);
+    }
+    
+    switch(format) {
+    case xmlSecXkmsServerFormatPlain:
+        /* try to create fatal error response with XKMS Status request */
+        result = xmlSecXkmsServerRequestNodeWrite(xmlSecXkmsServerRequestResultId, ctx, doc, NULL);
+        if(result == NULL) {
+            xmlSecError(XMLSEC_ERRORS_HERE,
+		        NULL,
+		        "xmlSecXkmsServerRequestNodeWrite",
+		        XMLSEC_ERRORS_R_XMLSEC_FAILED,
+		        XMLSEC_ERRORS_NO_MESSAGE);
+	    return(NULL);
+        }
+        break;
+#ifndef XMLSEC_NO_SOAP
+    case xmlSecXkmsServerFormatSoap11:
+        result = xmlSecSoap11CreateEnvelope(doc);
+        if(result == NULL) {
+            xmlSecError(XMLSEC_ERRORS_HERE,
+		        NULL,
+		        "xmlSecSoap11CreateEnvelope",
+		        XMLSEC_ERRORS_R_INVALID_DATA,
+		        XMLSEC_ERRORS_NO_MESSAGE);
+	    xmlSecXkmsServerCtxSetResult(ctx, xmlSecXkmsResultMajorReceiver, xmlSecXkmsResultMinorFailure);
+	    return(NULL);
+        }
+        
+        ret = xmlSecXkmsServerCtxWriteSoap11FatalError(ctx, result);
+        if(ret < 0) {
+            xmlSecError(XMLSEC_ERRORS_HERE,
+		        NULL,
+		        "xmlSecXkmsServerCtxWriteSoap11FatalError",
+		        XMLSEC_ERRORS_R_INVALID_DATA,
+		        XMLSEC_ERRORS_NO_MESSAGE);
+	    xmlSecXkmsServerCtxSetResult(ctx, xmlSecXkmsResultMajorReceiver, xmlSecXkmsResultMinorFailure);
+            xmlFreeNode(result);
+	    return(NULL);
+        }
+                
+        break;
+    case xmlSecXkmsServerFormatSoap12:
+        result = xmlSecSoap12CreateEnvelope(doc);
+        if(result == NULL) {
+            xmlSecError(XMLSEC_ERRORS_HERE,
+		        NULL,
+		        "xmlSecSoap12CreateEnvelope",
+		        XMLSEC_ERRORS_R_INVALID_DATA,
+		        XMLSEC_ERRORS_NO_MESSAGE);
+	    xmlSecXkmsServerCtxSetResult(ctx, xmlSecXkmsResultMajorReceiver, xmlSecXkmsResultMinorFailure);
+	    return(NULL);
+        }
+        
+        ret = xmlSecXkmsServerCtxWriteSoap12FatalError(ctx, result);
+        if(ret < 0) {
+            xmlSecError(XMLSEC_ERRORS_HERE,
+		        NULL,
+		        "xmlSecXkmsServerCtxWriteSoap12FatalError",
+		        XMLSEC_ERRORS_R_INVALID_DATA,
+		        XMLSEC_ERRORS_NO_MESSAGE);
+	    xmlSecXkmsServerCtxSetResult(ctx, xmlSecXkmsResultMajorReceiver, xmlSecXkmsResultMinorFailure);
+            xmlFreeNode(result);
+	    return(NULL);
+        }
+                
+        break;
+#endif /* XMLSEC_NO_SOAP */
+    default:
+    	xmlSecError(XMLSEC_ERRORS_HERE,
+		    NULL,
+		    NULL,
+		    XMLSEC_ERRORS_R_NOT_IMPLEMENTED,
+		    "format=%d",
+                    format);
+	xmlSecXkmsServerCtxSetResult(ctx, xmlSecXkmsResultMajorSender, xmlSecXkmsResultMinorFailure);
+	return(NULL);
+    }
+    
+    return(result);
+}
+
+#ifndef XMLSEC_NO_SOAP
+static int 
+xmlSecXkmsServerCtxWriteSoap11FatalError(xmlSecXkmsServerCtxPtr ctx, xmlNodePtr envNode) {
+    const xmlChar* faultCodeHref = NULL;
+    const xmlChar* faultCodeLocalPart = NULL;
+    xmlChar* faultString = NULL;
+    int len;
+    
+    xmlSecAssert2(ctx != NULL, -1);
+    xmlSecAssert2(envNode != NULL, -1);
+
+    if((ctx->resultMajor == xmlSecXkmsResultMajorVersionMismatch) ||
+       (ctx->requestNode == NULL)) {
+        /* we were not able to parse the envelope or its general version mismatch error */
+        faultCodeHref = xmlSecSoap11Ns;
+        faultCodeLocalPart = xmlSecSoapFaultCodeVersionMismatch;
+        faultString = xmlStrdup(xmlSecXkmsSoapFaultReasonUnsupportedVersion);
+        if(faultString == NULL) {
+            xmlSecError(XMLSEC_ERRORS_HERE,
+		        NULL,
+		        "xmlStrdup",
+		        XMLSEC_ERRORS_R_XML_FAILED,
+		        XMLSEC_ERRORS_NO_MESSAGE);
+	    xmlSecXkmsServerCtxSetResult(ctx, xmlSecXkmsResultMajorReceiver, xmlSecXkmsResultMinorFailure);
+            return(-1);
+        }
+    } else if((ctx->resultMajor == xmlSecXkmsResultMajorSender) && 
+              (ctx->requestId == NULL)) {
+        /* we understood the request but were not able to parse input message */
+        faultCodeHref = xmlSecSoap11Ns;
+        faultCodeLocalPart = xmlSecSoapFaultCodeClient;
+
+        len = xmlStrlen(BAD_CAST xmlSecErrorsSafeString(ctx->requestNode->name)) +
+              xmlStrlen(xmlSecXkmsSoapFaultReasonMessageInvalid) + 1;
+        faultString = xmlMalloc(len + 1);
+        if(faultString == NULL) {
+            xmlSecError(XMLSEC_ERRORS_HERE,
+		        NULL,
+		        "xmlMalloc",
+		        XMLSEC_ERRORS_R_XML_FAILED,
+		        XMLSEC_ERRORS_NO_MESSAGE);
+	    xmlSecXkmsServerCtxSetResult(ctx, xmlSecXkmsResultMajorReceiver, xmlSecXkmsResultMinorFailure);
+            return(-1);
+        }
+        xmlSecStrPrintf(faultString, len , xmlSecXkmsSoapFaultReasonMessageInvalid,
+                        xmlSecErrorsSafeString(ctx->requestNode->name));        
+    } else if((ctx->resultMajor == xmlSecXkmsResultMajorReceiver) &&
+              (ctx->requestId == NULL)) {
+        /* we understood the request but were not able to process it */
+        faultCodeHref = xmlSecSoap11Ns;
+        faultCodeLocalPart = xmlSecSoapFaultCodeServer;
+        faultString = xmlStrdup(xmlSecXkmsSoapFaultReasonServiceUnavailable);
+        if(faultString == NULL) {
+            xmlSecError(XMLSEC_ERRORS_HERE,
+		        NULL,
+		        "xmlStrdup",
+		        XMLSEC_ERRORS_R_XML_FAILED,
+		        XMLSEC_ERRORS_NO_MESSAGE);
+	    xmlSecXkmsServerCtxSetResult(ctx, xmlSecXkmsResultMajorReceiver, xmlSecXkmsResultMinorFailure);
+            return(-1);
+        }
+    } else if((ctx->requestId == NULL) && (ctx->requestNode != NULL)) {
+        /* we parsed the envelope but were not able to understand this request */
+        faultCodeHref = xmlSecSoap11Ns;
+        faultCodeLocalPart = xmlSecSoapFaultCodeClient;
+
+        len = xmlStrlen(BAD_CAST xmlSecErrorsSafeString(ctx->requestNode->name)) + 
+              xmlStrlen(xmlSecXkmsSoapFaultReasonMessageNotSupported) + 1;
+        faultString = xmlMalloc(len + 1);
+        if(faultString == NULL) {
+            xmlSecError(XMLSEC_ERRORS_HERE,
+		        NULL,
+		        "xmlMalloc",
+		        XMLSEC_ERRORS_R_XML_FAILED,
+		        XMLSEC_ERRORS_NO_MESSAGE);
+	    xmlSecXkmsServerCtxSetResult(ctx, xmlSecXkmsResultMajorReceiver, xmlSecXkmsResultMinorFailure);
+            return(-1);
+        }
+        xmlSecStrPrintf(faultString, len , xmlSecXkmsSoapFaultReasonMessageNotSupported,
+                        xmlSecErrorsSafeString(ctx->requestNode->name));
+    } else {
+        /* just some error */
+        faultCodeHref = xmlSecSoap11Ns;
+        faultCodeLocalPart = xmlSecSoapFaultCodeServer;
+        faultString = xmlStrdup(xmlSecXkmsSoapFaultReasonServiceUnavailable);
+        if(faultString == NULL) {
+            xmlSecError(XMLSEC_ERRORS_HERE,
+		        NULL,
+		        "xmlStrdup",
+		        XMLSEC_ERRORS_R_XML_FAILED,
+		        XMLSEC_ERRORS_NO_MESSAGE);
+	    xmlSecXkmsServerCtxSetResult(ctx, xmlSecXkmsResultMajorReceiver, xmlSecXkmsResultMinorFailure);
+            return(-1);
+        }
+    }
+    
+    if(xmlSecSoap11AddFaultEntry(envNode, faultCodeHref, faultCodeLocalPart, faultString, NULL) == NULL) {
+        xmlSecError(XMLSEC_ERRORS_HERE,
+		    NULL,
+		    "xmlSecSoap11AddFaultEntry",
+		    XMLSEC_ERRORS_R_XMLSEC_FAILED,
+		    XMLSEC_ERRORS_NO_MESSAGE);
+	xmlSecXkmsServerCtxSetResult(ctx, xmlSecXkmsResultMajorReceiver, xmlSecXkmsResultMinorFailure);
+        xmlFree(faultString);    
+        return(-1);
+    }
+
+    xmlFree(faultString);    
+    return(0);
+}
+
+static int 
+xmlSecXkmsServerCtxWriteSoap12FatalError(xmlSecXkmsServerCtxPtr ctx, xmlNodePtr envNode) {
+    xmlSecSoap12FaultCode faultCode = xmlSecSoap12FaultCodeUnknown;
+    const xmlChar* faultSubCodeHref = NULL;
+    const xmlChar* faultSubCodeLocalPart = NULL;
+    xmlChar* faultReason = NULL;
+    int len;
+    xmlNodePtr faultNode;
+    
+    xmlSecAssert2(ctx != NULL, -1);
+    xmlSecAssert2(envNode != NULL, -1);
+
+    if((ctx->resultMajor == xmlSecXkmsResultMajorVersionMismatch) ||
+       (ctx->requestNode == NULL)) {
+        /* we were not able to parse the envelope or its general version mismatch error */
+        faultCode = xmlSecSoap12FaultCodeVersionMismatch;
+        faultReason = xmlStrdup(xmlSecXkmsSoapFaultReasonUnsupportedVersion);
+        if(faultReason == NULL) {
+            xmlSecError(XMLSEC_ERRORS_HERE,
+		        NULL,
+		        "xmlStrdup",
+		        XMLSEC_ERRORS_R_XML_FAILED,
+		        XMLSEC_ERRORS_NO_MESSAGE);
+	    xmlSecXkmsServerCtxSetResult(ctx, xmlSecXkmsResultMajorReceiver, xmlSecXkmsResultMinorFailure);
+            return(-1);
+        }
+    } else if((ctx->resultMajor == xmlSecXkmsResultMajorSender) && 
+              (ctx->requestId == NULL)) {
+        /* we understood the request but were not able to parse input message */
+        faultCode = xmlSecSoap12FaultCodeSender;
+        faultSubCodeHref = xmlSecXkmsNs;
+        faultSubCodeLocalPart = xmlSecXkmsSoapSubcodeValueMessageNotSupported;
+
+        len = xmlStrlen(BAD_CAST xmlSecErrorsSafeString(ctx->requestNode->name)) +
+              xmlStrlen(xmlSecXkmsSoapFaultReasonMessageInvalid) + 1;
+        faultReason = xmlMalloc(len + 1);
+        if(faultReason == NULL) {
+            xmlSecError(XMLSEC_ERRORS_HERE,
+		        NULL,
+		        "xmlMalloc",
+		        XMLSEC_ERRORS_R_XML_FAILED,
+		        XMLSEC_ERRORS_NO_MESSAGE);
+	    xmlSecXkmsServerCtxSetResult(ctx, xmlSecXkmsResultMajorReceiver, xmlSecXkmsResultMinorFailure);
+            return(-1);
+        }
+        xmlSecStrPrintf(faultReason, len , xmlSecXkmsSoapFaultReasonMessageInvalid,
+                        xmlSecErrorsSafeString(ctx->requestNode->name));        
+    } else if((ctx->resultMajor == xmlSecXkmsResultMajorReceiver) &&
+              (ctx->requestId == NULL)) {
+        /* we understood the request but were not able to process it */
+        faultCode = xmlSecSoap12FaultCodeReceiver;
+        faultReason = xmlStrdup(xmlSecXkmsSoapFaultReasonServiceUnavailable);
+        if(faultReason == NULL) {
+            xmlSecError(XMLSEC_ERRORS_HERE,
+		        NULL,
+		        "xmlStrdup",
+		        XMLSEC_ERRORS_R_XML_FAILED,
+		        XMLSEC_ERRORS_NO_MESSAGE);
+	    xmlSecXkmsServerCtxSetResult(ctx, xmlSecXkmsResultMajorReceiver, xmlSecXkmsResultMinorFailure);
+            return(-1);
+        }
+    } else if((ctx->requestId == NULL) && (ctx->requestNode != NULL)) {
+        /* we parsed the envelope but were not able to understand this request */
+        faultCode = xmlSecSoap12FaultCodeSender;
+        faultSubCodeHref = xmlSecXkmsNs;
+        faultSubCodeLocalPart = xmlSecXkmsSoapSubcodeValueBadMessage;
+
+        len = xmlStrlen(BAD_CAST xmlSecErrorsSafeString(ctx->requestNode->name)) + 
+              xmlStrlen(xmlSecXkmsSoapFaultReasonMessageNotSupported) + 1;
+        faultReason = xmlMalloc(len + 1);
+        if(faultReason == NULL) {
+            xmlSecError(XMLSEC_ERRORS_HERE,
+		        NULL,
+		        "xmlMalloc",
+		        XMLSEC_ERRORS_R_XML_FAILED,
+		        XMLSEC_ERRORS_NO_MESSAGE);
+	    xmlSecXkmsServerCtxSetResult(ctx, xmlSecXkmsResultMajorReceiver, xmlSecXkmsResultMinorFailure);
+            return(-1);
+        }
+        xmlSecStrPrintf(faultReason, len , xmlSecXkmsSoapFaultReasonMessageNotSupported,
+                        xmlSecErrorsSafeString(ctx->requestNode->name));
+    } else {
+        /* just some error */
+        faultCode = xmlSecSoap12FaultCodeReceiver;
+        faultReason = xmlStrdup(xmlSecXkmsSoapFaultReasonServiceUnavailable);
+        if(faultReason == NULL) {
+            xmlSecError(XMLSEC_ERRORS_HERE,
+		        NULL,
+		        "xmlStrdup",
+		        XMLSEC_ERRORS_R_XML_FAILED,
+		        XMLSEC_ERRORS_NO_MESSAGE);
+	    xmlSecXkmsServerCtxSetResult(ctx, xmlSecXkmsResultMajorReceiver, xmlSecXkmsResultMinorFailure);
+            return(-1);
+        }
+    }
+    xmlSecAssert2(faultCode != xmlSecSoap12FaultCodeUnknown, -1);
+    xmlSecAssert2(faultReason != NULL, -1);
+    
+    faultNode = xmlSecSoap12AddFaultEntry(envNode, faultCode, faultReason, 
+                                    xmlSecXkmsSoapFaultReasonLang, NULL, NULL);
+    if(faultNode == NULL) {
+        xmlSecError(XMLSEC_ERRORS_HERE,
+		    NULL,
+		    "xmlSecSoap12AddFaultEntry",
+		    XMLSEC_ERRORS_R_XMLSEC_FAILED,
+		    XMLSEC_ERRORS_NO_MESSAGE);
+	xmlSecXkmsServerCtxSetResult(ctx, xmlSecXkmsResultMajorReceiver, xmlSecXkmsResultMinorFailure);
+        xmlFree(faultReason);    
+        return(-1);
+    }
+    xmlFree(faultReason);    
+
+    if((faultSubCodeHref != NULL) && (faultSubCodeLocalPart != NULL)) {
+        /* make sure that we have subcode (xkms) namespace declared */
+        if(xmlNewNs(faultNode, faultSubCodeHref, BAD_CAST "xkms") == NULL) {
+	    xmlSecError(XMLSEC_ERRORS_HERE,
+		        NULL,
+		        "xmlNewNs",
+		        XMLSEC_ERRORS_R_XML_FAILED,
+		        "ns=%s",
+		        xmlSecErrorsSafeString(faultSubCodeHref));
+            return(-1);
+        }
+        if(xmlSecSoap12AddFaultSubcode(faultNode, faultSubCodeHref, faultSubCodeLocalPart) == NULL) {
+	    xmlSecError(XMLSEC_ERRORS_HERE,
+		        NULL,
+		        "xmlSecSoap12AddFaultSubcode",
+		        XMLSEC_ERRORS_R_XMLSEC_FAILED,
+		        "href=%s,value=%s",
+		        xmlSecErrorsSafeString(faultSubCodeHref),
+		        xmlSecErrorsSafeString(faultSubCodeLocalPart));
+            return(-1);
+        }
+    }
+
+    return(0);
+}
+
+#endif /* XMLSEC_NO_SOAP */
+
+
+/** 
+ * xmlSecXkmsServerCtxSetResult: 
+ * @ctx:	 the pointer to XKMS processing context.
+ * @resultMajor: the major result code.
+ * @resultMinor: the minor result code.
+ * 
+ * Sets the major/minor result code in the context if no other result is already
+ * reported.
+ */
+EXPORT_C
+void 
+xmlSecXkmsServerCtxSetResult(xmlSecXkmsServerCtxPtr ctx, xmlSecXkmsResultMajor resultMajor, 
+                             xmlSecXkmsResultMinor resultMinor) {
+    xmlSecAssert(ctx != NULL);
+    
+    if((ctx->resultMajor == xmlSecXkmsResultMajorSuccess) && 
+       (resultMinor != xmlSecXkmsResultMajorSuccess)) {
+	ctx->resultMajor = resultMajor;
+	ctx->resultMinor = resultMinor;
+    } else if((ctx->resultMajor == xmlSecXkmsResultMajorSuccess) && 
+       (ctx->resultMinor == xmlSecXkmsResultMinorNone)) {
+	xmlSecAssert(resultMajor == xmlSecXkmsResultMajorSuccess);
+	
+	ctx->resultMinor = resultMinor;
+    }
+}
+
+
+/**
+ * xmlSecXkmsServerCtxDebugDump:
+ * @ctx:	the pointer to XKMS processing context.
+ * @output:	the pointer to output FILE.
+ *
+ * Prints the debug information about @ctx to @output.
+ */
+EXPORT_C
+void 
+xmlSecXkmsServerCtxDebugDump(xmlSecXkmsServerCtxPtr ctx, FILE* output) {
+    xmlSecAssert(ctx != NULL);
+    xmlSecAssert(output != NULL);
+    
+    fprintf(output, "= XKMS SERVER CONTEXT: %s\n",
+	    (ctx->requestId != xmlSecXkmsServerRequestIdUnknown && 
+	     xmlSecXkmsServerRequestKlassGetName(ctx->requestId)) ? 
+		xmlSecXkmsServerRequestKlassGetName(ctx->requestId) :
+		BAD_CAST "NULL");
+
+    xmlSecQName2IntegerDebugDump(gXmlSecXkmsResultMajorInfo, 
+		ctx->resultMajor, BAD_CAST "resultMajor", output);    
+    xmlSecQName2IntegerDebugDump(gXmlSecXkmsMinorErrorInfo, 
+		ctx->resultMinor, BAD_CAST "resultMinor", output);    
+
+    fprintf(output, "== id: %s\n", 
+		(ctx->id) ? ctx->id : BAD_CAST "");
+    fprintf(output, "== service: %s\n", 
+		(ctx->service) ? ctx->service : BAD_CAST "");
+    fprintf(output, "== nonce: %s\n", 
+		(ctx->nonce) ? ctx->nonce : BAD_CAST "");
+    fprintf(output, "== originalRequestId: %s\n", 
+		(ctx->originalRequestId) ? ctx->originalRequestId : BAD_CAST "");
+    fprintf(output, "== pendingNotificationMechanism: %s\n", 
+		(ctx->pendingNotificationMechanism) ? 
+		    ctx->pendingNotificationMechanism : 
+		    BAD_CAST "");
+    fprintf(output, "== pendingNotificationIdentifier: %s\n", 
+		(ctx->pendingNotificationIdentifier) ? 
+		    ctx->pendingNotificationIdentifier : 
+		    BAD_CAST "");
+    if(ctx->responseLimit != XMLSEC_XKMS_NO_RESPONSE_LIMIT) {
+        fprintf(output, "== ResponseLimit: %d\n", ctx->responseLimit);
+    }
+    xmlSecQName2BitMaskDebugDump(gXmlSecXkmsResponseMechanismInfo, 
+		ctx->responseMechanismMask, BAD_CAST "responseMechanism", output);    
+
+    if(ctx->expectedService != NULL) {    
+        fprintf(output, "== expected service: %s\n", ctx->expectedService);
+    }
+    fprintf(output, "== flags: 0x%08x\n", ctx->flags);
+    fprintf(output, "== flags2: 0x%08x\n", ctx->flags2);
+
+    fprintf(output, "== Key Info Read Ctx:\n");
+    xmlSecKeyInfoCtxDebugDump(&(ctx->keyInfoReadCtx), output);
+    
+    fprintf(output, "== Key Info Write Ctx:\n");
+    xmlSecKeyInfoCtxDebugDump(&(ctx->keyInfoWriteCtx), output);
+
+    if(xmlSecPtrListGetSize(&(ctx->enabledRespondWithIds)) > 0) {
+	fprintf(output, "== Enabled RespondWith: ");
+	xmlSecTransformIdListDebugDump(&(ctx->enabledRespondWithIds), output);
+    } else {
+	fprintf(output, "== Enabled RespondWith: all\n");
+    }
+
+    if(xmlSecPtrListGetSize(&(ctx->enabledServerRequestIds)) > 0) {
+	fprintf(output, "== Enabled ServerRequest: ");
+	xmlSecTransformIdListDebugDump(&(ctx->enabledServerRequestIds), output);
+    } else {
+	fprintf(output, "== Enabled ServerRequest: all\n");
+    }
+
+    fprintf(output, "== RespondWith List:\n");
+    xmlSecPtrListDebugDump(&(ctx->respWithList), output);
+
+    fprintf(output, "== Keys:\n");
+    xmlSecPtrListDebugDump(&(ctx->keys), output);
+    
+    if(ctx->compoundRequestContexts != NULL) {
+        fprintf(output, "== Compound Request:\n");
+        xmlSecPtrListDebugDump(ctx->compoundRequestContexts, output);
+    }
+}
+
+/**
+ * xmlSecXkmsServerCtxDebugXmlDump:
+ * @ctx:	the pointer to XKMS processing context.
+ * @output:	the pointer to output FILE.
+ *
+ * Prints the debug information about @ctx to @output in XML format.
+ */
+EXPORT_C
+void 
+xmlSecXkmsServerCtxDebugXmlDump(xmlSecXkmsServerCtxPtr ctx, FILE* output) {
+    xmlSecAssert(ctx != NULL);
+    xmlSecAssert(output != NULL);
+
+    fprintf(output, "<XkmsServerRequestContext name=\"%s\">\n",
+	    (ctx->requestId != xmlSecXkmsServerRequestIdUnknown && 
+	     xmlSecXkmsServerRequestKlassGetName(ctx->requestId)) ? 
+		xmlSecXkmsServerRequestKlassGetName(ctx->requestId) :
+		BAD_CAST "NULL");
+
+    xmlSecQName2IntegerDebugXmlDump(gXmlSecXkmsResultMajorInfo, 
+		ctx->resultMajor, BAD_CAST "MajorError", output);    
+    xmlSecQName2IntegerDebugXmlDump(gXmlSecXkmsMinorErrorInfo, 
+		ctx->resultMinor, BAD_CAST "MinorError", output);    
+
+    fprintf(output, "<Id>%s</Id>\n", 
+		(ctx->id) ? ctx->id : BAD_CAST "");
+    fprintf(output, "<Service>%s</Service>\n", 
+		(ctx->service) ? ctx->service : BAD_CAST "");
+    fprintf(output, "<Nonce>%s</Nonce>\n", 
+		(ctx->nonce) ? ctx->nonce : BAD_CAST "");
+    fprintf(output, "<OriginalRequestId>%s</OriginalRequestId>\n", 
+		(ctx->originalRequestId) ? ctx->originalRequestId : BAD_CAST "");
+    fprintf(output, "<PendingNotificationMechanism>%s</PendingNotificationMechanism>\n", 
+		(ctx->pendingNotificationMechanism) ? 
+		    ctx->pendingNotificationMechanism : 
+		    BAD_CAST "");
+    fprintf(output, "<PendingNotificationIdentifier>%s</PendingNotificationIdentifier>\n", 
+		(ctx->pendingNotificationIdentifier) ? 
+		    ctx->pendingNotificationIdentifier : 
+		    BAD_CAST "");
+    if(ctx->responseLimit != XMLSEC_XKMS_NO_RESPONSE_LIMIT) {
+        fprintf(output, "<ResponseLimit>%d</ResponseLimit>\n", ctx->responseLimit);
+    }
+    xmlSecQName2BitMaskDebugXmlDump(gXmlSecXkmsResponseMechanismInfo, 
+		ctx->responseMechanismMask, BAD_CAST "ResponseMechanism", output);    
+
+
+    if(ctx->expectedService != NULL) {    
+        fprintf(output, "<ExpectedService>%s</ExpectedService>\n", ctx->expectedService);
+    }
+    fprintf(output, "<Flags>%08x</Flags>\n", ctx->flags);
+    fprintf(output, "<Flags2>%08x</Flags2>\n", ctx->flags2);
+
+    fprintf(output, "<KeyInfoReadCtx>\n");
+    xmlSecKeyInfoCtxDebugXmlDump(&(ctx->keyInfoReadCtx), output);
+    fprintf(output, "</KeyInfoReadCtx>\n");
+
+    fprintf(output, "<KeyInfoWriteCtx>\n");
+    xmlSecKeyInfoCtxDebugXmlDump(&(ctx->keyInfoWriteCtx), output);
+    fprintf(output, "</KeyInfoWriteCtx>\n");
+
+    if(xmlSecPtrListGetSize(&(ctx->enabledRespondWithIds)) > 0) {
+	fprintf(output, "<EnabledRespondWith>\n");
+	xmlSecTransformIdListDebugXmlDump(&(ctx->enabledRespondWithIds), output);
+	fprintf(output, "</EnabledRespondWith>\n");
+    } else {
+	fprintf(output, "<EnabledRespondWith>all</EnabledRespondWith>\n");
+    }
+
+    if(xmlSecPtrListGetSize(&(ctx->enabledServerRequestIds)) > 0) {
+	fprintf(output, "<EnabledServerRequest>\n");
+	xmlSecTransformIdListDebugXmlDump(&(ctx->enabledServerRequestIds), output);
+	fprintf(output, "</EnabledServerRequest>\n");
+    } else {
+	fprintf(output, "<EnabledServerRequest>all</EnabledServerRequest>\n");
+    }
+
+
+    fprintf(output, "<RespondWithList>\n");
+    xmlSecPtrListDebugXmlDump(&(ctx->respWithList), output);
+    fprintf(output, "</RespondWithList>\n");
+
+    fprintf(output, "<Keys>\n");
+    xmlSecPtrListDebugXmlDump(&(ctx->keys), output);
+    fprintf(output, "</Keys>\n");
+
+    if(ctx->compoundRequestContexts != NULL) {
+        fprintf(output, "<CompoundRequest>\n");
+        xmlSecPtrListDebugXmlDump(ctx->compoundRequestContexts, output);
+        fprintf(output, "</CompoundRequest>\n");
+    }
+
+    fprintf(output, "</XkmsServerRequestContext>\n");
+}
+
+/**
+ *  <xkms:MessageAbstractType Id Service Nonce?>
+ *      <ds:Signature>?
+ *      <xkms:MessageExtension>*
+ *      (<xkms:OpaqueClientData>
+ *          <xkms:OpaqueData>?
+ *      )?
+ *  
+ *  <xkms:RequestAbstractType Id Service Nonce? OriginalRequestId? ResponseLimit?>
+ *      <ds:Signature>?
+ *      <xkms:MessageExtension>*
+ *      (<xkms:OpaqueClientData>
+ *          <xkms:OpaqueData>?
+ *      )?
+ *      <xkms:ResponseMechanism>*
+ *      <xkms:RespondWith>*
+ *      <xkms:PendingNotification Mechanism Identifier>?
+ *
+ * XML Schema:
+ *
+ *   <!-- RequestAbstractType -->
+ *   <complexType name="RequestAbstractType" abstract="true">
+ *      <complexContent>
+ *         <extension base="xkms:MessageAbstractType">
+ *            <sequence>
+ *              <element ref="xkms:ResponseMechanism" minOccurs="0" 
+ *                     maxOccurs="unbounded"/>
+ *               <element ref="xkms:RespondWith" minOccurs="0" 
+ *                     maxOccurs="unbounded"/>
+ *               <element ref="xkms:PendingNotification" minOccurs="0"/>
+ *            </sequence>
+ *            <attribute name="OriginalRequestId" type="anyURI" 
+ *                  use="optional"/>
+ *            <attribute name="ResponseLimit" type="integer" use="optional"/>
+ *         </extension>
+ *      </complexContent>
+ *   </complexType>
+ *   <!-- /RequestAbstractType -->
+ *
+ *   <!-- MessageAbstractType -->
+ *   <complexType name="MessageAbstractType" abstract="true">
+ *      <sequence>
+ *         <element ref="ds:Signature" minOccurs="0"/>
+ *         <element ref="xkms:MessageExtension" minOccurs="0" 
+ *               maxOccurs="unbounded"/>
+ *         <element ref="xkms:OpaqueClientData" minOccurs="0"/>
+ *      </sequence>
+ *      <attribute name="Id" type="ID" use="required"/>
+ *      <attribute name="Service" type="anyURI" use="required"/>
+ *      <attribute name="Nonce" type="base64Binary" use="optional"/>
+ *   </complexType>
+ *   <!-- /MessageAbstractType -->
+ */
+static int 
+xmlSecXkmsServerCtxRequestAbstractTypeNodeRead(xmlSecXkmsServerCtxPtr ctx, xmlNodePtr* node) {
+    xmlNodePtr cur;
+    xmlChar* tmp;
+    int ret;
+
+    xmlSecAssert2(ctx != NULL, -1);
+    xmlSecAssert2(node != NULL, -1);
+    xmlSecAssert2((*node) != NULL, -1);
+    
+    cur = (*node);
+    xmlSecAssert2(cur != NULL, -1);
+
+    /* required Id attribute */
+    xmlSecAssert2(ctx->id == NULL, -1);
+    ctx->id = xmlGetProp(cur, xmlSecAttrId);
+    if(ctx->id == NULL) {
+    	xmlSecError(XMLSEC_ERRORS_HERE,
+		    NULL,
+		    "xmlGetProp",
+		    XMLSEC_ERRORS_R_XML_FAILED,
+		    "name=%s;node=%s",
+		    xmlSecErrorsSafeString(xmlSecAttrId),
+		    xmlSecErrorsSafeString(cur->name));
+	return(-1);
+    }
+    
+    /* required Service attribute */
+    xmlSecAssert2(ctx->service == NULL, -1);
+    ctx->service = xmlGetProp(cur, xmlSecAttrService);
+    if(ctx->service == NULL) {
+    	xmlSecError(XMLSEC_ERRORS_HERE,
+		    NULL,
+		    "xmlGetProp",
+		    XMLSEC_ERRORS_R_XML_FAILED,
+		    "name=%s;node=%s",
+		    xmlSecErrorsSafeString(xmlSecAttrService),
+		    xmlSecErrorsSafeString(cur->name));
+	return(-1);
+    }
+    
+    /* check service */
+    if((ctx->expectedService != NULL) && (!xmlStrEqual(ctx->expectedService, ctx->service))) {
+    	xmlSecError(XMLSEC_ERRORS_HERE,
+		    NULL,
+		    NULL,
+		    XMLSEC_ERRORS_R_INVALID_DATA,
+		    "expectedService=%s;actualService=%s",
+		    xmlSecErrorsSafeString(ctx->expectedService),
+		    xmlSecErrorsSafeString(ctx->service));
+	return(-1);
+    }
+
+    /* optional Nonce attribute */
+    xmlSecAssert2(ctx->nonce == NULL, -1);
+    ctx->nonce = xmlGetProp(cur, xmlSecAttrNonce);
+
+    /* optional OriginalRequestId attribute */
+    xmlSecAssert2(ctx->originalRequestId == NULL, -1);
+    ctx->originalRequestId = xmlGetProp(cur, xmlSecAttrOriginalRequestId);
+
+    /* optional ResponseLimit attribute */
+    xmlSecAssert2(ctx->responseLimit == XMLSEC_XKMS_NO_RESPONSE_LIMIT, -1);
+    tmp = xmlGetProp(cur, xmlSecAttrResponseLimit);
+    if(tmp != NULL) {
+	ctx->responseLimit = atoi((char*)tmp);
+	xmlFree(tmp);
+    }
+
+    /* now read children */   
+    cur = xmlSecGetNextElementNode(cur->children);
+    
+    /* first node is optional <dsig:Signature/> node */
+    if((cur != NULL) && xmlSecCheckNodeName(cur, xmlSecNodeSignature, xmlSecDSigNs)) {
+	ret = xmlSecXkmsServerCtxSignatureNodeRead(ctx, cur);
+	if(ret < 0) {
+    	    xmlSecError(XMLSEC_ERRORS_HERE,
+		        NULL,
+		        "xmlSecXkmsServerCtxSignatureNodeRead",
+			XMLSEC_ERRORS_R_XMLSEC_FAILED,
+			XMLSEC_ERRORS_NO_MESSAGE);
+	    return(-1);
+	}
+	cur = xmlSecGetNextElementNode(cur->next);
+    }
+    
+    /* next is zero or more <xkms:MessageExtension/> nodes */
+    ret = xmlSecXkmsServerCtxMessageExtensionNodesRead(ctx, &cur);
+    if(ret < 0) {
+    	xmlSecError(XMLSEC_ERRORS_HERE,
+		    NULL,
+		    "xmlSecXkmsServerCtxMessageExtensionNodesRead",
+		    XMLSEC_ERRORS_R_XMLSEC_FAILED,
+		    XMLSEC_ERRORS_NO_MESSAGE);
+	return(-1);
+    }
+    
+    /* next is optional <xkms:OpaqueClientData/> node */
+    if((cur != NULL) && xmlSecCheckNodeName(cur, xmlSecNodeOpaqueClientData, xmlSecXkmsNs)) {
+	ret = xmlSecXkmsServerCtxOpaqueClientDataNodeRead(ctx, cur);
+	if(ret < 0) {
+    	    xmlSecError(XMLSEC_ERRORS_HERE,
+		        NULL,
+		        "xmlSecXkmsServerCtxOpaqueClientDataNodeRead",
+			XMLSEC_ERRORS_R_XMLSEC_FAILED,
+			XMLSEC_ERRORS_NO_MESSAGE);
+	    return(-1);
+	}
+	cur = xmlSecGetNextElementNode(cur->next);
+    }
+
+    /* next is zero or more <xkms:ResponseMechanism/> nodes */
+    ret = xmlSecQName2BitMaskNodesRead(gXmlSecXkmsResponseMechanismInfo, &cur, 
+			xmlSecNodeResponseMechanism, xmlSecXkmsNs,
+                        ((ctx->flags & XMLSEC_XKMS_SERVER_FLAGS_STOP_ON_UNKNOWN_RESPONSE_MECHANISM) != 0) ? 1 : 0, 
+			&ctx->responseMechanismMask);
+    if(ret < 0) {
+    	xmlSecError(XMLSEC_ERRORS_HERE,
+		    NULL,
+		    "xmlSecQName2BitMaskNodesRead",
+		    XMLSEC_ERRORS_R_XMLSEC_FAILED,
+		    "name=%s",
+		    xmlSecErrorsSafeString(xmlSecNodeResponseMechanism));
+	return(-1);
+    }
+    
+    /* next is zero or more <xkms:RespondWith/> nodes */
+    ret = xmlSecXkmsServerCtxRespondWithNodesRead(ctx, &cur);
+    if(ret < 0) {
+    	xmlSecError(XMLSEC_ERRORS_HERE,
+		    NULL,
+		    "xmlSecXkmsServerCtxRespondWithNodesRead",
+		    XMLSEC_ERRORS_R_XMLSEC_FAILED,
+		    XMLSEC_ERRORS_NO_MESSAGE);
+	return(-1);
+    }
+
+    /* next is optional <xkms:PendingNotification/> node */
+    if((cur != NULL) && xmlSecCheckNodeName(cur, xmlSecNodePendingNotification, xmlSecXkmsNs)) {
+	ret = xmlSecXkmsServerCtxPendingNotificationNodeRead(ctx, cur);    
+	if(ret < 0) {
+    	    xmlSecError(XMLSEC_ERRORS_HERE,
+		        NULL,
+		        "xmlSecXkmsServerCtxPendingNotificationNodeRead",
+			XMLSEC_ERRORS_R_XMLSEC_FAILED,
+			XMLSEC_ERRORS_NO_MESSAGE);
+	    return(-1);
+	}
+	cur = xmlSecGetNextElementNode(cur->next);
+    }
+
+    (*node) = cur;    
+    return(0);
+}
+
+static int 
+xmlSecXkmsServerCtxSignatureNodeRead(xmlSecXkmsServerCtxPtr ctx, xmlNodePtr node) {
+    xmlSecAssert2(ctx != NULL, -1);
+    xmlSecAssert2(node != NULL, -1);
+    
+    return(0);
+}
+
+/** 
+ *   <!-- MessageExtension -->
+ *   <element name="MessageExtension" type="xkms:MessageExtensionAbstractType"
+ *         abstract="true"/>
+ *   <complexType name="MessageExtensionAbstractType" abstract="true"/>
+ *   <!-- /MessageExtension -->
+ */
+static int
+xmlSecXkmsServerCtxMessageExtensionNodesRead(xmlSecXkmsServerCtxPtr ctx, xmlNodePtr* node) {
+    xmlNodePtr cur;
+
+    xmlSecAssert2(ctx != NULL, -1);
+    xmlSecAssert2(ctx->firtsMsgExtNode == NULL, -1);
+    xmlSecAssert2(node != NULL, -1);
+
+    cur = (*node);
+    while((cur != NULL) && xmlSecCheckNodeName(cur, xmlSecNodeMessageExtension, xmlSecXkmsNs)) {
+	if(ctx->firtsMsgExtNode == NULL) {
+	    ctx->firtsMsgExtNode = cur;
+	}
+	cur = xmlSecGetNextElementNode(cur->next);
+    }
+
+    (*node) = cur;    
+    return(0);
+}
+
+static int 
+xmlSecXkmsServerCtxOpaqueClientDataNodeRead(xmlSecXkmsServerCtxPtr ctx, xmlNodePtr node) {
+    xmlSecAssert2(ctx != NULL, -1);
+    xmlSecAssert2(ctx->opaqueClientDataNode == NULL, -1);
+    xmlSecAssert2(node != NULL, -1);
+
+    /* remember that node, will copy it in the response later */
+    ctx->opaqueClientDataNode = node;
+    return(0);
+}
+
+static int
+xmlSecXkmsServerCtxRespondWithNodesRead(xmlSecXkmsServerCtxPtr ctx, xmlNodePtr* node) {
+    xmlNodePtr cur;
+    int ret;
+
+    xmlSecAssert2(ctx != NULL, -1);
+    xmlSecAssert2(node != NULL, -1);
+
+    cur = (*node);
+    while((cur != NULL) && xmlSecCheckNodeName(cur, xmlSecNodeRespondWith, xmlSecXkmsNs)) {
+	xmlSecXkmsRespondWithId id = xmlSecXkmsRespondWithIdUnknown;
+
+	if(xmlSecPtrListGetSize(&(ctx->enabledRespondWithIds)) > 0) {
+	    id = xmlSecXkmsRespondWithIdListFindByNodeValue(&(ctx->enabledRespondWithIds), cur);
+	} else {
+	    id = xmlSecXkmsRespondWithIdListFindByNodeValue(xmlSecXkmsRespondWithIdsGet(), cur);	
+	}
+
+	if(id != xmlSecXkmsRespondWithIdUnknown) {	
+	    ret = xmlSecXkmsRespondWithNodeRead(id, ctx, cur);
+	    if(ret < 0) {
+	        xmlSecError(XMLSEC_ERRORS_HERE,
+			    NULL,
+			    "xmlSecCreateTree",
+			    XMLSEC_ERRORS_R_XMLSEC_FAILED,
+			    XMLSEC_ERRORS_NO_MESSAGE);
+		return(-1);
+	    }
+	} else if((ctx->flags & XMLSEC_XKMS_SERVER_FLAGS_STOP_ON_UNKNOWN_RESPOND_WITH) != 0) {
+            xmlChar* content ;
+            
+            content = xmlNodeGetContent(cur);
+    	    xmlSecError(XMLSEC_ERRORS_HERE,
+			NULL,
+			NULL,
+			XMLSEC_ERRORS_R_XMLSEC_FAILED,
+			"name=%s,value=%s",
+                        xmlSecErrorsSafeString(cur->name),
+                        xmlSecErrorsSafeString(content));
+            if(content != NULL) {
+                xmlFree(content);
+            }
+	    return(-1);
+	}
+	cur = xmlSecGetNextElementNode(cur->next);
+    }
+    
+    (*node) = cur;    
+    return(0);
+}
+
+/** 
+ * XML Schema:
+ *   <!-- PendingNotification -->
+ *   <element name="PendingNotification" type="xkms:PendingNotificationType"/>
+ *   <complexType name="PendingNotificationType">
+ *      <attribute name="Mechanism" type="anyURI" use="required"/>
+ *      <attribute name="Identifier" type="anyURI" use="required"/>
+ *   </complexType>
+ *   <!-- /PendingNotification -->
+ */
+static int 
+xmlSecXkmsServerCtxPendingNotificationNodeRead(xmlSecXkmsServerCtxPtr ctx, xmlNodePtr node) {
+    xmlSecAssert2(ctx != NULL, -1);
+    xmlSecAssert2(node != NULL, -1);
+
+    xmlSecAssert2(ctx->pendingNotificationMechanism == NULL, -1);
+    ctx->pendingNotificationMechanism = xmlGetProp(node, xmlSecAttrMechanism);
+    if(ctx->pendingNotificationMechanism == NULL) {
+	xmlSecError(XMLSEC_ERRORS_HERE,
+		    NULL,
+		    "xmlGetProp",
+		    XMLSEC_ERRORS_R_XML_FAILED,
+		    "name=%s;node=%s",
+		    xmlSecErrorsSafeString(xmlSecAttrMechanism),
+		    xmlSecErrorsSafeString(node->name));
+    	return(-1);
+    }
+
+    xmlSecAssert2(ctx->pendingNotificationIdentifier == NULL, -1);
+    ctx->pendingNotificationIdentifier = xmlGetProp(node, xmlSecAttrIdentifier);
+    if(ctx->pendingNotificationIdentifier == NULL) {
+	xmlSecError(XMLSEC_ERRORS_HERE,
+		    NULL,
+		    "xmlGetProp",
+		    XMLSEC_ERRORS_R_XML_FAILED,
+		    "name=%s;node=%s",
+		    xmlSecErrorsSafeString(xmlSecAttrIdentifier),
+		    xmlSecErrorsSafeString(node->name));
+    	return(-1);
+    }
+    
+    return(0);
+}
+
+/**
+ *  <xkms:PendingRequestType Id Service Nonce? OriginalRequestId? ResponseLimit? ResponseId?>
+ *      <ds:Signature>?
+ *      <xkms:MessageExtension>*
+ *      (<xkms:OpaqueClientData>
+ *          <xkms:OpaqueData>?
+ *      )?
+ *      <xkms:ResponseMechanism>*
+ *      <xkms:RespondWith>*
+ *      <xkms:PendingNotification Mechanism Identifier>?
+ *  
+ * XML Schema:
+ *
+ *   <!-- PendingRequest -->  
+ *   <element name="PendingRequest" type="xkms:PendingRequestType"/>   
+ *   <complexType name="PendingRequestType">
+ *       <complexContent>
+ *           <extension base="xkms:RequestAbstractType">
+ *               <attribute name="ResponseId" type="anyURI" use="optional"/>
+ *            </extension>
+ *       </complexContent>
+ *    </complexType>
+ *    <!-- /PendingRequest --> * 
+ */
+static int 
+xmlSecXkmsServerCtxPendingRequestNodeRead(xmlSecXkmsServerCtxPtr ctx, xmlNodePtr* node) {
+    int ret;
+
+    xmlSecAssert2(ctx != NULL, -1);
+    xmlSecAssert2(node != NULL, -1);
+    
+    /* first read "parent" type */
+    ret = xmlSecXkmsServerCtxRequestAbstractTypeNodeRead(ctx, node);
+    if(ret < 0) {
+    	xmlSecError(XMLSEC_ERRORS_HERE,
+		    NULL,
+		    "xmlSecXkmsServerCtxRequestAbstractTypeNodeRead",
+		    XMLSEC_ERRORS_R_XMLSEC_FAILED,
+		    XMLSEC_ERRORS_NO_MESSAGE);
+	return(-1);
+    }
+
+    return(0);
+}
+
+/**
+ *  <xkms:QueryKeyBinding Id?
+ *      <ds:KeyInfo>?
+ *      <xkms:KeyUsage>?
+ *      <xkms:KeyUsage>?
+ *      <xkms:KeyUsage>?
+ *      <xkms:UseKeyWith Application Identifier>*    
+ *      <xkms:TimeInstant Time>?
+ *  
+ * XML Schema:
+ *   <!-- QueryKeyBinding -->
+ *   <element name="QueryKeyBinding" type="xkms:QueryKeyBindingType"/>
+ *   <complexType name="QueryKeyBindingType">
+ *      <complexContent>
+ *          <extension base="xkms:KeyBindingAbstractType">
+ *	        <sequence>
+ *		    <element ref="xkms:TimeInstant" minOccurs="0"/>
+ *		</sequence>
+ *	    </extension>
+ *	</complexContent>
+ *   </complexType>
+ *   <!-- /QueryKeyBinding -->
+ */
+static int 
+xmlSecXkmsServerCtxQueryKeyBindingNodeRead(xmlSecXkmsServerCtxPtr ctx, xmlNodePtr node) {
+    xmlNodePtr cur;
+    int ret;
+    
+    xmlSecAssert2(ctx != NULL, -1);
+    xmlSecAssert2(node != NULL, -1);
+    
+    /* first read "parent" type */
+    cur = node;
+    ret = xmlSecXkmsServerCtxKeyBindingAbstractTypeNodeRead(ctx, &cur);
+    if(ret < 0) {
+    	xmlSecError(XMLSEC_ERRORS_HERE,
+		    NULL,
+		    "xmlSecXkmsServerCtxKeyBindingAbstractTypeNodeRead",
+		    XMLSEC_ERRORS_R_XMLSEC_FAILED,
+		    XMLSEC_ERRORS_NO_MESSAGE);
+	return(-1);
+    }
+
+    /* next is optional <xkms:TimeInstant/> node */
+    if((cur != NULL) && xmlSecCheckNodeName(cur, xmlSecNodeTimeInstant, xmlSecXkmsNs)) {
+	ret = xmlSecXkmsServerCtxTimeInstantNodeRead(ctx, cur);
+	if(ret < 0) {
+    	    xmlSecError(XMLSEC_ERRORS_HERE,
+		        NULL,
+			"xmlSecXkmsServerCtxTimeInstantNodeRead",
+			XMLSEC_ERRORS_R_XMLSEC_FAILED,
+			XMLSEC_ERRORS_NO_MESSAGE);
+	    return(-1);
+	}
+	cur = xmlSecGetNextElementNode(cur->next);
+    }
+
+    /* check that there is nothing after the last node */
+    if(cur != NULL) {
+	xmlSecError(XMLSEC_ERRORS_HERE,
+		    NULL,
+		    xmlSecErrorsSafeString(xmlSecNodeGetName(cur)),
+		    XMLSEC_ERRORS_R_UNEXPECTED_NODE,
+		    XMLSEC_ERRORS_NO_MESSAGE);
+	return(-1);
+    }
+    
+    return(0);
+}
+
+/**
+ *  <xkms:KeyBindingAbstractType Id?>
+ *      <ds:KeyInfo>?
+ *      <xkms:KeyUsage>?
+ *      <xkms:KeyUsage>?
+ *      <xkms:KeyUsage>?
+ *      <xkms:UseKeyWith Application Identifier>*
+ *
+ * XML Schema:
+ *    <!-- KeyBindingAbstractType-->
+ *    <complexType name="KeyBindingAbstractType" abstract="true">
+ *       <sequence>
+ *          <element ref="ds:KeyInfo" minOccurs="0"/>
+ *          <element ref="xkms:KeyUsage" minOccurs="0" maxOccurs="3"/>
+ *          <element ref="xkms:UseKeyWith" minOccurs="0" 
+ *                   maxOccurs="unbounded"/>
+ *       </sequence>
+ *       <attribute name="Id" type="ID" use="optional"/>
+ *    </complexType>
+ *    <!-- /KeyBindingAbstractType-->
+ */
+static int 
+xmlSecXkmsServerCtxKeyBindingAbstractTypeNodeRead(xmlSecXkmsServerCtxPtr ctx, xmlNodePtr* node) {
+    xmlNodePtr cur;
+    int ret;
+    
+    xmlSecAssert2(ctx != NULL, -1);
+    xmlSecAssert2(node != NULL, -1);
+    xmlSecAssert2((*node) != NULL, -1);
+    
+    cur = (*node);
+    xmlSecAssert2(cur != NULL, -1);
+    
+    /* we don't care about Id attribute in this node */
+    cur = xmlSecGetNextElementNode(cur->children);
+    
+    /* first node is optional <dsig:KeyInfo/> node. for now we only remember pointer */
+    xmlSecAssert2(ctx->keyInfoNode == NULL, -1);
+    if((cur != NULL) && xmlSecCheckNodeName(cur, xmlSecNodeKeyInfo, xmlSecDSigNs)) {
+	ctx->keyInfoNode = cur;
+	cur = xmlSecGetNextElementNode(cur->next);
+    }
+    
+    /* next is zero or more <xkms:KeyUsage/> nodes */
+    ret = xmlSecQName2BitMaskNodesRead(gXmlSecXkmsKeyUsageInfo, &cur,
+		    xmlSecNodeKeyUsage, xmlSecXkmsNs, 
+                    ((ctx->flags & XMLSEC_XKMS_SERVER_FLAGS_STOP_ON_UNKNOWN_KEY_USAGE) != 0) ? 1 : 0,
+		    &(ctx->keyInfoReadCtx.keyReq.keyUsage));
+    if(ret < 0) {
+    	xmlSecError(XMLSEC_ERRORS_HERE,
+		    NULL,
+		    "xmlSecQName2BitMaskNodesRead",
+		    XMLSEC_ERRORS_R_XMLSEC_FAILED,
+		    "name=%s",
+		    xmlSecErrorsSafeString(xmlSecNodeKeyUsage));
+	return(-1);
+    }
+    
+    /* next is zero or more <xkms:UseKeyWith/> nodes */
+    ret = xmlSecXkmsServerCtxUseKeyWithNodesRead(ctx, &cur);
+    if(ret < 0) {
+    	xmlSecError(XMLSEC_ERRORS_HERE,
+		    NULL,
+		    "xmlSecXkmsServerCtxUseKeyWithNodesRead",
+		    XMLSEC_ERRORS_R_XMLSEC_FAILED,
+		    XMLSEC_ERRORS_NO_MESSAGE);
+	return(-1);
+    }
+
+    (*node) = cur;
+    return(0);
+}
+
+static int 
+xmlSecXkmsServerCtxKeyBindingAbstractTypeNodeWrite(xmlSecXkmsServerCtxPtr ctx, xmlNodePtr node, xmlSecKeyPtr key) {
+    xmlNodePtr cur;
+    int ret;
+
+    xmlSecAssert2(ctx != NULL, -1);
+    xmlSecAssert2(node != NULL, -1);
+    xmlSecAssert2(key != NULL, -1);
+
+    /* generate and add Id attribute */
+    ret = xmlSecGenerateAndAddID(node, xmlSecAttrId, ctx->idPrefix, ctx->idLen);
+    if(ret < 0) {
+	xmlSecError(XMLSEC_ERRORS_HERE,
+		    NULL,
+		    "xmlSecGenerateAndAddID",
+		    XMLSEC_ERRORS_R_XMLSEC_FAILED,
+		    XMLSEC_ERRORS_NO_MESSAGE);
+	return(-1);  	
+    }
+
+    /* <dsig:KeyInfo/> node */
+    cur = xmlSecAddChild(node, xmlSecNodeKeyInfo, xmlSecDSigNs);
+    if(cur == NULL) {
+	xmlSecError(XMLSEC_ERRORS_HERE,
+		    NULL,
+		    "xmlSecAddChild",
+		    XMLSEC_ERRORS_R_XMLSEC_FAILED,
+		    "node=%s",
+		    xmlSecErrorsSafeString(xmlSecNodeKeyInfo));
+	return(-1);  	
+    }
+
+    ret = xmlSecXkmsServerCtxKeyInfoNodeWrite(ctx, cur, key);
+    if(ret < 0) {
+	xmlSecError(XMLSEC_ERRORS_HERE,
+		    NULL,
+		    "xmlSecXkmsServerCtxKeyInfoNodeWrite",
+		    XMLSEC_ERRORS_R_XMLSEC_FAILED,
+		    XMLSEC_ERRORS_NO_MESSAGE);
+	return(-1);  	
+    }
+    
+    /* next is <xkms:KeyUsage/> node */
+    ret = xmlSecQName2BitMaskNodesWrite(gXmlSecXkmsKeyUsageInfo, node,
+		    xmlSecNodeKeyUsage, xmlSecXkmsNs, 
+		    key->usage);
+    if(ret < 0) {
+    	xmlSecError(XMLSEC_ERRORS_HERE,
+		    NULL,
+		    "xmlSecQName2BitMaskNodesWrite",
+		    XMLSEC_ERRORS_R_XMLSEC_FAILED,
+		    "name=%s",
+		    xmlSecErrorsSafeString(xmlSecNodeKeyUsage));
+	return(-1);
+    }
+
+    /* and the last node is <xkms:UseKeyWith/> */
+    ret = xmlSecXkmsServerCtxUseKeyWithNodesWrite(ctx, node, key);
+    if(ret < 0) {
+    	xmlSecError(XMLSEC_ERRORS_HERE,
+		    NULL,
+		    "xmlSecXkmsServerCtxUseKeyWithNodesWrite",
+		    XMLSEC_ERRORS_R_XMLSEC_FAILED,
+		    XMLSEC_ERRORS_NO_MESSAGE);
+	return(-1);
+    }
+    
+    return(0);
+}
+
+static int 
+xmlSecXkmsServerCtxKeyInfoNodeWrite(xmlSecXkmsServerCtxPtr ctx, xmlNodePtr node, xmlSecKeyPtr key) {
+    int ret;
+
+    xmlSecAssert2(ctx != NULL, -1);
+    xmlSecAssert2(key != NULL, -1);
+    xmlSecAssert2(node != NULL, -1);
+
+    /* add child nodes as requested in <xkms:RespondWith/> nodes */
+    ret = xmlSecXkmsRespondWithIdListWrite(&(ctx->respWithList), ctx, node);
+    if(ret < 0) {
+	xmlSecError(XMLSEC_ERRORS_HERE,
+		    NULL,
+		    "xmlSecXkmsRespondWithIdListWrite",
+		    XMLSEC_ERRORS_R_XMLSEC_FAILED,
+		    XMLSEC_ERRORS_NO_MESSAGE);
+	return(-1);  	
+    }
+
+    ret = xmlSecKeyInfoNodeWrite(node, key, &(ctx->keyInfoWriteCtx));
+    if(ret < 0) {
+	xmlSecError(XMLSEC_ERRORS_HERE,
+		    NULL,
+		    "xmlSecKeyInfoNodeWrite",
+		    XMLSEC_ERRORS_R_XMLSEC_FAILED,
+		    XMLSEC_ERRORS_NO_MESSAGE);
+	return(-1);  	
+    }
+
+    return(0);
+}
+
+
+/**
+ * XML Schema:
+ *    <!-- UseKeyWith -->
+ *    <element name="UseKeyWith" type="xkms:UseKeyWithType"/>
+ *    <complexType name="UseKeyWithType">
+ *      <attribute name="Application" type="anyURI" use="required"/>
+ *      <attribute name="Identifier" type="string" use="required"/>
+ *    </complexType>
+ *    <!-- /UseKeyWith -->
+ */
+static int
+xmlSecXkmsServerCtxUseKeyWithNodesRead(xmlSecXkmsServerCtxPtr ctx, xmlNodePtr* node) {
+    xmlSecPtrListPtr list;
+    xmlNodePtr cur;
+    xmlSecKeyUseWithPtr keyUseWith;
+    xmlChar* application;
+    xmlChar* identifier;
+    int ret;
+    
+    xmlSecAssert2(ctx != NULL, -1);
+    xmlSecAssert2(node != NULL, -1);
+
+    list = &(ctx->keyInfoReadCtx.keyReq.keyUseWithList);
+    xmlSecAssert2(xmlSecPtrListGetSize(list) == 0, -1);
+
+    cur = (*node);
+    while((cur != NULL) && xmlSecCheckNodeName(cur, xmlSecNodeUseKeyWith, xmlSecXkmsNs)) {
+	application = xmlGetProp(cur, xmlSecAttrApplication);
+	if(application == NULL) {
+	    xmlSecError(XMLSEC_ERRORS_HERE,
+		    	NULL,
+			"xmlGetProp",
+			XMLSEC_ERRORS_R_XML_FAILED,
+			"name=%s;node=%s",
+			xmlSecErrorsSafeString(xmlSecAttrApplication),
+			xmlSecErrorsSafeString(cur->name));
+    	    return(-1);
+	}
+
+	identifier = xmlGetProp(cur, xmlSecAttrIdentifier);
+	if(identifier == NULL) {
+	    xmlSecError(XMLSEC_ERRORS_HERE,
+		    	NULL,
+			"xmlGetProp",
+			XMLSEC_ERRORS_R_XML_FAILED,
+			"name=%s;node=%s",
+			xmlSecErrorsSafeString(xmlSecAttrIdentifier),
+			xmlSecErrorsSafeString(cur->name));
+	    xmlFree(application);
+    	    return(-1);
+	}
+	
+	keyUseWith = xmlSecKeyUseWithCreate(application, identifier);
+	if(keyUseWith == NULL) {
+	    xmlSecError(XMLSEC_ERRORS_HERE,
+		    	NULL,
+			"xmlSecKeyUseWithCreate",
+		    	XMLSEC_ERRORS_R_XMLSEC_FAILED,
+			XMLSEC_ERRORS_NO_MESSAGE);
+	    xmlFree(application);
+	    xmlFree(identifier);
+    	    return(-1);
+	}
+	xmlFree(application);
+	xmlFree(identifier);
+	
+	ret = xmlSecPtrListAdd(list, keyUseWith);
+	if(ret < 0) {
+	    xmlSecError(XMLSEC_ERRORS_HERE,
+		    	NULL,
+			"xmlSecPtrListAdd",
+		    	XMLSEC_ERRORS_R_XMLSEC_FAILED,
+			XMLSEC_ERRORS_NO_MESSAGE);
+	    xmlSecKeyUseWithDestroy(keyUseWith);
+    	    return(-1);
+	}
+	
+	cur = xmlSecGetNextElementNode(cur->next);
+    }
+
+    (*node) = cur;    
+    return(0);
+}
+
+static int 
+xmlSecXkmsServerCtxUseKeyWithNodesWrite(xmlSecXkmsServerCtxPtr ctx, xmlNodePtr node, xmlSecKeyPtr key) {
+    xmlSecAssert2(ctx != NULL, -1);
+    xmlSecAssert2(node != NULL, -1);
+    xmlSecAssert2(key != NULL, -1);
+
+    return(0);
+}
+
+
+static int 
+xmlSecXkmsServerCtxTimeInstantNodeRead(xmlSecXkmsServerCtxPtr ctx, xmlNodePtr node) {
+    xmlSecAssert2(ctx != NULL, -1);
+    xmlSecAssert2(node != NULL, -1);
+
+    return(0);
+}
+
+/**
+ *  <xkms:ResultType Id Service Nonce? ResultMajor ResultMinor? RequestId?>
+ *      <ds:Signature>?
+ *      <xkms:MessageExtension>*
+ *      (<xkms:OpaqueClientData>
+ *          <xkms:OpaqueData>?
+ *      )?
+ *      <xkms:RequestSignatureValue>*
+ *
+ * XML Schema:
+ *    <!-- ResultType -->
+ *    <element name="Result" type="xkms:ResultType"/>
+ *    <complexType name="ResultType">
+ *       <complexContent>
+ *          <extension base="xkms:MessageAbstractType">
+ *             <sequence>
+ *                <element ref="xkms:RequestSignatureValue" minOccurs="0"/>
+ *	       </sequence>
+ *	       <attribute name="ResultMajor" type="QName" use="required"/>
+ *	       <attribute name="ResultMinor" type="QName" use="optional"/>
+ *	       <attribute name="RequestId" type="anyURI" use="optional"/>
+ *	    </extension>
+ *	 </complexContent>
+ *    </complexType>
+ *    <!-- /ResultType -->
+ */
+static int 
+xmlSecXkmsServerCtxResultTypeNodeWrite(xmlSecXkmsServerCtxPtr ctx, xmlNodePtr node) {
+    int ret;
+    
+    xmlSecAssert2(ctx != NULL, -1);
+    xmlSecAssert2(node != NULL, -1);
+
+    /* generate and add Id attribute */
+    ret = xmlSecGenerateAndAddID(node, xmlSecAttrId, ctx->idPrefix, ctx->idLen);
+    if(ret < 0) {
+	xmlSecError(XMLSEC_ERRORS_HERE,
+		    NULL,
+		    "xmlSecGenerateAndAddID",
+		    XMLSEC_ERRORS_R_XMLSEC_FAILED,
+		    XMLSEC_ERRORS_NO_MESSAGE);
+	return(-1);  	
+    }
+
+
+    /* set Service atribute (required) */   
+    if((ctx->service == NULL) || (xmlSetProp(node, xmlSecAttrService, ctx->service) == NULL)) {
+	xmlSecError(XMLSEC_ERRORS_HERE,
+		    NULL,
+		    "xmlSetProp",
+		    XMLSEC_ERRORS_R_XML_FAILED,
+		    "name=%s,value=%s",
+		    xmlSecErrorsSafeString(xmlSecAttrService),
+		    xmlSecErrorsSafeString(ctx->service));
+	return(-1);	
+    }
+    
+
+    /* set RequestId atribute (optional) */   
+    if((ctx->id != NULL) && (xmlSetProp(node, xmlSecAttrRequestId, ctx->id) == NULL)) {
+	xmlSecError(XMLSEC_ERRORS_HERE,
+		    NULL,
+		    "xmlSetProp",
+		    XMLSEC_ERRORS_R_XML_FAILED,
+		    "name=%s,value=%s",
+		    xmlSecErrorsSafeString(xmlSecAttrRequestId),
+		    xmlSecErrorsSafeString(ctx->id));
+	return(-1);	
+    }
+    
+    
+    /* set major code (required) */ 
+    ret = xmlSecQName2IntegerAttributeWrite(gXmlSecXkmsResultMajorInfo, node,
+					     xmlSecAttrResultMajor, ctx->resultMajor);
+    if(ret < 0) {
+	xmlSecError(XMLSEC_ERRORS_HERE,
+		    NULL,
+		    "xmlSecQName2IntegerAttributeWrite",
+		    XMLSEC_ERRORS_R_XMLSEC_FAILED,
+		    "name=%s,value=%d",
+		    xmlSecErrorsSafeString(xmlSecAttrResultMajor),
+		    ctx->resultMajor);
+	return(-1);	
+    }
+
+    /* set minor code (optional) */ 
+    if(ctx->resultMinor != xmlSecXkmsResultMinorNone) {
+        ret = xmlSecQName2IntegerAttributeWrite(gXmlSecXkmsMinorErrorInfo, node,
+					     xmlSecAttrResultMinor, ctx->resultMinor);
+	if(ret < 0) {
+	    xmlSecError(XMLSEC_ERRORS_HERE,
+		        NULL,
+			"xmlSecQName2IntegerAttributeWrite",
+			XMLSEC_ERRORS_R_XMLSEC_FAILED,
+		        "name=%s,value=%d",
+			xmlSecErrorsSafeString(xmlSecAttrResultMinor),
+			ctx->resultMinor);
+	    return(-1);	
+	}
+    }
+
+    
+
+    /* <xkms:OpaqueClientData/>: An XKMS service SHOULD return the value of 
+     * the <OpaqueClientData> element unmodified in a request in a response 
+     * with status code Succes */
+    if((ctx->resultMajor == xmlSecXkmsResultMajorSuccess) && (ctx->opaqueClientDataNode != NULL)) {
+        xmlNodePtr copyNode;
+
+	copyNode = xmlDocCopyNode(ctx->opaqueClientDataNode, node->doc, 1);
+	if(copyNode == NULL) {
+	    xmlSecError(XMLSEC_ERRORS_HERE,
+		    	NULL,
+			"xmlSetProp",
+			XMLSEC_ERRORS_R_XML_FAILED,
+			"name=%s",
+			xmlSecErrorsSafeString(ctx->opaqueClientDataNode->name));
+	    return(-1);
+	}	
+	
+	if(xmlSecAddChildNode(node, copyNode) == NULL) {
+	    xmlSecError(XMLSEC_ERRORS_HERE,
+		    	NULL,
+			"xmlSecAddChildNode",
+			XMLSEC_ERRORS_R_XMLSEC_FAILED,
+			"name=%s",
+			xmlSecErrorsSafeString(copyNode->name));
+	    return(-1);
+	}
+    }
+
+    ret = xmlSecXkmsServerCtxRequestSignatureValueNodeWrite(ctx, node);
+    if(ret < 0) {
+	xmlSecError(XMLSEC_ERRORS_HERE,
+		    NULL,
+		    "xmlSecXkmsServerCtxRequestSignatureValueNodeWrite",
+		    XMLSEC_ERRORS_R_XMLSEC_FAILED,
+		    XMLSEC_ERRORS_NO_MESSAGE);
+	return(-1);  	
+    }
+
+    return(0);
+}
+
+/** 
+ * A service SHOULD include the <RequestSignatureValue> element in a response 
+ * if the following conditions are satisfied and MUST NOT include the value 
+ * otherwise:
+ *
+ *
+ *  - The <ds:Signature> element was present in the corresponding request
+ *  - The service successfully verified the <ds:Signature> element in the 
+ *  corresponding request, and
+ *  - The ResponseMechanism RequestSignatureValue was specified.
+ *    
+ */
+static int 
+xmlSecXkmsServerCtxRequestSignatureValueNodeWrite(xmlSecXkmsServerCtxPtr ctx, xmlNodePtr node) {
+    xmlSecAssert2(ctx != NULL, -1);
+    xmlSecAssert2(node != NULL, -1);
+    
+    if((ctx->responseMechanismMask & XMLSEC_XKMS_RESPONSE_MECHANISM_MASK_REQUEST_SIGNATURE_VALUE) == 0) {
+	/* The ResponseMechanism RequestSignatureValue was not specified. */
+	return(0);
+    }
+    
+    return(0);
+}
+
+
+/** 
+ *  
+ *  <xkms:UnverifiedKeyBindingType Id?>
+ *      <ds:KeyInfo>?
+ *      <xkms:KeyUsage>?
+ *      <xkms:KeyUsage>?
+ *      <xkms:KeyUsage>?
+ *      <xkms:UseKeyWith Application Identifier>*    
+ *      <xkms:ValidityInterval NotBefore NotOnOrAfter>?
+ *  
+ * XML Schema:
+ *
+ *    <!-- UnverifiedKeyBinding -->
+ *    <element name="UnverifiedKeyBinding" type="xkms:UnverifiedKeyBindingType"/>
+ *    <complexType name="UnverifiedKeyBindingType">
+ *       <complexContent>
+ *          <extension base="xkms:KeyBindingAbstractType">
+ *             <sequence>
+ *                 <element ref="xkms:ValidityInterval" minOccurs="0"/>
+ *             </sequence>
+ *          </extension>
+ *       </complexContent>
+ *    </complexType>
+ *    <!-- /UnverifiedKeyBinding -->
+ */
+static int 
+xmlSecXkmsServerCtxUnverifiedKeyBindingNodeWrite(xmlSecXkmsServerCtxPtr ctx, xmlNodePtr node, xmlSecKeyPtr key) {
+    int ret;
+
+    xmlSecAssert2(ctx != NULL, -1);
+    xmlSecAssert2(key != NULL, -1);
+    xmlSecAssert2(node != NULL, -1);
+
+    /* first write "parent" type */
+    ret = xmlSecXkmsServerCtxKeyBindingAbstractTypeNodeWrite(ctx, node, key);    
+    if(ret < 0) {
+	xmlSecError(XMLSEC_ERRORS_HERE,
+		    NULL,
+		    "xmlSecXkmsServerCtxKeyBindingAbstractTypeNodeWrite",
+		    XMLSEC_ERRORS_R_XMLSEC_FAILED,
+		    XMLSEC_ERRORS_NO_MESSAGE);
+	return(-1);  	
+    }
+    
+    /* <xkms:ValidityInterval/> node */
+    ret = xmlSecXkmsServerCtxValidityIntervalNodeWrite(ctx, node, key);    
+    if(ret < 0) {
+	xmlSecError(XMLSEC_ERRORS_HERE,
+		    NULL,
+		    "xmlSecXkmsServerCtxValidityIntervalNodeWrite",
+		    XMLSEC_ERRORS_R_XMLSEC_FAILED,
+		    XMLSEC_ERRORS_NO_MESSAGE);
+	return(-1);  	
+    }
+
+    return(0);
+}
+
+static int 
+xmlSecXkmsServerCtxValidityIntervalNodeWrite(xmlSecXkmsServerCtxPtr ctx, xmlNodePtr node, xmlSecKeyPtr key) {
+    xmlSecAssert2(ctx != NULL, -1);
+    xmlSecAssert2(key != NULL, -1);
+    xmlSecAssert2(node != NULL, -1);
+    
+    return(0);
+}
+
+/** 
+ *  <xkms:KeyBinding Id?>
+ *      <ds:KeyInfo>?
+ *      <xkms:KeyUsage>?
+ *      <xkms:KeyUsage>?
+ *      <xkms:KeyUsage>?
+ *      <xkms:UseKeyWith Application Identifier>*    
+ *      <xkms:ValidityInterval NotBefore NotOnOrAfter>?
+ *      <xkms:Status StatusValue>
+ *          (<xkms:ValidReason>?
+ *           <xkms:IndeterminateReason>?
+ *           <xkms:InvalidReason>?
+ *           )*
+ *
+ * XML Schema:
+ * 
+ *    <!-- KeyBinding -->   
+ *    <element name="KeyBinding" type="xkms:KeyBindingType"/>   
+ *    <complexType name="KeyBindingType">      
+ *        <complexContent>         
+ *            <extension base="xkms:UnverifiedKeyBindingType">            
+ *                <sequence>               
+ *                    <element ref="xkms:Status"/>
+ *                </sequence>
+ *            </extension>
+ *        </complexContent>
+ *    </complexType>
+ *    <!-- /KeyBinding -->
+ */
+static int 
+xmlSecXkmsServerCtxKeyBindingNodeWrite(xmlSecXkmsServerCtxPtr ctx, xmlNodePtr node, xmlSecKeyPtr key) {
+    int ret;
+
+    xmlSecAssert2(ctx != NULL, -1);
+    xmlSecAssert2(key != NULL, -1);
+    xmlSecAssert2(node != NULL, -1);
+
+    /* first write "parent" type */
+    ret = xmlSecXkmsServerCtxUnverifiedKeyBindingNodeWrite(ctx, node, key);    
+    if(ret < 0) {
+	xmlSecError(XMLSEC_ERRORS_HERE,
+		    NULL,
+		    "xmlSecXkmsServerCtxKeyBindingAbstractTypeNodeWrite",
+		    XMLSEC_ERRORS_R_XMLSEC_FAILED,
+		    XMLSEC_ERRORS_NO_MESSAGE);
+	return(-1);  	
+    }
+
+    /* <xkms:Status/> node */
+    ret = xmlSecXkmsServerCtxKeyBindingStatusNodeWrite(ctx, node, key);    
+    if(ret < 0) {
+	xmlSecError(XMLSEC_ERRORS_HERE,
+		    NULL,
+		    "xmlSecXkmsServerCtxKeyBindingStatusNodeWrite",
+		    XMLSEC_ERRORS_R_XMLSEC_FAILED,
+		    XMLSEC_ERRORS_NO_MESSAGE);
+	return(-1);  	
+    }
+
+    return(0);
+}
+
+/**
+ *  <xkms:Status StatusValue>
+ *      (<xkms:ValidReason>?
+ *       <xkms:IndeterminateReason>?
+ *       <xkms:InvalidReason>?
+ *      )*
+ * 
+ * XML Schema:
+ *
+ *    <!-- Status -->   
+ *    <element name="Status" type="xkms:StatusType"/>
+ *    <complexType name="StatusType">
+ *       <sequence>
+ *          <element ref="xkms:ValidReason" minOccurs="0" 
+ *                maxOccurs="unbounded"/>
+ *          <element ref="xkms:IndeterminateReason" minOccurs="0" 
+ *                maxOccurs="unbounded"/>
+ *          <element ref="xkms:InvalidReason" minOccurs="0" 
+ *                maxOccurs="unbounded"/>
+ *       </sequence>
+ *       <attribute name="StatusValue" type="xkms:KeyBindingStatus" 
+ *             use="required"/>
+ *    </complexType>
+ *    <simpleType name="KeyBindingStatus">
+ *       <restriction base="QName">
+ *          <enumeration value="xkms:Valid"/>
+ *          <enumeration value="xkms:Invalid"/>
+ *          <enumeration value="xkms:Indeterminate"/>
+ *       </restriction>
+ *    </simpleType>
+ *    <!-- /Status -->
+ */
+static int 
+xmlSecXkmsServerCtxKeyBindingStatusNodeWrite(xmlSecXkmsServerCtxPtr ctx, xmlNodePtr node, xmlSecKeyPtr key) {
+    xmlNodePtr cur;
+    int ret;
+
+    xmlSecAssert2(ctx != NULL, -1);
+    xmlSecAssert2(key != NULL, -1);
+    xmlSecAssert2(node != NULL, -1);
+
+    cur = xmlSecAddChild(node, xmlSecNodeStatus, xmlSecXkmsNs);
+    if(cur == NULL) {
+	xmlSecError(XMLSEC_ERRORS_HERE,
+		    NULL,
+		    "xmlSecAddChild",
+		    XMLSEC_ERRORS_R_XMLSEC_FAILED,
+		    "node=%s",
+		    xmlSecErrorsSafeString(xmlSecNodeStatus));
+	return(-1);  	
+    }
+
+    /* if we are here then the key was validated */
+    ret = xmlSecQName2IntegerAttributeWrite(gXmlSecXkmsKeyBindingStatusInfo, cur, 
+		    xmlSecAttrStatusValue, xmlSecXkmsKeyBindingStatusValid);
+    if(ret < 0) {
+	xmlSecError(XMLSEC_ERRORS_HERE,
+		    NULL,
+		    "xmlSecQName2IntegerAttributeWrite",
+		    XMLSEC_ERRORS_R_XMLSEC_FAILED,
+		    "name=%s",
+		    xmlSecErrorsSafeString(xmlSecAttrStatusValue));
+	return(-1);	
+    }
+    
+    return(0);
+}
+
+/************************************************************************
+ *
+ * xmlSecXkmsServerCtx list
+ *
+ ************************************************************************/ 
+static xmlSecPtrListKlass xmlSecXkmsServerCtxPtrListKlass = {
+    BAD_CAST "xkms-server-ctx-list",
+    NULL, 								/* xmlSecPtrDuplicateItemMethod duplicateItem; */
+    (xmlSecPtrDestroyItemMethod)xmlSecXkmsServerCtxDestroy,	        /* xmlSecPtrDestroyItemMethod destroyItem; */
+    (xmlSecPtrDebugDumpItemMethod)xmlSecXkmsServerCtxDebugDump,	        /* xmlSecPtrDebugDumpItemMethod debugDumpItem; */
+    (xmlSecPtrDebugDumpItemMethod)xmlSecXkmsServerCtxDebugXmlDump,	/* xmlSecPtrDebugDumpItemMethod debugXmlDumpItem; */
+};
+EXPORT_C
+
+xmlSecPtrListId	
+xmlSecXkmsServerCtxPtrListGetKlass(void) {
+    return(&xmlSecXkmsServerCtxPtrListKlass);
+}
+
+
+/**************************************************************************
+ *
+ * Global xmlSecXkmsRespondWithIds list functions
+ *
+ *************************************************************************/
+static xmlSecPtrList xmlSecAllXkmsRespondWithIds;
+
+
+/** 
+ * xmlSecXkmsRespondWithIdsGet:
+ *
+ * Gets global registered RespondWith klasses list.
+ * 
+ * Returns the pointer to list of all registered RespondWith klasses.
+ */
+EXPORT_C
+xmlSecPtrListPtr
+xmlSecXkmsRespondWithIdsGet(void) {
+    return(&xmlSecAllXkmsRespondWithIds);
+}
+
+/** 
+ * xmlSecXkmsRespondWithIdsInit:
+ *
+ * Initializes the RespondWith klasses. This function is called from the 
+ * #xmlSecInit function and the application should not call it directly.
+ *
+ * Returns 0 on success or a negative value if an error occurs.
+ */
+EXPORT_C
+int 
+xmlSecXkmsRespondWithIdsInit(void) {
+    int ret;
+    
+    ret = xmlSecPtrListInitialize(xmlSecXkmsRespondWithIdsGet(), xmlSecXkmsRespondWithIdListId);
+    if(ret < 0) {
+	xmlSecError(XMLSEC_ERRORS_HERE,
+		    NULL,
+		    "xmlSecPtrListPtrInitialize",
+		    XMLSEC_ERRORS_R_XMLSEC_FAILED,
+		    "xmlSecXkmsRespondWithIdListId");
+        return(-1);
+    }
+    
+    ret = xmlSecXkmsRespondWithIdsRegisterDefault();
+    if(ret < 0) {
+	xmlSecError(XMLSEC_ERRORS_HERE,
+		    NULL,
+		    "xmlSecXkmsRespondWithIdsRegisterDefault",
+		    XMLSEC_ERRORS_R_XMLSEC_FAILED,
+		    XMLSEC_ERRORS_NO_MESSAGE);
+        return(-1);
+    }
+    
+    return(0);
+}
+
+/**
+ * xmlSecXkmsRespondWithIdsShutdown:
+ * 
+ * Shuts down the keys data klasses. This function is called from the 
+ * #xmlSecShutdown function and the application should not call it directly.
+ */
+EXPORT_C
+void
+xmlSecXkmsRespondWithIdsShutdown(void) {
+    xmlSecPtrListFinalize(xmlSecXkmsRespondWithIdsGet());
+}
+
+/** 
+ * xmlSecXkmsRespondWithIdsRegister:
+ * @id:		the RespondWith klass.
+ *
+ * Registers @id in the global list of RespondWith klasses.
+ *
+ * Returns 0 on success or a negative value if an error occurs.
+ */
+EXPORT_C
+int 
+xmlSecXkmsRespondWithIdsRegister(xmlSecXkmsRespondWithId id) {
+    int ret;
+        
+    xmlSecAssert2(id != xmlSecXkmsRespondWithIdUnknown, -1);
+    
+    ret = xmlSecPtrListAdd(xmlSecXkmsRespondWithIdsGet(), (xmlSecPtr)id);
+    if(ret < 0) {
+	xmlSecError(XMLSEC_ERRORS_HERE,
+		    NULL,
+		    "xmlSecPtrListAdd",
+		    XMLSEC_ERRORS_R_XMLSEC_FAILED,
+		    "RespondWith=%s",
+		    xmlSecErrorsSafeString(xmlSecXkmsRespondWithKlassGetName(id)));
+        return(-1);
+    }
+    
+    return(0);    
+}
+
+/**
+ * xmlSecXkmsRespondWithIdsRegisterDefault:
+ *
+ * Registers default (implemented by XML Security Library)
+ * RespondWith klasses: KeyName, KeyValue,...
+ *
+ * Returns 0 on success or a negative value if an error occurs.
+ */
+EXPORT_C
+int 
+xmlSecXkmsRespondWithIdsRegisterDefault(void) {
+    if(xmlSecXkmsRespondWithIdsRegister(xmlSecXkmsRespondWithKeyNameId) < 0) {
+	xmlSecError(XMLSEC_ERRORS_HERE,
+		    NULL,
+		    "xmlSecXkmsRespondWithIdsRegister",	    
+		    XMLSEC_ERRORS_R_XMLSEC_FAILED,
+		    "name=%s",
+		    xmlSecErrorsSafeString(xmlSecXkmsRespondWithKlassGetName(xmlSecXkmsRespondWithKeyNameId)));
+	return(-1);
+    }
+
+    if(xmlSecXkmsRespondWithIdsRegister(xmlSecXkmsRespondWithKeyValueId) < 0) {
+	xmlSecError(XMLSEC_ERRORS_HERE,
+		    NULL,
+		    "xmlSecXkmsRespondWithIdsRegister",	    
+		    XMLSEC_ERRORS_R_XMLSEC_FAILED,
+		    "name=%s",
+		    xmlSecErrorsSafeString(xmlSecXkmsRespondWithKlassGetName(xmlSecXkmsRespondWithKeyValueId)));
+	return(-1);
+    }
+
+    if(xmlSecXkmsRespondWithIdsRegister(xmlSecXkmsRespondWithPrivateKeyId) < 0) {
+	xmlSecError(XMLSEC_ERRORS_HERE,
+		    NULL,
+		    "xmlSecXkmsRespondWithIdsRegister",	    
+		    XMLSEC_ERRORS_R_XMLSEC_FAILED,
+		    "name=%s",
+		    xmlSecErrorsSafeString(xmlSecXkmsRespondWithKlassGetName(xmlSecXkmsRespondWithPrivateKeyId)));
+	return(-1);
+    }
+
+    if(xmlSecXkmsRespondWithIdsRegister(xmlSecXkmsRespondWithRetrievalMethodId) < 0) {
+	xmlSecError(XMLSEC_ERRORS_HERE,
+		    NULL,
+		    "xmlSecXkmsRespondWithIdsRegister",	    
+		    XMLSEC_ERRORS_R_XMLSEC_FAILED,
+		    "name=%s",
+		    xmlSecErrorsSafeString(xmlSecXkmsRespondWithKlassGetName(xmlSecXkmsRespondWithRetrievalMethodId)));
+	return(-1);
+    }
+
+    if(xmlSecXkmsRespondWithIdsRegister(xmlSecXkmsRespondWithX509CertId) < 0) {
+	xmlSecError(XMLSEC_ERRORS_HERE,
+		    NULL,
+		    "xmlSecXkmsRespondWithIdsRegister",	    
+		    XMLSEC_ERRORS_R_XMLSEC_FAILED,
+		    "name=%s",
+		    xmlSecErrorsSafeString(xmlSecXkmsRespondWithKlassGetName(xmlSecXkmsRespondWithX509CertId)));
+	return(-1);
+    }
+
+    if(xmlSecXkmsRespondWithIdsRegister(xmlSecXkmsRespondWithX509ChainId) < 0) {
+	xmlSecError(XMLSEC_ERRORS_HERE,
+		    NULL,
+		    "xmlSecXkmsRespondWithIdsRegister",	    
+		    XMLSEC_ERRORS_R_XMLSEC_FAILED,
+		    "name=%s",
+		    xmlSecErrorsSafeString(xmlSecXkmsRespondWithKlassGetName(xmlSecXkmsRespondWithX509ChainId)));
+	return(-1);
+    }
+
+    if(xmlSecXkmsRespondWithIdsRegister(xmlSecXkmsRespondWithX509CRLId) < 0) {
+	xmlSecError(XMLSEC_ERRORS_HERE,
+		    NULL,
+		    "xmlSecXkmsRespondWithIdsRegister",	    
+		    XMLSEC_ERRORS_R_XMLSEC_FAILED,
+		    "name=%s",
+		    xmlSecErrorsSafeString(xmlSecXkmsRespondWithKlassGetName(xmlSecXkmsRespondWithX509CRLId)));
+	return(-1);
+    }
+
+    /*
+    if(xmlSecXkmsRespondWithIdsRegister(xmlSecXkmsRespondWithPGPId) < 0) {
+	xmlSecError(XMLSEC_ERRORS_HERE,
+		    NULL,
+		    "xmlSecXkmsRespondWithIdsRegister",	    
+		    XMLSEC_ERRORS_R_XMLSEC_FAILED,
+		    "name=%s",
+		    xmlSecErrorsSafeString(xmlSecXkmsRespondWithKlassGetName(xmlSecXkmsRespondWithPGPId)));
+	return(-1);
+    }
+
+    if(xmlSecXkmsRespondWithIdsRegister(xmlSecXkmsRespondWithSPKIId) < 0) {
+	xmlSecError(XMLSEC_ERRORS_HERE,
+		    NULL,
+		    "xmlSecXkmsRespondWithIdsRegister",	    
+		    XMLSEC_ERRORS_R_XMLSEC_FAILED,
+		    "name=%s",
+		    xmlSecErrorsSafeString(xmlSecXkmsRespondWithKlassGetName(xmlSecXkmsRespondWithSPKIId)));
+	return(-1);
+    }
+    */
+    return(0);
+}
+
+
+/************************************************************************
+ *
+ * XKMS RespondWith Klass
+ *
+ ************************************************************************/ 
+/**
+ * xmlSecXkmsRespondWithNodeRead:
+ * @id:		the RespondWith class.
+ * @ctx:	the XKMS request processing context.
+ * @node:	the pointer to <xkms:RespondWith/> node.
+ *
+ * Reads the content of the <xkms:RespondWith/> @node.
+ *
+ * Returns 0 on success or a negative value if an error occurs.
+ */
+EXPORT_C
+int  
+xmlSecXkmsRespondWithNodeRead(xmlSecXkmsRespondWithId id, xmlSecXkmsServerCtxPtr ctx,
+			      xmlNodePtr node) {
+    xmlSecAssert2(id != xmlSecXkmsRespondWithIdUnknown, -1);
+    xmlSecAssert2(ctx != NULL, -1);
+    xmlSecAssert2(node != NULL, -1);
+
+    if(id->readNode != NULL) {
+	return((id->readNode)(id, ctx, node));
+    }
+    return(0);
+}
+
+/**
+ * xmlSecXkmsRespondWithNodeWrite:
+ * @id:		the RespondWith class.
+ * @ctx:	the XKMS request processing context.
+ * @node:	the pointer to <xkms:RespondWith/> node.
+ *
+ * Writes the content of the <xkms:RespondWith/> @node.
+ *
+ * Returns 0 on success or a negative value if an error occurs.
+ */
+EXPORT_C
+int 
+xmlSecXkmsRespondWithNodeWrite(xmlSecXkmsRespondWithId id, xmlSecXkmsServerCtxPtr ctx,
+			     xmlNodePtr node) {
+    xmlSecAssert2(id != xmlSecXkmsRespondWithIdUnknown, -1);
+    xmlSecAssert2(ctx != NULL, -1);
+    xmlSecAssert2(node != NULL, -1);
+
+    if(id->writeNode != NULL) {
+	return((id->writeNode)(id, ctx, node));
+    }
+    return(0);
+}
+
+/**
+ * xmlSecXkmsRespondWithDebugDump:
+ * @id:		the RespondWith class.
+ * @output:	the output file.
+ *
+ * Writes debug information about @id into the @output.
+ */
+EXPORT_C
+void 
+xmlSecXkmsRespondWithDebugDump(xmlSecXkmsRespondWithId id, FILE* output) {
+    xmlSecAssert(id != xmlSecXkmsRespondWithIdUnknown);
+    xmlSecAssert(output != NULL);
+
+    fprintf(output, "=== RespondWith: \"%s\" (href=\"%s\")\n", 
+        xmlSecErrorsSafeString(id->valueName),
+        xmlSecErrorsSafeString(id->valueNs));
+}
+
+/**
+ * xmlSecXkmsRespondWithDebugXmlDump:
+ * @id:		the RespondWith class.
+ * @output:	the output file.
+ *
+ * Writes debug information about @id into the @output in XML format.
+ */
+EXPORT_C
+void 
+xmlSecXkmsRespondWithDebugXmlDump(xmlSecXkmsRespondWithId id, FILE* output) {
+    xmlSecAssert(id != xmlSecXkmsRespondWithIdUnknown);
+    xmlSecAssert(output != NULL);
+
+    fprintf(output, "<RespondWith href=\"%s\">%s</RespondWith>\n", 
+        xmlSecErrorsSafeString(id->valueNs),
+        xmlSecErrorsSafeString(id->valueName));
+}
+EXPORT_C
+
+int 
+xmlSecXkmsRespondWithDefaultNodeRead(xmlSecXkmsRespondWithId id, xmlSecXkmsServerCtxPtr ctx,
+			    xmlNodePtr node) {
+    int ret;
+
+    xmlSecAssert2(id != xmlSecXkmsRespondWithIdUnknown, -1);
+    xmlSecAssert2(ctx != NULL, -1);
+    xmlSecAssert2(node != NULL, -1);
+
+    ret = xmlSecXkmsRespondWithIdListFind(&(ctx->respWithList), id);
+    if(ret < 0) {
+	xmlSecError(XMLSEC_ERRORS_HERE,
+		    xmlSecErrorsSafeString(xmlSecXkmsRespondWithKlassGetName(id)),
+		    "xmlSecXkmsRespondWithIdListFind",
+		    XMLSEC_ERRORS_R_XMLSEC_FAILED,
+		    XMLSEC_ERRORS_NO_MESSAGE);
+	return(-1);  	
+    } else if(ret > 0) {
+	/* do nothing, we already have it in the list */
+	return(0);
+    }    
+    
+    ret = xmlSecPtrListAdd(&(ctx->respWithList), id);
+    if(ret < 0) {
+	xmlSecError(XMLSEC_ERRORS_HERE,
+		    xmlSecErrorsSafeString(xmlSecXkmsRespondWithKlassGetName(id)),
+		    "xmlSecPtrListAdd",
+		    XMLSEC_ERRORS_R_XMLSEC_FAILED,
+		    XMLSEC_ERRORS_NO_MESSAGE);
+	return(-1);  	
+    }
+
+    return(0);
+}
+EXPORT_C
+
+int  
+xmlSecXkmsRespondWithDefaultNodeWrite(xmlSecXkmsRespondWithId id, xmlSecXkmsServerCtxPtr ctx,
+			    xmlNodePtr node) {
+    xmlNodePtr cur;
+
+    xmlSecAssert2(id != xmlSecXkmsRespondWithIdUnknown, -1);
+    xmlSecAssert2(id->nodeName != NULL, -1);
+    xmlSecAssert2(ctx != NULL, -1);
+    xmlSecAssert2(node != NULL, -1);
+
+    cur = xmlSecAddChild(node, id->nodeName, id->nodeNs);
+    if(cur == NULL) {
+	xmlSecError(XMLSEC_ERRORS_HERE,
+		    xmlSecErrorsSafeString(xmlSecXkmsRespondWithKlassGetName(id)),
+		    "xmlSecAddChild",
+		    XMLSEC_ERRORS_R_XMLSEC_FAILED,
+		    "node=%s",
+		    xmlSecErrorsSafeString(id->nodeName));
+	return(-1);  	
+    }
+
+    return(0);
+}
+
+/************************************************************************
+ *
+ * XKMS RespondWith Klass List
+ *
+ ************************************************************************/ 
+static xmlSecPtrListKlass xmlSecXkmsRespondWithIdListKlass = {
+    BAD_CAST "respond-with-ids-list",
+    NULL, 								/* xmlSecPtrDuplicateItemMethod duplicateItem; */
+    NULL,								/* xmlSecPtrDestroyItemMethod destroyItem; */
+    (xmlSecPtrDebugDumpItemMethod)xmlSecXkmsRespondWithDebugDump,	/* xmlSecPtrDebugDumpItemMethod debugDumpItem; */
+    (xmlSecPtrDebugDumpItemMethod)xmlSecXkmsRespondWithDebugXmlDump,	/* xmlSecPtrDebugDumpItemMethod debugXmlDumpItem; */
+};
+EXPORT_C
+
+xmlSecPtrListId	
+xmlSecXkmsRespondWithIdListGetKlass(void) {
+    return(&xmlSecXkmsRespondWithIdListKlass);
+}
+EXPORT_C
+
+int 
+xmlSecXkmsRespondWithIdListFind(xmlSecPtrListPtr list, xmlSecXkmsRespondWithId id) {
+    xmlSecSize i, size;
+    
+    xmlSecAssert2(xmlSecPtrListCheckId(list, xmlSecXkmsRespondWithIdListId), -1);
+    xmlSecAssert2(id != xmlSecXkmsRespondWithIdUnknown, -1);
+    
+    size = xmlSecPtrListGetSize(list);
+    for(i = 0; i < size; ++i) {
+	if((xmlSecXkmsRespondWithId)xmlSecPtrListGetItem(list, i) == id) {
+	    return(1);
+	}
+    }
+    return(0);
+}
+EXPORT_C
+
+xmlSecXkmsRespondWithId 
+xmlSecXkmsRespondWithIdListFindByNodeValue(xmlSecPtrListPtr list, xmlNodePtr node) {
+    xmlSecXkmsRespondWithId result = xmlSecXkmsRespondWithIdUnknown;
+    xmlSecXkmsRespondWithId id;
+    xmlChar* content;
+    xmlChar* qnameLocalPart = NULL;
+    xmlChar* qnamePrefix = NULL;
+    const xmlChar* qnameHref;
+    xmlNsPtr ns;
+    xmlSecSize i, size;
+    
+    xmlSecAssert2(xmlSecPtrListCheckId(list, xmlSecXkmsRespondWithIdListId), xmlSecXkmsRespondWithIdUnknown);
+    xmlSecAssert2(node != NULL, xmlSecXkmsRespondWithIdUnknown);
+
+    content = xmlNodeGetContent(node);
+    if(content == NULL) {
+	xmlSecError(XMLSEC_ERRORS_HERE,
+                    NULL,
+		    "xmlNodeGetContent",
+		    XMLSEC_ERRORS_R_XML_FAILED,
+		    "node=%s",
+		    xmlSecErrorsSafeString(node->name));
+	return(xmlSecXkmsRespondWithIdUnknown);  	
+    }
+
+    qnameLocalPart = (xmlChar*)xmlStrchr(content, ':');
+    if(qnameLocalPart != NULL) {
+        qnamePrefix = content;
+        *(qnameLocalPart++) = '\0';
+    } else {
+        qnamePrefix = NULL;
+        qnameLocalPart = content;
+    }
+    
+    /* search namespace href */
+    ns = xmlSearchNs(node->doc, node, qnamePrefix);
+    if((ns == NULL) && (qnamePrefix != NULL)) {
+	xmlSecError(XMLSEC_ERRORS_HERE,
+		    NULL,
+		    "xmlSearchNs",
+	    	    XMLSEC_ERRORS_R_XML_FAILED,
+		    "node=%s,qnamePrefix=%s",
+		    xmlSecErrorsSafeString(node->name),
+                    xmlSecErrorsSafeString(qnamePrefix));
+        xmlFree(content);
+	return(xmlSecXkmsRespondWithIdUnknown);	
+    }
+    qnameHref = (ns != NULL) ? ns->href : BAD_CAST NULL;
+
+    size = xmlSecPtrListGetSize(list);
+    for(i = 0; i < size; ++i) {
+	id = (xmlSecXkmsRespondWithId)xmlSecPtrListGetItem(list, i);
+	if((id !=  xmlSecXkmsRespondWithIdUnknown) && 
+                xmlStrEqual(id->valueName, qnameLocalPart) &&
+                xmlStrEqual(id->valueNs, qnameHref)) {
+	    result = id;
+            break;
+	}
+    }
+    
+    xmlFree(content);
+    return(result);    
+}
+EXPORT_C
+
+int 
+xmlSecXkmsRespondWithIdListWrite(xmlSecPtrListPtr list, xmlSecXkmsServerCtxPtr ctx, xmlNodePtr node) {
+    xmlSecXkmsRespondWithId id;
+    xmlSecSize i, size;
+    int ret;
+
+    xmlSecAssert2(xmlSecPtrListCheckId(list, xmlSecXkmsRespondWithIdListId), -1);
+    xmlSecAssert2(ctx != NULL, -1);
+    xmlSecAssert2(node != NULL, -1);
+
+    size = xmlSecPtrListGetSize(list);
+    for(i = 0; i < size; ++i) {
+	id = (xmlSecXkmsRespondWithId)xmlSecPtrListGetItem(list, i);
+	if(id !=  xmlSecXkmsRespondWithIdUnknown) {
+	    ret = xmlSecXkmsRespondWithNodeWrite(id, ctx, node);
+	    if(ret < 0) {
+		xmlSecError(XMLSEC_ERRORS_HERE,
+			    xmlSecErrorsSafeString(xmlSecXkmsRespondWithKlassGetName(id)),
+			    "xmlSecXkmsRespondWithNodeWrite",
+		    	    XMLSEC_ERRORS_R_XMLSEC_FAILED,
+			    XMLSEC_ERRORS_NO_MESSAGE);
+		return(-1);
+	    }
+	}
+    }
+
+    return(0);
+}
+
+/******************************************************************** 
+ *
+ * XML Sec Library RespondWith Ids
+ *
+ *******************************************************************/
+static xmlSecXkmsRespondWithKlass xmlSecXkmsRespondWithKeyNameKlass = {
+    xmlSecRespondWithKeyName,			/* const xmlChar* valueName; */
+    xmlSecXkmsNs,			        /* const xmlChar* valueNs; */
+    xmlSecNodeKeyName,				/* const xmlChar* nodeName; */
+    xmlSecDSigNs,				/* const xmlChar* nodeNs; */
+    xmlSecXkmsRespondWithDefaultNodeRead,	/* xmlSecXkmsRespondWithNodeReadMethod readNode; */
+    xmlSecXkmsRespondWithDefaultNodeWrite,	/* xmlSecXkmsRespondWithNodeWriteMethod writeNode; */
+    NULL,                                       /* void* reserved1; */
+    NULL                                        /* void* reserved2; */
+};
+
+/**
+ * xmlSecXkmsRespondWithKeyNameGetKlass:
+ *
+ * The respond with KeyName klass.
+ *
+ * Returns respond with KeyName klass.
+ */
+EXPORT_C 
+xmlSecXkmsRespondWithId	
+xmlSecXkmsRespondWithKeyNameGetKlass(void) {
+    return(&xmlSecXkmsRespondWithKeyNameKlass);
+}
+
+
+
+static  int  		xmlSecXkmsRespondWithKeyValueNodeRead	(xmlSecXkmsRespondWithId id,
+								 xmlSecXkmsServerCtxPtr ctx,
+								 xmlNodePtr node);
+static xmlSecXkmsRespondWithKlass xmlSecXkmsRespondWithKeyValueKlass = {
+    xmlSecRespondWithKeyValue,			/* const xmlChar* valueName; */
+    xmlSecXkmsNs,			        /* const xmlChar* valueNs; */
+    xmlSecNodeKeyValue,				/* const xmlChar* nodeName; */
+    xmlSecDSigNs,				/* const xmlChar* nodeNs; */
+    xmlSecXkmsRespondWithKeyValueNodeRead,	/* xmlSecXkmsRespondWithNodeReadMethod readNode; */
+    xmlSecXkmsRespondWithDefaultNodeWrite,	/* xmlSecXkmsRespondWithNodeWriteMethod writeNode; */
+    NULL,                                       /* void* reserved1; */
+    NULL                                        /* void* reserved2; */
+};
+
+/**
+ * xmlSecXkmsRespondWithKeyValueGetKlass:
+ *
+ * The respond with KeyValue klass.
+ *
+ * Returns respond with KeyValue klass.
+ */
+EXPORT_C 
+xmlSecXkmsRespondWithId	
+xmlSecXkmsRespondWithKeyValueGetKlass(void) {
+    return(&xmlSecXkmsRespondWithKeyValueKlass);
+}
+
+static  int  
+xmlSecXkmsRespondWithKeyValueNodeRead(xmlSecXkmsRespondWithId id, xmlSecXkmsServerCtxPtr ctx,
+				      xmlNodePtr node) {
+    int ret;
+
+    xmlSecAssert2(id == xmlSecXkmsRespondWithKeyValueId, -1);
+    xmlSecAssert2(ctx != NULL, -1);
+    xmlSecAssert2(node != NULL, -1);
+
+    /* do usual stuff */
+    ret = xmlSecXkmsRespondWithDefaultNodeRead(id, ctx, node);
+    if(ret < 0) {
+	xmlSecError(XMLSEC_ERRORS_HERE,
+		    xmlSecErrorsSafeString(xmlSecXkmsRespondWithKlassGetName(id)),
+		    "xmlSecXkmsRespondWithDefaultNodeRead",
+		    XMLSEC_ERRORS_R_XMLSEC_FAILED,
+		    XMLSEC_ERRORS_NO_MESSAGE);
+	return(-1);  	
+    }
+    
+    /* and now set some parameters in the ctx to look for a public or private 
+     * key and to write a public key
+     */
+    ctx->keyInfoReadCtx.keyReq.keyType  |= (xmlSecKeyDataTypePublic | xmlSecKeyDataTypePrivate);
+    ctx->keyInfoWriteCtx.keyReq.keyType |= xmlSecKeyDataTypePublic;
+
+    return(0);
+}
+
+static  int  		xmlSecXkmsRespondWithPrivateKeyNodeRead	(xmlSecXkmsRespondWithId id,
+								 xmlSecXkmsServerCtxPtr ctx,
+								 xmlNodePtr node);
+static xmlSecXkmsRespondWithKlass xmlSecXkmsRespondWithPrivateKeyKlass = {
+    xmlSecRespondWithPrivateKey,		/* const xmlChar* valueName; */
+    xmlSecXkmsNs,			        /* const xmlChar* valueNs; */
+    xmlSecNodeKeyValue,				/* const xmlChar* nodeName; */
+    xmlSecDSigNs,				/* const xmlChar* nodeNs; */
+    xmlSecXkmsRespondWithPrivateKeyNodeRead,	/* xmlSecXkmsRespondWithNodeReadMethod readNode; */
+    xmlSecXkmsRespondWithDefaultNodeWrite,	/* xmlSecXkmsRespondWithNodeWriteMethod writeNode; */
+    NULL,                                       /* void* reserved1; */
+    NULL                                        /* void* reserved2; */
+};
+
+/**
+ * xmlSecXkmsRespondWithPrivateKeyGetKlass:
+ *
+ * The respond with PrivateKey klass.
+ *
+ * Returns respond with PrivateKey klass.
+ */
+EXPORT_C 
+xmlSecXkmsRespondWithId	
+xmlSecXkmsRespondWithPrivateKeyGetKlass(void) {
+    return(&xmlSecXkmsRespondWithPrivateKeyKlass);
+}
+
+static  int  
+xmlSecXkmsRespondWithPrivateKeyNodeRead(xmlSecXkmsRespondWithId id, xmlSecXkmsServerCtxPtr ctx,
+				      xmlNodePtr node) {
+    int ret;
+
+    xmlSecAssert2(id == xmlSecXkmsRespondWithPrivateKeyId, -1);
+    xmlSecAssert2(ctx != NULL, -1);
+    xmlSecAssert2(node != NULL, -1);
+
+    /* do usual stuff */
+    ret = xmlSecXkmsRespondWithDefaultNodeRead(id, ctx, node);
+    if(ret < 0) {
+	xmlSecError(XMLSEC_ERRORS_HERE,
+		    xmlSecErrorsSafeString(xmlSecXkmsRespondWithKlassGetName(id)),
+		    "xmlSecXkmsRespondWithDefaultNodeRead",
+		    XMLSEC_ERRORS_R_XMLSEC_FAILED,
+		    XMLSEC_ERRORS_NO_MESSAGE);
+	return(-1);  	
+    }
+    
+    /* and now set some parameters in the ctx to look for a private 
+     * key and to write a private key
+     */
+    ctx->keyInfoReadCtx.keyReq.keyType  |= xmlSecKeyDataTypePrivate;
+    ctx->keyInfoWriteCtx.keyReq.keyType |= xmlSecKeyDataTypePrivate;
+
+    return(0);
+}
+
+static xmlSecXkmsRespondWithKlass xmlSecXkmsRespondWithRetrievalMethodKlass = {
+    xmlSecRespondWithRetrievalMethod,		/* const xmlChar* valueName; */
+    xmlSecXkmsNs,			        /* const xmlChar* valueNs; */
+    xmlSecNodeRetrievalMethod,			/* const xmlChar* nodeName; */
+    xmlSecDSigNs,				/* const xmlChar* nodeNs; */
+    xmlSecXkmsRespondWithDefaultNodeRead,	/* xmlSecXkmsRespondWithNodeReadMethod readNode; */
+    xmlSecXkmsRespondWithDefaultNodeWrite,	/* xmlSecXkmsRespondWithNodeWriteMethod writeNode; */
+    NULL,                                       /* void* reserved1; */
+    NULL                                        /* void* reserved2; */
+};
+
+/**
+ * xmlSecXkmsRespondWithRetrievalMethodGetKlass:
+ *
+ * The respond with RetrievalMethod klass.
+ *
+ * Returns respond with RetrievalMethod klass.
+ */
+EXPORT_C 
+xmlSecXkmsRespondWithId	
+xmlSecXkmsRespondWithRetrievalMethodGetKlass(void) {
+    return(&xmlSecXkmsRespondWithRetrievalMethodKlass);
+}
+
+
+
+static  int  		xmlSecXkmsRespondWithX509CertNodeRead	(xmlSecXkmsRespondWithId id,
+								 xmlSecXkmsServerCtxPtr ctx,
+								 xmlNodePtr node);
+static xmlSecXkmsRespondWithKlass xmlSecXkmsRespondWithX509CertKlass = {
+    xmlSecRespondWithX509Cert,			/* const xmlChar* valueName; */
+    xmlSecXkmsNs,			        /* const xmlChar* valueNs; */
+    xmlSecNodeX509Data,				/* const xmlChar* nodeName; */
+    xmlSecDSigNs,				/* const xmlChar* nodeNs; */
+    xmlSecXkmsRespondWithX509CertNodeRead,	/* xmlSecXkmsRespondWithNodeReadMethod readNode; */
+    xmlSecXkmsRespondWithDefaultNodeWrite,	/* xmlSecXkmsRespondWithNodeWriteMethod writeNode; */
+    NULL,                                       /* void* reserved1; */
+    NULL                                        /* void* reserved2; */
+};
+
+/**
+ * xmlSecXkmsRespondWithX509CertGetKlass:
+ *
+ * The respond with X509Cert klass.
+ *
+ * Returns respond with X509Cert klass.
+ */
+EXPORT_C 
+xmlSecXkmsRespondWithId	
+xmlSecXkmsRespondWithX509CertGetKlass(void) {
+    return(&xmlSecXkmsRespondWithX509CertKlass);
+}
+
+static  int  
+xmlSecXkmsRespondWithX509CertNodeRead(xmlSecXkmsRespondWithId id, xmlSecXkmsServerCtxPtr ctx,
+				      xmlNodePtr node) {
+    int ret;
+
+    xmlSecAssert2(id == xmlSecXkmsRespondWithX509CertId, -1);
+    xmlSecAssert2(ctx != NULL, -1);
+    xmlSecAssert2(node != NULL, -1);
+
+    /* do usual stuff */
+    ret = xmlSecXkmsRespondWithDefaultNodeRead(id, ctx, node);
+    if(ret < 0) {
+	xmlSecError(XMLSEC_ERRORS_HERE,
+		    xmlSecErrorsSafeString(xmlSecXkmsRespondWithKlassGetName(id)),
+		    "xmlSecXkmsRespondWithDefaultNodeRead",
+		    XMLSEC_ERRORS_R_XMLSEC_FAILED,
+		    XMLSEC_ERRORS_NO_MESSAGE);
+	return(-1);  	
+    }
+    
+    return(0);
+}
+
+static  int  		xmlSecXkmsRespondWithX509ChainNodeRead	(xmlSecXkmsRespondWithId id,
+								 xmlSecXkmsServerCtxPtr ctx,
+								 xmlNodePtr node);
+static xmlSecXkmsRespondWithKlass xmlSecXkmsRespondWithX509ChainKlass = {
+    xmlSecRespondWithX509Chain,			/* const xmlChar* valueName; */
+    xmlSecXkmsNs,			        /* const xmlChar* valueNs; */
+    xmlSecNodeX509Data,				/* const xmlChar* nodeName; */
+    xmlSecDSigNs,				/* const xmlChar* nodeNs; */
+    xmlSecXkmsRespondWithX509ChainNodeRead,	/* xmlSecXkmsRespondWithNodeReadMethod readNode; */
+    xmlSecXkmsRespondWithDefaultNodeWrite,	/* xmlSecXkmsRespondWithNodeWriteMethod writeNode; */
+    NULL,                                       /* void* reserved1; */
+    NULL                                        /* void* reserved2; */
+};
+
+/**
+ * xmlSecXkmsRespondWithX509ChainGetKlass:
+ *
+ * The respond with X509Chain klass.
+ *
+ * Returns respond with X509Chain klass.
+ */
+EXPORT_C 
+xmlSecXkmsRespondWithId	
+xmlSecXkmsRespondWithX509ChainGetKlass(void) {
+    return(&xmlSecXkmsRespondWithX509ChainKlass);
+}
+
+static  int  
+xmlSecXkmsRespondWithX509ChainNodeRead(xmlSecXkmsRespondWithId id, xmlSecXkmsServerCtxPtr ctx,
+				      xmlNodePtr node) {
+    int ret;
+
+    xmlSecAssert2(id == xmlSecXkmsRespondWithX509ChainId, -1);
+    xmlSecAssert2(ctx != NULL, -1);
+    xmlSecAssert2(node != NULL, -1);
+
+    /* do usual stuff */
+    ret = xmlSecXkmsRespondWithDefaultNodeRead(id, ctx, node);
+    if(ret < 0) {
+	xmlSecError(XMLSEC_ERRORS_HERE,
+		    xmlSecErrorsSafeString(xmlSecXkmsRespondWithKlassGetName(id)),
+		    "xmlSecXkmsRespondWithDefaultNodeRead",
+		    XMLSEC_ERRORS_R_XMLSEC_FAILED,
+		    XMLSEC_ERRORS_NO_MESSAGE);
+	return(-1);  	
+    }
+    
+    return(0);
+}
+
+static  int  		xmlSecXkmsRespondWithX509CRLNodeRead	(xmlSecXkmsRespondWithId id,
+								 xmlSecXkmsServerCtxPtr ctx,
+								 xmlNodePtr node);
+static xmlSecXkmsRespondWithKlass xmlSecXkmsRespondWithX509CRLKlass = {
+    xmlSecRespondWithX509CRL,			/* const xmlChar* valueName; */
+    xmlSecXkmsNs,			        /* const xmlChar* valueNs; */
+    xmlSecNodeX509Data,				/* const xmlChar* nodeName; */
+    xmlSecDSigNs,				/* const xmlChar* nodeNs; */
+    xmlSecXkmsRespondWithX509CRLNodeRead,	/* xmlSecXkmsRespondWithNodeReadMethod readNode; */
+    xmlSecXkmsRespondWithDefaultNodeWrite,	/* xmlSecXkmsRespondWithNodeWriteMethod writeNode; */
+    NULL,                                       /* void* reserved1; */
+    NULL                                        /* void* reserved2; */
+};
+
+/**
+ * xmlSecXkmsRespondWithX509CRLGetKlass:
+ *
+ * The respond with X509CRL klass.
+ *
+ * Returns respond with X509CRL klass.
+ */
+EXPORT_C 
+xmlSecXkmsRespondWithId	
+xmlSecXkmsRespondWithX509CRLGetKlass(void) {
+    return(&xmlSecXkmsRespondWithX509CRLKlass);
+}
+
+static  int  
+xmlSecXkmsRespondWithX509CRLNodeRead(xmlSecXkmsRespondWithId id, xmlSecXkmsServerCtxPtr ctx,
+				      xmlNodePtr node) {
+    int ret;
+
+    xmlSecAssert2(id == xmlSecXkmsRespondWithX509CRLId, -1);
+    xmlSecAssert2(ctx != NULL, -1);
+    xmlSecAssert2(node != NULL, -1);
+
+    /* do usual stuff */
+    ret = xmlSecXkmsRespondWithDefaultNodeRead(id, ctx, node);
+    if(ret < 0) {
+	xmlSecError(XMLSEC_ERRORS_HERE,
+		    xmlSecErrorsSafeString(xmlSecXkmsRespondWithKlassGetName(id)),
+		    "xmlSecXkmsRespondWithDefaultNodeRead",
+		    XMLSEC_ERRORS_R_XMLSEC_FAILED,
+		    XMLSEC_ERRORS_NO_MESSAGE);
+	return(-1);  	
+    }
+    
+    return(0);
+}
+
+static xmlSecXkmsRespondWithKlass xmlSecXkmsRespondWithPGPKlass = {
+    xmlSecRespondWithPGP,			/* const xmlChar* valueName; */
+    xmlSecXkmsNs,			        /* const xmlChar* valueNs; */
+    xmlSecNodePGPData,				/* const xmlChar* nodeName; */
+    xmlSecDSigNs,				/* const xmlChar* nodeNs; */
+    xmlSecXkmsRespondWithDefaultNodeRead,	/* xmlSecXkmsRespondWithNodeReadMethod readNode; */
+    xmlSecXkmsRespondWithDefaultNodeWrite,	/* xmlSecXkmsRespondWithNodeWriteMethod writeNode; */
+    NULL,                                       /* void* reserved1; */
+    NULL                                        /* void* reserved2; */
+};
+
+/**
+ * xmlSecXkmsRespondWithPGPGetKlass:
+ *
+ * The respond with PGP klass.
+ *
+ * Returns respond with PGP klass.
+ */
+EXPORT_C 
+xmlSecXkmsRespondWithId	
+xmlSecXkmsRespondWithPGPGetKlass(void) {
+    return(&xmlSecXkmsRespondWithPGPKlass);
+}
+
+static xmlSecXkmsRespondWithKlass xmlSecXkmsRespondWithSPKIKlass = {
+    xmlSecRespondWithSPKI,			/* const xmlChar* valueName; */
+    xmlSecXkmsNs,			        /* const xmlChar* valueNs; */
+    xmlSecNodeSPKIData,				/* const xmlChar* nodeName; */
+    xmlSecDSigNs,				/* const xmlChar* nodeNs; */
+    xmlSecXkmsRespondWithDefaultNodeRead,	/* xmlSecXkmsRespondWithNodeReadMethod readNode; */
+    xmlSecXkmsRespondWithDefaultNodeWrite,	/* xmlSecXkmsRespondWithNodeWriteMethod writeNode; */
+    NULL,                                       /* void* reserved1; */
+    NULL                                        /* void* reserved2; */
+};
+
+/**
+ * xmlSecXkmsRespondWithSPKIGetKlass:
+ *
+ * The respond with SPKI klass.
+ *
+ * Returns respond with SPKI klass.
+ */
+EXPORT_C 
+xmlSecXkmsRespondWithId	
+xmlSecXkmsRespondWithSPKIGetKlass(void) {
+    return(&xmlSecXkmsRespondWithSPKIKlass);
+}
+
+/**************************************************************************
+ *
+ * Global xmlSecXkmsServerRequestIds list functions
+ *
+ *************************************************************************/
+static xmlSecPtrList xmlSecAllXkmsServerRequestIds;
+
+
+/** 
+ * xmlSecXkmsServerRequestIdsGet:
+ *
+ * Gets global registered ServerRequest klasses list.
+ * 
+ * Returns the pointer to list of all registered ServerRequest klasses.
+ */
+EXPORT_C
+xmlSecPtrListPtr
+xmlSecXkmsServerRequestIdsGet(void) {
+    return(&xmlSecAllXkmsServerRequestIds);
+}
+
+/** 
+ * xmlSecXkmsServerRequestIdsInit:
+ *
+ * Initializes the ServerRequest klasses. This function is called from the 
+ * #xmlSecInit function and the application should not call it directly.
+ *
+ * Returns 0 on success or a negative value if an error occurs.
+ */
+EXPORT_C
+int 
+xmlSecXkmsServerRequestIdsInit(void) {
+    int ret;
+    
+    ret = xmlSecPtrListInitialize(xmlSecXkmsServerRequestIdsGet(), xmlSecXkmsServerRequestIdListId);
+    if(ret < 0) {
+	xmlSecError(XMLSEC_ERRORS_HERE,
+		    NULL,
+		    "xmlSecPtrListPtrInitialize",
+		    XMLSEC_ERRORS_R_XMLSEC_FAILED,
+		    "xmlSecXkmsServerRequestIdListId");
+        return(-1);
+    }
+    
+    ret = xmlSecXkmsServerRequestIdsRegisterDefault();
+    if(ret < 0) {
+	xmlSecError(XMLSEC_ERRORS_HERE,
+		    NULL,
+		    "xmlSecXkmsServerRequestIdsRegisterDefault",
+		    XMLSEC_ERRORS_R_XMLSEC_FAILED,
+		    XMLSEC_ERRORS_NO_MESSAGE);
+        return(-1);
+    }
+    
+    return(0);
+}
+
+/**
+ *  xmlSecXkmsServerRequestIdsShutdown:
+ * 
+ * Shuts down the keys data klasses. This function is called from the 
+ * #xmlSecShutdown function and the application should not call it directly.
+ */
+EXPORT_C
+void
+xmlSecXkmsServerRequestIdsShutdown(void) {
+    xmlSecPtrListFinalize(xmlSecXkmsServerRequestIdsGet());
+}
+
+/** 
+ * xmlSecXkmsServerRequestIdsRegister:
+ * @id:		the ServerRequest klass.
+ *
+ * Registers @id in the global list of ServerRequest klasses.
+ *
+ * Returns 0 on success or a negative value if an error occurs.
+ */
+EXPORT_C
+int 
+xmlSecXkmsServerRequestIdsRegister(xmlSecXkmsServerRequestId id) {
+    int ret;
+        
+    xmlSecAssert2(id != xmlSecXkmsServerRequestIdUnknown, -1);
+    
+    ret = xmlSecPtrListAdd(xmlSecXkmsServerRequestIdsGet(), (xmlSecPtr)id);
+    if(ret < 0) {
+	xmlSecError(XMLSEC_ERRORS_HERE,
+		    NULL,
+		    "xmlSecPtrListAdd",
+		    XMLSEC_ERRORS_R_XMLSEC_FAILED,
+		    "ServerRequest=%s",
+		    xmlSecErrorsSafeString(xmlSecXkmsServerRequestKlassGetName(id)));
+        return(-1);
+    }
+    
+    return(0);    
+}
+
+/**
+ * xmlSecXkmsServerRequestIdsRegisterDefault:
+ *
+ * Registers default (implemented by XML Security Library)
+ * ServerRequest klasses: KeyName, KeyValue,...
+ *
+ * Returns 0 on success or a negative value if an error occurs.
+ */
+EXPORT_C
+int 
+xmlSecXkmsServerRequestIdsRegisterDefault(void) {
+    if(xmlSecXkmsServerRequestIdsRegister(xmlSecXkmsServerRequestResultId) < 0) {
+	xmlSecError(XMLSEC_ERRORS_HERE,
+		    NULL,
+		    "xmlSecXkmsServerRequestIdsRegister",	    
+		    XMLSEC_ERRORS_R_XMLSEC_FAILED,
+		    "name=%s",
+		    xmlSecErrorsSafeString(xmlSecXkmsServerRequestKlassGetName(xmlSecXkmsServerRequestResultId)));
+	return(-1);
+    }
+
+    if(xmlSecXkmsServerRequestIdsRegister(xmlSecXkmsServerRequestStatusId) < 0) {
+	xmlSecError(XMLSEC_ERRORS_HERE,
+		    NULL,
+		    "xmlSecXkmsServerRequestIdsRegister",	    
+		    XMLSEC_ERRORS_R_XMLSEC_FAILED,
+		    "name=%s",
+		    xmlSecErrorsSafeString(xmlSecXkmsServerRequestKlassGetName(xmlSecXkmsServerRequestStatusId)));
+	return(-1);
+    }
+
+    if(xmlSecXkmsServerRequestIdsRegister(xmlSecXkmsServerRequestCompoundId) < 0) {
+	xmlSecError(XMLSEC_ERRORS_HERE,
+		    NULL,
+		    "xmlSecXkmsServerRequestIdsRegister",	    
+		    XMLSEC_ERRORS_R_XMLSEC_FAILED,
+		    "name=%s",
+		    xmlSecErrorsSafeString(xmlSecXkmsServerRequestKlassGetName(xmlSecXkmsServerRequestCompoundId)));
+	return(-1);
+    }
+
+    if(xmlSecXkmsServerRequestIdsRegister(xmlSecXkmsServerRequestLocateId) < 0) {
+	xmlSecError(XMLSEC_ERRORS_HERE,
+		    NULL,
+		    "xmlSecXkmsServerRequestIdsRegister",	    
+		    XMLSEC_ERRORS_R_XMLSEC_FAILED,
+		    "name=%s",
+		    xmlSecErrorsSafeString(xmlSecXkmsServerRequestKlassGetName(xmlSecXkmsServerRequestLocateId)));
+	return(-1);
+    }
+
+    if(xmlSecXkmsServerRequestIdsRegister(xmlSecXkmsServerRequestValidateId) < 0) {
+	xmlSecError(XMLSEC_ERRORS_HERE,
+		    NULL,
+		    "xmlSecXkmsServerRequestIdsRegister",	    
+		    XMLSEC_ERRORS_R_XMLSEC_FAILED,
+		    "name=%s",
+		    xmlSecErrorsSafeString(xmlSecXkmsServerRequestKlassGetName(xmlSecXkmsServerRequestValidateId)));
+	return(-1);
+    }
+
+    return(0);
+}
+
+
+/************************************************************************
+ *
+ * XKMS ServerRequest Klass
+ *
+ ************************************************************************/ 
+/**
+ * xmlSecXkmsServerRequestNodeRead:
+ * @id:		the ServerRequest class.
+ * @ctx:	the XKMS request processing context.
+ * @node:	the pointer to <xkms:ServerRequest/> node.
+ *
+ * Reads the content of the <xkms:ServerRequest/> @node.
+ *
+ * Returns 0 on success or a negative value if an error occurs.
+ */
+EXPORT_C
+int  
+xmlSecXkmsServerRequestNodeRead(xmlSecXkmsServerRequestId id, xmlSecXkmsServerCtxPtr ctx,
+			      xmlNodePtr node) {
+    xmlSecAssert2(id != xmlSecXkmsServerRequestIdUnknown, -1);
+    xmlSecAssert2(ctx != NULL, -1);
+    xmlSecAssert2(node != NULL, -1);
+
+    if(id->readNode != NULL) {
+	return((id->readNode)(id, ctx, node));
+    }
+    return(0);
+}
+
+/**
+ * xmlSecXkmsServerExecute:
+ * @id:		the ServerRequest class.
+ * @ctx:	the XKMS request processing context.
+ *
+ * Executes XKMS server request.
+ *
+ * Returns 0 on success or a negative value if an error occurs.
+ */
+EXPORT_C
+int  
+xmlSecXkmsServerRequestExecute(xmlSecXkmsServerRequestId id, xmlSecXkmsServerCtxPtr ctx) {
+    xmlSecAssert2(id != xmlSecXkmsServerRequestIdUnknown, -1);
+    xmlSecAssert2(ctx != NULL, -1);
+
+    if(id->execute != NULL) {
+	return((id->execute)(id, ctx));
+    }
+    return(0);
+}
+
+
+/**
+ * xmlSecXkmsServerResponseNodeWrite:
+ * @id:		the ServerRequest class.
+ * @ctx:	the XKMS request processing context.
+ * @doc:	the pointer to response parent XML document (might be NULL).
+ * @node:       the pointer to response parent XML node (might be NULL).
+ *
+ * Writes XKMS response from context to a newly created node. Caller is 
+ * responsible for adding the returned node to the XML document.
+ *
+ * Returns pointer to newly created XKMS response node or NULL
+ * if an error occurs.
+ */
+EXPORT_C
+xmlNodePtr 
+xmlSecXkmsServerRequestNodeWrite(xmlSecXkmsServerRequestId id, xmlSecXkmsServerCtxPtr ctx,
+			         xmlDocPtr doc, xmlNodePtr node) {
+    xmlNodePtr respNode;
+    int ret;
+    
+    xmlSecAssert2(id != xmlSecXkmsServerRequestIdUnknown, NULL);
+    xmlSecAssert2(ctx != NULL, NULL);
+
+    /* create the response root node */
+    if(node == NULL) {
+        xmlNsPtr ns;
+        
+        respNode = xmlNewDocNode(doc, NULL, id->resultNodeName, NULL);
+        if(respNode == NULL) {
+	    xmlSecError(XMLSEC_ERRORS_HERE,
+		        NULL,
+		        "xmlNewDocNode",
+		        XMLSEC_ERRORS_R_XML_FAILED,
+		        "node=%s",
+		        xmlSecErrorsSafeString(id->resultNodeName));
+            return(NULL);
+        }
+        ns = xmlNewNs(respNode, id->resultNodeNs, NULL);
+        if(ns == NULL) {
+	    xmlSecError(XMLSEC_ERRORS_HERE,
+		        NULL,
+		        "xmlNewNs",
+		        XMLSEC_ERRORS_R_XML_FAILED,
+		        "ns=%s",
+		        xmlSecErrorsSafeString(id->resultNodeNs));
+            xmlFreeNode(respNode);
+            return(NULL);
+        }
+        xmlSetNs(respNode, ns);
+    } else {
+        respNode = xmlSecAddChild(node, id->resultNodeName, id->resultNodeNs);
+        if(respNode == NULL) {
+	    xmlSecError(XMLSEC_ERRORS_HERE,
+		        NULL,
+		        "xmlSecAddChild",
+		        XMLSEC_ERRORS_R_XMLSEC_FAILED,
+		        "node=%s",
+		        xmlSecErrorsSafeString(id->resultNodeName));
+            return(NULL);
+        }
+    }
+    
+    if(id->writeNode != NULL) {
+	ret = (id->writeNode)(id, ctx, respNode);
+	if(ret < 0) {
+            xmlSecError(XMLSEC_ERRORS_HERE,
+		        NULL,
+		        "writeNode",
+		        XMLSEC_ERRORS_R_XMLSEC_FAILED,
+		        "node=%s",
+		        xmlSecErrorsSafeString(id->resultNodeName));
+            xmlFreeNode(respNode);
+            return(NULL);
+        }
+    }
+    
+    return(respNode);
+}
+
+/**
+ * xmlSecXkmsServerRequestDebugDump:
+ * @id:			the ServerRequest class.
+ * @output:		the output file.
+ *
+ * Writes debug information about @id into the @output.
+ */
+EXPORT_C
+void 
+xmlSecXkmsServerRequestDebugDump(xmlSecXkmsServerRequestId id, FILE* output) {
+    xmlSecAssert(id != xmlSecXkmsServerRequestIdUnknown);
+    xmlSecAssert(output != NULL);
+
+    fprintf(output, "=== ServerRequest: %s\n", xmlSecErrorsSafeString(id->name));
+}
+
+/**
+ * xmlSecXkmsServerRequestDebugXmlDump:
+ * @id:			the ServerRequest class.
+ * @output:		the output file.
+ *
+ * Writes debug information about @id into the @output in XML format.
+ */
+EXPORT_C
+void 
+xmlSecXkmsServerRequestDebugXmlDump(xmlSecXkmsServerRequestId id, FILE* output) {
+    xmlSecAssert(id != xmlSecXkmsServerRequestIdUnknown);
+    xmlSecAssert(output != NULL);
+
+    fprintf(output, "<ServerRequest>%s</ServerRequest>\n", xmlSecErrorsSafeString(id->name));
+}
+
+/************************************************************************
+ *
+ * XKMS ServerRequest Klass List
+ *
+ ************************************************************************/ 
+static xmlSecPtrListKlass xmlSecXkmsServerRequestIdListKlass = {
+    BAD_CAST "xkms-server-request-ids-list",
+    NULL, 								/* xmlSecPtrDuplicateItemMethod duplicateItem; */
+    NULL,								/* xmlSecPtrDestroyItemMethod destroyItem; */
+    (xmlSecPtrDebugDumpItemMethod)xmlSecXkmsServerRequestDebugDump,	/* xmlSecPtrDebugDumpItemMethod debugDumpItem; */
+    (xmlSecPtrDebugDumpItemMethod)xmlSecXkmsServerRequestDebugXmlDump,	/* xmlSecPtrDebugDumpItemMethod debugXmlDumpItem; */
+};
+EXPORT_C
+
+xmlSecPtrListId	
+xmlSecXkmsServerRequestIdListGetKlass(void) {
+    return(&xmlSecXkmsServerRequestIdListKlass);
+}
+EXPORT_C
+
+int 
+xmlSecXkmsServerRequestIdListFind(xmlSecPtrListPtr list, xmlSecXkmsServerRequestId id) {
+    xmlSecSize i, size;
+    
+    xmlSecAssert2(xmlSecPtrListCheckId(list, xmlSecXkmsServerRequestIdListId), -1);
+    xmlSecAssert2(id != xmlSecXkmsServerRequestIdUnknown, -1);
+    
+    size = xmlSecPtrListGetSize(list);
+    for(i = 0; i < size; ++i) {
+	if((xmlSecXkmsServerRequestId)xmlSecPtrListGetItem(list, i) == id) {
+	    return(1);
+	}
+    }
+    return(0);
+}
+EXPORT_C
+
+xmlSecXkmsServerRequestId 
+xmlSecXkmsServerRequestIdListFindByName(xmlSecPtrListPtr list, const xmlChar* name) {
+    xmlSecXkmsServerRequestId id;
+    xmlSecSize i, size;
+    
+    xmlSecAssert2(xmlSecPtrListCheckId(list, xmlSecXkmsServerRequestIdListId), xmlSecXkmsServerRequestIdUnknown);
+    xmlSecAssert2(name != NULL, xmlSecXkmsServerRequestIdUnknown);
+
+    size = xmlSecPtrListGetSize(list);
+    for(i = 0; i < size; ++i) {
+	id = (xmlSecXkmsServerRequestId)xmlSecPtrListGetItem(list, i);
+	if((id !=  xmlSecXkmsServerRequestIdUnknown) && xmlStrEqual(id->name, name)) {
+	    return(id);
+	}
+    }
+    return(xmlSecXkmsServerRequestIdUnknown);    
+}
+EXPORT_C
+
+xmlSecXkmsServerRequestId 
+xmlSecXkmsServerRequestIdListFindByNode(xmlSecPtrListPtr list, xmlNodePtr node) {
+    xmlSecXkmsServerRequestId id;
+    xmlSecSize i, size;
+    
+    xmlSecAssert2(xmlSecPtrListCheckId(list, xmlSecXkmsServerRequestIdListId), xmlSecXkmsServerRequestIdUnknown);
+    xmlSecAssert2(node != NULL, xmlSecXkmsServerRequestIdUnknown);
+
+    size = xmlSecPtrListGetSize(list);
+    for(i = 0; i < size; ++i) {
+	id = (xmlSecXkmsServerRequestId)xmlSecPtrListGetItem(list, i);
+	if((id !=  xmlSecXkmsServerRequestIdUnknown) &&
+            xmlSecCheckNodeName(node, id->requestNodeName, id->requestNodeNs)) {
+
+	    return(id);
+	}
+    }
+    return(xmlSecXkmsServerRequestIdUnknown);    
+}
+
+/******************************************************************** 
+ *
+ * XML Sec Library ServerRequest Ids
+ *
+ *******************************************************************/
+
+
+/******************************************************************** 
+ *
+ * Result response
+ *
+ *******************************************************************/
+static int		xmlSecXkmsServerRequestResultNodeWrite	(xmlSecXkmsServerRequestId id,
+								 xmlSecXkmsServerCtxPtr ctx,
+								 xmlNodePtr node);
+
+static xmlSecXkmsServerRequestKlass xmlSecXkmsServerRequestResultKlass = {
+    xmlSecXkmsServerRequestResultName,		/* const xmlChar* name; */
+    NULL,					/* const xmlChar* requestNodeName; */
+    NULL,					/* const xmlChar* requestNodeNs; */
+    xmlSecNodeResult,				/* const xmlChar* responseNodeName; */
+    xmlSecXkmsNs,				/* const xmlChar* responseNodeNs; */
+    0,                                          /* xmlSecBitMask flags; */
+    NULL,					/* xmlSecXkmsServerRequestNodeReadMethod readNode; */
+    xmlSecXkmsServerRequestResultNodeWrite,	/* xmlSecXkmsServerRequestNodeWriteMethod writeNode; */
+    NULL,					/* xmlSecXkmsServerRequestExecuteMethod execute; */
+    NULL,                                       /* void* reserved1; */
+    NULL                                        /* void* reserved2; */
+};
+
+/**
+ * xmlSecXkmsServerRequestResultGetKlass:
+ *
+ * The Result response klass.
+ *
+ * Returns Result response klass.
+ */
+EXPORT_C 
+xmlSecXkmsServerRequestId	
+xmlSecXkmsServerRequestResultGetKlass(void) {
+    return(&xmlSecXkmsServerRequestResultKlass);
+}
+
+static int 
+xmlSecXkmsServerRequestResultNodeWrite(xmlSecXkmsServerRequestId id, xmlSecXkmsServerCtxPtr ctx, xmlNodePtr node) {
+    int ret;
+    
+    xmlSecAssert2(id == xmlSecXkmsServerRequestResultId, -1);
+    xmlSecAssert2(ctx != NULL, -1);
+    xmlSecAssert2(node != NULL, -1);
+
+    /* set missing parameters (if any) */
+    if(ctx->service == NULL) {
+	ctx->service = xmlStrdup((ctx->expectedService != NULL) ? ctx->expectedService : BAD_CAST "");
+	if(ctx->service == NULL) {
+	    xmlSecError(XMLSEC_ERRORS_HERE,
+			NULL,
+			"xmlStrdup",
+		        XMLSEC_ERRORS_R_MALLOC_FAILED,
+			XMLSEC_ERRORS_NO_MESSAGE);
+	    return(-1);
+	}
+    }
+    
+    /* first write the "parent" type */
+    ret = xmlSecXkmsServerCtxResultTypeNodeWrite(ctx, node);
+    if(ret < 0) {
+	xmlSecError(XMLSEC_ERRORS_HERE,
+		    NULL,
+		    "xmlSecXkmsServerCtxResultTypeNodeWrite",
+		    XMLSEC_ERRORS_R_XMLSEC_FAILED,
+		    XMLSEC_ERRORS_NO_MESSAGE);
+	return(-1);  	
+    }
+
+    return(0);
+}
+
+/******************************************************************** 
+ *
+ * StatusRequest/StatusResponse
+ *
+ *******************************************************************/
+static int  		xmlSecXkmsServerRequestStatusNodeRead	(xmlSecXkmsServerRequestId id,
+								 xmlSecXkmsServerCtxPtr ctx,
+								 xmlNodePtr node);
+static int		xmlSecXkmsServerRequestStatusNodeWrite	(xmlSecXkmsServerRequestId id,
+								 xmlSecXkmsServerCtxPtr ctx,
+								 xmlNodePtr node);
+
+static xmlSecXkmsServerRequestKlass xmlSecXkmsServerRequestStatusKlass = {
+    xmlSecXkmsServerRequestStatusName,		/* const xmlChar* name; */
+    xmlSecNodeStatusRequest,			/* const xmlChar* requestNodeName; */
+    xmlSecXkmsNs,				/* const xmlChar* requestNodeNs; */
+    xmlSecNodeStatusResult,			/* const xmlChar* responseNodeName; */
+    xmlSecXkmsNs,				/* const xmlChar* responseNodeNs; */
+    0,                                          /* xmlSecBitMask flags; */
+    xmlSecXkmsServerRequestStatusNodeRead,	/* xmlSecXkmsServerRequestNodeReadMethod readNode; */
+    xmlSecXkmsServerRequestStatusNodeWrite,	/* xmlSecXkmsServerRequestNodeWriteMethod writeNode; */
+    NULL,					/* xmlSecXkmsServerRequestExecuteMethod execute; */
+    NULL,                                       /* void* reserved1; */
+    NULL                                        /* void* reserved2; */
+};
+
+/**
+ * xmlSecXkmsServerRequestStatusGetKlass:
+ *
+ * The StatusRequest klass.
+ *
+ * Returns StatusRequest klass.
+ */
+EXPORT_C 
+xmlSecXkmsServerRequestId	
+xmlSecXkmsServerRequestStatusGetKlass(void) {
+    return(&xmlSecXkmsServerRequestStatusKlass);
+}
+
+/**
+ * 
+ *  <xkms:StatusRequest Id Service Nonce? OriginalRequestId? ResponseLimit? ResponseId?>
+ *      <ds:Signature>?
+ *      <xkms:MessageExtension>*
+ *      (<xkms:OpaqueClientData>
+ *          <xkms:OpaqueData>?
+ *      )?
+ *      <xkms:ResponseMechanism>*
+ *      <xkms:RespondWith>*
+ *      <xkms:PendingNotification Mechanism Identifier>?
+ *  
+ * XML Schema:
+ *    <!-- StatusRequest -->   
+ *    <element name="StatusRequest" type="xkms:StatusRequestType"/>   
+ *    <complexType name="StatusRequestType">      
+ *        <complexContent>         
+ *            <extension base="xkms:PendingRequestType"/>      
+ *        </complexContent>   
+ *    </complexType>   
+ *    <!-- /StatusRequest -->
+ */
+static int  
+xmlSecXkmsServerRequestStatusNodeRead(xmlSecXkmsServerRequestId id, xmlSecXkmsServerCtxPtr ctx, xmlNodePtr node) {
+    xmlNodePtr cur;
+    int ret;
+    
+    xmlSecAssert2(id == xmlSecXkmsServerRequestStatusId, -1);
+    xmlSecAssert2(ctx != NULL, -1);
+    xmlSecAssert2(node != NULL, -1);
+
+    cur = node;
+    
+    /* first read "parent" type */
+    ret = xmlSecXkmsServerCtxPendingRequestNodeRead(ctx, &cur);
+    if(ret < 0) {
+    	xmlSecError(XMLSEC_ERRORS_HERE,
+		    NULL,
+		    "xmlSecXkmsServerCtxPendingRequestNodeRead",
+		    XMLSEC_ERRORS_R_XMLSEC_FAILED,
+		    XMLSEC_ERRORS_NO_MESSAGE);
+	return(-1);
+    }
+
+    /* check that there is nothing after the last node */
+    if(cur != NULL) {
+	xmlSecError(XMLSEC_ERRORS_HERE,
+		    NULL,
+		    xmlSecErrorsSafeString(xmlSecNodeGetName(cur)),
+		    XMLSEC_ERRORS_R_UNEXPECTED_NODE,
+		    XMLSEC_ERRORS_NO_MESSAGE);
+	return(-1);
+    }
+
+    return(0);
+}
+
+/**
+ * 
+ *  <xkms:StatusResult Id Service Nonce? ResultMajor ResultMinor? RequestId? Success? Failure? Pending?>
+ *      <ds:Signature>?
+ *      <xkms:MessageExtension>*
+ *      (<xkms:OpaqueClientData>
+ *          <xkms:OpaqueData>?
+ *      )?
+ *      <xkms:RequestSignatureValue>*
+ *
+ * XML Schema:
+ * 
+ *    <!-- StatusResult -->   
+ *    <element name="StatusResult" type="xkms:StatusResultType"/>   
+ *    <complexType name="StatusResultType">      
+ *        <complexContent>
+ *            <extension base="xkms:ResultType">
+ *                <attribute name="Success" type="integer" use="optional"/>
+ *                <attribute name="Failure" type="integer" use="optional"/>
+ *                <attribute name="Pending" type="integer" use="optional"/>
+ *            </extension>
+ *        </complexContent>
+ *    </complexType>
+ *    <!-- /StatusResult --> *
+ */ 
+static int 
+xmlSecXkmsServerRequestStatusNodeWrite(xmlSecXkmsServerRequestId id, xmlSecXkmsServerCtxPtr ctx, xmlNodePtr node) {
+    int ret;
+
+    xmlSecAssert2(id == xmlSecXkmsServerRequestStatusId, -1);
+    xmlSecAssert2(ctx != NULL, -1);
+    xmlSecAssert2(node != NULL, -1);
+
+    /* first write the "parent" type */
+    ret = xmlSecXkmsServerCtxResultTypeNodeWrite(ctx, node);
+    if(ret < 0) {
+	xmlSecError(XMLSEC_ERRORS_HERE,
+		    NULL,
+		    "xmlSecXkmsServerCtxResultTypeNodeWrite",
+		    XMLSEC_ERRORS_R_XMLSEC_FAILED,
+		    XMLSEC_ERRORS_NO_MESSAGE);
+	return(-1);  	
+    }
+    
+    return(0);
+}
+
+/******************************************************************** 
+ *
+ * CompoundRequest/CompoundResponse
+ *
+ *******************************************************************/
+static int  		xmlSecXkmsServerRequestCompoundNodeRead	(xmlSecXkmsServerRequestId id,
+								 xmlSecXkmsServerCtxPtr ctx,
+								 xmlNodePtr node);
+static int		xmlSecXkmsServerRequestCompoundNodeWrite(xmlSecXkmsServerRequestId id,
+								 xmlSecXkmsServerCtxPtr ctx,
+								 xmlNodePtr node);
+static int 		xmlSecXkmsServerRequestCompoundExecute	(xmlSecXkmsServerRequestId id, 
+								 xmlSecXkmsServerCtxPtr ctx);
+
+static xmlSecXkmsServerRequestKlass xmlSecXkmsServerRequestCompoundKlass = {
+    xmlSecXkmsServerRequestCompoundName,	/* const xmlChar* name; */
+    xmlSecNodeCompoundRequest,			/* const xmlChar* requestNodeName; */
+    xmlSecXkmsNs,				/* const xmlChar* requestNodeNs; */
+    xmlSecNodeCompoundResult,			/* const xmlChar* responseNodeName; */
+    xmlSecXkmsNs,				/* const xmlChar* responseNodeNs; */
+    0,                                          /* xmlSecBitMask flags; */
+    xmlSecXkmsServerRequestCompoundNodeRead,	/* xmlSecXkmsServerRequestNodeReadMethod readNode; */
+    xmlSecXkmsServerRequestCompoundNodeWrite,	/* xmlSecXkmsServerRequestNodeWriteMethod writeNode; */
+    xmlSecXkmsServerRequestCompoundExecute,	/* xmlSecXkmsServerRequestExecuteMethod execute; */
+    NULL,                                       /* void* reserved1; */
+    NULL                                        /* void* reserved2; */
+};
+
+/**
+ * xmlSecXkmsServerRequestCompoundGetKlass:
+ *
+ * The CompoundRequest klass.
+ *
+ * Returns CompoundRequest klass.
+ */
+EXPORT_C 
+xmlSecXkmsServerRequestId	
+xmlSecXkmsServerRequestCompoundGetKlass(void) {
+    return(&xmlSecXkmsServerRequestCompoundKlass);
+}
+
+/**
+ *  <xkms:CompoundRequest Id Service Nonce? OriginalRequestId? ResponseLimit?>
+ *      <ds:Signature>?
+ *      <xkms:MessageExtension>*
+ *      (<xkms:OpaqueClientData>
+ *          <xkms:OpaqueData>?
+ *      )?
+ *      <xkms:ResponseMechanism>*
+ *      <xkms:RespondWith>*
+ *      <xkms:PendingNotification Mechanism Identifier>?
+ *      (
+ *       <xkms:LocateRequest>?
+ *       <xkms:ValidateRequest>?
+ *       <xkms:RegisterRequest>?
+ *       <xkms:ReissueRequest>?
+ *       <xkms:RecoverRequest>?
+ *       <xkms:RevokeRequest>?
+ *      )*
+ *       
+ * XML Schema:
+ *
+ *    <!-- CompoundRequest -->   
+ *    <element name="CompoundRequest" type="xkms:CompoundRequestType"/>   
+ *    <complexType name="CompoundRequestType">      
+ *        <complexContent>         
+ *            <extension base="xkms:RequestAbstractType">            
+ *                <choice maxOccurs="unbounded">               
+ *                    <element ref="xkms:LocateRequest"/>               
+ *                    <element ref="xkms:ValidateRequest"/>               
+ *                    <element ref="xkms:RegisterRequest"/>               
+ *                    <element ref="xkms:ReissueRequest"/>               
+ *                    <element ref="xkms:RecoverRequest"/>               
+ *                    <element ref="xkms:RevokeRequest"/>            
+ *                </choice>         
+ *            </extension>      
+ *        </complexContent>   
+ *    </complexType>   
+ *    <!-- /CompoundRequest -->
+ */
+static int  
+xmlSecXkmsServerRequestCompoundNodeRead(xmlSecXkmsServerRequestId id, xmlSecXkmsServerCtxPtr ctx, xmlNodePtr node) {
+    xmlSecPtrListPtr serverRequestIdsList;
+    xmlNodePtr cur;
+    int ret;
+    
+    xmlSecAssert2(id == xmlSecXkmsServerRequestCompoundId, -1);
+    xmlSecAssert2(ctx != NULL, -1);
+    xmlSecAssert2(node != NULL, -1);
+
+    cur = node;
+    
+    /* first read "parent" type */
+    ret = xmlSecXkmsServerCtxRequestAbstractTypeNodeRead(ctx, &cur);
+    if(ret < 0) {
+    	xmlSecError(XMLSEC_ERRORS_HERE,
+		    NULL,
+		    "xmlSecXkmsServerCtxRequestAbstractTypeNodeRead",
+		    XMLSEC_ERRORS_R_XMLSEC_FAILED,
+		    XMLSEC_ERRORS_NO_MESSAGE);
+	return(-1);
+    }
+
+    /* create list for compound requests */
+    xmlSecAssert2(ctx->compoundRequestContexts == NULL, -1);
+    ctx->compoundRequestContexts = xmlSecPtrListCreate(xmlSecXkmsServerCtxPtrListId);
+    if(ctx->compoundRequestContexts == NULL) {
+    	xmlSecError(XMLSEC_ERRORS_HERE,
+		    NULL,
+		    "xmlSecPtrListCreate",
+		    XMLSEC_ERRORS_R_XMLSEC_FAILED,
+		    XMLSEC_ERRORS_NO_MESSAGE);
+	return(-1);
+    }
+
+    /* get the list of enabled or all request klasses */
+    if(xmlSecPtrListGetSize(&(ctx->enabledServerRequestIds)) > 0) {
+	serverRequestIdsList = &(ctx->enabledServerRequestIds);
+    } else {
+	serverRequestIdsList = xmlSecXkmsServerRequestIdsGet();
+    }
+    xmlSecAssert2(serverRequestIdsList != NULL, -1); 
+    
+    while(cur != NULL) {
+        xmlSecXkmsServerCtxPtr ctxChild;    
+        
+        /* create a new context */
+        ctxChild = xmlSecXkmsServerCtxCreate(ctx->keyInfoReadCtx.keysMngr);
+        if(ctxChild == NULL) {
+            xmlSecError(XMLSEC_ERRORS_HERE,
+		        NULL,
+		        "xmlSecXkmsServerCtxCreate",
+		        XMLSEC_ERRORS_R_XMLSEC_FAILED,
+		        XMLSEC_ERRORS_NO_MESSAGE);
+	    return(-1);
+        }
+
+        /* copy all settings from us */
+        ret = xmlSecXkmsServerCtxCopyUserPref(ctxChild, ctx);
+        if(ret < 0) {
+            xmlSecError(XMLSEC_ERRORS_HERE,
+		        NULL,
+		        "xmlSecXkmsServerCtxCopyUserPref",
+		        XMLSEC_ERRORS_R_XMLSEC_FAILED,
+		        XMLSEC_ERRORS_NO_MESSAGE);
+            xmlSecXkmsServerCtxDestroy(ctxChild);
+	    return(-1);
+        }
+
+        /* add it to the list */
+        ret = xmlSecPtrListAdd(ctx->compoundRequestContexts, ctxChild);
+        if(ret < 0) {
+            xmlSecError(XMLSEC_ERRORS_HERE,
+		        NULL,
+		        "xmlSecPtrListAdd",
+		        XMLSEC_ERRORS_R_XMLSEC_FAILED,
+		        XMLSEC_ERRORS_NO_MESSAGE);
+            xmlSecXkmsServerCtxDestroy(ctxChild);
+	    return(-1);
+        }
+
+        /* and now process request from current node */
+        ctxChild->requestId = xmlSecXkmsServerRequestIdListFindByNode(serverRequestIdsList, cur);
+        if((ctxChild->requestId == xmlSecXkmsServerRequestIdUnknown) || 
+           ((ctxChild->requestId->flags & XMLSEC_XKMS_SERVER_REQUEST_KLASS_ALLOWED_IN_COUMPOUND) == 0)) {
+            xmlSecError(XMLSEC_ERRORS_HERE,
+		        NULL,
+		        "xmlSecXkmsServerRequestIdListFindByNode",
+		        XMLSEC_ERRORS_R_XMLSEC_FAILED,
+		        "node=%s",
+		        xmlSecErrorsSafeString(node->name));
+	    xmlSecXkmsServerCtxSetResult(ctx, xmlSecXkmsResultMajorSender, xmlSecXkmsResultMinorMessageNotSupported);
+	    return(-1);
+        }
+
+        ret = xmlSecXkmsServerRequestNodeRead(ctxChild->requestId, ctxChild, cur);
+        if(ret < 0) {
+    	    xmlSecError(XMLSEC_ERRORS_HERE,
+		        NULL,
+		        "xmlSecXkmsServerRequestNodeRead",
+		        XMLSEC_ERRORS_R_XMLSEC_FAILED,
+		        "request=%s",
+		        xmlSecErrorsSafeString(xmlSecXkmsServerRequestKlassGetName(ctxChild->requestId)));
+	    xmlSecXkmsServerCtxSetResult(ctxChild, xmlSecXkmsResultMajorSender, xmlSecXkmsResultMinorFailure);
+	    return(-1);
+        }
+        cur = xmlSecGetNextElementNode(cur->next);
+    }
+
+    /* check that there is nothing after the last node */
+    if(cur != NULL) {
+	xmlSecError(XMLSEC_ERRORS_HERE,
+		    NULL,
+		    xmlSecErrorsSafeString(xmlSecNodeGetName(cur)),
+		    XMLSEC_ERRORS_R_UNEXPECTED_NODE,
+		    XMLSEC_ERRORS_NO_MESSAGE);
+	return(-1);
+    }
+
+    return(0);
+}
+
+/**
+ *  <xkms:CompoundResult Id Service Nonce? ResultMajor ResultMinor? RequestId?>
+ *      <ds:Signature>?
+ *      <xkms:MessageExtension>*
+ *      (<xkms:OpaqueClientData>
+ *          <xkms:OpaqueData>?
+ *      )?
+ *      <xkms:RequestSignatureValue>*
+ *      (
+ *       <xkms:LocateResult>?
+ *       <xkms:ValidateResult>?
+ *       <xkms:RegisterResult>?
+ *       <xkms:ReissueResult>?
+ *       <xkms:RecoverResult>?
+ *       <xkms:RevokeResult>?
+ *      )*
+ *
+ * 
+ * XML Schema:
+ *
+ *    <!-- CompoundResponse -->   
+ *    <element name="CompoundResult" type="xkms:CompoundResultType"/>   
+ *    <complexType name="CompoundResultType">      
+ *        <complexContent>         
+ *            <extension base="xkms:ResultType">            
+ *                <choice maxOccurs="unbounded">               
+ *                    <element ref="xkms:LocateResult"/>
+ *                    <element ref="xkms:ValidateResult"/>
+ *                    <element ref="xkms:RegisterResult"/>
+ *                    <element ref="xkms:ReissueResult"/>
+ *                    <element ref="xkms:RecoverResult"/>
+ *                    <element ref="xkms:RevokeResult"/>
+ *                </choice>
+ *            </extension>
+ *        </complexContent>
+ *   </complexType>
+ *   <!-- /CompoundResponse -->
+ */ 
+static int 
+xmlSecXkmsServerRequestCompoundNodeWrite(xmlSecXkmsServerRequestId id, xmlSecXkmsServerCtxPtr ctx, xmlNodePtr node) {
+    int ret;
+
+    xmlSecAssert2(id == xmlSecXkmsServerRequestCompoundId, -1);
+    xmlSecAssert2(ctx != NULL, -1);
+    xmlSecAssert2(node != NULL, -1);
+
+    /* walk thru the list of chilren and pickup first error */
+    if(ctx->compoundRequestContexts != NULL) {
+        xmlSecSize pos;
+
+        for(pos = 0; pos < xmlSecPtrListGetSize(ctx->compoundRequestContexts); pos++) {
+            xmlSecXkmsServerCtxPtr ctxChild;
+
+            ctxChild = (xmlSecXkmsServerCtxPtr)xmlSecPtrListGetItem(ctx->compoundRequestContexts, pos);
+            if(ctxChild == NULL) {
+	        xmlSecError(XMLSEC_ERRORS_HERE,
+		            NULL,
+		            "xmlSecPtrListGetItem",
+		            XMLSEC_ERRORS_R_XMLSEC_FAILED,
+		            XMLSEC_ERRORS_NO_MESSAGE);
+	        return(-1);  	
+            }
+	    
+	    if(ctxChild->resultMajor != xmlSecXkmsResultMajorSuccess) {
+	        xmlSecXkmsServerCtxSetResult(ctx, ctxChild->resultMajor, ctxChild->resultMinor);
+		break;
+	    }
+	}
+    }
+    
+    /* first write the "parent" type */
+    ret = xmlSecXkmsServerCtxResultTypeNodeWrite(ctx, node);
+    if(ret < 0) {
+	xmlSecError(XMLSEC_ERRORS_HERE,
+		    NULL,
+		    "xmlSecXkmsServerCtxResultTypeNodeWrite",
+		    XMLSEC_ERRORS_R_XMLSEC_FAILED,
+		    XMLSEC_ERRORS_NO_MESSAGE);
+	return(-1);  	
+    }
+    
+    /* write compound result */
+    if(ctx->compoundRequestContexts != NULL) {
+        xmlSecSize pos;
+
+        for(pos = 0; pos < xmlSecPtrListGetSize(ctx->compoundRequestContexts); pos++) {
+            xmlSecXkmsServerCtxPtr ctxChild;
+            xmlNodePtr cur;
+
+            ctxChild = (xmlSecXkmsServerCtxPtr)xmlSecPtrListGetItem(ctx->compoundRequestContexts, pos);
+            if(ctxChild == NULL) {
+	        xmlSecError(XMLSEC_ERRORS_HERE,
+		            NULL,
+		            "xmlSecPtrListGetItem",
+		            XMLSEC_ERRORS_R_XMLSEC_FAILED,
+		            XMLSEC_ERRORS_NO_MESSAGE);
+	        return(-1);  	
+            }
+            
+            cur = xmlSecXkmsServerRequestNodeWrite(ctxChild->requestId, ctxChild, node->doc, node);
+            if(cur == NULL) {
+    	        xmlSecError(XMLSEC_ERRORS_HERE,
+		            NULL,
+		            "xmlSecXkmsServerRequestNodeWrite",
+		            XMLSEC_ERRORS_R_XMLSEC_FAILED,
+		            "request=%s",
+		            xmlSecErrorsSafeString(xmlSecXkmsServerRequestKlassGetName(ctxChild->requestId)));
+                return(-1);
+            }
+            
+            if(xmlSecAddChildNode(node, cur) == NULL) {
+	        xmlSecError(XMLSEC_ERRORS_HERE,
+			    NULL,
+			    "xmlSecAddChildNode",
+			    XMLSEC_ERRORS_R_XMLSEC_FAILED,
+			    XMLSEC_ERRORS_NO_MESSAGE);
+                xmlFreeNode(cur);
+                return(-1);
+	    }
+        }
+    }
+
+    return(0);
+}
+
+static int 
+xmlSecXkmsServerRequestCompoundExecute(xmlSecXkmsServerRequestId id, xmlSecXkmsServerCtxPtr ctx) {
+    int ret;
+    
+    xmlSecAssert2(id == xmlSecXkmsServerRequestCompoundId, -1);
+    xmlSecAssert2(ctx != NULL, -1);
+
+    if(ctx->compoundRequestContexts != NULL) {
+        xmlSecSize pos;
+
+        for(pos = 0; pos < xmlSecPtrListGetSize(ctx->compoundRequestContexts); pos++) {
+            xmlSecXkmsServerCtxPtr ctxChild;
+
+            ctxChild = (xmlSecXkmsServerCtxPtr)xmlSecPtrListGetItem(ctx->compoundRequestContexts, pos);
+            if(ctxChild == NULL) {
+	        xmlSecError(XMLSEC_ERRORS_HERE,
+		            NULL,
+		            "xmlSecPtrListGetItem",
+		            XMLSEC_ERRORS_R_XMLSEC_FAILED,
+		            XMLSEC_ERRORS_NO_MESSAGE);
+	        xmlSecXkmsServerCtxSetResult(ctx, xmlSecXkmsResultMajorReceiver, xmlSecXkmsResultMinorFailure);
+	        continue;  	
+            }
+            
+            ret = xmlSecXkmsServerRequestExecute(ctxChild->requestId, ctxChild);
+            if(ret < 0) {
+    	        xmlSecError(XMLSEC_ERRORS_HERE,
+		            NULL,
+		            "xmlSecXkmsServerRequestExecute",
+		            XMLSEC_ERRORS_R_XMLSEC_FAILED,
+		            "request=%s",
+		            xmlSecErrorsSafeString(xmlSecXkmsServerRequestKlassGetName(ctxChild->requestId)));
+	        xmlSecXkmsServerCtxSetResult(ctxChild, xmlSecXkmsResultMajorSender, xmlSecXkmsResultMinorFailure);
+	        continue;  	
+            }
+        }
+    }
+
+    return(0);
+}
+
+
+/******************************************************************** 
+ *
+ * LocateRequest/LocateResponse
+ *
+ *******************************************************************/
+static int  		xmlSecXkmsServerRequestLocateNodeRead	(xmlSecXkmsServerRequestId id,
+								 xmlSecXkmsServerCtxPtr ctx,
+								 xmlNodePtr node);
+static int		xmlSecXkmsServerRequestLocateNodeWrite	(xmlSecXkmsServerRequestId id,
+								 xmlSecXkmsServerCtxPtr ctx,
+								 xmlNodePtr node);
+static int 		xmlSecXkmsServerRequestLocateExecute	(xmlSecXkmsServerRequestId id, 
+								 xmlSecXkmsServerCtxPtr ctx);
+
+static xmlSecXkmsServerRequestKlass xmlSecXkmsServerRequestLocateKlass = {
+    xmlSecXkmsServerRequestLocateName,		/* const xmlChar* name; */
+    xmlSecNodeLocateRequest,			/* const xmlChar* requestNodeName; */
+    xmlSecXkmsNs,				/* const xmlChar* requestNodeNs; */
+    xmlSecNodeLocateResult,			/* const xmlChar* responseNodeName; */
+    xmlSecXkmsNs,				/* const xmlChar* responseNodeNs; */
+    XMLSEC_XKMS_SERVER_REQUEST_KLASS_ALLOWED_IN_COUMPOUND,      /* xmlSecBitMask flags; */
+    xmlSecXkmsServerRequestLocateNodeRead,	/* xmlSecXkmsServerRequestNodeReadMethod readNode; */
+    xmlSecXkmsServerRequestLocateNodeWrite,	/* xmlSecXkmsServerRequestNodeWriteMethod writeNode; */
+    xmlSecXkmsServerRequestLocateExecute,	/* xmlSecXkmsServerRequestExecuteMethod execute; */
+    NULL,                                       /* void* reserved1; */
+    NULL                                        /* void* reserved2; */
+};
+
+/**
+ * xmlSecXkmsServerRequestLocateGetKlass:
+ *
+ * The LocateRequest klass.
+ *
+ * Returns LocateRequest klass.
+ */
+EXPORT_C 
+xmlSecXkmsServerRequestId	
+xmlSecXkmsServerRequestLocateGetKlass(void) {
+    return(&xmlSecXkmsServerRequestLocateKlass);
+}
+
+/**
+ *  <xkms:LocateRequest Id Service Nonce? OriginalRequestId? ResponseLimit?>
+ *      <ds:Signature>?
+ *      <xkms:MessageExtension>*
+ *      (<xkms:OpaqueClientData>
+ *          <xkms:OpaqueData>?
+ *      )?
+ *      <xkms:ResponseMechanism>*
+ *      <xkms:RespondWith>*
+ *      <xkms:PendingNotification Mechanism Identifier>?
+ *      <xkms:QueryKeyBinding Id?>
+ *          <ds:KeyInfo>?
+ *          <xkms:KeyUsage>?
+ *          <xkms:KeyUsage>?
+ *          <xkms:KeyUsage>?
+ *          <xkms:UseKeyWith Application Identifier>*    
+ *          <xkms:TimeInstant Time>?
+ *
+ * XML Schema:
+ *
+ *    <!-- LocateRequest -->
+ *    <element name="LocateRequest" type="xkms:LocateRequestType"/>
+ *    <complexType name="LocateRequestType">
+ *        <complexContent>
+ *            <extension base="xkms:RequestAbstractType">
+ *                <sequence>
+ *                    <element ref="xkms:QueryKeyBinding"/>
+ *                </sequence>
+ *            </extension>
+ *        </complexContent>
+ *    </complexType>
+ *    <!-- /LocateRequest -->
+ */
+static int  
+xmlSecXkmsServerRequestLocateNodeRead(xmlSecXkmsServerRequestId id, xmlSecXkmsServerCtxPtr ctx, xmlNodePtr node) {
+    xmlNodePtr cur;
+    int ret;
+    
+    xmlSecAssert2(id == xmlSecXkmsServerRequestLocateId, -1);
+    xmlSecAssert2(ctx != NULL, -1);
+    xmlSecAssert2(node != NULL, -1);
+
+    cur = node;
+    
+    /* first read "parent" type */
+    ret = xmlSecXkmsServerCtxRequestAbstractTypeNodeRead(ctx, &cur);
+    if(ret < 0) {
+    	xmlSecError(XMLSEC_ERRORS_HERE,
+		    NULL,
+		    "xmlSecXkmsServerCtxRequestAbstractTypeNodeRead",
+		    XMLSEC_ERRORS_R_XMLSEC_FAILED,
+		    XMLSEC_ERRORS_NO_MESSAGE);
+	return(-1);
+    }
+
+    /* now read required <xkms:QueryKeyBinding/> node */
+    if((cur == NULL) || (!xmlSecCheckNodeName(cur, xmlSecNodeQueryKeyBinding, xmlSecXkmsNs))) {
+	xmlSecError(XMLSEC_ERRORS_HERE,
+		    NULL,
+		    xmlSecErrorsSafeString(xmlSecNodeGetName(cur)),
+		    XMLSEC_ERRORS_R_INVALID_NODE,
+		    "node=%s", 
+		    xmlSecErrorsSafeString(xmlSecNodeQueryKeyBinding));
+	return(-1);
+    }
+    
+    /* read <xkms:QueryKeyBinding/> node */    
+    ret = xmlSecXkmsServerCtxQueryKeyBindingNodeRead(ctx, cur);
+    if(ret < 0) {
+    	xmlSecError(XMLSEC_ERRORS_HERE,
+		    NULL,
+		    "xmlSecXkmsServerCtxQueryKeyBindingNodeRead",
+		    XMLSEC_ERRORS_R_XMLSEC_FAILED,
+		    XMLSEC_ERRORS_NO_MESSAGE);
+	return(-1);
+    }
+    cur = xmlSecGetNextElementNode(cur->next);    
+
+    /* check that there is nothing after the last node */
+    if(cur != NULL) {
+	xmlSecError(XMLSEC_ERRORS_HERE,
+		    NULL,
+		    xmlSecErrorsSafeString(xmlSecNodeGetName(cur)),
+		    XMLSEC_ERRORS_R_UNEXPECTED_NODE,
+		    XMLSEC_ERRORS_NO_MESSAGE);
+	return(-1);
+    }
+
+    return(0);
+}
+
+/**
+ *  <xkms:LocateResult Id Service Nonce? ResultMajor ResultMinor? RequestId?>
+ *      <ds:Signature>?
+ *      <xkms:MessageExtension>*
+ *      (<xkms:OpaqueClientData>
+ *          <xkms:OpaqueData>?
+ *      )?
+ *      <xkms:RequestSignatureValue>*
+ *      (<xkms:UnverifiedKeyBinding Id?>
+ *          <ds:KeyInfo>?
+ *          <xkms:KeyUsage>?
+ *          <xkms:KeyUsage>?
+ *          <xkms:KeyUsage>?
+ *          <xkms:UseKeyWith Application Identifier>*    
+ *          <xkms:ValidityInterval NotBefore NotOnOrAfter>?
+ *      )*
+ * 
+ * XML Schema:
+ *    <!-- LocateResult -->
+ *    <element name="LocateResult" type="xkms:LocateResultType"/>
+ *    <complexType name="LocateResultType">
+ *         <complexContent>
+ *	        <extension base="xkms:ResultType">
+ *		     <sequence>
+ *		         <element ref="xkms:UnverifiedKeyBinding" minOccurs="0" 
+ *			          maxOccurs="unbounded"/>
+ *		     </sequence>
+ *		</extension>
+ *	   </complexContent>
+ *    </complexType>
+ *    <!-- /LocateResult -->
+ */ 
+static int 
+xmlSecXkmsServerRequestLocateNodeWrite(xmlSecXkmsServerRequestId id, xmlSecXkmsServerCtxPtr ctx, xmlNodePtr node) {
+    xmlSecSize pos, size;
+    xmlSecKeyPtr key;
+    xmlNodePtr cur;
+    int ret;
+
+    xmlSecAssert2(id == xmlSecXkmsServerRequestLocateId, -1);
+    xmlSecAssert2(ctx != NULL, -1);
+    xmlSecAssert2(node != NULL, -1);
+
+    /* first write the "parent" type */
+    ret = xmlSecXkmsServerCtxResultTypeNodeWrite(ctx, node);
+    if(ret < 0) {
+	xmlSecError(XMLSEC_ERRORS_HERE,
+		    NULL,
+		    "xmlSecXkmsServerCtxResultTypeNodeWrite",
+		    XMLSEC_ERRORS_R_XMLSEC_FAILED,
+		    XMLSEC_ERRORS_NO_MESSAGE);
+	return(-1);  	
+    }
+    
+    /* write keys in <xkms:UnverifiedKeyBinding> nodes */
+    size = xmlSecPtrListGetSize(&(ctx->keys));
+    for(pos = 0; pos < size; ++pos) {
+	key = (xmlSecKeyPtr)xmlSecPtrListGetItem(&(ctx->keys), pos);
+	if(key == NULL) {
+	    continue;
+	}
+            
+	cur = xmlSecAddChild(node, xmlSecNodeUnverifiedKeyBinding, xmlSecXkmsNs);
+	if(cur == NULL) {
+	    xmlSecError(XMLSEC_ERRORS_HERE,
+			NULL,
+			"xmlSecAddChild",
+			XMLSEC_ERRORS_R_XMLSEC_FAILED,
+			"node=%s",
+			xmlSecErrorsSafeString(xmlSecNodeUnverifiedKeyBinding));
+	    return(-1);  	
+    	}
+
+	ret = xmlSecXkmsServerCtxUnverifiedKeyBindingNodeWrite(ctx, cur, key);
+	if(ret < 0) {
+	    xmlSecError(XMLSEC_ERRORS_HERE,
+			NULL,
+			"xmlSecXkmsServerCtxUnverifiedKeyBindingNodeWrite",
+			XMLSEC_ERRORS_R_XMLSEC_FAILED,
+			XMLSEC_ERRORS_NO_MESSAGE);
+	    return(-1);  	
+	}
+    }
+
+    return(0);
+}
+
+static int 
+xmlSecXkmsServerRequestLocateExecute(xmlSecXkmsServerRequestId id, xmlSecXkmsServerCtxPtr ctx) {
+    xmlSecKeyPtr key = NULL;
+    int ret;
+    
+    xmlSecAssert2(id == xmlSecXkmsServerRequestLocateId, -1);
+    xmlSecAssert2(ctx != NULL, -1);
+
+    /* now we are ready to search for key */
+    if((ctx->keyInfoReadCtx.keysMngr != NULL) && (ctx->keyInfoReadCtx.keysMngr->getKey != NULL)) {
+	key = (ctx->keyInfoReadCtx.keysMngr->getKey)(ctx->keyInfoNode, &(ctx->keyInfoReadCtx));
+    }
+    
+    /* check that we got what we needed */
+    if((key == NULL) || (!xmlSecKeyMatch(key, NULL, &(ctx->keyInfoReadCtx.keyReq)))) {
+	if(key != NULL) {
+    	    xmlSecKeyDestroy(key);
+	}
+	xmlSecXkmsServerCtxSetResult(ctx, xmlSecXkmsResultMajorSender, xmlSecXkmsResultMinorNoMatch);
+	return(-1);
+    } 
+        
+    xmlSecAssert2(key != NULL, -1);
+    ret = xmlSecPtrListAdd(&(ctx->keys), key);
+    if(ret < 0) {
+    	xmlSecError(XMLSEC_ERRORS_HERE,
+		    NULL,
+		    "xmlSecPtrListAdd",
+		    XMLSEC_ERRORS_R_XMLSEC_FAILED,
+		    XMLSEC_ERRORS_NO_MESSAGE);
+	xmlSecKeyDestroy(key);
+	return(-1);
+    }
+    
+    return(0);
+}
+
+
+/******************************************************************** 
+ *
+ * ValidateRequest/ValidateResponse
+ *
+ *******************************************************************/
+static int  		xmlSecXkmsServerRequestValidateNodeRead	(xmlSecXkmsServerRequestId id,
+								 xmlSecXkmsServerCtxPtr ctx,
+								 xmlNodePtr node);
+static int		xmlSecXkmsServerRequestValidateNodeWrite(xmlSecXkmsServerRequestId id,
+								 xmlSecXkmsServerCtxPtr ctx,
+								 xmlNodePtr node);
+static int 		xmlSecXkmsServerRequestValidateExecute	(xmlSecXkmsServerRequestId id, 
+								 xmlSecXkmsServerCtxPtr ctx);
+
+static xmlSecXkmsServerRequestKlass xmlSecXkmsServerRequestValidateKlass = {
+    xmlSecXkmsServerRequestValidateName,	/* const xmlChar* name; */
+    xmlSecNodeValidateRequest,			/* const xmlChar* requestNodeName; */
+    xmlSecXkmsNs,				/* const xmlChar* requestNodeNs; */
+    xmlSecNodeValidateResult,			/* const xmlChar* responseNodeName; */
+    xmlSecXkmsNs,				/* const xmlChar* responseNodeNs; */
+    XMLSEC_XKMS_SERVER_REQUEST_KLASS_ALLOWED_IN_COUMPOUND,      /* xmlSecBitMask flags; */
+    xmlSecXkmsServerRequestValidateNodeRead,	/* xmlSecXkmsServerRequestNodeReadMethod readNode; */
+    xmlSecXkmsServerRequestValidateNodeWrite,	/* xmlSecXkmsServerRequestNodeWriteMethod writeNode; */
+    xmlSecXkmsServerRequestValidateExecute,	/* xmlSecXkmsServerRequestExecuteMethod execute; */
+    NULL,                                       /* void* reserved1; */
+    NULL                                        /* void* reserved2; */
+};
+
+/**
+ * xmlSecXkmsServerRequestValidateGetKlass:
+ *
+ * The ValidateRequest klass.
+ *
+ * Returns ValidateRequest klass.
+ */
+EXPORT_C 
+xmlSecXkmsServerRequestId	
+xmlSecXkmsServerRequestValidateGetKlass(void) {
+    return(&xmlSecXkmsServerRequestValidateKlass);
+}
+
+/**
+ *  <xkms:ValidateRequest Id Service Nonce? OriginalRequestId? ResponseLimit?>
+ *      <ds:Signature>?
+ *      <xkms:MessageExtension>*
+ *      (<xkms:OpaqueClientData>
+ *          <xkms:OpaqueData>?
+ *      )?
+ *      <xkms:ResponseMechanism>*
+ *      <xkms:RespondWith>*
+ *      <xkms:PendingNotification Mechanism Identifier>?
+ *      <xkms:QueryKeyBinding Id?>
+ *          <ds:KeyInfo>?
+ *          <xkms:KeyUsage>?
+ *          <xkms:KeyUsage>?
+ *          <xkms:KeyUsage>?
+ *          <xkms:UseKeyWith Application Identifier>*    
+ *          <xkms:TimeInstant Time>?
+ * 
+ * XML Schema:
+ * 
+ *    <!-- ValidateRequest -->   
+ *    <element name="ValidateRequest" type="xkms:ValidateRequestType"/>   
+ *    <complexType name="ValidateRequestType">      
+ *        <complexContent>         
+ *            <extension base="xkms:RequestAbstractType">
+ *                <sequence>
+ *                    <element ref="xkms:QueryKeyBinding"/>
+ *                </sequence>
+ *            </extension>						         
+ *        </complexContent> 
+ *    </complexType>
+ *    <!-- /ValidateRequest -->							        
+ */
+static int  
+xmlSecXkmsServerRequestValidateNodeRead(xmlSecXkmsServerRequestId id, xmlSecXkmsServerCtxPtr ctx, xmlNodePtr node) {
+    xmlNodePtr cur;
+    int ret;
+    
+    xmlSecAssert2(id == xmlSecXkmsServerRequestValidateId, -1);
+    xmlSecAssert2(ctx != NULL, -1);
+    xmlSecAssert2(node != NULL, -1);
+
+    cur = node;
+    
+    /* first read "parent" type */
+    ret = xmlSecXkmsServerCtxRequestAbstractTypeNodeRead(ctx, &cur);
+    if(ret < 0) {
+    	xmlSecError(XMLSEC_ERRORS_HERE,
+		    NULL,
+		    "xmlSecXkmsServerCtxRequestAbstractTypeNodeRead",
+		    XMLSEC_ERRORS_R_XMLSEC_FAILED,
+		    XMLSEC_ERRORS_NO_MESSAGE);
+	return(-1);
+    }
+
+    /* now read required <xkms:QueryKeyBinding/> node */
+    if((cur == NULL) || (!xmlSecCheckNodeName(cur, xmlSecNodeQueryKeyBinding, xmlSecXkmsNs))) {
+	xmlSecError(XMLSEC_ERRORS_HERE,
+		    NULL,
+		    xmlSecErrorsSafeString(xmlSecNodeGetName(cur)),
+		    XMLSEC_ERRORS_R_INVALID_NODE,
+		    "node=%s", 
+		    xmlSecErrorsSafeString(xmlSecNodeQueryKeyBinding));
+	return(-1);
+    }
+    
+    /* read <xkms:QueryKeyBinding/> node */    
+    ret = xmlSecXkmsServerCtxQueryKeyBindingNodeRead(ctx, cur);
+    if(ret < 0) {
+    	xmlSecError(XMLSEC_ERRORS_HERE,
+		    NULL,
+		    "xmlSecXkmsServerCtxQueryKeyBindingNodeRead",
+		    XMLSEC_ERRORS_R_XMLSEC_FAILED,
+		    XMLSEC_ERRORS_NO_MESSAGE);
+	return(-1);
+    }
+    cur = xmlSecGetNextElementNode(cur->next);    
+
+    /* check that there is nothing after the last node */
+    if(cur != NULL) {
+	xmlSecError(XMLSEC_ERRORS_HERE,
+		    NULL,
+		    xmlSecErrorsSafeString(xmlSecNodeGetName(cur)),
+		    XMLSEC_ERRORS_R_UNEXPECTED_NODE,
+		    XMLSEC_ERRORS_NO_MESSAGE);
+	return(-1);
+    }
+
+    return(0);
+}
+
+/**
+ *  <xkms:ValidateResult Id Service Nonce? ResultMajor ResultMinor? RequestId?>
+ *      <ds:Signature>?
+ *      <xkms:MessageExtension>*
+ *      (<xkms:OpaqueClientData>
+ *           <xkms:OpaqueData>?
+ *      )?
+ *      <xkms:RequestSignatureValue>*
+ *      (<xkms:KeyBinding Id?>
+ *          <ds:KeyInfo>?
+ *          <xkms:KeyUsage>?
+ *          <xkms:KeyUsage>?
+ *          <xkms:KeyUsage>?
+ *          <xkms:UseKeyWith Application Identifier>*    
+ *          <xkms:ValidityInterval NotBefore NotOnOrAfter>?
+ *          <xkms:Status StatusValue>
+ *              (<xkms:ValidReason>?
+ *               <xkms:IndeterminateReason>?
+ *               <xkms:InvalidReason>?
+ *              )*
+ *      )*
+ * 
+ * XML Schema:
+ *
+ *    <!-- ValidateResult -->   
+ *    <element name="ValidateResult" type="xkms:ValidateResultType"/>
+ *    <complexType name="ValidateResultType">
+ *        <complexContent>
+ *            <extension base="xkms:ResultType">
+ *                <sequence>
+ *                    <element ref="xkms:KeyBinding" minOccurs="0" 
+ *				    maxOccurs="unbounded"/>
+ *                </sequence>
+ *            </extension>
+ *        </complexContent>
+ *    </complexType>
+ *    <!-- /ValidateResult -->
+ */ 
+static int 
+xmlSecXkmsServerRequestValidateNodeWrite(xmlSecXkmsServerRequestId id, xmlSecXkmsServerCtxPtr ctx, xmlNodePtr node) {
+    xmlSecSize pos, size;
+    xmlSecKeyPtr key;
+    xmlNodePtr cur;
+    int ret;
+
+    xmlSecAssert2(id == xmlSecXkmsServerRequestValidateId, -1);
+    xmlSecAssert2(ctx != NULL, -1);
+    xmlSecAssert2(node != NULL, -1);
+
+    /* first write the "parent" type */
+    ret = xmlSecXkmsServerCtxResultTypeNodeWrite(ctx, node);
+    if(ret < 0) {
+	xmlSecError(XMLSEC_ERRORS_HERE,
+		    NULL,
+		    "xmlSecXkmsServerCtxResultTypeNodeWrite",
+		    XMLSEC_ERRORS_R_XMLSEC_FAILED,
+		    XMLSEC_ERRORS_NO_MESSAGE);
+	return(-1);  	
+    }
+    
+    /* write keys in <xkms:UnverifiedKeyBinding> nodes */
+    size = xmlSecPtrListGetSize(&(ctx->keys));
+    for(pos = 0; pos < size; ++pos) {
+	key = (xmlSecKeyPtr)xmlSecPtrListGetItem(&(ctx->keys), pos);
+	if(key == NULL) {
+	    continue;
+	}
+            
+	cur = xmlSecAddChild(node, xmlSecNodeUnverifiedKeyBinding, xmlSecXkmsNs);
+	if(cur == NULL) {
+	    xmlSecError(XMLSEC_ERRORS_HERE,
+			NULL,
+			"xmlSecAddChild",
+			XMLSEC_ERRORS_R_XMLSEC_FAILED,
+			"node=%s",
+			xmlSecErrorsSafeString(xmlSecNodeUnverifiedKeyBinding));
+	    return(-1);  	
+    	}
+
+	ret = xmlSecXkmsServerCtxKeyBindingNodeWrite(ctx, cur, key);
+	if(ret < 0) {
+	    xmlSecError(XMLSEC_ERRORS_HERE,
+			NULL,
+			"xmlSecXkmsServerCtxKeyBindingNodeWrite",
+			XMLSEC_ERRORS_R_XMLSEC_FAILED,
+			XMLSEC_ERRORS_NO_MESSAGE);
+	    return(-1);  	
+	}
+    }
+
+    return(0);
+}
+
+static int 
+xmlSecXkmsServerRequestValidateExecute(xmlSecXkmsServerRequestId id, xmlSecXkmsServerCtxPtr ctx) {
+    xmlSecKeyPtr key = NULL;
+    int ret;
+    
+    xmlSecAssert2(id == xmlSecXkmsServerRequestValidateId, -1);
+    xmlSecAssert2(ctx != NULL, -1);
+
+    /* now we are ready to search for key */
+    if((ctx->keyInfoReadCtx.keysMngr != NULL) && (ctx->keyInfoReadCtx.keysMngr->getKey != NULL)) {
+	key = (ctx->keyInfoReadCtx.keysMngr->getKey)(ctx->keyInfoNode, &(ctx->keyInfoReadCtx));
+    }
+    
+    /* check that we got what we needed */
+    if((key == NULL) || (!xmlSecKeyMatch(key, NULL, &(ctx->keyInfoReadCtx.keyReq)))) {
+	if(key != NULL) {
+    	    xmlSecKeyDestroy(key);
+	}
+	xmlSecXkmsServerCtxSetResult(ctx, xmlSecXkmsResultMajorSender, xmlSecXkmsResultMinorNoMatch);
+	return(-1);
+    } 
+        
+    xmlSecAssert2(key != NULL, -1);
+    ret = xmlSecPtrListAdd(&(ctx->keys), key);
+    if(ret < 0) {
+    	xmlSecError(XMLSEC_ERRORS_HERE,
+		    NULL,
+		    "xmlSecPtrListAdd",
+		    XMLSEC_ERRORS_R_XMLSEC_FAILED,
+		    XMLSEC_ERRORS_NO_MESSAGE);
+	xmlSecKeyDestroy(key);
+	return(-1);
+    }
+    
+    return(0);
+}
+
+#endif /* XMLSEC_NO_XKMS */
+