Coverage Report

Created: 2026-01-17 06:17

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/xmlsec/src/xmlenc.c
Line
Count
Source
1
/*
2
 * XML Security Library (http://www.aleksey.com/xmlsec).
3
 *
4
 *
5
 * This is free software; see the Copyright file in the source
6
 * distribution for precise wording.
7
 *
8
 * Copyright (C) 2002-2024 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
#include "cast_helpers.h"
40
41
static int      xmlSecEncCtxEncDataNodeRead             (xmlSecEncCtxPtr encCtx,
42
                                                         xmlNodePtr node);
43
static int      xmlSecEncCtxEncDataNodeWrite            (xmlSecEncCtxPtr encCtx);
44
static int      xmlSecEncCtxCipherDataNodeRead          (xmlSecEncCtxPtr encCtx,
45
                                                         xmlNodePtr node);
46
static int      xmlSecEncCtxCipherReferenceNodeRead     (xmlSecEncCtxPtr encCtx,
47
                                                         xmlNodePtr node);
48
49
static void     xmlSecEncCtxMarkAsFailed                (xmlSecEncCtxPtr encCtx,
50
                                                         xmlSecEncFailureReason failureReason);
51
52
/* The ID attribute in XMLEnc is 'Id' */
53
static const xmlChar*           xmlSecEncIds[] = { BAD_CAST "Id", NULL };
54
55
56
/**
57
 * xmlSecEncCtxCreate:
58
 * @keysMngr:           the pointer to keys manager.
59
 *
60
 * Creates &lt;enc:EncryptedData/&gt; element processing context.
61
 * The caller is responsible for destroying returned object by calling
62
 * #xmlSecEncCtxDestroy function.
63
 *
64
 * Returns: pointer to newly allocated context object or NULL if an error
65
 * occurs.
66
 */
67
xmlSecEncCtxPtr
68
0
xmlSecEncCtxCreate(xmlSecKeysMngrPtr keysMngr) {
69
0
    xmlSecEncCtxPtr encCtx;
70
0
    int ret;
71
72
0
    encCtx = (xmlSecEncCtxPtr) xmlMalloc(sizeof(xmlSecEncCtx));
73
0
    if(encCtx == NULL) {
74
0
        xmlSecMallocError(sizeof(xmlSecEncCtx), NULL);
75
0
        return(NULL);
76
0
    }
77
78
0
    ret = xmlSecEncCtxInitialize(encCtx, keysMngr);
79
0
    if(ret < 0) {
80
0
        xmlSecInternalError("xmlSecEncCtxInitialize", NULL);
81
0
        xmlSecEncCtxDestroy(encCtx);
82
0
        return(NULL);
83
0
    }
84
0
    return(encCtx);
85
0
}
86
87
/**
88
 * xmlSecEncCtxDestroy:
89
 * @encCtx:             the pointer to &lt;enc:EncryptedData/&gt; processing context.
90
 *
91
 * Destroy context object created with #xmlSecEncCtxCreate function.
92
 */
93
void
94
0
xmlSecEncCtxDestroy(xmlSecEncCtxPtr encCtx) {
95
0
    xmlSecAssert(encCtx != NULL);
96
97
0
    xmlSecEncCtxFinalize(encCtx);
98
0
    xmlFree(encCtx);
99
0
}
100
101
static void
102
0
xmlSecEncCtxSetDefaults(xmlSecEncCtxPtr encCtx) {
103
0
    xmlSecAssert(encCtx != NULL);
104
105
0
    encCtx->keyInfoReadCtx.mode = xmlSecKeyInfoModeRead;
106
107
    /* it's not wise to write private key :) */
108
0
    encCtx->keyInfoWriteCtx.mode = xmlSecKeyInfoModeWrite;
109
0
    encCtx->keyInfoWriteCtx.keyReq.keyType = xmlSecKeyDataTypePublic;
110
0
}
111
112
/**
113
 * xmlSecEncCtxInitialize:
114
 * @encCtx:             the pointer to &lt;enc:EncryptedData/&gt; processing context.
115
 * @keysMngr:           the pointer to keys manager.
116
 *
117
 * Initializes &lt;enc:EncryptedData/&gt; element processing context.
118
 * The caller is responsible for cleaning up returned object by calling
119
 * #xmlSecEncCtxFinalize function.
120
 *
121
 * Returns: 0 on success or a negative value if an error occurs.
122
 */
123
int
124
0
xmlSecEncCtxInitialize(xmlSecEncCtxPtr encCtx, xmlSecKeysMngrPtr keysMngr) {
125
0
    int ret;
126
127
0
    xmlSecAssert2(encCtx != NULL, -1);
128
129
0
    memset(encCtx, 0, sizeof(xmlSecEncCtx));
130
131
    /* initialize key info */
132
0
    ret = xmlSecKeyInfoCtxInitialize(&(encCtx->keyInfoReadCtx), keysMngr);
133
0
    if(ret < 0) {
134
0
        xmlSecInternalError("xmlSecKeyInfoCtxInitialize", NULL);
135
0
        return(-1);
136
0
    }
137
138
0
    ret = xmlSecKeyInfoCtxInitialize(&(encCtx->keyInfoWriteCtx), keysMngr);
139
0
    if(ret < 0) {
140
0
        xmlSecInternalError("xmlSecKeyInfoCtxInitialize", NULL);
141
0
        return(-1);
142
0
    }
143
144
    /* initializes transforms encCtx */
145
0
    ret = xmlSecTransformCtxInitialize(&(encCtx->transformCtx));
146
0
    if(ret < 0) {
147
0
        xmlSecInternalError("xmlSecTransformCtxInitialize", NULL);
148
0
        return(-1);
149
0
    }
150
151
0
    xmlSecEncCtxSetDefaults(encCtx);
152
0
    return(0);
153
0
}
154
155
/**
156
 * xmlSecEncCtxFinalize:
157
 * @encCtx:             the pointer to &lt;enc:EncryptedData/&gt; processing context.
158
 *
159
 * Cleans up @encCtx object.
160
 */
161
void
162
0
xmlSecEncCtxFinalize(xmlSecEncCtxPtr encCtx) {
163
0
    xmlSecAssert(encCtx != NULL);
164
165
0
    xmlSecEncCtxReset(encCtx);
166
167
0
    xmlSecTransformCtxFinalize(&(encCtx->transformCtx));
168
0
    xmlSecKeyInfoCtxFinalize(&(encCtx->keyInfoReadCtx));
169
0
    xmlSecKeyInfoCtxFinalize(&(encCtx->keyInfoWriteCtx));
170
171
0
    memset(encCtx, 0, sizeof(xmlSecEncCtx));
172
0
}
173
174
/**
175
 * xmlSecEncCtxReset:
176
 * @encCtx:             the pointer to &lt;enc:EncryptedData/&gt; processing context.
177
 *
178
 * Resets @encCtx object, user settings are not touched.
179
 */
180
void
181
0
xmlSecEncCtxReset(xmlSecEncCtxPtr encCtx) {
182
0
    xmlSecAssert(encCtx != NULL);
183
184
0
    xmlSecTransformCtxReset(&(encCtx->transformCtx));
185
0
    xmlSecKeyInfoCtxReset(&(encCtx->keyInfoReadCtx));
186
0
    xmlSecKeyInfoCtxReset(&(encCtx->keyInfoWriteCtx));
187
188
0
    encCtx->operation           = xmlSecTransformOperationNone;
189
0
    encCtx->result              = NULL;
190
0
    encCtx->resultBase64Encoded = 0;
191
0
    encCtx->resultReplaced      = 0;
192
0
    encCtx->encMethod           = NULL;
193
194
0
    if (encCtx->replacedNodeList != NULL) {
195
0
                xmlFreeNodeList(encCtx->replacedNodeList);
196
0
        encCtx->replacedNodeList = NULL;
197
0
    }
198
199
0
    if(encCtx->encKey != NULL) {
200
0
        xmlSecKeyDestroy(encCtx->encKey);
201
0
        encCtx->encKey = NULL;
202
0
    }
203
204
0
    if(encCtx->id != NULL) {
205
0
        xmlFree(encCtx->id);
206
0
        encCtx->id = NULL;
207
0
    }
208
209
0
    if(encCtx->type != NULL) {
210
0
        xmlFree(encCtx->type);
211
0
        encCtx->type = NULL;
212
0
    }
213
214
0
    if(encCtx->mimeType != NULL) {
215
0
        xmlFree(encCtx->mimeType);
216
0
        encCtx->mimeType = NULL;
217
0
    }
218
219
0
    if(encCtx->encoding != NULL) {
220
0
        xmlFree(encCtx->encoding);
221
0
        encCtx->encoding = NULL;
222
0
    }
223
224
0
    if(encCtx->recipient != NULL) {
225
0
        xmlFree(encCtx->recipient);
226
0
        encCtx->recipient = NULL;
227
0
    }
228
229
0
    if(encCtx->carriedKeyName != NULL) {
230
0
        xmlFree(encCtx->carriedKeyName);
231
0
        encCtx->carriedKeyName = NULL;
232
0
    }
233
234
0
    encCtx->encDataNode = encCtx->encMethodNode =
235
0
    encCtx->keyInfoNode = encCtx->cipherValueNode = NULL;
236
237
0
    xmlSecEncCtxSetDefaults(encCtx);
238
0
}
239
240
/**
241
 * xmlSecEncCtxCopyUserPref:
242
 * @dst:                the pointer to destination context.
243
 * @src:                the pointer to source context.
244
 *
245
 * Copies user preference from @src context to @dst.
246
 *
247
 * Returns: 0 on success or a negative value if an error occurs.
248
 */
249
int
250
0
xmlSecEncCtxCopyUserPref(xmlSecEncCtxPtr dst, xmlSecEncCtxPtr src) {
251
0
    int ret;
252
253
0
    xmlSecAssert2(dst != NULL, -1);
254
0
    xmlSecAssert2(src != NULL, -1);
255
256
0
    dst->userData       = src->userData;
257
0
    dst->flags          = src->flags;
258
0
    dst->flags2         = src->flags2;
259
0
    dst->defEncMethodId = src->defEncMethodId;
260
0
    dst->mode           = src->mode;
261
262
0
    ret = xmlSecTransformCtxCopyUserPref(&(dst->transformCtx), &(src->transformCtx));
263
0
    if(ret < 0) {
264
0
        xmlSecInternalError("xmlSecTransformCtxCopyUserPref", NULL);
265
0
        return(-1);
266
0
    }
267
268
0
    ret = xmlSecKeyInfoCtxCopyUserPref(&(dst->keyInfoReadCtx), &(src->keyInfoReadCtx));
269
0
    if(ret < 0) {
270
0
        xmlSecInternalError("xmlSecKeyInfoCtxCopyUserPref", NULL);
271
0
        return(-1);
272
0
    }
273
274
0
    ret = xmlSecKeyInfoCtxCopyUserPref(&(dst->keyInfoWriteCtx), &(src->keyInfoWriteCtx));
275
0
    if(ret < 0) {
276
0
        xmlSecInternalError("xmlSecKeyInfoCtxCopyUserPref", NULL);
277
0
        return(-1);
278
0
    }
279
280
0
    return(0);
281
0
}
282
283
/**
284
 * xmlSecEncCtxBinaryEncrypt:
285
 * @encCtx:             the pointer to &lt;enc:EncryptedData/&gt; processing context.
286
 * @tmpl:               the pointer to &lt;enc:EncryptedData/&gt; template node.
287
 * @data:               the pointer for binary buffer.
288
 * @dataSize:           the @data buffer size.
289
 *
290
 * Encrypts @data according to template @tmpl.
291
 *
292
 * Returns: 0 on success or a negative value if an error occurs.
293
 */
294
int
295
xmlSecEncCtxBinaryEncrypt(xmlSecEncCtxPtr encCtx, xmlNodePtr tmpl,
296
0
                          const xmlSecByte* data, xmlSecSize dataSize) {
297
0
    int ret;
298
299
0
    xmlSecAssert2(encCtx != NULL, -1);
300
0
    xmlSecAssert2(encCtx->result == NULL, -1);
301
0
    xmlSecAssert2(tmpl != NULL, -1);
302
0
    xmlSecAssert2(data != NULL, -1);
303
304
    /* initialize context and add ID atributes to the list of known ids */
305
0
    encCtx->operation = xmlSecTransformOperationEncrypt;
306
0
    xmlSecAddIDs(tmpl->doc, tmpl, xmlSecEncIds);
307
308
    /* read the template and set encryption method, key, etc. */
309
0
    ret = xmlSecEncCtxEncDataNodeRead(encCtx, tmpl);
310
0
    if(ret < 0) {
311
0
        xmlSecInternalError("xmlSecEncCtxEncDataNodeRead", NULL);
312
0
        return(-1);
313
0
    }
314
315
0
    ret = xmlSecTransformCtxBinaryExecute(&(encCtx->transformCtx), data, dataSize);
316
0
    if(ret < 0) {
317
0
        xmlSecInternalError2("xmlSecTransformCtxBinaryExecute", NULL,
318
0
                             "dataSize=" XMLSEC_SIZE_FMT,  dataSize);
319
0
        return(-1);
320
0
    }
321
322
0
    encCtx->result = encCtx->transformCtx.result;
323
0
    xmlSecAssert2(encCtx->result != NULL, -1);
324
325
0
    ret = xmlSecEncCtxEncDataNodeWrite(encCtx);
326
0
    if(ret < 0) {
327
0
        xmlSecInternalError("xmlSecEncCtxEncDataNodeWrite", NULL);
328
0
        return(-1);
329
0
    }
330
0
    return(0);
331
0
}
332
333
/**
334
 * xmlSecEncCtxXmlEncrypt:
335
 * @encCtx:             the pointer to &lt;enc:EncryptedData/&gt; processing context.
336
 * @tmpl:               the pointer to &lt;enc:EncryptedData/&gt; template node.
337
 * @node:               the pointer to node for encryption.
338
 *
339
 * Encrypts @node according to template @tmpl. If requested, @node is replaced
340
 * with result &lt;enc:EncryptedData/&gt; node.
341
 *
342
 * Returns: 0 on success or a negative value if an error occurs.
343
 */
344
int
345
0
xmlSecEncCtxXmlEncrypt(xmlSecEncCtxPtr encCtx, xmlNodePtr tmpl, xmlNodePtr node) {
346
0
    xmlOutputBufferPtr output;
347
0
    int ret;
348
349
0
    xmlSecAssert2(encCtx != NULL, -1);
350
0
    xmlSecAssert2(encCtx->result == NULL, -1);
351
0
    xmlSecAssert2(tmpl != NULL, -1);
352
0
    xmlSecAssert2(node != NULL, -1);
353
0
    xmlSecAssert2(node->doc != NULL, -1);
354
355
    /* initialize context and add ID atributes to the list of known ids */
356
0
    encCtx->operation = xmlSecTransformOperationEncrypt;
357
0
    xmlSecAddIDs(tmpl->doc, tmpl, xmlSecEncIds);
358
359
    /* read the template and set encryption method, key, etc. */
360
0
    ret = xmlSecEncCtxEncDataNodeRead(encCtx, tmpl);
361
0
    if(ret < 0) {
362
0
        xmlSecInternalError("xmlSecEncCtxEncDataNodeRead", NULL);
363
0
        return(-1);
364
0
    }
365
366
0
    ret = xmlSecTransformCtxPrepare(&(encCtx->transformCtx), xmlSecTransformDataTypeBin);
367
0
    if(ret < 0) {
368
0
        xmlSecInternalError("xmlSecTransformCtxPrepare(TypeBin)", NULL);
369
0
        return(-1);
370
0
    }
371
372
0
    xmlSecAssert2(encCtx->transformCtx.first != NULL, -1);
373
0
    output = xmlSecTransformCreateOutputBuffer(encCtx->transformCtx.first,
374
0
                                                &(encCtx->transformCtx));
375
0
    if(output == NULL) {
376
0
        xmlSecInternalError("xmlSecTransformCreateOutputBuffer",
377
0
                            xmlSecTransformGetName(encCtx->transformCtx.first));
378
0
        return(-1);
379
0
    }
380
381
    /* push data thru */
382
0
    if((encCtx->type != NULL) && xmlStrEqual(encCtx->type, xmlSecTypeEncElement)) {
383
        /* get the content of the node */
384
0
        xmlNodeDumpOutput(output, node->doc, node, 0, 0, NULL);
385
0
    } else if((encCtx->type != NULL) && xmlStrEqual(encCtx->type, xmlSecTypeEncContent)) {
386
0
        xmlNodePtr cur;
387
388
        /* get the content of the nodes childs */
389
0
        for(cur = node->children; cur != NULL; cur = cur->next) {
390
0
            xmlNodeDumpOutput(output, node->doc, cur, 0, 0, NULL);
391
0
        }
392
0
    } else {
393
0
        xmlSecInvalidStringTypeError("encryption type", encCtx->type,
394
0
                "supported encryption type", NULL);
395
0
        (void)xmlOutputBufferClose(output);
396
0
        return(-1);
397
0
    }
398
399
    /* close the buffer and flush everything */
400
0
    ret = xmlOutputBufferClose(output);
401
0
    if(ret < 0) {
402
0
        xmlSecXmlError("xmlOutputBufferClose", NULL);
403
0
        return(-1);
404
0
    }
405
406
0
    encCtx->result = encCtx->transformCtx.result;
407
0
    xmlSecAssert2(encCtx->result != NULL, -1);
408
409
0
    ret = xmlSecEncCtxEncDataNodeWrite(encCtx);
410
0
    if(ret < 0) {
411
0
        xmlSecInternalError("xmlSecEncCtxEncDataNodeWrite", NULL);
412
0
        return(-1);
413
0
    }
414
415
    /* now we need to update our original document */
416
0
    if((encCtx->type != NULL) && xmlStrEqual(encCtx->type, xmlSecTypeEncElement)) {
417
        /* check if we need to return the replaced node */
418
0
        if((encCtx->flags & XMLSEC_ENC_RETURN_REPLACED_NODE) != 0) {
419
0
            ret = xmlSecReplaceNodeAndReturn(node, tmpl, &(encCtx->replacedNodeList));
420
0
            if(ret < 0) {
421
0
                xmlSecInternalError("xmlSecReplaceNodeAndReturn",
422
0
                                    xmlSecNodeGetName(node));
423
0
                return(-1);
424
0
            }
425
0
        } else {
426
0
            ret = xmlSecReplaceNode(node, tmpl);
427
0
            if(ret < 0) {
428
0
                xmlSecInternalError("xmlSecReplaceNode",
429
0
                                    xmlSecNodeGetName(node));
430
0
                return(-1);
431
0
            }
432
0
        }
433
0
        encCtx->resultReplaced = 1;
434
0
    } else if((encCtx->type != NULL) && xmlStrEqual(encCtx->type, xmlSecTypeEncContent)) {
435
        /* check if we need to return the replaced node */
436
0
        if((encCtx->flags & XMLSEC_ENC_RETURN_REPLACED_NODE) != 0) {
437
0
            ret = xmlSecReplaceContentAndReturn(node, tmpl, &(encCtx->replacedNodeList));
438
0
            if(ret < 0) {
439
0
                xmlSecInternalError("xmlSecReplaceContentAndReturn",
440
0
                                    xmlSecNodeGetName(node));
441
0
                return(-1);
442
0
            }
443
0
        } else {
444
0
            ret = xmlSecReplaceContent(node, tmpl);
445
0
            if(ret < 0) {
446
0
                xmlSecInternalError("xmlSecReplaceContent",
447
0
                                    xmlSecNodeGetName(node));
448
0
                return(-1);
449
0
            }
450
0
        }
451
0
        encCtx->resultReplaced = 1;
452
0
    } else {
453
        /* we should've caught this error before */
454
0
        xmlSecInvalidStringTypeError("encryption type", encCtx->type,
455
0
                "supported encryption type", NULL);
456
0
        return(-1);
457
0
    }
458
    /* done */
459
0
    return(0);
460
0
}
461
462
/**
463
 * xmlSecEncCtxUriEncrypt:
464
 * @encCtx:             the pointer to &lt;enc:EncryptedData/&gt; processing context.
465
 * @tmpl:               the pointer to &lt;enc:EncryptedData/&gt; template node.
466
 * @uri:                the URI.
467
 *
468
 * Encrypts data from @uri according to template @tmpl.
469
 *
470
 * Returns: 0 on success or a negative value if an error occurs.
471
 */
472
int
473
0
xmlSecEncCtxUriEncrypt(xmlSecEncCtxPtr encCtx, xmlNodePtr tmpl, const xmlChar *uri) {
474
0
    int ret;
475
476
0
    xmlSecAssert2(encCtx != NULL, -1);
477
0
    xmlSecAssert2(encCtx->result == NULL, -1);
478
0
    xmlSecAssert2(tmpl != NULL, -1);
479
0
    xmlSecAssert2(uri != NULL, -1);
480
481
    /* initialize context and add ID atributes to the list of known ids */
482
0
    encCtx->operation = xmlSecTransformOperationEncrypt;
483
0
    xmlSecAddIDs(tmpl->doc, tmpl, xmlSecEncIds);
484
485
    /* we need to add input uri transform first */
486
0
    ret = xmlSecTransformCtxSetUri(&(encCtx->transformCtx), uri, tmpl);
487
0
    if(ret < 0) {
488
0
        xmlSecInternalError2("xmlSecTransformCtxSetUri", NULL,
489
0
                             "uri=%s", xmlSecErrorsSafeString(uri));
490
0
        return(-1);
491
0
    }
492
493
    /* read the template and set encryption method, key, etc. */
494
0
    ret = xmlSecEncCtxEncDataNodeRead(encCtx, tmpl);
495
0
    if(ret < 0) {
496
0
        xmlSecInternalError("xmlSecEncCtxEncDataNodeRead", NULL);
497
0
        return(-1);
498
0
    }
499
500
    /* encrypt the data */
501
0
    ret = xmlSecTransformCtxExecute(&(encCtx->transformCtx), tmpl->doc);
502
0
    if(ret < 0) {
503
0
        xmlSecInternalError("xmlSecTransformCtxExecute", NULL);
504
0
        return(-1);
505
0
    }
506
507
0
    encCtx->result = encCtx->transformCtx.result;
508
0
    xmlSecAssert2(encCtx->result != NULL, -1);
509
510
0
    ret = xmlSecEncCtxEncDataNodeWrite(encCtx);
511
0
    if(ret < 0) {
512
0
        xmlSecInternalError("xmlSecEncCtxEncDataNodeWrite", NULL);
513
0
        return(-1);
514
0
    }
515
516
0
    return(0);
517
0
}
518
519
/**
520
 * xmlSecEncCtxDecrypt:
521
 * @encCtx:             the pointer to &lt;enc:EncryptedData/&gt; processing context.
522
 * @node:               the pointer to &lt;enc:EncryptedData/&gt; node.
523
 *
524
 * Decrypts @node and if necessary replaces @node with decrypted data.
525
 *
526
 * Returns: 0 on success or a negative value if an error occurs.
527
 */
528
int
529
0
xmlSecEncCtxDecrypt(xmlSecEncCtxPtr encCtx, xmlNodePtr node) {
530
0
    xmlSecBufferPtr buffer;
531
0
    int ret;
532
533
0
    xmlSecAssert2(encCtx != NULL, -1);
534
0
    xmlSecAssert2(node != NULL, -1);
535
536
    /* decrypt */
537
0
    buffer = xmlSecEncCtxDecryptToBuffer(encCtx, node);
538
0
    if(buffer == NULL) {
539
0
        xmlSecInternalError("xmlSecEncCtxDecryptToBuffer", NULL);
540
0
        return(-1);
541
0
    }
542
543
    /* replace original node if requested */
544
0
    if((encCtx->type != NULL) && xmlStrEqual(encCtx->type, xmlSecTypeEncElement)) {
545
        /* check if we need to return the replaced node */
546
0
        if((encCtx->flags & XMLSEC_ENC_RETURN_REPLACED_NODE) != 0) {
547
0
                ret = xmlSecReplaceNodeBufferAndReturn(node, xmlSecBufferGetData(buffer),  xmlSecBufferGetSize(buffer), &(encCtx->replacedNodeList));
548
0
                if(ret < 0) {
549
0
                    xmlSecInternalError("xmlSecReplaceNodeBufferAndReturn",
550
0
                                        xmlSecNodeGetName(node));
551
0
                    return(-1);
552
0
                }
553
0
        } else {
554
0
                ret = xmlSecReplaceNodeBuffer(node, xmlSecBufferGetData(buffer),  xmlSecBufferGetSize(buffer));
555
0
                if(ret < 0) {
556
0
                    xmlSecInternalError("xmlSecReplaceNodeBuffer",
557
0
                                        xmlSecNodeGetName(node));
558
0
                    return(-1);
559
0
                }
560
0
        }
561
562
0
        encCtx->resultReplaced = 1;
563
0
    } else if((encCtx->type != NULL) && xmlStrEqual(encCtx->type, xmlSecTypeEncContent)) {
564
        /* replace the node with the buffer */
565
566
        /* check if we need to return the replaced node */
567
0
        if((encCtx->flags & XMLSEC_ENC_RETURN_REPLACED_NODE) != 0) {
568
0
                ret = xmlSecReplaceNodeBufferAndReturn(node, xmlSecBufferGetData(buffer), xmlSecBufferGetSize(buffer), &(encCtx->replacedNodeList));
569
0
                if(ret < 0) {
570
0
                    xmlSecInternalError("xmlSecReplaceNodeBufferAndReturn",
571
0
                                        xmlSecNodeGetName(node));
572
0
                    return(-1);
573
0
                }
574
0
        } else {
575
0
            ret = xmlSecReplaceNodeBuffer(node, xmlSecBufferGetData(buffer), xmlSecBufferGetSize(buffer));
576
0
                if(ret < 0) {
577
0
                    xmlSecInternalError("xmlSecReplaceNodeBuffer",
578
0
                                        xmlSecNodeGetName(node));
579
0
                    return(-1);
580
0
                }
581
0
        }
582
0
        encCtx->resultReplaced = 1;
583
0
    }
584
585
0
    return(0);
586
0
}
587
588
/**
589
 * xmlSecEncCtxDecryptToBuffer:
590
 * @encCtx:             the pointer to encryption processing context.
591
 * @node:               the pointer to &lt;enc:EncryptedData/&gt; node.
592
 *
593
 * Decrypts @node data to the result.
594
 *
595
 * Returns: a buffer with key on success or NULL if an error occurs.
596
 */
597
xmlSecBufferPtr
598
0
xmlSecEncCtxDecryptToBuffer(xmlSecEncCtxPtr encCtx, xmlNodePtr node) {
599
0
    xmlSecBufferPtr res = NULL;
600
0
    xmlChar* data = NULL;
601
0
    int ret;
602
603
0
    xmlSecAssert2(encCtx != NULL, NULL);
604
0
    xmlSecAssert2(encCtx->result == NULL, NULL);
605
0
    xmlSecAssert2(node != NULL, NULL);
606
607
    /* initialize context and add ID atributes to the list of known ids */
608
0
    encCtx->operation = xmlSecTransformOperationDecrypt;
609
0
    xmlSecAddIDs(node->doc, node, xmlSecEncIds);
610
611
0
    ret = xmlSecEncCtxEncDataNodeRead(encCtx, node);
612
0
    if(ret < 0) {
613
0
        xmlSecInternalError("xmlSecEncCtxEncDataNodeRead", NULL);
614
0
        goto done;
615
0
    }
616
617
    /* decrypt the data */
618
0
    if(encCtx->cipherValueNode != NULL) {
619
0
        data = xmlSecGetNodeContentAndTrim(encCtx->cipherValueNode);
620
0
        if(data == NULL) {
621
0
            xmlSecInvalidNodeContentError(encCtx->cipherValueNode, NULL, "empty");
622
0
            goto done;
623
0
        }
624
625
0
        ret = xmlSecTransformCtxBinaryExecute(&(encCtx->transformCtx), data, xmlSecStrlen(data));
626
0
        if(ret < 0) {
627
0
            xmlSecInternalError("xmlSecTransformCtxBinaryExecute", NULL);
628
0
            goto done;
629
0
        }
630
0
    } else {
631
0
        ret = xmlSecTransformCtxExecute(&(encCtx->transformCtx), node->doc);
632
0
        if(ret < 0) {
633
0
            xmlSecInternalError("xmlSecTransformCtxExecute", NULL);
634
0
            goto done;
635
0
        }
636
0
    }
637
638
    /* success  */
639
0
    res = encCtx->result = encCtx->transformCtx.result;
640
0
    xmlSecAssert2(encCtx->result != NULL, NULL);
641
642
0
done:
643
0
    if(data != NULL) {
644
0
        xmlFree(data);
645
0
    }
646
0
    return(res);
647
0
}
648
649
static int
650
0
xmlSecEncCtxEncDataNodeRead(xmlSecEncCtxPtr encCtx, xmlNodePtr node) {
651
0
    xmlNodePtr cur;
652
0
    int ret;
653
654
0
    xmlSecAssert2(encCtx != NULL, -1);
655
0
    xmlSecAssert2((encCtx->operation == xmlSecTransformOperationEncrypt) || (encCtx->operation == xmlSecTransformOperationDecrypt), -1);
656
0
    xmlSecAssert2(node != NULL, -1);
657
658
0
    switch(encCtx->mode) {
659
0
        case xmlEncCtxModeEncryptedData:
660
0
            if(!xmlSecCheckNodeName(node, xmlSecNodeEncryptedData, xmlSecEncNs)) {
661
0
                xmlSecInvalidNodeError(node, xmlSecNodeEncryptedData, NULL);
662
0
                return(-1);
663
0
            }
664
0
            break;
665
0
        case xmlEncCtxModeEncryptedKey:
666
0
            if(!xmlSecCheckNodeName(node, xmlSecNodeEncryptedKey, xmlSecEncNs)) {
667
0
                xmlSecInvalidNodeError(node, xmlSecNodeEncryptedKey, NULL);
668
0
                return(-1);
669
0
            }
670
0
            break;
671
0
    }
672
673
    /* first read node data */
674
0
    xmlSecAssert2(encCtx->id == NULL, -1);
675
0
    xmlSecAssert2(encCtx->type == NULL, -1);
676
0
    xmlSecAssert2(encCtx->mimeType == NULL, -1);
677
0
    xmlSecAssert2(encCtx->encoding == NULL, -1);
678
0
    xmlSecAssert2(encCtx->recipient == NULL, -1);
679
0
    xmlSecAssert2(encCtx->carriedKeyName == NULL, -1);
680
681
0
    encCtx->id = xmlGetProp(node, xmlSecAttrId);
682
0
    encCtx->type = xmlGetProp(node, xmlSecAttrType);
683
0
    encCtx->mimeType = xmlGetProp(node, xmlSecAttrMimeType);
684
0
    encCtx->encoding = xmlGetProp(node, xmlSecAttrEncoding);
685
0
    if(encCtx->mode == xmlEncCtxModeEncryptedKey) {
686
0
        encCtx->recipient = xmlGetProp(node, xmlSecAttrRecipient);
687
        /* todo: check recipient? */
688
0
    }
689
0
    cur = xmlSecGetNextElementNode(node->children);
690
691
    /* first node is optional EncryptionMethod, we'll read it later */
692
0
    xmlSecAssert2(encCtx->encMethodNode == NULL, -1);
693
0
    if((cur != NULL) && (xmlSecCheckNodeName(cur, xmlSecNodeEncryptionMethod, xmlSecEncNs))) {
694
0
        encCtx->encMethodNode = cur;
695
0
        cur = xmlSecGetNextElementNode(cur->next);
696
0
    }
697
698
    /* next node is optional KeyInfo, we'll process it later */
699
0
    xmlSecAssert2(encCtx->keyInfoNode == NULL, -1);
700
0
    if((cur != NULL) && (xmlSecCheckNodeName(cur, xmlSecNodeKeyInfo, xmlSecDSigNs))) {
701
0
        encCtx->keyInfoNode = cur;
702
0
        cur = xmlSecGetNextElementNode(cur->next);
703
0
    }
704
705
    /* next is required CipherData node */
706
0
    if((cur == NULL) || (!xmlSecCheckNodeName(cur, xmlSecNodeCipherData, xmlSecEncNs))) {
707
0
        xmlSecInvalidNodeError(cur, xmlSecNodeCipherData, NULL);
708
0
        return(-1);
709
0
    }
710
711
0
    ret = xmlSecEncCtxCipherDataNodeRead(encCtx, cur);
712
0
    if(ret < 0) {
713
0
        xmlSecInternalError("xmlSecEncCtxCipherDataNodeRead", NULL);
714
0
        return(-1);
715
0
    }
716
0
    cur = xmlSecGetNextElementNode(cur->next);
717
718
    /* next is optional EncryptionProperties node (we simply ignore it) */
719
0
    if((cur != NULL) && (xmlSecCheckNodeName(cur, xmlSecNodeEncryptionProperties, xmlSecEncNs))) {
720
0
        cur = xmlSecGetNextElementNode(cur->next);
721
0
    }
722
723
    /* there are more possible nodes for the <EncryptedKey> node */
724
0
    if(encCtx->mode == xmlEncCtxModeEncryptedKey) {
725
        /* next is optional ReferenceList node (we simply ignore it) */
726
0
        if((cur != NULL) && (xmlSecCheckNodeName(cur, xmlSecNodeReferenceList, xmlSecEncNs))) {
727
0
            cur = xmlSecGetNextElementNode(cur->next);
728
0
        }
729
730
        /* next is optional CarriedKeyName node (we simply ignore it) */
731
0
        if((cur != NULL) && (xmlSecCheckNodeName(cur, xmlSecNodeCarriedKeyName, xmlSecEncNs))) {
732
0
            encCtx->carriedKeyName = xmlSecGetNodeContentAndTrim(cur);
733
0
            if(encCtx->carriedKeyName == NULL) {
734
0
                xmlSecInvalidNodeContentError(cur, NULL, "empty");
735
0
                return(-1);
736
0
            }
737
            /* TODO: decode the name? */
738
0
            cur = xmlSecGetNextElementNode(cur->next);
739
0
        }
740
0
    }
741
742
    /* if there is something left than it's an error */
743
0
    if(cur != NULL) {
744
0
        xmlSecUnexpectedNodeError(cur,  NULL);
745
0
        return(-1);
746
0
    }
747
748
    /* now read the encryption method node */
749
0
    xmlSecAssert2(encCtx->encMethod == NULL, -1);
750
0
    if(encCtx->encMethodNode != NULL) {
751
0
        encCtx->encMethod = xmlSecTransformCtxNodeRead(&(encCtx->transformCtx), encCtx->encMethodNode,
752
0
                                                xmlSecTransformUsageEncryptionMethod);
753
0
        if(encCtx->encMethod == NULL) {
754
0
            xmlSecInternalError("xmlSecTransformCtxNodeRead",
755
0
                                xmlSecNodeGetName(encCtx->encMethodNode));
756
0
            return(-1);
757
0
        }
758
0
    } else if(encCtx->defEncMethodId != xmlSecTransformIdUnknown) {
759
0
        encCtx->encMethod = xmlSecTransformCtxCreateAndAppend(&(encCtx->transformCtx),
760
0
                                                              encCtx->defEncMethodId);
761
0
        if(encCtx->encMethod == NULL) {
762
0
            xmlSecInternalError("xmlSecTransformCtxCreateAndAppend",
763
0
                    xmlSecTransformKlassGetName(encCtx->defEncMethodId));
764
0
            return(-1);
765
0
        }
766
0
    } else {
767
0
        xmlSecInvalidDataError("encryption method not specified", NULL);
768
0
        return(-1);
769
0
    }
770
0
    encCtx->encMethod->operation = encCtx->operation;
771
0
    encCtx->keyInfoReadCtx.operation = encCtx->operation;
772
0
    encCtx->keyInfoWriteCtx.operation = encCtx->operation;
773
774
    /* we have encryption method, find key */
775
0
    ret = xmlSecTransformSetKeyReq(encCtx->encMethod, &(encCtx->keyInfoReadCtx.keyReq));
776
0
    if(ret < 0) {
777
0
        xmlSecInternalError("xmlSecTransformSetKeyReq",
778
0
                xmlSecTransformGetName(encCtx->encMethod));
779
0
        return(-1);
780
0
    }
781
782
    /* TODO: KeyInfo node != NULL and encKey != NULL */
783
0
    if((encCtx->encKey == NULL) && (encCtx->keyInfoReadCtx.keysMngr != NULL)
784
0
                        && (encCtx->keyInfoReadCtx.keysMngr->getKey != NULL)) {
785
0
        encCtx->encKey = (encCtx->keyInfoReadCtx.keysMngr->getKey)(encCtx->keyInfoNode,
786
0
                                                             &(encCtx->keyInfoReadCtx));
787
0
    }
788
789
    /* check that we have exactly what we want */
790
0
    if((encCtx->encKey == NULL) ||
791
0
       (!xmlSecKeyMatch(encCtx->encKey, NULL, &(encCtx->keyInfoReadCtx.keyReq)))) {
792
793
0
        xmlSecOtherError2(XMLSEC_ERRORS_R_KEY_NOT_FOUND, NULL,
794
0
                          "encMethod=%s",
795
0
                          xmlSecErrorsSafeString(xmlSecTransformGetName(encCtx->encMethod)));
796
0
        xmlSecEncCtxMarkAsFailed(encCtx, xmlSecEncFailureReasonKeyNotFound);
797
0
        return(-1);
798
0
    }
799
800
    /* set the key to the transform */
801
0
    ret = xmlSecTransformSetKey(encCtx->encMethod, encCtx->encKey);
802
0
    if(ret < 0) {
803
0
        xmlSecInternalError("xmlSecTransformSetKey",
804
0
                            xmlSecTransformGetName(encCtx->encMethod));
805
0
        return(-1);
806
0
    }
807
808
    /* if we need to write result to xml node then we need base64 encode it */
809
0
    if((encCtx->operation == xmlSecTransformOperationEncrypt) && (encCtx->cipherValueNode != NULL)) {
810
0
        xmlSecTransformPtr base64Encode;
811
812
        /* we need to add base64 encode transform */
813
0
        base64Encode = xmlSecTransformCtxCreateAndAppend(&(encCtx->transformCtx), xmlSecTransformBase64Id);
814
0
        if(base64Encode == NULL) {
815
0
            xmlSecInternalError("xmlSecTransformCtxCreateAndAppend", NULL);
816
0
            return(-1);
817
0
        }
818
0
        base64Encode->operation         = xmlSecTransformOperationEncode;
819
0
        encCtx->resultBase64Encoded     = 1;
820
0
    }
821
822
0
    return(0);
823
0
}
824
825
static int
826
0
xmlSecEncCtxEncDataNodeWrite(xmlSecEncCtxPtr encCtx) {
827
0
    int ret;
828
829
0
    xmlSecAssert2(encCtx != NULL, -1);
830
0
    xmlSecAssert2(encCtx->result != NULL, -1);
831
0
    xmlSecAssert2(encCtx->encKey != NULL, -1);
832
833
    /* write encrypted data to xml (if requested) */
834
0
    if(encCtx->cipherValueNode != NULL) {
835
0
        xmlSecByte* inBuf;
836
0
        xmlSecSize inSize;
837
0
        int inLen;
838
839
0
        inBuf = xmlSecBufferGetData(encCtx->result);
840
0
        inSize = xmlSecBufferGetSize(encCtx->result);
841
0
        xmlSecAssert2(inBuf != NULL, -1);
842
0
        XMLSEC_SAFE_CAST_SIZE_TO_INT(inSize, inLen, return(-1), NULL);
843
844
0
        xmlNodeSetContentLen(encCtx->cipherValueNode, inBuf, inLen);
845
0
        encCtx->resultReplaced = 1;
846
0
    }
847
848
    /* update &lt;enc:KeyInfo/&gt; node */
849
0
    if(encCtx->keyInfoNode != NULL) {
850
0
        ret = xmlSecKeyInfoNodeWrite(encCtx->keyInfoNode, encCtx->encKey, &(encCtx->keyInfoWriteCtx));
851
0
        if(ret < 0) {
852
0
            xmlSecInternalError("xmlSecKeyInfoNodeWrite", NULL);
853
0
            return(-1);
854
0
        }
855
0
    }
856
857
0
    return(0);
858
0
}
859
860
static int
861
0
xmlSecEncCtxCipherDataNodeRead(xmlSecEncCtxPtr encCtx, xmlNodePtr node) {
862
0
    xmlNodePtr cur;
863
0
    int ret;
864
865
0
    xmlSecAssert2(encCtx != NULL, -1);
866
0
    xmlSecAssert2(node != NULL, -1);
867
868
0
    cur = xmlSecGetNextElementNode(node->children);
869
870
    /* we either have CipherValue or CipherReference node  */
871
0
    xmlSecAssert2(encCtx->cipherValueNode == NULL, -1);
872
0
    if((cur != NULL) && (xmlSecCheckNodeName(cur, xmlSecNodeCipherValue, xmlSecEncNs))) {
873
        /* don't need data from CipherData node when we are encrypting */
874
0
        if(encCtx->operation == xmlSecTransformOperationDecrypt) {
875
0
            xmlSecTransformPtr base64Decode;
876
877
            /* we need to add base64 decode transform */
878
0
            base64Decode = xmlSecTransformCtxCreateAndPrepend(&(encCtx->transformCtx), xmlSecTransformBase64Id);
879
0
            if(base64Decode == NULL) {
880
0
                xmlSecInternalError("xmlSecTransformCtxCreateAndPrepend", NULL);
881
0
                return(-1);
882
0
            }
883
0
        }
884
0
        encCtx->cipherValueNode = cur;
885
0
        cur = xmlSecGetNextElementNode(cur->next);
886
0
    } else if((cur != NULL) && (xmlSecCheckNodeName(cur, xmlSecNodeCipherReference, xmlSecEncNs))) {
887
        /* don't need data from CipherReference node when we are encrypting */
888
0
        if(encCtx->operation == xmlSecTransformOperationDecrypt) {
889
0
            ret = xmlSecEncCtxCipherReferenceNodeRead(encCtx, cur);
890
0
            if(ret < 0) {
891
0
                xmlSecInternalError("xmlSecEncCtxCipherReferenceNodeRead",
892
0
                                    xmlSecNodeGetName(cur));
893
0
                return(-1);
894
0
            }
895
0
        }
896
0
        cur = xmlSecGetNextElementNode(cur->next);
897
0
    }
898
899
0
    if(cur != NULL) {
900
0
        xmlSecUnexpectedNodeError(cur,  NULL);
901
0
        return(-1);
902
0
    }
903
0
    return(0);
904
0
}
905
906
static int
907
0
xmlSecEncCtxCipherReferenceNodeRead(xmlSecEncCtxPtr encCtx, xmlNodePtr node) {
908
0
    xmlNodePtr cur;
909
0
    xmlChar* uri;
910
0
    int ret;
911
912
0
    xmlSecAssert2(encCtx != NULL, -1);
913
0
    xmlSecAssert2(node != NULL, -1);
914
915
    /* first read the optional uri attr and check that we can process it */
916
0
    uri = xmlGetProp(node, xmlSecAttrURI);
917
0
    ret = xmlSecTransformCtxSetUri(&(encCtx->transformCtx), uri, node);
918
0
    if(ret < 0) {
919
0
        xmlSecInternalError2("xmlSecTransformCtxSetUri", NULL,
920
0
                             "uri=%s", xmlSecErrorsSafeString(uri));
921
0
        xmlFree(uri);
922
0
        return(-1);
923
0
    }
924
0
    xmlFree(uri);
925
926
0
    cur = xmlSecGetNextElementNode(node->children);
927
928
    /* the only one node is optional Transforms node */
929
0
    if((cur != NULL) && (xmlSecCheckNodeName(cur, xmlSecNodeTransforms, xmlSecEncNs))) {
930
0
        ret = xmlSecTransformCtxNodesListRead(&(encCtx->transformCtx), cur,
931
0
                                    xmlSecTransformUsageDSigTransform);
932
0
        if(ret < 0) {
933
0
            xmlSecInternalError("xmlSecTransformCtxNodesListRead",
934
0
                                xmlSecNodeGetName(encCtx->encMethodNode));
935
0
            return(-1);
936
0
        }
937
0
        cur = xmlSecGetNextElementNode(cur->next);
938
0
    }
939
940
    /* if there is something left than it's an error */
941
0
    if(cur != NULL) {
942
0
        xmlSecUnexpectedNodeError(cur,  NULL);
943
0
        return(-1);
944
0
    }
945
0
    return(0);
946
0
}
947
948
static void
949
0
xmlSecEncCtxMarkAsFailed(xmlSecEncCtxPtr encCtx, xmlSecEncFailureReason failureReason) {
950
0
    xmlSecAssert(encCtx != NULL);
951
952
0
    if(encCtx->failureReason == xmlSecEncFailureReasonUnknown) {
953
0
        encCtx->failureReason = failureReason;
954
0
    }
955
0
}
956
957
/**
958
 * xmlSecEncCtxDebugDump:
959
 * @encCtx:             the pointer to &lt;enc:EncryptedData/&gt; processing context.
960
 * @output:             the pointer to output FILE.
961
 *
962
 * Prints the debug information about @encCtx to @output.
963
 */
964
void
965
0
xmlSecEncCtxDebugDump(xmlSecEncCtxPtr encCtx, FILE* output) {
966
0
    xmlSecAssert(encCtx != NULL);
967
0
    xmlSecAssert(output != NULL);
968
969
0
    switch(encCtx->mode) {
970
0
        case xmlEncCtxModeEncryptedData:
971
0
            if(encCtx->operation == xmlSecTransformOperationEncrypt) {
972
0
                fprintf(output, "= DATA ENCRYPTION CONTEXT\n");
973
0
            } else {
974
0
                fprintf(output, "= DATA DECRYPTION CONTEXT\n");
975
0
            }
976
0
            break;
977
0
        case xmlEncCtxModeEncryptedKey:
978
0
            if(encCtx->operation == xmlSecTransformOperationEncrypt) {
979
0
                fprintf(output, "= KEY ENCRYPTION CONTEXT\n");
980
0
            } else {
981
0
                fprintf(output, "= KEY DECRYPTION CONTEXT\n");
982
0
            }
983
0
            break;
984
0
    }
985
0
    fprintf(output, "== Failure reason: %s\n", xmlSecEncCtxGetFailureReasonString(encCtx->failureReason));
986
987
0
    fprintf(output, "== Status: %s\n",
988
0
            (encCtx->resultReplaced) ? "replaced" : "not-replaced" );
989
990
991
0
    fprintf(output, "== flags: 0x%08x\n", encCtx->flags);
992
0
    fprintf(output, "== flags2: 0x%08x\n", encCtx->flags2);
993
994
0
    if(encCtx->id != NULL) {
995
0
        fprintf(output, "== Id: \"%s\"\n", encCtx->id);
996
0
    }
997
0
    if(encCtx->type != NULL) {
998
0
        fprintf(output, "== Type: \"%s\"\n", encCtx->type);
999
0
    }
1000
0
    if(encCtx->mimeType != NULL) {
1001
0
        fprintf(output, "== MimeType: \"%s\"\n", encCtx->mimeType);
1002
0
    }
1003
0
    if(encCtx->encoding != NULL) {
1004
0
        fprintf(output, "== Encoding: \"%s\"\n", encCtx->encoding);
1005
0
    }
1006
0
    if(encCtx->recipient != NULL) {
1007
0
        fprintf(output, "== Recipient: \"%s\"\n", encCtx->recipient);
1008
0
    }
1009
0
    if(encCtx->carriedKeyName != NULL) {
1010
0
        fprintf(output, "== CarriedKeyName: \"%s\"\n", encCtx->carriedKeyName);
1011
0
    }
1012
1013
0
    fprintf(output, "== Key Info Read Ctx:\n");
1014
0
    xmlSecKeyInfoCtxDebugDump(&(encCtx->keyInfoReadCtx), output);
1015
1016
0
    fprintf(output, "== Key Info Write Ctx:\n");
1017
0
    xmlSecKeyInfoCtxDebugDump(&(encCtx->keyInfoWriteCtx), output);
1018
1019
0
    fprintf(output, "== Encryption Transform Ctx:\n");
1020
0
    xmlSecTransformCtxDebugDump(&(encCtx->transformCtx), output);
1021
1022
0
    if(encCtx->encMethod != NULL) {
1023
0
        fprintf(output, "== Encryption Method:\n");
1024
0
        xmlSecTransformDebugDump(encCtx->encMethod, output);
1025
0
    }
1026
1027
0
    if(encCtx->encKey != NULL) {
1028
0
        fprintf(output, "== Encryption Key:\n");
1029
0
        xmlSecKeyDebugDump(encCtx->encKey, output);
1030
0
    }
1031
1032
0
    if((encCtx->result != NULL) &&
1033
0
       (xmlSecBufferGetData(encCtx->result) != NULL) &&
1034
0
       (encCtx->resultBase64Encoded != 0)) {
1035
1036
0
        fprintf(output, "== Result - start buffer:\n");
1037
0
        (void)fwrite(xmlSecBufferGetData(encCtx->result),
1038
0
                     xmlSecBufferGetSize(encCtx->result), 1,
1039
0
                     output);
1040
0
        fprintf(output, "\n== Result - end buffer\n");
1041
0
    }
1042
0
}
1043
1044
/**
1045
 * xmlSecEncCtxDebugXmlDump:
1046
 * @encCtx:             the pointer to &lt;enc:EncryptedData/&gt; processing context.
1047
 * @output:             the pointer to output FILE.
1048
 *
1049
 * Prints the debug information about @encCtx to @output in XML format.
1050
 */
1051
void
1052
0
xmlSecEncCtxDebugXmlDump(xmlSecEncCtxPtr encCtx, FILE* output) {
1053
0
    xmlSecAssert(encCtx != NULL);
1054
0
    xmlSecAssert(output != NULL);
1055
1056
0
    switch(encCtx->mode) {
1057
0
        case xmlEncCtxModeEncryptedData:
1058
0
            if(encCtx->operation == xmlSecTransformOperationEncrypt) {
1059
0
                fprintf(output, "<DataEncryptionContext ");
1060
0
            } else {
1061
0
                fprintf(output, "<DataDecryptionContext ");
1062
0
            }
1063
0
            break;
1064
0
        case xmlEncCtxModeEncryptedKey:
1065
0
            if(encCtx->operation == xmlSecTransformOperationEncrypt) {
1066
0
                fprintf(output, "<KeyEncryptionContext ");
1067
0
            } else {
1068
0
                fprintf(output, "<KeyDecryptionContext ");
1069
0
            }
1070
0
            break;
1071
0
    }
1072
0
    fprintf(output, " status=\"%s\"\n", (encCtx->resultReplaced) ? "replaced" : "not-replaced" );
1073
0
    fprintf(output, " failureReason=\"%s\"\n", xmlSecEncCtxGetFailureReasonString(encCtx->failureReason));
1074
0
    fprintf(output, ">\n");
1075
1076
0
    fprintf(output, "<Flags>%08x</Flags>\n", encCtx->flags);
1077
0
    fprintf(output, "<Flags2>%08x</Flags2>\n", encCtx->flags2);
1078
1079
0
    fprintf(output, "<Id>");
1080
0
    xmlSecPrintXmlString(output, encCtx->id);
1081
0
    fprintf(output, "</Id>");
1082
1083
0
    fprintf(output, "<Type>");
1084
0
    xmlSecPrintXmlString(output, encCtx->type);
1085
0
    fprintf(output, "</Type>");
1086
1087
0
    fprintf(output, "<MimeType>");
1088
0
    xmlSecPrintXmlString(output, encCtx->mimeType);
1089
0
    fprintf(output, "</MimeType>");
1090
1091
0
    fprintf(output, "<Encoding>");
1092
0
    xmlSecPrintXmlString(output, encCtx->encoding);
1093
0
    fprintf(output, "</Encoding>");
1094
1095
0
    fprintf(output, "<Recipient>");
1096
0
    xmlSecPrintXmlString(output, encCtx->recipient);
1097
0
    fprintf(output, "</Recipient>");
1098
1099
0
    fprintf(output, "<CarriedKeyName>");
1100
0
    xmlSecPrintXmlString(output, encCtx->carriedKeyName);
1101
0
    fprintf(output, "</CarriedKeyName>");
1102
1103
0
    fprintf(output, "<KeyInfoReadCtx>\n");
1104
0
    xmlSecKeyInfoCtxDebugXmlDump(&(encCtx->keyInfoReadCtx), output);
1105
0
    fprintf(output, "</KeyInfoReadCtx>\n");
1106
1107
0
    fprintf(output, "<KeyInfoWriteCtx>\n");
1108
0
    xmlSecKeyInfoCtxDebugXmlDump(&(encCtx->keyInfoWriteCtx), output);
1109
0
    fprintf(output, "</KeyInfoWriteCtx>\n");
1110
1111
0
    fprintf(output, "<EncryptionTransformCtx>\n");
1112
0
    xmlSecTransformCtxDebugXmlDump(&(encCtx->transformCtx), output);
1113
0
    fprintf(output, "</EncryptionTransformCtx>\n");
1114
1115
0
    if(encCtx->encMethod != NULL) {
1116
0
        fprintf(output, "<EncryptionMethod>\n");
1117
0
        xmlSecTransformDebugXmlDump(encCtx->encMethod, output);
1118
0
        fprintf(output, "</EncryptionMethod>\n");
1119
0
    }
1120
1121
0
    if(encCtx->encKey != NULL) {
1122
0
        fprintf(output, "<EncryptionKey>\n");
1123
0
        xmlSecKeyDebugXmlDump(encCtx->encKey, output);
1124
0
        fprintf(output, "</EncryptionKey>\n");
1125
0
    }
1126
1127
0
    if((encCtx->result != NULL) &&
1128
0
       (xmlSecBufferGetData(encCtx->result) != NULL) &&
1129
0
       (encCtx->resultBase64Encoded != 0)) {
1130
1131
0
        fprintf(output, "<Result>");
1132
0
        (void)fwrite(xmlSecBufferGetData(encCtx->result),
1133
0
                     xmlSecBufferGetSize(encCtx->result), 1,
1134
0
                     output);
1135
0
        fprintf(output, "</Result>\n");
1136
0
    }
1137
1138
0
    switch(encCtx->mode) {
1139
0
        case xmlEncCtxModeEncryptedData:
1140
0
            if(encCtx->operation == xmlSecTransformOperationEncrypt) {
1141
0
                fprintf(output, "</DataEncryptionContext>\n");
1142
0
            } else {
1143
0
                fprintf(output, "</DataDecryptionContext>\n");
1144
0
            }
1145
0
            break;
1146
0
        case xmlEncCtxModeEncryptedKey:
1147
0
            if(encCtx->operation == xmlSecTransformOperationEncrypt) {
1148
0
                fprintf(output, "</KeyEncryptionContext>\n");
1149
0
            } else {
1150
0
                fprintf(output, "</KeyDecryptionContext>\n");
1151
0
            }
1152
0
            break;
1153
0
    }
1154
0
}
1155
1156
/****************************************************************************************
1157
 *
1158
 * Generate key (used in DerivedKey and AgreementMethod nodes processing)
1159
 *
1160
 ***************************************************************************************/
1161
1162
static xmlSecKeyPtr
1163
0
xmlSecEncCtxGenerateKey(xmlSecEncCtxPtr encCtx, xmlSecKeyDataId keyId, xmlSecKeyInfoCtxPtr keyInfoCtx) {
1164
0
    xmlSecKeyPtr key;
1165
0
    xmlSecByte * keyData;
1166
0
    xmlSecSize keySize;
1167
0
    int ret;
1168
1169
0
    xmlSecAssert2(encCtx != NULL, NULL);
1170
0
    xmlSecAssert2(encCtx->encMethod != NULL, NULL);
1171
0
    xmlSecAssert2(encCtx->result == NULL, NULL);
1172
1173
    /* we only support binary keys for now */
1174
0
    ret = xmlSecTransformCtxBinaryExecute(&(encCtx->transformCtx), NULL, 0);
1175
0
    if((ret < 0) || (encCtx->transformCtx.result == NULL)) {
1176
0
        xmlSecInternalError("xmlSecTransformCtxBinaryExecute", xmlSecTransformGetName(encCtx->encMethod));
1177
0
        return(NULL);
1178
0
    }
1179
0
    encCtx->result = encCtx->transformCtx.result;
1180
1181
0
    keyData = xmlSecBufferGetData(encCtx->result);
1182
0
    keySize = xmlSecBufferGetSize(encCtx->result);
1183
0
    if((keyData == NULL) || (keySize <= 0)) {
1184
0
        xmlSecInternalError("xmlSecTransformCtxBinaryExecute(no data)", xmlSecTransformGetName(encCtx->encMethod));
1185
0
        return(NULL);
1186
0
    }
1187
1188
0
    key = xmlSecKeyCreate();
1189
0
    if(key == NULL) {
1190
0
        xmlSecInternalError("xmlSecKeyCreate", xmlSecTransformGetName(encCtx->encMethod));
1191
0
        return(NULL);
1192
0
    }
1193
1194
0
    ret = xmlSecKeyDataBinRead(keyId, key, keyData, keySize, keyInfoCtx);
1195
0
    if(ret < 0) {
1196
0
        xmlSecInternalError("xmlSecKeyDataBinRead",
1197
0
                            xmlSecKeyDataKlassGetName(keyId));
1198
0
        xmlSecKeyDestroy(key);
1199
0
        return(NULL);
1200
0
    }
1201
1202
    /* success */
1203
0
    return(key);
1204
0
}
1205
1206
/**
1207
 * xmlSecEncCtxDerivedKeyGenerate:
1208
 * @encCtx:             the pointer to encryption processing context.
1209
 * @keyId:              the expected key id, the actual derived key might have a different id.
1210
 * @node:               the pointer to &lt;enc11:DerivedKey/&gt; node.
1211
 * @keyInfoCtx:         the pointer to the "parent" key info context.
1212
 *
1213
 * Generates (derives) key from @node (https://www.w3.org/TR/xmlenc-core1/#sec-DerivedKey):
1214
 * <programlisting><![CDATA[
1215
 *  <element name="DerivedKey" type="xenc11:DerivedKeyType"/>
1216
 *  <complexType name="DerivedKeyType">
1217
 *      <sequence>
1218
 *          <element ref="xenc11:KeyDerivationMethod" minOccurs="0"/>
1219
 *          <element ref="xenc:ReferenceList" minOccurs="0"/>
1220
 *          <element name="DerivedKeyName" type="string" minOccurs="0"/>
1221
 *          <element name="MasterKeyName" type="string" minOccurs="0"/>
1222
 *      </sequence>
1223
 *      <attribute name="Recipient" type="string" use="optional"/>
1224
 *      <attribute name="Id" type="ID" use="optional"/>
1225
 *      <attribute name="Type" type="anyURI" use="optional"/>
1226
 *  </complexType>
1227
 *
1228
 *  <element name="KeyDerivationMethod" type="xenc:KeyDerivationMethodType"/>
1229
 *  <complexType name="KeyDerivationMethodType">
1230
 *      <sequence>
1231
 *          <any namespace="##any" minOccurs="0" maxOccurs="unbounded"/>
1232
 *      </sequence>
1233
 *      <attribute name="Algorithm" type="anyURI" use="required"/>
1234
 *  </complexType>
1235
 * ]]></programlisting>
1236
 *
1237
 * Returns: the derived key on success or NULL  if an error occurs.
1238
 */
1239
xmlSecKeyPtr
1240
0
xmlSecEncCtxDerivedKeyGenerate(xmlSecEncCtxPtr encCtx, xmlSecKeyDataId keyId, xmlNodePtr node, xmlSecKeyInfoCtxPtr keyInfoCtx) {
1241
0
    xmlNodePtr cur;
1242
0
    xmlChar* masterKeyName = NULL;
1243
0
    xmlChar* derivedKeyName = NULL;
1244
0
    xmlSecKeyPtr key = NULL;
1245
0
    xmlSecKeyPtr res = NULL;
1246
0
    int ret;
1247
1248
0
    xmlSecAssert2(encCtx != NULL, NULL);
1249
0
    xmlSecAssert2(encCtx->encMethod == NULL, NULL);
1250
0
    xmlSecAssert2(node != NULL, NULL);
1251
0
    xmlSecAssert2(keyInfoCtx != NULL, NULL);
1252
1253
    /* initialize context and add ID atributes to the list of known ids */
1254
0
    encCtx->operation = keyInfoCtx->operation;
1255
0
    xmlSecAddIDs(node->doc, node, xmlSecEncIds);
1256
1257
    /* first read the children */
1258
0
    cur = xmlSecGetNextElementNode(node->children);
1259
1260
    /* TODO: read the Type attribute as a hint for the desired key type / size
1261
     * (https://github.com/lsh123/xmlsec/issues/515) */
1262
1263
    /* KeyDerivationMethod is an optional element that describes the key derivation algorithm applied to the master (underlying)
1264
     * key material. If the element is absent, the key derivation algorithm must be known by the recipient or the recipient's key
1265
     * derivation will fail.
1266
     *
1267
     * We don't have a pre-defined kd algorithm, so if KDM node is missing, we fail.
1268
     * Algorithm IS REQUIRED.
1269
     */
1270
0
    if((cur == NULL) || (!xmlSecCheckNodeName(cur, xmlSecNodeKeyDerivationMethod, xmlSecEnc11Ns))) {
1271
0
        xmlSecInvalidNodeError(cur, xmlSecNodeKeyDerivationMethod, NULL);
1272
0
        goto done;
1273
0
    }
1274
1275
0
    encCtx->encMethod = xmlSecTransformCtxNodeRead(&(encCtx->transformCtx), cur, xmlSecTransformUsageKeyDerivationMethod);
1276
0
    if(encCtx->encMethod == NULL) {
1277
0
        xmlSecInternalError("xmlSecTransformCtxNodeRead", xmlSecNodeGetName(cur));
1278
0
        goto done;
1279
0
    }
1280
    /* expected key size is determined by the requirements from the uplevel key info */
1281
0
    encCtx->encMethod->expectedOutputSize = keyInfoCtx->keyReq.keyBitsSize / 8;
1282
0
    encCtx->encMethod->operation = encCtx->operation;
1283
0
    encCtx->keyInfoReadCtx.operation = encCtx->operation;
1284
0
    encCtx->keyInfoWriteCtx.operation = encCtx->operation;
1285
1286
    /* next node */
1287
0
    cur = xmlSecGetNextElementNode(cur->next);
1288
1289
    /* second node is optional ReferenceList, simply skip it for now */
1290
0
    if((cur != NULL) && (xmlSecCheckNodeName(cur, xmlSecNodeReferenceList, xmlSecEncNs))) {
1291
        /* next node */
1292
0
        cur = xmlSecGetNextElementNode(cur->next);
1293
0
    }
1294
1295
    /* third node is optional DerivedKeyName */
1296
0
    if((cur != NULL) && (xmlSecCheckNodeName(cur, xmlSecNodeDerivedKeyName, xmlSecEnc11Ns))) {
1297
0
        derivedKeyName = xmlSecGetNodeContentAndTrim(cur);
1298
0
        if(derivedKeyName == NULL) {
1299
0
            xmlSecInvalidNodeContentError(cur, NULL, "empty");
1300
0
            goto done;
1301
0
        }
1302
1303
        /* next node */
1304
0
        cur = xmlSecGetNextElementNode(cur->next);
1305
0
    }
1306
1307
    /* forth node is optional MasterKeyName */
1308
0
    if((cur != NULL) && (xmlSecCheckNodeName(cur, xmlSecNodeMasterKeyName, xmlSecEnc11Ns))) {
1309
0
        masterKeyName = xmlSecGetNodeContentAndTrim(cur);
1310
0
        if(masterKeyName == NULL) {
1311
0
            xmlSecInvalidNodeContentError(cur, NULL, "empty");
1312
0
            goto done;
1313
0
        }
1314
        /* next node */
1315
0
        cur = xmlSecGetNextElementNode(cur->next);
1316
0
    }
1317
1318
    /* if there is something left than it's an error */
1319
0
    if(cur != NULL) {
1320
0
        xmlSecUnexpectedNodeError(cur,  NULL);
1321
0
        goto done;
1322
0
    }
1323
1324
    /* get master key */
1325
0
    ret = xmlSecTransformSetKeyReq(encCtx->encMethod, &(encCtx->keyInfoReadCtx.keyReq));
1326
0
    if(ret < 0) {
1327
0
        xmlSecInternalError("xmlSecTransformSetKeyReq", xmlSecTransformGetName(encCtx->encMethod));
1328
0
        goto done;
1329
0
    }
1330
0
    if((encCtx->encKey == NULL) && (encCtx->keyInfoReadCtx.keysMngr != NULL)) {
1331
0
        encCtx->encKey = xmlSecKeysMngrFindKey(encCtx->keyInfoReadCtx.keysMngr, masterKeyName, &(encCtx->keyInfoReadCtx));
1332
0
    }
1333
0
    if((encCtx->encKey == NULL) || (!xmlSecKeyMatch(encCtx->encKey, NULL, &(encCtx->keyInfoReadCtx.keyReq)))) {
1334
0
        xmlSecOtherError2(XMLSEC_ERRORS_R_KEY_NOT_FOUND, NULL,
1335
0
            "encMethod=%s", xmlSecErrorsSafeString(xmlSecTransformGetName(encCtx->encMethod)));
1336
0
        xmlSecEncCtxMarkAsFailed(encCtx, xmlSecEncFailureReasonKeyNotFound);
1337
0
        return(NULL);
1338
0
    }
1339
0
    ret = xmlSecTransformSetKey(encCtx->encMethod, encCtx->encKey);
1340
0
    if(ret < 0) {
1341
0
        xmlSecInternalError("xmlSecTransformSetKey", xmlSecTransformGetName(encCtx->encMethod));
1342
0
        return(NULL);
1343
0
    }
1344
1345
    /* let's get the derive key! */
1346
0
    key = xmlSecEncCtxGenerateKey(encCtx, keyId, keyInfoCtx);
1347
0
    if(key == NULL) {
1348
0
        xmlSecInternalError("xmlSecEncCtxGenerateKey", NULL);
1349
0
        goto done;
1350
0
    }
1351
1352
    /* set the key name if we have one */
1353
0
    if(derivedKeyName != NULL) {
1354
0
        ret = xmlSecKeySetName(key, derivedKeyName);
1355
0
        if(ret < 0) {
1356
0
            xmlSecInternalError("xmlSecKeySetName", NULL);
1357
0
            goto done;
1358
0
        }
1359
0
    }
1360
1361
    /* success */
1362
0
    res = key;
1363
0
    key = NULL;
1364
1365
0
done:
1366
0
    if(masterKeyName != NULL) {
1367
0
        xmlFree(masterKeyName);
1368
0
    }
1369
0
    if(derivedKeyName != NULL) {
1370
0
        xmlFree(derivedKeyName);
1371
0
    }
1372
0
    if(key != NULL) {
1373
0
        xmlSecKeyDestroy(key);
1374
0
    }
1375
0
    return(res);
1376
0
}
1377
1378
/**
1379
 * xmlSecEncCtxAgreementMethodGenerate:
1380
 * @encCtx:             the pointer to encryption processing context.
1381
 * @keyId:              the expected key id, the actual derived key might have a different id.
1382
 * @node:               the pointer to &lt;enc:AgreementMethod/&gt; node.
1383
 * @keyInfoCtx:         the pointer to the "parent" key info context.
1384
 *
1385
 * Generates (derives) key from @node (https://www.w3.org/TR/xmlenc-core1/#sec-AgreementMethod):
1386
 *
1387
 * <programlisting><![CDATA[
1388
 *  <element name="AgreementMethod" type="xenc:AgreementMethodType"/>
1389
 *  <complexType name="AgreementMethodType" mixed="true">
1390
 *      <sequence>
1391
 *          <element name="KA-Nonce" minOccurs="0" type="base64Binary"/>
1392
 *          <!-- <element ref="ds:DigestMethod" minOccurs="0"/> -->
1393
 *          <any namespace="##other" minOccurs="0" maxOccurs="unbounded"/>
1394
 *          <element name="OriginatorKeyInfo" minOccurs="0" type="ds:KeyInfoType"/>
1395
 *          <element name="RecipientKeyInfo" minOccurs="0" type="ds:KeyInfoType"/>
1396
 *      </sequence>
1397
 *      <attribute name="Algorithm" type="anyURI" use="required"/>
1398
 *  </complexType>
1399
 * ]]></programlisting>
1400
 *
1401
 * Returns: the generated key on success or NULL if an error occurs.
1402
 */
1403
xmlSecKeyPtr
1404
0
xmlSecEncCtxAgreementMethodGenerate(xmlSecEncCtxPtr encCtx, xmlSecKeyDataId keyId, xmlNodePtr node, xmlSecKeyInfoCtxPtr keyInfoCtx) {
1405
0
    xmlSecKeyPtr key;
1406
1407
0
    xmlSecAssert2(encCtx != NULL, NULL);
1408
0
    xmlSecAssert2(encCtx->encMethod == NULL, NULL);
1409
0
    xmlSecAssert2(node != NULL, NULL);
1410
0
    xmlSecAssert2(keyInfoCtx != NULL, NULL);
1411
1412
    /* initialize context and add ID atributes to the list of known ids */
1413
0
    encCtx->operation = keyInfoCtx->operation;
1414
0
    xmlSecAddIDs(node->doc, node, xmlSecEncIds);
1415
1416
    /* the AgreementMethod node is the transform node itself */
1417
0
    encCtx->transformCtx.parentKeyInfoCtx = keyInfoCtx;
1418
0
    encCtx->encMethod = xmlSecTransformCtxNodeRead(&(encCtx->transformCtx), node, xmlSecTransformUsageAgreementMethod);
1419
0
    if(encCtx->encMethod == NULL) {
1420
0
        xmlSecInternalError("xmlSecTransformCtxNodeRead", xmlSecNodeGetName(node));
1421
0
        return(NULL);
1422
0
    }
1423
1424
    /* expected key size is determined by the requirements from the uplevel key info */
1425
0
    encCtx->encMethod->expectedOutputSize = keyInfoCtx->keyReq.keyBitsSize / 8;
1426
0
    encCtx->encMethod->operation = encCtx->operation;
1427
0
    encCtx->keyInfoReadCtx.operation = encCtx->operation;
1428
0
    encCtx->keyInfoWriteCtx.operation = encCtx->operation;
1429
1430
    /* ecdh transform doesn't require a key, skip SetKeyReq(), FindKey(), and SetKey() */
1431
1432
    /* let's generate the key! */
1433
0
    key = xmlSecEncCtxGenerateKey(encCtx, keyId, keyInfoCtx);
1434
0
    if(key == NULL) {
1435
0
        xmlSecInternalError("xmlSecEncCtxGenerateKey", NULL);
1436
0
        return(NULL);
1437
0
    }
1438
1439
    /* success */
1440
0
    return(key);
1441
0
}
1442
1443
int
1444
0
xmlSecEncCtxAgreementMethodXmlWrite(xmlSecEncCtxPtr encCtx, xmlNodePtr node, xmlSecKeyInfoCtxPtr keyInfoCtx) {
1445
0
    int ret;
1446
1447
0
    xmlSecAssert2(encCtx != NULL, -1);
1448
0
    xmlSecAssert2(encCtx->encMethod == NULL, -1);
1449
0
    xmlSecAssert2(node != NULL, -1);
1450
0
    xmlSecAssert2(keyInfoCtx != NULL, -1);
1451
1452
    /* initialize context and add ID atributes to the list of known ids */
1453
0
    encCtx->operation = keyInfoCtx->operation;
1454
0
    xmlSecAddIDs(node->doc, node, xmlSecEncIds);
1455
1456
    /* the AgreementMethod node is the transform node itself */
1457
0
    encCtx->transformCtx.parentKeyInfoCtx = keyInfoCtx;
1458
0
    encCtx->encMethod = xmlSecTransformCtxNodeRead(&(encCtx->transformCtx), node, xmlSecTransformUsageAgreementMethod);
1459
0
    if(encCtx->encMethod == NULL) {
1460
0
        xmlSecInternalError("xmlSecTransformCtxNodeRead", xmlSecNodeGetName(node));
1461
0
        return(-1);
1462
0
    }
1463
1464
    /* write */
1465
0
    if(encCtx->encMethod->id->writeNode != NULL) {
1466
0
        ret = encCtx->encMethod->id->writeNode(encCtx->encMethod, node, &(encCtx->transformCtx));
1467
0
        if(ret < 0) {
1468
0
            xmlSecInternalError("writeNode", xmlSecNodeGetName(node));
1469
0
            return(-1);
1470
0
        }
1471
0
    }
1472
1473
0
    return(0);
1474
0
}
1475
1476
/**
1477
 * xmlSecEncCtxGetFailureReasonString:
1478
 * @failureReason:   the failure reason.
1479
 *
1480
 * Gets failure reason as a string.
1481
 *
1482
 * Returns failure reason as a string.
1483
 */
1484
const char*
1485
0
xmlSecEncCtxGetFailureReasonString(xmlSecEncFailureReason failureReason) {
1486
0
    switch(failureReason) {
1487
0
    case xmlSecEncFailureReasonKeyNotFound:
1488
0
        return "KEY-NOT-FOUND";
1489
1490
0
    case xmlSecEncFailureReasonUnknown:
1491
0
    default:
1492
0
        return "UNKNOWN";
1493
0
    }
1494
0
}
1495
#endif /* XMLSEC_NO_XMLENC */