[xmlsec] Manifest References

Aleksey Sanin aleksey at aleksey.com
Fri Jun 2 09:28:36 PDT 2017


Let me try to explain using the example from the spec
(https://www.w3.org/TR/xmldsig-core/#sec-o-Manifest):

   [   ] ...
   [m01]   <Reference URI="#MyFirstManifest"
   [m02]     Type="http://www.w3.org/2000/09/xmldsig#Manifest">
   [m03]     <Transforms>
   [m04]       <Transform
Algorithm="http://www.w3.org/2006/12/xml-c14n11"/>
   [m05]     </Transforms>
   [m06]     <DigestMethod
Algorithm="http://www.w3.org/2000/09/xmldsig#sha1"/>
   [m07]
<DigestValue>dGhpcyBpcyBub3QgYSBzaWduYXR1cmUK...=</DigestValue>
   [m08]   </Reference>
   [   ] ...
   [m09] <Object>
   [m10]   <Manifest Id="MyFirstManifest">
   [m11]     <Reference>
   [m12]     ...
   [m13]     </Reference>
   [m14]     <Reference>
   [m15]     ...
   [m16]     </Reference>
   [m17]   </Manifest>
   [m18] </Object>


What is happening here is the following:

1) The Reference element (m01) refers to the same document and the
digest is calculated/validated against the Manifest node (m10) according
to the usual XMLDsig rules. The signature validation fails if there
is a digest mismatch.

2) Separately, the Object element (m09) is processed and digests are
calculated/validated but this does not impact the signature validation.
The xmlsec library returns the status of the validation in
xmlSecDSigCtx::manifestReferences list.

In the code, xmlSecDSigReferenceCtxProcessNode() fails with an error
only if there is a real processing error (e.g. malformed Reference
object). The digest mismatch results in  dsigRefCtx->status to be set
to xmlSecDSigStatusInvalid. The xmlSecDSigCtxProcessManifestNode()
DOES NOT check dsigRefCtx->status (in comparison
xmlSecDSigCtxProcessReferences() DOES and fails if it is not
xmlSecDSigStatusSucceeded).

There are tests for this (e.g.
tests/merlin-xmldsig-twenty-three/signature.xml).


Best,
Aleksey




Aleksey

On 6/2/17 2:22 AM, Dan Seguin wrote:
> Greetings,
> 
> I have a question about signing and validating Signatures where Manifest
> blocks are present.
> 
> My understanding (if correct) from the XMLDSIG spec is that References
> within Manifest blocks can fail the digest operation or de-referencing
> of an URI, and not be considered a failure for signing or validation.
> 
> In cases where the Manifest block is Reference'd from a SignedInfo
> Reference, the whole block is digested (with whatever is in there)
> whether or not the digesting occurred on the internal Manifest Reference
> entries.
> 
> I'm seeing that xmlsec functions throw an error that halts the signing
> or verification if the References inside a Manifest block can't be
> processed.
> 
> Is this correct?
> 
> From xmldsig.c, function xmlSecDSigCtxProcessManifestNode, there is this
> snippet:
> 
>>     /* 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);
> 
> The call to xmlSecDSigReferenceCtxProcessNode exits
> xmlSecDSigCtxProcessManifestNode if there's a failure, sending the error
> upstream.
> 
> For producing a Signature (from template) with a Manifest block (with
> pre-calculated Digest from an application and populated with an URI that
> is NOT processable) this isn't a problem if setting dsigCtx->flags |=
> XMLSEC_DSIG_FLAGS_IGNORE_MANIFESTS.
> 
> However, for ingesting Signatures from external entities, Manifest
> blocks may have to be processed to verify (reference) digests before
> verifying signature. On failure, I'd assume that whatever digests are
> there are then used for signature validation. 
> 
> I would rather not use the IGNORE flag on validation.
> 
> Guidance?
> 
> Cheers.
> 
> 
> 
> 
> 
> 
> 
> 
> 
> 
> _______________________________________________
> xmlsec mailing list
> xmlsec at aleksey.com
> http://www.aleksey.com/mailman/listinfo/xmlsec
> 


More information about the xmlsec mailing list