Import mbedtls-3.6.0
Imports Mbed TLS 3.6.0 from https://github.com/Mbed-TLS/mbedtls.git
tags mbedtls-3.6.0, v3.6.0
Files that are not needed are removed:
cd lib/libmbedtls
rm -rf mbedtls
cp -R path/to/mbedtls-3.6.0/mbedtls .
cd mbedtls
rm CMakeLists.txt DartConfiguration.tcl Makefile
rm .gitignore .travis.yml .pylintrc .globalrc .mypy.ini BRANCHES.md
rm include/.gitignore include/CMakeLists.txt library/.gitignore
rm library/CMakeLists.txt library/Makefile
rm -r cmake
rm -rf .git .github doxygen configs programs scripts tests visualc
rm -rf 3rdparty ChangeLog.d docs pkgconfig .gitmodules .readthedocs.yaml
rm library/mps_*
cd ..
git add mbedtls
This time we leave library/psa_* present to enable TLS 1.3 features.
This is a complete overwrite of previous code so earlier changes in the
previous branch import/mbedtls-3.4.0 will be added on top of this commit.
Signed-off-by: Tom Van Eyck <tom.vaneyck@kuleuven.be>
Acked-by: Jens Wiklander <jens.wiklander@linaro.org>
diff --git a/lib/libmbedtls/mbedtls/library/pkparse.c b/lib/libmbedtls/mbedtls/library/pkparse.c
index ccca692..4f6ee13 100644
--- a/lib/libmbedtls/mbedtls/library/pkparse.c
+++ b/lib/libmbedtls/mbedtls/library/pkparse.c
@@ -2,19 +2,7 @@
* Public Key layer for parsing 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"
@@ -25,19 +13,25 @@
#include "mbedtls/asn1.h"
#include "mbedtls/oid.h"
#include "mbedtls/platform_util.h"
+#include "mbedtls/platform.h"
#include "mbedtls/error.h"
+#include "mbedtls/ecp.h"
+#include "pk_internal.h"
#include <string.h>
+#if defined(MBEDTLS_USE_PSA_CRYPTO)
+#include "mbedtls/psa_util.h"
+#include "psa/crypto.h"
+#endif
+
+/* Key types */
#if defined(MBEDTLS_RSA_C)
#include "mbedtls/rsa.h"
+#include "rsa_internal.h"
#endif
-#if defined(MBEDTLS_ECP_C)
-#include "mbedtls/ecp.h"
-#endif
-#if defined(MBEDTLS_ECDSA_C)
-#include "mbedtls/ecdsa.h"
-#endif
+
+/* Extended formats */
#if defined(MBEDTLS_PEM_PARSE_C)
#include "mbedtls/pem.h"
#endif
@@ -48,163 +42,55 @@
#include "mbedtls/pkcs12.h"
#endif
-#include "mbedtls/platform.h"
+#if defined(MBEDTLS_PK_HAVE_ECC_KEYS)
-#if defined(MBEDTLS_FS_IO)
-/*
- * Load all data from a file into a given buffer.
+/***********************************************************************
*
- * The file is expected to contain either PEM or DER encoded data.
- * A terminating null byte is always appended. It is included in the announced
- * length only if the data looks like it is PEM encoded.
- */
-int mbedtls_pk_load_file(const char *path, unsigned char **buf, size_t *n)
+ * Low-level ECC parsing: optional support for SpecifiedECDomain
+ *
+ * There are two functions here that are used by the rest of the code:
+ * - pk_ecc_tag_is_speficied_ec_domain()
+ * - pk_ecc_group_id_from_specified()
+ *
+ * All the other functions are internal to this section.
+ *
+ * The two "public" functions have a dummy variant provided
+ * in configs without MBEDTLS_PK_PARSE_EC_EXTENDED. This acts as an
+ * abstraction layer for this macro, which should not appear outside
+ * this section.
+ *
+ **********************************************************************/
+
+#if !defined(MBEDTLS_PK_PARSE_EC_EXTENDED)
+/* See the "real" version for documentation */
+static int pk_ecc_tag_is_specified_ec_domain(int tag)
{
- FILE *f;
- long size;
-
- if ((f = fopen(path, "rb")) == NULL) {
- return MBEDTLS_ERR_PK_FILE_IO_ERROR;
- }
-
- /* Ensure no stdio buffering of secrets, as such buffers cannot be wiped. */
- mbedtls_setbuf(f, NULL);
-
- fseek(f, 0, SEEK_END);
- if ((size = ftell(f)) == -1) {
- fclose(f);
- return MBEDTLS_ERR_PK_FILE_IO_ERROR;
- }
- fseek(f, 0, SEEK_SET);
-
- *n = (size_t) size;
-
- if (*n + 1 == 0 ||
- (*buf = mbedtls_calloc(1, *n + 1)) == NULL) {
- fclose(f);
- return MBEDTLS_ERR_PK_ALLOC_FAILED;
- }
-
- if (fread(*buf, 1, *n, f) != *n) {
- fclose(f);
-
- mbedtls_platform_zeroize(*buf, *n);
- mbedtls_free(*buf);
-
- return MBEDTLS_ERR_PK_FILE_IO_ERROR;
- }
-
- fclose(f);
-
- (*buf)[*n] = '\0';
-
- if (strstr((const char *) *buf, "-----BEGIN ") != NULL) {
- ++*n;
- }
-
+ (void) tag;
return 0;
}
+/* See the "real" version for documentation */
+static int pk_ecc_group_id_from_specified(const mbedtls_asn1_buf *params,
+ mbedtls_ecp_group_id *grp_id)
+{
+ (void) params;
+ (void) grp_id;
+ return MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE;
+}
+#else /* MBEDTLS_PK_PARSE_EC_EXTENDED */
/*
- * Load and parse a private key
+ * Tell if the passed tag might be the start of SpecifiedECDomain
+ * (that is, a sequence).
*/
-int mbedtls_pk_parse_keyfile(mbedtls_pk_context *ctx,
- const char *path, const char *pwd,
- int (*f_rng)(void *, unsigned char *, size_t), void *p_rng)
+static int pk_ecc_tag_is_specified_ec_domain(int tag)
{
- int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
- size_t n;
- unsigned char *buf;
-
- if ((ret = mbedtls_pk_load_file(path, &buf, &n)) != 0) {
- return ret;
- }
-
- if (pwd == NULL) {
- ret = mbedtls_pk_parse_key(ctx, buf, n, NULL, 0, f_rng, p_rng);
- } else {
- ret = mbedtls_pk_parse_key(ctx, buf, n,
- (const unsigned char *) pwd, strlen(pwd), f_rng, p_rng);
- }
-
- mbedtls_platform_zeroize(buf, n);
- mbedtls_free(buf);
-
- return ret;
+ return tag == (MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE);
}
/*
- * Load and parse a public key
- */
-int mbedtls_pk_parse_public_keyfile(mbedtls_pk_context *ctx, const char *path)
-{
- int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
- size_t n;
- unsigned char *buf;
-
- if ((ret = mbedtls_pk_load_file(path, &buf, &n)) != 0) {
- return ret;
- }
-
- ret = mbedtls_pk_parse_public_key(ctx, buf, n);
-
- mbedtls_platform_zeroize(buf, n);
- mbedtls_free(buf);
-
- return ret;
-}
-#endif /* MBEDTLS_FS_IO */
-
-#if defined(MBEDTLS_ECP_C)
-/* Minimally parse an ECParameters buffer to and mbedtls_asn1_buf
- *
- * ECParameters ::= CHOICE {
- * namedCurve OBJECT IDENTIFIER
- * specifiedCurve SpecifiedECDomain -- = SEQUENCE { ... }
- * -- implicitCurve NULL
- * }
- */
-static int pk_get_ecparams(unsigned char **p, const unsigned char *end,
- mbedtls_asn1_buf *params)
-{
- int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
-
- if (end - *p < 1) {
- return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_KEY_INVALID_FORMAT,
- MBEDTLS_ERR_ASN1_OUT_OF_DATA);
- }
-
- /* Tag may be either OID or SEQUENCE */
- params->tag = **p;
- if (params->tag != MBEDTLS_ASN1_OID
-#if defined(MBEDTLS_PK_PARSE_EC_EXTENDED)
- && params->tag != (MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)
-#endif
- ) {
- return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_KEY_INVALID_FORMAT,
- MBEDTLS_ERR_ASN1_UNEXPECTED_TAG);
- }
-
- if ((ret = mbedtls_asn1_get_tag(p, end, ¶ms->len, params->tag)) != 0) {
- return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_KEY_INVALID_FORMAT, ret);
- }
-
- params->p = *p;
- *p += params->len;
-
- if (*p != end) {
- return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_KEY_INVALID_FORMAT,
- MBEDTLS_ERR_ASN1_LENGTH_MISMATCH);
- }
-
- return 0;
-}
-
-#if defined(MBEDTLS_PK_PARSE_EC_EXTENDED)
-/*
* Parse a SpecifiedECDomain (SEC 1 C.2) and (mostly) fill the group with it.
* WARNING: the resulting group should only be used with
- * pk_group_id_from_specified(), since its base point may not be set correctly
+ * pk_ecc_group_id_from_specified(), since its base point may not be set correctly
* if it was encoded compressed.
*
* SpecifiedECDomain ::= SEQUENCE {
@@ -224,7 +110,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;
@@ -396,7 +282,6 @@
mbedtls_mpi_get_bit(&grp->G.Y, 0) == mbedtls_mpi_get_bit(&ref.G.Y, 0)) {
break;
}
-
}
cleanup:
@@ -414,8 +299,8 @@
/*
* Parse a SpecifiedECDomain (SEC 1 C.2) and find the associated group ID
*/
-static int pk_group_id_from_specified(const mbedtls_asn1_buf *params,
- mbedtls_ecp_group_id *grp_id)
+static int pk_ecc_group_id_from_specified(const mbedtls_asn1_buf *params,
+ mbedtls_ecp_group_id *grp_id)
{
int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
mbedtls_ecp_group grp;
@@ -430,7 +315,7 @@
cleanup:
/* The API respecting lifecycle for mbedtls_ecp_group struct is
- * _init(), _load() and _free(). In pk_group_id_from_specified() the
+ * _init(), _load() and _free(). In pk_ecc_group_id_from_specified() the
* temporary grp breaks that flow and it's members are populated
* by pk_group_id_from_group(). As such mbedtls_ecp_group_free()
* which is assuming a group populated by _setup() may not clean-up
@@ -446,6 +331,53 @@
}
#endif /* MBEDTLS_PK_PARSE_EC_EXTENDED */
+/***********************************************************************
+ *
+ * Unsorted (yet!) from this point on until the next section header
+ *
+ **********************************************************************/
+
+/* Minimally parse an ECParameters buffer to and mbedtls_asn1_buf
+ *
+ * ECParameters ::= CHOICE {
+ * namedCurve OBJECT IDENTIFIER
+ * specifiedCurve SpecifiedECDomain -- = SEQUENCE { ... }
+ * -- implicitCurve NULL
+ * }
+ */
+static int pk_get_ecparams(unsigned char **p, const unsigned char *end,
+ mbedtls_asn1_buf *params)
+{
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
+
+ if (end - *p < 1) {
+ return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_KEY_INVALID_FORMAT,
+ MBEDTLS_ERR_ASN1_OUT_OF_DATA);
+ }
+
+ /* Acceptable tags: OID for namedCurve, or specifiedECDomain */
+ params->tag = **p;
+ if (params->tag != MBEDTLS_ASN1_OID &&
+ !pk_ecc_tag_is_specified_ec_domain(params->tag)) {
+ return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_KEY_INVALID_FORMAT,
+ MBEDTLS_ERR_ASN1_UNEXPECTED_TAG);
+ }
+
+ if ((ret = mbedtls_asn1_get_tag(p, end, ¶ms->len, params->tag)) != 0) {
+ return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_KEY_INVALID_FORMAT, ret);
+ }
+
+ params->p = *p;
+ *p += params->len;
+
+ if (*p != end) {
+ return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_KEY_INVALID_FORMAT,
+ MBEDTLS_ERR_ASN1_LENGTH_MISMATCH);
+ }
+
+ return 0;
+}
+
/*
* Use EC parameters to initialise an EC group
*
@@ -454,7 +386,7 @@
* specifiedCurve SpecifiedECDomain -- = SEQUENCE { ... }
* -- implicitCurve NULL
*/
-static int pk_use_ecparams(const mbedtls_asn1_buf *params, mbedtls_ecp_group *grp)
+static int pk_use_ecparams(const mbedtls_asn1_buf *params, mbedtls_pk_context *pk)
{
int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
mbedtls_ecp_group_id grp_id;
@@ -464,116 +396,71 @@
return MBEDTLS_ERR_PK_UNKNOWN_NAMED_CURVE;
}
} else {
-#if defined(MBEDTLS_PK_PARSE_EC_EXTENDED)
- if ((ret = pk_group_id_from_specified(params, &grp_id)) != 0) {
+ ret = pk_ecc_group_id_from_specified(params, &grp_id);
+ if (ret != 0) {
return ret;
}
-#else
+ }
+
+ return mbedtls_pk_ecc_set_group(pk, grp_id);
+}
+
+#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_pk_context *pk)
+{
+ if (params->tag != 0 || params->len != 0) {
return MBEDTLS_ERR_PK_KEY_INVALID_FORMAT;
-#endif
+ }
+
+ return mbedtls_pk_ecc_set_group(pk, grp_id);
+}
+
+/*
+ * Parse an RFC 8410 encoded private EC key
+ *
+ * CurvePrivateKey ::= OCTET STRING
+ */
+static int pk_parse_key_rfc8410_der(mbedtls_pk_context *pk,
+ 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;
}
/*
- * grp may already be initialized; if so, make sure IDs match
+ * Load the private key
*/
- if (grp->id != MBEDTLS_ECP_DP_NONE && grp->id != grp_id) {
- return MBEDTLS_ERR_PK_KEY_INVALID_FORMAT;
+ ret = mbedtls_pk_ecc_set_key(pk, key, len);
+ if (ret != 0) {
+ return ret;
}
- if ((ret = mbedtls_ecp_group_load(grp, grp_id)) != 0) {
+ /* 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 = mbedtls_pk_ecc_set_pubkey_from_prv(pk, key, len, f_rng, p_rng)) != 0) {
return ret;
}
return 0;
}
+#endif /* MBEDTLS_PK_HAVE_RFC8410_CURVES */
-/*
- * EC public key is an EC point
- *
- * The caller is responsible for clearing the structure upon failure if
- * desired. Take care to pass along the possible ECP_FEATURE_UNAVAILABLE
- * return code of mbedtls_ecp_point_read_binary() and leave p in a usable state.
- */
-static int pk_get_ecpubkey(unsigned char **p, const unsigned char *end,
- mbedtls_ecp_keypair *key)
-{
- int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
-
- if ((ret = mbedtls_ecp_point_read_binary(&key->grp, &key->Q,
- (const unsigned char *) *p, end - *p)) == 0) {
- ret = mbedtls_ecp_check_pubkey(&key->grp, &key->Q);
- }
-
- /*
- * We know mbedtls_ecp_point_read_binary consumed all bytes or failed
- */
- *p = (unsigned char *) end;
-
- return ret;
-}
-#endif /* MBEDTLS_ECP_C */
-
-#if defined(MBEDTLS_RSA_C)
-/*
- * RSAPublicKey ::= SEQUENCE {
- * modulus INTEGER, -- n
- * publicExponent INTEGER -- e
- * }
- */
-static int pk_get_rsapubkey(unsigned char **p,
- const unsigned char *end,
- mbedtls_rsa_context *rsa)
-{
- int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
- size_t len;
-
- if ((ret = mbedtls_asn1_get_tag(p, end, &len,
- MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)) != 0) {
- return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_INVALID_PUBKEY, ret);
- }
-
- if (*p + len != end) {
- return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_INVALID_PUBKEY,
- MBEDTLS_ERR_ASN1_LENGTH_MISMATCH);
- }
-
- /* Import N */
- if ((ret = mbedtls_asn1_get_tag(p, end, &len, MBEDTLS_ASN1_INTEGER)) != 0) {
- return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_INVALID_PUBKEY, ret);
- }
-
- if ((ret = mbedtls_rsa_import_raw(rsa, *p, len, NULL, 0, NULL, 0,
- NULL, 0, NULL, 0)) != 0) {
- return MBEDTLS_ERR_PK_INVALID_PUBKEY;
- }
-
- *p += len;
-
- /* Import E */
- if ((ret = mbedtls_asn1_get_tag(p, end, &len, MBEDTLS_ASN1_INTEGER)) != 0) {
- return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_INVALID_PUBKEY, ret);
- }
-
- if ((ret = mbedtls_rsa_import_raw(rsa, NULL, 0, NULL, 0, NULL, 0,
- NULL, 0, *p, len)) != 0) {
- return MBEDTLS_ERR_PK_INVALID_PUBKEY;
- }
-
- *p += len;
-
- if (mbedtls_rsa_complete(rsa) != 0 ||
- mbedtls_rsa_check_pubkey(rsa) != 0) {
- return MBEDTLS_ERR_PK_INVALID_PUBKEY;
- }
-
- if (*p != end) {
- return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_INVALID_PUBKEY,
- MBEDTLS_ERR_ASN1_LENGTH_MISMATCH);
- }
-
- return 0;
-}
-#endif /* MBEDTLS_RSA_C */
+#endif /* MBEDTLS_PK_HAVE_ECC_KEYS */
/* Get a PK algorithm identifier
*
@@ -583,7 +470,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;
@@ -594,7 +482,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_PK_HAVE_ECC_KEYS)
+ 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;
}
@@ -622,6 +521,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,
@@ -631,7 +531,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;
}
@@ -654,17 +554,35 @@
#if defined(MBEDTLS_RSA_C)
if (pk_alg == MBEDTLS_PK_RSA) {
- ret = pk_get_rsapubkey(p, end, mbedtls_pk_rsa(*pk));
- } else
-#endif /* MBEDTLS_RSA_C */
-#if defined(MBEDTLS_ECP_C)
- if (pk_alg == MBEDTLS_PK_ECKEY_DH || pk_alg == MBEDTLS_PK_ECKEY) {
- ret = pk_use_ecparams(&alg_params, &mbedtls_pk_ec(*pk)->grp);
+ ret = mbedtls_rsa_parse_pubkey(mbedtls_pk_rsa(*pk), *p, (size_t) (end - *p));
if (ret == 0) {
- ret = pk_get_ecpubkey(p, end, mbedtls_pk_ec(*pk));
+ /* On success all the input has been consumed by the parsing function. */
+ *p += end - *p;
+ } else if ((ret <= MBEDTLS_ERR_ASN1_OUT_OF_DATA) &&
+ (ret >= MBEDTLS_ERR_ASN1_BUF_TOO_SMALL)) {
+ /* In case of ASN1 error codes add MBEDTLS_ERR_PK_INVALID_PUBKEY. */
+ ret = MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_INVALID_PUBKEY, ret);
+ } else {
+ ret = MBEDTLS_ERR_PK_INVALID_PUBKEY;
}
} else
-#endif /* MBEDTLS_ECP_C */
+#endif /* MBEDTLS_RSA_C */
+#if defined(MBEDTLS_PK_HAVE_ECC_KEYS)
+ if (pk_alg == MBEDTLS_PK_ECKEY_DH || pk_alg == MBEDTLS_PK_ECKEY) {
+#if defined(MBEDTLS_PK_HAVE_RFC8410_CURVES)
+ if (MBEDTLS_PK_IS_RFC8410_GROUP_ID(ec_grp_id)) {
+ ret = pk_use_ecparams_rfc8410(&alg_params, ec_grp_id, pk);
+ } else
+#endif
+ {
+ ret = pk_use_ecparams(&alg_params, pk);
+ }
+ if (ret == 0) {
+ ret = mbedtls_pk_ecc_set_pubkey(pk, *p, (size_t) (end - *p));
+ *p += end - *p;
+ }
+ } else
+#endif /* MBEDTLS_PK_HAVE_ECC_KEYS */
ret = MBEDTLS_ERR_PK_UNKNOWN_PK_ALG;
if (ret == 0 && *p != end) {
@@ -679,208 +597,20 @@
return ret;
}
-#if defined(MBEDTLS_RSA_C)
-/*
- * Wrapper around mbedtls_asn1_get_mpi() that rejects zero.
- *
- * The value zero is:
- * - never a valid value for an RSA parameter
- * - interpreted as "omitted, please reconstruct" by mbedtls_rsa_complete().
- *
- * Since values can't be omitted in PKCS#1, passing a zero value to
- * rsa_complete() would be incorrect, so reject zero values early.
- */
-static int asn1_get_nonzero_mpi(unsigned char **p,
- const unsigned char *end,
- mbedtls_mpi *X)
-{
- int ret;
-
- ret = mbedtls_asn1_get_mpi(p, end, X);
- if (ret != 0) {
- return ret;
- }
-
- if (mbedtls_mpi_cmp_int(X, 0) == 0) {
- return MBEDTLS_ERR_PK_KEY_INVALID_FORMAT;
- }
-
- return 0;
-}
-
-/*
- * Parse a PKCS#1 encoded private RSA key
- */
-static int pk_parse_key_pkcs1_der(mbedtls_rsa_context *rsa,
- const unsigned char *key,
- size_t keylen)
-{
- int ret, version;
- size_t len;
- unsigned char *p, *end;
-
- mbedtls_mpi T;
- mbedtls_mpi_init(&T);
-
- p = (unsigned char *) key;
- end = p + keylen;
-
- /*
- * This function parses the RSAPrivateKey (PKCS#1)
- *
- * RSAPrivateKey ::= SEQUENCE {
- * version Version,
- * modulus INTEGER, -- n
- * publicExponent INTEGER, -- e
- * privateExponent INTEGER, -- d
- * prime1 INTEGER, -- p
- * prime2 INTEGER, -- q
- * exponent1 INTEGER, -- d mod (p-1)
- * exponent2 INTEGER, -- d mod (q-1)
- * coefficient INTEGER, -- (inverse of q) mod p
- * otherPrimeInfos OtherPrimeInfos OPTIONAL
- * }
- */
- if ((ret = mbedtls_asn1_get_tag(&p, end, &len,
- MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)) != 0) {
- return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_KEY_INVALID_FORMAT, ret);
- }
-
- end = p + len;
-
- if ((ret = mbedtls_asn1_get_int(&p, end, &version)) != 0) {
- return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_KEY_INVALID_FORMAT, ret);
- }
-
- if (version != 0) {
- return MBEDTLS_ERR_PK_KEY_INVALID_VERSION;
- }
-
- /* Import N */
- if ((ret = asn1_get_nonzero_mpi(&p, end, &T)) != 0 ||
- (ret = mbedtls_rsa_import(rsa, &T, NULL, NULL,
- NULL, NULL)) != 0) {
- goto cleanup;
- }
-
- /* Import E */
- if ((ret = asn1_get_nonzero_mpi(&p, end, &T)) != 0 ||
- (ret = mbedtls_rsa_import(rsa, NULL, NULL, NULL,
- NULL, &T)) != 0) {
- goto cleanup;
- }
-
- /* Import D */
- if ((ret = asn1_get_nonzero_mpi(&p, end, &T)) != 0 ||
- (ret = mbedtls_rsa_import(rsa, NULL, NULL, NULL,
- &T, NULL)) != 0) {
- goto cleanup;
- }
-
- /* Import P */
- if ((ret = asn1_get_nonzero_mpi(&p, end, &T)) != 0 ||
- (ret = mbedtls_rsa_import(rsa, NULL, &T, NULL,
- NULL, NULL)) != 0) {
- goto cleanup;
- }
-
- /* Import Q */
- if ((ret = asn1_get_nonzero_mpi(&p, end, &T)) != 0 ||
- (ret = mbedtls_rsa_import(rsa, NULL, NULL, &T,
- NULL, NULL)) != 0) {
- goto cleanup;
- }
-
-#if !defined(MBEDTLS_RSA_NO_CRT) && !defined(MBEDTLS_RSA_ALT)
- /*
- * The RSA CRT parameters DP, DQ and QP are nominally redundant, in
- * that they can be easily recomputed from D, P and Q. However by
- * parsing them from the PKCS1 structure it is possible to avoid
- * recalculating them which both reduces the overhead of loading
- * RSA private keys into memory and also avoids side channels which
- * can arise when computing those values, since all of D, P, and Q
- * are secret. See https://eprint.iacr.org/2020/055 for a
- * description of one such attack.
- */
-
- /* Import DP */
- if ((ret = asn1_get_nonzero_mpi(&p, end, &T)) != 0 ||
- (ret = mbedtls_mpi_copy(&rsa->DP, &T)) != 0) {
- goto cleanup;
- }
-
- /* Import DQ */
- if ((ret = asn1_get_nonzero_mpi(&p, end, &T)) != 0 ||
- (ret = mbedtls_mpi_copy(&rsa->DQ, &T)) != 0) {
- goto cleanup;
- }
-
- /* Import QP */
- if ((ret = asn1_get_nonzero_mpi(&p, end, &T)) != 0 ||
- (ret = mbedtls_mpi_copy(&rsa->QP, &T)) != 0) {
- goto cleanup;
- }
-
-#else
- /* Verify existence of the CRT params */
- if ((ret = asn1_get_nonzero_mpi(&p, end, &T)) != 0 ||
- (ret = asn1_get_nonzero_mpi(&p, end, &T)) != 0 ||
- (ret = asn1_get_nonzero_mpi(&p, end, &T)) != 0) {
- goto cleanup;
- }
-#endif
-
- /* rsa_complete() doesn't complete anything with the default
- * implementation but is still called:
- * - for the benefit of alternative implementation that may want to
- * pre-compute stuff beyond what's provided (eg Montgomery factors)
- * - as is also sanity-checks the key
- *
- * Furthermore, we also check the public part for consistency with
- * mbedtls_pk_parse_pubkey(), as it includes size minima for example.
- */
- if ((ret = mbedtls_rsa_complete(rsa)) != 0 ||
- (ret = mbedtls_rsa_check_pubkey(rsa)) != 0) {
- goto cleanup;
- }
-
- if (p != end) {
- ret = MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_KEY_INVALID_FORMAT,
- MBEDTLS_ERR_ASN1_LENGTH_MISMATCH);
- }
-
-cleanup:
-
- mbedtls_mpi_free(&T);
-
- if (ret != 0) {
- /* Wrap error code if it's coming from a lower level */
- if ((ret & 0xff80) == 0) {
- ret = MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_KEY_INVALID_FORMAT, ret);
- } else {
- ret = MBEDTLS_ERR_PK_KEY_INVALID_FORMAT;
- }
-
- mbedtls_rsa_free(rsa);
- }
-
- return ret;
-}
-#endif /* MBEDTLS_RSA_C */
-
-#if defined(MBEDTLS_ECP_C)
+#if defined(MBEDTLS_PK_HAVE_ECC_KEYS)
/*
* Parse a SEC1 encoded private EC key
*/
-static int pk_parse_key_sec1_der(mbedtls_ecp_keypair *eck,
+static int pk_parse_key_sec1_der(mbedtls_pk_context *pk,
const unsigned char *key, size_t keylen,
int (*f_rng)(void *, unsigned char *, size_t), void *p_rng)
{
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;
@@ -913,10 +643,10 @@
return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_KEY_INVALID_FORMAT, ret);
}
- 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);
- }
+ /* Keep a reference to the position fo the private key. It will be used
+ * later in this function. */
+ d = p;
+ d_len = len;
p += len;
@@ -929,16 +659,22 @@
MBEDTLS_ASN1_CONTEXT_SPECIFIC | MBEDTLS_ASN1_CONSTRUCTED |
0)) == 0) {
if ((ret = pk_get_ecparams(&p, p + len, ¶ms)) != 0 ||
- (ret = pk_use_ecparams(¶ms, &eck->grp)) != 0) {
- mbedtls_ecp_keypair_free(eck);
+ (ret = pk_use_ecparams(¶ms, pk)) != 0) {
return ret;
}
} else if (ret != MBEDTLS_ERR_ASN1_UNEXPECTED_TAG) {
- mbedtls_ecp_keypair_free(eck);
return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_KEY_INVALID_FORMAT, ret);
}
}
+ /*
+ * Load the private key
+ */
+ ret = mbedtls_pk_ecc_set_key(pk, d, d_len);
+ if (ret != 0) {
+ return ret;
+ }
+
if (p != end) {
/*
* Is 'publickey' present? If not, or if we can't read it (eg because it
@@ -958,11 +694,11 @@
MBEDTLS_ERR_ASN1_LENGTH_MISMATCH);
}
- if ((ret = pk_get_ecpubkey(&p, end2, eck)) == 0) {
+ if ((ret = mbedtls_pk_ecc_set_pubkey(pk, p, (size_t) (end2 - p))) == 0) {
pubkey_done = 1;
} else {
/*
- * The only acceptable failure mode of pk_get_ecpubkey() above
+ * The only acceptable failure mode of mbedtls_pk_ecc_set_pubkey() above
* is if the point format is not recognized.
*/
if (ret != MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE) {
@@ -970,26 +706,25 @@
}
}
} else if (ret != MBEDTLS_ERR_ASN1_UNEXPECTED_TAG) {
- mbedtls_ecp_keypair_free(eck);
return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_KEY_INVALID_FORMAT, ret);
}
}
- if (!pubkey_done &&
- (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);
- }
-
- if ((ret = mbedtls_ecp_check_privkey(&eck->grp, &eck->d)) != 0) {
- mbedtls_ecp_keypair_free(eck);
- return ret;
+ if (!pubkey_done) {
+ if ((ret = mbedtls_pk_ecc_set_pubkey_from_prv(pk, d, d_len, f_rng, p_rng)) != 0) {
+ return ret;
+ }
}
return 0;
}
-#endif /* MBEDTLS_ECP_C */
+#endif /* MBEDTLS_PK_HAVE_ECC_KEYS */
+
+/***********************************************************************
+ *
+ * PKCS#8 parsing functions
+ *
+ **********************************************************************/
/*
* Parse an unencrypted PKCS#8 encoded private key
@@ -1015,9 +750,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_PK_HAVE_ECC_KEYS)
(void) f_rng;
(void) p_rng;
#endif
@@ -1053,7 +789,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;
}
@@ -1076,23 +812,43 @@
#if defined(MBEDTLS_RSA_C)
if (pk_alg == MBEDTLS_PK_RSA) {
- if ((ret = pk_parse_key_pkcs1_der(mbedtls_pk_rsa(*pk), p, len)) != 0) {
+ if ((ret = mbedtls_rsa_parse_key(mbedtls_pk_rsa(*pk), p, len)) != 0) {
mbedtls_pk_free(pk);
return ret;
}
} else
#endif /* MBEDTLS_RSA_C */
-#if defined(MBEDTLS_ECP_C)
+#if defined(MBEDTLS_PK_HAVE_ECC_KEYS)
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_GROUP_ID(ec_grp_id)) {
+ if ((ret =
+ pk_use_ecparams_rfc8410(¶ms, ec_grp_id, pk)) != 0 ||
+ (ret =
+ pk_parse_key_rfc8410_der(pk, p, len, end, f_rng,
+ p_rng)) != 0) {
+ mbedtls_pk_free(pk);
+ return ret;
+ }
+ } else
+#endif
+ {
+ if ((ret = pk_use_ecparams(¶ms, pk)) != 0 ||
+ (ret = pk_parse_key_sec1_der(pk, p, len, f_rng, p_rng)) != 0) {
+ mbedtls_pk_free(pk);
+ return ret;
+ }
}
} else
-#endif /* MBEDTLS_ECP_C */
+#endif /* MBEDTLS_PK_HAVE_ECC_KEYS */
return MBEDTLS_ERR_PK_UNKNOWN_PK_ALG;
+ end = p + len;
+ if (end != (key + keylen)) {
+ return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_KEY_INVALID_FORMAT,
+ MBEDTLS_ERR_ASN1_LENGTH_MISMATCH);
+ }
+
return 0;
}
@@ -1106,7 +862,7 @@
*
*/
#if defined(MBEDTLS_PKCS12_C) || defined(MBEDTLS_PKCS5_C)
-static int pk_parse_key_pkcs8_encrypted_der(
+MBEDTLS_STATIC_TESTABLE int mbedtls_pk_parse_key_pkcs8_encrypted_der(
mbedtls_pk_context *pk,
unsigned char *key, size_t keylen,
const unsigned char *pwd, size_t pwdlen,
@@ -1117,10 +873,11 @@
unsigned char *buf;
unsigned char *p, *end;
mbedtls_asn1_buf pbe_alg_oid, pbe_params;
-#if defined(MBEDTLS_PKCS12_C)
+#if defined(MBEDTLS_PKCS12_C) && defined(MBEDTLS_CIPHER_PADDING_PKCS7) && defined(MBEDTLS_CIPHER_C)
mbedtls_cipher_type_t cipher_alg;
mbedtls_md_type_t md_alg;
#endif
+ size_t outlen = 0;
p = key;
end = p + keylen;
@@ -1164,11 +921,11 @@
/*
* Decrypt EncryptedData with appropriate PBE
*/
-#if defined(MBEDTLS_PKCS12_C)
+#if defined(MBEDTLS_PKCS12_C) && defined(MBEDTLS_CIPHER_PADDING_PKCS7) && defined(MBEDTLS_CIPHER_C)
if (mbedtls_oid_get_pkcs12_pbe_alg(&pbe_alg_oid, &md_alg, &cipher_alg) == 0) {
- if ((ret = mbedtls_pkcs12_pbe(&pbe_params, MBEDTLS_PKCS12_PBE_DECRYPT,
- cipher_alg, md_alg,
- pwd, pwdlen, p, len, buf)) != 0) {
+ if ((ret = mbedtls_pkcs12_pbe_ext(&pbe_params, MBEDTLS_PKCS12_PBE_DECRYPT,
+ cipher_alg, md_alg,
+ pwd, pwdlen, p, len, buf, len, &outlen)) != 0) {
if (ret == MBEDTLS_ERR_PKCS12_PASSWORD_MISMATCH) {
return MBEDTLS_ERR_PK_PASSWORD_MISMATCH;
}
@@ -1178,11 +935,11 @@
decrypted = 1;
} else
-#endif /* MBEDTLS_PKCS12_C */
-#if defined(MBEDTLS_PKCS5_C)
+#endif /* MBEDTLS_PKCS12_C && MBEDTLS_CIPHER_PADDING_PKCS7 && MBEDTLS_CIPHER_C */
+#if defined(MBEDTLS_PKCS5_C) && defined(MBEDTLS_CIPHER_PADDING_PKCS7) && defined(MBEDTLS_CIPHER_C)
if (MBEDTLS_OID_CMP(MBEDTLS_OID_PKCS5_PBES2, &pbe_alg_oid) == 0) {
- if ((ret = mbedtls_pkcs5_pbes2(&pbe_params, MBEDTLS_PKCS5_DECRYPT, pwd, pwdlen,
- p, len, buf)) != 0) {
+ if ((ret = mbedtls_pkcs5_pbes2_ext(&pbe_params, MBEDTLS_PKCS5_DECRYPT, pwd, pwdlen,
+ p, len, buf, len, &outlen)) != 0) {
if (ret == MBEDTLS_ERR_PKCS5_PASSWORD_MISMATCH) {
return MBEDTLS_ERR_PK_PASSWORD_MISMATCH;
}
@@ -1192,7 +949,7 @@
decrypted = 1;
} else
-#endif /* MBEDTLS_PKCS5_C */
+#endif /* MBEDTLS_PKCS5_C && MBEDTLS_CIPHER_PADDING_PKCS7 && MBEDTLS_CIPHER_C */
{
((void) pwd);
}
@@ -1200,11 +957,16 @@
if (decrypted == 0) {
return MBEDTLS_ERR_PK_FEATURE_UNAVAILABLE;
}
-
- return pk_parse_key_pkcs8_unencrypted_der(pk, buf, len, f_rng, p_rng);
+ return pk_parse_key_pkcs8_unencrypted_der(pk, buf, outlen, f_rng, p_rng);
}
#endif /* MBEDTLS_PKCS12_C || MBEDTLS_PKCS5_C */
+/***********************************************************************
+ *
+ * Top-level functions, with format auto-discovery
+ *
+ **********************************************************************/
+
/*
* Parse a private key
*/
@@ -1233,16 +995,15 @@
ret = MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT;
} else {
ret = mbedtls_pem_read_buffer(&pem,
- "-----BEGIN RSA PRIVATE KEY-----",
- "-----END RSA PRIVATE KEY-----",
+ PEM_BEGIN_PRIVATE_KEY_RSA, PEM_END_PRIVATE_KEY_RSA,
key, pwd, pwdlen, &len);
}
if (ret == 0) {
pk_info = mbedtls_pk_info_from_type(MBEDTLS_PK_RSA);
if ((ret = mbedtls_pk_setup(pk, pk_info)) != 0 ||
- (ret = pk_parse_key_pkcs1_der(mbedtls_pk_rsa(*pk),
- pem.buf, pem.buflen)) != 0) {
+ (ret = mbedtls_rsa_parse_key(mbedtls_pk_rsa(*pk),
+ pem.buf, pem.buflen)) != 0) {
mbedtls_pk_free(pk);
}
@@ -1257,21 +1018,21 @@
}
#endif /* MBEDTLS_RSA_C */
-#if defined(MBEDTLS_ECP_C)
+#if defined(MBEDTLS_PK_HAVE_ECC_KEYS)
/* Avoid calling mbedtls_pem_read_buffer() on non-null-terminated string */
if (key[keylen - 1] != '\0') {
ret = MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT;
} else {
ret = mbedtls_pem_read_buffer(&pem,
- "-----BEGIN EC PRIVATE KEY-----",
- "-----END EC PRIVATE KEY-----",
+ PEM_BEGIN_PRIVATE_KEY_EC,
+ PEM_END_PRIVATE_KEY_EC,
key, pwd, pwdlen, &len);
}
if (ret == 0) {
pk_info = mbedtls_pk_info_from_type(MBEDTLS_PK_ECKEY);
if ((ret = mbedtls_pk_setup(pk, pk_info)) != 0 ||
- (ret = pk_parse_key_sec1_der(mbedtls_pk_ec(*pk),
+ (ret = pk_parse_key_sec1_der(pk,
pem.buf, pem.buflen,
f_rng, p_rng)) != 0) {
mbedtls_pk_free(pk);
@@ -1286,15 +1047,14 @@
} else if (ret != MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT) {
return ret;
}
-#endif /* MBEDTLS_ECP_C */
+#endif /* MBEDTLS_PK_HAVE_ECC_KEYS */
/* Avoid calling mbedtls_pem_read_buffer() on non-null-terminated string */
if (key[keylen - 1] != '\0') {
ret = MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT;
} else {
ret = mbedtls_pem_read_buffer(&pem,
- "-----BEGIN PRIVATE KEY-----",
- "-----END PRIVATE KEY-----",
+ PEM_BEGIN_PRIVATE_KEY_PKCS8, PEM_END_PRIVATE_KEY_PKCS8,
key, NULL, 0, &len);
}
if (ret == 0) {
@@ -1315,13 +1075,13 @@
ret = MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT;
} else {
ret = mbedtls_pem_read_buffer(&pem,
- "-----BEGIN ENCRYPTED PRIVATE KEY-----",
- "-----END ENCRYPTED PRIVATE KEY-----",
+ PEM_BEGIN_ENCRYPTED_PRIVATE_KEY_PKCS8,
+ PEM_END_ENCRYPTED_PRIVATE_KEY_PKCS8,
key, NULL, 0, &len);
}
if (ret == 0) {
- if ((ret = pk_parse_key_pkcs8_encrypted_der(pk, pem.buf, pem.buflen,
- pwd, pwdlen, f_rng, p_rng)) != 0) {
+ if ((ret = mbedtls_pk_parse_key_pkcs8_encrypted_der(pk, pem.buf, pem.buflen,
+ pwd, pwdlen, f_rng, p_rng)) != 0) {
mbedtls_pk_free(pk);
}
@@ -1353,11 +1113,10 @@
memcpy(key_copy, key, keylen);
- ret = pk_parse_key_pkcs8_encrypted_der(pk, key_copy, keylen,
- pwd, pwdlen, f_rng, p_rng);
+ ret = mbedtls_pk_parse_key_pkcs8_encrypted_der(pk, key_copy, keylen,
+ pwd, pwdlen, f_rng, p_rng);
- mbedtls_platform_zeroize(key_copy, keylen);
- mbedtls_free(key_copy);
+ mbedtls_zeroize_and_free(key_copy, keylen);
}
if (ret == 0) {
@@ -1384,7 +1143,7 @@
pk_info = mbedtls_pk_info_from_type(MBEDTLS_PK_RSA);
if (mbedtls_pk_setup(pk, pk_info) == 0 &&
- pk_parse_key_pkcs1_der(mbedtls_pk_rsa(*pk), key, keylen) == 0) {
+ mbedtls_rsa_parse_key(mbedtls_pk_rsa(*pk), key, keylen) == 0) {
return 0;
}
@@ -1392,21 +1151,21 @@
mbedtls_pk_init(pk);
#endif /* MBEDTLS_RSA_C */
-#if defined(MBEDTLS_ECP_C)
+#if defined(MBEDTLS_PK_HAVE_ECC_KEYS)
pk_info = mbedtls_pk_info_from_type(MBEDTLS_PK_ECKEY);
if (mbedtls_pk_setup(pk, pk_info) == 0 &&
- pk_parse_key_sec1_der(mbedtls_pk_ec(*pk),
+ pk_parse_key_sec1_der(pk,
key, keylen, f_rng, p_rng) == 0) {
return 0;
}
mbedtls_pk_free(pk);
-#endif /* MBEDTLS_ECP_C */
+#endif /* MBEDTLS_PK_HAVE_ECC_KEYS */
- /* If MBEDTLS_RSA_C is defined but MBEDTLS_ECP_C isn't,
+ /* If MBEDTLS_RSA_C is defined but MBEDTLS_PK_HAVE_ECC_KEYS isn't,
* it is ok to leave the PK context initialized but not
* freed: It is the caller's responsibility to call pk_init()
* before calling this function, and to call pk_free()
- * when it fails. If MBEDTLS_ECP_C is defined but MBEDTLS_RSA_C
+ * when it fails. If MBEDTLS_PK_HAVE_ECC_KEYS is defined but MBEDTLS_RSA_C
* isn't, this leads to mbedtls_pk_free() being called
* twice, once here and once by the caller, but this is
* also ok and in line with the mbedtls_pk_free() calls
@@ -1443,8 +1202,7 @@
ret = MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT;
} else {
ret = mbedtls_pem_read_buffer(&pem,
- "-----BEGIN RSA PUBLIC KEY-----",
- "-----END RSA PUBLIC KEY-----",
+ PEM_BEGIN_PUBLIC_KEY_RSA, PEM_END_PUBLIC_KEY_RSA,
key, NULL, 0, &len);
}
@@ -1460,7 +1218,7 @@
return ret;
}
- if ((ret = pk_get_rsapubkey(&p, p + pem.buflen, mbedtls_pk_rsa(*ctx))) != 0) {
+ if ((ret = mbedtls_rsa_parse_pubkey(mbedtls_pk_rsa(*ctx), p, pem.buflen)) != 0) {
mbedtls_pk_free(ctx);
}
@@ -1477,8 +1235,7 @@
ret = MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT;
} else {
ret = mbedtls_pem_read_buffer(&pem,
- "-----BEGIN PUBLIC KEY-----",
- "-----END PUBLIC KEY-----",
+ PEM_BEGIN_PUBLIC_KEY, PEM_END_PUBLIC_KEY,
key, NULL, 0, &len);
}
@@ -1488,7 +1245,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) {
@@ -1508,13 +1265,12 @@
}
p = (unsigned char *) key;
- ret = pk_get_rsapubkey(&p, p + keylen, mbedtls_pk_rsa(*ctx));
+ ret = mbedtls_rsa_parse_pubkey(mbedtls_pk_rsa(*ctx), p, keylen);
if (ret == 0) {
return ret;
}
mbedtls_pk_free(ctx);
- if (ret != (MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_INVALID_PUBKEY,
- MBEDTLS_ERR_ASN1_UNEXPECTED_TAG))) {
+ if (ret != MBEDTLS_ERR_ASN1_UNEXPECTED_TAG) {
return ret;
}
#endif /* MBEDTLS_RSA_C */
@@ -1525,4 +1281,112 @@
return ret;
}
+/***********************************************************************
+ *
+ * Top-level functions, with filesystem support
+ *
+ **********************************************************************/
+
+#if defined(MBEDTLS_FS_IO)
+/*
+ * Load all data from a file into a given buffer.
+ *
+ * The file is expected to contain either PEM or DER encoded data.
+ * A terminating null byte is always appended. It is included in the announced
+ * length only if the data looks like it is PEM encoded.
+ */
+int mbedtls_pk_load_file(const char *path, unsigned char **buf, size_t *n)
+{
+ FILE *f;
+ long size;
+
+ if ((f = fopen(path, "rb")) == NULL) {
+ return MBEDTLS_ERR_PK_FILE_IO_ERROR;
+ }
+
+ /* Ensure no stdio buffering of secrets, as such buffers cannot be wiped. */
+ mbedtls_setbuf(f, NULL);
+
+ fseek(f, 0, SEEK_END);
+ if ((size = ftell(f)) == -1) {
+ fclose(f);
+ return MBEDTLS_ERR_PK_FILE_IO_ERROR;
+ }
+ fseek(f, 0, SEEK_SET);
+
+ *n = (size_t) size;
+
+ if (*n + 1 == 0 ||
+ (*buf = mbedtls_calloc(1, *n + 1)) == NULL) {
+ fclose(f);
+ return MBEDTLS_ERR_PK_ALLOC_FAILED;
+ }
+
+ if (fread(*buf, 1, *n, f) != *n) {
+ fclose(f);
+
+ mbedtls_zeroize_and_free(*buf, *n);
+
+ return MBEDTLS_ERR_PK_FILE_IO_ERROR;
+ }
+
+ fclose(f);
+
+ (*buf)[*n] = '\0';
+
+ if (strstr((const char *) *buf, "-----BEGIN ") != NULL) {
+ ++*n;
+ }
+
+ return 0;
+}
+
+/*
+ * Load and parse a private key
+ */
+int mbedtls_pk_parse_keyfile(mbedtls_pk_context *ctx,
+ const char *path, const char *pwd,
+ int (*f_rng)(void *, unsigned char *, size_t), void *p_rng)
+{
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
+ size_t n;
+ unsigned char *buf;
+
+ if ((ret = mbedtls_pk_load_file(path, &buf, &n)) != 0) {
+ return ret;
+ }
+
+ if (pwd == NULL) {
+ ret = mbedtls_pk_parse_key(ctx, buf, n, NULL, 0, f_rng, p_rng);
+ } else {
+ ret = mbedtls_pk_parse_key(ctx, buf, n,
+ (const unsigned char *) pwd, strlen(pwd), f_rng, p_rng);
+ }
+
+ mbedtls_zeroize_and_free(buf, n);
+
+ return ret;
+}
+
+/*
+ * Load and parse a public key
+ */
+int mbedtls_pk_parse_public_keyfile(mbedtls_pk_context *ctx, const char *path)
+{
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
+ size_t n;
+ unsigned char *buf;
+
+ if ((ret = mbedtls_pk_load_file(path, &buf, &n)) != 0) {
+ return ret;
+ }
+
+ ret = mbedtls_pk_parse_public_key(ctx, buf, n);
+
+ mbedtls_zeroize_and_free(buf, n);
+
+ return ret;
+}
+#endif /* MBEDTLS_FS_IO */
+
#endif /* MBEDTLS_PK_PARSE_C */