Coverage Report

Created: 2026-07-16 06:49

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