#include <sys/param.h> | #include <sys/param.h> | ||||
#include <arpa/inet.h> | #include <arpa/inet.h> | ||||
#include <sodium.h> | |||||
#include "../inc/libchat6.h" | #include "../inc/libchat6.h" | ||||
#include "../inc/lc6_helpers.h" | #include "../inc/lc6_helpers.h" | ||||
#include "../inc/lc6_debug.h" | #include "../inc/lc6_debug.h" | ||||
#endif | #endif | ||||
#define LC6_CRYPTO_HASHLEN crypto_generichash_BYTES | |||||
#define LC6_CRYPTO_HASHSIGNLEN (crypto_secretbox_NONCEBYTES+crypto_box_MACBYTES+crypto_generichash_BYTES) | |||||
#define LC6_CRYPTO_PUBLEN crypto_kx_PUBLICKEYBYTES | |||||
#define LC6_CRYPTO_PRIVLEN crypto_kx_SECRETKEYBYTES | |||||
#define LC6_CRYPTO_RXLEN crypto_kx_SESSIONKEYBYTES | |||||
#define LC6_CRYPTO_TXLEN crypto_kx_SESSIONKEYBYTES | |||||
typedef struct LC6_NODE { | typedef struct LC6_NODE { | ||||
unsigned char *pub_key; | unsigned char *pub_key; | ||||
unsigned char *priv_key; | unsigned char *priv_key; | ||||
} LC6_NODE; | } LC6_NODE; | ||||
typedef struct LC6_PEER { | |||||
int sock; | |||||
LC6_NODE keys; | |||||
unsigned char bufi[65536]; | |||||
unsigned char bufo[65536]; | |||||
} LC6_PEER; | |||||
typedef struct LC6_USER { | typedef struct LC6_USER { | ||||
struct LC6_USER *prev; | struct LC6_USER *prev; | ||||
struct LC6_USER *next; | struct LC6_USER *next; | ||||
unsigned char nickname[256]; | unsigned char nickname[256]; | ||||
unsigned char pub_key[32]; | |||||
unsigned char priv_key[32]; | |||||
unsigned char pub_key[LC6_CRYPTO_PUBLEN]; | |||||
unsigned char priv_key[LC6_CRYPTO_PRIVLEN]; | |||||
uint8_t status; | uint8_t status; | ||||
} LC6_USER; | } LC6_USER; | ||||
struct LC6_FRIEND *prev; | struct LC6_FRIEND *prev; | ||||
struct LC6_FRIEND *next; | struct LC6_FRIEND *next; | ||||
unsigned char nickname[256]; | unsigned char nickname[256]; | ||||
unsigned char pub_key[32]; | |||||
unsigned char pub_key[LC6_CRYPTO_PUBLEN]; | |||||
unsigned char key_rx[LC6_CRYPTO_RXLEN]; | |||||
unsigned char key_tx[LC6_CRYPTO_TXLEN]; | |||||
uint8_t status; | uint8_t status; | ||||
} LC6_FRIEND; | } LC6_FRIEND; | ||||
LC6_MSG_TYPE_CLIENT_ONLINE, | LC6_MSG_TYPE_CLIENT_ONLINE, | ||||
LC6_MSG_TYPE_CLIENT_UPDATE, | LC6_MSG_TYPE_CLIENT_UPDATE, | ||||
LC6_MSG_TYPE_CLIENT_OFFLINE, | LC6_MSG_TYPE_CLIENT_OFFLINE, | ||||
LC6_MSG_TYPE_KEEPALIVE_QUERY, | |||||
LC6_MSG_TYPE_KEEPALIVE_REQUEST, | |||||
LC6_MSG_TYPE_KEEPALIVE_RESPONSE, | LC6_MSG_TYPE_KEEPALIVE_RESPONSE, | ||||
LC6_MSG_TYPE_FRIEND_REQUEST, | LC6_MSG_TYPE_FRIEND_REQUEST, | ||||
LC6_MSG_TYPE_FRIEND_CONFIRM, | |||||
LC6_MSG_TYPE_FRIEND_RESPONSE, | |||||
LC6_MSG_TYPE_MESSAGE_SEND, | LC6_MSG_TYPE_MESSAGE_SEND, | ||||
LC6_MSG_TYPE_MESSAGE_RECV, | LC6_MSG_TYPE_MESSAGE_RECV, | ||||
LC6_MSG_TYPE_MESSAGE_READ, | LC6_MSG_TYPE_MESSAGE_READ, | ||||
typedef struct LC6_CTX { | typedef struct LC6_CTX { | ||||
char path[MAXPATHLEN-LC6_CONFIG_MAXLEN]; | char path[MAXPATHLEN-LC6_CONFIG_MAXLEN]; | ||||
LIBCHAT_CB *callback; | |||||
LC6_USER *user; | LC6_USER *user; | ||||
LC6_USER *node; | |||||
LC6_NODE *node; | |||||
LC6_FRIEND *friend; | LC6_FRIEND *friend; | ||||
LC6_BOOTSTRAP *bootstrap; | LC6_BOOTSTRAP *bootstrap; | ||||
} LC6_CTX; | } LC6_CTX; |
int lc6crypto_init(void); | int lc6crypto_init(void); | ||||
int lc6crypto_genrequestsessionkey(LC6_USER *user, LC6_FRIEND *friend); | |||||
int lc6crypto_genresponsesessionkey(LC6_USER *user, LC6_FRIEND *friend); | |||||
int lc6crypto_encrypt( | int lc6crypto_encrypt( | ||||
const unsigned char *data, | const unsigned char *data, | ||||
const int data_len, | const int data_len, | ||||
const int data_len); | const int data_len); | ||||
LC6_USER* lc6crypto_genuserkey(LC6_USER*); | LC6_USER* lc6crypto_genuserkey(LC6_USER*); | ||||
LC6_NODE* lc6crypto_gennodekey(LC6_NODE*); | |||||
unsigned char* lc6crypto_hash(unsigned char*, int); | unsigned char* lc6crypto_hash(unsigned char*, int); | ||||
void lc6crypto_random(unsigned char*, int); | void lc6crypto_random(unsigned char*, int); | ||||
#define LC6_CRYPTO_HASHLEN crypto_generichash_BYTES | |||||
#define LC6_CRYPTO_HASHSIGNLEN (crypto_secretbox_NONCEBYTES+crypto_box_MACBYTES+crypto_generichash_BYTES) | |||||
#endif | #endif |
LC6_STATUS_TYPING | LC6_STATUS_TYPING | ||||
}; | }; | ||||
typedef struct LIBCHAT_EVENT { | |||||
int event_type; | |||||
union { | |||||
int a; | |||||
int b; | |||||
} event; | |||||
} LIBCHAT_EVENT; | |||||
typedef void *LIBCHAT; | typedef void *LIBCHAT; | ||||
typedef int(*LIBCHAT_CB)(LIBCHAT_EVENT*); | |||||
LIBCHAT* libchat_init(char *path, unsigned char *password); | LIBCHAT* libchat_init(char *path, unsigned char *password); | ||||
int libchat_event_reg(LIBCHAT *ctx, LIBCHAT_CB *cb); | |||||
int libchat_start(LIBCHAT *ctx); | |||||
#endif | #endif |
TARGETS:= $(LIBDIR)/libchat6.so $(LIBDIR)/libchat6.a | TARGETS:= $(LIBDIR)/libchat6.so $(LIBDIR)/libchat6.a | ||||
MAINS := $(.o, $(TARGETS) ) | MAINS := $(.o, $(TARGETS) ) | ||||
OBJ := \ | OBJ := \ | ||||
lc6_event.o \ | |||||
lc6_msg.o \ | lc6_msg.o \ | ||||
lc6_common.o \ | lc6_common.o \ | ||||
lc6_debug.o \ | lc6_debug.o \ |
// the neighbours. | // the neighbours. | ||||
conf->node = malloc(sizeof(LC6_USER)); | conf->node = malloc(sizeof(LC6_USER)); | ||||
assert(conf->node); | assert(conf->node); | ||||
lc6crypto_genuserkey(conf->node); | |||||
lc6crypto_gennodekey(conf->node); | |||||
// conf->user may stay NULL | // conf->user may stay NULL | ||||
return sodium_init(); | return sodium_init(); | ||||
} | } | ||||
LC6_USER* lc6crypto_genuserkey(LC6_USER *user) { | LC6_USER* lc6crypto_genuserkey(LC6_USER *user) { | ||||
assert(user); | assert(user); | ||||
crypto_box_keypair(user->pub_key, user->priv_key); | crypto_box_keypair(user->pub_key, user->priv_key); | ||||
return user; | return user; | ||||
} | } | ||||
LC6_NODE* lc6crypto_gennodekey(LC6_NODE *node) { | |||||
assert(node); | |||||
crypto_box_keypair(node->pub_key, node->priv_key); | |||||
return node; | |||||
} | |||||
int lc6crypto_genrequestsessionkey(LC6_USER *user, LC6_FRIEND *friend) { | |||||
assert(user); | |||||
assert(friend); | |||||
// client = me | |||||
// server = friend | |||||
if ( | |||||
crypto_kx_client_session_keys( | |||||
friend->key_rx, | |||||
friend->key_tx, | |||||
user->pub_key, | |||||
user->priv_key, | |||||
friend->pub_key | |||||
) != 0 ) | |||||
{ | |||||
return -1; | |||||
} | |||||
return 0; | |||||
} | |||||
int lc6crypto_genresponsesessionkey(LC6_USER *user, LC6_FRIEND *friend) { | |||||
assert(user); | |||||
assert(friend); | |||||
// server = me | |||||
// client = friend | |||||
if ( | |||||
crypto_kx_server_session_keys( | |||||
friend->key_rx, | |||||
friend->key_tx, | |||||
user->pub_key, | |||||
user->priv_key, | |||||
friend->pub_key | |||||
) != 0 ) | |||||
{ | |||||
return -1; | |||||
} | |||||
return 0; | |||||
} | |||||
int lc6crypto_encrypt( | int lc6crypto_encrypt( | ||||
const unsigned char *data, | const unsigned char *data, | ||||
const int data_len, | const int data_len, |
#include "../inc/lc6_time.h" | #include "../inc/lc6_time.h" | ||||
#include "../inc/lc6_crypto.h" | #include "../inc/lc6_crypto.h" | ||||
unsigned char* lc6msg_peer_encrypt(LC6_NODE *node, LC6_NODE *peer, unsigned char *msg) { | |||||
unsigned char *encrypted = NULL; | |||||
unsigned char nonce[crypto_box_NONCEBYTES]; | |||||
int msglen = strlen((char*)msg); | |||||
unsigned char* lc6msg_compose(unsigned char *srckey, unsigned char *dstkey, LC6_MSG *msg) { | |||||
randombytes_buf(nonce, sizeof nonce); | |||||
encrypted = malloc(crypto_box_MACBYTES + msglen); | |||||
assert(encrypted); | |||||
if ( crypto_box_easy(encrypted, msg, msglen, nonce, peer->pub_key, node->priv_key) != 0 ) { | |||||
free(encrypted); | |||||
return NULL; | |||||
} | |||||
return encrypted; | |||||
} | |||||
unsigned char* lc6msg_peer_decrypt(LC6_NODE *node, LC6_NODE *peer, unsigned char *encrypted) { | |||||
unsigned char *msg = encrypted; | |||||
unsigned char *nonce = encrypted; | |||||
int encryptedlen = strlen((char*)encrypted); | |||||
if ( crypto_box_open_easy(msg, encrypted, encryptedlen, nonce, peer->pub_key, node->priv_key) != 0 ) { | |||||
return NULL; | |||||
} | |||||
return msg; | |||||
} | |||||
unsigned char* lc6msg_compose(LC6_USER *user, LC6_FRIEND *friend, LC6_MSG *msg) { | |||||
unsigned char *ret = NULL; | unsigned char *ret = NULL; | ||||
unsigned char *timestamp = lc6time_getstr(); | unsigned char *timestamp = lc6time_getstr(); | ||||
unsigned char *type = NULL; | unsigned char *type = NULL; | ||||
LC6_MSG_TLV *tlv = NULL; | LC6_MSG_TLV *tlv = NULL; | ||||
int total_len = 0; | int total_len = 0; | ||||
assert(srckey); | |||||
assert(dstkey); | |||||
assert(msg); | assert(msg); | ||||
/* <proof> | /* <proof> |
#include "../inc/lc6_config.h" | #include "../inc/lc6_config.h" | ||||
#include "../inc/lc6_user.h" | #include "../inc/lc6_user.h" | ||||
#include "../inc/lc6_crypto.h" | #include "../inc/lc6_crypto.h" | ||||
#include "../inc/lc6_event.h" | |||||
LIBCHAT* libchat_init(char *path, unsigned char *password) { | LIBCHAT* libchat_init(char *path, unsigned char *password) { | ||||
LC6_CTX *conf; | LC6_CTX *conf; | ||||
return (LIBCHAT*)conf; | return (LIBCHAT*)conf; | ||||
} | } | ||||
int libchat_event_reg(LIBCHAT *ctx, LIBCHAT_CB *cb) { | |||||
LC6_CTX *conf = (LC6_CTX*)ctx; | |||||
assert(conf); | |||||
assert(cb); | |||||
conf->callback = cb; | |||||
return 0; | |||||
} | |||||
int libchat_start(LIBCHAT *ctx) { | |||||
LC6_CTX *conf = (LC6_CTX*)ctx; | |||||
return lc6_event_start(conf); | |||||
} | |||||
int libchat_stop(LIBCHAT *ctx) { | |||||
LC6_CTX *conf = (LC6_CTX*)ctx; | |||||
return lc6_event_stop(conf); | |||||
} |