Commit 78e01080 authored by johan's avatar johan

Add API to get the trust status of a peer active device

- this function shall be used in a mono-device per account environment
- give the trust status of a peer uri based on the
last device involved in a ZRTP exchange associated to that uri.
parent c4625d00
......@@ -187,6 +187,18 @@ typedef struct bzrtpCallbacks_struct {
#define BZRTP_CACHE_SETUP 0x2000
#define BZRTP_CACHE_UPDATE 0x2001
#define BZRTP_CACHE_DATA_NOTFOUND 0x2002
#define BZRTP_CACHE_PEER_STATUS_UNKNOWN 0x2010
#define BZRTP_CACHE_PEER_STATUS_VALID 0x2011
#define BZRTP_CACHE_PEER_STATUS_INVALID 0x2012
/* cache function error codes */
#define BZRTP_ZIDCACHE_INVALID_CONTEXT 0x2101
#define BZRTP_ZIDCACHE_INVALID_CACHE 0x2102
#define BZRTP_ZIDCACHE_UNABLETOUPDATE 0x2103
#define BZRTP_ZIDCACHE_UNABLETOREAD 0x2104
#define BZRTP_ZIDCACHE_BADINPUTDATA 0x2105
#define BZRTP_ZIDCACHE_RUNTIME_CACHELESS 0x2110
/**
* @brief bzrtpContext_t The ZRTP engine context
* Store current state, timers, HMAC and encryption keys
......@@ -496,6 +508,33 @@ BZRTP_EXPORT int bzrtp_cache_migration(void *cacheXmlPtr, void *cacheSqlite, con
*/
BZRTP_EXPORT int bzrtp_exportKey(bzrtpContext_t *zrtpContext, char *label, size_t labelLength, uint8_t *derivedKey, size_t *derivedKeyLength);
/**
* @brief Retrieve from bzrtp cache the trust status(based on the previously verified flag) of a peer URI
*
* This function will return the SAS validation status of the active device
* associated to the given peerURI.
*
* Important note about the active device:
* - any ZRTP exchange with a peer device will set it to be the active one for its sip:uri
* - the concept of active device is shared between local accounts if there are several of them, it means that :
* - if you have several local users on your device, each of them may have an entry in the ZRTP cache with a particular peer sip:uri (if they ever got in contact with it) but only one of this entry is set to active
* - this function will return the status associated to the last updated entry without any consideration for the local users it is associated with
* - any call where the SAS was neither accepted or rejected will not update the trust status but will set as active device for the peer sip:uri the one involved in the call
*
* This function is intended for use in a mono-device environment.
*
* @param[in] dbPointer Pointer to an already opened sqlite db
* @param[in] peerURI The peer sip:uri we're interested in
*
* @return one of:
* - BZRTP_CACHE_PEER_STATUS_UNKNOWN : this uri is not present in cache OR during calls with the active device, SAS never was validated or rejected
* Note: once the SAS has been validated or rejected, the status will never return to UNKNOWN(unless you delete your cache)
* - BZRTP_CACHE_PEER_STATUS_VALID : the active device status is set to valid
* - BZRTP_CACHE_PEER_STATUS_INVALID : the active peer device status is set to invalid
*
*/
BZRTP_EXPORT int bzrtp_cache_getPeerStatus(void *dbPointer, const char *peerURI);
#ifdef __cplusplus
}
#endif
......
......@@ -29,12 +29,6 @@
#include "typedef.h"
#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
......@@ -68,4 +62,25 @@ BZRTP_EXPORT int bzrtp_getPeerAssociatedSecrets(bzrtpContext_t *context, uint8_t
#define BZRTP_ZIDCACHE_INSERT_ZUID 1
BZRTP_EXPORT int bzrtp_cache_getZuid(void *dbPointer, const char *selfURI, const char *peerURI, const uint8_t peerZID[12], const uint8_t insertFlag, int *zuid);
/**
* @brief This is a convenience wrapper to the bzrtp_cache_write function which will also take care of
* setting the ziduri table 'active' flag to one for the current row and reset all other rows with matching peeruri
*
* Write(insert or update) data in cache, adressing it by zuid (ZID/URI binding id used in cache)
* Get arrays of column names, values to be inserted, lengths of theses values
* All three arrays must be the same lenght: columnsCount
* If the row isn't present in the given table, it will be inserted
*
* @param[in/out] dbPointer Pointer to an already opened sqlite db
* @param[in] zuid The DB internal id to adress the correct row(binding between local uri and peer ZID+URI)
* @param[in] tableName The name of the table to write in the db, must already exists. Null terminated string
* @param[in] columns An array of null terminated strings containing the name of the columns to update
* @param[in] values An array of buffers containing the values to insert/update matching the order of columns array
* @param[in] lengths An array of integer containing the lengths of values array buffer matching the order of columns array
* @param[in] columnsCount length common to columns,values and lengths arrays
*
* @return 0 on succes, error code otherwise
*/
BZRTP_EXPORT int bzrtp_cache_write_active(void *dbPointer, int zuid, const char *tableName, const char **columns, uint8_t **values, size_t *lengths, uint8_t columnsCount);
#endif /* ZIDCACHE_H */
......@@ -557,7 +557,7 @@ int state_keyAgreement_sendingCommit(bzrtpEvent_t event) {
size_t colLength[] = {1};
zrtpContext->cachedSecret.previouslyVerifiedSas = 0;
bzrtp_cache_write(zrtpContext->zidCache, zrtpContext->zuid, "zrtp", colNames, colValues, colLength, 1);
bzrtp_cache_write_active(zrtpContext->zidCache, zrtpContext->zuid, "zrtp", colNames, colValues, colLength, 1);
/* if we have a statusMessage callback, use it to warn user */
if (zrtpContext->zrtpCallbacks.bzrtp_statusMessage!=NULL && zrtpContext->zrtpCallbacks.bzrtp_messageLevel>=BZRTP_MESSAGE_ERROR) { /* use error level as this one MUST (RFC section 4.3.2) be warned */
......@@ -861,7 +861,7 @@ int state_keyAgreement_responderSendingDHPart1(bzrtpEvent_t event) {
size_t colLength[] = {1};
zrtpContext->cachedSecret.previouslyVerifiedSas = 0;
bzrtp_cache_write(zrtpContext->zidCache, zrtpContext->zuid, "zrtp", colNames, colValues, colLength, 1);
bzrtp_cache_write_active(zrtpContext->zidCache, zrtpContext->zuid, "zrtp", colNames, colValues, colLength, 1);
/* if we have a statusMessage callback, use it to warn user */
if (zrtpContext->zrtpCallbacks.bzrtp_statusMessage!=NULL && zrtpContext->zrtpCallbacks.bzrtp_messageLevel>=BZRTP_MESSAGE_ERROR) { /* use error level as this one MUST (RFC section 4.3.2) be warned */
......@@ -2260,7 +2260,7 @@ int bzrtp_updateCachedSecrets(bzrtpContext_t *zrtpContext, bzrtpChannelContext_t
bzrtp_cache_getZuid((void *)zrtpContext->zidCache, zrtpContext->selfURI, zrtpContext->peerURI, zrtpContext->peerZID, BZRTP_ZIDCACHE_INSERT_ZUID, &zrtpContext->zuid);
}
bzrtp_cache_write(zrtpContext->zidCache, zrtpContext->zuid, "zrtp", colNames, colValues, colLength, 2);
bzrtp_cache_write_active(zrtpContext->zidCache, zrtpContext->zuid, "zrtp", colNames, colValues, colLength, 2);
/* 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) {
......
......@@ -45,8 +45,12 @@
#endif
/* define a version number for the DB schema as an interger MMmmpp */
/* current version is 0.0.1 */
#define ZIDCACHE_DBSCHEMA_VERSION_NUMBER 000001
/* current version is 0.0.2 */
/* Changelog:
* version 0.0.2 : Add a the active flag in the ziduri table
* version 0.0.1 : Initial version
*/
#define ZIDCACHE_DBSCHEMA_VERSION_NUMBER 0x000002
static int callback_getSelfZID(void *data, int argc, char **argv, char **colName){
uint8_t **selfZID = (uint8_t **)data;
......@@ -70,9 +74,32 @@ static int callback_getUserVersion(void *data, int argc, char **argv, char **col
return 0;
}
/**
* @brief Update the database schema from version 0.0.1 to version 0.0.2
*
* Add an integer field 'active' defaulting to 0 in the ziduri table
*
* @param[in/out] db The sqlite pointer to the table to be updated
*
* @return 0 on success, BZRTP_ZIDCACHE_UNABLETOUPDATE otherwise
*/
static int bzrtp_cache_update_000001_to_000002(sqlite3 *db) {
/* create the ziduri table */
int ret;
char* errmsg=NULL;
ret=sqlite3_exec(db,"ALTER TABLE ziduri ADD COLUMN active INTEGER DEFAULT 0;", 0, 0, &errmsg);
if(ret != SQLITE_OK) {
sqlite3_free(errmsg);
return BZRTP_ZIDCACHE_UNABLETOUPDATE;
}
return 0;
}
/* ZID cache is split in several tables
* ziduri : zuid(unique key) | ZID | selfuri | peeruri
* zuid(ZID/URI binding id) will be used for fastest access to the cache, it binds a local user(self uri/self ZID) to a peer identified both by URI and ZID
* ziduri : zuid(unique key) | ZID | selfuri | peeruri | active
* zuid(ZID/URI binding id) will be used for fastest access to the cache, it binds a local user(self uri/self ZID) to a peer identified both by URI and ZID
* active is a flag set to spot the last active peer device associated to an URI. Each time a ZRTP exchange takes place, the active flag is set to one and all other rows with the same peeruri are set to zero
* self ZID is stored in this table too in a record having 'self' as peer uri, each local user(uri) has a different ZID
*
* All values except zuid in the following tables are blob, actual integers are split and stored in big endian by callers
......@@ -106,7 +133,21 @@ int bzrtp_initCache(void *dbPointer) {
if (userVersion > ZIDCACHE_DBSCHEMA_VERSION_NUMBER) { /* nothing to do if we encounter a superior version number than expected, just hope it is compatible */
//TODO: Log this event
} else { /* Perform update if needed */
switch ( userVersion ) {
case 0x000000 :
/* nothing to do this is base creation */
break;
case 0x000001 :
ret = bzrtp_cache_update_000001_to_000002(db);
if (ret != 0) {
return ret;
}
break;
default : /* nothing particular to do but it shall not append and we shall warn the dev: db schema version was upgraded but no migration function is executed */
break;
}
/* update the schema version in DB metadata */
sql = sqlite3_mprintf("PRAGMA user_version = %d;",ZIDCACHE_DBSCHEMA_VERSION_NUMBER);
ret = sqlite3_prepare(db, sql, -1, &stmt, NULL);
sqlite3_free(sql);
......@@ -139,12 +180,18 @@ int bzrtp_initCache(void *dbPointer) {
}
sqlite3_finalize(stmt);
/* check/create the ziduri table */
/* if we have an update, we can exit now */
if (retval == BZRTP_CACHE_UPDATE) {
return BZRTP_CACHE_UPDATE;
}
/* create the ziduri table */
ret=sqlite3_exec(db,"CREATE TABLE IF NOT EXISTS ziduri ("
"zuid INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL,"
"zuid INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL,"
"zid BLOB NOT NULL DEFAULT '000000000000',"
"selfuri TEXT NOT NULL DEFAULT 'unset',"
"peeruri TEXT NOT NULL DEFAULT 'unset'"
"selfuri TEXT NOT NULL DEFAULT 'unset',"
"peeruri TEXT NOT NULL DEFAULT 'unset',"
"active INTEGER DEFAULT 0"
");",
0,0,&errmsg);
if(ret != SQLITE_OK) {
......@@ -571,6 +618,101 @@ int bzrtp_cache_write(void *dbPointer, int zuid, const char *tableName, const ch
return 0;
}
/**
* @brief This is a convenience wrapper to the bzrtp_cache_write function which will also take care of
* setting the ziduri table 'active' flag to one for the current row and reset all other rows with matching peeruri
*
* Write(insert or update) data in cache, adressing it by zuid (ZID/URI binding id used in cache)
* Get arrays of column names, values to be inserted, lengths of theses values
* All three arrays must be the same lenght: columnsCount
* If the row isn't present in the given table, it will be inserted
*
* @param[in/out] dbPointer Pointer to an already opened sqlite db
* @param[in] zuid The DB internal id to adress the correct row(binding between local uri and peer ZID+URI)
* @param[in] tableName The name of the table to write in the db, must already exists. Null terminated string
* @param[in] columns An array of null terminated strings containing the name of the columns to update
* @param[in] values An array of buffers containing the values to insert/update matching the order of columns array
* @param[in] lengths An array of integer containing the lengths of values array buffer matching the order of columns array
* @param[in] columnsCount length common to columns,values and lengths arrays
*
* @return 0 on succes, error code otherwise
*/
int bzrtp_cache_write_active(void *dbPointer, int zuid, const char *tableName, const char **columns, uint8_t **values, size_t *lengths, uint8_t columnsCount) {
char *stmt=NULL;
int ret;
const unsigned char *peeruri=NULL;
int activeFlag=0;
sqlite3_stmt *sqlStmt = NULL;
sqlite3 *db = (sqlite3 *)dbPointer;
/* initial checks */
if (dbPointer == NULL) { /* we are running cacheless */
return BZRTP_ZIDCACHE_RUNTIME_CACHELESS;
}
if (zuid == 0) { /* we're giving an invalid zuid, means we were not able to retrieve it previously, just do nothing */
return BZRTP_ERROR_CACHE_PEERNOTFOUND;
}
/* Retrieve the peerUri and active flag from ziduri table */
stmt = sqlite3_mprintf("SELECT peeruri, active FROM ziduri WHERE zuid=? LIMIT 1;");
ret = sqlite3_prepare_v2(db, stmt, -1, &sqlStmt, NULL);
sqlite3_free(stmt);
if (ret != SQLITE_OK) {
return BZRTP_ZIDCACHE_UNABLETOREAD;
}
sqlite3_bind_int(sqlStmt, 1, zuid);
ret = sqlite3_step(sqlStmt);
if (ret!=SQLITE_ROW) { /* We didn't found this zuid in the DB -> we would not be able to write */
sqlite3_finalize(sqlStmt);
return BZRTP_ZIDCACHE_UNABLETOUPDATE;
}
/* retrieve values 0:peeruri, 1:active */
peeruri = sqlite3_column_text(sqlStmt, 0); /* warning: finalize the statement will invalidate peeruri pointer */
activeFlag = sqlite3_column_int(sqlStmt, 1);
/* if active flag is already set, just do nothing otherwise set it and reset all others with the same peeruri(active device is shared among local users) */
if (activeFlag == 0) {
sqlite3_stmt *sqlStmtActive = NULL;
/* reset all active flags with this peeruri */
stmt = sqlite3_mprintf("UPDATE ziduri SET active=0 WHERE active<>0 AND zuid<>? AND peeruri=?;");
ret = sqlite3_prepare_v2(db, stmt, -1, &sqlStmtActive, NULL);
sqlite3_free(stmt);
if (ret != SQLITE_OK) {
sqlite3_finalize(sqlStmt);
sqlite3_finalize(sqlStmtActive);
return BZRTP_ZIDCACHE_UNABLETOREAD;
}
sqlite3_bind_int(sqlStmtActive, 1, zuid);
sqlite3_bind_text(sqlStmtActive, 2, (const char *)peeruri, -1, SQLITE_TRANSIENT);
ret = sqlite3_step(sqlStmtActive);
sqlite3_finalize(sqlStmtActive);
/* set to 1 the active flag four current row */
stmt = sqlite3_mprintf("UPDATE ziduri SET active=1 WHERE zuid=? LIMIT 1;");
ret = sqlite3_prepare_v2(db, stmt, -1, &sqlStmtActive, NULL);
sqlite3_free(stmt);
if (ret != SQLITE_OK) {
sqlite3_finalize(sqlStmt);
sqlite3_finalize(sqlStmtActive);
return BZRTP_ZIDCACHE_UNABLETOREAD;
}
sqlite3_bind_int(sqlStmtActive, 1, zuid);
ret = sqlite3_step(sqlStmtActive);
sqlite3_finalize(sqlStmtActive);
}
sqlite3_finalize(sqlStmt);
/* and perform the actual writing */
return bzrtp_cache_write(dbPointer, zuid, tableName, columns, values, lengths, columnsCount);
}
/**
* @brief Read data from specified table/columns from cache adressing it by zuid (ZID/URI binding id used in cache)
* Get arrays of column names, values to be read, and the number of colums to be read
......@@ -835,6 +977,79 @@ int bzrtp_cache_migration(void *cacheXmlPtr, void *cacheSqlite, const char *self
#endif /* HAVE_LIBXML2 */
}
/*
* @brief Retrieve from bzrtp cache the trust status(based on the previously verified flag) of a peer URI
*
* This function will return the SAS validation status of the active device
* associated to the given peerURI.
*
* Important note about the active device:
* - any ZRTP exchange with a peer device will set it to be the active one for its sip:uri
* - the concept of active device is shared between local accounts if there are several of them, it means that :
* - if you have several local users on your device, each of them may have an entry in the ZRTP cache with a particular peer sip:uri (if they ever got in contact with it) but only one of this entry is set to active
* - this function will return the status associated to the last updated entry without any consideration for the local users it is associated with
* - any call where the SAS was neither accepted or rejected will not update the trust status but will set as active device for the peer sip:uri the one involved in the call
*
* This function is intended for use in a mono-device environment.
*
* @param[in] dbPointer Pointer to an already opened sqlite db
* @param[in] peerURI The peer sip:uri we're interested in
*
* @return one of:
* - BZRTP_CACHE_PEER_STATUS_UNKNOWN : this uri is not present in cache OR during calls with the active device, SAS never was validated or rejected
* Note: once the SAS has been validated or rejected, the status will never return to UNKNOWN(unless you delete your cache)
* - BZRTP_CACHE_PEER_STATUS_VALID : the active device status is set to valid
* - BZRTP_CACHE_PEER_STATUS_INVALID : the active peer device status is set to invalid
*
*/
int bzrtp_cache_getPeerStatus(void *dbPointer, const char *peerURI) {
char *stmt=NULL;
int ret,retval = BZRTP_CACHE_PEER_STATUS_UNKNOWN;
sqlite3_stmt *sqlStmt = NULL;
sqlite3 *db = (sqlite3 *)dbPointer;
/* initial checks */
if (dbPointer == NULL) { /* we are running cacheless */
return BZRTP_ZIDCACHE_RUNTIME_CACHELESS;
}
/* Retrieve the pvs flag from zrtp table for the given peerURI
* Order by active desc so we get the row with the active flag set to 1
* if there is no such row(just after migration from version 0.0.1 of DB schema
* we will get the last device inserted for this peer, it is the most likely to be the active one in the context of a mono-device environment) */
stmt = sqlite3_mprintf("SELECT z.pvs FROM ziduri as zu INNER JOIN zrtp as z ON z.zuid=zu.zuid WHERE zu.peeruri=? ORDER BY zu.active DESC,zu.zuid DESC LIMIT 1;");
ret = sqlite3_prepare_v2(db, stmt, -1, &sqlStmt, NULL);
sqlite3_free(stmt);
if (ret != SQLITE_OK) {
return BZRTP_ZIDCACHE_UNABLETOREAD;
}
sqlite3_bind_text(sqlStmt, 1, peerURI, -1, SQLITE_TRANSIENT);
ret = sqlite3_step(sqlStmt);
if (ret==SQLITE_ROW) { /* We found the peerURI in the DB */
/* pvs is stored as blob in memory, just get the first byte(length shall be one anyway) */
/* it may be NULL -> return UNKNOWN */
int length = sqlite3_column_bytes(sqlStmt, 0);
if (length!=1) { /* value is NULL(or we have something that is not 0x01 or 0x00) in db, we do not know the status of this device */
retval = BZRTP_CACHE_PEER_STATUS_UNKNOWN;
} else {
if (*((uint8_t *)sqlite3_column_blob(sqlStmt, 0)) == 0x01) {
retval = BZRTP_CACHE_PEER_STATUS_VALID;
} else {
retval = BZRTP_CACHE_PEER_STATUS_INVALID;
}
}
} else { /* the peerURI was not found in DB */
retval = BZRTP_CACHE_PEER_STATUS_UNKNOWN;
}
sqlite3_finalize(sqlStmt);
return retval;
}
#else /* ZIDCACHE_ENABLED */
int bzrtp_getSelfZID(void *dbPointer, const char *selfURI, uint8_t selfZID[12], bctbx_rng_context_t *RNGContext) {
......@@ -870,6 +1085,10 @@ int bzrtp_getPeerAssociatedSecrets(bzrtpContext_t *context, uint8_t peerZID[12])
return 0;
}
int bzrtp_cache_write_active(void *dbPointer, int zuid, const char *tableName, const char **columns, uint8_t **values, size_t *lengths, uint8_t columnsCount) {
return BZRTP_ERROR_CACHEDISABLED;
}
int bzrtp_cache_write(void *dbPointer, int zuid, const char *tableName, const char **columns, uint8_t **values, size_t *lengths, uint8_t columnsCount) {
return BZRTP_ERROR_CACHEDISABLED;
}
......@@ -881,4 +1100,8 @@ int bzrtp_cache_read(void *dbPointer, int zuid, const char *tableName, const cha
int bzrtp_cache_migration(xmlDocPtr cacheXml, void *cacheSqlite, const char *selfURI) {
return BZRTP_ERROR_CACHEDISABLED;
}
int bzrtp_cache_getPeerStatus(void *dbPointer, const char *peerURI) {
return BZRTP_CACHE_PEER_STATUS_UNKNOWN;
}
#endif /* ZIDCACHE_ENABLED */
......@@ -60,7 +60,8 @@ typedef struct cryptoParams_struct {
uint8_t sasNb;
uint8_t authtag[MAX_CRYPTO_ALG] ;
uint8_t authtagNb;
uint8_t dontValidateSASflag; /**< if set, SAS will not be validated even if matching peer **/
uint8_t dontValidateSASflag; /**< if set to 1, SAS will not be validated even if matching peer **/
/**< if set to 2, SAS will be reset even if matching peer **/
} cryptoParams_t;
......@@ -95,6 +96,15 @@ cryptoParams_t *defaultCryptoAlgoSelectionNoSASValidation(void) {
return &withoutX255noSAS;
}
static cryptoParams_t withoutX255resetSAS = {{ZRTP_CIPHER_AES1},1,{ZRTP_HASH_S256},1,{ZRTP_KEYAGREEMENT_DH3k},1,{ZRTP_SAS_B32},1,{ZRTP_AUTHTAG_HS32},1,2};
static cryptoParams_t withX255resetSAS = {{ZRTP_CIPHER_AES1},1,{ZRTP_HASH_S256},1,{ZRTP_KEYAGREEMENT_X255},1,{ZRTP_SAS_B32},1,{ZRTP_AUTHTAG_HS32},1,2};
cryptoParams_t *defaultCryptoAlgoSelectionResetSAS(void) {
if (bctbx_key_agreement_algo_list()&BCTBX_ECDH_X25519) {
return &withX255resetSAS;
}
return &withoutX255resetSAS;
}
/* static global settings and their reset function */
static uint64_t msSTC = 0; /* Simulation Time Coordinated start at 0 and increment it at each sleep, is in milliseconds */
static int loosePacketPercentage=0; /* simulate bd network condition: loose packet */
......@@ -443,15 +453,26 @@ uint32_t multichannel_exchange_pvs_params(cryptoParams_t *aliceCryptoParams, cry
if ((retval=compareSecrets(Alice.secrets, Bob.secrets, TRUE))!=0) {
BC_ASSERT_EQUAL(retval, 0, int, "%d");
if (aliceCache != NULL && bobCache != NULL) {
bzrtp_resetSASVerified(Alice.bzrtpContext);
bzrtp_resetSASVerified(Bob.bzrtpContext);
}
return retval;
} else { /* SAS comparison is Ok, if we have a cache, confirm it */
if (aliceCache != NULL && bobCache != NULL) {
/* Confirm only when the cryptoParam->dontValidateSASflag is not present or set to 0 */
if (aliceCryptoParams==NULL || aliceCryptoParams->dontValidateSASflag == 0) {
bzrtp_SASVerified(Alice.bzrtpContext);
} else if (aliceCryptoParams!=NULL && aliceCryptoParams->dontValidateSASflag == 2) { /* if flag is set to 2 reset the SAS */
bzrtp_resetSASVerified(Alice.bzrtpContext);
}
/* Confirm only when the cryptoParam->dontValidateSASflag is not present or set to 0 */
if (bobCryptoParams==NULL || bobCryptoParams->dontValidateSASflag == 0) {
bzrtp_SASVerified(Bob.bzrtpContext);
} else if (bobCryptoParams!=NULL && bobCryptoParams->dontValidateSASflag == 2) { /* if flag is set to 2 reset the SAS */
bzrtp_resetSASVerified(Bob.bzrtpContext);
}
/* if flag is set to 1 just ignore the SAS validation */
}
}
......@@ -1318,8 +1339,112 @@ static void test_abort_retry(void) {
sqlite3_close(bobDB);
/* clean temporary files */
remove("tmpZIDAlice_simpleCache.sqlite");
remove("tmpZIDBob_simpleCache.sqlite");
remove("tmpZIDAlice_abortRetry.sqlite");
remove("tmpZIDBob_abortRetry.sqlite");
#endif /* ZIDCACHE_ENABLED */
}
static void test_active_flag(void) {
#ifdef ZIDCACHE_ENABLED
sqlite3 *aliceDB=NULL;
sqlite3 *bob1DB=NULL;
sqlite3 *bob2DB=NULL;
sqlite3 *bob3DB=NULL;
sqlite3 *claire1DB=NULL;
sqlite3 *claire2DB=NULL;
resetGlobalParams();
/* create tempory DB files, just try to clean them from dir before, just in case */
remove("tmpZIDAlice_activeFlag.sqlite");
/* bob has 3 devices */
remove("tmpZIDBob1_activeFlag.sqlite");
remove("tmpZIDBob2_activeFlag.sqlite");
remove("tmpZIDBob3_activeFlag.sqlite");
/* claire has 2 devices */
remove("tmpZIDClaire1_activeFlag.sqlite");
remove("tmpZIDClaire2_activeFlag.sqlite");
bzrtptester_sqlite3_open(bc_tester_file("tmpZIDAlice_activeFlag.sqlite"), &aliceDB);
bzrtptester_sqlite3_open(bc_tester_file("tmpZIDBob1_activeFlag.sqlite"), &bob1DB);
bzrtptester_sqlite3_open(bc_tester_file("tmpZIDBob2_activeFlag.sqlite"), &bob2DB);
bzrtptester_sqlite3_open(bc_tester_file("tmpZIDBob3_activeFlag.sqlite"), &bob3DB);
bzrtptester_sqlite3_open(bc_tester_file("tmpZIDClaire1_activeFlag.sqlite"), &claire1DB);
bzrtptester_sqlite3_open(bc_tester_file("tmpZIDClaire2_activeFlag.sqlite"), &claire2DB);
/* make a first exchange alice <-> bob1, validate the SAS */
BC_ASSERT_EQUAL(multichannel_exchange(NULL, NULL, defaultCryptoAlgoSelection(), aliceDB, "alice@sip.linphone.org", bob1DB, "bob@sip.linphone.org"), 0, int, "%x");
/* ask alice what is the pvs status of the active bob uri: bob@sip.linphone.org, it shall be valid(bob1 is active) */
BC_ASSERT_EQUAL(bzrtp_cache_getPeerStatus(aliceDB, "bob@sip.linphone.org"), BZRTP_CACHE_PEER_STATUS_VALID, int, "%x");
/* make an exchange, alice <-> bob2, alice is instructed to not validate the SAS nor invalidate it */
BC_ASSERT_EQUAL(multichannel_exchange(defaultCryptoAlgoSelectionNoSASValidation(), defaultCryptoAlgoSelection(), defaultCryptoAlgoSelection(), aliceDB, "alice@sip.linphone.org", bob2DB, "bob@sip.linphone.org"), 0, int, "%x");
/* ask alice what is the pvs status of the active bob uri: bob@sip.linphone.org, it shall be unknown(as it is the first exchange with bob2 which is now active) */
BC_ASSERT_EQUAL(bzrtp_cache_getPeerStatus(aliceDB, "bob@sip.linphone.org"), BZRTP_CACHE_PEER_STATUS_UNKNOWN, int, "%x");
/* make an exchange, alice <-> bob1, alice is instructed to not validate the SAS nor invalidate it */
BC_ASSERT_EQUAL(multichannel_exchange(defaultCryptoAlgoSelectionNoSASValidation(), defaultCryptoAlgoSelection(), defaultCryptoAlgoSelection(), aliceDB, "alice@sip.linphone.org", bob1DB, "bob@sip.linphone.org"), 0, int, "%x");
/* ask alice what is the pvs status of the active bob uri: bob@sip.linphone.org, it shall be valid(bob1 is now active) */
BC_ASSERT_EQUAL(bzrtp_cache_getPeerStatus(aliceDB, "bob@sip.linphone.org"), BZRTP_CACHE_PEER_STATUS_VALID, int, "%x");
/* make an exchange, alice <-> bob1, alice is instructed to reset the SAS */
BC_ASSERT_EQUAL(multichannel_exchange(defaultCryptoAlgoSelectionResetSAS(), defaultCryptoAlgoSelection(), defaultCryptoAlgoSelection(), aliceDB, "alice@sip.linphone.org", bob1DB, "bob@sip.linphone.org"), 0, int, "%x");
/* ask alice what is the pvs status of the active bob uri: bob@sip.linphone.org, it shall be invalid(bob1 is still active) */
BC_ASSERT_EQUAL(bzrtp_cache_getPeerStatus(aliceDB, "bob@sip.linphone.org"), BZRTP_CACHE_PEER_STATUS_INVALID, int, "%x");
/* make an exchange, alice <-> bob2, alice is instructed to not validate the SAS nor invalidate it */
BC_ASSERT_EQUAL(multichannel_exchange(defaultCryptoAlgoSelectionNoSASValidation(), defaultCryptoAlgoSelection(), defaultCryptoAlgoSelection(), aliceDB, "alice@sip.linphone.org", bob2DB, "bob@sip.linphone.org"), 0, int, "%x");
/* ask alice what is the pvs status of the active bob uri: bob@sip.linphone.org, it shall be unknown(as it is the first exchange with bob2 which is now active) */
BC_ASSERT_EQUAL(bzrtp_cache_getPeerStatus(aliceDB, "bob@sip.linphone.org"), BZRTP_CACHE_PEER_STATUS_UNKNOWN, int, "%x");
/* make an exchange alice <-> bob2, validate the SAS */
BC_ASSERT_EQUAL(multichannel_exchange(NULL, NULL, defaultCryptoAlgoSelection(), aliceDB, "alice@sip.linphone.org", bob2DB, "bob@sip.linphone.org"), 0, int, "%x");
/* ask alice what is the pvs status of the active bob uri: bob@sip.linphone.org, it shall be valid (bob2 is now active) */
BC_ASSERT_EQUAL(bzrtp_cache_getPeerStatus(aliceDB, "bob@sip.linphone.org"), BZRTP_CACHE_PEER_STATUS_VALID, int, "%x");
/* make an exchange, alice <-> bob1, alice is instructed to not validate the SAS nor invalidate it */
BC_ASSERT_EQUAL(multichannel_exchange(defaultCryptoAlgoSelectionNoSASValidation(), defaultCryptoAlgoSelection(), defaultCryptoAlgoSelection(), aliceDB, "alice@sip.linphone.org", bob1DB, "bob@sip.linphone.org"), 0, int, "%x");
/* ask alice what is the pvs status of the active bob uri: bob@sip.linphone.org, it shall be invalid(bob1 is now active) */
BC_ASSERT_EQUAL(bzrtp_cache_getPeerStatus(aliceDB, "bob@sip.linphone.org"), BZRTP_CACHE_PEER_STATUS_INVALID, int, "%x");
/* make an exchange, alice <-> bob3, alice is instructed to not validate the SAS nor invalidate it */
BC_ASSERT_EQUAL(multichannel_exchange(defaultCryptoAlgoSelectionNoSASValidation(), defaultCryptoAlgoSelection(), defaultCryptoAlgoSelection(), aliceDB, "alice@sip.linphone.org", bob3DB, "bob@sip.linphone.org"), 0, int, "%x");
/* ask alice what is the pvs status of the active bob uri: bob@sip.linphone.org, it shall be unknown(as it is the first exchange with bob3 which is now active) */
BC_ASSERT_EQUAL(bzrtp_cache_getPeerStatus(aliceDB, "bob@sip.linphone.org"), BZRTP_CACHE_PEER_STATUS_UNKNOWN, int, "%x");
/* introducing Claire */
/* ask alice what is the pvs status of the active claire uri: claire@sip.linphone.org, it shall still be unknown as alice never heard about clairee yet */
BC_ASSERT_EQUAL(bzrtp_cache_getPeerStatus(aliceDB, "claire@sip.linphone.org"), BZRTP_CACHE_PEER_STATUS_UNKNOWN, int, "%x");
/* make an exchange, alice <-> claire1, alice is instructed to reset the SAS */
BC_ASSERT_EQUAL(multichannel_exchange(defaultCryptoAlgoSelectionResetSAS(), defaultCryptoAlgoSelection(), defaultCryptoAlgoSelection(), aliceDB, "alice@sip.linphone.org", claire1DB, "claire@sip.linphone.org"), 0, int, "%x");
/* ask alice what is the pvs status of the active bob uri: bob@sip.linphone.org, it shall still be unknown(bob3 is still active) */
BC_ASSERT_EQUAL(bzrtp_cache_getPeerStatus(aliceDB, "bob@sip.linphone.org"), BZRTP_CACHE_PEER_STATUS_UNKNOWN, int, "%x");
/* ask alice what is the pvs status of the active claire uri: claire@sip.linphone.org, it shall still be invalid */
BC_ASSERT_EQUAL(bzrtp_cache_getPeerStatus(aliceDB, "claire@sip.linphone.org"), BZRTP_CACHE_PEER_STATUS_INVALID, int, "%x");
/* make a first exchange alice <-> claire2, validate the SAS */
BC_ASSERT_EQUAL(multichannel_exchange(NULL, NULL, defaultCryptoAlgoSelection(), aliceDB, "alice@sip.linphone.org", claire2DB, "claire@sip.linphone.org"), 0, int, "%x");
/* ask alice what is the pvs status of the active bob uri: bob@sip.linphone.org, it shall still be unknown(bob3 is still active) */
BC_ASSERT_EQUAL(bzrtp_cache_getPeerStatus(aliceDB, "bob@sip.linphone.org"), BZRTP_CACHE_PEER_STATUS_UNKNOWN, int, "%x");
/* ask alice what is the pvs status of the active claire uri: claire@sip.linphone.org, it shall still be valid */
BC_ASSERT_EQUAL(bzrtp_cache_getPeerStatus(aliceDB, "claire@sip.linphone.org"), BZRTP_CACHE_PEER_STATUS_VALID, int, "%x");
/* make an exchange, alice <-> bob1, alice is instructed to not validate the SAS nor invalidate it */
BC_ASSERT_EQUAL(multichannel_exchange(defaultCryptoAlgoSelectionNoSASValidation(), defaultCryptoAlgoSelection(), defaultCryptoAlgoSelection(), aliceDB, "alice@sip.linphone.org", bob1DB, "bob@sip.linphone.org"), 0, int, "%x");
/* ask alice what is the pvs status of the active bob uri: bob@sip.linphone.org, it shall be invalid(bob1 is now active) */
BC_ASSERT_EQUAL(bzrtp_cache_getPeerStatus(aliceDB, "bob@sip.linphone.org"), BZRTP_CACHE_PEER_STATUS_INVALID, int, "%x");
/* ask alice what is the pvs status of the active claire uri: claire@sip.linphone.org, it shall still be valid */
BC_ASSERT_EQUAL(bzrtp_cache_getPeerStatus(aliceDB, "claire@sip.linphone.org"), BZRTP_CACHE_PEER_STATUS_VALID, int, "%x");
/* clean temporary files */
remove("tmpZIDAlice_activeFlag.sqlite");
remove("tmpZIDBob1_activeFlag.sqlite");
remove("tmpZIDBob2_activeFlag.sqlite");
remove("tmpZIDBob3_activeFlag.sqlite");
remove("tmpZIDClaire1_activeFlag.sqlite");
remove("tmpZIDClaire2_activeFlag.sqlite");
#endif /* ZIDCACHE_ENABLED */
}
......@@ -1331,7 +1456,8 @@ static test_t key_exchange_tests[] = {
TEST_NO_TAG("Loosy network", test_loosy_network),
TEST_NO_TAG("Cached PVS", test_cache_sas_not_confirmed),
TEST_NO_TAG("Auxiliary Secret", test_auxiliary_secret),
TEST_NO_TAG("Abort and retry", test_abort_retry)
TEST_NO_TAG("Abort and retry", test_abort_retry),
TEST_NO_TAG("Active flag", test_active_flag)
};
test_suite_t key_exchange_test_suite = {
......
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