Line data Source code
1 : /**
2 : * XML Security Library (http://www.aleksey.com/xmlsec).
3 : *
4 : * "XML Digital Signature" implementation
5 : * http://www.w3.org/TR/xmldsig-core/
6 : * http://www.w3.org/Signature/Overview.html
7 : *
8 : * This is free software; see Copyright file in the source
9 : * distribution for preciese wording.
10 : *
11 : * Copyright (C) 2002-2003 Aleksey Sanin <aleksey@aleksey.com>
12 : */
13 : #include "globals.h"
14 :
15 : #ifndef XMLSEC_NO_XMLDSIG
16 :
17 : #include <stdlib.h>
18 : #include <stdio.h>
19 : #include <string.h>
20 :
21 : #include <libxml/tree.h>
22 : #include <libxml/parser.h>
23 :
24 : #include <xmlsec/xmlsec.h>
25 : #include <xmlsec/buffer.h>
26 : #include <xmlsec/xmltree.h>
27 : #include <xmlsec/keys.h>
28 : #include <xmlsec/keysmngr.h>
29 : #include <xmlsec/transforms.h>
30 : #include <xmlsec/membuf.h>
31 : #include <xmlsec/xmldsig.h>
32 : #include <xmlsec/errors.h>
33 :
34 : /**************************************************************************
35 : *
36 : * xmlSecDSigCtx
37 : *
38 : *************************************************************************/
39 : static int xmlSecDSigCtxProcessSignatureNode (xmlSecDSigCtxPtr dsigCtx,
40 : xmlNodePtr node);
41 : static int xmlSecDSigCtxProcessSignedInfoNode (xmlSecDSigCtxPtr dsigCtx,
42 : xmlNodePtr node);
43 : static int xmlSecDSigCtxProcessKeyInfoNode (xmlSecDSigCtxPtr dsigCtx,
44 : xmlNodePtr node);
45 : static int xmlSecDSigCtxProcessObjectNode (xmlSecDSigCtxPtr dsigCtx,
46 : xmlNodePtr node);
47 : static int xmlSecDSigCtxProcessManifestNode (xmlSecDSigCtxPtr dsigCtx,
48 : xmlNodePtr node);
49 :
50 : /* The ID attribute in XMLDSig is 'Id' */
51 : static const xmlChar* xmlSecDSigIds[] = { xmlSecAttrId, NULL };
52 :
53 : /**
54 : * xmlSecDSigCtxCreate:
55 : * @keysMngr: the pointer to keys manager.
56 : *
57 : * Creates <dsig:Signature/> element processing context.
58 : * The caller is responsible for destroying returend object by calling
59 : * #xmlSecDSigCtxDestroy function.
60 : *
61 : * Returns: pointer to newly allocated context object or NULL if an error
62 : * occurs.
63 : */
64 : xmlSecDSigCtxPtr
65 0 : xmlSecDSigCtxCreate(xmlSecKeysMngrPtr keysMngr) {
66 : xmlSecDSigCtxPtr dsigCtx;
67 : int ret;
68 :
69 0 : dsigCtx = (xmlSecDSigCtxPtr) xmlMalloc(sizeof(xmlSecDSigCtx));
70 0 : if(dsigCtx == NULL) {
71 0 : xmlSecError(XMLSEC_ERRORS_HERE,
72 : NULL,
73 : NULL,
74 : XMLSEC_ERRORS_R_MALLOC_FAILED,
75 : "sizeof(xmlSecDSigCtx)=%d",
76 : sizeof(xmlSecDSigCtx));
77 0 : return(NULL);
78 : }
79 :
80 0 : ret = xmlSecDSigCtxInitialize(dsigCtx, keysMngr);
81 0 : if(ret < 0) {
82 0 : xmlSecError(XMLSEC_ERRORS_HERE,
83 : NULL,
84 : "xmlSecDSigCtxInitialize",
85 : XMLSEC_ERRORS_R_XMLSEC_FAILED,
86 : XMLSEC_ERRORS_NO_MESSAGE);
87 0 : xmlSecDSigCtxDestroy(dsigCtx);
88 0 : return(NULL);
89 : }
90 0 : return(dsigCtx);
91 : }
92 :
93 : /**
94 : * xmlSecDSigCtxDestroy:
95 : * @dsigCtx: the pointer to <dsig:Signature/> processing context.
96 : *
97 : * Destroy context object created with #xmlSecDSigCtxCreate function.
98 : */
99 : void
100 0 : xmlSecDSigCtxDestroy(xmlSecDSigCtxPtr dsigCtx) {
101 0 : xmlSecAssert(dsigCtx != NULL);
102 :
103 0 : xmlSecDSigCtxFinalize(dsigCtx);
104 0 : xmlFree(dsigCtx);
105 : }
106 :
107 : /**
108 : * xmlSecDSigCtxInitialize:
109 : * @dsigCtx: the pointer to <dsig:Signature/> processing context.
110 : * @keysMngr: the pointer to keys manager.
111 : *
112 : * Initializes <dsig:Signature/> element processing context.
113 : * The caller is responsible for cleaing up returend object by calling
114 : * #xmlSecDSigCtxFinalize function.
115 : *
116 : * Returns: 0 on success or a negative value if an error occurs.
117 : */
118 : int
119 0 : xmlSecDSigCtxInitialize(xmlSecDSigCtxPtr dsigCtx, xmlSecKeysMngrPtr keysMngr) {
120 : int ret;
121 :
122 0 : xmlSecAssert2(dsigCtx != NULL, -1);
123 :
124 0 : memset(dsigCtx, 0, sizeof(xmlSecDSigCtx));
125 :
126 : /* initialize key info */
127 0 : ret = xmlSecKeyInfoCtxInitialize(&(dsigCtx->keyInfoReadCtx), keysMngr);
128 0 : if(ret < 0) {
129 0 : xmlSecError(XMLSEC_ERRORS_HERE,
130 : NULL,
131 : "xmlSecKeyInfoCtxInitialize",
132 : XMLSEC_ERRORS_R_XMLSEC_FAILED,
133 : XMLSEC_ERRORS_NO_MESSAGE);
134 0 : return(-1);
135 : }
136 0 : dsigCtx->keyInfoReadCtx.mode = xmlSecKeyInfoModeRead;
137 :
138 0 : ret = xmlSecKeyInfoCtxInitialize(&(dsigCtx->keyInfoWriteCtx), keysMngr);
139 0 : if(ret < 0) {
140 0 : xmlSecError(XMLSEC_ERRORS_HERE,
141 : NULL,
142 : "xmlSecKeyInfoCtxInitialize",
143 : XMLSEC_ERRORS_R_XMLSEC_FAILED,
144 : XMLSEC_ERRORS_NO_MESSAGE);
145 0 : return(-1);
146 : }
147 0 : dsigCtx->keyInfoWriteCtx.mode = xmlSecKeyInfoModeWrite;
148 : /* it's not wise to write private key :) */
149 0 : dsigCtx->keyInfoWriteCtx.keyReq.keyType = xmlSecKeyDataTypePublic;
150 :
151 : /* initializes transforms dsigCtx */
152 0 : ret = xmlSecTransformCtxInitialize(&(dsigCtx->transformCtx));
153 0 : if(ret < 0) {
154 0 : xmlSecError(XMLSEC_ERRORS_HERE,
155 : NULL,
156 : "xmlSecTransformCtxInitialize",
157 : XMLSEC_ERRORS_R_XMLSEC_FAILED,
158 : XMLSEC_ERRORS_NO_MESSAGE);
159 0 : return(-1);
160 : }
161 :
162 : /* references lists from SignedInfo and Manifest elements */
163 0 : xmlSecPtrListInitialize(&(dsigCtx->signedInfoReferences),
164 : xmlSecDSigReferenceCtxListId);
165 0 : xmlSecPtrListInitialize(&(dsigCtx->manifestReferences),
166 : xmlSecDSigReferenceCtxListId);
167 :
168 0 : dsigCtx->enabledReferenceUris = xmlSecTransformUriTypeAny;
169 0 : return(0);
170 : }
171 :
172 : /**
173 : * xmlSecDSigCtxFinalize:
174 : * @dsigCtx: the pointer to <dsig:Signature/> processing context.
175 : *
176 : * Cleans up @dsigCtx object initialized with #xmlSecDSigCtxInitialize function.
177 : */
178 : void
179 0 : xmlSecDSigCtxFinalize(xmlSecDSigCtxPtr dsigCtx) {
180 0 : xmlSecAssert(dsigCtx != NULL);
181 :
182 0 : xmlSecTransformCtxFinalize(&(dsigCtx->transformCtx));
183 0 : xmlSecKeyInfoCtxFinalize(&(dsigCtx->keyInfoReadCtx));
184 0 : xmlSecKeyInfoCtxFinalize(&(dsigCtx->keyInfoWriteCtx));
185 0 : xmlSecPtrListFinalize(&(dsigCtx->signedInfoReferences));
186 0 : xmlSecPtrListFinalize(&(dsigCtx->manifestReferences));
187 :
188 0 : if(dsigCtx->enabledReferenceTransforms != NULL) {
189 0 : xmlSecPtrListDestroy(dsigCtx->enabledReferenceTransforms);
190 : }
191 0 : if(dsigCtx->signKey != NULL) {
192 0 : xmlSecKeyDestroy(dsigCtx->signKey);
193 : }
194 0 : if(dsigCtx->id != NULL) {
195 0 : xmlFree(dsigCtx->id);
196 : }
197 0 : memset(dsigCtx, 0, sizeof(xmlSecDSigCtx));
198 : }
199 :
200 : /**
201 : * xmlSecDSigCtxEnableReferenceTransform:
202 : * @dsigCtx: the pointer to <dsig:Signature/> processing context.
203 : * @transformId: the transform klass.
204 : *
205 : * Enables @transformId for <dsig:Reference/> elements processing.
206 : *
207 : * Returns: 0 on success or a negative value if an error occurs.
208 : */
209 : int
210 0 : xmlSecDSigCtxEnableReferenceTransform(xmlSecDSigCtxPtr dsigCtx, xmlSecTransformId transformId) {
211 : int ret;
212 :
213 0 : xmlSecAssert2(dsigCtx != NULL, -1);
214 0 : xmlSecAssert2(dsigCtx->result == NULL, -1);
215 0 : xmlSecAssert2(transformId != xmlSecTransformIdUnknown, -1);
216 :
217 0 : if(dsigCtx->enabledReferenceTransforms == NULL) {
218 0 : dsigCtx->enabledReferenceTransforms = xmlSecPtrListCreate(xmlSecTransformIdListId);
219 0 : if(dsigCtx->enabledReferenceTransforms == NULL) {
220 0 : xmlSecError(XMLSEC_ERRORS_HERE,
221 : NULL,
222 : "xmlSecPtrListCreate",
223 : XMLSEC_ERRORS_R_XMLSEC_FAILED,
224 : XMLSEC_ERRORS_NO_MESSAGE);
225 0 : return(-1);
226 : }
227 : }
228 :
229 0 : ret = xmlSecPtrListAdd(dsigCtx->enabledReferenceTransforms, (void*)transformId);
230 0 : if(ret < 0) {
231 0 : xmlSecError(XMLSEC_ERRORS_HERE,
232 : NULL,
233 : "xmlSecPtrListAdd",
234 : XMLSEC_ERRORS_R_XMLSEC_FAILED,
235 : XMLSEC_ERRORS_NO_MESSAGE);
236 0 : return(-1);
237 : }
238 0 : return(0);
239 : }
240 :
241 : /**
242 : * xmlSecDSigCtxEnableSignatureTransform:
243 : * @dsigCtx: the pointer to <dsig:Signature/> processing context.
244 : * @transformId: the transform klass.
245 : *
246 : * Enables @transformId for <dsig:SignedInfo/> element processing.
247 : *
248 : * Returns: 0 on success or a negative value if an error occurs.
249 : */
250 : int
251 0 : xmlSecDSigCtxEnableSignatureTransform(xmlSecDSigCtxPtr dsigCtx, xmlSecTransformId transformId) {
252 0 : xmlSecAssert2(dsigCtx != NULL, -1);
253 0 : xmlSecAssert2(dsigCtx->result == NULL, -1);
254 0 : xmlSecAssert2(transformId != xmlSecTransformIdUnknown, -1);
255 :
256 0 : return(xmlSecPtrListAdd(&(dsigCtx->transformCtx.enabledTransforms), (void*)transformId));
257 : }
258 :
259 : /**
260 : * xmlSecDSigCtxGetPreSignBuffer:
261 : * @dsigCtx: the pointer to <dsig:Signature/> processing context.
262 : *
263 : * Gets pointer to the buffer with serialized <dsig:SignedInfo/> element
264 : * just before signature claculation (valid if and only if
265 : * #XMLSEC_DSIG_FLAGS_STORE_SIGNATURE context flag is set.
266 : *
267 : * Returns: 0 on success or a negative value if an error occurs.
268 : */
269 : xmlSecBufferPtr
270 0 : xmlSecDSigCtxGetPreSignBuffer(xmlSecDSigCtxPtr dsigCtx) {
271 0 : xmlSecAssert2(dsigCtx != NULL, NULL);
272 :
273 0 : return((dsigCtx->preSignMemBufMethod != NULL) ?
274 0 : xmlSecTransformMemBufGetBuffer(dsigCtx->preSignMemBufMethod) : NULL);
275 : }
276 :
277 : /**
278 : * xmlSecDSigCtxSign:
279 : * @dsigCtx: the pointer to <dsig:Signature/> processing context.
280 : * @tmpl: the pointer to <dsig:Signature/> node with signature template.
281 : *
282 : * Signs the data as described in @tmpl node.
283 : *
284 : * Returns: 0 on success or a negative value if an error occurs.
285 : */
286 : int
287 0 : xmlSecDSigCtxSign(xmlSecDSigCtxPtr dsigCtx, xmlNodePtr tmpl) {
288 : int ret;
289 :
290 0 : xmlSecAssert2(dsigCtx != NULL, -1);
291 0 : xmlSecAssert2(dsigCtx->result == NULL, -1);
292 0 : xmlSecAssert2(tmpl != NULL, -1);
293 0 : xmlSecAssert2(tmpl->doc != NULL, -1);
294 :
295 : /* add ids for Signature nodes */
296 0 : dsigCtx->operation = xmlSecTransformOperationSign;
297 0 : dsigCtx->status = xmlSecDSigStatusUnknown;
298 0 : xmlSecAddIDs(tmpl->doc, tmpl, xmlSecDSigIds);
299 :
300 : /* read signature template */
301 0 : ret = xmlSecDSigCtxProcessSignatureNode(dsigCtx, tmpl);
302 0 : if(ret < 0) {
303 0 : xmlSecError(XMLSEC_ERRORS_HERE,
304 : NULL,
305 : "xmlSecDSigCtxSigantureProcessNode",
306 : XMLSEC_ERRORS_R_XMLSEC_FAILED,
307 : XMLSEC_ERRORS_NO_MESSAGE);
308 0 : return(-1);
309 : }
310 0 : xmlSecAssert2(dsigCtx->signMethod != NULL, -1);
311 0 : xmlSecAssert2(dsigCtx->signValueNode != NULL, -1);
312 :
313 : /* references processing might change the status */
314 0 : if(dsigCtx->status != xmlSecDSigStatusUnknown) {
315 0 : return(0);
316 : }
317 :
318 : /* check what we've got */
319 0 : dsigCtx->result = dsigCtx->transformCtx.result;
320 0 : if((dsigCtx->result == NULL) || (xmlSecBufferGetData(dsigCtx->result) == NULL)) {
321 0 : xmlSecError(XMLSEC_ERRORS_HERE,
322 : NULL,
323 : NULL,
324 : XMLSEC_ERRORS_R_INVALID_RESULT,
325 : XMLSEC_ERRORS_NO_MESSAGE);
326 0 : return(-1);
327 : }
328 :
329 : /* write signed data to xml */
330 0 : xmlNodeSetContentLen(dsigCtx->signValueNode,
331 0 : xmlSecBufferGetData(dsigCtx->result),
332 0 : xmlSecBufferGetSize(dsigCtx->result));
333 :
334 : /* set success status and we are done */
335 0 : dsigCtx->status = xmlSecDSigStatusSucceeded;
336 0 : return(0);
337 : }
338 :
339 : /**
340 : * xmlSecDSigCtxVerify:
341 : * @dsigCtx: the pointer to <dsig:Signature/> processing context.
342 : * @node: the pointer with <dsig:Signature/> node.
343 : *
344 : * Vaidates signature in the @node. The verification result is returned
345 : * in #status member of the @dsigCtx object.
346 : *
347 : * Returns: 0 on success (check #status member of @dsigCtx to get
348 : * signature verification result) or a negative value if an error occurs.
349 : */
350 : int
351 0 : xmlSecDSigCtxVerify(xmlSecDSigCtxPtr dsigCtx, xmlNodePtr node) {
352 : int ret;
353 :
354 0 : xmlSecAssert2(dsigCtx != NULL, -1);
355 0 : xmlSecAssert2(node != NULL, -1);
356 0 : xmlSecAssert2(node->doc != NULL, -1);
357 :
358 : /* add ids for Signature nodes */
359 0 : dsigCtx->operation = xmlSecTransformOperationVerify;
360 0 : dsigCtx->status = xmlSecDSigStatusUnknown;
361 0 : xmlSecAddIDs(node->doc, node, xmlSecDSigIds);
362 :
363 : /* read siganture info */
364 0 : ret = xmlSecDSigCtxProcessSignatureNode(dsigCtx, node);
365 0 : if(ret < 0) {
366 0 : xmlSecError(XMLSEC_ERRORS_HERE,
367 : NULL,
368 : "xmlSecDSigCtxSigantureProcessNode",
369 : XMLSEC_ERRORS_R_XMLSEC_FAILED,
370 : XMLSEC_ERRORS_NO_MESSAGE);
371 0 : return(-1);
372 : }
373 0 : xmlSecAssert2(dsigCtx->signMethod != NULL, -1);
374 0 : xmlSecAssert2(dsigCtx->signValueNode != NULL, -1);
375 :
376 : /* references processing might change the status */
377 0 : if(dsigCtx->status != xmlSecDSigStatusUnknown) {
378 0 : return(0);
379 : }
380 :
381 : /* verify SignatureValue node content */
382 0 : ret = xmlSecTransformVerifyNodeContent(dsigCtx->signMethod, dsigCtx->signValueNode,
383 0 : &(dsigCtx->transformCtx));
384 0 : if(ret < 0) {
385 0 : xmlSecError(XMLSEC_ERRORS_HERE,
386 : NULL,
387 : "xmlSecTransformVerifyNodeContent",
388 : XMLSEC_ERRORS_R_XMLSEC_FAILED,
389 : XMLSEC_ERRORS_NO_MESSAGE);
390 0 : return(-1);
391 : }
392 :
393 : /* set status and we are done */
394 0 : if(dsigCtx->signMethod->status == xmlSecTransformStatusOk) {
395 0 : dsigCtx->status = xmlSecDSigStatusSucceeded;
396 : } else {
397 0 : dsigCtx->status = xmlSecDSigStatusInvalid;
398 : }
399 0 : return(0);
400 : }
401 :
402 : /**
403 : * xmlSecDSigCtxProcessSignatureNode:
404 : *
405 : * The Signature element (http://www.w3.org/TR/xmldsig-core/#sec-Signature)
406 : *
407 : * The Signature element is the root element of an XML Signature.
408 : * Implementation MUST generate laxly schema valid [XML-schema] Signature
409 : * elements as specified by the following schema:
410 : * The way in which the SignedInfo element is presented to the
411 : * canonicalization method is dependent on that method. The following
412 : * applies to algorithms which process XML as nodes or characters:
413 : *
414 : * - XML based canonicalization implementations MUST be provided with
415 : * a [XPath] node-set originally formed from the document containing
416 : * the SignedInfo and currently indicating the SignedInfo, its descendants,
417 : * and the attribute and namespace nodes of SignedInfo and its descendant
418 : * elements.
419 : *
420 : * - Text based canonicalization algorithms (such as CRLF and charset
421 : * normalization) should be provided with the UTF-8 octets that represent
422 : * the well-formed SignedInfo element, from the first character to the
423 : * last character of the XML representation, inclusive. This includes
424 : * the entire text of the start and end tags of the SignedInfo element
425 : * as well as all descendant markup and character data (i.e., the text)
426 : * between those tags. Use of text based canonicalization of SignedInfo
427 : * is NOT RECOMMENDED.
428 : *
429 : * =================================
430 : * we do not support any non XML based C14N
431 : *
432 : * Schema Definition:
433 : *
434 : * <element name="Signature" type="ds:SignatureType"/>
435 : * <complexType name="SignatureType">
436 : * <sequence>
437 : * <element ref="ds:SignedInfo"/>
438 : * <element ref="ds:SignatureValue"/>
439 : * <element ref="ds:KeyInfo" minOccurs="0"/>
440 : * <element ref="ds:Object" minOccurs="0" maxOccurs="unbounded"/>
441 : * </sequence> <attribute name="Id" type="ID" use="optional"/>
442 : * </complexType>
443 : *
444 : * DTD:
445 : *
446 : * <!ELEMENT Signature (SignedInfo, SignatureValue, KeyInfo?, Object*) >
447 : * <!ATTLIST Signature
448 : * xmlns CDATA #FIXED 'http://www.w3.org/2000/09/xmldsig#'
449 : * Id ID #IMPLIED >
450 : *
451 : */
452 : static int
453 0 : xmlSecDSigCtxProcessSignatureNode(xmlSecDSigCtxPtr dsigCtx, xmlNodePtr node) {
454 : xmlSecTransformDataType firstType;
455 0 : xmlNodePtr signedInfoNode = NULL;
456 0 : xmlNodePtr keyInfoNode = NULL;
457 : xmlNodePtr cur;
458 : int ret;
459 :
460 0 : xmlSecAssert2(dsigCtx != NULL, -1);
461 0 : xmlSecAssert2((dsigCtx->operation == xmlSecTransformOperationSign) || (dsigCtx->operation == xmlSecTransformOperationVerify), -1);
462 0 : xmlSecAssert2(dsigCtx->status == xmlSecDSigStatusUnknown, -1);
463 0 : xmlSecAssert2(dsigCtx->signValueNode == NULL, -1);
464 0 : xmlSecAssert2(dsigCtx->signMethod == NULL, -1);
465 0 : xmlSecAssert2(dsigCtx->c14nMethod == NULL, -1);
466 0 : xmlSecAssert2(node != NULL, -1);
467 :
468 0 : if(!xmlSecCheckNodeName(node, xmlSecNodeSignature, xmlSecDSigNs)) {
469 0 : xmlSecError(XMLSEC_ERRORS_HERE,
470 : NULL,
471 0 : xmlSecErrorsSafeString(xmlSecNodeGetName(node)),
472 : XMLSEC_ERRORS_R_INVALID_NODE,
473 : "expected=%s",
474 : xmlSecErrorsSafeString(xmlSecNodeSignature));
475 0 : return(-1);
476 : }
477 :
478 : /* read node data */
479 0 : xmlSecAssert2(dsigCtx->id == NULL, -1);
480 0 : dsigCtx->id = xmlGetProp(node, xmlSecAttrId);
481 :
482 : /* first node is required SignedInfo */
483 0 : cur = xmlSecGetNextElementNode(node->children);
484 0 : if((cur == NULL) || (!xmlSecCheckNodeName(cur, xmlSecNodeSignedInfo, xmlSecDSigNs))) {
485 0 : xmlSecError(XMLSEC_ERRORS_HERE,
486 : NULL,
487 0 : xmlSecErrorsSafeString(xmlSecNodeGetName(cur)),
488 : XMLSEC_ERRORS_R_INVALID_NODE,
489 : "expected=%s",
490 : xmlSecErrorsSafeString(xmlSecNodeSignedInfo));
491 0 : return(-1);
492 : }
493 0 : signedInfoNode = cur;
494 0 : cur = xmlSecGetNextElementNode(cur->next);
495 :
496 : /* next node is required SignatureValue */
497 0 : if((cur == NULL) || (!xmlSecCheckNodeName(cur, xmlSecNodeSignatureValue, xmlSecDSigNs))) {
498 0 : xmlSecError(XMLSEC_ERRORS_HERE,
499 : NULL,
500 0 : xmlSecErrorsSafeString(xmlSecNodeGetName(cur)),
501 : XMLSEC_ERRORS_R_INVALID_NODE,
502 : "expected=%s",
503 : xmlSecErrorsSafeString(xmlSecNodeSignatureValue));
504 0 : return(-1);
505 : }
506 0 : dsigCtx->signValueNode = cur;
507 0 : cur = xmlSecGetNextElementNode(cur->next);
508 :
509 : /* next node is optional KeyInfo */
510 0 : if((cur != NULL) && (xmlSecCheckNodeName(cur, xmlSecNodeKeyInfo, xmlSecDSigNs))) {
511 0 : keyInfoNode = cur;
512 0 : cur = xmlSecGetNextElementNode(cur->next);
513 : } else {
514 0 : keyInfoNode = NULL;
515 : }
516 :
517 : /* next nodes are optional Object nodes */
518 0 : while((cur != NULL) && (xmlSecCheckNodeName(cur, xmlSecNodeObject, xmlSecDSigNs))) {
519 : /* read manifests from objects */
520 0 : if((dsigCtx->flags & XMLSEC_DSIG_FLAGS_IGNORE_MANIFESTS) == 0) {
521 0 : ret = xmlSecDSigCtxProcessObjectNode(dsigCtx, cur);
522 0 : if(ret < 0) {
523 0 : xmlSecError(XMLSEC_ERRORS_HERE,
524 : NULL,
525 : "xmlSecDSigCtxProcessObjectNode",
526 : XMLSEC_ERRORS_R_XMLSEC_FAILED,
527 : XMLSEC_ERRORS_NO_MESSAGE);
528 0 : return(-1);
529 : }
530 : }
531 0 : cur = xmlSecGetNextElementNode(cur->next);
532 : }
533 :
534 : /* if there is something left than it's an error */
535 0 : if(cur != NULL) {
536 0 : xmlSecError(XMLSEC_ERRORS_HERE,
537 : NULL,
538 0 : xmlSecErrorsSafeString(xmlSecNodeGetName(cur)),
539 : XMLSEC_ERRORS_R_UNEXPECTED_NODE,
540 : XMLSEC_ERRORS_NO_MESSAGE);
541 0 : return(-1);
542 : }
543 :
544 : /* now validated all the references and prepare transform */
545 0 : ret = xmlSecDSigCtxProcessSignedInfoNode(dsigCtx, signedInfoNode);
546 0 : if(ret < 0) {
547 0 : xmlSecError(XMLSEC_ERRORS_HERE,
548 : NULL,
549 : "xmlSecDSigCtxProcessSignedInfoNode",
550 : XMLSEC_ERRORS_R_XMLSEC_FAILED,
551 : XMLSEC_ERRORS_NO_MESSAGE);
552 0 : return(-1);
553 : }
554 : /* references processing might change the status */
555 0 : if(dsigCtx->status != xmlSecDSigStatusUnknown) {
556 0 : return(0);
557 : }
558 :
559 : /* as the result, we should have sign and c14n methods set */
560 0 : xmlSecAssert2(dsigCtx->signMethod != NULL, -1);
561 0 : xmlSecAssert2(dsigCtx->c14nMethod != NULL, -1);
562 :
563 0 : ret = xmlSecDSigCtxProcessKeyInfoNode(dsigCtx, keyInfoNode);
564 0 : if(ret < 0) {
565 0 : xmlSecError(XMLSEC_ERRORS_HERE,
566 : NULL,
567 : "xmlSecDSigCtxProcessKeyInfoNode",
568 : XMLSEC_ERRORS_R_XMLSEC_FAILED,
569 : XMLSEC_ERRORS_NO_MESSAGE);
570 0 : return(-1);
571 : }
572 : /* as the result, we should have a key */
573 0 : xmlSecAssert2(dsigCtx->signKey != NULL, -1);
574 :
575 : /* if we need to write result to xml node then we need base64 encode result */
576 0 : if(dsigCtx->operation == xmlSecTransformOperationSign) {
577 : xmlSecTransformPtr base64Encode;
578 :
579 : /* we need to add base64 encode transform */
580 0 : base64Encode = xmlSecTransformCtxCreateAndAppend(&(dsigCtx->transformCtx),
581 : xmlSecTransformBase64Id);
582 0 : if(base64Encode == NULL) {
583 0 : xmlSecError(XMLSEC_ERRORS_HERE,
584 : NULL,
585 : "xmlSecTransformCtxCreateAndAppend",
586 : XMLSEC_ERRORS_R_XMLSEC_FAILED,
587 : XMLSEC_ERRORS_NO_MESSAGE);
588 0 : return(-1);
589 : }
590 0 : base64Encode->operation = xmlSecTransformOperationEncode;
591 : }
592 :
593 0 : firstType = xmlSecTransformGetDataType(dsigCtx->transformCtx.first,
594 : xmlSecTransformModePush,
595 0 : &(dsigCtx->transformCtx));
596 0 : if((firstType & xmlSecTransformDataTypeXml) != 0) {
597 0 : xmlSecNodeSetPtr nodeset = NULL;
598 :
599 0 : xmlSecAssert2(signedInfoNode != NULL, -1);
600 0 : nodeset = xmlSecNodeSetGetChildren(signedInfoNode->doc, signedInfoNode, 1, 0);
601 0 : if(nodeset == NULL) {
602 0 : xmlSecError(XMLSEC_ERRORS_HERE,
603 : NULL,
604 : "xmlSecNodeSetGetChildren",
605 : XMLSEC_ERRORS_R_XMLSEC_FAILED,
606 : "node=%s",
607 0 : xmlSecErrorsSafeString(xmlSecNodeGetName(signedInfoNode)));
608 0 : return(-1);
609 : }
610 :
611 : /* calculate the signature */
612 0 : ret = xmlSecTransformCtxXmlExecute(&(dsigCtx->transformCtx), nodeset);
613 0 : if(ret < 0) {
614 0 : xmlSecError(XMLSEC_ERRORS_HERE,
615 : NULL,
616 : "xmlSecTransformCtxXmlExecute",
617 : XMLSEC_ERRORS_R_XMLSEC_FAILED,
618 : XMLSEC_ERRORS_NO_MESSAGE);
619 0 : xmlSecNodeSetDestroy(nodeset);
620 0 : return(-1);
621 : }
622 0 : xmlSecNodeSetDestroy(nodeset);
623 : } else {
624 : /* TODO */
625 0 : xmlSecError(XMLSEC_ERRORS_HERE,
626 : NULL,
627 : "the binary c14n transforms are not supported yet",
628 : XMLSEC_ERRORS_R_NOT_IMPLEMENTED,
629 : XMLSEC_ERRORS_NO_MESSAGE);
630 0 : return(-1);
631 : }
632 0 : return(0);
633 : }
634 :
635 : /**
636 : * xmlSecDSigCtxProcessSignedInfoNode:
637 : *
638 : * The SignedInfo Element (http://www.w3.org/TR/xmldsig-core/#sec-SignedInfo)
639 : *
640 : * The structure of SignedInfo includes the canonicalization algorithm,
641 : * a result algorithm, and one or more references. The SignedInfo element
642 : * may contain an optional ID attribute that will allow it to be referenced by
643 : * other signatures and objects.
644 : *
645 : * SignedInfo does not include explicit result or digest properties (such as
646 : * calculation time, cryptographic device serial number, etc.). If an
647 : * application needs to associate properties with the result or digest,
648 : * it may include such information in a SignatureProperties element within
649 : * an Object element.
650 : *
651 : * Schema Definition:
652 : *
653 : * <element name="SignedInfo" type="ds:SignedInfoType"/>
654 : * <complexType name="SignedInfoType">
655 : * <sequence>
656 : * <element ref="ds:CanonicalizationMethod"/>
657 : * <element ref="ds:SignatureMethod"/>
658 : * <element ref="ds:Reference" maxOccurs="unbounded"/>
659 : * </sequence>
660 : * <attribute name="Id" type="ID" use="optional"/>
661 : * </complexType>
662 : *
663 : * DTD:
664 : *
665 : * <!ELEMENT SignedInfo (CanonicalizationMethod, SignatureMethod, Reference+) >
666 : * <!ATTLIST SignedInfo Id ID #IMPLIED>
667 : *
668 : */
669 : static int
670 0 : xmlSecDSigCtxProcessSignedInfoNode(xmlSecDSigCtxPtr dsigCtx, xmlNodePtr node) {
671 : xmlSecDSigReferenceCtxPtr dsigRefCtx;
672 : xmlNodePtr cur;
673 : int ret;
674 :
675 0 : xmlSecAssert2(dsigCtx != NULL, -1);
676 0 : xmlSecAssert2(dsigCtx->status == xmlSecDSigStatusUnknown, -1);
677 0 : xmlSecAssert2(dsigCtx->signMethod == NULL, -1);
678 0 : xmlSecAssert2(dsigCtx->c14nMethod == NULL, -1);
679 0 : xmlSecAssert2((dsigCtx->operation == xmlSecTransformOperationSign) || (dsigCtx->operation == xmlSecTransformOperationVerify), -1);
680 0 : xmlSecAssert2(xmlSecPtrListGetSize(&(dsigCtx->signedInfoReferences)) == 0, -1);
681 0 : xmlSecAssert2(node != NULL, -1);
682 :
683 : /* first node is required CanonicalizationMethod. */
684 0 : cur = xmlSecGetNextElementNode(node->children);
685 0 : if((cur != NULL) && (xmlSecCheckNodeName(cur, xmlSecNodeCanonicalizationMethod, xmlSecDSigNs))) {
686 0 : dsigCtx->c14nMethod = xmlSecTransformCtxNodeRead(&(dsigCtx->transformCtx),
687 : cur, xmlSecTransformUsageC14NMethod);
688 0 : if(dsigCtx->c14nMethod == NULL) {
689 0 : xmlSecError(XMLSEC_ERRORS_HERE,
690 : NULL,
691 : "xmlSecTransformCtxNodeRead",
692 : XMLSEC_ERRORS_R_XMLSEC_FAILED,
693 : "node=%s",
694 0 : xmlSecErrorsSafeString(xmlSecNodeGetName(cur)));
695 0 : return(-1);
696 : }
697 0 : } else if(dsigCtx->defC14NMethodId != xmlSecTransformIdUnknown) {
698 : /* the dsig spec does require CanonicalizationMethod node
699 : * to be present but in some case it application might decide to
700 : * minimize traffic */
701 0 : dsigCtx->c14nMethod = xmlSecTransformCtxCreateAndAppend(&(dsigCtx->transformCtx),
702 : dsigCtx->defC14NMethodId);
703 0 : if(dsigCtx->c14nMethod == NULL) {
704 0 : xmlSecError(XMLSEC_ERRORS_HERE,
705 : NULL,
706 : "xmlSecTransformCtxAppend",
707 : XMLSEC_ERRORS_R_XMLSEC_FAILED,
708 : XMLSEC_ERRORS_NO_MESSAGE);
709 0 : return(-1);
710 : }
711 : } else {
712 0 : xmlSecError(XMLSEC_ERRORS_HERE,
713 : NULL,
714 : "CanonicalizationMethod",
715 : XMLSEC_ERRORS_R_INVALID_NODE,
716 : "expected=%s",
717 : xmlSecErrorsSafeString(xmlSecNodeCanonicalizationMethod));
718 0 : return(-1);
719 : }
720 :
721 : /* insert membuf if requested */
722 0 : if((dsigCtx->flags & XMLSEC_DSIG_FLAGS_STORE_SIGNATURE) != 0) {
723 0 : xmlSecAssert2(dsigCtx->preSignMemBufMethod == NULL, -1);
724 0 : dsigCtx->preSignMemBufMethod = xmlSecTransformCtxCreateAndAppend(&(dsigCtx->transformCtx),
725 : xmlSecTransformMemBufId);
726 0 : if(dsigCtx->preSignMemBufMethod == NULL) {
727 0 : xmlSecError(XMLSEC_ERRORS_HERE,
728 : NULL,
729 : "xmlSecTransformCtxCreateAndAppend",
730 : XMLSEC_ERRORS_R_XMLSEC_FAILED,
731 : "transform=%s",
732 0 : xmlSecErrorsSafeString(xmlSecTransformKlassGetName(xmlSecTransformMemBufId)));
733 : }
734 : }
735 :
736 : /* next node is required SignatureMethod. */
737 0 : cur = xmlSecGetNextElementNode( ((cur != NULL) ? cur->next : node->children) );
738 0 : if((cur != NULL) && (xmlSecCheckNodeName(cur, xmlSecNodeSignatureMethod, xmlSecDSigNs))) {
739 0 : dsigCtx->signMethod = xmlSecTransformCtxNodeRead(&(dsigCtx->transformCtx),
740 : cur, xmlSecTransformUsageSignatureMethod);
741 0 : if(dsigCtx->signMethod == NULL) {
742 0 : xmlSecError(XMLSEC_ERRORS_HERE,
743 : NULL,
744 : "xmlSecTransformCtxNodeRead",
745 : XMLSEC_ERRORS_R_XMLSEC_FAILED,
746 : "node=%s",
747 0 : xmlSecErrorsSafeString(xmlSecNodeGetName(cur)));
748 0 : return(-1);
749 : }
750 0 : } else if(dsigCtx->defSignMethodId != xmlSecTransformIdUnknown) {
751 : /* the dsig spec does require SignatureMethod node
752 : * to be present but in some case it application might decide to
753 : * minimize traffic */
754 0 : dsigCtx->signMethod = xmlSecTransformCtxCreateAndAppend(&(dsigCtx->transformCtx),
755 : dsigCtx->defSignMethodId);
756 0 : if(dsigCtx->signMethod == NULL) {
757 0 : xmlSecError(XMLSEC_ERRORS_HERE,
758 : NULL,
759 : "xmlSecTransformCtxAppend",
760 : XMLSEC_ERRORS_R_XMLSEC_FAILED,
761 : XMLSEC_ERRORS_NO_MESSAGE);
762 0 : return(-1);
763 : }
764 : } else {
765 0 : xmlSecError(XMLSEC_ERRORS_HERE,
766 : NULL,
767 0 : xmlSecErrorsSafeString(xmlSecNodeGetName(cur)),
768 : XMLSEC_ERRORS_R_INVALID_NODE,
769 : "expected=%s",
770 : xmlSecErrorsSafeString(xmlSecNodeSignatureMethod));
771 0 : return(-1);
772 : }
773 0 : dsigCtx->signMethod->operation = dsigCtx->operation;
774 :
775 : /* calculate references */
776 0 : cur = xmlSecGetNextElementNode(cur->next);
777 0 : while((cur != NULL) && (xmlSecCheckNodeName(cur, xmlSecNodeReference, xmlSecDSigNs))) {
778 : /* create reference */
779 0 : dsigRefCtx = xmlSecDSigReferenceCtxCreate(dsigCtx, xmlSecDSigReferenceOriginSignedInfo);
780 0 : if(dsigRefCtx == NULL) {
781 0 : xmlSecError(XMLSEC_ERRORS_HERE,
782 : NULL,
783 : "xmlSecDSigReferenceCtxCreate",
784 : XMLSEC_ERRORS_R_XMLSEC_FAILED,
785 : XMLSEC_ERRORS_NO_MESSAGE);
786 0 : return(-1);
787 : }
788 :
789 : /* add to the list */
790 0 : ret = xmlSecPtrListAdd(&(dsigCtx->signedInfoReferences), dsigRefCtx);
791 0 : if(ret < 0) {
792 0 : xmlSecError(XMLSEC_ERRORS_HERE,
793 : NULL,
794 : "xmlSecPtrListAdd",
795 : XMLSEC_ERRORS_R_XMLSEC_FAILED,
796 : XMLSEC_ERRORS_NO_MESSAGE);
797 0 : xmlSecDSigReferenceCtxDestroy(dsigRefCtx);
798 0 : return(-1);
799 : }
800 :
801 : /* process */
802 0 : ret = xmlSecDSigReferenceCtxProcessNode(dsigRefCtx, cur);
803 0 : if(ret < 0) {
804 0 : xmlSecError(XMLSEC_ERRORS_HERE,
805 : NULL,
806 : "xmlSecDSigReferenceCtxProcessNode",
807 : XMLSEC_ERRORS_R_XMLSEC_FAILED,
808 : "node=%s",
809 0 : xmlSecErrorsSafeString(xmlSecNodeGetName(cur)));
810 0 : return(-1);
811 : }
812 :
813 : /* bail out if next Reference processing failed */
814 0 : if(dsigRefCtx->status != xmlSecDSigStatusSucceeded) {
815 0 : dsigCtx->status = xmlSecDSigStatusInvalid;
816 0 : return(0);
817 : }
818 0 : cur = xmlSecGetNextElementNode(cur->next);
819 : }
820 :
821 : /* check that we have at least one Reference */
822 0 : if(xmlSecPtrListGetSize(&(dsigCtx->signedInfoReferences)) == 0) {
823 0 : xmlSecError(XMLSEC_ERRORS_HERE,
824 : NULL,
825 : NULL,
826 : XMLSEC_ERRORS_R_DSIG_NO_REFERENCES,
827 : XMLSEC_ERRORS_NO_MESSAGE);
828 0 : return(-1);
829 : }
830 :
831 : /* if there is something left than it's an error */
832 0 : if(cur != NULL) {
833 0 : xmlSecError(XMLSEC_ERRORS_HERE,
834 : NULL,
835 0 : xmlSecErrorsSafeString(xmlSecNodeGetName(cur)),
836 : XMLSEC_ERRORS_R_UNEXPECTED_NODE,
837 : XMLSEC_ERRORS_NO_MESSAGE);
838 0 : return(-1);
839 : }
840 0 : return(0);
841 : }
842 :
843 : static int
844 0 : xmlSecDSigCtxProcessKeyInfoNode(xmlSecDSigCtxPtr dsigCtx, xmlNodePtr node) {
845 : int ret;
846 :
847 0 : xmlSecAssert2(dsigCtx != NULL, -1);
848 0 : xmlSecAssert2(dsigCtx->signMethod != NULL, -1);
849 :
850 : /* set key requirements */
851 0 : ret = xmlSecTransformSetKeyReq(dsigCtx->signMethod, &(dsigCtx->keyInfoReadCtx.keyReq));
852 0 : if(ret < 0) {
853 0 : xmlSecError(XMLSEC_ERRORS_HERE,
854 : NULL,
855 : "xmlSecTransformSetKeyReq",
856 : XMLSEC_ERRORS_R_XMLSEC_FAILED,
857 : "transform=%s",
858 0 : xmlSecErrorsSafeString(xmlSecTransformGetName(dsigCtx->signMethod)));
859 0 : return(-1);
860 : }
861 :
862 : /* ignore <dsig:KeyInfo /> if there is the key is already set */
863 : /* todo: throw an error if key is set and node != NULL? */
864 0 : if((dsigCtx->signKey == NULL) && (dsigCtx->keyInfoReadCtx.keysMngr != NULL)
865 0 : && (dsigCtx->keyInfoReadCtx.keysMngr->getKey != NULL)) {
866 0 : dsigCtx->signKey = (dsigCtx->keyInfoReadCtx.keysMngr->getKey)(node, &(dsigCtx->keyInfoReadCtx));
867 : }
868 :
869 : /* check that we have exactly what we want */
870 0 : if((dsigCtx->signKey == NULL) || (!xmlSecKeyMatch(dsigCtx->signKey, NULL, &(dsigCtx->keyInfoReadCtx.keyReq)))) {
871 0 : xmlSecError(XMLSEC_ERRORS_HERE,
872 : NULL,
873 : NULL,
874 : XMLSEC_ERRORS_R_KEY_NOT_FOUND,
875 : XMLSEC_ERRORS_NO_MESSAGE);
876 0 : return(-1);
877 : }
878 :
879 : /* set the key to the transform */
880 0 : ret = xmlSecTransformSetKey(dsigCtx->signMethod, dsigCtx->signKey);
881 0 : if(ret < 0) {
882 0 : xmlSecError(XMLSEC_ERRORS_HERE,
883 : NULL,
884 : "xmlSecTransformSetKey",
885 : XMLSEC_ERRORS_R_XMLSEC_FAILED,
886 : "transform=%s",
887 0 : xmlSecErrorsSafeString(xmlSecTransformGetName(dsigCtx->signMethod)));
888 0 : return(-1);
889 : }
890 :
891 : /* if we are signing document, update <dsig:KeyInfo/> node */
892 0 : if((node != NULL) && (dsigCtx->operation == xmlSecTransformOperationSign)) {
893 0 : ret = xmlSecKeyInfoNodeWrite(node, dsigCtx->signKey, &(dsigCtx->keyInfoWriteCtx));
894 0 : if(ret < 0) {
895 0 : xmlSecError(XMLSEC_ERRORS_HERE,
896 : NULL,
897 : "xmlSecKeyInfoNodeWrite",
898 : XMLSEC_ERRORS_R_XMLSEC_FAILED,
899 : XMLSEC_ERRORS_NO_MESSAGE);
900 0 : return(-1);
901 : }
902 : }
903 :
904 0 : return(0);
905 : }
906 :
907 : /**
908 : * xmlSecDSigCtxProcessObjectNode:
909 : *
910 : * The Object Element (http://www.w3.org/TR/xmldsig-core/#sec-Object)
911 : *
912 : * Object is an optional element that may occur one or more times. When
913 : * present, this element may contain any data. The Object element may include
914 : * optional MIME type, ID, and encoding attributes.
915 : *
916 : * Schema Definition:
917 : *
918 : * <element name="Object" type="ds:ObjectType"/>
919 : * <complexType name="ObjectType" mixed="true">
920 : * <sequence minOccurs="0" maxOccurs="unbounded">
921 : * <any namespace="##any" processContents="lax"/>
922 : * </sequence>
923 : * <attribute name="Id" type="ID" use="optional"/>
924 : * <attribute name="MimeType" type="string" use="optional"/>
925 : * <attribute name="Encoding" type="anyURI" use="optional"/>
926 : * </complexType>
927 : *
928 : * DTD:
929 : *
930 : * <!ELEMENT Object (#PCDATA|Signature|SignatureProperties|Manifest %Object.ANY;)* >
931 : * <!ATTLIST Object Id ID #IMPLIED
932 : * MimeType CDATA #IMPLIED
933 : * Encoding CDATA #IMPLIED >
934 : */
935 : static int
936 0 : xmlSecDSigCtxProcessObjectNode(xmlSecDSigCtxPtr dsigCtx, xmlNodePtr node) {
937 : xmlNodePtr cur;
938 : int ret;
939 :
940 0 : xmlSecAssert2(dsigCtx != NULL, -1);
941 0 : xmlSecAssert2(dsigCtx->status == xmlSecDSigStatusUnknown, -1);
942 0 : xmlSecAssert2(node != NULL, -1);
943 :
944 : /* we care about Manifest nodes only; ignore everything else */
945 0 : cur = xmlSecGetNextElementNode(node->children);
946 0 : while(cur != NULL) {
947 0 : if(xmlSecCheckNodeName(cur, xmlSecNodeManifest, xmlSecDSigNs)) {
948 0 : ret = xmlSecDSigCtxProcessManifestNode(dsigCtx, cur);
949 0 : if(ret < 0){
950 0 : xmlSecError(XMLSEC_ERRORS_HERE,
951 : NULL,
952 : "xmlSecDSigCtxProcessManifestNode",
953 : XMLSEC_ERRORS_R_XMLSEC_FAILED,
954 : XMLSEC_ERRORS_NO_MESSAGE);
955 0 : return(-1);
956 : }
957 : }
958 0 : cur = xmlSecGetNextElementNode(cur->next);
959 : }
960 0 : return(0);
961 : }
962 :
963 : /**
964 : * xmlSecDSigCtxProcessManifestNode:
965 : *
966 : * The Manifest Element (http://www.w3.org/TR/xmldsig-core/#sec-Manifest)
967 : *
968 : * The Manifest element provides a list of References. The difference from
969 : * the list in SignedInfo is that it is application defined which, if any, of
970 : * the digests are actually checked against the objects referenced and what to
971 : * do if the object is inaccessible or the digest compare fails. If a Manifest
972 : * is pointed to from SignedInfo, the digest over the Manifest itself will be
973 : * checked by the core result validation behavior. The digests within such
974 : * a Manifest are checked at the application's discretion. If a Manifest is
975 : * referenced from another Manifest, even the overall digest of this two level
976 : * deep Manifest might not be checked.
977 : *
978 : * Schema Definition:
979 : *
980 : * <element name="Manifest" type="ds:ManifestType"/>
981 : * <complexType name="ManifestType">
982 : * <sequence>
983 : * <element ref="ds:Reference" maxOccurs="unbounded"/>
984 : * </sequence>
985 : * <attribute name="Id" type="ID" use="optional"/>
986 : * </complexType>
987 : *
988 : * DTD:
989 : *
990 : * <!ELEMENT Manifest (Reference+) >
991 : * <!ATTLIST Manifest Id ID #IMPLIED >
992 : */
993 : static int
994 0 : xmlSecDSigCtxProcessManifestNode(xmlSecDSigCtxPtr dsigCtx, xmlNodePtr node) {
995 : xmlSecDSigReferenceCtxPtr dsigRefCtx;
996 : xmlNodePtr cur;
997 : int ret;
998 :
999 0 : xmlSecAssert2(dsigCtx != NULL, -1);
1000 0 : xmlSecAssert2(dsigCtx->status == xmlSecDSigStatusUnknown, -1);
1001 0 : xmlSecAssert2(node != NULL, -1);
1002 :
1003 : /* calculate references */
1004 0 : cur = xmlSecGetNextElementNode(node->children);
1005 0 : while((cur != NULL) && (xmlSecCheckNodeName(cur, xmlSecNodeReference, xmlSecDSigNs))) {
1006 : /* create reference */
1007 0 : dsigRefCtx = xmlSecDSigReferenceCtxCreate(dsigCtx, xmlSecDSigReferenceOriginManifest);
1008 0 : if(dsigRefCtx == NULL) {
1009 0 : xmlSecError(XMLSEC_ERRORS_HERE,
1010 : NULL,
1011 : "xmlSecDSigReferenceCtxCreate",
1012 : XMLSEC_ERRORS_R_XMLSEC_FAILED,
1013 : XMLSEC_ERRORS_NO_MESSAGE);
1014 0 : return(-1);
1015 : }
1016 :
1017 : /* add to the list */
1018 0 : ret = xmlSecPtrListAdd(&(dsigCtx->manifestReferences), dsigRefCtx);
1019 0 : if(ret < 0) {
1020 0 : xmlSecError(XMLSEC_ERRORS_HERE,
1021 : NULL,
1022 : "xmlSecPtrListAdd",
1023 : XMLSEC_ERRORS_R_XMLSEC_FAILED,
1024 : XMLSEC_ERRORS_NO_MESSAGE);
1025 0 : xmlSecDSigReferenceCtxDestroy(dsigRefCtx);
1026 0 : return(-1);
1027 : }
1028 :
1029 : /* process */
1030 0 : ret = xmlSecDSigReferenceCtxProcessNode(dsigRefCtx, cur);
1031 0 : if(ret < 0) {
1032 0 : xmlSecError(XMLSEC_ERRORS_HERE,
1033 : NULL,
1034 : "xmlSecDSigReferenceCtxProcessNode",
1035 : XMLSEC_ERRORS_R_XMLSEC_FAILED,
1036 : "node=%s",
1037 0 : xmlSecErrorsSafeString(xmlSecNodeGetName(cur)));
1038 0 : return(-1);
1039 : }
1040 :
1041 : /* we don;t care if Reference processing failed because
1042 : * it's Manifest node */
1043 0 : cur = xmlSecGetNextElementNode(cur->next);
1044 : }
1045 :
1046 : /* we should have nothing else here */
1047 0 : if(cur != NULL) {
1048 0 : xmlSecError(XMLSEC_ERRORS_HERE,
1049 : NULL,
1050 0 : xmlSecErrorsSafeString(xmlSecNodeGetName(cur)),
1051 : XMLSEC_ERRORS_R_UNEXPECTED_NODE,
1052 : XMLSEC_ERRORS_NO_MESSAGE);
1053 0 : return(-1);
1054 : }
1055 0 : return(0);
1056 : }
1057 :
1058 : /**
1059 : * xmlSecDSigCtxDebugDump:
1060 : * @dsigCtx: the pointer to <dsig:Signature/> processing context.
1061 : * @output: the pointer to output FILE.
1062 : *
1063 : * Prints the debug information about @dsigCtx to @output.
1064 : */
1065 : void
1066 0 : xmlSecDSigCtxDebugDump(xmlSecDSigCtxPtr dsigCtx, FILE* output) {
1067 0 : xmlSecAssert(dsigCtx != NULL);
1068 0 : xmlSecAssert(output != NULL);
1069 :
1070 0 : if(dsigCtx->operation == xmlSecTransformOperationSign) {
1071 0 : fprintf(output, "= SIGNATURE CONTEXT\n");
1072 : } else {
1073 0 : fprintf(output, "= VERIFICATION CONTEXT\n");
1074 : }
1075 0 : switch(dsigCtx->status) {
1076 : case xmlSecDSigStatusUnknown:
1077 0 : fprintf(output, "== Status: unknown\n");
1078 0 : break;
1079 : case xmlSecDSigStatusSucceeded:
1080 0 : fprintf(output, "== Status: succeeded\n");
1081 0 : break;
1082 : case xmlSecDSigStatusInvalid:
1083 0 : fprintf(output, "== Status: invalid\n");
1084 0 : break;
1085 : }
1086 0 : fprintf(output, "== flags: 0x%08x\n", dsigCtx->flags);
1087 0 : fprintf(output, "== flags2: 0x%08x\n", dsigCtx->flags2);
1088 :
1089 0 : if(dsigCtx->id != NULL) {
1090 0 : fprintf(output, "== Id: \"%s\"\n", dsigCtx->id);
1091 : }
1092 :
1093 0 : fprintf(output, "== Key Info Read Ctx:\n");
1094 0 : xmlSecKeyInfoCtxDebugDump(&(dsigCtx->keyInfoReadCtx), output);
1095 0 : fprintf(output, "== Key Info Write Ctx:\n");
1096 0 : xmlSecKeyInfoCtxDebugDump(&(dsigCtx->keyInfoWriteCtx), output);
1097 :
1098 0 : fprintf(output, "== Signature Transform Ctx:\n");
1099 0 : xmlSecTransformCtxDebugDump(&(dsigCtx->transformCtx), output);
1100 :
1101 0 : if(dsigCtx->signMethod != NULL) {
1102 0 : fprintf(output, "== Signature Method:\n");
1103 0 : xmlSecTransformDebugDump(dsigCtx->signMethod, output);
1104 : }
1105 :
1106 0 : if(dsigCtx->signKey != NULL) {
1107 0 : fprintf(output, "== Signature Key:\n");
1108 0 : xmlSecKeyDebugDump(dsigCtx->signKey, output);
1109 : }
1110 :
1111 0 : fprintf(output, "== SignedInfo References List:\n");
1112 0 : xmlSecPtrListDebugDump(&(dsigCtx->signedInfoReferences), output);
1113 :
1114 0 : fprintf(output, "== Manifest References List:\n");
1115 0 : xmlSecPtrListDebugDump(&(dsigCtx->manifestReferences), output);
1116 :
1117 0 : if((dsigCtx->result != NULL) &&
1118 0 : (xmlSecBufferGetData(dsigCtx->result) != NULL)) {
1119 :
1120 0 : fprintf(output, "== Result - start buffer:\n");
1121 0 : fwrite(xmlSecBufferGetData(dsigCtx->result),
1122 : xmlSecBufferGetSize(dsigCtx->result),
1123 : 1, output);
1124 0 : fprintf(output, "\n== Result - end buffer\n");
1125 : }
1126 0 : if(((dsigCtx->flags & XMLSEC_DSIG_FLAGS_STORE_SIGNATURE) != 0) &&
1127 0 : (xmlSecDSigCtxGetPreSignBuffer(dsigCtx) != NULL) &&
1128 0 : (xmlSecBufferGetData(xmlSecDSigCtxGetPreSignBuffer(dsigCtx)) != NULL)) {
1129 :
1130 0 : fprintf(output, "== PreSigned data - start buffer:\n");
1131 0 : fwrite(xmlSecBufferGetData(xmlSecDSigCtxGetPreSignBuffer(dsigCtx)),
1132 : xmlSecBufferGetSize(xmlSecDSigCtxGetPreSignBuffer(dsigCtx)),
1133 : 1, output);
1134 0 : fprintf(output, "\n== PreSigned data - end buffer\n");
1135 : }
1136 : }
1137 :
1138 : /**
1139 : * xmlSecDSigCtxDebugXmlDump:
1140 : * @dsigCtx: the pointer to <dsig:Signature/> processing context.
1141 : * @output: the pointer to output FILE.
1142 : *
1143 : * Prints the debug information about @dsigCtx to @output in XML format.
1144 : */
1145 : void
1146 0 : xmlSecDSigCtxDebugXmlDump(xmlSecDSigCtxPtr dsigCtx, FILE* output) {
1147 0 : xmlSecAssert(dsigCtx != NULL);
1148 0 : xmlSecAssert(output != NULL);
1149 :
1150 0 : if(dsigCtx->operation == xmlSecTransformOperationSign) {
1151 0 : fprintf(output, "<SignatureContext \n");
1152 : } else {
1153 0 : fprintf(output, "<VerificationContext \n");
1154 : }
1155 0 : switch(dsigCtx->status) {
1156 : case xmlSecDSigStatusUnknown:
1157 0 : fprintf(output, "status=\"unknown\" >\n");
1158 0 : break;
1159 : case xmlSecDSigStatusSucceeded:
1160 0 : fprintf(output, "status=\"succeeded\" >\n");
1161 0 : break;
1162 : case xmlSecDSigStatusInvalid:
1163 0 : fprintf(output, "status=\"invalid\" >\n");
1164 0 : break;
1165 : }
1166 :
1167 0 : fprintf(output, "<Flags>%08x</Flags>\n", dsigCtx->flags);
1168 0 : fprintf(output, "<Flags2>%08x</Flags2>\n", dsigCtx->flags2);
1169 :
1170 0 : fprintf(output, "<Id>");
1171 0 : xmlSecPrintXmlString(output, dsigCtx->id);
1172 0 : fprintf(output, "</Id>\n");
1173 :
1174 0 : fprintf(output, "<KeyInfoReadCtx>\n");
1175 0 : xmlSecKeyInfoCtxDebugXmlDump(&(dsigCtx->keyInfoReadCtx), output);
1176 0 : fprintf(output, "</KeyInfoReadCtx>\n");
1177 :
1178 0 : fprintf(output, "<KeyInfoWriteCtx>\n");
1179 0 : xmlSecKeyInfoCtxDebugXmlDump(&(dsigCtx->keyInfoWriteCtx), output);
1180 0 : fprintf(output, "</KeyInfoWriteCtx>\n");
1181 :
1182 0 : fprintf(output, "<SignatureTransformCtx>\n");
1183 0 : xmlSecTransformCtxDebugXmlDump(&(dsigCtx->transformCtx), output);
1184 0 : fprintf(output, "</SignatureTransformCtx>\n");
1185 :
1186 0 : if(dsigCtx->signMethod != NULL) {
1187 0 : fprintf(output, "<SignatureMethod>\n");
1188 0 : xmlSecTransformDebugXmlDump(dsigCtx->signMethod, output);
1189 0 : fprintf(output, "</SignatureMethod>\n");
1190 : }
1191 :
1192 0 : if(dsigCtx->signKey != NULL) {
1193 0 : fprintf(output, "<SignatureKey>\n");
1194 0 : xmlSecKeyDebugXmlDump(dsigCtx->signKey, output);
1195 0 : fprintf(output, "</SignatureKey>\n");
1196 : }
1197 :
1198 0 : fprintf(output, "<SignedInfoReferences>\n");
1199 0 : xmlSecPtrListDebugXmlDump(&(dsigCtx->signedInfoReferences), output);
1200 0 : fprintf(output, "</SignedInfoReferences>\n");
1201 :
1202 0 : fprintf(output, "<ManifestReferences>\n");
1203 0 : xmlSecPtrListDebugXmlDump(&(dsigCtx->manifestReferences), output);
1204 0 : fprintf(output, "</ManifestReferences>\n");
1205 :
1206 0 : if((dsigCtx->result != NULL) &&
1207 0 : (xmlSecBufferGetData(dsigCtx->result) != NULL)) {
1208 :
1209 0 : fprintf(output, "<Result>");
1210 0 : fwrite(xmlSecBufferGetData(dsigCtx->result),
1211 : xmlSecBufferGetSize(dsigCtx->result),
1212 : 1, output);
1213 0 : fprintf(output, "</Result>\n");
1214 : }
1215 0 : if(((dsigCtx->flags & XMLSEC_DSIG_FLAGS_STORE_SIGNATURE) != 0) &&
1216 0 : (xmlSecDSigCtxGetPreSignBuffer(dsigCtx) != NULL) &&
1217 0 : (xmlSecBufferGetData(xmlSecDSigCtxGetPreSignBuffer(dsigCtx)) != NULL)) {
1218 :
1219 0 : fprintf(output, "<PreSignedData>");
1220 0 : fwrite(xmlSecBufferGetData(xmlSecDSigCtxGetPreSignBuffer(dsigCtx)),
1221 : xmlSecBufferGetSize(xmlSecDSigCtxGetPreSignBuffer(dsigCtx)),
1222 : 1, output);
1223 0 : fprintf(output, "</PreSignedData>\n");
1224 : }
1225 :
1226 0 : if(dsigCtx->operation == xmlSecTransformOperationSign) {
1227 0 : fprintf(output, "</SignatureContext>\n");
1228 : } else {
1229 0 : fprintf(output, "</VerificationContext>\n");
1230 : }
1231 : }
1232 :
1233 : /**************************************************************************
1234 : *
1235 : * xmlSecDSigReferenceCtx
1236 : *
1237 : *************************************************************************/
1238 : /**
1239 : * xmlSecDSigReferenceCtxCreate:
1240 : * @dsigCtx: the pointer to parent <dsig:Signature/> node processing context.
1241 : * @origin: the reference origin (<dsig:SignedInfo/> or <dsig:Manifest/> node).
1242 : *
1243 : * Creates new <dsig:Reference/> element processing context. Caller is responsible
1244 : * for destroying the returned context by calling #xmlSecDSigReferenceCtxDestroy
1245 : * function.
1246 : *
1247 : * Returns: pointer to newly created context or NULL if an error occurs.
1248 : */
1249 : xmlSecDSigReferenceCtxPtr
1250 0 : xmlSecDSigReferenceCtxCreate(xmlSecDSigCtxPtr dsigCtx, xmlSecDSigReferenceOrigin origin) {
1251 : xmlSecDSigReferenceCtxPtr dsigRefCtx;
1252 : int ret;
1253 :
1254 0 : xmlSecAssert2(dsigCtx != NULL, NULL);
1255 :
1256 0 : dsigRefCtx = (xmlSecDSigReferenceCtxPtr) xmlMalloc(sizeof(xmlSecDSigReferenceCtx));
1257 0 : if(dsigRefCtx == NULL) {
1258 0 : xmlSecError(XMLSEC_ERRORS_HERE,
1259 : NULL,
1260 : NULL,
1261 : XMLSEC_ERRORS_R_MALLOC_FAILED,
1262 : "sizeof(xmlSecDSigReferenceCtx)=%d",
1263 : sizeof(xmlSecDSigReferenceCtx));
1264 0 : return(NULL);
1265 : }
1266 :
1267 0 : ret = xmlSecDSigReferenceCtxInitialize(dsigRefCtx, dsigCtx, origin);
1268 0 : if(ret < 0) {
1269 0 : xmlSecError(XMLSEC_ERRORS_HERE,
1270 : NULL,
1271 : "xmlSecDSigReferenceCtxInitialize",
1272 : XMLSEC_ERRORS_R_XMLSEC_FAILED,
1273 : XMLSEC_ERRORS_NO_MESSAGE);
1274 0 : xmlSecDSigReferenceCtxDestroy(dsigRefCtx);
1275 0 : return(NULL);
1276 : }
1277 0 : return(dsigRefCtx);
1278 : }
1279 :
1280 : /**
1281 : * xmlSecDSigReferenceCtxDestroy:
1282 : * @dsigRefCtx: the pointer to <dsig:Reference/> element processing context.
1283 : *
1284 : * Destroy context object created with #xmlSecDSigReferenceCtxCreate function.
1285 : */
1286 : void
1287 0 : xmlSecDSigReferenceCtxDestroy(xmlSecDSigReferenceCtxPtr dsigRefCtx) {
1288 0 : xmlSecAssert(dsigRefCtx != NULL);
1289 :
1290 0 : xmlSecDSigReferenceCtxFinalize(dsigRefCtx);
1291 0 : xmlFree(dsigRefCtx);
1292 : }
1293 :
1294 : /**
1295 : * xmlSecDSigReferenceCtxInitialize:
1296 : * @dsigRefCtx: the pointer to <dsig:Reference/> element processing context.
1297 : * @dsigCtx: the pointer to parent <dsig:Signature/> node processing context.
1298 : * @origin: the reference origin (<dsig:SignedInfo/> or <dsig:Manifest/> node).
1299 : *
1300 : * Initializes new <dsig:Reference/> element processing context. Caller is responsible
1301 : * for cleaning up the returned context by calling #xmlSecDSigReferenceCtxFinalize
1302 : * function.
1303 : *
1304 : * Returns: 0 on succes or aa negative value otherwise.
1305 : */
1306 : int
1307 0 : xmlSecDSigReferenceCtxInitialize(xmlSecDSigReferenceCtxPtr dsigRefCtx, xmlSecDSigCtxPtr dsigCtx,
1308 : xmlSecDSigReferenceOrigin origin) {
1309 : int ret;
1310 :
1311 0 : xmlSecAssert2(dsigCtx != NULL, -1);
1312 0 : xmlSecAssert2(dsigRefCtx != NULL, -1);
1313 :
1314 0 : memset(dsigRefCtx, 0, sizeof(xmlSecDSigReferenceCtx));
1315 :
1316 0 : dsigRefCtx->dsigCtx = dsigCtx;
1317 0 : dsigRefCtx->origin = origin;
1318 :
1319 : /* initializes transforms dsigRefCtx */
1320 0 : ret = xmlSecTransformCtxInitialize(&(dsigRefCtx->transformCtx));
1321 0 : if(ret < 0) {
1322 0 : xmlSecError(XMLSEC_ERRORS_HERE,
1323 : NULL,
1324 : "xmlSecTransformCtxInitialize",
1325 : XMLSEC_ERRORS_R_XMLSEC_FAILED,
1326 : XMLSEC_ERRORS_NO_MESSAGE);
1327 0 : return(-1);
1328 : }
1329 :
1330 : /* copy enabled transforms */
1331 0 : if(dsigCtx->enabledReferenceTransforms != NULL) {
1332 0 : ret = xmlSecPtrListCopy(&(dsigRefCtx->transformCtx.enabledTransforms),
1333 : dsigCtx->enabledReferenceTransforms);
1334 0 : if(ret < 0) {
1335 0 : xmlSecError(XMLSEC_ERRORS_HERE,
1336 : NULL,
1337 : "xmlSecPtrListCopy",
1338 : XMLSEC_ERRORS_R_XMLSEC_FAILED,
1339 : XMLSEC_ERRORS_NO_MESSAGE);
1340 0 : return(-1);
1341 : }
1342 : }
1343 0 : dsigRefCtx->transformCtx.preExecCallback = dsigCtx->referencePreExecuteCallback;
1344 0 : dsigRefCtx->transformCtx.enabledUris = dsigCtx->enabledReferenceUris;
1345 :
1346 0 : if((dsigCtx->flags & XMLSEC_DSIG_FLAGS_USE_VISA3D_HACK) != 0) {
1347 0 : dsigRefCtx->transformCtx.flags |= XMLSEC_TRANSFORMCTX_FLAGS_USE_VISA3D_HACK;
1348 : }
1349 0 : return(0);
1350 : }
1351 :
1352 : /**
1353 : * xmlSecDSigReferenceCtxFinalize:
1354 : * @dsigRefCtx: the pointer to <dsig:Reference/> element processing context.
1355 : *
1356 : * Cleans up context object created with #xmlSecDSigReferenceCtxInitialize function.
1357 : */
1358 : void
1359 0 : xmlSecDSigReferenceCtxFinalize(xmlSecDSigReferenceCtxPtr dsigRefCtx) {
1360 0 : xmlSecAssert(dsigRefCtx != NULL);
1361 :
1362 0 : xmlSecTransformCtxFinalize(&(dsigRefCtx->transformCtx));
1363 0 : if(dsigRefCtx->id != NULL) {
1364 0 : xmlFree(dsigRefCtx->id);
1365 : }
1366 0 : if(dsigRefCtx->uri != NULL) {
1367 0 : xmlFree(dsigRefCtx->uri);
1368 : }
1369 0 : if(dsigRefCtx->type != NULL) {
1370 0 : xmlFree(dsigRefCtx->type);
1371 : }
1372 0 : memset(dsigRefCtx, 0, sizeof(xmlSecDSigReferenceCtx));
1373 : }
1374 :
1375 : /**
1376 : * xmlSecDSigReferenceCtxGetPreDigestBuffer:
1377 : * @dsigRefCtx: the pointer to <dsig:Reference/> element processing context.
1378 : *
1379 : * Gets the results of <dsig:Reference/> node processing just before digesting
1380 : * (valid only if #XMLSEC_DSIG_FLAGS_STORE_SIGNEDINFO_REFERENCES or
1381 : * #XMLSEC_DSIG_FLAGS_STORE_MANIFEST_REFERENCES flas of signature context
1382 : * is set).
1383 : *
1384 : * Returns: pointer to the buffer or NULL if an error occurs.
1385 : */
1386 : xmlSecBufferPtr
1387 0 : xmlSecDSigReferenceCtxGetPreDigestBuffer(xmlSecDSigReferenceCtxPtr dsigRefCtx) {
1388 0 : xmlSecAssert2(dsigRefCtx != NULL, NULL);
1389 :
1390 0 : return((dsigRefCtx->preDigestMemBufMethod != NULL) ?
1391 0 : xmlSecTransformMemBufGetBuffer(dsigRefCtx->preDigestMemBufMethod) : NULL);
1392 : }
1393 :
1394 : /**
1395 : * xmlSecDSigReferenceCtxProcessNode:
1396 : * @dsigRefCtx: the pointer to <dsig:Reference/> element processing context.
1397 : * @node: the pointer to <dsig:Reference/> node.
1398 :
1399 : * The Reference Element (http://www.w3.org/TR/xmldsig-core/#sec-Reference)
1400 : *
1401 : * Reference is an element that may occur one or more times. It specifies
1402 : * a digest algorithm and digest value, and optionally an identifier of the
1403 : * object being signed, the type of the object, and/or a list of transforms
1404 : * to be applied prior to digesting. The identification (URI) and transforms
1405 : * describe how the digested content (i.e., the input to the digest method)
1406 : * was created. The Type attribute facilitates the processing of referenced
1407 : * data. For example, while this specification makes no requirements over
1408 : * external data, an application may wish to signal that the referent is a
1409 : * Manifest. An optional ID attribute permits a Reference to be referenced
1410 : * from elsewhere.
1411 : *
1412 : * Returns: 0 on succes or aa negative value otherwise.
1413 : */
1414 : int
1415 0 : xmlSecDSigReferenceCtxProcessNode(xmlSecDSigReferenceCtxPtr dsigRefCtx, xmlNodePtr node) {
1416 : xmlSecTransformCtxPtr transformCtx;
1417 : xmlNodePtr digestValueNode;
1418 : xmlNodePtr cur;
1419 : int ret;
1420 :
1421 0 : xmlSecAssert2(dsigRefCtx != NULL, -1);
1422 0 : xmlSecAssert2(dsigRefCtx->dsigCtx != NULL, -1);
1423 0 : xmlSecAssert2(dsigRefCtx->digestMethod == NULL, -1);
1424 0 : xmlSecAssert2(dsigRefCtx->digestMethod == NULL, -1);
1425 0 : xmlSecAssert2(dsigRefCtx->preDigestMemBufMethod == NULL, -1);
1426 0 : xmlSecAssert2(node != NULL, -1);
1427 0 : xmlSecAssert2(node->doc != NULL, -1);
1428 :
1429 0 : transformCtx = &(dsigRefCtx->transformCtx);
1430 :
1431 : /* read attributes first */
1432 0 : dsigRefCtx->uri = xmlGetProp(node, xmlSecAttrURI);
1433 0 : dsigRefCtx->id = xmlGetProp(node, xmlSecAttrId);
1434 0 : dsigRefCtx->type= xmlGetProp(node, xmlSecAttrType);
1435 :
1436 : /* set start URI (and check that it is enabled!) */
1437 0 : ret = xmlSecTransformCtxSetUri(transformCtx, dsigRefCtx->uri, node);
1438 0 : if(ret < 0) {
1439 0 : xmlSecError(XMLSEC_ERRORS_HERE,
1440 : NULL,
1441 : "xmlSecTransformCtxSetUri",
1442 : XMLSEC_ERRORS_R_XMLSEC_FAILED,
1443 : "uri=%s",
1444 0 : xmlSecErrorsSafeString(dsigRefCtx->uri));
1445 0 : return(-1);
1446 : }
1447 :
1448 : /* first is optional Transforms node */
1449 0 : cur = xmlSecGetNextElementNode(node->children);
1450 0 : if((cur != NULL) && (xmlSecCheckNodeName(cur, xmlSecNodeTransforms, xmlSecDSigNs))) {
1451 0 : ret = xmlSecTransformCtxNodesListRead(transformCtx,
1452 : cur, xmlSecTransformUsageDSigTransform);
1453 0 : if(ret < 0) {
1454 0 : xmlSecError(XMLSEC_ERRORS_HERE,
1455 : NULL,
1456 : "xmlSecTransformCtxNodesListRead",
1457 : XMLSEC_ERRORS_R_XMLSEC_FAILED,
1458 : "node=%s",
1459 0 : xmlSecErrorsSafeString(xmlSecNodeGetName(cur)));
1460 0 : return(-1);
1461 : }
1462 :
1463 0 : cur = xmlSecGetNextElementNode(cur->next);
1464 : }
1465 :
1466 : /* insert membuf if requested */
1467 0 : if(((dsigRefCtx->origin == xmlSecDSigReferenceOriginSignedInfo) &&
1468 0 : ((dsigRefCtx->dsigCtx->flags & XMLSEC_DSIG_FLAGS_STORE_SIGNEDINFO_REFERENCES) != 0)) ||
1469 0 : ((dsigRefCtx->origin == xmlSecDSigReferenceOriginManifest) &&
1470 0 : ((dsigRefCtx->dsigCtx->flags & XMLSEC_DSIG_FLAGS_STORE_MANIFEST_REFERENCES) != 0))) {
1471 :
1472 0 : xmlSecAssert2(dsigRefCtx->preDigestMemBufMethod == NULL, -1);
1473 0 : dsigRefCtx->preDigestMemBufMethod = xmlSecTransformCtxCreateAndAppend(
1474 : transformCtx,
1475 : xmlSecTransformMemBufId);
1476 0 : if(dsigRefCtx->preDigestMemBufMethod == NULL) {
1477 0 : xmlSecError(XMLSEC_ERRORS_HERE,
1478 : NULL,
1479 : "xmlSecTransformCtxCreateAndAppend",
1480 : XMLSEC_ERRORS_R_XMLSEC_FAILED,
1481 : "transform=%s",
1482 0 : xmlSecErrorsSafeString(xmlSecTransformKlassGetName(xmlSecTransformMemBufId)));
1483 0 : return(-1);
1484 : }
1485 : }
1486 :
1487 : /* next node is required DigestMethod. */
1488 0 : if((cur != NULL) && (xmlSecCheckNodeName(cur, xmlSecNodeDigestMethod, xmlSecDSigNs))) {
1489 0 : dsigRefCtx->digestMethod = xmlSecTransformCtxNodeRead(&(dsigRefCtx->transformCtx),
1490 : cur, xmlSecTransformUsageDigestMethod);
1491 0 : if(dsigRefCtx->digestMethod == NULL) {
1492 0 : xmlSecError(XMLSEC_ERRORS_HERE,
1493 : NULL,
1494 : "xmlSecTransformCtxNodeRead",
1495 : XMLSEC_ERRORS_R_XMLSEC_FAILED,
1496 : "node=%s",
1497 0 : xmlSecErrorsSafeString(xmlSecNodeGetName(cur)));
1498 0 : return(-1);
1499 : }
1500 :
1501 0 : cur = xmlSecGetNextElementNode(cur->next);
1502 0 : } else if(dsigRefCtx->dsigCtx->defSignMethodId != xmlSecTransformIdUnknown) {
1503 : /* the dsig spec does require DigestMethod node
1504 : * to be present but in some case it application might decide to
1505 : * minimize traffic */
1506 0 : dsigRefCtx->digestMethod = xmlSecTransformCtxCreateAndAppend(&(dsigRefCtx->transformCtx),
1507 0 : dsigRefCtx->dsigCtx->defSignMethodId);
1508 0 : if(dsigRefCtx->digestMethod == NULL) {
1509 0 : xmlSecError(XMLSEC_ERRORS_HERE,
1510 : NULL,
1511 : "xmlSecTransformCtxAppend",
1512 : XMLSEC_ERRORS_R_XMLSEC_FAILED,
1513 : XMLSEC_ERRORS_NO_MESSAGE);
1514 0 : return(-1);
1515 : }
1516 : } else {
1517 0 : xmlSecError(XMLSEC_ERRORS_HERE,
1518 : NULL,
1519 0 : xmlSecErrorsSafeString(xmlSecNodeGetName(cur)),
1520 : XMLSEC_ERRORS_R_INVALID_NODE,
1521 : "expected=%s",
1522 : xmlSecErrorsSafeString(xmlSecNodeDigestMethod));
1523 0 : return(-1);
1524 : }
1525 0 : dsigRefCtx->digestMethod->operation = dsigRefCtx->dsigCtx->operation;
1526 :
1527 : /* last node is required DigestValue */
1528 0 : if((cur != NULL) && (xmlSecCheckNodeName(cur, xmlSecNodeDigestValue, xmlSecDSigNs))) {
1529 0 : digestValueNode = cur;
1530 0 : cur = xmlSecGetNextElementNode(cur->next);
1531 : } else {
1532 0 : xmlSecError(XMLSEC_ERRORS_HERE,
1533 : NULL,
1534 0 : xmlSecErrorsSafeString(xmlSecNodeGetName(cur)),
1535 : XMLSEC_ERRORS_R_XMLSEC_FAILED,
1536 : "node=%s",
1537 : xmlSecErrorsSafeString(xmlSecNodeDigestValue));
1538 0 : return(-1);
1539 : }
1540 :
1541 : /* if we have something else then it's an error */
1542 0 : if(cur != NULL) {
1543 0 : xmlSecError(XMLSEC_ERRORS_HERE,
1544 : NULL,
1545 0 : xmlSecErrorsSafeString(xmlSecNodeGetName(cur)),
1546 : XMLSEC_ERRORS_R_UNEXPECTED_NODE,
1547 : XMLSEC_ERRORS_NO_MESSAGE);
1548 0 : return(-1);
1549 : }
1550 :
1551 : /* if we need to write result to xml node then we need base64 encode result */
1552 0 : if(dsigRefCtx->dsigCtx->operation == xmlSecTransformOperationSign) {
1553 : xmlSecTransformPtr base64Encode;
1554 :
1555 : /* we need to add base64 encode transform */
1556 0 : base64Encode = xmlSecTransformCtxCreateAndAppend(transformCtx, xmlSecTransformBase64Id);
1557 0 : if(base64Encode == NULL) {
1558 0 : xmlSecError(XMLSEC_ERRORS_HERE,
1559 : NULL,
1560 : "xmlSecTransformCtxCreateAndAppend",
1561 : XMLSEC_ERRORS_R_XMLSEC_FAILED,
1562 : XMLSEC_ERRORS_NO_MESSAGE);
1563 0 : return(-1);
1564 : }
1565 0 : base64Encode->operation = xmlSecTransformOperationEncode;
1566 : }
1567 :
1568 : /* finally get transforms results */
1569 0 : ret = xmlSecTransformCtxExecute(transformCtx, node->doc);
1570 0 : if(ret < 0) {
1571 0 : xmlSecError(XMLSEC_ERRORS_HERE,
1572 : NULL,
1573 : "xmlSecTransformCtxExecute",
1574 : XMLSEC_ERRORS_R_XMLSEC_FAILED,
1575 : XMLSEC_ERRORS_NO_MESSAGE);
1576 0 : return(-1);
1577 : }
1578 0 : dsigRefCtx->result = transformCtx->result;
1579 :
1580 0 : if(dsigRefCtx->dsigCtx->operation == xmlSecTransformOperationSign) {
1581 0 : if((dsigRefCtx->result == NULL) || (xmlSecBufferGetData(dsigRefCtx->result) == NULL)) {
1582 0 : xmlSecError(XMLSEC_ERRORS_HERE,
1583 : NULL,
1584 : "xmlSecTransformCtxExecute",
1585 : XMLSEC_ERRORS_R_XMLSEC_FAILED,
1586 : XMLSEC_ERRORS_NO_MESSAGE);
1587 0 : return(-1);
1588 : }
1589 :
1590 : /* write signed data to xml */
1591 0 : xmlNodeSetContentLen(digestValueNode,
1592 0 : xmlSecBufferGetData(dsigRefCtx->result),
1593 0 : xmlSecBufferGetSize(dsigRefCtx->result));
1594 :
1595 : /* set success status and we are done */
1596 0 : dsigRefCtx->status = xmlSecDSigStatusSucceeded;
1597 : } else {
1598 : /* verify SignatureValue node content */
1599 0 : ret = xmlSecTransformVerifyNodeContent(dsigRefCtx->digestMethod,
1600 : digestValueNode, transformCtx);
1601 0 : if(ret < 0) {
1602 0 : xmlSecError(XMLSEC_ERRORS_HERE,
1603 : NULL,
1604 : "xmlSecTransformVerifyNodeContent",
1605 : XMLSEC_ERRORS_R_XMLSEC_FAILED,
1606 : XMLSEC_ERRORS_NO_MESSAGE);
1607 0 : return(-1);
1608 : }
1609 :
1610 : /* set status and we are done */
1611 0 : if(dsigRefCtx->digestMethod->status == xmlSecTransformStatusOk) {
1612 0 : dsigRefCtx->status = xmlSecDSigStatusSucceeded;
1613 : } else {
1614 0 : dsigRefCtx->status = xmlSecDSigStatusInvalid;
1615 : }
1616 : }
1617 :
1618 0 : return(0);
1619 : }
1620 :
1621 : /**
1622 : * xmlSecDSigReferenceCtxDebugDump:
1623 : * @dsigRefCtx: the pointer to <dsig:Reference/> element processing context.
1624 : * @output: the pointer to output FILE.
1625 : *
1626 : * Prints debug information about @dsigRefCtx to @output.
1627 : */
1628 : void
1629 0 : xmlSecDSigReferenceCtxDebugDump(xmlSecDSigReferenceCtxPtr dsigRefCtx, FILE* output) {
1630 0 : xmlSecAssert(dsigRefCtx != NULL);
1631 0 : xmlSecAssert(dsigRefCtx->dsigCtx != NULL);
1632 0 : xmlSecAssert(output != NULL);
1633 :
1634 0 : if(dsigRefCtx->dsigCtx->operation == xmlSecTransformOperationSign) {
1635 0 : fprintf(output, "= REFERENCE CALCULATION CONTEXT\n");
1636 : } else {
1637 0 : fprintf(output, "= REFERENCE VERIFICATION CONTEXT\n");
1638 : }
1639 0 : switch(dsigRefCtx->status) {
1640 : case xmlSecDSigStatusUnknown:
1641 0 : fprintf(output, "== Status: unknown\n");
1642 0 : break;
1643 : case xmlSecDSigStatusSucceeded:
1644 0 : fprintf(output, "== Status: succeeded\n");
1645 0 : break;
1646 : case xmlSecDSigStatusInvalid:
1647 0 : fprintf(output, "== Status: invalid\n");
1648 0 : break;
1649 : }
1650 0 : if(dsigRefCtx->id != NULL) {
1651 0 : fprintf(output, "== Id: \"%s\"\n", dsigRefCtx->id);
1652 : }
1653 0 : if(dsigRefCtx->uri != NULL) {
1654 0 : fprintf(output, "== URI: \"%s\"\n", dsigRefCtx->uri);
1655 : }
1656 0 : if(dsigRefCtx->type != NULL) {
1657 0 : fprintf(output, "== Type: \"%s\"\n", dsigRefCtx->type);
1658 : }
1659 :
1660 0 : fprintf(output, "== Reference Transform Ctx:\n");
1661 0 : xmlSecTransformCtxDebugDump(&(dsigRefCtx->transformCtx), output);
1662 :
1663 0 : if(dsigRefCtx->digestMethod != NULL) {
1664 0 : fprintf(output, "== Digest Method:\n");
1665 0 : xmlSecTransformDebugDump(dsigRefCtx->digestMethod, output);
1666 : }
1667 :
1668 0 : if((xmlSecDSigReferenceCtxGetPreDigestBuffer(dsigRefCtx) != NULL) &&
1669 0 : (xmlSecBufferGetData(xmlSecDSigReferenceCtxGetPreDigestBuffer(dsigRefCtx)) != NULL)) {
1670 :
1671 0 : fprintf(output, "== PreDigest data - start buffer:\n");
1672 0 : fwrite(xmlSecBufferGetData(xmlSecDSigReferenceCtxGetPreDigestBuffer(dsigRefCtx)),
1673 : xmlSecBufferGetSize(xmlSecDSigReferenceCtxGetPreDigestBuffer(dsigRefCtx)),
1674 : 1, output);
1675 0 : fprintf(output, "\n== PreDigest data - end buffer\n");
1676 : }
1677 :
1678 0 : if((dsigRefCtx->result != NULL) &&
1679 0 : (xmlSecBufferGetData(dsigRefCtx->result) != NULL)) {
1680 :
1681 0 : fprintf(output, "== Result - start buffer:\n");
1682 0 : fwrite(xmlSecBufferGetData(dsigRefCtx->result),
1683 : xmlSecBufferGetSize(dsigRefCtx->result), 1,
1684 : output);
1685 0 : fprintf(output, "\n== Result - end buffer\n");
1686 : }
1687 : }
1688 :
1689 : /**
1690 : * xmlSecDSigReferenceCtxDebugXmlDump:
1691 : * @dsigRefCtx: the pointer to <dsig:Reference/> element processing context.
1692 : * @output: the pointer to output FILE.
1693 : *
1694 : * Prints debug information about @dsigRefCtx to @output in output format.
1695 : */
1696 : void
1697 0 : xmlSecDSigReferenceCtxDebugXmlDump(xmlSecDSigReferenceCtxPtr dsigRefCtx, FILE* output) {
1698 0 : xmlSecAssert(dsigRefCtx != NULL);
1699 0 : xmlSecAssert(dsigRefCtx->dsigCtx != NULL);
1700 0 : xmlSecAssert(output != NULL);
1701 :
1702 0 : if(dsigRefCtx->dsigCtx->operation == xmlSecTransformOperationSign) {
1703 0 : fprintf(output, "<ReferenceCalculationContext ");
1704 : } else {
1705 0 : fprintf(output, "<ReferenceVerificationContext ");
1706 : }
1707 0 : switch(dsigRefCtx->status) {
1708 : case xmlSecDSigStatusUnknown:
1709 0 : fprintf(output, "status=\"unknown\" >\n");
1710 0 : break;
1711 : case xmlSecDSigStatusSucceeded:
1712 0 : fprintf(output, "status=\"succeeded\" >\n");
1713 0 : break;
1714 : case xmlSecDSigStatusInvalid:
1715 0 : fprintf(output, "status=\"invalid\" >\n");
1716 0 : break;
1717 : }
1718 :
1719 0 : fprintf(output, "<Id>");
1720 0 : xmlSecPrintXmlString(output, dsigRefCtx->id);
1721 0 : fprintf(output, "</Id>\n");
1722 :
1723 0 : fprintf(output, "<URI>");
1724 0 : xmlSecPrintXmlString(output, dsigRefCtx->uri);
1725 0 : fprintf(output, "</URI>\n");
1726 :
1727 0 : fprintf(output, "<Type>");
1728 0 : xmlSecPrintXmlString(output, dsigRefCtx->type);
1729 0 : fprintf(output, "</Type>\n");
1730 :
1731 0 : fprintf(output, "<ReferenceTransformCtx>\n");
1732 0 : xmlSecTransformCtxDebugXmlDump(&(dsigRefCtx->transformCtx), output);
1733 0 : fprintf(output, "</ReferenceTransformCtx>\n");
1734 :
1735 0 : if(dsigRefCtx->digestMethod != NULL) {
1736 0 : fprintf(output, "<DigestMethod>\n");
1737 0 : xmlSecTransformDebugXmlDump(dsigRefCtx->digestMethod, output);
1738 0 : fprintf(output, "</DigestMethod>\n");
1739 : }
1740 :
1741 0 : if((dsigRefCtx->result != NULL) &&
1742 0 : (xmlSecBufferGetData(dsigRefCtx->result) != NULL)) {
1743 :
1744 0 : fprintf(output, "<Result>");
1745 0 : fwrite(xmlSecBufferGetData(dsigRefCtx->result),
1746 : xmlSecBufferGetSize(dsigRefCtx->result), 1,
1747 : output);
1748 0 : fprintf(output, "</Result>\n");
1749 : }
1750 :
1751 0 : if((xmlSecDSigReferenceCtxGetPreDigestBuffer(dsigRefCtx) != NULL) &&
1752 0 : (xmlSecBufferGetData(xmlSecDSigReferenceCtxGetPreDigestBuffer(dsigRefCtx)) != NULL)) {
1753 :
1754 0 : fprintf(output, "<PreDigestData>");
1755 0 : fwrite(xmlSecBufferGetData(xmlSecDSigReferenceCtxGetPreDigestBuffer(dsigRefCtx)),
1756 : xmlSecBufferGetSize(xmlSecDSigReferenceCtxGetPreDigestBuffer(dsigRefCtx)),
1757 : 1, output);
1758 0 : fprintf(output, "</PreDigestData>\n");
1759 : }
1760 0 : if(dsigRefCtx->dsigCtx->operation == xmlSecTransformOperationSign) {
1761 0 : fprintf(output, "</ReferenceCalculationContext>\n");
1762 : } else {
1763 0 : fprintf(output, "</ReferenceVerificationContext>\n");
1764 : }
1765 : }
1766 :
1767 :
1768 : /**************************************************************************
1769 : *
1770 : * xmlSecDSigReferenceCtxListKlass
1771 : *
1772 : *************************************************************************/
1773 : static xmlSecPtrListKlass xmlSecDSigReferenceCtxListKlass = {
1774 : BAD_CAST "dsig-reference-list",
1775 : NULL, /* xmlSecPtrDuplicateItemMethod duplicateItem; */
1776 : (xmlSecPtrDestroyItemMethod)xmlSecDSigReferenceCtxDestroy, /* xmlSecPtrDestroyItemMethod destroyItem; */
1777 : (xmlSecPtrDebugDumpItemMethod)xmlSecDSigReferenceCtxDebugDump, /* xmlSecPtrDebugDumpItemMethod debugDumpItem; */
1778 : (xmlSecPtrDebugDumpItemMethod)xmlSecDSigReferenceCtxDebugXmlDump, /* xmlSecPtrDebugDumpItemMethod debugXmlDumpItem; */
1779 : };
1780 :
1781 : /**
1782 : * xmlSecDSigReferenceCtxListGetKlass:
1783 : *
1784 : * The <dsig:Reference/> element processing contexts list klass.
1785 : *
1786 : * Returns: <dsig:Reference/> element processing context list klass.
1787 : */
1788 : xmlSecPtrListId
1789 0 : xmlSecDSigReferenceCtxListGetKlass(void) {
1790 0 : return(&xmlSecDSigReferenceCtxListKlass);
1791 : }
1792 :
1793 : #endif /* XMLSEC_NO_XMLDSIG */
1794 :
1795 :
|