1 /*
2  * XML Security Library (http://www.aleksey.com/xmlsec).
3  *
4  *
5  * This is free software; see Copyright file in the source
6  * distribution for preciese wording.
7  *
8  * Copyright (C) 2002-2016 Aleksey Sanin <aleksey@aleksey.com>. All Rights Reserved.
9  */
10 /**
11  * SECTION:xmlenc
12  * @Short_description: XML Encryption support.
13  * @Stability: Stable
14  *
15  * [XML Encryption](http://www.w3.org/TR/xmlenc-core) implementation.
16  */
17 
18 #include "globals.h"
19 
20 #ifndef XMLSEC_NO_XMLENC
21 
22 #include <stdlib.h>
23 #include <stdio.h>
24 #include <string.h>
25 
26 #include <libxml/tree.h>
27 #include <libxml/parser.h>
28 
29 #include <xmlsec/xmlsec.h>
30 #include <xmlsec/buffer.h>
31 #include <xmlsec/xmltree.h>
32 #include <xmlsec/keys.h>
33 #include <xmlsec/keysmngr.h>
34 #include <xmlsec/transforms.h>
35 #include <xmlsec/keyinfo.h>
36 #include <xmlsec/xmlenc.h>
37 #include <xmlsec/errors.h>
38 
39 static int      xmlSecEncCtxEncDataNodeRead             (xmlSecEncCtxPtr encCtx,
40                                                          xmlNodePtr node);
41 static int      xmlSecEncCtxEncDataNodeWrite            (xmlSecEncCtxPtr encCtx);
42 static int      xmlSecEncCtxCipherDataNodeRead          (xmlSecEncCtxPtr encCtx,
43                                                          xmlNodePtr node);
44 static int      xmlSecEncCtxCipherReferenceNodeRead     (xmlSecEncCtxPtr encCtx,
45                                                          xmlNodePtr node);
46 
47 /* The ID attribute in XMLEnc is 'Id' */
48 static const xmlChar*           xmlSecEncIds[] = { BAD_CAST "Id", NULL };
49 
50 
51 /**
52  * xmlSecEncCtxCreate:
53  * @keysMngr:           the pointer to keys manager.
54  *
55  * Creates <enc:EncryptedData/> element processing context.
56  * The caller is responsible for destroying returned object by calling
57  * #xmlSecEncCtxDestroy function.
58  *
59  * Returns: pointer to newly allocated context object or NULL if an error
60  * occurs.
61  */
62 xmlSecEncCtxPtr
xmlSecEncCtxCreate(xmlSecKeysMngrPtr keysMngr)63 xmlSecEncCtxCreate(xmlSecKeysMngrPtr keysMngr) {
64     xmlSecEncCtxPtr encCtx;
65     int ret;
66 
67     encCtx = (xmlSecEncCtxPtr) xmlMalloc(sizeof(xmlSecEncCtx));
68     if(encCtx == NULL) {
69         xmlSecMallocError(sizeof(xmlSecEncCtx), NULL);
70         return(NULL);
71     }
72 
73     ret = xmlSecEncCtxInitialize(encCtx, keysMngr);
74     if(ret < 0) {
75         xmlSecInternalError("xmlSecEncCtxInitialize", NULL);
76         xmlSecEncCtxDestroy(encCtx);
77         return(NULL);
78     }
79     return(encCtx);
80 }
81 
82 /**
83  * xmlSecEncCtxDestroy:
84  * @encCtx:             the pointer to <enc:EncryptedData/> processing context.
85  *
86  * Destroy context object created with #xmlSecEncCtxCreate function.
87  */
88 void
xmlSecEncCtxDestroy(xmlSecEncCtxPtr encCtx)89 xmlSecEncCtxDestroy(xmlSecEncCtxPtr encCtx) {
90     xmlSecAssert(encCtx != NULL);
91 
92     xmlSecEncCtxFinalize(encCtx);
93     xmlFree(encCtx);
94 }
95 
96 /**
97  * xmlSecEncCtxInitialize:
98  * @encCtx:             the pointer to <enc:EncryptedData/> processing context.
99  * @keysMngr:           the pointer to keys manager.
100  *
101  * Initializes <enc:EncryptedData/> element processing context.
102  * The caller is responsible for cleaning up returned object by calling
103  * #xmlSecEncCtxFinalize function.
104  *
105  * Returns: 0 on success or a negative value if an error occurs.
106  */
107 int
xmlSecEncCtxInitialize(xmlSecEncCtxPtr encCtx,xmlSecKeysMngrPtr keysMngr)108 xmlSecEncCtxInitialize(xmlSecEncCtxPtr encCtx, xmlSecKeysMngrPtr keysMngr) {
109     int ret;
110 
111     xmlSecAssert2(encCtx != NULL, -1);
112 
113     memset(encCtx, 0, sizeof(xmlSecEncCtx));
114 
115     /* initialize key info */
116     ret = xmlSecKeyInfoCtxInitialize(&(encCtx->keyInfoReadCtx), keysMngr);
117     if(ret < 0) {
118         xmlSecInternalError("xmlSecKeyInfoCtxInitialize", NULL);
119         return(-1);
120     }
121     encCtx->keyInfoReadCtx.mode = xmlSecKeyInfoModeRead;
122 
123     ret = xmlSecKeyInfoCtxInitialize(&(encCtx->keyInfoWriteCtx), keysMngr);
124     if(ret < 0) {
125         xmlSecInternalError("xmlSecKeyInfoCtxInitialize", NULL);
126         return(-1);
127     }
128     encCtx->keyInfoWriteCtx.mode = xmlSecKeyInfoModeWrite;
129     /* it's not wise to write private key :) */
130     encCtx->keyInfoWriteCtx.keyReq.keyType = xmlSecKeyDataTypePublic;
131 
132     /* initializes transforms encCtx */
133     ret = xmlSecTransformCtxInitialize(&(encCtx->transformCtx));
134     if(ret < 0) {
135         xmlSecInternalError("xmlSecTransformCtxInitialize", NULL);
136         return(-1);
137     }
138 
139     return(0);
140 }
141 
142 /**
143  * xmlSecEncCtxFinalize:
144  * @encCtx:             the pointer to <enc:EncryptedData/> processing context.
145  *
146  * Cleans up @encCtx object.
147  */
148 void
xmlSecEncCtxFinalize(xmlSecEncCtxPtr encCtx)149 xmlSecEncCtxFinalize(xmlSecEncCtxPtr encCtx) {
150     xmlSecAssert(encCtx != NULL);
151 
152     xmlSecEncCtxReset(encCtx);
153 
154     xmlSecTransformCtxFinalize(&(encCtx->transformCtx));
155     xmlSecKeyInfoCtxFinalize(&(encCtx->keyInfoReadCtx));
156     xmlSecKeyInfoCtxFinalize(&(encCtx->keyInfoWriteCtx));
157 
158     memset(encCtx, 0, sizeof(xmlSecEncCtx));
159 }
160 
161 /**
162  * xmlSecEncCtxReset:
163  * @encCtx:             the pointer to <enc:EncryptedData/> processing context.
164  *
165  * Resets @encCtx object, user settings are not touched.
166  */
167 void
xmlSecEncCtxReset(xmlSecEncCtxPtr encCtx)168 xmlSecEncCtxReset(xmlSecEncCtxPtr encCtx) {
169     xmlSecAssert(encCtx != NULL);
170 
171     xmlSecTransformCtxReset(&(encCtx->transformCtx));
172     xmlSecKeyInfoCtxReset(&(encCtx->keyInfoReadCtx));
173     xmlSecKeyInfoCtxReset(&(encCtx->keyInfoWriteCtx));
174 
175     encCtx->operation           = xmlSecTransformOperationNone;
176     encCtx->result              = NULL;
177     encCtx->resultBase64Encoded = 0;
178     encCtx->resultReplaced      = 0;
179     encCtx->encMethod           = NULL;
180 
181     if (encCtx->replacedNodeList != NULL) {
182                 xmlFreeNodeList(encCtx->replacedNodeList);
183         encCtx->replacedNodeList = NULL;
184     }
185 
186     if(encCtx->encKey != NULL) {
187             xmlSecKeyDestroy(encCtx->encKey);
188             encCtx->encKey = NULL;
189     }
190 
191     if(encCtx->id != NULL) {
192             xmlFree(encCtx->id);
193             encCtx->id = NULL;
194     }
195 
196     if(encCtx->type != NULL) {
197             xmlFree(encCtx->type);
198             encCtx->type = NULL;
199     }
200 
201     if(encCtx->mimeType != NULL) {
202             xmlFree(encCtx->mimeType);
203             encCtx->mimeType = NULL;
204     }
205 
206     if(encCtx->encoding != NULL) {
207             xmlFree(encCtx->encoding);
208             encCtx->encoding = NULL;
209     }
210 
211     if(encCtx->recipient != NULL) {
212             xmlFree(encCtx->recipient);
213             encCtx->recipient = NULL;
214     }
215 
216     if(encCtx->carriedKeyName != NULL) {
217             xmlFree(encCtx->carriedKeyName);
218             encCtx->carriedKeyName = NULL;
219     }
220 
221     encCtx->encDataNode = encCtx->encMethodNode =
222         encCtx->keyInfoNode = encCtx->cipherValueNode = NULL;
223 }
224 
225 /**
226  * xmlSecEncCtxCopyUserPref:
227  * @dst:                the pointer to destination context.
228  * @src:                the pointer to source context.
229  *
230  * Copies user preference from @src context to @dst.
231  *
232  * Returns: 0 on success or a negative value if an error occurs.
233  */
234 int
xmlSecEncCtxCopyUserPref(xmlSecEncCtxPtr dst,xmlSecEncCtxPtr src)235 xmlSecEncCtxCopyUserPref(xmlSecEncCtxPtr dst, xmlSecEncCtxPtr src) {
236     int ret;
237 
238     xmlSecAssert2(dst != NULL, -1);
239     xmlSecAssert2(src != NULL, -1);
240 
241     dst->userData       = src->userData;
242     dst->flags          = src->flags;
243     dst->flags2         = src->flags2;
244     dst->defEncMethodId = src->defEncMethodId;
245     dst->mode           = src->mode;
246 
247     ret = xmlSecTransformCtxCopyUserPref(&(dst->transformCtx), &(src->transformCtx));
248     if(ret < 0) {
249         xmlSecInternalError("xmlSecTransformCtxCopyUserPref", NULL);
250         return(-1);
251     }
252 
253     ret = xmlSecKeyInfoCtxCopyUserPref(&(dst->keyInfoReadCtx), &(src->keyInfoReadCtx));
254     if(ret < 0) {
255         xmlSecInternalError("xmlSecKeyInfoCtxCopyUserPref", NULL);
256         return(-1);
257     }
258 
259     ret = xmlSecKeyInfoCtxCopyUserPref(&(dst->keyInfoWriteCtx), &(src->keyInfoWriteCtx));
260     if(ret < 0) {
261         xmlSecInternalError("xmlSecKeyInfoCtxCopyUserPref", NULL);
262         return(-1);
263     }
264 
265     return(0);
266 }
267 
268 /**
269  * xmlSecEncCtxBinaryEncrypt:
270  * @encCtx:             the pointer to <enc:EncryptedData/> processing context.
271  * @tmpl:               the pointer to <enc:EncryptedData/> template node.
272  * @data:               the pointer for binary buffer.
273  * @dataSize:           the @data buffer size.
274  *
275  * Encrypts @data according to template @tmpl.
276  *
277  * Returns: 0 on success or a negative value if an error occurs.
278  */
279 int
xmlSecEncCtxBinaryEncrypt(xmlSecEncCtxPtr encCtx,xmlNodePtr tmpl,const xmlSecByte * data,xmlSecSize dataSize)280 xmlSecEncCtxBinaryEncrypt(xmlSecEncCtxPtr encCtx, xmlNodePtr tmpl,
281                           const xmlSecByte* data, xmlSecSize dataSize) {
282     int ret;
283 
284     xmlSecAssert2(encCtx != NULL, -1);
285     xmlSecAssert2(encCtx->result == NULL, -1);
286     xmlSecAssert2(tmpl != NULL, -1);
287     xmlSecAssert2(data != NULL, -1);
288 
289     /* initialize context and add ID atributes to the list of known ids */
290     encCtx->operation = xmlSecTransformOperationEncrypt;
291     xmlSecAddIDs(tmpl->doc, tmpl, xmlSecEncIds);
292 
293     /* read the template and set encryption method, key, etc. */
294     ret = xmlSecEncCtxEncDataNodeRead(encCtx, tmpl);
295     if(ret < 0) {
296         xmlSecInternalError("xmlSecEncCtxEncDataNodeRead", NULL);
297         return(-1);
298     }
299 
300     ret = xmlSecTransformCtxBinaryExecute(&(encCtx->transformCtx), data, dataSize);
301     if(ret < 0) {
302         xmlSecInternalError2("xmlSecTransformCtxBinaryExecute", NULL,
303                              "dataSize=%d", dataSize);
304         return(-1);
305     }
306 
307     encCtx->result = encCtx->transformCtx.result;
308     xmlSecAssert2(encCtx->result != NULL, -1);
309 
310     ret = xmlSecEncCtxEncDataNodeWrite(encCtx);
311     if(ret < 0) {
312         xmlSecInternalError("xmlSecEncCtxEncDataNodeWrite", NULL);
313         return(-1);
314     }
315     return(0);
316 }
317 
318 /**
319  * xmlSecEncCtxXmlEncrypt:
320  * @encCtx:             the pointer to <enc:EncryptedData/> processing context.
321  * @tmpl:               the pointer to <enc:EncryptedData/> template node.
322  * @node:               the pointer to node for encryption.
323  *
324  * Encrypts @node according to template @tmpl. If requested, @node is replaced
325  * with result <enc:EncryptedData/> node.
326  *
327  * Returns: 0 on success or a negative value if an error occurs.
328  */
329 int
xmlSecEncCtxXmlEncrypt(xmlSecEncCtxPtr encCtx,xmlNodePtr tmpl,xmlNodePtr node)330 xmlSecEncCtxXmlEncrypt(xmlSecEncCtxPtr encCtx, xmlNodePtr tmpl, xmlNodePtr node) {
331     xmlOutputBufferPtr output;
332     int ret;
333 
334     xmlSecAssert2(encCtx != NULL, -1);
335     xmlSecAssert2(encCtx->result == NULL, -1);
336     xmlSecAssert2(tmpl != NULL, -1);
337     xmlSecAssert2(node != NULL, -1);
338     xmlSecAssert2(node->doc != NULL, -1);
339 
340     /* initialize context and add ID atributes to the list of known ids */
341     encCtx->operation = xmlSecTransformOperationEncrypt;
342     xmlSecAddIDs(tmpl->doc, tmpl, xmlSecEncIds);
343 
344     /* read the template and set encryption method, key, etc. */
345     ret = xmlSecEncCtxEncDataNodeRead(encCtx, tmpl);
346     if(ret < 0) {
347         xmlSecInternalError("xmlSecEncCtxEncDataNodeRead", NULL);
348         return(-1);
349     }
350 
351     ret = xmlSecTransformCtxPrepare(&(encCtx->transformCtx), xmlSecTransformDataTypeBin);
352     if(ret < 0) {
353         xmlSecInternalError("xmlSecTransformCtxPrepare(TypeBin)", NULL);
354         return(-1);
355     }
356 
357     xmlSecAssert2(encCtx->transformCtx.first != NULL, -1);
358     output = xmlSecTransformCreateOutputBuffer(encCtx->transformCtx.first,
359                                                 &(encCtx->transformCtx));
360     if(output == NULL) {
361         xmlSecInternalError("xmlSecTransformCreateOutputBuffer",
362                             xmlSecTransformGetName(encCtx->transformCtx.first));
363         return(-1);
364     }
365 
366     /* push data thru */
367     if((encCtx->type != NULL) && xmlStrEqual(encCtx->type, xmlSecTypeEncElement)) {
368         /* get the content of the node */
369         xmlNodeDumpOutput(output, node->doc, node, 0, 0, NULL);
370     } else if((encCtx->type != NULL) && xmlStrEqual(encCtx->type, xmlSecTypeEncContent)) {
371         xmlNodePtr cur;
372 
373         /* get the content of the nodes childs */
374         for(cur = node->children; cur != NULL; cur = cur->next) {
375             xmlNodeDumpOutput(output, node->doc, cur, 0, 0, NULL);
376         }
377     } else {
378         xmlSecInvalidStringTypeError("encryption type", encCtx->type,
379                 "supported encryption type", NULL);
380         xmlOutputBufferClose(output);
381         return(-1);
382     }
383 
384     /* close the buffer and flush everything */
385     ret = xmlOutputBufferClose(output);
386     if(ret < 0) {
387         xmlSecXmlError("xmlOutputBufferClose", NULL);
388         return(-1);
389     }
390 
391     encCtx->result = encCtx->transformCtx.result;
392     xmlSecAssert2(encCtx->result != NULL, -1);
393 
394     ret = xmlSecEncCtxEncDataNodeWrite(encCtx);
395     if(ret < 0) {
396         xmlSecInternalError("xmlSecEncCtxEncDataNodeWrite", NULL);
397         return(-1);
398     }
399 
400     /* now we need to update our original document */
401     if((encCtx->type != NULL) && xmlStrEqual(encCtx->type, xmlSecTypeEncElement)) {
402         /* check if we need to return the replaced node */
403         if((encCtx->flags & XMLSEC_ENC_RETURN_REPLACED_NODE) != 0) {
404             ret = xmlSecReplaceNodeAndReturn(node, tmpl, &(encCtx->replacedNodeList));
405             if(ret < 0) {
406                 xmlSecInternalError("xmlSecReplaceNodeAndReturn",
407                                     xmlSecNodeGetName(node));
408                 return(-1);
409             }
410         } else {
411             ret = xmlSecReplaceNode(node, tmpl);
412             if(ret < 0) {
413                 xmlSecInternalError("xmlSecReplaceNode",
414                                     xmlSecNodeGetName(node));
415                 return(-1);
416             }
417         }
418 
419             encCtx->resultReplaced = 1;
420     } else if((encCtx->type != NULL) && xmlStrEqual(encCtx->type, xmlSecTypeEncContent)) {
421         /* check if we need to return the replaced node */
422         if((encCtx->flags & XMLSEC_ENC_RETURN_REPLACED_NODE) != 0) {
423             ret = xmlSecReplaceContentAndReturn(node, tmpl, &(encCtx->replacedNodeList));
424             if(ret < 0) {
425                 xmlSecInternalError("xmlSecReplaceContentAndReturn",
426                                     xmlSecNodeGetName(node));
427                 return(-1);
428             }
429         } else {
430             ret = xmlSecReplaceContent(node, tmpl);
431             if(ret < 0) {
432                 xmlSecInternalError("xmlSecReplaceContent",
433                                     xmlSecNodeGetName(node));
434                 return(-1);
435             }
436         }
437 
438         encCtx->resultReplaced = 1;
439     } else {
440         /* we should've caught this error before */
441         xmlSecInvalidStringTypeError("encryption type", encCtx->type,
442                 "supported encryption type", NULL);
443         return(-1);
444     }
445     /* done */
446     return(0);
447 }
448 
449 /**
450  * xmlSecEncCtxUriEncrypt:
451  * @encCtx:             the pointer to <enc:EncryptedData/> processing context.
452  * @tmpl:               the pointer to <enc:EncryptedData/> template node.
453  * @uri:                the URI.
454  *
455  * Encrypts data from @uri according to template @tmpl.
456  *
457  * Returns: 0 on success or a negative value if an error occurs.
458  */
459 int
xmlSecEncCtxUriEncrypt(xmlSecEncCtxPtr encCtx,xmlNodePtr tmpl,const xmlChar * uri)460 xmlSecEncCtxUriEncrypt(xmlSecEncCtxPtr encCtx, xmlNodePtr tmpl, const xmlChar *uri) {
461     int ret;
462 
463     xmlSecAssert2(encCtx != NULL, -1);
464     xmlSecAssert2(encCtx->result == NULL, -1);
465     xmlSecAssert2(tmpl != NULL, -1);
466     xmlSecAssert2(uri != NULL, -1);
467 
468     /* initialize context and add ID atributes to the list of known ids */
469     encCtx->operation = xmlSecTransformOperationEncrypt;
470     xmlSecAddIDs(tmpl->doc, tmpl, xmlSecEncIds);
471 
472     /* we need to add input uri transform first */
473     ret = xmlSecTransformCtxSetUri(&(encCtx->transformCtx), uri, tmpl);
474     if(ret < 0) {
475         xmlSecInternalError2("xmlSecTransformCtxSetUri", NULL,
476                              "uri=%s", xmlSecErrorsSafeString(uri));
477         return(-1);
478     }
479 
480     /* read the template and set encryption method, key, etc. */
481     ret = xmlSecEncCtxEncDataNodeRead(encCtx, tmpl);
482     if(ret < 0) {
483         xmlSecInternalError("xmlSecEncCtxEncDataNodeRead", NULL);
484         return(-1);
485     }
486 
487     /* encrypt the data */
488     ret = xmlSecTransformCtxExecute(&(encCtx->transformCtx), tmpl->doc);
489     if(ret < 0) {
490         xmlSecInternalError("xmlSecTransformCtxExecute", NULL);
491         return(-1);
492     }
493 
494     encCtx->result = encCtx->transformCtx.result;
495     xmlSecAssert2(encCtx->result != NULL, -1);
496 
497     ret = xmlSecEncCtxEncDataNodeWrite(encCtx);
498     if(ret < 0) {
499         xmlSecInternalError("xmlSecEncCtxEncDataNodeWrite", NULL);
500         return(-1);
501     }
502 
503     return(0);
504 }
505 
506 /**
507  * xmlSecEncCtxDecrypt:
508  * @encCtx:             the pointer to <enc:EncryptedData/> processing context.
509  * @node:               the pointer to <enc:EncryptedData/> node.
510  *
511  * Decrypts @node and if necessary replaces @node with decrypted data.
512  *
513  * Returns: 0 on success or a negative value if an error occurs.
514  */
515 int
xmlSecEncCtxDecrypt(xmlSecEncCtxPtr encCtx,xmlNodePtr node)516 xmlSecEncCtxDecrypt(xmlSecEncCtxPtr encCtx, xmlNodePtr node) {
517     xmlSecBufferPtr buffer;
518     int ret;
519 
520     xmlSecAssert2(encCtx != NULL, -1);
521     xmlSecAssert2(node != NULL, -1);
522 
523     /* decrypt */
524     buffer = xmlSecEncCtxDecryptToBuffer(encCtx, node);
525     if(buffer == NULL) {
526         xmlSecInternalError("xmlSecEncCtxDecryptToBuffer", NULL);
527         return(-1);
528     }
529 
530     /* replace original node if requested */
531     if((encCtx->type != NULL) && xmlStrEqual(encCtx->type, xmlSecTypeEncElement)) {
532         /* check if we need to return the replaced node */
533         if((encCtx->flags & XMLSEC_ENC_RETURN_REPLACED_NODE) != 0) {
534                 ret = xmlSecReplaceNodeBufferAndReturn(node, xmlSecBufferGetData(buffer),  xmlSecBufferGetSize(buffer), &(encCtx->replacedNodeList));
535                 if(ret < 0) {
536                     xmlSecInternalError("xmlSecReplaceNodeBufferAndReturn",
537                                         xmlSecNodeGetName(node));
538                     return(-1);
539                 }
540         } else {
541                 ret = xmlSecReplaceNodeBuffer(node, xmlSecBufferGetData(buffer),  xmlSecBufferGetSize(buffer));
542                 if(ret < 0) {
543                     xmlSecInternalError("xmlSecReplaceNodeBuffer",
544                                         xmlSecNodeGetName(node));
545                     return(-1);
546                 }
547         }
548 
549         encCtx->resultReplaced = 1;
550     } else if((encCtx->type != NULL) && xmlStrEqual(encCtx->type, xmlSecTypeEncContent)) {
551         /* replace the node with the buffer */
552 
553         /* check if we need to return the replaced node */
554         if((encCtx->flags & XMLSEC_ENC_RETURN_REPLACED_NODE) != 0) {
555                 ret = xmlSecReplaceNodeBufferAndReturn(node, xmlSecBufferGetData(buffer), xmlSecBufferGetSize(buffer), &(encCtx->replacedNodeList));
556                 if(ret < 0) {
557                     xmlSecInternalError("xmlSecReplaceNodeBufferAndReturn",
558                                         xmlSecNodeGetName(node));
559                     return(-1);
560                 }
561         } else {
562             ret = xmlSecReplaceNodeBuffer(node, xmlSecBufferGetData(buffer), xmlSecBufferGetSize(buffer));
563                 if(ret < 0) {
564                     xmlSecInternalError("xmlSecReplaceNodeBuffer",
565                                         xmlSecNodeGetName(node));
566                     return(-1);
567                 }
568         }
569         encCtx->resultReplaced = 1;
570     }
571 
572     return(0);
573 }
574 
575 /**
576  * xmlSecEncCtxDecryptToBuffer:
577  * @encCtx:             the pointer to <enc:EncryptedData/> processing context.
578  * @node:               the pointer to <enc:EncryptedData/> node.
579  *
580  * Decrypts @node data to the @encCtx buffer.
581  *
582  * Returns: 0 on success or a negative value if an error occurs.
583  */
584 xmlSecBufferPtr
xmlSecEncCtxDecryptToBuffer(xmlSecEncCtxPtr encCtx,xmlNodePtr node)585 xmlSecEncCtxDecryptToBuffer(xmlSecEncCtxPtr encCtx, xmlNodePtr node) {
586     int ret;
587 
588     xmlSecAssert2(encCtx != NULL, NULL);
589     xmlSecAssert2(encCtx->result == NULL, NULL);
590     xmlSecAssert2(node != NULL, NULL);
591 
592     /* initialize context and add ID atributes to the list of known ids */
593     encCtx->operation = xmlSecTransformOperationDecrypt;
594     xmlSecAddIDs(node->doc, node, xmlSecEncIds);
595 
596     ret = xmlSecEncCtxEncDataNodeRead(encCtx, node);
597     if(ret < 0) {
598         xmlSecInternalError("xmlSecEncCtxEncDataNodeRead", NULL);
599         return(NULL);
600     }
601 
602     /* decrypt the data */
603     if(encCtx->cipherValueNode != NULL) {
604         xmlChar* data = NULL;
605         xmlSecSize dataSize = 0;
606 
607         data = xmlNodeGetContent(encCtx->cipherValueNode);
608         if(data == NULL) {
609             xmlSecInvalidNodeContentError(encCtx->cipherValueNode, NULL, "empty");
610             return(NULL);
611         }
612         dataSize = xmlStrlen(data);
613 
614         ret = xmlSecTransformCtxBinaryExecute(&(encCtx->transformCtx), data, dataSize);
615         if(ret < 0) {
616             xmlSecInternalError("xmlSecTransformCtxBinaryExecute", NULL);
617             if(data != NULL) {
618                 xmlFree(data);
619             }
620             return(NULL);
621         }
622         if(data != NULL) {
623             xmlFree(data);
624         }
625     } else {
626         ret = xmlSecTransformCtxExecute(&(encCtx->transformCtx), node->doc);
627         if(ret < 0) {
628             xmlSecInternalError("xmlSecTransformCtxExecute", NULL);
629             return(NULL);
630         }
631     }
632 
633     encCtx->result = encCtx->transformCtx.result;
634     xmlSecAssert2(encCtx->result != NULL, NULL);
635 
636     return(encCtx->result);
637 }
638 
639 static int
xmlSecEncCtxEncDataNodeRead(xmlSecEncCtxPtr encCtx,xmlNodePtr node)640 xmlSecEncCtxEncDataNodeRead(xmlSecEncCtxPtr encCtx, xmlNodePtr node) {
641     xmlNodePtr cur;
642     int ret;
643 
644     xmlSecAssert2(encCtx != NULL, -1);
645     xmlSecAssert2((encCtx->operation == xmlSecTransformOperationEncrypt) || (encCtx->operation == xmlSecTransformOperationDecrypt), -1);
646     xmlSecAssert2(node != NULL, -1);
647 
648     switch(encCtx->mode) {
649         case xmlEncCtxModeEncryptedData:
650             if(!xmlSecCheckNodeName(node, xmlSecNodeEncryptedData, xmlSecEncNs)) {
651                 xmlSecInvalidNodeError(node, xmlSecNodeEncryptedData, NULL);
652                 return(-1);
653             }
654             break;
655         case xmlEncCtxModeEncryptedKey:
656             if(!xmlSecCheckNodeName(node, xmlSecNodeEncryptedKey, xmlSecEncNs)) {
657                 xmlSecInvalidNodeError(node, xmlSecNodeEncryptedKey, NULL);
658                 return(-1);
659             }
660             break;
661     }
662 
663     /* first read node data */
664     xmlSecAssert2(encCtx->id == NULL, -1);
665     xmlSecAssert2(encCtx->type == NULL, -1);
666     xmlSecAssert2(encCtx->mimeType == NULL, -1);
667     xmlSecAssert2(encCtx->encoding == NULL, -1);
668     xmlSecAssert2(encCtx->recipient == NULL, -1);
669     xmlSecAssert2(encCtx->carriedKeyName == NULL, -1);
670 
671     encCtx->id = xmlGetProp(node, xmlSecAttrId);
672     encCtx->type = xmlGetProp(node, xmlSecAttrType);
673     encCtx->mimeType = xmlGetProp(node, xmlSecAttrMimeType);
674     encCtx->encoding = xmlGetProp(node, xmlSecAttrEncoding);
675     if(encCtx->mode == xmlEncCtxModeEncryptedKey) {
676         encCtx->recipient = xmlGetProp(node, xmlSecAttrRecipient);
677         /* todo: check recipient? */
678     }
679     cur = xmlSecGetNextElementNode(node->children);
680 
681     /* first node is optional EncryptionMethod, we'll read it later */
682     xmlSecAssert2(encCtx->encMethodNode == NULL, -1);
683     if((cur != NULL) && (xmlSecCheckNodeName(cur, xmlSecNodeEncryptionMethod, xmlSecEncNs))) {
684         encCtx->encMethodNode = cur;
685         cur = xmlSecGetNextElementNode(cur->next);
686     }
687 
688     /* next node is optional KeyInfo, we'll process it later */
689     xmlSecAssert2(encCtx->keyInfoNode == NULL, -1);
690     if((cur != NULL) && (xmlSecCheckNodeName(cur, xmlSecNodeKeyInfo, xmlSecDSigNs))) {
691         encCtx->keyInfoNode = cur;
692         cur = xmlSecGetNextElementNode(cur->next);
693     }
694 
695     /* next is required CipherData node */
696     if((cur == NULL) || (!xmlSecCheckNodeName(cur, xmlSecNodeCipherData, xmlSecEncNs))) {
697         xmlSecInvalidNodeError(cur, xmlSecNodeCipherData, NULL);
698         return(-1);
699     }
700 
701     ret = xmlSecEncCtxCipherDataNodeRead(encCtx, cur);
702     if(ret < 0) {
703         xmlSecInternalError("xmlSecEncCtxCipherDataNodeRead", NULL);
704         return(-1);
705     }
706     cur = xmlSecGetNextElementNode(cur->next);
707 
708     /* next is optional EncryptionProperties node (we simply ignore it) */
709     if((cur != NULL) && (xmlSecCheckNodeName(cur, xmlSecNodeEncryptionProperties, xmlSecEncNs))) {
710         cur = xmlSecGetNextElementNode(cur->next);
711     }
712 
713     /* there are more possible nodes for the <EncryptedKey> node */
714     if(encCtx->mode == xmlEncCtxModeEncryptedKey) {
715         /* next is optional ReferenceList node (we simply ignore it) */
716         if((cur != NULL) && (xmlSecCheckNodeName(cur, xmlSecNodeReferenceList, xmlSecEncNs))) {
717             cur = xmlSecGetNextElementNode(cur->next);
718         }
719 
720         /* next is optional CarriedKeyName node (we simply ignore it) */
721         if((cur != NULL) && (xmlSecCheckNodeName(cur, xmlSecNodeCarriedKeyName, xmlSecEncNs))) {
722             encCtx->carriedKeyName = xmlNodeGetContent(cur);
723             if(encCtx->carriedKeyName == NULL) {
724                 xmlSecInvalidNodeContentError(cur, NULL, "empty");
725                 return(-1);
726             }
727             /* TODO: decode the name? */
728             cur = xmlSecGetNextElementNode(cur->next);
729         }
730     }
731 
732     /* if there is something left than it's an error */
733     if(cur != NULL) {
734         xmlSecUnexpectedNodeError(cur,  NULL);
735         return(-1);
736     }
737 
738     /* now read the encryption method node */
739     xmlSecAssert2(encCtx->encMethod == NULL, -1);
740     if(encCtx->encMethodNode != NULL) {
741         encCtx->encMethod = xmlSecTransformCtxNodeRead(&(encCtx->transformCtx), encCtx->encMethodNode,
742                                                 xmlSecTransformUsageEncryptionMethod);
743         if(encCtx->encMethod == NULL) {
744             xmlSecInternalError("xmlSecTransformCtxNodeRead",
745                                 xmlSecNodeGetName(encCtx->encMethodNode));
746             return(-1);
747         }
748     } else if(encCtx->defEncMethodId != xmlSecTransformIdUnknown) {
749         encCtx->encMethod = xmlSecTransformCtxCreateAndAppend(&(encCtx->transformCtx),
750                                                               encCtx->defEncMethodId);
751         if(encCtx->encMethod == NULL) {
752             xmlSecInternalError("xmlSecTransformCtxCreateAndAppend",
753                     xmlSecTransformKlassGetName(encCtx->defEncMethodId));
754             return(-1);
755         }
756     } else {
757         xmlSecInvalidDataError("encryption method not specified", NULL);
758         return(-1);
759     }
760     encCtx->encMethod->operation = encCtx->operation;
761 
762     /* we have encryption method, find key */
763     ret = xmlSecTransformSetKeyReq(encCtx->encMethod, &(encCtx->keyInfoReadCtx.keyReq));
764     if(ret < 0) {
765         xmlSecInternalError("xmlSecTransformSetKeyReq",
766                 xmlSecTransformGetName(encCtx->encMethod));
767         return(-1);
768     }
769 
770     /* TODO: KeyInfo node != NULL and encKey != NULL */
771     if((encCtx->encKey == NULL) && (encCtx->keyInfoReadCtx.keysMngr != NULL)
772                         && (encCtx->keyInfoReadCtx.keysMngr->getKey != NULL)) {
773         encCtx->encKey = (encCtx->keyInfoReadCtx.keysMngr->getKey)(encCtx->keyInfoNode,
774                                                              &(encCtx->keyInfoReadCtx));
775     }
776 
777     /* check that we have exactly what we want */
778     if((encCtx->encKey == NULL) ||
779        (!xmlSecKeyMatch(encCtx->encKey, NULL, &(encCtx->keyInfoReadCtx.keyReq)))) {
780 
781         xmlSecOtherError2(XMLSEC_ERRORS_R_KEY_NOT_FOUND, NULL,
782                           "encMethod=%s",
783                           xmlSecErrorsSafeString(xmlSecTransformGetName(encCtx->encMethod)));
784         return(-1);
785     }
786 
787     /* set the key to the transform */
788     ret = xmlSecTransformSetKey(encCtx->encMethod, encCtx->encKey);
789     if(ret < 0) {
790         xmlSecInternalError("xmlSecTransformSetKey",
791                             xmlSecTransformGetName(encCtx->encMethod));
792         return(-1);
793     }
794 
795     /* if we need to write result to xml node then we need base64 encode it */
796     if((encCtx->operation == xmlSecTransformOperationEncrypt) && (encCtx->cipherValueNode != NULL)) {
797         xmlSecTransformPtr base64Encode;
798 
799         /* we need to add base64 encode transform */
800         base64Encode = xmlSecTransformCtxCreateAndAppend(&(encCtx->transformCtx), xmlSecTransformBase64Id);
801         if(base64Encode == NULL) {
802             xmlSecInternalError("xmlSecTransformCtxCreateAndAppend", NULL);
803             return(-1);
804         }
805         base64Encode->operation         = xmlSecTransformOperationEncode;
806         encCtx->resultBase64Encoded     = 1;
807     }
808 
809     return(0);
810 }
811 
812 static int
xmlSecEncCtxEncDataNodeWrite(xmlSecEncCtxPtr encCtx)813 xmlSecEncCtxEncDataNodeWrite(xmlSecEncCtxPtr encCtx) {
814     int ret;
815 
816     xmlSecAssert2(encCtx != NULL, -1);
817     xmlSecAssert2(encCtx->result != NULL, -1);
818     xmlSecAssert2(encCtx->encKey != NULL, -1);
819 
820     /* write encrypted data to xml (if requested) */
821     if(encCtx->cipherValueNode != NULL) {
822         xmlSecAssert2(xmlSecBufferGetData(encCtx->result) != NULL, -1);
823 
824         xmlNodeSetContentLen(encCtx->cipherValueNode,
825                             xmlSecBufferGetData(encCtx->result),
826                             xmlSecBufferGetSize(encCtx->result));
827         encCtx->resultReplaced = 1;
828     }
829 
830     /* update <enc:KeyInfo/> node */
831     if(encCtx->keyInfoNode != NULL) {
832         ret = xmlSecKeyInfoNodeWrite(encCtx->keyInfoNode, encCtx->encKey, &(encCtx->keyInfoWriteCtx));
833         if(ret < 0) {
834             xmlSecInternalError("xmlSecKeyInfoNodeWrite", NULL);
835             return(-1);
836         }
837     }
838 
839     return(0);
840 }
841 
842 static int
xmlSecEncCtxCipherDataNodeRead(xmlSecEncCtxPtr encCtx,xmlNodePtr node)843 xmlSecEncCtxCipherDataNodeRead(xmlSecEncCtxPtr encCtx, xmlNodePtr node) {
844     xmlNodePtr cur;
845     int ret;
846 
847     xmlSecAssert2(encCtx != NULL, -1);
848     xmlSecAssert2(node != NULL, -1);
849 
850     cur = xmlSecGetNextElementNode(node->children);
851 
852     /* we either have CipherValue or CipherReference node  */
853     xmlSecAssert2(encCtx->cipherValueNode == NULL, -1);
854     if((cur != NULL) && (xmlSecCheckNodeName(cur, xmlSecNodeCipherValue, xmlSecEncNs))) {
855         /* don't need data from CipherData node when we are encrypting */
856         if(encCtx->operation == xmlSecTransformOperationDecrypt) {
857             xmlSecTransformPtr base64Decode;
858 
859             /* we need to add base64 decode transform */
860             base64Decode = xmlSecTransformCtxCreateAndPrepend(&(encCtx->transformCtx), xmlSecTransformBase64Id);
861             if(base64Decode == NULL) {
862                 xmlSecInternalError("xmlSecTransformCtxCreateAndPrepend", NULL);
863                 return(-1);
864             }
865         }
866         encCtx->cipherValueNode = cur;
867         cur = xmlSecGetNextElementNode(cur->next);
868     } else if((cur != NULL) && (xmlSecCheckNodeName(cur, xmlSecNodeCipherReference, xmlSecEncNs))) {
869         /* don't need data from CipherReference node when we are encrypting */
870         if(encCtx->operation == xmlSecTransformOperationDecrypt) {
871             ret = xmlSecEncCtxCipherReferenceNodeRead(encCtx, cur);
872             if(ret < 0) {
873                 xmlSecInternalError("xmlSecEncCtxCipherReferenceNodeRead",
874                                     xmlSecNodeGetName(cur));
875                 return(-1);
876             }
877         }
878         cur = xmlSecGetNextElementNode(cur->next);
879     }
880 
881     if(cur != NULL) {
882         xmlSecUnexpectedNodeError(cur,  NULL);
883         return(-1);
884     }
885     return(0);
886 }
887 
888 static int
xmlSecEncCtxCipherReferenceNodeRead(xmlSecEncCtxPtr encCtx,xmlNodePtr node)889 xmlSecEncCtxCipherReferenceNodeRead(xmlSecEncCtxPtr encCtx, xmlNodePtr node) {
890     xmlNodePtr cur;
891     xmlChar* uri;
892     int ret;
893 
894     xmlSecAssert2(encCtx != NULL, -1);
895     xmlSecAssert2(node != NULL, -1);
896 
897     /* first read the optional uri attr and check that we can process it */
898     uri = xmlGetProp(node, xmlSecAttrURI);
899     ret = xmlSecTransformCtxSetUri(&(encCtx->transformCtx), uri, node);
900     if(ret < 0) {
901         xmlSecInternalError2("xmlSecTransformCtxSetUri", NULL,
902                              "uri=%s", xmlSecErrorsSafeString(uri));
903         xmlFree(uri);
904         return(-1);
905     }
906     xmlFree(uri);
907 
908     cur = xmlSecGetNextElementNode(node->children);
909 
910     /* the only one node is optional Transforms node */
911     if((cur != NULL) && (xmlSecCheckNodeName(cur, xmlSecNodeTransforms, xmlSecEncNs))) {
912         ret = xmlSecTransformCtxNodesListRead(&(encCtx->transformCtx), cur,
913                                     xmlSecTransformUsageDSigTransform);
914         if(ret < 0) {
915             xmlSecInternalError("xmlSecTransformCtxNodesListRead",
916                                 xmlSecNodeGetName(encCtx->encMethodNode));
917             return(-1);
918         }
919         cur = xmlSecGetNextElementNode(cur->next);
920     }
921 
922     /* if there is something left than it's an error */
923     if(cur != NULL) {
924         xmlSecUnexpectedNodeError(cur,  NULL);
925         return(-1);
926     }
927     return(0);
928 }
929 
930 /**
931  * xmlSecEncCtxDebugDump:
932  * @encCtx:             the pointer to <enc:EncryptedData/> processing context.
933  * @output:             the pointer to output FILE.
934  *
935  * Prints the debug information about @encCtx to @output.
936  */
937 void
xmlSecEncCtxDebugDump(xmlSecEncCtxPtr encCtx,FILE * output)938 xmlSecEncCtxDebugDump(xmlSecEncCtxPtr encCtx, FILE* output) {
939     xmlSecAssert(encCtx != NULL);
940     xmlSecAssert(output != NULL);
941 
942     switch(encCtx->mode) {
943         case xmlEncCtxModeEncryptedData:
944             if(encCtx->operation == xmlSecTransformOperationEncrypt) {
945                 fprintf(output, "= DATA ENCRYPTION CONTEXT\n");
946             } else {
947                 fprintf(output, "= DATA DECRYPTION CONTEXT\n");
948             }
949             break;
950         case xmlEncCtxModeEncryptedKey:
951             if(encCtx->operation == xmlSecTransformOperationEncrypt) {
952                 fprintf(output, "= KEY ENCRYPTION CONTEXT\n");
953             } else {
954                 fprintf(output, "= KEY DECRYPTION CONTEXT\n");
955             }
956             break;
957     }
958     fprintf(output, "== Status: %s\n",
959             (encCtx->resultReplaced) ? "replaced" : "not-replaced" );
960 
961     fprintf(output, "== flags: 0x%08x\n", encCtx->flags);
962     fprintf(output, "== flags2: 0x%08x\n", encCtx->flags2);
963 
964     if(encCtx->id != NULL) {
965         fprintf(output, "== Id: \"%s\"\n", encCtx->id);
966     }
967     if(encCtx->type != NULL) {
968         fprintf(output, "== Type: \"%s\"\n", encCtx->type);
969     }
970     if(encCtx->mimeType != NULL) {
971         fprintf(output, "== MimeType: \"%s\"\n", encCtx->mimeType);
972     }
973     if(encCtx->encoding != NULL) {
974         fprintf(output, "== Encoding: \"%s\"\n", encCtx->encoding);
975     }
976     if(encCtx->recipient != NULL) {
977         fprintf(output, "== Recipient: \"%s\"\n", encCtx->recipient);
978     }
979     if(encCtx->carriedKeyName != NULL) {
980         fprintf(output, "== CarriedKeyName: \"%s\"\n", encCtx->carriedKeyName);
981     }
982 
983     fprintf(output, "== Key Info Read Ctx:\n");
984     xmlSecKeyInfoCtxDebugDump(&(encCtx->keyInfoReadCtx), output);
985 
986     fprintf(output, "== Key Info Write Ctx:\n");
987     xmlSecKeyInfoCtxDebugDump(&(encCtx->keyInfoWriteCtx), output);
988 
989     fprintf(output, "== Encryption Transform Ctx:\n");
990     xmlSecTransformCtxDebugDump(&(encCtx->transformCtx), output);
991 
992     if(encCtx->encMethod != NULL) {
993         fprintf(output, "== Encryption Method:\n");
994         xmlSecTransformDebugDump(encCtx->encMethod, output);
995     }
996 
997     if(encCtx->encKey != NULL) {
998         fprintf(output, "== Encryption Key:\n");
999         xmlSecKeyDebugDump(encCtx->encKey, output);
1000     }
1001 
1002     if((encCtx->result != NULL) &&
1003        (xmlSecBufferGetData(encCtx->result) != NULL) &&
1004        (encCtx->resultBase64Encoded != 0)) {
1005 
1006         fprintf(output, "== Result - start buffer:\n");
1007         (void)fwrite(xmlSecBufferGetData(encCtx->result),
1008                      xmlSecBufferGetSize(encCtx->result), 1,
1009                      output);
1010         fprintf(output, "\n== Result - end buffer\n");
1011     }
1012 }
1013 
1014 /**
1015  * xmlSecEncCtxDebugXmlDump:
1016  * @encCtx:             the pointer to <enc:EncryptedData/> processing context.
1017  * @output:             the pointer to output FILE.
1018  *
1019  * Prints the debug information about @encCtx to @output in XML format.
1020  */
1021 void
xmlSecEncCtxDebugXmlDump(xmlSecEncCtxPtr encCtx,FILE * output)1022 xmlSecEncCtxDebugXmlDump(xmlSecEncCtxPtr encCtx, FILE* output) {
1023     xmlSecAssert(encCtx != NULL);
1024     xmlSecAssert(output != NULL);
1025 
1026     switch(encCtx->mode) {
1027         case xmlEncCtxModeEncryptedData:
1028             if(encCtx->operation == xmlSecTransformOperationEncrypt) {
1029                 fprintf(output, "<DataEncryptionContext ");
1030             } else {
1031                 fprintf(output, "<DataDecryptionContext ");
1032             }
1033             break;
1034         case xmlEncCtxModeEncryptedKey:
1035             if(encCtx->operation == xmlSecTransformOperationEncrypt) {
1036                 fprintf(output, "<KeyEncryptionContext ");
1037             } else {
1038                 fprintf(output, "<KeyDecryptionContext ");
1039             }
1040             break;
1041     }
1042     fprintf(output, "status=\"%s\" >\n", (encCtx->resultReplaced) ? "replaced" : "not-replaced" );
1043 
1044     fprintf(output, "<Flags>%08x</Flags>\n", encCtx->flags);
1045     fprintf(output, "<Flags2>%08x</Flags2>\n", encCtx->flags2);
1046 
1047     fprintf(output, "<Id>");
1048     xmlSecPrintXmlString(output, encCtx->id);
1049     fprintf(output, "</Id>");
1050 
1051     fprintf(output, "<Type>");
1052     xmlSecPrintXmlString(output, encCtx->type);
1053     fprintf(output, "</Type>");
1054 
1055     fprintf(output, "<MimeType>");
1056     xmlSecPrintXmlString(output, encCtx->mimeType);
1057     fprintf(output, "</MimeType>");
1058 
1059     fprintf(output, "<Encoding>");
1060     xmlSecPrintXmlString(output, encCtx->encoding);
1061     fprintf(output, "</Encoding>");
1062 
1063     fprintf(output, "<Recipient>");
1064     xmlSecPrintXmlString(output, encCtx->recipient);
1065     fprintf(output, "</Recipient>");
1066 
1067     fprintf(output, "<CarriedKeyName>");
1068     xmlSecPrintXmlString(output, encCtx->carriedKeyName);
1069     fprintf(output, "</CarriedKeyName>");
1070 
1071     fprintf(output, "<KeyInfoReadCtx>\n");
1072     xmlSecKeyInfoCtxDebugXmlDump(&(encCtx->keyInfoReadCtx), output);
1073     fprintf(output, "</KeyInfoReadCtx>\n");
1074 
1075     fprintf(output, "<KeyInfoWriteCtx>\n");
1076     xmlSecKeyInfoCtxDebugXmlDump(&(encCtx->keyInfoWriteCtx), output);
1077     fprintf(output, "</KeyInfoWriteCtx>\n");
1078 
1079     fprintf(output, "<EncryptionTransformCtx>\n");
1080     xmlSecTransformCtxDebugXmlDump(&(encCtx->transformCtx), output);
1081     fprintf(output, "</EncryptionTransformCtx>\n");
1082 
1083     if(encCtx->encMethod != NULL) {
1084         fprintf(output, "<EncryptionMethod>\n");
1085         xmlSecTransformDebugXmlDump(encCtx->encMethod, output);
1086         fprintf(output, "</EncryptionMethod>\n");
1087     }
1088 
1089     if(encCtx->encKey != NULL) {
1090         fprintf(output, "<EncryptionKey>\n");
1091         xmlSecKeyDebugXmlDump(encCtx->encKey, output);
1092         fprintf(output, "</EncryptionKey>\n");
1093     }
1094 
1095     if((encCtx->result != NULL) &&
1096        (xmlSecBufferGetData(encCtx->result) != NULL) &&
1097        (encCtx->resultBase64Encoded != 0)) {
1098 
1099         fprintf(output, "<Result>");
1100         (void)fwrite(xmlSecBufferGetData(encCtx->result),
1101                      xmlSecBufferGetSize(encCtx->result), 1,
1102                      output);
1103         fprintf(output, "</Result>\n");
1104     }
1105 
1106     switch(encCtx->mode) {
1107         case xmlEncCtxModeEncryptedData:
1108             if(encCtx->operation == xmlSecTransformOperationEncrypt) {
1109                 fprintf(output, "</DataEncryptionContext>\n");
1110             } else {
1111                 fprintf(output, "</DataDecryptionContext>\n");
1112             }
1113             break;
1114         case xmlEncCtxModeEncryptedKey:
1115             if(encCtx->operation == xmlSecTransformOperationEncrypt) {
1116                 fprintf(output, "</KeyEncryptionContext>\n");
1117             } else {
1118                 fprintf(output, "</KeyDecryptionContext>\n");
1119             }
1120             break;
1121     }
1122 }
1123 
1124 #endif /* XMLSEC_NO_XMLENC */
1125 
1126