/**
* 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);
}