/* * Public Key layer for parsing key files and structures * * Copyright The Mbed TLS Contributors * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ #include "common.h" #if defined(MBEDTLS_PK_PARSE_C) #include "mbedtls/pk.h" #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 /* Extended formats */ #if defined(MBEDTLS_PEM_PARSE_C) #include "mbedtls/pem.h" #endif #if defined(MBEDTLS_PKCS5_C) #include "mbedtls/pkcs5.h" #endif #if defined(MBEDTLS_PKCS12_C) #include "mbedtls/pkcs12.h" #endif #if defined(MBEDTLS_PK_HAVE_ECC_KEYS) /*********************************************************************** * * 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) { (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 */ /* * Tell if the passed tag might be the start of SpecifiedECDomain * (that is, a sequence). */ static int pk_ecc_tag_is_specified_ec_domain(int tag) { … } /* * Parse a SpecifiedECDomain (SEC 1 C.2) and (mostly) fill the group with it. * WARNING: the resulting group should only be used with * pk_ecc_group_id_from_specified(), since its base point may not be set correctly * if it was encoded compressed. * * SpecifiedECDomain ::= SEQUENCE { * version SpecifiedECDomainVersion(ecdpVer1 | ecdpVer2 | ecdpVer3, ...), * fieldID FieldID {{FieldTypes}}, * curve Curve, * base ECPoint, * order INTEGER, * cofactor INTEGER OPTIONAL, * hash HashAlgorithm OPTIONAL, * ... * } * * We only support prime-field as field type, and ignore hash and cofactor. */ static int pk_group_from_specified(const mbedtls_asn1_buf *params, mbedtls_ecp_group *grp) { … } /* * Find the group id associated with an (almost filled) group as generated by * pk_group_from_specified(), or return an error if unknown. */ static int pk_group_id_from_group(const mbedtls_ecp_group *grp, mbedtls_ecp_group_id *grp_id) { … } /* * Parse a SpecifiedECDomain (SEC 1 C.2) and find the associated group ID */ static int pk_ecc_group_id_from_specified(const mbedtls_asn1_buf *params, mbedtls_ecp_group_id *grp_id) { … } #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) { … } /* * Use EC parameters to initialise an EC group * * ECParameters ::= CHOICE { * namedCurve OBJECT IDENTIFIER * specifiedCurve SpecifiedECDomain -- = SEQUENCE { ... } * -- implicitCurve NULL */ static int pk_use_ecparams(const mbedtls_asn1_buf *params, mbedtls_pk_context *pk) { … } #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) { … } /* * 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) { … } #endif /* MBEDTLS_PK_HAVE_RFC8410_CURVES */ #endif /* MBEDTLS_PK_HAVE_ECC_KEYS */ /* Get a PK algorithm identifier * * AlgorithmIdentifier ::= SEQUENCE { * algorithm OBJECT IDENTIFIER, * parameters ANY DEFINED BY algorithm OPTIONAL } */ static int pk_get_pk_alg(unsigned char **p, const unsigned char *end, mbedtls_pk_type_t *pk_alg, mbedtls_asn1_buf *params, mbedtls_ecp_group_id *ec_grp_id) { … } /* * SubjectPublicKeyInfo ::= SEQUENCE { * algorithm AlgorithmIdentifier, * subjectPublicKey BIT STRING } */ int mbedtls_pk_parse_subpubkey(unsigned char **p, const unsigned char *end, mbedtls_pk_context *pk) { … } #if defined(MBEDTLS_PK_HAVE_ECC_KEYS) /* * Parse a SEC1 encoded private EC key */ 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) { … } #endif /* MBEDTLS_PK_HAVE_ECC_KEYS */ /*********************************************************************** * * PKCS#8 parsing functions * **********************************************************************/ /* * Parse an unencrypted PKCS#8 encoded private key * * Notes: * * - This function does not own the key buffer. It is the * responsibility of the caller to take care of zeroizing * and freeing it after use. * * - The function is responsible for freeing the provided * PK context on failure. * */ static int pk_parse_key_pkcs8_unencrypted_der( mbedtls_pk_context *pk, const unsigned char *key, size_t keylen, int (*f_rng)(void *, unsigned char *, size_t), void *p_rng) { … } /* * Parse an encrypted PKCS#8 encoded private key * * To save space, the decryption happens in-place on the given key buffer. * Also, while this function may modify the keybuffer, it doesn't own it, * and instead it is the responsibility of the caller to zeroize and properly * free it after use. * */ #if defined(MBEDTLS_PKCS12_C) || defined(MBEDTLS_PKCS5_C) 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, int (*f_rng)(void *, unsigned char *, size_t), void *p_rng) { … } #endif /* MBEDTLS_PKCS12_C || MBEDTLS_PKCS5_C */ /*********************************************************************** * * Top-level functions, with format auto-discovery * **********************************************************************/ /* * Parse a private key */ int mbedtls_pk_parse_key(mbedtls_pk_context *pk, const unsigned char *key, size_t keylen, const unsigned char *pwd, size_t pwdlen, int (*f_rng)(void *, unsigned char *, size_t), void *p_rng) { … } /* * Parse a public key */ int mbedtls_pk_parse_public_key(mbedtls_pk_context *ctx, const unsigned char *key, size_t keylen) { … } /*********************************************************************** * * 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) { … } /* * 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) { … } /* * Load and parse a public key */ int mbedtls_pk_parse_public_keyfile(mbedtls_pk_context *ctx, const char *path) { … } #endif /* MBEDTLS_FS_IO */ #endif /* MBEDTLS_PK_PARSE_C */