xmlsecurityengine/xmlsec/src/xmlsec_xmldsig.c
changeset 0 e35f40988205
child 16 d10d750052f0
equal deleted inserted replaced
-1:000000000000 0:e35f40988205
       
     1 /** 
       
     2  * XML Security Library (http://www.aleksey.com/xmlsec).
       
     3  *
       
     4  * "XML Digital Signature" implementation
       
     5  *  http://www.w3.org/TR/xmldsig-core/
       
     6  *  http://www.w3.org/Signature/Overview.html
       
     7  * 
       
     8  * This is free software; see Copyright file in the source
       
     9  * distribution for preciese wording.
       
    10  * 
       
    11  * Copyright (C) 2002-2003 Aleksey Sanin <aleksey@aleksey.com>
       
    12  * Portion Copyright © 2009 Nokia Corporation and/or its subsidiary(-ies). All rights reserved.
       
    13  */
       
    14 #include "xmlsec_config.h"
       
    15 #ifndef XMLSEC_NO_XMLDSIG
       
    16 #include "xmlsec_globals.h"
       
    17 
       
    18 #include <stdlib.h>
       
    19 #include <stdio.h>
       
    20 #include <string.h>
       
    21 
       
    22 #include <libxml2_tree.h>
       
    23 #include <libxml2_parser.h>
       
    24 #include <libxml2_globals.h>
       
    25 
       
    26 #include "xmlsec_xmlsec.h"
       
    27 #include "xmlsec_buffer.h"
       
    28 #include "xmlsec_xmltree.h"
       
    29 #include "xmlsec_keys.h"
       
    30 #include "xmlsec_keysmngr.h"
       
    31 #include "xmlsec_transforms.h"
       
    32 #include "xmlsec_membuf.h"
       
    33 #include "xmlsec_xmldsig.h"
       
    34 #include "xmlsec_errors.h"
       
    35 
       
    36 /**************************************************************************
       
    37  *
       
    38  * xmlSecDSigCtx
       
    39  *
       
    40  *************************************************************************/
       
    41 static int	xmlSecDSigCtxProcessSignatureNode	(xmlSecDSigCtxPtr dsigCtx, 
       
    42 							 xmlNodePtr node);
       
    43 static int	xmlSecDSigCtxProcessSignedInfoNode	(xmlSecDSigCtxPtr dsigCtx, 
       
    44 							 xmlNodePtr node);
       
    45 static int	xmlSecDSigCtxProcessKeyInfoNode		(xmlSecDSigCtxPtr dsigCtx, 
       
    46 							 xmlNodePtr node);
       
    47 static int	xmlSecDSigCtxProcessObjectNode		(xmlSecDSigCtxPtr dsigCtx, 
       
    48 							 xmlNodePtr node);
       
    49 static int	xmlSecDSigCtxProcessManifestNode	(xmlSecDSigCtxPtr dsigCtx, 
       
    50 							 xmlNodePtr node);
       
    51 
       
    52 /* The ID attribute in XMLDSig is 'Id' */
       
    53 static const xmlChar*		xmlSecDSigIds[] = { xmlSecAttrId, NULL };
       
    54 
       
    55 /**
       
    56  * xmlSecDSigCtxCreate:
       
    57  * @keysMngr: 		the pointer to keys manager.
       
    58  *
       
    59  * Creates <dsig:Signature/> element processing context.
       
    60  * The caller is responsible for destroying returend object by calling 
       
    61  * #xmlSecDSigCtxDestroy function.
       
    62  *
       
    63  * Returns pointer to newly allocated context object or NULL if an error
       
    64  * occurs.
       
    65  */
       
    66 EXPORT_C
       
    67 xmlSecDSigCtxPtr	
       
    68 xmlSecDSigCtxCreate(xmlSecKeysMngrPtr keysMngr) {
       
    69     xmlSecDSigCtxPtr dsigCtx;
       
    70     int ret;
       
    71     
       
    72     dsigCtx = (xmlSecDSigCtxPtr) xmlMalloc(sizeof(xmlSecDSigCtx));
       
    73     if(dsigCtx == NULL) {
       
    74 	xmlSecError(XMLSEC_ERRORS_HERE,
       
    75 		    NULL,
       
    76 		    NULL,
       
    77 		    XMLSEC_ERRORS_R_MALLOC_FAILED,
       
    78 		    "sizeof(xmlSecDSigCtx)=%d", 
       
    79 		    sizeof(xmlSecDSigCtx));
       
    80 	return(NULL);
       
    81     }
       
    82     
       
    83     ret = xmlSecDSigCtxInitialize(dsigCtx, keysMngr);
       
    84     if(ret < 0) {
       
    85 	xmlSecError(XMLSEC_ERRORS_HERE,
       
    86 		    NULL,
       
    87 		    "xmlSecDSigCtxInitialize",
       
    88 		    XMLSEC_ERRORS_R_XMLSEC_FAILED,
       
    89 		    XMLSEC_ERRORS_NO_MESSAGE);
       
    90 	xmlSecDSigCtxDestroy(dsigCtx);
       
    91 	return(NULL);   
       
    92     }
       
    93     return(dsigCtx);    
       
    94 }
       
    95 
       
    96 /**
       
    97  * xmlSecDSigCtxDestroy:
       
    98  * @dsigCtx:		the pointer to <dsig:Signature/> processing context.
       
    99  *
       
   100  * Destroy context object created with #xmlSecDSigCtxCreate function.
       
   101  */
       
   102 EXPORT_C
       
   103 void  
       
   104 xmlSecDSigCtxDestroy(xmlSecDSigCtxPtr dsigCtx) {
       
   105     xmlSecAssert(dsigCtx != NULL);
       
   106     
       
   107     xmlSecDSigCtxFinalize(dsigCtx);
       
   108     xmlFree(dsigCtx);
       
   109 }
       
   110 
       
   111 /**
       
   112  * xmlSecDSigCtxInitialize:
       
   113  * @dsigCtx:		the pointer to <dsig:Signature/> processing context.
       
   114  * @keysMngr: 		the pointer to keys manager.
       
   115  *
       
   116  * Initializes <dsig:Signature/> element processing context.
       
   117  * The caller is responsible for cleaing up returend object by calling 
       
   118  * #xmlSecDSigCtxFinalize function.
       
   119  *
       
   120  * Returns 0 on success or a negative value if an error occurs.
       
   121  */
       
   122 EXPORT_C
       
   123 int 
       
   124 xmlSecDSigCtxInitialize(xmlSecDSigCtxPtr dsigCtx, xmlSecKeysMngrPtr keysMngr) {
       
   125     int ret;
       
   126     
       
   127     xmlSecAssert2(dsigCtx != NULL, -1);
       
   128     
       
   129     memset(dsigCtx, 0, sizeof(xmlSecDSigCtx));
       
   130 
       
   131     /* initialize key info */
       
   132     ret = xmlSecKeyInfoCtxInitialize(&(dsigCtx->keyInfoReadCtx), keysMngr);
       
   133     if(ret < 0) {
       
   134 	xmlSecError(XMLSEC_ERRORS_HERE,
       
   135 		    NULL,
       
   136 		    "xmlSecKeyInfoCtxInitialize",
       
   137 		    XMLSEC_ERRORS_R_XMLSEC_FAILED,
       
   138 		    XMLSEC_ERRORS_NO_MESSAGE);
       
   139 	return(-1);   
       
   140     }
       
   141     dsigCtx->keyInfoReadCtx.mode = xmlSecKeyInfoModeRead;
       
   142     
       
   143     ret = xmlSecKeyInfoCtxInitialize(&(dsigCtx->keyInfoWriteCtx), keysMngr);
       
   144     if(ret < 0) {
       
   145 	xmlSecError(XMLSEC_ERRORS_HERE,
       
   146 		    NULL,
       
   147 		    "xmlSecKeyInfoCtxInitialize",
       
   148 		    XMLSEC_ERRORS_R_XMLSEC_FAILED,
       
   149 		    XMLSEC_ERRORS_NO_MESSAGE);
       
   150 	return(-1);   
       
   151     }
       
   152     dsigCtx->keyInfoWriteCtx.mode = xmlSecKeyInfoModeWrite;
       
   153     /* it's not wise to write private key :) */
       
   154     dsigCtx->keyInfoWriteCtx.keyReq.keyType = xmlSecKeyDataTypePublic;
       
   155 
       
   156     /* initializes transforms dsigCtx */
       
   157     ret = xmlSecTransformCtxInitialize(&(dsigCtx->transformCtx));
       
   158     if(ret < 0) {
       
   159 	xmlSecError(XMLSEC_ERRORS_HERE,
       
   160 		    NULL,
       
   161 		    "xmlSecTransformCtxInitialize",
       
   162 		    XMLSEC_ERRORS_R_XMLSEC_FAILED,
       
   163 		    XMLSEC_ERRORS_NO_MESSAGE);
       
   164 	return(-1);   
       
   165     }
       
   166 
       
   167     /* references lists from SignedInfo and Manifest elements */
       
   168     xmlSecPtrListInitialize(&(dsigCtx->signedInfoReferences), 
       
   169 			    xmlSecDSigReferenceCtxListId);
       
   170     xmlSecPtrListInitialize(&(dsigCtx->manifestReferences), 
       
   171 			    xmlSecDSigReferenceCtxListId);    
       
   172 
       
   173     dsigCtx->enabledReferenceUris = xmlSecTransformUriTypeAny;
       
   174     return(0);
       
   175 }
       
   176 
       
   177 /**
       
   178  * xmlSecDSigCtxFinalize:
       
   179  * @dsigCtx:		the pointer to <dsig:Signature/> processing context.
       
   180  *
       
   181  * Cleans up @dsigCtx object initialized with #xmlSecDSigCtxInitialize function.
       
   182  */
       
   183 EXPORT_C
       
   184 void 
       
   185 xmlSecDSigCtxFinalize(xmlSecDSigCtxPtr dsigCtx) {
       
   186     xmlSecAssert(dsigCtx != NULL);
       
   187 
       
   188     xmlSecTransformCtxFinalize(&(dsigCtx->transformCtx));
       
   189     xmlSecKeyInfoCtxFinalize(&(dsigCtx->keyInfoReadCtx));
       
   190     xmlSecKeyInfoCtxFinalize(&(dsigCtx->keyInfoWriteCtx));
       
   191     xmlSecPtrListFinalize(&(dsigCtx->signedInfoReferences));
       
   192     xmlSecPtrListFinalize(&(dsigCtx->manifestReferences));
       
   193 
       
   194     if(dsigCtx->enabledReferenceTransforms != NULL) {
       
   195 	xmlSecPtrListDestroy(dsigCtx->enabledReferenceTransforms);	
       
   196     }
       
   197     if(dsigCtx->signKey != NULL) {
       
   198 	xmlSecKeyDestroy(dsigCtx->signKey);
       
   199     }
       
   200     if(dsigCtx->id != NULL) {
       
   201 	xmlFree(dsigCtx->id);
       
   202     }	
       
   203     memset(dsigCtx, 0, sizeof(xmlSecDSigCtx));
       
   204 }
       
   205 
       
   206 /**
       
   207  * xmlSecDSigCtxEnableReferenceTransform:
       
   208  * @dsigCtx:		the pointer to <dsig:Signature/> processing context.
       
   209  * @transformId:	the transform klass.
       
   210  *
       
   211  * Enables @transformId for <dsig:Reference/> elements processing.
       
   212  *
       
   213  * Returns 0 on success or a negative value if an error occurs.
       
   214  */
       
   215 EXPORT_C
       
   216 int 
       
   217 xmlSecDSigCtxEnableReferenceTransform(xmlSecDSigCtxPtr dsigCtx, xmlSecTransformId transformId) {
       
   218     int ret;
       
   219     
       
   220     xmlSecAssert2(dsigCtx != NULL, -1);
       
   221     xmlSecAssert2(dsigCtx->result == NULL, -1);
       
   222     xmlSecAssert2(transformId != xmlSecTransformIdUnknown, -1);
       
   223 
       
   224     if(dsigCtx->enabledReferenceTransforms == NULL) {
       
   225 	dsigCtx->enabledReferenceTransforms = xmlSecPtrListCreate(xmlSecTransformIdListId);
       
   226 	if(dsigCtx->enabledReferenceTransforms == NULL) {
       
   227 	    xmlSecError(XMLSEC_ERRORS_HERE,
       
   228 			NULL,
       
   229 			"xmlSecPtrListCreate",
       
   230 			XMLSEC_ERRORS_R_XMLSEC_FAILED,
       
   231 			XMLSEC_ERRORS_NO_MESSAGE);
       
   232 	    return(-1);   
       
   233 	}
       
   234     }	
       
   235 	
       
   236     ret = xmlSecPtrListAdd(dsigCtx->enabledReferenceTransforms, (void*)transformId);
       
   237     if(ret < 0) {
       
   238 	xmlSecError(XMLSEC_ERRORS_HERE,
       
   239 		    NULL,
       
   240 		    "xmlSecPtrListAdd",
       
   241 		    XMLSEC_ERRORS_R_XMLSEC_FAILED,
       
   242 		    XMLSEC_ERRORS_NO_MESSAGE);
       
   243 	return(-1);   
       
   244     }
       
   245     return(0);
       
   246 }
       
   247 
       
   248 /**
       
   249  * xmlSecDSigCtxEnableSignatureTransform:
       
   250  * @dsigCtx:		the pointer to <dsig:Signature/> processing context.
       
   251  * @transformId:	the transform klass.
       
   252  *
       
   253  * Enables @transformId for <dsig:SignedInfo/> element processing.
       
   254  *
       
   255  * Returns 0 on success or a negative value if an error occurs.
       
   256  */
       
   257 EXPORT_C
       
   258 int 
       
   259 xmlSecDSigCtxEnableSignatureTransform(xmlSecDSigCtxPtr dsigCtx, xmlSecTransformId transformId) {
       
   260     xmlSecAssert2(dsigCtx != NULL, -1);
       
   261     xmlSecAssert2(dsigCtx->result == NULL, -1);
       
   262     xmlSecAssert2(transformId != xmlSecTransformIdUnknown, -1);
       
   263 
       
   264     return(xmlSecPtrListAdd(&(dsigCtx->transformCtx.enabledTransforms), (void*)transformId));
       
   265 }
       
   266 
       
   267 /**
       
   268  * xmlSecDSigCtxGetPreSignBuffer:
       
   269  * @dsigCtx:		the pointer to <dsig:Signature/> processing context.
       
   270  * 
       
   271  * Gets pointer to the buffer with serialized <dsig:SignedInfo/> element
       
   272  * just before signature claculation (valid if and only if 
       
   273  * #XMLSEC_DSIG_FLAGS_STORE_SIGNATURE context flag is set.
       
   274  *
       
   275  * Returns 0 on success or a negative value if an error occurs.
       
   276  */
       
   277 EXPORT_C
       
   278 xmlSecBufferPtr 
       
   279 xmlSecDSigCtxGetPreSignBuffer(xmlSecDSigCtxPtr dsigCtx) {
       
   280     xmlSecAssert2(dsigCtx != NULL, NULL);
       
   281     
       
   282     return((dsigCtx->preSignMemBufMethod != NULL) ? 
       
   283 	    xmlSecTransformMemBufGetBuffer(dsigCtx->preSignMemBufMethod) : NULL);
       
   284 }
       
   285 
       
   286 /**
       
   287  * xmlSecDSigCtxSign:
       
   288  * @dsigCtx:		the pointer to <dsig:Signature/> processing context.
       
   289  * @tmpl:		the pointer to <dsig:Signature/> node with signature template.
       
   290  *
       
   291  * Signs the data as described in @tmpl node.
       
   292  *
       
   293  * Returns 0 on success or a negative value if an error occurs.
       
   294  */
       
   295 EXPORT_C
       
   296 int 
       
   297 xmlSecDSigCtxSign(xmlSecDSigCtxPtr dsigCtx, xmlNodePtr tmpl) {
       
   298     int ret;
       
   299     
       
   300     xmlSecAssert2(dsigCtx != NULL, -1);
       
   301     xmlSecAssert2(dsigCtx->result == NULL, -1);
       
   302     xmlSecAssert2(tmpl != NULL, -1);
       
   303     xmlSecAssert2(tmpl->doc != NULL, -1);
       
   304 
       
   305     /* add ids for Signature nodes */
       
   306     dsigCtx->operation 	= xmlSecTransformOperationSign;
       
   307     dsigCtx->status 	= xmlSecDSigStatusUnknown;
       
   308     xmlSecAddIDs(tmpl->doc, tmpl, xmlSecDSigIds);
       
   309 
       
   310     /* read signature template */
       
   311     ret = xmlSecDSigCtxProcessSignatureNode(dsigCtx, tmpl);
       
   312     if(ret < 0) {
       
   313     	xmlSecError(XMLSEC_ERRORS_HERE,
       
   314 		    NULL,
       
   315 		    "xmlSecDSigCtxSigantureProcessNode",
       
   316 		    XMLSEC_ERRORS_R_XMLSEC_FAILED,
       
   317 		    XMLSEC_ERRORS_NO_MESSAGE);
       
   318 	return(-1);
       
   319     }
       
   320     xmlSecAssert2(dsigCtx->signMethod != NULL, -1);
       
   321     xmlSecAssert2(dsigCtx->signValueNode != NULL, -1);
       
   322 
       
   323     /* references processing might change the status */
       
   324     if(dsigCtx->status != xmlSecDSigStatusUnknown) {
       
   325 	return(0);
       
   326     }
       
   327 
       
   328     /* check what we've got */
       
   329     dsigCtx->result = dsigCtx->transformCtx.result;
       
   330     if((dsigCtx->result == NULL) || (xmlSecBufferGetData(dsigCtx->result) == NULL)) {
       
   331     	xmlSecError(XMLSEC_ERRORS_HERE,
       
   332 		    NULL,
       
   333 		    NULL,
       
   334 		    XMLSEC_ERRORS_R_INVALID_RESULT,
       
   335 		    XMLSEC_ERRORS_NO_MESSAGE);
       
   336 	return(-1);
       
   337     }
       
   338 
       
   339     /* write signed data to xml */
       
   340     xmlNodeSetContentLen(dsigCtx->signValueNode,
       
   341 			    xmlSecBufferGetData(dsigCtx->result),
       
   342 			    xmlSecBufferGetSize(dsigCtx->result));
       
   343     if ( OOM_FLAG )
       
   344         {
       
   345         return(-1);
       
   346         }
       
   347     
       
   348     /* set success status and we are done */
       
   349     dsigCtx->status = xmlSecDSigStatusSucceeded;
       
   350     return(0);    
       
   351 }
       
   352 
       
   353 /**
       
   354  * xmlSecDSigCtxVerify:
       
   355  * @dsigCtx:		the pointer to <dsig:Signature/> processing context.
       
   356  * @node:		the pointer with <dsig:Signature/> node.
       
   357  * 
       
   358  * Vaidates signature in the @node. The verification result is returned
       
   359  * in #status member of the @dsigCtx object.
       
   360  *
       
   361  * Returns 0 on success (check #status member of @dsigCtx to get 
       
   362  * signature verification result) or a negative value if an error occurs.
       
   363  */
       
   364 EXPORT_C
       
   365 int 
       
   366 xmlSecDSigCtxVerify(xmlSecDSigCtxPtr dsigCtx, xmlNodePtr node) {
       
   367     int ret;
       
   368     
       
   369     xmlSecAssert2(dsigCtx != NULL, -1);
       
   370     xmlSecAssert2(node != NULL, -1);
       
   371     xmlSecAssert2(node->doc != NULL, -1);
       
   372 
       
   373     /* add ids for Signature nodes */
       
   374     dsigCtx->operation 	= xmlSecTransformOperationVerify;
       
   375     dsigCtx->status 	= xmlSecDSigStatusUnknown;
       
   376     xmlSecAddIDs(node->doc, node, xmlSecDSigIds);
       
   377     
       
   378     /* read siganture info */
       
   379     ret = xmlSecDSigCtxProcessSignatureNode(dsigCtx, node);
       
   380     if(ret < 0) {
       
   381     	xmlSecError(XMLSEC_ERRORS_HERE,
       
   382 		    NULL,
       
   383 		    "xmlSecDSigCtxSigantureProcessNode",
       
   384 		    XMLSEC_ERRORS_R_XMLSEC_FAILED,
       
   385 		    XMLSEC_ERRORS_NO_MESSAGE);
       
   386 	return(-1);
       
   387     }
       
   388     xmlSecAssert2(dsigCtx->signMethod != NULL, -1);
       
   389     xmlSecAssert2(dsigCtx->signValueNode != NULL, -1);
       
   390 
       
   391     /* references processing might change the status */
       
   392     if(dsigCtx->status != xmlSecDSigStatusUnknown) {
       
   393 	return(0);
       
   394     }
       
   395 
       
   396     /* verify SignatureValue node content */
       
   397     ret = xmlSecTransformVerifyNodeContent(dsigCtx->signMethod, dsigCtx->signValueNode,
       
   398 					   &(dsigCtx->transformCtx));
       
   399     if(ret < 0) {
       
   400     	xmlSecError(XMLSEC_ERRORS_HERE,
       
   401 		    NULL,
       
   402 		    "xmlSecTransformVerifyNodeContent",
       
   403 		    XMLSEC_ERRORS_R_XMLSEC_FAILED,
       
   404 		    XMLSEC_ERRORS_NO_MESSAGE);
       
   405 	return(-1);
       
   406     }
       
   407     
       
   408     /* set status and we are done */
       
   409     if(dsigCtx->signMethod->status == xmlSecTransformStatusOk) {
       
   410         dsigCtx->status = xmlSecDSigStatusSucceeded;
       
   411     } else {
       
   412         dsigCtx->status = xmlSecDSigStatusInvalid;
       
   413     }
       
   414     return(0);
       
   415 }
       
   416 
       
   417 /**
       
   418  * xmlSecDSigCtxProcessSignatureNode:
       
   419  *
       
   420  * The Signature  element (http://www.w3.org/TR/xmldsig-core/#sec-Signature)
       
   421  *
       
   422  * The Signature element is the root element of an XML Signature. 
       
   423  * Implementation MUST generate laxly schema valid [XML-schema] Signature 
       
   424  * elements as specified by the following schema:
       
   425  * The way in which the SignedInfo element is presented to the 
       
   426  * canonicalization method is dependent on that method. The following 
       
   427  * applies to algorithms which process XML as nodes or characters:
       
   428  *
       
   429  *  - XML based canonicalization implementations MUST be provided with 
       
   430  *  a [XPath] node-set originally formed from the document containing 
       
   431  *  the SignedInfo and currently indicating the SignedInfo, its descendants,
       
   432  *  and the attribute and namespace nodes of SignedInfo and its descendant 
       
   433  *  elements.
       
   434  *
       
   435  *  - Text based canonicalization algorithms (such as CRLF and charset 
       
   436  *  normalization) should be provided with the UTF-8 octets that represent 
       
   437  *  the well-formed SignedInfo element, from the first character to the 
       
   438  *  last character of the XML representation, inclusive. This includes 
       
   439  *  the entire text of the start and end tags of the SignedInfo element 
       
   440  *  as well as all descendant markup and character data (i.e., the text) 
       
   441  *  between those tags. Use of text based canonicalization of SignedInfo 
       
   442  *  is NOT RECOMMENDED.   	     
       
   443  *
       
   444  *  =================================
       
   445  *  we do not support any non XML based C14N 
       
   446  *
       
   447  * Schema Definition:
       
   448  *
       
   449  *  <element name="Signature" type="ds:SignatureType"/>
       
   450  *  <complexType name="SignatureType">
       
   451  *  <sequence> 
       
   452  *     <element ref="ds:SignedInfo"/> 
       
   453  *     <element ref="ds:SignatureValue"/> 
       
   454  *     <element ref="ds:KeyInfo" minOccurs="0"/> 
       
   455  *     <element ref="ds:Object" minOccurs="0" maxOccurs="unbounded"/> 
       
   456  *     </sequence> <attribute name="Id" type="ID" use="optional"/>
       
   457  *  </complexType>
       
   458  *    
       
   459  * DTD:
       
   460  *    
       
   461  *  <!ELEMENT Signature (SignedInfo, SignatureValue, KeyInfo?, Object*)  >
       
   462  *  <!ATTLIST Signature  
       
   463  *      xmlns   CDATA   #FIXED 'http://www.w3.org/2000/09/xmldsig#'
       
   464  *      Id      ID  #IMPLIED >
       
   465  *
       
   466  */
       
   467 static int
       
   468 xmlSecDSigCtxProcessSignatureNode(xmlSecDSigCtxPtr dsigCtx, xmlNodePtr node) {
       
   469     xmlSecTransformDataType firstType;
       
   470     xmlNodePtr signedInfoNode = NULL;
       
   471     xmlNodePtr keyInfoNode = NULL;
       
   472     xmlNodePtr cur;
       
   473     int ret;
       
   474     
       
   475     xmlSecAssert2(dsigCtx != NULL, -1);
       
   476     xmlSecAssert2((dsigCtx->operation == xmlSecTransformOperationSign) || (dsigCtx->operation == xmlSecTransformOperationVerify), -1);
       
   477     xmlSecAssert2(dsigCtx->status == xmlSecDSigStatusUnknown, -1);
       
   478     xmlSecAssert2(dsigCtx->signValueNode == NULL, -1);
       
   479     xmlSecAssert2(dsigCtx->signMethod == NULL, -1);
       
   480     xmlSecAssert2(dsigCtx->c14nMethod == NULL, -1);
       
   481     xmlSecAssert2(node != NULL, -1);
       
   482 
       
   483     if(!xmlSecCheckNodeName(node, xmlSecNodeSignature, xmlSecDSigNs)) {
       
   484     	xmlSecError(XMLSEC_ERRORS_HERE,
       
   485 		    NULL,
       
   486 		    xmlSecErrorsSafeString(xmlSecNodeGetName(node)),
       
   487 		    XMLSEC_ERRORS_R_INVALID_NODE,
       
   488 		    "expected=%s",
       
   489 		    xmlSecErrorsSafeString(xmlSecNodeSignature));
       
   490 	return(-1);	    
       
   491     }
       
   492 
       
   493     /* read node data */
       
   494     xmlSecAssert2(dsigCtx->id == NULL, -1);
       
   495     dsigCtx->id = xmlGetProp(node, xmlSecAttrId);
       
   496 
       
   497     /* first node is required SignedInfo */
       
   498     cur = xmlSecGetNextElementNode(node->children);    
       
   499     if((cur == NULL) || (!xmlSecCheckNodeName(cur, xmlSecNodeSignedInfo, xmlSecDSigNs))) {
       
   500     	xmlSecError(XMLSEC_ERRORS_HERE,
       
   501 		    NULL,
       
   502 		    xmlSecErrorsSafeString(xmlSecNodeGetName(cur)),
       
   503 		    XMLSEC_ERRORS_R_INVALID_NODE,
       
   504 		    "expected=%s",
       
   505 		    xmlSecErrorsSafeString(xmlSecNodeSignedInfo));
       
   506         return(-1);
       
   507     }
       
   508     signedInfoNode = cur;
       
   509     cur = xmlSecGetNextElementNode(cur->next);
       
   510 
       
   511     /* next node is required SignatureValue */
       
   512     if((cur == NULL) || (!xmlSecCheckNodeName(cur, xmlSecNodeSignatureValue, xmlSecDSigNs))) {
       
   513     	xmlSecError(XMLSEC_ERRORS_HERE,
       
   514 		    NULL,
       
   515 		    xmlSecErrorsSafeString(xmlSecNodeGetName(cur)),
       
   516 		    XMLSEC_ERRORS_R_INVALID_NODE,
       
   517 		    "expected=%s",
       
   518 		    xmlSecErrorsSafeString(xmlSecNodeSignatureValue));
       
   519 	return(-1);
       
   520     }
       
   521     dsigCtx->signValueNode = cur;
       
   522     cur = xmlSecGetNextElementNode(cur->next);
       
   523 
       
   524     /* next node is optional KeyInfo */
       
   525     if((cur != NULL) && (xmlSecCheckNodeName(cur, xmlSecNodeKeyInfo, xmlSecDSigNs))) {
       
   526 	keyInfoNode = cur;
       
   527 	cur = xmlSecGetNextElementNode(cur->next);
       
   528     } else {
       
   529 	keyInfoNode = NULL;
       
   530     }
       
   531     
       
   532     /* next nodes are optional Object nodes */
       
   533     while((cur != NULL) && (xmlSecCheckNodeName(cur, xmlSecNodeObject, xmlSecDSigNs))) {
       
   534 	/* read manifests from objects */
       
   535 	if((dsigCtx->flags & XMLSEC_DSIG_FLAGS_IGNORE_MANIFESTS) == 0) {
       
   536 	    ret = xmlSecDSigCtxProcessObjectNode(dsigCtx, cur);
       
   537 	    if(ret < 0) {
       
   538     		xmlSecError(XMLSEC_ERRORS_HERE,
       
   539 			    NULL,
       
   540 			    "xmlSecDSigCtxProcessObjectNode",
       
   541 			    XMLSEC_ERRORS_R_XMLSEC_FAILED,
       
   542 			    XMLSEC_ERRORS_NO_MESSAGE);
       
   543 		return(-1);	    	    
       
   544 	    }
       
   545 	}
       
   546 	cur = xmlSecGetNextElementNode(cur->next);
       
   547     }
       
   548     
       
   549     /* if there is something left than it's an error */
       
   550     if(cur != NULL) {
       
   551     	xmlSecError(XMLSEC_ERRORS_HERE,
       
   552 		    NULL,
       
   553 		    xmlSecErrorsSafeString(xmlSecNodeGetName(cur)),
       
   554 		    XMLSEC_ERRORS_R_UNEXPECTED_NODE,
       
   555 		    XMLSEC_ERRORS_NO_MESSAGE);
       
   556 	return(-1);
       
   557     }
       
   558 
       
   559     /* now validated all the references and prepare transform */
       
   560     ret = xmlSecDSigCtxProcessSignedInfoNode(dsigCtx, signedInfoNode);
       
   561     if(ret < 0) {
       
   562     	xmlSecError(XMLSEC_ERRORS_HERE,
       
   563 		    NULL,
       
   564 		    "xmlSecDSigCtxProcessSignedInfoNode",
       
   565 		    XMLSEC_ERRORS_R_XMLSEC_FAILED,
       
   566 		    XMLSEC_ERRORS_NO_MESSAGE);
       
   567 	return(-1);	
       
   568     }				
       
   569     /* references processing might change the status */
       
   570     if(dsigCtx->status != xmlSecDSigStatusUnknown) {
       
   571 	return(0);
       
   572     }
       
   573     
       
   574     /* as the result, we should have sign and c14n methods set */    
       
   575     xmlSecAssert2(dsigCtx->signMethod != NULL, -1);
       
   576     xmlSecAssert2(dsigCtx->c14nMethod != NULL, -1);
       
   577 
       
   578     ret = xmlSecDSigCtxProcessKeyInfoNode(dsigCtx, keyInfoNode);
       
   579     if(ret < 0) {
       
   580     	xmlSecError(XMLSEC_ERRORS_HERE,
       
   581 		    NULL,
       
   582 		    "xmlSecDSigCtxProcessKeyInfoNode",
       
   583 		    XMLSEC_ERRORS_R_XMLSEC_FAILED,
       
   584 		    XMLSEC_ERRORS_NO_MESSAGE);
       
   585 	return(-1);	
       
   586     }				
       
   587     /* as the result, we should have a key */
       
   588     xmlSecAssert2(dsigCtx->signKey != NULL, -1);
       
   589 
       
   590     /* if we need to write result to xml node then we need base64 encode result */
       
   591     if(dsigCtx->operation == xmlSecTransformOperationSign) {	
       
   592 	xmlSecTransformPtr base64Encode;
       
   593 	
       
   594 	/* we need to add base64 encode transform */
       
   595 	base64Encode = xmlSecTransformCtxCreateAndAppend(&(dsigCtx->transformCtx), 
       
   596 							 xmlSecTransformBase64Id);
       
   597     	if(base64Encode == NULL) {
       
   598     	    xmlSecError(XMLSEC_ERRORS_HERE,
       
   599 			NULL,
       
   600 			"xmlSecTransformCtxCreateAndAppend",
       
   601 			XMLSEC_ERRORS_R_XMLSEC_FAILED,
       
   602 			XMLSEC_ERRORS_NO_MESSAGE);
       
   603 	    return(-1);
       
   604 	}
       
   605 	base64Encode->operation = xmlSecTransformOperationEncode;
       
   606     }
       
   607 
       
   608     firstType = xmlSecTransformGetDataType(dsigCtx->transformCtx.first, 
       
   609 					   xmlSecTransformModePush, 
       
   610 					   &(dsigCtx->transformCtx));
       
   611     if((firstType & xmlSecTransformDataTypeXml) != 0) {
       
   612 	xmlSecNodeSetPtr nodeset = NULL;
       
   613 
       
   614 	xmlSecAssert2(signedInfoNode != NULL, -1);
       
   615         nodeset = xmlSecNodeSetGetChildren(signedInfoNode->doc, signedInfoNode, 1, 0);
       
   616 	if(nodeset == NULL) {
       
   617     	    xmlSecError(XMLSEC_ERRORS_HERE,
       
   618 			NULL,
       
   619 			"xmlSecNodeSetGetChildren",
       
   620 			XMLSEC_ERRORS_R_XMLSEC_FAILED,
       
   621 			"node=%s",
       
   622 		        xmlSecErrorsSafeString(xmlSecNodeGetName(signedInfoNode)));
       
   623 	    return(-1);
       
   624 	}
       
   625 
       
   626 	/* calculate the signature */
       
   627 	ret = xmlSecTransformCtxXmlExecute(&(dsigCtx->transformCtx), nodeset);
       
   628 	if(ret < 0) {
       
   629     	    xmlSecError(XMLSEC_ERRORS_HERE,
       
   630 		        NULL,
       
   631 			"xmlSecTransformCtxXmlExecute",
       
   632 		        XMLSEC_ERRORS_R_XMLSEC_FAILED,
       
   633 			XMLSEC_ERRORS_NO_MESSAGE);
       
   634 	    xmlSecNodeSetDestroy(nodeset);
       
   635 	    return(-1);
       
   636 	}
       
   637 	xmlSecNodeSetDestroy(nodeset);
       
   638     } else {
       
   639     	xmlSecError(XMLSEC_ERRORS_HERE,
       
   640 		    NULL,
       
   641 		    "the binary c14n transforms are not supported yet",
       
   642 		    XMLSEC_ERRORS_R_NOT_IMPLEMENTED,
       
   643 		    XMLSEC_ERRORS_NO_MESSAGE);
       
   644 	return(-1);
       
   645     }
       
   646     return(0);
       
   647 }
       
   648 
       
   649 /** 
       
   650  * xmlSecDSigCtxProcessSignedInfoNode:
       
   651  *
       
   652  * The SignedInfo Element (http://www.w3.org/TR/xmldsig-core/#sec-SignedInfo)
       
   653  * 
       
   654  * The structure of SignedInfo includes the canonicalization algorithm, 
       
   655  * a result algorithm, and one or more references. The SignedInfo element 
       
   656  * may contain an optional ID attribute that will allow it to be referenced by 
       
   657  * other signatures and objects.
       
   658  *
       
   659  * SignedInfo does not include explicit result or digest properties (such as
       
   660  * calculation time, cryptographic device serial number, etc.). If an 
       
   661  * application needs to associate properties with the result or digest, 
       
   662  * it may include such information in a SignatureProperties element within 
       
   663  * an Object element.
       
   664  *
       
   665  * Schema Definition:
       
   666  *
       
   667  *  <element name="SignedInfo" type="ds:SignedInfoType"/> 
       
   668  *  <complexType name="SignedInfoType">
       
   669  *    <sequence> 
       
   670  *      <element ref="ds:CanonicalizationMethod"/>
       
   671  *      <element ref="ds:SignatureMethod"/> 
       
   672  *      <element ref="ds:Reference" maxOccurs="unbounded"/> 
       
   673  *    </sequence> 
       
   674  *    <attribute name="Id" type="ID" use="optional"/> 
       
   675  *  </complexType>
       
   676  *    
       
   677  * DTD:
       
   678  *    
       
   679  *  <!ELEMENT SignedInfo (CanonicalizationMethod, SignatureMethod,  Reference+) >
       
   680  *  <!ATTLIST SignedInfo  Id   ID      #IMPLIED>
       
   681  * 
       
   682  */
       
   683 static int 
       
   684 xmlSecDSigCtxProcessSignedInfoNode(xmlSecDSigCtxPtr dsigCtx, xmlNodePtr node) {
       
   685     xmlSecDSigReferenceCtxPtr dsigRefCtx;
       
   686     xmlNodePtr cur;
       
   687     int ret;
       
   688     
       
   689     xmlSecAssert2(dsigCtx != NULL, -1);	
       
   690     xmlSecAssert2(dsigCtx->status == xmlSecDSigStatusUnknown, -1);
       
   691     xmlSecAssert2(dsigCtx->signMethod == NULL, -1);
       
   692     xmlSecAssert2(dsigCtx->c14nMethod == NULL, -1);
       
   693     xmlSecAssert2((dsigCtx->operation == xmlSecTransformOperationSign) || (dsigCtx->operation == xmlSecTransformOperationVerify), -1);
       
   694     xmlSecAssert2(xmlSecPtrListGetSize(&(dsigCtx->signedInfoReferences)) == 0, -1);
       
   695     xmlSecAssert2(node != NULL, -1);
       
   696     
       
   697     /* first node is required CanonicalizationMethod. */
       
   698     cur = xmlSecGetNextElementNode(node->children);
       
   699     if((cur != NULL) && (xmlSecCheckNodeName(cur, xmlSecNodeCanonicalizationMethod, xmlSecDSigNs))) {
       
   700 	dsigCtx->c14nMethod = xmlSecTransformCtxNodeRead(&(dsigCtx->transformCtx), 
       
   701 					cur, xmlSecTransformUsageC14NMethod);
       
   702 	if(dsigCtx->c14nMethod == NULL) {
       
   703 	    xmlSecError(XMLSEC_ERRORS_HERE,
       
   704 			NULL,
       
   705 			"xmlSecTransformCtxNodeRead",
       
   706 			XMLSEC_ERRORS_R_XMLSEC_FAILED,
       
   707 			"node=%s",
       
   708 			xmlSecErrorsSafeString(xmlSecNodeGetName(cur)));
       
   709 	    return(-1);	
       
   710 	}	
       
   711     } else if(dsigCtx->defC14NMethodId != xmlSecTransformIdUnknown) {
       
   712 	/* the dsig spec does require CanonicalizationMethod node
       
   713 	 * to be present but in some case it application might decide to
       
   714 	 * minimize traffic */
       
   715 	dsigCtx->c14nMethod = xmlSecTransformCtxCreateAndAppend(&(dsigCtx->transformCtx), 
       
   716 							      dsigCtx->defC14NMethodId);
       
   717 	if(dsigCtx->c14nMethod == NULL) {
       
   718     	    xmlSecError(XMLSEC_ERRORS_HERE,
       
   719 			NULL,
       
   720 			"xmlSecTransformCtxAppend",
       
   721 			XMLSEC_ERRORS_R_XMLSEC_FAILED,
       
   722 			XMLSEC_ERRORS_NO_MESSAGE);
       
   723 	    return(-1);
       
   724 	}
       
   725     } else {
       
   726     	xmlSecError(XMLSEC_ERRORS_HERE,
       
   727 		    NULL,
       
   728 		    xmlSecErrorsSafeString(xmlSecNodeGetName(cur)),
       
   729 		    XMLSEC_ERRORS_R_INVALID_NODE,
       
   730 		    "expected=%s",
       
   731 		    xmlSecErrorsSafeString(xmlSecNodeCanonicalizationMethod));
       
   732 	return(-1);
       
   733     }	
       
   734     
       
   735     /* insert membuf if requested */
       
   736     if((dsigCtx->flags & XMLSEC_DSIG_FLAGS_STORE_SIGNATURE) != 0) {
       
   737 	xmlSecAssert2(dsigCtx->preSignMemBufMethod == NULL, -1);
       
   738 	dsigCtx->preSignMemBufMethod = xmlSecTransformCtxCreateAndAppend(&(dsigCtx->transformCtx), 
       
   739 						xmlSecTransformMemBufId);
       
   740 	if(dsigCtx->preSignMemBufMethod == NULL) {
       
   741     	    xmlSecError(XMLSEC_ERRORS_HERE,
       
   742 			NULL,
       
   743 			"xmlSecTransformCtxCreateAndAppend",
       
   744 			XMLSEC_ERRORS_R_XMLSEC_FAILED,
       
   745 			"transform=%s",
       
   746 			xmlSecErrorsSafeString(xmlSecTransformKlassGetName(xmlSecTransformMemBufId)));
       
   747 	}
       
   748     }
       
   749         
       
   750     /* next node is required SignatureMethod. */
       
   751 	if (cur != NULL){
       
   752 		cur = xmlSecGetNextElementNode(cur->next);
       
   753 	}
       
   754     if((cur != NULL) && (xmlSecCheckNodeName(cur, xmlSecNodeSignatureMethod, xmlSecDSigNs))) {
       
   755 	dsigCtx->signMethod = xmlSecTransformCtxNodeRead(&(dsigCtx->transformCtx), 
       
   756 					cur, xmlSecTransformUsageSignatureMethod);
       
   757 	if(dsigCtx->signMethod == NULL) {
       
   758 	    xmlSecError(XMLSEC_ERRORS_HERE,
       
   759 			NULL,
       
   760 			"xmlSecTransformCtxNodeRead",
       
   761 			XMLSEC_ERRORS_R_XMLSEC_FAILED,
       
   762 			"node=%s",
       
   763 			xmlSecErrorsSafeString(xmlSecNodeGetName(cur)));
       
   764 	    return(-1);	
       
   765 	}	
       
   766     } else if(dsigCtx->defSignMethodId != xmlSecTransformIdUnknown) {
       
   767 	/* the dsig spec does require SignatureMethod node
       
   768 	 * to be present but in some case it application might decide to
       
   769 	 * minimize traffic */
       
   770 	dsigCtx->signMethod = xmlSecTransformCtxCreateAndAppend(&(dsigCtx->transformCtx), 
       
   771 							      dsigCtx->defSignMethodId);
       
   772 	if(dsigCtx->signMethod == NULL) {
       
   773     	    xmlSecError(XMLSEC_ERRORS_HERE,
       
   774 			NULL,
       
   775 			"xmlSecTransformCtxAppend",
       
   776 			XMLSEC_ERRORS_R_XMLSEC_FAILED,
       
   777 			XMLSEC_ERRORS_NO_MESSAGE);
       
   778 	    return(-1);
       
   779 	}
       
   780     } else {
       
   781     	xmlSecError(XMLSEC_ERRORS_HERE,
       
   782 		    NULL,
       
   783 		    xmlSecErrorsSafeString(xmlSecNodeGetName(cur)),
       
   784 		    XMLSEC_ERRORS_R_INVALID_NODE,
       
   785 		    "expected=%s",
       
   786 		    xmlSecErrorsSafeString(xmlSecNodeSignatureMethod));
       
   787 	return(-1);
       
   788     }	
       
   789     dsigCtx->signMethod->operation = dsigCtx->operation;
       
   790     
       
   791     /* calculate references */
       
   792 	if (cur != NULL) {
       
   793 		cur = xmlSecGetNextElementNode(cur->next);
       
   794 	}
       
   795     while((cur != NULL) && (xmlSecCheckNodeName(cur, xmlSecNodeReference, xmlSecDSigNs))) {
       
   796         /* create reference */
       
   797 	dsigRefCtx = xmlSecDSigReferenceCtxCreate(dsigCtx, xmlSecDSigReferenceOriginSignedInfo);
       
   798 	if(dsigRefCtx == NULL) {
       
   799 	    xmlSecError(XMLSEC_ERRORS_HERE,
       
   800 			NULL,
       
   801 		        "xmlSecDSigReferenceCtxCreate",
       
   802 			XMLSEC_ERRORS_R_XMLSEC_FAILED,
       
   803 			XMLSEC_ERRORS_NO_MESSAGE);
       
   804 	    return(-1);	    
       
   805 	}
       
   806 
       
   807 	/* add to the list */
       
   808 	ret = xmlSecPtrListAdd(&(dsigCtx->signedInfoReferences), dsigRefCtx);
       
   809 	if(ret < 0) {
       
   810 	    xmlSecError(XMLSEC_ERRORS_HERE,
       
   811 			NULL,
       
   812 			"xmlSecPtrListAdd",
       
   813 			XMLSEC_ERRORS_R_XMLSEC_FAILED,
       
   814 			XMLSEC_ERRORS_NO_MESSAGE);
       
   815 	    xmlSecDSigReferenceCtxDestroy(dsigRefCtx);
       
   816 	    return(-1);	    
       
   817 	}
       
   818 
       
   819 	/* process */
       
   820 	ret = xmlSecDSigReferenceCtxProcessNode(dsigRefCtx, cur);
       
   821 	if(ret < 0) {
       
   822 	    xmlSecError(XMLSEC_ERRORS_HERE,
       
   823 			NULL,
       
   824 			"xmlSecDSigReferenceCtxProcessNode",
       
   825 			XMLSEC_ERRORS_R_XMLSEC_FAILED,
       
   826 			"node=%s",
       
   827 			xmlSecErrorsSafeString(xmlSecNodeGetName(cur)));
       
   828 	    return(-1);	    
       
   829 	}
       
   830 
       
   831 	/* bail out if next Reference processing failed */
       
   832 	if(dsigRefCtx->status != xmlSecDSigStatusSucceeded) {
       
   833 	    dsigCtx->status = xmlSecDSigStatusInvalid;
       
   834 	    return(0); 
       
   835 	}
       
   836 	cur = xmlSecGetNextElementNode(cur->next);
       
   837     }
       
   838 
       
   839     /* check that we have at least one Reference */
       
   840     if(xmlSecPtrListGetSize(&(dsigCtx->signedInfoReferences)) == 0) {
       
   841     	xmlSecError(XMLSEC_ERRORS_HERE,
       
   842 		    NULL,
       
   843 		    NULL,
       
   844 		    XMLSEC_ERRORS_R_DSIG_NO_REFERENCES,
       
   845 		    XMLSEC_ERRORS_NO_MESSAGE);
       
   846 	return(-1);
       
   847     }
       
   848 
       
   849     /* if there is something left than it's an error */
       
   850     if(cur != NULL) {
       
   851 	xmlSecError(XMLSEC_ERRORS_HERE,
       
   852 		    NULL,
       
   853 		    xmlSecErrorsSafeString(xmlSecNodeGetName(cur)),
       
   854 		    XMLSEC_ERRORS_R_UNEXPECTED_NODE,
       
   855 		    XMLSEC_ERRORS_NO_MESSAGE);
       
   856 	return(-1);
       
   857     }
       
   858     return(0);
       
   859 }
       
   860 
       
   861 static int 
       
   862 xmlSecDSigCtxProcessKeyInfoNode(xmlSecDSigCtxPtr dsigCtx, xmlNodePtr node) {
       
   863     int ret;
       
   864     
       
   865     xmlSecAssert2(dsigCtx != NULL, -1);
       
   866     xmlSecAssert2(dsigCtx->signMethod != NULL, -1);
       
   867 
       
   868     /* set key requirements */
       
   869     ret = xmlSecTransformSetKeyReq(dsigCtx->signMethod, &(dsigCtx->keyInfoReadCtx.keyReq));
       
   870     if(ret < 0) {
       
   871     	xmlSecError(XMLSEC_ERRORS_HERE,
       
   872 		    NULL,
       
   873 		    "xmlSecTransformSetKeyReq",
       
   874 		    XMLSEC_ERRORS_R_XMLSEC_FAILED,
       
   875 		    "transform=%s",
       
   876 		    xmlSecErrorsSafeString(xmlSecTransformGetName(dsigCtx->signMethod)));
       
   877 	return(-1);
       
   878     }	
       
   879     
       
   880     /* ignore <dsig:KeyInfo /> if there is the key is already set */
       
   881     if((dsigCtx->signKey == NULL) && (dsigCtx->keyInfoReadCtx.keysMngr != NULL) 
       
   882 			&& (dsigCtx->keyInfoReadCtx.keysMngr->getKey != NULL)) {	
       
   883 	dsigCtx->signKey = (dsigCtx->keyInfoReadCtx.keysMngr->getKey)(node, &(dsigCtx->keyInfoReadCtx));
       
   884     }
       
   885     
       
   886     /* check that we have exactly what we want */
       
   887     if((dsigCtx->signKey == NULL) || (!xmlSecKeyMatch(dsigCtx->signKey, NULL, &(dsigCtx->keyInfoReadCtx.keyReq)))) {
       
   888 	xmlSecError(XMLSEC_ERRORS_HERE,
       
   889 		    NULL,
       
   890 		    NULL,
       
   891 		    XMLSEC_ERRORS_R_KEY_NOT_FOUND,
       
   892 		    XMLSEC_ERRORS_NO_MESSAGE);
       
   893 	return(-1);
       
   894     }
       
   895     
       
   896     /* set the key to the transform */
       
   897     ret = xmlSecTransformSetKey(dsigCtx->signMethod, dsigCtx->signKey);
       
   898     if(ret < 0) {
       
   899 	xmlSecError(XMLSEC_ERRORS_HERE,
       
   900 		    NULL,
       
   901 		    "xmlSecTransformSetKey",
       
   902 		    XMLSEC_ERRORS_R_XMLSEC_FAILED,
       
   903 		    "transform=%s",
       
   904 		    xmlSecErrorsSafeString(xmlSecTransformGetName(dsigCtx->signMethod)));
       
   905 	return(-1);
       
   906     }
       
   907 
       
   908     /* if we are signing document, update <dsig:KeyInfo/> node */
       
   909     if((node != NULL) && (dsigCtx->operation == xmlSecTransformOperationSign)) {	
       
   910 	ret = xmlSecKeyInfoNodeWrite(node, dsigCtx->signKey, &(dsigCtx->keyInfoWriteCtx));
       
   911 	if(ret < 0) {
       
   912     	    xmlSecError(XMLSEC_ERRORS_HERE,
       
   913 			NULL,
       
   914 			"xmlSecKeyInfoNodeWrite",
       
   915 			XMLSEC_ERRORS_R_XMLSEC_FAILED,
       
   916 			XMLSEC_ERRORS_NO_MESSAGE);
       
   917 	    return(-1);
       
   918 	}	
       
   919     }
       
   920     
       
   921     return(0);
       
   922 }
       
   923 
       
   924 /**
       
   925  * xmlSecDSigCtxProcessObjectNode:
       
   926  * 	
       
   927  * The Object Element (http://www.w3.org/TR/xmldsig-core/#sec-Object)
       
   928  * 
       
   929  * Object is an optional element that may occur one or more times. When 
       
   930  * present, this element may contain any data. The Object element may include 
       
   931  * optional MIME type, ID, and encoding attributes.
       
   932  *     
       
   933  * Schema Definition:
       
   934  *     
       
   935  * <element name="Object" type="ds:ObjectType"/> 
       
   936  * <complexType name="ObjectType" mixed="true">
       
   937  *   <sequence minOccurs="0" maxOccurs="unbounded">
       
   938  *     <any namespace="##any" processContents="lax"/>
       
   939  *   </sequence>
       
   940  *   <attribute name="Id" type="ID" use="optional"/> 
       
   941  *   <attribute name="MimeType" type="string" use="optional"/>
       
   942  *   <attribute name="Encoding" type="anyURI" use="optional"/> 
       
   943  * </complexType>
       
   944  *	
       
   945  * DTD:
       
   946  *	
       
   947  * <!ELEMENT Object (#PCDATA|Signature|SignatureProperties|Manifest %Object.ANY;)* >
       
   948  * <!ATTLIST Object  Id  ID  #IMPLIED 
       
   949  *                   MimeType    CDATA   #IMPLIED 
       
   950  *                   Encoding    CDATA   #IMPLIED >
       
   951  */
       
   952 static int
       
   953 xmlSecDSigCtxProcessObjectNode(xmlSecDSigCtxPtr dsigCtx, xmlNodePtr node) {
       
   954     xmlNodePtr cur;
       
   955     int ret;
       
   956 
       
   957     xmlSecAssert2(dsigCtx != NULL, -1);	
       
   958     xmlSecAssert2(dsigCtx->status == xmlSecDSigStatusUnknown, -1);
       
   959     xmlSecAssert2(node != NULL, -1);
       
   960     
       
   961     /* we care about Manifest nodes only; ignore everything else */
       
   962     cur = xmlSecGetNextElementNode(node->children);
       
   963     while(cur != NULL) {
       
   964 	if(xmlSecCheckNodeName(cur, xmlSecNodeManifest, xmlSecDSigNs)) {
       
   965 	    ret = xmlSecDSigCtxProcessManifestNode(dsigCtx, cur);
       
   966 	    if(ret < 0){
       
   967     		xmlSecError(XMLSEC_ERRORS_HERE,
       
   968 			    NULL,
       
   969 			    "xmlSecDSigCtxProcessManifestNode",
       
   970 			    XMLSEC_ERRORS_R_XMLSEC_FAILED,
       
   971 			    XMLSEC_ERRORS_NO_MESSAGE);
       
   972 		return(-1);	    
       
   973 	    }
       
   974 	}
       
   975 	cur = xmlSecGetNextElementNode(cur->next);
       
   976     }
       
   977     return(0);
       
   978 }
       
   979 
       
   980 /**
       
   981  * xmlSecDSigCtxProcessManifestNode: 
       
   982  *
       
   983  * The Manifest  Element (http://www.w3.org/TR/xmldsig-core/#sec-Manifest)
       
   984  *
       
   985  * The Manifest element provides a list of References. The difference from 
       
   986  * the list in SignedInfo is that it is application defined which, if any, of 
       
   987  * the digests are actually checked against the objects referenced and what to 
       
   988  * do if the object is inaccessible or the digest compare fails. If a Manifest 
       
   989  * is pointed to from SignedInfo, the digest over the Manifest itself will be 
       
   990  * checked by the core result validation behavior. The digests within such 
       
   991  * a Manifest are checked at the application's discretion. If a Manifest is 
       
   992  * referenced from another Manifest, even the overall digest of this two level 
       
   993  * deep Manifest might not be checked.
       
   994  *     
       
   995  * Schema Definition:
       
   996  *     
       
   997  * <element name="Manifest" type="ds:ManifestType"/> 
       
   998  * <complexType name="ManifestType">
       
   999  *   <sequence>
       
  1000  *     <element ref="ds:Reference" maxOccurs="unbounded"/> 
       
  1001  *   </sequence> 
       
  1002  *   <attribute name="Id" type="ID" use="optional"/> 
       
  1003  *  </complexType>
       
  1004  *	
       
  1005  * DTD:
       
  1006  *
       
  1007  * <!ELEMENT Manifest (Reference+)  >
       
  1008  * <!ATTLIST Manifest Id ID  #IMPLIED >
       
  1009  */
       
  1010 static int
       
  1011 xmlSecDSigCtxProcessManifestNode(xmlSecDSigCtxPtr dsigCtx, xmlNodePtr node) {
       
  1012     xmlSecDSigReferenceCtxPtr dsigRefCtx;
       
  1013     xmlNodePtr cur;
       
  1014     int ret;
       
  1015 
       
  1016     xmlSecAssert2(dsigCtx != NULL, -1);	
       
  1017     xmlSecAssert2(dsigCtx->status == xmlSecDSigStatusUnknown, -1);
       
  1018     xmlSecAssert2(node != NULL, -1);
       
  1019 
       
  1020     /* calculate references */
       
  1021     cur = xmlSecGetNextElementNode(node->children);
       
  1022     while((cur != NULL) && (xmlSecCheckNodeName(cur, xmlSecNodeReference, xmlSecDSigNs))) {
       
  1023         /* create reference */
       
  1024 	dsigRefCtx = xmlSecDSigReferenceCtxCreate(dsigCtx, xmlSecDSigReferenceOriginManifest);
       
  1025 	if(dsigRefCtx == NULL) {
       
  1026 	    xmlSecError(XMLSEC_ERRORS_HERE,
       
  1027 			NULL,
       
  1028 		        "xmlSecDSigReferenceCtxCreate",
       
  1029 			XMLSEC_ERRORS_R_XMLSEC_FAILED,
       
  1030 			XMLSEC_ERRORS_NO_MESSAGE);
       
  1031 	    return(-1);	    
       
  1032 	}
       
  1033 
       
  1034 	/* add to the list */
       
  1035 	ret = xmlSecPtrListAdd(&(dsigCtx->manifestReferences), dsigRefCtx);
       
  1036 	if(ret < 0) {
       
  1037 	    xmlSecError(XMLSEC_ERRORS_HERE,
       
  1038 			NULL,
       
  1039 			"xmlSecPtrListAdd",
       
  1040 			XMLSEC_ERRORS_R_XMLSEC_FAILED,
       
  1041 			XMLSEC_ERRORS_NO_MESSAGE);
       
  1042 	    xmlSecDSigReferenceCtxDestroy(dsigRefCtx);
       
  1043 	    return(-1);	    
       
  1044 	}
       
  1045 
       
  1046 	/* process */
       
  1047 	ret = xmlSecDSigReferenceCtxProcessNode(dsigRefCtx, cur);
       
  1048 	if(ret < 0) {
       
  1049 	    xmlSecError(XMLSEC_ERRORS_HERE,
       
  1050 			NULL,
       
  1051 			"xmlSecDSigReferenceCtxProcessNode",
       
  1052 			XMLSEC_ERRORS_R_XMLSEC_FAILED,
       
  1053 			"node=%s",
       
  1054 			xmlSecErrorsSafeString(xmlSecNodeGetName(cur)));
       
  1055 	    return(-1);	    
       
  1056 	}
       
  1057 
       
  1058 	/* we don;t care if Reference processing failed because
       
  1059 	 * it's Manifest node */
       
  1060 	cur = xmlSecGetNextElementNode(cur->next);
       
  1061     }
       
  1062 
       
  1063     /* we should have nothing else here */
       
  1064     if(cur != NULL) {
       
  1065     	xmlSecError(XMLSEC_ERRORS_HERE,
       
  1066 		    NULL,
       
  1067 		    xmlSecErrorsSafeString(xmlSecNodeGetName(cur)),
       
  1068 		    XMLSEC_ERRORS_R_UNEXPECTED_NODE,
       
  1069 		    XMLSEC_ERRORS_NO_MESSAGE);
       
  1070 	return(-1);
       
  1071     }    
       
  1072     return(0);
       
  1073 }
       
  1074 
       
  1075 /**
       
  1076  * xmlSecDSigCtxDebugDump:
       
  1077  * @dsigCtx:		the pointer to <dsig:Signature/> processing context.
       
  1078  * @output:		the pointer to output FILE.
       
  1079  *
       
  1080  * Prints the debug information about @dsigCtx to @output.
       
  1081  */
       
  1082 EXPORT_C
       
  1083 void 
       
  1084 xmlSecDSigCtxDebugDump(xmlSecDSigCtxPtr dsigCtx, FILE* output) {
       
  1085     xmlSecAssert(dsigCtx != NULL);
       
  1086     xmlSecAssert(output != NULL);
       
  1087 
       
  1088     if(dsigCtx->operation == xmlSecTransformOperationSign) {    
       
  1089 	fprintf(output, "= SIGNATURE CONTEXT\n");
       
  1090     } else {
       
  1091 	fprintf(output, "= VERIFICATION CONTEXT\n");
       
  1092     }
       
  1093     switch(dsigCtx->status) {
       
  1094 	case xmlSecDSigStatusUnknown:
       
  1095 	    fprintf(output, "== Status: unknown\n");
       
  1096 	    break;
       
  1097 	case xmlSecDSigStatusSucceeded:
       
  1098 	    fprintf(output, "== Status: succeeded\n");
       
  1099 	    break;
       
  1100 	case xmlSecDSigStatusInvalid:
       
  1101 	    fprintf(output, "== Status: invalid\n");
       
  1102 	    break;
       
  1103     }
       
  1104     fprintf(output, "== flags: 0x%08x\n", dsigCtx->flags);
       
  1105     fprintf(output, "== flags2: 0x%08x\n", dsigCtx->flags2);
       
  1106 
       
  1107     if(dsigCtx->id != NULL) {
       
  1108 	fprintf(output, "== Id: \"%s\"\n", dsigCtx->id);
       
  1109     }
       
  1110     
       
  1111     fprintf(output, "== Key Info Read Ctx:\n");
       
  1112     xmlSecKeyInfoCtxDebugDump(&(dsigCtx->keyInfoReadCtx), output);
       
  1113     fprintf(output, "== Key Info Write Ctx:\n");
       
  1114     xmlSecKeyInfoCtxDebugDump(&(dsigCtx->keyInfoWriteCtx), output);
       
  1115 
       
  1116     fprintf(output, "== Signature Transform Ctx:\n");
       
  1117     xmlSecTransformCtxDebugDump(&(dsigCtx->transformCtx), output);
       
  1118 
       
  1119     if(dsigCtx->signMethod != NULL) {
       
  1120         fprintf(output, "== Signature Method:\n");
       
  1121 	xmlSecTransformDebugDump(dsigCtx->signMethod, output);
       
  1122     }
       
  1123 
       
  1124     if(dsigCtx->signKey != NULL) {
       
  1125         fprintf(output, "== Signature Key:\n");
       
  1126 	xmlSecKeyDebugDump(dsigCtx->signKey, output);
       
  1127     }
       
  1128     
       
  1129     fprintf(output, "== SignedInfo References List:\n");
       
  1130     xmlSecPtrListDebugDump(&(dsigCtx->signedInfoReferences), output);
       
  1131 
       
  1132     fprintf(output, "== Manifest References List:\n");
       
  1133     xmlSecPtrListDebugDump(&(dsigCtx->manifestReferences), output);
       
  1134     
       
  1135     if((dsigCtx->result != NULL) && 
       
  1136        (xmlSecBufferGetData(dsigCtx->result) != NULL)) {
       
  1137 
       
  1138 	fprintf(output, "== Result - start buffer:\n");
       
  1139 	fwrite(xmlSecBufferGetData(dsigCtx->result), 
       
  1140 	       xmlSecBufferGetSize(dsigCtx->result), 
       
  1141 	       1, output);
       
  1142 	fprintf(output, "\n== Result - end buffer\n");
       
  1143     }
       
  1144     if(((dsigCtx->flags & XMLSEC_DSIG_FLAGS_STORE_SIGNATURE) != 0) &&
       
  1145        (xmlSecDSigCtxGetPreSignBuffer(dsigCtx) != NULL) &&
       
  1146        (xmlSecBufferGetData(xmlSecDSigCtxGetPreSignBuffer(dsigCtx)) != NULL)) {
       
  1147        
       
  1148 	fprintf(output, "== PreSigned data - start buffer:\n");
       
  1149 	fwrite(xmlSecBufferGetData(xmlSecDSigCtxGetPreSignBuffer(dsigCtx)), 
       
  1150 	       xmlSecBufferGetSize(xmlSecDSigCtxGetPreSignBuffer(dsigCtx)), 
       
  1151 	       1, output);
       
  1152 	fprintf(output, "\n== PreSigned data - end buffer\n");       
       
  1153     }
       
  1154 }
       
  1155 
       
  1156 /**
       
  1157  * xmlSecDSigCtxDebugXmlDump:
       
  1158  * @dsigCtx:		the pointer to <dsig:Signature/> processing context.
       
  1159  * @output:		the pointer to output FILE.
       
  1160  *
       
  1161  * Prints the debug information about @dsigCtx to @output in XML format.
       
  1162  */
       
  1163 EXPORT_C
       
  1164 void 
       
  1165 xmlSecDSigCtxDebugXmlDump(xmlSecDSigCtxPtr dsigCtx, FILE* output) {
       
  1166     xmlSecAssert(dsigCtx != NULL);
       
  1167     xmlSecAssert(output != NULL);
       
  1168 
       
  1169     if(dsigCtx->operation == xmlSecTransformOperationSign) {    
       
  1170 	fprintf(output, "<SignatureContext \n");
       
  1171     } else {
       
  1172 	fprintf(output, "<VerificationContext \n");
       
  1173     }
       
  1174     switch(dsigCtx->status) {
       
  1175 	case xmlSecDSigStatusUnknown:
       
  1176 	    fprintf(output, "status=\"unknown\" >\n");
       
  1177 	    break;
       
  1178 	case xmlSecDSigStatusSucceeded:
       
  1179 	    fprintf(output, "status=\"succeeded\" >\n");
       
  1180 	    break;
       
  1181 	case xmlSecDSigStatusInvalid:
       
  1182 	    fprintf(output, "status=\"invalid\" >\n");
       
  1183 	    break;
       
  1184     }
       
  1185 
       
  1186     fprintf(output, "<Flags>%08x</Flags>\n", dsigCtx->flags);
       
  1187     fprintf(output, "<Flags2>%08x</Flags2>\n", dsigCtx->flags2);
       
  1188 
       
  1189     if(dsigCtx->id != NULL) {
       
  1190 	fprintf(output, "<Id>%s</Id>\n", dsigCtx->id);
       
  1191     }
       
  1192 
       
  1193     fprintf(output, "<KeyInfoReadCtx>\n");
       
  1194     xmlSecKeyInfoCtxDebugXmlDump(&(dsigCtx->keyInfoReadCtx), output);
       
  1195     fprintf(output, "</KeyInfoReadCtx>\n");
       
  1196 
       
  1197     fprintf(output, "<KeyInfoWriteCtx>\n");
       
  1198     xmlSecKeyInfoCtxDebugXmlDump(&(dsigCtx->keyInfoWriteCtx), output);
       
  1199     fprintf(output, "</KeyInfoWriteCtx>\n");
       
  1200 
       
  1201     fprintf(output, "<SignatureTransformCtx>\n");
       
  1202     xmlSecTransformCtxDebugXmlDump(&(dsigCtx->transformCtx), output);
       
  1203     fprintf(output, "</SignatureTransformCtx>\n");
       
  1204 
       
  1205     if(dsigCtx->signMethod != NULL) {
       
  1206         fprintf(output, "<SignatureMethod>\n");
       
  1207 	xmlSecTransformDebugXmlDump(dsigCtx->signMethod, output);
       
  1208         fprintf(output, "</SignatureMethod>\n");
       
  1209     }
       
  1210 
       
  1211     if(dsigCtx->signKey != NULL) {
       
  1212         fprintf(output, "<SignatureKey>\n");
       
  1213 	xmlSecKeyDebugXmlDump(dsigCtx->signKey, output);
       
  1214         fprintf(output, "</SignatureKey>\n");
       
  1215     }
       
  1216 
       
  1217     fprintf(output, "<SignedInfoReferences>\n");
       
  1218     xmlSecPtrListDebugXmlDump(&(dsigCtx->signedInfoReferences), output);
       
  1219     fprintf(output, "</SignedInfoReferences>\n");
       
  1220 
       
  1221     fprintf(output, "<ManifestReferences>\n");
       
  1222     xmlSecPtrListDebugXmlDump(&(dsigCtx->manifestReferences), output);
       
  1223     fprintf(output, "</ManifestReferences>\n");
       
  1224 
       
  1225     if((dsigCtx->result != NULL) && 
       
  1226        (xmlSecBufferGetData(dsigCtx->result) != NULL)) {
       
  1227 
       
  1228 	fprintf(output, "<Result>");
       
  1229 	fwrite(xmlSecBufferGetData(dsigCtx->result), 
       
  1230 	       xmlSecBufferGetSize(dsigCtx->result), 
       
  1231 	       1, output);
       
  1232 	fprintf(output, "</Result>\n");
       
  1233     }
       
  1234     if(((dsigCtx->flags & XMLSEC_DSIG_FLAGS_STORE_SIGNATURE) != 0) &&
       
  1235        (xmlSecDSigCtxGetPreSignBuffer(dsigCtx) != NULL) &&
       
  1236        (xmlSecBufferGetData(xmlSecDSigCtxGetPreSignBuffer(dsigCtx)) != NULL)) {
       
  1237        
       
  1238 	fprintf(output, "<PreSignedData>");
       
  1239 	fwrite(xmlSecBufferGetData(xmlSecDSigCtxGetPreSignBuffer(dsigCtx)), 
       
  1240 	       xmlSecBufferGetSize(xmlSecDSigCtxGetPreSignBuffer(dsigCtx)), 
       
  1241 	       1, output);
       
  1242 	fprintf(output, "</PreSignedData>\n");       
       
  1243     }
       
  1244 
       
  1245     if(dsigCtx->operation == xmlSecTransformOperationSign) {    
       
  1246 	fprintf(output, "</SignatureContext>\n");
       
  1247     } else {
       
  1248 	fprintf(output, "</VerificationContext>\n");
       
  1249     }
       
  1250 }
       
  1251 
       
  1252 /**************************************************************************
       
  1253  *
       
  1254  * xmlSecDSigReferenceCtx
       
  1255  *
       
  1256  *************************************************************************/
       
  1257 /**
       
  1258  * xmlSecDSigReferenceCtxCreate:
       
  1259  * @dsigCtx:		the pointer to parent <dsig:Signature/> node processing context.
       
  1260  * @origin:		the reference origin (<dsig:SignedInfo/> or <dsig:Manifest/> node).
       
  1261  *
       
  1262  * Creates new <dsig:Reference/> element processing context. Caller is responsible
       
  1263  * for destroying the returned context by calling #xmlSecDSigReferenceCtxDestroy
       
  1264  * function.
       
  1265  *
       
  1266  * Returns pointer to newly created context or NULL if an error occurs.
       
  1267  */
       
  1268 EXPORT_C
       
  1269 xmlSecDSigReferenceCtxPtr	
       
  1270 xmlSecDSigReferenceCtxCreate(xmlSecDSigCtxPtr dsigCtx, xmlSecDSigReferenceOrigin origin) {
       
  1271     xmlSecDSigReferenceCtxPtr dsigRefCtx;
       
  1272     int ret;
       
  1273     
       
  1274     xmlSecAssert2(dsigCtx != NULL, NULL);
       
  1275     
       
  1276     dsigRefCtx = (xmlSecDSigReferenceCtxPtr) xmlMalloc(sizeof(xmlSecDSigReferenceCtx));
       
  1277     if(dsigRefCtx == NULL) {
       
  1278 	xmlSecError(XMLSEC_ERRORS_HERE,
       
  1279 		    NULL,
       
  1280 		    NULL,
       
  1281 		    XMLSEC_ERRORS_R_MALLOC_FAILED,
       
  1282 		    "sizeof(xmlSecDSigReferenceCtx)=%d", 
       
  1283 		    sizeof(xmlSecDSigReferenceCtx));
       
  1284 	return(NULL);
       
  1285     }
       
  1286     
       
  1287     ret = xmlSecDSigReferenceCtxInitialize(dsigRefCtx, dsigCtx, origin);
       
  1288     if(ret < 0) {
       
  1289 	xmlSecError(XMLSEC_ERRORS_HERE,
       
  1290 		    NULL,
       
  1291 		    "xmlSecDSigReferenceCtxInitialize",
       
  1292 		    XMLSEC_ERRORS_R_XMLSEC_FAILED,
       
  1293 		    XMLSEC_ERRORS_NO_MESSAGE);
       
  1294 	xmlSecDSigReferenceCtxDestroy(dsigRefCtx);
       
  1295 	return(NULL);   
       
  1296     }
       
  1297     return(dsigRefCtx);    
       
  1298 }
       
  1299 
       
  1300 /** 
       
  1301  * xmlSecDSigReferenceCtxDestroy:
       
  1302  * @dsigRefCtx:		the pointer to <dsig:Reference/> element processing context.
       
  1303  *
       
  1304  * Destroy context object created with #xmlSecDSigReferenceCtxCreate function.
       
  1305  */
       
  1306 EXPORT_C
       
  1307 void  
       
  1308 xmlSecDSigReferenceCtxDestroy(xmlSecDSigReferenceCtxPtr dsigRefCtx) {
       
  1309     xmlSecAssert(dsigRefCtx != NULL);
       
  1310     
       
  1311     xmlSecDSigReferenceCtxFinalize(dsigRefCtx);
       
  1312     xmlFree(dsigRefCtx);
       
  1313 }
       
  1314 
       
  1315 /**
       
  1316  * xmlSecDSigReferenceCtxInitialize:
       
  1317  * @dsigRefCtx:		the pointer to <dsig:Reference/> element processing context.
       
  1318  * @dsigCtx:		the pointer to parent <dsig:Signature/> node processing context.
       
  1319  * @origin:		the reference origin (<dsig:SignedInfo/> or <dsig:Manifest/> node).
       
  1320  *
       
  1321  * Initializes new <dsig:Reference/> element processing context. Caller is responsible
       
  1322  * for cleaning up the returned context by calling #xmlSecDSigReferenceCtxFinalize
       
  1323  * function.
       
  1324  *
       
  1325  * Returns 0 on succes or aa negative value otherwise.
       
  1326  */
       
  1327 EXPORT_C
       
  1328 int 
       
  1329 xmlSecDSigReferenceCtxInitialize(xmlSecDSigReferenceCtxPtr dsigRefCtx, xmlSecDSigCtxPtr dsigCtx,
       
  1330 				xmlSecDSigReferenceOrigin origin) {
       
  1331     int ret;
       
  1332     
       
  1333     xmlSecAssert2(dsigCtx != NULL, -1);
       
  1334     xmlSecAssert2(dsigRefCtx != NULL, -1);
       
  1335     
       
  1336     memset(dsigRefCtx, 0, sizeof(xmlSecDSigReferenceCtx));
       
  1337     
       
  1338     dsigRefCtx->dsigCtx = dsigCtx;
       
  1339     dsigRefCtx->origin = origin;
       
  1340     
       
  1341     /* initializes transforms dsigRefCtx */
       
  1342     ret = xmlSecTransformCtxInitialize(&(dsigRefCtx->transformCtx));
       
  1343     if(ret < 0) {
       
  1344 	xmlSecError(XMLSEC_ERRORS_HERE,
       
  1345 		    NULL,
       
  1346 		    "xmlSecTransformCtxInitialize",
       
  1347 		    XMLSEC_ERRORS_R_XMLSEC_FAILED,
       
  1348 		    XMLSEC_ERRORS_NO_MESSAGE);
       
  1349 	return(-1);   
       
  1350     }
       
  1351     
       
  1352     /* copy enabled transforms */
       
  1353     if(dsigCtx->enabledReferenceTransforms != NULL) {
       
  1354 	ret = xmlSecPtrListCopy(&(dsigRefCtx->transformCtx.enabledTransforms), 
       
  1355 				     dsigCtx->enabledReferenceTransforms);
       
  1356 	if(ret < 0) {
       
  1357 	    xmlSecError(XMLSEC_ERRORS_HERE,
       
  1358 			NULL,
       
  1359 			"xmlSecPtrListCopy",
       
  1360 			XMLSEC_ERRORS_R_XMLSEC_FAILED,
       
  1361 			XMLSEC_ERRORS_NO_MESSAGE);
       
  1362 	    return(-1);   
       
  1363 	}
       
  1364     }    
       
  1365     dsigRefCtx->transformCtx.preExecCallback = dsigCtx->referencePreExecuteCallback;
       
  1366     dsigRefCtx->transformCtx.enabledUris = dsigCtx->enabledReferenceUris;
       
  1367 
       
  1368     if((dsigCtx->flags & XMLSEC_DSIG_FLAGS_USE_VISA3D_HACK) != 0) {
       
  1369 	dsigRefCtx->transformCtx.flags |= XMLSEC_TRANSFORMCTX_FLAGS_USE_VISA3D_HACK;
       
  1370     }
       
  1371     return(0);
       
  1372 }
       
  1373 
       
  1374 /** 
       
  1375  * xmlSecDSigReferenceCtxFinalize:
       
  1376  * @dsigRefCtx:		the pointer to <dsig:Reference/> element processing context.
       
  1377  *
       
  1378  * Cleans up context object created with #xmlSecDSigReferenceCtxInitialize function.
       
  1379  */
       
  1380 EXPORT_C
       
  1381 void 
       
  1382 xmlSecDSigReferenceCtxFinalize(xmlSecDSigReferenceCtxPtr dsigRefCtx) {
       
  1383     xmlSecAssert(dsigRefCtx != NULL);
       
  1384 
       
  1385     xmlSecTransformCtxFinalize(&(dsigRefCtx->transformCtx));
       
  1386     if(dsigRefCtx->id != NULL) {
       
  1387 	xmlFree(dsigRefCtx->id);
       
  1388     }	
       
  1389     if(dsigRefCtx->uri != NULL) {
       
  1390 	xmlFree(dsigRefCtx->uri);
       
  1391     }	
       
  1392     if(dsigRefCtx->type != NULL) {
       
  1393 	xmlFree(dsigRefCtx->type);
       
  1394     }	
       
  1395     memset(dsigRefCtx, 0, sizeof(xmlSecDSigReferenceCtx));
       
  1396 }
       
  1397 
       
  1398 /**
       
  1399  * xmlSecDSigReferenceCtxGetPreDigestBuffer:
       
  1400  * @dsigRefCtx:		the pointer to <dsig:Reference/> element processing context.
       
  1401  * 
       
  1402  * Gets the results of <dsig:Reference/> node processing just before digesting
       
  1403  * (valid only if #XMLSEC_DSIG_FLAGS_STORE_SIGNEDINFO_REFERENCES or
       
  1404  * #XMLSEC_DSIG_FLAGS_STORE_MANIFEST_REFERENCES flas of signature context
       
  1405  * is set).
       
  1406  *
       
  1407  * Returns pointer to the buffer or NULL if an error occurs.
       
  1408  */
       
  1409 EXPORT_C
       
  1410 xmlSecBufferPtr 
       
  1411 xmlSecDSigReferenceCtxGetPreDigestBuffer(xmlSecDSigReferenceCtxPtr dsigRefCtx) {
       
  1412     xmlSecAssert2(dsigRefCtx != NULL, NULL);
       
  1413     
       
  1414     return((dsigRefCtx->preDigestMemBufMethod != NULL) ? 
       
  1415 	    xmlSecTransformMemBufGetBuffer(dsigRefCtx->preDigestMemBufMethod) : NULL);
       
  1416 }
       
  1417 
       
  1418 /**
       
  1419  * xmlSecDSigReferenceCtxProcessNode:
       
  1420  * @dsigRefCtx:		the pointer to <dsig:Reference/> element processing context.
       
  1421  * @node:		the pointer to <dsig:Reference/> node.
       
  1422 
       
  1423  * The Reference Element (http://www.w3.org/TR/xmldsig-core/#sec-Reference)
       
  1424  * 
       
  1425  * Reference is an element that may occur one or more times. It specifies 
       
  1426  * a digest algorithm and digest value, and optionally an identifier of the 
       
  1427  * object being signed, the type of the object, and/or a list of transforms 
       
  1428  * to be applied prior to digesting. The identification (URI) and transforms 
       
  1429  * describe how the digested content (i.e., the input to the digest method) 
       
  1430  * was created. The Type attribute facilitates the processing of referenced 
       
  1431  * data. For example, while this specification makes no requirements over 
       
  1432  * external data, an application may wish to signal that the referent is a 
       
  1433  * Manifest. An optional ID attribute permits a Reference to be referenced 
       
  1434  * from elsewhere.
       
  1435  *
       
  1436  * Returns 0 on succes or aa negative value otherwise.
       
  1437  */
       
  1438 EXPORT_C
       
  1439 int 
       
  1440 xmlSecDSigReferenceCtxProcessNode(xmlSecDSigReferenceCtxPtr dsigRefCtx, xmlNodePtr node) {
       
  1441     xmlSecTransformCtxPtr transformCtx;
       
  1442     xmlNodePtr digestValueNode;
       
  1443     xmlNodePtr cur;
       
  1444     int ret;
       
  1445     
       
  1446     xmlSecAssert2(dsigRefCtx != NULL, -1);
       
  1447     xmlSecAssert2(dsigRefCtx->dsigCtx != NULL, -1);
       
  1448     xmlSecAssert2(dsigRefCtx->digestMethod == NULL, -1);
       
  1449     xmlSecAssert2(dsigRefCtx->digestMethod == NULL, -1);
       
  1450     xmlSecAssert2(dsigRefCtx->preDigestMemBufMethod == NULL, -1);
       
  1451     xmlSecAssert2(node != NULL, -1);
       
  1452     xmlSecAssert2(node->doc != NULL, -1);
       
  1453 
       
  1454     transformCtx = &(dsigRefCtx->transformCtx);
       
  1455 
       
  1456     /* read attributes first */
       
  1457     dsigRefCtx->uri = xmlGetProp(node, xmlSecAttrURI);
       
  1458     dsigRefCtx->id  = xmlGetProp(node, xmlSecAttrId);
       
  1459     dsigRefCtx->type= xmlGetProp(node, xmlSecAttrType);
       
  1460 
       
  1461     /* set start URI (and check that it is enabled!) */
       
  1462     ret = xmlSecTransformCtxSetUri(transformCtx, dsigRefCtx->uri, node);
       
  1463     if(ret < 0) {
       
  1464 	xmlSecError(XMLSEC_ERRORS_HERE,
       
  1465 		    NULL,
       
  1466 		    "xmlSecTransformCtxSetUri",
       
  1467 		    XMLSEC_ERRORS_R_XMLSEC_FAILED,
       
  1468 		    "uri=%s",
       
  1469 		    xmlSecErrorsSafeString(dsigRefCtx->uri));
       
  1470 	return(-1);
       
  1471     }
       
  1472 
       
  1473     /* first is optional Transforms node */
       
  1474     cur = xmlSecGetNextElementNode(node->children);
       
  1475     if((cur != NULL) && (xmlSecCheckNodeName(cur, xmlSecNodeTransforms, xmlSecDSigNs))) {
       
  1476 	ret = xmlSecTransformCtxNodesListRead(transformCtx, 
       
  1477 					cur, xmlSecTransformUsageDSigTransform);
       
  1478 	if(ret < 0) {
       
  1479 	    xmlSecError(XMLSEC_ERRORS_HERE,
       
  1480 			NULL,
       
  1481 			"xmlSecTransformCtxNodesListRead",
       
  1482 			XMLSEC_ERRORS_R_XMLSEC_FAILED,
       
  1483 			"node=%s",
       
  1484 			xmlSecErrorsSafeString(xmlSecNodeGetName(cur)));
       
  1485 	    return(-1);
       
  1486 	}	
       
  1487         cur = xmlSecGetNextElementNode(cur->next);
       
  1488     }
       
  1489 
       
  1490     /* insert membuf if requested */
       
  1491     if(((dsigRefCtx->origin == xmlSecDSigReferenceOriginSignedInfo) &&
       
  1492 	((dsigRefCtx->dsigCtx->flags & XMLSEC_DSIG_FLAGS_STORE_SIGNEDINFO_REFERENCES) != 0)) ||
       
  1493        ((dsigRefCtx->origin == xmlSecDSigReferenceOriginManifest) &&
       
  1494 	((dsigRefCtx->dsigCtx->flags & XMLSEC_DSIG_FLAGS_STORE_MANIFEST_REFERENCES) != 0))) {
       
  1495 
       
  1496 	xmlSecAssert2(dsigRefCtx->preDigestMemBufMethod == NULL, -1);
       
  1497 	dsigRefCtx->preDigestMemBufMethod = xmlSecTransformCtxCreateAndAppend(
       
  1498 						transformCtx, 
       
  1499 						xmlSecTransformMemBufId);
       
  1500 	if(dsigRefCtx->preDigestMemBufMethod == NULL) {
       
  1501     	    xmlSecError(XMLSEC_ERRORS_HERE,
       
  1502 			NULL,
       
  1503 			"xmlSecTransformCtxCreateAndAppend",
       
  1504 			XMLSEC_ERRORS_R_XMLSEC_FAILED,
       
  1505 			"transform=%s",
       
  1506 			xmlSecErrorsSafeString(xmlSecTransformKlassGetName(xmlSecTransformMemBufId)));
       
  1507 	    return(-1);
       
  1508 	}
       
  1509     }
       
  1510         
       
  1511     /* next node is required DigestMethod. */
       
  1512     if((cur != NULL) && (xmlSecCheckNodeName(cur, xmlSecNodeDigestMethod, xmlSecDSigNs))) {
       
  1513 	dsigRefCtx->digestMethod = xmlSecTransformCtxNodeRead(&(dsigRefCtx->transformCtx), 
       
  1514 					cur, xmlSecTransformUsageDigestMethod);
       
  1515 	if(dsigRefCtx->digestMethod == NULL) {
       
  1516 	    xmlSecError(XMLSEC_ERRORS_HERE,
       
  1517 			NULL,
       
  1518 			"xmlSecTransformCtxNodeRead",
       
  1519 			XMLSEC_ERRORS_R_XMLSEC_FAILED,
       
  1520 			"node=%s",
       
  1521 			xmlSecErrorsSafeString(xmlSecNodeGetName(cur)));
       
  1522 	    return(-1);	
       
  1523 	}	
       
  1524     } else if(dsigRefCtx->dsigCtx->defSignMethodId != xmlSecTransformIdUnknown) {
       
  1525 	/* the dsig spec does require DigestMethod node
       
  1526 	 * to be present but in some case it application might decide to
       
  1527 	 * minimize traffic */
       
  1528 	dsigRefCtx->digestMethod = xmlSecTransformCtxCreateAndAppend(&(dsigRefCtx->transformCtx), 
       
  1529 							      dsigRefCtx->dsigCtx->defSignMethodId);
       
  1530 	if(dsigRefCtx->digestMethod == NULL) {
       
  1531     	    xmlSecError(XMLSEC_ERRORS_HERE,
       
  1532 			NULL,
       
  1533 			"xmlSecTransformCtxAppend",
       
  1534 			XMLSEC_ERRORS_R_XMLSEC_FAILED,
       
  1535 			XMLSEC_ERRORS_NO_MESSAGE);
       
  1536 	    return(-1);
       
  1537 	}
       
  1538     } else {
       
  1539     	xmlSecError(XMLSEC_ERRORS_HERE,
       
  1540 		    NULL,
       
  1541 		    xmlSecErrorsSafeString(xmlSecNodeGetName(cur)),
       
  1542 		    XMLSEC_ERRORS_R_INVALID_NODE,
       
  1543 		    "expected=%s",
       
  1544 		    xmlSecErrorsSafeString(xmlSecNodeDigestMethod));
       
  1545 	return(-1);
       
  1546     }	
       
  1547     dsigRefCtx->digestMethod->operation = dsigRefCtx->dsigCtx->operation;
       
  1548 
       
  1549     /* last node is required DigestValue */
       
  1550 	if (cur != NULL) {
       
  1551 		cur = xmlSecGetNextElementNode(cur->next);     
       
  1552 	}
       
  1553     if((cur == NULL) || (!xmlSecCheckNodeName(cur, xmlSecNodeDigestValue, xmlSecDSigNs))) {
       
  1554     	xmlSecError(XMLSEC_ERRORS_HERE,
       
  1555 		    NULL,
       
  1556 		    xmlSecErrorsSafeString(xmlSecNodeGetName(cur)),
       
  1557 		    XMLSEC_ERRORS_R_XMLSEC_FAILED,
       
  1558 		    "node=%s",
       
  1559 		    xmlSecErrorsSafeString(xmlSecNodeDigestValue));
       
  1560 	return(-1);
       
  1561     }
       
  1562     digestValueNode = cur;
       
  1563     cur = xmlSecGetNextElementNode(cur->next);     
       
  1564 
       
  1565     /* if we have something else then it's an error */
       
  1566     if(cur != NULL) {
       
  1567 	xmlSecError(XMLSEC_ERRORS_HERE,
       
  1568 		    NULL,
       
  1569 		    xmlSecErrorsSafeString(xmlSecNodeGetName(cur)),
       
  1570 		    XMLSEC_ERRORS_R_UNEXPECTED_NODE,
       
  1571 		    XMLSEC_ERRORS_NO_MESSAGE);
       
  1572 	return(-1);
       
  1573     }
       
  1574 
       
  1575     /* if we need to write result to xml node then we need base64 encode result */
       
  1576     if(dsigRefCtx->dsigCtx->operation == xmlSecTransformOperationSign) {	
       
  1577 	xmlSecTransformPtr base64Encode;
       
  1578 	
       
  1579 	/* we need to add base64 encode transform */
       
  1580 	base64Encode = xmlSecTransformCtxCreateAndAppend(transformCtx, xmlSecTransformBase64Id);
       
  1581     	if(base64Encode == NULL) {
       
  1582     	    xmlSecError(XMLSEC_ERRORS_HERE,
       
  1583 			NULL,
       
  1584 			"xmlSecTransformCtxCreateAndAppend",
       
  1585 			XMLSEC_ERRORS_R_XMLSEC_FAILED,
       
  1586 			XMLSEC_ERRORS_NO_MESSAGE);
       
  1587 	    return(-1);
       
  1588 	}
       
  1589 	base64Encode->operation = xmlSecTransformOperationEncode;
       
  1590     }
       
  1591 
       
  1592     /* finally get transforms results */
       
  1593     ret = xmlSecTransformCtxExecute(transformCtx, node->doc);
       
  1594     if(ret < 0) {
       
  1595 	xmlSecError(XMLSEC_ERRORS_HERE,
       
  1596 		    NULL,
       
  1597 		    "xmlSecTransformCtxExecute",
       
  1598 	    	    XMLSEC_ERRORS_R_XMLSEC_FAILED,
       
  1599 		    XMLSEC_ERRORS_NO_MESSAGE);
       
  1600 	return(-1);
       
  1601     }    
       
  1602     dsigRefCtx->result = transformCtx->result;
       
  1603 
       
  1604     if(dsigRefCtx->dsigCtx->operation == xmlSecTransformOperationSign) {	
       
  1605 	if((dsigRefCtx->result == NULL) || (xmlSecBufferGetData(dsigRefCtx->result) == NULL)) {
       
  1606 	    xmlSecError(XMLSEC_ERRORS_HERE,
       
  1607 			NULL,
       
  1608 			"xmlSecTransformCtxExecute",
       
  1609 	    		XMLSEC_ERRORS_R_XMLSEC_FAILED,
       
  1610 			XMLSEC_ERRORS_NO_MESSAGE);
       
  1611 	    return(-1);
       
  1612 	}
       
  1613 	
       
  1614 	/* write signed data to xml */
       
  1615 	xmlNodeSetContentLen(digestValueNode,
       
  1616 			    xmlSecBufferGetData(dsigRefCtx->result),
       
  1617 			    xmlSecBufferGetSize(dsigRefCtx->result));
       
  1618     if ( OOM_FLAG )
       
  1619         {
       
  1620         return(-1);
       
  1621         }
       
  1622     
       
  1623 	/* set success status and we are done */
       
  1624 	dsigRefCtx->status = xmlSecDSigStatusSucceeded;
       
  1625     } else {
       
  1626 	/* verify SignatureValue node content */
       
  1627 	ret = xmlSecTransformVerifyNodeContent(dsigRefCtx->digestMethod, 
       
  1628 			    digestValueNode, transformCtx);
       
  1629 	if(ret < 0) {
       
  1630     	    xmlSecError(XMLSEC_ERRORS_HERE,
       
  1631 			NULL,
       
  1632 			"xmlSecTransformVerifyNodeContent",
       
  1633 			XMLSEC_ERRORS_R_XMLSEC_FAILED,
       
  1634 			XMLSEC_ERRORS_NO_MESSAGE);
       
  1635 	    return(-1);
       
  1636 	}
       
  1637     
       
  1638         /* set status and we are done */
       
  1639 	if(dsigRefCtx->digestMethod->status == xmlSecTransformStatusOk) {
       
  1640 	    dsigRefCtx->status = xmlSecDSigStatusSucceeded;
       
  1641 	} else {
       
  1642     	    dsigRefCtx->status = xmlSecDSigStatusInvalid;
       
  1643 	}
       
  1644     }
       
  1645 
       
  1646     return(0);
       
  1647 }
       
  1648 
       
  1649 /**
       
  1650  * xmlSecDSigReferenceCtxDebugDump:
       
  1651  * @dsigRefCtx:		the pointer to <dsig:Reference/> element processing context.
       
  1652  * @output:		the pointer to output FILE.
       
  1653  *
       
  1654  * Prints debug information about @dsigRefCtx to @output.
       
  1655  */
       
  1656 EXPORT_C
       
  1657 void 
       
  1658 xmlSecDSigReferenceCtxDebugDump(xmlSecDSigReferenceCtxPtr dsigRefCtx, FILE* output) {
       
  1659     xmlSecAssert(dsigRefCtx != NULL);
       
  1660     xmlSecAssert(dsigRefCtx->dsigCtx != NULL);
       
  1661     xmlSecAssert(output != NULL);
       
  1662 
       
  1663     if(dsigRefCtx->dsigCtx->operation == xmlSecTransformOperationSign) {    
       
  1664 	fprintf(output, "= REFERENCE CALCULATION CONTEXT\n");
       
  1665     } else {
       
  1666 	fprintf(output, "= REFERENCE VERIFICATION CONTEXT\n");
       
  1667     }
       
  1668     switch(dsigRefCtx->status) {
       
  1669 	case xmlSecDSigStatusUnknown:
       
  1670 	    fprintf(output, "== Status: unknown\n");
       
  1671 	    break;
       
  1672 	case xmlSecDSigStatusSucceeded:
       
  1673 	    fprintf(output, "== Status: succeeded\n");
       
  1674 	    break;
       
  1675 	case xmlSecDSigStatusInvalid:
       
  1676 	    fprintf(output, "== Status: invalid\n");
       
  1677 	    break;
       
  1678     }
       
  1679     if(dsigRefCtx->id != NULL) {
       
  1680 	fprintf(output, "== Id: \"%s\"\n", dsigRefCtx->id);
       
  1681     }
       
  1682     if(dsigRefCtx->uri != NULL) {
       
  1683 	fprintf(output, "== URI: \"%s\"\n", dsigRefCtx->uri);
       
  1684     }
       
  1685     if(dsigRefCtx->type != NULL) {
       
  1686 	fprintf(output, "== Type: \"%s\"\n", dsigRefCtx->type);
       
  1687     }
       
  1688 
       
  1689     fprintf(output, "== Reference Transform Ctx:\n");
       
  1690     xmlSecTransformCtxDebugDump(&(dsigRefCtx->transformCtx), output);
       
  1691 
       
  1692     if(dsigRefCtx->digestMethod != NULL) {
       
  1693         fprintf(output, "== Digest Method:\n");
       
  1694 	xmlSecTransformDebugDump(dsigRefCtx->digestMethod, output);
       
  1695     }
       
  1696 
       
  1697     if((xmlSecDSigReferenceCtxGetPreDigestBuffer(dsigRefCtx) != NULL) &&
       
  1698        (xmlSecBufferGetData(xmlSecDSigReferenceCtxGetPreDigestBuffer(dsigRefCtx)) != NULL)) {
       
  1699        
       
  1700 	fprintf(output, "== PreDigest data - start buffer:\n");
       
  1701 	fwrite(xmlSecBufferGetData(xmlSecDSigReferenceCtxGetPreDigestBuffer(dsigRefCtx)), 
       
  1702 	       xmlSecBufferGetSize(xmlSecDSigReferenceCtxGetPreDigestBuffer(dsigRefCtx)), 
       
  1703 	       1, output);
       
  1704 	fprintf(output, "\n== PreDigest data - end buffer\n");       
       
  1705     }
       
  1706 
       
  1707     if((dsigRefCtx->result != NULL) && 
       
  1708        (xmlSecBufferGetData(dsigRefCtx->result) != NULL)) {
       
  1709 
       
  1710 	fprintf(output, "== Result - start buffer:\n");
       
  1711 	fwrite(xmlSecBufferGetData(dsigRefCtx->result), 
       
  1712 	       xmlSecBufferGetSize(dsigRefCtx->result), 1,
       
  1713 	       output);
       
  1714 	fprintf(output, "\n== Result - end buffer\n");
       
  1715     }
       
  1716 }
       
  1717 
       
  1718 /**
       
  1719  * xmlSecDSigReferenceCtxDebugXmlDump:
       
  1720  * @dsigRefCtx:		the pointer to <dsig:Reference/> element processing context.
       
  1721  * @output:		the pointer to output FILE.
       
  1722  *
       
  1723  * Prints debug information about @dsigRefCtx to @output in output format.
       
  1724  */
       
  1725 EXPORT_C
       
  1726 void 
       
  1727 xmlSecDSigReferenceCtxDebugXmlDump(xmlSecDSigReferenceCtxPtr dsigRefCtx, FILE* output) {
       
  1728     xmlSecAssert(dsigRefCtx != NULL);
       
  1729     xmlSecAssert(dsigRefCtx->dsigCtx != NULL);
       
  1730     xmlSecAssert(output != NULL);
       
  1731 
       
  1732     if(dsigRefCtx->dsigCtx->operation == xmlSecTransformOperationSign) {    
       
  1733 	fprintf(output, "<ReferenceCalculationContext ");
       
  1734     } else {
       
  1735 	fprintf(output, "<ReferenceVerificationContext ");
       
  1736     }
       
  1737     switch(dsigRefCtx->status) {
       
  1738 	case xmlSecDSigStatusUnknown:
       
  1739 	    fprintf(output, "status=\"unknown\" >\n");
       
  1740 	    break;
       
  1741 	case xmlSecDSigStatusSucceeded:
       
  1742 	    fprintf(output, "status=\"succeeded\" >\n");
       
  1743 	    break;
       
  1744 	case xmlSecDSigStatusInvalid:
       
  1745 	    fprintf(output, "status=\"invalid\" >\n");
       
  1746 	    break;
       
  1747     }
       
  1748 
       
  1749     if(dsigRefCtx->id != NULL) {
       
  1750 	fprintf(output, "<Id>%s</Id>\n", dsigRefCtx->id);
       
  1751     }
       
  1752     if(dsigRefCtx->uri != NULL) {
       
  1753 	fprintf(output, "<URI>%s</URI>\n", dsigRefCtx->uri);
       
  1754     }
       
  1755     if(dsigRefCtx->type != NULL) {
       
  1756 	fprintf(output, "<Type>%s</Type>\n", dsigRefCtx->type);
       
  1757     }
       
  1758 
       
  1759     fprintf(output, "<ReferenceTransformCtx>\n");
       
  1760     xmlSecTransformCtxDebugXmlDump(&(dsigRefCtx->transformCtx), output);
       
  1761     fprintf(output, "</ReferenceTransformCtx>\n");
       
  1762 
       
  1763     if(dsigRefCtx->digestMethod != NULL) {
       
  1764         fprintf(output, "<DigestMethod>\n");
       
  1765 	xmlSecTransformDebugXmlDump(dsigRefCtx->digestMethod, output);
       
  1766         fprintf(output, "</DigestMethod>\n");
       
  1767     }
       
  1768 
       
  1769     if((dsigRefCtx->result != NULL) && 
       
  1770        (xmlSecBufferGetData(dsigRefCtx->result) != NULL)) {
       
  1771 
       
  1772 	fprintf(output, "<Result>");
       
  1773 	fwrite(xmlSecBufferGetData(dsigRefCtx->result), 
       
  1774 	       xmlSecBufferGetSize(dsigRefCtx->result), 1,
       
  1775 	       output);
       
  1776 	fprintf(output, "</Result>\n");
       
  1777     }
       
  1778 
       
  1779     if((xmlSecDSigReferenceCtxGetPreDigestBuffer(dsigRefCtx) != NULL) &&
       
  1780        (xmlSecBufferGetData(xmlSecDSigReferenceCtxGetPreDigestBuffer(dsigRefCtx)) != NULL)) {
       
  1781        
       
  1782 	fprintf(output, "<PreDigestData>");
       
  1783 	fwrite(xmlSecBufferGetData(xmlSecDSigReferenceCtxGetPreDigestBuffer(dsigRefCtx)), 
       
  1784 	       xmlSecBufferGetSize(xmlSecDSigReferenceCtxGetPreDigestBuffer(dsigRefCtx)), 
       
  1785 	       1, output);
       
  1786 	fprintf(output, "</PreDigestData>\n");       
       
  1787     }
       
  1788     if(dsigRefCtx->dsigCtx->operation == xmlSecTransformOperationSign) {    
       
  1789 	fprintf(output, "</ReferenceCalculationContext>\n");
       
  1790     } else {
       
  1791 	fprintf(output, "</ReferenceVerificationContext>\n");
       
  1792     }
       
  1793 }
       
  1794 
       
  1795 
       
  1796 /**************************************************************************
       
  1797  *
       
  1798  * xmlSecDSigReferenceCtxListKlass
       
  1799  *
       
  1800  *************************************************************************/
       
  1801 static xmlSecPtrListKlass xmlSecDSigReferenceCtxListKlass = {
       
  1802     BAD_CAST "dsig-reference-list",
       
  1803     NULL,								/* xmlSecPtrDuplicateItemMethod duplicateItem; */
       
  1804     (xmlSecPtrDestroyItemMethod)xmlSecDSigReferenceCtxDestroy,		/* xmlSecPtrDestroyItemMethod destroyItem; */
       
  1805     (xmlSecPtrDebugDumpItemMethod)xmlSecDSigReferenceCtxDebugDump,	/* xmlSecPtrDebugDumpItemMethod debugDumpItem; */
       
  1806     (xmlSecPtrDebugDumpItemMethod)xmlSecDSigReferenceCtxDebugXmlDump,	/* xmlSecPtrDebugDumpItemMethod debugXmlDumpItem; */
       
  1807 };
       
  1808 
       
  1809 /**
       
  1810  * xmlSecDSigReferenceCtxListGetKlass:
       
  1811  *
       
  1812  * The <dsig:Reference/> element processing contexts list klass.
       
  1813  *
       
  1814  * Returns <dsig:Reference/> element processing context list klass.
       
  1815  */
       
  1816 EXPORT_C
       
  1817 xmlSecPtrListId 
       
  1818 xmlSecDSigReferenceCtxListGetKlass(void) {
       
  1819     return(&xmlSecDSigReferenceCtxListKlass);
       
  1820 }
       
  1821 
       
  1822 #endif /* XMLSEC_NO_XMLDSIG */
       
  1823 
       
  1824