1
0
Fork 0

Compare commits

...

10 Commits

Author SHA1 Message Date
Alexander Andreev 3b68835c9c
Oh, because of goto used some var can never be presented, so lets move them right before the first use of a goto. 2024-03-24 04:56:02 +04:00
Alexander Andreev 98581204e9
Well, actually, let a crypt_hello_get_nonce func return just a "unsigned char *" without a const modifier. 2024-03-24 04:54:59 +04:00
Alexander Andreev 8df5a6344e
Another change of main to show an example of key exchange and data encryption. 2024-03-24 04:41:08 +04:00
Alexander Andreev acc016f10b
crypt_session_encrypt() and crypt_session_decrypt() was implemented. 2024-03-24 04:38:32 +04:00
Alexander Andreev 3ec30111e2
Removed an absolutely clueless const modifier from a bool argument that was introduced during a usual late night programming session. :) 2024-03-24 02:23:57 +04:00
Alexander Andreev 0cdca672a0
Now hello has a half of a nonce is being generated. A crypt_hello_get_nonce() func was introduced to make a full-length nonce. 2024-03-24 02:18:27 +04:00
Alexander Andreev 61b1992828
Put just a touch of pointer magick in a crypt module. Also put const modifiers here and there. 2024-03-23 05:52:03 +04:00
Alexander Andreev 2786fb9c87
An unused stdlib.h include was removed from net.c. 2024-03-23 04:22:36 +04:00
Alexander Andreev 0d47261c51
Current state of main. 2024-03-23 04:22:01 +04:00
Alexander Andreev a875891088
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. 2024-03-23 04:21:41 +04:00
4 changed files with 277 additions and 56 deletions

View File

@ -1,8 +1,9 @@
#include "crypt.h"
#include <stdlib.h>
#include <string.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) {
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, const char phex[CRYPT_PKEY_HEXLEN], const 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, const 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,108 @@ 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) {
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) {
return NULL;
}
randombytes_buf(hello+CRYPT_PKEY_HEXLEN+CRYPT_SIGN_LEN, CRYPT_NONCEHALF_LEN);
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;
if (crypto_sign_verify_detached(hello+CRYPT_PKEY_HEXLEN, (const unsigned char *const)hello, CRYPT_PKEY_HEXLEN, remote->sign_pub))
return -1;
return 0;
}
unsigned char *crypt_hello_get_nonce(const unsigned char *const own_hello, const unsigned char *const remote_hello, bool is_client) {
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;
}
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) {
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");
@ -88,5 +159,33 @@ int crypt_session_init(crypt_session_t *s, crypt_key_t *own, crypt_key_t *remote
s->remote_key = remote;
memcpy(s->nonce, nonce, CRYPT_NONCE_LEN);
return 0;
}
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;
}
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);
sodium_memzero(s->nonce, CRYPT_NONCE_LEN);
crypt_key_destroy(s->remote_key);
}

View File

@ -6,9 +6,24 @@
#include <sodium.h>
#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_SIGN_LEN crypto_sign_BYTES
#define CRYPT_SESS_KEY_LEN crypto_kx_SESSIONKEYBYTES
#define CRYPT_NONCE_LEN crypto_aead_aegis256_NPUBBYTES
#define CRYPT_NONCEHALF_LEN (CRYPT_NONCE_LEN/2)
#define CRYPT_HELLO_LEN (CRYPT_PKEY_HEXLEN + CRYPT_SIGN_LEN + (CRYPT_NONCEHALF_LEN))
#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 +32,53 @@ 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, const char phex[CRYPT_PKEY_HEXLEN], const 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, const 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 of CRYPT_SIGN_LEN long.
unsigned char *crypt_hello(const crypt_key_t *const own);
// Verify a hello message. It only shows that a remote public key's sign is ok.
int crypt_hello_verify(const unsigned char *const hello, crypt_key_t *const remote);
// Combines own and remote halves of a nonce depending in a connection direction and returns it.
// It will be of CRYPT_NONCE_LEN length.
unsigned char *crypt_hello_get_nonce(const unsigned char *const own_hello, const unsigned char *const remote_hello, bool is_client);
// 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];
unsigned char nonce[CRYPT_NONCE_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 unsigned char *const nonce, bool is_client);
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 *crypt_session_decrypt(crypt_session_t *const s, const unsigned char *const c, unsigned long long clen, unsigned long long *mlen);
// Securely erase the fields of a crypt_session_t struct.
void crypt_session_destroy(crypt_session_t *const s);
#endif /* _CRYPT_H_ */

View File

@ -1,5 +1,5 @@
#include <sodium/utils.h>
#include <stdio.h>
#include <stdint.h>
#include <string.h>
#include "audio.h"
@ -20,25 +20,102 @@ int main(int argc, char **argv) {
return -1;
}
crypt_key_t own;
crypt_key_t own, remote;
if (crypt_key_gen(&own) < 0) {
fprintf(stderr, "Failed to generate the keys.");
return -1;
}
FILE *fp = fopen("own_pub_key", "w");
FILE *fs = fopen("own_sec_key", "w");
if (crypt_key_gen(&remote) < 0) {
fprintf(stderr, "Failed to generate the keys.");
return -1;
}
crypt_store_public_key(&own, fp);
crypt_store_secret_key(&own, fs);
unsigned char *oh = crypt_hello(&own);
unsigned char *rh = crypt_hello(&remote);
fclose(fp);
fclose(fs);
unsigned char *oc = NULL;
char *rmsg = NULL;
unsigned long long ocl = 0, rml = 0;
int rt = 0;
crypt_session_t os, rs;
unsigned char *nonce_own = NULL, *nonce_rem = NULL;
if (crypt_hello_verify(oh, &own) < 0) {
fprintf(stderr, "oh v fail");
rt = -1;
goto cleanup;
}
if (crypt_hello_verify(rh, &remote) < 0) {
fprintf(stderr, "rh v fail");
rt = -1;
goto cleanup;
}
nonce_own = crypt_hello_get_nonce(oh, rh, false);
nonce_rem = crypt_hello_get_nonce(rh, oh, true);
for (unsigned int i = 0; i < CRYPT_NONCE_LEN; ++i)
if (nonce_own[i] != nonce_rem[i]) {
fprintf(stderr, "A nonce mismatch occured.");
rt = -1;
goto cleanup;
}
if (crypt_session_init(&os, &own, &remote, nonce_own, true) < 0) {
rt = -1;
goto cleanup;
}
if (crypt_session_init(&rs, &remote, &own, nonce_rem, false) < 0) {
rt = -1;
goto cleanup;
}
char msg[] = "Hello!";
unsigned long long msglen = 6;
oc = crypt_session_encrypt(&os, (unsigned char *)msg, msglen, &ocl);
if (oc == NULL) {
fprintf(stderr, "oc is null");
rt = -1;
goto cleanup;
}
rmsg = (char *)crypt_session_decrypt(&rs, oc, ocl, &rml);
if (rmsg == NULL) {
rt = -1;
goto cleanup;
}
if (strcmp(msg, rmsg) != 0)
fprintf(stderr, "Yikes!");
cleanup:
free(oh);
free(rh);
free(oc);
free(rmsg);
free(nonce_own);
free(nonce_rem);
crypt_key_destroy(&own);
crypt_key_destroy(&remote);
crypt_session_destroy(&os);
crypt_session_destroy(&rs);
// audio_t aud;
// uint8_t buf[BUF_SIZE];
// unsigned char buf[BUF_SIZE];
// memset(buf, 0, BUF_SIZE);
// audio_init(&aud, CHANNELS, SAMPLE_RATE, FRAMES_PER_BUFFFER);
@ -52,5 +129,5 @@ int main(int argc, char **argv) {
// audio_destroy(&aud);
return 0;
return rt;
}

View File

@ -1,6 +1,5 @@
#include "net.h"
#include <stdlib.h>
#include <string.h>
#include <unistd.h>