diff --git a/include/key.h b/include/key.h index 17f42eb..4167add 100644 --- a/include/key.h +++ b/include/key.h @@ -7,15 +7,17 @@ #define TIME_SIZE sizeof(time_t) #define SIGN_SIZE crypto_sign_BYTES -#define PK_RAW_SIZE crypto_kx_PUBLICKEYBYTES -#define SK_RAW_SIZE crypto_sign_SECRETKEYBYTES -#define PK_DATA_SIZE PK_RAW_SIZE + MAX_NAME + TIME_SIZE +#define PK_ED25519_SIZE crypto_sign_PUBLICKEYBYTES /* 32, size for signature keys */ +#define SK_ED25519_SIZE crypto_sign_SECRETKEYBYTES /* 64 */ +#define PK_X25519_SIZE crypto_kx_PUBLICKEYBYTES /* 32, size for key exchange keys */ +#define SK_X25519_SIZE crypto_kx_PUBLICKEYBYTES /* same with public key */ +#define PK_DATA_SIZE PK_ED25519_SIZE + MAX_NAME + TIME_SIZE #define PK_SIZE PK_DATA_SIZE + SIGN_SIZE /* Size with signature */ -#define SK_SIZE SK_RAW_SIZE +#define SK_SIZE SK_ED25519_SIZE #define SHARED_KEY_SIZE crypto_kx_SESSIONKEYBYTES typedef struct public_key { - uint8_t raw[PK_RAW_SIZE]; + uint8_t raw[PK_ED25519_SIZE]; uint8_t username[MAX_NAME]; time_t creation; uint8_t signature[SIGN_SIZE]; diff --git a/src/lib/key.c b/src/lib/key.c index fff4a74..f8ce2a8 100644 --- a/src/lib/key.c +++ b/src/lib/key.c @@ -4,7 +4,7 @@ keypair_t *create_keypair(char *username) { - uint8_t pk_raw[PK_RAW_SIZE], sk[SK_SIZE], pk_data[PK_DATA_SIZE], + uint8_t pk_raw[PK_ED25519_SIZE], sk[SK_SIZE], pk_data[PK_DATA_SIZE], username_padded[MAX_NAME], pk_hash[HASH_SIZE], pk_sign[SIGN_SIZE], pk[PK_SIZE]; @@ -22,9 +22,9 @@ keypair_t *create_keypair(char *username) return NULL; } - memcpy(pk_data, pk_raw, PK_RAW_SIZE); - memcpy(pk_data + PK_RAW_SIZE, username_padded, MAX_NAME); - memcpy(pk_data + PK_RAW_SIZE + MAX_NAME, ¤t_time, TIME_SIZE); + memcpy(pk_data, pk_raw, PK_ED25519_SIZE); + memcpy(pk_data + PK_ED25519_SIZE, username_padded, MAX_NAME); + memcpy(pk_data + PK_ED25519_SIZE + MAX_NAME, ¤t_time, TIME_SIZE); crypto_generichash(pk_hash, HASH_SIZE, pk_data, PK_DATA_SIZE, NULL, 0); crypto_sign_detached(pk_sign, NULL, pk_hash, HASH_SIZE, sk); @@ -53,7 +53,7 @@ keypair_t *create_keypair(char *username) fclose(keyf); keypair_t *kp = memalloc(sizeof(keypair_t)); - memcpy(kp->pk.raw, pk_raw, PK_RAW_SIZE); + memcpy(kp->pk.raw, pk_raw, PK_ED25519_SIZE); memcpy(kp->pk.username, username_padded, MAX_NAME); kp->pk.creation = current_time; memcpy(kp->pk.signature, pk_sign, SIGN_SIZE); @@ -92,10 +92,10 @@ keypair_t *get_keypair(char *username) keypair_t *kp = memalloc(sizeof(keypair_t)); - memcpy(kp->pk.raw, pk, PK_RAW_SIZE); - memcpy(kp->pk.username, pk + PK_RAW_SIZE, MAX_NAME); - memcpy(&kp->pk.creation, pk + PK_RAW_SIZE + MAX_NAME, TIME_SIZE); - memcpy(kp->pk.signature, pk + PK_RAW_SIZE + MAX_NAME + TIME_SIZE, SIGN_SIZE); + memcpy(kp->pk.raw, pk, PK_ED25519_SIZE); + memcpy(kp->pk.username, pk + PK_ED25519_SIZE, MAX_NAME); + memcpy(&kp->pk.creation, pk + PK_ED25519_SIZE + MAX_NAME, TIME_SIZE); + memcpy(kp->pk.signature, pk + PK_DATA_SIZE, SIGN_SIZE); memcpy(kp->pk.full, pk, PK_SIZE); memcpy(kp->sk, sk, SK_SIZE); @@ -108,14 +108,14 @@ keypair_t *get_keypair(char *username) */ uint8_t *get_pk_from_ks(char *username) { - size_t bin_len = PK_RAW_SIZE; + size_t bin_len = PK_ED25519_SIZE; unsigned char *bin = memalloc(bin_len); /* TEMPORARY */ if (strcmp(username, "night") == 0) { - sodium_hex2bin(bin, bin_len, "e2f0287d9c23aed8404dd8ba407e7dff8abe40fa98f0b9adf74904978a5fcd50", PK_RAW_SIZE * 2, NULL, NULL, NULL); + sodium_hex2bin(bin, bin_len, "e2f0287d9c23aed8404dd8ba407e7dff8abe40fa98f0b9adf74904978a5fcd50", PK_ED25519_SIZE * 2, NULL, NULL, NULL); return bin; } else if (strcmp(username, "palanix") == 0) { - sodium_hex2bin(bin, bin_len, "932aee08aa338108e49f65a5c4f0eb0a08a15bf717fdf8c0ff60eefd0ea014ae", PK_RAW_SIZE * 2, NULL, NULL, NULL); + sodium_hex2bin(bin, bin_len, "932aee08aa338108e49f65a5c4f0eb0a08a15bf717fdf8c0ff60eefd0ea014ae", PK_ED25519_SIZE * 2, NULL, NULL, NULL); return bin; } return NULL; diff --git a/src/zen/ui.c b/src/zen/ui.c index a8e7751..d098cf8 100644 --- a/src/zen/ui.c +++ b/src/zen/ui.c @@ -521,15 +521,30 @@ void send_message() uint8_t *recipient = users->items[current_user].name; keypair_t *kp_from = get_keypair(USERNAME); - keypair_t *kp_to = get_keypair(recipient); + uint8_t *pk_to = get_pk_from_ks(recipient); /* ed25519 */ int status = ZSM_STA_SUCCESS; - uint8_t shared_key[SHARED_KEY_SIZE]; - if (crypto_kx_client_session_keys(shared_key, NULL, kp_from->pk.raw, - kp_from->sk, kp_to->pk.raw) != 0) { - /* Recipient public key is suspicious */ - write_log(LOG_ERROR, "Error performing key exchange with %s", recipient); + uint8_t *shared_key = get_sharedkey(recipient); + if (shared_key == NULL) { + uint8_t shared_key[SHARED_KEY_SIZE]; + + /* Key exchange need to be done with x25519 public and secret keys */ + uint8_t from_pk[PK_X25519_SIZE]; + uint8_t to_pk[PK_X25519_SIZE]; + uint8_t from_sk[SK_X25519_SIZE]; + crypto_sign_ed25519_pk_to_curve25519(from_pk, kp_from->pk.raw); + crypto_sign_ed25519_pk_to_curve25519(to_pk, pk_to); + crypto_sign_ed25519_sk_to_curve25519(from_sk, kp_from->sk); + + + if (crypto_kx_client_session_keys(shared_key, NULL, from_pk, from_sk, + to_pk) != 0) { + deinit(); + /* Recipient public key is suspicious */ + error(1, "Error performing key exchange with %s", recipient); + } + save_sharedkey(recipient, shared_key); } size_t content_len = strlen(content); @@ -548,9 +563,20 @@ void send_message() size_t data_len = MAX_NAME * 2 + NONCE_SIZE + cipher_len; uint8_t *data = memalloc(data_len); + uint8_t recipient_padded[MAX_NAME]; + strcpy(recipient_padded, recipient); + size_t length = strlen(recipient); + if (length < MAX_NAME) { + /* Pad with null characters up to max length */ + memset(recipient_padded + length, 0, MAX_NAME - length); + } else { + deinit(); + error(1, "Recipient username must be shorter than MAX_NAME"); + } + /* Construct data */ memcpy(data, kp_from->pk.username, MAX_NAME); - memcpy(data + MAX_NAME, kp_to->pk.username, MAX_NAME); + memcpy(data + MAX_NAME, recipient, MAX_NAME); memcpy(data + MAX_NAME * 2, nonce, NONCE_SIZE); memcpy(data + MAX_NAME * 2 + NONCE_SIZE, encrypted, cipher_len); @@ -583,6 +609,7 @@ void ui(int *fd) users = arraylist_init(LINES); marked = arraylist_init(100); sqlite_init(); + get_users(); draw_users(); refresh(); while (1) { diff --git a/src/zen/zen.c b/src/zen/zen.c index 2ddd5a7..3f4b48f 100644 --- a/src/zen/zen.c +++ b/src/zen/zen.c @@ -89,14 +89,27 @@ void *receive_worker(void *arg) memcpy(nonce, pkt.data + MAX_NAME * 2, NONCE_SIZE); memcpy(encrypted, pkt.data + MAX_NAME * 2 + NONCE_SIZE, cipher_len); - keypair_t *kp_from = get_keypair(from); + uint8_t *pk_from = get_pk_from_ks(from); /* ed25519 */ keypair_t *kp_to = get_keypair(to); - - uint8_t shared_key[SHARED_KEY_SIZE]; - if (crypto_kx_client_session_keys(shared_key, NULL, kp_from->pk.raw, - kp_from->sk, kp_to->pk.raw) != 0) { - /* Suspicious server public key, bail out */ - write_log(LOG_ERROR, "Error performing key exchange with %s", from); + + uint8_t *shared_key = get_sharedkey(from); + if (shared_key == NULL) { + uint8_t shared_key[SHARED_KEY_SIZE]; + + /* Key exchange need to be done with x25519 public and secret keys */ + uint8_t to_pk[PK_X25519_SIZE]; + uint8_t from_pk[PK_X25519_SIZE]; + uint8_t to_sk[SK_X25519_SIZE]; + crypto_sign_ed25519_pk_to_curve25519(to_pk, kp_to->pk.raw); + crypto_sign_ed25519_pk_to_curve25519(from_pk, pk_from); + crypto_sign_ed25519_sk_to_curve25519(to_sk, kp_to->sk); + + if (crypto_kx_server_session_keys(shared_key, NULL, to_pk, + to_sk, from_pk) != 0) { + /* Author public key is suspicious */ + write_log(LOG_ERROR, "Error performing key exchange with %s", from); + } + save_sharedkey(from, shared_key); } /* We don't need it anymore */ diff --git a/src/zmr/zmr.c b/src/zmr/zmr.c index d73188f..c6941ef 100644 --- a/src/zmr/zmr.c +++ b/src/zmr/zmr.c @@ -36,9 +36,9 @@ int authenticate_client(int clientfd, uint8_t *username) goto failure; } - uint8_t pk_bin[PK_RAW_SIZE], pk_username[MAX_NAME]; - memcpy(pk_bin, pkt->data, PK_RAW_SIZE); - memcpy(pk_username, pkt->data + PK_RAW_SIZE, MAX_NAME); + uint8_t pk_bin[PK_ED25519_SIZE], pk_username[MAX_NAME]; + memcpy(pk_bin, pkt->data, PK_ED25519_SIZE); + memcpy(pk_username, pkt->data + PK_ED25519_SIZE, MAX_NAME); if (crypto_sign_verify_detached(pkt->signature, challenge, CHALLENGE_SIZE, pk_bin) != 0) {