Git init
[external/xmlsec1.git] / src / keysmngr.c
1 /** 
2  * XML Security Library (http://www.aleksey.com/xmlsec).
3  *
4  * Keys Manager
5  * 
6  * This is free software; see Copyright file in the source
7  * distribution for preciese wording.
8  * 
9  * Copyright (C) 2002-2003 Aleksey Sanin <aleksey@aleksey.com>
10  */
11 #include "globals.h"
12
13 #include <stdlib.h>
14 #include <stdio.h>
15 #include <string.h>
16 #include <errno.h>
17
18 #include <libxml/tree.h>
19 #include <libxml/parser.h>
20
21 #include <xmlsec/xmlsec.h>
22 #include <xmlsec/xmltree.h>
23 #include <xmlsec/list.h>
24 #include <xmlsec/keys.h>
25 #include <xmlsec/transforms.h>
26 #include <xmlsec/keysmngr.h>
27 #include <xmlsec/errors.h>
28
29 /****************************************************************************
30  *
31  * Keys Manager
32  *
33  ***************************************************************************/
34 /** 
35  * xmlSecKeysMngrCreate:
36  * 
37  * Creates new keys manager. Caller is responsible for freeing it with 
38  * #xmlSecKeysMngrDestroy function.
39  * 
40  * Returns: the pointer to newly allocated keys manager or NULL if 
41  * an error occurs.
42  */
43 xmlSecKeysMngrPtr 
44 xmlSecKeysMngrCreate(void) {
45     xmlSecKeysMngrPtr mngr;
46     int ret;
47     
48     /* Allocate a new xmlSecKeysMngr and fill the fields. */
49     mngr = (xmlSecKeysMngrPtr)xmlMalloc(sizeof(xmlSecKeysMngr));
50     if(mngr == NULL) {
51         xmlSecError(XMLSEC_ERRORS_HERE,
52                     NULL,
53                     NULL,
54                     XMLSEC_ERRORS_R_MALLOC_FAILED,
55                     "sizeof(xmlSecKeysMngr)=%d", 
56                     sizeof(xmlSecKeysMngr));
57         return(NULL);
58     }
59     memset(mngr, 0, sizeof(xmlSecKeysMngr));    
60
61     ret = xmlSecPtrListInitialize(&(mngr->storesList), xmlSecKeyDataStorePtrListId);
62     if(ret < 0) {
63         xmlSecError(XMLSEC_ERRORS_HERE,
64                     NULL,
65                     "xmlSecPtrListInitialize",
66                     XMLSEC_ERRORS_R_XMLSEC_FAILED,
67                     "xmlSecKeyDataStorePtrListId");
68         return(NULL);
69     }
70
71     return(mngr);    
72 }
73
74 /** 
75  * xmlSecKeysMngrDestroy:
76  * @mngr:               the pointer to keys manager.
77  *
78  * Destroys keys manager created with #xmlSecKeysMngrCreate function.
79  */
80 void
81 xmlSecKeysMngrDestroy(xmlSecKeysMngrPtr mngr) {
82     xmlSecAssert(mngr != NULL);
83
84     /* destroy keys store */
85     if(mngr->keysStore != NULL) {
86         xmlSecKeyStoreDestroy(mngr->keysStore);
87     }
88     
89     /* destroy other data stores */
90     xmlSecPtrListFinalize(&(mngr->storesList));
91
92     memset(mngr, 0, sizeof(xmlSecKeysMngr));    
93     xmlFree(mngr);    
94 }
95
96 /**
97  * xmlSecKeysMngrFindKey:
98  * @mngr:               the pointer to keys manager.
99  * @name:               the desired key name.
100  * @keyInfoCtx:         the pointer to <dsig:KeyInfo/> node processing context.
101  *
102  * Lookups key in the keys manager keys store. The caller is responsible 
103  * for destroying the returned key using #xmlSecKeyDestroy method.
104  *
105  * Returns: the pointer to a key or NULL if key is not found or an error occurs.
106  */
107 xmlSecKeyPtr
108 xmlSecKeysMngrFindKey(xmlSecKeysMngrPtr mngr, const xmlChar* name, xmlSecKeyInfoCtxPtr keyInfoCtx) {
109     xmlSecKeyStorePtr store;
110     
111     xmlSecAssert2(mngr != NULL, NULL);
112     xmlSecAssert2(keyInfoCtx != NULL, NULL);
113     
114     store = xmlSecKeysMngrGetKeysStore(mngr);
115     if(store == NULL) {
116         /* no store. is it an error? */
117         return(NULL);
118     }
119     
120     return(xmlSecKeyStoreFindKey(store, name, keyInfoCtx));
121 }
122
123 /**
124  * xmlSecKeysMngrAdoptKeysStore:
125  * @mngr:               the pointer to keys manager.
126  * @store:              the pointer to keys store.
127  *
128  * Adopts keys store in the keys manager @mngr.
129  *
130  * Returns: 0 on success or a negative value if an error occurs.
131  */
132 int
133 xmlSecKeysMngrAdoptKeysStore(xmlSecKeysMngrPtr mngr, xmlSecKeyStorePtr store) {
134     xmlSecAssert2(mngr != NULL, -1);
135     xmlSecAssert2(xmlSecKeyStoreIsValid(store), -1);
136     
137     if(mngr->keysStore != NULL) {
138         xmlSecKeyStoreDestroy(mngr->keysStore);
139     }
140     mngr->keysStore = store;
141     
142     return(0);
143 }
144
145 /**
146  * xmlSecKeysMngrGetKeysStore:
147  * @mngr:               the pointer to keys manager.
148  *
149  * Gets the keys store.
150  *
151  * Returns: the keys store in the keys manager @mngr or NULL if 
152  * there is no store or an error occurs.
153  */
154 xmlSecKeyStorePtr
155 xmlSecKeysMngrGetKeysStore(xmlSecKeysMngrPtr mngr) {
156     xmlSecAssert2(mngr != NULL, NULL);
157     
158     return(mngr->keysStore);
159 }
160
161 /**
162  * xmlSecKeysMngrAdoptDataStore:
163  * @mngr:               the pointer to keys manager.
164  * @store:              the pointer to data store.
165  *
166  * Adopts data store in the keys manager.
167  *
168  * Returns: 0 on success or a negative value if an error occurs.
169  */
170 int
171 xmlSecKeysMngrAdoptDataStore(xmlSecKeysMngrPtr mngr, xmlSecKeyDataStorePtr store) {
172     xmlSecKeyDataStorePtr tmp;
173     xmlSecSize pos, size;
174     
175     xmlSecAssert2(mngr != NULL, -1);
176     xmlSecAssert2(xmlSecKeyDataStoreIsValid(store), -1);
177
178     size = xmlSecPtrListGetSize(&(mngr->storesList));
179     for(pos = 0; pos < size; ++pos) {
180         tmp = (xmlSecKeyDataStorePtr)xmlSecPtrListGetItem(&(mngr->storesList), pos);
181         if((tmp != NULL) && (tmp->id == store->id)) {   
182             return(xmlSecPtrListSet(&(mngr->storesList), store, pos));
183         }
184     }
185     
186     return(xmlSecPtrListAdd(&(mngr->storesList), store));
187 }
188
189
190 /**
191  * xmlSecKeysMngrGetDataStore:
192  * @mngr:               the pointer to keys manager.
193  * @id:                 the desired data store klass.
194  *
195  * Lookups the data store of given klass @id in the keys manager.
196  *
197  * Returns: pointer to data store or NULL if it is not found or an error
198  * occurs.
199  */
200 xmlSecKeyDataStorePtr 
201 xmlSecKeysMngrGetDataStore(xmlSecKeysMngrPtr mngr, xmlSecKeyDataStoreId id) {
202     xmlSecKeyDataStorePtr tmp;
203     xmlSecSize pos, size;
204     
205     xmlSecAssert2(mngr != NULL, NULL);
206     xmlSecAssert2(id != xmlSecKeyDataStoreIdUnknown, NULL);
207
208     size = xmlSecPtrListGetSize(&(mngr->storesList));
209     for(pos = 0; pos < size; ++pos) {
210         tmp = (xmlSecKeyDataStorePtr)xmlSecPtrListGetItem(&(mngr->storesList), pos);
211         if((tmp != NULL) && (tmp->id == id)) {  
212             return(tmp);
213         }
214     }
215     
216     return(NULL);
217 }
218
219 /**************************************************************************
220  *
221  * xmlSecKeyStore functions
222  *
223  *************************************************************************/
224 /**
225  * xmlSecKeyStoreCreate:
226  * @id:                 the key store klass.
227  *
228  * Creates new store of the specified klass @klass. Caller is responsible
229  * for freeing the returned store by calling #xmlSecKeyStoreDestroy function.
230  *
231  * Returns: the pointer to newly allocated keys store or NULL if an error occurs.
232  */
233 xmlSecKeyStorePtr       
234 xmlSecKeyStoreCreate(xmlSecKeyStoreId id)  {
235     xmlSecKeyStorePtr store;
236     int ret;
237         
238     xmlSecAssert2(id != NULL, NULL);
239     xmlSecAssert2(id->objSize > 0, NULL);
240         
241     /* Allocate a new xmlSecKeyStore and fill the fields. */
242     store = (xmlSecKeyStorePtr)xmlMalloc(id->objSize);
243     if(store == NULL) {
244         xmlSecError(XMLSEC_ERRORS_HERE,
245                     xmlSecErrorsSafeString(xmlSecKeyStoreKlassGetName(id)),
246                     NULL,
247                     XMLSEC_ERRORS_R_MALLOC_FAILED,
248                     "size=%d", id->objSize); 
249         return(NULL);
250     }
251     memset(store, 0, id->objSize);    
252     store->id = id;
253
254     if(id->initialize != NULL) {
255         ret = (id->initialize)(store);
256         if(ret < 0) {
257             xmlSecError(XMLSEC_ERRORS_HERE,
258                         xmlSecErrorsSafeString(xmlSecKeyStoreKlassGetName(id)),
259                         "id->initialize",
260                         XMLSEC_ERRORS_R_XMLSEC_FAILED,
261                         XMLSEC_ERRORS_NO_MESSAGE);
262             xmlSecKeyStoreDestroy(store);
263             return(NULL);
264         }
265     }
266     
267     return(store);
268 }
269
270 /**
271  * xmlSecKeyStoreDestroy:
272  * @store:              the pointer to keys store. 
273  *
274  * Destroys the store created with #xmlSecKeyStoreCreate function.
275  */
276 void
277 xmlSecKeyStoreDestroy(xmlSecKeyStorePtr store) {
278     xmlSecAssert(xmlSecKeyStoreIsValid(store));    
279     xmlSecAssert(store->id->objSize > 0);
280     
281     if(store->id->finalize != NULL) {  
282         (store->id->finalize)(store);
283     }
284     memset(store, 0, store->id->objSize);
285     xmlFree(store);
286 }
287
288 /**
289  * xmlSecKeyStoreFindKey:
290  * @store:              the pointer to keys store.
291  * @name:               the desired key name.
292  * @keyInfoCtx:         the pointer to <dsig:KeyInfo/> node processing context.
293  *
294  * Lookups key in the store. The caller is responsible for destroying 
295  * the returned key using #xmlSecKeyDestroy method.
296  *
297  * Returns: the pointer to a key or NULL if key is not found or an error occurs.
298  */
299 xmlSecKeyPtr
300 xmlSecKeyStoreFindKey(xmlSecKeyStorePtr store, const xmlChar* name, xmlSecKeyInfoCtxPtr keyInfoCtx) {
301     xmlSecAssert2(xmlSecKeyStoreIsValid(store), NULL);    
302     xmlSecAssert2(store->id->findKey != NULL, NULL);
303     xmlSecAssert2(keyInfoCtx != NULL, NULL);
304
305     return(store->id->findKey(store, name, keyInfoCtx));
306 }
307
308 /****************************************************************************
309  *
310  * Simple Keys Store
311  * 
312  * keys list (xmlSecPtrList) is located after xmlSecKeyStore
313  *
314  ***************************************************************************/
315 #define xmlSecSimpleKeysStoreSize \
316         (sizeof(xmlSecKeyStore) + sizeof(xmlSecPtrList))
317 #define xmlSecSimpleKeysStoreGetList(store) \
318     ((xmlSecKeyStoreCheckSize((store), xmlSecSimpleKeysStoreSize)) ? \
319         (xmlSecPtrListPtr)(((xmlSecByte*)(store)) + sizeof(xmlSecKeyStore)) : \
320         (xmlSecPtrListPtr)NULL)
321
322 static int                      xmlSecSimpleKeysStoreInitialize (xmlSecKeyStorePtr store);
323 static void                     xmlSecSimpleKeysStoreFinalize   (xmlSecKeyStorePtr store);
324 static xmlSecKeyPtr             xmlSecSimpleKeysStoreFindKey    (xmlSecKeyStorePtr store, 
325                                                                  const xmlChar* name, 
326                                                                  xmlSecKeyInfoCtxPtr keyInfoCtx);
327
328 static xmlSecKeyStoreKlass xmlSecSimpleKeysStoreKlass = {
329     sizeof(xmlSecKeyStoreKlass),
330     xmlSecSimpleKeysStoreSize,
331
332     /* data */
333     BAD_CAST "simple-keys-store",               /* const xmlChar* name; */ 
334         
335     /* constructors/destructor */
336     xmlSecSimpleKeysStoreInitialize,            /* xmlSecKeyStoreInitializeMethod initialize; */
337     xmlSecSimpleKeysStoreFinalize,              /* xmlSecKeyStoreFinalizeMethod finalize; */
338     xmlSecSimpleKeysStoreFindKey,               /* xmlSecKeyStoreFindKeyMethod findKey; */
339
340     /* reserved for the future */
341     NULL,                                       /* void* reserved0; */
342     NULL,                                       /* void* reserved1; */
343 };
344
345 /**
346  * xmlSecSimpleKeysStoreGetKlass:
347  * 
348  * The simple list based keys store klass.
349  *
350  * Returns: simple list based keys store klass.
351  */
352 xmlSecKeyStoreId 
353 xmlSecSimpleKeysStoreGetKlass(void) {
354     return(&xmlSecSimpleKeysStoreKlass);
355 }
356
357 /**
358  * xmlSecSimpleKeysStoreAdoptKey:
359  * @store:              the pointer to simple keys store.
360  * @key:                the pointer to key.
361  * 
362  * Adds @key to the @store. 
363  *
364  * Returns: 0 on success or a negative value if an error occurs.
365  */
366 int 
367 xmlSecSimpleKeysStoreAdoptKey(xmlSecKeyStorePtr store, xmlSecKeyPtr key) {
368     xmlSecPtrListPtr list;
369     int ret;
370     
371     xmlSecAssert2(xmlSecKeyStoreCheckId(store, xmlSecSimpleKeysStoreId), -1);
372     xmlSecAssert2(key != NULL, -1);
373
374     list = xmlSecSimpleKeysStoreGetList(store);
375     xmlSecAssert2(xmlSecPtrListCheckId(list, xmlSecKeyPtrListId), -1);
376
377     ret = xmlSecPtrListAdd(list, key);
378     if(ret < 0) {
379         xmlSecError(XMLSEC_ERRORS_HERE,
380                     xmlSecErrorsSafeString(xmlSecKeyStoreGetName(store)),
381                     "xmlSecPtrListAdd",
382                     XMLSEC_ERRORS_R_XMLSEC_FAILED,
383                     XMLSEC_ERRORS_NO_MESSAGE);
384         return(-1);
385     }
386
387     return(0);
388 }
389
390 /** 
391  * xmlSecSimpleKeysStoreLoad:
392  * @store:              the pointer to simple keys store.
393  * @uri:                the filename.
394  * @keysMngr:           the pointer to associated keys manager. 
395  * 
396  * Reads keys from an XML file.
397  *
398  * Returns: 0 on success or a negative value if an error occurs.
399  */
400 int
401 xmlSecSimpleKeysStoreLoad(xmlSecKeyStorePtr store, const char *uri, 
402                             xmlSecKeysMngrPtr keysMngr) {
403     xmlDocPtr doc;
404     xmlNodePtr root;
405     xmlNodePtr cur;
406     xmlSecKeyPtr key;
407     xmlSecKeyInfoCtx keyInfoCtx;
408     int ret;
409
410     xmlSecAssert2(xmlSecKeyStoreCheckId(store, xmlSecSimpleKeysStoreId), -1);
411     xmlSecAssert2(uri != NULL, -1);    
412
413     doc = xmlParseFile(uri);
414     if(doc == NULL) {
415         xmlSecError(XMLSEC_ERRORS_HERE,
416                     xmlSecErrorsSafeString(xmlSecKeyStoreGetName(store)),
417                     "xmlParseFile",
418                     XMLSEC_ERRORS_R_XML_FAILED,
419                     "uri=%s", 
420                     xmlSecErrorsSafeString(uri));
421         return(-1);
422     }
423     
424     root = xmlDocGetRootElement(doc);
425     if(!xmlSecCheckNodeName(root, BAD_CAST "Keys", xmlSecNs)) {
426         xmlSecError(XMLSEC_ERRORS_HERE,
427                     xmlSecErrorsSafeString(xmlSecKeyStoreGetName(store)),
428                     xmlSecErrorsSafeString(xmlSecNodeGetName(root)),
429                     XMLSEC_ERRORS_R_INVALID_NODE,
430                     "expected-node=<xmlsec:Keys>");
431         xmlFreeDoc(doc);
432         return(-1);
433     }
434         
435     cur = xmlSecGetNextElementNode(root->children);
436     while((cur != NULL) && xmlSecCheckNodeName(cur, xmlSecNodeKeyInfo, xmlSecDSigNs)) {  
437         key = xmlSecKeyCreate();
438         if(key == NULL) {
439             xmlSecError(XMLSEC_ERRORS_HERE,
440                         xmlSecErrorsSafeString(xmlSecKeyStoreGetName(store)),
441                         xmlSecErrorsSafeString(xmlSecNodeGetName(cur)),
442                         XMLSEC_ERRORS_R_INVALID_NODE,
443                         "expected-node=%s",
444                         xmlSecErrorsSafeString(xmlSecNodeKeyInfo));
445             xmlFreeDoc(doc);
446             return(-1);
447         }
448
449         ret = xmlSecKeyInfoCtxInitialize(&keyInfoCtx, NULL);
450         if(ret < 0) {
451             xmlSecError(XMLSEC_ERRORS_HERE,
452                         xmlSecErrorsSafeString(xmlSecKeyStoreGetName(store)),
453                         "xmlSecKeyInfoCtxInitialize",
454                         XMLSEC_ERRORS_R_XMLSEC_FAILED,
455                         XMLSEC_ERRORS_NO_MESSAGE);
456             xmlSecKeyDestroy(key);
457             xmlFreeDoc(doc);
458             return(-1);
459         }
460         
461         keyInfoCtx.mode           = xmlSecKeyInfoModeRead;
462         keyInfoCtx.keysMngr       = keysMngr;
463         keyInfoCtx.flags          = XMLSEC_KEYINFO_FLAGS_DONT_STOP_ON_KEY_FOUND |
464                                     XMLSEC_KEYINFO_FLAGS_X509DATA_DONT_VERIFY_CERTS;
465         keyInfoCtx.keyReq.keyId   = xmlSecKeyDataIdUnknown;
466         keyInfoCtx.keyReq.keyType = xmlSecKeyDataTypeAny;
467         keyInfoCtx.keyReq.keyUsage= xmlSecKeyDataUsageAny;
468
469         ret = xmlSecKeyInfoNodeRead(cur, key, &keyInfoCtx);
470         if(ret < 0) {
471             xmlSecError(XMLSEC_ERRORS_HERE,
472                         xmlSecErrorsSafeString(xmlSecKeyStoreGetName(store)),
473                         "xmlSecKeyInfoNodeRead",
474                         XMLSEC_ERRORS_R_XMLSEC_FAILED,
475                         XMLSEC_ERRORS_NO_MESSAGE);
476             xmlSecKeyInfoCtxFinalize(&keyInfoCtx);
477             xmlSecKeyDestroy(key);
478             xmlFreeDoc(doc);
479             return(-1);
480         }
481         xmlSecKeyInfoCtxFinalize(&keyInfoCtx);
482         
483         if(xmlSecKeyIsValid(key)) {
484             ret = xmlSecSimpleKeysStoreAdoptKey(store, key);
485             if(ret < 0) {
486                 xmlSecError(XMLSEC_ERRORS_HERE,
487                             xmlSecErrorsSafeString(xmlSecKeyStoreGetName(store)),
488                             "xmlSecSimpleKeysStoreAdoptKey",
489                             XMLSEC_ERRORS_R_XMLSEC_FAILED,
490                             XMLSEC_ERRORS_NO_MESSAGE);
491                 xmlSecKeyDestroy(key);
492                 xmlFreeDoc(doc);
493                 return(-1);
494             }
495         } else {
496             /* we have an unknown key in our file, just ignore it */
497             xmlSecKeyDestroy(key);
498         }
499         cur = xmlSecGetNextElementNode(cur->next);
500     }
501     
502     if(cur != NULL) {
503         xmlSecError(XMLSEC_ERRORS_HERE,
504                     xmlSecErrorsSafeString(xmlSecKeyStoreGetName(store)),
505                     xmlSecErrorsSafeString(xmlSecNodeGetName(cur)),
506                     XMLSEC_ERRORS_R_UNEXPECTED_NODE,
507                     XMLSEC_ERRORS_NO_MESSAGE);
508         xmlFreeDoc(doc);
509         return(-1);         
510     }
511     
512     xmlFreeDoc(doc);
513     return(0);
514
515 }
516
517 /** 
518  * xmlSecSimpleKeysStoreSave:
519  * @store:              the pointer to simple keys store.
520  * @filename:           the filename.
521  * @type:               the saved keys type (public, private, ...).
522  * 
523  * Writes keys from @store to an XML file.
524  *
525  * Returns: 0 on success or a negative value if an error occurs.
526  */
527 int
528 xmlSecSimpleKeysStoreSave(xmlSecKeyStorePtr store, const char *filename, xmlSecKeyDataType type) {
529     xmlSecKeyInfoCtx keyInfoCtx;
530     xmlSecPtrListPtr list;
531     xmlSecKeyPtr key;
532     xmlSecSize i, keysSize;    
533     xmlDocPtr doc;
534     xmlNodePtr cur;
535     xmlSecKeyDataPtr data;
536     xmlSecPtrListPtr idsList;
537     xmlSecKeyDataId dataId;
538     xmlSecSize idsSize, j;
539     int ret;
540
541     xmlSecAssert2(xmlSecKeyStoreCheckId(store, xmlSecSimpleKeysStoreId), -1);
542     xmlSecAssert2(filename != NULL, -1);    
543
544     list = xmlSecSimpleKeysStoreGetList(store);
545     xmlSecAssert2(xmlSecPtrListCheckId(list, xmlSecKeyPtrListId), -1);
546
547     /* create doc */
548     doc = xmlSecCreateTree(BAD_CAST "Keys", xmlSecNs);
549     if(doc == NULL) {
550         xmlSecError(XMLSEC_ERRORS_HERE,
551                     xmlSecErrorsSafeString(xmlSecKeyStoreGetName(store)),
552                     "xmlSecCreateTree",
553                     XMLSEC_ERRORS_R_XMLSEC_FAILED,
554                     XMLSEC_ERRORS_NO_MESSAGE);
555         return(-1);
556     }
557     
558     idsList = xmlSecKeyDataIdsGet();    
559     xmlSecAssert2(idsList != NULL, -1);
560         
561     keysSize = xmlSecPtrListGetSize(list);
562     idsSize = xmlSecPtrListGetSize(idsList);
563     for(i = 0; i < keysSize; ++i) {
564         key = (xmlSecKeyPtr)xmlSecPtrListGetItem(list, i);
565         xmlSecAssert2(key != NULL, -1);
566             
567         cur = xmlSecAddChild(xmlDocGetRootElement(doc), xmlSecNodeKeyInfo, xmlSecDSigNs);
568         if(cur == NULL) {
569             xmlSecError(XMLSEC_ERRORS_HERE,
570                         xmlSecErrorsSafeString(xmlSecKeyStoreGetName(store)),
571                         "xmlSecAddChild",
572                         XMLSEC_ERRORS_R_XMLSEC_FAILED,
573                         "node=%s",
574                         xmlSecErrorsSafeString(xmlSecNodeKeyInfo));
575             xmlFreeDoc(doc); 
576             return(-1);
577         }
578
579         /* special data key name */
580         if(xmlSecKeyGetName(key) != NULL) {
581             if(xmlSecAddChild(cur, xmlSecNodeKeyName, xmlSecDSigNs) == NULL) {
582                 xmlSecError(XMLSEC_ERRORS_HERE,
583                             xmlSecErrorsSafeString(xmlSecKeyStoreGetName(store)),
584                             "xmlSecAddChild",
585                             XMLSEC_ERRORS_R_XMLSEC_FAILED,
586                             "node=%s",
587                             xmlSecErrorsSafeString(xmlSecNodeKeyName));
588                 xmlFreeDoc(doc); 
589                 return(-1);
590             }
591         }
592     
593         /* create nodes for other keys data */
594         for(j = 0; j < idsSize; ++j) {
595             dataId = (xmlSecKeyDataId)xmlSecPtrListGetItem(idsList, j);
596             xmlSecAssert2(dataId != xmlSecKeyDataIdUnknown, -1);
597
598             if(dataId->dataNodeName == NULL) {
599                 continue;
600             }
601             
602             data = xmlSecKeyGetData(key, dataId);
603             if(data == NULL) {
604                 continue;
605             }
606
607             if(xmlSecAddChild(cur, dataId->dataNodeName, dataId->dataNodeNs) == NULL) {
608                 xmlSecError(XMLSEC_ERRORS_HERE,
609                             xmlSecErrorsSafeString(xmlSecKeyStoreGetName(store)),
610                             "xmlSecAddChild",
611                             XMLSEC_ERRORS_R_XMLSEC_FAILED,
612                             "node=%s", 
613                             xmlSecErrorsSafeString(dataId->dataNodeName));
614                 xmlFreeDoc(doc); 
615                 return(-1);
616             }
617         }
618
619         ret = xmlSecKeyInfoCtxInitialize(&keyInfoCtx, NULL);
620         if(ret < 0) {
621             xmlSecError(XMLSEC_ERRORS_HERE,
622                         xmlSecErrorsSafeString(xmlSecKeyStoreGetName(store)),
623                         "xmlSecKeyInfoCtxInitialize",
624                         XMLSEC_ERRORS_R_XMLSEC_FAILED,
625                         XMLSEC_ERRORS_NO_MESSAGE);
626             xmlFreeDoc(doc);
627             return(-1);
628         }
629
630         keyInfoCtx.mode                 = xmlSecKeyInfoModeWrite;
631         keyInfoCtx.keyReq.keyId         = xmlSecKeyDataIdUnknown;
632         keyInfoCtx.keyReq.keyType       = type;
633         keyInfoCtx.keyReq.keyUsage      = xmlSecKeyDataUsageAny;
634
635         /* finally write key in the node */
636         ret = xmlSecKeyInfoNodeWrite(cur, key, &keyInfoCtx);
637         if(ret < 0) {
638             xmlSecError(XMLSEC_ERRORS_HERE,
639                         xmlSecErrorsSafeString(xmlSecKeyStoreGetName(store)),
640                         "xmlSecKeyInfoNodeWrite",
641                         XMLSEC_ERRORS_R_XMLSEC_FAILED,
642                         XMLSEC_ERRORS_NO_MESSAGE);
643             xmlSecKeyInfoCtxFinalize(&keyInfoCtx);
644             xmlFreeDoc(doc); 
645             return(-1);
646         }               
647         xmlSecKeyInfoCtxFinalize(&keyInfoCtx);
648     }
649     
650     /* now write result */
651     ret = xmlSaveFormatFile(filename, doc, 1);
652     if(ret < 0) {
653         xmlSecError(XMLSEC_ERRORS_HERE,
654                     xmlSecErrorsSafeString(xmlSecKeyStoreGetName(store)),
655                     "xmlSaveFormatFile",
656                     XMLSEC_ERRORS_R_XML_FAILED,
657                     "filename=%s", 
658                     xmlSecErrorsSafeString(filename));
659         xmlFreeDoc(doc); 
660         return(-1);
661     }      
662     
663     xmlFreeDoc(doc);
664     return(0);
665 }
666
667 /** 
668  * xmlSecSimpleKeysStoreGetKeys:
669  * @store:              the pointer to simple keys store.
670  * 
671  * Gets list of keys from simple keys store.
672  * 
673  * Returns: pointer to the list of keys stored in the keys store or NULL
674  * if an error occurs.
675  */
676 xmlSecPtrListPtr 
677 xmlSecSimpleKeysStoreGetKeys(xmlSecKeyStorePtr store) {
678     xmlSecPtrListPtr list;
679
680     xmlSecAssert2(xmlSecKeyStoreCheckId(store, xmlSecSimpleKeysStoreId), NULL);
681
682     list = xmlSecSimpleKeysStoreGetList(store);
683     xmlSecAssert2(xmlSecPtrListCheckId(list, xmlSecKeyPtrListId), NULL);
684
685     return list;
686 }
687
688 static int
689 xmlSecSimpleKeysStoreInitialize(xmlSecKeyStorePtr store) {
690     xmlSecPtrListPtr list;
691     int ret;
692
693     xmlSecAssert2(xmlSecKeyStoreCheckId(store, xmlSecSimpleKeysStoreId), -1);
694
695     list = xmlSecSimpleKeysStoreGetList(store);
696     xmlSecAssert2(list != NULL, -1);
697     
698     ret = xmlSecPtrListInitialize(list, xmlSecKeyPtrListId);
699     if(ret < 0) {
700         xmlSecError(XMLSEC_ERRORS_HERE,
701                     xmlSecErrorsSafeString(xmlSecKeyStoreGetName(store)),
702                     "xmlSecPtrListInitialize",
703                     XMLSEC_ERRORS_R_XMLSEC_FAILED,
704                     "xmlSecKeyPtrListId");
705         return(-1);
706     }
707
708     return(0);    
709 }
710
711 static void
712 xmlSecSimpleKeysStoreFinalize(xmlSecKeyStorePtr store) {
713     xmlSecPtrListPtr list;
714     
715     xmlSecAssert(xmlSecKeyStoreCheckId(store, xmlSecSimpleKeysStoreId));
716     
717     list = xmlSecSimpleKeysStoreGetList(store);
718     xmlSecAssert(list != NULL);
719     
720     xmlSecPtrListFinalize(list);
721 }
722
723 static xmlSecKeyPtr 
724 xmlSecSimpleKeysStoreFindKey(xmlSecKeyStorePtr store, const xmlChar* name, 
725                             xmlSecKeyInfoCtxPtr keyInfoCtx) {
726     xmlSecPtrListPtr list;
727     xmlSecKeyPtr key;
728     xmlSecSize pos, size;
729
730     xmlSecAssert2(xmlSecKeyStoreCheckId(store, xmlSecSimpleKeysStoreId), NULL);
731     xmlSecAssert2(keyInfoCtx != NULL, NULL);
732
733     list = xmlSecSimpleKeysStoreGetList(store);
734     xmlSecAssert2(xmlSecPtrListCheckId(list, xmlSecKeyPtrListId), NULL);
735
736     size = xmlSecPtrListGetSize(list);
737     for(pos = 0; pos < size; ++pos) {
738         key = (xmlSecKeyPtr)xmlSecPtrListGetItem(list, pos);
739         if((key != NULL) && (xmlSecKeyMatch(key, name, &(keyInfoCtx->keyReq)) == 1)) {
740             return(xmlSecKeyDuplicate(key));
741         }
742     }
743     return(NULL);
744 }
745