1 /*
2  * XML Security Library (http://www.aleksey.com/xmlsec).
3  *
4  *
5  * This is free software; see Copyright file in the source
6  * distribution for preciese wording.
7  *
8  * Copyright (C) 2002-2016 Aleksey Sanin <aleksey@aleksey.com>. All Rights Reserved.
9  */
10 /**
11  * SECTION:keyinfo
12  * @Short_description: &lt;dsig:KeyInfo/&gt; node parser functions.
13  * @Stability: Stable
14  *
15  *
16  * [KeyInfo](https://www.w3.org/TR/xmldsig-core/#sec-KeyInfo) is an
17  * optional element that enables the recipient(s) to obtain
18  * the key needed to validate the signature.  KeyInfo may contain keys,
19  * names, certificates and other public key management information, such as
20  * in-band key distribution or key agreement data.
21  *
22  * Schema Definition:
23  *
24  * |[<!-- language="XML" -->
25  *  <element name="KeyInfo" type="ds:KeyInfoType"/>
26  *  <complexType name="KeyInfoType" mixed="true">
27  *    <choice maxOccurs="unbounded">
28  *       <element ref="ds:KeyName"/>
29  *       <element ref="ds:KeyValue"/>
30  *       <element ref="ds:RetrievalMethod"/>
31  *       <element ref="ds:X509Data"/>
32  *       <element ref="ds:PGPData"/>
33  *       <element ref="ds:SPKIData"/>
34  *       <element ref="ds:MgmtData"/>
35  *       <any processContents="lax" namespace="##other"/>
36  *       <!-- (1,1) elements from (0,unbounded) namespaces -->
37  *    </choice>
38  *    <attribute name="Id" type="ID" use="optional"/>
39  *  </complexType>
40  * ]|
41  *
42  * DTD:
43  *
44  * |[<!-- language="XML" -->
45  * <!ELEMENT KeyInfo (#PCDATA|KeyName|KeyValue|RetrievalMethod|
46  *                    X509Data|PGPData|SPKIData|MgmtData %KeyInfo.ANY;)* >
47  * <!ATTLIST KeyInfo  Id  ID   #IMPLIED >
48  * ]|
49  */
50 
51 #include "globals.h"
52 
53 #include <stdlib.h>
54 #include <string.h>
55 
56 #include <libxml/tree.h>
57 
58 #include <xmlsec/xmlsec.h>
59 #include <xmlsec/xmltree.h>
60 #include <xmlsec/base64.h>
61 #include <xmlsec/keys.h>
62 #include <xmlsec/keysmngr.h>
63 #include <xmlsec/transforms.h>
64 #include <xmlsec/xmlenc.h>
65 #include <xmlsec/keyinfo.h>
66 #include <xmlsec/errors.h>
67 
68 
69 /**************************************************************************
70  *
71  * High-level functions
72  *
73  *************************************************************************/
74 /**
75  * xmlSecKeyInfoNodeRead:
76  * @keyInfoNode:        the pointer to <dsig:KeyInfo/> node.
77  * @key:                the pointer to result key object.
78  * @keyInfoCtx:         the pointer to <dsig:KeyInfo/> element processing context.
79  *
80  * Parses the <dsig:KeyInfo/> element @keyInfoNode, extracts the key data
81  * and stores into @key.
82  *
83  * Returns: 0 on success or -1 if an error occurs.
84  */
85 int
xmlSecKeyInfoNodeRead(xmlNodePtr keyInfoNode,xmlSecKeyPtr key,xmlSecKeyInfoCtxPtr keyInfoCtx)86 xmlSecKeyInfoNodeRead(xmlNodePtr keyInfoNode, xmlSecKeyPtr key, xmlSecKeyInfoCtxPtr keyInfoCtx) {
87     const xmlChar* nodeName;
88     const xmlChar* nodeNs;
89     xmlSecKeyDataId dataId;
90     xmlNodePtr cur;
91     int ret;
92 
93     xmlSecAssert2(keyInfoNode != NULL, -1);
94     xmlSecAssert2(key != NULL, -1);
95     xmlSecAssert2(keyInfoCtx != NULL, -1);
96     xmlSecAssert2(keyInfoCtx->mode == xmlSecKeyInfoModeRead, -1);
97 
98     for(cur = xmlSecGetNextElementNode(keyInfoNode->children);
99         (cur != NULL) &&
100         (((keyInfoCtx->flags & XMLSEC_KEYINFO_FLAGS_DONT_STOP_ON_KEY_FOUND) != 0) ||
101          (xmlSecKeyIsValid(key) == 0) ||
102          (xmlSecKeyMatch(key, NULL, &(keyInfoCtx->keyReq)) == 0));
103         cur = xmlSecGetNextElementNode(cur->next)) {
104 
105         /* find data id */
106         nodeName = cur->name;
107         nodeNs = xmlSecGetNodeNsHref(cur);
108 
109         /* use global list only if we don't have a local one */
110         if(xmlSecPtrListGetSize(&(keyInfoCtx->enabledKeyData)) > 0) {
111             dataId = xmlSecKeyDataIdListFindByNode(&(keyInfoCtx->enabledKeyData),
112                             nodeName, nodeNs, xmlSecKeyDataUsageKeyInfoNodeRead);
113         } else {
114             dataId = xmlSecKeyDataIdListFindByNode(xmlSecKeyDataIdsGet(),
115                             nodeName, nodeNs, xmlSecKeyDataUsageKeyInfoNodeRead);
116         }
117         if(dataId != xmlSecKeyDataIdUnknown) {
118             /* read data node */
119             ret = xmlSecKeyDataXmlRead(dataId, key, cur, keyInfoCtx);
120             if(ret < 0) {
121                 xmlSecInternalError2("xmlSecKeyDataXmlRead",
122                                      xmlSecKeyDataKlassGetName(dataId),
123                                      "node=%s",
124                                      xmlSecErrorsSafeString(xmlSecNodeGetName(cur)));
125                 return(-1);
126             }
127         } else if((keyInfoCtx->flags & XMLSEC_KEYINFO_FLAGS_STOP_ON_UNKNOWN_CHILD) != 0) {
128             /* there is a laxi schema validation but application may
129              * desire to disable unknown nodes*/
130             xmlSecUnexpectedNodeError(cur, NULL);
131             return(-1);
132         }
133     }
134 
135     return(0);
136 }
137 
138 /**
139  * xmlSecKeyInfoNodeWrite:
140  * @keyInfoNode:        the pointer to <dsig:KeyInfo/> node.
141  * @key:                the pointer to key object.
142  * @keyInfoCtx:         the pointer to <dsig:KeyInfo/> element processing context.
143  *
144  * Writes the @key into the <dsig:KeyInfo/> element template @keyInfoNode.
145  *
146  * Returns: 0 on success or -1 if an error occurs.
147  */
148 int
xmlSecKeyInfoNodeWrite(xmlNodePtr keyInfoNode,xmlSecKeyPtr key,xmlSecKeyInfoCtxPtr keyInfoCtx)149 xmlSecKeyInfoNodeWrite(xmlNodePtr keyInfoNode, xmlSecKeyPtr key, xmlSecKeyInfoCtxPtr keyInfoCtx) {
150     const xmlChar* nodeName;
151     const xmlChar* nodeNs;
152     xmlSecKeyDataId dataId;
153     xmlNodePtr cur;
154     int ret;
155 
156     xmlSecAssert2(keyInfoNode != NULL, -1);
157     xmlSecAssert2(key != NULL, -1);
158     xmlSecAssert2(keyInfoCtx != NULL, -1);
159     xmlSecAssert2(keyInfoCtx->mode == xmlSecKeyInfoModeWrite, -1);
160 
161     for(cur = xmlSecGetNextElementNode(keyInfoNode->children);
162         cur != NULL;
163         cur = xmlSecGetNextElementNode(cur->next)) {
164 
165         /* find data id */
166         nodeName = cur->name;
167         nodeNs = xmlSecGetNodeNsHref(cur);
168 
169         /* use global list only if we don't have a local one */
170         if(xmlSecPtrListGetSize(&(keyInfoCtx->enabledKeyData)) > 0) {
171                 dataId = xmlSecKeyDataIdListFindByNode(&(keyInfoCtx->enabledKeyData),
172                             nodeName, nodeNs,
173                             xmlSecKeyDataUsageKeyInfoNodeWrite);
174         } else {
175                 dataId = xmlSecKeyDataIdListFindByNode(xmlSecKeyDataIdsGet(),
176                             nodeName, nodeNs,
177                             xmlSecKeyDataUsageKeyInfoNodeWrite);
178         }
179         if(dataId != xmlSecKeyDataIdUnknown) {
180             ret = xmlSecKeyDataXmlWrite(dataId, key, cur, keyInfoCtx);
181             if(ret < 0) {
182                 xmlSecInternalError2("xmlSecKeyDataXmlWrite",
183                                      xmlSecKeyDataKlassGetName(dataId),
184                                      "node=%s",
185                                      xmlSecErrorsSafeString(xmlSecNodeGetName(cur)));
186                 return(-1);
187             }
188         } else if((keyInfoCtx->flags & XMLSEC_KEYINFO_FLAGS_STOP_ON_UNKNOWN_CHILD) != 0) {
189             /* laxi schema validation but application can disable it*/
190             xmlSecUnexpectedNodeError(cur, NULL);
191             return(-1);
192         }
193     }
194 
195     return(0);
196 }
197 
198 /**************************************************************************
199  *
200  * KeyInfo context
201  *
202  *************************************************************************/
203 /**
204  * xmlSecKeyInfoCtxCreate:
205  * @keysMngr:           the pointer to keys manager (may be NULL).
206  *
207  * Allocates and initializes <dsig:KeyInfo/> element processing context.
208  * Caller is responsible for freeing it by calling #xmlSecKeyInfoCtxDestroy
209  * function.
210  *
211  * Returns: pointer to newly allocated object or NULL if an error occurs.
212  */
213 xmlSecKeyInfoCtxPtr
xmlSecKeyInfoCtxCreate(xmlSecKeysMngrPtr keysMngr)214 xmlSecKeyInfoCtxCreate(xmlSecKeysMngrPtr keysMngr) {
215     xmlSecKeyInfoCtxPtr keyInfoCtx;
216     int ret;
217 
218     /* Allocate a new xmlSecKeyInfoCtx and fill the fields. */
219     keyInfoCtx = (xmlSecKeyInfoCtxPtr)xmlMalloc(sizeof(xmlSecKeyInfoCtx));
220     if(keyInfoCtx == NULL) {
221         xmlSecMallocError(sizeof(xmlSecKeyInfoCtx), NULL);
222         return(NULL);
223     }
224 
225     ret = xmlSecKeyInfoCtxInitialize(keyInfoCtx, keysMngr);
226     if(ret < 0) {
227         xmlSecInternalError("xmlSecKeyInfoCtxInitialize", NULL);
228         xmlSecKeyInfoCtxDestroy(keyInfoCtx);
229         return(NULL);
230     }
231 
232     return(keyInfoCtx);
233 }
234 
235 /**
236  * xmlSecKeyInfoCtxDestroy:
237  * @keyInfoCtx:         the pointer to <dsig:KeyInfo/> element processing context.
238  *
239  * Destroys @keyInfoCtx object created with #xmlSecKeyInfoCtxCreate function.
240  */
241 void
xmlSecKeyInfoCtxDestroy(xmlSecKeyInfoCtxPtr keyInfoCtx)242 xmlSecKeyInfoCtxDestroy(xmlSecKeyInfoCtxPtr keyInfoCtx) {
243     xmlSecAssert(keyInfoCtx != NULL);
244 
245     xmlSecKeyInfoCtxFinalize(keyInfoCtx);
246     xmlFree(keyInfoCtx);
247 }
248 
249 /**
250  * xmlSecKeyInfoCtxInitialize:
251  * @keyInfoCtx:         the pointer to <dsig:KeyInfo/> element processing context.
252  * @keysMngr:           the pointer to keys manager (may be NULL).
253  *
254  * Initializes <dsig:KeyInfo/> element processing context. Caller is
255  * responsible for cleaning it up by #xmlSecKeyInfoCtxFinalize function.
256  *
257  * Returns: 0 on success and a negative value if an error occurs.
258  */
259 int
xmlSecKeyInfoCtxInitialize(xmlSecKeyInfoCtxPtr keyInfoCtx,xmlSecKeysMngrPtr keysMngr)260 xmlSecKeyInfoCtxInitialize(xmlSecKeyInfoCtxPtr keyInfoCtx, xmlSecKeysMngrPtr keysMngr) {
261     int ret;
262 
263     xmlSecAssert2(keyInfoCtx != NULL, -1);
264 
265     memset(keyInfoCtx, 0, sizeof(xmlSecKeyInfoCtx));
266     keyInfoCtx->keysMngr = keysMngr;
267     keyInfoCtx->base64LineSize = xmlSecBase64GetDefaultLineSize();
268     ret = xmlSecPtrListInitialize(&(keyInfoCtx->enabledKeyData), xmlSecKeyDataIdListId);
269     if(ret < 0) {
270         xmlSecInternalError("xmlSecPtrListInitialize", NULL);
271         return(-1);
272     }
273 
274     keyInfoCtx->maxRetrievalMethodLevel = 1;
275     ret = xmlSecTransformCtxInitialize(&(keyInfoCtx->retrievalMethodCtx));
276     if(ret < 0) {
277         xmlSecInternalError("xmlSecTransformCtxInitialize", NULL);
278         return(-1);
279     }
280 
281 #ifndef XMLSEC_NO_XMLENC
282     keyInfoCtx->maxEncryptedKeyLevel = 1;
283 #endif /* XMLSEC_NO_XMLENC */
284 
285 #ifndef XMLSEC_NO_X509
286     keyInfoCtx->certsVerificationDepth= 9;
287 #endif /* XMLSEC_NO_X509 */
288 
289     ret = xmlSecKeyReqInitialize(&(keyInfoCtx->keyReq));
290     if(ret < 0) {
291         xmlSecInternalError("xmlSecKeyReqInitialize", NULL);
292         return(-1);
293     }
294 
295     return(0);
296 }
297 
298 /**
299  * xmlSecKeyInfoCtxFinalize:
300  * @keyInfoCtx:         the pointer to <dsig:KeyInfo/> element processing context.
301  *
302  * Cleans up the @keyInfoCtx initialized with #xmlSecKeyInfoCtxInitialize
303  * function.
304  */
305 void
xmlSecKeyInfoCtxFinalize(xmlSecKeyInfoCtxPtr keyInfoCtx)306 xmlSecKeyInfoCtxFinalize(xmlSecKeyInfoCtxPtr keyInfoCtx) {
307     xmlSecAssert(keyInfoCtx != NULL);
308 
309     xmlSecPtrListFinalize(&(keyInfoCtx->enabledKeyData));
310     xmlSecTransformCtxFinalize(&(keyInfoCtx->retrievalMethodCtx));
311     xmlSecKeyReqFinalize(&(keyInfoCtx->keyReq));
312 
313 #ifndef XMLSEC_NO_XMLENC
314     if(keyInfoCtx->encCtx != NULL) {
315         xmlSecEncCtxDestroy(keyInfoCtx->encCtx);
316     }
317 #endif /* XMLSEC_NO_XMLENC */
318 
319     memset(keyInfoCtx, 0, sizeof(xmlSecKeyInfoCtx));
320 }
321 
322 /**
323  * xmlSecKeyInfoCtxReset:
324  * @keyInfoCtx:         the pointer to <dsig:KeyInfo/> element processing context.
325  *
326  * Resets the @keyInfoCtx state. User settings are not changed.
327  */
328 void
xmlSecKeyInfoCtxReset(xmlSecKeyInfoCtxPtr keyInfoCtx)329 xmlSecKeyInfoCtxReset(xmlSecKeyInfoCtxPtr keyInfoCtx) {
330     xmlSecAssert(keyInfoCtx != NULL);
331 
332     xmlSecTransformCtxReset(&(keyInfoCtx->retrievalMethodCtx));
333     keyInfoCtx->curRetrievalMethodLevel = 0;
334 
335 #ifndef XMLSEC_NO_XMLENC
336     if(keyInfoCtx->encCtx != NULL) {
337         xmlSecEncCtxReset(keyInfoCtx->encCtx);
338     }
339     keyInfoCtx->curEncryptedKeyLevel = 0;
340 #endif /* XMLSEC_NO_XMLENC */
341 
342     xmlSecKeyReqReset(&(keyInfoCtx->keyReq));
343 }
344 
345 /**
346  * xmlSecKeyInfoCtxCreateEncCtx:
347  * @keyInfoCtx:         the pointer to <dsig:KeyInfo/> element processing context.
348  *
349  * Creates encryption context form processing <enc:EncryptedKey/> child
350  * of <dsig:KeyInfo/> element.
351  *
352  * Returns: 0 on success and a negative value if an error occurs.
353  */
354 int
xmlSecKeyInfoCtxCreateEncCtx(xmlSecKeyInfoCtxPtr keyInfoCtx)355 xmlSecKeyInfoCtxCreateEncCtx(xmlSecKeyInfoCtxPtr keyInfoCtx) {
356 #ifndef XMLSEC_NO_XMLENC
357     xmlSecEncCtxPtr tmp;
358     int ret;
359 
360     xmlSecAssert2(keyInfoCtx != NULL, -1);
361     xmlSecAssert2(keyInfoCtx->encCtx == NULL, -1);
362 
363     /* we have to use tmp variable to avoid a recursive loop */
364     tmp = xmlSecEncCtxCreate(keyInfoCtx->keysMngr);
365     if(tmp == NULL) {
366         xmlSecInternalError("xmlSecEncCtxCreate", NULL);
367         return(-1);
368     }
369     tmp->mode = xmlEncCtxModeEncryptedKey;
370 
371     /* copy user preferences from our current ctx */
372     switch(keyInfoCtx->mode) {
373         case xmlSecKeyInfoModeRead:
374             ret = xmlSecKeyInfoCtxCopyUserPref(&(tmp->keyInfoReadCtx), keyInfoCtx);
375             if(ret < 0) {
376                 xmlSecInternalError("xmlSecKeyInfoCtxCopyUserPref", NULL);
377                 xmlSecEncCtxDestroy(tmp);
378                 return(-1);
379             }
380             break;
381         case xmlSecKeyInfoModeWrite:
382             ret = xmlSecKeyInfoCtxCopyUserPref(&(tmp->keyInfoWriteCtx), keyInfoCtx);
383             if(ret < 0) {
384                 xmlSecInternalError("xmlSecKeyInfoCtxCopyUserPref", NULL);
385                 xmlSecEncCtxDestroy(tmp);
386                 return(-1);
387             }
388             break;
389     }
390     keyInfoCtx->encCtx = tmp;
391 
392     return(0);
393 #else /* XMLSEC_NO_XMLENC */
394 
395     xmlSecOtherError(XMLSEC_ERRORS_R_DISABLED, NULL, "xml encryption");
396     return(-1);
397 #endif /* XMLSEC_NO_XMLENC */
398 }
399 
400 /**
401  * xmlSecKeyInfoCtxCopyUserPref:
402  * @dst:                the pointer to destination context object.
403  * @src:                the pointer to source context object.
404  *
405  * Copies user preferences from @src context to @dst context.
406  *
407  * Returns: 0 on success and a negative value if an error occurs.
408  */
409 int
xmlSecKeyInfoCtxCopyUserPref(xmlSecKeyInfoCtxPtr dst,xmlSecKeyInfoCtxPtr src)410 xmlSecKeyInfoCtxCopyUserPref(xmlSecKeyInfoCtxPtr dst, xmlSecKeyInfoCtxPtr src) {
411     int ret;
412 
413     xmlSecAssert2(dst != NULL, -1);
414     xmlSecAssert2(src != NULL, -1);
415 
416     dst->userData       = src->userData;
417     dst->flags          = src->flags;
418     dst->flags2         = src->flags2;
419     dst->keysMngr       = src->keysMngr;
420     dst->mode           = src->mode;
421     dst->base64LineSize = src->base64LineSize;
422 
423     ret = xmlSecPtrListCopy(&(dst->enabledKeyData), &(src->enabledKeyData));
424     if(ret < 0) {
425         xmlSecInternalError("xmlSecPtrListCopy(enabledKeyData)", NULL);
426         return(-1);
427     }
428 
429     /* <dsig:RetrievalMethod/> */
430     dst->maxRetrievalMethodLevel= src->maxRetrievalMethodLevel;
431     ret = xmlSecTransformCtxCopyUserPref(&(dst->retrievalMethodCtx),
432                                          &(src->retrievalMethodCtx));
433     if(ret < 0) {
434         xmlSecInternalError("xmlSecTransformCtxCopyUserPref(enabledKeyData)", NULL);
435         return(-1);
436     }
437 
438     /* <enc:EncryptedContext /> */
439 #ifndef XMLSEC_NO_XMLENC
440     xmlSecAssert2(dst->encCtx == NULL, -1);
441     if(src->encCtx != NULL) {
442         dst->encCtx = xmlSecEncCtxCreate(dst->keysMngr);
443         if(dst->encCtx == NULL) {
444             xmlSecInternalError("xmlSecEncCtxCreate", NULL);
445             return(-1);
446         }
447 
448         dst->encCtx->mode = xmlEncCtxModeEncryptedKey;
449         ret = xmlSecEncCtxCopyUserPref(dst->encCtx, src->encCtx);
450         if(ret < 0) {
451             xmlSecInternalError("xmlSecEncCtxCopyUserPref", NULL);
452             return(-1);
453         }
454     }
455     dst->maxEncryptedKeyLevel   = src->maxEncryptedKeyLevel;
456 #endif /* XMLSEC_NO_XMLENC */
457 
458     /* <dsig:X509Data /> */
459 #ifndef XMLSEC_NO_X509
460     dst->certsVerificationTime  = src->certsVerificationTime;
461     dst->certsVerificationDepth = src->certsVerificationDepth;
462 #endif /* XMLSEC_NO_X509 */
463 
464     return(0);
465 }
466 
467 /**
468  * xmlSecKeyInfoCtxDebugDump:
469  * @keyInfoCtx:         the pointer to <dsig:KeyInfo/> element processing context.
470  * @output:             the output file pointer.
471  *
472  * Prints user settings and current context state to @output.
473  */
474 void
xmlSecKeyInfoCtxDebugDump(xmlSecKeyInfoCtxPtr keyInfoCtx,FILE * output)475 xmlSecKeyInfoCtxDebugDump(xmlSecKeyInfoCtxPtr keyInfoCtx, FILE* output) {
476     xmlSecAssert(keyInfoCtx != NULL);
477     xmlSecAssert(output != NULL);
478 
479     switch(keyInfoCtx->mode) {
480         case xmlSecKeyInfoModeRead:
481             fprintf(output, "= KEY INFO READ CONTEXT\n");
482             break;
483         case xmlSecKeyInfoModeWrite:
484             fprintf(output, "= KEY INFO WRITE CONTEXT\n");
485             break;
486     }
487 
488     fprintf(output, "== flags: 0x%08x\n", keyInfoCtx->flags);
489     fprintf(output, "== flags2: 0x%08x\n", keyInfoCtx->flags2);
490     if(xmlSecPtrListGetSize(&(keyInfoCtx->enabledKeyData)) > 0) {
491         fprintf(output, "== enabled key data: ");
492         xmlSecKeyDataIdListDebugDump(&(keyInfoCtx->enabledKeyData), output);
493     } else {
494         fprintf(output, "== enabled key data: all\n");
495     }
496     fprintf(output, "== RetrievalMethod level (cur/max): %d/%d\n",
497             keyInfoCtx->curRetrievalMethodLevel,
498             keyInfoCtx->maxRetrievalMethodLevel);
499     xmlSecTransformCtxDebugDump(&(keyInfoCtx->retrievalMethodCtx), output);
500 
501 #ifndef XMLSEC_NO_XMLENC
502     fprintf(output, "== EncryptedKey level (cur/max): %d/%d\n",
503             keyInfoCtx->curEncryptedKeyLevel,
504             keyInfoCtx->maxEncryptedKeyLevel);
505     if(keyInfoCtx->encCtx != NULL) {
506         xmlSecEncCtxDebugDump(keyInfoCtx->encCtx, output);
507     }
508 #endif /* XMLSEC_NO_XMLENC */
509 
510     xmlSecKeyReqDebugDump(&(keyInfoCtx->keyReq), output);
511 }
512 
513 /**
514  * xmlSecKeyInfoCtxDebugXmlDump:
515  * @keyInfoCtx:         the pointer to <dsig:KeyInfo/> element processing context.
516  * @output:             the output file pointer.
517  *
518  * Prints user settings and current context state in XML format to @output.
519  */
520 void
xmlSecKeyInfoCtxDebugXmlDump(xmlSecKeyInfoCtxPtr keyInfoCtx,FILE * output)521 xmlSecKeyInfoCtxDebugXmlDump(xmlSecKeyInfoCtxPtr keyInfoCtx, FILE* output) {
522     xmlSecAssert(keyInfoCtx != NULL);
523     xmlSecAssert(output != NULL);
524 
525     switch(keyInfoCtx->mode) {
526         case xmlSecKeyInfoModeRead:
527             fprintf(output, "<KeyInfoReadContext>\n");
528             break;
529         case xmlSecKeyInfoModeWrite:
530             fprintf(output, "<KeyInfoWriteContext>\n");
531             break;
532     }
533 
534     fprintf(output, "<Flags>%08x</Flags>\n", keyInfoCtx->flags);
535     fprintf(output, "<Flags2>%08x</Flags2>\n", keyInfoCtx->flags2);
536     if(xmlSecPtrListGetSize(&(keyInfoCtx->enabledKeyData)) > 0) {
537         fprintf(output, "<EnabledKeyData>\n");
538         xmlSecKeyDataIdListDebugXmlDump(&(keyInfoCtx->enabledKeyData), output);
539         fprintf(output, "</EnabledKeyData>\n");
540     } else {
541         fprintf(output, "<EnabledKeyData>all</EnabledKeyData>\n");
542     }
543 
544     fprintf(output, "<RetrievalMethodLevel cur=\"%d\" max=\"%d\" />\n",
545             keyInfoCtx->curRetrievalMethodLevel,
546             keyInfoCtx->maxRetrievalMethodLevel);
547     xmlSecTransformCtxDebugXmlDump(&(keyInfoCtx->retrievalMethodCtx), output);
548 
549 #ifndef XMLSEC_NO_XMLENC
550     fprintf(output, "<EncryptedKeyLevel cur=\"%d\" max=\"%d\" />\n",
551             keyInfoCtx->curEncryptedKeyLevel,
552             keyInfoCtx->maxEncryptedKeyLevel);
553     if(keyInfoCtx->encCtx != NULL) {
554         xmlSecEncCtxDebugXmlDump(keyInfoCtx->encCtx, output);
555     }
556 #endif /* XMLSEC_NO_XMLENC */
557 
558     xmlSecKeyReqDebugXmlDump(&(keyInfoCtx->keyReq), output);
559     switch(keyInfoCtx->mode) {
560         case xmlSecKeyInfoModeRead:
561             fprintf(output, "</KeyInfoReadContext>\n");
562             break;
563         case xmlSecKeyInfoModeWrite:
564             fprintf(output, "</KeyInfoWriteContext>\n");
565             break;
566     }
567 }
568 
569 /**************************************************************************
570  *
571  * <dsig:KeyName/> processing
572  *
573  *************************************************************************/
574 static int                      xmlSecKeyDataNameXmlRead        (xmlSecKeyDataId id,
575                                                                  xmlSecKeyPtr key,
576                                                                  xmlNodePtr node,
577                                                                  xmlSecKeyInfoCtxPtr keyInfoCtx);
578 static int                      xmlSecKeyDataNameXmlWrite       (xmlSecKeyDataId id,
579                                                                  xmlSecKeyPtr key,
580                                                                  xmlNodePtr node,
581                                                                  xmlSecKeyInfoCtxPtr keyInfoCtx);
582 
583 static xmlSecKeyDataKlass xmlSecKeyDataNameKlass = {
584     sizeof(xmlSecKeyDataKlass),
585     sizeof(xmlSecKeyData),
586 
587     /* data */
588     xmlSecNameKeyName,
589     xmlSecKeyDataUsageKeyInfoNode,              /* xmlSecKeyDataUsage usage; */
590     NULL,                                       /* const xmlChar* href; */
591     xmlSecNodeKeyName,                          /* const xmlChar* dataNodeName; */
592     xmlSecDSigNs,                               /* const xmlChar* dataNodeNs; */
593 
594     /* constructors/destructor */
595     NULL,                                       /* xmlSecKeyDataInitializeMethod initialize; */
596     NULL,                                       /* xmlSecKeyDataDuplicateMethod duplicate; */
597     NULL,                                       /* xmlSecKeyDataFinalizeMethod finalize; */
598     NULL,                                       /* xmlSecKeyDataGenerateMethod generate; */
599 
600     /* get info */
601     NULL,                                       /* xmlSecKeyDataGetTypeMethod getType; */
602     NULL,                                       /* xmlSecKeyDataGetSizeMethod getSize; */
603     NULL,                                       /* xmlSecKeyDataGetIdentifier getIdentifier; */
604 
605     /* read/write */
606     xmlSecKeyDataNameXmlRead,                   /* xmlSecKeyDataXmlReadMethod xmlRead; */
607     xmlSecKeyDataNameXmlWrite,                  /* xmlSecKeyDataXmlWriteMethod xmlWrite; */
608     NULL,                                       /* xmlSecKeyDataBinReadMethod binRead; */
609     NULL,                                       /* xmlSecKeyDataBinWriteMethod binWrite; */
610 
611     /* debug */
612     NULL,                                       /* xmlSecKeyDataDebugDumpMethod debugDump; */
613     NULL,                                       /* xmlSecKeyDataDebugDumpMethod debugXmlDump; */
614 
615     /* reserved for the future */
616     NULL,                                       /* void* reserved0; */
617     NULL,                                       /* void* reserved1; */
618 };
619 
620 /**
621  * xmlSecKeyDataNameGetKlass:
622  *
623  * The <dsig:KeyName/> element key data klass
624  * (http://www.w3.org/TR/xmldsig-core/#sec-KeyName):
625  *
626  * The KeyName element contains a string value (in which white space is
627  * significant) which may be used by the signer to communicate a key
628  * identifier to the recipient. Typically, KeyName contains an identifier
629  * related to the key pair used to sign the message, but it may contain
630  * other protocol-related information that indirectly identifies a key pair.
631  * (Common uses of KeyName include simple string names for keys, a key index,
632  * a distinguished name (DN), an email address, etc.)
633  *
634  * Returns: the <dsig:KeyName/> element processing key data klass.
635  */
636 xmlSecKeyDataId
xmlSecKeyDataNameGetKlass(void)637 xmlSecKeyDataNameGetKlass(void) {
638     return(&xmlSecKeyDataNameKlass);
639 }
640 
641 static int
xmlSecKeyDataNameXmlRead(xmlSecKeyDataId id,xmlSecKeyPtr key,xmlNodePtr node,xmlSecKeyInfoCtxPtr keyInfoCtx)642 xmlSecKeyDataNameXmlRead(xmlSecKeyDataId id, xmlSecKeyPtr key, xmlNodePtr node, xmlSecKeyInfoCtxPtr keyInfoCtx) {
643     xmlChar* newName;
644     int ret;
645 
646     xmlSecAssert2(id == xmlSecKeyDataNameId, -1);
647     xmlSecAssert2(key != NULL, -1);
648     xmlSecAssert2(node != NULL, -1);
649     xmlSecAssert2(keyInfoCtx != NULL, -1);
650     xmlSecAssert2(keyInfoCtx->mode == xmlSecKeyInfoModeRead, -1);
651 
652     /* read key name */
653     newName = xmlNodeGetContent(node);
654     if(newName == NULL) {
655         xmlSecInvalidNodeContentError(node, xmlSecKeyDataKlassGetName(id), "empty");
656         return(-1);
657     }
658 
659     /* try to find key in the manager */
660     if((xmlSecKeyGetValue(key) == NULL) && (keyInfoCtx->keysMngr != NULL)) {
661         xmlSecKeyPtr tmpKey;
662 
663         tmpKey = xmlSecKeysMngrFindKey(keyInfoCtx->keysMngr, newName, keyInfoCtx);
664         if(tmpKey != NULL) {
665             /* erase any current information in the key */
666             xmlSecKeyEmpty(key);
667 
668             /* TODO: since we will destroy tmpKey anyway, we can easily
669              * just re-assign key data values. It'll save use some memory
670              * malloc/free
671              */
672 
673             /* and copy what we've found */
674             ret = xmlSecKeyCopy(key, tmpKey);
675             if(ret < 0) {
676                 xmlSecInternalError("xmlSecKeyCopy",
677                                     xmlSecKeyDataKlassGetName(id));
678                 xmlSecKeyDestroy(tmpKey);
679                 xmlFree(newName);
680                 return(-1);
681             }
682             xmlSecKeyDestroy(tmpKey);
683 
684             /* and set the key name */
685             ret = xmlSecKeySetName(key, newName);
686             if(ret < 0) {
687                 xmlSecInternalError("xmlSecKeySetName",
688                                     xmlSecKeyDataKlassGetName(id));
689                 xmlFree(newName);
690                 return(-1);
691             }
692         }
693         /* TODO: record the key names we tried */
694     } else {
695         const xmlChar* oldName;
696 
697         /* if we already have a keyname, make sure that it matches or set it */
698         oldName = xmlSecKeyGetName(key);
699         if(oldName != NULL) {
700             if(!xmlStrEqual(oldName, newName)) {
701                 xmlSecOtherError(XMLSEC_ERRORS_R_INVALID_KEY_DATA,
702                                  xmlSecKeyDataKlassGetName(id),
703                                  "key name is already specified");
704                 xmlFree(newName);
705                 return(-1);
706             }
707         } else {
708             ret = xmlSecKeySetName(key, newName);
709             if(ret < 0) {
710                 xmlSecInternalError("xmlSecKeySetName",
711                                     xmlSecKeyDataKlassGetName(id));
712                 xmlFree(newName);
713                 return(-1);
714             }
715         }
716     }
717 
718     /* done */
719     xmlFree(newName);
720     return(0);
721 }
722 
723 static int
xmlSecKeyDataNameXmlWrite(xmlSecKeyDataId id,xmlSecKeyPtr key,xmlNodePtr node,xmlSecKeyInfoCtxPtr keyInfoCtx)724 xmlSecKeyDataNameXmlWrite(xmlSecKeyDataId id, xmlSecKeyPtr key, xmlNodePtr node, xmlSecKeyInfoCtxPtr keyInfoCtx) {
725     const xmlChar* name;
726     int ret;
727 
728     xmlSecAssert2(id == xmlSecKeyDataNameId, -1);
729     xmlSecAssert2(key != NULL, -1);
730     xmlSecAssert2(node != NULL, -1);
731     xmlSecAssert2(keyInfoCtx != NULL, -1);
732     xmlSecAssert2(keyInfoCtx->mode == xmlSecKeyInfoModeWrite, -1);
733 
734     name = xmlSecKeyGetName(key);
735     if(name == NULL) {
736         return(8);
737     }
738 
739     if(!xmlSecIsEmptyNode(node)) {
740         return(0);
741     }
742 
743     ret = xmlSecNodeEncodeAndSetContent(node, name);
744     if(ret < 0) {
745         xmlSecInternalError("xmlSecNodeEncodeAndSetContent", NULL);
746         return(-1);
747     }
748 
749     /* done */
750     return(0);
751 }
752 
753 /**************************************************************************
754  *
755  * <dsig:KeyValue/> processing
756  *
757  *************************************************************************/
758 static int                      xmlSecKeyDataValueXmlRead       (xmlSecKeyDataId id,
759                                                                  xmlSecKeyPtr key,
760                                                                  xmlNodePtr node,
761                                                                  xmlSecKeyInfoCtxPtr keyInfoCtx);
762 static int                      xmlSecKeyDataValueXmlWrite      (xmlSecKeyDataId id,
763                                                                  xmlSecKeyPtr key,
764                                                                  xmlNodePtr node,
765                                                                  xmlSecKeyInfoCtxPtr keyInfoCtx);
766 
767 static xmlSecKeyDataKlass xmlSecKeyDataValueKlass = {
768     sizeof(xmlSecKeyDataKlass),
769     sizeof(xmlSecKeyData),
770 
771     /* data */
772     xmlSecNameKeyValue,
773     xmlSecKeyDataUsageKeyInfoNode,              /* xmlSecKeyDataUsage usage; */
774     NULL,                                       /* const xmlChar* href; */
775     xmlSecNodeKeyValue,                         /* const xmlChar* dataNodeName; */
776     xmlSecDSigNs,                               /* const xmlChar* dataNodeNs; */
777 
778     /* constructors/destructor */
779     NULL,                                       /* xmlSecKeyDataInitializeMethod initialize; */
780     NULL,                                       /* xmlSecKeyDataDuplicateMethod duplicate; */
781     NULL,                                       /* xmlSecKeyDataFinalizeMethod finalize; */
782     NULL,                                       /* xmlSecKeyDataGenerateMethod generate; */
783 
784     /* get info */
785     NULL,                                       /* xmlSecKeyDataGetTypeMethod getType; */
786     NULL,                                       /* xmlSecKeyDataGetSizeMethod getSize; */
787     NULL,                                       /* xmlSecKeyDataGetIdentifier getIdentifier; */
788 
789     /* read/write */
790     xmlSecKeyDataValueXmlRead,                  /* xmlSecKeyDataXmlReadMethod xmlRead; */
791     xmlSecKeyDataValueXmlWrite,                 /* xmlSecKeyDataXmlWriteMethod xmlWrite; */
792     NULL,                                       /* xmlSecKeyDataBinReadMethod binRead; */
793     NULL,                                       /* xmlSecKeyDataBinWriteMethod binWrite; */
794 
795     /* debug */
796     NULL,                                       /* xmlSecKeyDataDebugDumpMethod debugDump; */
797     NULL,                                       /* xmlSecKeyDataDebugDumpMethod debugXmlDump; */
798 
799     /* reserved for the future */
800     NULL,                                       /* void* reserved0; */
801     NULL,                                       /* void* reserved1; */
802 };
803 
804 /**
805  * xmlSecKeyDataValueGetKlass:
806  *
807  * The <dsig:KeyValue/> element key data klass
808  * (http://www.w3.org/TR/xmldsig-core/#sec-KeyValue):
809  *
810  * The KeyValue element contains a single public key that may be useful in
811  * validating the signature.
812  *
813  * Returns: the <dsig:KeyValue/> element processing key data klass.
814  */
815 xmlSecKeyDataId
xmlSecKeyDataValueGetKlass(void)816 xmlSecKeyDataValueGetKlass(void) {
817     return(&xmlSecKeyDataValueKlass);
818 }
819 
820 static int
xmlSecKeyDataValueXmlRead(xmlSecKeyDataId id,xmlSecKeyPtr key,xmlNodePtr node,xmlSecKeyInfoCtxPtr keyInfoCtx)821 xmlSecKeyDataValueXmlRead(xmlSecKeyDataId id, xmlSecKeyPtr key, xmlNodePtr node, xmlSecKeyInfoCtxPtr keyInfoCtx) {
822     const xmlChar* nodeName;
823     const xmlChar* nodeNs;
824     xmlSecKeyDataId dataId;
825     xmlNodePtr cur;
826     int ret;
827 
828     xmlSecAssert2(id == xmlSecKeyDataValueId, -1);
829     xmlSecAssert2(key != NULL, -1);
830     xmlSecAssert2(node != NULL, -1);
831     xmlSecAssert2(keyInfoCtx != NULL, -1);
832     xmlSecAssert2(keyInfoCtx->mode == xmlSecKeyInfoModeRead, -1);
833 
834     cur = xmlSecGetNextElementNode(node->children);
835     if(cur == NULL) {
836         /* just an empty node */
837         return(0);
838     }
839 
840     /* find data id */
841     nodeName = cur->name;
842     nodeNs = xmlSecGetNodeNsHref(cur);
843 
844     /* use global list only if we don't have a local one */
845     if(xmlSecPtrListGetSize(&(keyInfoCtx->enabledKeyData)) > 0) {
846         dataId = xmlSecKeyDataIdListFindByNode(&(keyInfoCtx->enabledKeyData),
847                             nodeName, nodeNs, xmlSecKeyDataUsageKeyValueNodeRead);
848     } else {
849         dataId = xmlSecKeyDataIdListFindByNode(xmlSecKeyDataIdsGet(),
850                             nodeName, nodeNs, xmlSecKeyDataUsageKeyValueNodeRead);
851     }
852     if(dataId != xmlSecKeyDataIdUnknown) {
853         /* read data node */
854         ret = xmlSecKeyDataXmlRead(dataId, key, cur, keyInfoCtx);
855         if(ret < 0) {
856             xmlSecInternalError2("xmlSecKeyDataXmlRead",
857                                  xmlSecKeyDataKlassGetName(id),
858                                  "node=%s",
859                                  xmlSecErrorsSafeString(xmlSecNodeGetName(cur)));
860             return(-1);
861         }
862     } else if((keyInfoCtx->flags & XMLSEC_KEYINFO_FLAGS_KEYVALUE_STOP_ON_UNKNOWN_CHILD) != 0) {
863         /* laxi schema validation but application can disable it */
864         xmlSecUnexpectedNodeError(cur, xmlSecKeyDataKlassGetName(id));
865         return(-1);
866     }
867 
868     /* <dsig:KeyValue/> might have only one node */
869     cur = xmlSecGetNextElementNode(cur->next);
870     if(cur != NULL) {
871         xmlSecUnexpectedNodeError(cur, xmlSecKeyDataKlassGetName(id));
872         return(-1);
873     }
874 
875     return(0);
876 }
877 
878 static int
xmlSecKeyDataValueXmlWrite(xmlSecKeyDataId id,xmlSecKeyPtr key,xmlNodePtr node,xmlSecKeyInfoCtxPtr keyInfoCtx)879 xmlSecKeyDataValueXmlWrite(xmlSecKeyDataId id, xmlSecKeyPtr key, xmlNodePtr node, xmlSecKeyInfoCtxPtr keyInfoCtx) {
880     const xmlChar* nodeName;
881     const xmlChar* nodeNs;
882     xmlNodePtr cur;
883     int ret;
884 
885     xmlSecAssert2(id == xmlSecKeyDataValueId, -1);
886     xmlSecAssert2(key != NULL, -1);
887     xmlSecAssert2(node != NULL, -1);
888     xmlSecAssert2(keyInfoCtx != NULL, -1);
889     xmlSecAssert2(keyInfoCtx->mode == xmlSecKeyInfoModeWrite, -1);
890 
891     if(!xmlSecKeyDataIsValid(key->value) ||
892        !xmlSecKeyDataCheckUsage(key->value, xmlSecKeyDataUsageKeyValueNodeWrite)){
893         /* nothing to write */
894         return(0);
895     }
896     if((xmlSecPtrListGetSize(&(keyInfoCtx->enabledKeyData)) > 0) &&
897         (xmlSecKeyDataIdListFind(&(keyInfoCtx->enabledKeyData), id) != 1)) {
898 
899         /* we are not enabled to write out key data with this id */
900         return(0);
901     }
902     if(xmlSecKeyReqMatchKey(&(keyInfoCtx->keyReq), key) != 1) {
903         /* we are not allowed to write out this key */
904         return(0);
905     }
906 
907     nodeName = key->value->id->dataNodeName;
908     nodeNs = key->value->id->dataNodeNs;
909     xmlSecAssert2(nodeName != NULL, -1);
910 
911     /* remove all existing key value */
912     xmlNodeSetContent(node, NULL);
913 
914     /* create key node */
915     cur = xmlSecAddChild(node, nodeName, nodeNs);
916     if(cur == NULL) {
917         xmlSecInternalError2("xmlSecAddChild",
918                              xmlSecKeyDataKlassGetName(id),
919                              "node=%s",
920                              xmlSecErrorsSafeString(xmlSecNodeGetName(node)));
921         return(-1);
922     }
923 
924     ret = xmlSecKeyDataXmlWrite(key->value->id, key, cur, keyInfoCtx);
925     if(ret < 0) {
926         xmlSecInternalError2("xmlSecKeyDataXmlWrite",
927                              xmlSecKeyDataKlassGetName(id),
928                              "node=%s",
929                              xmlSecErrorsSafeString(xmlSecNodeGetName(cur)));
930         return(-1);
931     }
932 
933     return(0);
934 }
935 
936 /**************************************************************************
937  *
938  * <dsig:RetrievalMethod/> processing
939  *
940  *************************************************************************/
941 static int                      xmlSecKeyDataRetrievalMethodXmlRead(xmlSecKeyDataId id,
942                                                                  xmlSecKeyPtr key,
943                                                                  xmlNodePtr node,
944                                                                  xmlSecKeyInfoCtxPtr keyInfoCtx);
945 static int                      xmlSecKeyDataRetrievalMethodXmlWrite(xmlSecKeyDataId id,
946                                                                  xmlSecKeyPtr key,
947                                                                  xmlNodePtr node,
948                                                                  xmlSecKeyInfoCtxPtr keyInfoCtx);
949 
950 
951 
952 static xmlSecKeyDataKlass xmlSecKeyDataRetrievalMethodKlass = {
953     sizeof(xmlSecKeyDataKlass),
954     sizeof(xmlSecKeyData),
955 
956     /* data */
957     xmlSecNameRetrievalMethod,
958     xmlSecKeyDataUsageKeyInfoNode,              /* xmlSecKeyDataUsage usage; */
959     NULL,                                       /* const xmlChar* href; */
960     xmlSecNodeRetrievalMethod,                  /* const xmlChar* dataNodeName; */
961     xmlSecDSigNs,                               /* const xmlChar* dataNodeNs; */
962 
963     /* constructors/destructor */
964     NULL,                                       /* xmlSecKeyDataInitializeMethod initialize; */
965     NULL,                                       /* xmlSecKeyDataDuplicateMethod duplicate; */
966     NULL,                                       /* xmlSecKeyDataFinalizeMethod finalize; */
967     NULL,                                       /* xmlSecKeyDataGenerateMethod generate; */
968 
969     /* get info */
970     NULL,                                       /* xmlSecKeyDataGetTypeMethod getType; */
971     NULL,                                       /* xmlSecKeyDataGetSizeMethod getSize; */
972     NULL,                                       /* xmlSecKeyDataGetIdentifier getIdentifier; */
973 
974     /* read/write */
975     xmlSecKeyDataRetrievalMethodXmlRead,        /* xmlSecKeyDataXmlReadMethod xmlRead; */
976     xmlSecKeyDataRetrievalMethodXmlWrite,       /* xmlSecKeyDataXmlWriteMethod xmlWrite; */
977     NULL,                                       /* xmlSecKeyDataBinReadMethod binRead; */
978     NULL,                                       /* xmlSecKeyDataBinWriteMethod binWrite; */
979 
980     /* debug */
981     NULL,                                       /* xmlSecKeyDataDebugDumpMethod debugDump; */
982     NULL,                                       /* xmlSecKeyDataDebugDumpMethod debugXmlDump; */
983 
984     /* reserved for the future */
985     NULL,                                       /* void* reserved0; */
986     NULL,                                       /* void* reserved1; */
987 };
988 
989 static int                      xmlSecKeyDataRetrievalMethodReadXmlResult(xmlSecKeyDataId typeId,
990                                                                  xmlSecKeyPtr key,
991                                                                  const xmlChar* buffer,
992                                                                  xmlSecSize bufferSize,
993                                                                  xmlSecKeyInfoCtxPtr keyInfoCtx);
994 
995 /**
996  * xmlSecKeyDataRetrievalMethodGetKlass:
997  *
998  * The <dsig:RetrievalMethod/> element key data klass
999  * (http://www.w3.org/TR/xmldsig-core/#sec-RetrievalMethod):
1000  * A RetrievalMethod element within KeyInfo is used to convey a reference to
1001  * KeyInfo information that is stored at another location. For example,
1002  * several signatures in a document might use a key verified by an X.509v3
1003  * certificate chain appearing once in the document or remotely outside the
1004  * document; each signature's KeyInfo can reference this chain using a single
1005  * RetrievalMethod element instead of including the entire chain with a
1006  * sequence of X509Certificate elements.
1007  *
1008  * RetrievalMethod uses the same syntax and dereferencing behavior as
1009  * Reference's URI and The Reference Processing Model.
1010  *
1011  * Returns: the <dsig:RetrievalMethod/> element processing key data klass.
1012  */
1013 xmlSecKeyDataId
xmlSecKeyDataRetrievalMethodGetKlass(void)1014 xmlSecKeyDataRetrievalMethodGetKlass(void) {
1015     return(&xmlSecKeyDataRetrievalMethodKlass);
1016 }
1017 
1018 static int
xmlSecKeyDataRetrievalMethodXmlRead(xmlSecKeyDataId id,xmlSecKeyPtr key,xmlNodePtr node,xmlSecKeyInfoCtxPtr keyInfoCtx)1019 xmlSecKeyDataRetrievalMethodXmlRead(xmlSecKeyDataId id, xmlSecKeyPtr key, xmlNodePtr node, xmlSecKeyInfoCtxPtr keyInfoCtx) {
1020     xmlSecKeyDataId dataId = xmlSecKeyDataIdUnknown;
1021     xmlChar *retrType = NULL;
1022     xmlChar *uri = NULL;
1023     xmlNodePtr cur;
1024     int res = -1;
1025     int ret;
1026 
1027     xmlSecAssert2(id == xmlSecKeyDataRetrievalMethodId, -1);
1028     xmlSecAssert2(key != NULL, -1);
1029     xmlSecAssert2(node != NULL, -1);
1030     xmlSecAssert2(node->doc != NULL, -1);
1031     xmlSecAssert2(keyInfoCtx != NULL, -1);
1032     xmlSecAssert2(keyInfoCtx->mode == xmlSecKeyInfoModeRead, -1);
1033 
1034     /* check retrieval level */
1035     if(keyInfoCtx->curRetrievalMethodLevel >= keyInfoCtx->maxRetrievalMethodLevel) {
1036         xmlSecOtherError3(XMLSEC_ERRORS_R_MAX_RETRIEVALS_LEVEL,
1037                           xmlSecKeyDataKlassGetName(id),
1038                           "cur=%d;max=%d",
1039                           keyInfoCtx->curRetrievalMethodLevel,
1040                           keyInfoCtx->maxRetrievalMethodLevel);
1041         goto done;
1042     }
1043     ++keyInfoCtx->curRetrievalMethodLevel;
1044 
1045     retrType = xmlGetProp(node, xmlSecAttrType);
1046     if(retrType != NULL) {
1047         /* use global list only if we don't have a local one */
1048         if(xmlSecPtrListGetSize(&(keyInfoCtx->enabledKeyData)) > 0) {
1049             dataId = xmlSecKeyDataIdListFindByHref(&(keyInfoCtx->enabledKeyData),
1050                             retrType, xmlSecKeyDataUsageRetrievalMethodNode);
1051         } else {
1052             dataId = xmlSecKeyDataIdListFindByHref(xmlSecKeyDataIdsGet(),
1053                             retrType, xmlSecKeyDataUsageRetrievalMethodNode);
1054         }
1055     }
1056 
1057     /* laxi schema validation but application can disable it */
1058     if(dataId == xmlSecKeyDataIdUnknown) {
1059         if((keyInfoCtx->flags & XMLSEC_KEYINFO_FLAGS_RETRMETHOD_STOP_ON_UNKNOWN_HREF) != 0) {
1060             xmlSecInvalidNodeAttributeError(node, xmlSecAttrType,
1061                                             xmlSecKeyDataKlassGetName(id),
1062                                             "retrieval type is unknown");
1063         } else {
1064             res = 0;
1065         }
1066         goto done;
1067     }
1068 
1069     /* destroy prev retrieval method context */
1070     xmlSecTransformCtxReset(&(keyInfoCtx->retrievalMethodCtx));
1071 
1072     /* set start URI and check that it is enabled */
1073     uri = xmlGetProp(node, xmlSecAttrURI);
1074     ret = xmlSecTransformCtxSetUri(&(keyInfoCtx->retrievalMethodCtx), uri, node);
1075     if(ret < 0) {
1076         xmlSecInternalError2("xmlSecTransformCtxSetUri",
1077                              xmlSecKeyDataKlassGetName(id),
1078                              "uri=%s", xmlSecErrorsSafeString(uri));
1079         goto done;
1080     }
1081 
1082     /* the only one node is optional Transforms node */
1083     cur = xmlSecGetNextElementNode(node->children);
1084     if((cur != NULL) && (xmlSecCheckNodeName(cur, xmlSecNodeTransforms, xmlSecDSigNs))) {
1085         ret = xmlSecTransformCtxNodesListRead(&(keyInfoCtx->retrievalMethodCtx),
1086                                             cur, xmlSecTransformUsageDSigTransform);
1087         if(ret < 0) {
1088             xmlSecInternalError2("xmlSecTransformCtxNodesListRead",
1089                                  xmlSecKeyDataKlassGetName(id),
1090                                  "node=%s",
1091                                  xmlSecErrorsSafeString(xmlSecNodeGetName(cur)));
1092             goto done;
1093         }
1094         cur = xmlSecGetNextElementNode(cur->next);
1095     }
1096 
1097     if(cur != NULL) {
1098         xmlSecUnexpectedNodeError(cur, xmlSecKeyDataKlassGetName(id));
1099         goto done;
1100     }
1101 
1102     /* finally get transforms results */
1103     ret = xmlSecTransformCtxExecute(&(keyInfoCtx->retrievalMethodCtx), node->doc);
1104     if((ret < 0) ||
1105        (keyInfoCtx->retrievalMethodCtx.result == NULL) ||
1106        (xmlSecBufferGetData(keyInfoCtx->retrievalMethodCtx.result) == NULL)) {
1107 
1108         xmlSecInternalError("xmlSecTransformCtxExecute",
1109                             xmlSecKeyDataKlassGetName(id));
1110         goto done;
1111     }
1112 
1113 
1114     /* assume that the data is in XML if we could not find id */
1115     if((dataId == xmlSecKeyDataIdUnknown) ||
1116        ((dataId->usage & xmlSecKeyDataUsageRetrievalMethodNodeXml) != 0)) {
1117 
1118         ret = xmlSecKeyDataRetrievalMethodReadXmlResult(dataId, key,
1119                     xmlSecBufferGetData(keyInfoCtx->retrievalMethodCtx.result),
1120                     xmlSecBufferGetSize(keyInfoCtx->retrievalMethodCtx.result),
1121                     keyInfoCtx);
1122         if(ret < 0) {
1123             xmlSecInternalError("xmlSecKeyDataRetrievalMethodReadXmlResult",
1124                                 xmlSecKeyDataKlassGetName(id));
1125             goto done;
1126         }
1127     } else {
1128         ret = xmlSecKeyDataBinRead(dataId, key,
1129                     xmlSecBufferGetData(keyInfoCtx->retrievalMethodCtx.result),
1130                     xmlSecBufferGetSize(keyInfoCtx->retrievalMethodCtx.result),
1131                     keyInfoCtx);
1132         if(ret < 0) {
1133             xmlSecInternalError("xmlSecKeyDataBinRead",
1134                                 xmlSecKeyDataKlassGetName(id));
1135             goto done;
1136         }
1137     }
1138     --keyInfoCtx->curRetrievalMethodLevel;
1139 
1140     res = 0;
1141 done:
1142     if(uri != NULL) {
1143         xmlFree(uri);
1144     }
1145     if(retrType != NULL) {
1146         xmlFree(retrType);
1147     }
1148     return(res);
1149 }
1150 
1151 static int
xmlSecKeyDataRetrievalMethodXmlWrite(xmlSecKeyDataId id,xmlSecKeyPtr key,xmlNodePtr node,xmlSecKeyInfoCtxPtr keyInfoCtx)1152 xmlSecKeyDataRetrievalMethodXmlWrite(xmlSecKeyDataId id, xmlSecKeyPtr key, xmlNodePtr node, xmlSecKeyInfoCtxPtr keyInfoCtx) {
1153     xmlSecAssert2(id == xmlSecKeyDataRetrievalMethodId, -1);
1154     xmlSecAssert2(key != NULL, -1);
1155     xmlSecAssert2(node != NULL, -1);
1156     xmlSecAssert2(keyInfoCtx != NULL, -1);
1157     xmlSecAssert2(keyInfoCtx->mode == xmlSecKeyInfoModeWrite, -1);
1158 
1159     /* just do nothing */
1160     return(0);
1161 }
1162 
1163 static int
xmlSecKeyDataRetrievalMethodReadXmlResult(xmlSecKeyDataId typeId,xmlSecKeyPtr key,const xmlChar * buffer,xmlSecSize bufferSize,xmlSecKeyInfoCtxPtr keyInfoCtx)1164 xmlSecKeyDataRetrievalMethodReadXmlResult(xmlSecKeyDataId typeId, xmlSecKeyPtr key,
1165                                           const xmlChar* buffer, xmlSecSize bufferSize,
1166                                           xmlSecKeyInfoCtxPtr keyInfoCtx) {
1167     xmlDocPtr doc;
1168     xmlNodePtr cur;
1169     const xmlChar* nodeName;
1170     const xmlChar* nodeNs;
1171     xmlSecKeyDataId dataId;
1172     int ret;
1173 
1174     xmlSecAssert2(key != NULL, -1);
1175     xmlSecAssert2(buffer != NULL, -1);
1176     xmlSecAssert2(bufferSize > 0, -1);
1177     xmlSecAssert2(keyInfoCtx != NULL, -1);
1178     xmlSecAssert2(keyInfoCtx->mode == xmlSecKeyInfoModeRead, -1);
1179 
1180     doc = xmlRecoverMemory((const char*)buffer, bufferSize);
1181     if(doc == NULL) {
1182         xmlSecXmlError("xmlRecoverMemory", xmlSecKeyDataKlassGetName(typeId));
1183         return(-1);
1184     }
1185 
1186     cur = xmlDocGetRootElement(doc);
1187     if(cur == NULL) {
1188         xmlSecXmlError("xmlDocGetRootElement", xmlSecKeyDataKlassGetName(typeId));
1189         xmlFreeDoc(doc);
1190         return(-1);
1191     }
1192 
1193     nodeName = cur->name;
1194     nodeNs = xmlSecGetNodeNsHref(cur);
1195 
1196     /* use global list only if we don't have a local one */
1197     if(xmlSecPtrListGetSize(&(keyInfoCtx->enabledKeyData)) > 0) {
1198         dataId = xmlSecKeyDataIdListFindByNode(&(keyInfoCtx->enabledKeyData),
1199                             nodeName, nodeNs, xmlSecKeyDataUsageRetrievalMethodNodeXml);
1200     } else {
1201         dataId = xmlSecKeyDataIdListFindByNode(xmlSecKeyDataIdsGet(),
1202                             nodeName, nodeNs, xmlSecKeyDataUsageRetrievalMethodNodeXml);
1203     }
1204     if(dataId == xmlSecKeyDataIdUnknown) {
1205         xmlFreeDoc(doc);
1206 
1207         /* laxi schema validation but application can disable it */
1208         if((keyInfoCtx->flags & XMLSEC_KEYINFO_FLAGS_KEYVALUE_STOP_ON_UNKNOWN_CHILD) != 0) {
1209             xmlSecUnexpectedNodeError(cur, xmlSecKeyDataKlassGetName(typeId));
1210             return(-1);
1211         }
1212         return(0);
1213     } else if((typeId != xmlSecKeyDataIdUnknown) && (typeId != dataId) &&
1214               ((keyInfoCtx->flags & XMLSEC_KEYINFO_FLAGS_RETRMETHOD_STOP_ON_MISMATCH_HREF) != 0)) {
1215 
1216         xmlSecOtherError2(XMLSEC_ERRORS_R_MAX_RETRIEVAL_TYPE_MISMATCH,
1217                           xmlSecKeyDataKlassGetName(dataId),
1218                           "typeId=%s", xmlSecErrorsSafeString(xmlSecKeyDataKlassGetName(typeId)));
1219         xmlFreeDoc(doc);
1220         return(-1);
1221     }
1222 
1223     /* read data node */
1224     ret = xmlSecKeyDataXmlRead(dataId, key, cur, keyInfoCtx);
1225     if(ret < 0) {
1226         xmlSecInternalError2("xmlSecKeyDataXmlRead",
1227                              xmlSecKeyDataKlassGetName(typeId),
1228                              "node=%s",
1229                              xmlSecErrorsSafeString(xmlSecNodeGetName(cur)));
1230         xmlFreeDoc(doc);
1231         return(-1);
1232     }
1233 
1234     xmlFreeDoc(doc);
1235     return(0);
1236 }
1237 
1238 
1239 #ifndef XMLSEC_NO_XMLENC
1240 /**************************************************************************
1241  *
1242  * <enc:EncryptedKey/> processing
1243  *
1244  *************************************************************************/
1245 static int      xmlSecKeyDataEncryptedKeyXmlRead        (xmlSecKeyDataId id,
1246                                                          xmlSecKeyPtr key,
1247                                                          xmlNodePtr node,
1248                                                          xmlSecKeyInfoCtxPtr keyInfoCtx);
1249 static int      xmlSecKeyDataEncryptedKeyXmlWrite       (xmlSecKeyDataId id,
1250                                                          xmlSecKeyPtr key,
1251                                                          xmlNodePtr node,
1252                                                          xmlSecKeyInfoCtxPtr keyInfoCtx);
1253 
1254 
1255 
1256 static xmlSecKeyDataKlass xmlSecKeyDataEncryptedKeyKlass = {
1257     sizeof(xmlSecKeyDataKlass),
1258     sizeof(xmlSecKeyData),
1259 
1260     /* data */
1261     xmlSecNameEncryptedKey,
1262     xmlSecKeyDataUsageKeyInfoNode | xmlSecKeyDataUsageRetrievalMethodNodeXml,
1263                                                 /* xmlSecKeyDataUsage usage; */
1264     xmlSecHrefEncryptedKey,                     /* const xmlChar* href; */
1265     xmlSecNodeEncryptedKey,                     /* const xmlChar* dataNodeName; */
1266     xmlSecEncNs,                                /* const xmlChar* dataNodeNs; */
1267 
1268     /* constructors/destructor */
1269     NULL,                                       /* xmlSecKeyDataInitializeMethod initialize; */
1270     NULL,                                       /* xmlSecKeyDataDuplicateMethod duplicate; */
1271     NULL,                                       /* xmlSecKeyDataFinalizeMethod finalize; */
1272     NULL,                                       /* xmlSecKeyDataGenerateMethod generate; */
1273 
1274     /* get info */
1275     NULL,                                       /* xmlSecKeyDataGetTypeMethod getType; */
1276     NULL,                                       /* xmlSecKeyDataGetSizeMethod getSize; */
1277     NULL,                                       /* xmlSecKeyDataGetIdentifier getIdentifier; */
1278 
1279     /* read/write */
1280     xmlSecKeyDataEncryptedKeyXmlRead,           /* xmlSecKeyDataXmlReadMethod xmlRead; */
1281     xmlSecKeyDataEncryptedKeyXmlWrite,          /* xmlSecKeyDataXmlWriteMethod xmlWrite; */
1282     NULL,                                       /* xmlSecKeyDataBinReadMethod binRead; */
1283     NULL,                                       /* xmlSecKeyDataBinWriteMethod binWrite; */
1284 
1285     /* debug */
1286     NULL,                                       /* xmlSecKeyDataDebugDumpMethod debugDump; */
1287     NULL,                                       /* xmlSecKeyDataDebugDumpMethod debugXmlDump; */
1288 
1289     /* reserved for the future */
1290     NULL,                                       /* void* reserved0; */
1291     NULL,                                       /* void* reserved1; */
1292 };
1293 
1294 /**
1295  * xmlSecKeyDataEncryptedKeyGetKlass:
1296  *
1297  * The <enc:EncryptedKey/> element key data klass
1298  * (http://www.w3.org/TR/xmlenc-core/#sec-EncryptedKey):
1299  *
1300  * The EncryptedKey element is used to transport encryption keys from
1301  * the originator to a known recipient(s). It may be used as a stand-alone
1302  * XML document, be placed within an application document, or appear inside
1303  * an EncryptedData element as a child of a ds:KeyInfo element. The key value
1304  * is always encrypted to the recipient(s). When EncryptedKey is decrypted the
1305  * resulting octets are made available to the EncryptionMethod algorithm
1306  * without any additional processing.
1307  *
1308  * Returns: the <enc:EncryptedKey/> element processing key data klass.
1309  */
1310 xmlSecKeyDataId
xmlSecKeyDataEncryptedKeyGetKlass(void)1311 xmlSecKeyDataEncryptedKeyGetKlass(void) {
1312     return(&xmlSecKeyDataEncryptedKeyKlass);
1313 }
1314 
1315 static int
xmlSecKeyDataEncryptedKeyXmlRead(xmlSecKeyDataId id,xmlSecKeyPtr key,xmlNodePtr node,xmlSecKeyInfoCtxPtr keyInfoCtx)1316 xmlSecKeyDataEncryptedKeyXmlRead(xmlSecKeyDataId id, xmlSecKeyPtr key, xmlNodePtr node, xmlSecKeyInfoCtxPtr keyInfoCtx) {
1317     xmlSecBufferPtr result;
1318     int ret;
1319 
1320     xmlSecAssert2(id == xmlSecKeyDataEncryptedKeyId, -1);
1321     xmlSecAssert2(key != NULL, -1);
1322     xmlSecAssert2(node != NULL, -1);
1323     xmlSecAssert2(keyInfoCtx != NULL, -1);
1324     xmlSecAssert2(keyInfoCtx->mode == xmlSecKeyInfoModeRead, -1);
1325 
1326     /* check the enc level */
1327     if(keyInfoCtx->curEncryptedKeyLevel >= keyInfoCtx->maxEncryptedKeyLevel) {
1328         xmlSecOtherError3(XMLSEC_ERRORS_R_MAX_ENCKEY_LEVEL,
1329                           xmlSecKeyDataKlassGetName(id),
1330                           "cur=%d;max=%d",
1331                           (int)keyInfoCtx->curEncryptedKeyLevel,
1332                           (int)keyInfoCtx->maxEncryptedKeyLevel);
1333         return(-1);
1334     }
1335     ++keyInfoCtx->curEncryptedKeyLevel;
1336 
1337     /* init Enc context */
1338     if(keyInfoCtx->encCtx != NULL) {
1339         xmlSecEncCtxReset(keyInfoCtx->encCtx);
1340     } else {
1341         ret = xmlSecKeyInfoCtxCreateEncCtx(keyInfoCtx);
1342         if(ret < 0) {
1343             xmlSecInternalError("xmlSecKeyInfoCtxCreateEncCtx",
1344                                 xmlSecKeyDataKlassGetName(id));
1345             return(-1);
1346         }
1347     }
1348     xmlSecAssert2(keyInfoCtx->encCtx != NULL, -1);
1349 
1350     result = xmlSecEncCtxDecryptToBuffer(keyInfoCtx->encCtx, node);
1351     if((result == NULL) || (xmlSecBufferGetData(result) == NULL)) {
1352         /* We might have multiple EncryptedKey elements, encrypted
1353          * for different recipients but application can enforce
1354          * correct enc key.
1355          */
1356         if((keyInfoCtx->flags & XMLSEC_KEYINFO_FLAGS_ENCKEY_DONT_STOP_ON_FAILED_DECRYPTION) != 0) {
1357             xmlSecInternalError("xmlSecEncCtxDecryptToBuffer",
1358                                 xmlSecKeyDataKlassGetName(id));
1359             return(-1);
1360         }
1361         return(0);
1362     }
1363 
1364     ret = xmlSecKeyDataBinRead(keyInfoCtx->keyReq.keyId, key,
1365                            xmlSecBufferGetData(result),
1366                            xmlSecBufferGetSize(result),
1367                            keyInfoCtx);
1368     if(ret < 0) {
1369         xmlSecInternalError("xmlSecKeyDataBinRead",
1370                             xmlSecKeyDataKlassGetName(id));
1371         return(-1);
1372     }
1373     --keyInfoCtx->curEncryptedKeyLevel;
1374 
1375     return(0);
1376 }
1377 
1378 static int
xmlSecKeyDataEncryptedKeyXmlWrite(xmlSecKeyDataId id,xmlSecKeyPtr key,xmlNodePtr node,xmlSecKeyInfoCtxPtr keyInfoCtx)1379 xmlSecKeyDataEncryptedKeyXmlWrite(xmlSecKeyDataId id, xmlSecKeyPtr key, xmlNodePtr node, xmlSecKeyInfoCtxPtr keyInfoCtx) {
1380     xmlSecKeyInfoCtx keyInfoCtx2;
1381     xmlSecByte *keyBuf = NULL;
1382     xmlSecSize keySize = 0;
1383     int res = -1;
1384     int ret;
1385 
1386     xmlSecAssert2(id == xmlSecKeyDataEncryptedKeyId, -1);
1387     xmlSecAssert2(key != NULL, -1);
1388     xmlSecAssert2(xmlSecKeyIsValid(key), -1);
1389     xmlSecAssert2(node != NULL, -1);
1390     xmlSecAssert2(keyInfoCtx != NULL, -1);
1391     xmlSecAssert2(keyInfoCtx->mode == xmlSecKeyInfoModeWrite, -1);
1392 
1393     /* dump key to a binary buffer */
1394     ret = xmlSecKeyInfoCtxInitialize(&keyInfoCtx2, NULL);
1395     if(ret < 0) {
1396         xmlSecInternalError("xmlSecKeyInfoCtxInitialize",
1397                             xmlSecKeyDataKlassGetName(id));
1398         goto done;
1399     }
1400 
1401     ret = xmlSecKeyInfoCtxCopyUserPref(&keyInfoCtx2, keyInfoCtx);
1402     if(ret < 0) {
1403         xmlSecInternalError("xmlSecKeyInfoCtxCopyUserPref",
1404                             xmlSecKeyDataKlassGetName(id));
1405         xmlSecKeyInfoCtxFinalize(&keyInfoCtx2);
1406         goto done;
1407     }
1408 
1409     keyInfoCtx2.keyReq.keyType = xmlSecKeyDataTypeAny;
1410     ret = xmlSecKeyDataBinWrite(key->value->id, key, &keyBuf, &keySize, &keyInfoCtx2);
1411     if(ret < 0) {
1412         xmlSecInternalError("xmlSecKeyDataBinWrite",
1413                             xmlSecKeyDataKlassGetName(id));
1414         xmlSecKeyInfoCtxFinalize(&keyInfoCtx2);
1415         goto done;
1416     }
1417     xmlSecKeyInfoCtxFinalize(&keyInfoCtx2);
1418 
1419     /* init Enc context */
1420     if(keyInfoCtx->encCtx != NULL) {
1421         xmlSecEncCtxReset(keyInfoCtx->encCtx);
1422     } else {
1423         ret = xmlSecKeyInfoCtxCreateEncCtx(keyInfoCtx);
1424         if(ret < 0) {
1425             xmlSecInternalError("xmlSecKeyInfoCtxCreateEncCtx",
1426                                 xmlSecKeyDataKlassGetName(id));
1427             goto done;
1428         }
1429     }
1430     xmlSecAssert2(keyInfoCtx->encCtx != NULL, -1);
1431 
1432     ret = xmlSecEncCtxBinaryEncrypt(keyInfoCtx->encCtx, node, keyBuf, keySize);
1433     if(ret < 0) {
1434         xmlSecInternalError("xmlSecEncCtxBinaryEncrypt",
1435                             xmlSecKeyDataKlassGetName(id));
1436         goto done;
1437     }
1438 
1439     res = 0;
1440 done:
1441     if(keyBuf != NULL) {
1442         memset(keyBuf, 0, keySize);
1443         xmlFree(keyBuf); keyBuf = NULL;
1444     }
1445     return(res);
1446 }
1447 
1448 #endif /* XMLSEC_NO_XMLENC */
1449 
1450