Replace vulnerable function to thread safety
[platform/upstream/xmlsec1.git] / src / xmldsig.c
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-2016 Aleksey Sanin <aleksey@aleksey.com>. All Rights Reserved.
12  */
13 #include "globals.h"
14
15 #ifndef XMLSEC_NO_XMLDSIG
16
17 #include <stdlib.h>
18 #include <stdio.h>
19 #include <string.h>
20
21 #include <libxml/tree.h>
22 #include <libxml/parser.h>
23
24 #include <xmlsec/xmlsec.h>
25 #include <xmlsec/buffer.h>
26 #include <xmlsec/xmltree.h>
27 #include <xmlsec/keys.h>
28 #include <xmlsec/keysmngr.h>
29 #include <xmlsec/transforms.h>
30 #include <xmlsec/membuf.h>
31 #include <xmlsec/xmldsig.h>
32 #include <xmlsec/errors.h>
33
34 /**************************************************************************
35  *
36  * xmlSecDSigCtx
37  *
38  *************************************************************************/
39 static int      xmlSecDSigCtxProcessSignatureNode       (xmlSecDSigCtxPtr dsigCtx,
40                                                          xmlNodePtr node);
41 static int      xmlSecDSigCtxProcessSignedInfoNode      (xmlSecDSigCtxPtr dsigCtx,
42                                                          xmlNodePtr node,
43                                                          xmlNodePtr * firstReferenceNode);
44 static int      xmlSecDSigCtxProcessKeyInfoNode         (xmlSecDSigCtxPtr dsigCtx,
45                                                          xmlNodePtr node);
46 static int      xmlSecDSigCtxProcessObjectNode          (xmlSecDSigCtxPtr dsigCtx,
47                                                          xmlNodePtr node);
48 static int      xmlSecDSigCtxProcessManifestNode        (xmlSecDSigCtxPtr dsigCtx,
49                                                          xmlNodePtr node);
50 static int      xmlSecDSigCtxProcessReferences          (xmlSecDSigCtxPtr dsigCtx,
51                                                          xmlNodePtr firstReferenceNode);
52
53 /* Tizen : Support for various validation mode */
54 static int      xmlSecDSigCtxProcessSignatureNodeEx     (xmlSecDSigCtxPtr dsigCtx,
55                                                          xmlNodePtr node, int noHash, void* pList);
56 static int      xmlSecDSigCtxProcessSignedInfoNodeEx    (xmlSecDSigCtxPtr dsigCtx,
57                                                          xmlNodePtr node, int noHash, void* pList);
58 static int      xmlSecDSigReferenceCtxProcessNodeEx     (xmlSecDSigReferenceCtxPtr dsigRefCtx,
59                                                          xmlNodePtr node, int noHash, void* pList);
60
61 /* The ID attribute in XMLDSig is 'Id' */
62 static const xmlChar*           xmlSecDSigIds[] = { xmlSecAttrId, NULL };
63
64
65 #define _start //xmlSecError(XMLSEC_ERRORS_HERE, NULL, NULL, XMLSEC_ERRORS_MAX_NUMBER," >> start ");
66 #define _end //xmlSecError(XMLSEC_ERRORS_HERE, NULL, NULL, XMLSEC_ERRORS_MAX_NUMBER," >> end ");
67 static char logMsg[1024];
68
69 /**
70  * xmlSecDSigCtxCreate:
71  * @keysMngr:           the pointer to keys manager.
72  *
73  * Creates <dsig:Signature/> element processing context.
74  * The caller is responsible for destroying returned object by calling
75  * #xmlSecDSigCtxDestroy function.
76  *
77  * Returns: pointer to newly allocated context object or NULL if an error
78  * occurs.
79  */
80 xmlSecDSigCtxPtr
81 xmlSecDSigCtxCreate(xmlSecKeysMngrPtr keysMngr) {
82     xmlSecDSigCtxPtr dsigCtx;
83     int ret;
84
85     dsigCtx = (xmlSecDSigCtxPtr) xmlMalloc(sizeof(xmlSecDSigCtx));
86     if(dsigCtx == NULL) {
87         xmlSecError(XMLSEC_ERRORS_HERE,
88                     NULL,
89                     NULL,
90                     XMLSEC_ERRORS_R_MALLOC_FAILED,
91                     "sizeof(xmlSecDSigCtx)=%d",
92                     (int)sizeof(xmlSecDSigCtx));
93         return(NULL);
94     }
95
96     ret = xmlSecDSigCtxInitialize(dsigCtx, keysMngr);
97     if(ret < 0) {
98         xmlSecError(XMLSEC_ERRORS_HERE,
99                     NULL,
100                     "xmlSecDSigCtxInitialize",
101                     XMLSEC_ERRORS_R_XMLSEC_FAILED,
102                     XMLSEC_ERRORS_NO_MESSAGE);
103         xmlSecDSigCtxDestroy(dsigCtx);
104         return(NULL);
105     }
106     return(dsigCtx);
107 }
108
109 /**
110  * xmlSecDSigCtxDestroy:
111  * @dsigCtx:            the pointer to <dsig:Signature/> processing context.
112  *
113  * Destroy context object created with #xmlSecDSigCtxCreate function.
114  */
115 void
116 xmlSecDSigCtxDestroy(xmlSecDSigCtxPtr dsigCtx) {
117     xmlSecAssert(dsigCtx != NULL);
118
119     xmlSecDSigCtxFinalize(dsigCtx);
120     xmlFree(dsigCtx);
121 }
122
123 /**
124  * xmlSecDSigCtxInitialize:
125  * @dsigCtx:            the pointer to <dsig:Signature/> processing context.
126  * @keysMngr:           the pointer to keys manager.
127  *
128  * Initializes <dsig:Signature/> element processing context.
129  * The caller is responsible for cleaning up returned object by calling
130  * #xmlSecDSigCtxFinalize function.
131  *
132  * Returns: 0 on success or a negative value if an error occurs.
133  */
134 int
135 xmlSecDSigCtxInitialize(xmlSecDSigCtxPtr dsigCtx, xmlSecKeysMngrPtr keysMngr) {
136     int ret;
137
138     xmlSecAssert2(dsigCtx != NULL, -1);
139
140     memset(dsigCtx, 0, sizeof(xmlSecDSigCtx));
141
142     /* initialize key info */
143     ret = xmlSecKeyInfoCtxInitialize(&(dsigCtx->keyInfoReadCtx), 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->keyInfoReadCtx.mode = xmlSecKeyInfoModeRead;
153
154     ret = xmlSecKeyInfoCtxInitialize(&(dsigCtx->keyInfoWriteCtx), keysMngr);
155     if(ret < 0) {
156         xmlSecError(XMLSEC_ERRORS_HERE,
157                     NULL,
158                     "xmlSecKeyInfoCtxInitialize",
159                     XMLSEC_ERRORS_R_XMLSEC_FAILED,
160                     XMLSEC_ERRORS_NO_MESSAGE);
161         return(-1);
162     }
163     dsigCtx->keyInfoWriteCtx.mode = xmlSecKeyInfoModeWrite;
164     /* it's not wise to write private key :) */
165     dsigCtx->keyInfoWriteCtx.keyReq.keyType = xmlSecKeyDataTypePublic;
166
167     /* initializes transforms dsigCtx */
168     ret = xmlSecTransformCtxInitialize(&(dsigCtx->transformCtx));
169     if(ret < 0) {
170         xmlSecError(XMLSEC_ERRORS_HERE,
171                     NULL,
172                     "xmlSecTransformCtxInitialize",
173                     XMLSEC_ERRORS_R_XMLSEC_FAILED,
174                     XMLSEC_ERRORS_NO_MESSAGE);
175         return(-1);
176     }
177
178     /* references lists from SignedInfo and Manifest elements */
179     ret = xmlSecPtrListInitialize(&(dsigCtx->signedInfoReferences),
180                                   xmlSecDSigReferenceCtxListId);
181     if(ret != 0) {
182         xmlSecError(XMLSEC_ERRORS_HERE,
183                     NULL,
184                     "xmlSecPtrListInitialize",
185                     XMLSEC_ERRORS_R_XMLSEC_FAILED,
186                     XMLSEC_ERRORS_NO_MESSAGE);
187         return(ret);
188     }
189     ret = xmlSecPtrListInitialize(&(dsigCtx->manifestReferences),
190                                   xmlSecDSigReferenceCtxListId);
191     if(ret != 0) {
192         xmlSecError(XMLSEC_ERRORS_HERE,
193                     NULL,
194                     "xmlSecPtrListInitialize",
195                     XMLSEC_ERRORS_R_XMLSEC_FAILED,
196                     XMLSEC_ERRORS_NO_MESSAGE);
197         return(ret);
198     }
199
200     dsigCtx->enabledReferenceUris = xmlSecTransformUriTypeAny;
201     return(0);
202 }
203
204 /**
205  * xmlSecDSigCtxFinalize:
206  * @dsigCtx:            the pointer to <dsig:Signature/> processing context.
207  *
208  * Cleans up @dsigCtx object initialized with #xmlSecDSigCtxInitialize function.
209  */
210 void
211 xmlSecDSigCtxFinalize(xmlSecDSigCtxPtr dsigCtx) {
212     xmlSecAssert(dsigCtx != NULL);
213
214     xmlSecTransformCtxFinalize(&(dsigCtx->transformCtx));
215     xmlSecKeyInfoCtxFinalize(&(dsigCtx->keyInfoReadCtx));
216     xmlSecKeyInfoCtxFinalize(&(dsigCtx->keyInfoWriteCtx));
217     xmlSecPtrListFinalize(&(dsigCtx->signedInfoReferences));
218     xmlSecPtrListFinalize(&(dsigCtx->manifestReferences));
219
220     if(dsigCtx->enabledReferenceTransforms != NULL) {
221         xmlSecPtrListDestroy(dsigCtx->enabledReferenceTransforms);
222     }
223     if(dsigCtx->signKey != NULL) {
224         xmlSecKeyDestroy(dsigCtx->signKey);
225     }
226     if(dsigCtx->id != NULL) {
227         xmlFree(dsigCtx->id);
228     }
229     memset(dsigCtx, 0, sizeof(xmlSecDSigCtx));
230 }
231
232 /**
233  * xmlSecDSigCtxEnableReferenceTransform:
234  * @dsigCtx:            the pointer to <dsig:Signature/> processing context.
235  * @transformId:        the transform klass.
236  *
237  * Enables @transformId for <dsig:Reference/> elements processing.
238  *
239  * Returns: 0 on success or a negative value if an error occurs.
240  */
241 int
242 xmlSecDSigCtxEnableReferenceTransform(xmlSecDSigCtxPtr dsigCtx, xmlSecTransformId transformId) {
243     int ret;
244
245     xmlSecAssert2(dsigCtx != NULL, -1);
246     xmlSecAssert2(dsigCtx->result == NULL, -1);
247     xmlSecAssert2(transformId != xmlSecTransformIdUnknown, -1);
248
249     if(dsigCtx->enabledReferenceTransforms == NULL) {
250         dsigCtx->enabledReferenceTransforms = xmlSecPtrListCreate(xmlSecTransformIdListId);
251         if(dsigCtx->enabledReferenceTransforms == NULL) {
252             xmlSecError(XMLSEC_ERRORS_HERE,
253                         NULL,
254                         "xmlSecPtrListCreate",
255                         XMLSEC_ERRORS_R_XMLSEC_FAILED,
256                         XMLSEC_ERRORS_NO_MESSAGE);
257             return(-1);
258         }
259     }
260
261     ret = xmlSecPtrListAdd(dsigCtx->enabledReferenceTransforms, (void*)transformId);
262     if(ret < 0) {
263         xmlSecError(XMLSEC_ERRORS_HERE,
264                     NULL,
265                     "xmlSecPtrListAdd",
266                     XMLSEC_ERRORS_R_XMLSEC_FAILED,
267                     XMLSEC_ERRORS_NO_MESSAGE);
268         return(-1);
269     }
270     return(0);
271 }
272
273 /**
274  * xmlSecDSigCtxEnableSignatureTransform:
275  * @dsigCtx:            the pointer to <dsig:Signature/> processing context.
276  * @transformId:        the transform klass.
277  *
278  * Enables @transformId for <dsig:SignedInfo/> element processing.
279  *
280  * Returns: 0 on success or a negative value if an error occurs.
281  */
282 int
283 xmlSecDSigCtxEnableSignatureTransform(xmlSecDSigCtxPtr dsigCtx, xmlSecTransformId transformId) {
284     xmlSecAssert2(dsigCtx != NULL, -1);
285     xmlSecAssert2(dsigCtx->result == NULL, -1);
286     xmlSecAssert2(transformId != xmlSecTransformIdUnknown, -1);
287
288     return(xmlSecPtrListAdd(&(dsigCtx->transformCtx.enabledTransforms), (void*)transformId));
289 }
290
291 /**
292  * xmlSecDSigCtxGetPreSignBuffer:
293  * @dsigCtx:            the pointer to <dsig:Signature/> processing context.
294  *
295  * Gets pointer to the buffer with serialized <dsig:SignedInfo/> element
296  * just before signature claculation (valid if and only if
297  * #XMLSEC_DSIG_FLAGS_STORE_SIGNATURE context flag is set.
298  *
299  * Returns: 0 on success or a negative value if an error occurs.
300  */
301 xmlSecBufferPtr
302 xmlSecDSigCtxGetPreSignBuffer(xmlSecDSigCtxPtr dsigCtx) {
303     xmlSecAssert2(dsigCtx != NULL, NULL);
304
305     return((dsigCtx->preSignMemBufMethod != NULL) ?
306             xmlSecTransformMemBufGetBuffer(dsigCtx->preSignMemBufMethod) : NULL);
307 }
308
309 /**
310  * xmlSecDSigCtxSign:
311  * @dsigCtx:            the pointer to <dsig:Signature/> processing context.
312  * @tmpl:               the pointer to <dsig:Signature/> node with signature template.
313  *
314  * Signs the data as described in @tmpl node.
315  *
316  * Returns: 0 on success or a negative value if an error occurs.
317  */
318 int
319 xmlSecDSigCtxSign(xmlSecDSigCtxPtr dsigCtx, xmlNodePtr tmpl) {
320     int ret;
321
322     xmlSecAssert2(dsigCtx != NULL, -1);
323     xmlSecAssert2(dsigCtx->result == NULL, -1);
324     xmlSecAssert2(tmpl != NULL, -1);
325     xmlSecAssert2(tmpl->doc != NULL, -1);
326
327     /* add ids for Signature nodes */
328     dsigCtx->operation  = xmlSecTransformOperationSign;
329     dsigCtx->status     = xmlSecDSigStatusUnknown;
330     xmlSecAddIDs(tmpl->doc, tmpl, xmlSecDSigIds);
331
332     /* read signature template */
333     ret = xmlSecDSigCtxProcessSignatureNode(dsigCtx, tmpl);
334     if(ret < 0) {
335         xmlSecError(XMLSEC_ERRORS_HERE,
336                     NULL,
337                     "xmlSecDSigCtxSignatureProcessNode",
338                     XMLSEC_ERRORS_R_XMLSEC_FAILED,
339                     XMLSEC_ERRORS_NO_MESSAGE);
340         return(-1);
341     }
342     xmlSecAssert2(dsigCtx->signMethod != NULL, -1);
343     xmlSecAssert2(dsigCtx->signValueNode != NULL, -1);
344
345     /* references processing might change the status */
346     if(dsigCtx->status != xmlSecDSigStatusUnknown) {
347         return(0);
348     }
349
350     /* check what we've got */
351     dsigCtx->result = dsigCtx->transformCtx.result;
352     if((dsigCtx->result == NULL) || (xmlSecBufferGetData(dsigCtx->result) == NULL)) {
353         xmlSecError(XMLSEC_ERRORS_HERE,
354                     NULL,
355                     NULL,
356                     XMLSEC_ERRORS_R_INVALID_RESULT,
357                     XMLSEC_ERRORS_NO_MESSAGE);
358         return(-1);
359     }
360
361     /* write signed data to xml */
362     xmlNodeSetContentLen(dsigCtx->signValueNode,
363                             xmlSecBufferGetData(dsigCtx->result),
364                             xmlSecBufferGetSize(dsigCtx->result));
365
366     /* set success status and we are done */
367     dsigCtx->status = xmlSecDSigStatusSucceeded;
368     return(0);
369 }
370
371 /**
372  * xmlSecDSigCtxVerify:
373  * @dsigCtx:            the pointer to <dsig:Signature/> processing context.
374  * @node:               the pointer with <dsig:Signature/> node.
375  *
376  * Vaidates signature in the @node. The verification result is returned
377  * in #status member of the @dsigCtx object.
378  *
379  * Returns: 0 on success (check #status member of @dsigCtx to get
380  * signature verification result) or a negative value if an error occurs.
381  */
382 int
383 xmlSecDSigCtxVerify(xmlSecDSigCtxPtr dsigCtx, xmlNodePtr node) {
384     int ret;
385
386     xmlSecAssert2(dsigCtx != NULL, -1);
387     xmlSecAssert2(node != NULL, -1);
388     xmlSecAssert2(node->doc != NULL, -1);
389
390     /* add ids for Signature nodes */
391     dsigCtx->operation  = xmlSecTransformOperationVerify;
392     dsigCtx->status     = xmlSecDSigStatusUnknown;
393     xmlSecAddIDs(node->doc, node, xmlSecDSigIds);
394
395     /* read signature info */
396     ret = xmlSecDSigCtxProcessSignatureNode(dsigCtx, node);
397     if(ret < 0) {
398         xmlSecError(XMLSEC_ERRORS_HERE,
399                     NULL,
400                     "xmlSecDSigCtxSignatureProcessNode",
401                     XMLSEC_ERRORS_R_XMLSEC_FAILED,
402                     XMLSEC_ERRORS_NO_MESSAGE);
403         return(-1);
404     }
405     xmlSecAssert2(dsigCtx->signMethod != NULL, -1);
406     xmlSecAssert2(dsigCtx->signValueNode != NULL, -1);
407
408     /* references processing might change the status */
409     if(dsigCtx->status != xmlSecDSigStatusUnknown) {
410         return(0);
411     }
412
413     /* verify SignatureValue node content */
414     ret = xmlSecTransformVerifyNodeContent(dsigCtx->signMethod, dsigCtx->signValueNode,
415                                            &(dsigCtx->transformCtx));
416     if(ret < 0) {
417         xmlSecError(XMLSEC_ERRORS_HERE,
418                     NULL,
419                     "xmlSecTransformVerifyNodeContent",
420                     XMLSEC_ERRORS_R_XMLSEC_FAILED,
421                     XMLSEC_ERRORS_NO_MESSAGE);
422         return(-1);
423     }
424
425     /* set status and we are done */
426     if(dsigCtx->signMethod->status == xmlSecTransformStatusOk) {
427         dsigCtx->status = xmlSecDSigStatusSucceeded;
428     } else {
429         dsigCtx->status = xmlSecDSigStatusInvalid;
430     }
431     return(0);
432 }
433
434 /**
435  * xmlSecDSigCtxProcessSignatureNode:
436  *
437  * The Signature  element (http://www.w3.org/TR/xmldsig-core/#sec-Signature)
438  *
439  * The Signature element is the root element of an XML Signature.
440  * Implementation MUST generate laxly schema valid [XML-schema] Signature
441  * elements as specified by the following schema:
442  * The way in which the SignedInfo element is presented to the
443  * canonicalization method is dependent on that method. The following
444  * applies to algorithms which process XML as nodes or characters:
445  *
446  *  - XML based canonicalization implementations MUST be provided with
447  *  a [XPath] node-set originally formed from the document containing
448  *  the SignedInfo and currently indicating the SignedInfo, its descendants,
449  *  and the attribute and namespace nodes of SignedInfo and its descendant
450  *  elements.
451  *
452  *  - Text based canonicalization algorithms (such as CRLF and charset
453  *  normalization) should be provided with the UTF-8 octets that represent
454  *  the well-formed SignedInfo element, from the first character to the
455  *  last character of the XML representation, inclusive. This includes
456  *  the entire text of the start and end tags of the SignedInfo element
457  *  as well as all descendant markup and character data (i.e., the text)
458  *  between those tags. Use of text based canonicalization of SignedInfo
459  *  is NOT RECOMMENDED.
460  *
461  *  =================================
462  *  we do not support any non XML based C14N
463  *
464  * Schema Definition:
465  *
466  *  <element name="Signature" type="ds:SignatureType"/>
467  *  <complexType name="SignatureType">
468  *  <sequence>
469  *     <element ref="ds:SignedInfo"/>
470  *     <element ref="ds:SignatureValue"/>
471  *     <element ref="ds:KeyInfo" minOccurs="0"/>
472  *     <element ref="ds:Object" minOccurs="0" maxOccurs="unbounded"/>
473  *     </sequence> <attribute name="Id" type="ID" use="optional"/>
474  *  </complexType>
475  *
476  * DTD:
477  *
478  *  <!ELEMENT Signature (SignedInfo, SignatureValue, KeyInfo?, Object*)  >
479  *  <!ATTLIST Signature
480  *      xmlns   CDATA   #FIXED 'http://www.w3.org/2000/09/xmldsig#'
481  *      Id      ID  #IMPLIED >
482  *
483  */
484 static int
485 xmlSecDSigCtxProcessSignatureNode(xmlSecDSigCtxPtr dsigCtx, xmlNodePtr node) {
486     xmlSecTransformDataType firstType;
487     xmlNodePtr signedInfoNode = NULL;
488     xmlNodePtr keyInfoNode = NULL;
489     xmlNodePtr firstReferenceNode = NULL;
490     xmlNodePtr cur;
491     int ret;
492
493     xmlSecAssert2(dsigCtx != NULL, -1);
494     xmlSecAssert2((dsigCtx->operation == xmlSecTransformOperationSign) || (dsigCtx->operation == xmlSecTransformOperationVerify), -1);
495     xmlSecAssert2(dsigCtx->status == xmlSecDSigStatusUnknown, -1);
496     xmlSecAssert2(dsigCtx->signValueNode == NULL, -1);
497     xmlSecAssert2(dsigCtx->signMethod == NULL, -1);
498     xmlSecAssert2(dsigCtx->c14nMethod == NULL, -1);
499     xmlSecAssert2(node != NULL, -1);
500
501     if(!xmlSecCheckNodeName(node, xmlSecNodeSignature, xmlSecDSigNs)) {
502         xmlSecError(XMLSEC_ERRORS_HERE,
503                     NULL,
504                     xmlSecErrorsSafeString(xmlSecNodeGetName(node)),
505                     XMLSEC_ERRORS_R_INVALID_NODE,
506                     "expected=%s",
507                     xmlSecErrorsSafeString(xmlSecNodeSignature));
508         return(-1);
509     }
510
511     /* read node data */
512     xmlSecAssert2(dsigCtx->id == NULL, -1);
513     dsigCtx->id = xmlGetProp(node, xmlSecAttrId);
514
515     /* first node is required SignedInfo */
516     cur = xmlSecGetNextElementNode(node->children);
517     if((cur == NULL) || (!xmlSecCheckNodeName(cur, xmlSecNodeSignedInfo, xmlSecDSigNs))) {
518         xmlSecError(XMLSEC_ERRORS_HERE,
519                     NULL,
520                     xmlSecErrorsSafeString(xmlSecNodeGetName(cur)),
521                     XMLSEC_ERRORS_R_INVALID_NODE,
522                     "expected=%s",
523                     xmlSecErrorsSafeString(xmlSecNodeSignedInfo));
524         return(-1);
525     }
526     signedInfoNode = cur;
527     cur = xmlSecGetNextElementNode(cur->next);
528
529     /* next node is required SignatureValue */
530     if((cur == NULL) || (!xmlSecCheckNodeName(cur, xmlSecNodeSignatureValue, xmlSecDSigNs))) {
531         xmlSecError(XMLSEC_ERRORS_HERE,
532                     NULL,
533                     xmlSecErrorsSafeString(xmlSecNodeGetName(cur)),
534                     XMLSEC_ERRORS_R_INVALID_NODE,
535                     "expected=%s",
536                     xmlSecErrorsSafeString(xmlSecNodeSignatureValue));
537         return(-1);
538     }
539     dsigCtx->signValueNode = cur;
540     cur = xmlSecGetNextElementNode(cur->next);
541
542     /* next node is optional KeyInfo */
543     if((cur != NULL) && (xmlSecCheckNodeName(cur, xmlSecNodeKeyInfo, xmlSecDSigNs))) {
544         keyInfoNode = cur;
545         cur = xmlSecGetNextElementNode(cur->next);
546     } else {
547         keyInfoNode = NULL;
548     }
549
550     /* next nodes are optional Object nodes */
551     while((cur != NULL) && (xmlSecCheckNodeName(cur, xmlSecNodeObject, xmlSecDSigNs))) {
552         /* read manifests from objects */
553         if((dsigCtx->flags & XMLSEC_DSIG_FLAGS_IGNORE_MANIFESTS) == 0) {
554             ret = xmlSecDSigCtxProcessObjectNode(dsigCtx, cur);
555             if(ret < 0) {
556                 xmlSecError(XMLSEC_ERRORS_HERE,
557                             NULL,
558                             "xmlSecDSigCtxProcessObjectNode",
559                             XMLSEC_ERRORS_R_XMLSEC_FAILED,
560                             XMLSEC_ERRORS_NO_MESSAGE);
561                 return(-1);
562             }
563         }
564         cur = xmlSecGetNextElementNode(cur->next);
565     }
566
567     /* if there is something left than it's an error */
568     if(cur != NULL) {
569         xmlSecError(XMLSEC_ERRORS_HERE,
570                     NULL,
571                     xmlSecErrorsSafeString(xmlSecNodeGetName(cur)),
572                     XMLSEC_ERRORS_R_UNEXPECTED_NODE,
573                     XMLSEC_ERRORS_NO_MESSAGE);
574         return(-1);
575     }
576
577     /* now validated all the references and prepare transform */
578     ret = xmlSecDSigCtxProcessSignedInfoNode(dsigCtx, signedInfoNode, &firstReferenceNode);
579     if(ret < 0) {
580         xmlSecError(XMLSEC_ERRORS_HERE,
581                     NULL,
582                     "xmlSecDSigCtxProcessSignedInfoNode",
583                     XMLSEC_ERRORS_R_XMLSEC_FAILED,
584                     XMLSEC_ERRORS_NO_MESSAGE);
585         return(-1);
586     }
587
588     /* as the result, we should have sign and c14n methods set */
589     xmlSecAssert2(dsigCtx->signMethod != NULL, -1);
590     xmlSecAssert2(dsigCtx->c14nMethod != NULL, -1);
591
592     /* now read key info node */
593     ret = xmlSecDSigCtxProcessKeyInfoNode(dsigCtx, keyInfoNode);
594     if(ret < 0) {
595         xmlSecError(XMLSEC_ERRORS_HERE,
596                     NULL,
597                     "xmlSecDSigCtxProcessKeyInfoNode",
598                     XMLSEC_ERRORS_R_XMLSEC_FAILED,
599                     XMLSEC_ERRORS_NO_MESSAGE);
600         return(-1);
601     }
602     /* as the result, we should have a key */
603     xmlSecAssert2(dsigCtx->signKey != NULL, -1);
604
605     /* now actually process references and calculate digests */
606     ret = xmlSecDSigCtxProcessReferences(dsigCtx, firstReferenceNode);
607     if(ret < 0) {
608         xmlSecError(XMLSEC_ERRORS_HERE,
609                     NULL,
610                     "xmlSecDSigCtxProcessReferences",
611                     XMLSEC_ERRORS_R_XMLSEC_FAILED,
612                     XMLSEC_ERRORS_NO_MESSAGE);
613         return(-1);
614     }
615     /* references processing might change the status */
616     if(dsigCtx->status != xmlSecDSigStatusUnknown) {
617         return(0);
618     }
619
620     /* if we need to write result to xml node then we need base64 encode result */
621     if(dsigCtx->operation == xmlSecTransformOperationSign) {
622         xmlSecTransformPtr base64Encode;
623
624         /* we need to add base64 encode transform */
625         base64Encode = xmlSecTransformCtxCreateAndAppend(&(dsigCtx->transformCtx),
626                                                          xmlSecTransformBase64Id);
627         if(base64Encode == NULL) {
628             xmlSecError(XMLSEC_ERRORS_HERE,
629                         NULL,
630                         "xmlSecTransformCtxCreateAndAppend",
631                         XMLSEC_ERRORS_R_XMLSEC_FAILED,
632                         XMLSEC_ERRORS_NO_MESSAGE);
633             return(-1);
634         }
635         base64Encode->operation = xmlSecTransformOperationEncode;
636     }
637
638     firstType = xmlSecTransformGetDataType(dsigCtx->transformCtx.first,
639                                            xmlSecTransformModePush,
640                                            &(dsigCtx->transformCtx));
641     if((firstType & xmlSecTransformDataTypeXml) != 0) {
642         xmlSecNodeSetPtr nodeset = NULL;
643
644         xmlSecAssert2(signedInfoNode != NULL, -1);
645         nodeset = xmlSecNodeSetGetChildren(signedInfoNode->doc, signedInfoNode, 1, 0);
646         if(nodeset == NULL) {
647             xmlSecError(XMLSEC_ERRORS_HERE,
648                         NULL,
649                         "xmlSecNodeSetGetChildren",
650                         XMLSEC_ERRORS_R_XMLSEC_FAILED,
651                         "node=%s",
652                         xmlSecErrorsSafeString(xmlSecNodeGetName(signedInfoNode)));
653             return(-1);
654         }
655
656         /* calculate the signature */
657         ret = xmlSecTransformCtxXmlExecute(&(dsigCtx->transformCtx), nodeset);
658         if(ret < 0) {
659             xmlSecError(XMLSEC_ERRORS_HERE,
660                         NULL,
661                         "xmlSecTransformCtxXmlExecute",
662                         XMLSEC_ERRORS_R_XMLSEC_FAILED,
663                         XMLSEC_ERRORS_NO_MESSAGE);
664             xmlSecNodeSetDestroy(nodeset);
665             return(-1);
666         }
667         xmlSecNodeSetDestroy(nodeset);
668     } else {
669         /* TODO */
670         xmlSecError(XMLSEC_ERRORS_HERE,
671                     NULL,
672                     "the binary c14n transforms are not supported yet",
673                     XMLSEC_ERRORS_R_NOT_IMPLEMENTED,
674                     XMLSEC_ERRORS_NO_MESSAGE);
675         return(-1);
676     }
677     return(0);
678 }
679
680 /**
681  * xmlSecDSigCtxProcessSignedInfoNode:
682  *
683  * The SignedInfo Element (http://www.w3.org/TR/xmldsig-core/#sec-SignedInfo)
684  *
685  * The structure of SignedInfo includes the canonicalization algorithm,
686  * a result algorithm, and one or more references. The SignedInfo element
687  * may contain an optional ID attribute that will allow it to be referenced by
688  * other signatures and objects.
689  *
690  * SignedInfo does not include explicit result or digest properties (such as
691  * calculation time, cryptographic device serial number, etc.). If an
692  * application needs to associate properties with the result or digest,
693  * it may include such information in a SignatureProperties element within
694  * an Object element.
695  *
696  * Schema Definition:
697  *
698  *  <element name="SignedInfo" type="ds:SignedInfoType"/>
699  *  <complexType name="SignedInfoType">
700  *    <sequence>
701  *      <element ref="ds:CanonicalizationMethod"/>
702  *      <element ref="ds:SignatureMethod"/>
703  *      <element ref="ds:Reference" maxOccurs="unbounded"/>
704  *    </sequence>
705  *    <attribute name="Id" type="ID" use="optional"/>
706  *  </complexType>
707  *
708  * DTD:
709  *
710  *  <!ELEMENT SignedInfo (CanonicalizationMethod, SignatureMethod,  Reference+) >
711  *  <!ATTLIST SignedInfo  Id   ID      #IMPLIED>
712  *
713  */
714 static int
715 xmlSecDSigCtxProcessSignedInfoNode(xmlSecDSigCtxPtr dsigCtx, xmlNodePtr node, xmlNodePtr * firstReferenceNode) {
716     xmlSecSize refNodesCount = 0;
717     xmlNodePtr cur;
718
719     xmlSecAssert2(dsigCtx != NULL, -1);
720     xmlSecAssert2(dsigCtx->status == xmlSecDSigStatusUnknown, -1);
721     xmlSecAssert2(dsigCtx->signMethod == NULL, -1);
722     xmlSecAssert2(dsigCtx->c14nMethod == NULL, -1);
723     xmlSecAssert2((dsigCtx->operation == xmlSecTransformOperationSign) || (dsigCtx->operation == xmlSecTransformOperationVerify), -1);
724     xmlSecAssert2(node != NULL, -1);
725     xmlSecAssert2(firstReferenceNode != NULL, -1);
726     xmlSecAssert2((*firstReferenceNode) == NULL, -1);
727
728     /* first node is required CanonicalizationMethod. */
729     cur = xmlSecGetNextElementNode(node->children);
730     if((cur != NULL) && (xmlSecCheckNodeName(cur, xmlSecNodeCanonicalizationMethod, xmlSecDSigNs))) {
731         dsigCtx->c14nMethod = xmlSecTransformCtxNodeRead(&(dsigCtx->transformCtx),
732                                         cur, xmlSecTransformUsageC14NMethod);
733         if(dsigCtx->c14nMethod == NULL) {
734             xmlSecError(XMLSEC_ERRORS_HERE,
735                         NULL,
736                         "xmlSecTransformCtxNodeRead",
737                         XMLSEC_ERRORS_R_XMLSEC_FAILED,
738                         "node=%s",
739                         xmlSecErrorsSafeString(xmlSecNodeGetName(cur)));
740             return(-1);
741         }
742     } else if(dsigCtx->defC14NMethodId != xmlSecTransformIdUnknown) {
743         /* the dsig spec does require CanonicalizationMethod node
744          * to be present but in some case it application might decide to
745          * minimize traffic */
746         dsigCtx->c14nMethod = xmlSecTransformCtxCreateAndAppend(&(dsigCtx->transformCtx),
747                                                               dsigCtx->defC14NMethodId);
748         if(dsigCtx->c14nMethod == NULL) {
749             xmlSecError(XMLSEC_ERRORS_HERE,
750                         NULL,
751                         "xmlSecTransformCtxAppend",
752                         XMLSEC_ERRORS_R_XMLSEC_FAILED,
753                         XMLSEC_ERRORS_NO_MESSAGE);
754             return(-1);
755         }
756     } else {
757         xmlSecError(XMLSEC_ERRORS_HERE,
758                     NULL,
759                     "CanonicalizationMethod",
760                     XMLSEC_ERRORS_R_INVALID_NODE,
761                     "expected=%s",
762                     xmlSecErrorsSafeString(xmlSecNodeCanonicalizationMethod));
763         return(-1);
764     }
765
766     /* insert membuf if requested */
767     if((dsigCtx->flags & XMLSEC_DSIG_FLAGS_STORE_SIGNATURE) != 0) {
768         xmlSecAssert2(dsigCtx->preSignMemBufMethod == NULL, -1);
769         dsigCtx->preSignMemBufMethod = xmlSecTransformCtxCreateAndAppend(&(dsigCtx->transformCtx),
770                                                 xmlSecTransformMemBufId);
771         if(dsigCtx->preSignMemBufMethod == NULL) {
772             xmlSecError(XMLSEC_ERRORS_HERE,
773                         NULL,
774                         "xmlSecTransformCtxCreateAndAppend",
775                         XMLSEC_ERRORS_R_XMLSEC_FAILED,
776                         "transform=%s",
777                         xmlSecErrorsSafeString(xmlSecTransformKlassGetName(xmlSecTransformMemBufId)));
778         }
779     }
780
781     /* next node is required SignatureMethod. */
782     cur = xmlSecGetNextElementNode( ((cur != NULL) ? cur->next : node->children) );
783     if((cur != NULL) && (xmlSecCheckNodeName(cur, xmlSecNodeSignatureMethod, xmlSecDSigNs))) {
784         dsigCtx->signMethod = xmlSecTransformCtxNodeRead(&(dsigCtx->transformCtx),
785                                         cur, xmlSecTransformUsageSignatureMethod);
786         if(dsigCtx->signMethod == NULL) {
787             xmlSecError(XMLSEC_ERRORS_HERE,
788                         NULL,
789                         "xmlSecTransformCtxNodeRead",
790                         XMLSEC_ERRORS_R_XMLSEC_FAILED,
791                         "node=%s",
792                         xmlSecErrorsSafeString(xmlSecNodeGetName(cur)));
793             return(-1);
794         }
795     } else if(dsigCtx->defSignMethodId != xmlSecTransformIdUnknown) {
796         /* the dsig spec does require SignatureMethod node
797          * to be present but in some case it application might decide to
798          * minimize traffic */
799         dsigCtx->signMethod = xmlSecTransformCtxCreateAndAppend(&(dsigCtx->transformCtx),
800                                                               dsigCtx->defSignMethodId);
801         if(dsigCtx->signMethod == NULL) {
802             xmlSecError(XMLSEC_ERRORS_HERE,
803                         NULL,
804                         "xmlSecTransformCtxAppend",
805                         XMLSEC_ERRORS_R_XMLSEC_FAILED,
806                         XMLSEC_ERRORS_NO_MESSAGE);
807             return(-1);
808         }
809     } else {
810         xmlSecError(XMLSEC_ERRORS_HERE,
811                     NULL,
812                     xmlSecErrorsSafeString(xmlSecNodeGetName(cur)),
813                     XMLSEC_ERRORS_R_INVALID_NODE,
814                     "expected=%s",
815                     xmlSecErrorsSafeString(xmlSecNodeSignatureMethod));
816         return(-1);
817     }
818     dsigCtx->signMethod->operation = dsigCtx->operation;
819
820     /* read references */
821     if(cur != NULL) {
822         cur = xmlSecGetNextElementNode(cur->next);
823     }
824     while((cur != NULL) && (xmlSecCheckNodeName(cur, xmlSecNodeReference, xmlSecDSigNs))) {
825         /* record first reference node */
826         if((*firstReferenceNode) == NULL) {
827             (*firstReferenceNode) = cur;
828         }
829         ++refNodesCount;
830
831         /* go to next */
832         cur = xmlSecGetNextElementNode(cur->next);
833     }
834
835     /* check that we have at least one Reference */
836     if(refNodesCount == 0) {
837         xmlSecError(XMLSEC_ERRORS_HERE,
838                     NULL,
839                     NULL,
840                     XMLSEC_ERRORS_R_DSIG_NO_REFERENCES,
841                     XMLSEC_ERRORS_NO_MESSAGE);
842         return(-1);
843     }
844
845     /* if there is something left than it's an error */
846     if(cur != NULL) {
847         xmlSecError(XMLSEC_ERRORS_HERE,
848                     NULL,
849                     xmlSecErrorsSafeString(xmlSecNodeGetName(cur)),
850                     XMLSEC_ERRORS_R_UNEXPECTED_NODE,
851                     XMLSEC_ERRORS_NO_MESSAGE);
852         return(-1);
853     }
854
855     /* done */
856     return(0);
857 }
858
859
860 static int
861 xmlSecDSigCtxProcessReferences(xmlSecDSigCtxPtr dsigCtx, xmlNodePtr firstReferenceNode) {
862     xmlSecDSigReferenceCtxPtr dsigRefCtx;
863     xmlNodePtr cur;
864     int ret;
865
866     xmlSecAssert2(dsigCtx != NULL, -1);
867     xmlSecAssert2(dsigCtx->status == xmlSecDSigStatusUnknown, -1);
868     xmlSecAssert2((dsigCtx->operation == xmlSecTransformOperationSign) || (dsigCtx->operation == xmlSecTransformOperationVerify), -1);
869     xmlSecAssert2(xmlSecPtrListGetSize(&(dsigCtx->signedInfoReferences)) == 0, -1);
870     xmlSecAssert2(firstReferenceNode != NULL, -1);
871
872     /* process references */
873     for(cur = firstReferenceNode; (cur != NULL); cur = xmlSecGetNextElementNode(cur->next)) {
874         /* already checked but we trust none */
875         if(!xmlSecCheckNodeName(cur, xmlSecNodeReference, xmlSecDSigNs)) {
876             xmlSecError(XMLSEC_ERRORS_HERE,
877                         NULL,
878                         xmlSecErrorsSafeString(xmlSecNodeGetName(cur)),
879                         XMLSEC_ERRORS_R_INVALID_NODE,
880                         "expected=%s",
881                         xmlSecErrorsSafeString(xmlSecNodeReference));
882             return(-1);
883         }
884
885         /* create reference */
886         dsigRefCtx = xmlSecDSigReferenceCtxCreate(dsigCtx, xmlSecDSigReferenceOriginSignedInfo);
887         if(dsigRefCtx == NULL) {
888             xmlSecError(XMLSEC_ERRORS_HERE,
889                         NULL,
890                         "xmlSecDSigReferenceCtxCreate",
891                         XMLSEC_ERRORS_R_XMLSEC_FAILED,
892                         XMLSEC_ERRORS_NO_MESSAGE);
893             return(-1);
894         }
895
896         /* add to the list */
897         ret = xmlSecPtrListAdd(&(dsigCtx->signedInfoReferences), dsigRefCtx);
898         if(ret < 0) {
899             xmlSecError(XMLSEC_ERRORS_HERE,
900                         NULL,
901                         "xmlSecPtrListAdd",
902                         XMLSEC_ERRORS_R_XMLSEC_FAILED,
903                         XMLSEC_ERRORS_NO_MESSAGE);
904             xmlSecDSigReferenceCtxDestroy(dsigRefCtx);
905             return(-1);
906         }
907
908         /* process */
909         ret = xmlSecDSigReferenceCtxProcessNode(dsigRefCtx, cur);
910         if(ret < 0) {
911             xmlSecError(XMLSEC_ERRORS_HERE,
912                         NULL,
913                         "xmlSecDSigReferenceCtxProcessNode",
914                         XMLSEC_ERRORS_R_XMLSEC_FAILED,
915                         "node=%s",
916                         xmlSecErrorsSafeString(xmlSecNodeGetName(cur)));
917             return(-1);
918         }
919
920         /* bail out if next Reference processing failed */
921         if(dsigRefCtx->status != xmlSecDSigStatusSucceeded) {
922             dsigCtx->status = xmlSecDSigStatusInvalid;
923             return(0);
924         }
925     }
926
927     /* done */
928     return(0);
929 }
930
931
932 static int
933 xmlSecDSigCtxProcessKeyInfoNode(xmlSecDSigCtxPtr dsigCtx, xmlNodePtr node) {
934     int ret;
935
936     xmlSecAssert2(dsigCtx != NULL, -1);
937     xmlSecAssert2(dsigCtx->signMethod != NULL, -1);
938
939     /* set key requirements */
940     ret = xmlSecTransformSetKeyReq(dsigCtx->signMethod, &(dsigCtx->keyInfoReadCtx.keyReq));
941     if(ret < 0) {
942         xmlSecError(XMLSEC_ERRORS_HERE,
943                     NULL,
944                     "xmlSecTransformSetKeyReq",
945                     XMLSEC_ERRORS_R_XMLSEC_FAILED,
946                     "transform=%s",
947                     xmlSecErrorsSafeString(xmlSecTransformGetName(dsigCtx->signMethod)));
948         return(-1);
949     }
950
951     /* ignore <dsig:KeyInfo /> if there is the key is already set */
952     /* todo: throw an error if key is set and node != NULL? */
953     if((dsigCtx->signKey == NULL) && (dsigCtx->keyInfoReadCtx.keysMngr != NULL)
954                         && (dsigCtx->keyInfoReadCtx.keysMngr->getKey != NULL)) {
955         dsigCtx->signKey = (dsigCtx->keyInfoReadCtx.keysMngr->getKey)(node, &(dsigCtx->keyInfoReadCtx));
956     }
957
958     /* check that we have exactly what we want */
959     if((dsigCtx->signKey == NULL) || (!xmlSecKeyMatch(dsigCtx->signKey, NULL, &(dsigCtx->keyInfoReadCtx.keyReq)))) {
960         xmlSecError(XMLSEC_ERRORS_HERE,
961                     NULL,
962                     NULL,
963                     XMLSEC_ERRORS_R_KEY_NOT_FOUND,
964                     XMLSEC_ERRORS_NO_MESSAGE);
965         return(-1);
966     }
967
968     /* set the key to the transform */
969     ret = xmlSecTransformSetKey(dsigCtx->signMethod, dsigCtx->signKey);
970     if(ret < 0) {
971         xmlSecError(XMLSEC_ERRORS_HERE,
972                     NULL,
973                     "xmlSecTransformSetKey",
974                     XMLSEC_ERRORS_R_XMLSEC_FAILED,
975                     "transform=%s",
976                     xmlSecErrorsSafeString(xmlSecTransformGetName(dsigCtx->signMethod)));
977         return(-1);
978     }
979
980     /* if we are signing document, update <dsig:KeyInfo/> node */
981     if((node != NULL) && (dsigCtx->operation == xmlSecTransformOperationSign)) {
982         ret = xmlSecKeyInfoNodeWrite(node, dsigCtx->signKey, &(dsigCtx->keyInfoWriteCtx));
983         if(ret < 0) {
984             xmlSecError(XMLSEC_ERRORS_HERE,
985                         NULL,
986                         "xmlSecKeyInfoNodeWrite",
987                         XMLSEC_ERRORS_R_XMLSEC_FAILED,
988                         XMLSEC_ERRORS_NO_MESSAGE);
989             return(-1);
990         }
991     }
992
993     return(0);
994 }
995
996 /**
997  * xmlSecDSigCtxProcessObjectNode:
998  *
999  * The Object Element (http://www.w3.org/TR/xmldsig-core/#sec-Object)
1000  *
1001  * Object is an optional element that may occur one or more times. When
1002  * present, this element may contain any data. The Object element may include
1003  * optional MIME type, ID, and encoding attributes.
1004  *
1005  * Schema Definition:
1006  *
1007  * <element name="Object" type="ds:ObjectType"/>
1008  * <complexType name="ObjectType" mixed="true">
1009  *   <sequence minOccurs="0" maxOccurs="unbounded">
1010  *     <any namespace="##any" processContents="lax"/>
1011  *   </sequence>
1012  *   <attribute name="Id" type="ID" use="optional"/>
1013  *   <attribute name="MimeType" type="string" use="optional"/>
1014  *   <attribute name="Encoding" type="anyURI" use="optional"/>
1015  * </complexType>
1016  *
1017  * DTD:
1018  *
1019  * <!ELEMENT Object (#PCDATA|Signature|SignatureProperties|Manifest %Object.ANY;)* >
1020  * <!ATTLIST Object  Id  ID  #IMPLIED
1021  *                   MimeType    CDATA   #IMPLIED
1022  *                   Encoding    CDATA   #IMPLIED >
1023  */
1024 static int
1025 xmlSecDSigCtxProcessObjectNode(xmlSecDSigCtxPtr dsigCtx, xmlNodePtr node) {
1026     xmlNodePtr cur;
1027     int ret;
1028
1029     xmlSecAssert2(dsigCtx != NULL, -1);
1030     xmlSecAssert2(dsigCtx->status == xmlSecDSigStatusUnknown, -1);
1031     xmlSecAssert2(node != NULL, -1);
1032
1033     /* we care about Manifest nodes only; ignore everything else */
1034     cur = xmlSecGetNextElementNode(node->children);
1035     while(cur != NULL) {
1036         if(xmlSecCheckNodeName(cur, xmlSecNodeManifest, xmlSecDSigNs)) {
1037             ret = xmlSecDSigCtxProcessManifestNode(dsigCtx, cur);
1038             if(ret < 0){
1039                 xmlSecError(XMLSEC_ERRORS_HERE,
1040                             NULL,
1041                             "xmlSecDSigCtxProcessManifestNode",
1042                             XMLSEC_ERRORS_R_XMLSEC_FAILED,
1043                             XMLSEC_ERRORS_NO_MESSAGE);
1044                 return(-1);
1045             }
1046         }
1047         cur = xmlSecGetNextElementNode(cur->next);
1048     }
1049     return(0);
1050 }
1051
1052 /**
1053  * xmlSecDSigCtxProcessManifestNode:
1054  *
1055  * The Manifest  Element (http://www.w3.org/TR/xmldsig-core/#sec-Manifest)
1056  *
1057  * The Manifest element provides a list of References. The difference from
1058  * the list in SignedInfo is that it is application defined which, if any, of
1059  * the digests are actually checked against the objects referenced and what to
1060  * do if the object is inaccessible or the digest compare fails. If a Manifest
1061  * is pointed to from SignedInfo, the digest over the Manifest itself will be
1062  * checked by the core result validation behavior. The digests within such
1063  * a Manifest are checked at the application's discretion. If a Manifest is
1064  * referenced from another Manifest, even the overall digest of this two level
1065  * deep Manifest might not be checked.
1066  *
1067  * Schema Definition:
1068  *
1069  * <element name="Manifest" type="ds:ManifestType"/>
1070  * <complexType name="ManifestType">
1071  *   <sequence>
1072  *     <element ref="ds:Reference" maxOccurs="unbounded"/>
1073  *   </sequence>
1074  *   <attribute name="Id" type="ID" use="optional"/>
1075  *  </complexType>
1076  *
1077  * DTD:
1078  *
1079  * <!ELEMENT Manifest (Reference+)  >
1080  * <!ATTLIST Manifest Id ID  #IMPLIED >
1081  */
1082 static int
1083 xmlSecDSigCtxProcessManifestNode(xmlSecDSigCtxPtr dsigCtx, xmlNodePtr node) {
1084     xmlSecDSigReferenceCtxPtr dsigRefCtx;
1085     xmlNodePtr cur;
1086     int ret;
1087
1088     xmlSecAssert2(dsigCtx != NULL, -1);
1089     xmlSecAssert2(dsigCtx->status == xmlSecDSigStatusUnknown, -1);
1090     xmlSecAssert2(node != NULL, -1);
1091
1092     /* calculate references */
1093     cur = xmlSecGetNextElementNode(node->children);
1094     while((cur != NULL) && (xmlSecCheckNodeName(cur, xmlSecNodeReference, xmlSecDSigNs))) {
1095         /* create reference */
1096         dsigRefCtx = xmlSecDSigReferenceCtxCreate(dsigCtx, xmlSecDSigReferenceOriginManifest);
1097         if(dsigRefCtx == NULL) {
1098             xmlSecError(XMLSEC_ERRORS_HERE,
1099                         NULL,
1100                         "xmlSecDSigReferenceCtxCreate",
1101                         XMLSEC_ERRORS_R_XMLSEC_FAILED,
1102                         XMLSEC_ERRORS_NO_MESSAGE);
1103             return(-1);
1104         }
1105
1106         /* add to the list */
1107         ret = xmlSecPtrListAdd(&(dsigCtx->manifestReferences), dsigRefCtx);
1108         if(ret < 0) {
1109             xmlSecError(XMLSEC_ERRORS_HERE,
1110                         NULL,
1111                         "xmlSecPtrListAdd",
1112                         XMLSEC_ERRORS_R_XMLSEC_FAILED,
1113                         XMLSEC_ERRORS_NO_MESSAGE);
1114             xmlSecDSigReferenceCtxDestroy(dsigRefCtx);
1115             return(-1);
1116         }
1117
1118         /* process */
1119         ret = xmlSecDSigReferenceCtxProcessNode(dsigRefCtx, cur);
1120         if(ret < 0) {
1121             xmlSecError(XMLSEC_ERRORS_HERE,
1122                         NULL,
1123                         "xmlSecDSigReferenceCtxProcessNode",
1124                         XMLSEC_ERRORS_R_XMLSEC_FAILED,
1125                         "node=%s",
1126                         xmlSecErrorsSafeString(xmlSecNodeGetName(cur)));
1127             return(-1);
1128         }
1129
1130         /* we don;t care if Reference processing failed because
1131          * it's Manifest node */
1132         cur = xmlSecGetNextElementNode(cur->next);
1133     }
1134
1135     /* we should have nothing else here */
1136     if(cur != NULL) {
1137         xmlSecError(XMLSEC_ERRORS_HERE,
1138                     NULL,
1139                     xmlSecErrorsSafeString(xmlSecNodeGetName(cur)),
1140                     XMLSEC_ERRORS_R_UNEXPECTED_NODE,
1141                     XMLSEC_ERRORS_NO_MESSAGE);
1142         return(-1);
1143     }
1144     return(0);
1145 }
1146
1147 /**
1148  * xmlSecDSigCtxDebugDump:
1149  * @dsigCtx:            the pointer to <dsig:Signature/> processing context.
1150  * @output:             the pointer to output FILE.
1151  *
1152  * Prints the debug information about @dsigCtx to @output.
1153  */
1154 void
1155 xmlSecDSigCtxDebugDump(xmlSecDSigCtxPtr dsigCtx, FILE* output) {
1156     xmlSecAssert(dsigCtx != NULL);
1157     xmlSecAssert(output != NULL);
1158
1159     if(dsigCtx->operation == xmlSecTransformOperationSign) {
1160         fprintf(output, "= SIGNATURE CONTEXT\n");
1161     } else {
1162         fprintf(output, "= VERIFICATION CONTEXT\n");
1163     }
1164     switch(dsigCtx->status) {
1165         case xmlSecDSigStatusUnknown:
1166             fprintf(output, "== Status: unknown\n");
1167             break;
1168         case xmlSecDSigStatusSucceeded:
1169             fprintf(output, "== Status: succeeded\n");
1170             break;
1171         case xmlSecDSigStatusInvalid:
1172             fprintf(output, "== Status: invalid\n");
1173             break;
1174     }
1175     fprintf(output, "== flags: 0x%08x\n", dsigCtx->flags);
1176     fprintf(output, "== flags2: 0x%08x\n", dsigCtx->flags2);
1177
1178     if(dsigCtx->id != NULL) {
1179         fprintf(output, "== Id: \"%s\"\n", dsigCtx->id);
1180     }
1181
1182     fprintf(output, "== Key Info Read Ctx:\n");
1183     xmlSecKeyInfoCtxDebugDump(&(dsigCtx->keyInfoReadCtx), output);
1184     fprintf(output, "== Key Info Write Ctx:\n");
1185     xmlSecKeyInfoCtxDebugDump(&(dsigCtx->keyInfoWriteCtx), output);
1186
1187     fprintf(output, "== Signature Transform Ctx:\n");
1188     xmlSecTransformCtxDebugDump(&(dsigCtx->transformCtx), output);
1189
1190     if(dsigCtx->signMethod != NULL) {
1191         fprintf(output, "== Signature Method:\n");
1192         xmlSecTransformDebugDump(dsigCtx->signMethod, output);
1193     }
1194
1195     if(dsigCtx->signKey != NULL) {
1196         fprintf(output, "== Signature Key:\n");
1197         xmlSecKeyDebugDump(dsigCtx->signKey, output);
1198     }
1199
1200     fprintf(output, "== SignedInfo References List:\n");
1201     xmlSecPtrListDebugDump(&(dsigCtx->signedInfoReferences), output);
1202
1203     fprintf(output, "== Manifest References List:\n");
1204     xmlSecPtrListDebugDump(&(dsigCtx->manifestReferences), output);
1205
1206     if((dsigCtx->result != NULL) &&
1207        (xmlSecBufferGetData(dsigCtx->result) != NULL)) {
1208
1209         fprintf(output, "== Result - start buffer:\n");
1210         (void)fwrite(xmlSecBufferGetData(dsigCtx->result),
1211                      xmlSecBufferGetSize(dsigCtx->result),
1212                      1, output);
1213         fprintf(output, "\n== Result - end buffer\n");
1214     }
1215     if(((dsigCtx->flags & XMLSEC_DSIG_FLAGS_STORE_SIGNATURE) != 0) &&
1216        (xmlSecDSigCtxGetPreSignBuffer(dsigCtx) != NULL) &&
1217        (xmlSecBufferGetData(xmlSecDSigCtxGetPreSignBuffer(dsigCtx)) != NULL)) {
1218
1219         fprintf(output, "== PreSigned data - start buffer:\n");
1220         (void)fwrite(xmlSecBufferGetData(xmlSecDSigCtxGetPreSignBuffer(dsigCtx)),
1221                      xmlSecBufferGetSize(xmlSecDSigCtxGetPreSignBuffer(dsigCtx)),
1222                      1, output);
1223         fprintf(output, "\n== PreSigned data - end buffer\n");
1224     }
1225 }
1226
1227 /**
1228  * xmlSecDSigCtxDebugXmlDump:
1229  * @dsigCtx:            the pointer to <dsig:Signature/> processing context.
1230  * @output:             the pointer to output FILE.
1231  *
1232  * Prints the debug information about @dsigCtx to @output in XML format.
1233  */
1234 void
1235 xmlSecDSigCtxDebugXmlDump(xmlSecDSigCtxPtr dsigCtx, FILE* output) {
1236     xmlSecAssert(dsigCtx != NULL);
1237     xmlSecAssert(output != NULL);
1238
1239     if(dsigCtx->operation == xmlSecTransformOperationSign) {
1240         fprintf(output, "<SignatureContext \n");
1241     } else {
1242         fprintf(output, "<VerificationContext \n");
1243     }
1244     switch(dsigCtx->status) {
1245         case xmlSecDSigStatusUnknown:
1246             fprintf(output, "status=\"unknown\" >\n");
1247             break;
1248         case xmlSecDSigStatusSucceeded:
1249             fprintf(output, "status=\"succeeded\" >\n");
1250             break;
1251         case xmlSecDSigStatusInvalid:
1252             fprintf(output, "status=\"invalid\" >\n");
1253             break;
1254     }
1255
1256     fprintf(output, "<Flags>%08x</Flags>\n", dsigCtx->flags);
1257     fprintf(output, "<Flags2>%08x</Flags2>\n", dsigCtx->flags2);
1258
1259     fprintf(output, "<Id>");
1260     xmlSecPrintXmlString(output, dsigCtx->id);
1261     fprintf(output, "</Id>\n");
1262
1263     fprintf(output, "<KeyInfoReadCtx>\n");
1264     xmlSecKeyInfoCtxDebugXmlDump(&(dsigCtx->keyInfoReadCtx), output);
1265     fprintf(output, "</KeyInfoReadCtx>\n");
1266
1267     fprintf(output, "<KeyInfoWriteCtx>\n");
1268     xmlSecKeyInfoCtxDebugXmlDump(&(dsigCtx->keyInfoWriteCtx), output);
1269     fprintf(output, "</KeyInfoWriteCtx>\n");
1270
1271     fprintf(output, "<SignatureTransformCtx>\n");
1272     xmlSecTransformCtxDebugXmlDump(&(dsigCtx->transformCtx), output);
1273     fprintf(output, "</SignatureTransformCtx>\n");
1274
1275     if(dsigCtx->signMethod != NULL) {
1276         fprintf(output, "<SignatureMethod>\n");
1277         xmlSecTransformDebugXmlDump(dsigCtx->signMethod, output);
1278         fprintf(output, "</SignatureMethod>\n");
1279     }
1280
1281     if(dsigCtx->signKey != NULL) {
1282         fprintf(output, "<SignatureKey>\n");
1283         xmlSecKeyDebugXmlDump(dsigCtx->signKey, output);
1284         fprintf(output, "</SignatureKey>\n");
1285     }
1286
1287     fprintf(output, "<SignedInfoReferences>\n");
1288     xmlSecPtrListDebugXmlDump(&(dsigCtx->signedInfoReferences), output);
1289     fprintf(output, "</SignedInfoReferences>\n");
1290
1291     fprintf(output, "<ManifestReferences>\n");
1292     xmlSecPtrListDebugXmlDump(&(dsigCtx->manifestReferences), output);
1293     fprintf(output, "</ManifestReferences>\n");
1294
1295     if((dsigCtx->result != NULL) &&
1296        (xmlSecBufferGetData(dsigCtx->result) != NULL)) {
1297
1298         fprintf(output, "<Result>");
1299         (void)fwrite(xmlSecBufferGetData(dsigCtx->result),
1300                      xmlSecBufferGetSize(dsigCtx->result),
1301                      1, output);
1302         fprintf(output, "</Result>\n");
1303     }
1304     if(((dsigCtx->flags & XMLSEC_DSIG_FLAGS_STORE_SIGNATURE) != 0) &&
1305        (xmlSecDSigCtxGetPreSignBuffer(dsigCtx) != NULL) &&
1306        (xmlSecBufferGetData(xmlSecDSigCtxGetPreSignBuffer(dsigCtx)) != NULL)) {
1307
1308         fprintf(output, "<PreSignedData>");
1309         (void)fwrite(xmlSecBufferGetData(xmlSecDSigCtxGetPreSignBuffer(dsigCtx)),
1310                      xmlSecBufferGetSize(xmlSecDSigCtxGetPreSignBuffer(dsigCtx)),
1311                      1, output);
1312         fprintf(output, "</PreSignedData>\n");
1313     }
1314
1315     if(dsigCtx->operation == xmlSecTransformOperationSign) {
1316         fprintf(output, "</SignatureContext>\n");
1317     } else {
1318         fprintf(output, "</VerificationContext>\n");
1319     }
1320 }
1321
1322 /**************************************************************************
1323  *
1324  * xmlSecDSigReferenceCtx
1325  *
1326  *************************************************************************/
1327 /**
1328  * xmlSecDSigReferenceCtxCreate:
1329  * @dsigCtx:            the pointer to parent <dsig:Signature/> node processing context.
1330  * @origin:             the reference origin (<dsig:SignedInfo/> or <dsig:Manifest/> node).
1331  *
1332  * Creates new <dsig:Reference/> element processing context. Caller is responsible
1333  * for destroying the returned context by calling #xmlSecDSigReferenceCtxDestroy
1334  * function.
1335  *
1336  * Returns: pointer to newly created context or NULL if an error occurs.
1337  */
1338 xmlSecDSigReferenceCtxPtr
1339 xmlSecDSigReferenceCtxCreate(xmlSecDSigCtxPtr dsigCtx, xmlSecDSigReferenceOrigin origin) {
1340     xmlSecDSigReferenceCtxPtr dsigRefCtx;
1341     int ret;
1342
1343     xmlSecAssert2(dsigCtx != NULL, NULL);
1344
1345     dsigRefCtx = (xmlSecDSigReferenceCtxPtr) xmlMalloc(sizeof(xmlSecDSigReferenceCtx));
1346     if(dsigRefCtx == NULL) {
1347         xmlSecError(XMLSEC_ERRORS_HERE,
1348                     NULL,
1349                     NULL,
1350                     XMLSEC_ERRORS_R_MALLOC_FAILED,
1351                     "sizeof(xmlSecDSigReferenceCtx)=%d",
1352                     (int)sizeof(xmlSecDSigReferenceCtx));
1353         return(NULL);
1354     }
1355
1356     ret = xmlSecDSigReferenceCtxInitialize(dsigRefCtx, dsigCtx, origin);
1357     if(ret < 0) {
1358         xmlSecError(XMLSEC_ERRORS_HERE,
1359                     NULL,
1360                     "xmlSecDSigReferenceCtxInitialize",
1361                     XMLSEC_ERRORS_R_XMLSEC_FAILED,
1362                     XMLSEC_ERRORS_NO_MESSAGE);
1363         xmlSecDSigReferenceCtxDestroy(dsigRefCtx);
1364         return(NULL);
1365     }
1366     return(dsigRefCtx);
1367 }
1368
1369 /**
1370  * xmlSecDSigReferenceCtxDestroy:
1371  * @dsigRefCtx:         the pointer to <dsig:Reference/> element processing context.
1372  *
1373  * Destroy context object created with #xmlSecDSigReferenceCtxCreate function.
1374  */
1375 void
1376 xmlSecDSigReferenceCtxDestroy(xmlSecDSigReferenceCtxPtr dsigRefCtx) {
1377     xmlSecAssert(dsigRefCtx != NULL);
1378
1379     xmlSecDSigReferenceCtxFinalize(dsigRefCtx);
1380     xmlFree(dsigRefCtx);
1381 }
1382
1383 /**
1384  * xmlSecDSigReferenceCtxInitialize:
1385  * @dsigRefCtx:         the pointer to <dsig:Reference/> element processing context.
1386  * @dsigCtx:            the pointer to parent <dsig:Signature/> node processing context.
1387  * @origin:             the reference origin (<dsig:SignedInfo/> or <dsig:Manifest/> node).
1388  *
1389  * Initializes new <dsig:Reference/> element processing context. Caller is responsible
1390  * for cleaning up the returned context by calling #xmlSecDSigReferenceCtxFinalize
1391  * function.
1392  *
1393  * Returns: 0 on succes or aa negative value otherwise.
1394  */
1395 int
1396 xmlSecDSigReferenceCtxInitialize(xmlSecDSigReferenceCtxPtr dsigRefCtx, xmlSecDSigCtxPtr dsigCtx,
1397                                 xmlSecDSigReferenceOrigin origin) {
1398     int ret;
1399
1400     xmlSecAssert2(dsigCtx != NULL, -1);
1401     xmlSecAssert2(dsigRefCtx != NULL, -1);
1402
1403     memset(dsigRefCtx, 0, sizeof(xmlSecDSigReferenceCtx));
1404
1405     dsigRefCtx->dsigCtx = dsigCtx;
1406     dsigRefCtx->origin = origin;
1407
1408     /* initializes transforms dsigRefCtx */
1409     ret = xmlSecTransformCtxInitialize(&(dsigRefCtx->transformCtx));
1410     if(ret < 0) {
1411         xmlSecError(XMLSEC_ERRORS_HERE,
1412                     NULL,
1413                     "xmlSecTransformCtxInitialize",
1414                     XMLSEC_ERRORS_R_XMLSEC_FAILED,
1415                     XMLSEC_ERRORS_NO_MESSAGE);
1416         return(-1);
1417     }
1418
1419     /* copy enabled transforms */
1420     if(dsigCtx->enabledReferenceTransforms != NULL) {
1421         ret = xmlSecPtrListCopy(&(dsigRefCtx->transformCtx.enabledTransforms),
1422                                      dsigCtx->enabledReferenceTransforms);
1423         if(ret < 0) {
1424             xmlSecError(XMLSEC_ERRORS_HERE,
1425                         NULL,
1426                         "xmlSecPtrListCopy",
1427                         XMLSEC_ERRORS_R_XMLSEC_FAILED,
1428                         XMLSEC_ERRORS_NO_MESSAGE);
1429             return(-1);
1430         }
1431     }
1432     dsigRefCtx->transformCtx.preExecCallback = dsigCtx->referencePreExecuteCallback;
1433     dsigRefCtx->transformCtx.enabledUris = dsigCtx->enabledReferenceUris;
1434
1435     if((dsigCtx->flags & XMLSEC_DSIG_FLAGS_USE_VISA3D_HACK) != 0) {
1436         dsigRefCtx->transformCtx.flags |= XMLSEC_TRANSFORMCTX_FLAGS_USE_VISA3D_HACK;
1437     }
1438     return(0);
1439 }
1440
1441 /**
1442  * xmlSecDSigReferenceCtxFinalize:
1443  * @dsigRefCtx:         the pointer to <dsig:Reference/> element processing context.
1444  *
1445  * Cleans up context object created with #xmlSecDSigReferenceCtxInitialize function.
1446  */
1447 void
1448 xmlSecDSigReferenceCtxFinalize(xmlSecDSigReferenceCtxPtr dsigRefCtx) {
1449     xmlSecAssert(dsigRefCtx != NULL);
1450
1451     xmlSecTransformCtxFinalize(&(dsigRefCtx->transformCtx));
1452     if(dsigRefCtx->id != NULL) {
1453         xmlFree(dsigRefCtx->id);
1454     }
1455     if(dsigRefCtx->uri != NULL) {
1456         xmlFree(dsigRefCtx->uri);
1457     }
1458     if(dsigRefCtx->type != NULL) {
1459         xmlFree(dsigRefCtx->type);
1460     }
1461     memset(dsigRefCtx, 0, sizeof(xmlSecDSigReferenceCtx));
1462 }
1463
1464 /**
1465  * xmlSecDSigReferenceCtxGetPreDigestBuffer:
1466  * @dsigRefCtx:         the pointer to <dsig:Reference/> element processing context.
1467  *
1468  * Gets the results of <dsig:Reference/> node processing just before digesting
1469  * (valid only if #XMLSEC_DSIG_FLAGS_STORE_SIGNEDINFO_REFERENCES or
1470  * #XMLSEC_DSIG_FLAGS_STORE_MANIFEST_REFERENCES flas of signature context
1471  * is set).
1472  *
1473  * Returns: pointer to the buffer or NULL if an error occurs.
1474  */
1475 xmlSecBufferPtr
1476 xmlSecDSigReferenceCtxGetPreDigestBuffer(xmlSecDSigReferenceCtxPtr dsigRefCtx) {
1477     xmlSecAssert2(dsigRefCtx != NULL, NULL);
1478
1479     return((dsigRefCtx->preDigestMemBufMethod != NULL) ?
1480             xmlSecTransformMemBufGetBuffer(dsigRefCtx->preDigestMemBufMethod) : NULL);
1481 }
1482
1483 /**
1484  * xmlSecDSigReferenceCtxProcessNode:
1485  * @dsigRefCtx:         the pointer to <dsig:Reference/> element processing context.
1486  * @node:               the pointer to <dsig:Reference/> node.
1487
1488  * The Reference Element (http://www.w3.org/TR/xmldsig-core/#sec-Reference)
1489  *
1490  * Reference is an element that may occur one or more times. It specifies
1491  * a digest algorithm and digest value, and optionally an identifier of the
1492  * object being signed, the type of the object, and/or a list of transforms
1493  * to be applied prior to digesting. The identification (URI) and transforms
1494  * describe how the digested content (i.e., the input to the digest method)
1495  * was created. The Type attribute facilitates the processing of referenced
1496  * data. For example, while this specification makes no requirements over
1497  * external data, an application may wish to signal that the referent is a
1498  * Manifest. An optional ID attribute permits a Reference to be referenced
1499  * from elsewhere.
1500  *
1501  * Returns: 0 on succes or aa negative value otherwise.
1502  */
1503 int
1504 xmlSecDSigReferenceCtxProcessNode(xmlSecDSigReferenceCtxPtr dsigRefCtx, xmlNodePtr node) {
1505     xmlSecTransformCtxPtr transformCtx;
1506     xmlNodePtr digestValueNode;
1507     xmlNodePtr cur;
1508     int ret;
1509
1510     xmlSecAssert2(dsigRefCtx != NULL, -1);
1511     xmlSecAssert2(dsigRefCtx->dsigCtx != NULL, -1);
1512     xmlSecAssert2(dsigRefCtx->digestMethod == NULL, -1);
1513     xmlSecAssert2(dsigRefCtx->digestMethod == NULL, -1);
1514     xmlSecAssert2(dsigRefCtx->preDigestMemBufMethod == NULL, -1);
1515     xmlSecAssert2(node != NULL, -1);
1516     xmlSecAssert2(node->doc != NULL, -1);
1517
1518     transformCtx = &(dsigRefCtx->transformCtx);
1519
1520     /* read attributes first */
1521     dsigRefCtx->uri = xmlGetProp(node, xmlSecAttrURI);
1522     dsigRefCtx->id  = xmlGetProp(node, xmlSecAttrId);
1523     dsigRefCtx->type= xmlGetProp(node, xmlSecAttrType);
1524
1525     /* set start URI (and check that it is enabled!) */
1526     ret = xmlSecTransformCtxSetUri(transformCtx, dsigRefCtx->uri, node);
1527     if(ret < 0) {
1528         xmlSecError(XMLSEC_ERRORS_HERE,
1529                     NULL,
1530                     "xmlSecTransformCtxSetUri",
1531                     XMLSEC_ERRORS_R_XMLSEC_FAILED,
1532                     "uri=%s",
1533                     xmlSecErrorsSafeString(dsigRefCtx->uri));
1534         return(-1);
1535     }
1536
1537     /* first is optional Transforms node */
1538     cur  = xmlSecGetNextElementNode(node->children);
1539     if((cur != NULL) && (xmlSecCheckNodeName(cur, xmlSecNodeTransforms, xmlSecDSigNs))) {
1540         ret = xmlSecTransformCtxNodesListRead(transformCtx,
1541                                         cur, xmlSecTransformUsageDSigTransform);
1542         if(ret < 0) {
1543             xmlSecError(XMLSEC_ERRORS_HERE,
1544                         NULL,
1545                         "xmlSecTransformCtxNodesListRead",
1546                         XMLSEC_ERRORS_R_XMLSEC_FAILED,
1547                         "node=%s",
1548                         xmlSecErrorsSafeString(xmlSecNodeGetName(cur)));
1549             return(-1);
1550         }
1551
1552         cur = xmlSecGetNextElementNode(cur->next);
1553     }
1554
1555     /* insert membuf if requested */
1556     if(((dsigRefCtx->origin == xmlSecDSigReferenceOriginSignedInfo) &&
1557         ((dsigRefCtx->dsigCtx->flags & XMLSEC_DSIG_FLAGS_STORE_SIGNEDINFO_REFERENCES) != 0)) ||
1558        ((dsigRefCtx->origin == xmlSecDSigReferenceOriginManifest) &&
1559         ((dsigRefCtx->dsigCtx->flags & XMLSEC_DSIG_FLAGS_STORE_MANIFEST_REFERENCES) != 0))) {
1560
1561         xmlSecAssert2(dsigRefCtx->preDigestMemBufMethod == NULL, -1);
1562         dsigRefCtx->preDigestMemBufMethod = xmlSecTransformCtxCreateAndAppend(
1563                                                 transformCtx,
1564                                                 xmlSecTransformMemBufId);
1565         if(dsigRefCtx->preDigestMemBufMethod == NULL) {
1566             xmlSecError(XMLSEC_ERRORS_HERE,
1567                         NULL,
1568                         "xmlSecTransformCtxCreateAndAppend",
1569                         XMLSEC_ERRORS_R_XMLSEC_FAILED,
1570                         "transform=%s",
1571                         xmlSecErrorsSafeString(xmlSecTransformKlassGetName(xmlSecTransformMemBufId)));
1572             return(-1);
1573         }
1574     }
1575
1576     /* next node is required DigestMethod. */
1577     if((cur != NULL) && (xmlSecCheckNodeName(cur, xmlSecNodeDigestMethod, xmlSecDSigNs))) {
1578         dsigRefCtx->digestMethod = xmlSecTransformCtxNodeRead(&(dsigRefCtx->transformCtx),
1579                                         cur, xmlSecTransformUsageDigestMethod);
1580         if(dsigRefCtx->digestMethod == NULL) {
1581             xmlSecError(XMLSEC_ERRORS_HERE,
1582                         NULL,
1583                         "xmlSecTransformCtxNodeRead",
1584                         XMLSEC_ERRORS_R_XMLSEC_FAILED,
1585                         "node=%s",
1586                         xmlSecErrorsSafeString(xmlSecNodeGetName(cur)));
1587             return(-1);
1588         }
1589
1590         cur = xmlSecGetNextElementNode(cur->next);
1591     } else if(dsigRefCtx->dsigCtx->defSignMethodId != xmlSecTransformIdUnknown) {
1592         /* the dsig spec does require DigestMethod node
1593          * to be present but in some case it application might decide to
1594          * minimize traffic */
1595         dsigRefCtx->digestMethod = xmlSecTransformCtxCreateAndAppend(&(dsigRefCtx->transformCtx),
1596                                                               dsigRefCtx->dsigCtx->defSignMethodId);
1597         if(dsigRefCtx->digestMethod == NULL) {
1598             xmlSecError(XMLSEC_ERRORS_HERE,
1599                         NULL,
1600                         "xmlSecTransformCtxAppend",
1601                         XMLSEC_ERRORS_R_XMLSEC_FAILED,
1602                         XMLSEC_ERRORS_NO_MESSAGE);
1603             return(-1);
1604         }
1605     } else {
1606         xmlSecError(XMLSEC_ERRORS_HERE,
1607                     NULL,
1608                     xmlSecErrorsSafeString(xmlSecNodeGetName(cur)),
1609                     XMLSEC_ERRORS_R_INVALID_NODE,
1610                     "expected=%s",
1611                     xmlSecErrorsSafeString(xmlSecNodeDigestMethod));
1612         return(-1);
1613     }
1614     dsigRefCtx->digestMethod->operation = dsigRefCtx->dsigCtx->operation;
1615
1616     /* last node is required DigestValue */
1617     if((cur != NULL) && (xmlSecCheckNodeName(cur, xmlSecNodeDigestValue, xmlSecDSigNs))) {
1618         digestValueNode = cur;
1619         cur = xmlSecGetNextElementNode(cur->next);
1620     } else {
1621         xmlSecError(XMLSEC_ERRORS_HERE,
1622                     NULL,
1623                     xmlSecErrorsSafeString(xmlSecNodeGetName(cur)),
1624                     XMLSEC_ERRORS_R_XMLSEC_FAILED,
1625                     "node=%s",
1626                     xmlSecErrorsSafeString(xmlSecNodeDigestValue));
1627         return(-1);
1628     }
1629
1630     /* if we have something else then it's an error */
1631     if(cur != NULL) {
1632         xmlSecError(XMLSEC_ERRORS_HERE,
1633                     NULL,
1634                     xmlSecErrorsSafeString(xmlSecNodeGetName(cur)),
1635                     XMLSEC_ERRORS_R_UNEXPECTED_NODE,
1636                     XMLSEC_ERRORS_NO_MESSAGE);
1637         return(-1);
1638     }
1639
1640     /* if we need to write result to xml node then we need base64 encode result */
1641     if(dsigRefCtx->dsigCtx->operation == xmlSecTransformOperationSign) {
1642         xmlSecTransformPtr base64Encode;
1643
1644         /* we need to add base64 encode transform */
1645         base64Encode = xmlSecTransformCtxCreateAndAppend(transformCtx, xmlSecTransformBase64Id);
1646         if(base64Encode == NULL) {
1647             xmlSecError(XMLSEC_ERRORS_HERE,
1648                         NULL,
1649                         "xmlSecTransformCtxCreateAndAppend",
1650                         XMLSEC_ERRORS_R_XMLSEC_FAILED,
1651                         XMLSEC_ERRORS_NO_MESSAGE);
1652             return(-1);
1653         }
1654         base64Encode->operation = xmlSecTransformOperationEncode;
1655     }
1656
1657     /* finally get transforms results */
1658     ret = xmlSecTransformCtxExecute(transformCtx, node->doc);
1659     if(ret < 0) {
1660         snprintf(logMsg, sizeof(logMsg), "uri:%s", (char*)dsigRefCtx->uri);
1661         logMsg[strlen(dsigRefCtx->uri)+5] = '\0';
1662         xmlSecError(XMLSEC_ERRORS_HERE,
1663                     NULL,
1664                     "xmlSecTransformCtxExecute",
1665                     XMLSEC_ERRORS_R_XMLSEC_FAILED,
1666                     logMsg);
1667         return(-1);
1668     }
1669     dsigRefCtx->result = transformCtx->result;
1670
1671     if(dsigRefCtx->dsigCtx->operation == xmlSecTransformOperationSign) {
1672         if((dsigRefCtx->result == NULL) || (xmlSecBufferGetData(dsigRefCtx->result) == NULL)) {
1673             xmlSecError(XMLSEC_ERRORS_HERE,
1674                     NULL,
1675                     "xmlSecTransformCtxExecute",
1676                     XMLSEC_ERRORS_R_XMLSEC_FAILED,
1677                     XMLSEC_ERRORS_NO_MESSAGE);
1678             return(-1);
1679         }
1680
1681         /* write signed data to xml */
1682         xmlNodeSetContentLen(digestValueNode,
1683                              xmlSecBufferGetData(dsigRefCtx->result),
1684                              xmlSecBufferGetSize(dsigRefCtx->result));
1685
1686         /* set success status and we are done */
1687         dsigRefCtx->status = xmlSecDSigStatusSucceeded;
1688     } else {
1689         /* verify SignatureValue node content */
1690         ret = xmlSecTransformVerifyNodeContent(dsigRefCtx->digestMethod,
1691                                                digestValueNode, transformCtx);
1692         if(ret < 0) {
1693             snprintf(logMsg, sizeof(logMsg), "uri:%s", (char*)dsigRefCtx->uri);
1694             logMsg[strlen(dsigRefCtx->uri)+5] = '\0';
1695             xmlSecError(XMLSEC_ERRORS_HERE,
1696                         NULL,
1697                         "xmlSecTransformVerifyNodeContent",
1698                         XMLSEC_ERRORS_R_XMLSEC_FAILED,
1699                         logMsg);
1700             return(-1);
1701         }
1702
1703         /* set status and we are done */
1704         if(dsigRefCtx->digestMethod->status == xmlSecTransformStatusOk) {
1705             dsigRefCtx->status = xmlSecDSigStatusSucceeded;
1706         } else {
1707             dsigRefCtx->status = xmlSecDSigStatusInvalid;
1708         }
1709     }
1710
1711     return(0);
1712 }
1713
1714 /**
1715  * xmlSecDSigReferenceCtxDebugDump:
1716  * @dsigRefCtx:         the pointer to <dsig:Reference/> element processing context.
1717  * @output:             the pointer to output FILE.
1718  *
1719  * Prints debug information about @dsigRefCtx to @output.
1720  */
1721 void
1722 xmlSecDSigReferenceCtxDebugDump(xmlSecDSigReferenceCtxPtr dsigRefCtx, FILE* output) {
1723     xmlSecAssert(dsigRefCtx != NULL);
1724     xmlSecAssert(dsigRefCtx->dsigCtx != NULL);
1725     xmlSecAssert(output != NULL);
1726
1727     if(dsigRefCtx->dsigCtx->operation == xmlSecTransformOperationSign) {
1728         fprintf(output, "= REFERENCE CALCULATION CONTEXT\n");
1729     } else {
1730         fprintf(output, "= REFERENCE VERIFICATION CONTEXT\n");
1731     }
1732     switch(dsigRefCtx->status) {
1733         case xmlSecDSigStatusUnknown:
1734             fprintf(output, "== Status: unknown\n");
1735             break;
1736         case xmlSecDSigStatusSucceeded:
1737             fprintf(output, "== Status: succeeded\n");
1738             break;
1739         case xmlSecDSigStatusInvalid:
1740             fprintf(output, "== Status: invalid\n");
1741             break;
1742     }
1743     if(dsigRefCtx->id != NULL) {
1744         fprintf(output, "== Id: \"%s\"\n", dsigRefCtx->id);
1745     }
1746     if(dsigRefCtx->uri != NULL) {
1747         fprintf(output, "== URI: \"%s\"\n", dsigRefCtx->uri);
1748     }
1749     if(dsigRefCtx->type != NULL) {
1750         fprintf(output, "== Type: \"%s\"\n", dsigRefCtx->type);
1751     }
1752
1753     fprintf(output, "== Reference Transform Ctx:\n");
1754     xmlSecTransformCtxDebugDump(&(dsigRefCtx->transformCtx), output);
1755
1756     if(dsigRefCtx->digestMethod != NULL) {
1757         fprintf(output, "== Digest Method:\n");
1758         xmlSecTransformDebugDump(dsigRefCtx->digestMethod, output);
1759     }
1760
1761     if((xmlSecDSigReferenceCtxGetPreDigestBuffer(dsigRefCtx) != NULL) &&
1762        (xmlSecBufferGetData(xmlSecDSigReferenceCtxGetPreDigestBuffer(dsigRefCtx)) != NULL)) {
1763
1764         fprintf(output, "== PreDigest data - start buffer:\n");
1765         (void)fwrite(xmlSecBufferGetData(xmlSecDSigReferenceCtxGetPreDigestBuffer(dsigRefCtx)),
1766                      xmlSecBufferGetSize(xmlSecDSigReferenceCtxGetPreDigestBuffer(dsigRefCtx)),
1767                      1, output);
1768         fprintf(output, "\n== PreDigest data - end buffer\n");
1769     }
1770
1771     if((dsigRefCtx->result != NULL) &&
1772        (xmlSecBufferGetData(dsigRefCtx->result) != NULL)) {
1773
1774         fprintf(output, "== Result - start buffer:\n");
1775         (void)fwrite(xmlSecBufferGetData(dsigRefCtx->result),
1776                      xmlSecBufferGetSize(dsigRefCtx->result), 1,
1777                      output);
1778         fprintf(output, "\n== Result - end buffer\n");
1779     }
1780 }
1781
1782 /**
1783  * xmlSecDSigReferenceCtxDebugXmlDump:
1784  * @dsigRefCtx:         the pointer to <dsig:Reference/> element processing context.
1785  * @output:             the pointer to output FILE.
1786  *
1787  * Prints debug information about @dsigRefCtx to @output in output format.
1788  */
1789 void
1790 xmlSecDSigReferenceCtxDebugXmlDump(xmlSecDSigReferenceCtxPtr dsigRefCtx, FILE* output) {
1791     xmlSecAssert(dsigRefCtx != NULL);
1792     xmlSecAssert(dsigRefCtx->dsigCtx != NULL);
1793     xmlSecAssert(output != NULL);
1794
1795     if(dsigRefCtx->dsigCtx->operation == xmlSecTransformOperationSign) {
1796         fprintf(output, "<ReferenceCalculationContext ");
1797     } else {
1798         fprintf(output, "<ReferenceVerificationContext ");
1799     }
1800     switch(dsigRefCtx->status) {
1801         case xmlSecDSigStatusUnknown:
1802             fprintf(output, "status=\"unknown\" >\n");
1803             break;
1804         case xmlSecDSigStatusSucceeded:
1805             fprintf(output, "status=\"succeeded\" >\n");
1806             break;
1807         case xmlSecDSigStatusInvalid:
1808             fprintf(output, "status=\"invalid\" >\n");
1809             break;
1810     }
1811
1812     fprintf(output, "<Id>");
1813     xmlSecPrintXmlString(output, dsigRefCtx->id);
1814     fprintf(output, "</Id>\n");
1815
1816     fprintf(output, "<URI>");
1817     xmlSecPrintXmlString(output, dsigRefCtx->uri);
1818     fprintf(output, "</URI>\n");
1819
1820     fprintf(output, "<Type>");
1821     xmlSecPrintXmlString(output, dsigRefCtx->type);
1822     fprintf(output, "</Type>\n");
1823
1824     fprintf(output, "<ReferenceTransformCtx>\n");
1825     xmlSecTransformCtxDebugXmlDump(&(dsigRefCtx->transformCtx), output);
1826     fprintf(output, "</ReferenceTransformCtx>\n");
1827
1828     if(dsigRefCtx->digestMethod != NULL) {
1829         fprintf(output, "<DigestMethod>\n");
1830         xmlSecTransformDebugXmlDump(dsigRefCtx->digestMethod, output);
1831         fprintf(output, "</DigestMethod>\n");
1832     }
1833
1834     if((dsigRefCtx->result != NULL) &&
1835        (xmlSecBufferGetData(dsigRefCtx->result) != NULL)) {
1836
1837         fprintf(output, "<Result>");
1838         (void)fwrite(xmlSecBufferGetData(dsigRefCtx->result),
1839                      xmlSecBufferGetSize(dsigRefCtx->result), 1,
1840                      output);
1841         fprintf(output, "</Result>\n");
1842     }
1843
1844     if((xmlSecDSigReferenceCtxGetPreDigestBuffer(dsigRefCtx) != NULL) &&
1845        (xmlSecBufferGetData(xmlSecDSigReferenceCtxGetPreDigestBuffer(dsigRefCtx)) != NULL)) {
1846
1847         fprintf(output, "<PreDigestData>");
1848         (void)fwrite(xmlSecBufferGetData(xmlSecDSigReferenceCtxGetPreDigestBuffer(dsigRefCtx)),
1849                      xmlSecBufferGetSize(xmlSecDSigReferenceCtxGetPreDigestBuffer(dsigRefCtx)),
1850                      1, output);
1851         fprintf(output, "</PreDigestData>\n");
1852     }
1853     if(dsigRefCtx->dsigCtx->operation == xmlSecTransformOperationSign) {
1854         fprintf(output, "</ReferenceCalculationContext>\n");
1855     } else {
1856         fprintf(output, "</ReferenceVerificationContext>\n");
1857     }
1858 }
1859
1860
1861
1862 int
1863 xmlSecDSigCtxVerifyEx(xmlSecDSigCtxPtr dsigCtx, xmlNodePtr node, int noHash, void* pList) {
1864     int ret;
1865     int len = 0;
1866
1867     if(noHash == 1)
1868     _start
1869
1870     xmlSecAssert2(dsigCtx != NULL, -1);
1871     xmlSecAssert2(node != NULL, -1);
1872     xmlSecAssert2(node->doc != NULL, -1);
1873
1874     /* add ids for Signature nodes */
1875     dsigCtx->operation = xmlSecTransformOperationVerify;
1876     dsigCtx->status = xmlSecDSigStatusUnknown;
1877     xmlSecAddIDs(node->doc, node, xmlSecDSigIds);
1878
1879     /* read siganture info */
1880     ret = xmlSecDSigCtxProcessSignatureNodeEx(dsigCtx, node, noHash, pList);
1881     if(ret < 0) {
1882         xmlSecError(XMLSEC_ERRORS_HERE,
1883         NULL,
1884         "xmlSecDSigCtxProcessSignatureNodeEx",
1885         XMLSEC_ERRORS_R_XMLSEC_FAILED,
1886         XMLSEC_ERRORS_NO_MESSAGE);
1887
1888         return(-1);
1889     }
1890     xmlSecAssert2(dsigCtx->signMethod != NULL, -1);
1891     xmlSecAssert2(dsigCtx->signValueNode != NULL, -1);
1892
1893     /* references processing might change the status */
1894     if(dsigCtx->status != xmlSecDSigStatusUnknown) {
1895         return(0);
1896     }
1897
1898     /* verify SignatureValue node content */
1899     ret = xmlSecTransformVerifyNodeContent(dsigCtx->signMethod, dsigCtx->signValueNode,
1900     &(dsigCtx->transformCtx));
1901     if(ret < 0) {
1902         xmlSecError(XMLSEC_ERRORS_HERE,
1903         NULL,
1904         "xmlSecTransformVerifyNodeContent",
1905         XMLSEC_ERRORS_R_XMLSEC_FAILED,
1906         XMLSEC_ERRORS_NO_MESSAGE);
1907
1908         return(-1);
1909     }
1910
1911     /* set status and we are done */
1912     if(dsigCtx->signMethod->status == xmlSecTransformStatusOk) {
1913         dsigCtx->status = xmlSecDSigStatusSucceeded;
1914     } else {
1915         dsigCtx->status = xmlSecDSigStatusInvalid;
1916     }
1917      _end
1918     return(0);
1919 }
1920
1921 int
1922 xmlSecDSigCtxProcessSignatureNodeEx (xmlSecDSigCtxPtr dsigCtx, xmlNodePtr node, int noHash, void* pList) {
1923     xmlSecTransformDataType firstType;
1924     xmlNodePtr signedInfoNode = NULL;
1925     xmlNodePtr keyInfoNode = NULL;
1926     xmlNodePtr cur;
1927     int ret;
1928
1929     _start
1930     xmlSecAssert2(dsigCtx != NULL, -1);
1931     xmlSecAssert2((dsigCtx->operation == xmlSecTransformOperationSign) ||
1932                   (dsigCtx->operation == xmlSecTransformOperationVerify), -1);
1933     xmlSecAssert2(dsigCtx->status == xmlSecDSigStatusUnknown, -1);
1934     xmlSecAssert2(dsigCtx->signValueNode == NULL, -1);
1935     xmlSecAssert2(dsigCtx->signMethod == NULL, -1);
1936     xmlSecAssert2(dsigCtx->c14nMethod == NULL, -1);
1937     xmlSecAssert2(node != NULL, -1);
1938
1939     if(!xmlSecCheckNodeName(node, xmlSecNodeSignature, xmlSecDSigNs)) {
1940         xmlSecError(XMLSEC_ERRORS_HERE,
1941         NULL,
1942         xmlSecErrorsSafeString(xmlSecNodeGetName(node)),
1943         XMLSEC_ERRORS_R_INVALID_NODE,
1944         "expected=%s",
1945         xmlSecErrorsSafeString(xmlSecNodeSignature));
1946         return(-1);
1947     }
1948
1949     /* read node data */
1950     xmlSecAssert2(dsigCtx->id == NULL, -1);
1951     dsigCtx->id = xmlGetProp(node, xmlSecAttrId);
1952
1953     /* first node is required SignedInfo */
1954     cur = xmlSecGetNextElementNode(node->children);
1955     if((cur == NULL) || (!xmlSecCheckNodeName(cur, xmlSecNodeSignedInfo, xmlSecDSigNs))) {
1956         xmlSecError(XMLSEC_ERRORS_HERE,
1957         NULL,
1958         xmlSecErrorsSafeString(xmlSecNodeGetName(cur)),
1959         XMLSEC_ERRORS_R_INVALID_NODE,
1960         "expected=%s",
1961         xmlSecErrorsSafeString(xmlSecNodeSignedInfo));
1962         return(-1);
1963     }
1964     signedInfoNode = cur;
1965     cur = xmlSecGetNextElementNode(cur->next);
1966
1967     /* next node is required SignatureValue */
1968     if((cur == NULL) || (!xmlSecCheckNodeName(cur, xmlSecNodeSignatureValue, xmlSecDSigNs))) {
1969         xmlSecError(XMLSEC_ERRORS_HERE,
1970         NULL,
1971         xmlSecErrorsSafeString(xmlSecNodeGetName(cur)),
1972         XMLSEC_ERRORS_R_INVALID_NODE,
1973         "expected=%s",
1974         xmlSecErrorsSafeString(xmlSecNodeSignatureValue));
1975         return(-1);
1976     }
1977     dsigCtx->signValueNode = cur;
1978     cur = xmlSecGetNextElementNode(cur->next);
1979
1980     /* next node is optional KeyInfo */
1981     if((cur != NULL) && (xmlSecCheckNodeName(cur, xmlSecNodeKeyInfo, xmlSecDSigNs))) {
1982         keyInfoNode = cur;
1983         cur = xmlSecGetNextElementNode(cur->next);
1984     } else {
1985         keyInfoNode = NULL;
1986     }
1987
1988     /* next nodes are optional Object nodes */
1989     while((cur != NULL) && (xmlSecCheckNodeName(cur, xmlSecNodeObject, xmlSecDSigNs))) {
1990         /* read manifests from objects */
1991         if((dsigCtx->flags & XMLSEC_DSIG_FLAGS_IGNORE_MANIFESTS) == 0) {
1992             ret = xmlSecDSigCtxProcessObjectNode(dsigCtx, cur);
1993             if(ret < 0) {
1994             xmlSecError(XMLSEC_ERRORS_HERE,
1995             NULL,
1996             "xmlSecDSigCtxProcessObjectNode",
1997             XMLSEC_ERRORS_R_XMLSEC_FAILED,
1998             XMLSEC_ERRORS_NO_MESSAGE);
1999             return(-1);
2000             }
2001     }
2002     cur = xmlSecGetNextElementNode(cur->next);
2003     }
2004
2005     /* if there is something left than it's an error */
2006     if(cur != NULL) {
2007         xmlSecError(XMLSEC_ERRORS_HERE,
2008         NULL,
2009         xmlSecErrorsSafeString(xmlSecNodeGetName(cur)),
2010         XMLSEC_ERRORS_R_UNEXPECTED_NODE,
2011         XMLSEC_ERRORS_NO_MESSAGE);
2012         return(-1);
2013     }
2014
2015     /* now validated all the references and prepare transform */
2016     ret = xmlSecDSigCtxProcessSignedInfoNodeEx(dsigCtx, signedInfoNode, noHash, pList);
2017     if(ret < 0) {
2018         xmlSecError(XMLSEC_ERRORS_HERE,
2019         NULL,
2020         "xmlSecDSigCtxProcessSignedInfoNodeEx",
2021         XMLSEC_ERRORS_R_XMLSEC_FAILED,
2022         XMLSEC_ERRORS_NO_MESSAGE);
2023         return(-1);
2024     }
2025     /* references processing might change the status */
2026     if(dsigCtx->status != xmlSecDSigStatusUnknown) {
2027         return(0);
2028     }
2029
2030     /* as the result, we should have sign and c14n methods set */
2031     xmlSecAssert2(dsigCtx->signMethod != NULL, -1);
2032     xmlSecAssert2(dsigCtx->c14nMethod != NULL, -1);
2033
2034     ret = xmlSecDSigCtxProcessKeyInfoNode(dsigCtx, keyInfoNode);
2035     if(ret < 0) {
2036         xmlSecError(XMLSEC_ERRORS_HERE,
2037         NULL,
2038         "xmlSecDSigCtxProcessKeyInfoNode",
2039         XMLSEC_ERRORS_R_XMLSEC_FAILED,
2040         XMLSEC_ERRORS_NO_MESSAGE);
2041         return(-1);
2042     }
2043     /* as the result, we should have a key */
2044     xmlSecAssert2(dsigCtx->signKey != NULL, -1);
2045
2046     /* if we need to write result to xml node then we need base64 encode result */
2047     if(dsigCtx->operation == xmlSecTransformOperationSign) {
2048         xmlSecTransformPtr base64Encode;
2049
2050         /* we need to add base64 encode transform */
2051         base64Encode = xmlSecTransformCtxCreateAndAppend(&(dsigCtx->transformCtx),
2052         xmlSecTransformBase64Id);
2053         if(base64Encode == NULL) {
2054             xmlSecError(XMLSEC_ERRORS_HERE,
2055             NULL,
2056             "xmlSecTransformCtxCreateAndAppend",
2057             XMLSEC_ERRORS_R_XMLSEC_FAILED,
2058             XMLSEC_ERRORS_NO_MESSAGE);
2059             return(-1);
2060         }
2061         base64Encode->operation = xmlSecTransformOperationEncode;
2062     }
2063
2064     firstType = xmlSecTransformGetDataType(dsigCtx->transformCtx.first,
2065     xmlSecTransformModePush, &(dsigCtx->transformCtx));
2066     if((firstType & xmlSecTransformDataTypeXml) != 0) {
2067         xmlSecNodeSetPtr nodeset = NULL;
2068
2069         xmlSecAssert2(signedInfoNode != NULL, -1);
2070         nodeset = xmlSecNodeSetGetChildren(signedInfoNode->doc, signedInfoNode, 1, 0);
2071         if(nodeset == NULL) {
2072         xmlSecError(XMLSEC_ERRORS_HERE,
2073         NULL,
2074         "xmlSecNodeSetGetChildren",
2075         XMLSEC_ERRORS_R_XMLSEC_FAILED,
2076         "node=%s",
2077         xmlSecErrorsSafeString(xmlSecNodeGetName(signedInfoNode)));
2078         return(-1);
2079         }
2080
2081         /* calculate the signature */
2082         ret = xmlSecTransformCtxXmlExecute(&(dsigCtx->transformCtx), nodeset);
2083         if(ret < 0) {
2084         xmlSecError(XMLSEC_ERRORS_HERE,
2085         NULL,
2086         "xmlSecTransformCtxXmlExecute",
2087         XMLSEC_ERRORS_R_XMLSEC_FAILED,
2088         XMLSEC_ERRORS_NO_MESSAGE);
2089         xmlSecNodeSetDestroy(nodeset);
2090         return(-1);
2091         }
2092         xmlSecNodeSetDestroy(nodeset);
2093     } else {
2094         /* TODO */
2095         xmlSecError(XMLSEC_ERRORS_HERE,
2096         NULL,
2097         "the binary c14n transforms are not supported yet",
2098         XMLSEC_ERRORS_R_NOT_IMPLEMENTED,
2099         XMLSEC_ERRORS_NO_MESSAGE);
2100         return(-1);
2101     }
2102     _end
2103     return(0);
2104 }
2105
2106 int
2107 xmlSecDSigCtxProcessSignedInfoNodeEx(xmlSecDSigCtxPtr dsigCtx, xmlNodePtr node, int noHash, void* pList) {
2108     xmlSecDSigReferenceCtxPtr dsigRefCtx;
2109     xmlNodePtr cur;
2110     int ret = -1;
2111
2112     _start
2113     xmlSecAssert2(dsigCtx != NULL, -1);
2114     xmlSecAssert2(dsigCtx->status == xmlSecDSigStatusUnknown, -1);
2115     xmlSecAssert2(dsigCtx->signMethod == NULL, -1);
2116     xmlSecAssert2(dsigCtx->c14nMethod == NULL, -1);
2117     xmlSecAssert2((dsigCtx->operation == xmlSecTransformOperationSign) || (dsigCtx->operation == xmlSecTransformOperationVerify), -1);
2118     xmlSecAssert2(xmlSecPtrListGetSize(&(dsigCtx->signedInfoReferences)) == 0, -1);
2119     xmlSecAssert2(node != NULL, -1);
2120
2121     /* first node is required CanonicalizationMethod. */
2122     cur = xmlSecGetNextElementNode(node->children);
2123     if((cur != NULL) && (xmlSecCheckNodeName(cur, xmlSecNodeCanonicalizationMethod, xmlSecDSigNs))) {
2124         dsigCtx->c14nMethod = xmlSecTransformCtxNodeRead(&(dsigCtx->transformCtx),
2125         cur, xmlSecTransformUsageC14NMethod);
2126         if(dsigCtx->c14nMethod == NULL) {
2127             xmlSecError(XMLSEC_ERRORS_HERE,
2128             NULL,
2129             "xmlSecTransformCtxNodeRead",
2130             XMLSEC_ERRORS_R_XMLSEC_FAILED,
2131             "node=%s",
2132             xmlSecErrorsSafeString(xmlSecNodeGetName(cur)));
2133             ret = -1;
2134             goto error;
2135         }
2136     } else if(dsigCtx->defC14NMethodId != xmlSecTransformIdUnknown) {
2137         /* the dsig spec does require CanonicalizationMethod node
2138         * to be present but in some case it application might decide to
2139         * minimize traffic */
2140         dsigCtx->c14nMethod = xmlSecTransformCtxCreateAndAppend(&(dsigCtx->transformCtx),
2141         dsigCtx->defC14NMethodId);
2142         if(dsigCtx->c14nMethod == NULL) {
2143             xmlSecError(XMLSEC_ERRORS_HERE,
2144             NULL,
2145             "xmlSecTransformCtxAppend",
2146             XMLSEC_ERRORS_R_XMLSEC_FAILED,
2147             XMLSEC_ERRORS_NO_MESSAGE);
2148             ret = -1;
2149             goto error;
2150         }
2151     } else {
2152         xmlSecError(XMLSEC_ERRORS_HERE,
2153         NULL,
2154         "CanonicalizationMethod",
2155         XMLSEC_ERRORS_R_INVALID_NODE,
2156         "expected=%s",
2157         xmlSecErrorsSafeString(xmlSecNodeCanonicalizationMethod));
2158         ret = -1;
2159         goto error;
2160     }
2161
2162     /* insert membuf if requested */
2163     if((dsigCtx->flags & XMLSEC_DSIG_FLAGS_STORE_SIGNATURE) != 0) {
2164         xmlSecAssert2(dsigCtx->preSignMemBufMethod == NULL, -1);
2165         dsigCtx->preSignMemBufMethod = xmlSecTransformCtxCreateAndAppend(&(dsigCtx->transformCtx),
2166         xmlSecTransformMemBufId);
2167         if(dsigCtx->preSignMemBufMethod == NULL) {
2168             xmlSecError(XMLSEC_ERRORS_HERE,
2169             NULL,
2170             "xmlSecTransformCtxCreateAndAppend",
2171             XMLSEC_ERRORS_R_XMLSEC_FAILED,
2172             "transform=%s",
2173             xmlSecErrorsSafeString(xmlSecTransformKlassGetName(xmlSecTransformMemBufId)));
2174         }
2175     }
2176
2177     /* next node is required SignatureMethod. */
2178     cur = xmlSecGetNextElementNode( ((cur != NULL) ? cur->next : node->children) );
2179     if((cur != NULL) && (xmlSecCheckNodeName(cur, xmlSecNodeSignatureMethod, xmlSecDSigNs))) {
2180         dsigCtx->signMethod = xmlSecTransformCtxNodeRead(&(dsigCtx->transformCtx),
2181         cur, xmlSecTransformUsageSignatureMethod);
2182         if(dsigCtx->signMethod == NULL) {
2183         xmlSecError(XMLSEC_ERRORS_HERE,
2184         NULL,
2185         "xmlSecTransformCtxNodeRead",
2186         XMLSEC_ERRORS_R_XMLSEC_FAILED,
2187         "node=%s",
2188         xmlSecErrorsSafeString(xmlSecNodeGetName(cur)));
2189         ret = -1;
2190         goto error;
2191         }
2192     } else if(dsigCtx->defSignMethodId != xmlSecTransformIdUnknown) {
2193         /* the dsig spec does require SignatureMethod node
2194         * to be present but in some case it application might decide to
2195         * minimize traffic */
2196         dsigCtx->signMethod = xmlSecTransformCtxCreateAndAppend(&(dsigCtx->transformCtx),
2197         dsigCtx->defSignMethodId);
2198         if(dsigCtx->signMethod == NULL) {
2199         xmlSecError(XMLSEC_ERRORS_HERE,
2200         NULL,
2201         "xmlSecTransformCtxAppend",
2202         XMLSEC_ERRORS_R_XMLSEC_FAILED,
2203         XMLSEC_ERRORS_NO_MESSAGE);
2204         ret = -1;
2205         goto error;
2206         }
2207     } else {
2208         xmlSecError(XMLSEC_ERRORS_HERE,
2209         NULL,
2210         xmlSecErrorsSafeString(xmlSecNodeGetName(cur)),
2211         XMLSEC_ERRORS_R_INVALID_NODE,
2212         "expected=%s",
2213         xmlSecErrorsSafeString(xmlSecNodeSignatureMethod));
2214         ret = -1;
2215         goto error;
2216     }
2217     dsigCtx->signMethod->operation = dsigCtx->operation;
2218
2219     /* calculate references */
2220     cur = xmlSecGetNextElementNode(cur->next);
2221     while((cur != NULL) && (xmlSecCheckNodeName(cur, xmlSecNodeReference, xmlSecDSigNs))) {
2222         /* create reference */
2223         dsigRefCtx = xmlSecDSigReferenceCtxCreate(dsigCtx, xmlSecDSigReferenceOriginSignedInfo);
2224         if(dsigRefCtx == NULL) {
2225             xmlSecError(XMLSEC_ERRORS_HERE,
2226             NULL,
2227             "xmlSecDSigReferenceCtxCreate",
2228             XMLSEC_ERRORS_R_XMLSEC_FAILED,
2229             XMLSEC_ERRORS_NO_MESSAGE);
2230             ret = -1;
2231             goto error;
2232         }
2233
2234         /* add to the list */
2235         ret = xmlSecPtrListAdd(&(dsigCtx->signedInfoReferences), dsigRefCtx);
2236         if(ret < 0) {
2237             xmlSecError(XMLSEC_ERRORS_HERE,
2238             NULL,
2239             "xmlSecPtrListAdd",
2240             XMLSEC_ERRORS_R_XMLSEC_FAILED,
2241             XMLSEC_ERRORS_NO_MESSAGE);
2242             xmlSecDSigReferenceCtxDestroy(dsigRefCtx);
2243             ret = -1;
2244             goto error;
2245         }
2246
2247         /* process */
2248         if(noHash != 1) { //if 0, then partial ///if 1, then no_hash
2249             ret = xmlSecDSigReferenceCtxProcessNodeEx(dsigRefCtx, cur, noHash, pList);
2250             if(ret < 0) {
2251                 xmlSecError(XMLSEC_ERRORS_HERE,
2252                 NULL,
2253                 "xmlSecDSigReferenceCtxProcessNode",
2254                 XMLSEC_ERRORS_R_XMLSEC_FAILED,
2255                 "node=%s",
2256                 xmlSecErrorsSafeString(xmlSecNodeGetName(cur)));
2257
2258                 ret = -1;
2259                 goto error;
2260             }
2261         }
2262
2263         dsigRefCtx->status = xmlSecDSigStatusSucceeded;
2264
2265         /* bail out if next Reference processing failed */
2266         if(dsigRefCtx->status != xmlSecDSigStatusSucceeded) {
2267             xmlSecError(XMLSEC_ERRORS_HERE, NULL, NULL, XMLSEC_ERRORS_MAX_NUMBER, "###### false");
2268             dsigCtx->status = xmlSecDSigStatusInvalid;
2269             ret = -1;
2270             goto error;
2271         }
2272         cur = xmlSecGetNextElementNode(cur->next);
2273     }
2274
2275     /* check that we have at least one Reference */
2276     if(xmlSecPtrListGetSize(&(dsigCtx->signedInfoReferences)) == 0) {
2277         xmlSecError(XMLSEC_ERRORS_HERE,
2278         NULL,
2279         NULL,
2280         XMLSEC_ERRORS_R_DSIG_NO_REFERENCES,
2281         XMLSEC_ERRORS_NO_MESSAGE);
2282         ret = -1;
2283         goto error;
2284     }
2285
2286     /* if there is something left than it's an error */
2287     if(cur != NULL) {
2288         xmlSecError(XMLSEC_ERRORS_HERE,
2289         NULL,
2290         xmlSecErrorsSafeString(xmlSecNodeGetName(cur)),
2291         XMLSEC_ERRORS_R_UNEXPECTED_NODE,
2292         XMLSEC_ERRORS_NO_MESSAGE);
2293         ret = -1;
2294         goto error;
2295      }
2296     _end
2297 error:
2298     return(ret);
2299 }
2300
2301 int
2302 xmlSecDSigReferenceCtxProcessNodeEx(xmlSecDSigReferenceCtxPtr dsigRefCtx, xmlNodePtr node, int noHash, void* pList) {
2303     xmlSecTransformCtxPtr transformCtx;
2304     xmlNodePtr digestValueNode;
2305     xmlNodePtr cur;
2306     int ret;
2307     int cmpResult = -1;
2308     int len = 0;
2309     int i = 0;
2310
2311     char** pNextTmp = (char**)pList;
2312
2313     xmlSecAssert2(dsigRefCtx != NULL, -1);
2314     xmlSecAssert2(dsigRefCtx->dsigCtx != NULL, -1);
2315     xmlSecAssert2(dsigRefCtx->digestMethod == NULL, -1);
2316     xmlSecAssert2(dsigRefCtx->digestMethod == NULL, -1);
2317     xmlSecAssert2(dsigRefCtx->preDigestMemBufMethod == NULL, -1);
2318     xmlSecAssert2(node != NULL, -1);
2319     xmlSecAssert2(node->doc != NULL, -1);
2320
2321     _start
2322
2323     transformCtx = &(dsigRefCtx->transformCtx);
2324
2325     if(pList == NULL) {
2326        xmlSecError(XMLSEC_ERRORS_HERE,
2327        NULL,
2328        NULL,
2329        XMLSEC_ERRORS_R_UNEXPECTED_NODE,
2330        XMLSEC_ERRORS_NO_MESSAGE);
2331        return(-1);
2332     }
2333
2334     /* read attributes first */
2335     dsigRefCtx->uri = xmlGetProp(node, xmlSecAttrURI);
2336
2337     while(pNextTmp[i] != NULL) {
2338         len =  strlen(pNextTmp[i]);
2339         cmpResult = strncmp((const char *)dsigRefCtx->uri, (const char *)pNextTmp[i], len);
2340         if(cmpResult == 0) {
2341             snprintf(logMsg, sizeof(logMsg), "uri: %s", (char*)pNextTmp[i]);
2342             xmlSecError(XMLSEC_ERRORS_HERE, NULL, NULL, XMLSEC_ERRORS_MAX_NUMBER, logMsg);
2343             break;
2344         }
2345         ++i;
2346     }
2347
2348     if(cmpResult !=  0) {
2349         cmpResult = -1;
2350         goto partial;
2351     }
2352
2353     dsigRefCtx->id = xmlGetProp(node, xmlSecAttrId);
2354     dsigRefCtx->type= xmlGetProp(node, xmlSecAttrType);
2355
2356     /* set start URI (and check that it is enabled!) */
2357     ret = xmlSecTransformCtxSetUri(transformCtx, dsigRefCtx->uri, node);
2358     if(ret < 0) {
2359         xmlSecError(XMLSEC_ERRORS_HERE,
2360         NULL,
2361         "xmlSecTransformCtxSetUri",
2362         XMLSEC_ERRORS_R_XMLSEC_FAILED,
2363         "uri=%s",
2364          xmlSecErrorsSafeString(dsigRefCtx->uri));
2365          return(-1);
2366     }
2367
2368     /* first is optional Transforms node */
2369     cur  = xmlSecGetNextElementNode(node->children);
2370     if((cur != NULL) && (xmlSecCheckNodeName(cur, xmlSecNodeTransforms, xmlSecDSigNs))) {
2371         ret = xmlSecTransformCtxNodesListRead(transformCtx,
2372         cur, xmlSecTransformUsageDSigTransform);
2373         if(ret < 0) {
2374             xmlSecError(XMLSEC_ERRORS_HERE,
2375             NULL,
2376             "xmlSecTransformCtxNodesListRead",
2377             XMLSEC_ERRORS_R_XMLSEC_FAILED,
2378             "node=%s",
2379             xmlSecErrorsSafeString(xmlSecNodeGetName(cur)));
2380             return(-1);
2381         }
2382         cur = xmlSecGetNextElementNode(cur->next);
2383     }
2384
2385     /* insert membuf if requested */
2386     if(((dsigRefCtx->origin == xmlSecDSigReferenceOriginSignedInfo) &&
2387        ((dsigRefCtx->dsigCtx->flags & XMLSEC_DSIG_FLAGS_STORE_SIGNEDINFO_REFERENCES) != 0)) ||
2388        ((dsigRefCtx->origin == xmlSecDSigReferenceOriginManifest) &&
2389        ((dsigRefCtx->dsigCtx->flags & XMLSEC_DSIG_FLAGS_STORE_MANIFEST_REFERENCES) != 0))) {
2390         xmlSecAssert2(dsigRefCtx->preDigestMemBufMethod == NULL, -1);
2391         dsigRefCtx->preDigestMemBufMethod = xmlSecTransformCtxCreateAndAppend(
2392         transformCtx,
2393         xmlSecTransformMemBufId);
2394         if(dsigRefCtx->preDigestMemBufMethod == NULL) {
2395             xmlSecError(XMLSEC_ERRORS_HERE,
2396             NULL,
2397             "xmlSecTransformCtxCreateAndAppend",
2398             XMLSEC_ERRORS_R_XMLSEC_FAILED,
2399             "transform=%s",
2400             xmlSecErrorsSafeString(xmlSecTransformKlassGetName(xmlSecTransformMemBufId)));
2401             return(-1);
2402         }
2403     }
2404
2405     /* next node is required DigestMethod. */
2406     if((cur != NULL) && (xmlSecCheckNodeName(cur, xmlSecNodeDigestMethod, xmlSecDSigNs))) {
2407         dsigRefCtx->digestMethod = xmlSecTransformCtxNodeRead(&(dsigRefCtx->transformCtx),
2408         cur, xmlSecTransformUsageDigestMethod);
2409         if(dsigRefCtx->digestMethod == NULL) {
2410             xmlSecError(XMLSEC_ERRORS_HERE,
2411             NULL,
2412             "xmlSecTransformCtxNodeRead",
2413             XMLSEC_ERRORS_R_XMLSEC_FAILED,
2414             "node=%s",
2415             xmlSecErrorsSafeString(xmlSecNodeGetName(cur)));
2416             return(-1);
2417         }
2418         cur = xmlSecGetNextElementNode(cur->next);
2419     } else if(dsigRefCtx->dsigCtx->defSignMethodId != xmlSecTransformIdUnknown) {
2420         /* the dsig spec does require DigestMethod node
2421         * to be present but in some case it application might decide to
2422         * minimize traffic */
2423         dsigRefCtx->digestMethod = xmlSecTransformCtxCreateAndAppend(&(dsigRefCtx->transformCtx),
2424         dsigRefCtx->dsigCtx->defSignMethodId);
2425         if(dsigRefCtx->digestMethod == NULL) {
2426             xmlSecError(XMLSEC_ERRORS_HERE,
2427             NULL,
2428             "xmlSecTransformCtxAppend",
2429             XMLSEC_ERRORS_R_XMLSEC_FAILED,
2430             XMLSEC_ERRORS_NO_MESSAGE);
2431             return(-1);
2432         }
2433     } else {
2434         xmlSecError(XMLSEC_ERRORS_HERE,
2435         NULL,
2436         xmlSecErrorsSafeString(xmlSecNodeGetName(cur)),
2437         XMLSEC_ERRORS_R_INVALID_NODE,
2438         "expected=%s",
2439         xmlSecErrorsSafeString(xmlSecNodeDigestMethod));
2440         return(-1);
2441     }
2442
2443     dsigRefCtx->digestMethod->operation = dsigRefCtx->dsigCtx->operation;
2444
2445     /* last node is required DigestValue */
2446     if((cur != NULL) && (xmlSecCheckNodeName(cur, xmlSecNodeDigestValue, xmlSecDSigNs))) {
2447         digestValueNode = cur;
2448         cur = xmlSecGetNextElementNode(cur->next);
2449     } else {
2450         xmlSecError(XMLSEC_ERRORS_HERE,
2451         NULL,
2452         xmlSecErrorsSafeString(xmlSecNodeGetName(cur)),
2453         XMLSEC_ERRORS_R_XMLSEC_FAILED,
2454         "node=%s",
2455         xmlSecErrorsSafeString(xmlSecNodeDigestValue));
2456         return(-1);
2457     }
2458
2459     /* if we have something else then it's an error */
2460     if(cur != NULL) {
2461         xmlSecError(XMLSEC_ERRORS_HERE,
2462         NULL,
2463         xmlSecErrorsSafeString(xmlSecNodeGetName(cur)),
2464         XMLSEC_ERRORS_R_UNEXPECTED_NODE,
2465         XMLSEC_ERRORS_NO_MESSAGE);
2466         return(-1);
2467     }
2468
2469     /* if we need to write result to xml node then we need base64 encode result */
2470     if(dsigRefCtx->dsigCtx->operation == xmlSecTransformOperationSign) {
2471         xmlSecTransformPtr base64Encode;
2472
2473         /* we need to add base64 encode transform */
2474         base64Encode = xmlSecTransformCtxCreateAndAppend(transformCtx, xmlSecTransformBase64Id);
2475         if(base64Encode == NULL) {
2476             xmlSecError(XMLSEC_ERRORS_HERE,
2477             NULL,
2478             "xmlSecTransformCtxCreateAndAppend",
2479             XMLSEC_ERRORS_R_XMLSEC_FAILED,
2480             XMLSEC_ERRORS_NO_MESSAGE);
2481             return(-1);
2482         }
2483         base64Encode->operation = xmlSecTransformOperationEncode;
2484     }
2485
2486     /* finally get transforms results */
2487     ret = xmlSecTransformCtxExecute(transformCtx, node->doc);
2488     if(ret < 0) {
2489         snprintf(logMsg, sizeof(logMsg), "uri:%s", (char*)dsigRefCtx->uri);
2490         logMsg[strlen(dsigRefCtx->uri)+5] = '\0';
2491         xmlSecError(XMLSEC_ERRORS_HERE,
2492         NULL,
2493         "xmlSecTransformCtxExecute",
2494         XMLSEC_ERRORS_R_XMLSEC_FAILED,
2495         logMsg);
2496         return(-1);
2497     }
2498
2499     dsigRefCtx->result = transformCtx->result;
2500
2501     if(dsigRefCtx->dsigCtx->operation == xmlSecTransformOperationSign) {
2502         if((dsigRefCtx->result == NULL) || (xmlSecBufferGetData(dsigRefCtx->result) == NULL)) {
2503             xmlSecError(XMLSEC_ERRORS_HERE,
2504             NULL,
2505             "xmlSecTransformCtxExecute",
2506             XMLSEC_ERRORS_R_XMLSEC_FAILED,
2507             XMLSEC_ERRORS_NO_MESSAGE);
2508             return(-1);
2509         }
2510
2511         /* write signed data to xml */
2512         xmlNodeSetContentLen(digestValueNode,
2513         xmlSecBufferGetData(dsigRefCtx->result),
2514         xmlSecBufferGetSize(dsigRefCtx->result));
2515
2516         /* set success status and we are done */
2517         dsigRefCtx->status = xmlSecDSigStatusSucceeded;
2518     } else {
2519         /* verify SignatureValue node content */
2520         ret = xmlSecTransformVerifyNodeContent(dsigRefCtx->digestMethod,
2521         digestValueNode, transformCtx);
2522         if(ret < 0) {
2523             snprintf(logMsg, sizeof(logMsg), "uri:%s", (char*)dsigRefCtx->uri);
2524             logMsg[strlen(dsigRefCtx->uri)+5] = '\0';
2525             xmlSecError(XMLSEC_ERRORS_HERE,
2526             NULL,
2527             "xmlSecTransformVerifyNodeContent",
2528             XMLSEC_ERRORS_R_XMLSEC_FAILED, logMsg);
2529             return(-1);
2530         }
2531
2532         /* set status and we are done */
2533         if(dsigRefCtx->digestMethod->status == xmlSecTransformStatusOk) {
2534             dsigRefCtx->status = xmlSecDSigStatusSucceeded;
2535         } else {
2536             dsigRefCtx->status = xmlSecDSigStatusInvalid;
2537         }
2538     }
2539
2540     if(dsigRefCtx->digestMethod->status == xmlSecTransformStatusOk) {
2541        dsigRefCtx->status = xmlSecDSigStatusSucceeded;
2542     }
2543
2544     _end
2545
2546 partial:
2547     return(0);
2548 }
2549
2550 /**************************************************************************
2551  *
2552  * xmlSecDSigReferenceCtxListKlass
2553  *
2554  *************************************************************************/
2555 static xmlSecPtrListKlass xmlSecDSigReferenceCtxListKlass = {
2556     BAD_CAST "dsig-reference-list",
2557     NULL,                                                               /* xmlSecPtrDuplicateItemMethod duplicateItem; */
2558     (xmlSecPtrDestroyItemMethod)xmlSecDSigReferenceCtxDestroy,          /* xmlSecPtrDestroyItemMethod destroyItem; */
2559     (xmlSecPtrDebugDumpItemMethod)xmlSecDSigReferenceCtxDebugDump,      /* xmlSecPtrDebugDumpItemMethod debugDumpItem; */
2560     (xmlSecPtrDebugDumpItemMethod)xmlSecDSigReferenceCtxDebugXmlDump,   /* xmlSecPtrDebugDumpItemMethod debugXmlDumpItem; */
2561 };
2562
2563 /**
2564  * xmlSecDSigReferenceCtxListGetKlass:
2565  *
2566  * The <dsig:Reference/> element processing contexts list klass.
2567  *
2568  * Returns: <dsig:Reference/> element processing context list klass.
2569  */
2570 xmlSecPtrListId
2571 xmlSecDSigReferenceCtxListGetKlass(void) {
2572     return(&xmlSecDSigReferenceCtxListKlass);
2573 }
2574
2575 #endif /* XMLSEC_NO_XMLDSIG */