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_ */ | 
