diff options
author | Ian Moffett <ian@osmora.org> | 2024-09-25 21:15:02 -0400 |
---|---|---|
committer | Ian Moffett <ian@osmora.org> | 2024-09-25 21:15:02 -0400 |
commit | 845481ad91fb7aba8b335083bd8f3fe224b3a376 (patch) | |
tree | 097a867696bb84b87e604afeb7a4ce483c571c92 | |
parent | 9cb48c92ea0f653c0924a466be07e5ac11a67ee7 (diff) |
lib: crypto: Add session key generation
Signed-off-by: Ian Moffett <ian@osmora.org>
-rw-r--r-- | lib/crypto/ecdh.c | 101 | ||||
-rw-r--r-- | lib/include/crypto/ecdh.h | 3 |
2 files changed, 104 insertions, 0 deletions
diff --git a/lib/crypto/ecdh.c b/lib/crypto/ecdh.c index b7c6f2b..31d5fd9 100644 --- a/lib/crypto/ecdh.c +++ b/lib/crypto/ecdh.c @@ -27,6 +27,7 @@ * POSSIBILITY OF SUCH DAMAGE. */ +#include <sys/mman.h> #include <openssl/evp.h> #include <openssl/ec.h> #include <openssl/pem.h> @@ -35,6 +36,8 @@ #include <crypto/ecdh.h> #include <stdio.h> +#define KEY_SIZE 32 + int gen_x25519_keypair(struct x25519_keypair *res) { @@ -123,3 +126,101 @@ free_x25519_keypair(struct x25519_keypair *xkp) free(xkp->privkey); return 0; } + +int +gen_session_key(const unsigned char *priv, const unsigned char *peer_key, + unsigned char **res) +{ + size_t tmp; + unsigned char *session_key; + EVP_PKEY *own_key = NULL; + EVP_PKEY *peer_pubkey = NULL; + EVP_PKEY_CTX *ctx = NULL; + + /* Allocate memory for session key */ + session_key = malloc(KEY_SIZE); + if (session_key == NULL) { + printf("Failed to allocate session key memory\n"); + return -1; + } + + /* Lock and load session key pages */ + if (mlock(session_key, KEY_SIZE) != 0) { + printf("Failed to lock session key pages\n"); + free(session_key); + return -1; + } + + /* Create an EVP_PKEY from our private key */ + own_key = EVP_PKEY_new_raw_private_key(EVP_PKEY_X25519, NULL, priv, + KEY_SIZE); + + if (own_key == NULL) { + printf("Failed to serialize private key\n"); + free_session_key(session_key); + return -1; + } + + /* Create an EVP_PKEY for peer public key */ + peer_pubkey = EVP_PKEY_new_raw_public_key(EVP_PKEY_X25519, NULL, + peer_key, KEY_SIZE); + + if (peer_pubkey == NULL) { + printf("Failed to serialize peer public key\n"); + EVP_PKEY_free(own_key); + free_session_key(session_key); + return -1; + } + + ctx = EVP_PKEY_CTX_new(own_key, NULL); + if (ctx == NULL) { + printf("Failed to create context\n"); + EVP_PKEY_free(own_key); + EVP_PKEY_free(peer_pubkey); + free_session_key(session_key); + return -1; + } + + /* Initialize key derivation */ + if (EVP_PKEY_derive_init(ctx) <= 0) { + printf("Failed initializing key derivation\n"); + EVP_PKEY_CTX_free(ctx); + EVP_PKEY_free(own_key); + EVP_PKEY_free(peer_pubkey); + free_session_key(session_key); + return -1; + } + + /* Set peer public key */ + if (EVP_PKEY_derive_set_peer(ctx, peer_pubkey) <= 0) { + printf("Failed to set peer key\n"); + EVP_PKEY_CTX_free(ctx); + EVP_PKEY_free(own_key); + EVP_PKEY_free(peer_pubkey); + free_session_key(session_key); + return -1; + } + + /* Derive the session key */ + if (EVP_PKEY_derive(ctx, session_key, &tmp) <= 0) { + printf("Failed to derive session key\n"); + EVP_PKEY_CTX_free(ctx); + EVP_PKEY_free(own_key); + EVP_PKEY_free(peer_pubkey); + free_session_key(session_key); + return -1; + } + + EVP_PKEY_CTX_free(ctx); + EVP_PKEY_free(own_key); + EVP_PKEY_free(peer_pubkey); + *res = session_key; + return 0; +} + +int +free_session_key(unsigned char *session_key) +{ + munlock(session_key, KEY_SIZE); + free(session_key); +} diff --git a/lib/include/crypto/ecdh.h b/lib/include/crypto/ecdh.h index 6c87bbe..c28dbd5 100644 --- a/lib/include/crypto/ecdh.h +++ b/lib/include/crypto/ecdh.h @@ -41,5 +41,8 @@ struct x25519_keypair { int gen_x25519_keypair(struct x25519_keypair *res); int free_x25519_keypair(struct x25519_keypair *xkp); +int gen_session_key(const unsigned char *priv, + const unsigned char *peer_pubkey, unsigned char **res); +int free_session_key(unsigned char *session_key); #endif /* CRYPTO_ECDH_H_ */ |