Squashed commit upgrading to mbedtls-3.6.0
Squash merging branch import/mbedtls-3.6.0
0fc9291f4 ("libmbedtls: bignum: restore mbedtls_mpi_exp_mod() from v3.5.2")
0ef87b1e6 ("libmbedtls: reset minimum rsa key size")
70b079496 ("libmbedtls: adjust use of rsa pk_wrap API")
6cf76464f ("libmbedtls: allow inclusion of arm_neon.h")
27df5c911 ("libmbedtls: fix cipher_wrap.c for NIST AES Key Wrap mode")
aa584f9ed ("libmbedtls: fix cipher_wrap.c for chacha20 and chachapoly")
523ae957e ("libmbedtls: add fault mitigation in mbedtls_rsa_rsassa_pkcs1_v15_verify()")
30bdb1bbf ("libmbedtls: add fault mitigation in mbedtls_rsa_rsassa_pss_verify_ext()")
e45cdab62 ("libmbedtls: add SM2 curve")
d2fda4fc2 ("libmbedtls: fix no CRT issue")
ab0eb5515 ("libmbedtls: add interfaces in mbedtls for context memory operation")
7925a6f26 ("libmedtls: mpi_miller_rabin: increase count limit")
8eaf69279 ("libmbedtls: add mbedtls_mpi_init_mempool()")
12e83fc8d ("libmbedtls: make mbedtls_mpi_mont*() available")
f9e261da5 ("mbedtls: configure mbedtls to reach for config")
7b6f378d7 ("mbedtls: remove default include/mbedtls/config.h")
c16331743 ("Import mbedtls-3.6.0")
Signed-off-by: Tom Van Eyck <tom.vaneyck@kuleuven.be>
Acked-by: Jerome Forissier <jerome.forissier@linaro.org>
diff --git a/lib/libmbedtls/mbedtls/library/pkwrite.c b/lib/libmbedtls/mbedtls/library/pkwrite.c
index 2194c97..5e009c5 100644
--- a/lib/libmbedtls/mbedtls/library/pkwrite.c
+++ b/lib/libmbedtls/mbedtls/library/pkwrite.c
@@ -2,19 +2,7 @@
* Public Key layer for writing key files and structures
*
* Copyright The Mbed TLS Contributors
- * SPDX-License-Identifier: Apache-2.0
- *
- * Licensed under the Apache License, Version 2.0 (the "License"); you may
- * not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
- * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
+ * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
*/
#include "common.h"
@@ -26,93 +14,92 @@
#include "mbedtls/oid.h"
#include "mbedtls/platform_util.h"
#include "mbedtls/error.h"
+#include "pk_internal.h"
#include <string.h>
-#if defined(MBEDTLS_RSA_C)
-#include "mbedtls/rsa.h"
-#endif
#if defined(MBEDTLS_ECP_C)
#include "mbedtls/bignum.h"
#include "mbedtls/ecp.h"
#include "mbedtls/platform_util.h"
#endif
-#if defined(MBEDTLS_RSA_C) || defined(MBEDTLS_ECP_C)
-#include "pkwrite.h"
+#if defined(MBEDTLS_PK_HAVE_ECC_KEYS)
+#include "pk_internal.h"
#endif
-#if defined(MBEDTLS_ECDSA_C)
-#include "mbedtls/ecdsa.h"
+#if defined(MBEDTLS_RSA_C) || defined(MBEDTLS_PK_HAVE_ECC_KEYS)
+#include "pkwrite.h"
#endif
#if defined(MBEDTLS_PEM_WRITE_C)
#include "mbedtls/pem.h"
#endif
+#if defined(MBEDTLS_RSA_C)
+#include "rsa_internal.h"
+#endif
#if defined(MBEDTLS_USE_PSA_CRYPTO)
#include "psa/crypto.h"
-#include "mbedtls/psa_util.h"
+#include "psa_util_internal.h"
#endif
#include "mbedtls/platform.h"
+/* Helpers for properly sizing buffers aimed at holding public keys or
+ * key-pairs based on build symbols. */
+#if defined(MBEDTLS_PK_USE_PSA_EC_DATA)
+#define PK_MAX_EC_PUBLIC_KEY_SIZE PSA_EXPORT_PUBLIC_KEY_MAX_SIZE
+#define PK_MAX_EC_KEY_PAIR_SIZE MBEDTLS_PSA_MAX_EC_KEY_PAIR_LENGTH
+#elif defined(MBEDTLS_USE_PSA_CRYPTO)
+#define PK_MAX_EC_PUBLIC_KEY_SIZE PSA_EXPORT_PUBLIC_KEY_MAX_SIZE
+#define PK_MAX_EC_KEY_PAIR_SIZE MBEDTLS_PSA_MAX_EC_KEY_PAIR_LENGTH
+#else
+#define PK_MAX_EC_PUBLIC_KEY_SIZE MBEDTLS_ECP_MAX_PT_LEN
+#define PK_MAX_EC_KEY_PAIR_SIZE MBEDTLS_ECP_MAX_BYTES
+#endif
+
+/******************************************************************************
+ * Internal functions for RSA keys.
+ ******************************************************************************/
#if defined(MBEDTLS_RSA_C)
-/*
- * RSAPublicKey ::= SEQUENCE {
- * modulus INTEGER, -- n
- * publicExponent INTEGER -- e
- * }
- */
-static int pk_write_rsa_pubkey(unsigned char **p, unsigned char *start,
- mbedtls_rsa_context *rsa)
+static int pk_write_rsa_der(unsigned char **p, unsigned char *buf,
+ const mbedtls_pk_context *pk)
{
- int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
- size_t len = 0;
- mbedtls_mpi T;
+#if defined(MBEDTLS_USE_PSA_CRYPTO)
+ if (mbedtls_pk_get_type(pk) == MBEDTLS_PK_OPAQUE) {
+ uint8_t tmp[PSA_EXPORT_KEY_PAIR_MAX_SIZE];
+ size_t len = 0, tmp_len = 0;
- mbedtls_mpi_init(&T);
+ if (psa_export_key(pk->priv_id, tmp, sizeof(tmp), &tmp_len) != PSA_SUCCESS) {
+ return MBEDTLS_ERR_PK_BAD_INPUT_DATA;
+ }
+ *p -= tmp_len;
+ memcpy(*p, tmp, tmp_len);
+ len += tmp_len;
+ mbedtls_platform_zeroize(tmp, sizeof(tmp));
- /* Export E */
- if ((ret = mbedtls_rsa_export(rsa, NULL, NULL, NULL, NULL, &T)) != 0 ||
- (ret = mbedtls_asn1_write_mpi(p, start, &T)) < 0) {
- goto end_of_export;
+ return (int) len;
}
- len += ret;
-
- /* Export N */
- if ((ret = mbedtls_rsa_export(rsa, &T, NULL, NULL, NULL, NULL)) != 0 ||
- (ret = mbedtls_asn1_write_mpi(p, start, &T)) < 0) {
- goto end_of_export;
- }
- len += ret;
-
-end_of_export:
-
- mbedtls_mpi_free(&T);
- if (ret < 0) {
- return ret;
- }
-
- MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_len(p, start, len));
- MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_tag(p, start, MBEDTLS_ASN1_CONSTRUCTED |
- MBEDTLS_ASN1_SEQUENCE));
-
- return (int) len;
+#endif /* MBEDTLS_USE_PSA_CRYPTO */
+ return mbedtls_rsa_write_key(mbedtls_pk_rsa(*pk), buf, p);
}
#endif /* MBEDTLS_RSA_C */
-#if defined(MBEDTLS_ECP_C)
-/*
- * EC public key is an EC point
- */
+/******************************************************************************
+ * Internal functions for EC keys.
+ ******************************************************************************/
+#if defined(MBEDTLS_PK_HAVE_ECC_KEYS)
+#if defined(MBEDTLS_PK_USE_PSA_EC_DATA)
static int pk_write_ec_pubkey(unsigned char **p, unsigned char *start,
- mbedtls_ecp_keypair *ec)
+ const mbedtls_pk_context *pk)
{
- int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
size_t len = 0;
- unsigned char buf[MBEDTLS_ECP_MAX_PT_LEN];
+ uint8_t buf[PK_MAX_EC_PUBLIC_KEY_SIZE];
- if ((ret = mbedtls_ecp_point_write_binary(&ec->grp, &ec->Q,
- MBEDTLS_ECP_PF_UNCOMPRESSED,
- &len, buf, sizeof(buf))) != 0) {
- return ret;
+ if (mbedtls_pk_get_type(pk) == MBEDTLS_PK_OPAQUE) {
+ if (psa_export_public_key(pk->priv_id, buf, sizeof(buf), &len) != PSA_SUCCESS) {
+ return MBEDTLS_ERR_PK_BAD_INPUT_DATA;
+ }
+ } else {
+ len = pk->pub_raw_len;
+ memcpy(buf, pk->pub_raw, len);
}
if (*p < start || (size_t) (*p - start) < len) {
@@ -124,6 +111,108 @@
return (int) len;
}
+#else /* MBEDTLS_PK_USE_PSA_EC_DATA */
+static int pk_write_ec_pubkey(unsigned char **p, unsigned char *start,
+ const mbedtls_pk_context *pk)
+{
+ size_t len = 0;
+ unsigned char buf[PK_MAX_EC_PUBLIC_KEY_SIZE];
+ mbedtls_ecp_keypair *ec = mbedtls_pk_ec(*pk);
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
+
+#if defined(MBEDTLS_USE_PSA_CRYPTO)
+ if (mbedtls_pk_get_type(pk) == MBEDTLS_PK_OPAQUE) {
+ if (psa_export_public_key(pk->priv_id, buf, sizeof(buf), &len) != PSA_SUCCESS) {
+ return MBEDTLS_ERR_PK_BAD_INPUT_DATA;
+ }
+ *p -= len;
+ memcpy(*p, buf, len);
+ return (int) len;
+ } else
+#endif /* MBEDTLS_USE_PSA_CRYPTO */
+ {
+ if ((ret = mbedtls_ecp_point_write_binary(&ec->grp, &ec->Q,
+ MBEDTLS_ECP_PF_UNCOMPRESSED,
+ &len, buf, sizeof(buf))) != 0) {
+ return ret;
+ }
+ }
+
+ if (*p < start || (size_t) (*p - start) < len) {
+ return MBEDTLS_ERR_ASN1_BUF_TOO_SMALL;
+ }
+
+ *p -= len;
+ memcpy(*p, buf, len);
+
+ return (int) len;
+}
+#endif /* MBEDTLS_PK_USE_PSA_EC_DATA */
+
+/*
+ * privateKey OCTET STRING -- always of length ceil(log2(n)/8)
+ */
+#if defined(MBEDTLS_PK_USE_PSA_EC_DATA)
+static int pk_write_ec_private(unsigned char **p, unsigned char *start,
+ const mbedtls_pk_context *pk)
+{
+ size_t byte_length;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
+ unsigned char tmp[PK_MAX_EC_KEY_PAIR_SIZE];
+ psa_status_t status;
+
+ if (mbedtls_pk_get_type(pk) == MBEDTLS_PK_OPAQUE) {
+ status = psa_export_key(pk->priv_id, tmp, sizeof(tmp), &byte_length);
+ if (status != PSA_SUCCESS) {
+ ret = PSA_PK_ECDSA_TO_MBEDTLS_ERR(status);
+ return ret;
+ }
+ } else {
+ status = psa_export_key(pk->priv_id, tmp, sizeof(tmp), &byte_length);
+ if (status != PSA_SUCCESS) {
+ ret = PSA_PK_ECDSA_TO_MBEDTLS_ERR(status);
+ goto exit;
+ }
+ }
+
+ ret = mbedtls_asn1_write_octet_string(p, start, tmp, byte_length);
+exit:
+ mbedtls_platform_zeroize(tmp, sizeof(tmp));
+ return ret;
+}
+#else /* MBEDTLS_PK_USE_PSA_EC_DATA */
+static int pk_write_ec_private(unsigned char **p, unsigned char *start,
+ const mbedtls_pk_context *pk)
+{
+ size_t byte_length;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
+ unsigned char tmp[PK_MAX_EC_KEY_PAIR_SIZE];
+
+#if defined(MBEDTLS_USE_PSA_CRYPTO)
+ psa_status_t status;
+ if (mbedtls_pk_get_type(pk) == MBEDTLS_PK_OPAQUE) {
+ status = psa_export_key(pk->priv_id, tmp, sizeof(tmp), &byte_length);
+ if (status != PSA_SUCCESS) {
+ ret = PSA_PK_ECDSA_TO_MBEDTLS_ERR(status);
+ return ret;
+ }
+ } else
+#endif /* MBEDTLS_USE_PSA_CRYPTO */
+ {
+ mbedtls_ecp_keypair *ec = mbedtls_pk_ec_rw(*pk);
+ byte_length = (ec->grp.pbits + 7) / 8;
+
+ ret = mbedtls_ecp_write_key_ext(ec, &byte_length, tmp, sizeof(tmp));
+ if (ret != 0) {
+ goto exit;
+ }
+ }
+ ret = mbedtls_asn1_write_octet_string(p, start, tmp, byte_length);
+exit:
+ mbedtls_platform_zeroize(tmp, sizeof(tmp));
+ return ret;
+}
+#endif /* MBEDTLS_PK_USE_PSA_EC_DATA */
/*
* ECParameters ::= CHOICE {
@@ -131,14 +220,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;
}
@@ -147,28 +236,178 @@
return (int) len;
}
+#if defined(MBEDTLS_PK_HAVE_RFC8410_CURVES)
/*
- * privateKey OCTET STRING -- always of length ceil(log2(n)/8)
+ * RFC8410 section 7
+ *
+ * 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_private(unsigned char **p, unsigned char *start,
- mbedtls_ecp_keypair *ec)
+static int pk_write_ec_rfc8410_der(unsigned char **p, unsigned char *buf,
+ const mbedtls_pk_context *pk)
{
int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
- size_t byte_length = (ec->grp.pbits + 7) / 8;
- unsigned char tmp[MBEDTLS_ECP_MAX_BYTES];
+ size_t len = 0;
+ size_t oid_len = 0;
+ const char *oid;
+ mbedtls_ecp_group_id grp_id;
- ret = mbedtls_ecp_write_key(ec, tmp, byte_length);
- if (ret != 0) {
- goto exit;
+ /* privateKey */
+ MBEDTLS_ASN1_CHK_ADD(len, pk_write_ec_private(p, buf, pk));
+ 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));
+
+ grp_id = mbedtls_pk_get_ec_group_id(pk);
+ /* privateKeyAlgorithm */
+ if ((ret = mbedtls_oid_get_oid_by_ec_grp_algid(grp_id, &oid, &oid_len)) != 0) {
+ return ret;
}
- ret = mbedtls_asn1_write_octet_string(p, start, tmp, byte_length);
+ MBEDTLS_ASN1_CHK_ADD(len,
+ mbedtls_asn1_write_algorithm_identifier_ext(p, buf, oid, oid_len, 0, 0));
-exit:
- mbedtls_platform_zeroize(tmp, byte_length);
- return ret;
+ /* 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_ECP_C */
+#endif /* MBEDTLS_PK_HAVE_RFC8410_CURVES */
+/*
+ * RFC 5915, or SEC1 Appendix C.4
+ *
+ * ECPrivateKey ::= SEQUENCE {
+ * version INTEGER { ecPrivkeyVer1(1) } (ecPrivkeyVer1),
+ * privateKey OCTET STRING,
+ * parameters [0] ECParameters {{ NamedCurve }} OPTIONAL,
+ * publicKey [1] BIT STRING OPTIONAL
+ * }
+ */
+static int pk_write_ec_der(unsigned char **p, unsigned char *buf,
+ const mbedtls_pk_context *pk)
+{
+ size_t len = 0;
+ int ret;
+ size_t pub_len = 0, par_len = 0;
+ mbedtls_ecp_group_id grp_id;
+
+ /* publicKey */
+ MBEDTLS_ASN1_CHK_ADD(pub_len, pk_write_ec_pubkey(p, buf, pk));
+
+ if (*p - buf < 1) {
+ return MBEDTLS_ERR_ASN1_BUF_TOO_SMALL;
+ }
+ (*p)--;
+ **p = 0;
+ pub_len += 1;
+
+ MBEDTLS_ASN1_CHK_ADD(pub_len, mbedtls_asn1_write_len(p, buf, pub_len));
+ MBEDTLS_ASN1_CHK_ADD(pub_len, mbedtls_asn1_write_tag(p, buf, MBEDTLS_ASN1_BIT_STRING));
+
+ MBEDTLS_ASN1_CHK_ADD(pub_len, mbedtls_asn1_write_len(p, buf, pub_len));
+ MBEDTLS_ASN1_CHK_ADD(pub_len, mbedtls_asn1_write_tag(p, buf,
+ MBEDTLS_ASN1_CONTEXT_SPECIFIC |
+ MBEDTLS_ASN1_CONSTRUCTED | 1));
+ len += pub_len;
+
+ /* parameters */
+ grp_id = mbedtls_pk_get_ec_group_id(pk);
+ MBEDTLS_ASN1_CHK_ADD(par_len, pk_write_ec_param(p, buf, grp_id));
+ MBEDTLS_ASN1_CHK_ADD(par_len, mbedtls_asn1_write_len(p, buf, par_len));
+ MBEDTLS_ASN1_CHK_ADD(par_len, mbedtls_asn1_write_tag(p, buf,
+ MBEDTLS_ASN1_CONTEXT_SPECIFIC |
+ MBEDTLS_ASN1_CONSTRUCTED | 0));
+ len += par_len;
+
+ /* privateKey */
+ MBEDTLS_ASN1_CHK_ADD(len, pk_write_ec_private(p, buf, pk));
+
+ /* version */
+ MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_int(p, buf, 1));
+
+ 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_ECC_KEYS */
+
+/******************************************************************************
+ * Internal functions for Opaque keys.
+ ******************************************************************************/
+#if defined(MBEDTLS_USE_PSA_CRYPTO)
+static int pk_write_opaque_pubkey(unsigned char **p, unsigned char *start,
+ const mbedtls_pk_context *pk)
+{
+ size_t buffer_size;
+ size_t len = 0;
+
+ if (*p < start) {
+ return MBEDTLS_ERR_PK_BAD_INPUT_DATA;
+ }
+
+ buffer_size = (size_t) (*p - start);
+ if (psa_export_public_key(pk->priv_id, start, buffer_size,
+ &len) != PSA_SUCCESS) {
+ return MBEDTLS_ERR_PK_BAD_INPUT_DATA;
+ }
+
+ *p -= len;
+ memmove(*p, start, len);
+
+ return (int) len;
+}
+#endif /* MBEDTLS_USE_PSA_CRYPTO */
+
+/******************************************************************************
+ * Generic helpers
+ ******************************************************************************/
+
+/* Extend the public mbedtls_pk_get_type() by getting key type also in case of
+ * opaque keys. */
+static mbedtls_pk_type_t pk_get_type_ext(const mbedtls_pk_context *pk)
+{
+ mbedtls_pk_type_t pk_type = mbedtls_pk_get_type(pk);
+
+#if defined(MBEDTLS_USE_PSA_CRYPTO)
+ if (pk_type == MBEDTLS_PK_OPAQUE) {
+ psa_key_attributes_t opaque_attrs = PSA_KEY_ATTRIBUTES_INIT;
+ psa_key_type_t opaque_key_type;
+
+ if (psa_get_key_attributes(pk->priv_id, &opaque_attrs) != PSA_SUCCESS) {
+ return MBEDTLS_PK_NONE;
+ }
+ opaque_key_type = psa_get_key_type(&opaque_attrs);
+ psa_reset_key_attributes(&opaque_attrs);
+
+ if (PSA_KEY_TYPE_IS_ECC(opaque_key_type)) {
+ return MBEDTLS_PK_ECKEY;
+ } else if (PSA_KEY_TYPE_IS_RSA(opaque_key_type)) {
+ return MBEDTLS_PK_RSA;
+ } else {
+ return MBEDTLS_PK_NONE;
+ }
+ } else
+#endif
+ return pk_type;
+}
+
+/******************************************************************************
+ * Public functions for writing private/public DER keys.
+ ******************************************************************************/
int mbedtls_pk_write_pubkey(unsigned char **p, unsigned char *start,
const mbedtls_pk_context *key)
{
@@ -177,31 +416,17 @@
#if defined(MBEDTLS_RSA_C)
if (mbedtls_pk_get_type(key) == MBEDTLS_PK_RSA) {
- MBEDTLS_ASN1_CHK_ADD(len, pk_write_rsa_pubkey(p, start, mbedtls_pk_rsa(*key)));
+ MBEDTLS_ASN1_CHK_ADD(len, mbedtls_rsa_write_pubkey(mbedtls_pk_rsa(*key), start, p));
} else
#endif
-#if defined(MBEDTLS_ECP_C)
+#if defined(MBEDTLS_PK_HAVE_ECC_KEYS)
if (mbedtls_pk_get_type(key) == MBEDTLS_PK_ECKEY) {
- MBEDTLS_ASN1_CHK_ADD(len, pk_write_ec_pubkey(p, start, mbedtls_pk_ec(*key)));
+ MBEDTLS_ASN1_CHK_ADD(len, pk_write_ec_pubkey(p, start, key));
} else
#endif
#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)
- != PSA_SUCCESS) {
- return MBEDTLS_ERR_PK_BAD_INPUT_DATA;
- } else {
- *p -= len;
- memmove(*p, start, len);
- }
+ MBEDTLS_ASN1_CHK_ADD(len, pk_write_opaque_pubkey(p, start, key));
} else
#endif /* MBEDTLS_USE_PSA_CRYPTO */
return MBEDTLS_ERR_PK_FEATURE_UNAVAILABLE;
@@ -213,9 +438,10 @@
{
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;
- const char *oid;
+ const char *oid = NULL;
if (size == 0) {
return MBEDTLS_ERR_ASN1_BUF_TOO_SMALL;
@@ -240,64 +466,33 @@
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_BIT_STRING));
- pk_type = mbedtls_pk_get_type(key);
-#if defined(MBEDTLS_ECP_C)
- if (pk_type == MBEDTLS_PK_ECKEY) {
- MBEDTLS_ASN1_CHK_ADD(par_len, pk_write_ec_param(&c, buf, mbedtls_pk_ec(*key)));
- }
-#endif
-#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;
+ pk_type = pk_get_type_ext(key);
- 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 (PSA_KEY_TYPE_IS_ECC_KEY_PAIR(key_type)) {
- curve = PSA_KEY_TYPE_ECC_GET_FAMILY(key_type);
- if (curve == 0) {
- return MBEDTLS_ERR_PK_FEATURE_UNAVAILABLE;
- }
-
- ret = mbedtls_psa_get_ecc_oid_from_id(curve, bits,
- &oid, &oid_len);
+#if defined(MBEDTLS_PK_HAVE_ECC_KEYS)
+ if (pk_get_type_ext(key) == MBEDTLS_PK_ECKEY) {
+ mbedtls_ecp_group_id ec_grp_id = mbedtls_pk_get_ec_group_id(key);
+ if (MBEDTLS_PK_IS_RFC8410_GROUP_ID(ec_grp_id)) {
+ ret = mbedtls_oid_get_oid_by_ec_grp_algid(ec_grp_id, &oid, &oid_len);
if (ret != 0) {
- return MBEDTLS_ERR_PK_FEATURE_UNAVAILABLE;
+ return ret;
}
-
- /* 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)) {
- /* The rest of the function works as for legacy RSA contexts. */
- pk_type = MBEDTLS_PK_RSA;
+ has_par = 0;
} else {
- return MBEDTLS_ERR_PK_FEATURE_UNAVAILABLE;
+ MBEDTLS_ASN1_CHK_ADD(par_len, pk_write_ec_param(&c, buf, ec_grp_id));
}
}
-#endif /* MBEDTLS_USE_PSA_CRYPTO */
+#endif /* MBEDTLS_PK_HAVE_ECC_KEYS */
- if ((ret = mbedtls_oid_get_oid_by_pk_alg(pk_type, &oid,
- &oid_len)) != 0) {
- return ret;
+ /* At this point oid_len is not null only for EC Montgomery keys. */
+ if (oid_len == 0) {
+ ret = mbedtls_oid_get_oid_by_pk_alg(pk_type, &oid, &oid_len);
+ if (ret != 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 |
@@ -308,9 +503,7 @@
int mbedtls_pk_write_key_der(const mbedtls_pk_context *key, unsigned char *buf, size_t size)
{
- int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
unsigned char *c;
- size_t len = 0;
if (size == 0) {
return MBEDTLS_ERR_ASN1_BUF_TOO_SMALL;
@@ -319,160 +512,28 @@
c = buf + size;
#if defined(MBEDTLS_RSA_C)
- if (mbedtls_pk_get_type(key) == MBEDTLS_PK_RSA) {
- mbedtls_mpi T; /* Temporary holding the exported parameters */
- mbedtls_rsa_context *rsa = mbedtls_pk_rsa(*key);
-
- /*
- * Export the parameters one after another to avoid simultaneous copies.
- */
-
- mbedtls_mpi_init(&T);
-
- /* Export QP */
- if ((ret = mbedtls_rsa_export_crt(rsa, NULL, NULL, &T)) != 0 ||
- (ret = mbedtls_asn1_write_mpi(&c, buf, &T)) < 0) {
- goto end_of_export;
- }
- len += ret;
-
- /* Export DQ */
- if ((ret = mbedtls_rsa_export_crt(rsa, NULL, &T, NULL)) != 0 ||
- (ret = mbedtls_asn1_write_mpi(&c, buf, &T)) < 0) {
- goto end_of_export;
- }
- len += ret;
-
- /* Export DP */
- if ((ret = mbedtls_rsa_export_crt(rsa, &T, NULL, NULL)) != 0 ||
- (ret = mbedtls_asn1_write_mpi(&c, buf, &T)) < 0) {
- goto end_of_export;
- }
- len += ret;
-
- /* Export Q */
- if ((ret = mbedtls_rsa_export(rsa, NULL, NULL,
- &T, NULL, NULL)) != 0 ||
- (ret = mbedtls_asn1_write_mpi(&c, buf, &T)) < 0) {
- goto end_of_export;
- }
- len += ret;
-
- /* Export P */
- if ((ret = mbedtls_rsa_export(rsa, NULL, &T,
- NULL, NULL, NULL)) != 0 ||
- (ret = mbedtls_asn1_write_mpi(&c, buf, &T)) < 0) {
- goto end_of_export;
- }
- len += ret;
-
- /* Export D */
- if ((ret = mbedtls_rsa_export(rsa, NULL, NULL,
- NULL, &T, NULL)) != 0 ||
- (ret = mbedtls_asn1_write_mpi(&c, buf, &T)) < 0) {
- goto end_of_export;
- }
- len += ret;
-
- /* Export E */
- if ((ret = mbedtls_rsa_export(rsa, NULL, NULL,
- NULL, NULL, &T)) != 0 ||
- (ret = mbedtls_asn1_write_mpi(&c, buf, &T)) < 0) {
- goto end_of_export;
- }
- len += ret;
-
- /* Export N */
- if ((ret = mbedtls_rsa_export(rsa, &T, NULL,
- NULL, NULL, NULL)) != 0 ||
- (ret = mbedtls_asn1_write_mpi(&c, buf, &T)) < 0) {
- goto end_of_export;
- }
- len += ret;
-
-end_of_export:
-
- mbedtls_mpi_free(&T);
- if (ret < 0) {
- return ret;
- }
-
- MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_int(&c, buf, 0));
- 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 |
- MBEDTLS_ASN1_SEQUENCE));
+ if (pk_get_type_ext(key) == MBEDTLS_PK_RSA) {
+ return pk_write_rsa_der(&c, buf, key);
} else
#endif /* MBEDTLS_RSA_C */
-#if defined(MBEDTLS_ECP_C)
- if (mbedtls_pk_get_type(key) == MBEDTLS_PK_ECKEY) {
- mbedtls_ecp_keypair *ec = mbedtls_pk_ec(*key);
- size_t pub_len = 0, par_len = 0;
-
- /*
- * RFC 5915, or SEC1 Appendix C.4
- *
- * ECPrivateKey ::= SEQUENCE {
- * version INTEGER { ecPrivkeyVer1(1) } (ecPrivkeyVer1),
- * privateKey OCTET STRING,
- * parameters [0] ECParameters {{ NamedCurve }} OPTIONAL,
- * publicKey [1] BIT STRING OPTIONAL
- * }
- */
-
- /* publicKey */
- MBEDTLS_ASN1_CHK_ADD(pub_len, pk_write_ec_pubkey(&c, buf, ec));
-
- if (c - buf < 1) {
- return MBEDTLS_ERR_ASN1_BUF_TOO_SMALL;
+#if defined(MBEDTLS_PK_HAVE_ECC_KEYS)
+ if (pk_get_type_ext(key) == MBEDTLS_PK_ECKEY) {
+#if defined(MBEDTLS_PK_HAVE_RFC8410_CURVES)
+ if (mbedtls_pk_is_rfc8410(key)) {
+ return pk_write_ec_rfc8410_der(&c, buf, key);
}
- *--c = 0;
- pub_len += 1;
-
- MBEDTLS_ASN1_CHK_ADD(pub_len, mbedtls_asn1_write_len(&c, buf, pub_len));
- MBEDTLS_ASN1_CHK_ADD(pub_len, mbedtls_asn1_write_tag(&c, buf, MBEDTLS_ASN1_BIT_STRING));
-
- MBEDTLS_ASN1_CHK_ADD(pub_len, mbedtls_asn1_write_len(&c, buf, pub_len));
- MBEDTLS_ASN1_CHK_ADD(pub_len, mbedtls_asn1_write_tag(&c, buf,
- MBEDTLS_ASN1_CONTEXT_SPECIFIC |
- MBEDTLS_ASN1_CONSTRUCTED | 1));
- len += pub_len;
-
- /* parameters */
- MBEDTLS_ASN1_CHK_ADD(par_len, pk_write_ec_param(&c, buf, ec));
-
- 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,
- MBEDTLS_ASN1_CONTEXT_SPECIFIC |
- MBEDTLS_ASN1_CONSTRUCTED | 0));
- len += par_len;
-
- /* privateKey */
- MBEDTLS_ASN1_CHK_ADD(len, pk_write_ec_private(&c, buf, ec));
-
- /* version */
- MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_int(&c, buf, 1));
-
- 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 |
- MBEDTLS_ASN1_SEQUENCE));
+#endif /* MBEDTLS_PK_HAVE_RFC8410_CURVES */
+ return pk_write_ec_der(&c, buf, key);
} else
-#endif /* MBEDTLS_ECP_C */
+#endif /* MBEDTLS_PK_HAVE_ECC_KEYS */
return MBEDTLS_ERR_PK_FEATURE_UNAVAILABLE;
-
- return (int) len;
}
+/******************************************************************************
+ * Public functions for wrinting private/public PEM keys.
+ ******************************************************************************/
#if defined(MBEDTLS_PEM_WRITE_C)
-#define PEM_BEGIN_PUBLIC_KEY "-----BEGIN PUBLIC KEY-----\n"
-#define PEM_END_PUBLIC_KEY "-----END PUBLIC KEY-----\n"
-
-#define PEM_BEGIN_PRIVATE_KEY_RSA "-----BEGIN RSA PRIVATE KEY-----\n"
-#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 PUB_DER_MAX_BYTES \
(MBEDTLS_PK_RSA_PUB_DER_MAX_BYTES > MBEDTLS_PK_ECP_PUB_DER_MAX_BYTES ? \
MBEDTLS_PK_RSA_PUB_DER_MAX_BYTES : MBEDTLS_PK_ECP_PUB_DER_MAX_BYTES)
@@ -483,55 +544,77 @@
int mbedtls_pk_write_pubkey_pem(const mbedtls_pk_context *key, unsigned char *buf, size_t size)
{
int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
- unsigned char output_buf[PUB_DER_MAX_BYTES];
+ unsigned char *output_buf = NULL;
+ output_buf = mbedtls_calloc(1, PUB_DER_MAX_BYTES);
+ if (output_buf == NULL) {
+ return MBEDTLS_ERR_PK_ALLOC_FAILED;
+ }
size_t olen = 0;
if ((ret = mbedtls_pk_write_pubkey_der(key, output_buf,
- sizeof(output_buf))) < 0) {
- return ret;
+ PUB_DER_MAX_BYTES)) < 0) {
+ goto cleanup;
}
- if ((ret = mbedtls_pem_write_buffer(PEM_BEGIN_PUBLIC_KEY, PEM_END_PUBLIC_KEY,
- output_buf + sizeof(output_buf) - ret,
+ if ((ret = mbedtls_pem_write_buffer(PEM_BEGIN_PUBLIC_KEY "\n", PEM_END_PUBLIC_KEY "\n",
+ output_buf + PUB_DER_MAX_BYTES - ret,
ret, buf, size, &olen)) != 0) {
- return ret;
+ goto cleanup;
}
- return 0;
+ ret = 0;
+cleanup:
+ mbedtls_free(output_buf);
+ return ret;
}
int mbedtls_pk_write_key_pem(const mbedtls_pk_context *key, unsigned char *buf, size_t size)
{
int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
- unsigned char output_buf[PRV_DER_MAX_BYTES];
+ unsigned char *output_buf = NULL;
+ output_buf = mbedtls_calloc(1, PRV_DER_MAX_BYTES);
+ if (output_buf == NULL) {
+ return MBEDTLS_ERR_PK_ALLOC_FAILED;
+ }
const char *begin, *end;
size_t olen = 0;
- if ((ret = mbedtls_pk_write_key_der(key, output_buf, sizeof(output_buf))) < 0) {
- return ret;
+ if ((ret = mbedtls_pk_write_key_der(key, output_buf, PRV_DER_MAX_BYTES)) < 0) {
+ goto cleanup;
}
#if defined(MBEDTLS_RSA_C)
- if (mbedtls_pk_get_type(key) == MBEDTLS_PK_RSA) {
- begin = PEM_BEGIN_PRIVATE_KEY_RSA;
- end = PEM_END_PRIVATE_KEY_RSA;
+ if (pk_get_type_ext(key) == MBEDTLS_PK_RSA) {
+ begin = PEM_BEGIN_PRIVATE_KEY_RSA "\n";
+ end = PEM_END_PRIVATE_KEY_RSA "\n";
} else
#endif
-#if defined(MBEDTLS_ECP_C)
- 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_ECC_KEYS)
+ if (pk_get_type_ext(key) == MBEDTLS_PK_ECKEY) {
+ if (mbedtls_pk_is_rfc8410(key)) {
+ begin = PEM_BEGIN_PRIVATE_KEY_PKCS8 "\n";
+ end = PEM_END_PRIVATE_KEY_PKCS8 "\n";
+ } else {
+ begin = PEM_BEGIN_PRIVATE_KEY_EC "\n";
+ end = PEM_END_PRIVATE_KEY_EC "\n";
+ }
} else
-#endif
- return MBEDTLS_ERR_PK_FEATURE_UNAVAILABLE;
-
- if ((ret = mbedtls_pem_write_buffer(begin, end,
- output_buf + sizeof(output_buf) - ret,
- ret, buf, size, &olen)) != 0) {
- return ret;
+#endif /* MBEDTLS_PK_HAVE_ECC_KEYS */
+ {
+ ret = MBEDTLS_ERR_PK_FEATURE_UNAVAILABLE;
+ goto cleanup;
}
- return 0;
+ if ((ret = mbedtls_pem_write_buffer(begin, end,
+ output_buf + PRV_DER_MAX_BYTES - ret,
+ ret, buf, size, &olen)) != 0) {
+ goto cleanup;
+ }
+
+ ret = 0;
+cleanup:
+ mbedtls_zeroize_and_free(output_buf, PRV_DER_MAX_BYTES);
+ return ret;
}
#endif /* MBEDTLS_PEM_WRITE_C */