Merge pull request #7552 from davidhorstmann-arm/remove-doxygen-mainpage-content
Remove API docs mainpage content
diff --git a/ChangeLog.d/rfc8410.txt b/ChangeLog.d/rfc8410.txt
new file mode 100644
index 0000000..e2984ee
--- /dev/null
+++ b/ChangeLog.d/rfc8410.txt
@@ -0,0 +1,3 @@
+Features
+ * Add support for reading and writing X25519 and X448
+ public and private keys in RFC 8410 format using the existing PK APIs.
diff --git a/include/mbedtls/asn1write.h b/include/mbedtls/asn1write.h
index da73759..3c5072c 100644
--- a/include/mbedtls/asn1write.h
+++ b/include/mbedtls/asn1write.h
@@ -164,6 +164,27 @@
size_t par_len);
/**
+ * \brief Write an AlgorithmIdentifier sequence in ASN.1 format.
+ *
+ * \note This function works backwards in data buffer.
+ *
+ * \param p The reference to the current position pointer.
+ * \param start The start of the buffer, for bounds-checking.
+ * \param oid The OID of the algorithm to write.
+ * \param oid_len The length of the algorithm's OID.
+ * \param par_len The length of the parameters, which must be already written.
+ * \param has_par If there are any parameters. If 0, par_len must be 0. If 1
+ * and \p par_len is 0, NULL parameters are added.
+ *
+ * \return The number of bytes written to \p p on success.
+ * \return A negative \c MBEDTLS_ERR_ASN1_XXX error code on failure.
+ */
+int mbedtls_asn1_write_algorithm_identifier_ext(unsigned char **p,
+ const unsigned char *start,
+ const char *oid, size_t oid_len,
+ size_t par_len, int has_par);
+
+/**
* \brief Write a boolean tag (#MBEDTLS_ASN1_BOOLEAN) and value
* in ASN.1 format.
*
diff --git a/include/mbedtls/oid.h b/include/mbedtls/oid.h
index a72f51c..1cbf968 100644
--- a/include/mbedtls/oid.h
+++ b/include/mbedtls/oid.h
@@ -90,6 +90,9 @@
#define MBEDTLS_OID_OIW_SECSIG MBEDTLS_OID_ORG_OIW "\x03"
#define MBEDTLS_OID_OIW_SECSIG_ALG MBEDTLS_OID_OIW_SECSIG "\x02"
#define MBEDTLS_OID_OIW_SECSIG_SHA1 MBEDTLS_OID_OIW_SECSIG_ALG "\x1a"
+#define MBEDTLS_OID_ORG_THAWTE "\x65" /* thawte(101) */
+#define MBEDTLS_OID_THAWTE MBEDTLS_OID_ISO_IDENTIFIED_ORG \
+ MBEDTLS_OID_ORG_THAWTE
#define MBEDTLS_OID_ORG_CERTICOM "\x81\x04" /* certicom(132) */
#define MBEDTLS_OID_CERTICOM MBEDTLS_OID_ISO_IDENTIFIED_ORG \
MBEDTLS_OID_ORG_CERTICOM
@@ -437,6 +440,15 @@
* ecdsa-with-SHA2(3) 4 } */
#define MBEDTLS_OID_ECDSA_SHA512 MBEDTLS_OID_ANSI_X9_62_SIG_SHA2 "\x04"
+/*
+ * EC key algorithms from RFC 8410
+ */
+
+#define MBEDTLS_OID_X25519 MBEDTLS_OID_THAWTE "\x6e" /**< id-X25519 OBJECT IDENTIFIER ::= { 1 3 101 110 } */
+#define MBEDTLS_OID_X448 MBEDTLS_OID_THAWTE "\x6f" /**< id-X448 OBJECT IDENTIFIER ::= { 1 3 101 111 } */
+#define MBEDTLS_OID_ED25519 MBEDTLS_OID_THAWTE "\x70" /**< id-Ed25519 OBJECT IDENTIFIER ::= { 1 3 101 112 } */
+#define MBEDTLS_OID_ED448 MBEDTLS_OID_THAWTE "\x71" /**< id-Ed448 OBJECT IDENTIFIER ::= { 1 3 101 113 } */
+
#ifdef __cplusplus
extern "C" {
#endif
@@ -531,6 +543,30 @@
*/
int mbedtls_oid_get_oid_by_ec_grp(mbedtls_ecp_group_id grp_id,
const char **oid, size_t *olen);
+
+/**
+ * \brief Translate AlgorithmIdentifier OID into an EC group identifier,
+ * for curves that are directly encoded at this level
+ *
+ * \param oid OID to use
+ * \param grp_id place to store group id
+ *
+ * \return 0 if successful, or MBEDTLS_ERR_OID_NOT_FOUND
+ */
+int mbedtls_oid_get_ec_grp_algid(const mbedtls_asn1_buf *oid, mbedtls_ecp_group_id *grp_id);
+
+/**
+ * \brief Translate EC group identifier into AlgorithmIdentifier OID,
+ * for curves that are directly encoded at this level
+ *
+ * \param grp_id EC group identifier
+ * \param oid place to store ASN.1 OID string pointer
+ * \param olen length of the OID
+ *
+ * \return 0 if successful, or MBEDTLS_ERR_OID_NOT_FOUND
+ */
+int mbedtls_oid_get_oid_by_ec_grp_algid(mbedtls_ecp_group_id grp_id,
+ const char **oid, size_t *olen);
#endif /* MBEDTLS_ECP_LIGHT */
/**
diff --git a/include/mbedtls/pk.h b/include/mbedtls/pk.h
index c579661..8d6d60f 100644
--- a/include/mbedtls/pk.h
+++ b/include/mbedtls/pk.h
@@ -40,7 +40,7 @@
#include "mbedtls/ecdsa.h"
#endif
-#if defined(MBEDTLS_USE_PSA_CRYPTO)
+#if defined(MBEDTLS_USE_PSA_CRYPTO) || defined(MBEDTLS_PSA_CRYPTO_C)
#include "psa/crypto.h"
#endif
@@ -234,10 +234,17 @@
/**
* \brief Public key container
+ *
+ * \note The priv_id is guarded by MBEDTLS_PSA_CRYPTO_C and not
+ * by MBEDTLS_USE_PSA_CRYPTO because it can be used also
+ * in mbedtls_pk_sign_ext for RSA keys.
*/
typedef struct mbedtls_pk_context {
const mbedtls_pk_info_t *MBEDTLS_PRIVATE(pk_info); /**< Public key information */
void *MBEDTLS_PRIVATE(pk_ctx); /**< Underlying public key context */
+#if defined(MBEDTLS_PSA_CRYPTO_C)
+ mbedtls_svc_key_id_t MBEDTLS_PRIVATE(priv_id); /**< Key ID for opaque keys */
+#endif /* MBEDTLS_PSA_CRYPTO_C */
} mbedtls_pk_context;
#if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE)
diff --git a/library/asn1write.c b/library/asn1write.c
index b9d586a..c65d937 100644
--- a/library/asn1write.c
+++ b/library/asn1write.c
@@ -195,13 +195,22 @@
const char *oid, size_t oid_len,
size_t par_len)
{
+ return mbedtls_asn1_write_algorithm_identifier_ext(p, start, oid, oid_len, par_len, 1);
+}
+
+int mbedtls_asn1_write_algorithm_identifier_ext(unsigned char **p, const unsigned char *start,
+ const char *oid, size_t oid_len,
+ size_t par_len, int has_par)
+{
int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
size_t len = 0;
- if (par_len == 0) {
- MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_null(p, start));
- } else {
- len += par_len;
+ if (has_par) {
+ if (par_len == 0) {
+ MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_null(p, start));
+ } else {
+ len += par_len;
+ }
}
MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_oid(p, start, oid, oid_len));
diff --git a/library/oid.c b/library/oid.c
index 80cadcd..8e57fe4 100644
--- a/library/oid.c
+++ b/library/oid.c
@@ -533,7 +533,7 @@
#if defined(MBEDTLS_ECP_LIGHT)
/*
- * For namedCurve (RFC 5480)
+ * For elliptic curves that use namedCurve inside ECParams (RFC 5480)
*/
typedef struct {
mbedtls_oid_descriptor_t descriptor;
@@ -621,6 +621,47 @@
oid_ecp_grp,
mbedtls_ecp_group_id,
grp_id)
+
+/*
+ * For Elliptic Curve algorithms that are directly
+ * encoded in the AlgorithmIdentifier (RFC 8410)
+ */
+typedef struct {
+ mbedtls_oid_descriptor_t descriptor;
+ mbedtls_ecp_group_id grp_id;
+} oid_ecp_grp_algid_t;
+
+static const oid_ecp_grp_algid_t oid_ecp_grp_algid[] =
+{
+#if defined(MBEDTLS_ECP_DP_CURVE25519_ENABLED)
+ {
+ OID_DESCRIPTOR(MBEDTLS_OID_X25519, "X25519", "X25519"),
+ MBEDTLS_ECP_DP_CURVE25519,
+ },
+#endif /* MBEDTLS_ECP_DP_CURVE25519_ENABLED */
+#if defined(MBEDTLS_ECP_DP_CURVE448_ENABLED)
+ {
+ OID_DESCRIPTOR(MBEDTLS_OID_X448, "X448", "X448"),
+ MBEDTLS_ECP_DP_CURVE448,
+ },
+#endif /* MBEDTLS_ECP_DP_CURVE448_ENABLED */
+ {
+ NULL_OID_DESCRIPTOR,
+ MBEDTLS_ECP_DP_NONE,
+ },
+};
+
+FN_OID_TYPED_FROM_ASN1(oid_ecp_grp_algid_t, grp_id_algid, oid_ecp_grp_algid)
+FN_OID_GET_ATTR1(mbedtls_oid_get_ec_grp_algid,
+ oid_ecp_grp_algid_t,
+ grp_id_algid,
+ mbedtls_ecp_group_id,
+ grp_id)
+FN_OID_GET_OID_BY_ATTR1(mbedtls_oid_get_oid_by_ec_grp_algid,
+ oid_ecp_grp_algid_t,
+ oid_ecp_grp_algid,
+ mbedtls_ecp_group_id,
+ grp_id)
#endif /* MBEDTLS_ECP_LIGHT */
#if defined(MBEDTLS_CIPHER_C)
diff --git a/library/pk.c b/library/pk.c
index 4e2f218..71ab60d 100644
--- a/library/pk.c
+++ b/library/pk.c
@@ -60,6 +60,9 @@
{
ctx->pk_info = NULL;
ctx->pk_ctx = NULL;
+#if defined(MBEDTLS_PSA_CRYPTO_C)
+ ctx->priv_id = MBEDTLS_SVC_KEY_ID_INIT;
+#endif /* MBEDTLS_PSA_CRYPTO_C */
}
/*
@@ -71,7 +74,7 @@
return;
}
- if (ctx->pk_info != NULL) {
+ if ((ctx->pk_info != NULL) && (ctx->pk_info->ctx_free_func != NULL)) {
ctx->pk_info->ctx_free_func(ctx->pk_ctx);
}
@@ -140,7 +143,8 @@
return MBEDTLS_ERR_PK_BAD_INPUT_DATA;
}
- if ((ctx->pk_ctx = info->ctx_alloc_func()) == NULL) {
+ if ((info->ctx_alloc_func == NULL) ||
+ ((ctx->pk_ctx = info->ctx_alloc_func()) == NULL)) {
return MBEDTLS_ERR_PK_ALLOC_FAILED;
}
@@ -158,7 +162,6 @@
{
const mbedtls_pk_info_t *info = NULL;
psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
- mbedtls_svc_key_id_t *pk_ctx;
psa_key_type_t type;
if (ctx == NULL || ctx->pk_info != NULL) {
@@ -179,14 +182,8 @@
return MBEDTLS_ERR_PK_FEATURE_UNAVAILABLE;
}
- if ((ctx->pk_ctx = info->ctx_alloc_func()) == NULL) {
- return MBEDTLS_ERR_PK_ALLOC_FAILED;
- }
-
ctx->pk_info = info;
-
- pk_ctx = (mbedtls_svc_key_id_t *) ctx->pk_ctx;
- *pk_ctx = key;
+ ctx->priv_id = key;
return 0;
}
@@ -315,12 +312,11 @@
return (key_usage & usage) == usage;
}
- const mbedtls_svc_key_id_t *key = (const mbedtls_svc_key_id_t *) ctx->pk_ctx;
psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
psa_algorithm_t key_alg, key_alg2;
psa_status_t status;
- status = psa_get_key_attributes(*key, &attributes);
+ status = psa_get_key_attributes(ctx->priv_id, &attributes);
if (status != PSA_SUCCESS) {
return 0;
}
@@ -701,10 +697,9 @@
}
if (mbedtls_pk_get_type(ctx) == MBEDTLS_PK_OPAQUE) {
- const mbedtls_svc_key_id_t *key = (const mbedtls_svc_key_id_t *) ctx->pk_ctx;
psa_status_t status;
- status = psa_sign_hash(*key, PSA_ALG_RSA_PSS(psa_md_alg),
+ status = psa_sign_hash(ctx->priv_id, PSA_ALG_RSA_PSS(psa_md_alg),
hash, hash_len,
sig, sig_size, sig_len);
return PSA_PK_RSA_TO_MBEDTLS_ERR(status);
@@ -873,7 +868,7 @@
#else /* !MBEDTLS_ECP_LIGHT && !MBEDTLS_RSA_C */
#if defined(MBEDTLS_ECP_LIGHT)
if (mbedtls_pk_get_type(pk) == MBEDTLS_PK_ECKEY) {
- const mbedtls_ecp_keypair *ec;
+ mbedtls_ecp_keypair *ec;
unsigned char d[MBEDTLS_ECP_MAX_BYTES];
size_t d_len;
psa_ecc_family_t curve_id;
@@ -886,7 +881,7 @@
/* export the private key material in the format PSA wants */
ec = mbedtls_pk_ec(*pk);
d_len = PSA_BITS_TO_BYTES(ec->grp.nbits);
- if ((ret = mbedtls_mpi_write_binary(&ec->d, d, d_len)) != 0) {
+ if ((ret = mbedtls_ecp_write_key(ec, d, d_len)) != 0) {
return ret;
}
diff --git a/library/pk_wrap.c b/library/pk_wrap.c
index 6c9f97b..0e5e120 100644
--- a/library/pk_wrap.c
+++ b/library/pk_wrap.c
@@ -1503,29 +1503,12 @@
#endif /* MBEDTLS_PK_RSA_ALT_SUPPORT */
#if defined(MBEDTLS_USE_PSA_CRYPTO)
-
-static void *pk_opaque_alloc_wrap(void)
-{
- void *ctx = mbedtls_calloc(1, sizeof(mbedtls_svc_key_id_t));
-
- /* no _init() function to call, as calloc() already zeroized */
-
- return ctx;
-}
-
-static void pk_opaque_free_wrap(void *ctx)
-{
- mbedtls_platform_zeroize(ctx, sizeof(mbedtls_svc_key_id_t));
- mbedtls_free(ctx);
-}
-
static size_t pk_opaque_get_bitlen(mbedtls_pk_context *pk)
{
- const mbedtls_svc_key_id_t *key = pk->pk_ctx;
size_t bits;
psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
- if (PSA_SUCCESS != psa_get_key_attributes(*key, &attributes)) {
+ if (PSA_SUCCESS != psa_get_key_attributes(pk->priv_id, &attributes)) {
return 0;
}
@@ -1563,7 +1546,6 @@
((void) p_rng);
return MBEDTLS_ERR_PK_FEATURE_UNAVAILABLE;
#else /* !MBEDTLS_PK_CAN_ECDSA_SIGN && !MBEDTLS_RSA_C */
- const mbedtls_svc_key_id_t *key = pk->pk_ctx;
psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
psa_algorithm_t alg;
psa_key_type_t type;
@@ -1573,7 +1555,7 @@
(void) f_rng;
(void) p_rng;
- status = psa_get_key_attributes(*key, &attributes);
+ status = psa_get_key_attributes(pk->priv_id, &attributes);
if (status != PSA_SUCCESS) {
return PSA_PK_TO_MBEDTLS_ERR(status);
}
@@ -1594,7 +1576,7 @@
return MBEDTLS_ERR_PK_FEATURE_UNAVAILABLE;
/* make the signature */
- status = psa_sign_hash(*key, alg, hash, hash_len,
+ status = psa_sign_hash(pk->priv_id, alg, hash, hash_len,
sig, sig_size, sig_len);
if (status != PSA_SUCCESS) {
#if defined(MBEDTLS_PK_CAN_ECDSA_SIGN)
@@ -1635,8 +1617,8 @@
NULL, /* decrypt - not relevant */
NULL, /* encrypt - not relevant */
NULL, /* check_pair - could be done later or left NULL */
- pk_opaque_alloc_wrap,
- pk_opaque_free_wrap,
+ NULL, /* alloc - no need to allocate new data dynamically */
+ NULL, /* free - as for the alloc, there is no data to free */
#if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE)
NULL, /* restart alloc - not relevant */
NULL, /* restart free - not relevant */
@@ -1650,14 +1632,13 @@
unsigned char *output, size_t *olen, size_t osize,
int (*f_rng)(void *, unsigned char *, size_t), void *p_rng)
{
- const mbedtls_svc_key_id_t *key = pk->pk_ctx;
psa_status_t status;
/* PSA has its own RNG */
(void) f_rng;
(void) p_rng;
- status = psa_asymmetric_decrypt(*key, PSA_ALG_RSA_PKCS1V15_CRYPT,
+ status = psa_asymmetric_decrypt(pk->priv_id, PSA_ALG_RSA_PKCS1V15_CRYPT,
input, ilen,
NULL, 0,
output, osize, olen);
@@ -1687,8 +1668,8 @@
#endif /* PSA_WANT_KEY_TYPE_RSA_PUBLIC_KEY */
NULL, /* encrypt - will be done later */
NULL, /* check_pair - could be done later or left NULL */
- pk_opaque_alloc_wrap,
- pk_opaque_free_wrap,
+ NULL, /* alloc - no need to allocate new data dynamically */
+ NULL, /* free - as for the alloc, there is no data to free */
#if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE)
NULL, /* restart alloc - not relevant */
NULL, /* restart free - not relevant */
diff --git a/library/pkparse.c b/library/pkparse.c
index 800e352..ade8a04 100644
--- a/library/pkparse.c
+++ b/library/pkparse.c
@@ -32,8 +32,9 @@
#if defined(MBEDTLS_RSA_C)
#include "mbedtls/rsa.h"
#endif
-#if defined(MBEDTLS_ECP_C)
#include "mbedtls/ecp.h"
+#if defined(MBEDTLS_RSA_C) || defined(MBEDTLS_ECP_C)
+#include "pkwrite.h"
#endif
#if defined(MBEDTLS_ECDSA_C)
#include "mbedtls/ecdsa.h"
@@ -232,7 +233,7 @@
{
int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
unsigned char *p = params->p;
- const unsigned char * const end = params->p + params->len;
+ const unsigned char *const end = params->p + params->len;
const unsigned char *end_field, *end_curve;
size_t len;
int ver;
@@ -404,7 +405,6 @@
mbedtls_mpi_get_bit(&grp->G.Y, 0) == mbedtls_mpi_get_bit(&ref.G.Y, 0)) {
break;
}
-
}
cleanup:
@@ -495,6 +495,119 @@
return 0;
}
+#if defined(MBEDTLS_ECP_LIGHT)
+/*
+ * Helper function for deriving a public key from its private counterpart.
+ */
+static int pk_derive_public_key(mbedtls_ecp_keypair *eck,
+ const unsigned char *d, size_t d_len,
+ int (*f_rng)(void *, unsigned char *, size_t), void *p_rng)
+{
+ int ret;
+#if defined(MBEDTLS_USE_PSA_CRYPTO)
+ psa_status_t status, destruction_status;
+ psa_key_attributes_t key_attr = PSA_KEY_ATTRIBUTES_INIT;
+ size_t curve_bits;
+ psa_ecc_family_t curve = mbedtls_ecc_group_to_psa(eck->grp.id, &curve_bits);
+ /* This buffer is used to store the private key at first and then the
+ * public one (but not at the same time). Therefore we size it for the
+ * latter since it's bigger. */
+ unsigned char key_buf[MBEDTLS_PSA_MAX_EC_PUBKEY_LENGTH];
+ size_t key_len;
+ mbedtls_svc_key_id_t key_id = MBEDTLS_SVC_KEY_ID_INIT;
+
+ (void) f_rng;
+ (void) p_rng;
+
+ psa_set_key_type(&key_attr, PSA_KEY_TYPE_ECC_KEY_PAIR(curve));
+ psa_set_key_usage_flags(&key_attr, PSA_KEY_USAGE_EXPORT);
+
+ status = psa_import_key(&key_attr, d, d_len, &key_id);
+ ret = psa_pk_status_to_mbedtls(status);
+ if (ret != 0) {
+ return ret;
+ }
+
+ mbedtls_platform_zeroize(key_buf, sizeof(key_buf));
+
+ status = psa_export_public_key(key_id, key_buf, sizeof(key_buf), &key_len);
+ ret = psa_pk_status_to_mbedtls(status);
+ destruction_status = psa_destroy_key(key_id);
+ if (ret != 0) {
+ return ret;
+ } else if (destruction_status != PSA_SUCCESS) {
+ return psa_pk_status_to_mbedtls(destruction_status);
+ }
+
+ ret = mbedtls_ecp_point_read_binary(&eck->grp, &eck->Q, key_buf, key_len);
+#else /* MBEDTLS_USE_PSA_CRYPTO */
+ (void) d;
+ (void) d_len;
+
+ ret = mbedtls_ecp_mul(&eck->grp, &eck->Q, &eck->d, &eck->grp.G, f_rng, p_rng);
+#endif /* MBEDTLS_USE_PSA_CRYPTO */
+ return ret;
+}
+
+#if defined(MBEDTLS_PK_HAVE_RFC8410_CURVES)
+
+/*
+ * Load an RFC8410 EC key, which doesn't have any parameters
+ */
+static int pk_use_ecparams_rfc8410(const mbedtls_asn1_buf *params,
+ mbedtls_ecp_group_id grp_id,
+ mbedtls_ecp_group *grp)
+{
+ if (params->tag != 0 || params->len != 0) {
+ return MBEDTLS_ERR_PK_KEY_INVALID_FORMAT;
+ }
+
+ return mbedtls_ecp_group_load(grp, grp_id);
+}
+
+/*
+ * Parse an RFC 8410 encoded private EC key
+ *
+ * CurvePrivateKey ::= OCTET STRING
+ */
+static int pk_parse_key_rfc8410_der(mbedtls_ecp_keypair *eck,
+ unsigned char *key, size_t keylen, const unsigned char *end,
+ int (*f_rng)(void *, unsigned char *, size_t), void *p_rng)
+{
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
+ size_t len;
+
+ if ((ret = mbedtls_asn1_get_tag(&key, (key + keylen), &len, MBEDTLS_ASN1_OCTET_STRING)) != 0) {
+ return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_KEY_INVALID_FORMAT, ret);
+ }
+
+ if (key + len != end) {
+ return MBEDTLS_ERR_PK_KEY_INVALID_FORMAT;
+ }
+
+ if ((ret = mbedtls_mpi_read_binary_le(&eck->d, key, len)) != 0) {
+ mbedtls_ecp_keypair_free(eck);
+ return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_KEY_INVALID_FORMAT, ret);
+ }
+
+ // pk_parse_key_pkcs8_unencrypted_der() only supports version 1 PKCS8 keys,
+ // which never contain a public key. As such, derive the public key
+ // unconditionally.
+ if ((ret = pk_derive_public_key(eck, key, len, f_rng, p_rng)) != 0) {
+ mbedtls_ecp_keypair_free(eck);
+ return ret;
+ }
+
+ if ((ret = mbedtls_ecp_check_privkey(&eck->grp, &eck->d)) != 0) {
+ mbedtls_ecp_keypair_free(eck);
+ return ret;
+ }
+
+ return 0;
+}
+#endif /* MBEDTLS_PK_HAVE_RFC8410_CURVES */
+#endif /* MBEDTLS_ECP_LIGHT */
+
/*
* EC public key is an EC point
*
@@ -591,7 +704,8 @@
*/
static int pk_get_pk_alg(unsigned char **p,
const unsigned char *end,
- mbedtls_pk_type_t *pk_alg, mbedtls_asn1_buf *params)
+ mbedtls_pk_type_t *pk_alg, mbedtls_asn1_buf *params,
+ mbedtls_ecp_group_id *ec_grp_id)
{
int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
mbedtls_asn1_buf alg_oid;
@@ -602,7 +716,18 @@
return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_INVALID_ALG, ret);
}
- if (mbedtls_oid_get_pk_alg(&alg_oid, pk_alg) != 0) {
+ ret = mbedtls_oid_get_pk_alg(&alg_oid, pk_alg);
+#if defined(MBEDTLS_ECP_LIGHT)
+ if (ret == MBEDTLS_ERR_OID_NOT_FOUND) {
+ ret = mbedtls_oid_get_ec_grp_algid(&alg_oid, ec_grp_id);
+ if (ret == 0) {
+ *pk_alg = MBEDTLS_PK_ECKEY;
+ }
+ }
+#else
+ (void) ec_grp_id;
+#endif
+ if (ret != 0) {
return MBEDTLS_ERR_PK_UNKNOWN_PK_ALG;
}
@@ -630,6 +755,7 @@
size_t len;
mbedtls_asn1_buf alg_params;
mbedtls_pk_type_t pk_alg = MBEDTLS_PK_NONE;
+ mbedtls_ecp_group_id ec_grp_id = MBEDTLS_ECP_DP_NONE;
const mbedtls_pk_info_t *pk_info;
if ((ret = mbedtls_asn1_get_tag(p, end, &len,
@@ -639,7 +765,7 @@
end = *p + len;
- if ((ret = pk_get_pk_alg(p, end, &pk_alg, &alg_params)) != 0) {
+ if ((ret = pk_get_pk_alg(p, end, &pk_alg, &alg_params, &ec_grp_id)) != 0) {
return ret;
}
@@ -667,7 +793,14 @@
#endif /* MBEDTLS_RSA_C */
#if defined(MBEDTLS_ECP_LIGHT)
if (pk_alg == MBEDTLS_PK_ECKEY_DH || pk_alg == MBEDTLS_PK_ECKEY) {
- ret = pk_use_ecparams(&alg_params, &mbedtls_pk_ec(*pk)->grp);
+#if defined(MBEDTLS_PK_HAVE_RFC8410_CURVES)
+ if (mbedtls_pk_is_rfc8410_curve(ec_grp_id)) {
+ ret = pk_use_ecparams_rfc8410(&alg_params, ec_grp_id, &mbedtls_pk_ec(*pk)->grp);
+ } else
+#endif
+ {
+ ret = pk_use_ecparams(&alg_params, &mbedtls_pk_ec(*pk)->grp);
+ }
if (ret == 0) {
ret = pk_get_ecpubkey(p, end, mbedtls_pk_ec(*pk));
}
@@ -877,57 +1010,6 @@
#endif /* MBEDTLS_RSA_C */
#if defined(MBEDTLS_ECP_LIGHT)
-#if defined(MBEDTLS_USE_PSA_CRYPTO)
-/*
- * Helper function for deriving a public key from its private counterpart by
- * using PSA functions.
- */
-static int pk_derive_public_key(mbedtls_ecp_group *grp, mbedtls_ecp_point *Q,
- const mbedtls_mpi *d)
-{
- psa_status_t status, destruction_status;
- psa_key_attributes_t key_attr = PSA_KEY_ATTRIBUTES_INIT;
- size_t curve_bits;
- psa_ecc_family_t curve = mbedtls_ecc_group_to_psa(grp->id, &curve_bits);
- /* This buffer is used to store the private key at first and then the
- * public one (but not at the same time). Therefore we size it for the
- * latter since it's bigger. */
- unsigned char key_buf[MBEDTLS_PSA_MAX_EC_PUBKEY_LENGTH];
- size_t key_len = PSA_BITS_TO_BYTES(curve_bits);
- mbedtls_svc_key_id_t key_id = MBEDTLS_SVC_KEY_ID_INIT;
- int ret;
-
- psa_set_key_type(&key_attr, PSA_KEY_TYPE_ECC_KEY_PAIR(curve));
- psa_set_key_usage_flags(&key_attr, PSA_KEY_USAGE_EXPORT);
-
- ret = mbedtls_mpi_write_binary(d, key_buf, key_len);
- if (ret != 0) {
- return ret;
- }
-
- status = psa_import_key(&key_attr, key_buf, key_len, &key_id);
- ret = psa_pk_status_to_mbedtls(status);
- if (ret != 0) {
- return ret;
- }
-
- mbedtls_platform_zeroize(key_buf, sizeof(key_buf));
-
- status = psa_export_public_key(key_id, key_buf, sizeof(key_buf), &key_len);
- ret = psa_pk_status_to_mbedtls(status);
- destruction_status = psa_destroy_key(key_id);
- if (ret != 0) {
- return ret;
- } else if (destruction_status != PSA_SUCCESS) {
- return psa_pk_status_to_mbedtls(destruction_status);
- }
-
- ret = mbedtls_ecp_point_read_binary(grp, Q, key_buf, key_len);
-
- return ret;
-}
-#endif /* MBEDTLS_USE_PSA_CRYPTO */
-
/*
* Parse a SEC1 encoded private EC key
*/
@@ -937,9 +1019,10 @@
{
int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
int version, pubkey_done;
- size_t len;
+ size_t len, d_len;
mbedtls_asn1_buf params = { 0, 0, NULL };
unsigned char *p = (unsigned char *) key;
+ unsigned char *d;
unsigned char *end = p + keylen;
unsigned char *end2;
@@ -972,6 +1055,8 @@
return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_KEY_INVALID_FORMAT, ret);
}
+ d = p;
+ d_len = len;
if ((ret = mbedtls_mpi_read_binary(&eck->d, p, len)) != 0) {
mbedtls_ecp_keypair_free(eck);
return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_KEY_INVALID_FORMAT, ret);
@@ -1035,20 +1120,10 @@
}
if (!pubkey_done) {
-#if defined(MBEDTLS_USE_PSA_CRYPTO)
- (void) f_rng;
- (void) p_rng;
- if ((ret = pk_derive_public_key(&eck->grp, &eck->Q, &eck->d)) != 0) {
+ if ((ret = pk_derive_public_key(eck, d, d_len, f_rng, p_rng)) != 0) {
mbedtls_ecp_keypair_free(eck);
return ret;
}
-#else /* MBEDTLS_USE_PSA_CRYPTO */
- if ((ret = mbedtls_ecp_mul(&eck->grp, &eck->Q, &eck->d, &eck->grp.G,
- f_rng, p_rng)) != 0) {
- mbedtls_ecp_keypair_free(eck);
- return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_KEY_INVALID_FORMAT, ret);
- }
-#endif /* MBEDTLS_USE_PSA_CRYPTO */
}
if ((ret = mbedtls_ecp_check_privkey(&eck->grp, &eck->d)) != 0) {
@@ -1084,9 +1159,10 @@
unsigned char *p = (unsigned char *) key;
unsigned char *end = p + keylen;
mbedtls_pk_type_t pk_alg = MBEDTLS_PK_NONE;
+ mbedtls_ecp_group_id ec_grp_id = MBEDTLS_ECP_DP_NONE;
const mbedtls_pk_info_t *pk_info;
-#if !defined(MBEDTLS_ECP_C)
+#if !defined(MBEDTLS_ECP_LIGHT)
(void) f_rng;
(void) p_rng;
#endif
@@ -1122,7 +1198,7 @@
return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_KEY_INVALID_VERSION, ret);
}
- if ((ret = pk_get_pk_alg(&p, end, &pk_alg, ¶ms)) != 0) {
+ if ((ret = pk_get_pk_alg(&p, end, &pk_alg, ¶ms, &ec_grp_id)) != 0) {
return ret;
}
@@ -1153,10 +1229,24 @@
#endif /* MBEDTLS_RSA_C */
#if defined(MBEDTLS_ECP_LIGHT)
if (pk_alg == MBEDTLS_PK_ECKEY || pk_alg == MBEDTLS_PK_ECKEY_DH) {
- if ((ret = pk_use_ecparams(¶ms, &mbedtls_pk_ec(*pk)->grp)) != 0 ||
- (ret = pk_parse_key_sec1_der(mbedtls_pk_ec(*pk), p, len, f_rng, p_rng)) != 0) {
- mbedtls_pk_free(pk);
- return ret;
+#if defined(MBEDTLS_PK_HAVE_RFC8410_CURVES)
+ if (mbedtls_pk_is_rfc8410_curve(ec_grp_id)) {
+ if ((ret =
+ pk_use_ecparams_rfc8410(¶ms, ec_grp_id, &mbedtls_pk_ec(*pk)->grp)) != 0 ||
+ (ret =
+ pk_parse_key_rfc8410_der(mbedtls_pk_ec(*pk), p, len, end, f_rng,
+ p_rng)) != 0) {
+ mbedtls_pk_free(pk);
+ return ret;
+ }
+ } else
+#endif
+ {
+ if ((ret = pk_use_ecparams(¶ms, &mbedtls_pk_ec(*pk)->grp)) != 0 ||
+ (ret = pk_parse_key_sec1_der(mbedtls_pk_ec(*pk), p, len, f_rng, p_rng)) != 0) {
+ mbedtls_pk_free(pk);
+ return ret;
+ }
}
} else
#endif /* MBEDTLS_ECP_LIGHT */
@@ -1557,7 +1647,7 @@
*/
p = pem.buf;
- ret = mbedtls_pk_parse_subpubkey(&p, p + pem.buflen, ctx);
+ ret = mbedtls_pk_parse_subpubkey(&p, p + pem.buflen, ctx);
mbedtls_pem_free(&pem);
return ret;
} else if (ret != MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT) {
diff --git a/library/pkwrite.c b/library/pkwrite.c
index 3c1a408..8872953 100644
--- a/library/pkwrite.c
+++ b/library/pkwrite.c
@@ -131,14 +131,14 @@
* }
*/
static int pk_write_ec_param(unsigned char **p, unsigned char *start,
- mbedtls_ecp_keypair *ec)
+ mbedtls_ecp_group_id grp_id)
{
int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
size_t len = 0;
const char *oid;
size_t oid_len;
- if ((ret = mbedtls_oid_get_oid_by_ec_grp(ec->grp.id, &oid, &oid_len)) != 0) {
+ if ((ret = mbedtls_oid_get_oid_by_ec_grp(grp_id, &oid, &oid_len)) != 0) {
return ret;
}
@@ -188,14 +188,13 @@
#if defined(MBEDTLS_USE_PSA_CRYPTO)
if (mbedtls_pk_get_type(key) == MBEDTLS_PK_OPAQUE) {
size_t buffer_size;
- mbedtls_svc_key_id_t *key_id = (mbedtls_svc_key_id_t *) key->pk_ctx;
if (*p < start) {
return MBEDTLS_ERR_PK_BAD_INPUT_DATA;
}
buffer_size = (size_t) (*p - start);
- if (psa_export_public_key(*key_id, start, buffer_size, &len)
+ if (psa_export_public_key(key->priv_id, start, buffer_size, &len)
!= PSA_SUCCESS) {
return MBEDTLS_ERR_PK_BAD_INPUT_DATA;
} else {
@@ -213,8 +212,12 @@
{
int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
unsigned char *c;
- size_t len = 0, par_len = 0, oid_len;
+ int has_par = 1;
+ size_t len = 0, par_len = 0, oid_len = 0;
mbedtls_pk_type_t pk_type;
+#if defined(MBEDTLS_ECP_LIGHT)
+ mbedtls_ecp_group_id ec_grp_id = MBEDTLS_ECP_DP_NONE;
+#endif
const char *oid;
if (size == 0) {
@@ -243,61 +246,72 @@
pk_type = mbedtls_pk_get_type(key);
#if defined(MBEDTLS_ECP_LIGHT)
if (pk_type == MBEDTLS_PK_ECKEY) {
- MBEDTLS_ASN1_CHK_ADD(par_len, pk_write_ec_param(&c, buf, mbedtls_pk_ec(*key)));
+ ec_grp_id = mbedtls_pk_ec(*key)->grp.id;
}
#endif /* MBEDTLS_ECP_LIGHT */
#if defined(MBEDTLS_USE_PSA_CRYPTO)
if (pk_type == MBEDTLS_PK_OPAQUE) {
psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
psa_key_type_t key_type;
- mbedtls_svc_key_id_t key_id;
- psa_ecc_family_t curve;
- size_t bits;
- key_id = *((mbedtls_svc_key_id_t *) key->pk_ctx);
- if (PSA_SUCCESS != psa_get_key_attributes(key_id, &attributes)) {
+ if (PSA_SUCCESS != psa_get_key_attributes(key->priv_id,
+ &attributes)) {
return MBEDTLS_ERR_PLATFORM_HW_ACCEL_FAILED;
}
key_type = psa_get_key_type(&attributes);
- bits = psa_get_key_bits(&attributes);
- psa_reset_key_attributes(&attributes);
+#if defined(MBEDTLS_ECP_LIGHT)
if (PSA_KEY_TYPE_IS_ECC_KEY_PAIR(key_type)) {
+ psa_ecc_family_t curve;
+
curve = PSA_KEY_TYPE_ECC_GET_FAMILY(key_type);
- if (curve == 0) {
- return MBEDTLS_ERR_PK_FEATURE_UNAVAILABLE;
+ if (curve != 0) {
+ ec_grp_id = mbedtls_ecc_group_of_psa(curve, psa_get_key_bits(&attributes), 0);
+ if (ec_grp_id != MBEDTLS_ECP_DP_NONE) {
+ /* The rest of the function works as for legacy EC contexts. */
+ pk_type = MBEDTLS_PK_ECKEY;
+ }
}
-
- ret = mbedtls_psa_get_ecc_oid_from_id(curve, bits,
- &oid, &oid_len);
- if (ret != 0) {
- return MBEDTLS_ERR_PK_FEATURE_UNAVAILABLE;
- }
-
- /* Write EC algorithm parameters; that's akin
- * to pk_write_ec_param() above. */
- MBEDTLS_ASN1_CHK_ADD(par_len, mbedtls_asn1_write_oid(&c, buf,
- oid,
- oid_len));
-
- /* The rest of the function works as for legacy EC contexts. */
- pk_type = MBEDTLS_PK_ECKEY;
- } else if (PSA_KEY_TYPE_IS_RSA(key_type)) {
+ }
+#endif /* MBEDTLS_ECP_LIGHT */
+ if (PSA_KEY_TYPE_IS_RSA(key_type)) {
/* The rest of the function works as for legacy RSA contexts. */
pk_type = MBEDTLS_PK_RSA;
- } else {
- return MBEDTLS_ERR_PK_FEATURE_UNAVAILABLE;
}
+
+ psa_reset_key_attributes(&attributes);
+ }
+ /* `pk_type` will have been changed to non-opaque by here if this function can handle it */
+ if (pk_type == MBEDTLS_PK_OPAQUE) {
+ return MBEDTLS_ERR_PK_FEATURE_UNAVAILABLE;
}
#endif /* MBEDTLS_USE_PSA_CRYPTO */
- if ((ret = mbedtls_oid_get_oid_by_pk_alg(pk_type, &oid,
- &oid_len)) != 0) {
- return ret;
+#if defined(MBEDTLS_ECP_LIGHT)
+ if (pk_type == MBEDTLS_PK_ECKEY) {
+ /* Some groups have their own AlgorithmIdentifier OID, others are handled by mbedtls_oid_get_oid_by_pk_alg() below */
+ ret = mbedtls_oid_get_oid_by_ec_grp_algid(ec_grp_id, &oid, &oid_len);
+
+ if (ret == 0) {
+ /* Currently, none of the supported algorithms that have their own AlgorithmIdentifier OID have any parameters */
+ has_par = 0;
+ } else if (ret == MBEDTLS_ERR_OID_NOT_FOUND) {
+ MBEDTLS_ASN1_CHK_ADD(par_len, pk_write_ec_param(&c, buf, ec_grp_id));
+ } else {
+ return ret;
+ }
+ }
+#endif /* MBEDTLS_ECP_LIGHT */
+
+ if (oid_len == 0) {
+ if ((ret = mbedtls_oid_get_oid_by_pk_alg(pk_type, &oid,
+ &oid_len)) != 0) {
+ return ret;
+ }
}
- MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_algorithm_identifier(&c, buf, oid, oid_len,
- par_len));
+ MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_algorithm_identifier_ext(&c, buf, oid, oid_len,
+ par_len, has_par));
MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_len(&c, buf, len));
MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_tag(&c, buf, MBEDTLS_ASN1_CONSTRUCTED |
@@ -306,6 +320,55 @@
return (int) len;
}
+#if defined(MBEDTLS_ECP_LIGHT)
+#if defined(MBEDTLS_PK_HAVE_RFC8410_CURVES)
+/*
+ * RFC8410
+ *
+ * OneAsymmetricKey ::= SEQUENCE {
+ * version Version,
+ * privateKeyAlgorithm PrivateKeyAlgorithmIdentifier,
+ * privateKey PrivateKey,
+ * attributes [0] IMPLICIT Attributes OPTIONAL,
+ * ...,
+ * [[2: publicKey [1] IMPLICIT PublicKey OPTIONAL ]],
+ * ...
+ * }
+ *
+ * CurvePrivateKey ::= OCTET STRING
+ */
+static int pk_write_ec_rfc8410_der(unsigned char **p, unsigned char *buf,
+ mbedtls_ecp_keypair *ec)
+{
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
+ size_t len = 0;
+ size_t oid_len = 0;
+ const char *oid;
+
+ /* privateKey */
+ MBEDTLS_ASN1_CHK_ADD(len, pk_write_ec_private(p, buf, ec));
+ MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_len(p, buf, len));
+ MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_tag(p, buf, MBEDTLS_ASN1_OCTET_STRING));
+
+ /* privateKeyAlgorithm */
+ if ((ret = mbedtls_oid_get_oid_by_ec_grp_algid(ec->grp.id, &oid, &oid_len)) != 0) {
+ return ret;
+ }
+ MBEDTLS_ASN1_CHK_ADD(len,
+ mbedtls_asn1_write_algorithm_identifier_ext(p, buf, oid, oid_len, 0, 0));
+
+ /* version */
+ MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_int(p, buf, 0));
+
+ MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_len(p, buf, len));
+ MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_tag(p, buf, MBEDTLS_ASN1_CONSTRUCTED |
+ MBEDTLS_ASN1_SEQUENCE));
+
+ return (int) len;
+}
+#endif /* MBEDTLS_PK_HAVE_RFC8410_CURVES */
+#endif /* MBEDTLS_ECP_LIGHT */
+
int mbedtls_pk_write_key_der(const mbedtls_pk_context *key, unsigned char *buf, size_t size)
{
int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
@@ -409,6 +472,12 @@
mbedtls_ecp_keypair *ec = mbedtls_pk_ec(*key);
size_t pub_len = 0, par_len = 0;
+#if defined(MBEDTLS_PK_HAVE_RFC8410_CURVES)
+ if (mbedtls_pk_is_rfc8410_curve(ec->grp.id)) {
+ return pk_write_ec_rfc8410_der(&c, buf, ec);
+ }
+#endif
+
/*
* RFC 5915, or SEC1 Appendix C.4
*
@@ -439,7 +508,7 @@
len += pub_len;
/* parameters */
- MBEDTLS_ASN1_CHK_ADD(par_len, pk_write_ec_param(&c, buf, ec));
+ MBEDTLS_ASN1_CHK_ADD(par_len, pk_write_ec_param(&c, buf, ec->grp.id));
MBEDTLS_ASN1_CHK_ADD(par_len, mbedtls_asn1_write_len(&c, buf, par_len));
MBEDTLS_ASN1_CHK_ADD(par_len, mbedtls_asn1_write_tag(&c, buf,
@@ -472,6 +541,8 @@
#define PEM_END_PRIVATE_KEY_RSA "-----END RSA PRIVATE KEY-----\n"
#define PEM_BEGIN_PRIVATE_KEY_EC "-----BEGIN EC PRIVATE KEY-----\n"
#define PEM_END_PRIVATE_KEY_EC "-----END EC PRIVATE KEY-----\n"
+#define PEM_BEGIN_PRIVATE_KEY_PKCS8 "-----BEGIN PRIVATE KEY-----\n"
+#define PEM_END_PRIVATE_KEY_PKCS8 "-----END PRIVATE KEY-----\n"
#define PUB_DER_MAX_BYTES \
(MBEDTLS_PK_RSA_PUB_DER_MAX_BYTES > MBEDTLS_PK_ECP_PUB_DER_MAX_BYTES ? \
@@ -519,8 +590,16 @@
#endif
#if defined(MBEDTLS_ECP_LIGHT)
if (mbedtls_pk_get_type(key) == MBEDTLS_PK_ECKEY) {
- begin = PEM_BEGIN_PRIVATE_KEY_EC;
- end = PEM_END_PRIVATE_KEY_EC;
+#if defined(MBEDTLS_PK_HAVE_RFC8410_CURVES)
+ if (mbedtls_pk_is_rfc8410_curve(mbedtls_pk_ec(*key)->grp.id)) {
+ begin = PEM_BEGIN_PRIVATE_KEY_PKCS8;
+ end = PEM_END_PRIVATE_KEY_PKCS8;
+ } else
+#endif
+ {
+ begin = PEM_BEGIN_PRIVATE_KEY_EC;
+ end = PEM_END_PRIVATE_KEY_EC;
+ }
} else
#endif
return MBEDTLS_ERR_PK_FEATURE_UNAVAILABLE;
diff --git a/library/pkwrite.h b/library/pkwrite.h
index 8aebd0c..537bd0f 100644
--- a/library/pkwrite.h
+++ b/library/pkwrite.h
@@ -105,4 +105,27 @@
#endif /* MBEDTLS_ECP_C */
+#if defined(MBEDTLS_ECP_LIGHT)
+#include "mbedtls/ecp.h"
+
+#if defined(MBEDTLS_ECP_DP_CURVE25519_ENABLED) || defined(MBEDTLS_ECP_DP_CURVE448_ENABLED)
+#define MBEDTLS_PK_HAVE_RFC8410_CURVES
+
+static inline int mbedtls_pk_is_rfc8410_curve(mbedtls_ecp_group_id id)
+{
+#if defined(MBEDTLS_ECP_DP_CURVE25519_ENABLED)
+ if (id == MBEDTLS_ECP_DP_CURVE25519) {
+ return 1;
+ }
+#endif
+#if defined(MBEDTLS_ECP_DP_CURVE448_ENABLED)
+ if (id == MBEDTLS_ECP_DP_CURVE448) {
+ return 1;
+ }
+#endif
+ return 0;
+}
+#endif /* MBEDTLS_ECP_DP_CURVE25519_ENABLED || MBEDTLS_ECP_DP_CURVE448_ENABLED */
+#endif /* MBEDTLS_ECP_LIGHT */
+
#endif /* MBEDTLS_PK_WRITE_H */
diff --git a/library/ssl_tls.c b/library/ssl_tls.c
index 331bb79..cd87164 100644
--- a/library/ssl_tls.c
+++ b/library/ssl_tls.c
@@ -4973,7 +4973,7 @@
MBEDTLS_SSL_IANA_TLS_GROUP_NONE
};
-static int ssl_preset_suiteb_ciphersuites[] = {
+static const int ssl_preset_suiteb_ciphersuites[] = {
MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256,
MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384,
0
diff --git a/library/ssl_tls12_server.c b/library/ssl_tls12_server.c
index 42f5fe9..ac6c10d 100644
--- a/library/ssl_tls12_server.c
+++ b/library/ssl_tls12_server.c
@@ -2614,8 +2614,7 @@
return MBEDTLS_ERR_SSL_PK_TYPE_MISMATCH;
}
- ssl->handshake->ecdh_psa_privkey =
- *((mbedtls_svc_key_id_t *) pk->pk_ctx);
+ ssl->handshake->ecdh_psa_privkey = pk->priv_id;
/* Key should not be destroyed in the TLS library */
ssl->handshake->ecdh_psa_privkey_is_external = 1;
diff --git a/programs/test/benchmark.c b/programs/test/benchmark.c
index 773c538..226faf3 100644
--- a/programs/test/benchmark.c
+++ b/programs/test/benchmark.c
@@ -363,7 +363,7 @@
#endif /* !HAVE_HARDCLOCK && MBEDTLS_HAVE_ASM &&
__GNUC__ && __ia64__ */
-#if !defined(HAVE_HARDCLOCK) && defined(_MSC_VER) && \
+#if !defined(HAVE_HARDCLOCK) && defined(_WIN32) && \
!defined(EFIX64) && !defined(EFI32)
#define HAVE_HARDCLOCK
@@ -376,7 +376,7 @@
return (unsigned long) (offset.QuadPart);
}
-#endif /* !HAVE_HARDCLOCK && _MSC_VER && !EFIX64 && !EFI32 */
+#endif /* !HAVE_HARDCLOCK && _WIN32 && !EFIX64 && !EFI32 */
#if !defined(HAVE_HARDCLOCK)
diff --git a/tests/data_files/Makefile b/tests/data_files/Makefile
index 257903c..bf61706 100644
--- a/tests/data_files/Makefile
+++ b/tests/data_files/Makefile
@@ -1003,6 +1003,38 @@
$(OPENSSL) ec -pubin -in $< -out $@ -conv_form compressed
all_final += ec_bp512_pub.comp.pem
+ec_x25519_prv.der:
+ $(OPENSSL) genpkey -algorithm X25519 -out $@ -outform DER
+all_final += ec_x25519_prv.der
+
+ec_x25519_pub.der: ec_x25519_pub.der
+ $(OPENSSL) pkey -in $< -inform DER -out $@ -outform DER
+all_final += ec_x25519_pub.der
+
+ec_x25519_prv.pem: ec_x25519_prv.pem
+ $(OPENSSL) pkey -in $< -inform DER -out $@
+all_final += ec_x25519_prv.pem
+
+ec_x25519_pub.pem: ec_x25519_pub.pem
+ $(OPENSSL) pkey -in $< -inform DER -out $@
+all_final += ec_x25519_pub.pem
+
+ec_x448_prv.der:
+ $(OPENSSL) genpkey -algorithm X448 -out $@ -outform DER
+all_final += ec_x448_prv.der
+
+ec_x448_pub.der: ec_x448_pub.der
+ $(OPENSSL) pkey -in $< -inform DER -out $@ -outform DER
+all_final += ec_x448_pub.der
+
+ec_x448_prv.pem: ec_x448_prv.pem
+ $(OPENSSL) pkey -in $< -inform DER -out $@
+all_final += ec_x448_prv.pem
+
+ec_x448_pub.pem: ec_x448_pub.pem
+ $(OPENSSL) pkey -in $< -inform DER -out $@
+all_final += ec_x448_pub.pem
+
################################################################
#### Convert PEM keys to DER format
################################################################
diff --git a/tests/data_files/ec_x25519_prv.der b/tests/data_files/ec_x25519_prv.der
new file mode 100644
index 0000000..ea23733
--- /dev/null
+++ b/tests/data_files/ec_x25519_prv.der
Binary files differ
diff --git a/tests/data_files/ec_x25519_prv.pem b/tests/data_files/ec_x25519_prv.pem
new file mode 100644
index 0000000..0072240
--- /dev/null
+++ b/tests/data_files/ec_x25519_prv.pem
@@ -0,0 +1,3 @@
+-----BEGIN PRIVATE KEY-----
+MC4CAQAwBQYDK2VuBCIEILBtgpZVVDpRy6NuU1IrwKz9YK9ZRmVV+z4eeWhyqxpZ
+-----END PRIVATE KEY-----
diff --git a/tests/data_files/ec_x25519_pub.der b/tests/data_files/ec_x25519_pub.der
new file mode 100644
index 0000000..922cb76
--- /dev/null
+++ b/tests/data_files/ec_x25519_pub.der
Binary files differ
diff --git a/tests/data_files/ec_x25519_pub.pem b/tests/data_files/ec_x25519_pub.pem
new file mode 100644
index 0000000..2a36b5b
--- /dev/null
+++ b/tests/data_files/ec_x25519_pub.pem
@@ -0,0 +1,3 @@
+-----BEGIN PUBLIC KEY-----
+MCowBQYDK2VuAyEAm8Ow6T2CM/5qi6YTiUjMEqkTYtXC7YFYTbBatUGcnRE=
+-----END PUBLIC KEY-----
diff --git a/tests/data_files/ec_x448_prv.der b/tests/data_files/ec_x448_prv.der
new file mode 100644
index 0000000..f6d52f7
--- /dev/null
+++ b/tests/data_files/ec_x448_prv.der
Binary files differ
diff --git a/tests/data_files/ec_x448_prv.pem b/tests/data_files/ec_x448_prv.pem
new file mode 100644
index 0000000..7bca661
--- /dev/null
+++ b/tests/data_files/ec_x448_prv.pem
@@ -0,0 +1,4 @@
+-----BEGIN PRIVATE KEY-----
+MEYCAQAwBQYDK2VvBDoEOGTpCDYD9atLDMYwDnjdwUTkjO4ZMB/uacXKw+4iUiED
+oe50tXsIxi5REqWe2YOoL7eD7npOGRPt
+-----END PRIVATE KEY-----
diff --git a/tests/data_files/ec_x448_pub.der b/tests/data_files/ec_x448_pub.der
new file mode 100644
index 0000000..7c44c91
--- /dev/null
+++ b/tests/data_files/ec_x448_pub.der
Binary files differ
diff --git a/tests/data_files/ec_x448_pub.pem b/tests/data_files/ec_x448_pub.pem
new file mode 100644
index 0000000..306e10c
--- /dev/null
+++ b/tests/data_files/ec_x448_pub.pem
@@ -0,0 +1,4 @@
+-----BEGIN PUBLIC KEY-----
+MEIwBQYDK2VvAzkAlrVhn5KDNBt3nL38B9mqGKqrPwnah3ynJgaWQ5IcLzv6zZT+
+TIjhGQ1NFGWwgtOV8UqU2tO4pYQ=
+-----END PUBLIC KEY-----
diff --git a/tests/src/test_helpers/ssl_helpers.c b/tests/src/test_helpers/ssl_helpers.c
index e79d152..fbf9ea5 100644
--- a/tests/src/test_helpers/ssl_helpers.c
+++ b/tests/src/test_helpers/ssl_helpers.c
@@ -595,8 +595,7 @@
if (cert->pkey != NULL) {
#if defined(MBEDTLS_USE_PSA_CRYPTO)
if (mbedtls_pk_get_type(cert->pkey) == MBEDTLS_PK_OPAQUE) {
- mbedtls_svc_key_id_t *key_slot = cert->pkey->pk_ctx;
- psa_destroy_key(*key_slot);
+ psa_destroy_key(cert->pkey->priv_id);
}
#endif
mbedtls_pk_free(cert->pkey);
diff --git a/tests/ssl-opt.sh b/tests/ssl-opt.sh
index 2bbd34a..cfb0bab 100755
--- a/tests/ssl-opt.sh
+++ b/tests/ssl-opt.sh
@@ -11783,8 +11783,7 @@
-c "got a certificate request" \
-c "client state: MBEDTLS_SSL_CLIENT_CERTIFICATE" \
-c "client state: MBEDTLS_SSL_CLIENT_CERTIFICATE_VERIFY" \
- -c "no suitable signature algorithm" \
- -C "unknown pk type"
+ -c "no suitable signature algorithm"
requires_gnutls_tls1_3
requires_gnutls_next_no_ticket
@@ -11801,8 +11800,7 @@
-c "got a certificate request" \
-c "client state: MBEDTLS_SSL_CLIENT_CERTIFICATE" \
-c "client state: MBEDTLS_SSL_CLIENT_CERTIFICATE_VERIFY" \
- -c "no suitable signature algorithm" \
- -C "unknown pk type"
+ -c "no suitable signature algorithm"
# Test using an opaque private key for client authentication
requires_openssl_tls1_3
@@ -12055,8 +12053,7 @@
-c "got a certificate request" \
-c "client state: MBEDTLS_SSL_CLIENT_CERTIFICATE" \
-c "client state: MBEDTLS_SSL_CLIENT_CERTIFICATE_VERIFY" \
- -c "no suitable signature algorithm" \
- -C "unkown pk type"
+ -c "no suitable signature algorithm"
requires_gnutls_tls1_3
requires_gnutls_next_no_ticket
@@ -12074,8 +12071,7 @@
-c "got a certificate request" \
-c "client state: MBEDTLS_SSL_CLIENT_CERTIFICATE" \
-c "client state: MBEDTLS_SSL_CLIENT_CERTIFICATE_VERIFY" \
- -c "no suitable signature algorithm" \
- -C "unkown pk type"
+ -c "no suitable signature algorithm"
requires_openssl_tls1_3
requires_config_enabled MBEDTLS_DEBUG_C
diff --git a/tests/suites/test_suite_pkparse.data b/tests/suites/test_suite_pkparse.data
index 3a53dc0..1bd1af2 100644
--- a/tests/suites/test_suite_pkparse.data
+++ b/tests/suites/test_suite_pkparse.data
@@ -974,6 +974,22 @@
depends_on:MBEDTLS_PEM_PARSE_C:MBEDTLS_ECP_LIGHT:MBEDTLS_ECP_DP_BP512R1_ENABLED
pk_parse_public_keyfile_ec:"data_files/ec_bp512_pub.comp.pem":0
+Parse Public EC Key #10 (RFC 8410, DER, X25519)
+depends_on:MBEDTLS_PEM_PARSE_C:MBEDTLS_ECP_LIGHT:MBEDTLS_ECP_DP_CURVE25519_ENABLED
+pk_parse_public_keyfile_ec:"data_files/ec_x25519_pub.der":0
+
+Parse Public EC Key #11 (RFC 8410, DER, X448)
+depends_on:MBEDTLS_PEM_PARSE_C:MBEDTLS_ECP_LIGHT:MBEDTLS_ECP_DP_CURVE448_ENABLED
+pk_parse_public_keyfile_ec:"data_files/ec_x448_pub.der":0
+
+Parse Public EC Key #12 (RFC 8410, PEM, X25519)
+depends_on:MBEDTLS_PEM_PARSE_C:MBEDTLS_ECP_LIGHT:MBEDTLS_ECP_DP_CURVE25519_ENABLED
+pk_parse_public_keyfile_ec:"data_files/ec_x25519_pub.pem":0
+
+Parse Public EC Key #13 (RFC 8410, PEM, X448)
+depends_on:MBEDTLS_PEM_PARSE_C:MBEDTLS_ECP_LIGHT:MBEDTLS_ECP_DP_CURVE448_ENABLED
+pk_parse_public_keyfile_ec:"data_files/ec_x448_pub.pem":0
+
Parse EC Key #1 (SEC1 DER)
depends_on:MBEDTLS_ECP_LIGHT:MBEDTLS_ECP_DP_SECP192R1_ENABLED
pk_parse_keyfile_ec:"data_files/ec_prv.sec1.der":"NULL":0
@@ -1082,6 +1098,22 @@
depends_on:MBEDTLS_ECP_LIGHT:MBEDTLS_ECP_DP_SECP256K1_ENABLED:MBEDTLS_PK_PARSE_EC_EXTENDED
pk_parse_keyfile_ec:"data_files/ec_prv.specdom.der":"NULL":0
+Parse EC Key #16 (RFC 8410, DER, X25519)
+depends_on:MBEDTLS_ECP_LIGHT:MBEDTLS_ECP_DP_CURVE25519_ENABLED
+pk_parse_keyfile_ec:"data_files/ec_x25519_prv.der":"NULL":0
+
+Parse EC Key #17 (RFC 8410, DER, X448)
+depends_on:MBEDTLS_ECP_LIGHT:MBEDTLS_ECP_DP_CURVE448_ENABLED
+pk_parse_keyfile_ec:"data_files/ec_x448_prv.der":"NULL":0
+
+Parse EC Key #18 (RFC 8410, PEM, X25519)
+depends_on:MBEDTLS_PEM_PARSE_C:MBEDTLS_ECP_LIGHT:MBEDTLS_ECP_DP_CURVE25519_ENABLED
+pk_parse_keyfile_ec:"data_files/ec_x25519_prv.pem":"NULL":0
+
+Parse EC Key #19 (RFC 8410, PEM, X448)
+depends_on:MBEDTLS_PEM_PARSE_C:MBEDTLS_ECP_LIGHT:MBEDTLS_ECP_DP_CURVE448_ENABLED
+pk_parse_keyfile_ec:"data_files/ec_x448_prv.pem":"NULL":0
+
Key ASN1 (No data)
pk_parse_key:"":MBEDTLS_ERR_PK_KEY_INVALID_FORMAT
@@ -1163,3 +1195,30 @@
Key ASN1 (ECPrivateKey, empty parameters)
depends_on:MBEDTLS_ECP_LIGHT
pk_parse_key:"30070201010400a000":MBEDTLS_ERR_PK_KEY_INVALID_FORMAT
+
+Key ASN1 (OneAsymmetricKey X25519, doesn't match masking requirements, from RFC8410 Appendix A but made into version 0)
+depends_on:MBEDTLS_ECP_LIGHT
+pk_parse_key:"302e020100300506032b656e04220420f8ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff3f":MBEDTLS_ERR_PK_KEY_INVALID_FORMAT
+
+Key ASN1 (OneAsymmetricKey X25519, with invalid optional AlgorithIdentifier parameters)
+depends_on:MBEDTLS_ECP_LIGHT
+pk_parse_key:"3030020100300706032b656e050004220420b06d829655543a51cba36e53522bc0acfd60af59466555fb3e1e796872ab1a59":MBEDTLS_ERR_PK_KEY_INVALID_FORMAT
+
+Key ASN1 (OneAsymmetricKey X25519, with NULL private key)
+depends_on:MBEDTLS_ECP_LIGHT
+pk_parse_key:"300e020100300506032b656e04020500":MBEDTLS_ERR_PK_KEY_INVALID_FORMAT
+
+Key ASN1 (OneAsymmetricKey with invalid AlgorithIdentifier)
+pk_parse_key:"3013020100300a06082b0601040181fd5904020500":MBEDTLS_ERR_PK_KEY_INVALID_FORMAT
+
+Key ASN1 (OneAsymmetricKey X25519, with unsupported attributes)
+depends_on:MBEDTLS_ECP_LIGHT
+pk_parse_key:"304f020100300506032b656e04220420b06d829655543a51cba36e53522bc0acfd60af59466555fb3e1e796872ab1a59a01f301d060a2a864886f70d01090914310f0c0d437572646c6520436861697273":MBEDTLS_ERR_PK_KEY_INVALID_FORMAT
+
+Key ASN1 (OneAsymmetricKey X25519, unsupported version 2 with public key)
+depends_on:MBEDTLS_ECP_LIGHT
+pk_parse_key:"3051020101300506032b656e04220420b06d829655543a51cba36e53522bc0acfd60af59466555fb3e1e796872ab1a598121009bc3b0e93d8233fe6a8ba6138948cc12a91362d5c2ed81584db05ab5419c9d11":MBEDTLS_ERR_PK_KEY_INVALID_FORMAT
+
+Key ASN1 (OneAsymmetricKey X25519, unsupported version 2 with public key and unsupported attributes)
+depends_on:MBEDTLS_ECP_LIGHT
+pk_parse_key:"3072020101300506032b656e04220420b06d829655543a51cba36e53522bc0acfd60af59466555fb3e1e796872ab1a59a01f301d060a2a864886f70d01090914310f0c0d437572646c65204368616972738121009bc3b0e93d8233fe6a8ba6138948cc12a91362d5c2ed81584db05ab5419c9d11":MBEDTLS_ERR_PK_KEY_INVALID_FORMAT
diff --git a/tests/suites/test_suite_pkwrite.data b/tests/suites/test_suite_pkwrite.data
index 34bf0da..4199ff2 100644
--- a/tests/suites/test_suite_pkwrite.data
+++ b/tests/suites/test_suite_pkwrite.data
@@ -38,6 +38,22 @@
depends_on:MBEDTLS_ECP_LIGHT:MBEDTLS_ECP_DP_BP512R1_ENABLED
pk_write_pubkey_check:"data_files/ec_bp512_pub.der":TEST_DER
+Public key write check EC X25519
+depends_on:MBEDTLS_ECP_LIGHT:MBEDTLS_BASE64_C:MBEDTLS_ECP_DP_CURVE25519_ENABLED
+pk_write_pubkey_check:"data_files/ec_x25519_pub.pem":TEST_PEM
+
+Public key write check EC X25519 (DER)
+depends_on:MBEDTLS_ECP_LIGHT:MBEDTLS_BASE64_C:MBEDTLS_ECP_DP_CURVE25519_ENABLED
+pk_write_pubkey_check:"data_files/ec_x25519_pub.der":TEST_DER
+
+Public key write check EC X448
+depends_on:MBEDTLS_ECP_LIGHT:MBEDTLS_BASE64_C:MBEDTLS_ECP_DP_CURVE448_ENABLED
+pk_write_pubkey_check:"data_files/ec_x448_pub.pem":TEST_PEM
+
+Public key write check EC X448 (DER)
+depends_on:MBEDTLS_ECP_LIGHT:MBEDTLS_BASE64_C:MBEDTLS_ECP_DP_CURVE448_ENABLED
+pk_write_pubkey_check:"data_files/ec_x448_pub.der":TEST_DER
+
Private key write check RSA
depends_on:MBEDTLS_RSA_C:MBEDTLS_PEM_PARSE_C:MBEDTLS_PEM_WRITE_C
pk_write_key_check:"data_files/server1.key":TEST_PEM
@@ -94,6 +110,22 @@
depends_on:MBEDTLS_ECP_LIGHT:MBEDTLS_ECP_DP_BP512R1_ENABLED
pk_write_key_check:"data_files/ec_bp512_prv.der":TEST_DER
+Private key write check EC X25519
+depends_on:MBEDTLS_ECP_LIGHT:MBEDTLS_BASE64_C:MBEDTLS_ECP_DP_CURVE25519_ENABLED
+pk_write_key_check:"data_files/ec_x25519_prv.pem":TEST_PEM
+
+Private key write check EC X25519 (DER)
+depends_on:MBEDTLS_ECP_LIGHT:MBEDTLS_BASE64_C:MBEDTLS_ECP_DP_CURVE25519_ENABLED
+pk_write_key_check:"data_files/ec_x25519_prv.der":TEST_DER
+
+Private key write check EC X448
+depends_on:MBEDTLS_ECP_LIGHT:MBEDTLS_BASE64_C:MBEDTLS_ECP_DP_CURVE448_ENABLED
+pk_write_key_check:"data_files/ec_x448_prv.pem":TEST_PEM
+
+Private key write check EC X448 (DER)
+depends_on:MBEDTLS_ECP_LIGHT:MBEDTLS_BASE64_C:MBEDTLS_ECP_DP_CURVE448_ENABLED
+pk_write_key_check:"data_files/ec_x448_prv.der":TEST_DER
+
Derive public key RSA
depends_on:MBEDTLS_RSA_C
pk_write_public_from_private:"data_files/server1.key.der":"data_files/server1.pubkey.der"
@@ -113,3 +145,11 @@
Derive public key EC Brainpool 512 bits
depends_on:MBEDTLS_ECP_LIGHT:MBEDTLS_ECP_DP_BP512R1_ENABLED
pk_write_public_from_private:"data_files/ec_bp512_prv.der":"data_files/ec_bp512_pub.der"
+
+Derive public key EC X25519
+depends_on:MBEDTLS_ECP_LIGHT:MBEDTLS_ECP_DP_CURVE25519_ENABLED
+pk_write_public_from_private:"data_files/ec_x25519_prv.der":"data_files/ec_x25519_pub.der"
+
+Derive public key EC X448
+depends_on:MBEDTLS_ECP_LIGHT:MBEDTLS_ECP_DP_CURVE448_ENABLED
+pk_write_public_from_private:"data_files/ec_x448_prv.der":"data_files/ec_x448_pub.der"
diff --git a/tests/suites/test_suite_platform.data b/tests/suites/test_suite_platform.data
index 39b423f..4276b8f 100644
--- a/tests/suites/test_suite_platform.data
+++ b/tests/suites/test_suite_platform.data
@@ -4,6 +4,3 @@
Time: get seconds
time_get_seconds:
-
-Time: delay milliseconds
-time_delay_milliseconds:1000
diff --git a/tests/suites/test_suite_platform.function b/tests/suites/test_suite_platform.function
index 7453c32..61681b8 100644
--- a/tests/suites/test_suite_platform.function
+++ b/tests/suites/test_suite_platform.function
@@ -10,7 +10,8 @@
#if defined(MBEDTLS_HAVE_TIME)
#include "mbedtls/platform_time.h"
-#ifdef WIN32
+#if defined(_WIN32) || defined(WIN32) || defined(__CYGWIN__) || \
+ defined(__MINGW32__) || defined(_WIN64)
#include <windows.h>
#elif _POSIX_C_SOURCE >= 199309L
#include <time.h>
@@ -19,7 +20,8 @@
#endif
void sleep_ms(int milliseconds)
{
-#ifdef WIN32
+#if defined(_WIN32) || defined(WIN32) || defined(__CYGWIN__) || \
+ defined(__MINGW32__) || defined(_WIN64)
Sleep(milliseconds);
#elif _POSIX_C_SOURCE >= 199309L
struct timespec ts;
@@ -64,6 +66,13 @@
mbedtls_ms_time_t current = mbedtls_ms_time();
mbedtls_ms_time_t elapsed_ms;
+ /*
+ * WARNING: DO NOT ENABLE THIS TEST. We keep the code here to document the
+ * reason.
+ *
+ * Windows CI reports random test fail on platform-suite. It might
+ * be caused by this case.
+ */
sleep_ms(delay_ms);
elapsed_ms = mbedtls_ms_time() - current;