xmlsecurityengine/xmlsec/src/xmlsec_xmldsig.c
changeset 0 e35f40988205
child 16 d10d750052f0
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/xmlsecurityengine/xmlsec/src/xmlsec_xmldsig.c	Thu Dec 17 09:29:21 2009 +0200
@@ -0,0 +1,1824 @@
+/** 
+ * XML Security Library (http://www.aleksey.com/xmlsec).
+ *
+ * "XML Digital Signature" implementation
+ *  http://www.w3.org/TR/xmldsig-core/
+ *  http://www.w3.org/Signature/Overview.html
+ * 
+ * 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_XMLDSIG
+#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_membuf.h"
+#include "xmlsec_xmldsig.h"
+#include "xmlsec_errors.h"
+
+/**************************************************************************
+ *
+ * xmlSecDSigCtx
+ *
+ *************************************************************************/
+static int	xmlSecDSigCtxProcessSignatureNode	(xmlSecDSigCtxPtr dsigCtx, 
+							 xmlNodePtr node);
+static int	xmlSecDSigCtxProcessSignedInfoNode	(xmlSecDSigCtxPtr dsigCtx, 
+							 xmlNodePtr node);
+static int	xmlSecDSigCtxProcessKeyInfoNode		(xmlSecDSigCtxPtr dsigCtx, 
+							 xmlNodePtr node);
+static int	xmlSecDSigCtxProcessObjectNode		(xmlSecDSigCtxPtr dsigCtx, 
+							 xmlNodePtr node);
+static int	xmlSecDSigCtxProcessManifestNode	(xmlSecDSigCtxPtr dsigCtx, 
+							 xmlNodePtr node);
+
+/* The ID attribute in XMLDSig is 'Id' */
+static const xmlChar*		xmlSecDSigIds[] = { xmlSecAttrId, NULL };
+
+/**
+ * xmlSecDSigCtxCreate:
+ * @keysMngr: 		the pointer to keys manager.
+ *
+ * Creates <dsig:Signature/> element processing context.
+ * The caller is responsible for destroying returend object by calling 
+ * #xmlSecDSigCtxDestroy function.
+ *
+ * Returns pointer to newly allocated context object or NULL if an error
+ * occurs.
+ */
+EXPORT_C
+xmlSecDSigCtxPtr	
+xmlSecDSigCtxCreate(xmlSecKeysMngrPtr keysMngr) {
+    xmlSecDSigCtxPtr dsigCtx;
+    int ret;
+    
+    dsigCtx = (xmlSecDSigCtxPtr) xmlMalloc(sizeof(xmlSecDSigCtx));
+    if(dsigCtx == NULL) {
+	xmlSecError(XMLSEC_ERRORS_HERE,
+		    NULL,
+		    NULL,
+		    XMLSEC_ERRORS_R_MALLOC_FAILED,
+		    "sizeof(xmlSecDSigCtx)=%d", 
+		    sizeof(xmlSecDSigCtx));
+	return(NULL);
+    }
+    
+    ret = xmlSecDSigCtxInitialize(dsigCtx, keysMngr);
+    if(ret < 0) {
+	xmlSecError(XMLSEC_ERRORS_HERE,
+		    NULL,
+		    "xmlSecDSigCtxInitialize",
+		    XMLSEC_ERRORS_R_XMLSEC_FAILED,
+		    XMLSEC_ERRORS_NO_MESSAGE);
+	xmlSecDSigCtxDestroy(dsigCtx);
+	return(NULL);   
+    }
+    return(dsigCtx);    
+}
+
+/**
+ * xmlSecDSigCtxDestroy:
+ * @dsigCtx:		the pointer to <dsig:Signature/> processing context.
+ *
+ * Destroy context object created with #xmlSecDSigCtxCreate function.
+ */
+EXPORT_C
+void  
+xmlSecDSigCtxDestroy(xmlSecDSigCtxPtr dsigCtx) {
+    xmlSecAssert(dsigCtx != NULL);
+    
+    xmlSecDSigCtxFinalize(dsigCtx);
+    xmlFree(dsigCtx);
+}
+
+/**
+ * xmlSecDSigCtxInitialize:
+ * @dsigCtx:		the pointer to <dsig:Signature/> processing context.
+ * @keysMngr: 		the pointer to keys manager.
+ *
+ * Initializes <dsig:Signature/> element processing context.
+ * The caller is responsible for cleaing up returend object by calling 
+ * #xmlSecDSigCtxFinalize function.
+ *
+ * Returns 0 on success or a negative value if an error occurs.
+ */
+EXPORT_C
+int 
+xmlSecDSigCtxInitialize(xmlSecDSigCtxPtr dsigCtx, xmlSecKeysMngrPtr keysMngr) {
+    int ret;
+    
+    xmlSecAssert2(dsigCtx != NULL, -1);
+    
+    memset(dsigCtx, 0, sizeof(xmlSecDSigCtx));
+
+    /* initialize key info */
+    ret = xmlSecKeyInfoCtxInitialize(&(dsigCtx->keyInfoReadCtx), keysMngr);
+    if(ret < 0) {
+	xmlSecError(XMLSEC_ERRORS_HERE,
+		    NULL,
+		    "xmlSecKeyInfoCtxInitialize",
+		    XMLSEC_ERRORS_R_XMLSEC_FAILED,
+		    XMLSEC_ERRORS_NO_MESSAGE);
+	return(-1);   
+    }
+    dsigCtx->keyInfoReadCtx.mode = xmlSecKeyInfoModeRead;
+    
+    ret = xmlSecKeyInfoCtxInitialize(&(dsigCtx->keyInfoWriteCtx), keysMngr);
+    if(ret < 0) {
+	xmlSecError(XMLSEC_ERRORS_HERE,
+		    NULL,
+		    "xmlSecKeyInfoCtxInitialize",
+		    XMLSEC_ERRORS_R_XMLSEC_FAILED,
+		    XMLSEC_ERRORS_NO_MESSAGE);
+	return(-1);   
+    }
+    dsigCtx->keyInfoWriteCtx.mode = xmlSecKeyInfoModeWrite;
+    /* it's not wise to write private key :) */
+    dsigCtx->keyInfoWriteCtx.keyReq.keyType = xmlSecKeyDataTypePublic;
+
+    /* initializes transforms dsigCtx */
+    ret = xmlSecTransformCtxInitialize(&(dsigCtx->transformCtx));
+    if(ret < 0) {
+	xmlSecError(XMLSEC_ERRORS_HERE,
+		    NULL,
+		    "xmlSecTransformCtxInitialize",
+		    XMLSEC_ERRORS_R_XMLSEC_FAILED,
+		    XMLSEC_ERRORS_NO_MESSAGE);
+	return(-1);   
+    }
+
+    /* references lists from SignedInfo and Manifest elements */
+    xmlSecPtrListInitialize(&(dsigCtx->signedInfoReferences), 
+			    xmlSecDSigReferenceCtxListId);
+    xmlSecPtrListInitialize(&(dsigCtx->manifestReferences), 
+			    xmlSecDSigReferenceCtxListId);    
+
+    dsigCtx->enabledReferenceUris = xmlSecTransformUriTypeAny;
+    return(0);
+}
+
+/**
+ * xmlSecDSigCtxFinalize:
+ * @dsigCtx:		the pointer to <dsig:Signature/> processing context.
+ *
+ * Cleans up @dsigCtx object initialized with #xmlSecDSigCtxInitialize function.
+ */
+EXPORT_C
+void 
+xmlSecDSigCtxFinalize(xmlSecDSigCtxPtr dsigCtx) {
+    xmlSecAssert(dsigCtx != NULL);
+
+    xmlSecTransformCtxFinalize(&(dsigCtx->transformCtx));
+    xmlSecKeyInfoCtxFinalize(&(dsigCtx->keyInfoReadCtx));
+    xmlSecKeyInfoCtxFinalize(&(dsigCtx->keyInfoWriteCtx));
+    xmlSecPtrListFinalize(&(dsigCtx->signedInfoReferences));
+    xmlSecPtrListFinalize(&(dsigCtx->manifestReferences));
+
+    if(dsigCtx->enabledReferenceTransforms != NULL) {
+	xmlSecPtrListDestroy(dsigCtx->enabledReferenceTransforms);	
+    }
+    if(dsigCtx->signKey != NULL) {
+	xmlSecKeyDestroy(dsigCtx->signKey);
+    }
+    if(dsigCtx->id != NULL) {
+	xmlFree(dsigCtx->id);
+    }	
+    memset(dsigCtx, 0, sizeof(xmlSecDSigCtx));
+}
+
+/**
+ * xmlSecDSigCtxEnableReferenceTransform:
+ * @dsigCtx:		the pointer to <dsig:Signature/> processing context.
+ * @transformId:	the transform klass.
+ *
+ * Enables @transformId for <dsig:Reference/> elements processing.
+ *
+ * Returns 0 on success or a negative value if an error occurs.
+ */
+EXPORT_C
+int 
+xmlSecDSigCtxEnableReferenceTransform(xmlSecDSigCtxPtr dsigCtx, xmlSecTransformId transformId) {
+    int ret;
+    
+    xmlSecAssert2(dsigCtx != NULL, -1);
+    xmlSecAssert2(dsigCtx->result == NULL, -1);
+    xmlSecAssert2(transformId != xmlSecTransformIdUnknown, -1);
+
+    if(dsigCtx->enabledReferenceTransforms == NULL) {
+	dsigCtx->enabledReferenceTransforms = xmlSecPtrListCreate(xmlSecTransformIdListId);
+	if(dsigCtx->enabledReferenceTransforms == NULL) {
+	    xmlSecError(XMLSEC_ERRORS_HERE,
+			NULL,
+			"xmlSecPtrListCreate",
+			XMLSEC_ERRORS_R_XMLSEC_FAILED,
+			XMLSEC_ERRORS_NO_MESSAGE);
+	    return(-1);   
+	}
+    }	
+	
+    ret = xmlSecPtrListAdd(dsigCtx->enabledReferenceTransforms, (void*)transformId);
+    if(ret < 0) {
+	xmlSecError(XMLSEC_ERRORS_HERE,
+		    NULL,
+		    "xmlSecPtrListAdd",
+		    XMLSEC_ERRORS_R_XMLSEC_FAILED,
+		    XMLSEC_ERRORS_NO_MESSAGE);
+	return(-1);   
+    }
+    return(0);
+}
+
+/**
+ * xmlSecDSigCtxEnableSignatureTransform:
+ * @dsigCtx:		the pointer to <dsig:Signature/> processing context.
+ * @transformId:	the transform klass.
+ *
+ * Enables @transformId for <dsig:SignedInfo/> element processing.
+ *
+ * Returns 0 on success or a negative value if an error occurs.
+ */
+EXPORT_C
+int 
+xmlSecDSigCtxEnableSignatureTransform(xmlSecDSigCtxPtr dsigCtx, xmlSecTransformId transformId) {
+    xmlSecAssert2(dsigCtx != NULL, -1);
+    xmlSecAssert2(dsigCtx->result == NULL, -1);
+    xmlSecAssert2(transformId != xmlSecTransformIdUnknown, -1);
+
+    return(xmlSecPtrListAdd(&(dsigCtx->transformCtx.enabledTransforms), (void*)transformId));
+}
+
+/**
+ * xmlSecDSigCtxGetPreSignBuffer:
+ * @dsigCtx:		the pointer to <dsig:Signature/> processing context.
+ * 
+ * Gets pointer to the buffer with serialized <dsig:SignedInfo/> element
+ * just before signature claculation (valid if and only if 
+ * #XMLSEC_DSIG_FLAGS_STORE_SIGNATURE context flag is set.
+ *
+ * Returns 0 on success or a negative value if an error occurs.
+ */
+EXPORT_C
+xmlSecBufferPtr 
+xmlSecDSigCtxGetPreSignBuffer(xmlSecDSigCtxPtr dsigCtx) {
+    xmlSecAssert2(dsigCtx != NULL, NULL);
+    
+    return((dsigCtx->preSignMemBufMethod != NULL) ? 
+	    xmlSecTransformMemBufGetBuffer(dsigCtx->preSignMemBufMethod) : NULL);
+}
+
+/**
+ * xmlSecDSigCtxSign:
+ * @dsigCtx:		the pointer to <dsig:Signature/> processing context.
+ * @tmpl:		the pointer to <dsig:Signature/> node with signature template.
+ *
+ * Signs the data as described in @tmpl node.
+ *
+ * Returns 0 on success or a negative value if an error occurs.
+ */
+EXPORT_C
+int 
+xmlSecDSigCtxSign(xmlSecDSigCtxPtr dsigCtx, xmlNodePtr tmpl) {
+    int ret;
+    
+    xmlSecAssert2(dsigCtx != NULL, -1);
+    xmlSecAssert2(dsigCtx->result == NULL, -1);
+    xmlSecAssert2(tmpl != NULL, -1);
+    xmlSecAssert2(tmpl->doc != NULL, -1);
+
+    /* add ids for Signature nodes */
+    dsigCtx->operation 	= xmlSecTransformOperationSign;
+    dsigCtx->status 	= xmlSecDSigStatusUnknown;
+    xmlSecAddIDs(tmpl->doc, tmpl, xmlSecDSigIds);
+
+    /* read signature template */
+    ret = xmlSecDSigCtxProcessSignatureNode(dsigCtx, tmpl);
+    if(ret < 0) {
+    	xmlSecError(XMLSEC_ERRORS_HERE,
+		    NULL,
+		    "xmlSecDSigCtxSigantureProcessNode",
+		    XMLSEC_ERRORS_R_XMLSEC_FAILED,
+		    XMLSEC_ERRORS_NO_MESSAGE);
+	return(-1);
+    }
+    xmlSecAssert2(dsigCtx->signMethod != NULL, -1);
+    xmlSecAssert2(dsigCtx->signValueNode != NULL, -1);
+
+    /* references processing might change the status */
+    if(dsigCtx->status != xmlSecDSigStatusUnknown) {
+	return(0);
+    }
+
+    /* check what we've got */
+    dsigCtx->result = dsigCtx->transformCtx.result;
+    if((dsigCtx->result == NULL) || (xmlSecBufferGetData(dsigCtx->result) == NULL)) {
+    	xmlSecError(XMLSEC_ERRORS_HERE,
+		    NULL,
+		    NULL,
+		    XMLSEC_ERRORS_R_INVALID_RESULT,
+		    XMLSEC_ERRORS_NO_MESSAGE);
+	return(-1);
+    }
+
+    /* write signed data to xml */
+    xmlNodeSetContentLen(dsigCtx->signValueNode,
+			    xmlSecBufferGetData(dsigCtx->result),
+			    xmlSecBufferGetSize(dsigCtx->result));
+    if ( OOM_FLAG )
+        {
+        return(-1);
+        }
+    
+    /* set success status and we are done */
+    dsigCtx->status = xmlSecDSigStatusSucceeded;
+    return(0);    
+}
+
+/**
+ * xmlSecDSigCtxVerify:
+ * @dsigCtx:		the pointer to <dsig:Signature/> processing context.
+ * @node:		the pointer with <dsig:Signature/> node.
+ * 
+ * Vaidates signature in the @node. The verification result is returned
+ * in #status member of the @dsigCtx object.
+ *
+ * Returns 0 on success (check #status member of @dsigCtx to get 
+ * signature verification result) or a negative value if an error occurs.
+ */
+EXPORT_C
+int 
+xmlSecDSigCtxVerify(xmlSecDSigCtxPtr dsigCtx, xmlNodePtr node) {
+    int ret;
+    
+    xmlSecAssert2(dsigCtx != NULL, -1);
+    xmlSecAssert2(node != NULL, -1);
+    xmlSecAssert2(node->doc != NULL, -1);
+
+    /* add ids for Signature nodes */
+    dsigCtx->operation 	= xmlSecTransformOperationVerify;
+    dsigCtx->status 	= xmlSecDSigStatusUnknown;
+    xmlSecAddIDs(node->doc, node, xmlSecDSigIds);
+    
+    /* read siganture info */
+    ret = xmlSecDSigCtxProcessSignatureNode(dsigCtx, node);
+    if(ret < 0) {
+    	xmlSecError(XMLSEC_ERRORS_HERE,
+		    NULL,
+		    "xmlSecDSigCtxSigantureProcessNode",
+		    XMLSEC_ERRORS_R_XMLSEC_FAILED,
+		    XMLSEC_ERRORS_NO_MESSAGE);
+	return(-1);
+    }
+    xmlSecAssert2(dsigCtx->signMethod != NULL, -1);
+    xmlSecAssert2(dsigCtx->signValueNode != NULL, -1);
+
+    /* references processing might change the status */
+    if(dsigCtx->status != xmlSecDSigStatusUnknown) {
+	return(0);
+    }
+
+    /* verify SignatureValue node content */
+    ret = xmlSecTransformVerifyNodeContent(dsigCtx->signMethod, dsigCtx->signValueNode,
+					   &(dsigCtx->transformCtx));
+    if(ret < 0) {
+    	xmlSecError(XMLSEC_ERRORS_HERE,
+		    NULL,
+		    "xmlSecTransformVerifyNodeContent",
+		    XMLSEC_ERRORS_R_XMLSEC_FAILED,
+		    XMLSEC_ERRORS_NO_MESSAGE);
+	return(-1);
+    }
+    
+    /* set status and we are done */
+    if(dsigCtx->signMethod->status == xmlSecTransformStatusOk) {
+        dsigCtx->status = xmlSecDSigStatusSucceeded;
+    } else {
+        dsigCtx->status = xmlSecDSigStatusInvalid;
+    }
+    return(0);
+}
+
+/**
+ * xmlSecDSigCtxProcessSignatureNode:
+ *
+ * The Signature  element (http://www.w3.org/TR/xmldsig-core/#sec-Signature)
+ *
+ * The Signature element is the root element of an XML Signature. 
+ * Implementation MUST generate laxly schema valid [XML-schema] Signature 
+ * elements as specified by the following schema:
+ * The way in which the SignedInfo element is presented to the 
+ * canonicalization method is dependent on that method. The following 
+ * applies to algorithms which process XML as nodes or characters:
+ *
+ *  - XML based canonicalization implementations MUST be provided with 
+ *  a [XPath] node-set originally formed from the document containing 
+ *  the SignedInfo and currently indicating the SignedInfo, its descendants,
+ *  and the attribute and namespace nodes of SignedInfo and its descendant 
+ *  elements.
+ *
+ *  - Text based canonicalization algorithms (such as CRLF and charset 
+ *  normalization) should be provided with the UTF-8 octets that represent 
+ *  the well-formed SignedInfo element, from the first character to the 
+ *  last character of the XML representation, inclusive. This includes 
+ *  the entire text of the start and end tags of the SignedInfo element 
+ *  as well as all descendant markup and character data (i.e., the text) 
+ *  between those tags. Use of text based canonicalization of SignedInfo 
+ *  is NOT RECOMMENDED.   	     
+ *
+ *  =================================
+ *  we do not support any non XML based C14N 
+ *
+ * Schema Definition:
+ *
+ *  <element name="Signature" type="ds:SignatureType"/>
+ *  <complexType name="SignatureType">
+ *  <sequence> 
+ *     <element ref="ds:SignedInfo"/> 
+ *     <element ref="ds:SignatureValue"/> 
+ *     <element ref="ds:KeyInfo" minOccurs="0"/> 
+ *     <element ref="ds:Object" minOccurs="0" maxOccurs="unbounded"/> 
+ *     </sequence> <attribute name="Id" type="ID" use="optional"/>
+ *  </complexType>
+ *    
+ * DTD:
+ *    
+ *  <!ELEMENT Signature (SignedInfo, SignatureValue, KeyInfo?, Object*)  >
+ *  <!ATTLIST Signature  
+ *      xmlns   CDATA   #FIXED 'http://www.w3.org/2000/09/xmldsig#'
+ *      Id      ID  #IMPLIED >
+ *
+ */
+static int
+xmlSecDSigCtxProcessSignatureNode(xmlSecDSigCtxPtr dsigCtx, xmlNodePtr node) {
+    xmlSecTransformDataType firstType;
+    xmlNodePtr signedInfoNode = NULL;
+    xmlNodePtr keyInfoNode = NULL;
+    xmlNodePtr cur;
+    int ret;
+    
+    xmlSecAssert2(dsigCtx != NULL, -1);
+    xmlSecAssert2((dsigCtx->operation == xmlSecTransformOperationSign) || (dsigCtx->operation == xmlSecTransformOperationVerify), -1);
+    xmlSecAssert2(dsigCtx->status == xmlSecDSigStatusUnknown, -1);
+    xmlSecAssert2(dsigCtx->signValueNode == NULL, -1);
+    xmlSecAssert2(dsigCtx->signMethod == NULL, -1);
+    xmlSecAssert2(dsigCtx->c14nMethod == NULL, -1);
+    xmlSecAssert2(node != NULL, -1);
+
+    if(!xmlSecCheckNodeName(node, xmlSecNodeSignature, xmlSecDSigNs)) {
+    	xmlSecError(XMLSEC_ERRORS_HERE,
+		    NULL,
+		    xmlSecErrorsSafeString(xmlSecNodeGetName(node)),
+		    XMLSEC_ERRORS_R_INVALID_NODE,
+		    "expected=%s",
+		    xmlSecErrorsSafeString(xmlSecNodeSignature));
+	return(-1);	    
+    }
+
+    /* read node data */
+    xmlSecAssert2(dsigCtx->id == NULL, -1);
+    dsigCtx->id = xmlGetProp(node, xmlSecAttrId);
+
+    /* first node is required SignedInfo */
+    cur = xmlSecGetNextElementNode(node->children);    
+    if((cur == NULL) || (!xmlSecCheckNodeName(cur, xmlSecNodeSignedInfo, xmlSecDSigNs))) {
+    	xmlSecError(XMLSEC_ERRORS_HERE,
+		    NULL,
+		    xmlSecErrorsSafeString(xmlSecNodeGetName(cur)),
+		    XMLSEC_ERRORS_R_INVALID_NODE,
+		    "expected=%s",
+		    xmlSecErrorsSafeString(xmlSecNodeSignedInfo));
+        return(-1);
+    }
+    signedInfoNode = cur;
+    cur = xmlSecGetNextElementNode(cur->next);
+
+    /* next node is required SignatureValue */
+    if((cur == NULL) || (!xmlSecCheckNodeName(cur, xmlSecNodeSignatureValue, xmlSecDSigNs))) {
+    	xmlSecError(XMLSEC_ERRORS_HERE,
+		    NULL,
+		    xmlSecErrorsSafeString(xmlSecNodeGetName(cur)),
+		    XMLSEC_ERRORS_R_INVALID_NODE,
+		    "expected=%s",
+		    xmlSecErrorsSafeString(xmlSecNodeSignatureValue));
+	return(-1);
+    }
+    dsigCtx->signValueNode = cur;
+    cur = xmlSecGetNextElementNode(cur->next);
+
+    /* next node is optional KeyInfo */
+    if((cur != NULL) && (xmlSecCheckNodeName(cur, xmlSecNodeKeyInfo, xmlSecDSigNs))) {
+	keyInfoNode = cur;
+	cur = xmlSecGetNextElementNode(cur->next);
+    } else {
+	keyInfoNode = NULL;
+    }
+    
+    /* next nodes are optional Object nodes */
+    while((cur != NULL) && (xmlSecCheckNodeName(cur, xmlSecNodeObject, xmlSecDSigNs))) {
+	/* read manifests from objects */
+	if((dsigCtx->flags & XMLSEC_DSIG_FLAGS_IGNORE_MANIFESTS) == 0) {
+	    ret = xmlSecDSigCtxProcessObjectNode(dsigCtx, cur);
+	    if(ret < 0) {
+    		xmlSecError(XMLSEC_ERRORS_HERE,
+			    NULL,
+			    "xmlSecDSigCtxProcessObjectNode",
+			    XMLSEC_ERRORS_R_XMLSEC_FAILED,
+			    XMLSEC_ERRORS_NO_MESSAGE);
+		return(-1);	    	    
+	    }
+	}
+	cur = xmlSecGetNextElementNode(cur->next);
+    }
+    
+    /* if there is something left than it's an error */
+    if(cur != NULL) {
+    	xmlSecError(XMLSEC_ERRORS_HERE,
+		    NULL,
+		    xmlSecErrorsSafeString(xmlSecNodeGetName(cur)),
+		    XMLSEC_ERRORS_R_UNEXPECTED_NODE,
+		    XMLSEC_ERRORS_NO_MESSAGE);
+	return(-1);
+    }
+
+    /* now validated all the references and prepare transform */
+    ret = xmlSecDSigCtxProcessSignedInfoNode(dsigCtx, signedInfoNode);
+    if(ret < 0) {
+    	xmlSecError(XMLSEC_ERRORS_HERE,
+		    NULL,
+		    "xmlSecDSigCtxProcessSignedInfoNode",
+		    XMLSEC_ERRORS_R_XMLSEC_FAILED,
+		    XMLSEC_ERRORS_NO_MESSAGE);
+	return(-1);	
+    }				
+    /* references processing might change the status */
+    if(dsigCtx->status != xmlSecDSigStatusUnknown) {
+	return(0);
+    }
+    
+    /* as the result, we should have sign and c14n methods set */    
+    xmlSecAssert2(dsigCtx->signMethod != NULL, -1);
+    xmlSecAssert2(dsigCtx->c14nMethod != NULL, -1);
+
+    ret = xmlSecDSigCtxProcessKeyInfoNode(dsigCtx, keyInfoNode);
+    if(ret < 0) {
+    	xmlSecError(XMLSEC_ERRORS_HERE,
+		    NULL,
+		    "xmlSecDSigCtxProcessKeyInfoNode",
+		    XMLSEC_ERRORS_R_XMLSEC_FAILED,
+		    XMLSEC_ERRORS_NO_MESSAGE);
+	return(-1);	
+    }				
+    /* as the result, we should have a key */
+    xmlSecAssert2(dsigCtx->signKey != NULL, -1);
+
+    /* if we need to write result to xml node then we need base64 encode result */
+    if(dsigCtx->operation == xmlSecTransformOperationSign) {	
+	xmlSecTransformPtr base64Encode;
+	
+	/* we need to add base64 encode transform */
+	base64Encode = xmlSecTransformCtxCreateAndAppend(&(dsigCtx->transformCtx), 
+							 xmlSecTransformBase64Id);
+    	if(base64Encode == NULL) {
+    	    xmlSecError(XMLSEC_ERRORS_HERE,
+			NULL,
+			"xmlSecTransformCtxCreateAndAppend",
+			XMLSEC_ERRORS_R_XMLSEC_FAILED,
+			XMLSEC_ERRORS_NO_MESSAGE);
+	    return(-1);
+	}
+	base64Encode->operation = xmlSecTransformOperationEncode;
+    }
+
+    firstType = xmlSecTransformGetDataType(dsigCtx->transformCtx.first, 
+					   xmlSecTransformModePush, 
+					   &(dsigCtx->transformCtx));
+    if((firstType & xmlSecTransformDataTypeXml) != 0) {
+	xmlSecNodeSetPtr nodeset = NULL;
+
+	xmlSecAssert2(signedInfoNode != NULL, -1);
+        nodeset = xmlSecNodeSetGetChildren(signedInfoNode->doc, signedInfoNode, 1, 0);
+	if(nodeset == NULL) {
+    	    xmlSecError(XMLSEC_ERRORS_HERE,
+			NULL,
+			"xmlSecNodeSetGetChildren",
+			XMLSEC_ERRORS_R_XMLSEC_FAILED,
+			"node=%s",
+		        xmlSecErrorsSafeString(xmlSecNodeGetName(signedInfoNode)));
+	    return(-1);
+	}
+
+	/* calculate the signature */
+	ret = xmlSecTransformCtxXmlExecute(&(dsigCtx->transformCtx), nodeset);
+	if(ret < 0) {
+    	    xmlSecError(XMLSEC_ERRORS_HERE,
+		        NULL,
+			"xmlSecTransformCtxXmlExecute",
+		        XMLSEC_ERRORS_R_XMLSEC_FAILED,
+			XMLSEC_ERRORS_NO_MESSAGE);
+	    xmlSecNodeSetDestroy(nodeset);
+	    return(-1);
+	}
+	xmlSecNodeSetDestroy(nodeset);
+    } else {
+    	xmlSecError(XMLSEC_ERRORS_HERE,
+		    NULL,
+		    "the binary c14n transforms are not supported yet",
+		    XMLSEC_ERRORS_R_NOT_IMPLEMENTED,
+		    XMLSEC_ERRORS_NO_MESSAGE);
+	return(-1);
+    }
+    return(0);
+}
+
+/** 
+ * xmlSecDSigCtxProcessSignedInfoNode:
+ *
+ * The SignedInfo Element (http://www.w3.org/TR/xmldsig-core/#sec-SignedInfo)
+ * 
+ * The structure of SignedInfo includes the canonicalization algorithm, 
+ * a result algorithm, and one or more references. The SignedInfo element 
+ * may contain an optional ID attribute that will allow it to be referenced by 
+ * other signatures and objects.
+ *
+ * SignedInfo does not include explicit result or digest properties (such as
+ * calculation time, cryptographic device serial number, etc.). If an 
+ * application needs to associate properties with the result or digest, 
+ * it may include such information in a SignatureProperties element within 
+ * an Object element.
+ *
+ * Schema Definition:
+ *
+ *  <element name="SignedInfo" type="ds:SignedInfoType"/> 
+ *  <complexType name="SignedInfoType">
+ *    <sequence> 
+ *      <element ref="ds:CanonicalizationMethod"/>
+ *      <element ref="ds:SignatureMethod"/> 
+ *      <element ref="ds:Reference" maxOccurs="unbounded"/> 
+ *    </sequence> 
+ *    <attribute name="Id" type="ID" use="optional"/> 
+ *  </complexType>
+ *    
+ * DTD:
+ *    
+ *  <!ELEMENT SignedInfo (CanonicalizationMethod, SignatureMethod,  Reference+) >
+ *  <!ATTLIST SignedInfo  Id   ID      #IMPLIED>
+ * 
+ */
+static int 
+xmlSecDSigCtxProcessSignedInfoNode(xmlSecDSigCtxPtr dsigCtx, xmlNodePtr node) {
+    xmlSecDSigReferenceCtxPtr dsigRefCtx;
+    xmlNodePtr cur;
+    int ret;
+    
+    xmlSecAssert2(dsigCtx != NULL, -1);	
+    xmlSecAssert2(dsigCtx->status == xmlSecDSigStatusUnknown, -1);
+    xmlSecAssert2(dsigCtx->signMethod == NULL, -1);
+    xmlSecAssert2(dsigCtx->c14nMethod == NULL, -1);
+    xmlSecAssert2((dsigCtx->operation == xmlSecTransformOperationSign) || (dsigCtx->operation == xmlSecTransformOperationVerify), -1);
+    xmlSecAssert2(xmlSecPtrListGetSize(&(dsigCtx->signedInfoReferences)) == 0, -1);
+    xmlSecAssert2(node != NULL, -1);
+    
+    /* first node is required CanonicalizationMethod. */
+    cur = xmlSecGetNextElementNode(node->children);
+    if((cur != NULL) && (xmlSecCheckNodeName(cur, xmlSecNodeCanonicalizationMethod, xmlSecDSigNs))) {
+	dsigCtx->c14nMethod = xmlSecTransformCtxNodeRead(&(dsigCtx->transformCtx), 
+					cur, xmlSecTransformUsageC14NMethod);
+	if(dsigCtx->c14nMethod == NULL) {
+	    xmlSecError(XMLSEC_ERRORS_HERE,
+			NULL,
+			"xmlSecTransformCtxNodeRead",
+			XMLSEC_ERRORS_R_XMLSEC_FAILED,
+			"node=%s",
+			xmlSecErrorsSafeString(xmlSecNodeGetName(cur)));
+	    return(-1);	
+	}	
+    } else if(dsigCtx->defC14NMethodId != xmlSecTransformIdUnknown) {
+	/* the dsig spec does require CanonicalizationMethod node
+	 * to be present but in some case it application might decide to
+	 * minimize traffic */
+	dsigCtx->c14nMethod = xmlSecTransformCtxCreateAndAppend(&(dsigCtx->transformCtx), 
+							      dsigCtx->defC14NMethodId);
+	if(dsigCtx->c14nMethod == NULL) {
+    	    xmlSecError(XMLSEC_ERRORS_HERE,
+			NULL,
+			"xmlSecTransformCtxAppend",
+			XMLSEC_ERRORS_R_XMLSEC_FAILED,
+			XMLSEC_ERRORS_NO_MESSAGE);
+	    return(-1);
+	}
+    } else {
+    	xmlSecError(XMLSEC_ERRORS_HERE,
+		    NULL,
+		    xmlSecErrorsSafeString(xmlSecNodeGetName(cur)),
+		    XMLSEC_ERRORS_R_INVALID_NODE,
+		    "expected=%s",
+		    xmlSecErrorsSafeString(xmlSecNodeCanonicalizationMethod));
+	return(-1);
+    }	
+    
+    /* insert membuf if requested */
+    if((dsigCtx->flags & XMLSEC_DSIG_FLAGS_STORE_SIGNATURE) != 0) {
+	xmlSecAssert2(dsigCtx->preSignMemBufMethod == NULL, -1);
+	dsigCtx->preSignMemBufMethod = xmlSecTransformCtxCreateAndAppend(&(dsigCtx->transformCtx), 
+						xmlSecTransformMemBufId);
+	if(dsigCtx->preSignMemBufMethod == NULL) {
+    	    xmlSecError(XMLSEC_ERRORS_HERE,
+			NULL,
+			"xmlSecTransformCtxCreateAndAppend",
+			XMLSEC_ERRORS_R_XMLSEC_FAILED,
+			"transform=%s",
+			xmlSecErrorsSafeString(xmlSecTransformKlassGetName(xmlSecTransformMemBufId)));
+	}
+    }
+        
+    /* next node is required SignatureMethod. */
+	if (cur != NULL){
+		cur = xmlSecGetNextElementNode(cur->next);
+	}
+    if((cur != NULL) && (xmlSecCheckNodeName(cur, xmlSecNodeSignatureMethod, xmlSecDSigNs))) {
+	dsigCtx->signMethod = xmlSecTransformCtxNodeRead(&(dsigCtx->transformCtx), 
+					cur, xmlSecTransformUsageSignatureMethod);
+	if(dsigCtx->signMethod == NULL) {
+	    xmlSecError(XMLSEC_ERRORS_HERE,
+			NULL,
+			"xmlSecTransformCtxNodeRead",
+			XMLSEC_ERRORS_R_XMLSEC_FAILED,
+			"node=%s",
+			xmlSecErrorsSafeString(xmlSecNodeGetName(cur)));
+	    return(-1);	
+	}	
+    } else if(dsigCtx->defSignMethodId != xmlSecTransformIdUnknown) {
+	/* the dsig spec does require SignatureMethod node
+	 * to be present but in some case it application might decide to
+	 * minimize traffic */
+	dsigCtx->signMethod = xmlSecTransformCtxCreateAndAppend(&(dsigCtx->transformCtx), 
+							      dsigCtx->defSignMethodId);
+	if(dsigCtx->signMethod == NULL) {
+    	    xmlSecError(XMLSEC_ERRORS_HERE,
+			NULL,
+			"xmlSecTransformCtxAppend",
+			XMLSEC_ERRORS_R_XMLSEC_FAILED,
+			XMLSEC_ERRORS_NO_MESSAGE);
+	    return(-1);
+	}
+    } else {
+    	xmlSecError(XMLSEC_ERRORS_HERE,
+		    NULL,
+		    xmlSecErrorsSafeString(xmlSecNodeGetName(cur)),
+		    XMLSEC_ERRORS_R_INVALID_NODE,
+		    "expected=%s",
+		    xmlSecErrorsSafeString(xmlSecNodeSignatureMethod));
+	return(-1);
+    }	
+    dsigCtx->signMethod->operation = dsigCtx->operation;
+    
+    /* calculate references */
+	if (cur != NULL) {
+		cur = xmlSecGetNextElementNode(cur->next);
+	}
+    while((cur != NULL) && (xmlSecCheckNodeName(cur, xmlSecNodeReference, xmlSecDSigNs))) {
+        /* create reference */
+	dsigRefCtx = xmlSecDSigReferenceCtxCreate(dsigCtx, xmlSecDSigReferenceOriginSignedInfo);
+	if(dsigRefCtx == NULL) {
+	    xmlSecError(XMLSEC_ERRORS_HERE,
+			NULL,
+		        "xmlSecDSigReferenceCtxCreate",
+			XMLSEC_ERRORS_R_XMLSEC_FAILED,
+			XMLSEC_ERRORS_NO_MESSAGE);
+	    return(-1);	    
+	}
+
+	/* add to the list */
+	ret = xmlSecPtrListAdd(&(dsigCtx->signedInfoReferences), dsigRefCtx);
+	if(ret < 0) {
+	    xmlSecError(XMLSEC_ERRORS_HERE,
+			NULL,
+			"xmlSecPtrListAdd",
+			XMLSEC_ERRORS_R_XMLSEC_FAILED,
+			XMLSEC_ERRORS_NO_MESSAGE);
+	    xmlSecDSigReferenceCtxDestroy(dsigRefCtx);
+	    return(-1);	    
+	}
+
+	/* process */
+	ret = xmlSecDSigReferenceCtxProcessNode(dsigRefCtx, cur);
+	if(ret < 0) {
+	    xmlSecError(XMLSEC_ERRORS_HERE,
+			NULL,
+			"xmlSecDSigReferenceCtxProcessNode",
+			XMLSEC_ERRORS_R_XMLSEC_FAILED,
+			"node=%s",
+			xmlSecErrorsSafeString(xmlSecNodeGetName(cur)));
+	    return(-1);	    
+	}
+
+	/* bail out if next Reference processing failed */
+	if(dsigRefCtx->status != xmlSecDSigStatusSucceeded) {
+	    dsigCtx->status = xmlSecDSigStatusInvalid;
+	    return(0); 
+	}
+	cur = xmlSecGetNextElementNode(cur->next);
+    }
+
+    /* check that we have at least one Reference */
+    if(xmlSecPtrListGetSize(&(dsigCtx->signedInfoReferences)) == 0) {
+    	xmlSecError(XMLSEC_ERRORS_HERE,
+		    NULL,
+		    NULL,
+		    XMLSEC_ERRORS_R_DSIG_NO_REFERENCES,
+		    XMLSEC_ERRORS_NO_MESSAGE);
+	return(-1);
+    }
+
+    /* if there is something left than it's an error */
+    if(cur != NULL) {
+	xmlSecError(XMLSEC_ERRORS_HERE,
+		    NULL,
+		    xmlSecErrorsSafeString(xmlSecNodeGetName(cur)),
+		    XMLSEC_ERRORS_R_UNEXPECTED_NODE,
+		    XMLSEC_ERRORS_NO_MESSAGE);
+	return(-1);
+    }
+    return(0);
+}
+
+static int 
+xmlSecDSigCtxProcessKeyInfoNode(xmlSecDSigCtxPtr dsigCtx, xmlNodePtr node) {
+    int ret;
+    
+    xmlSecAssert2(dsigCtx != NULL, -1);
+    xmlSecAssert2(dsigCtx->signMethod != NULL, -1);
+
+    /* set key requirements */
+    ret = xmlSecTransformSetKeyReq(dsigCtx->signMethod, &(dsigCtx->keyInfoReadCtx.keyReq));
+    if(ret < 0) {
+    	xmlSecError(XMLSEC_ERRORS_HERE,
+		    NULL,
+		    "xmlSecTransformSetKeyReq",
+		    XMLSEC_ERRORS_R_XMLSEC_FAILED,
+		    "transform=%s",
+		    xmlSecErrorsSafeString(xmlSecTransformGetName(dsigCtx->signMethod)));
+	return(-1);
+    }	
+    
+    /* ignore <dsig:KeyInfo /> if there is the key is already set */
+    if((dsigCtx->signKey == NULL) && (dsigCtx->keyInfoReadCtx.keysMngr != NULL) 
+			&& (dsigCtx->keyInfoReadCtx.keysMngr->getKey != NULL)) {	
+	dsigCtx->signKey = (dsigCtx->keyInfoReadCtx.keysMngr->getKey)(node, &(dsigCtx->keyInfoReadCtx));
+    }
+    
+    /* check that we have exactly what we want */
+    if((dsigCtx->signKey == NULL) || (!xmlSecKeyMatch(dsigCtx->signKey, NULL, &(dsigCtx->keyInfoReadCtx.keyReq)))) {
+	xmlSecError(XMLSEC_ERRORS_HERE,
+		    NULL,
+		    NULL,
+		    XMLSEC_ERRORS_R_KEY_NOT_FOUND,
+		    XMLSEC_ERRORS_NO_MESSAGE);
+	return(-1);
+    }
+    
+    /* set the key to the transform */
+    ret = xmlSecTransformSetKey(dsigCtx->signMethod, dsigCtx->signKey);
+    if(ret < 0) {
+	xmlSecError(XMLSEC_ERRORS_HERE,
+		    NULL,
+		    "xmlSecTransformSetKey",
+		    XMLSEC_ERRORS_R_XMLSEC_FAILED,
+		    "transform=%s",
+		    xmlSecErrorsSafeString(xmlSecTransformGetName(dsigCtx->signMethod)));
+	return(-1);
+    }
+
+    /* if we are signing document, update <dsig:KeyInfo/> node */
+    if((node != NULL) && (dsigCtx->operation == xmlSecTransformOperationSign)) {	
+	ret = xmlSecKeyInfoNodeWrite(node, dsigCtx->signKey, &(dsigCtx->keyInfoWriteCtx));
+	if(ret < 0) {
+    	    xmlSecError(XMLSEC_ERRORS_HERE,
+			NULL,
+			"xmlSecKeyInfoNodeWrite",
+			XMLSEC_ERRORS_R_XMLSEC_FAILED,
+			XMLSEC_ERRORS_NO_MESSAGE);
+	    return(-1);
+	}	
+    }
+    
+    return(0);
+}
+
+/**
+ * xmlSecDSigCtxProcessObjectNode:
+ * 	
+ * The Object Element (http://www.w3.org/TR/xmldsig-core/#sec-Object)
+ * 
+ * Object is an optional element that may occur one or more times. When 
+ * present, this element may contain any data. The Object element may include 
+ * optional MIME type, ID, and encoding attributes.
+ *     
+ * Schema Definition:
+ *     
+ * <element name="Object" type="ds:ObjectType"/> 
+ * <complexType name="ObjectType" mixed="true">
+ *   <sequence minOccurs="0" maxOccurs="unbounded">
+ *     <any namespace="##any" processContents="lax"/>
+ *   </sequence>
+ *   <attribute name="Id" type="ID" use="optional"/> 
+ *   <attribute name="MimeType" type="string" use="optional"/>
+ *   <attribute name="Encoding" type="anyURI" use="optional"/> 
+ * </complexType>
+ *	
+ * DTD:
+ *	
+ * <!ELEMENT Object (#PCDATA|Signature|SignatureProperties|Manifest %Object.ANY;)* >
+ * <!ATTLIST Object  Id  ID  #IMPLIED 
+ *                   MimeType    CDATA   #IMPLIED 
+ *                   Encoding    CDATA   #IMPLIED >
+ */
+static int
+xmlSecDSigCtxProcessObjectNode(xmlSecDSigCtxPtr dsigCtx, xmlNodePtr node) {
+    xmlNodePtr cur;
+    int ret;
+
+    xmlSecAssert2(dsigCtx != NULL, -1);	
+    xmlSecAssert2(dsigCtx->status == xmlSecDSigStatusUnknown, -1);
+    xmlSecAssert2(node != NULL, -1);
+    
+    /* we care about Manifest nodes only; ignore everything else */
+    cur = xmlSecGetNextElementNode(node->children);
+    while(cur != NULL) {
+	if(xmlSecCheckNodeName(cur, xmlSecNodeManifest, xmlSecDSigNs)) {
+	    ret = xmlSecDSigCtxProcessManifestNode(dsigCtx, cur);
+	    if(ret < 0){
+    		xmlSecError(XMLSEC_ERRORS_HERE,
+			    NULL,
+			    "xmlSecDSigCtxProcessManifestNode",
+			    XMLSEC_ERRORS_R_XMLSEC_FAILED,
+			    XMLSEC_ERRORS_NO_MESSAGE);
+		return(-1);	    
+	    }
+	}
+	cur = xmlSecGetNextElementNode(cur->next);
+    }
+    return(0);
+}
+
+/**
+ * xmlSecDSigCtxProcessManifestNode: 
+ *
+ * The Manifest  Element (http://www.w3.org/TR/xmldsig-core/#sec-Manifest)
+ *
+ * The Manifest element provides a list of References. The difference from 
+ * the list in SignedInfo is that it is application defined which, if any, of 
+ * the digests are actually checked against the objects referenced and what to 
+ * do if the object is inaccessible or the digest compare fails. If a Manifest 
+ * is pointed to from SignedInfo, the digest over the Manifest itself will be 
+ * checked by the core result validation behavior. The digests within such 
+ * a Manifest are checked at the application's discretion. If a Manifest is 
+ * referenced from another Manifest, even the overall digest of this two level 
+ * deep Manifest might not be checked.
+ *     
+ * Schema Definition:
+ *     
+ * <element name="Manifest" type="ds:ManifestType"/> 
+ * <complexType name="ManifestType">
+ *   <sequence>
+ *     <element ref="ds:Reference" maxOccurs="unbounded"/> 
+ *   </sequence> 
+ *   <attribute name="Id" type="ID" use="optional"/> 
+ *  </complexType>
+ *	
+ * DTD:
+ *
+ * <!ELEMENT Manifest (Reference+)  >
+ * <!ATTLIST Manifest Id ID  #IMPLIED >
+ */
+static int
+xmlSecDSigCtxProcessManifestNode(xmlSecDSigCtxPtr dsigCtx, xmlNodePtr node) {
+    xmlSecDSigReferenceCtxPtr dsigRefCtx;
+    xmlNodePtr cur;
+    int ret;
+
+    xmlSecAssert2(dsigCtx != NULL, -1);	
+    xmlSecAssert2(dsigCtx->status == xmlSecDSigStatusUnknown, -1);
+    xmlSecAssert2(node != NULL, -1);
+
+    /* calculate references */
+    cur = xmlSecGetNextElementNode(node->children);
+    while((cur != NULL) && (xmlSecCheckNodeName(cur, xmlSecNodeReference, xmlSecDSigNs))) {
+        /* create reference */
+	dsigRefCtx = xmlSecDSigReferenceCtxCreate(dsigCtx, xmlSecDSigReferenceOriginManifest);
+	if(dsigRefCtx == NULL) {
+	    xmlSecError(XMLSEC_ERRORS_HERE,
+			NULL,
+		        "xmlSecDSigReferenceCtxCreate",
+			XMLSEC_ERRORS_R_XMLSEC_FAILED,
+			XMLSEC_ERRORS_NO_MESSAGE);
+	    return(-1);	    
+	}
+
+	/* add to the list */
+	ret = xmlSecPtrListAdd(&(dsigCtx->manifestReferences), dsigRefCtx);
+	if(ret < 0) {
+	    xmlSecError(XMLSEC_ERRORS_HERE,
+			NULL,
+			"xmlSecPtrListAdd",
+			XMLSEC_ERRORS_R_XMLSEC_FAILED,
+			XMLSEC_ERRORS_NO_MESSAGE);
+	    xmlSecDSigReferenceCtxDestroy(dsigRefCtx);
+	    return(-1);	    
+	}
+
+	/* process */
+	ret = xmlSecDSigReferenceCtxProcessNode(dsigRefCtx, cur);
+	if(ret < 0) {
+	    xmlSecError(XMLSEC_ERRORS_HERE,
+			NULL,
+			"xmlSecDSigReferenceCtxProcessNode",
+			XMLSEC_ERRORS_R_XMLSEC_FAILED,
+			"node=%s",
+			xmlSecErrorsSafeString(xmlSecNodeGetName(cur)));
+	    return(-1);	    
+	}
+
+	/* we don;t care if Reference processing failed because
+	 * it's Manifest node */
+	cur = xmlSecGetNextElementNode(cur->next);
+    }
+
+    /* we should have nothing else here */
+    if(cur != NULL) {
+    	xmlSecError(XMLSEC_ERRORS_HERE,
+		    NULL,
+		    xmlSecErrorsSafeString(xmlSecNodeGetName(cur)),
+		    XMLSEC_ERRORS_R_UNEXPECTED_NODE,
+		    XMLSEC_ERRORS_NO_MESSAGE);
+	return(-1);
+    }    
+    return(0);
+}
+
+/**
+ * xmlSecDSigCtxDebugDump:
+ * @dsigCtx:		the pointer to <dsig:Signature/> processing context.
+ * @output:		the pointer to output FILE.
+ *
+ * Prints the debug information about @dsigCtx to @output.
+ */
+EXPORT_C
+void 
+xmlSecDSigCtxDebugDump(xmlSecDSigCtxPtr dsigCtx, FILE* output) {
+    xmlSecAssert(dsigCtx != NULL);
+    xmlSecAssert(output != NULL);
+
+    if(dsigCtx->operation == xmlSecTransformOperationSign) {    
+	fprintf(output, "= SIGNATURE CONTEXT\n");
+    } else {
+	fprintf(output, "= VERIFICATION CONTEXT\n");
+    }
+    switch(dsigCtx->status) {
+	case xmlSecDSigStatusUnknown:
+	    fprintf(output, "== Status: unknown\n");
+	    break;
+	case xmlSecDSigStatusSucceeded:
+	    fprintf(output, "== Status: succeeded\n");
+	    break;
+	case xmlSecDSigStatusInvalid:
+	    fprintf(output, "== Status: invalid\n");
+	    break;
+    }
+    fprintf(output, "== flags: 0x%08x\n", dsigCtx->flags);
+    fprintf(output, "== flags2: 0x%08x\n", dsigCtx->flags2);
+
+    if(dsigCtx->id != NULL) {
+	fprintf(output, "== Id: \"%s\"\n", dsigCtx->id);
+    }
+    
+    fprintf(output, "== Key Info Read Ctx:\n");
+    xmlSecKeyInfoCtxDebugDump(&(dsigCtx->keyInfoReadCtx), output);
+    fprintf(output, "== Key Info Write Ctx:\n");
+    xmlSecKeyInfoCtxDebugDump(&(dsigCtx->keyInfoWriteCtx), output);
+
+    fprintf(output, "== Signature Transform Ctx:\n");
+    xmlSecTransformCtxDebugDump(&(dsigCtx->transformCtx), output);
+
+    if(dsigCtx->signMethod != NULL) {
+        fprintf(output, "== Signature Method:\n");
+	xmlSecTransformDebugDump(dsigCtx->signMethod, output);
+    }
+
+    if(dsigCtx->signKey != NULL) {
+        fprintf(output, "== Signature Key:\n");
+	xmlSecKeyDebugDump(dsigCtx->signKey, output);
+    }
+    
+    fprintf(output, "== SignedInfo References List:\n");
+    xmlSecPtrListDebugDump(&(dsigCtx->signedInfoReferences), output);
+
+    fprintf(output, "== Manifest References List:\n");
+    xmlSecPtrListDebugDump(&(dsigCtx->manifestReferences), output);
+    
+    if((dsigCtx->result != NULL) && 
+       (xmlSecBufferGetData(dsigCtx->result) != NULL)) {
+
+	fprintf(output, "== Result - start buffer:\n");
+	fwrite(xmlSecBufferGetData(dsigCtx->result), 
+	       xmlSecBufferGetSize(dsigCtx->result), 
+	       1, output);
+	fprintf(output, "\n== Result - end buffer\n");
+    }
+    if(((dsigCtx->flags & XMLSEC_DSIG_FLAGS_STORE_SIGNATURE) != 0) &&
+       (xmlSecDSigCtxGetPreSignBuffer(dsigCtx) != NULL) &&
+       (xmlSecBufferGetData(xmlSecDSigCtxGetPreSignBuffer(dsigCtx)) != NULL)) {
+       
+	fprintf(output, "== PreSigned data - start buffer:\n");
+	fwrite(xmlSecBufferGetData(xmlSecDSigCtxGetPreSignBuffer(dsigCtx)), 
+	       xmlSecBufferGetSize(xmlSecDSigCtxGetPreSignBuffer(dsigCtx)), 
+	       1, output);
+	fprintf(output, "\n== PreSigned data - end buffer\n");       
+    }
+}
+
+/**
+ * xmlSecDSigCtxDebugXmlDump:
+ * @dsigCtx:		the pointer to <dsig:Signature/> processing context.
+ * @output:		the pointer to output FILE.
+ *
+ * Prints the debug information about @dsigCtx to @output in XML format.
+ */
+EXPORT_C
+void 
+xmlSecDSigCtxDebugXmlDump(xmlSecDSigCtxPtr dsigCtx, FILE* output) {
+    xmlSecAssert(dsigCtx != NULL);
+    xmlSecAssert(output != NULL);
+
+    if(dsigCtx->operation == xmlSecTransformOperationSign) {    
+	fprintf(output, "<SignatureContext \n");
+    } else {
+	fprintf(output, "<VerificationContext \n");
+    }
+    switch(dsigCtx->status) {
+	case xmlSecDSigStatusUnknown:
+	    fprintf(output, "status=\"unknown\" >\n");
+	    break;
+	case xmlSecDSigStatusSucceeded:
+	    fprintf(output, "status=\"succeeded\" >\n");
+	    break;
+	case xmlSecDSigStatusInvalid:
+	    fprintf(output, "status=\"invalid\" >\n");
+	    break;
+    }
+
+    fprintf(output, "<Flags>%08x</Flags>\n", dsigCtx->flags);
+    fprintf(output, "<Flags2>%08x</Flags2>\n", dsigCtx->flags2);
+
+    if(dsigCtx->id != NULL) {
+	fprintf(output, "<Id>%s</Id>\n", dsigCtx->id);
+    }
+
+    fprintf(output, "<KeyInfoReadCtx>\n");
+    xmlSecKeyInfoCtxDebugXmlDump(&(dsigCtx->keyInfoReadCtx), output);
+    fprintf(output, "</KeyInfoReadCtx>\n");
+
+    fprintf(output, "<KeyInfoWriteCtx>\n");
+    xmlSecKeyInfoCtxDebugXmlDump(&(dsigCtx->keyInfoWriteCtx), output);
+    fprintf(output, "</KeyInfoWriteCtx>\n");
+
+    fprintf(output, "<SignatureTransformCtx>\n");
+    xmlSecTransformCtxDebugXmlDump(&(dsigCtx->transformCtx), output);
+    fprintf(output, "</SignatureTransformCtx>\n");
+
+    if(dsigCtx->signMethod != NULL) {
+        fprintf(output, "<SignatureMethod>\n");
+	xmlSecTransformDebugXmlDump(dsigCtx->signMethod, output);
+        fprintf(output, "</SignatureMethod>\n");
+    }
+
+    if(dsigCtx->signKey != NULL) {
+        fprintf(output, "<SignatureKey>\n");
+	xmlSecKeyDebugXmlDump(dsigCtx->signKey, output);
+        fprintf(output, "</SignatureKey>\n");
+    }
+
+    fprintf(output, "<SignedInfoReferences>\n");
+    xmlSecPtrListDebugXmlDump(&(dsigCtx->signedInfoReferences), output);
+    fprintf(output, "</SignedInfoReferences>\n");
+
+    fprintf(output, "<ManifestReferences>\n");
+    xmlSecPtrListDebugXmlDump(&(dsigCtx->manifestReferences), output);
+    fprintf(output, "</ManifestReferences>\n");
+
+    if((dsigCtx->result != NULL) && 
+       (xmlSecBufferGetData(dsigCtx->result) != NULL)) {
+
+	fprintf(output, "<Result>");
+	fwrite(xmlSecBufferGetData(dsigCtx->result), 
+	       xmlSecBufferGetSize(dsigCtx->result), 
+	       1, output);
+	fprintf(output, "</Result>\n");
+    }
+    if(((dsigCtx->flags & XMLSEC_DSIG_FLAGS_STORE_SIGNATURE) != 0) &&
+       (xmlSecDSigCtxGetPreSignBuffer(dsigCtx) != NULL) &&
+       (xmlSecBufferGetData(xmlSecDSigCtxGetPreSignBuffer(dsigCtx)) != NULL)) {
+       
+	fprintf(output, "<PreSignedData>");
+	fwrite(xmlSecBufferGetData(xmlSecDSigCtxGetPreSignBuffer(dsigCtx)), 
+	       xmlSecBufferGetSize(xmlSecDSigCtxGetPreSignBuffer(dsigCtx)), 
+	       1, output);
+	fprintf(output, "</PreSignedData>\n");       
+    }
+
+    if(dsigCtx->operation == xmlSecTransformOperationSign) {    
+	fprintf(output, "</SignatureContext>\n");
+    } else {
+	fprintf(output, "</VerificationContext>\n");
+    }
+}
+
+/**************************************************************************
+ *
+ * xmlSecDSigReferenceCtx
+ *
+ *************************************************************************/
+/**
+ * xmlSecDSigReferenceCtxCreate:
+ * @dsigCtx:		the pointer to parent <dsig:Signature/> node processing context.
+ * @origin:		the reference origin (<dsig:SignedInfo/> or <dsig:Manifest/> node).
+ *
+ * Creates new <dsig:Reference/> element processing context. Caller is responsible
+ * for destroying the returned context by calling #xmlSecDSigReferenceCtxDestroy
+ * function.
+ *
+ * Returns pointer to newly created context or NULL if an error occurs.
+ */
+EXPORT_C
+xmlSecDSigReferenceCtxPtr	
+xmlSecDSigReferenceCtxCreate(xmlSecDSigCtxPtr dsigCtx, xmlSecDSigReferenceOrigin origin) {
+    xmlSecDSigReferenceCtxPtr dsigRefCtx;
+    int ret;
+    
+    xmlSecAssert2(dsigCtx != NULL, NULL);
+    
+    dsigRefCtx = (xmlSecDSigReferenceCtxPtr) xmlMalloc(sizeof(xmlSecDSigReferenceCtx));
+    if(dsigRefCtx == NULL) {
+	xmlSecError(XMLSEC_ERRORS_HERE,
+		    NULL,
+		    NULL,
+		    XMLSEC_ERRORS_R_MALLOC_FAILED,
+		    "sizeof(xmlSecDSigReferenceCtx)=%d", 
+		    sizeof(xmlSecDSigReferenceCtx));
+	return(NULL);
+    }
+    
+    ret = xmlSecDSigReferenceCtxInitialize(dsigRefCtx, dsigCtx, origin);
+    if(ret < 0) {
+	xmlSecError(XMLSEC_ERRORS_HERE,
+		    NULL,
+		    "xmlSecDSigReferenceCtxInitialize",
+		    XMLSEC_ERRORS_R_XMLSEC_FAILED,
+		    XMLSEC_ERRORS_NO_MESSAGE);
+	xmlSecDSigReferenceCtxDestroy(dsigRefCtx);
+	return(NULL);   
+    }
+    return(dsigRefCtx);    
+}
+
+/** 
+ * xmlSecDSigReferenceCtxDestroy:
+ * @dsigRefCtx:		the pointer to <dsig:Reference/> element processing context.
+ *
+ * Destroy context object created with #xmlSecDSigReferenceCtxCreate function.
+ */
+EXPORT_C
+void  
+xmlSecDSigReferenceCtxDestroy(xmlSecDSigReferenceCtxPtr dsigRefCtx) {
+    xmlSecAssert(dsigRefCtx != NULL);
+    
+    xmlSecDSigReferenceCtxFinalize(dsigRefCtx);
+    xmlFree(dsigRefCtx);
+}
+
+/**
+ * xmlSecDSigReferenceCtxInitialize:
+ * @dsigRefCtx:		the pointer to <dsig:Reference/> element processing context.
+ * @dsigCtx:		the pointer to parent <dsig:Signature/> node processing context.
+ * @origin:		the reference origin (<dsig:SignedInfo/> or <dsig:Manifest/> node).
+ *
+ * Initializes new <dsig:Reference/> element processing context. Caller is responsible
+ * for cleaning up the returned context by calling #xmlSecDSigReferenceCtxFinalize
+ * function.
+ *
+ * Returns 0 on succes or aa negative value otherwise.
+ */
+EXPORT_C
+int 
+xmlSecDSigReferenceCtxInitialize(xmlSecDSigReferenceCtxPtr dsigRefCtx, xmlSecDSigCtxPtr dsigCtx,
+				xmlSecDSigReferenceOrigin origin) {
+    int ret;
+    
+    xmlSecAssert2(dsigCtx != NULL, -1);
+    xmlSecAssert2(dsigRefCtx != NULL, -1);
+    
+    memset(dsigRefCtx, 0, sizeof(xmlSecDSigReferenceCtx));
+    
+    dsigRefCtx->dsigCtx = dsigCtx;
+    dsigRefCtx->origin = origin;
+    
+    /* initializes transforms dsigRefCtx */
+    ret = xmlSecTransformCtxInitialize(&(dsigRefCtx->transformCtx));
+    if(ret < 0) {
+	xmlSecError(XMLSEC_ERRORS_HERE,
+		    NULL,
+		    "xmlSecTransformCtxInitialize",
+		    XMLSEC_ERRORS_R_XMLSEC_FAILED,
+		    XMLSEC_ERRORS_NO_MESSAGE);
+	return(-1);   
+    }
+    
+    /* copy enabled transforms */
+    if(dsigCtx->enabledReferenceTransforms != NULL) {
+	ret = xmlSecPtrListCopy(&(dsigRefCtx->transformCtx.enabledTransforms), 
+				     dsigCtx->enabledReferenceTransforms);
+	if(ret < 0) {
+	    xmlSecError(XMLSEC_ERRORS_HERE,
+			NULL,
+			"xmlSecPtrListCopy",
+			XMLSEC_ERRORS_R_XMLSEC_FAILED,
+			XMLSEC_ERRORS_NO_MESSAGE);
+	    return(-1);   
+	}
+    }    
+    dsigRefCtx->transformCtx.preExecCallback = dsigCtx->referencePreExecuteCallback;
+    dsigRefCtx->transformCtx.enabledUris = dsigCtx->enabledReferenceUris;
+
+    if((dsigCtx->flags & XMLSEC_DSIG_FLAGS_USE_VISA3D_HACK) != 0) {
+	dsigRefCtx->transformCtx.flags |= XMLSEC_TRANSFORMCTX_FLAGS_USE_VISA3D_HACK;
+    }
+    return(0);
+}
+
+/** 
+ * xmlSecDSigReferenceCtxFinalize:
+ * @dsigRefCtx:		the pointer to <dsig:Reference/> element processing context.
+ *
+ * Cleans up context object created with #xmlSecDSigReferenceCtxInitialize function.
+ */
+EXPORT_C
+void 
+xmlSecDSigReferenceCtxFinalize(xmlSecDSigReferenceCtxPtr dsigRefCtx) {
+    xmlSecAssert(dsigRefCtx != NULL);
+
+    xmlSecTransformCtxFinalize(&(dsigRefCtx->transformCtx));
+    if(dsigRefCtx->id != NULL) {
+	xmlFree(dsigRefCtx->id);
+    }	
+    if(dsigRefCtx->uri != NULL) {
+	xmlFree(dsigRefCtx->uri);
+    }	
+    if(dsigRefCtx->type != NULL) {
+	xmlFree(dsigRefCtx->type);
+    }	
+    memset(dsigRefCtx, 0, sizeof(xmlSecDSigReferenceCtx));
+}
+
+/**
+ * xmlSecDSigReferenceCtxGetPreDigestBuffer:
+ * @dsigRefCtx:		the pointer to <dsig:Reference/> element processing context.
+ * 
+ * Gets the results of <dsig:Reference/> node processing just before digesting
+ * (valid only if #XMLSEC_DSIG_FLAGS_STORE_SIGNEDINFO_REFERENCES or
+ * #XMLSEC_DSIG_FLAGS_STORE_MANIFEST_REFERENCES flas of signature context
+ * is set).
+ *
+ * Returns pointer to the buffer or NULL if an error occurs.
+ */
+EXPORT_C
+xmlSecBufferPtr 
+xmlSecDSigReferenceCtxGetPreDigestBuffer(xmlSecDSigReferenceCtxPtr dsigRefCtx) {
+    xmlSecAssert2(dsigRefCtx != NULL, NULL);
+    
+    return((dsigRefCtx->preDigestMemBufMethod != NULL) ? 
+	    xmlSecTransformMemBufGetBuffer(dsigRefCtx->preDigestMemBufMethod) : NULL);
+}
+
+/**
+ * xmlSecDSigReferenceCtxProcessNode:
+ * @dsigRefCtx:		the pointer to <dsig:Reference/> element processing context.
+ * @node:		the pointer to <dsig:Reference/> node.
+
+ * The Reference Element (http://www.w3.org/TR/xmldsig-core/#sec-Reference)
+ * 
+ * Reference is an element that may occur one or more times. It specifies 
+ * a digest algorithm and digest value, and optionally an identifier of the 
+ * object being signed, the type of the object, and/or a list of transforms 
+ * to be applied prior to digesting. The identification (URI) and transforms 
+ * describe how the digested content (i.e., the input to the digest method) 
+ * was created. The Type attribute facilitates the processing of referenced 
+ * data. For example, while this specification makes no requirements over 
+ * external data, an application may wish to signal that the referent is a 
+ * Manifest. An optional ID attribute permits a Reference to be referenced 
+ * from elsewhere.
+ *
+ * Returns 0 on succes or aa negative value otherwise.
+ */
+EXPORT_C
+int 
+xmlSecDSigReferenceCtxProcessNode(xmlSecDSigReferenceCtxPtr dsigRefCtx, xmlNodePtr node) {
+    xmlSecTransformCtxPtr transformCtx;
+    xmlNodePtr digestValueNode;
+    xmlNodePtr cur;
+    int ret;
+    
+    xmlSecAssert2(dsigRefCtx != NULL, -1);
+    xmlSecAssert2(dsigRefCtx->dsigCtx != NULL, -1);
+    xmlSecAssert2(dsigRefCtx->digestMethod == NULL, -1);
+    xmlSecAssert2(dsigRefCtx->digestMethod == NULL, -1);
+    xmlSecAssert2(dsigRefCtx->preDigestMemBufMethod == NULL, -1);
+    xmlSecAssert2(node != NULL, -1);
+    xmlSecAssert2(node->doc != NULL, -1);
+
+    transformCtx = &(dsigRefCtx->transformCtx);
+
+    /* read attributes first */
+    dsigRefCtx->uri = xmlGetProp(node, xmlSecAttrURI);
+    dsigRefCtx->id  = xmlGetProp(node, xmlSecAttrId);
+    dsigRefCtx->type= xmlGetProp(node, xmlSecAttrType);
+
+    /* set start URI (and check that it is enabled!) */
+    ret = xmlSecTransformCtxSetUri(transformCtx, dsigRefCtx->uri, node);
+    if(ret < 0) {
+	xmlSecError(XMLSEC_ERRORS_HERE,
+		    NULL,
+		    "xmlSecTransformCtxSetUri",
+		    XMLSEC_ERRORS_R_XMLSEC_FAILED,
+		    "uri=%s",
+		    xmlSecErrorsSafeString(dsigRefCtx->uri));
+	return(-1);
+    }
+
+    /* first is optional Transforms node */
+    cur = xmlSecGetNextElementNode(node->children);
+    if((cur != NULL) && (xmlSecCheckNodeName(cur, xmlSecNodeTransforms, xmlSecDSigNs))) {
+	ret = xmlSecTransformCtxNodesListRead(transformCtx, 
+					cur, xmlSecTransformUsageDSigTransform);
+	if(ret < 0) {
+	    xmlSecError(XMLSEC_ERRORS_HERE,
+			NULL,
+			"xmlSecTransformCtxNodesListRead",
+			XMLSEC_ERRORS_R_XMLSEC_FAILED,
+			"node=%s",
+			xmlSecErrorsSafeString(xmlSecNodeGetName(cur)));
+	    return(-1);
+	}	
+        cur = xmlSecGetNextElementNode(cur->next);
+    }
+
+    /* insert membuf if requested */
+    if(((dsigRefCtx->origin == xmlSecDSigReferenceOriginSignedInfo) &&
+	((dsigRefCtx->dsigCtx->flags & XMLSEC_DSIG_FLAGS_STORE_SIGNEDINFO_REFERENCES) != 0)) ||
+       ((dsigRefCtx->origin == xmlSecDSigReferenceOriginManifest) &&
+	((dsigRefCtx->dsigCtx->flags & XMLSEC_DSIG_FLAGS_STORE_MANIFEST_REFERENCES) != 0))) {
+
+	xmlSecAssert2(dsigRefCtx->preDigestMemBufMethod == NULL, -1);
+	dsigRefCtx->preDigestMemBufMethod = xmlSecTransformCtxCreateAndAppend(
+						transformCtx, 
+						xmlSecTransformMemBufId);
+	if(dsigRefCtx->preDigestMemBufMethod == NULL) {
+    	    xmlSecError(XMLSEC_ERRORS_HERE,
+			NULL,
+			"xmlSecTransformCtxCreateAndAppend",
+			XMLSEC_ERRORS_R_XMLSEC_FAILED,
+			"transform=%s",
+			xmlSecErrorsSafeString(xmlSecTransformKlassGetName(xmlSecTransformMemBufId)));
+	    return(-1);
+	}
+    }
+        
+    /* next node is required DigestMethod. */
+    if((cur != NULL) && (xmlSecCheckNodeName(cur, xmlSecNodeDigestMethod, xmlSecDSigNs))) {
+	dsigRefCtx->digestMethod = xmlSecTransformCtxNodeRead(&(dsigRefCtx->transformCtx), 
+					cur, xmlSecTransformUsageDigestMethod);
+	if(dsigRefCtx->digestMethod == NULL) {
+	    xmlSecError(XMLSEC_ERRORS_HERE,
+			NULL,
+			"xmlSecTransformCtxNodeRead",
+			XMLSEC_ERRORS_R_XMLSEC_FAILED,
+			"node=%s",
+			xmlSecErrorsSafeString(xmlSecNodeGetName(cur)));
+	    return(-1);	
+	}	
+    } else if(dsigRefCtx->dsigCtx->defSignMethodId != xmlSecTransformIdUnknown) {
+	/* the dsig spec does require DigestMethod node
+	 * to be present but in some case it application might decide to
+	 * minimize traffic */
+	dsigRefCtx->digestMethod = xmlSecTransformCtxCreateAndAppend(&(dsigRefCtx->transformCtx), 
+							      dsigRefCtx->dsigCtx->defSignMethodId);
+	if(dsigRefCtx->digestMethod == NULL) {
+    	    xmlSecError(XMLSEC_ERRORS_HERE,
+			NULL,
+			"xmlSecTransformCtxAppend",
+			XMLSEC_ERRORS_R_XMLSEC_FAILED,
+			XMLSEC_ERRORS_NO_MESSAGE);
+	    return(-1);
+	}
+    } else {
+    	xmlSecError(XMLSEC_ERRORS_HERE,
+		    NULL,
+		    xmlSecErrorsSafeString(xmlSecNodeGetName(cur)),
+		    XMLSEC_ERRORS_R_INVALID_NODE,
+		    "expected=%s",
+		    xmlSecErrorsSafeString(xmlSecNodeDigestMethod));
+	return(-1);
+    }	
+    dsigRefCtx->digestMethod->operation = dsigRefCtx->dsigCtx->operation;
+
+    /* last node is required DigestValue */
+	if (cur != NULL) {
+		cur = xmlSecGetNextElementNode(cur->next);     
+	}
+    if((cur == NULL) || (!xmlSecCheckNodeName(cur, xmlSecNodeDigestValue, xmlSecDSigNs))) {
+    	xmlSecError(XMLSEC_ERRORS_HERE,
+		    NULL,
+		    xmlSecErrorsSafeString(xmlSecNodeGetName(cur)),
+		    XMLSEC_ERRORS_R_XMLSEC_FAILED,
+		    "node=%s",
+		    xmlSecErrorsSafeString(xmlSecNodeDigestValue));
+	return(-1);
+    }
+    digestValueNode = cur;
+    cur = xmlSecGetNextElementNode(cur->next);     
+
+    /* if we have something else then it's an error */
+    if(cur != NULL) {
+	xmlSecError(XMLSEC_ERRORS_HERE,
+		    NULL,
+		    xmlSecErrorsSafeString(xmlSecNodeGetName(cur)),
+		    XMLSEC_ERRORS_R_UNEXPECTED_NODE,
+		    XMLSEC_ERRORS_NO_MESSAGE);
+	return(-1);
+    }
+
+    /* if we need to write result to xml node then we need base64 encode result */
+    if(dsigRefCtx->dsigCtx->operation == xmlSecTransformOperationSign) {	
+	xmlSecTransformPtr base64Encode;
+	
+	/* we need to add base64 encode transform */
+	base64Encode = xmlSecTransformCtxCreateAndAppend(transformCtx, xmlSecTransformBase64Id);
+    	if(base64Encode == NULL) {
+    	    xmlSecError(XMLSEC_ERRORS_HERE,
+			NULL,
+			"xmlSecTransformCtxCreateAndAppend",
+			XMLSEC_ERRORS_R_XMLSEC_FAILED,
+			XMLSEC_ERRORS_NO_MESSAGE);
+	    return(-1);
+	}
+	base64Encode->operation = xmlSecTransformOperationEncode;
+    }
+
+    /* finally get transforms results */
+    ret = xmlSecTransformCtxExecute(transformCtx, node->doc);
+    if(ret < 0) {
+	xmlSecError(XMLSEC_ERRORS_HERE,
+		    NULL,
+		    "xmlSecTransformCtxExecute",
+	    	    XMLSEC_ERRORS_R_XMLSEC_FAILED,
+		    XMLSEC_ERRORS_NO_MESSAGE);
+	return(-1);
+    }    
+    dsigRefCtx->result = transformCtx->result;
+
+    if(dsigRefCtx->dsigCtx->operation == xmlSecTransformOperationSign) {	
+	if((dsigRefCtx->result == NULL) || (xmlSecBufferGetData(dsigRefCtx->result) == NULL)) {
+	    xmlSecError(XMLSEC_ERRORS_HERE,
+			NULL,
+			"xmlSecTransformCtxExecute",
+	    		XMLSEC_ERRORS_R_XMLSEC_FAILED,
+			XMLSEC_ERRORS_NO_MESSAGE);
+	    return(-1);
+	}
+	
+	/* write signed data to xml */
+	xmlNodeSetContentLen(digestValueNode,
+			    xmlSecBufferGetData(dsigRefCtx->result),
+			    xmlSecBufferGetSize(dsigRefCtx->result));
+    if ( OOM_FLAG )
+        {
+        return(-1);
+        }
+    
+	/* set success status and we are done */
+	dsigRefCtx->status = xmlSecDSigStatusSucceeded;
+    } else {
+	/* verify SignatureValue node content */
+	ret = xmlSecTransformVerifyNodeContent(dsigRefCtx->digestMethod, 
+			    digestValueNode, transformCtx);
+	if(ret < 0) {
+    	    xmlSecError(XMLSEC_ERRORS_HERE,
+			NULL,
+			"xmlSecTransformVerifyNodeContent",
+			XMLSEC_ERRORS_R_XMLSEC_FAILED,
+			XMLSEC_ERRORS_NO_MESSAGE);
+	    return(-1);
+	}
+    
+        /* set status and we are done */
+	if(dsigRefCtx->digestMethod->status == xmlSecTransformStatusOk) {
+	    dsigRefCtx->status = xmlSecDSigStatusSucceeded;
+	} else {
+    	    dsigRefCtx->status = xmlSecDSigStatusInvalid;
+	}
+    }
+
+    return(0);
+}
+
+/**
+ * xmlSecDSigReferenceCtxDebugDump:
+ * @dsigRefCtx:		the pointer to <dsig:Reference/> element processing context.
+ * @output:		the pointer to output FILE.
+ *
+ * Prints debug information about @dsigRefCtx to @output.
+ */
+EXPORT_C
+void 
+xmlSecDSigReferenceCtxDebugDump(xmlSecDSigReferenceCtxPtr dsigRefCtx, FILE* output) {
+    xmlSecAssert(dsigRefCtx != NULL);
+    xmlSecAssert(dsigRefCtx->dsigCtx != NULL);
+    xmlSecAssert(output != NULL);
+
+    if(dsigRefCtx->dsigCtx->operation == xmlSecTransformOperationSign) {    
+	fprintf(output, "= REFERENCE CALCULATION CONTEXT\n");
+    } else {
+	fprintf(output, "= REFERENCE VERIFICATION CONTEXT\n");
+    }
+    switch(dsigRefCtx->status) {
+	case xmlSecDSigStatusUnknown:
+	    fprintf(output, "== Status: unknown\n");
+	    break;
+	case xmlSecDSigStatusSucceeded:
+	    fprintf(output, "== Status: succeeded\n");
+	    break;
+	case xmlSecDSigStatusInvalid:
+	    fprintf(output, "== Status: invalid\n");
+	    break;
+    }
+    if(dsigRefCtx->id != NULL) {
+	fprintf(output, "== Id: \"%s\"\n", dsigRefCtx->id);
+    }
+    if(dsigRefCtx->uri != NULL) {
+	fprintf(output, "== URI: \"%s\"\n", dsigRefCtx->uri);
+    }
+    if(dsigRefCtx->type != NULL) {
+	fprintf(output, "== Type: \"%s\"\n", dsigRefCtx->type);
+    }
+
+    fprintf(output, "== Reference Transform Ctx:\n");
+    xmlSecTransformCtxDebugDump(&(dsigRefCtx->transformCtx), output);
+
+    if(dsigRefCtx->digestMethod != NULL) {
+        fprintf(output, "== Digest Method:\n");
+	xmlSecTransformDebugDump(dsigRefCtx->digestMethod, output);
+    }
+
+    if((xmlSecDSigReferenceCtxGetPreDigestBuffer(dsigRefCtx) != NULL) &&
+       (xmlSecBufferGetData(xmlSecDSigReferenceCtxGetPreDigestBuffer(dsigRefCtx)) != NULL)) {
+       
+	fprintf(output, "== PreDigest data - start buffer:\n");
+	fwrite(xmlSecBufferGetData(xmlSecDSigReferenceCtxGetPreDigestBuffer(dsigRefCtx)), 
+	       xmlSecBufferGetSize(xmlSecDSigReferenceCtxGetPreDigestBuffer(dsigRefCtx)), 
+	       1, output);
+	fprintf(output, "\n== PreDigest data - end buffer\n");       
+    }
+
+    if((dsigRefCtx->result != NULL) && 
+       (xmlSecBufferGetData(dsigRefCtx->result) != NULL)) {
+
+	fprintf(output, "== Result - start buffer:\n");
+	fwrite(xmlSecBufferGetData(dsigRefCtx->result), 
+	       xmlSecBufferGetSize(dsigRefCtx->result), 1,
+	       output);
+	fprintf(output, "\n== Result - end buffer\n");
+    }
+}
+
+/**
+ * xmlSecDSigReferenceCtxDebugXmlDump:
+ * @dsigRefCtx:		the pointer to <dsig:Reference/> element processing context.
+ * @output:		the pointer to output FILE.
+ *
+ * Prints debug information about @dsigRefCtx to @output in output format.
+ */
+EXPORT_C
+void 
+xmlSecDSigReferenceCtxDebugXmlDump(xmlSecDSigReferenceCtxPtr dsigRefCtx, FILE* output) {
+    xmlSecAssert(dsigRefCtx != NULL);
+    xmlSecAssert(dsigRefCtx->dsigCtx != NULL);
+    xmlSecAssert(output != NULL);
+
+    if(dsigRefCtx->dsigCtx->operation == xmlSecTransformOperationSign) {    
+	fprintf(output, "<ReferenceCalculationContext ");
+    } else {
+	fprintf(output, "<ReferenceVerificationContext ");
+    }
+    switch(dsigRefCtx->status) {
+	case xmlSecDSigStatusUnknown:
+	    fprintf(output, "status=\"unknown\" >\n");
+	    break;
+	case xmlSecDSigStatusSucceeded:
+	    fprintf(output, "status=\"succeeded\" >\n");
+	    break;
+	case xmlSecDSigStatusInvalid:
+	    fprintf(output, "status=\"invalid\" >\n");
+	    break;
+    }
+
+    if(dsigRefCtx->id != NULL) {
+	fprintf(output, "<Id>%s</Id>\n", dsigRefCtx->id);
+    }
+    if(dsigRefCtx->uri != NULL) {
+	fprintf(output, "<URI>%s</URI>\n", dsigRefCtx->uri);
+    }
+    if(dsigRefCtx->type != NULL) {
+	fprintf(output, "<Type>%s</Type>\n", dsigRefCtx->type);
+    }
+
+    fprintf(output, "<ReferenceTransformCtx>\n");
+    xmlSecTransformCtxDebugXmlDump(&(dsigRefCtx->transformCtx), output);
+    fprintf(output, "</ReferenceTransformCtx>\n");
+
+    if(dsigRefCtx->digestMethod != NULL) {
+        fprintf(output, "<DigestMethod>\n");
+	xmlSecTransformDebugXmlDump(dsigRefCtx->digestMethod, output);
+        fprintf(output, "</DigestMethod>\n");
+    }
+
+    if((dsigRefCtx->result != NULL) && 
+       (xmlSecBufferGetData(dsigRefCtx->result) != NULL)) {
+
+	fprintf(output, "<Result>");
+	fwrite(xmlSecBufferGetData(dsigRefCtx->result), 
+	       xmlSecBufferGetSize(dsigRefCtx->result), 1,
+	       output);
+	fprintf(output, "</Result>\n");
+    }
+
+    if((xmlSecDSigReferenceCtxGetPreDigestBuffer(dsigRefCtx) != NULL) &&
+       (xmlSecBufferGetData(xmlSecDSigReferenceCtxGetPreDigestBuffer(dsigRefCtx)) != NULL)) {
+       
+	fprintf(output, "<PreDigestData>");
+	fwrite(xmlSecBufferGetData(xmlSecDSigReferenceCtxGetPreDigestBuffer(dsigRefCtx)), 
+	       xmlSecBufferGetSize(xmlSecDSigReferenceCtxGetPreDigestBuffer(dsigRefCtx)), 
+	       1, output);
+	fprintf(output, "</PreDigestData>\n");       
+    }
+    if(dsigRefCtx->dsigCtx->operation == xmlSecTransformOperationSign) {    
+	fprintf(output, "</ReferenceCalculationContext>\n");
+    } else {
+	fprintf(output, "</ReferenceVerificationContext>\n");
+    }
+}
+
+
+/**************************************************************************
+ *
+ * xmlSecDSigReferenceCtxListKlass
+ *
+ *************************************************************************/
+static xmlSecPtrListKlass xmlSecDSigReferenceCtxListKlass = {
+    BAD_CAST "dsig-reference-list",
+    NULL,								/* xmlSecPtrDuplicateItemMethod duplicateItem; */
+    (xmlSecPtrDestroyItemMethod)xmlSecDSigReferenceCtxDestroy,		/* xmlSecPtrDestroyItemMethod destroyItem; */
+    (xmlSecPtrDebugDumpItemMethod)xmlSecDSigReferenceCtxDebugDump,	/* xmlSecPtrDebugDumpItemMethod debugDumpItem; */
+    (xmlSecPtrDebugDumpItemMethod)xmlSecDSigReferenceCtxDebugXmlDump,	/* xmlSecPtrDebugDumpItemMethod debugXmlDumpItem; */
+};
+
+/**
+ * xmlSecDSigReferenceCtxListGetKlass:
+ *
+ * The <dsig:Reference/> element processing contexts list klass.
+ *
+ * Returns <dsig:Reference/> element processing context list klass.
+ */
+EXPORT_C
+xmlSecPtrListId 
+xmlSecDSigReferenceCtxListGetKlass(void) {
+    return(&xmlSecDSigReferenceCtxListKlass);
+}
+
+#endif /* XMLSEC_NO_XMLDSIG */
+
+