|         |      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  |