/** | |
* @file ax_mbedtls.c | |
* @author NXP Semiconductors | |
* @version 1.0 | |
* @par License | |
* | |
* Copyright 2018 NXP | |
* SPDX-License-Identifier: Apache-2.0 | |
* | |
* @par Description | |
* Implementation of key association between A71CH and mbedtls. | |
* @par History | |
* 1.0 30-jan-2018 : Initial version | |
* | |
*****************************************************************************/ | |
#if !defined(MBEDTLS_CONFIG_FILE) | |
#include "mbedtls/config.h" | |
#else | |
#include MBEDTLS_CONFIG_FILE | |
#endif | |
#if defined(MBEDTLS_ECP_ALT) | |
/** @ingroup ax_mbed_tls */ | |
/** @{ */ | |
#include "mbedtls/version.h" | |
#include "mbedtls/ssl.h" | |
#include "mbedtls/ssl_internal.h" | |
#include "ax_mbedtls.h" | |
#include "mbedtls/pk_internal.h" | |
#include "mbedtls/platform.h" | |
#include "sm_printf.h" | |
#include "sm_const.h" | |
#include "HLSEObjects.h" | |
#include "HLSECrypto.h" | |
#include "HLSEAPI.h" | |
#include "sm_apdu.h" | |
#if defined(FLOW_VERBOSE) && (FLOW_VERBOSE == 1) | |
# define LOG_API_CALLS 1 | |
#else | |
# define LOG_API_CALLS 1 | |
#endif /* FLOW_VERBOSE */ | |
#ifndef LOG_API_CALLS | |
# define LOG_API_CALLS 1 /* Log by default */ | |
#endif | |
static size_t ax_eckey_get_bitlen( | |
const void *ctx); | |
static int ax_eckey_sign( | |
void *ctx, mbedtls_md_type_t md_alg, | |
const unsigned char *hash, size_t hash_len, | |
unsigned char *sig, size_t *sig_len, | |
int (*f_rng)( | |
void *, unsigned char *, size_t), void *p_rng); | |
static int ax_eckey_verify( | |
void *ctx, mbedtls_md_type_t md_alg, | |
const unsigned char *hash, size_t hash_len, | |
const unsigned char *sig, size_t sig_len); | |
static int ax_eckey_check_pair( | |
const void *pub, const void *prv); | |
static int ax_eckeypair_can_do( | |
mbedtls_pk_type_t type); | |
static int ax_ecpubkey_can_do( | |
mbedtls_pk_type_t type); | |
static void ax_eckeypair_free_func( | |
void *ctx); | |
static void ax_ecpubkey_free_func( | |
void *ctx); | |
static const mbedtls_pk_info_t ax_mbedtls_eckeypair_info = { | |
MBEDTLS_PK_ECKEY, | |
"AxEC_Keypair", | |
&ax_eckey_get_bitlen, | |
&ax_eckeypair_can_do, | |
NULL, | |
&ax_eckey_sign, | |
NULL, // decrypt_func, | |
NULL, // encrypt_func, | |
&ax_eckey_check_pair, | |
NULL, //&ax_eckey_alloc, | |
&ax_eckeypair_free_func, | |
NULL, //&ax_eckey_debug, | |
}; | |
static const mbedtls_pk_info_t ax_mbedtls_ecpubkey_info = { | |
MBEDTLS_PK_ECKEY, | |
"AxEC_pubkey", | |
&ax_eckey_get_bitlen, | |
&ax_ecpubkey_can_do, | |
&ax_eckey_verify, | |
NULL, | |
NULL, | |
NULL, | |
NULL, | |
NULL, | |
&ax_ecpubkey_free_func, | |
NULL, | |
}; | |
static mbedtls_ecp_keypair * gmbedtls_ecp_keypair[4]; | |
static mbedtls_ecp_keypair * gmbedtls_ecp_pubkey[3]; | |
int ax_mbedtls_associate_keypair( | |
SST_Index_t key_index, mbedtls_pk_context * pkey) | |
{ | |
mbedtls_ecp_keypair * pax_ctx; | |
HLSE_OBJECT_HANDLE keyPairHandles[A71CH_KEY_PAIR_MAX]; | |
U16 kpHandleNum = A71CH_KEY_PAIR_MAX; | |
U16 kpHandleNumMax; | |
U8 i = 0; | |
HLSE_RET_CODE err; | |
if (key_index >= (sizeof(gmbedtls_ecp_keypair)/sizeof(gmbedtls_ecp_keypair[0]))) { | |
/** Return 1 (failed) if key_index is out of range. */ | |
return 1; | |
} | |
pkey->pk_info = &ax_mbedtls_eckeypair_info; | |
if (gmbedtls_ecp_keypair[key_index] == NULL) | |
{ | |
gmbedtls_ecp_keypair[key_index] = (mbedtls_ecp_keypair *) mbedtls_calloc(1, sizeof(mbedtls_ecp_keypair)); | |
} | |
pax_ctx = gmbedtls_ecp_keypair[key_index]; | |
err = HLSE_EnumerateObjects(HLSE_KEY_PAIR, keyPairHandles, &kpHandleNum); | |
kpHandleNumMax = kpHandleNum; | |
if (err != HLSE_SW_OK) | |
{ | |
return 1; | |
} | |
while(kpHandleNum) | |
{ | |
if (HLSE_GET_OBJECT_INDEX(keyPairHandles[i]) == key_index) | |
{ | |
pax_ctx->grp.hlse_handle = keyPairHandles[i]; | |
break; | |
} | |
i++; | |
kpHandleNum--; | |
} | |
if (i >= kpHandleNumMax) | |
{ | |
/*unable to find the keypair at specified index */ | |
return 1; | |
} | |
pax_ctx->grp.id = MBEDTLS_ECP_DP_SECP256R1; | |
#if LOG_API_CALLS | |
sm_printf(DBGOUT, "Associating ECC key-pair '%d'.\r\n",HLSE_GET_OBJECT_INDEX(pax_ctx->grp.hlse_handle)); | |
#endif /* LOG_API_CALLS */ | |
pkey->pk_ctx = pax_ctx; | |
return 0; | |
} | |
int ax_mbedtls_associate_pubkey( | |
SST_Index_t key_index, mbedtls_pk_context * pkey) | |
{ | |
mbedtls_ecp_keypair * pax_ctx; | |
HLSE_RET_CODE err; | |
HLSE_OBJECT_HANDLE handles[A71CH_PUBLIC_KEY_MAX]; | |
U16 handleNum = A71CH_PUBLIC_KEY_MAX; | |
U16 handleNumMax; | |
U8 i = 0; | |
if (key_index >= (sizeof(gmbedtls_ecp_pubkey)/sizeof(gmbedtls_ecp_pubkey[0]))) { | |
return 1; | |
} | |
pkey->pk_info = &ax_mbedtls_ecpubkey_info; | |
if (gmbedtls_ecp_pubkey[key_index] == NULL) | |
{ | |
gmbedtls_ecp_pubkey[key_index] = (mbedtls_ecp_keypair *) mbedtls_calloc(1, sizeof(mbedtls_ecp_keypair)); | |
} | |
pax_ctx = gmbedtls_ecp_pubkey[key_index]; | |
err = HLSE_EnumerateObjects(HLSE_PUBLIC_KEY, handles, &handleNum); | |
handleNumMax = handleNum; | |
if (err != HLSE_SW_OK) | |
{ | |
return 1; | |
} | |
while(handleNum) | |
{ | |
if (HLSE_GET_OBJECT_INDEX(handles[i]) == key_index) | |
{ | |
pax_ctx->grp.hlse_handle = handles[i]; | |
break; | |
} | |
i++; | |
handleNum--; | |
} | |
if (i >= handleNumMax) | |
{ | |
/*Unable to find the key at specified index */ | |
return 1; | |
} | |
pax_ctx->grp.id = MBEDTLS_ECP_DP_SECP256R1; | |
#if LOG_API_CALLS | |
sm_printf(DBGOUT, "Associating ECC public key '%d'.\r\n",HLSE_GET_OBJECT_INDEX(pax_ctx->grp.hlse_handle)); | |
#endif /* LOG_API_CALLS */ | |
pkey->pk_ctx = pax_ctx; | |
return 0; | |
} | |
int ax_mbedtls_associate_ecdhctx(SST_Index_t key_index, mbedtls_ssl_handshake_params * handshake) { | |
if (key_index >= (sizeof(gmbedtls_ecp_keypair)/sizeof(gmbedtls_ecp_keypair[0]))) { | |
return 1; | |
} | |
handshake->ecdh_ctx.grp.id = MBEDTLS_ECP_DP_SECP256R1; | |
handshake->ecdh_ctx.grp.hlse_handle = HLSE_KEY_PAIR | key_index; | |
#if LOG_API_CALLS > 1 | |
sm_printf(DBGOUT, "Associating ECC key-pair '%d' for handshake.\r\n",key_index); | |
#endif | |
return 0; | |
} | |
static size_t ax_eckey_get_bitlen( | |
const void *ctx) | |
{ | |
return ((64 << 1) + 1); | |
} | |
static int ax_eckey_verify( | |
void *ctx, mbedtls_md_type_t md_alg, | |
const unsigned char *hash, size_t hash_len, | |
const unsigned char *sig, size_t sig_len) | |
{ | |
int ret = 1; | |
HLSE_RET_CODE err; | |
SM_Error_t status = SW_OK; | |
mbedtls_ecp_keypair * pax_ctx = (mbedtls_ecp_keypair *) ctx; | |
HLSE_MECHANISM_INFO mechInfo; | |
#if LOG_API_CALLS | |
sm_printf(DBGOUT, "Using ECC key '%d' for verification.\r\n",HLSE_GET_OBJECT_INDEX(pax_ctx->grp.hlse_handle)); | |
#endif /* LOG_API_CALLS */ | |
if (HLSE_GET_OBJECT_TYPE(pax_ctx->grp.hlse_handle) == HLSE_PUBLIC_KEY) | |
{ | |
memset(&mechInfo, 0, sizeof(mechInfo)); | |
mechInfo.mechanism = HLSE_ECDSA_VERIFY; | |
err = HLSE_VerifySignature(&mechInfo, pax_ctx->grp.hlse_handle , (U8 *)hash, hash_len, | |
(U8 *)sig, sig_len); | |
} | |
else | |
{ | |
sm_printf(DBGOUT, "hlse_handle:0x'%X' is not a public key.\r\n", pax_ctx->grp.hlse_handle); | |
err = HLSE_ERR_GENERAL_ERROR; | |
status = SW_CONDITIONS_NOT_SATISFIED; | |
} | |
if ((err == HLSE_SW_OK) && (status == SW_OK)) | |
{ | |
ret = 0; | |
} | |
return (ret); | |
} | |
static int ax_eckey_sign( | |
void *ctx, mbedtls_md_type_t md_alg, | |
const unsigned char *hash, size_t hash_len, | |
unsigned char *sig, size_t *sig_len, | |
int (*f_rng)( | |
void *, unsigned char *, size_t), void *p_rng) | |
{ | |
int ret = 0; | |
HLSE_RET_CODE err; | |
mbedtls_ecp_keypair * pax_ctx = (mbedtls_ecp_keypair *) ctx; | |
U16 u16_sig_len = 72; //*sig_len; | |
HLSE_MECHANISM_INFO mechInfo; | |
if (hash_len > AX_SHA256_LEN) | |
hash_len = AX_SHA256_LEN; | |
#if LOG_API_CALLS | |
sm_printf(DBGOUT, "Using ECC key '%d' for signing.\r\n",HLSE_GET_OBJECT_INDEX(pax_ctx->grp.hlse_handle)); | |
#endif /* LOG_API_CALLS */ | |
if (HLSE_GET_OBJECT_TYPE(pax_ctx->grp.hlse_handle) == HLSE_KEY_PAIR) | |
{ | |
memset(&mechInfo, 0, sizeof(mechInfo)); | |
mechInfo.mechanism = HLSE_ECDSA_SIGN; | |
err = HLSE_Sign(&mechInfo, pax_ctx->grp.hlse_handle, (U8 *)hash, hash_len, sig, &u16_sig_len); | |
*sig_len = u16_sig_len; | |
if (err == HLSE_SW_OK) | |
ret = 0; | |
else | |
ret = 1; | |
} | |
else | |
{ | |
ret = 1; | |
} | |
return (ret); | |
} | |
static int ax_eckey_check_pair( | |
const void *pub, const void *prv) | |
{ | |
return 0; | |
} | |
static int ax_eckeypair_can_do( | |
mbedtls_pk_type_t type) | |
{ | |
return (type == MBEDTLS_PK_ECKEY || | |
type == MBEDTLS_PK_ECKEY_DH || | |
type == MBEDTLS_PK_ECDSA); | |
} | |
static int ax_ecpubkey_can_do( | |
mbedtls_pk_type_t type) | |
{ | |
return (type == MBEDTLS_PK_ECKEY || | |
type == MBEDTLS_PK_ECKEY_DH || | |
type == MBEDTLS_PK_ECDSA); | |
} | |
static void ax_eckeypair_free_func( | |
void *ctx) | |
{ | |
mbedtls_ecp_keypair * pax_ctx = (mbedtls_ecp_keypair *) ctx; | |
if (pax_ctx != NULL | |
&& pax_ctx->grp.hlse_handle != 0 | |
&& gmbedtls_ecp_keypair[HLSE_GET_OBJECT_INDEX(pax_ctx->grp.hlse_handle)] != NULL) | |
{ | |
mbedtls_ecp_keypair_free(gmbedtls_ecp_keypair[HLSE_GET_OBJECT_INDEX(pax_ctx->grp.hlse_handle)]); | |
gmbedtls_ecp_keypair[HLSE_GET_OBJECT_INDEX(pax_ctx->grp.hlse_handle)] = NULL; | |
pax_ctx->grp.hlse_handle = 0; | |
mbedtls_free(ctx); | |
} | |
return; | |
} | |
static void ax_ecpubkey_free_func( | |
void *ctx) | |
{ | |
mbedtls_ecp_keypair * pax_ctx = (mbedtls_ecp_keypair *) ctx; | |
if (pax_ctx != NULL | |
&& pax_ctx->grp.hlse_handle != 0 | |
&& gmbedtls_ecp_pubkey[HLSE_GET_OBJECT_INDEX(pax_ctx->grp.hlse_handle)] != NULL) | |
{ | |
mbedtls_ecp_keypair_free(gmbedtls_ecp_pubkey[HLSE_GET_OBJECT_INDEX(pax_ctx->grp.hlse_handle)]); | |
gmbedtls_ecp_pubkey[HLSE_GET_OBJECT_INDEX(pax_ctx->grp.hlse_handle)] = NULL; | |
pax_ctx->grp.hlse_handle = 0; | |
mbedtls_free(ctx); | |
} | |
return; | |
} | |
/** @} */ | |
#endif /* MBEDTLS_ECP_ALT */ |