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