Commit 1aa26e8d71 for strongswan.org
commit 1aa26e8d71220788b8869db1d3b002c7d9bdd55d
Author: Tobias Brunner <tobias@strongswan.org>
Date: Mon Feb 23 18:59:43 2026 +0100
openssl: Add generic loader for public keys to avoid pkcs1 dependency
This can load public keys of unknown type via KEY_ANY without requiring
the pkcs1 plugin.
diff --git a/src/libstrongswan/plugins/openssl/openssl_ec_public_key.c b/src/libstrongswan/plugins/openssl/openssl_ec_public_key.c
index 7c21902a72..2d57d8429f 100644
--- a/src/libstrongswan/plugins/openssl/openssl_ec_public_key.c
+++ b/src/libstrongswan/plugins/openssl/openssl_ec_public_key.c
@@ -42,10 +42,11 @@ typedef struct private_openssl_ec_public_key_t private_openssl_ec_public_key_t;
* Private data structure with signing context.
*/
struct private_openssl_ec_public_key_t {
+
/**
- * Public interface for this signer.
+ * Public interface
*/
- openssl_ec_public_key_t public;
+ public_key_t public;
/**
* EC key object
@@ -282,7 +283,7 @@ METHOD(public_key_t, get_ref, public_key_t*,
private_openssl_ec_public_key_t *this)
{
ref_get(&this->ref);
- return &this->public.key;
+ return &this->public;
}
METHOD(public_key_t, destroy, void,
@@ -319,13 +320,44 @@ bool openssl_check_explicit_params(const EVP_PKEY *key)
return explicit == 1;
}
+/*
+ * Described in header
+ */
+public_key_t *openssl_ec_public_key_create(EVP_PKEY *key)
+{
+ private_openssl_ec_public_key_t *this;
+
+ if (!key || EVP_PKEY_base_id(key) != EVP_PKEY_EC ||
+ openssl_check_explicit_params(key))
+ {
+ EVP_PKEY_free(key);
+ return NULL;
+ }
+
+ INIT(this,
+ .public = {
+ .get_type = _get_type,
+ .verify = _verify,
+ .encrypt = _encrypt,
+ .get_keysize = _get_keysize,
+ .equals = public_key_equals,
+ .get_fingerprint = _get_fingerprint,
+ .has_fingerprint = public_key_has_fingerprint,
+ .get_encoding = _get_encoding,
+ .get_ref = _get_ref,
+ .destroy = _destroy,
+ },
+ .ref = 1,
+ .key = key,
+ );
+ return &this->public;
+}
+
/**
* See header.
*/
-openssl_ec_public_key_t *openssl_ec_public_key_load(key_type_t type,
- va_list args)
+public_key_t *openssl_ec_public_key_load(key_type_t type, va_list args)
{
- private_openssl_ec_public_key_t *this;
chunk_t blob = chunk_empty;
EVP_PKEY *key;
@@ -344,32 +376,7 @@ openssl_ec_public_key_t *openssl_ec_public_key_load(key_type_t type,
break;
}
key = d2i_PUBKEY(NULL, (const u_char**)&blob.ptr, blob.len);
- if (!key || EVP_PKEY_base_id(key) != EVP_PKEY_EC ||
- openssl_check_explicit_params(key))
- {
- EVP_PKEY_free(key);
- return NULL;
- }
-
- INIT(this,
- .public = {
- .key = {
- .get_type = _get_type,
- .verify = _verify,
- .encrypt = _encrypt,
- .get_keysize = _get_keysize,
- .equals = public_key_equals,
- .get_fingerprint = _get_fingerprint,
- .has_fingerprint = public_key_has_fingerprint,
- .get_encoding = _get_encoding,
- .get_ref = _get_ref,
- .destroy = _destroy,
- },
- },
- .ref = 1,
- .key = key,
- );
- return &this->public;
+ return openssl_ec_public_key_create(key);
}
#endif /* OPENSSL_NO_ECDSA */
diff --git a/src/libstrongswan/plugins/openssl/openssl_ec_public_key.h b/src/libstrongswan/plugins/openssl/openssl_ec_public_key.h
index 7b380487de..19a3092a81 100644
--- a/src/libstrongswan/plugins/openssl/openssl_ec_public_key.h
+++ b/src/libstrongswan/plugins/openssl/openssl_ec_public_key.h
@@ -15,6 +15,8 @@
*/
/**
+ * public_key_t implementation of ECDSA using OpenSSL
+ *
* @defgroup openssl_ec_public_key openssl_ec_public_key
* @{ @ingroup openssl_p
*/
@@ -22,22 +24,10 @@
#ifndef OPENSSL_EC_PUBLIC_KEY_H_
#define OPENSSL_EC_PUBLIC_KEY_H_
-typedef struct openssl_ec_public_key_t openssl_ec_public_key_t;
+#include <openssl/evp.h>
-#include <credentials/builder.h>
#include <credentials/keys/public_key.h>
-/**
- * public_key_t implementation of ECDSA using OpenSSL.
- */
-struct openssl_ec_public_key_t {
-
- /**
- * Implements the public_key_t interface
- */
- public_key_t key;
-};
-
/**
* Load a ECDSA public key using OpenSSL.
*
@@ -47,7 +37,14 @@ struct openssl_ec_public_key_t {
* @param args builder_part_t argument list
* @return loaded key, NULL on failure
*/
-openssl_ec_public_key_t *openssl_ec_public_key_load(key_type_t type,
- va_list args);
+public_key_t *openssl_ec_public_key_load(key_type_t type, va_list args);
+
+/**
+ * Wrap an EVP_PKEY object of type ECDSA.
+ *
+ * @param key EVP_PKEY object (adopted)
+ * @return generated key, NULL on failure
+ */
+public_key_t *openssl_ec_public_key_create(EVP_PKEY *key);
#endif /** OPENSSL_EC_PUBLIC_KEY_H_ @}*/
diff --git a/src/libstrongswan/plugins/openssl/openssl_ed_private_key.c b/src/libstrongswan/plugins/openssl/openssl_ed_private_key.c
index b6974ca1a4..3a29900218 100644
--- a/src/libstrongswan/plugins/openssl/openssl_ed_private_key.c
+++ b/src/libstrongswan/plugins/openssl/openssl_ed_private_key.c
@@ -67,6 +67,7 @@ int asn1_unwrap(chunk_t*, chunk_t*);
/* from ed public key */
int openssl_ed_key_type(key_type_t type);
+key_type_t openssl_ed_evp_pkey_key_type(EVP_PKEY *key);
int openssl_ed_keysize(key_type_t type);
METHOD(private_key_t, sign, bool,
@@ -257,17 +258,11 @@ private_key_t *openssl_ed_private_key_create(EVP_PKEY *key, bool engine)
private_private_key_t *this;
key_type_t type;
- switch (EVP_PKEY_base_id(key))
+ type = openssl_ed_evp_pkey_key_type(key);
+ if (type == KEY_ANY)
{
- case EVP_PKEY_ED25519:
- type = KEY_ED25519;
- break;
- case EVP_PKEY_ED448:
- type = KEY_ED448;
- break;
- default:
- EVP_PKEY_free(key);
- return NULL;
+ EVP_PKEY_free(key);
+ return NULL;
}
this = create_internal(type, key);
diff --git a/src/libstrongswan/plugins/openssl/openssl_ed_public_key.c b/src/libstrongswan/plugins/openssl/openssl_ed_public_key.c
index 0467c3d79a..6eb4ce98dc 100644
--- a/src/libstrongswan/plugins/openssl/openssl_ed_public_key.c
+++ b/src/libstrongswan/plugins/openssl/openssl_ed_public_key.c
@@ -69,6 +69,22 @@ int openssl_ed_key_type(key_type_t type)
}
}
+/**
+ * Map an EVP_PKEY type to a key type
+ */
+key_type_t openssl_ed_evp_pkey_key_type(EVP_PKEY *key)
+{
+ switch (EVP_PKEY_base_id(key))
+ {
+ case EVP_PKEY_ED25519:
+ return KEY_ED25519;
+ case EVP_PKEY_ED448:
+ return KEY_ED448;
+ default:
+ return KEY_ANY;
+ }
+}
+
/**
* Map a key type to a key size
*/
@@ -203,6 +219,28 @@ static private_public_key_t *create_empty(key_type_t type)
return this;
}
+/*
+ * Described in header
+ */
+public_key_t *openssl_ed_public_key_create(EVP_PKEY *key)
+{
+ private_public_key_t *this;
+ key_type_t type;
+
+ if (key)
+ {
+ type = openssl_ed_evp_pkey_key_type(key);
+ if (type != KEY_ANY)
+ {
+ this = create_empty(type);
+ this->key = key;
+ return &this->public;
+ }
+ EVP_PKEY_free(key);
+ }
+ return NULL;
+}
+
/*
* Described in header
*/
diff --git a/src/libstrongswan/plugins/openssl/openssl_ed_public_key.h b/src/libstrongswan/plugins/openssl/openssl_ed_public_key.h
index 29155d1686..0e3b34b55e 100644
--- a/src/libstrongswan/plugins/openssl/openssl_ed_public_key.h
+++ b/src/libstrongswan/plugins/openssl/openssl_ed_public_key.h
@@ -36,4 +36,12 @@
*/
public_key_t *openssl_ed_public_key_load(key_type_t type, va_list args);
+/**
+ * Wrap an EVP_PKEY object of type EdDSA.
+ *
+ * @param key EVP_PKEY object (adopted)
+ * @return generated key, NULL on failure
+ */
+public_key_t *openssl_ed_public_key_create(EVP_PKEY *key);
+
#endif /** OPENSSL_ED_PUBLIC_KEY_H_ @}*/
diff --git a/src/libstrongswan/plugins/openssl/openssl_ml_dsa_public_key.c b/src/libstrongswan/plugins/openssl/openssl_ml_dsa_public_key.c
index 6f736aa0dc..2678357aa7 100644
--- a/src/libstrongswan/plugins/openssl/openssl_ml_dsa_public_key.c
+++ b/src/libstrongswan/plugins/openssl/openssl_ml_dsa_public_key.c
@@ -234,7 +234,7 @@ METHOD(public_key_t, destroy, void,
/**
* Generic private constructor
*/
-static private_public_key_t *create_empty(key_type_t type)
+static public_key_t *create_internal(key_type_t type, EVP_PKEY *key)
{
private_public_key_t *this;
@@ -252,10 +252,27 @@ static private_public_key_t *create_empty(key_type_t type)
.destroy = _destroy,
},
.type = type,
+ .key = key,
.ref = 1,
);
- return this;
+ return &this->public;
+}
+
+/*
+ * Described in header
+ */
+public_key_t *openssl_ml_dsa_public_key_create(EVP_PKEY *key)
+{
+ key_type_t type;
+
+ type = openssl_ml_dsa_evp_pkey_key_type(key);
+ if (type == KEY_ANY)
+ {
+ EVP_PKEY_free(key);
+ return NULL;
+ }
+ return create_internal(type, key);
}
/*
@@ -263,7 +280,6 @@ static private_public_key_t *create_empty(key_type_t type)
*/
public_key_t *openssl_ml_dsa_public_key_load(key_type_t type, va_list args)
{
- private_public_key_t *this;
chunk_t pkcs1 = chunk_empty, blob = chunk_empty;
EVP_PKEY *key = NULL;
@@ -289,25 +305,25 @@ public_key_t *openssl_ml_dsa_public_key_load(key_type_t type, va_list args)
{
key = EVP_PKEY_new_raw_public_key(openssl_ml_dsa_key_type(type), NULL,
blob.ptr, blob.len);
+ if (key)
+ {
+ return create_internal(type, key);
+ }
}
else if (pkcs1.len)
{
key = d2i_PUBKEY(NULL, (const u_char**)&pkcs1.ptr, pkcs1.len);
- type = openssl_ml_dsa_evp_pkey_key_type(key);
- if (key && type == KEY_ANY)
+ if (key)
{
+ if (type == openssl_ml_dsa_evp_pkey_key_type(key))
+ {
+ return create_internal(type, key);
+ }
EVP_PKEY_free(key);
return NULL;
}
}
- if (!key)
- {
- return NULL;
- }
- this = create_empty(type);
- this->key = key;
-
- return &this->public;
+ return NULL;
}
#endif /* OPENSSL_VERSION_NUMBER */
diff --git a/src/libstrongswan/plugins/openssl/openssl_ml_dsa_public_key.h b/src/libstrongswan/plugins/openssl/openssl_ml_dsa_public_key.h
index 82185a19a8..e6e1a9304c 100644
--- a/src/libstrongswan/plugins/openssl/openssl_ml_dsa_public_key.h
+++ b/src/libstrongswan/plugins/openssl/openssl_ml_dsa_public_key.h
@@ -36,4 +36,12 @@
*/
public_key_t *openssl_ml_dsa_public_key_load(key_type_t type, va_list args);
+/**
+ * Wrap an EVP_PKEY object of type ML-DSA-44/65/87.
+ *
+ * @param key EVP_PKEY object (adopted)
+ * @return generated key, NULL on failure
+ */
+public_key_t *openssl_ml_dsa_public_key_create(EVP_PKEY *key);
+
#endif /** OPENSSL_ML_DSA_PUBLIC_KEY_H_ @}*/
diff --git a/src/libstrongswan/plugins/openssl/openssl_plugin.c b/src/libstrongswan/plugins/openssl/openssl_plugin.c
index b5ac88d0bb..df167bad14 100644
--- a/src/libstrongswan/plugins/openssl/openssl_plugin.c
+++ b/src/libstrongswan/plugins/openssl/openssl_plugin.c
@@ -24,6 +24,7 @@
#include <openssl/err.h>
#include <openssl/evp.h>
+#include <openssl/x509.h>
#include <openssl/conf.h>
#include <openssl/rand.h>
#include <openssl/crypto.h>
@@ -269,7 +270,7 @@ static bool seed_rng()
#endif /* OPENSSL_VERSION_NUMBER */
/**
- * Generic key loader
+ * Generic private key loader
*/
static private_key_t *openssl_private_key_load(key_type_t type, va_list args)
{
@@ -298,6 +299,36 @@ static private_key_t *openssl_private_key_load(key_type_t type, va_list args)
return NULL;
}
+/**
+ * Generic public key loader
+ */
+static public_key_t *openssl_public_key_load(key_type_t type, va_list args)
+{
+ chunk_t blob = chunk_empty;
+ EVP_PKEY *key;
+
+ while (TRUE)
+ {
+ switch (va_arg(args, builder_part_t))
+ {
+ case BUILD_BLOB_ASN1_DER:
+ blob = va_arg(args, chunk_t);
+ continue;
+ case BUILD_END:
+ break;
+ default:
+ return NULL;
+ }
+ break;
+ }
+ if (blob.ptr)
+ {
+ key = d2i_PUBKEY(NULL, (const u_char**)&blob.ptr, blob.len);
+ return openssl_wrap_public_key(key);
+ }
+ return NULL;
+}
+
METHOD(plugin_t, get_name, char*,
private_openssl_plugin_t *this)
{
@@ -547,8 +578,6 @@ METHOD(plugin_t, get_features, int,
PLUGIN_PROVIDE(PRIVKEY_GEN, KEY_RSA),
PLUGIN_REGISTER(PUBKEY, openssl_rsa_public_key_load, TRUE),
PLUGIN_PROVIDE(PUBKEY, KEY_RSA),
- PLUGIN_REGISTER(PUBKEY, openssl_rsa_public_key_load, TRUE),
- PLUGIN_PROVIDE(PUBKEY, KEY_ANY),
/* signature/encryption schemes */
PLUGIN_PROVIDE(PRIVKEY_SIGN, SIGN_RSA_EMSA_PKCS1_NULL),
PLUGIN_PROVIDE(PUBKEY_VERIFY, SIGN_RSA_EMSA_PKCS1_NULL),
@@ -678,7 +707,6 @@ METHOD(plugin_t, get_features, int,
PLUGIN_PROVIDE(PUBKEY, KEY_ML_DSA_44),
PLUGIN_PROVIDE(PUBKEY, KEY_ML_DSA_65),
PLUGIN_PROVIDE(PUBKEY, KEY_ML_DSA_87),
- PLUGIN_PROVIDE(PUBKEY, KEY_ANY),
PLUGIN_REGISTER(PRIVKEY, openssl_ml_dsa_private_key_load, TRUE),
PLUGIN_PROVIDE(PRIVKEY, KEY_ML_DSA_44),
PLUGIN_PROVIDE(PRIVKEY, KEY_ML_DSA_65),
@@ -696,6 +724,8 @@ METHOD(plugin_t, get_features, int,
#endif /* OPENSSL_NO_ML_DSA */
/* generic key loader */
+ PLUGIN_REGISTER(PUBKEY, openssl_public_key_load, TRUE),
+ PLUGIN_PROVIDE(PUBKEY, KEY_ANY),
PLUGIN_REGISTER(PRIVKEY, openssl_private_key_load, TRUE),
PLUGIN_PROVIDE(PRIVKEY, KEY_ANY),
PLUGIN_REGISTER(PRIVKEY, openssl_private_key_connect, FALSE),
diff --git a/src/libstrongswan/plugins/openssl/openssl_rsa_public_key.c b/src/libstrongswan/plugins/openssl/openssl_rsa_public_key.c
index 1607d75790..4bbd552c04 100644
--- a/src/libstrongswan/plugins/openssl/openssl_rsa_public_key.c
+++ b/src/libstrongswan/plugins/openssl/openssl_rsa_public_key.c
@@ -47,10 +47,11 @@ typedef struct private_openssl_rsa_public_key_t private_openssl_rsa_public_key_t
* Private data structure with signing context.
*/
struct private_openssl_rsa_public_key_t {
+
/**
- * Public interface for this signer.
+ * Public interface
*/
- openssl_rsa_public_key_t public;
+ public_key_t public;
/**
* RSA key object
@@ -479,7 +480,7 @@ METHOD(public_key_t, get_ref, public_key_t*,
private_openssl_rsa_public_key_t *this)
{
ref_get(&this->ref);
- return &this->public.key;
+ return &this->public;
}
METHOD(public_key_t, destroy, void,
@@ -505,18 +506,16 @@ static private_openssl_rsa_public_key_t *create_internal(EVP_PKEY *key)
INIT(this,
.public = {
- .key = {
- .get_type = _get_type,
- .verify = _verify,
- .encrypt = _encrypt,
- .equals = public_key_equals,
- .get_keysize = _get_keysize,
- .get_fingerprint = _get_fingerprint,
- .has_fingerprint = public_key_has_fingerprint,
- .get_encoding = _get_encoding,
- .get_ref = _get_ref,
- .destroy = _destroy,
- },
+ .get_type = _get_type,
+ .verify = _verify,
+ .encrypt = _encrypt,
+ .equals = public_key_equals,
+ .get_keysize = _get_keysize,
+ .get_fingerprint = _get_fingerprint,
+ .has_fingerprint = public_key_has_fingerprint,
+ .get_encoding = _get_encoding,
+ .get_ref = _get_ref,
+ .destroy = _destroy,
},
.ref = 1,
.key = key,
@@ -525,11 +524,26 @@ static private_openssl_rsa_public_key_t *create_internal(EVP_PKEY *key)
return this;
}
+/*
+ * Described in header
+ */
+public_key_t *openssl_rsa_public_key_create(EVP_PKEY *key)
+{
+ private_openssl_rsa_public_key_t *this;
+
+ if (!key || EVP_PKEY_base_id(key) != EVP_PKEY_RSA)
+ {
+ EVP_PKEY_free(key);
+ return NULL;
+ }
+ this = create_internal(key);
+ return &this->public;
+}
+
/**
* See header.
*/
-openssl_rsa_public_key_t *openssl_rsa_public_key_load(key_type_t type,
- va_list args)
+public_key_t *openssl_rsa_public_key_load(key_type_t type, va_list args)
{
private_openssl_rsa_public_key_t *this;
EVP_PKEY *key = NULL;
@@ -559,40 +573,23 @@ openssl_rsa_public_key_t *openssl_rsa_public_key_load(key_type_t type,
if (blob.ptr)
{
- switch (type)
- {
- case KEY_ANY:
- key = d2i_PUBKEY(NULL, (const u_char**)&blob.ptr, blob.len);
- if (key && EVP_PKEY_base_id(key) != EVP_PKEY_RSA)
- {
- EVP_PKEY_free(key);
- key = NULL;
- }
- break;
- case KEY_RSA:
#if defined(OPENSSL_IS_BORINGSSL) && \
(!defined(BORINGSSL_API_VERSION) || BORINGSSL_API_VERSION < 10)
- {
- RSA *rsa = d2i_RSAPublicKey(NULL, (const u_char**)&blob.ptr,
- blob.len);
- key = EVP_PKEY_new();
- if (!key || !EVP_PKEY_assign_RSA(key, rsa))
- {
- RSA_free(rsa);
- EVP_PKEY_free(key);
- key = NULL;
- }
- }
-#else
- key = d2i_PublicKey(EVP_PKEY_RSA, NULL, (const u_char**)&blob.ptr,
+ RSA *rsa = d2i_RSAPublicKey(NULL, (const u_char**)&blob.ptr,
blob.len);
-#endif
- break;
- default:
- break;
+ key = EVP_PKEY_new();
+ if (!key || !EVP_PKEY_assign_RSA(key, rsa))
+ {
+ RSA_free(rsa);
+ EVP_PKEY_free(key);
+ key = NULL;
}
+#else
+ key = d2i_PublicKey(EVP_PKEY_RSA, NULL, (const u_char**)&blob.ptr,
+ blob.len);
+#endif
}
- else if (n.ptr && e.ptr && type == KEY_RSA)
+ else if (n.ptr && e.ptr)
{
BIGNUM *bn_n, *bn_e;
diff --git a/src/libstrongswan/plugins/openssl/openssl_rsa_public_key.h b/src/libstrongswan/plugins/openssl/openssl_rsa_public_key.h
index 77a573a638..a3945476b3 100644
--- a/src/libstrongswan/plugins/openssl/openssl_rsa_public_key.h
+++ b/src/libstrongswan/plugins/openssl/openssl_rsa_public_key.h
@@ -15,6 +15,8 @@
*/
/**
+ * public_key_t implementation of RSA algorithm using OpenSSL.
+ *
* @defgroup openssl_rsa_public_key openssl_rsa_public_key
* @{ @ingroup openssl_p
*/
@@ -22,21 +24,10 @@
#ifndef OPENSSL_RSA_PUBLIC_KEY_H_
#define OPENSSL_RSA_PUBLIC_KEY_H_
-typedef struct openssl_rsa_public_key_t openssl_rsa_public_key_t;
+#include <openssl/evp.h>
#include <credentials/keys/public_key.h>
-/**
- * public_key_t implementation of RSA algorithm using OpenSSL.
- */
-struct openssl_rsa_public_key_t {
-
- /**
- * Implements the public_key_t interface
- */
- public_key_t key;
-};
-
/**
* Load a RSA public key using OpenSSL.
*
@@ -46,7 +37,14 @@ struct openssl_rsa_public_key_t {
* @param args builder_part_t argument list
* @return loaded key, NULL on failure
*/
-openssl_rsa_public_key_t *openssl_rsa_public_key_load(key_type_t type,
- va_list args);
+public_key_t *openssl_rsa_public_key_load(key_type_t type, va_list args);
+
+/**
+ * Wrap an EVP_PKEY object of type RSA.
+ *
+ * @param key EVP_PKEY object (adopted)
+ * @return generated key, NULL on failure
+ */
+public_key_t *openssl_rsa_public_key_create(EVP_PKEY *key);
#endif /** OPENSSL_RSA_PUBLIC_KEY_H_ @}*/
diff --git a/src/libstrongswan/plugins/openssl/openssl_util.c b/src/libstrongswan/plugins/openssl/openssl_util.c
index 212a598265..5bdfb42822 100644
--- a/src/libstrongswan/plugins/openssl/openssl_util.c
+++ b/src/libstrongswan/plugins/openssl/openssl_util.c
@@ -30,9 +30,13 @@
#endif
#include "openssl_ec_private_key.h"
+#include "openssl_ec_public_key.h"
#include "openssl_ed_private_key.h"
+#include "openssl_ed_public_key.h"
#include "openssl_rsa_private_key.h"
+#include "openssl_rsa_public_key.h"
#include "openssl_ml_dsa_private_key.h"
+#include "openssl_ml_dsa_public_key.h"
/* these were added with 1.1.0 when ASN1_OBJECT was made opaque */
#if OPENSSL_VERSION_NUMBER < 0x10100000L
@@ -203,6 +207,48 @@ private_key_t *openssl_wrap_private_key(EVP_PKEY *key, bool engine)
return NULL;
}
+/*
+ * Described in header
+ */
+public_key_t *openssl_wrap_public_key(EVP_PKEY *key)
+{
+ if (key)
+ {
+ switch (EVP_PKEY_base_id(key))
+ {
+#ifndef OPENSSL_NO_RSA
+ case EVP_PKEY_RSA:
+ return openssl_rsa_public_key_create(key);
+#endif
+#ifndef OPENSSL_NO_ECDSA
+ case EVP_PKEY_EC:
+ return openssl_ec_public_key_create(key);
+#endif
+#if OPENSSL_VERSION_NUMBER >= 0x1010100fL && !defined(OPENSSL_NO_EC)
+ case EVP_PKEY_ED25519:
+#ifndef OPENSSL_IS_AWSLC
+ case EVP_PKEY_ED448:
+#endif
+ return openssl_ed_public_key_create(key);
+#endif /* OPENSSL_VERSION_NUMBER && !OPENSSL_NO_EC && !OPENSSL_IS_AWSLC */
+ default:
+#if (OPENSSL_VERSION_NUMBER >= 0x30500000L && !defined(OPENSSL_NO_ML_DSA))
+ /* OpenSSL does not provide an ID for ML-DSA keys, which is
+ * apparently a legacy feature */
+ if (EVP_PKEY_is_a(key, "ML-DSA-44") ||
+ EVP_PKEY_is_a(key, "ML-DSA-65") ||
+ EVP_PKEY_is_a(key, "ML-DSA-87"))
+ {
+ return openssl_ml_dsa_public_key_create(key);
+ }
+#endif
+ EVP_PKEY_free(key);
+ break;
+ }
+ }
+ return NULL;
+}
+
/**
* Described in header.
*/
diff --git a/src/libstrongswan/plugins/openssl/openssl_util.h b/src/libstrongswan/plugins/openssl/openssl_util.h
index 7c72db2cce..9e1ccb2ecc 100644
--- a/src/libstrongswan/plugins/openssl/openssl_util.h
+++ b/src/libstrongswan/plugins/openssl/openssl_util.h
@@ -66,6 +66,14 @@ bool openssl_fingerprint(EVP_PKEY *key, cred_encoding_type_t type, chunk_t *fp);
*/
private_key_t *openssl_wrap_private_key(EVP_PKEY *key, bool engine);
+/**
+ * Wrap the given OpenSSL public key in a type-specific public key object.
+ *
+ * @param key key object to wrap
+ * @returns created object or NULL if key type is not supported
+ */
+public_key_t *openssl_wrap_public_key(EVP_PKEY *key);
+
/**
* Concatenates two bignums into a chunk, thereby enforcing the length of
* a single BIGNUM, if necessary, by prepending it with zeros.