Commit bc32e7b1 authored by johan's avatar johan

Generate exported keys and store them in cache for IM encryption

parent 7f4c4333
......@@ -110,11 +110,12 @@ __attribute__ ((visibility ("default"))) void bzrtp_initBzrtpContext(bzrtpContex
*/
__attribute__ ((visibility ("default"))) void bzrtp_destroyBzrtpContext(bzrtpContext_t *context, uint32_t selfSSRC);
#define ZRTP_CALLBACK_LOADCACHE 0x0101
#define ZRTP_CALLBACK_WRITECACHE 0x0102
#define ZRTP_CALLBACK_SENDDATA 0x0110
#define ZRTP_CALLBACK_SRTPSECRETSAVAILABLE 0x0120
#define ZRTP_CALLBACK_STARTSRTPSESSION 0x0140
#define ZRTP_CALLBACK_LOADCACHE 0x0101
#define ZRTP_CALLBACK_WRITECACHE 0x0102
#define ZRTP_CALLBACK_SENDDATA 0x0110
#define ZRTP_CALLBACK_SRTPSECRETSAVAILABLE 0x0120
#define ZRTP_CALLBACK_STARTSRTPSESSION 0x0140
#define ZRTP_CALLBACK_CONTEXTREADYFOREXPORTEDKEYS 0x0180
/**
* @brief Allocate a function pointer to the callback function identified by his id
* @param[in/out] context The zrtp context to set the callback function
......@@ -206,6 +207,37 @@ __attribute__ ((visibility ("default"))) void bzrtp_SASVerified(bzrtpContext_t *
*
* @param[in/out] zrtpContext The ZRTP context we're dealing with
*/
__attribute__ ((visibility ("default"))) void bzrtp_resetSASVerified(bzrtpContext_t *zrtpContext);
__attribute__ ((visibility ("default"))) void bzrtp_resetSASVerified(bzrtpContext_t *zrtpContext);
#define BZRTP_CUSTOMCACHE_USEKDF 1
#define BZRTP_CUSTOMCACHE_PLAINDATA 0
#define BZRTP_CACHE_LOADFILE 0x01
#define BZRTP_CACHE_DONTLOADFILE 0x00
#define BZRTP_CACHE_WRITEFILE 0x10
#define BZRTP_CACHE_DONTWRITEFILE 0x00
/* role mapping */
#define INITIATOR 0
#define RESPONDER 1
/**
* @brief Allow client to write data in cache in the current <peer> tag.
* Data can be written directly or ciphered using the ZRTP Key Derivation Function and current s0.
* If useKDF flag is set but no s0 is available, nothing is written in cache and an error is returned
*
* @param[in/out] zrtpContext The ZRTP context we're dealing with
* @param[in] peerZID The ZID identifying the peer node we want to write into
* @param[in] tagName The name of the tag to be written
* @param[in] tagNameLength The length in bytes of the tagName
* @param[in] tagContent The content of the tag to be written(a string, if KDF is used the result will be turned into an hexa string)
* @param[in] tagContentLength The length in bytes of tagContent
* @param[in] useKDF A flag, if set to 0, write data as it is provided, if set to 1, write KDF(s0, "tagContent", KDF_Context, negotiated hash lenght)
* @param[in] fileFlag Flag, if LOADFILE bit is set, reload the cache buffer from file before updating.
* if WRITEFILE bit is set, update the cache file
*
* @return 0 on success, errorcode otherwise
*/
__attribute__ ((visibility ("default"))) int bzrtp_addCustomDataInCache(bzrtpContext_t *zrtpContext, uint8_t peerZID[12], uint8_t *tagName, uint16_t tagNameLength, uint8_t *tagContent, uint16_t tagContentLength, uint8_t useKDF, uint8_t fileFlag);
#endif /* ifndef BZRTP_H */
......@@ -34,9 +34,6 @@
#define DHPART_MESSAGE_STORE_ID 2
#define CONFIRM_MESSAGE_STORE_ID 3
/* role mapping */
#define INITIATOR 0
#define RESPONDER 1
#include <stdint.h>
......@@ -111,6 +108,9 @@ typedef struct zrtpCallbacks_struct {
/* dealing with SRTP session */
int (* bzrtp_srtpSecretsAvailable)(void *clientData, bzrtpSrtpSecrets_t *srtpSecrets, uint8_t part); /**< Send the srtp secrets to the client, for either sender, receiver or both according to the part parameter value. Client may wait for the end of ZRTP process before using it */
int (* bzrtp_startSrtpSession)(void *clientData, char* sas, int32_t verified); /**< ZRTP process ended well, client is given the SAS and may start his SRTP session if not done when calling srtpSecretsAvailable */
/* ready for exported keys */
int (* bzrtp_contextReadyForExportedKeys)(void *clientData, uint8_t peerZID[12], uint8_t role); /**< Tell the client that this is the time to create and store in cache any exported keys, client is given the peerZID to adress the correct node in cache and current role which is needed to set a pair of keys for IM encryption */
} zrtpCallbacks_t;
/**
......
......@@ -56,6 +56,19 @@ int bzrtp_getSelfZID(bzrtpContext_t *context, uint8_t selfZID[12]);
*/
int bzrtp_getPeerAssociatedSecretsHash(bzrtpContext_t *context, uint8_t peerZID[12]);
/* Define for write peer flags */
/* define positions for bit into the flags */
#define BZRTP_CACHE_ISSTRINGBIT 0x01
#define BZRTP_CACHE_MULTIPLETAGSBIT 0x10
#define BZRTP_CACHE_LOADFILEBIT 0x01
#define BZRTP_CACHE_WRITEFILEBIT 0x10
#define BZRTP_CACHE_TAGISSTRING 0x01
#define BZRTP_CACHE_TAGISBYTE 0x00
#define BZRTP_CACHE_ALLOWMULTIPLETAGS 0x10
#define BZRTP_CACHE_NOMULTIPLETAGS 0x00
/**
* @brief Write the given taf into peer Node, if the tag exists, content is replaced
* Cache file is locked(TODO), read and updated during this call
......@@ -65,9 +78,13 @@ int bzrtp_getPeerAssociatedSecretsHash(bzrtpContext_t *context, uint8_t peerZID[
* @param[in] tagName the tagname of node to be written, it MUST be null terminated
* @param[in] tagNameLength the length of tagname (not including the null termination char)
* @param[in] tagContent the content of the node(a byte buffer which will be converted to hexa string)
* @param[in] tagContentLength the length of the content to be written
* @param[in] tagContentLength the length of the content to be written(not including the null termination if it is a string)
* @param[in] nodeFlag Flag, if the ISSTRING bit is set write directly the value into the tag, otherwise convert the byte buffer to hexa string
* if the MULTIPLETAGS bit is set, allow multiple tags with the same name inside the peer node(only if their value differs)
* @param[in] fileFlag Flag, if LOADFILE bit is set, reload the cache buffer from file before updatin.
* if WRITEFILE bit is set, update the cache file
*
* return 0 on success, error code otherwise
*/
int bzrtp_writePeerNode(bzrtpContext_t *context, uint8_t peerZID[12], uint8_t *tagName, uint8_t tagNameLength, uint8_t *tagContent, uint32_t tagContentLength);
int bzrtp_writePeerNode(bzrtpContext_t *context, uint8_t peerZID[12], uint8_t *tagName, uint8_t tagNameLength, uint8_t *tagContent, uint32_t tagContentLength, uint8_t nodeFlag, uint8_t fileFlag);
#endif /* ZIDCACHE_H */
......@@ -68,6 +68,7 @@ bzrtpContext_t *bzrtp_createBzrtpContext(uint32_t selfSSRC) {
context->zrtpCallbacks.bzrtp_sendData = NULL;
context->zrtpCallbacks.bzrtp_srtpSecretsAvailable = NULL;
context->zrtpCallbacks.bzrtp_startSrtpSession = NULL;
context->zrtpCallbacks.bzrtp_contextReadyForExportedKeys = NULL;
/* allocate 1 channel context, set all the others pointers to NULL */
context->channelContext[0] = (bzrtpChannelContext_t *)malloc(sizeof(bzrtpChannelContext_t));
......@@ -205,6 +206,8 @@ int bzrtp_setCallback(bzrtpContext_t *context, int (*functionPointer)(), uint16_
case ZRTP_CALLBACK_STARTSRTPSESSION:
context->zrtpCallbacks.bzrtp_startSrtpSession = (int (*)(void *, char*, int32_t))functionPointer;
break;
case ZRTP_CALLBACK_CONTEXTREADYFOREXPORTEDKEYS:
context->zrtpCallbacks.bzrtp_contextReadyForExportedKeys = (int (*)(void *, uint8_t *, uint8_t))functionPointer;
default:
return BZRTP_ERROR_INVALIDCALLBACKID;
break;
......@@ -459,7 +462,7 @@ int bzrtp_isSecure(bzrtpContext_t *zrtpContext, uint32_t selfSSRC) {
void bzrtp_SASVerified(bzrtpContext_t *zrtpContext) {
if (zrtpContext != NULL) {
uint8_t pvsFlag = 1;
bzrtp_writePeerNode(zrtpContext, zrtpContext->peerZID, (uint8_t *)"pvs", 3, &pvsFlag, 1);
bzrtp_writePeerNode(zrtpContext, zrtpContext->peerZID, (uint8_t *)"pvs", 3, &pvsFlag, 1, BZRTP_CACHE_TAGISBYTE|BZRTP_CACHE_NOMULTIPLETAGS, BZRTP_CACHE_LOADFILE|BZRTP_CACHE_WRITEFILE);
}
}
......@@ -472,7 +475,48 @@ void bzrtp_SASVerified(bzrtpContext_t *zrtpContext) {
void bzrtp_resetSASVerified(bzrtpContext_t *zrtpContext) {
if (zrtpContext != NULL) {
uint8_t pvsFlag = 0;
bzrtp_writePeerNode(zrtpContext, zrtpContext->peerZID, (uint8_t *)"pvs", 3, &pvsFlag, 1);
bzrtp_writePeerNode(zrtpContext, zrtpContext->peerZID, (uint8_t *)"pvs", 3, &pvsFlag, 1, BZRTP_CACHE_TAGISBYTE|BZRTP_CACHE_NOMULTIPLETAGS, BZRTP_CACHE_LOADFILE|BZRTP_CACHE_WRITEFILE);
}
}
/*
* @brief Allow client to write data in cache in the current <peer> tag.
* Data can be written directly or ciphered using the ZRTP Key Derivation Function and current s0.
* If useKDF flag is set but no s0 is available, nothing is written in cache and an error is returned
*
* @param[in/out] zrtpContext The ZRTP context we're dealing with
* @param[in] peerZID The ZID identifying the peer node we want to write into
* @param[in] tagName The name of the tag to be written
* @param[in] tagNameLength The length in bytes of the tagName
* @param[in] tagContent The content of the tag to be written(a string, if KDF is used the result will be turned into an hexa string)
* @param[in] tagContentLength The length in bytes of tagContent
* @param[in] useKDF A flag, if set to 0, write data as it is provided, if set to 1, write KDF(s0, "tagContent", KDF_Context, negotiated hash lenght)
* @param[in] fileFlag Flag, if LOADFILE bit is set, reload the cache buffer from file before updating.
* if WRITEFILE bit is set, update the cache file
*
* @return 0 on success, errorcode otherwise
*/
int bzrtp_addCustomDataInCache(bzrtpContext_t *zrtpContext, uint8_t peerZID[12], uint8_t *tagName, uint16_t tagNameLength, uint8_t *tagContent, uint16_t tagContentLength, uint8_t useKDF, uint8_t fileFlag) {
/* check we have a valid context, a cache access callback function and a valid channelContext[0] */
if (zrtpContext == NULL || zrtpContext->zrtpCallbacks.bzrtp_loadCache == NULL || zrtpContext->channelContext[0]==NULL) {
return BZRTP_ERROR_INVALIDCONTEXT;
}
if (useKDF == BZRTP_CUSTOMCACHE_PLAINDATA) { /* write content as provided : content is a string and multiple tag is allowed as we are writing the peer URI(To be modified if needed) */
return bzrtp_writePeerNode(zrtpContext, peerZID, tagName, tagNameLength, tagContent, tagContentLength, BZRTP_CACHE_TAGISSTRING|BZRTP_CACHE_ALLOWMULTIPLETAGS, fileFlag);
} else { /* we must derive the content using the key derivation function */
/* check we have s0 and KDFContext in channel[0] */
bzrtpChannelContext_t *zrtpChannelContext = zrtpContext->channelContext[0];
if (zrtpChannelContext->s0 == NULL || zrtpChannelContext->KDFContext == NULL) {
return BZRTP_ERROR_INVALIDCONTEXT;
}
/* We derive 16 bytes for a 128 bit key */
uint8_t derivedContent[16];
bzrtp_keyDerivationFunction(zrtpChannelContext->s0, zrtpChannelContext->hashLength, tagContent, tagContentLength, zrtpChannelContext->KDFContext, zrtpChannelContext->KDFContextLength, 16, (void (*)(uint8_t *, uint8_t, uint8_t *, uint32_t, uint8_t, uint8_t *))zrtpChannelContext->hmacFunction, derivedContent);
/* write it to cache, do not allow multiple tags */
return bzrtp_writePeerNode(zrtpContext, peerZID, tagName, tagNameLength, derivedContent, 16, BZRTP_CACHE_TAGISBYTE|BZRTP_CACHE_NOMULTIPLETAGS, fileFlag);
}
}
......
......@@ -1453,8 +1453,6 @@ int bzrtp_turnIntoResponder(bzrtpContext_t *zrtpContext, bzrtpChannelContext_t *
zrtpChannelContext->keyAgreementAlgo = commitMessage->keyAgreementAlgo;
zrtpChannelContext->sasAlgo = commitMessage->sasAlgo;
/* TODO: check that our selected algo match the availables?? */
/* if we have a self DHPart packet (means we are in DHM mode) we must rebuild the self DHPart packet to be responder and not initiator */
/* as responder we must swap the aux shared secret between responder and initiator as they are computed using the H3 and not a constant string */
if (zrtpChannelContext->selfPackets[DHPART_MESSAGE_STORE_ID] != NULL) {
......@@ -2045,10 +2043,10 @@ int bzrtp_updateCachedSecrets(bzrtpContext_t *zrtpContext, bzrtpChannelContext_t
return 0;
}
/* if this channel context is not in DHM mode, backup rs1 in rs2 if it exists */
/* if this channel context is in DHM mode, backup rs1 in rs2 if it exists */
if (zrtpChannelContext->keyAgreementAlgo != ZRTP_KEYAGREEMENT_Prsh) {
if (zrtpContext->cachedSecret.rs1 != NULL) {
bzrtp_writePeerNode(zrtpContext, zrtpContext->peerZID, (uint8_t *)"rs2", 3, zrtpContext->cachedSecret.rs1, zrtpContext->cachedSecret.rs1Length);
bzrtp_writePeerNode(zrtpContext, zrtpContext->peerZID, (uint8_t *)"rs2", 3, zrtpContext->cachedSecret.rs1, zrtpContext->cachedSecret.rs1Length, BZRTP_CACHE_TAGISBYTE|BZRTP_CACHE_NOMULTIPLETAGS, BZRTP_CACHE_LOADFILE|BZRTP_CACHE_WRITEFILE);
}
}
......@@ -2058,8 +2056,12 @@ int bzrtp_updateCachedSecrets(bzrtpContext_t *zrtpContext, bzrtpChannelContext_t
zrtpContext->cachedSecret.rs1Length = RETAINED_SECRET_LENGTH;
}
bzrtp_keyDerivationFunction(zrtpChannelContext->s0, zrtpChannelContext->hashLength, (uint8_t *)"retained secret", 15, zrtpChannelContext->KDFContext, zrtpChannelContext->KDFContextLength, 32, (void (*)(uint8_t *, uint8_t, uint8_t *, uint32_t, uint8_t, uint8_t *))zrtpChannelContext->hmacFunction, zrtpContext->cachedSecret.rs1);
bzrtp_writePeerNode(zrtpContext, zrtpContext->peerZID, (uint8_t *)"rs1", 3, zrtpContext->cachedSecret.rs1, zrtpContext->cachedSecret.rs1Length);
bzrtp_writePeerNode(zrtpContext, zrtpContext->peerZID, (uint8_t *)"rs1", 3, zrtpContext->cachedSecret.rs1, zrtpContext->cachedSecret.rs1Length, BZRTP_CACHE_TAGISBYTE|BZRTP_CACHE_NOMULTIPLETAGS, BZRTP_CACHE_LOADFILE|BZRTP_CACHE_WRITEFILE);
/* if exist, call the callback function to perform custom cache operation that may use s0(writing exported key into cache) */
if (zrtpContext->zrtpCallbacks.bzrtp_contextReadyForExportedKeys != NULL) {
zrtpContext->zrtpCallbacks.bzrtp_contextReadyForExportedKeys(zrtpChannelContext->clientData, zrtpContext->peerZID, zrtpChannelContext->role);
}
/* destroy s0 */
bzrtp_DestroyKey(zrtpChannelContext->s0, zrtpChannelContext->hashLength, zrtpContext->RNGContext);
free(zrtpChannelContext->s0);
......
......@@ -42,7 +42,7 @@ void bzrtp_strToUint8(uint8_t *outputBytes, uint8_t *inputString, uint16_t input
void bzrtp_int8ToStr(uint8_t *outputString, uint8_t *inputBytes, uint16_t inputBytesLength);
uint8_t bzrtp_byteToChar(uint8_t inputByte);
uint8_t bzrtp_charToByte(uint8_t inputChar);
void bzrtp_writeCache(bzrtpContext_t *zrtpContext, xmlDocPtr doc);
void bzrtp_writeCache(bzrtpContext_t *zrtpContext, xmlDocPtr doc, uint8_t fileFlag);
int bzrtp_getSelfZID(bzrtpContext_t *context, uint8_t selfZID[12]) {
if (context == NULL) {
......@@ -100,7 +100,7 @@ int bzrtp_getSelfZID(bzrtpContext_t *context, uint8_t selfZID[12]) {
xmlNewTextChild(rootNode, NULL, (const xmlChar *)"selfZID", newZidHex);
/* write the cache file and unlock it(TODO)*/
bzrtp_writeCache(context, doc);
bzrtp_writeCache(context, doc, 1);
}
/* TODO unlock the cache */
xmlFree(selfZidHex);
......@@ -216,25 +216,39 @@ int bzrtp_getPeerAssociatedSecretsHash(bzrtpContext_t *context, uint8_t peerZID[
* @param[in] tagName the tagname of node to be written, it MUST be null terminated
* @param[in] tagNameLength the length of tagname (not including the null termination char)
* @param[in] tagContent the content of the node(a byte buffer which will be converted to hexa string)
* @param[in] tagContentLength the length of the content to be written
* @param[in] tagContentLength the length of the content to be written(not including the null termination)
* @param[in] nodeFlag Flag, if the ISSTRING bit is set write directly the value into the tag, otherwise convert the byte buffer to hexa string
* if the MULTIPLETAGS bit is set, allow multiple tags with the same name inside the peer node(only if their value differs)
* @param[in] fileFlag Flag, if LOADFILE bit is set, reload the cache buffer from file before updatin.
* if WRITEFILE bit is set, update the cache file
*
* Note : multiple tags mode manage string content only
*
* return 0 on success, error code otherwise
*/
int bzrtp_writePeerNode(bzrtpContext_t *context, uint8_t peerZID[12], uint8_t *tagName, uint8_t tagNameLength, uint8_t *tagContent, uint32_t tagContentLength) {
int bzrtp_writePeerNode(bzrtpContext_t *context, uint8_t peerZID[12], uint8_t *tagName, uint8_t tagNameLength, uint8_t *tagContent, uint32_t tagContentLength, uint8_t nodeFlag, uint8_t fileFlag) {
if ((context == NULL) || (context->zrtpCallbacks.bzrtp_loadCache == NULL)) {
return ZRTP_ZIDCACHE_INVALID_CONTEXT;
}
/* turn the tagContent to an hexa string null terminated */
uint8_t *tagContentHex = (uint8_t *)malloc(2*tagContentLength+1);
bzrtp_int8ToStr(tagContentHex, tagContent, tagContentLength);
tagContentHex[2*tagContentLength] = '\0';
uint8_t *tagContentHex; /* this one will store the actual value to be written in cache */
if ((nodeFlag&BZRTP_CACHE_ISSTRINGBIT) == BZRTP_CACHE_TAGISBYTE) { /* tag content is a byte buffer, convert it to hexa string */
/* turn the tagContent to an hexa string null terminated */
tagContentHex = (uint8_t *)malloc(2*tagContentLength+1);
bzrtp_int8ToStr(tagContentHex, tagContent, tagContentLength);
tagContentHex[2*tagContentLength] = '\0';
} else { /* tag content is a string, write it directly */
tagContentHex = (uint8_t *)malloc(tagContentLength+1);
memcpy(tagContentHex, tagContent, tagContentLength+1); /* duplicate the string to have it in the same variable in both case and be able to free it at the end */
}
/* reload cache from file locking it (TODO: lock) */
free(context->cacheBuffer);
context->cacheBuffer = NULL;
context->cacheBufferLength = 0;
context->zrtpCallbacks.bzrtp_loadCache(context->channelContext[0]->clientData, &context->cacheBuffer, &(context->cacheBufferLength));
if ((fileFlag&BZRTP_CACHE_LOADFILEBIT) == BZRTP_CACHE_LOADFILE) { /* we must reload the cache from file */
/* reload cache from file locking it (TODO: lock) */
free(context->cacheBuffer);
context->cacheBuffer = NULL;
context->cacheBufferLength = 0;
context->zrtpCallbacks.bzrtp_loadCache(context->channelContext[0]->clientData, &context->cacheBuffer, &(context->cacheBufferLength));
}
/* parse the cache to find the peer element matching the given ZID */
xmlDocPtr doc = NULL;
......@@ -259,13 +273,24 @@ int bzrtp_writePeerNode(bzrtpContext_t *context, uint8_t peerZID[12], uint8_t *t
if ((!xmlStrcmp(cur->name, (const xmlChar *)"peer"))){ /* found a peer, check his ZID element */
currentZidHex = xmlNodeListGetString(doc, cur->xmlChildrenNode->xmlChildrenNode, 1); /* ZID is the first element of peer */
if (memcmp(currentZidHex, peerZidHex, 24) == 0) { /* we found the peer element we are looking for */
xmlNodePtr peerNode = cur->xmlChildrenNode->next;
while (peerNode != NULL && nodeUpdated==0) { /* look for the tag we want to write */
if ((!xmlStrcmp(peerNode->name, (const xmlChar *)tagName))){ /* check if we already have the tag we want to write */
xmlNodeSetContent(peerNode, (const xmlChar *)tagContentHex);
nodeUpdated = 1;
xmlNodePtr peerNodeChildren = cur->xmlChildrenNode->next;
while (peerNodeChildren != NULL && nodeUpdated==0) { /* look for the tag we want to write */
if ((!xmlStrcmp(peerNodeChildren->name, (const xmlChar *)tagName))){ /* check if we already have the tag we want to write */
if ((nodeFlag&BZRTP_CACHE_MULTIPLETAGSBIT) == BZRTP_CACHE_ALLOWMULTIPLETAGS) { /* multiple nodes with the same name are allowed, check the current one have a different value */
/* check if the node found have the same content than the one we want to add */
uint8_t *currentNodeContent = xmlNodeListGetString(doc, peerNodeChildren->xmlChildrenNode, 1);
if (!xmlStrcmp((const xmlChar *)currentNodeContent, (const xmlChar *)tagContent)) { /* contents are the same, do nothing and get out */
nodeUpdated = 1;
} else { /* tagname is the same but content differs, keep on parsing this peer node */
peerNodeChildren = peerNodeChildren->next;
}
xmlFree(currentNodeContent);
} else { /* no multiple tags with the same name allowed, overwrite the content in any case */
xmlNodeSetContent(peerNodeChildren, (const xmlChar *)tagContentHex);
nodeUpdated = 1;
}
} else {
peerNode = peerNode->next;
peerNodeChildren = peerNodeChildren->next;
}
}
if (nodeUpdated == 0) { /* if we didn't found our node, add it at the end of peer node */
......@@ -290,7 +315,7 @@ int bzrtp_writePeerNode(bzrtpContext_t *context, uint8_t peerZID[12], uint8_t *t
/* write the cache file and unlock it(TODO)*/
bzrtp_writeCache(context, doc);
bzrtp_writeCache(context, doc, ((fileFlag&BZRTP_CACHE_WRITEFILEBIT) == BZRTP_CACHE_WRITEFILE));
}
xmlFree(doc);
......@@ -302,16 +327,31 @@ int bzrtp_writePeerNode(bzrtpContext_t *context, uint8_t peerZID[12], uint8_t *t
/*** Local functions implementations ***/
void bzrtp_writeCache(bzrtpContext_t *zrtpContext, xmlDocPtr doc) {
free(zrtpContext->cacheBuffer);
zrtpContext->cacheBuffer = NULL;
zrtpContext->cacheBufferLength = 0;
xmlChar *xmlStringOutput;
xmlDocDumpFormatMemoryEnc(doc, &xmlStringOutput, (int *)&zrtpContext->cacheBufferLength, "UTF-8", 0);
zrtpContext->cacheBuffer = malloc(zrtpContext->cacheBufferLength);
memcpy(zrtpContext->cacheBuffer, xmlStringOutput, zrtpContext->cacheBufferLength);
xmlFree(xmlStringOutput);
/**
* @brief write the cache from the xmlDoc to string buffer and file if requested
*
* @param[in/out] zrtpContext The zrtp context containing the cacheBuffer
* @param[in] doc The xml Document Tree to be parsed into a string
* @param[in] fileFlag When set to 0, do not write to the cache File, just update the cacheBuffer
*
*/
void bzrtp_writeCache(bzrtpContext_t *zrtpContext, xmlDocPtr doc, uint8_t fileFlag) {
/* free the current cacheBuffer */
free(zrtpContext->cacheBuffer);
zrtpContext->cacheBuffer = NULL;
zrtpContext->cacheBufferLength = 0;
/* parse the xml document into a string */
xmlChar *xmlStringOutput;
xmlDocDumpFormatMemoryEnc(doc, &xmlStringOutput, (int *)&zrtpContext->cacheBufferLength, "UTF-8", 0);
/* write it to the cache buffer */
zrtpContext->cacheBuffer = malloc(zrtpContext->cacheBufferLength+1); /* +1 to add the null termination */
memcpy(zrtpContext->cacheBuffer, xmlStringOutput, zrtpContext->cacheBufferLength);
zrtpContext->cacheBuffer[zrtpContext->cacheBufferLength] = '\0'; /* cacheBuffer must be a null terminated string */
zrtpContext->cacheBufferLength +=1;
xmlFree(xmlStringOutput);
if (fileFlag != 0) { /* check if we have to write it to the cache file too */
zrtpContext->zrtpCallbacks.bzrtp_writeCache(zrtpContext->channelContext[0]->clientData, zrtpContext->cacheBuffer, zrtpContext->cacheBufferLength);
}
}
/**
* @brief Convert an hexadecimal string into the corresponding byte buffer
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment