diff --git a/ChangeLog.d/rfc8410.txt b/ChangeLog.d/rfc8410.txt new file mode 100644 index 0000000000..e2984ee4b5 --- /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 da7375962c..3c5072c018 100644 --- a/include/mbedtls/asn1write.h +++ b/include/mbedtls/asn1write.h @@ -163,6 +163,27 @@ int mbedtls_asn1_write_algorithm_identifier(unsigned char **p, const char *oid, size_t oid_len, 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 a72f51c4f7..1cbf968a71 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_ec_grp(const mbedtls_asn1_buf *oid, mbedtls_ecp_group_id *gr */ 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/library/asn1write.c b/library/asn1write.c index b9d586aef4..c65d9370e2 100644 --- a/library/asn1write.c +++ b/library/asn1write.c @@ -194,14 +194,23 @@ int mbedtls_asn1_write_oid(unsigned char **p, const unsigned char *start, int mbedtls_asn1_write_algorithm_identifier(unsigned char **p, const unsigned char *start, 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 80cadcd536..8e57fe46d1 100644 --- a/library/oid.c +++ b/library/oid.c @@ -533,7 +533,7 @@ FN_OID_GET_OID_BY_ATTR1(mbedtls_oid_get_oid_by_pk_alg, #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 @@ FN_OID_GET_OID_BY_ATTR1(mbedtls_oid_get_oid_by_ec_grp, 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 4e2f218032..ae1966bee3 100644 --- a/library/pk.c +++ b/library/pk.c @@ -873,7 +873,7 @@ int mbedtls_pk_wrap_as_opaque(mbedtls_pk_context *pk, #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 +886,7 @@ int mbedtls_pk_wrap_as_opaque(mbedtls_pk_context *pk, /* 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/pkparse.c b/library/pkparse.c index 800e352da2..ade8a04cab 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 @@ static int pk_group_from_specified(const mbedtls_asn1_buf *params, mbedtls_ecp_g { 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 @@ static int pk_group_id_from_group(const mbedtls_ecp_group *grp, mbedtls_ecp_grou mbedtls_mpi_get_bit(&grp->G.Y, 0) == mbedtls_mpi_get_bit(&ref.G.Y, 0)) { break; } - } cleanup: @@ -495,6 +495,119 @@ static int pk_use_ecparams(const mbedtls_asn1_buf *params, mbedtls_ecp_group *gr 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_rsapubkey(unsigned char **p, */ 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 @@ static int pk_get_pk_alg(unsigned char **p, 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 @@ int mbedtls_pk_parse_subpubkey(unsigned char **p, const unsigned char *end, 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 @@ int mbedtls_pk_parse_subpubkey(unsigned char **p, const unsigned char *end, 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 @@ int mbedtls_pk_parse_subpubkey(unsigned char **p, const unsigned char *end, #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 @@ cleanup: #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 @@ static int pk_parse_key_sec1_der(mbedtls_ecp_keypair *eck, { 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 @@ static int pk_parse_key_sec1_der(mbedtls_ecp_keypair *eck, 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 @@ static int pk_parse_key_sec1_der(mbedtls_ecp_keypair *eck, } 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 @@ static int pk_parse_key_pkcs8_unencrypted_der( 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 @@ static int pk_parse_key_pkcs8_unencrypted_der( 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 @@ static int pk_parse_key_pkcs8_unencrypted_der( #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 @@ int mbedtls_pk_parse_public_key(mbedtls_pk_context *ctx, */ 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 3c1a40809e..b83a13e0a6 100644 --- a/library/pkwrite.c +++ b/library/pkwrite.c @@ -131,14 +131,14 @@ static int pk_write_ec_pubkey(unsigned char **p, unsigned char *start, * } */ 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; } @@ -213,8 +213,12 @@ int mbedtls_pk_write_pubkey_der(const mbedtls_pk_context *key, unsigned char *bu { 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,7 +247,7 @@ int mbedtls_pk_write_pubkey_der(const mbedtls_pk_context *key, unsigned char *bu 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) @@ -251,53 +255,64 @@ int mbedtls_pk_write_pubkey_der(const mbedtls_pk_context *key, unsigned char *bu 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)) { 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 +321,55 @@ int mbedtls_pk_write_pubkey_der(const mbedtls_pk_context *key, unsigned char *bu 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 +473,12 @@ end_of_export: 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 +509,7 @@ end_of_export: 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 +542,8 @@ end_of_export: #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 +591,16 @@ int mbedtls_pk_write_key_pem(const mbedtls_pk_context *key, unsigned char *buf, #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 8aebd0c24d..537bd0f8c8 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/tests/data_files/Makefile b/tests/data_files/Makefile index 257903ce80..bf61706e0a 100644 --- a/tests/data_files/Makefile +++ b/tests/data_files/Makefile @@ -1003,6 +1003,38 @@ ec_bp512_pub.comp.pem: ec_bp512_pub.pem $(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 0000000000..ea23733746 Binary files /dev/null and b/tests/data_files/ec_x25519_prv.der differ diff --git a/tests/data_files/ec_x25519_prv.pem b/tests/data_files/ec_x25519_prv.pem new file mode 100644 index 0000000000..007224040f --- /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 0000000000..922cb76188 Binary files /dev/null and b/tests/data_files/ec_x25519_pub.der differ diff --git a/tests/data_files/ec_x25519_pub.pem b/tests/data_files/ec_x25519_pub.pem new file mode 100644 index 0000000000..2a36b5be91 --- /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 0000000000..f6d52f7ae4 Binary files /dev/null and b/tests/data_files/ec_x448_prv.der differ diff --git a/tests/data_files/ec_x448_prv.pem b/tests/data_files/ec_x448_prv.pem new file mode 100644 index 0000000000..7bca6618ed --- /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 0000000000..7c44c91f1e Binary files /dev/null and b/tests/data_files/ec_x448_pub.der differ diff --git a/tests/data_files/ec_x448_pub.pem b/tests/data_files/ec_x448_pub.pem new file mode 100644 index 0000000000..306e10c2dd --- /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/suites/test_suite_pkparse.data b/tests/suites/test_suite_pkparse.data index 3a53dc011a..1bd1af240c 100644 --- a/tests/suites/test_suite_pkparse.data +++ b/tests/suites/test_suite_pkparse.data @@ -974,6 +974,22 @@ Parse Public EC Key #9a (RFC 5480, brainpoolP512r1, compressed) 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 @@ Parse EC Key #15 (SEC1 DER, secp256k1, SpecifiedECDomain) 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 @@ pk_parse_key:"3063020100021100cc8ab070369ede72920e5a51523c857102030100010211009a 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 34bf0da853..4199ff2646 100644 --- a/tests/suites/test_suite_pkwrite.data +++ b/tests/suites/test_suite_pkwrite.data @@ -38,6 +38,22 @@ Public key write check EC Brainpool 512 bits (DER) 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 @@ Private key write check EC Brainpool 512 bits (DER) 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 @@ pk_write_public_from_private:"data_files/ec_521_prv.der":"data_files/ec_521_pub. 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"