diff --git a/src/crypt.c b/src/crypt.c index ddd4ec0..9efb2d7 100644 --- a/src/crypt.c +++ b/src/crypt.c @@ -1,8 +1,9 @@ #include "crypt.h" +#include #include -int crypt_key_gen(crypt_key_t *k) { +int crypt_key_gen(crypt_key_t *const k) { if (crypto_kx_keypair(k->kx_pub, k->kx_sec) < 0) { return -1; } @@ -16,19 +17,14 @@ int crypt_key_gen(crypt_key_t *k) { return 0; } -int crypt_key_from_hex(crypt_key_t *k, char phex[CRYPT_PUBKEY_HEXSIZE], char shex[CRYPT_SECKEY_HEXSIZE]) { - int res = 0; - res = sodium_hex2bin(k->kx_pub, crypto_kx_PUBLICKEYBYTES, phex, crypto_kx_PUBLICKEYBYTES * 2, NULL, NULL, NULL); - if (res < 0) +int crypt_key_from_hex(crypt_key_t *const k, char phex[CRYPT_PKEY_HEXLEN], char shex[CRYPT_SKEY_HEXLEN]) { + if (sodium_hex2bin(k->kx_pub, CRYPT_KX_PKEY_LEN, phex, CRYPT_KX_PKEY_LEN * 2, NULL, NULL, NULL) < 0) return -1; - res = sodium_hex2bin(k->kx_sec, crypto_kx_SECRETKEYBYTES, shex, crypto_kx_SECRETKEYBYTES * 2, NULL, NULL, NULL); - if (res < 0) + if (sodium_hex2bin(k->kx_sec, CRYPT_KX_SKEY_LEN, shex, CRYPT_KX_SKEY_LEN * 2, NULL, NULL, NULL) < 0) return -1; - res = sodium_hex2bin(k->sign_pub, crypto_sign_PUBLICKEYBYTES, phex+(crypto_kx_PUBLICKEYBYTES * 2), crypto_sign_PUBLICKEYBYTES * 2, NULL, NULL, NULL); - if (res < 0) + 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) return -1; - res = sodium_hex2bin(k->sign_sec, crypto_sign_SECRETKEYBYTES, shex+(crypto_kx_SECRETKEYBYTES * 2), crypto_sign_SECRETKEYBYTES * 2, NULL, NULL, NULL); - if (res < 0) + 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) return -1; k->hasSecKey = true; @@ -36,13 +32,10 @@ int crypt_key_from_hex(crypt_key_t *k, char phex[CRYPT_PUBKEY_HEXSIZE], char she return 0; } -int crypt_key_from_hex_public(crypt_key_t *k, char phex[CRYPT_PUBKEY_HEXSIZE]) { - int res = 0; - res = sodium_hex2bin(k->kx_pub, crypto_kx_PUBLICKEYBYTES, phex, crypto_kx_PUBLICKEYBYTES * 2, NULL, NULL, NULL); - if (res < 0) +int crypt_key_from_hex_public(crypt_key_t *const k, char phex[CRYPT_PKEY_HEXLEN]) { + if (sodium_hex2bin(k->kx_pub, CRYPT_KX_PKEY_LEN, phex, CRYPT_KX_PKEY_LEN * 2, NULL, NULL, NULL) < 0) return -1; - res = sodium_hex2bin(k->sign_pub, crypto_sign_PUBLICKEYBYTES, phex+(crypto_kx_PUBLICKEYBYTES * 2), crypto_sign_PUBLICKEYBYTES * 2, NULL, NULL, NULL); - if (res < 0) + 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) return -1; k->hasSecKey = false; @@ -50,30 +43,78 @@ int crypt_key_from_hex_public(crypt_key_t *k, char phex[CRYPT_PUBKEY_HEXSIZE]) { return 0; } -void crypt_key_export_public(crypt_key_t *k, char hex[CRYPT_PUBKEY_HEXSIZE]) { - sodium_bin2hex(hex, crypto_kx_PUBLICKEYBYTES * 2 + 1, k->kx_pub, crypto_kx_PUBLICKEYBYTES); - sodium_bin2hex(hex+(crypto_kx_PUBLICKEYBYTES * 2), crypto_sign_PUBLICKEYBYTES * 2 + 1, k->sign_pub, crypto_sign_PUBLICKEYBYTES); +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); } -void crypt_key_export_secret(crypt_key_t *k, char hex[CRYPT_SECKEY_HEXSIZE]) { - sodium_bin2hex(hex, crypto_kx_SECRETKEYBYTES * 2 + 1, k->kx_sec, crypto_kx_SECRETKEYBYTES); - sodium_bin2hex(hex+(crypto_kx_SECRETKEYBYTES * 2), crypto_sign_SECRETKEYBYTES * 2 + 1, k->sign_sec, crypto_sign_SECRETKEYBYTES); +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; } -void crypt_store_public_key(crypt_key_t *k, FILE *out_file) { - char phex[CRYPT_PUBKEY_HEXSIZE+1]; - crypt_key_export_public(k, phex); - int o = fwrite(phex, sizeof(phex[0]), CRYPT_PUBKEY_HEXSIZE, out_file); - printf("%li %i | %i\n", sizeof(phex[0]), CRYPT_PUBKEY_HEXSIZE, o); +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; } -void crypt_store_secret_key(crypt_key_t *k, FILE *out_file) { - char shex[CRYPT_SECKEY_HEXSIZE+1]; - crypt_key_export_secret(k, shex); - fwrite(shex, sizeof(shex[0]), CRYPT_SECKEY_HEXSIZE, out_file); +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); } -int crypt_session_init(crypt_session_t *s, crypt_key_t *own, crypt_key_t *remote, bool is_client) { +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; +} + +unsigned char *crypt_hello(const crypt_key_t *const own, long long unsigned int *const sign_len) { + char pub_hex[CRYPT_PKEY_HEXLEN]; + crypt_key_export_public(own, pub_hex); + *sign_len = crypto_sign_BYTES + CRYPT_PKEY_HEXLEN; + unsigned char *sign = (unsigned char *)malloc(*sign_len * sizeof(unsigned char)); + if (crypto_sign(sign, sign_len, (const unsigned char *)pub_hex, CRYPT_PKEY_HEXLEN, own->sign_sec) == -1) + return NULL; + return sign; +} + +int crypt_session_init(crypt_session_t *const s, const crypt_key_t *const own, crypt_key_t *const remote, const bool is_client) { if (is_client) { if (crypto_kx_client_session_keys(s->rx, s->tx, own->kx_pub, own->kx_sec, remote->kx_pub) != 0) { fprintf(stderr, "Failed to instantiate a client session.\n"); @@ -89,4 +130,10 @@ int crypt_session_init(crypt_session_t *s, crypt_key_t *own, crypt_key_t *remote s->remote_key = remote; return 0; +} + +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); + crypt_key_destroy(s->remote_key); } \ No newline at end of file diff --git a/src/crypt.h b/src/crypt.h index 9a483ec..ee3aa8f 100644 --- a/src/crypt.h +++ b/src/crypt.h @@ -6,9 +6,16 @@ #include -#define CRYPT_PUBKEY_HEXSIZE (crypto_kx_PUBLICKEYBYTES + crypto_sign_PUBLICKEYBYTES) * 2 -#define CRYPT_SECKEY_HEXSIZE (crypto_kx_SECRETKEYBYTES + crypto_sign_SECRETKEYBYTES) * 2 +#define CRYPT_KX_PKEY_LEN crypto_kx_PUBLICKEYBYTES +#define CRYPT_KX_SKEY_LEN crypto_kx_SECRETKEYBYTES +#define CRYPT_SIGN_PKEY_LEN crypto_sign_PUBLICKEYBYTES +#define CRYPT_SIGN_SKEY_LEN crypto_sign_SECRETKEYBYTES +#define CRYPT_SESS_KEY_LEN crypto_kx_SESSIONKEYBYTES +#define CRYPT_PKEY_HEXLEN (CRYPT_KX_PKEY_LEN + CRYPT_SIGN_PKEY_LEN) * 2 +#define CRYPT_SKEY_HEXLEN (CRYPT_SIGN_PKEY_LEN + CRYPT_SIGN_SKEY_LEN) * 2 + +// Stores the public and secret keys used in a key exchange and for signing. typedef struct crypt_key_t { unsigned char kx_pub[crypto_kx_PUBLICKEYBYTES]; unsigned char kx_sec[crypto_kx_SECRETKEYBYTES]; @@ -17,22 +24,45 @@ typedef struct crypt_key_t { bool hasSecKey; } crypt_key_t; -int crypt_key_gen(crypt_key_t *k); -int crypt_key_from_hex(crypt_key_t *k, char phex[CRYPT_PUBKEY_HEXSIZE], char shex[CRYPT_SECKEY_HEXSIZE]); -int crypt_key_from_hex_public(crypt_key_t *k, char phex[CRYPT_PUBKEY_HEXSIZE]); +// Generates the new pairs of a key exchange and sign keys. +int crypt_key_gen(crypt_key_t *const k); +// Initialise a crypt_key_t with a provided hex representaions of public and secret keys. +int crypt_key_from_hex(crypt_key_t *const k, char phex[CRYPT_PKEY_HEXLEN], char shex[CRYPT_SKEY_HEXLEN]); +// Initialise a crypt_key_t with a provided hex representaion of just a public key. Used for remote keys. +int crypt_key_from_hex_public(crypt_key_t *const k, char phex[CRYPT_PKEY_HEXLEN]); -void crypt_key_export_public(crypt_key_t *k, char hex[CRYPT_PUBKEY_HEXSIZE]); -void crypt_key_export_secret(crypt_key_t *k, char hex[CRYPT_SECKEY_HEXSIZE]); +// Securely erase the fields of a crypt_key_t struct. +void crypt_key_destroy(crypt_key_t *const k); -void crypt_store_public_key(crypt_key_t *k, FILE *out_file); -void crypt_store_secret_key(crypt_key_t *k, FILE *out_file); +// Export a public sign and key exchange keys as a hex string. +int crypt_key_export_public(const crypt_key_t *const k, char hex[CRYPT_PKEY_HEXLEN]); +// Export a secret sign and key exchange keys as a hex string. +int crypt_key_export_secret(const crypt_key_t *const k, char hex[CRYPT_SKEY_HEXLEN]); +// Load the sign and key exchange keys in a hex representaion from files +// and initialise a crypt_key_t. +int crypt_load_key(crypt_key_t *const k, FILE *const pub, FILE *const sec); +// Store a hex representaion of the sign and key exchange keys into files +// that are corresponding to a public and a secret parts. +int crypt_store_key(const crypt_key_t *const k, FILE *const pub, FILE *const sec); + +// Returns a hello packet consisting of a public key and its sign. +// The packet is sign_len long. +unsigned char *crypt_hello(const crypt_key_t *const own, long long unsigned int *const sign_len); + +// Stores symmetric keys used for a data encryption in both directions +// and a remote public key. typedef struct crypt_session_t { - unsigned char rx[crypto_kx_SESSIONKEYBYTES]; - unsigned char tx[crypto_kx_SESSIONKEYBYTES]; + unsigned char rx[CRYPT_SESS_KEY_LEN]; + unsigned char tx[CRYPT_SESS_KEY_LEN]; crypt_key_t *remote_key; } crypt_session_t; -int crypt_session_init(crypt_session_t *s, crypt_key_t *own, crypt_key_t *remote, bool is_client); +// Derives the symmetric keys for a data encryption using own public and secret and remote's public keys. +// +// is_client should be set to true if you are the one establishing the connection. +int crypt_session_init(crypt_session_t *const s, const crypt_key_t *const own, crypt_key_t *const remote, const bool is_client); +// Securely erase the fields of a crypt_session_t struct. +void crypt_session_destroy(crypt_session_t *const s); #endif /* _CRYPT_H_ */ \ No newline at end of file