aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorIan Moffett <ian@osmora.org>2024-09-25 21:15:02 -0400
committerIan Moffett <ian@osmora.org>2024-09-25 21:15:02 -0400
commit845481ad91fb7aba8b335083bd8f3fe224b3a376 (patch)
tree097a867696bb84b87e604afeb7a4ce483c571c92
parent9cb48c92ea0f653c0924a466be07e5ac11a67ee7 (diff)
lib: crypto: Add session key generation
Signed-off-by: Ian Moffett <ian@osmora.org>
-rw-r--r--lib/crypto/ecdh.c101
-rw-r--r--lib/include/crypto/ecdh.h3
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_ */