diff options
author | Toni Uhlig <matzeton@googlemail.com> | 2025-02-24 09:40:59 +0100 |
---|---|---|
committer | Toni Uhlig <matzeton@googlemail.com> | 2025-02-24 09:40:59 +0100 |
commit | 1a916a49dae7f7000b96d76ea7a6a86f5cf056fb (patch) | |
tree | 55648b6797d5f2483d6be9697e8003910204d6ac | |
parent | 6e7f0a8d179c5ea15d3cc737ffb01f69a58c14e6 (diff) |
Added preps for different packet types + AAD (type+size)add/udp-aes256-gcm
Signed-off-by: Toni Uhlig <matzeton@googlemail.com>
-rw-r--r-- | ncrypt.c | 110 | ||||
-rw-r--r-- | ncrypt.h | 2 |
2 files changed, 81 insertions, 31 deletions
@@ -25,7 +25,7 @@ } while (0); #define PACKET_TYPE_KEYEX 0x00u -#define PACKET_TYPE_DATA 0xFFu +#define PACKET_TYPE_JSON 0xFFu #define NCRYPT_PACKED __attribute__((__packed__)) @@ -59,9 +59,20 @@ union packet uint16_t size; } NCRYPT_PACKED; } NCRYPT_PACKED aad; - unsigned char iv[NCRYPT_AES_IVLEN]; - unsigned char tag[NCRYPT_TAG_SIZE]; - unsigned char data[NCRYPT_BUFFER_SIZE]; + union + { + struct + { + unsigned char pubkey[NCRYPT_X25519_KEYLEN]; + unsigned char signature[32]; + } keyex; + struct + { + unsigned char iv[NCRYPT_AES_IVLEN]; + unsigned char tag[NCRYPT_TAG_SIZE]; + unsigned char data[NCRYPT_BUFFER_SIZE]; + } json; + }; } NCRYPT_PACKED; } NCRYPT_PACKED; @@ -69,9 +80,9 @@ union packet _Static_assert(sizeof(((union packet *)0)->aad.raw) == sizeof(((union packet *)0)->aad.type) + sizeof(((union packet *)0)->aad.size), "NCrypt packet AAD is not equal the expected size"); -_Static_assert(sizeof(((union packet *)0)->raw) == sizeof(((union packet *)0)->aad) + sizeof(((union packet *)0)->iv) + - sizeof(((union packet *)0)->tag) + - sizeof(((union packet *)0)->data), +_Static_assert(sizeof(((union packet *)0)->raw) == + sizeof(((union packet *)0)->aad) + sizeof(((union packet *)0)->json.iv) + + sizeof(((union packet *)0)->json.tag) + sizeof(((union packet *)0)->json.data), "NCrypt packet is not equal the expected size"); _Static_assert(sizeof(((union iv *)0)->buffer) == sizeof(((union iv *)0)->numeric), "IV buffer must be of the same size as the numerics"); @@ -280,14 +291,13 @@ int ncrypt_init(struct ncrypt * const nc, size_t secret_len = 0; struct { - EVP_PKEY * priv_key; unsigned char pub_key[NCRYPT_X25519_KEYLEN]; - } local = {.priv_key = NULL, .pub_key = {}}; + unsigned char uni_dist_shared_key[NCRYPT_X25519_KEYLEN]; + } local = {.pub_key = {}, .uni_dist_shared_key = {}}; struct { EVP_PKEY * pub_key; } remote = {.pub_key = NULL}; - unsigned char uni_dist_shared_key[NCRYPT_X25519_KEYLEN]; if (nc->libctx != NULL) { @@ -299,15 +309,15 @@ int ncrypt_init(struct ncrypt * const nc, return -2; } - local.priv_key = + nc->private_key = EVP_PKEY_new_raw_private_key_ex(nc->libctx, "X25519", nc->propq, local_priv_key, NCRYPT_X25519_KEYLEN); - if (local.priv_key == NULL) + if (nc->private_key == NULL) { return -3; } if (EVP_PKEY_get_octet_string_param( - local.priv_key, OSSL_PKEY_PARAM_PUB_KEY, local.pub_key, sizeof(local.pub_key), &pub_key_datalen) == 0) + nc->private_key, OSSL_PKEY_PARAM_PUB_KEY, local.pub_key, sizeof(local.pub_key), &pub_key_datalen) == 0) { rv = -4; goto error; @@ -326,7 +336,7 @@ int ncrypt_init(struct ncrypt * const nc, goto error; } - key_ctx = EVP_PKEY_CTX_new_from_pkey(nc->libctx, local.priv_key, nc->propq); + key_ctx = EVP_PKEY_CTX_new_from_pkey(nc->libctx, nc->private_key, nc->propq); if (key_ctx == NULL) { rv = -7; @@ -362,22 +372,19 @@ int ncrypt_init(struct ncrypt * const nc, OPENSSL_cleanse(nc->shared_secret, NCRYPT_X25519_KEYLEN); goto error; } - OPENSSL_DUMP(nc->shared_secret, sizeof(nc->shared_secret)); - if (hkdf_x25519(nc->shared_secret, "ncrypt initial keygen", uni_dist_shared_key) != 0) + if (hkdf_x25519(nc->shared_secret, "ncrypt initial keygen", local.uni_dist_shared_key) != 0) { rv = -13; OPENSSL_cleanse(nc->shared_secret, NCRYPT_X25519_KEYLEN); goto error; } - memcpy(nc->shared_secret, uni_dist_shared_key, NCRYPT_X25519_KEYLEN); - OPENSSL_DUMP(nc->shared_secret, sizeof(nc->shared_secret)); + memcpy(nc->shared_secret, local.uni_dist_shared_key, NCRYPT_X25519_KEYLEN); OPENSSL_cleanse(local_priv_key, NCRYPT_X25519_KEYLEN); OPENSSL_cleanse(remote_pub_key, NCRYPT_X25519_KEYLEN); error: EVP_PKEY_CTX_free(key_ctx); - EVP_PKEY_free(local.priv_key); EVP_PKEY_free(remote.pub_key); return rv; @@ -490,6 +497,8 @@ static void cleanup_peers(struct ncrypt * const nc) void ncrypt_free(struct ncrypt * const nc) { + EVP_PKEY_free(nc->private_key); + nc->private_key = NULL; OPENSSL_cleanse(nc->shared_secret, NCRYPT_X25519_KEYLEN); if (nc->libctx != NULL) @@ -624,14 +633,16 @@ int ncrypt_dgram_send(struct ncrypt * const nc, int fd, char const * const plain struct peer * current_peer; struct peer * tmp_peer; union packet encrypted; + encrypted.aad.type = PACKET_TYPE_JSON; HASH_ITER(hh, nc->peers, current_peer, tmp_peer) { + encrypted.aad.size = htons(NCRYPT_AES_IVLEN + NCRYPT_TAG_SIZE + plaintext_size); int encrypted_used = encrypt(¤t_peer->aes, plaintext, plaintext_size, current_peer->iv, - encrypted.data, - encrypted.tag, + encrypted.json.data, + encrypted.json.tag, encrypted.aad.raw); if (encrypted_used < 0 || encrypted_used > (int)NCRYPT_BUFFER_SIZE) { @@ -641,7 +652,7 @@ int ncrypt_dgram_send(struct ncrypt * const nc, int fd, char const * const plain } current_peer->cryptions++; - memcpy(encrypted.iv, current_peer->iv, NCRYPT_AES_IVLEN); + memcpy(encrypted.json.iv, current_peer->iv, NCRYPT_AES_IVLEN); ssize_t bytes_written = sendto(fd, encrypted.raw, NCRYPT_PACKET_OVERHEAD + encrypted_used, @@ -667,6 +678,40 @@ int ncrypt_dgram_send(struct ncrypt * const nc, int fd, char const * const plain return retval; } +static size_t check_packet_size(union packet const * const pkt, size_t bytes_read) +{ + size_t payload_size = 0; + + if (bytes_read < NCRYPT_AAD_SIZE) + { + return 0; + } + payload_size = ntohs(pkt->aad.size); + switch (pkt->aad.type) + { + case PACKET_TYPE_KEYEX: + if (payload_size != sizeof(pkt->keyex)) + { + return 0; + } + break; + case PACKET_TYPE_JSON: + if (payload_size < NCRYPT_AES_IVLEN + NCRYPT_TAG_SIZE + 1) + { + return 0; + } + break; + default: + return 0; + } + if (bytes_read != NCRYPT_AAD_SIZE + payload_size) + { + return 0; + } + + return payload_size; +} + int ncrypt_dgram_recv(struct ncrypt * const nc, int fd, char * const plaintext, size_t plaintext_size) { if (plaintext_size > NCRYPT_BUFFER_SIZE) @@ -682,11 +727,12 @@ int ncrypt_dgram_recv(struct ncrypt * const nc, int fd, char * const plaintext, { return -2; } - if (bytes_read < NCRYPT_PACKET_MIN_SIZE) + size_t payload_size = check_packet_size(&encrypted, bytes_read); + if (payload_size == 0) { return -3; } - if (plaintext_size < (size_t)bytes_read - NCRYPT_PACKET_OVERHEAD) + if (plaintext_size < payload_size) { return -4; } @@ -699,26 +745,30 @@ int ncrypt_dgram_recv(struct ncrypt * const nc, int fd, char * const plaintext, return -5; } peer = ncrypt_get_peer(nc, &remote); + if (peer == NULL) + { + return -6; + } ncrypt_init_decrypt(nc, &peer->aes); } - if (memcmp(peer->iv, encrypted.iv, NCRYPT_AES_IVLEN) != 0) + if (memcmp(peer->iv, encrypted.json.iv, NCRYPT_AES_IVLEN) != 0) { peer->iv_mismatches++; - memcpy(peer->iv, encrypted.iv, NCRYPT_AES_IVLEN); + memcpy(peer->iv, encrypted.json.iv, NCRYPT_AES_IVLEN); } int decrypted_used = decrypt(&peer->aes, - encrypted.data, - bytes_read - NCRYPT_PACKET_OVERHEAD, + encrypted.json.data, + payload_size - NCRYPT_AES_IVLEN - NCRYPT_TAG_SIZE, peer->iv, - encrypted.tag, + encrypted.json.tag, plaintext, encrypted.aad.raw); next_iv(peer); if (decrypted_used < 0) { - return -6; + return -7; } peer->cryptions++; @@ -13,7 +13,6 @@ #define NCRYPT_BUFFER_SIZE NETWORK_BUFFER_MAX_SIZE #define NCRYPT_PACKET_OVERHEAD (NCRYPT_AAD_SIZE + NCRYPT_AES_IVLEN + NCRYPT_TAG_SIZE) #define NCRYPT_PACKET_BUFFER_SIZE (NCRYPT_PACKET_OVERHEAD + NCRYPT_BUFFER_SIZE) -#define NCRYPT_PACKET_MIN_SIZE (NCRYPT_PACKET_OVERHEAD + NETWORK_BUFFER_LENGTH_DIGITS + 3 /* "{}\n" */) struct aes { @@ -39,6 +38,7 @@ struct ncrypt { void * libctx; const char * propq; + void * private_key; unsigned char shared_secret[NCRYPT_X25519_KEYLEN]; struct peer * peers; }; |