/** * 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 */ #include "globals.h" #include #include #include #include #include #include #include #include #include #include #include /************************************************************************** * * 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. */ 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. */ 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. */ 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. */ 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: element processing klass, * element processing klass, ... * * Returns: 0 on success or a negative value if an error occurs. */ 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 destroying returned object with * #xmlSecKeyDataDestroy function. * * Returns: the pointer to newly allocated key data structure * or NULL if an error occurs. */ 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 * destroying returned object with #xmlSecKeyDataDestroy function. * * Returns: the pointer to newly allocated key data structure * or NULL if an error occurs. */ 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) { xmlSecError(XMLSEC_ERRORS_HERE, xmlSecErrorsSafeString(xmlSecKeyDataGetName(data)), "id->duplicate", XMLSEC_ERRORS_R_XMLSEC_FAILED, XMLSEC_ERRORS_NO_MESSAGE); xmlSecKeyDataDestroy(newData); return(NULL); } return(newData); } /** * xmlSecKeyDataDestroy: * @data: the pointer to the key data. * * Destroys the data and frees all allocated memory. */ 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 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. */ 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 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. */ 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 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. */ 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 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. */ 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. */ 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. */ 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). */ 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. */ 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. */ 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. */ 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. */ 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. */ 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. */ 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 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. */ 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 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. */ 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 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. */ 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 element processing context. * * Writes binary key data of klass @id from the @key to @buf. * * Returns: 0 on success or a negative value otherwise. */ 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. */ 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. */ 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. */ 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. */ 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. */ 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. */ 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. */ 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. */ 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. */ 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. */ 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. */ 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. */ 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. */ void xmlSecKeyDataIdListDebugXmlDump(xmlSecPtrListPtr list, FILE* output) { xmlSecKeyDataId dataId; xmlSecSize i, size; xmlSecAssert(xmlSecPtrListCheckId(list, xmlSecKeyDataIdListId)); xmlSecAssert(output != NULL); fprintf(output, "\n"); size = xmlSecPtrListGetSize(list); for(i = 0; i < size; ++i) { dataId = (xmlSecKeyDataId)xmlSecPtrListGetItem(list, i); xmlSecAssert(dataId != NULL); xmlSecAssert(dataId->name != NULL); fprintf(output, "name); fprintf(output, "\"/>"); } fprintf(output, "\n"); } /************************************************************************** * * xmlSecKeyDataStore functions * *************************************************************************/ /** * xmlSecKeyDataStoreCreate: * @id: the store id. * * Creates new key data store of the specified klass @id. Caller is responsible * for freeing returned object with #xmlSecKeyDataStoreDestroy function. * * Returns: the pointer to newly allocated key data store structure * or NULL if an error occurs. */ 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. */ 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. */ xmlSecPtrListId xmlSecKeyDataStorePtrListGetKlass(void) { return(&xmlSecKeyDataStorePtrListKlass); }