2 * XML Security Library (http://www.aleksey.com/xmlsec).
4 * "XML Digital Signature" implementation
5 * http://www.w3.org/TR/xmldsig-core/
6 * http://www.w3.org/Signature/Overview.html
8 * This is free software; see Copyright file in the source
9 * distribution for preciese wording.
11 * Copyright (C) 2002-2016 Aleksey Sanin <aleksey@aleksey.com>. All Rights Reserved.
15 #ifndef XMLSEC_NO_XMLDSIG
21 #include <libxml/tree.h>
22 #include <libxml/parser.h>
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>
34 /**************************************************************************
38 *************************************************************************/
39 static int xmlSecDSigCtxProcessSignatureNode (xmlSecDSigCtxPtr dsigCtx,
41 static int xmlSecDSigCtxProcessSignedInfoNode (xmlSecDSigCtxPtr dsigCtx,
43 xmlNodePtr * firstReferenceNode);
44 static int xmlSecDSigCtxProcessKeyInfoNode (xmlSecDSigCtxPtr dsigCtx,
46 static int xmlSecDSigCtxProcessObjectNode (xmlSecDSigCtxPtr dsigCtx,
48 static int xmlSecDSigCtxProcessManifestNode (xmlSecDSigCtxPtr dsigCtx,
50 static int xmlSecDSigCtxProcessReferences (xmlSecDSigCtxPtr dsigCtx,
51 xmlNodePtr firstReferenceNode);
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);
61 /* The ID attribute in XMLDSig is 'Id' */
62 static const xmlChar* xmlSecDSigIds[] = { xmlSecAttrId, NULL };
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];
70 * xmlSecDSigCtxCreate:
71 * @keysMngr: the pointer to keys manager.
73 * Creates <dsig:Signature/> element processing context.
74 * The caller is responsible for destroying returned object by calling
75 * #xmlSecDSigCtxDestroy function.
77 * Returns: pointer to newly allocated context object or NULL if an error
81 xmlSecDSigCtxCreate(xmlSecKeysMngrPtr keysMngr) {
82 xmlSecDSigCtxPtr dsigCtx;
85 dsigCtx = (xmlSecDSigCtxPtr) xmlMalloc(sizeof(xmlSecDSigCtx));
87 xmlSecError(XMLSEC_ERRORS_HERE,
90 XMLSEC_ERRORS_R_MALLOC_FAILED,
91 "sizeof(xmlSecDSigCtx)=%d",
92 (int)sizeof(xmlSecDSigCtx));
96 ret = xmlSecDSigCtxInitialize(dsigCtx, keysMngr);
98 xmlSecError(XMLSEC_ERRORS_HERE,
100 "xmlSecDSigCtxInitialize",
101 XMLSEC_ERRORS_R_XMLSEC_FAILED,
102 XMLSEC_ERRORS_NO_MESSAGE);
103 xmlSecDSigCtxDestroy(dsigCtx);
110 * xmlSecDSigCtxDestroy:
111 * @dsigCtx: the pointer to <dsig:Signature/> processing context.
113 * Destroy context object created with #xmlSecDSigCtxCreate function.
116 xmlSecDSigCtxDestroy(xmlSecDSigCtxPtr dsigCtx) {
117 xmlSecAssert(dsigCtx != NULL);
119 xmlSecDSigCtxFinalize(dsigCtx);
124 * xmlSecDSigCtxInitialize:
125 * @dsigCtx: the pointer to <dsig:Signature/> processing context.
126 * @keysMngr: the pointer to keys manager.
128 * Initializes <dsig:Signature/> element processing context.
129 * The caller is responsible for cleaning up returned object by calling
130 * #xmlSecDSigCtxFinalize function.
132 * Returns: 0 on success or a negative value if an error occurs.
135 xmlSecDSigCtxInitialize(xmlSecDSigCtxPtr dsigCtx, xmlSecKeysMngrPtr keysMngr) {
138 xmlSecAssert2(dsigCtx != NULL, -1);
140 memset(dsigCtx, 0, sizeof(xmlSecDSigCtx));
142 /* initialize key info */
143 ret = xmlSecKeyInfoCtxInitialize(&(dsigCtx->keyInfoReadCtx), keysMngr);
145 xmlSecError(XMLSEC_ERRORS_HERE,
147 "xmlSecKeyInfoCtxInitialize",
148 XMLSEC_ERRORS_R_XMLSEC_FAILED,
149 XMLSEC_ERRORS_NO_MESSAGE);
152 dsigCtx->keyInfoReadCtx.mode = xmlSecKeyInfoModeRead;
154 ret = xmlSecKeyInfoCtxInitialize(&(dsigCtx->keyInfoWriteCtx), keysMngr);
156 xmlSecError(XMLSEC_ERRORS_HERE,
158 "xmlSecKeyInfoCtxInitialize",
159 XMLSEC_ERRORS_R_XMLSEC_FAILED,
160 XMLSEC_ERRORS_NO_MESSAGE);
163 dsigCtx->keyInfoWriteCtx.mode = xmlSecKeyInfoModeWrite;
164 /* it's not wise to write private key :) */
165 dsigCtx->keyInfoWriteCtx.keyReq.keyType = xmlSecKeyDataTypePublic;
167 /* initializes transforms dsigCtx */
168 ret = xmlSecTransformCtxInitialize(&(dsigCtx->transformCtx));
170 xmlSecError(XMLSEC_ERRORS_HERE,
172 "xmlSecTransformCtxInitialize",
173 XMLSEC_ERRORS_R_XMLSEC_FAILED,
174 XMLSEC_ERRORS_NO_MESSAGE);
178 /* references lists from SignedInfo and Manifest elements */
179 ret = xmlSecPtrListInitialize(&(dsigCtx->signedInfoReferences),
180 xmlSecDSigReferenceCtxListId);
182 xmlSecError(XMLSEC_ERRORS_HERE,
184 "xmlSecPtrListInitialize",
185 XMLSEC_ERRORS_R_XMLSEC_FAILED,
186 XMLSEC_ERRORS_NO_MESSAGE);
189 ret = xmlSecPtrListInitialize(&(dsigCtx->manifestReferences),
190 xmlSecDSigReferenceCtxListId);
192 xmlSecError(XMLSEC_ERRORS_HERE,
194 "xmlSecPtrListInitialize",
195 XMLSEC_ERRORS_R_XMLSEC_FAILED,
196 XMLSEC_ERRORS_NO_MESSAGE);
200 dsigCtx->enabledReferenceUris = xmlSecTransformUriTypeAny;
205 * xmlSecDSigCtxFinalize:
206 * @dsigCtx: the pointer to <dsig:Signature/> processing context.
208 * Cleans up @dsigCtx object initialized with #xmlSecDSigCtxInitialize function.
211 xmlSecDSigCtxFinalize(xmlSecDSigCtxPtr dsigCtx) {
212 xmlSecAssert(dsigCtx != NULL);
214 xmlSecTransformCtxFinalize(&(dsigCtx->transformCtx));
215 xmlSecKeyInfoCtxFinalize(&(dsigCtx->keyInfoReadCtx));
216 xmlSecKeyInfoCtxFinalize(&(dsigCtx->keyInfoWriteCtx));
217 xmlSecPtrListFinalize(&(dsigCtx->signedInfoReferences));
218 xmlSecPtrListFinalize(&(dsigCtx->manifestReferences));
220 if(dsigCtx->enabledReferenceTransforms != NULL) {
221 xmlSecPtrListDestroy(dsigCtx->enabledReferenceTransforms);
223 if(dsigCtx->signKey != NULL) {
224 xmlSecKeyDestroy(dsigCtx->signKey);
226 if(dsigCtx->id != NULL) {
227 xmlFree(dsigCtx->id);
229 memset(dsigCtx, 0, sizeof(xmlSecDSigCtx));
233 * xmlSecDSigCtxEnableReferenceTransform:
234 * @dsigCtx: the pointer to <dsig:Signature/> processing context.
235 * @transformId: the transform klass.
237 * Enables @transformId for <dsig:Reference/> elements processing.
239 * Returns: 0 on success or a negative value if an error occurs.
242 xmlSecDSigCtxEnableReferenceTransform(xmlSecDSigCtxPtr dsigCtx, xmlSecTransformId transformId) {
245 xmlSecAssert2(dsigCtx != NULL, -1);
246 xmlSecAssert2(dsigCtx->result == NULL, -1);
247 xmlSecAssert2(transformId != xmlSecTransformIdUnknown, -1);
249 if(dsigCtx->enabledReferenceTransforms == NULL) {
250 dsigCtx->enabledReferenceTransforms = xmlSecPtrListCreate(xmlSecTransformIdListId);
251 if(dsigCtx->enabledReferenceTransforms == NULL) {
252 xmlSecError(XMLSEC_ERRORS_HERE,
254 "xmlSecPtrListCreate",
255 XMLSEC_ERRORS_R_XMLSEC_FAILED,
256 XMLSEC_ERRORS_NO_MESSAGE);
261 ret = xmlSecPtrListAdd(dsigCtx->enabledReferenceTransforms, (void*)transformId);
263 xmlSecError(XMLSEC_ERRORS_HERE,
266 XMLSEC_ERRORS_R_XMLSEC_FAILED,
267 XMLSEC_ERRORS_NO_MESSAGE);
274 * xmlSecDSigCtxEnableSignatureTransform:
275 * @dsigCtx: the pointer to <dsig:Signature/> processing context.
276 * @transformId: the transform klass.
278 * Enables @transformId for <dsig:SignedInfo/> element processing.
280 * Returns: 0 on success or a negative value if an error occurs.
283 xmlSecDSigCtxEnableSignatureTransform(xmlSecDSigCtxPtr dsigCtx, xmlSecTransformId transformId) {
284 xmlSecAssert2(dsigCtx != NULL, -1);
285 xmlSecAssert2(dsigCtx->result == NULL, -1);
286 xmlSecAssert2(transformId != xmlSecTransformIdUnknown, -1);
288 return(xmlSecPtrListAdd(&(dsigCtx->transformCtx.enabledTransforms), (void*)transformId));
292 * xmlSecDSigCtxGetPreSignBuffer:
293 * @dsigCtx: the pointer to <dsig:Signature/> processing context.
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.
299 * Returns: 0 on success or a negative value if an error occurs.
302 xmlSecDSigCtxGetPreSignBuffer(xmlSecDSigCtxPtr dsigCtx) {
303 xmlSecAssert2(dsigCtx != NULL, NULL);
305 return((dsigCtx->preSignMemBufMethod != NULL) ?
306 xmlSecTransformMemBufGetBuffer(dsigCtx->preSignMemBufMethod) : NULL);
311 * @dsigCtx: the pointer to <dsig:Signature/> processing context.
312 * @tmpl: the pointer to <dsig:Signature/> node with signature template.
314 * Signs the data as described in @tmpl node.
316 * Returns: 0 on success or a negative value if an error occurs.
319 xmlSecDSigCtxSign(xmlSecDSigCtxPtr dsigCtx, xmlNodePtr tmpl) {
322 xmlSecAssert2(dsigCtx != NULL, -1);
323 xmlSecAssert2(dsigCtx->result == NULL, -1);
324 xmlSecAssert2(tmpl != NULL, -1);
325 xmlSecAssert2(tmpl->doc != NULL, -1);
327 /* add ids for Signature nodes */
328 dsigCtx->operation = xmlSecTransformOperationSign;
329 dsigCtx->status = xmlSecDSigStatusUnknown;
330 xmlSecAddIDs(tmpl->doc, tmpl, xmlSecDSigIds);
332 /* read signature template */
333 ret = xmlSecDSigCtxProcessSignatureNode(dsigCtx, tmpl);
335 xmlSecError(XMLSEC_ERRORS_HERE,
337 "xmlSecDSigCtxSignatureProcessNode",
338 XMLSEC_ERRORS_R_XMLSEC_FAILED,
339 XMLSEC_ERRORS_NO_MESSAGE);
342 xmlSecAssert2(dsigCtx->signMethod != NULL, -1);
343 xmlSecAssert2(dsigCtx->signValueNode != NULL, -1);
345 /* references processing might change the status */
346 if(dsigCtx->status != xmlSecDSigStatusUnknown) {
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,
356 XMLSEC_ERRORS_R_INVALID_RESULT,
357 XMLSEC_ERRORS_NO_MESSAGE);
361 /* write signed data to xml */
362 xmlNodeSetContentLen(dsigCtx->signValueNode,
363 xmlSecBufferGetData(dsigCtx->result),
364 xmlSecBufferGetSize(dsigCtx->result));
366 /* set success status and we are done */
367 dsigCtx->status = xmlSecDSigStatusSucceeded;
372 * xmlSecDSigCtxVerify:
373 * @dsigCtx: the pointer to <dsig:Signature/> processing context.
374 * @node: the pointer with <dsig:Signature/> node.
376 * Vaidates signature in the @node. The verification result is returned
377 * in #status member of the @dsigCtx object.
379 * Returns: 0 on success (check #status member of @dsigCtx to get
380 * signature verification result) or a negative value if an error occurs.
383 xmlSecDSigCtxVerify(xmlSecDSigCtxPtr dsigCtx, xmlNodePtr node) {
386 xmlSecAssert2(dsigCtx != NULL, -1);
387 xmlSecAssert2(node != NULL, -1);
388 xmlSecAssert2(node->doc != NULL, -1);
390 /* add ids for Signature nodes */
391 dsigCtx->operation = xmlSecTransformOperationVerify;
392 dsigCtx->status = xmlSecDSigStatusUnknown;
393 xmlSecAddIDs(node->doc, node, xmlSecDSigIds);
395 /* read signature info */
396 ret = xmlSecDSigCtxProcessSignatureNode(dsigCtx, node);
398 xmlSecError(XMLSEC_ERRORS_HERE,
400 "xmlSecDSigCtxSignatureProcessNode",
401 XMLSEC_ERRORS_R_XMLSEC_FAILED,
402 XMLSEC_ERRORS_NO_MESSAGE);
405 xmlSecAssert2(dsigCtx->signMethod != NULL, -1);
406 xmlSecAssert2(dsigCtx->signValueNode != NULL, -1);
408 /* references processing might change the status */
409 if(dsigCtx->status != xmlSecDSigStatusUnknown) {
413 /* verify SignatureValue node content */
414 ret = xmlSecTransformVerifyNodeContent(dsigCtx->signMethod, dsigCtx->signValueNode,
415 &(dsigCtx->transformCtx));
417 xmlSecError(XMLSEC_ERRORS_HERE,
419 "xmlSecTransformVerifyNodeContent",
420 XMLSEC_ERRORS_R_XMLSEC_FAILED,
421 XMLSEC_ERRORS_NO_MESSAGE);
425 /* set status and we are done */
426 if(dsigCtx->signMethod->status == xmlSecTransformStatusOk) {
427 dsigCtx->status = xmlSecDSigStatusSucceeded;
429 dsigCtx->status = xmlSecDSigStatusInvalid;
435 * xmlSecDSigCtxProcessSignatureNode:
437 * The Signature element (http://www.w3.org/TR/xmldsig-core/#sec-Signature)
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:
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
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.
461 * =================================
462 * we do not support any non XML based C14N
466 * <element name="Signature" type="ds:SignatureType"/>
467 * <complexType name="SignatureType">
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"/>
478 * <!ELEMENT Signature (SignedInfo, SignatureValue, KeyInfo?, Object*) >
479 * <!ATTLIST Signature
480 * xmlns CDATA #FIXED 'http://www.w3.org/2000/09/xmldsig#'
485 xmlSecDSigCtxProcessSignatureNode(xmlSecDSigCtxPtr dsigCtx, xmlNodePtr node) {
486 xmlSecTransformDataType firstType;
487 xmlNodePtr signedInfoNode = NULL;
488 xmlNodePtr keyInfoNode = NULL;
489 xmlNodePtr firstReferenceNode = NULL;
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);
501 if(!xmlSecCheckNodeName(node, xmlSecNodeSignature, xmlSecDSigNs)) {
502 xmlSecError(XMLSEC_ERRORS_HERE,
504 xmlSecErrorsSafeString(xmlSecNodeGetName(node)),
505 XMLSEC_ERRORS_R_INVALID_NODE,
507 xmlSecErrorsSafeString(xmlSecNodeSignature));
512 xmlSecAssert2(dsigCtx->id == NULL, -1);
513 dsigCtx->id = xmlGetProp(node, xmlSecAttrId);
515 /* first node is required SignedInfo */
516 cur = xmlSecGetNextElementNode(node->children);
517 if((cur == NULL) || (!xmlSecCheckNodeName(cur, xmlSecNodeSignedInfo, xmlSecDSigNs))) {
518 xmlSecError(XMLSEC_ERRORS_HERE,
520 xmlSecErrorsSafeString(xmlSecNodeGetName(cur)),
521 XMLSEC_ERRORS_R_INVALID_NODE,
523 xmlSecErrorsSafeString(xmlSecNodeSignedInfo));
526 signedInfoNode = cur;
527 cur = xmlSecGetNextElementNode(cur->next);
529 /* next node is required SignatureValue */
530 if((cur == NULL) || (!xmlSecCheckNodeName(cur, xmlSecNodeSignatureValue, xmlSecDSigNs))) {
531 xmlSecError(XMLSEC_ERRORS_HERE,
533 xmlSecErrorsSafeString(xmlSecNodeGetName(cur)),
534 XMLSEC_ERRORS_R_INVALID_NODE,
536 xmlSecErrorsSafeString(xmlSecNodeSignatureValue));
539 dsigCtx->signValueNode = cur;
540 cur = xmlSecGetNextElementNode(cur->next);
542 /* next node is optional KeyInfo */
543 if((cur != NULL) && (xmlSecCheckNodeName(cur, xmlSecNodeKeyInfo, xmlSecDSigNs))) {
545 cur = xmlSecGetNextElementNode(cur->next);
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);
556 xmlSecError(XMLSEC_ERRORS_HERE,
558 "xmlSecDSigCtxProcessObjectNode",
559 XMLSEC_ERRORS_R_XMLSEC_FAILED,
560 XMLSEC_ERRORS_NO_MESSAGE);
564 cur = xmlSecGetNextElementNode(cur->next);
567 /* if there is something left than it's an error */
569 xmlSecError(XMLSEC_ERRORS_HERE,
571 xmlSecErrorsSafeString(xmlSecNodeGetName(cur)),
572 XMLSEC_ERRORS_R_UNEXPECTED_NODE,
573 XMLSEC_ERRORS_NO_MESSAGE);
577 /* now validated all the references and prepare transform */
578 ret = xmlSecDSigCtxProcessSignedInfoNode(dsigCtx, signedInfoNode, &firstReferenceNode);
580 xmlSecError(XMLSEC_ERRORS_HERE,
582 "xmlSecDSigCtxProcessSignedInfoNode",
583 XMLSEC_ERRORS_R_XMLSEC_FAILED,
584 XMLSEC_ERRORS_NO_MESSAGE);
588 /* as the result, we should have sign and c14n methods set */
589 xmlSecAssert2(dsigCtx->signMethod != NULL, -1);
590 xmlSecAssert2(dsigCtx->c14nMethod != NULL, -1);
592 /* now read key info node */
593 ret = xmlSecDSigCtxProcessKeyInfoNode(dsigCtx, keyInfoNode);
595 xmlSecError(XMLSEC_ERRORS_HERE,
597 "xmlSecDSigCtxProcessKeyInfoNode",
598 XMLSEC_ERRORS_R_XMLSEC_FAILED,
599 XMLSEC_ERRORS_NO_MESSAGE);
602 /* as the result, we should have a key */
603 xmlSecAssert2(dsigCtx->signKey != NULL, -1);
605 /* now actually process references and calculate digests */
606 ret = xmlSecDSigCtxProcessReferences(dsigCtx, firstReferenceNode);
608 xmlSecError(XMLSEC_ERRORS_HERE,
610 "xmlSecDSigCtxProcessReferences",
611 XMLSEC_ERRORS_R_XMLSEC_FAILED,
612 XMLSEC_ERRORS_NO_MESSAGE);
615 /* references processing might change the status */
616 if(dsigCtx->status != xmlSecDSigStatusUnknown) {
620 /* if we need to write result to xml node then we need base64 encode result */
621 if(dsigCtx->operation == xmlSecTransformOperationSign) {
622 xmlSecTransformPtr base64Encode;
624 /* we need to add base64 encode transform */
625 base64Encode = xmlSecTransformCtxCreateAndAppend(&(dsigCtx->transformCtx),
626 xmlSecTransformBase64Id);
627 if(base64Encode == NULL) {
628 xmlSecError(XMLSEC_ERRORS_HERE,
630 "xmlSecTransformCtxCreateAndAppend",
631 XMLSEC_ERRORS_R_XMLSEC_FAILED,
632 XMLSEC_ERRORS_NO_MESSAGE);
635 base64Encode->operation = xmlSecTransformOperationEncode;
638 firstType = xmlSecTransformGetDataType(dsigCtx->transformCtx.first,
639 xmlSecTransformModePush,
640 &(dsigCtx->transformCtx));
641 if((firstType & xmlSecTransformDataTypeXml) != 0) {
642 xmlSecNodeSetPtr nodeset = NULL;
644 xmlSecAssert2(signedInfoNode != NULL, -1);
645 nodeset = xmlSecNodeSetGetChildren(signedInfoNode->doc, signedInfoNode, 1, 0);
646 if(nodeset == NULL) {
647 xmlSecError(XMLSEC_ERRORS_HERE,
649 "xmlSecNodeSetGetChildren",
650 XMLSEC_ERRORS_R_XMLSEC_FAILED,
652 xmlSecErrorsSafeString(xmlSecNodeGetName(signedInfoNode)));
656 /* calculate the signature */
657 ret = xmlSecTransformCtxXmlExecute(&(dsigCtx->transformCtx), nodeset);
659 xmlSecError(XMLSEC_ERRORS_HERE,
661 "xmlSecTransformCtxXmlExecute",
662 XMLSEC_ERRORS_R_XMLSEC_FAILED,
663 XMLSEC_ERRORS_NO_MESSAGE);
664 xmlSecNodeSetDestroy(nodeset);
667 xmlSecNodeSetDestroy(nodeset);
670 xmlSecError(XMLSEC_ERRORS_HERE,
672 "the binary c14n transforms are not supported yet",
673 XMLSEC_ERRORS_R_NOT_IMPLEMENTED,
674 XMLSEC_ERRORS_NO_MESSAGE);
681 * xmlSecDSigCtxProcessSignedInfoNode:
683 * The SignedInfo Element (http://www.w3.org/TR/xmldsig-core/#sec-SignedInfo)
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.
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
698 * <element name="SignedInfo" type="ds:SignedInfoType"/>
699 * <complexType name="SignedInfoType">
701 * <element ref="ds:CanonicalizationMethod"/>
702 * <element ref="ds:SignatureMethod"/>
703 * <element ref="ds:Reference" maxOccurs="unbounded"/>
705 * <attribute name="Id" type="ID" use="optional"/>
710 * <!ELEMENT SignedInfo (CanonicalizationMethod, SignatureMethod, Reference+) >
711 * <!ATTLIST SignedInfo Id ID #IMPLIED>
715 xmlSecDSigCtxProcessSignedInfoNode(xmlSecDSigCtxPtr dsigCtx, xmlNodePtr node, xmlNodePtr * firstReferenceNode) {
716 xmlSecSize refNodesCount = 0;
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);
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,
736 "xmlSecTransformCtxNodeRead",
737 XMLSEC_ERRORS_R_XMLSEC_FAILED,
739 xmlSecErrorsSafeString(xmlSecNodeGetName(cur)));
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,
751 "xmlSecTransformCtxAppend",
752 XMLSEC_ERRORS_R_XMLSEC_FAILED,
753 XMLSEC_ERRORS_NO_MESSAGE);
757 xmlSecError(XMLSEC_ERRORS_HERE,
759 "CanonicalizationMethod",
760 XMLSEC_ERRORS_R_INVALID_NODE,
762 xmlSecErrorsSafeString(xmlSecNodeCanonicalizationMethod));
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,
774 "xmlSecTransformCtxCreateAndAppend",
775 XMLSEC_ERRORS_R_XMLSEC_FAILED,
777 xmlSecErrorsSafeString(xmlSecTransformKlassGetName(xmlSecTransformMemBufId)));
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,
789 "xmlSecTransformCtxNodeRead",
790 XMLSEC_ERRORS_R_XMLSEC_FAILED,
792 xmlSecErrorsSafeString(xmlSecNodeGetName(cur)));
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,
804 "xmlSecTransformCtxAppend",
805 XMLSEC_ERRORS_R_XMLSEC_FAILED,
806 XMLSEC_ERRORS_NO_MESSAGE);
810 xmlSecError(XMLSEC_ERRORS_HERE,
812 xmlSecErrorsSafeString(xmlSecNodeGetName(cur)),
813 XMLSEC_ERRORS_R_INVALID_NODE,
815 xmlSecErrorsSafeString(xmlSecNodeSignatureMethod));
818 dsigCtx->signMethod->operation = dsigCtx->operation;
820 /* read references */
822 cur = xmlSecGetNextElementNode(cur->next);
824 while((cur != NULL) && (xmlSecCheckNodeName(cur, xmlSecNodeReference, xmlSecDSigNs))) {
825 /* record first reference node */
826 if((*firstReferenceNode) == NULL) {
827 (*firstReferenceNode) = cur;
832 cur = xmlSecGetNextElementNode(cur->next);
835 /* check that we have at least one Reference */
836 if(refNodesCount == 0) {
837 xmlSecError(XMLSEC_ERRORS_HERE,
840 XMLSEC_ERRORS_R_DSIG_NO_REFERENCES,
841 XMLSEC_ERRORS_NO_MESSAGE);
845 /* if there is something left than it's an error */
847 xmlSecError(XMLSEC_ERRORS_HERE,
849 xmlSecErrorsSafeString(xmlSecNodeGetName(cur)),
850 XMLSEC_ERRORS_R_UNEXPECTED_NODE,
851 XMLSEC_ERRORS_NO_MESSAGE);
861 xmlSecDSigCtxProcessReferences(xmlSecDSigCtxPtr dsigCtx, xmlNodePtr firstReferenceNode) {
862 xmlSecDSigReferenceCtxPtr dsigRefCtx;
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);
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,
878 xmlSecErrorsSafeString(xmlSecNodeGetName(cur)),
879 XMLSEC_ERRORS_R_INVALID_NODE,
881 xmlSecErrorsSafeString(xmlSecNodeReference));
885 /* create reference */
886 dsigRefCtx = xmlSecDSigReferenceCtxCreate(dsigCtx, xmlSecDSigReferenceOriginSignedInfo);
887 if(dsigRefCtx == NULL) {
888 xmlSecError(XMLSEC_ERRORS_HERE,
890 "xmlSecDSigReferenceCtxCreate",
891 XMLSEC_ERRORS_R_XMLSEC_FAILED,
892 XMLSEC_ERRORS_NO_MESSAGE);
896 /* add to the list */
897 ret = xmlSecPtrListAdd(&(dsigCtx->signedInfoReferences), dsigRefCtx);
899 xmlSecError(XMLSEC_ERRORS_HERE,
902 XMLSEC_ERRORS_R_XMLSEC_FAILED,
903 XMLSEC_ERRORS_NO_MESSAGE);
904 xmlSecDSigReferenceCtxDestroy(dsigRefCtx);
909 ret = xmlSecDSigReferenceCtxProcessNode(dsigRefCtx, cur);
911 xmlSecError(XMLSEC_ERRORS_HERE,
913 "xmlSecDSigReferenceCtxProcessNode",
914 XMLSEC_ERRORS_R_XMLSEC_FAILED,
916 xmlSecErrorsSafeString(xmlSecNodeGetName(cur)));
920 /* bail out if next Reference processing failed */
921 if(dsigRefCtx->status != xmlSecDSigStatusSucceeded) {
922 dsigCtx->status = xmlSecDSigStatusInvalid;
933 xmlSecDSigCtxProcessKeyInfoNode(xmlSecDSigCtxPtr dsigCtx, xmlNodePtr node) {
936 xmlSecAssert2(dsigCtx != NULL, -1);
937 xmlSecAssert2(dsigCtx->signMethod != NULL, -1);
939 /* set key requirements */
940 ret = xmlSecTransformSetKeyReq(dsigCtx->signMethod, &(dsigCtx->keyInfoReadCtx.keyReq));
942 xmlSecError(XMLSEC_ERRORS_HERE,
944 "xmlSecTransformSetKeyReq",
945 XMLSEC_ERRORS_R_XMLSEC_FAILED,
947 xmlSecErrorsSafeString(xmlSecTransformGetName(dsigCtx->signMethod)));
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));
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,
963 XMLSEC_ERRORS_R_KEY_NOT_FOUND,
964 XMLSEC_ERRORS_NO_MESSAGE);
968 /* set the key to the transform */
969 ret = xmlSecTransformSetKey(dsigCtx->signMethod, dsigCtx->signKey);
971 xmlSecError(XMLSEC_ERRORS_HERE,
973 "xmlSecTransformSetKey",
974 XMLSEC_ERRORS_R_XMLSEC_FAILED,
976 xmlSecErrorsSafeString(xmlSecTransformGetName(dsigCtx->signMethod)));
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));
984 xmlSecError(XMLSEC_ERRORS_HERE,
986 "xmlSecKeyInfoNodeWrite",
987 XMLSEC_ERRORS_R_XMLSEC_FAILED,
988 XMLSEC_ERRORS_NO_MESSAGE);
997 * xmlSecDSigCtxProcessObjectNode:
999 * The Object Element (http://www.w3.org/TR/xmldsig-core/#sec-Object)
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.
1005 * Schema Definition:
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"/>
1012 * <attribute name="Id" type="ID" use="optional"/>
1013 * <attribute name="MimeType" type="string" use="optional"/>
1014 * <attribute name="Encoding" type="anyURI" use="optional"/>
1019 * <!ELEMENT Object (#PCDATA|Signature|SignatureProperties|Manifest %Object.ANY;)* >
1020 * <!ATTLIST Object Id ID #IMPLIED
1021 * MimeType CDATA #IMPLIED
1022 * Encoding CDATA #IMPLIED >
1025 xmlSecDSigCtxProcessObjectNode(xmlSecDSigCtxPtr dsigCtx, xmlNodePtr node) {
1029 xmlSecAssert2(dsigCtx != NULL, -1);
1030 xmlSecAssert2(dsigCtx->status == xmlSecDSigStatusUnknown, -1);
1031 xmlSecAssert2(node != NULL, -1);
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);
1039 xmlSecError(XMLSEC_ERRORS_HERE,
1041 "xmlSecDSigCtxProcessManifestNode",
1042 XMLSEC_ERRORS_R_XMLSEC_FAILED,
1043 XMLSEC_ERRORS_NO_MESSAGE);
1047 cur = xmlSecGetNextElementNode(cur->next);
1053 * xmlSecDSigCtxProcessManifestNode:
1055 * The Manifest Element (http://www.w3.org/TR/xmldsig-core/#sec-Manifest)
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.
1067 * Schema Definition:
1069 * <element name="Manifest" type="ds:ManifestType"/>
1070 * <complexType name="ManifestType">
1072 * <element ref="ds:Reference" maxOccurs="unbounded"/>
1074 * <attribute name="Id" type="ID" use="optional"/>
1079 * <!ELEMENT Manifest (Reference+) >
1080 * <!ATTLIST Manifest Id ID #IMPLIED >
1083 xmlSecDSigCtxProcessManifestNode(xmlSecDSigCtxPtr dsigCtx, xmlNodePtr node) {
1084 xmlSecDSigReferenceCtxPtr dsigRefCtx;
1088 xmlSecAssert2(dsigCtx != NULL, -1);
1089 xmlSecAssert2(dsigCtx->status == xmlSecDSigStatusUnknown, -1);
1090 xmlSecAssert2(node != NULL, -1);
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,
1100 "xmlSecDSigReferenceCtxCreate",
1101 XMLSEC_ERRORS_R_XMLSEC_FAILED,
1102 XMLSEC_ERRORS_NO_MESSAGE);
1106 /* add to the list */
1107 ret = xmlSecPtrListAdd(&(dsigCtx->manifestReferences), dsigRefCtx);
1109 xmlSecError(XMLSEC_ERRORS_HERE,
1112 XMLSEC_ERRORS_R_XMLSEC_FAILED,
1113 XMLSEC_ERRORS_NO_MESSAGE);
1114 xmlSecDSigReferenceCtxDestroy(dsigRefCtx);
1119 ret = xmlSecDSigReferenceCtxProcessNode(dsigRefCtx, cur);
1121 xmlSecError(XMLSEC_ERRORS_HERE,
1123 "xmlSecDSigReferenceCtxProcessNode",
1124 XMLSEC_ERRORS_R_XMLSEC_FAILED,
1126 xmlSecErrorsSafeString(xmlSecNodeGetName(cur)));
1130 /* we don;t care if Reference processing failed because
1131 * it's Manifest node */
1132 cur = xmlSecGetNextElementNode(cur->next);
1135 /* we should have nothing else here */
1137 xmlSecError(XMLSEC_ERRORS_HERE,
1139 xmlSecErrorsSafeString(xmlSecNodeGetName(cur)),
1140 XMLSEC_ERRORS_R_UNEXPECTED_NODE,
1141 XMLSEC_ERRORS_NO_MESSAGE);
1148 * xmlSecDSigCtxDebugDump:
1149 * @dsigCtx: the pointer to <dsig:Signature/> processing context.
1150 * @output: the pointer to output FILE.
1152 * Prints the debug information about @dsigCtx to @output.
1155 xmlSecDSigCtxDebugDump(xmlSecDSigCtxPtr dsigCtx, FILE* output) {
1156 xmlSecAssert(dsigCtx != NULL);
1157 xmlSecAssert(output != NULL);
1159 if(dsigCtx->operation == xmlSecTransformOperationSign) {
1160 fprintf(output, "= SIGNATURE CONTEXT\n");
1162 fprintf(output, "= VERIFICATION CONTEXT\n");
1164 switch(dsigCtx->status) {
1165 case xmlSecDSigStatusUnknown:
1166 fprintf(output, "== Status: unknown\n");
1168 case xmlSecDSigStatusSucceeded:
1169 fprintf(output, "== Status: succeeded\n");
1171 case xmlSecDSigStatusInvalid:
1172 fprintf(output, "== Status: invalid\n");
1175 fprintf(output, "== flags: 0x%08x\n", dsigCtx->flags);
1176 fprintf(output, "== flags2: 0x%08x\n", dsigCtx->flags2);
1178 if(dsigCtx->id != NULL) {
1179 fprintf(output, "== Id: \"%s\"\n", dsigCtx->id);
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);
1187 fprintf(output, "== Signature Transform Ctx:\n");
1188 xmlSecTransformCtxDebugDump(&(dsigCtx->transformCtx), output);
1190 if(dsigCtx->signMethod != NULL) {
1191 fprintf(output, "== Signature Method:\n");
1192 xmlSecTransformDebugDump(dsigCtx->signMethod, output);
1195 if(dsigCtx->signKey != NULL) {
1196 fprintf(output, "== Signature Key:\n");
1197 xmlSecKeyDebugDump(dsigCtx->signKey, output);
1200 fprintf(output, "== SignedInfo References List:\n");
1201 xmlSecPtrListDebugDump(&(dsigCtx->signedInfoReferences), output);
1203 fprintf(output, "== Manifest References List:\n");
1204 xmlSecPtrListDebugDump(&(dsigCtx->manifestReferences), output);
1206 if((dsigCtx->result != NULL) &&
1207 (xmlSecBufferGetData(dsigCtx->result) != NULL)) {
1209 fprintf(output, "== Result - start buffer:\n");
1210 (void)fwrite(xmlSecBufferGetData(dsigCtx->result),
1211 xmlSecBufferGetSize(dsigCtx->result),
1213 fprintf(output, "\n== Result - end buffer\n");
1215 if(((dsigCtx->flags & XMLSEC_DSIG_FLAGS_STORE_SIGNATURE) != 0) &&
1216 (xmlSecDSigCtxGetPreSignBuffer(dsigCtx) != NULL) &&
1217 (xmlSecBufferGetData(xmlSecDSigCtxGetPreSignBuffer(dsigCtx)) != NULL)) {
1219 fprintf(output, "== PreSigned data - start buffer:\n");
1220 (void)fwrite(xmlSecBufferGetData(xmlSecDSigCtxGetPreSignBuffer(dsigCtx)),
1221 xmlSecBufferGetSize(xmlSecDSigCtxGetPreSignBuffer(dsigCtx)),
1223 fprintf(output, "\n== PreSigned data - end buffer\n");
1228 * xmlSecDSigCtxDebugXmlDump:
1229 * @dsigCtx: the pointer to <dsig:Signature/> processing context.
1230 * @output: the pointer to output FILE.
1232 * Prints the debug information about @dsigCtx to @output in XML format.
1235 xmlSecDSigCtxDebugXmlDump(xmlSecDSigCtxPtr dsigCtx, FILE* output) {
1236 xmlSecAssert(dsigCtx != NULL);
1237 xmlSecAssert(output != NULL);
1239 if(dsigCtx->operation == xmlSecTransformOperationSign) {
1240 fprintf(output, "<SignatureContext \n");
1242 fprintf(output, "<VerificationContext \n");
1244 switch(dsigCtx->status) {
1245 case xmlSecDSigStatusUnknown:
1246 fprintf(output, "status=\"unknown\" >\n");
1248 case xmlSecDSigStatusSucceeded:
1249 fprintf(output, "status=\"succeeded\" >\n");
1251 case xmlSecDSigStatusInvalid:
1252 fprintf(output, "status=\"invalid\" >\n");
1256 fprintf(output, "<Flags>%08x</Flags>\n", dsigCtx->flags);
1257 fprintf(output, "<Flags2>%08x</Flags2>\n", dsigCtx->flags2);
1259 fprintf(output, "<Id>");
1260 xmlSecPrintXmlString(output, dsigCtx->id);
1261 fprintf(output, "</Id>\n");
1263 fprintf(output, "<KeyInfoReadCtx>\n");
1264 xmlSecKeyInfoCtxDebugXmlDump(&(dsigCtx->keyInfoReadCtx), output);
1265 fprintf(output, "</KeyInfoReadCtx>\n");
1267 fprintf(output, "<KeyInfoWriteCtx>\n");
1268 xmlSecKeyInfoCtxDebugXmlDump(&(dsigCtx->keyInfoWriteCtx), output);
1269 fprintf(output, "</KeyInfoWriteCtx>\n");
1271 fprintf(output, "<SignatureTransformCtx>\n");
1272 xmlSecTransformCtxDebugXmlDump(&(dsigCtx->transformCtx), output);
1273 fprintf(output, "</SignatureTransformCtx>\n");
1275 if(dsigCtx->signMethod != NULL) {
1276 fprintf(output, "<SignatureMethod>\n");
1277 xmlSecTransformDebugXmlDump(dsigCtx->signMethod, output);
1278 fprintf(output, "</SignatureMethod>\n");
1281 if(dsigCtx->signKey != NULL) {
1282 fprintf(output, "<SignatureKey>\n");
1283 xmlSecKeyDebugXmlDump(dsigCtx->signKey, output);
1284 fprintf(output, "</SignatureKey>\n");
1287 fprintf(output, "<SignedInfoReferences>\n");
1288 xmlSecPtrListDebugXmlDump(&(dsigCtx->signedInfoReferences), output);
1289 fprintf(output, "</SignedInfoReferences>\n");
1291 fprintf(output, "<ManifestReferences>\n");
1292 xmlSecPtrListDebugXmlDump(&(dsigCtx->manifestReferences), output);
1293 fprintf(output, "</ManifestReferences>\n");
1295 if((dsigCtx->result != NULL) &&
1296 (xmlSecBufferGetData(dsigCtx->result) != NULL)) {
1298 fprintf(output, "<Result>");
1299 (void)fwrite(xmlSecBufferGetData(dsigCtx->result),
1300 xmlSecBufferGetSize(dsigCtx->result),
1302 fprintf(output, "</Result>\n");
1304 if(((dsigCtx->flags & XMLSEC_DSIG_FLAGS_STORE_SIGNATURE) != 0) &&
1305 (xmlSecDSigCtxGetPreSignBuffer(dsigCtx) != NULL) &&
1306 (xmlSecBufferGetData(xmlSecDSigCtxGetPreSignBuffer(dsigCtx)) != NULL)) {
1308 fprintf(output, "<PreSignedData>");
1309 (void)fwrite(xmlSecBufferGetData(xmlSecDSigCtxGetPreSignBuffer(dsigCtx)),
1310 xmlSecBufferGetSize(xmlSecDSigCtxGetPreSignBuffer(dsigCtx)),
1312 fprintf(output, "</PreSignedData>\n");
1315 if(dsigCtx->operation == xmlSecTransformOperationSign) {
1316 fprintf(output, "</SignatureContext>\n");
1318 fprintf(output, "</VerificationContext>\n");
1322 /**************************************************************************
1324 * xmlSecDSigReferenceCtx
1326 *************************************************************************/
1328 * xmlSecDSigReferenceCtxCreate:
1329 * @dsigCtx: the pointer to parent <dsig:Signature/> node processing context.
1330 * @origin: the reference origin (<dsig:SignedInfo/> or <dsig:Manifest/> node).
1332 * Creates new <dsig:Reference/> element processing context. Caller is responsible
1333 * for destroying the returned context by calling #xmlSecDSigReferenceCtxDestroy
1336 * Returns: pointer to newly created context or NULL if an error occurs.
1338 xmlSecDSigReferenceCtxPtr
1339 xmlSecDSigReferenceCtxCreate(xmlSecDSigCtxPtr dsigCtx, xmlSecDSigReferenceOrigin origin) {
1340 xmlSecDSigReferenceCtxPtr dsigRefCtx;
1343 xmlSecAssert2(dsigCtx != NULL, NULL);
1345 dsigRefCtx = (xmlSecDSigReferenceCtxPtr) xmlMalloc(sizeof(xmlSecDSigReferenceCtx));
1346 if(dsigRefCtx == NULL) {
1347 xmlSecError(XMLSEC_ERRORS_HERE,
1350 XMLSEC_ERRORS_R_MALLOC_FAILED,
1351 "sizeof(xmlSecDSigReferenceCtx)=%d",
1352 (int)sizeof(xmlSecDSigReferenceCtx));
1356 ret = xmlSecDSigReferenceCtxInitialize(dsigRefCtx, dsigCtx, origin);
1358 xmlSecError(XMLSEC_ERRORS_HERE,
1360 "xmlSecDSigReferenceCtxInitialize",
1361 XMLSEC_ERRORS_R_XMLSEC_FAILED,
1362 XMLSEC_ERRORS_NO_MESSAGE);
1363 xmlSecDSigReferenceCtxDestroy(dsigRefCtx);
1370 * xmlSecDSigReferenceCtxDestroy:
1371 * @dsigRefCtx: the pointer to <dsig:Reference/> element processing context.
1373 * Destroy context object created with #xmlSecDSigReferenceCtxCreate function.
1376 xmlSecDSigReferenceCtxDestroy(xmlSecDSigReferenceCtxPtr dsigRefCtx) {
1377 xmlSecAssert(dsigRefCtx != NULL);
1379 xmlSecDSigReferenceCtxFinalize(dsigRefCtx);
1380 xmlFree(dsigRefCtx);
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).
1389 * Initializes new <dsig:Reference/> element processing context. Caller is responsible
1390 * for cleaning up the returned context by calling #xmlSecDSigReferenceCtxFinalize
1393 * Returns: 0 on succes or aa negative value otherwise.
1396 xmlSecDSigReferenceCtxInitialize(xmlSecDSigReferenceCtxPtr dsigRefCtx, xmlSecDSigCtxPtr dsigCtx,
1397 xmlSecDSigReferenceOrigin origin) {
1400 xmlSecAssert2(dsigCtx != NULL, -1);
1401 xmlSecAssert2(dsigRefCtx != NULL, -1);
1403 memset(dsigRefCtx, 0, sizeof(xmlSecDSigReferenceCtx));
1405 dsigRefCtx->dsigCtx = dsigCtx;
1406 dsigRefCtx->origin = origin;
1408 /* initializes transforms dsigRefCtx */
1409 ret = xmlSecTransformCtxInitialize(&(dsigRefCtx->transformCtx));
1411 xmlSecError(XMLSEC_ERRORS_HERE,
1413 "xmlSecTransformCtxInitialize",
1414 XMLSEC_ERRORS_R_XMLSEC_FAILED,
1415 XMLSEC_ERRORS_NO_MESSAGE);
1419 /* copy enabled transforms */
1420 if(dsigCtx->enabledReferenceTransforms != NULL) {
1421 ret = xmlSecPtrListCopy(&(dsigRefCtx->transformCtx.enabledTransforms),
1422 dsigCtx->enabledReferenceTransforms);
1424 xmlSecError(XMLSEC_ERRORS_HERE,
1426 "xmlSecPtrListCopy",
1427 XMLSEC_ERRORS_R_XMLSEC_FAILED,
1428 XMLSEC_ERRORS_NO_MESSAGE);
1432 dsigRefCtx->transformCtx.preExecCallback = dsigCtx->referencePreExecuteCallback;
1433 dsigRefCtx->transformCtx.enabledUris = dsigCtx->enabledReferenceUris;
1435 if((dsigCtx->flags & XMLSEC_DSIG_FLAGS_USE_VISA3D_HACK) != 0) {
1436 dsigRefCtx->transformCtx.flags |= XMLSEC_TRANSFORMCTX_FLAGS_USE_VISA3D_HACK;
1442 * xmlSecDSigReferenceCtxFinalize:
1443 * @dsigRefCtx: the pointer to <dsig:Reference/> element processing context.
1445 * Cleans up context object created with #xmlSecDSigReferenceCtxInitialize function.
1448 xmlSecDSigReferenceCtxFinalize(xmlSecDSigReferenceCtxPtr dsigRefCtx) {
1449 xmlSecAssert(dsigRefCtx != NULL);
1451 xmlSecTransformCtxFinalize(&(dsigRefCtx->transformCtx));
1452 if(dsigRefCtx->id != NULL) {
1453 xmlFree(dsigRefCtx->id);
1455 if(dsigRefCtx->uri != NULL) {
1456 xmlFree(dsigRefCtx->uri);
1458 if(dsigRefCtx->type != NULL) {
1459 xmlFree(dsigRefCtx->type);
1461 memset(dsigRefCtx, 0, sizeof(xmlSecDSigReferenceCtx));
1465 * xmlSecDSigReferenceCtxGetPreDigestBuffer:
1466 * @dsigRefCtx: the pointer to <dsig:Reference/> element processing context.
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
1473 * Returns: pointer to the buffer or NULL if an error occurs.
1476 xmlSecDSigReferenceCtxGetPreDigestBuffer(xmlSecDSigReferenceCtxPtr dsigRefCtx) {
1477 xmlSecAssert2(dsigRefCtx != NULL, NULL);
1479 return((dsigRefCtx->preDigestMemBufMethod != NULL) ?
1480 xmlSecTransformMemBufGetBuffer(dsigRefCtx->preDigestMemBufMethod) : NULL);
1484 * xmlSecDSigReferenceCtxProcessNode:
1485 * @dsigRefCtx: the pointer to <dsig:Reference/> element processing context.
1486 * @node: the pointer to <dsig:Reference/> node.
1488 * The Reference Element (http://www.w3.org/TR/xmldsig-core/#sec-Reference)
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
1501 * Returns: 0 on succes or aa negative value otherwise.
1504 xmlSecDSigReferenceCtxProcessNode(xmlSecDSigReferenceCtxPtr dsigRefCtx, xmlNodePtr node) {
1505 xmlSecTransformCtxPtr transformCtx;
1506 xmlNodePtr digestValueNode;
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);
1518 transformCtx = &(dsigRefCtx->transformCtx);
1520 /* read attributes first */
1521 dsigRefCtx->uri = xmlGetProp(node, xmlSecAttrURI);
1522 dsigRefCtx->id = xmlGetProp(node, xmlSecAttrId);
1523 dsigRefCtx->type= xmlGetProp(node, xmlSecAttrType);
1525 /* set start URI (and check that it is enabled!) */
1526 ret = xmlSecTransformCtxSetUri(transformCtx, dsigRefCtx->uri, node);
1528 xmlSecError(XMLSEC_ERRORS_HERE,
1530 "xmlSecTransformCtxSetUri",
1531 XMLSEC_ERRORS_R_XMLSEC_FAILED,
1533 xmlSecErrorsSafeString(dsigRefCtx->uri));
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);
1543 xmlSecError(XMLSEC_ERRORS_HERE,
1545 "xmlSecTransformCtxNodesListRead",
1546 XMLSEC_ERRORS_R_XMLSEC_FAILED,
1548 xmlSecErrorsSafeString(xmlSecNodeGetName(cur)));
1552 cur = xmlSecGetNextElementNode(cur->next);
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))) {
1561 xmlSecAssert2(dsigRefCtx->preDigestMemBufMethod == NULL, -1);
1562 dsigRefCtx->preDigestMemBufMethod = xmlSecTransformCtxCreateAndAppend(
1564 xmlSecTransformMemBufId);
1565 if(dsigRefCtx->preDigestMemBufMethod == NULL) {
1566 xmlSecError(XMLSEC_ERRORS_HERE,
1568 "xmlSecTransformCtxCreateAndAppend",
1569 XMLSEC_ERRORS_R_XMLSEC_FAILED,
1571 xmlSecErrorsSafeString(xmlSecTransformKlassGetName(xmlSecTransformMemBufId)));
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,
1583 "xmlSecTransformCtxNodeRead",
1584 XMLSEC_ERRORS_R_XMLSEC_FAILED,
1586 xmlSecErrorsSafeString(xmlSecNodeGetName(cur)));
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,
1600 "xmlSecTransformCtxAppend",
1601 XMLSEC_ERRORS_R_XMLSEC_FAILED,
1602 XMLSEC_ERRORS_NO_MESSAGE);
1606 xmlSecError(XMLSEC_ERRORS_HERE,
1608 xmlSecErrorsSafeString(xmlSecNodeGetName(cur)),
1609 XMLSEC_ERRORS_R_INVALID_NODE,
1611 xmlSecErrorsSafeString(xmlSecNodeDigestMethod));
1614 dsigRefCtx->digestMethod->operation = dsigRefCtx->dsigCtx->operation;
1616 /* last node is required DigestValue */
1617 if((cur != NULL) && (xmlSecCheckNodeName(cur, xmlSecNodeDigestValue, xmlSecDSigNs))) {
1618 digestValueNode = cur;
1619 cur = xmlSecGetNextElementNode(cur->next);
1621 xmlSecError(XMLSEC_ERRORS_HERE,
1623 xmlSecErrorsSafeString(xmlSecNodeGetName(cur)),
1624 XMLSEC_ERRORS_R_XMLSEC_FAILED,
1626 xmlSecErrorsSafeString(xmlSecNodeDigestValue));
1630 /* if we have something else then it's an error */
1632 xmlSecError(XMLSEC_ERRORS_HERE,
1634 xmlSecErrorsSafeString(xmlSecNodeGetName(cur)),
1635 XMLSEC_ERRORS_R_UNEXPECTED_NODE,
1636 XMLSEC_ERRORS_NO_MESSAGE);
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;
1644 /* we need to add base64 encode transform */
1645 base64Encode = xmlSecTransformCtxCreateAndAppend(transformCtx, xmlSecTransformBase64Id);
1646 if(base64Encode == NULL) {
1647 xmlSecError(XMLSEC_ERRORS_HERE,
1649 "xmlSecTransformCtxCreateAndAppend",
1650 XMLSEC_ERRORS_R_XMLSEC_FAILED,
1651 XMLSEC_ERRORS_NO_MESSAGE);
1654 base64Encode->operation = xmlSecTransformOperationEncode;
1657 /* finally get transforms results */
1658 ret = xmlSecTransformCtxExecute(transformCtx, node->doc);
1660 snprintf(logMsg, sizeof(logMsg), "uri:%s", (char*)dsigRefCtx->uri);
1661 logMsg[strlen(dsigRefCtx->uri)+5] = '\0';
1662 xmlSecError(XMLSEC_ERRORS_HERE,
1664 "xmlSecTransformCtxExecute",
1665 XMLSEC_ERRORS_R_XMLSEC_FAILED,
1669 dsigRefCtx->result = transformCtx->result;
1671 if(dsigRefCtx->dsigCtx->operation == xmlSecTransformOperationSign) {
1672 if((dsigRefCtx->result == NULL) || (xmlSecBufferGetData(dsigRefCtx->result) == NULL)) {
1673 xmlSecError(XMLSEC_ERRORS_HERE,
1675 "xmlSecTransformCtxExecute",
1676 XMLSEC_ERRORS_R_XMLSEC_FAILED,
1677 XMLSEC_ERRORS_NO_MESSAGE);
1681 /* write signed data to xml */
1682 xmlNodeSetContentLen(digestValueNode,
1683 xmlSecBufferGetData(dsigRefCtx->result),
1684 xmlSecBufferGetSize(dsigRefCtx->result));
1686 /* set success status and we are done */
1687 dsigRefCtx->status = xmlSecDSigStatusSucceeded;
1689 /* verify SignatureValue node content */
1690 ret = xmlSecTransformVerifyNodeContent(dsigRefCtx->digestMethod,
1691 digestValueNode, transformCtx);
1693 snprintf(logMsg, sizeof(logMsg), "uri:%s", (char*)dsigRefCtx->uri);
1694 logMsg[strlen(dsigRefCtx->uri)+5] = '\0';
1695 xmlSecError(XMLSEC_ERRORS_HERE,
1697 "xmlSecTransformVerifyNodeContent",
1698 XMLSEC_ERRORS_R_XMLSEC_FAILED,
1703 /* set status and we are done */
1704 if(dsigRefCtx->digestMethod->status == xmlSecTransformStatusOk) {
1705 dsigRefCtx->status = xmlSecDSigStatusSucceeded;
1707 dsigRefCtx->status = xmlSecDSigStatusInvalid;
1715 * xmlSecDSigReferenceCtxDebugDump:
1716 * @dsigRefCtx: the pointer to <dsig:Reference/> element processing context.
1717 * @output: the pointer to output FILE.
1719 * Prints debug information about @dsigRefCtx to @output.
1722 xmlSecDSigReferenceCtxDebugDump(xmlSecDSigReferenceCtxPtr dsigRefCtx, FILE* output) {
1723 xmlSecAssert(dsigRefCtx != NULL);
1724 xmlSecAssert(dsigRefCtx->dsigCtx != NULL);
1725 xmlSecAssert(output != NULL);
1727 if(dsigRefCtx->dsigCtx->operation == xmlSecTransformOperationSign) {
1728 fprintf(output, "= REFERENCE CALCULATION CONTEXT\n");
1730 fprintf(output, "= REFERENCE VERIFICATION CONTEXT\n");
1732 switch(dsigRefCtx->status) {
1733 case xmlSecDSigStatusUnknown:
1734 fprintf(output, "== Status: unknown\n");
1736 case xmlSecDSigStatusSucceeded:
1737 fprintf(output, "== Status: succeeded\n");
1739 case xmlSecDSigStatusInvalid:
1740 fprintf(output, "== Status: invalid\n");
1743 if(dsigRefCtx->id != NULL) {
1744 fprintf(output, "== Id: \"%s\"\n", dsigRefCtx->id);
1746 if(dsigRefCtx->uri != NULL) {
1747 fprintf(output, "== URI: \"%s\"\n", dsigRefCtx->uri);
1749 if(dsigRefCtx->type != NULL) {
1750 fprintf(output, "== Type: \"%s\"\n", dsigRefCtx->type);
1753 fprintf(output, "== Reference Transform Ctx:\n");
1754 xmlSecTransformCtxDebugDump(&(dsigRefCtx->transformCtx), output);
1756 if(dsigRefCtx->digestMethod != NULL) {
1757 fprintf(output, "== Digest Method:\n");
1758 xmlSecTransformDebugDump(dsigRefCtx->digestMethod, output);
1761 if((xmlSecDSigReferenceCtxGetPreDigestBuffer(dsigRefCtx) != NULL) &&
1762 (xmlSecBufferGetData(xmlSecDSigReferenceCtxGetPreDigestBuffer(dsigRefCtx)) != NULL)) {
1764 fprintf(output, "== PreDigest data - start buffer:\n");
1765 (void)fwrite(xmlSecBufferGetData(xmlSecDSigReferenceCtxGetPreDigestBuffer(dsigRefCtx)),
1766 xmlSecBufferGetSize(xmlSecDSigReferenceCtxGetPreDigestBuffer(dsigRefCtx)),
1768 fprintf(output, "\n== PreDigest data - end buffer\n");
1771 if((dsigRefCtx->result != NULL) &&
1772 (xmlSecBufferGetData(dsigRefCtx->result) != NULL)) {
1774 fprintf(output, "== Result - start buffer:\n");
1775 (void)fwrite(xmlSecBufferGetData(dsigRefCtx->result),
1776 xmlSecBufferGetSize(dsigRefCtx->result), 1,
1778 fprintf(output, "\n== Result - end buffer\n");
1783 * xmlSecDSigReferenceCtxDebugXmlDump:
1784 * @dsigRefCtx: the pointer to <dsig:Reference/> element processing context.
1785 * @output: the pointer to output FILE.
1787 * Prints debug information about @dsigRefCtx to @output in output format.
1790 xmlSecDSigReferenceCtxDebugXmlDump(xmlSecDSigReferenceCtxPtr dsigRefCtx, FILE* output) {
1791 xmlSecAssert(dsigRefCtx != NULL);
1792 xmlSecAssert(dsigRefCtx->dsigCtx != NULL);
1793 xmlSecAssert(output != NULL);
1795 if(dsigRefCtx->dsigCtx->operation == xmlSecTransformOperationSign) {
1796 fprintf(output, "<ReferenceCalculationContext ");
1798 fprintf(output, "<ReferenceVerificationContext ");
1800 switch(dsigRefCtx->status) {
1801 case xmlSecDSigStatusUnknown:
1802 fprintf(output, "status=\"unknown\" >\n");
1804 case xmlSecDSigStatusSucceeded:
1805 fprintf(output, "status=\"succeeded\" >\n");
1807 case xmlSecDSigStatusInvalid:
1808 fprintf(output, "status=\"invalid\" >\n");
1812 fprintf(output, "<Id>");
1813 xmlSecPrintXmlString(output, dsigRefCtx->id);
1814 fprintf(output, "</Id>\n");
1816 fprintf(output, "<URI>");
1817 xmlSecPrintXmlString(output, dsigRefCtx->uri);
1818 fprintf(output, "</URI>\n");
1820 fprintf(output, "<Type>");
1821 xmlSecPrintXmlString(output, dsigRefCtx->type);
1822 fprintf(output, "</Type>\n");
1824 fprintf(output, "<ReferenceTransformCtx>\n");
1825 xmlSecTransformCtxDebugXmlDump(&(dsigRefCtx->transformCtx), output);
1826 fprintf(output, "</ReferenceTransformCtx>\n");
1828 if(dsigRefCtx->digestMethod != NULL) {
1829 fprintf(output, "<DigestMethod>\n");
1830 xmlSecTransformDebugXmlDump(dsigRefCtx->digestMethod, output);
1831 fprintf(output, "</DigestMethod>\n");
1834 if((dsigRefCtx->result != NULL) &&
1835 (xmlSecBufferGetData(dsigRefCtx->result) != NULL)) {
1837 fprintf(output, "<Result>");
1838 (void)fwrite(xmlSecBufferGetData(dsigRefCtx->result),
1839 xmlSecBufferGetSize(dsigRefCtx->result), 1,
1841 fprintf(output, "</Result>\n");
1844 if((xmlSecDSigReferenceCtxGetPreDigestBuffer(dsigRefCtx) != NULL) &&
1845 (xmlSecBufferGetData(xmlSecDSigReferenceCtxGetPreDigestBuffer(dsigRefCtx)) != NULL)) {
1847 fprintf(output, "<PreDigestData>");
1848 (void)fwrite(xmlSecBufferGetData(xmlSecDSigReferenceCtxGetPreDigestBuffer(dsigRefCtx)),
1849 xmlSecBufferGetSize(xmlSecDSigReferenceCtxGetPreDigestBuffer(dsigRefCtx)),
1851 fprintf(output, "</PreDigestData>\n");
1853 if(dsigRefCtx->dsigCtx->operation == xmlSecTransformOperationSign) {
1854 fprintf(output, "</ReferenceCalculationContext>\n");
1856 fprintf(output, "</ReferenceVerificationContext>\n");
1863 xmlSecDSigCtxVerifyEx(xmlSecDSigCtxPtr dsigCtx, xmlNodePtr node, int noHash, void* pList) {
1870 xmlSecAssert2(dsigCtx != NULL, -1);
1871 xmlSecAssert2(node != NULL, -1);
1872 xmlSecAssert2(node->doc != NULL, -1);
1874 /* add ids for Signature nodes */
1875 dsigCtx->operation = xmlSecTransformOperationVerify;
1876 dsigCtx->status = xmlSecDSigStatusUnknown;
1877 xmlSecAddIDs(node->doc, node, xmlSecDSigIds);
1879 /* read siganture info */
1880 ret = xmlSecDSigCtxProcessSignatureNodeEx(dsigCtx, node, noHash, pList);
1882 xmlSecError(XMLSEC_ERRORS_HERE,
1884 "xmlSecDSigCtxProcessSignatureNodeEx",
1885 XMLSEC_ERRORS_R_XMLSEC_FAILED,
1886 XMLSEC_ERRORS_NO_MESSAGE);
1890 xmlSecAssert2(dsigCtx->signMethod != NULL, -1);
1891 xmlSecAssert2(dsigCtx->signValueNode != NULL, -1);
1893 /* references processing might change the status */
1894 if(dsigCtx->status != xmlSecDSigStatusUnknown) {
1898 /* verify SignatureValue node content */
1899 ret = xmlSecTransformVerifyNodeContent(dsigCtx->signMethod, dsigCtx->signValueNode,
1900 &(dsigCtx->transformCtx));
1902 xmlSecError(XMLSEC_ERRORS_HERE,
1904 "xmlSecTransformVerifyNodeContent",
1905 XMLSEC_ERRORS_R_XMLSEC_FAILED,
1906 XMLSEC_ERRORS_NO_MESSAGE);
1911 /* set status and we are done */
1912 if(dsigCtx->signMethod->status == xmlSecTransformStatusOk) {
1913 dsigCtx->status = xmlSecDSigStatusSucceeded;
1915 dsigCtx->status = xmlSecDSigStatusInvalid;
1922 xmlSecDSigCtxProcessSignatureNodeEx (xmlSecDSigCtxPtr dsigCtx, xmlNodePtr node, int noHash, void* pList) {
1923 xmlSecTransformDataType firstType;
1924 xmlNodePtr signedInfoNode = NULL;
1925 xmlNodePtr keyInfoNode = NULL;
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);
1939 if(!xmlSecCheckNodeName(node, xmlSecNodeSignature, xmlSecDSigNs)) {
1940 xmlSecError(XMLSEC_ERRORS_HERE,
1942 xmlSecErrorsSafeString(xmlSecNodeGetName(node)),
1943 XMLSEC_ERRORS_R_INVALID_NODE,
1945 xmlSecErrorsSafeString(xmlSecNodeSignature));
1949 /* read node data */
1950 xmlSecAssert2(dsigCtx->id == NULL, -1);
1951 dsigCtx->id = xmlGetProp(node, xmlSecAttrId);
1953 /* first node is required SignedInfo */
1954 cur = xmlSecGetNextElementNode(node->children);
1955 if((cur == NULL) || (!xmlSecCheckNodeName(cur, xmlSecNodeSignedInfo, xmlSecDSigNs))) {
1956 xmlSecError(XMLSEC_ERRORS_HERE,
1958 xmlSecErrorsSafeString(xmlSecNodeGetName(cur)),
1959 XMLSEC_ERRORS_R_INVALID_NODE,
1961 xmlSecErrorsSafeString(xmlSecNodeSignedInfo));
1964 signedInfoNode = cur;
1965 cur = xmlSecGetNextElementNode(cur->next);
1967 /* next node is required SignatureValue */
1968 if((cur == NULL) || (!xmlSecCheckNodeName(cur, xmlSecNodeSignatureValue, xmlSecDSigNs))) {
1969 xmlSecError(XMLSEC_ERRORS_HERE,
1971 xmlSecErrorsSafeString(xmlSecNodeGetName(cur)),
1972 XMLSEC_ERRORS_R_INVALID_NODE,
1974 xmlSecErrorsSafeString(xmlSecNodeSignatureValue));
1977 dsigCtx->signValueNode = cur;
1978 cur = xmlSecGetNextElementNode(cur->next);
1980 /* next node is optional KeyInfo */
1981 if((cur != NULL) && (xmlSecCheckNodeName(cur, xmlSecNodeKeyInfo, xmlSecDSigNs))) {
1983 cur = xmlSecGetNextElementNode(cur->next);
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);
1994 xmlSecError(XMLSEC_ERRORS_HERE,
1996 "xmlSecDSigCtxProcessObjectNode",
1997 XMLSEC_ERRORS_R_XMLSEC_FAILED,
1998 XMLSEC_ERRORS_NO_MESSAGE);
2002 cur = xmlSecGetNextElementNode(cur->next);
2005 /* if there is something left than it's an error */
2007 xmlSecError(XMLSEC_ERRORS_HERE,
2009 xmlSecErrorsSafeString(xmlSecNodeGetName(cur)),
2010 XMLSEC_ERRORS_R_UNEXPECTED_NODE,
2011 XMLSEC_ERRORS_NO_MESSAGE);
2015 /* now validated all the references and prepare transform */
2016 ret = xmlSecDSigCtxProcessSignedInfoNodeEx(dsigCtx, signedInfoNode, noHash, pList);
2018 xmlSecError(XMLSEC_ERRORS_HERE,
2020 "xmlSecDSigCtxProcessSignedInfoNodeEx",
2021 XMLSEC_ERRORS_R_XMLSEC_FAILED,
2022 XMLSEC_ERRORS_NO_MESSAGE);
2025 /* references processing might change the status */
2026 if(dsigCtx->status != xmlSecDSigStatusUnknown) {
2030 /* as the result, we should have sign and c14n methods set */
2031 xmlSecAssert2(dsigCtx->signMethod != NULL, -1);
2032 xmlSecAssert2(dsigCtx->c14nMethod != NULL, -1);
2034 ret = xmlSecDSigCtxProcessKeyInfoNode(dsigCtx, keyInfoNode);
2036 xmlSecError(XMLSEC_ERRORS_HERE,
2038 "xmlSecDSigCtxProcessKeyInfoNode",
2039 XMLSEC_ERRORS_R_XMLSEC_FAILED,
2040 XMLSEC_ERRORS_NO_MESSAGE);
2043 /* as the result, we should have a key */
2044 xmlSecAssert2(dsigCtx->signKey != NULL, -1);
2046 /* if we need to write result to xml node then we need base64 encode result */
2047 if(dsigCtx->operation == xmlSecTransformOperationSign) {
2048 xmlSecTransformPtr base64Encode;
2050 /* we need to add base64 encode transform */
2051 base64Encode = xmlSecTransformCtxCreateAndAppend(&(dsigCtx->transformCtx),
2052 xmlSecTransformBase64Id);
2053 if(base64Encode == NULL) {
2054 xmlSecError(XMLSEC_ERRORS_HERE,
2056 "xmlSecTransformCtxCreateAndAppend",
2057 XMLSEC_ERRORS_R_XMLSEC_FAILED,
2058 XMLSEC_ERRORS_NO_MESSAGE);
2061 base64Encode->operation = xmlSecTransformOperationEncode;
2064 firstType = xmlSecTransformGetDataType(dsigCtx->transformCtx.first,
2065 xmlSecTransformModePush, &(dsigCtx->transformCtx));
2066 if((firstType & xmlSecTransformDataTypeXml) != 0) {
2067 xmlSecNodeSetPtr nodeset = NULL;
2069 xmlSecAssert2(signedInfoNode != NULL, -1);
2070 nodeset = xmlSecNodeSetGetChildren(signedInfoNode->doc, signedInfoNode, 1, 0);
2071 if(nodeset == NULL) {
2072 xmlSecError(XMLSEC_ERRORS_HERE,
2074 "xmlSecNodeSetGetChildren",
2075 XMLSEC_ERRORS_R_XMLSEC_FAILED,
2077 xmlSecErrorsSafeString(xmlSecNodeGetName(signedInfoNode)));
2081 /* calculate the signature */
2082 ret = xmlSecTransformCtxXmlExecute(&(dsigCtx->transformCtx), nodeset);
2084 xmlSecError(XMLSEC_ERRORS_HERE,
2086 "xmlSecTransformCtxXmlExecute",
2087 XMLSEC_ERRORS_R_XMLSEC_FAILED,
2088 XMLSEC_ERRORS_NO_MESSAGE);
2089 xmlSecNodeSetDestroy(nodeset);
2092 xmlSecNodeSetDestroy(nodeset);
2095 xmlSecError(XMLSEC_ERRORS_HERE,
2097 "the binary c14n transforms are not supported yet",
2098 XMLSEC_ERRORS_R_NOT_IMPLEMENTED,
2099 XMLSEC_ERRORS_NO_MESSAGE);
2107 xmlSecDSigCtxProcessSignedInfoNodeEx(xmlSecDSigCtxPtr dsigCtx, xmlNodePtr node, int noHash, void* pList) {
2108 xmlSecDSigReferenceCtxPtr dsigRefCtx;
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);
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,
2129 "xmlSecTransformCtxNodeRead",
2130 XMLSEC_ERRORS_R_XMLSEC_FAILED,
2132 xmlSecErrorsSafeString(xmlSecNodeGetName(cur)));
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,
2145 "xmlSecTransformCtxAppend",
2146 XMLSEC_ERRORS_R_XMLSEC_FAILED,
2147 XMLSEC_ERRORS_NO_MESSAGE);
2152 xmlSecError(XMLSEC_ERRORS_HERE,
2154 "CanonicalizationMethod",
2155 XMLSEC_ERRORS_R_INVALID_NODE,
2157 xmlSecErrorsSafeString(xmlSecNodeCanonicalizationMethod));
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,
2170 "xmlSecTransformCtxCreateAndAppend",
2171 XMLSEC_ERRORS_R_XMLSEC_FAILED,
2173 xmlSecErrorsSafeString(xmlSecTransformKlassGetName(xmlSecTransformMemBufId)));
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,
2185 "xmlSecTransformCtxNodeRead",
2186 XMLSEC_ERRORS_R_XMLSEC_FAILED,
2188 xmlSecErrorsSafeString(xmlSecNodeGetName(cur)));
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,
2201 "xmlSecTransformCtxAppend",
2202 XMLSEC_ERRORS_R_XMLSEC_FAILED,
2203 XMLSEC_ERRORS_NO_MESSAGE);
2208 xmlSecError(XMLSEC_ERRORS_HERE,
2210 xmlSecErrorsSafeString(xmlSecNodeGetName(cur)),
2211 XMLSEC_ERRORS_R_INVALID_NODE,
2213 xmlSecErrorsSafeString(xmlSecNodeSignatureMethod));
2217 dsigCtx->signMethod->operation = dsigCtx->operation;
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,
2227 "xmlSecDSigReferenceCtxCreate",
2228 XMLSEC_ERRORS_R_XMLSEC_FAILED,
2229 XMLSEC_ERRORS_NO_MESSAGE);
2234 /* add to the list */
2235 ret = xmlSecPtrListAdd(&(dsigCtx->signedInfoReferences), dsigRefCtx);
2237 xmlSecError(XMLSEC_ERRORS_HERE,
2240 XMLSEC_ERRORS_R_XMLSEC_FAILED,
2241 XMLSEC_ERRORS_NO_MESSAGE);
2242 xmlSecDSigReferenceCtxDestroy(dsigRefCtx);
2248 if(noHash != 1) { //if 0, then partial ///if 1, then no_hash
2249 ret = xmlSecDSigReferenceCtxProcessNodeEx(dsigRefCtx, cur, noHash, pList);
2251 xmlSecError(XMLSEC_ERRORS_HERE,
2253 "xmlSecDSigReferenceCtxProcessNode",
2254 XMLSEC_ERRORS_R_XMLSEC_FAILED,
2256 xmlSecErrorsSafeString(xmlSecNodeGetName(cur)));
2263 dsigRefCtx->status = xmlSecDSigStatusSucceeded;
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;
2272 cur = xmlSecGetNextElementNode(cur->next);
2275 /* check that we have at least one Reference */
2276 if(xmlSecPtrListGetSize(&(dsigCtx->signedInfoReferences)) == 0) {
2277 xmlSecError(XMLSEC_ERRORS_HERE,
2280 XMLSEC_ERRORS_R_DSIG_NO_REFERENCES,
2281 XMLSEC_ERRORS_NO_MESSAGE);
2286 /* if there is something left than it's an error */
2288 xmlSecError(XMLSEC_ERRORS_HERE,
2290 xmlSecErrorsSafeString(xmlSecNodeGetName(cur)),
2291 XMLSEC_ERRORS_R_UNEXPECTED_NODE,
2292 XMLSEC_ERRORS_NO_MESSAGE);
2302 xmlSecDSigReferenceCtxProcessNodeEx(xmlSecDSigReferenceCtxPtr dsigRefCtx, xmlNodePtr node, int noHash, void* pList) {
2303 xmlSecTransformCtxPtr transformCtx;
2304 xmlNodePtr digestValueNode;
2311 char** pNextTmp = (char**)pList;
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);
2323 transformCtx = &(dsigRefCtx->transformCtx);
2326 xmlSecError(XMLSEC_ERRORS_HERE,
2329 XMLSEC_ERRORS_R_UNEXPECTED_NODE,
2330 XMLSEC_ERRORS_NO_MESSAGE);
2334 /* read attributes first */
2335 dsigRefCtx->uri = xmlGetProp(node, xmlSecAttrURI);
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);
2348 if(cmpResult != 0) {
2353 dsigRefCtx->id = xmlGetProp(node, xmlSecAttrId);
2354 dsigRefCtx->type= xmlGetProp(node, xmlSecAttrType);
2356 /* set start URI (and check that it is enabled!) */
2357 ret = xmlSecTransformCtxSetUri(transformCtx, dsigRefCtx->uri, node);
2359 xmlSecError(XMLSEC_ERRORS_HERE,
2361 "xmlSecTransformCtxSetUri",
2362 XMLSEC_ERRORS_R_XMLSEC_FAILED,
2364 xmlSecErrorsSafeString(dsigRefCtx->uri));
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);
2374 xmlSecError(XMLSEC_ERRORS_HERE,
2376 "xmlSecTransformCtxNodesListRead",
2377 XMLSEC_ERRORS_R_XMLSEC_FAILED,
2379 xmlSecErrorsSafeString(xmlSecNodeGetName(cur)));
2382 cur = xmlSecGetNextElementNode(cur->next);
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(
2393 xmlSecTransformMemBufId);
2394 if(dsigRefCtx->preDigestMemBufMethod == NULL) {
2395 xmlSecError(XMLSEC_ERRORS_HERE,
2397 "xmlSecTransformCtxCreateAndAppend",
2398 XMLSEC_ERRORS_R_XMLSEC_FAILED,
2400 xmlSecErrorsSafeString(xmlSecTransformKlassGetName(xmlSecTransformMemBufId)));
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,
2412 "xmlSecTransformCtxNodeRead",
2413 XMLSEC_ERRORS_R_XMLSEC_FAILED,
2415 xmlSecErrorsSafeString(xmlSecNodeGetName(cur)));
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,
2428 "xmlSecTransformCtxAppend",
2429 XMLSEC_ERRORS_R_XMLSEC_FAILED,
2430 XMLSEC_ERRORS_NO_MESSAGE);
2434 xmlSecError(XMLSEC_ERRORS_HERE,
2436 xmlSecErrorsSafeString(xmlSecNodeGetName(cur)),
2437 XMLSEC_ERRORS_R_INVALID_NODE,
2439 xmlSecErrorsSafeString(xmlSecNodeDigestMethod));
2443 dsigRefCtx->digestMethod->operation = dsigRefCtx->dsigCtx->operation;
2445 /* last node is required DigestValue */
2446 if((cur != NULL) && (xmlSecCheckNodeName(cur, xmlSecNodeDigestValue, xmlSecDSigNs))) {
2447 digestValueNode = cur;
2448 cur = xmlSecGetNextElementNode(cur->next);
2450 xmlSecError(XMLSEC_ERRORS_HERE,
2452 xmlSecErrorsSafeString(xmlSecNodeGetName(cur)),
2453 XMLSEC_ERRORS_R_XMLSEC_FAILED,
2455 xmlSecErrorsSafeString(xmlSecNodeDigestValue));
2459 /* if we have something else then it's an error */
2461 xmlSecError(XMLSEC_ERRORS_HERE,
2463 xmlSecErrorsSafeString(xmlSecNodeGetName(cur)),
2464 XMLSEC_ERRORS_R_UNEXPECTED_NODE,
2465 XMLSEC_ERRORS_NO_MESSAGE);
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;
2473 /* we need to add base64 encode transform */
2474 base64Encode = xmlSecTransformCtxCreateAndAppend(transformCtx, xmlSecTransformBase64Id);
2475 if(base64Encode == NULL) {
2476 xmlSecError(XMLSEC_ERRORS_HERE,
2478 "xmlSecTransformCtxCreateAndAppend",
2479 XMLSEC_ERRORS_R_XMLSEC_FAILED,
2480 XMLSEC_ERRORS_NO_MESSAGE);
2483 base64Encode->operation = xmlSecTransformOperationEncode;
2486 /* finally get transforms results */
2487 ret = xmlSecTransformCtxExecute(transformCtx, node->doc);
2489 snprintf(logMsg, sizeof(logMsg), "uri:%s", (char*)dsigRefCtx->uri);
2490 logMsg[strlen(dsigRefCtx->uri)+5] = '\0';
2491 xmlSecError(XMLSEC_ERRORS_HERE,
2493 "xmlSecTransformCtxExecute",
2494 XMLSEC_ERRORS_R_XMLSEC_FAILED,
2499 dsigRefCtx->result = transformCtx->result;
2501 if(dsigRefCtx->dsigCtx->operation == xmlSecTransformOperationSign) {
2502 if((dsigRefCtx->result == NULL) || (xmlSecBufferGetData(dsigRefCtx->result) == NULL)) {
2503 xmlSecError(XMLSEC_ERRORS_HERE,
2505 "xmlSecTransformCtxExecute",
2506 XMLSEC_ERRORS_R_XMLSEC_FAILED,
2507 XMLSEC_ERRORS_NO_MESSAGE);
2511 /* write signed data to xml */
2512 xmlNodeSetContentLen(digestValueNode,
2513 xmlSecBufferGetData(dsigRefCtx->result),
2514 xmlSecBufferGetSize(dsigRefCtx->result));
2516 /* set success status and we are done */
2517 dsigRefCtx->status = xmlSecDSigStatusSucceeded;
2519 /* verify SignatureValue node content */
2520 ret = xmlSecTransformVerifyNodeContent(dsigRefCtx->digestMethod,
2521 digestValueNode, transformCtx);
2523 snprintf(logMsg, sizeof(logMsg), "uri:%s", (char*)dsigRefCtx->uri);
2524 logMsg[strlen(dsigRefCtx->uri)+5] = '\0';
2525 xmlSecError(XMLSEC_ERRORS_HERE,
2527 "xmlSecTransformVerifyNodeContent",
2528 XMLSEC_ERRORS_R_XMLSEC_FAILED, logMsg);
2532 /* set status and we are done */
2533 if(dsigRefCtx->digestMethod->status == xmlSecTransformStatusOk) {
2534 dsigRefCtx->status = xmlSecDSigStatusSucceeded;
2536 dsigRefCtx->status = xmlSecDSigStatusInvalid;
2540 if(dsigRefCtx->digestMethod->status == xmlSecTransformStatusOk) {
2541 dsigRefCtx->status = xmlSecDSigStatusSucceeded;
2550 /**************************************************************************
2552 * xmlSecDSigReferenceCtxListKlass
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; */
2564 * xmlSecDSigReferenceCtxListGetKlass:
2566 * The <dsig:Reference/> element processing contexts list klass.
2568 * Returns: <dsig:Reference/> element processing context list klass.
2571 xmlSecDSigReferenceCtxListGetKlass(void) {
2572 return(&xmlSecDSigReferenceCtxListKlass);
2575 #endif /* XMLSEC_NO_XMLDSIG */