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