Commit 470a17a2 authored by johan's avatar johan

Switch cache from XML to sqlite

- add binding ZID/sipURI in cache to prevent evil friend attack
- expose read/write cache API for external use(LIME)
- add callback to give information to user(cache mismatch only for now)
- stick to RFC 4.5.2 for exported key generation
  (but use the ZRTP Client ID to ensure backward compatibility)
- direct access to exported key computation(not anymore related to cache)
- add cache related tests

Note: no cache migration function provided
parent 556335fe
......@@ -27,6 +27,7 @@ project(bzrtp VERSION 1.0.5 LANGUAGES C CXX)
option(ENABLE_SHARED "Build shared library." YES)
option(ENABLE_STATIC "Build static library." YES)
option(ENABLE_ZIDCACHE "Turn on compilation of ZID cache, request sqlite" YES)
option(ENABLE_STRICT "Build with strict compile options." YES)
option(ENABLE_TESTS "Enable compilation of unit tests." NO)
......@@ -54,10 +55,8 @@ else()
find_package(BcToolbox 0.0.3 REQUIRED OPTIONAL_COMPONENTS tester)
endif()
find_package(XML2)
if(XML2_FOUND)
set(HAVE_LIBXML2 1)
if(ENABLE_ZIDCACHE)
find_package(Sqlite3 REQUIRED)
endif()
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/config.h.cmake ${CMAKE_CURRENT_BINARY_DIR}/config.h)
......@@ -95,10 +94,14 @@ include_directories(
set(LIBS ${BCTOOLBOX_CORE_LIBRARIES})
if(XML2_FOUND)
include_directories(${XML2_INCLUDE_DIRS})
list(APPEND LIBS ${XML2_LIBRARIES})
if(SQLITE3_FOUND)
include_directories(${SQLITE3_INCLUDE_DIRS})
list(APPEND LIBS ${SQLITE3_LIBRARIES})
if(ENABLE_ZIDCACHE)
add_definitions("-DZIDCACHE_ENABLED")
endif()
endif()
if(MSVC)
include_directories(${MSVC_INCLUDE_DIR})
endif()
......
############################################################################
# FindXML2.txt
# Copyright (C) 2015 Belledonne Communications, Grenoble France
# FindSqlite3.cmake
# Copyright (C) 2014 Belledonne Communications, Grenoble France
#
############################################################################
#
......@@ -20,38 +20,38 @@
#
############################################################################
#
# - Find the libxml2 include file and library
# - Find the sqlite3 include file and library
#
# XML2_FOUND - system has libxml2
# XML2_INCLUDE_DIRS - the libxml2 include directory
# XML2_LIBRARIES - The libraries needed to use libxml2
# SQLITE3_FOUND - system has sqlite3
# SQLITE3_INCLUDE_DIRS - the sqlite3 include directory
# SQLITE3_LIBRARIES - The libraries needed to use sqlite3
if(APPLE AND NOT IOS)
set(XML2_HINTS "/usr")
set(SQLITE3_HINTS "/usr")
endif()
if(XML2_HINTS)
set(XML2_LIBRARIES_HINTS "${XML2_HINTS}/lib")
if(SQLITE3_HINTS)
set(SQLITE3_LIBRARIES_HINTS "${SQLITE3_HINTS}/lib")
endif()
find_path(XML2_INCLUDE_DIRS
NAMES libxml/xmlreader.h
HINTS "${XML2_HINTS}"
PATH_SUFFIXES include/libxml2
find_path(SQLITE3_INCLUDE_DIRS
NAMES sqlite3.h
HINTS "${SQLITE3_HINTS}"
PATH_SUFFIXES include
)
if(XML2_INCLUDE_DIRS)
set(HAVE_LIBXML_XMLREADER_H 1)
if(SQLITE3_INCLUDE_DIRS)
set(HAVE_SQLITE3_H 1)
endif()
find_library(XML2_LIBRARIES
NAMES xml2
HINTS "${XML2_LIBRARIES_HINTS}"
find_library(SQLITE3_LIBRARIES
NAMES sqlite3
HINTS "${SQLITE3_LIBRARIES_HINTS}"
)
include(FindPackageHandleStandardArgs)
find_package_handle_standard_args(XML2
find_package_handle_standard_args(Sqlite3
DEFAULT_MSG
XML2_INCLUDE_DIRS XML2_LIBRARIES
SQLITE3_INCLUDE_DIRS SQLITE3_LIBRARIES HAVE_SQLITE3_H
)
mark_as_advanced(XML2_INCLUDE_DIRS XML2_LIBRARIES)
mark_as_advanced(SQLITE3_INCLUDE_DIRS SQLITE3_LIBRARIES HAVE_SQLITE3_H)
......@@ -24,4 +24,4 @@
#cmakedefine HAVE_CU_GET_SUITE
#cmakedefine HAVE_CU_CURSES
#cmakedefine HAVE_LIBXML2
#cmakedefine ZIDCACHE_ENABLED
This diff is collapsed.
......@@ -37,22 +37,22 @@
#define BZRTP_PARSER_ERROR_OUTOFORDER 0xa004
#define BZRTP_PARSER_ERROR_INVALIDMESSAGE 0xa008
#define BZRTP_PARSER_ERROR_INVALIDCONTEXT 0xa010
#define BZRTP_PARSER_ERROR_UNMATCHINGCONFIRMMAC 0xa020
#define BZRTP_PARSER_ERROR_UNMATCHINGCONFIRMMAC 0xa020
#define BZRTP_PARSER_ERROR_UNMATCHINGSSRC 0xa040
#define BZRTP_PARSER_ERROR_UNMATCHINGHASHCHAIN 0xa080
#define BZRTP_PARSER_ERROR_UNMATCHINGHASHCHAIN 0xa080
#define BZRTP_PARSER_ERROR_UNMATCHINGMAC 0xa100
#define BZRTP_PARSER_ERROR_UNEXPECTEDMESSAGE 0xa200
#define BZRTP_PARSER_ERROR_UNEXPECTEDMESSAGE 0xa200
#define BZRTP_PARSER_ERROR_UNMATCHINGHVI 0xa400
#define BZRTP_BUILDER_ERROR_INVALIDPACKET 0x5001
#define BZRTP_BUILDER_ERROR_INVALIDMESSAGE 0x5002
#define BZRTP_BUILDER_ERROR_INVALIDMESSAGETYPE 0x5004
#define BZRTP_BUILDER_ERROR_UNKNOWN 0x5008
#define BZRTP_BUILDER_ERROR_INVALIDMESSAGETYPE 0x5004
#define BZRTP_BUILDER_ERROR_UNKNOWN 0x5008
#define BZRTP_BUILDER_ERROR_INVALIDCONTEXT 0x5010
#define BZRTP_CREATE_ERROR_INVALIDMESSAGETYPE 0x0a01
#define BZRTP_CREATE_ERROR_INVALIDMESSAGETYPE 0x0a01
#define BZRTP_CREATE_ERROR_UNABLETOCREATECRYPTOCONTEXT 0x0a02
#define BZRTP_CREATE_ERROR_INVALIDCONTEXT 0x0a04
#define BZRTP_CREATE_ERROR_INVALIDCONTEXT 0x0a04
/* map all message type to an uint8_t value */
#define MSGTYPE_INVALID 0x00
......
......@@ -40,11 +40,10 @@
#include <stdint.h>
/* some include needed for the cache */
#ifdef HAVE_LIBXML2
#include <libxml/tree.h>
#include <libxml/parser.h>
#endif
#ifdef ZIDCACHE_ENABLED
#include "sqlite3.h"
#endif /* ZIDCACHE_ENABLED */
typedef struct bzrtpChannelContext_struct bzrtpChannelContext_t;
......@@ -52,6 +51,10 @@ typedef struct bzrtpChannelContext_struct bzrtpChannelContext_t;
#include "packetParser.h"
#include "stateMachine.h"
/* logging */
#define BCTBX_LOG_DOMAIN "bzrtp"
#include "bctoolbox/logging.h"
#ifdef _WIN32
#define snprintf _snprintf
#endif
......@@ -185,9 +188,8 @@ struct bzrtpChannelContext_struct {
/**
* @brief structure of the ZRTP engine context
* Store current state, timers, HMAC and encryption keys
*/
*/
struct bzrtpContext_struct {
void *ZIDCacheData; /**< this is a pointer provided by the client which is then resent as a parameter of the ZID cache related callbacks functions. */
/* contexts */
bctbx_rng_context_t *RNGContext; /**< context for random number generation */
bctbx_DHMContext_t *DHMContext; /**< context for the Diffie-Hellman-Merkle operations. Only one DHM computation may be done during a call, so this belongs to the general context and not the channel one */
......@@ -218,11 +220,17 @@ struct bzrtpContext_struct {
uint8_t supportedSas[7]; /**< list of supported Sas representations mapped to uint8_t */
/* ZIDs and cache */
#ifdef HAVE_LIBXML2
xmlDocPtr cacheBuffer; /**< cache file is load in this buffer to be parsed/written */
#endif
#ifdef ZIDCACHE_ENABLED
sqlite3 *zidCache; /**< an sqlite3 db pointer to the zid cache **/
#else
void *zidCache; /**< an empty pointer always set to NULL when cache is disabled **/
#endif /* ZIDCACHE_ENABLED */
int zuid; /**< internal id used to address zid cache SIP/ZID pair binding **/
char *selfURI; /**< a null terminated string storing the local user URI **/
uint8_t selfZID[12]; /**< The ZRTP Identifier of this ZRTP end point - a random if running cache less */
char *peerURI; /**< a null terminated string storing the peer user URI **/
uint8_t peerZID[12]; /**< The ZRTP Identifier of the peer ZRTP end point - given by the Hello packet */
uint32_t peerBzrtpVersion; /**< The Bzrtp library version used by peer, retrieved from the peer Hello packet Client identifier and used for backward compatibility in exported key computation */
cachedSecrets_t cachedSecret; /**< the local cached secrets */
cachedSecretsHash_t initiatorCachedSecretHash; /**< The hash of cached secret from initiator side, computed as described in rfc section 4.3.1 */
cachedSecretsHash_t responderCachedSecretHash; /**< The hash of cached secret from responder side, computed as described in rfc section 4.3.1 */
......@@ -231,6 +239,8 @@ struct bzrtpContext_struct {
/* keys */
uint8_t *ZRTPSess; /**< ZRTP session key as described in rfc section 4.5.2 */
uint8_t ZRTPSessLength; /**< length of ZRTP session key depends on agreed hash algorithm */
uint8_t *exportedKey; /**< computed as in rfc section 4.5.2 only if needed */
uint8_t exportedKeyLength; /**< length of previous buffer, shall be channel[0]->hashLength */
};
......
......@@ -8,7 +8,7 @@
@author Johan Pascal
@copyright Copyright (C) 2014 Belledonne Communications, Grenoble, France
@copyright Copyright (C) 2017 Belledonne Communications, Grenoble, France
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
......@@ -29,62 +29,22 @@
#include "typedef.h"
#define ZRTP_ZIDCACHE_INVALID_CONTEXT 0x2001
#define ZRTP_ZIDCACHE_INVALID_CACHE 0x2002
#define ZRTP_ZIDCACHE_UNABLETOUPDATE 0x2003
/**
* @brief : retrieve ZID from cache
* ZID is randomly generated if cache is empty or inexistant
* ZID is randamly generated in case of cacheless implementation
*
* @param[in] context The current zrpt context, used to access the random function if needed
* and the ZID cache access function
* @param[out] selfZID The ZID, retrieved from cache or randomly generated
*
* @return 0 on success
*/
int bzrtp_getSelfZID(bzrtpContext_t *context, uint8_t selfZID[12]);
#define BZRTP_ZIDCACHE_INVALID_CONTEXT 0x2001
#define BZRTP_ZIDCACHE_INVALID_CACHE 0x2002
#define BZRTP_ZIDCACHE_UNABLETOUPDATE 0x2003
#define BZRTP_ZIDCACHE_UNABLETOREAD 0x2004
#define BZRTP_ZIDCACHE_BADINPUTDATA 0x2005
#define BZRTP_ZIDCACHE_RUNTIME_CACHELESS 0x2010
/**
* @brief Parse the cache to find secrets associated to the given ZID, set them and their length in the context if they are found
* Note: this function also retrieve zuid(set in the context) wich allow successive calls to cache operation to be faster.
*
* @param[in/out] context the current context, used to get the negotiated Hash algorithm and cache access functions and store result
* @param[in/out] context the current context, used to get the cache db pointer, self and peer URI and store results
* @param[in] peerZID a byte array of the peer ZID
*
* return 0 on succes, error code otherwise
*/
BZRTP_EXPORT 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
BZRTP_EXPORT int bzrtp_getPeerAssociatedSecrets(bzrtpContext_t *context, uint8_t peerZID[12]);
#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
*
* @param[in/out] context the current context, used to get the negotiated Hash algorithm and cache access functions and store result
* @param[in] peerZID a byte array of the peer ZID
* @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(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, uint8_t nodeFlag, uint8_t fileFlag);
#endif /* ZIDCACHE_H */
This diff is collapsed.
......@@ -427,7 +427,7 @@ int bzrtp_packetParser(bzrtpContext_t *zrtpContext, bzrtpChannelContext_t *zrtpC
messageContent +=32;
/* We have now H1, check it matches the H2 we had in the commit message H2=SHA256(H1) and that the Commit message MAC is correct */
if ( zrtpChannelContext->role == RESPONDER) { /* do it only if we are responder (we received a commit packet) */
if ( zrtpChannelContext->role == BZRTP_ROLE_RESPONDER) { /* do it only if we are responder (we received a commit packet) */
uint8_t checkH2[32];
uint8_t checkMAC[32];
bzrtpCommitMessage_t *peerCommitMessageData;
......@@ -538,7 +538,7 @@ int bzrtp_packetParser(bzrtpContext_t *zrtpContext, bzrtpChannelContext_t *zrtpC
uint8_t *confirmPlainMessage;
/* we shall first decrypt and validate the message, check we have the keys to do it */
if (zrtpChannelContext->role == RESPONDER) { /* responder uses initiator's keys to decrypt */
if (zrtpChannelContext->role == BZRTP_ROLE_RESPONDER) { /* responder uses initiator's keys to decrypt */
if ((zrtpChannelContext->zrtpkeyi == NULL) || (zrtpChannelContext->mackeyi == NULL)) {
return BZRTP_PARSER_ERROR_INVALIDCONTEXT;
}
......@@ -546,7 +546,7 @@ int bzrtp_packetParser(bzrtpContext_t *zrtpContext, bzrtpChannelContext_t *zrtpC
confirmMessageMacKey = zrtpChannelContext->mackeyi;
}
if (zrtpChannelContext->role == INITIATOR) { /* the iniator uses responder's keys to decrypt */
if (zrtpChannelContext->role == BZRTP_ROLE_INITIATOR) { /* the iniator uses responder's keys to decrypt */
if ((zrtpChannelContext->zrtpkeyr == NULL) || (zrtpChannelContext->mackeyr == NULL)) {
return BZRTP_PARSER_ERROR_INVALIDCONTEXT;
}
......@@ -592,7 +592,7 @@ int bzrtp_packetParser(bzrtpContext_t *zrtpContext, bzrtpChannelContext_t *zrtpC
bctbx_sha256(messageData->H0, 32, 32, checkH1);
/* if we are responder, we received a commit packet with H2 then check that H2=SHA256(H1) and that the commit message MAC keyed with H1 match */
if ( zrtpChannelContext->role == RESPONDER) {
if ( zrtpChannelContext->role == BZRTP_ROLE_RESPONDER) {
uint8_t checkH2[32];
uint8_t checkMAC[32];
bzrtpCommitMessage_t *peerCommitMessageData;
......@@ -962,7 +962,7 @@ int bzrtp_packetBuild(bzrtpContext_t *zrtpContext, bzrtpChannelContext_t *zrtpCh
uint16_t plainMessageStringIndex = 0;
/* we will have to encrypt and validate the message, check we have the keys to do it */
if (zrtpChannelContext->role == INITIATOR) {
if (zrtpChannelContext->role == BZRTP_ROLE_INITIATOR) {
if ((zrtpChannelContext->zrtpkeyi == NULL) || (zrtpChannelContext->mackeyi == NULL)) {
return BZRTP_BUILDER_ERROR_INVALIDCONTEXT;
}
......@@ -970,7 +970,7 @@ int bzrtp_packetBuild(bzrtpContext_t *zrtpContext, bzrtpChannelContext_t *zrtpCh
confirmMessageMacKey = zrtpChannelContext->mackeyi;
}
if (zrtpChannelContext->role == RESPONDER) {
if (zrtpChannelContext->role == BZRTP_ROLE_RESPONDER) {
if ((zrtpChannelContext->zrtpkeyr == NULL) || (zrtpChannelContext->mackeyr == NULL)) {
return BZRTP_BUILDER_ERROR_INVALIDCONTEXT;
}
......
This diff is collapsed.
This diff is collapsed.
......@@ -24,6 +24,7 @@ set(TEST_SOURCES
bzrtpCryptoTest.c
bzrtpParserTest.c
bzrtpConfigsTest.c
bzrtpZidCacheTest.c
bzrtpTest.c
testUtils.c
)
......@@ -43,8 +44,8 @@ target_link_libraries(bzrtpTest ${BCTOOLBOX_LIBRARIES})
if(HAVE_SQRT)
target_link_libraries(bzrtpTest m)
endif()
if(XML2_FOUND)
target_link_libraries(bzrtpTest ${XML2_LIBRARIES})
if(SQLITE3_FOUND)
target_link_libraries(bzrtpTest ${SQLITE3_LIBRARIES})
endif()
unset(PATTERN_FILES_IN_TEST_DIR CACHE)
......
<?xml version="1.0" encoding="UTF-8"?>
<cache><selfZID>ef7692d0792a67491ae2d44e</selfZID><peer><ZID>005dbe0399643d953a2202dd</ZID><rs1>4ad68d1c48c0452bdc65a0d03f9fa226f5ecd9696dbd79f6b0aa54f61adb0f61</rs1><aux>f8324dd18ea905171ec2be89f879d01d5994132048d92ea020778cbdf31c605e</aux><rs2>c1f9c4575e7bb95de84f8363c68d7c4ecfd41f214df10292922ce89f0f89e613</rs2><pvs>01</pvs></peer></cache>
<?xml version="1.0" encoding="UTF-8"?>
<cache><selfZID>005dbe0399643d953a2202dd</selfZID><peer><ZID>ef7692d0792a67491ae2d44e</ZID><rs1>4ad68d1c48c0452bdc65a0d03f9fa226f5ecd9696dbd79f6b0aa54f61adb0f61</rs1><aux>f8324dd18ea905171ec2be89f879d01d5994132048d92ea020778cbdf31c605e</aux><rs2>c1f9c4575e7bb95de84f8363c68d7c4ecfd41f214df10292922ce89f0f89e613</rs2><pvs>01</pvs></peer></cache>
This diff is collapsed.
......@@ -21,4 +21,6 @@
*/
void test_cacheless_exchange(void);
void test_loosy_network(void);
void test_cache_enabled_exchange(void);
void test_cache_mismatch_exchange(void);
......@@ -166,7 +166,7 @@ void test_parser_param(uint8_t hvi_trick) {
memcpy(context87654321->channelContext[0]->zrtpkeyr, zrtpkeyr, 16);
/* set the role: 87654321 is initiator in our exchange pattern */
context12345678->channelContext[0]->role = RESPONDER;
context12345678->channelContext[0]->role = BZRTP_ROLE_RESPONDER;
/* set the peer hello packet Hash for context 12345678, the other one will be set after Hello Packet reception */
bzrtp_setPeerHelloHash(context12345678, 0x12345678, (uint8_t *)patternZRTPHelloHash87654321, strlen((const char *)patternZRTPHelloHash87654321));
......@@ -282,76 +282,6 @@ typedef struct my_Context_struct {
bzrtpChannelContext_t *peerChannelContext;
} my_Context_t;
typedef struct my_ZIDCacheContext_struct {
char zidFilename[80]; /* nom du fichier de cache */
} my_ZIDCacheContext_t;
static void freeBuf(void* p){
free(p);
}
int floadAlice(void *clientData, uint8_t **output, uint32_t *size, zrtpFreeBuffer_callback *cb) {
/* get filename from ClientData */
my_ZIDCacheContext_t *clientContext = (my_ZIDCacheContext_t *)clientData;
char *filename = clientContext->zidFilename;
FILE *ALICECACHE = fopen(filename, "r+");
fseek(ALICECACHE, 0L, SEEK_END); /* Position to end of file */
*size = ftell(ALICECACHE); /* Get file length */
rewind(ALICECACHE); /* Back to start of file */
*output = (uint8_t *)malloc(*size*sizeof(uint8_t)+1);
if (fread(*output, 1, *size, ALICECACHE)==0){
fprintf(stderr,"floadAlice() fread() error\n");
}
*(*output+*size) = '\0';
*size += 1;
fclose(ALICECACHE);
*cb=freeBuf;
return *size;
}
int fwriteAlice(void *clientData, const uint8_t *input, uint32_t size) {
/* get filename from ClientData */
my_ZIDCacheContext_t *clientContext = (my_ZIDCacheContext_t *)clientData;
char *filename = clientContext->zidFilename;
FILE *ALICECACHE = fopen(filename, "w+");
int retval = fwrite(input, 1, size, ALICECACHE);
fclose(ALICECACHE);
return retval;
}
int floadBob(void *clientData, uint8_t **output, uint32_t *size, zrtpFreeBuffer_callback *cb) {
/* get filename from ClientData */
my_ZIDCacheContext_t *clientContext = (my_ZIDCacheContext_t *)clientData;
char *filename = clientContext->zidFilename;
FILE *BOBCACHE = fopen(filename, "r+");
fseek(BOBCACHE, 0L, SEEK_END); /* Position to end of file */
*size = ftell(BOBCACHE); /* Get file length */
rewind(BOBCACHE); /* Back to start of file */
*output = (uint8_t *)malloc(*size*sizeof(uint8_t)+1);
if (fread(*output, 1, *size, BOBCACHE)==0){
fprintf(stderr,"floadBob(): fread error.\n");
return -1;
}
*(*output+*size) = '\0';
*size += 1;
fclose(BOBCACHE);
*cb=freeBuf;
return *size;
}
int fwriteBob(void *clientData, const uint8_t *input, uint32_t size) {
/* get filename from ClientData */
my_ZIDCacheContext_t *clientContext = (my_ZIDCacheContext_t *)clientData;
char *filename = clientContext->zidFilename;
FILE *BOBCACHE = fopen(filename, "w+");
int retval = fwrite(input, 1, size, BOBCACHE);
fclose(BOBCACHE);
return retval;
}
void test_parserComplete() {
......@@ -410,27 +340,6 @@ void test_parserComplete() {
bzrtpConfirmMessage_t *alice_Confirm2FromBob_message=NULL;
bzrtpPacket_t *alice_Conf2ACK;
bzrtpPacket_t *bob_Conf2ACKFromAlice;
bzrtpCallbacks_t cbs={0};
/* Create the client context, used for zidFilename only */
my_ZIDCacheContext_t clientContextAlice;
my_ZIDCacheContext_t clientContextBob;
strcpy(clientContextAlice.zidFilename, "./ZIDAlice.txt");
strcpy(clientContextBob.zidFilename, "./ZIDBob.txt");
/* attach the ZIDCache Context to the bzrtp Context */
retval = bzrtp_setZIDCacheData(contextAlice, (void *)&clientContextAlice);
retval += bzrtp_setZIDCacheData(contextBob, (void *)&clientContextBob);
/* set the cache related callback functions */
cbs.bzrtp_loadCache=floadAlice;
cbs.bzrtp_writeCache=fwriteAlice;
bzrtp_setCallbacks(contextAlice, &cbs);
cbs.bzrtp_loadCache=floadBob;
cbs.bzrtp_writeCache=fwriteBob;
bzrtp_setCallbacks(contextBob, &cbs);
bzrtp_message ("Init the contexts\n");
......@@ -513,8 +422,8 @@ void test_parserComplete() {
memcpy(contextBob->channelContext[0]->peerH[3], bob_HelloFromAlice_message->H3, 32);
/* get the secrets associated to peer ZID */
bzrtp_getPeerAssociatedSecretsHash(contextAlice, alice_HelloFromBob_message->ZID);
bzrtp_getPeerAssociatedSecretsHash(contextBob, bob_HelloFromAlice_message->ZID);
bzrtp_getPeerAssociatedSecrets(contextAlice, alice_HelloFromBob_message->ZID);
bzrtp_getPeerAssociatedSecrets(contextBob, bob_HelloFromAlice_message->ZID);
/* compute the initiator hashed secret as in rfc section 4.3.1 */
if (contextAlice->cachedSecret.rs1!=NULL) {
......@@ -726,7 +635,7 @@ void test_parserComplete() {
/* Now determine who shall be the initiator : rfc section 4.2 */
/* select the one with the lowest value of hvi */
/* for test purpose, we will set Alice as the initiator */
contextBob->channelContext[0]->role = RESPONDER;
contextBob->channelContext[0]->role = BZRTP_ROLE_RESPONDER;
/* Bob (responder) shall update his selected algo list to match Alice selection */
/* no need to do this here as we have the same selection */
......@@ -1410,7 +1319,7 @@ void test_parserComplete() {
packetDump(alice_CommitFromBob, 0);
/* for test purpose define Alice as the responder */
contextAlice->channelContext[1]->role = RESPONDER;
contextAlice->channelContext[1]->role = BZRTP_ROLE_RESPONDER;
/* compute the total hash as in rfc section 4.4.3.2 total_hash = hash(Hello of responder || Commit) */
totalHashDataLength = alice_Hello->messageLength + bob_Commit->messageLength;
......@@ -1678,7 +1587,6 @@ static void sleepMs(int ms){
void test_stateMachine() {
int retval;
my_Context_t aliceClientData, bobClientData;
my_ZIDCacheContext_t aliceZIDCacheData, bobZIDCacheData;
uint64_t initialTime;
uint8_t pingPacketString[ZRTP_PACKET_OVERHEAD+ZRTP_PINGMESSAGE_FIXED_LENGTH]; /* there is no builder for ping packet and it is 24 bytes long(12 bytes of message header, 12 of data + packet overhead*/
uint32_t CRC;
......@@ -1690,20 +1598,10 @@ void test_stateMachine() {
bzrtpContext_t *contextAlice = bzrtp_createBzrtpContext();
bzrtpContext_t *contextBob = bzrtp_createBzrtpContext();
/* Create the ZIDCache data and associate them to the zrtp contexts */
strcpy(aliceZIDCacheData.zidFilename, "./ZIDAlice.txt");
strcpy(bobZIDCacheData.zidFilename, "./ZIDBob.txt");
bzrtp_setZIDCacheData(contextAlice, (void *)&aliceZIDCacheData);
bzrtp_setZIDCacheData(contextBob, (void *)&bobZIDCacheData);
/* set the cache related callback functions */
cbs.bzrtp_loadCache=floadAlice;
cbs.bzrtp_writeCache=fwriteAlice;
cbs.bzrtp_sendData=bzrtp_sendData;
bzrtp_setCallbacks(contextAlice, &cbs);
cbs.bzrtp_loadCache=floadBob;
cbs.bzrtp_writeCache=fwriteBob;
cbs.bzrtp_sendData=bzrtp_sendData;
bzrtp_setCallbacks(contextBob, &cbs);
......
......@@ -24,16 +24,12 @@
#include "bzrtpCryptoTest.h"
#include "bzrtpParserTest.h"
#include "bzrtpConfigsTest.h"
#include "bzrtpZidCacheTest.h"
#include "typedef.h"
#include "testUtils.h"
#include <bctoolbox/logging.h>
#include <bctoolbox/tester.h>
#ifdef HAVE_LIBXML2
#include <libxml/parser.h>
#endif
test_t crypto_utils_tests[] = {
TEST_NO_TAG("zrtpKDF", test_zrtpKDF),
TEST_NO_TAG("CRC32", test_CRC32),
......@@ -70,8 +66,25 @@ test_suite_t packet_parser_test_suite = {
packet_parser_tests
};
test_t zidcache_tests[] = {
TEST_NO_TAG("SelfZID", test_cache_getSelfZID),
TEST_NO_TAG("ZRTP secrets", test_cache_zrtpSecrets),
};
test_suite_t zidcache_test_suite = {
"ZID Cache",
NULL,
NULL,
NULL,
NULL,
sizeof(zidcache_tests) / sizeof(zidcache_tests[0]),
zidcache_tests
};
test_t key_exchange_tests[] = {
TEST_NO_TAG("Cacheless multi channel", test_cacheless_exchange),
TEST_NO_TAG("Cached Simple", test_cache_enabled_exchange),
TEST_NO_TAG("Cached mismatch", test_cache_mismatch_exchange),
TEST_NO_TAG("Loosy network", test_loosy_network)
};
......@@ -86,22 +99,16 @@ test_suite_t key_exchange_test_suite = {
};
void bzrtp_tester_init(void) {
#ifdef HAVE_LIBXML2
xmlInitParser();
#endif
bc_tester_init(NULL, BCTBX_LOG_MESSAGE, BCTBX_LOG_ERROR, NULL);
bc_tester_add_suite(&crypto_utils_test_suite);
bc_tester_add_suite(&packet_parser_test_suite);
bc_tester_add_suite(&key_exchange_test_suite);
bc_tester_add_suite(&zidcache_test_suite);
}
void bzrtp_tester_uninit(void) {
bc_tester_uninit();
#ifdef HAVE_LIBXML2
/* cleanup libxml2 */
xmlCleanupParser();
#endif
}
int main(int argc, char *argv[]) {
......
This diff is collapsed.
/**
@file bzrtpZidCacheTest.h
@author Johan Pascal
@copyright Copyright (C) 2017 Belledonne Communications, Grenoble, France
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
void test_cache_getSelfZID(void);
void test_cache_zrtpSecrets(void);
......@@ -27,6 +27,20 @@
#include "testUtils.h"
#include "cryptoUtils.h"
#ifndef _WIN32
#if !defined(__QNXNTO__) && !(defined(__ANDROID__) && defined(__LP64__))
#include <ctype.h>
#include <langinfo.h>
#include <locale.h>
#include <iconv.h>
#include <string.h>
#endif
#else
#include <Windows.h>
#endif
int verbose = 0;
/* trace functions: bzrtp algo code to string */
......@@ -327,3 +341,70 @@ void dumpContext(char *title, bzrtpContext_t *zrtpContext) {
fflush(NULL);
}
}
#ifdef ZIDCACHE_ENABLED
#define MAX_PATH_SIZE 1024
static char *utf8_convert(const char *filename){
char db_file_utf8[MAX_PATH_SIZE] = "";
#if defined(_WIN32)
wchar_t db_file_utf16[MAX_PATH_SIZE]={0};
MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, filename, -1, db_file_utf16, MAX_PATH_SIZE);
WideCharToMultiByte(CP_UTF8, 0, db_file_utf16, -1, db_file_utf8, sizeof(db_file_utf8), NULL, NULL);
#elif defined(__QNXNTO__) || (defined(__ANDROID__) && defined(__LP64__))
strncpy(db_file_utf8, filename, MAX_PATH_SIZE - 1);
#else
char db_file_locale[MAX_PATH_SIZE] = {'\0'};
char *inbuf=db_file_locale, *outbuf=db_file_utf8;
size_t inbyteleft = MAX_PATH_SIZE, outbyteleft = MAX_PATH_SIZE;
iconv_t cb;
if (strcasecmp("UTF-8", nl_langinfo(CODESET)) == 0) {
strncpy(db_file_utf8, filename, MAX_PATH_SIZE - 1);
} else {
strncpy(db_file_locale, filename, MAX_PATH_SIZE-1);
cb = iconv_open("UTF-8", nl_langinfo(CODESET));
if (cb != (iconv_t)-1) {
int ret;
ret = iconv(cb, &inbuf, &inbyteleft, &outbuf, &outbyteleft);
if(ret == -1) db_file_utf8[0] = '\0';
iconv_close(cb);
}
}
#endif
return bctbx_strdup(db_file_utf8);
}
int bzrtptester_sqlite3_open(const char *db_file, sqlite3 **db) {
char* errmsg = NULL;
int ret;
int flags = SQLITE_OPEN_READWRITE|SQLITE_OPEN_CREATE;
#if TARGET_OS_IPHONE
/* the secured filesystem of the iPHone doesn't allow writing while the app is in background mode, which is problematic.
* We workaround by asking that the open is made with no protection*/
flags |= SQLITE_OPEN_FILEPROTECTION_NONE;
#endif
/*since we plug our vfs into sqlite, we convert to UTF-8.
* On Windows, the filename has to be converted back to windows native charset.*/
char *utf8_filename = utf8_convert(db_file);
//ret = sqlite3_open_v2(utf8_filename, db, flags, LINPHONE_SQLITE3_VFS);
ret = sqlite3_open_v2(utf8_filename, db, flags, NULL);
bctbx_free(utf8_filename);
if (ret != SQLITE_OK) return ret;
// Some platforms do not provide a way to create temporary files which are needed
// for transactions... so we work in memory only
// see http ://www.sqlite.org/compile.html#temp_store
ret = sqlite3_exec(*db, "PRAGMA temp_store=MEMORY", NULL, NULL, &errmsg);
if (ret != SQLITE_OK) {
sqlite3_free(errmsg);
}
return ret;
}
#endif /* ZIDCACHE_ENABLED */
......@@ -35,3 +35,6 @@ const char *bzrtp_keyAgreement_toString(uint8_t keyAgreementAlgo);
const char *bzrtp_cipher_toString(uint8_t cipherAlgo);
const char *bzrtp_authtag_toString(uint8_t authtagAlgo);
const char *bzrtp_sas_toString(uint8_t sasAlgo);
#ifdef ZIDCACHE_ENABLED
int bzrtptester_sqlite3_open(const char *db_file, sqlite3 **db);
#endif /* ZIDCACHE_ENABLED */