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