2 * XML Security Library (http://www.aleksey.com/xmlsec).
4 * "XML Encryption" implementation
5 * http://www.w3.org/TR/xmlenc-core
7 * This is free software; see Copyright file in the source
8 * distribution for preciese wording.
10 * Copyright (C) 2002-2003 Aleksey Sanin <aleksey@aleksey.com>
14 #ifndef XMLSEC_NO_XMLENC
20 #include <libxml/tree.h>
21 #include <libxml/parser.h>
23 #include <xmlsec/xmlsec.h>
24 #include <xmlsec/buffer.h>
25 #include <xmlsec/xmltree.h>
26 #include <xmlsec/keys.h>
27 #include <xmlsec/keysmngr.h>
28 #include <xmlsec/transforms.h>
29 #include <xmlsec/keyinfo.h>
30 #include <xmlsec/xmlenc.h>
31 #include <xmlsec/errors.h>
33 static int xmlSecEncCtxEncDataNodeRead (xmlSecEncCtxPtr encCtx,
35 static int xmlSecEncCtxEncDataNodeWrite (xmlSecEncCtxPtr encCtx);
36 static int xmlSecEncCtxCipherDataNodeRead (xmlSecEncCtxPtr encCtx,
38 static int xmlSecEncCtxCipherReferenceNodeRead (xmlSecEncCtxPtr encCtx,
41 /* The ID attribute in XMLEnc is 'Id' */
42 static const xmlChar* xmlSecEncIds[] = { BAD_CAST "Id", NULL };
47 * @keysMngr: the pointer to keys manager.
49 * Creates <enc:EncryptedData/> element processing context.
50 * The caller is responsible for destroying returend object by calling
51 * #xmlSecEncCtxDestroy function.
53 * Returns: pointer to newly allocated context object or NULL if an error
57 xmlSecEncCtxCreate(xmlSecKeysMngrPtr keysMngr) {
58 xmlSecEncCtxPtr encCtx;
61 encCtx = (xmlSecEncCtxPtr) xmlMalloc(sizeof(xmlSecEncCtx));
63 xmlSecError(XMLSEC_ERRORS_HERE,
66 XMLSEC_ERRORS_R_MALLOC_FAILED,
67 "sizeof(xmlSecEncCtx)=%d",
68 sizeof(xmlSecEncCtx));
72 ret = xmlSecEncCtxInitialize(encCtx, keysMngr);
74 xmlSecError(XMLSEC_ERRORS_HERE,
76 "xmlSecEncCtxInitialize",
77 XMLSEC_ERRORS_R_XMLSEC_FAILED,
78 XMLSEC_ERRORS_NO_MESSAGE);
79 xmlSecEncCtxDestroy(encCtx);
86 * xmlSecEncCtxDestroy:
87 * @encCtx: the pointer to <enc:EncryptedData/> processing context.
89 * Destroy context object created with #xmlSecEncCtxCreate function.
92 xmlSecEncCtxDestroy(xmlSecEncCtxPtr encCtx) {
93 xmlSecAssert(encCtx != NULL);
95 xmlSecEncCtxFinalize(encCtx);
100 * xmlSecEncCtxInitialize:
101 * @encCtx: the pointer to <enc:EncryptedData/> processing context.
102 * @keysMngr: the pointer to keys manager.
104 * Initializes <enc:EncryptedData/> element processing context.
105 * The caller is responsible for cleaing up returend object by calling
106 * #xmlSecEncCtxFinalize function.
108 * Returns: 0 on success or a negative value if an error occurs.
111 xmlSecEncCtxInitialize(xmlSecEncCtxPtr encCtx, xmlSecKeysMngrPtr keysMngr) {
114 xmlSecAssert2(encCtx != NULL, -1);
116 memset(encCtx, 0, sizeof(xmlSecEncCtx));
118 /* initialize key info */
119 ret = xmlSecKeyInfoCtxInitialize(&(encCtx->keyInfoReadCtx), keysMngr);
121 xmlSecError(XMLSEC_ERRORS_HERE,
123 "xmlSecKeyInfoCtxInitialize",
124 XMLSEC_ERRORS_R_XMLSEC_FAILED,
125 XMLSEC_ERRORS_NO_MESSAGE);
128 encCtx->keyInfoReadCtx.mode = xmlSecKeyInfoModeRead;
130 ret = xmlSecKeyInfoCtxInitialize(&(encCtx->keyInfoWriteCtx), keysMngr);
132 xmlSecError(XMLSEC_ERRORS_HERE,
134 "xmlSecKeyInfoCtxInitialize",
135 XMLSEC_ERRORS_R_XMLSEC_FAILED,
136 XMLSEC_ERRORS_NO_MESSAGE);
139 encCtx->keyInfoWriteCtx.mode = xmlSecKeyInfoModeWrite;
140 /* it's not wise to write private key :) */
141 encCtx->keyInfoWriteCtx.keyReq.keyType = xmlSecKeyDataTypePublic;
143 /* initializes transforms encCtx */
144 ret = xmlSecTransformCtxInitialize(&(encCtx->transformCtx));
146 xmlSecError(XMLSEC_ERRORS_HERE,
148 "xmlSecTransformCtxInitialize",
149 XMLSEC_ERRORS_R_XMLSEC_FAILED,
150 XMLSEC_ERRORS_NO_MESSAGE);
158 * xmlSecEncCtxFinalize:
159 * @encCtx: the pointer to <enc:EncryptedData/> processing context.
161 * Cleans up @encCtx object.
164 xmlSecEncCtxFinalize(xmlSecEncCtxPtr encCtx) {
165 xmlSecAssert(encCtx != NULL);
167 xmlSecEncCtxReset(encCtx);
169 xmlSecTransformCtxFinalize(&(encCtx->transformCtx));
170 xmlSecKeyInfoCtxFinalize(&(encCtx->keyInfoReadCtx));
171 xmlSecKeyInfoCtxFinalize(&(encCtx->keyInfoWriteCtx));
173 memset(encCtx, 0, sizeof(xmlSecEncCtx));
178 * @encCtx: the pointer to <enc:EncryptedData/> processing context.
180 * Resets @encCtx object, user settings are not touched.
183 xmlSecEncCtxReset(xmlSecEncCtxPtr encCtx) {
184 xmlSecAssert(encCtx != NULL);
186 xmlSecTransformCtxReset(&(encCtx->transformCtx));
187 xmlSecKeyInfoCtxReset(&(encCtx->keyInfoReadCtx));
188 xmlSecKeyInfoCtxReset(&(encCtx->keyInfoWriteCtx));
190 encCtx->operation = xmlSecTransformOperationNone;
191 encCtx->result = NULL;
192 encCtx->resultBase64Encoded = 0;
193 encCtx->resultReplaced = 0;
194 encCtx->encMethod = NULL;
196 if (encCtx->replacedNodeList != NULL) {
197 xmlFreeNodeList(encCtx->replacedNodeList);
198 encCtx->replacedNodeList = NULL;
201 if(encCtx->encKey != NULL) {
202 xmlSecKeyDestroy(encCtx->encKey);
203 encCtx->encKey = NULL;
206 if(encCtx->id != NULL) {
211 if(encCtx->type != NULL) {
212 xmlFree(encCtx->type);
216 if(encCtx->mimeType != NULL) {
217 xmlFree(encCtx->mimeType);
218 encCtx->mimeType = NULL;
221 if(encCtx->encoding != NULL) {
222 xmlFree(encCtx->encoding);
223 encCtx->encoding = NULL;
226 if(encCtx->recipient != NULL) {
227 xmlFree(encCtx->recipient);
228 encCtx->recipient = NULL;
231 if(encCtx->carriedKeyName != NULL) {
232 xmlFree(encCtx->carriedKeyName);
233 encCtx->carriedKeyName = NULL;
236 encCtx->encDataNode = encCtx->encMethodNode =
237 encCtx->keyInfoNode = encCtx->cipherValueNode = NULL;
241 * xmlSecEncCtxCopyUserPref:
242 * @dst: the pointer to destination context.
243 * @src: the pointer to source context.
245 * Copies user preference from @src context to @dst.
247 * Returns: 0 on success or a negative value if an error occurs.
250 xmlSecEncCtxCopyUserPref(xmlSecEncCtxPtr dst, xmlSecEncCtxPtr src) {
253 xmlSecAssert2(dst != NULL, -1);
254 xmlSecAssert2(src != NULL, -1);
256 dst->userData = src->userData;
257 dst->flags = src->flags;
258 dst->flags2 = src->flags2;
259 dst->defEncMethodId = src->defEncMethodId;
260 dst->mode = src->mode;
262 ret = xmlSecTransformCtxCopyUserPref(&(dst->transformCtx), &(src->transformCtx));
264 xmlSecError(XMLSEC_ERRORS_HERE,
266 "xmlSecTransformCtxCopyUserPref",
267 XMLSEC_ERRORS_R_XMLSEC_FAILED,
268 XMLSEC_ERRORS_NO_MESSAGE);
272 ret = xmlSecKeyInfoCtxCopyUserPref(&(dst->keyInfoReadCtx), &(src->keyInfoReadCtx));
274 xmlSecError(XMLSEC_ERRORS_HERE,
276 "xmlSecKeyInfoCtxCopyUserPref",
277 XMLSEC_ERRORS_R_XMLSEC_FAILED,
278 XMLSEC_ERRORS_NO_MESSAGE);
282 ret = xmlSecKeyInfoCtxCopyUserPref(&(dst->keyInfoWriteCtx), &(src->keyInfoWriteCtx));
284 xmlSecError(XMLSEC_ERRORS_HERE,
286 "xmlSecKeyInfoCtxCopyUserPref",
287 XMLSEC_ERRORS_R_XMLSEC_FAILED,
288 XMLSEC_ERRORS_NO_MESSAGE);
296 * xmlSecEncCtxBinaryEncrypt:
297 * @encCtx: the pointer to <enc:EncryptedData/> processing context.
298 * @tmpl: the pointer to <enc:EncryptedData/> template node.
299 * @data: the pointer for binary buffer.
300 * @dataSize: the @data buffer size.
302 * Encrypts @data according to template @tmpl.
304 * Returns: 0 on success or a negative value if an error occurs.
307 xmlSecEncCtxBinaryEncrypt(xmlSecEncCtxPtr encCtx, xmlNodePtr tmpl,
308 const xmlSecByte* data, xmlSecSize dataSize) {
311 xmlSecAssert2(encCtx != NULL, -1);
312 xmlSecAssert2(encCtx->result == NULL, -1);
313 xmlSecAssert2(tmpl != NULL, -1);
314 xmlSecAssert2(data != NULL, -1);
316 /* initialize context and add ID atributes to the list of known ids */
317 encCtx->operation = xmlSecTransformOperationEncrypt;
318 xmlSecAddIDs(tmpl->doc, tmpl, xmlSecEncIds);
320 /* read the template and set encryption method, key, etc. */
321 ret = xmlSecEncCtxEncDataNodeRead(encCtx, tmpl);
323 xmlSecError(XMLSEC_ERRORS_HERE,
325 "xmlSecEncCtxEncDataNodeRead",
326 XMLSEC_ERRORS_R_XMLSEC_FAILED,
327 XMLSEC_ERRORS_NO_MESSAGE);
331 ret = xmlSecTransformCtxBinaryExecute(&(encCtx->transformCtx), data, dataSize);
333 xmlSecError(XMLSEC_ERRORS_HERE,
335 "xmlSecTransformCtxBinaryExecute",
336 XMLSEC_ERRORS_R_XMLSEC_FAILED,
342 encCtx->result = encCtx->transformCtx.result;
343 xmlSecAssert2(encCtx->result != NULL, -1);
345 ret = xmlSecEncCtxEncDataNodeWrite(encCtx);
347 xmlSecError(XMLSEC_ERRORS_HERE,
349 "xmlSecEncCtxEncDataNodeWrite",
350 XMLSEC_ERRORS_R_XMLSEC_FAILED,
351 XMLSEC_ERRORS_NO_MESSAGE);
358 * xmlSecEncCtxXmlEncrypt:
359 * @encCtx: the pointer to <enc:EncryptedData/> processing context.
360 * @tmpl: the pointer to <enc:EncryptedData/> template node.
361 * @node: the pointer to node for encryption.
363 * Encrypts @node according to template @tmpl. If requested, @node is replaced
364 * with result <enc:EncryptedData/> node.
366 * Returns: 0 on success or a negative value if an error occurs.
369 xmlSecEncCtxXmlEncrypt(xmlSecEncCtxPtr encCtx, xmlNodePtr tmpl, xmlNodePtr node) {
370 xmlOutputBufferPtr output;
373 xmlSecAssert2(encCtx != NULL, -1);
374 xmlSecAssert2(encCtx->result == NULL, -1);
375 xmlSecAssert2(tmpl != NULL, -1);
376 xmlSecAssert2(node != NULL, -1);
377 xmlSecAssert2(node->doc != NULL, -1);
379 /* initialize context and add ID atributes to the list of known ids */
380 encCtx->operation = xmlSecTransformOperationEncrypt;
381 xmlSecAddIDs(tmpl->doc, tmpl, xmlSecEncIds);
383 /* read the template and set encryption method, key, etc. */
384 ret = xmlSecEncCtxEncDataNodeRead(encCtx, tmpl);
386 xmlSecError(XMLSEC_ERRORS_HERE,
388 "xmlSecEncCtxEncDataNodeRead",
389 XMLSEC_ERRORS_R_XMLSEC_FAILED,
390 XMLSEC_ERRORS_NO_MESSAGE);
394 ret = xmlSecTransformCtxPrepare(&(encCtx->transformCtx), xmlSecTransformDataTypeBin);
396 xmlSecError(XMLSEC_ERRORS_HERE,
398 "xmlSecTransformCtxPrepare",
399 XMLSEC_ERRORS_R_XMLSEC_FAILED,
404 xmlSecAssert2(encCtx->transformCtx.first != NULL, -1);
405 output = xmlSecTransformCreateOutputBuffer(encCtx->transformCtx.first,
406 &(encCtx->transformCtx));
408 xmlSecError(XMLSEC_ERRORS_HERE,
409 xmlSecErrorsSafeString(xmlSecTransformGetName(encCtx->transformCtx.first)),
410 "xmlSecTransformCreateOutputBuffer",
411 XMLSEC_ERRORS_R_XMLSEC_FAILED,
412 XMLSEC_ERRORS_NO_MESSAGE);
417 if((encCtx->type != NULL) && xmlStrEqual(encCtx->type, xmlSecTypeEncElement)) {
418 /* get the content of the node */
419 xmlNodeDumpOutput(output, node->doc, node, 0, 0, NULL);
420 } else if((encCtx->type != NULL) && xmlStrEqual(encCtx->type, xmlSecTypeEncContent)) {
423 /* get the content of the nodes childs */
424 for(cur = node->children; cur != NULL; cur = cur->next) {
425 xmlNodeDumpOutput(output, node->doc, cur, 0, 0, NULL);
428 xmlSecError(XMLSEC_ERRORS_HERE,
431 XMLSEC_ERRORS_R_INVALID_TYPE,
433 xmlSecErrorsSafeString(encCtx->type));
434 xmlOutputBufferClose(output);
438 /* close the buffer and flush everything */
439 ret = xmlOutputBufferClose(output);
441 xmlSecError(XMLSEC_ERRORS_HERE,
443 "xmlOutputBufferClose",
444 XMLSEC_ERRORS_R_XML_FAILED,
445 XMLSEC_ERRORS_NO_MESSAGE);
449 encCtx->result = encCtx->transformCtx.result;
450 xmlSecAssert2(encCtx->result != NULL, -1);
452 ret = xmlSecEncCtxEncDataNodeWrite(encCtx);
454 xmlSecError(XMLSEC_ERRORS_HERE,
456 "xmlSecEncCtxEncDataNodeWrite",
457 XMLSEC_ERRORS_R_XMLSEC_FAILED,
458 XMLSEC_ERRORS_NO_MESSAGE);
462 /* now we need to update our original document */
463 if((encCtx->type != NULL) && xmlStrEqual(encCtx->type, xmlSecTypeEncElement)) {
464 /* check if we need to return the replaced node */
465 if((encCtx->flags & XMLSEC_ENC_RETURN_REPLACED_NODE) != 0) {
466 ret = xmlSecReplaceNodeAndReturn(node, tmpl, &(encCtx->replacedNodeList));
468 xmlSecError(XMLSEC_ERRORS_HERE,
471 XMLSEC_ERRORS_R_XMLSEC_FAILED,
473 xmlSecErrorsSafeString(xmlSecNodeGetName(node)));
477 ret = xmlSecReplaceNode(node, tmpl);
479 xmlSecError(XMLSEC_ERRORS_HERE,
482 XMLSEC_ERRORS_R_XMLSEC_FAILED,
484 xmlSecErrorsSafeString(xmlSecNodeGetName(node)));
489 encCtx->resultReplaced = 1;
490 } else if((encCtx->type != NULL) && xmlStrEqual(encCtx->type, xmlSecTypeEncContent)) {
491 /* check if we need to return the replaced node */
492 if((encCtx->flags & XMLSEC_ENC_RETURN_REPLACED_NODE) != 0) {
493 ret = xmlSecReplaceContentAndReturn(node, tmpl, &(encCtx->replacedNodeList));
495 xmlSecError(XMLSEC_ERRORS_HERE,
497 "xmlSecReplaceContentAndReturn",
498 XMLSEC_ERRORS_R_XMLSEC_FAILED,
500 xmlSecErrorsSafeString(xmlSecNodeGetName(node)));
504 ret = xmlSecReplaceContent(node, tmpl);
506 xmlSecError(XMLSEC_ERRORS_HERE,
508 "xmlSecReplaceContent",
509 XMLSEC_ERRORS_R_XMLSEC_FAILED,
511 xmlSecErrorsSafeString(xmlSecNodeGetName(node)));
516 encCtx->resultReplaced = 1;
518 /* we should've catached this error before */
519 xmlSecError(XMLSEC_ERRORS_HERE,
522 XMLSEC_ERRORS_R_INVALID_TYPE,
524 xmlSecErrorsSafeString(encCtx->type));
531 * xmlSecEncCtxUriEncrypt:
532 * @encCtx: the pointer to <enc:EncryptedData/> processing context.
533 * @tmpl: the pointer to <enc:EncryptedData/> template node.
536 * Encrypts data from @uri according to template @tmpl.
538 * Returns: 0 on success or a negative value if an error occurs.
541 xmlSecEncCtxUriEncrypt(xmlSecEncCtxPtr encCtx, xmlNodePtr tmpl, const xmlChar *uri) {
544 xmlSecAssert2(encCtx != NULL, -1);
545 xmlSecAssert2(encCtx->result == NULL, -1);
546 xmlSecAssert2(tmpl != NULL, -1);
547 xmlSecAssert2(uri != NULL, -1);
549 /* initialize context and add ID atributes to the list of known ids */
550 encCtx->operation = xmlSecTransformOperationEncrypt;
551 xmlSecAddIDs(tmpl->doc, tmpl, xmlSecEncIds);
553 /* we need to add input uri transform first */
554 ret = xmlSecTransformCtxSetUri(&(encCtx->transformCtx), uri, tmpl);
556 xmlSecError(XMLSEC_ERRORS_HERE,
558 "xmlSecTransformCtxSetUri",
559 XMLSEC_ERRORS_R_XMLSEC_FAILED,
561 xmlSecErrorsSafeString(uri));
565 /* read the template and set encryption method, key, etc. */
566 ret = xmlSecEncCtxEncDataNodeRead(encCtx, tmpl);
568 xmlSecError(XMLSEC_ERRORS_HERE,
570 "xmlSecEncCtxEncDataNodeRead",
571 XMLSEC_ERRORS_R_XMLSEC_FAILED,
572 XMLSEC_ERRORS_NO_MESSAGE);
576 /* encrypt the data */
577 ret = xmlSecTransformCtxExecute(&(encCtx->transformCtx), tmpl->doc);
579 xmlSecError(XMLSEC_ERRORS_HERE,
581 "xmlSecTransformCtxExecute",
582 XMLSEC_ERRORS_R_XMLSEC_FAILED,
583 XMLSEC_ERRORS_NO_MESSAGE);
587 encCtx->result = encCtx->transformCtx.result;
588 xmlSecAssert2(encCtx->result != NULL, -1);
590 ret = xmlSecEncCtxEncDataNodeWrite(encCtx);
592 xmlSecError(XMLSEC_ERRORS_HERE,
594 "xmlSecEncCtxEncDataNodeWrite",
595 XMLSEC_ERRORS_R_XMLSEC_FAILED,
596 XMLSEC_ERRORS_NO_MESSAGE);
604 * xmlSecEncCtxDecrypt:
605 * @encCtx: the pointer to <enc:EncryptedData/> processing context.
606 * @node: the pointer to <enc:EncryptedData/> node.
608 * Decrypts @node and if necessary replaces @node with decrypted data.
610 * Returns: 0 on success or a negative value if an error occurs.
613 xmlSecEncCtxDecrypt(xmlSecEncCtxPtr encCtx, xmlNodePtr node) {
614 xmlSecBufferPtr buffer;
617 xmlSecAssert2(encCtx != NULL, -1);
618 xmlSecAssert2(node != NULL, -1);
621 buffer = xmlSecEncCtxDecryptToBuffer(encCtx, node);
623 xmlSecError(XMLSEC_ERRORS_HERE,
625 "xmlSecEncCtxDecryptToBuffer",
626 XMLSEC_ERRORS_R_XMLSEC_FAILED,
627 XMLSEC_ERRORS_NO_MESSAGE);
631 /* replace original node if requested */
632 if((encCtx->type != NULL) && xmlStrEqual(encCtx->type, xmlSecTypeEncElement)) {
633 /* check if we need to return the replaced node */
634 if((encCtx->flags & XMLSEC_ENC_RETURN_REPLACED_NODE) != 0) {
635 ret = xmlSecReplaceNodeBufferAndReturn(node, xmlSecBufferGetData(buffer), xmlSecBufferGetSize(buffer), &(encCtx->replacedNodeList));
637 xmlSecError(XMLSEC_ERRORS_HERE,
639 "xmlSecReplaceNodeBufferAndReturn",
640 XMLSEC_ERRORS_R_XMLSEC_FAILED,
642 xmlSecErrorsSafeString(xmlSecNodeGetName(node)));
646 ret = xmlSecReplaceNodeBuffer(node, xmlSecBufferGetData(buffer), xmlSecBufferGetSize(buffer));
648 xmlSecError(XMLSEC_ERRORS_HERE,
650 "xmlSecReplaceNodeBuffer",
651 XMLSEC_ERRORS_R_XMLSEC_FAILED,
653 xmlSecErrorsSafeString(xmlSecNodeGetName(node)));
658 encCtx->resultReplaced = 1;
659 } else if((encCtx->type != NULL) && xmlStrEqual(encCtx->type, xmlSecTypeEncContent)) {
660 /* replace the node with the buffer */
662 /* check if we need to return the replaced node */
663 if((encCtx->flags & XMLSEC_ENC_RETURN_REPLACED_NODE) != 0) {
664 ret = xmlSecReplaceNodeBufferAndReturn(node, xmlSecBufferGetData(buffer), xmlSecBufferGetSize(buffer), &(encCtx->replacedNodeList));
666 xmlSecError(XMLSEC_ERRORS_HERE,
668 "xmlSecReplaceNodeBufferAndReturn",
669 XMLSEC_ERRORS_R_XMLSEC_FAILED,
671 xmlSecErrorsSafeString(xmlSecNodeGetName(node)));
675 ret = xmlSecReplaceNodeBuffer(node, xmlSecBufferGetData(buffer), xmlSecBufferGetSize(buffer));
677 xmlSecError(XMLSEC_ERRORS_HERE,
679 "xmlSecReplaceNodeBuffer",
680 XMLSEC_ERRORS_R_XMLSEC_FAILED,
682 xmlSecErrorsSafeString(xmlSecNodeGetName(node)));
686 encCtx->resultReplaced = 1;
693 * xmlSecEncCtxDecryptToBuffer:
694 * @encCtx: the pointer to <enc:EncryptedData/> processing context.
695 * @node: the pointer to <enc:EncryptedData/> node.
697 * Decrypts @node data to the @encCtx buffer.
699 * Returns: 0 on success or a negative value if an error occurs.
702 xmlSecEncCtxDecryptToBuffer(xmlSecEncCtxPtr encCtx, xmlNodePtr node) {
705 xmlSecAssert2(encCtx != NULL, NULL);
706 xmlSecAssert2(encCtx->result == NULL, NULL);
707 xmlSecAssert2(node != NULL, NULL);
709 /* initialize context and add ID atributes to the list of known ids */
710 encCtx->operation = xmlSecTransformOperationDecrypt;
711 xmlSecAddIDs(node->doc, node, xmlSecEncIds);
713 ret = xmlSecEncCtxEncDataNodeRead(encCtx, node);
715 xmlSecError(XMLSEC_ERRORS_HERE,
717 "xmlSecEncCtxEncDataNodeRead",
718 XMLSEC_ERRORS_R_XMLSEC_FAILED,
719 XMLSEC_ERRORS_NO_MESSAGE);
723 /* decrypt the data */
724 if(encCtx->cipherValueNode != NULL) {
725 xmlChar* data = NULL;
726 xmlSecSize dataSize = 0;
728 data = xmlNodeGetContent(encCtx->cipherValueNode);
730 xmlSecError(XMLSEC_ERRORS_HERE,
732 xmlSecErrorsSafeString(xmlSecNodeGetName(encCtx->cipherValueNode)),
733 XMLSEC_ERRORS_R_INVALID_NODE_CONTENT,
734 XMLSEC_ERRORS_NO_MESSAGE);
737 dataSize = xmlStrlen(data);
739 ret = xmlSecTransformCtxBinaryExecute(&(encCtx->transformCtx), data, dataSize);
741 xmlSecError(XMLSEC_ERRORS_HERE,
743 "xmlSecTransformCtxBinaryExecute",
744 XMLSEC_ERRORS_R_XMLSEC_FAILED,
745 XMLSEC_ERRORS_NO_MESSAGE);
755 ret = xmlSecTransformCtxExecute(&(encCtx->transformCtx), node->doc);
757 xmlSecError(XMLSEC_ERRORS_HERE,
759 "xmlSecTransformCtxBinaryExecute",
760 XMLSEC_ERRORS_R_XMLSEC_FAILED,
761 XMLSEC_ERRORS_NO_MESSAGE);
766 encCtx->result = encCtx->transformCtx.result;
767 xmlSecAssert2(encCtx->result != NULL, NULL);
769 return(encCtx->result);
773 xmlSecEncCtxEncDataNodeRead(xmlSecEncCtxPtr encCtx, xmlNodePtr node) {
777 xmlSecAssert2(encCtx != NULL, -1);
778 xmlSecAssert2((encCtx->operation == xmlSecTransformOperationEncrypt) || (encCtx->operation == xmlSecTransformOperationDecrypt), -1);
779 xmlSecAssert2(node != NULL, -1);
781 switch(encCtx->mode) {
782 case xmlEncCtxModeEncryptedData:
783 if(!xmlSecCheckNodeName(node, xmlSecNodeEncryptedData, xmlSecEncNs)) {
784 xmlSecError(XMLSEC_ERRORS_HERE,
786 xmlSecErrorsSafeString(xmlSecNodeGetName(node)),
787 XMLSEC_ERRORS_R_INVALID_NODE,
789 xmlSecErrorsSafeString(xmlSecNodeEncryptedData));
793 case xmlEncCtxModeEncryptedKey:
794 if(!xmlSecCheckNodeName(node, xmlSecNodeEncryptedKey, xmlSecEncNs)) {
795 xmlSecError(XMLSEC_ERRORS_HERE,
797 xmlSecErrorsSafeString(xmlSecNodeGetName(node)),
798 XMLSEC_ERRORS_R_INVALID_NODE,
800 xmlSecErrorsSafeString(xmlSecNodeEncryptedKey));
806 /* first read node data */
807 xmlSecAssert2(encCtx->id == NULL, -1);
808 xmlSecAssert2(encCtx->type == NULL, -1);
809 xmlSecAssert2(encCtx->mimeType == NULL, -1);
810 xmlSecAssert2(encCtx->encoding == NULL, -1);
811 xmlSecAssert2(encCtx->recipient == NULL, -1);
812 xmlSecAssert2(encCtx->carriedKeyName == NULL, -1);
814 encCtx->id = xmlGetProp(node, xmlSecAttrId);
815 encCtx->type = xmlGetProp(node, xmlSecAttrType);
816 encCtx->mimeType = xmlGetProp(node, xmlSecAttrMimeType);
817 encCtx->encoding = xmlGetProp(node, xmlSecAttrEncoding);
818 if(encCtx->mode == xmlEncCtxModeEncryptedKey) {
819 encCtx->recipient = xmlGetProp(node, xmlSecAttrRecipient);
820 /* todo: check recipient? */
822 cur = xmlSecGetNextElementNode(node->children);
824 /* first node is optional EncryptionMethod, we'll read it later */
825 xmlSecAssert2(encCtx->encMethodNode == NULL, -1);
826 if((cur != NULL) && (xmlSecCheckNodeName(cur, xmlSecNodeEncryptionMethod, xmlSecEncNs))) {
827 encCtx->encMethodNode = cur;
828 cur = xmlSecGetNextElementNode(cur->next);
831 /* next node is optional KeyInfo, we'll process it later */
832 xmlSecAssert2(encCtx->keyInfoNode == NULL, -1);
833 if((cur != NULL) && (xmlSecCheckNodeName(cur, xmlSecNodeKeyInfo, xmlSecDSigNs))) {
834 encCtx->keyInfoNode = cur;
835 cur = xmlSecGetNextElementNode(cur->next);
838 /* next is required CipherData node */
839 if((cur == NULL) || (!xmlSecCheckNodeName(cur, xmlSecNodeCipherData, xmlSecEncNs))) {
840 xmlSecError(XMLSEC_ERRORS_HERE,
842 xmlSecErrorsSafeString(xmlSecNodeGetName(cur)),
843 XMLSEC_ERRORS_R_INVALID_NODE,
845 xmlSecErrorsSafeString(xmlSecNodeCipherData));
849 ret = xmlSecEncCtxCipherDataNodeRead(encCtx, cur);
851 xmlSecError(XMLSEC_ERRORS_HERE,
853 "xmlSecEncCtxCipherDataNodeRead",
854 XMLSEC_ERRORS_R_XMLSEC_FAILED,
855 XMLSEC_ERRORS_NO_MESSAGE);
858 cur = xmlSecGetNextElementNode(cur->next);
860 /* next is optional EncryptionProperties node (we simply ignore it) */
861 if((cur != NULL) && (xmlSecCheckNodeName(cur, xmlSecNodeEncryptionProperties, xmlSecEncNs))) {
862 cur = xmlSecGetNextElementNode(cur->next);
865 /* there are more possible nodes for the <EncryptedKey> node */
866 if(encCtx->mode == xmlEncCtxModeEncryptedKey) {
867 /* next is optional ReferenceList node (we simply ignore it) */
868 if((cur != NULL) && (xmlSecCheckNodeName(cur, xmlSecNodeReferenceList, xmlSecEncNs))) {
869 cur = xmlSecGetNextElementNode(cur->next);
872 /* next is optional CarriedKeyName node (we simply ignore it) */
873 if((cur != NULL) && (xmlSecCheckNodeName(cur, xmlSecNodeCarriedKeyName, xmlSecEncNs))) {
874 encCtx->carriedKeyName = xmlNodeGetContent(cur);
875 if(encCtx->carriedKeyName == NULL) {
876 xmlSecError(XMLSEC_ERRORS_HERE,
878 xmlSecErrorsSafeString(xmlSecNodeGetName(cur)),
879 XMLSEC_ERRORS_R_INVALID_NODE_CONTENT,
881 xmlSecErrorsSafeString(xmlSecNodeCipherData));
884 /* TODO: decode the name? */
885 cur = xmlSecGetNextElementNode(cur->next);
889 /* if there is something left than it's an error */
891 xmlSecError(XMLSEC_ERRORS_HERE,
893 xmlSecErrorsSafeString(xmlSecNodeGetName(cur)),
894 XMLSEC_ERRORS_R_UNEXPECTED_NODE,
895 XMLSEC_ERRORS_NO_MESSAGE);
899 /* now read the encryption method node */
900 xmlSecAssert2(encCtx->encMethod == NULL, -1);
901 if(encCtx->encMethodNode != NULL) {
902 encCtx->encMethod = xmlSecTransformCtxNodeRead(&(encCtx->transformCtx), encCtx->encMethodNode,
903 xmlSecTransformUsageEncryptionMethod);
904 if(encCtx->encMethod == NULL) {
905 xmlSecError(XMLSEC_ERRORS_HERE,
907 "xmlSecTransformCtxNodeRead",
908 XMLSEC_ERRORS_R_XMLSEC_FAILED,
910 xmlSecErrorsSafeString(xmlSecNodeGetName(encCtx->encMethodNode)));
913 } else if(encCtx->defEncMethodId != xmlSecTransformIdUnknown) {
914 encCtx->encMethod = xmlSecTransformCtxCreateAndAppend(&(encCtx->transformCtx),
915 encCtx->defEncMethodId);
916 if(encCtx->encMethod == NULL) {
917 xmlSecError(XMLSEC_ERRORS_HERE,
919 "xmlSecTransformCtxAppend",
920 XMLSEC_ERRORS_R_XMLSEC_FAILED,
921 XMLSEC_ERRORS_NO_MESSAGE);
925 xmlSecError(XMLSEC_ERRORS_HERE,
928 XMLSEC_ERRORS_R_INVALID_DATA,
929 "encryption method not specified");
932 encCtx->encMethod->operation = encCtx->operation;
934 /* we have encryption method, find key */
935 ret = xmlSecTransformSetKeyReq(encCtx->encMethod, &(encCtx->keyInfoReadCtx.keyReq));
937 xmlSecError(XMLSEC_ERRORS_HERE,
939 "xmlSecTransformSetKeyReq",
940 XMLSEC_ERRORS_R_XMLSEC_FAILED,
942 xmlSecErrorsSafeString(xmlSecTransformGetName(encCtx->encMethod)));
946 /* TODO: KeyInfo node != NULL and encKey != NULL */
947 if((encCtx->encKey == NULL) && (encCtx->keyInfoReadCtx.keysMngr != NULL)
948 && (encCtx->keyInfoReadCtx.keysMngr->getKey != NULL)) {
949 encCtx->encKey = (encCtx->keyInfoReadCtx.keysMngr->getKey)(encCtx->keyInfoNode,
950 &(encCtx->keyInfoReadCtx));
953 /* check that we have exactly what we want */
954 if((encCtx->encKey == NULL) ||
955 (!xmlSecKeyMatch(encCtx->encKey, NULL, &(encCtx->keyInfoReadCtx.keyReq)))) {
957 xmlSecError(XMLSEC_ERRORS_HERE,
960 XMLSEC_ERRORS_R_KEY_NOT_FOUND,
961 XMLSEC_ERRORS_NO_MESSAGE);
965 /* set the key to the transform */
966 ret = xmlSecTransformSetKey(encCtx->encMethod, encCtx->encKey);
968 xmlSecError(XMLSEC_ERRORS_HERE,
970 "xmlSecTransformSetKey",
971 XMLSEC_ERRORS_R_XMLSEC_FAILED,
973 xmlSecErrorsSafeString(xmlSecTransformGetName(encCtx->encMethod)));
977 /* if we need to write result to xml node then we need base64 encode it */
978 if((encCtx->operation == xmlSecTransformOperationEncrypt) && (encCtx->cipherValueNode != NULL)) {
979 xmlSecTransformPtr base64Encode;
981 /* we need to add base64 encode transform */
982 base64Encode = xmlSecTransformCtxCreateAndAppend(&(encCtx->transformCtx), xmlSecTransformBase64Id);
983 if(base64Encode == NULL) {
984 xmlSecError(XMLSEC_ERRORS_HERE,
986 "xmlSecTransformCtxCreateAndAppend",
987 XMLSEC_ERRORS_R_XMLSEC_FAILED,
988 XMLSEC_ERRORS_NO_MESSAGE);
991 base64Encode->operation = xmlSecTransformOperationEncode;
992 encCtx->resultBase64Encoded = 1;
999 xmlSecEncCtxEncDataNodeWrite(xmlSecEncCtxPtr encCtx) {
1002 xmlSecAssert2(encCtx != NULL, -1);
1003 xmlSecAssert2(encCtx->result != NULL, -1);
1004 xmlSecAssert2(encCtx->encKey != NULL, -1);
1006 /* write encrypted data to xml (if requested) */
1007 if(encCtx->cipherValueNode != NULL) {
1008 xmlSecAssert2(xmlSecBufferGetData(encCtx->result) != NULL, -1);
1010 xmlNodeSetContentLen(encCtx->cipherValueNode,
1011 xmlSecBufferGetData(encCtx->result),
1012 xmlSecBufferGetSize(encCtx->result));
1013 encCtx->resultReplaced = 1;
1016 /* update <enc:KeyInfo/> node */
1017 if(encCtx->keyInfoNode != NULL) {
1018 ret = xmlSecKeyInfoNodeWrite(encCtx->keyInfoNode, encCtx->encKey, &(encCtx->keyInfoWriteCtx));
1020 xmlSecError(XMLSEC_ERRORS_HERE,
1022 "xmlSecKeyInfoNodeWrite",
1023 XMLSEC_ERRORS_R_XMLSEC_FAILED,
1024 XMLSEC_ERRORS_NO_MESSAGE);
1033 xmlSecEncCtxCipherDataNodeRead(xmlSecEncCtxPtr encCtx, xmlNodePtr node) {
1037 xmlSecAssert2(encCtx != NULL, -1);
1038 xmlSecAssert2(node != NULL, -1);
1040 cur = xmlSecGetNextElementNode(node->children);
1042 /* we either have CipherValue or CipherReference node */
1043 xmlSecAssert2(encCtx->cipherValueNode == NULL, -1);
1044 if((cur != NULL) && (xmlSecCheckNodeName(cur, xmlSecNodeCipherValue, xmlSecEncNs))) {
1045 /* don't need data from CipherData node when we are encrypting */
1046 if(encCtx->operation == xmlSecTransformOperationDecrypt) {
1047 xmlSecTransformPtr base64Decode;
1049 /* we need to add base64 decode transform */
1050 base64Decode = xmlSecTransformCtxCreateAndPrepend(&(encCtx->transformCtx), xmlSecTransformBase64Id);
1051 if(base64Decode == NULL) {
1052 xmlSecError(XMLSEC_ERRORS_HERE,
1054 "xmlSecTransformCtxCreateAndPrepend",
1055 XMLSEC_ERRORS_R_XMLSEC_FAILED,
1056 XMLSEC_ERRORS_NO_MESSAGE);
1060 encCtx->cipherValueNode = cur;
1061 cur = xmlSecGetNextElementNode(cur->next);
1062 } else if((cur != NULL) && (xmlSecCheckNodeName(cur, xmlSecNodeCipherReference, xmlSecEncNs))) {
1063 /* don't need data from CipherReference node when we are encrypting */
1064 if(encCtx->operation == xmlSecTransformOperationDecrypt) {
1065 ret = xmlSecEncCtxCipherReferenceNodeRead(encCtx, cur);
1067 xmlSecError(XMLSEC_ERRORS_HERE,
1069 "xmlSecEncCtxCipherReferenceNodeRead",
1070 XMLSEC_ERRORS_R_XMLSEC_FAILED,
1072 xmlSecErrorsSafeString(xmlSecNodeGetName(cur)));
1076 cur = xmlSecGetNextElementNode(cur->next);
1080 xmlSecError(XMLSEC_ERRORS_HERE,
1082 xmlSecErrorsSafeString(xmlSecNodeGetName(cur)),
1083 XMLSEC_ERRORS_R_UNEXPECTED_NODE,
1084 XMLSEC_ERRORS_NO_MESSAGE);
1091 xmlSecEncCtxCipherReferenceNodeRead(xmlSecEncCtxPtr encCtx, xmlNodePtr node) {
1096 xmlSecAssert2(encCtx != NULL, -1);
1097 xmlSecAssert2(node != NULL, -1);
1099 /* first read the optional uri attr and check that we can process it */
1100 uri = xmlGetProp(node, xmlSecAttrURI);
1101 ret = xmlSecTransformCtxSetUri(&(encCtx->transformCtx), uri, node);
1103 xmlSecError(XMLSEC_ERRORS_HERE,
1105 "xmlSecTransformCtxSetUri",
1106 XMLSEC_ERRORS_R_XMLSEC_FAILED,
1108 xmlSecErrorsSafeString(uri));
1114 cur = xmlSecGetNextElementNode(node->children);
1116 /* the only one node is optional Transforms node */
1117 if((cur != NULL) && (xmlSecCheckNodeName(cur, xmlSecNodeTransforms, xmlSecEncNs))) {
1118 ret = xmlSecTransformCtxNodesListRead(&(encCtx->transformCtx), cur,
1119 xmlSecTransformUsageDSigTransform);
1121 xmlSecError(XMLSEC_ERRORS_HERE,
1123 "xmlSecTransformCtxNodesListRead",
1124 XMLSEC_ERRORS_R_XMLSEC_FAILED,
1126 xmlSecErrorsSafeString(xmlSecNodeGetName(encCtx->encMethodNode)));
1129 cur = xmlSecGetNextElementNode(cur->next);
1132 /* if there is something left than it's an error */
1134 xmlSecError(XMLSEC_ERRORS_HERE,
1136 xmlSecErrorsSafeString(xmlSecNodeGetName(cur)),
1137 XMLSEC_ERRORS_R_UNEXPECTED_NODE,
1138 XMLSEC_ERRORS_NO_MESSAGE);
1145 * xmlSecEncCtxDebugDump:
1146 * @encCtx: the pointer to <enc:EncryptedData/> processing context.
1147 * @output: the pointer to output FILE.
1149 * Prints the debug information about @encCtx to @output.
1152 xmlSecEncCtxDebugDump(xmlSecEncCtxPtr encCtx, FILE* output) {
1153 xmlSecAssert(encCtx != NULL);
1154 xmlSecAssert(output != NULL);
1156 switch(encCtx->mode) {
1157 case xmlEncCtxModeEncryptedData:
1158 if(encCtx->operation == xmlSecTransformOperationEncrypt) {
1159 fprintf(output, "= DATA ENCRYPTION CONTEXT\n");
1161 fprintf(output, "= DATA DECRYPTION CONTEXT\n");
1164 case xmlEncCtxModeEncryptedKey:
1165 if(encCtx->operation == xmlSecTransformOperationEncrypt) {
1166 fprintf(output, "= KEY ENCRYPTION CONTEXT\n");
1168 fprintf(output, "= KEY DECRYPTION CONTEXT\n");
1172 fprintf(output, "== Status: %s\n",
1173 (encCtx->resultReplaced) ? "replaced" : "not-replaced" );
1175 fprintf(output, "== flags: 0x%08x\n", encCtx->flags);
1176 fprintf(output, "== flags2: 0x%08x\n", encCtx->flags2);
1178 if(encCtx->id != NULL) {
1179 fprintf(output, "== Id: \"%s\"\n", encCtx->id);
1181 if(encCtx->type != NULL) {
1182 fprintf(output, "== Type: \"%s\"\n", encCtx->type);
1184 if(encCtx->mimeType != NULL) {
1185 fprintf(output, "== MimeType: \"%s\"\n", encCtx->mimeType);
1187 if(encCtx->encoding != NULL) {
1188 fprintf(output, "== Encoding: \"%s\"\n", encCtx->encoding);
1190 if(encCtx->recipient != NULL) {
1191 fprintf(output, "== Recipient: \"%s\"\n", encCtx->recipient);
1193 if(encCtx->carriedKeyName != NULL) {
1194 fprintf(output, "== CarriedKeyName: \"%s\"\n", encCtx->carriedKeyName);
1197 fprintf(output, "== Key Info Read Ctx:\n");
1198 xmlSecKeyInfoCtxDebugDump(&(encCtx->keyInfoReadCtx), output);
1200 fprintf(output, "== Key Info Write Ctx:\n");
1201 xmlSecKeyInfoCtxDebugDump(&(encCtx->keyInfoWriteCtx), output);
1203 fprintf(output, "== Encryption Transform Ctx:\n");
1204 xmlSecTransformCtxDebugDump(&(encCtx->transformCtx), output);
1206 if(encCtx->encMethod != NULL) {
1207 fprintf(output, "== Encryption Method:\n");
1208 xmlSecTransformDebugDump(encCtx->encMethod, output);
1211 if(encCtx->encKey != NULL) {
1212 fprintf(output, "== Encryption Key:\n");
1213 xmlSecKeyDebugDump(encCtx->encKey, output);
1216 if((encCtx->result != NULL) &&
1217 (xmlSecBufferGetData(encCtx->result) != NULL) &&
1218 (encCtx->resultBase64Encoded != 0)) {
1220 fprintf(output, "== Result - start buffer:\n");
1221 fwrite(xmlSecBufferGetData(encCtx->result),
1222 xmlSecBufferGetSize(encCtx->result), 1,
1224 fprintf(output, "\n== Result - end buffer\n");
1229 * xmlSecEncCtxDebugXmlDump:
1230 * @encCtx: the pointer to <enc:EncryptedData/> processing context.
1231 * @output: the pointer to output FILE.
1233 * Prints the debug information about @encCtx to @output in XML format.
1236 xmlSecEncCtxDebugXmlDump(xmlSecEncCtxPtr encCtx, FILE* output) {
1237 xmlSecAssert(encCtx != NULL);
1238 xmlSecAssert(output != NULL);
1240 switch(encCtx->mode) {
1241 case xmlEncCtxModeEncryptedData:
1242 if(encCtx->operation == xmlSecTransformOperationEncrypt) {
1243 fprintf(output, "<DataEncryptionContext ");
1245 fprintf(output, "<DataDecryptionContext ");
1248 case xmlEncCtxModeEncryptedKey:
1249 if(encCtx->operation == xmlSecTransformOperationEncrypt) {
1250 fprintf(output, "<KeyEncryptionContext ");
1252 fprintf(output, "<KeyDecryptionContext ");
1256 fprintf(output, "status=\"%s\" >\n", (encCtx->resultReplaced) ? "replaced" : "not-replaced" );
1258 fprintf(output, "<Flags>%08x</Flags>\n", encCtx->flags);
1259 fprintf(output, "<Flags2>%08x</Flags2>\n", encCtx->flags2);
1261 fprintf(output, "<Id>");
1262 xmlSecPrintXmlString(output, encCtx->id);
1263 fprintf(output, "</Id>");
1265 fprintf(output, "<Type>");
1266 xmlSecPrintXmlString(output, encCtx->type);
1267 fprintf(output, "</Type>");
1269 fprintf(output, "<MimeType>");
1270 xmlSecPrintXmlString(output, encCtx->mimeType);
1271 fprintf(output, "</MimeType>");
1273 fprintf(output, "<Encoding>");
1274 xmlSecPrintXmlString(output, encCtx->encoding);
1275 fprintf(output, "</Encoding>");
1277 fprintf(output, "<Recipient>");
1278 xmlSecPrintXmlString(output, encCtx->recipient);
1279 fprintf(output, "</Recipient>");
1281 fprintf(output, "<CarriedKeyName>");
1282 xmlSecPrintXmlString(output, encCtx->carriedKeyName);
1283 fprintf(output, "</CarriedKeyName>");
1285 fprintf(output, "<KeyInfoReadCtx>\n");
1286 xmlSecKeyInfoCtxDebugXmlDump(&(encCtx->keyInfoReadCtx), output);
1287 fprintf(output, "</KeyInfoReadCtx>\n");
1289 fprintf(output, "<KeyInfoWriteCtx>\n");
1290 xmlSecKeyInfoCtxDebugXmlDump(&(encCtx->keyInfoWriteCtx), output);
1291 fprintf(output, "</KeyInfoWriteCtx>\n");
1293 fprintf(output, "<EncryptionTransformCtx>\n");
1294 xmlSecTransformCtxDebugXmlDump(&(encCtx->transformCtx), output);
1295 fprintf(output, "</EncryptionTransformCtx>\n");
1297 if(encCtx->encMethod != NULL) {
1298 fprintf(output, "<EncryptionMethod>\n");
1299 xmlSecTransformDebugXmlDump(encCtx->encMethod, output);
1300 fprintf(output, "</EncryptionMethod>\n");
1303 if(encCtx->encKey != NULL) {
1304 fprintf(output, "<EncryptionKey>\n");
1305 xmlSecKeyDebugXmlDump(encCtx->encKey, output);
1306 fprintf(output, "</EncryptionKey>\n");
1309 if((encCtx->result != NULL) &&
1310 (xmlSecBufferGetData(encCtx->result) != NULL) &&
1311 (encCtx->resultBase64Encoded != 0)) {
1313 fprintf(output, "<Result>");
1314 fwrite(xmlSecBufferGetData(encCtx->result),
1315 xmlSecBufferGetSize(encCtx->result), 1,
1317 fprintf(output, "</Result>\n");
1320 switch(encCtx->mode) {
1321 case xmlEncCtxModeEncryptedData:
1322 if(encCtx->operation == xmlSecTransformOperationEncrypt) {
1323 fprintf(output, "</DataEncryptionContext>\n");
1325 fprintf(output, "</DataDecryptionContext>\n");
1328 case xmlEncCtxModeEncryptedKey:
1329 if(encCtx->operation == xmlSecTransformOperationEncrypt) {
1330 fprintf(output, "</KeyEncryptionContext>\n");
1332 fprintf(output, "</KeyDecryptionContext>\n");
1338 #endif /* XMLSEC_NO_XMLENC */