A crypt module had many changes. *_destroy() funcs were added to securely erase the keys. A set of new defines were introduced to mask the ones from a libsodium. Funcs for load and store the keys in a FILE. Added a crypt_hello() func.
This commit is contained in:
parent
b5d92489b8
commit
a875891088
113
src/crypt.c
113
src/crypt.c
@ -1,8 +1,9 @@
|
|||||||
#include "crypt.h"
|
#include "crypt.h"
|
||||||
|
|
||||||
|
#include <sodium/utils.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
|
||||||
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) {
|
if (crypto_kx_keypair(k->kx_pub, k->kx_sec) < 0) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
@ -16,19 +17,14 @@ int crypt_key_gen(crypt_key_t *k) {
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int crypt_key_from_hex(crypt_key_t *k, char phex[CRYPT_PUBKEY_HEXSIZE], char shex[CRYPT_SECKEY_HEXSIZE]) {
|
int crypt_key_from_hex(crypt_key_t *const k, char phex[CRYPT_PKEY_HEXLEN], char shex[CRYPT_SKEY_HEXLEN]) {
|
||||||
int res = 0;
|
if (sodium_hex2bin(k->kx_pub, CRYPT_KX_PKEY_LEN, phex, CRYPT_KX_PKEY_LEN * 2, NULL, NULL, NULL) < 0)
|
||||||
res = sodium_hex2bin(k->kx_pub, crypto_kx_PUBLICKEYBYTES, phex, crypto_kx_PUBLICKEYBYTES * 2, NULL, NULL, NULL);
|
|
||||||
if (res < 0)
|
|
||||||
return -1;
|
return -1;
|
||||||
res = sodium_hex2bin(k->kx_sec, crypto_kx_SECRETKEYBYTES, shex, crypto_kx_SECRETKEYBYTES * 2, NULL, NULL, NULL);
|
if (sodium_hex2bin(k->kx_sec, CRYPT_KX_SKEY_LEN, shex, CRYPT_KX_SKEY_LEN * 2, NULL, NULL, NULL) < 0)
|
||||||
if (res < 0)
|
|
||||||
return -1;
|
return -1;
|
||||||
res = sodium_hex2bin(k->sign_pub, crypto_sign_PUBLICKEYBYTES, phex+(crypto_kx_PUBLICKEYBYTES * 2), crypto_sign_PUBLICKEYBYTES * 2, NULL, NULL, NULL);
|
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)
|
||||||
if (res < 0)
|
|
||||||
return -1;
|
return -1;
|
||||||
res = sodium_hex2bin(k->sign_sec, crypto_sign_SECRETKEYBYTES, shex+(crypto_kx_SECRETKEYBYTES * 2), crypto_sign_SECRETKEYBYTES * 2, NULL, NULL, NULL);
|
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)
|
||||||
if (res < 0)
|
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
k->hasSecKey = true;
|
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;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int crypt_key_from_hex_public(crypt_key_t *k, char phex[CRYPT_PUBKEY_HEXSIZE]) {
|
int crypt_key_from_hex_public(crypt_key_t *const k, char phex[CRYPT_PKEY_HEXLEN]) {
|
||||||
int res = 0;
|
if (sodium_hex2bin(k->kx_pub, CRYPT_KX_PKEY_LEN, phex, CRYPT_KX_PKEY_LEN * 2, NULL, NULL, NULL) < 0)
|
||||||
res = sodium_hex2bin(k->kx_pub, crypto_kx_PUBLICKEYBYTES, phex, crypto_kx_PUBLICKEYBYTES * 2, NULL, NULL, NULL);
|
|
||||||
if (res < 0)
|
|
||||||
return -1;
|
return -1;
|
||||||
res = sodium_hex2bin(k->sign_pub, crypto_sign_PUBLICKEYBYTES, phex+(crypto_kx_PUBLICKEYBYTES * 2), crypto_sign_PUBLICKEYBYTES * 2, NULL, NULL, NULL);
|
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)
|
||||||
if (res < 0)
|
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
k->hasSecKey = false;
|
k->hasSecKey = false;
|
||||||
@ -50,30 +43,78 @@ int crypt_key_from_hex_public(crypt_key_t *k, char phex[CRYPT_PUBKEY_HEXSIZE]) {
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void crypt_key_export_public(crypt_key_t *k, char hex[CRYPT_PUBKEY_HEXSIZE]) {
|
void crypt_key_destroy(crypt_key_t *const k) {
|
||||||
sodium_bin2hex(hex, crypto_kx_PUBLICKEYBYTES * 2 + 1, k->kx_pub, crypto_kx_PUBLICKEYBYTES);
|
sodium_memzero(k->kx_pub, CRYPT_KX_PKEY_LEN);
|
||||||
sodium_bin2hex(hex+(crypto_kx_PUBLICKEYBYTES * 2), crypto_sign_PUBLICKEYBYTES * 2 + 1, k->sign_pub, crypto_sign_PUBLICKEYBYTES);
|
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]) {
|
int crypt_key_export_public(const crypt_key_t *const k, char hex[CRYPT_PKEY_HEXLEN]) {
|
||||||
sodium_bin2hex(hex, crypto_kx_SECRETKEYBYTES * 2 + 1, k->kx_sec, crypto_kx_SECRETKEYBYTES);
|
if (sodium_bin2hex(hex, CRYPT_KX_PKEY_LEN * 2 + 1, k->kx_pub, CRYPT_KX_PKEY_LEN) == NULL)
|
||||||
sodium_bin2hex(hex+(crypto_kx_SECRETKEYBYTES * 2), crypto_sign_SECRETKEYBYTES * 2 + 1, k->sign_sec, crypto_sign_SECRETKEYBYTES);
|
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) {
|
int crypt_key_export_secret(const crypt_key_t *const k, char hex[CRYPT_SKEY_HEXLEN]) {
|
||||||
char phex[CRYPT_PUBKEY_HEXSIZE+1];
|
if (!k->hasSecKey)
|
||||||
crypt_key_export_public(k, phex);
|
return -1;
|
||||||
int o = fwrite(phex, sizeof(phex[0]), CRYPT_PUBKEY_HEXSIZE, out_file);
|
|
||||||
printf("%li %i | %i\n", sizeof(phex[0]), CRYPT_PUBKEY_HEXSIZE, o);
|
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) {
|
int crypt_load_key(crypt_key_t *const k, FILE *const pub, FILE *const sec) {
|
||||||
char shex[CRYPT_SECKEY_HEXSIZE+1];
|
if (pub == NULL || sec == NULL)
|
||||||
crypt_key_export_secret(k, shex);
|
return -1;
|
||||||
fwrite(shex, sizeof(shex[0]), CRYPT_SECKEY_HEXSIZE, out_file);
|
|
||||||
|
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 (is_client) {
|
||||||
if (crypto_kx_client_session_keys(s->rx, s->tx, own->kx_pub, own->kx_sec, remote->kx_pub) != 0) {
|
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");
|
fprintf(stderr, "Failed to instantiate a client session.\n");
|
||||||
@ -90,3 +131,9 @@ int crypt_session_init(crypt_session_t *s, crypt_key_t *own, crypt_key_t *remote
|
|||||||
|
|
||||||
return 0;
|
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);
|
||||||
|
}
|
54
src/crypt.h
54
src/crypt.h
@ -6,9 +6,16 @@
|
|||||||
|
|
||||||
#include <sodium.h>
|
#include <sodium.h>
|
||||||
|
|
||||||
#define CRYPT_PUBKEY_HEXSIZE (crypto_kx_PUBLICKEYBYTES + crypto_sign_PUBLICKEYBYTES) * 2
|
#define CRYPT_KX_PKEY_LEN crypto_kx_PUBLICKEYBYTES
|
||||||
#define CRYPT_SECKEY_HEXSIZE (crypto_kx_SECRETKEYBYTES + crypto_sign_SECRETKEYBYTES) * 2
|
#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 {
|
typedef struct crypt_key_t {
|
||||||
unsigned char kx_pub[crypto_kx_PUBLICKEYBYTES];
|
unsigned char kx_pub[crypto_kx_PUBLICKEYBYTES];
|
||||||
unsigned char kx_sec[crypto_kx_SECRETKEYBYTES];
|
unsigned char kx_sec[crypto_kx_SECRETKEYBYTES];
|
||||||
@ -17,22 +24,45 @@ typedef struct crypt_key_t {
|
|||||||
bool hasSecKey;
|
bool hasSecKey;
|
||||||
} crypt_key_t;
|
} crypt_key_t;
|
||||||
|
|
||||||
int crypt_key_gen(crypt_key_t *k);
|
// Generates the new pairs of a key exchange and sign keys.
|
||||||
int crypt_key_from_hex(crypt_key_t *k, char phex[CRYPT_PUBKEY_HEXSIZE], char shex[CRYPT_SECKEY_HEXSIZE]);
|
int crypt_key_gen(crypt_key_t *const k);
|
||||||
int crypt_key_from_hex_public(crypt_key_t *k, char phex[CRYPT_PUBKEY_HEXSIZE]);
|
// 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]);
|
// Securely erase the fields of a crypt_key_t struct.
|
||||||
void crypt_key_export_secret(crypt_key_t *k, char hex[CRYPT_SECKEY_HEXSIZE]);
|
void crypt_key_destroy(crypt_key_t *const k);
|
||||||
|
|
||||||
void crypt_store_public_key(crypt_key_t *k, FILE *out_file);
|
// Export a public sign and key exchange keys as a hex string.
|
||||||
void crypt_store_secret_key(crypt_key_t *k, FILE *out_file);
|
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 {
|
typedef struct crypt_session_t {
|
||||||
unsigned char rx[crypto_kx_SESSIONKEYBYTES];
|
unsigned char rx[CRYPT_SESS_KEY_LEN];
|
||||||
unsigned char tx[crypto_kx_SESSIONKEYBYTES];
|
unsigned char tx[CRYPT_SESS_KEY_LEN];
|
||||||
crypt_key_t *remote_key;
|
crypt_key_t *remote_key;
|
||||||
} crypt_session_t;
|
} 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_ */
|
#endif /* _CRYPT_H_ */
|
Loading…
Reference in New Issue
Block a user