#include "common.h"
#if defined(MBEDTLS_PK_C)
#include "mbedtls/pk.h"
#include "pk_wrap.h"
#include "pkwrite.h"
#include "pk_internal.h"
#include "mbedtls/platform_util.h"
#include "mbedtls/error.h"
#if defined(MBEDTLS_RSA_C)
#include "mbedtls/rsa.h"
#include "rsa_internal.h"
#endif
#if defined(MBEDTLS_PK_HAVE_ECC_KEYS)
#include "mbedtls/ecp.h"
#endif
#if defined(MBEDTLS_ECDSA_C)
#include "mbedtls/ecdsa.h"
#endif
#if defined(MBEDTLS_PSA_CRYPTO_CLIENT)
#include "psa_util_internal.h"
#include "mbedtls/psa_util.h"
#endif
#include <limits.h>
#include <stdint.h>
#define PSA_EXPORT_KEY_PAIR_OR_PUBLIC_MAX_SIZE …
void mbedtls_pk_init(mbedtls_pk_context *ctx)
{ … }
void mbedtls_pk_free(mbedtls_pk_context *ctx)
{ … }
#if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE)
void mbedtls_pk_restart_init(mbedtls_pk_restart_ctx *ctx)
{
ctx->pk_info = NULL;
ctx->rs_ctx = NULL;
}
void mbedtls_pk_restart_free(mbedtls_pk_restart_ctx *ctx)
{
if (ctx == NULL || ctx->pk_info == NULL ||
ctx->pk_info->rs_free_func == NULL) {
return;
}
ctx->pk_info->rs_free_func(ctx->rs_ctx);
ctx->pk_info = NULL;
ctx->rs_ctx = NULL;
}
#endif
const mbedtls_pk_info_t *mbedtls_pk_info_from_type(mbedtls_pk_type_t pk_type)
{ … }
int mbedtls_pk_setup(mbedtls_pk_context *ctx, const mbedtls_pk_info_t *info)
{ … }
#if defined(MBEDTLS_USE_PSA_CRYPTO)
int mbedtls_pk_setup_opaque(mbedtls_pk_context *ctx,
const mbedtls_svc_key_id_t key)
{
const mbedtls_pk_info_t *info = NULL;
psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
psa_key_type_t type;
if (ctx == NULL || ctx->pk_info != NULL) {
return MBEDTLS_ERR_PK_BAD_INPUT_DATA;
}
if (PSA_SUCCESS != psa_get_key_attributes(key, &attributes)) {
return MBEDTLS_ERR_PK_BAD_INPUT_DATA;
}
type = psa_get_key_type(&attributes);
psa_reset_key_attributes(&attributes);
#if defined(MBEDTLS_PK_HAVE_ECC_KEYS)
if (PSA_KEY_TYPE_IS_ECC_KEY_PAIR(type)) {
info = &mbedtls_ecdsa_opaque_info;
} else
#endif
if (type == PSA_KEY_TYPE_RSA_KEY_PAIR) {
info = &mbedtls_rsa_opaque_info;
} else {
return MBEDTLS_ERR_PK_FEATURE_UNAVAILABLE;
}
ctx->pk_info = info;
ctx->priv_id = key;
return 0;
}
#endif
#if defined(MBEDTLS_PK_RSA_ALT_SUPPORT)
int mbedtls_pk_setup_rsa_alt(mbedtls_pk_context *ctx, void *key,
mbedtls_pk_rsa_alt_decrypt_func decrypt_func,
mbedtls_pk_rsa_alt_sign_func sign_func,
mbedtls_pk_rsa_alt_key_len_func key_len_func)
{ … }
#endif
int mbedtls_pk_can_do(const mbedtls_pk_context *ctx, mbedtls_pk_type_t type)
{ … }
#if defined(MBEDTLS_USE_PSA_CRYPTO)
int mbedtls_pk_can_do_ext(const mbedtls_pk_context *ctx, psa_algorithm_t alg,
psa_key_usage_t usage)
{
psa_key_usage_t key_usage;
if (ctx == NULL || ctx->pk_info == NULL) {
return 0;
}
if (PSA_ALG_IS_ECDSA(alg) == 0 &&
PSA_ALG_IS_RSA_PKCS1V15_SIGN(alg) == 0 &&
PSA_ALG_IS_RSA_PSS(alg) == 0 &&
alg != PSA_ALG_RSA_PKCS1V15_CRYPT &&
PSA_ALG_IS_ECDH(alg) == 0) {
return 0;
}
if (usage == 0 ||
(usage & ~(PSA_KEY_USAGE_SIGN_HASH |
PSA_KEY_USAGE_DECRYPT |
PSA_KEY_USAGE_DERIVE)) != 0) {
return 0;
}
if (PSA_ALG_IS_SIGN_HASH(alg) &&
PSA_ALG_SIGN_GET_HASH(alg) == PSA_ALG_ANY_HASH) {
return 0;
}
if (mbedtls_pk_get_type(ctx) != MBEDTLS_PK_OPAQUE) {
mbedtls_pk_type_t type;
if (PSA_ALG_IS_ECDSA(alg) || PSA_ALG_IS_ECDH(alg)) {
type = MBEDTLS_PK_ECKEY;
} else if (PSA_ALG_IS_RSA_PKCS1V15_SIGN(alg) ||
alg == PSA_ALG_RSA_PKCS1V15_CRYPT) {
type = MBEDTLS_PK_RSA;
} else if (PSA_ALG_IS_RSA_PSS(alg)) {
type = MBEDTLS_PK_RSASSA_PSS;
} else {
return 0;
}
if (ctx->pk_info->can_do(type) == 0) {
return 0;
}
switch (type) {
case MBEDTLS_PK_ECKEY:
key_usage = PSA_KEY_USAGE_SIGN_HASH | PSA_KEY_USAGE_DERIVE;
break;
case MBEDTLS_PK_RSA:
case MBEDTLS_PK_RSASSA_PSS:
key_usage = PSA_KEY_USAGE_SIGN_HASH |
PSA_KEY_USAGE_SIGN_MESSAGE |
PSA_KEY_USAGE_DECRYPT;
break;
default:
return 0;
}
return (key_usage & usage) == usage;
}
psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
psa_status_t status;
status = psa_get_key_attributes(ctx->priv_id, &attributes);
if (status != PSA_SUCCESS) {
return 0;
}
psa_algorithm_t key_alg = psa_get_key_algorithm(&attributes);
#if defined(MBEDTLS_PSA_CRYPTO_C)
psa_algorithm_t key_alg2 = psa_get_key_enrollment_algorithm(&attributes);
#endif
key_usage = psa_get_key_usage_flags(&attributes);
psa_reset_key_attributes(&attributes);
if ((key_usage & usage) != usage) {
return 0;
}
if (alg == key_alg) {
return 1;
}
#if defined(MBEDTLS_PSA_CRYPTO_C)
if (alg == key_alg2) {
return 1;
}
#endif
if (PSA_ALG_IS_SIGN_HASH(alg)) {
if (PSA_ALG_IS_SIGN_HASH(key_alg) &&
PSA_ALG_SIGN_GET_HASH(key_alg) == PSA_ALG_ANY_HASH &&
(alg & ~PSA_ALG_HASH_MASK) == (key_alg & ~PSA_ALG_HASH_MASK)) {
return 1;
}
#if defined(MBEDTLS_PSA_CRYPTO_C)
if (PSA_ALG_IS_SIGN_HASH(key_alg2) &&
PSA_ALG_SIGN_GET_HASH(key_alg2) == PSA_ALG_ANY_HASH &&
(alg & ~PSA_ALG_HASH_MASK) == (key_alg2 & ~PSA_ALG_HASH_MASK)) {
return 1;
}
#endif
}
return 0;
}
#endif
#if defined(MBEDTLS_PSA_CRYPTO_CLIENT)
#if defined(MBEDTLS_RSA_C)
static psa_algorithm_t psa_algorithm_for_rsa(const mbedtls_rsa_context *rsa,
int want_crypt)
{ … }
#endif
int mbedtls_pk_get_psa_attributes(const mbedtls_pk_context *pk,
psa_key_usage_t usage,
psa_key_attributes_t *attributes)
{ … }
#if defined(MBEDTLS_PK_USE_PSA_EC_DATA) || defined(MBEDTLS_USE_PSA_CRYPTO)
static psa_status_t export_import_into_psa(mbedtls_svc_key_id_t old_key_id,
const psa_key_attributes_t *attributes,
mbedtls_svc_key_id_t *new_key_id)
{
unsigned char key_buffer[PSA_EXPORT_KEY_PAIR_MAX_SIZE];
size_t key_length = 0;
psa_status_t status = psa_export_key(old_key_id,
key_buffer, sizeof(key_buffer),
&key_length);
if (status != PSA_SUCCESS) {
return status;
}
status = psa_import_key(attributes, key_buffer, key_length, new_key_id);
mbedtls_platform_zeroize(key_buffer, key_length);
return status;
}
static int copy_into_psa(mbedtls_svc_key_id_t old_key_id,
const psa_key_attributes_t *attributes,
mbedtls_svc_key_id_t *new_key_id)
{
psa_status_t status = psa_copy_key(old_key_id, attributes, new_key_id);
if (status == PSA_ERROR_NOT_PERMITTED ||
status == PSA_ERROR_INVALID_ARGUMENT ) {
psa_key_attributes_t old_attributes = PSA_KEY_ATTRIBUTES_INIT;
status = psa_get_key_attributes(old_key_id, &old_attributes);
if (status != PSA_SUCCESS) {
return MBEDTLS_ERR_PK_BAD_INPUT_DATA;
}
psa_key_type_t old_type = psa_get_key_type(&old_attributes);
psa_reset_key_attributes(&old_attributes);
if (old_type != psa_get_key_type(attributes)) {
return MBEDTLS_ERR_PK_TYPE_MISMATCH;
}
status = export_import_into_psa(old_key_id, attributes, new_key_id);
}
return PSA_PK_TO_MBEDTLS_ERR(status);
}
#endif
static int import_pair_into_psa(const mbedtls_pk_context *pk,
const psa_key_attributes_t *attributes,
mbedtls_svc_key_id_t *key_id)
{ … }
static int import_public_into_psa(const mbedtls_pk_context *pk,
const psa_key_attributes_t *attributes,
mbedtls_svc_key_id_t *key_id)
{ … }
int mbedtls_pk_import_into_psa(const mbedtls_pk_context *pk,
const psa_key_attributes_t *attributes,
mbedtls_svc_key_id_t *key_id)
{ … }
static int copy_from_psa(mbedtls_svc_key_id_t key_id,
mbedtls_pk_context *pk,
int public_only)
{ … }
int mbedtls_pk_copy_from_psa(mbedtls_svc_key_id_t key_id,
mbedtls_pk_context *pk)
{ … }
int mbedtls_pk_copy_public_from_psa(mbedtls_svc_key_id_t key_id,
mbedtls_pk_context *pk)
{ … }
#endif
static inline int pk_hashlen_helper(mbedtls_md_type_t md_alg, size_t *hash_len)
{ … }
#if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE)
static int pk_restart_setup(mbedtls_pk_restart_ctx *ctx,
const mbedtls_pk_info_t *info)
{
if (ctx == NULL || ctx->pk_info != NULL) {
return 0;
}
if (info->rs_alloc_func == NULL || info->rs_free_func == NULL) {
return MBEDTLS_ERR_PK_BAD_INPUT_DATA;
}
if ((ctx->rs_ctx = info->rs_alloc_func()) == NULL) {
return MBEDTLS_ERR_PK_ALLOC_FAILED;
}
ctx->pk_info = info;
return 0;
}
#endif
int mbedtls_pk_verify_restartable(mbedtls_pk_context *ctx,
mbedtls_md_type_t md_alg,
const unsigned char *hash, size_t hash_len,
const unsigned char *sig, size_t sig_len,
mbedtls_pk_restart_ctx *rs_ctx)
{ … }
int mbedtls_pk_verify(mbedtls_pk_context *ctx, mbedtls_md_type_t md_alg,
const unsigned char *hash, size_t hash_len,
const unsigned char *sig, size_t sig_len)
{ … }
int mbedtls_pk_verify_ext(mbedtls_pk_type_t type, const void *options,
mbedtls_pk_context *ctx, mbedtls_md_type_t md_alg,
const unsigned char *hash, size_t hash_len,
const unsigned char *sig, size_t sig_len)
{ … }
int mbedtls_pk_sign_restartable(mbedtls_pk_context *ctx,
mbedtls_md_type_t md_alg,
const unsigned char *hash, size_t hash_len,
unsigned char *sig, size_t sig_size, size_t *sig_len,
int (*f_rng)(void *, unsigned char *, size_t), void *p_rng,
mbedtls_pk_restart_ctx *rs_ctx)
{ … }
int mbedtls_pk_sign(mbedtls_pk_context *ctx, mbedtls_md_type_t md_alg,
const unsigned char *hash, size_t hash_len,
unsigned char *sig, size_t sig_size, size_t *sig_len,
int (*f_rng)(void *, unsigned char *, size_t), void *p_rng)
{ … }
int mbedtls_pk_sign_ext(mbedtls_pk_type_t pk_type,
mbedtls_pk_context *ctx,
mbedtls_md_type_t md_alg,
const unsigned char *hash, size_t hash_len,
unsigned char *sig, size_t sig_size, size_t *sig_len,
int (*f_rng)(void *, unsigned char *, size_t),
void *p_rng)
{ … }
int mbedtls_pk_decrypt(mbedtls_pk_context *ctx,
const unsigned char *input, size_t ilen,
unsigned char *output, size_t *olen, size_t osize,
int (*f_rng)(void *, unsigned char *, size_t), void *p_rng)
{ … }
int mbedtls_pk_encrypt(mbedtls_pk_context *ctx,
const unsigned char *input, size_t ilen,
unsigned char *output, size_t *olen, size_t osize,
int (*f_rng)(void *, unsigned char *, size_t), void *p_rng)
{ … }
int mbedtls_pk_check_pair(const mbedtls_pk_context *pub,
const mbedtls_pk_context *prv,
int (*f_rng)(void *, unsigned char *, size_t),
void *p_rng)
{ … }
size_t mbedtls_pk_get_bitlen(const mbedtls_pk_context *ctx)
{ … }
int mbedtls_pk_debug(const mbedtls_pk_context *ctx, mbedtls_pk_debug_item *items)
{ … }
const char *mbedtls_pk_get_name(const mbedtls_pk_context *ctx)
{ … }
mbedtls_pk_type_t mbedtls_pk_get_type(const mbedtls_pk_context *ctx)
{ … }
#endif