2024-03-21 17:50:55 +04:00
|
|
|
#include "crypt.h"
|
|
|
|
|
|
|
|
#include <stdlib.h>
|
2024-03-23 05:52:03 +04:00
|
|
|
#include <string.h>
|
2024-03-21 17:50:55 +04:00
|
|
|
|
2024-03-23 04:21:41 +04:00
|
|
|
int crypt_key_gen(crypt_key_t *const k) {
|
2024-03-22 03:32:40 +04:00
|
|
|
if (crypto_kx_keypair(k->kx_pub, k->kx_sec) < 0) {
|
2024-03-21 17:50:55 +04:00
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
2024-03-22 03:32:40 +04:00
|
|
|
if (crypto_sign_keypair(k->sign_pub, k->sign_sec) < 0) {
|
2024-03-21 17:50:55 +04:00
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
k->hasSecKey = true;
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2024-03-23 05:52:03 +04:00
|
|
|
int crypt_key_from_hex(crypt_key_t *const k, const char phex[CRYPT_PKEY_HEXLEN], const char shex[CRYPT_SKEY_HEXLEN]) {
|
2024-03-23 04:21:41 +04:00
|
|
|
if (sodium_hex2bin(k->kx_pub, CRYPT_KX_PKEY_LEN, phex, CRYPT_KX_PKEY_LEN * 2, NULL, NULL, NULL) < 0)
|
2024-03-21 17:50:55 +04:00
|
|
|
return -1;
|
2024-03-23 04:21:41 +04:00
|
|
|
if (sodium_hex2bin(k->kx_sec, CRYPT_KX_SKEY_LEN, shex, CRYPT_KX_SKEY_LEN * 2, NULL, NULL, NULL) < 0)
|
2024-03-21 17:50:55 +04:00
|
|
|
return -1;
|
2024-03-23 04:21:41 +04:00
|
|
|
if (sodium_hex2bin(k->sign_pub, CRYPT_SIGN_PKEY_LEN, phex+(CRYPT_KX_PKEY_LEN * 2), CRYPT_SIGN_PKEY_LEN * 2, NULL, NULL, NULL) < 0)
|
2024-03-21 17:50:55 +04:00
|
|
|
return -1;
|
2024-03-23 04:21:41 +04:00
|
|
|
if (sodium_hex2bin(k->sign_sec, CRYPT_SIGN_SKEY_LEN, shex+(CRYPT_KX_SKEY_LEN * 2), CRYPT_SIGN_SKEY_LEN * 2, NULL, NULL, NULL) < 0)
|
2024-03-21 17:50:55 +04:00
|
|
|
return -1;
|
|
|
|
|
|
|
|
k->hasSecKey = true;
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2024-03-23 05:52:03 +04:00
|
|
|
int crypt_key_from_hex_public(crypt_key_t *const k, const char phex[CRYPT_PKEY_HEXLEN]) {
|
2024-03-23 04:21:41 +04:00
|
|
|
if (sodium_hex2bin(k->kx_pub, CRYPT_KX_PKEY_LEN, phex, CRYPT_KX_PKEY_LEN * 2, NULL, NULL, NULL) < 0)
|
2024-03-21 17:50:55 +04:00
|
|
|
return -1;
|
2024-03-23 04:21:41 +04:00
|
|
|
if (sodium_hex2bin(k->sign_pub, CRYPT_SIGN_PKEY_LEN, phex+(CRYPT_KX_PKEY_LEN * 2), CRYPT_SIGN_PKEY_LEN * 2, NULL, NULL, NULL) < 0)
|
2024-03-21 17:50:55 +04:00
|
|
|
return -1;
|
|
|
|
|
|
|
|
k->hasSecKey = false;
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2024-03-23 04:21:41 +04:00
|
|
|
void crypt_key_destroy(crypt_key_t *const k) {
|
|
|
|
sodium_memzero(k->kx_pub, CRYPT_KX_PKEY_LEN);
|
|
|
|
sodium_memzero(k->kx_sec, CRYPT_KX_SKEY_LEN);
|
|
|
|
sodium_memzero(k->sign_pub, CRYPT_SIGN_PKEY_LEN);
|
|
|
|
sodium_memzero(k->sign_sec, CRYPT_SIGN_SKEY_LEN);
|
2024-03-21 17:50:55 +04:00
|
|
|
}
|
|
|
|
|
2024-03-23 04:21:41 +04:00
|
|
|
int crypt_key_export_public(const crypt_key_t *const k, char hex[CRYPT_PKEY_HEXLEN]) {
|
|
|
|
if (sodium_bin2hex(hex, CRYPT_KX_PKEY_LEN * 2 + 1, k->kx_pub, CRYPT_KX_PKEY_LEN) == NULL)
|
|
|
|
return -1;
|
|
|
|
if (sodium_bin2hex(hex+(CRYPT_KX_PKEY_LEN * 2), CRYPT_SIGN_PKEY_LEN * 2 + 1, k->sign_pub, CRYPT_SIGN_PKEY_LEN) == NULL)
|
|
|
|
return -1;
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
int crypt_key_export_secret(const crypt_key_t *const k, char hex[CRYPT_SKEY_HEXLEN]) {
|
|
|
|
if (!k->hasSecKey)
|
|
|
|
return -1;
|
|
|
|
|
|
|
|
if (sodium_bin2hex(hex, CRYPT_KX_SKEY_LEN * 2 + 1, k->kx_sec, CRYPT_KX_SKEY_LEN) == NULL)
|
|
|
|
return -1;
|
|
|
|
if (sodium_bin2hex(hex+(CRYPT_KX_SKEY_LEN * 2), CRYPT_SIGN_SKEY_LEN * 2 + 1, k->sign_sec, CRYPT_SIGN_SKEY_LEN) == NULL)
|
|
|
|
return -1;
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
int crypt_load_key(crypt_key_t *const k, FILE *const pub, FILE *const sec) {
|
|
|
|
if (pub == NULL || sec == NULL)
|
|
|
|
return -1;
|
|
|
|
|
|
|
|
char phex[CRYPT_PKEY_HEXLEN], shex[CRYPT_SKEY_HEXLEN];
|
|
|
|
|
|
|
|
if (fread(phex, sizeof(phex[0]), CRYPT_PKEY_HEXLEN, pub) != CRYPT_PKEY_HEXLEN)
|
|
|
|
return -1;
|
|
|
|
if (fread(shex, sizeof(shex[0]), CRYPT_SKEY_HEXLEN, sec) != CRYPT_SKEY_HEXLEN)
|
|
|
|
return -1;
|
|
|
|
|
|
|
|
return crypt_key_from_hex(k, phex, shex);
|
2024-03-21 17:50:55 +04:00
|
|
|
}
|
|
|
|
|
2024-03-23 04:21:41 +04:00
|
|
|
int crypt_store_key(const crypt_key_t *const k, FILE *const pub, FILE *const sec) {
|
|
|
|
if (!k->hasSecKey || pub == NULL || sec == NULL)
|
|
|
|
return -1;
|
|
|
|
|
|
|
|
char phex[CRYPT_PKEY_HEXLEN], shex[CRYPT_SKEY_HEXLEN];
|
|
|
|
|
|
|
|
if (crypt_key_export_public(k, phex) < 0)
|
|
|
|
return -1;
|
|
|
|
if (crypt_key_export_secret(k, shex) < 0)
|
|
|
|
return -1;
|
|
|
|
|
|
|
|
if (fwrite(phex, sizeof(phex[0]), CRYPT_PKEY_HEXLEN, pub) != CRYPT_PKEY_HEXLEN)
|
|
|
|
return -1;
|
|
|
|
if (fwrite(shex, sizeof(shex[0]), CRYPT_SKEY_HEXLEN, sec) != CRYPT_SKEY_HEXLEN)
|
|
|
|
return -1;
|
|
|
|
|
|
|
|
return 0;
|
2024-03-22 04:16:43 +04:00
|
|
|
}
|
|
|
|
|
2024-03-23 05:52:03 +04:00
|
|
|
unsigned char *crypt_hello(const crypt_key_t *const own) {
|
|
|
|
unsigned char *hello = (unsigned char *)malloc(CRYPT_HELLO_LEN * sizeof(unsigned char));
|
|
|
|
|
|
|
|
crypt_key_export_public(own, (char *const)hello);
|
|
|
|
|
|
|
|
if (crypto_sign_detached(hello+CRYPT_PKEY_HEXLEN, NULL, (const unsigned char *)hello, CRYPT_PKEY_HEXLEN, own->sign_sec) == -1) {
|
2024-03-23 04:21:41 +04:00
|
|
|
return NULL;
|
2024-03-23 05:52:03 +04:00
|
|
|
}
|
|
|
|
|
2024-03-24 02:18:27 +04:00
|
|
|
randombytes_buf(hello+CRYPT_PKEY_HEXLEN+CRYPT_SIGN_LEN, CRYPT_NONCEHALF_LEN);
|
|
|
|
|
2024-03-23 05:52:03 +04:00
|
|
|
return hello;
|
|
|
|
}
|
|
|
|
|
|
|
|
int crypt_hello_verify(const unsigned char *const hello, crypt_key_t *const remote) {
|
|
|
|
if (crypt_key_from_hex_public(remote, (const char *const)hello) < 0)
|
|
|
|
return -1;
|
|
|
|
|
2024-03-24 02:18:27 +04:00
|
|
|
if (crypto_sign_verify_detached(hello+CRYPT_PKEY_HEXLEN, (const unsigned char *const)hello, CRYPT_PKEY_HEXLEN, remote->sign_pub))
|
|
|
|
return -1;
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2024-03-24 04:54:59 +04:00
|
|
|
unsigned char *crypt_hello_get_nonce(const unsigned char *const own_hello, const unsigned char *const remote_hello, bool is_client) {
|
2024-03-24 02:18:27 +04:00
|
|
|
unsigned char *nonce = (unsigned char *)malloc(CRYPT_NONCE_LEN * sizeof(unsigned char));
|
|
|
|
if (nonce == NULL)
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
const unsigned char *first = NULL, *second = NULL;
|
|
|
|
|
|
|
|
first = (is_client ? own_hello : remote_hello) + CRYPT_PKEY_HEXLEN+CRYPT_SIGN_LEN;
|
|
|
|
second = (is_client ? remote_hello : own_hello) + CRYPT_PKEY_HEXLEN+CRYPT_SIGN_LEN;
|
|
|
|
|
|
|
|
memcpy(nonce, first, CRYPT_NONCEHALF_LEN);
|
|
|
|
memcpy(nonce+CRYPT_NONCEHALF_LEN, second, CRYPT_NONCEHALF_LEN);
|
|
|
|
|
|
|
|
return nonce;
|
2024-03-22 04:16:43 +04:00
|
|
|
}
|
|
|
|
|
2024-03-24 04:38:32 +04:00
|
|
|
int crypt_session_init(crypt_session_t *const s, const crypt_key_t *const own, crypt_key_t *const remote, const unsigned char *const nonce, bool is_client) {
|
2024-03-22 03:32:40 +04:00
|
|
|
if (is_client) {
|
|
|
|
if (crypto_kx_client_session_keys(s->rx, s->tx, own->kx_pub, own->kx_sec, remote->kx_pub) != 0) {
|
2024-03-21 17:50:55 +04:00
|
|
|
fprintf(stderr, "Failed to instantiate a client session.\n");
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
} else {
|
2024-03-22 03:32:40 +04:00
|
|
|
if (crypto_kx_server_session_keys(s->rx, s->tx, own->kx_pub, own->kx_sec, remote->kx_pub) != 0) {
|
2024-03-21 17:50:55 +04:00
|
|
|
fprintf(stderr, "Failed to instantiate a server session.\n");
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2024-03-22 03:32:40 +04:00
|
|
|
s->remote_key = remote;
|
2024-03-21 17:50:55 +04:00
|
|
|
|
2024-03-24 04:38:32 +04:00
|
|
|
memcpy(s->nonce, nonce, CRYPT_NONCE_LEN);
|
|
|
|
|
2024-03-21 17:50:55 +04:00
|
|
|
return 0;
|
2024-03-23 04:21:41 +04:00
|
|
|
}
|
|
|
|
|
2024-03-24 04:38:32 +04:00
|
|
|
unsigned char *crypt_session_encrypt(crypt_session_t *const s, const unsigned char *const m, unsigned long long mlen, unsigned long long *clen) {
|
|
|
|
unsigned char *c = (unsigned char *)malloc((mlen + crypto_aead_aegis256_ABYTES) * sizeof(unsigned char));
|
|
|
|
|
|
|
|
crypto_aead_aegis256_encrypt(c, clen, m, mlen, NULL, 0, NULL, s->nonce, s->tx);
|
|
|
|
|
|
|
|
return c;
|
|
|
|
}
|
|
|
|
|
|
|
|
unsigned char *crypt_session_decrypt(crypt_session_t *const s, const unsigned char *const c, unsigned long long clen, unsigned long long *mlen) {
|
|
|
|
unsigned char *m = (unsigned char *)malloc((clen - crypto_aead_aegis256_ABYTES) * sizeof(unsigned char));
|
|
|
|
|
|
|
|
if (crypto_aead_aegis256_decrypt(m, mlen, NULL, c, clen, NULL, 0, s->nonce, s->rx) != 0) {
|
|
|
|
free(m);
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
return m;
|
|
|
|
}
|
|
|
|
|
2024-03-23 04:21:41 +04:00
|
|
|
void crypt_session_destroy(crypt_session_t *const s) {
|
|
|
|
sodium_memzero(s->rx, CRYPT_SESS_KEY_LEN);
|
|
|
|
sodium_memzero(s->tx, CRYPT_SESS_KEY_LEN);
|
2024-03-24 04:38:32 +04:00
|
|
|
sodium_memzero(s->nonce, CRYPT_NONCE_LEN);
|
2024-03-23 04:21:41 +04:00
|
|
|
crypt_key_destroy(s->remote_key);
|
2024-03-21 17:50:55 +04:00
|
|
|
}
|