/** * @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 */