xmlsecurityengine/xmlsec/src/xmlsec_keysdata.c
changeset 0 e35f40988205
child 24 74f0b3eb154c
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/xmlsecurityengine/xmlsec/src/xmlsec_keysdata.c	Thu Dec 17 09:29:21 2009 +0200
@@ -0,0 +1,1429 @@
+/** 
+ * XML Security Library (http://www.aleksey.com/xmlsec).
+ *
+ * Key data.
+ *
+ * This is free software; see Copyright file in the source
+ * distribution for preciese wording.
+ * 
+ * Copyright (C) 2002-2003 Aleksey Sanin <aleksey@aleksey.com>
+ * Portion Copyright © 2009 Nokia Corporation and/or its subsidiary(-ies). All rights reserved. 
+ */
+
+#include "xmlsec_globals.h"
+
+#include <stdlib.h>
+#include <string.h>
+ 
+#include <libxml2_tree.h>
+#include <libxml2_globals.h>
+
+#include "xmlsec_xmlsec.h"
+#include "xmlsec_xmltree.h"
+#include "xmlsec_keys.h"
+#include "xmlsec_keyinfo.h"
+#include "xmlsec_transforms.h"
+#include "xmlsec_base64.h"
+#include "xmlsec_keyinfo.h"
+#include "xmlsec_errors.h"
+
+
+/**************************************************************************
+ *
+ * Global xmlSecKeyDataIds list functions
+ *
+ *************************************************************************/
+static xmlSecPtrList xmlSecAllKeyDataIds;
+
+/** 
+ * xmlSecKeyDataIdsGet:
+ *
+ * Gets global registered key data klasses list.
+ * 
+ * Returns the pointer to list of all registered key data klasses.
+ */
+EXPORT_C
+xmlSecPtrListPtr
+xmlSecKeyDataIdsGet(void) {
+    return(&xmlSecAllKeyDataIds);
+}
+
+/** 
+ * xmlSecKeyDataIdsInit:
+ *
+ * Initializes the key data klasses. This function is called from the 
+ * #xmlSecInit function and the application should not call it directly.
+ *
+ * Returns 0 on success or a negative value if an error occurs.
+ */
+EXPORT_C
+int 
+xmlSecKeyDataIdsInit(void) {
+    int ret;
+    
+    ret = xmlSecPtrListInitialize(xmlSecKeyDataIdsGet(), xmlSecKeyDataIdListId);
+    if(ret < 0) {
+	xmlSecError(XMLSEC_ERRORS_HERE,
+		    NULL,
+		    "xmlSecPtrListPtrInitialize",
+		    XMLSEC_ERRORS_R_XMLSEC_FAILED,
+		    "xmlSecKeyDataIdListId");
+        return(-1);
+    }
+    
+    ret = xmlSecKeyDataIdsRegisterDefault();
+    if(ret < 0) {
+	xmlSecError(XMLSEC_ERRORS_HERE,
+		    NULL,
+		    "xmlSecKeyDataIdsRegisterDefault",
+		    XMLSEC_ERRORS_R_XMLSEC_FAILED,
+		    XMLSEC_ERRORS_NO_MESSAGE);
+        return(-1);
+    }
+    
+    return(0);
+}
+
+/**
+ * xmlSecKeyDataIdsShutdown:
+ * 
+ * Shuts down the keys data klasses. This function is called from the 
+ * #xmlSecShutdown function and the application should not call it directly.
+ */
+EXPORT_C
+void
+xmlSecKeyDataIdsShutdown(void) {
+    xmlSecPtrListFinalize(xmlSecKeyDataIdsGet());
+}
+
+/** 
+ * xmlSecKeyDataIdsRegister:
+ * @id:			the key data klass.
+ *
+ * Registers @id in the global list of key data klasses.
+ *
+ * Returns 0 on success or a negative value if an error occurs.
+ */
+EXPORT_C
+int 
+xmlSecKeyDataIdsRegister(xmlSecKeyDataId id) {
+    int ret;
+        
+    xmlSecAssert2(id != xmlSecKeyDataIdUnknown, -1);
+    
+    ret = xmlSecPtrListAdd(xmlSecKeyDataIdsGet(), (xmlSecPtr)id);
+    if(ret < 0) {
+	xmlSecError(XMLSEC_ERRORS_HERE,
+		    NULL,
+		    "xmlSecPtrListAdd",
+		    XMLSEC_ERRORS_R_XMLSEC_FAILED,
+		    "dataId=%s",
+		    xmlSecErrorsSafeString(xmlSecKeyDataKlassGetName(id)));
+        return(-1);
+    }
+    
+    return(0);    
+}
+
+/**
+ * xmlSecKeyDataIdsRegisterDefault:
+ *
+ * Registers default (implemented by XML Security Library)
+ * key data klasses: <dsig:KeyName/> element processing klass, 
+ * <dsig:KeyValue/> element processing klass, ...
+ *
+ * Returns 0 on success or a negative value if an error occurs.
+ */
+EXPORT_C
+int 
+xmlSecKeyDataIdsRegisterDefault(void) {
+    if(xmlSecKeyDataIdsRegister(xmlSecKeyDataNameId) < 0) {
+	xmlSecError(XMLSEC_ERRORS_HERE,
+		    NULL,
+		    "xmlSecKeyDataIdsRegister",
+		    XMLSEC_ERRORS_R_XMLSEC_FAILED,
+		    "xmlSecKeyDataNameId");
+        return(-1);	
+    }
+
+    if(xmlSecKeyDataIdsRegister(xmlSecKeyDataValueId) < 0) {
+	xmlSecError(XMLSEC_ERRORS_HERE,
+		    NULL,
+		    "xmlSecKeyDataIdsRegister",
+		    XMLSEC_ERRORS_R_XMLSEC_FAILED,
+		    "xmlSecKeyDataValueId");
+        return(-1);	
+    }
+
+    if(xmlSecKeyDataIdsRegister(xmlSecKeyDataRetrievalMethodId) < 0) {
+	xmlSecError(XMLSEC_ERRORS_HERE,
+		    NULL,
+		    "xmlSecKeyDataIdsRegister",
+		    XMLSEC_ERRORS_R_XMLSEC_FAILED,
+		    "xmlSecKeyDataRetrievalMethodId");
+        return(-1);	
+    }
+
+#ifndef XMLSEC_NO_XMLENC
+    if(xmlSecKeyDataIdsRegister(xmlSecKeyDataEncryptedKeyId) < 0) {
+	xmlSecError(XMLSEC_ERRORS_HERE,
+		    NULL,
+		    "xmlSecKeyDataIdsRegister",
+		    XMLSEC_ERRORS_R_XMLSEC_FAILED,
+		    "xmlSecKeyDataEncryptedKeyId");
+        return(-1);	
+    }
+#endif /* XMLSEC_NO_XMLENC */
+    
+    return(0);
+}
+
+/**************************************************************************
+ *
+ * xmlSecKeyData functions
+ *
+ *************************************************************************/
+/**
+ * xmlSecKeyDataCreate:
+ * @id: 		the data id.
+ *
+ * Allocates and initializes new key data of the specified type @id.
+ * Caller is responsible for destroing returend object with 
+ * #xmlSecKeyDataDestroy function.
+ *
+ * Returns the pointer to newly allocated key data structure
+ * or NULL if an error occurs.
+ */
+EXPORT_C
+xmlSecKeyDataPtr	
+xmlSecKeyDataCreate(xmlSecKeyDataId id)  {
+    xmlSecKeyDataPtr data;
+    int ret;
+        
+    xmlSecAssert2(id != NULL, NULL);
+    xmlSecAssert2(id->klassSize >= sizeof(xmlSecKeyDataKlass), NULL);
+    xmlSecAssert2(id->objSize >= sizeof(xmlSecKeyData), NULL);
+    xmlSecAssert2(id->name != NULL, NULL);
+        
+    /* Allocate a new xmlSecKeyData and fill the fields. */
+    data = (xmlSecKeyDataPtr)xmlMalloc(id->objSize);
+    if(data == NULL) {
+	xmlSecError(XMLSEC_ERRORS_HERE,
+		    xmlSecErrorsSafeString(xmlSecKeyDataKlassGetName(id)),
+		    NULL,
+		    XMLSEC_ERRORS_R_MALLOC_FAILED,
+		    "size=%d", id->objSize); 
+	return(NULL);
+    }
+    memset(data, 0, id->objSize);    
+    data->id = id;
+
+    if(id->initialize != NULL) {
+	ret = (id->initialize)(data);
+        if(ret < 0) {
+	    xmlSecError(XMLSEC_ERRORS_HERE,
+			xmlSecErrorsSafeString(xmlSecKeyDataKlassGetName(id)),
+			"id->initialize",
+			XMLSEC_ERRORS_R_XMLSEC_FAILED,
+			XMLSEC_ERRORS_NO_MESSAGE);
+	    xmlSecKeyDataDestroy(data);
+	    return(NULL);
+	}
+    }
+    
+    return(data);
+}
+
+/**
+ * xmlSecKeyDataDuplicate:
+ * @data: 		the pointer to the key data.
+ *
+ * Creates a duplicate of the given @data. Caller is responsible for 
+ * destroing returend object with #xmlSecKeyDataDestroy function.
+ *
+ * Returns the pointer to newly allocated key data structure
+ * or NULL if an error occurs.
+ */
+EXPORT_C
+xmlSecKeyDataPtr	
+xmlSecKeyDataDuplicate(xmlSecKeyDataPtr data) {
+    xmlSecKeyDataPtr newData;
+    int ret;
+
+    xmlSecAssert2(xmlSecKeyDataIsValid(data), NULL);
+    xmlSecAssert2(data->id->duplicate != NULL, NULL);
+
+    newData = xmlSecKeyDataCreate(data->id);
+    if(newData == NULL) {
+	xmlSecError(XMLSEC_ERRORS_HERE,
+		    xmlSecErrorsSafeString(xmlSecKeyDataGetName(data)),
+		    "xmlSecKeyDataCreate",
+		    XMLSEC_ERRORS_R_XMLSEC_FAILED,
+		    XMLSEC_ERRORS_NO_MESSAGE); 
+	return(NULL);
+    }
+
+    ret = (data->id->duplicate)(newData, data);
+    
+    if(newData == NULL || ret<0) {
+	xmlSecError(XMLSEC_ERRORS_HERE,
+		    xmlSecErrorsSafeString(xmlSecKeyDataGetName(data)),
+		    "id->duplicate",
+		    XMLSEC_ERRORS_R_XMLSEC_FAILED,
+		    XMLSEC_ERRORS_NO_MESSAGE);
+	xmlSecKeyDataDestroy(newData);
+	return(NULL);	
+    }
+    xmlSecKeyDataDestroy(data);
+    return(newData);
+}
+
+/**
+ * xmlSecKeyDataDestroy:
+ * @data: 		the pointer to the key data.
+ *
+ * Destroys the data and frees all allocated memory. 
+ */
+EXPORT_C
+void
+xmlSecKeyDataDestroy(xmlSecKeyDataPtr data) {
+    xmlSecAssert(xmlSecKeyDataIsValid(data));    
+    xmlSecAssert(data->id->objSize > 0);
+    
+    if(data->id->finalize != NULL) { 
+	(data->id->finalize)(data);
+    }
+    memset(data, 0, data->id->objSize);
+    xmlFree(data);
+}
+
+
+/**
+ * xmlSecKeyDataXmlRead:
+ * @id: 		the data klass.
+ * @key: 		the destination key.
+ * @node: 		the pointer to an XML node.
+ * @keyInfoCtx: 	the pointer to <dsig:KeyInfo/> element processing context.
+ * 
+ * Reads the key data of klass @id from XML @node and adds them to @key.
+ *
+ * Returns 0 on success or a negative value otherwise.
+ */
+EXPORT_C
+int
+xmlSecKeyDataXmlRead(xmlSecKeyDataId id, xmlSecKeyPtr key, xmlNodePtr node, xmlSecKeyInfoCtxPtr keyInfoCtx) {
+    xmlSecAssert2(id != NULL, -1);
+    xmlSecAssert2(id->xmlRead != NULL, -1);
+    xmlSecAssert2(key != NULL, -1);
+    xmlSecAssert2(node != NULL, -1);
+
+    return((id->xmlRead)(id, key, node, keyInfoCtx));
+}
+
+/**
+ * xmlSecKeyDataXmlWrite:
+ * @id: 		the data klass.
+ * @key: 		the source key.
+ * @node: 		the pointer to an XML node.
+ * @keyInfoCtx: 	the pointer to <dsig:KeyInfo/> element processing context.
+ * 
+ * Writes the key data of klass @id from @key to an XML @node.
+ *
+ * Returns 0 on success or a negative value otherwise.
+ */
+EXPORT_C
+int
+xmlSecKeyDataXmlWrite(xmlSecKeyDataId id, xmlSecKeyPtr key, xmlNodePtr node, xmlSecKeyInfoCtxPtr keyInfoCtx) {
+    xmlSecAssert2(id != NULL, -1);
+    xmlSecAssert2(id->xmlWrite != NULL, -1);
+    xmlSecAssert2(key != NULL, -1);
+    xmlSecAssert2(node != NULL, -1);
+
+    return((id->xmlWrite)(id, key, node, keyInfoCtx));
+}
+
+/** 
+ * xmlSecKeyDataBinRead:
+ * @id: 		the data klass.
+ * @key: 		the destination key.
+ * @buf: 		the input binary buffer.
+ * @bufSize: 		the input buffer size.
+ * @keyInfoCtx: 	the <dsig:KeyInfo/> node processing context.
+ *
+ * Reads the key data of klass @id from binary buffer @buf to @key.
+ * 
+ * Returns 0 on success or a negative value if an error occurs.
+ */
+EXPORT_C
+int
+xmlSecKeyDataBinRead(xmlSecKeyDataId id, xmlSecKeyPtr key, 
+		    const xmlSecByte* buf, xmlSecSize bufSize, 
+		    xmlSecKeyInfoCtxPtr keyInfoCtx) {
+    xmlSecAssert2(id != NULL, -1);
+    xmlSecAssert2(id->binRead != NULL, -1);
+    xmlSecAssert2(key != NULL, -1);
+    xmlSecAssert2(buf != NULL, -1);
+
+    return((id->binRead)(id, key, buf, bufSize, keyInfoCtx));
+}
+
+/** 
+ * xmlSecKeyDataBinWrite:
+ * @id: 		the data klass.
+ * @key: 		the source key.
+ * @buf: 		the output binary buffer.
+ * @bufSize: 		the output buffer size.
+ * @keyInfoCtx: 	the <dsig:KeyInfo/> node processing context.
+ *
+ * Writes the key data of klass @id from the @key to a binary buffer @buf. 
+ * 
+ * Returns 0 on success or a negative value if an error occurs.
+ */
+EXPORT_C
+int
+xmlSecKeyDataBinWrite(xmlSecKeyDataId id, xmlSecKeyPtr key, 
+		    xmlSecByte** buf, xmlSecSize* bufSize, 
+		    xmlSecKeyInfoCtxPtr keyInfoCtx) {
+    xmlSecAssert2(id != NULL, -1);
+    xmlSecAssert2(id->binWrite != NULL, -1);
+    xmlSecAssert2(key != NULL, -1);
+    xmlSecAssert2(buf != NULL, -1);
+
+    return((id->binWrite)(id, key, buf, bufSize, keyInfoCtx));
+}
+
+/** 
+ * xmlSecKeyDataGenerate:
+ * @data: 		the pointer to key data.
+ * @sizeBits: 		the desired key data size (in bits).
+ * @type:		the desired key data type.
+ *
+ * Generates new key data of given size and type.
+ *
+ * Returns 0 on success or a negative value otherwise.
+ */
+EXPORT_C
+int
+xmlSecKeyDataGenerate(xmlSecKeyDataPtr data, xmlSecSize sizeBits, 
+		      xmlSecKeyDataType type) {
+    int ret;
+
+    xmlSecAssert2(xmlSecKeyDataIsValid(data), -1);
+    xmlSecAssert2(data->id->generate != NULL, -1);
+    
+    /* write data */
+    ret = data->id->generate(data, sizeBits, type);
+    if(ret < 0) {
+	xmlSecError(XMLSEC_ERRORS_HERE,
+		    xmlSecErrorsSafeString(xmlSecKeyDataGetName(data)),
+		    "id->generate",
+		    XMLSEC_ERRORS_R_XMLSEC_FAILED,
+		    "size=%d", sizeBits);
+	return(-1);	    
+    }
+    return(0);    
+}
+
+/** 
+ * xmlSecKeyDataGetType:
+ * @data: 		the pointer to key data.
+ *
+ * Gets key data type.
+ *
+ * Returns key data type.
+ */
+EXPORT_C  
+xmlSecKeyDataType	
+xmlSecKeyDataGetType(xmlSecKeyDataPtr data) {
+    xmlSecAssert2(xmlSecKeyDataIsValid(data), xmlSecKeyDataTypeUnknown);
+    xmlSecAssert2(data->id->getType != NULL, xmlSecKeyDataTypeUnknown);
+    
+    return(data->id->getType(data));
+}
+
+/** 
+ * xmlSecKeyDataGetSize:
+ * @data: 		the pointer to key data.
+ *
+ * Gets key data size.
+ *
+ * Returns key data size (in bits).
+ */
+EXPORT_C
+xmlSecSize
+xmlSecKeyDataGetSize(xmlSecKeyDataPtr data) {
+    xmlSecAssert2(xmlSecKeyDataIsValid(data), 0);
+    xmlSecAssert2(data->id->getSize != NULL, 0);
+    
+    return(data->id->getSize(data));
+}
+
+/**
+ * xmlSecKeyDataGetIdentifier:
+ * @data: 		the pointer to key data.
+ * 
+ * Gets key data identifier string.
+ *
+ * Returns key data id string.
+ */
+EXPORT_C
+const xmlChar*
+xmlSecKeyDataGetIdentifier(xmlSecKeyDataPtr data) {
+    xmlSecAssert2(xmlSecKeyDataIsValid(data), NULL);
+    xmlSecAssert2(data->id->getIdentifier != NULL, NULL);
+    
+    return(data->id->getIdentifier(data));
+}
+
+/** 
+ * xmlSecKeyDataDebugDump:
+ * @data: 		the pointer to key data.
+ * @output: 		the pointer to output FILE.
+ *
+ * Prints key data debug info.
+ */
+EXPORT_C
+void
+xmlSecKeyDataDebugDump(xmlSecKeyDataPtr data, FILE *output) {
+    xmlSecAssert(xmlSecKeyDataIsValid(data));
+    xmlSecAssert(data->id->debugDump != NULL);
+    xmlSecAssert(output != NULL);
+    
+    data->id->debugDump(data, output);
+}
+
+/** 
+ * xmlSecKeyDataDebugXmlDump:
+ * @data: 		the pointer to key data.
+ * @output: 		the pointer to output FILE.
+ *
+ * Prints key data debug info in XML format.
+ */
+EXPORT_C 
+void 
+xmlSecKeyDataDebugXmlDump(xmlSecKeyDataPtr data, FILE *output) {
+    xmlSecAssert(xmlSecKeyDataIsValid(data));
+    xmlSecAssert(data->id->debugXmlDump != NULL);
+    xmlSecAssert(output != NULL);
+    
+    data->id->debugXmlDump(data, output);
+}
+
+/**************************************************************************
+ *
+ * xmlSecKeyDataBinary methods
+ *
+ * key (xmlSecBuffer) is located after xmlSecKeyData structure
+ *
+ *************************************************************************/
+/** 
+ * xmlSecKeyDataBinaryValueInitialize:
+ * @data: 		the pointer to binary key data.
+ *
+ * Initializes key data.
+ * 
+ * Returns 0 on success or a negative value otherwise.
+ */
+EXPORT_C
+int
+xmlSecKeyDataBinaryValueInitialize(xmlSecKeyDataPtr data) {
+    xmlSecBufferPtr buffer;
+    int ret;
+    
+    xmlSecAssert2(xmlSecKeyDataIsValid(data), -1);
+    xmlSecAssert2(xmlSecKeyDataCheckSize(data, xmlSecKeyDataBinarySize), -1);
+        
+    /* initialize buffer */
+    buffer = xmlSecKeyDataBinaryValueGetBuffer(data);
+    xmlSecAssert2(buffer != NULL, -1);
+    
+    ret = xmlSecBufferInitialize(buffer, 0);
+    if(ret < 0) {
+	xmlSecError(XMLSEC_ERRORS_HERE,
+		    xmlSecErrorsSafeString(xmlSecKeyDataGetName(data)),
+		    "xmlSecBufferInitialize",
+		    XMLSEC_ERRORS_R_XMLSEC_FAILED,
+		    XMLSEC_ERRORS_NO_MESSAGE);
+	return(-1);
+    }
+    
+    return(0);    
+}
+
+/** 
+ * xmlSecKeyDataBinaryValueDuplicate:
+ * @dst: 		the pointer to destination binary key data.
+ * @src: 		the pointer to source binary key data.
+ *
+ * Copies binary key data from @src to @dst.
+ * 
+ * Returns 0 on success or a negative value otherwise.
+ */
+EXPORT_C
+int
+xmlSecKeyDataBinaryValueDuplicate(xmlSecKeyDataPtr dst, xmlSecKeyDataPtr src) {
+    xmlSecBufferPtr buffer;
+    int ret;
+    
+    xmlSecAssert2(xmlSecKeyDataIsValid(dst), -1);
+    xmlSecAssert2(xmlSecKeyDataCheckSize(dst, xmlSecKeyDataBinarySize), -1);
+    xmlSecAssert2(xmlSecKeyDataIsValid(src), -1);
+    xmlSecAssert2(xmlSecKeyDataCheckSize(src, xmlSecKeyDataBinarySize), -1);
+
+    buffer = xmlSecKeyDataBinaryValueGetBuffer(src);
+    xmlSecAssert2(buffer != NULL, -1);
+    
+    /* copy data */
+    ret = xmlSecKeyDataBinaryValueSetBuffer(dst,
+		    xmlSecBufferGetData(buffer),
+		    xmlSecBufferGetSize(buffer));
+    if(ret < 0) {
+	xmlSecError(XMLSEC_ERRORS_HERE,
+		    xmlSecErrorsSafeString(xmlSecKeyDataGetName(dst)),
+		    "xmlSecKeyDataBinaryValueSetBuffer",
+		    XMLSEC_ERRORS_R_XMLSEC_FAILED,
+		    XMLSEC_ERRORS_NO_MESSAGE);
+	return(-1);
+    }
+
+    return(0);
+}
+
+/** 
+ * xmlSecKeyDataBinaryValueFinalize:
+ * @data: 		the pointer to binary key data.
+ *
+ * Cleans up binary key data.
+ */
+EXPORT_C
+void 
+xmlSecKeyDataBinaryValueFinalize(xmlSecKeyDataPtr data) {
+    xmlSecBufferPtr buffer;
+    
+    xmlSecAssert(xmlSecKeyDataIsValid(data));
+    xmlSecAssert(xmlSecKeyDataCheckSize(data, xmlSecKeyDataBinarySize));
+    
+    /* initialize buffer */
+    buffer = xmlSecKeyDataBinaryValueGetBuffer(data);
+    xmlSecAssert(buffer != NULL);
+    
+    xmlSecBufferFinalize(buffer);    
+}
+
+/** 
+ * xmlSecKeyDataBinaryValueXmlRead:
+ * @id: 		the data klass.
+ * @key:		the pointer to destination key.
+ * @node: 		the pointer to an XML node.
+ * @keyInfoCtx: 	the pointer to <dsig:KeyInfo/> element processing context.
+ *
+ * Reads binary key data from @node to the key by base64 decoding the @node content.
+ * 
+ * Returns 0 on success or a negative value otherwise.
+ */
+EXPORT_C
+int 
+xmlSecKeyDataBinaryValueXmlRead(xmlSecKeyDataId id, xmlSecKeyPtr key, 
+				xmlNodePtr node, xmlSecKeyInfoCtxPtr keyInfoCtx) {
+    xmlChar* str;
+    xmlSecSize len;
+    xmlSecKeyDataPtr data;
+    int ret;
+    
+    xmlSecAssert2(id != xmlSecKeyDataIdUnknown, -1);
+    xmlSecAssert2(key != NULL, -1);
+    xmlSecAssert2(node != NULL, -1);
+    xmlSecAssert2(keyInfoCtx != NULL, -1);
+
+    str = xmlNodeGetContent(node);
+    if(str == NULL) {
+	xmlSecError(XMLSEC_ERRORS_HERE, 
+		    xmlSecErrorsSafeString(xmlSecKeyDataKlassGetName(id)),
+		    xmlSecErrorsSafeString(xmlSecNodeGetName(node)),
+		    XMLSEC_ERRORS_R_INVALID_NODE_CONTENT,
+		    XMLSEC_ERRORS_NO_MESSAGE);
+	return(-1);
+    }
+
+    /* usual trick: decode into the same buffer */
+    ret = xmlSecBase64Decode(str, (xmlSecByte*)str, xmlStrlen(str));
+    if(ret < 0) {
+	xmlSecError(XMLSEC_ERRORS_HERE, 
+		    xmlSecErrorsSafeString(xmlSecKeyDataKlassGetName(id)),
+		    "xmlSecBase64Decode",
+		    XMLSEC_ERRORS_R_XMLSEC_FAILED,
+		    XMLSEC_ERRORS_NO_MESSAGE);
+	xmlFree(str);
+	return(-1);
+    }
+    len = ret;
+
+    /* check do we have a key already */
+    data = xmlSecKeyGetValue(key);
+    if(data != NULL) {
+	xmlSecBufferPtr buffer;
+	
+	if(!xmlSecKeyDataCheckId(data, id)) {
+	    xmlSecError(XMLSEC_ERRORS_HERE,
+			xmlSecErrorsSafeString(xmlSecKeyDataKlassGetName(id)),
+			xmlSecErrorsSafeString(xmlSecKeyDataGetName(data)),
+			XMLSEC_ERRORS_R_KEY_DATA_ALREADY_EXIST,
+			XMLSEC_ERRORS_NO_MESSAGE);
+	    xmlFree(str);
+	    return(-1);	
+	}
+	
+	buffer = xmlSecKeyDataBinaryValueGetBuffer(data);	
+	if((buffer != NULL) && ((xmlSecSize)xmlSecBufferGetSize(buffer) != len)) {
+	    xmlSecError(XMLSEC_ERRORS_HERE,
+			xmlSecErrorsSafeString(xmlSecKeyDataKlassGetName(id)),
+			xmlSecErrorsSafeString(xmlSecKeyDataGetName(data)),
+			XMLSEC_ERRORS_R_KEY_DATA_ALREADY_EXIST,
+			"cur-data-size=%d;new-data-size=%d",
+			xmlSecBufferGetSize(buffer), len);
+	    xmlFree(str);
+	    return(-1);		
+	}
+	if((buffer != NULL) && (len > 0) && (memcmp(xmlSecBufferGetData(buffer), str, len) != 0)) {
+	    xmlSecError(XMLSEC_ERRORS_HERE,
+			xmlSecErrorsSafeString(xmlSecKeyDataKlassGetName(id)),
+			xmlSecErrorsSafeString(xmlSecKeyDataGetName(data)),
+			XMLSEC_ERRORS_R_KEY_DATA_ALREADY_EXIST,
+			"key already has a different value");
+	    xmlFree(str);
+	    return(-1);		
+	}
+	if(buffer != NULL) {
+	    /* we already have exactly the same key */
+    	    xmlFree(str);
+	    return(0);
+	}
+	
+	/* we have binary key value with empty buffer */
+    }
+
+    
+    data = xmlSecKeyDataCreate(id);
+    if(data == NULL ) {
+	xmlSecError(XMLSEC_ERRORS_HERE,
+		    xmlSecErrorsSafeString(xmlSecKeyDataKlassGetName(id)),
+		    "xmlSecKeyDataCreate",
+		    XMLSEC_ERRORS_R_XMLSEC_FAILED,
+		    XMLSEC_ERRORS_NO_MESSAGE);
+	xmlFree(str);
+	return(-1);
+    }
+        
+    ret = xmlSecKeyDataBinaryValueSetBuffer(data, (xmlSecByte*)str, len);
+    if(ret < 0) {
+	xmlSecError(XMLSEC_ERRORS_HERE,
+		    xmlSecErrorsSafeString(xmlSecKeyDataKlassGetName(id)),
+		    "xmlSecKeyDataBinaryValueSetBuffer",
+		    XMLSEC_ERRORS_R_XMLSEC_FAILED,
+		    "size=%d", len);
+	xmlSecKeyDataDestroy(data);
+	xmlFree(str);
+	return(-1);
+    }
+    xmlFree(str);
+
+    if(xmlSecKeyReqMatchKeyValue(&(keyInfoCtx->keyReq), data) != 1) {
+	xmlSecError(XMLSEC_ERRORS_HERE,
+		    xmlSecErrorsSafeString(xmlSecKeyDataKlassGetName(id)),
+		    "xmlSecKeyReqMatchKeyValue",
+		    XMLSEC_ERRORS_R_XMLSEC_FAILED,
+		    XMLSEC_ERRORS_NO_MESSAGE);
+	xmlSecKeyDataDestroy(data);
+	return(0);
+    }
+    
+    ret = xmlSecKeySetValue(key, data);
+    if(ret < 0) {
+	xmlSecError(XMLSEC_ERRORS_HERE,
+		    xmlSecErrorsSafeString(xmlSecKeyDataKlassGetName(id)),
+		    "xmlSecKeySetValue",
+		    XMLSEC_ERRORS_R_XMLSEC_FAILED,
+		    XMLSEC_ERRORS_NO_MESSAGE);
+	xmlSecKeyDataDestroy(data);
+	return(-1);
+    }
+
+    return(0);
+}
+
+/** 
+ * xmlSecKeyDataBinaryValueXmlWrite:
+ * @id: 		the data klass.
+ * @key:		the pointer to source key.
+ * @node: 		the pointer to an XML node.
+ * @keyInfoCtx: 	the pointer to <dsig:KeyInfo/> element processing context.
+ *
+ * Base64 encodes binary key data of klass @id from the @key and 
+ * sets to the @node content. 
+ * 
+ * Returns 0 on success or a negative value otherwise.
+ */
+EXPORT_C
+int 
+xmlSecKeyDataBinaryValueXmlWrite(xmlSecKeyDataId id, xmlSecKeyPtr key, 
+			    xmlNodePtr node, xmlSecKeyInfoCtxPtr keyInfoCtx) {
+    xmlSecBufferPtr buffer;
+    xmlSecKeyDataPtr value;
+    xmlChar* str;
+    
+    xmlSecAssert2(id != xmlSecKeyDataIdUnknown, -1);
+    xmlSecAssert2(key != NULL, -1);
+    xmlSecAssert2(node != NULL, -1);
+    xmlSecAssert2(keyInfoCtx != NULL, -1);
+
+    if((xmlSecKeyDataTypeSymmetric & keyInfoCtx->keyReq.keyType) == 0) {
+	/* we can have only symmetric key */
+	return(0);
+    }    
+
+    value = xmlSecKeyGetValue(key);
+    xmlSecAssert2(xmlSecKeyDataIsValid(value), -1);
+
+    buffer = xmlSecKeyDataBinaryValueGetBuffer(value);
+    xmlSecAssert2(buffer != NULL, -1);
+
+    str = xmlSecBase64Encode(xmlSecBufferGetData(buffer),
+			     xmlSecBufferGetSize(buffer),
+			     keyInfoCtx->base64LineSize);
+    if(str == NULL) {
+	xmlSecError(XMLSEC_ERRORS_HERE, 
+		    xmlSecErrorsSafeString(xmlSecKeyDataKlassGetName(id)),
+		    "xmlSecBase64Encode",
+		    XMLSEC_ERRORS_R_XMLSEC_FAILED,
+		    XMLSEC_ERRORS_NO_MESSAGE);
+	return(-1);
+    }    
+    xmlNodeSetContent(node, str);
+    xmlFree(str);
+    return(0);
+}
+
+/** 
+ * xmlSecKeyDataBinaryValueBinRead:
+ * @id: 		the data klass.
+ * @key:		the pointer to destination key.
+ * @buf:		the source binary buffer.
+ * @bufSize:		the source binary buffer size.
+ * @keyInfoCtx: 	the pointer to <dsig:KeyInfo/> element processing context.
+ *
+ * Reads binary key data of the klass @id from @buf to the @key.
+ * 
+ * Returns 0 on success or a negative value otherwise.
+ */
+EXPORT_C
+int 
+xmlSecKeyDataBinaryValueBinRead(xmlSecKeyDataId id, xmlSecKeyPtr key, 
+				const xmlSecByte* buf, xmlSecSize bufSize, 
+				xmlSecKeyInfoCtxPtr keyInfoCtx) {
+    xmlSecKeyDataPtr data;
+    int ret;
+    
+    xmlSecAssert2(id != xmlSecKeyDataIdUnknown, -1);
+    xmlSecAssert2(key != NULL, -1);
+    xmlSecAssert2(buf != NULL, -1);
+    xmlSecAssert2(bufSize > 0, -1);
+    xmlSecAssert2(keyInfoCtx != NULL, -1);
+
+    /* check do we have a key already */
+    data = xmlSecKeyGetValue(key);
+    if(data != NULL) {
+	xmlSecBufferPtr buffer;
+	
+	if(!xmlSecKeyDataCheckId(data, id)) {
+	    xmlSecError(XMLSEC_ERRORS_HERE,
+			xmlSecErrorsSafeString(xmlSecKeyDataKlassGetName(id)),
+			xmlSecErrorsSafeString(xmlSecKeyDataGetName(data)),
+    			XMLSEC_ERRORS_R_KEY_DATA_ALREADY_EXIST,
+			XMLSEC_ERRORS_NO_MESSAGE);
+	    return(-1);	
+	}
+	
+	buffer = xmlSecKeyDataBinaryValueGetBuffer(data);	
+	if((buffer != NULL) && ((xmlSecSize)xmlSecBufferGetSize(buffer) != bufSize)) {
+	    xmlSecError(XMLSEC_ERRORS_HERE,
+			xmlSecErrorsSafeString(xmlSecKeyDataKlassGetName(id)),
+			xmlSecErrorsSafeString(xmlSecKeyDataGetName(data)),
+			XMLSEC_ERRORS_R_KEY_DATA_ALREADY_EXIST,
+			"cur-data-size=%d;new-data-size=%d",
+			xmlSecBufferGetSize(buffer), bufSize);
+	    return(-1);		
+	}
+	if((buffer != NULL) && (bufSize > 0) && (memcmp(xmlSecBufferGetData(buffer), buf, bufSize) != 0)) {
+	    xmlSecError(XMLSEC_ERRORS_HERE,
+			xmlSecErrorsSafeString(xmlSecKeyDataKlassGetName(id)),
+			xmlSecErrorsSafeString(xmlSecKeyDataGetName(data)),
+			XMLSEC_ERRORS_R_KEY_DATA_ALREADY_EXIST,
+			"key already has a different value");
+	    return(-1);		
+	}
+	if(buffer != NULL) {
+	    /* we already have exactly the same key */
+	    return(0);
+	}
+	
+	/* we have binary key value with empty buffer */
+    }
+    
+    data = xmlSecKeyDataCreate(id);
+    if(data == NULL ) {
+	xmlSecError(XMLSEC_ERRORS_HERE,
+		    xmlSecErrorsSafeString(xmlSecKeyDataKlassGetName(id)),
+		    "xmlSecKeyDataCreate",
+		    XMLSEC_ERRORS_R_XMLSEC_FAILED,
+		    XMLSEC_ERRORS_NO_MESSAGE);
+	return(-1);
+    }
+        
+    ret = xmlSecKeyDataBinaryValueSetBuffer(data, buf, bufSize);
+    if(ret < 0) {
+	xmlSecError(XMLSEC_ERRORS_HERE,
+		    xmlSecErrorsSafeString(xmlSecKeyDataKlassGetName(id)),
+		    "xmlSecKeyDataBinaryValueSetBuffer",
+		    XMLSEC_ERRORS_R_XMLSEC_FAILED,
+		    "size=%d", bufSize);
+	xmlSecKeyDataDestroy(data);
+	return(-1);
+    }
+
+    if(xmlSecKeyReqMatchKeyValue(&(keyInfoCtx->keyReq), data) != 1) {
+	xmlSecError(XMLSEC_ERRORS_HERE,
+		    xmlSecErrorsSafeString(xmlSecKeyDataKlassGetName(id)),
+		    "xmlSecKeyReqMatchKeyValue",
+		    XMLSEC_ERRORS_R_XMLSEC_FAILED,
+		    XMLSEC_ERRORS_NO_MESSAGE);
+	xmlSecKeyDataDestroy(data);
+	return(0);
+    }
+    
+    ret = xmlSecKeySetValue(key, data);
+    if(ret < 0) {
+	xmlSecError(XMLSEC_ERRORS_HERE,
+		    xmlSecErrorsSafeString(xmlSecKeyDataKlassGetName(id)),
+		    "xmlSecKeySetValue",
+		    XMLSEC_ERRORS_R_XMLSEC_FAILED,
+		    XMLSEC_ERRORS_NO_MESSAGE);
+	xmlSecKeyDataDestroy(data);
+	return(-1);
+    }
+
+    return(0);
+}
+
+/** 
+ * xmlSecKeyDataBinaryValueBinWrite:
+ * @id: 		the data klass.
+ * @key:		the pointer to source key.
+ * @buf:		the destination binary buffer.
+ * @bufSize:		the destination binary buffer size.
+ * @keyInfoCtx: 	the pointer to <dsig:KeyInfo/> element processing context.
+ *
+ * Writes binary key data of klass @id from the @key to @buf.
+ * 
+ * Returns 0 on success or a negative value otherwise.
+ */
+EXPORT_C
+int 
+xmlSecKeyDataBinaryValueBinWrite(xmlSecKeyDataId id, xmlSecKeyPtr key, 
+				xmlSecByte** buf, xmlSecSize* bufSize, 
+				xmlSecKeyInfoCtxPtr keyInfoCtx) {
+    xmlSecKeyDataPtr value;
+    xmlSecBufferPtr buffer;
+
+    xmlSecAssert2(id != xmlSecKeyDataIdUnknown, -1);
+    xmlSecAssert2(key != NULL, -1);
+    xmlSecAssert2(buf != NULL, -1);
+    xmlSecAssert2(bufSize != NULL, -1);
+    xmlSecAssert2(keyInfoCtx != NULL, -1);
+
+    if((xmlSecKeyDataTypeSymmetric & keyInfoCtx->keyReq.keyType) == 0) {
+	/* we can have only symmetric key */
+	return(0);
+    }    
+
+    value = xmlSecKeyGetValue(key);
+    xmlSecAssert2(xmlSecKeyDataIsValid(value), -1);
+
+    buffer = xmlSecKeyDataBinaryValueGetBuffer(key->value);
+    xmlSecAssert2(buffer != NULL, -1);
+
+    (*bufSize) = xmlSecBufferGetSize(buffer);
+    (*buf) = (xmlSecByte*) xmlMalloc((*bufSize));
+    if((*buf) == NULL) {
+	xmlSecError(XMLSEC_ERRORS_HERE,
+		    xmlSecErrorsSafeString(xmlSecKeyDataKlassGetName(id)),
+		    NULL,
+		    XMLSEC_ERRORS_R_MALLOC_FAILED,
+		    XMLSEC_ERRORS_NO_MESSAGE);
+	return(-1);
+    }
+    memcpy((*buf), xmlSecBufferGetData(buffer), (*bufSize));    
+    return(0);
+}
+
+/** 
+ * xmlSecKeyDataBinaryValueDebugDump:
+ * @data: 		the pointer to binary key data.
+ * @output:		the pointer to output FILE.
+ * 
+ * Prints binary key data debug information to @output.
+ */
+EXPORT_C
+void 
+xmlSecKeyDataBinaryValueDebugDump(xmlSecKeyDataPtr data, FILE* output) {
+    xmlSecBufferPtr buffer;
+    
+    xmlSecAssert(xmlSecKeyDataIsValid(data));
+    xmlSecAssert(xmlSecKeyDataCheckSize(data, xmlSecKeyDataBinarySize));
+    xmlSecAssert(data->id->dataNodeName != NULL);
+    xmlSecAssert(output != NULL);
+
+    buffer = xmlSecKeyDataBinaryValueGetBuffer(data);
+    xmlSecAssert(buffer != NULL);
+
+    /* print only size, everything else is sensitive */    
+    fprintf(output, "=== %s: size=%d\n", data->id->dataNodeName, 
+					 xmlSecKeyDataGetSize(data));
+}
+
+/** 
+ * xmlSecKeyDataBinaryValueDebugXmlDump:
+ * @data: 		the pointer to binary key data.
+ * @output:		the pointer to output FILE.
+ * 
+ * Prints binary key data debug information to @output in XML format.
+ */
+EXPORT_C
+void 
+xmlSecKeyDataBinaryValueDebugXmlDump(xmlSecKeyDataPtr data, FILE* output) {
+    xmlSecBufferPtr buffer;
+
+    xmlSecAssert(xmlSecKeyDataIsValid(data));
+    xmlSecAssert(xmlSecKeyDataCheckSize(data, xmlSecKeyDataBinarySize));
+    xmlSecAssert(data->id->dataNodeName != NULL);
+    xmlSecAssert(output != NULL);
+
+    buffer = xmlSecKeyDataBinaryValueGetBuffer(data);
+    xmlSecAssert(buffer != NULL);
+    
+    /* print only size, everything else is sensitive */    
+    fprintf(output, "<%s size=\"%d\" />\n", data->id->dataNodeName, 
+					    xmlSecKeyDataGetSize(data));
+}
+
+/** 
+ * xmlSecKeyDataBinaryValueGetSize:
+ * @data: 		the pointer to binary key data.
+ *
+ * Gets the binary key data size.
+ *
+ * Returns binary key data size in bits.
+ */
+EXPORT_C
+xmlSecSize
+xmlSecKeyDataBinaryValueGetSize(xmlSecKeyDataPtr data) {
+    xmlSecBufferPtr buffer;
+
+    xmlSecAssert2(xmlSecKeyDataIsValid(data), 0);
+    xmlSecAssert2(xmlSecKeyDataCheckSize(data, xmlSecKeyDataBinarySize), 0);
+
+    buffer = xmlSecKeyDataBinaryValueGetBuffer(data);
+    xmlSecAssert2(buffer != NULL, 0);
+
+    /* return size in bits */    
+    return(8 * xmlSecBufferGetSize(buffer));    
+}
+
+/** 
+ * xmlSecKeyDataBinaryValueGetBuffer:
+ * @data: 		the pointer to binary key data.
+ *
+ * Gets the binary key data buffer.
+ *
+ * Returns pointer to binary key data buffer.
+ */
+EXPORT_C
+xmlSecBufferPtr 
+xmlSecKeyDataBinaryValueGetBuffer(xmlSecKeyDataPtr data) {
+    xmlSecAssert2(xmlSecKeyDataIsValid(data), NULL);
+    xmlSecAssert2(xmlSecKeyDataCheckSize(data, xmlSecKeyDataBinarySize), NULL);
+
+    /* key (xmlSecBuffer) is located after xmlSecKeyData structure */
+    return((xmlSecBufferPtr)(((xmlSecByte*)data) + sizeof(xmlSecKeyData)));
+}
+
+/** 
+ * xmlSecKeyDataBinaryValueSetBuffer:
+ * @data: 		the pointer to binary key data.
+ * @buf: 		the pointer to binary buffer.
+ * @bufSize:		the binary buffer size.
+ *
+ * Sets the value of @data to @buf.
+ * 
+ * Returns 0 on success or a negative value otherwise.
+ */
+EXPORT_C
+int
+xmlSecKeyDataBinaryValueSetBuffer(xmlSecKeyDataPtr data, 
+			const xmlSecByte* buf, xmlSecSize bufSize) {
+    xmlSecBufferPtr buffer;
+
+    xmlSecAssert2(xmlSecKeyDataIsValid(data), -1);
+    xmlSecAssert2(xmlSecKeyDataCheckSize(data, xmlSecKeyDataBinarySize), -1);
+    xmlSecAssert2(buf != NULL, -1);
+    xmlSecAssert2(bufSize > 0, -1);
+
+    buffer = xmlSecKeyDataBinaryValueGetBuffer(data);
+    xmlSecAssert2(buffer != NULL, -1);
+
+    return(xmlSecBufferSetData(buffer, buf, bufSize));
+}
+
+/***********************************************************************
+ *
+ * Keys Data list
+ *
+ **********************************************************************/
+static xmlSecPtrListKlass xmlSecKeyDataListKlass = {
+    BAD_CAST "key-data-list",
+    (xmlSecPtrDuplicateItemMethod)xmlSecKeyDataDuplicate, 	/* xmlSecPtrDuplicateItemMethod duplicateItem; */
+    (xmlSecPtrDestroyItemMethod)xmlSecKeyDataDestroy,		/* xmlSecPtrDestroyItemMethod destroyItem; */
+    (xmlSecPtrDebugDumpItemMethod)xmlSecKeyDataDebugDump,	/* xmlSecPtrDebugDumpItemMethod debugDumpItem; */
+    (xmlSecPtrDebugDumpItemMethod)xmlSecKeyDataDebugXmlDump,	/* xmlSecPtrDebugDumpItemMethod debugXmlDumpItem; */
+};
+
+/**
+ * xmlSecKeyDataListGetKlass:
+ * 
+ * The key data list klass.
+ *
+ * Returns pointer to the key data list klass.
+ */
+EXPORT_C
+xmlSecPtrListId 
+xmlSecKeyDataListGetKlass(void) {
+    return(&xmlSecKeyDataListKlass);
+}
+
+
+/***********************************************************************
+ *
+ * Keys Data Ids list
+ *
+ **********************************************************************/
+static xmlSecPtrListKlass xmlSecKeyDataIdListKlass = {
+    BAD_CAST "key-data-ids-list",
+    NULL, 							/* xmlSecPtrDuplicateItemMethod duplicateItem; */
+    NULL,							/* xmlSecPtrDestroyItemMethod destroyItem; */
+    NULL,							/* xmlSecPtrDebugDumpItemMethod debugDumpItem; */
+    NULL,							/* xmlSecPtrDebugDumpItemMethod debugXmlDumpItem; */
+};
+
+/**
+ * xmlSecKeyDataIdListGetKlass:
+ * 
+ * The key data id list klass.
+ *
+ * Returns pointer to the key data id list klass.
+ */
+EXPORT_C
+xmlSecPtrListId 
+xmlSecKeyDataIdListGetKlass(void) {
+    return(&xmlSecKeyDataIdListKlass);
+}
+
+/**
+ * xmlSecKeyDataIdListFind:
+ * @list:		the pointer to key data ids list.
+ * @dataId:		the key data klass.
+ *
+ * Lookups @dataId in @list.
+ *
+ * Returns 1 if @dataId is found in the @list, 0 if not and a negative
+ * value if an error occurs.
+ */
+EXPORT_C
+int 
+xmlSecKeyDataIdListFind(xmlSecPtrListPtr list, xmlSecKeyDataId dataId) {
+    xmlSecSize i, size;
+    
+    xmlSecAssert2(xmlSecPtrListCheckId(list, xmlSecKeyDataIdListId), 0);
+    xmlSecAssert2(dataId != NULL, 0);
+    
+    size = xmlSecPtrListGetSize(list);
+    for(i = 0; i < size; ++i) {
+	if((xmlSecKeyDataId)xmlSecPtrListGetItem(list, i) == dataId) {
+	    return(1);
+	}
+    }
+    return(0);
+}
+
+/** 
+ * xmlSecKeyDataIdListFindByNode:
+ * @list:		the pointer to key data ids list.
+ * @nodeName:		the desired key data klass XML node name.
+ * @nodeNs:		the desired key data klass XML node namespace.
+ * @usage:		the desired key data usage.
+ *
+ * Lookups data klass in the list with given @nodeName, @nodeNs and 
+ * @usage in the @list.
+ *
+ * Returns key data klass is found and NULL otherwise.
+ */
+EXPORT_C 
+xmlSecKeyDataId	
+xmlSecKeyDataIdListFindByNode(xmlSecPtrListPtr list, const xmlChar* nodeName,
+			    const xmlChar* nodeNs, xmlSecKeyDataUsage usage) {
+    xmlSecKeyDataId dataId;
+    xmlSecSize i, size;
+    
+    xmlSecAssert2(xmlSecPtrListCheckId(list, xmlSecKeyDataIdListId), xmlSecKeyDataIdUnknown);
+    xmlSecAssert2(nodeName != NULL, xmlSecKeyDataIdUnknown);
+    
+    size = xmlSecPtrListGetSize(list);
+    for(i = 0; i < size; ++i) {
+	dataId = (xmlSecKeyDataId)xmlSecPtrListGetItem(list, i);
+	xmlSecAssert2(dataId != xmlSecKeyDataIdUnknown, xmlSecKeyDataIdUnknown);
+
+	if(((usage & dataId->usage) != 0) &&
+	   xmlStrEqual(nodeName, dataId->dataNodeName) &&
+	   xmlStrEqual(nodeNs, dataId->dataNodeNs)) {
+	    
+	   return(dataId);	   
+	}
+    }
+    return(xmlSecKeyDataIdUnknown);
+}
+
+/** 
+ * xmlSecKeyDataIdListFindByHref:
+ * @list:		the pointer to key data ids list.
+ * @href:		the desired key data klass href.
+ * @usage:		the desired key data usage.
+ *
+ * Lookups data klass in the list with given @href and @usage in @list.
+ *
+ * Returns key data klass is found and NULL otherwise.
+ */
+EXPORT_C 
+xmlSecKeyDataId	
+xmlSecKeyDataIdListFindByHref(xmlSecPtrListPtr list, const xmlChar* href,
+			    xmlSecKeyDataUsage usage) {
+    xmlSecKeyDataId dataId;
+    xmlSecSize i, size;
+    
+    xmlSecAssert2(xmlSecPtrListCheckId(list, xmlSecKeyDataIdListId), xmlSecKeyDataIdUnknown);
+    xmlSecAssert2(href != NULL, xmlSecKeyDataIdUnknown);
+    
+    size = xmlSecPtrListGetSize(list);
+    for(i = 0; i < size; ++i) {
+	dataId = (xmlSecKeyDataId)xmlSecPtrListGetItem(list, i);
+	xmlSecAssert2(dataId != xmlSecKeyDataIdUnknown, xmlSecKeyDataIdUnknown);
+
+	if(((usage & dataId->usage) != 0) && (dataId->href != NULL) &&
+	   xmlStrEqual(href, dataId->href)) {
+	   
+	   return(dataId);	   
+	}
+    }
+    return(xmlSecKeyDataIdUnknown);
+}
+
+/** 
+ * xmlSecKeyDataIdListFindByName:
+ * @list:		the pointer to key data ids list.
+ * @name:		the desired key data klass name.
+ * @usage:		the desired key data usage.
+ *
+ * Lookups data klass in the list with given @name and @usage in @list.
+ *
+ * Returns key data klass is found and NULL otherwise.
+ */
+EXPORT_C 
+xmlSecKeyDataId	
+xmlSecKeyDataIdListFindByName(xmlSecPtrListPtr list, const xmlChar* name, 
+			    xmlSecKeyDataUsage usage) {
+    xmlSecKeyDataId dataId;
+    xmlSecSize i, size;
+    
+    xmlSecAssert2(xmlSecPtrListCheckId(list, xmlSecKeyDataIdListId), xmlSecKeyDataIdUnknown);
+    xmlSecAssert2(name != NULL, xmlSecKeyDataIdUnknown);
+    
+    size = xmlSecPtrListGetSize(list);
+    for(i = 0; i < size; ++i) {
+	dataId = (xmlSecKeyDataId)xmlSecPtrListGetItem(list, i);
+	xmlSecAssert2(dataId != xmlSecKeyDataIdUnknown, xmlSecKeyDataIdUnknown);
+
+	if(((usage & dataId->usage) != 0) && (dataId->name != NULL) && 
+	   xmlStrEqual(name, BAD_CAST dataId->name)) {
+	   
+	   return(dataId);	   
+	}
+    }
+    return(xmlSecKeyDataIdUnknown);
+}
+
+/** 
+ * xmlSecKeyDataIdListDebugDump:
+ * @list:		the pointer to key data ids list.
+ * @output:		the pointer to output FILE.
+ * 
+ * Prints binary key data debug information to @output.
+ */
+EXPORT_C
+void 
+xmlSecKeyDataIdListDebugDump(xmlSecPtrListPtr list, FILE* output) {
+    xmlSecKeyDataId dataId;
+    xmlSecSize i, size;
+    
+    xmlSecAssert(xmlSecPtrListCheckId(list, xmlSecKeyDataIdListId));
+    xmlSecAssert(output != NULL);
+
+    size = xmlSecPtrListGetSize(list);
+    for(i = 0; i < size; ++i) {
+	dataId = (xmlSecKeyDataId)xmlSecPtrListGetItem(list, i);
+	xmlSecAssert(dataId != NULL);
+	xmlSecAssert(dataId->name != NULL);
+	    
+	if(i > 0) {
+	    fprintf(output, ",\"%s\"", dataId->name);
+	} else {
+	    fprintf(output, "\"%s\"", dataId->name);
+	}	    
+    }
+    fprintf(output, "\n");
+}
+
+/** 
+ * xmlSecKeyDataIdListDebugXmlDump:
+ * @list:		the pointer to key data ids list.
+ * @output:		the pointer to output FILE.
+ * 
+ * Prints binary key data debug information to @output in XML format.
+ */
+EXPORT_C
+void 
+xmlSecKeyDataIdListDebugXmlDump(xmlSecPtrListPtr list, FILE* output) {
+    xmlSecKeyDataId dataId;
+    xmlSecSize i, size;
+
+    xmlSecAssert(xmlSecPtrListCheckId(list, xmlSecKeyDataIdListId));
+    xmlSecAssert(output != NULL);
+
+    fprintf(output, "<KeyDataIdsList>\n");
+    size = xmlSecPtrListGetSize(list);
+    for(i = 0; i < size; ++i) {
+	dataId = (xmlSecKeyDataId)xmlSecPtrListGetItem(list, i);
+	xmlSecAssert(dataId != NULL);
+	xmlSecAssert(dataId->name != NULL);
+	    
+	fprintf(output, "<DataId name=\"%s\" />", dataId->name);
+    }
+    fprintf(output, "</KeyDataIdsList>\n");
+}
+
+/**************************************************************************
+ *
+ * xmlSecKeyDataStore functions
+ *
+ *************************************************************************/
+/**
+ * xmlSecKeyDataStoreCreate:
+ * @id: 		the store id.
+ *
+ * Creates new key data store of the specified klass @id. Caller is responsible
+ * for freeng returned object with #xmlSecKeyDataStoreDestroy function.
+ *
+ * Returns the pointer to newly allocated key data store structure
+ * or NULL if an error occurs.
+ */
+EXPORT_C
+xmlSecKeyDataStorePtr	
+xmlSecKeyDataStoreCreate(xmlSecKeyDataStoreId id)  {
+    xmlSecKeyDataStorePtr store;
+    int ret;
+        
+    xmlSecAssert2(id != NULL, NULL);
+    xmlSecAssert2(id->objSize > 0, NULL);
+        
+    /* Allocate a new xmlSecKeyDataStore and fill the fields. */
+    store = (xmlSecKeyDataStorePtr)xmlMalloc(id->objSize);
+    if(store == NULL) {
+	xmlSecError(XMLSEC_ERRORS_HERE,
+		    xmlSecErrorsSafeString(xmlSecKeyDataStoreKlassGetName(id)),
+		    NULL,
+		    XMLSEC_ERRORS_R_MALLOC_FAILED,
+		    "size=%d", id->objSize); 
+	return(NULL);
+    }
+    memset(store, 0, id->objSize);    
+    store->id = id;
+
+    if(id->initialize != NULL) {
+	ret = (id->initialize)(store);
+        if(ret < 0) {
+	    xmlSecError(XMLSEC_ERRORS_HERE,
+			xmlSecErrorsSafeString(xmlSecKeyDataStoreKlassGetName(id)),
+			"id->initialize",
+			XMLSEC_ERRORS_R_XMLSEC_FAILED,
+			XMLSEC_ERRORS_NO_MESSAGE);
+	    xmlSecKeyDataStoreDestroy(store);
+	    return(NULL);
+	}
+    }
+    
+    return(store);
+}
+
+/**
+ * xmlSecKeyDataStoreDestroy:
+ * @store: 		the pointer to the key data store..
+ *
+ * Destroys the key data store created with #xmlSecKeyDataStoreCreate
+ * function.
+ */
+EXPORT_C
+void
+xmlSecKeyDataStoreDestroy(xmlSecKeyDataStorePtr store) {
+    xmlSecAssert(xmlSecKeyDataStoreIsValid(store));    
+    xmlSecAssert(store->id->objSize > 0);
+    
+    if(store->id->finalize != NULL) {  
+        (store->id->finalize)(store);
+    }
+    memset(store, 0, store->id->objSize);
+    xmlFree(store);
+}
+
+/***********************************************************************
+ *
+ * Keys Data Store list
+ *
+ **********************************************************************/
+static xmlSecPtrListKlass xmlSecKeyDataStorePtrListKlass = {
+    BAD_CAST "keys-data-store-list",
+    NULL, 							/* xmlSecPtrDuplicateItemMethod duplicateItem; */
+    (xmlSecPtrDestroyItemMethod)xmlSecKeyDataStoreDestroy,	/* xmlSecPtrDestroyItemMethod destroyItem; */
+    NULL,							/* xmlSecPtrDebugDumpItemMethod debugDumpItem; */
+    NULL,							/* xmlSecPtrDebugDumpItemMethod debugXmlDumpItem; */
+};
+
+/**
+ * xmlSecKeyDataStorePtrListGetKlass:
+ * 
+ * Key data stores list.
+ *
+ * Returns key data stores list klass.
+ */
+EXPORT_C
+xmlSecPtrListId 
+xmlSecKeyDataStorePtrListGetKlass(void) {
+    return(&xmlSecKeyDataStorePtrListKlass);
+}
+
+