| /* |
| * |
| * Copyright 2018-2019 NXP |
| * SPDX-License-Identifier: Apache-2.0 |
| */ |
| |
| /** |
| * @par Description |
| * Implementation of key association between NXP Secure Element 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) && SSS_HAVE_ALT_SSS |
| |
| /** @ingroup ax_mbed_tls */ |
| /** @{ */ |
| |
| #include <fsl_sss_util_asn1_der.h> |
| #include <nxLog_sss.h> |
| #include <string.h> |
| |
| #include "fsl_sss_api.h" |
| #include "mbedtls/pk_internal.h" |
| #include "mbedtls/platform.h" |
| #include "mbedtls/rsa.h" |
| #include "mbedtls/ssl.h" |
| #include "mbedtls/ssl_internal.h" |
| #include "mbedtls/version.h" |
| #include "sss_mbedtls.h" |
| #if defined(FLOW_VERBOSE) && (FLOW_VERBOSE == 1) |
| #define LOG_API_CALLS 1 |
| #else |
| #define LOG_API_CALLS 0 |
| #endif /* FLOW_VERBOSE */ |
| |
| #ifndef LOG_API_CALLS |
| #define LOG_API_CALLS 1 /* Log by default */ |
| #endif |
| |
| extern mbedtls_pk_info_t ax_mbedtls_rsakeypair_info; |
| extern mbedtls_pk_info_t ax_mbedtls_rsapubkey_info; |
| |
| static size_t sss_eckey_get_bitlen(const void *ctx); |
| static int sss_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 sss_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 sss_eckey_check_pair(const void *pub, const void *prv); |
| static int sss_eckeypair_can_do(mbedtls_pk_type_t type); |
| static int sss_ecpubkey_can_do(mbedtls_pk_type_t type); |
| static void sss_eckeypair_free_func(void *ctx); |
| static void sss_ecpubkey_free_func(void *ctx); |
| |
| static const mbedtls_pk_info_t ax_mbedtls_eckeypair_info = { |
| MBEDTLS_PK_ECKEY, |
| "AxEC_Keypair", |
| &sss_eckey_get_bitlen, |
| &sss_eckeypair_can_do, |
| NULL, |
| &sss_eckey_sign, |
| NULL, // decrypt_func, |
| NULL, // encrypt_func, |
| &sss_eckey_check_pair, |
| NULL, //&ax_eckey_alloc, |
| &sss_eckeypair_free_func, |
| NULL, //&ax_eckey_debug, |
| }; |
| |
| static const mbedtls_pk_info_t ax_mbedtls_ecpubkey_info = { |
| MBEDTLS_PK_ECKEY, |
| "AxEC_pubkey", |
| &sss_eckey_get_bitlen, |
| &sss_ecpubkey_can_do, |
| &sss_eckey_verify, |
| NULL, |
| NULL, |
| NULL, |
| NULL, |
| NULL, |
| &sss_ecpubkey_free_func, |
| NULL, |
| }; |
| |
| /* clang-format off */ |
| typedef struct _object_identifiers |
| { |
| uint32_t identifier[16]; |
| size_t indentifier_len; |
| int groupId; |
| char* name; |
| } object_identifiers_t; |
| object_identifiers_t object_identifiers_gvar[] = { |
| |
| { { 1, 2, 840, 10045, 3, 1, 1 }, 7, MBEDTLS_ECP_DP_SECP192R1, "MBEDTLS_ECP_DP_SECP192R1" }, |
| { { 1, 3, 132, 0, 33 }, 5, MBEDTLS_ECP_DP_SECP224R1, "MBEDTLS_ECP_DP_SECP224R1" }, |
| { { 1, 2, 840, 10045, 3, 1, 7 }, 7, MBEDTLS_ECP_DP_SECP256R1, "MBEDTLS_ECP_DP_SECP256R1" }, |
| { { 1, 3, 132, 0, 34 }, 5, MBEDTLS_ECP_DP_SECP384R1, "MBEDTLS_ECP_DP_SECP384R1" }, |
| { { 1, 3, 132, 0, 35 }, 5, MBEDTLS_ECP_DP_SECP521R1, "MBEDTLS_ECP_DP_SECP521R1" }, |
| |
| { { 1, 3, 36, 3, 3, 2, 8, 1, 1, 7 }, 10, MBEDTLS_ECP_DP_BP256R1, "MBEDTLS_ECP_DP_BP256R1" }, |
| { { 1, 3, 24, 3, 3, 2, 8, 1, 1, 7 }, 10, MBEDTLS_ECP_DP_BP256R1, "MBEDTLS_ECP_DP_BP256R1" }, |
| { { 1, 3, 36, 3, 3, 2, 8, 1, 1, 11}, 10, MBEDTLS_ECP_DP_BP384R1, "MBEDTLS_ECP_DP_BP384R1" }, |
| { { 1, 3, 36, 3, 3, 2, 8, 1, 1, 13}, 10, MBEDTLS_ECP_DP_BP512R1, "MBEDTLS_ECP_DP_BP512R1" }, |
| |
| { { 1, 3, 132, 0, 31 }, 5, MBEDTLS_ECP_DP_SECP192K1, "MBEDTLS_ECP_DP_SECP192K1" }, |
| { { 1, 3, 132, 0, 32 }, 5, MBEDTLS_ECP_DP_SECP224K1, "MBEDTLS_ECP_DP_SECP224K1" }, |
| { { 1, 3, 132, 0, 10 }, 5, MBEDTLS_ECP_DP_SECP256K1, "MBEDTLS_ECP_DP_SECP256K1" }, |
| {{0,}, 0, 0}, |
| }; |
| /* clang-format on */ |
| |
| #ifdef _MSC_VER |
| #pragma warning(disable : 4127) |
| #endif |
| |
| int get_group_id(uint32_t *objectid, uint8_t objectIdLen) |
| { |
| size_t i = 0, j = 0; |
| int groupId = -1; |
| |
| while (1) { |
| if (object_identifiers_gvar[i].indentifier_len == 0) { |
| break; |
| } |
| |
| if (object_identifiers_gvar[i].indentifier_len != objectIdLen) { |
| i++; |
| continue; |
| } |
| |
| for (j = 0; j < object_identifiers_gvar[i].indentifier_len; j++) { |
| if (object_identifiers_gvar[i].identifier[j] != objectid[j]) { |
| i++; |
| goto skip_oid; |
| } |
| } |
| |
| groupId = object_identifiers_gvar[i].groupId; |
| LOG_I("Group id found - %s \n", object_identifiers_gvar[i].name); |
| break; |
| skip_oid: |
| continue; |
| } |
| |
| return groupId; |
| } |
| |
| int sss_mbedtls_associate_keypair(mbedtls_pk_context *pkey, sss_object_t *pkeyObject) |
| { |
| void *pax_ctx = NULL; |
| uint32_t objectId[16] = { |
| 0, |
| }; |
| uint8_t objectIdLen = sizeof(objectId); |
| sss_status_t status = kStatus_SSS_Fail; |
| |
| memset(pkey, 0, sizeof(*pkey)); |
| |
| if (pkeyObject->cipherType == kSSS_CipherType_EC_NIST_P || pkeyObject->cipherType == kSSS_CipherType_EC_NIST_K || |
| pkeyObject->cipherType == kSSS_CipherType_EC_BRAINPOOL || |
| pkeyObject->cipherType == kSSS_CipherType_EC_MONTGOMERY || |
| pkeyObject->cipherType == kSSS_CipherType_EC_TWISTED_ED) { |
| LOG_D("Associating ECC key-pair '0x%08X'", pkeyObject->keyId); |
| |
| pkey->pk_info = &ax_mbedtls_eckeypair_info; |
| pax_ctx = (mbedtls_ecp_keypair *)mbedtls_calloc(1, sizeof(mbedtls_ecp_keypair)); |
| ((mbedtls_ecp_keypair *)pax_ctx)->grp.pSSSObject = pkeyObject; |
| status = sss_util_asn1_get_oid_from_sssObj(pkeyObject, objectId, &objectIdLen); |
| if (status != kStatus_SSS_Success) { |
| if (pax_ctx != NULL) { |
| mbedtls_free(pax_ctx); |
| } |
| return 1; |
| } |
| |
| ((mbedtls_ecp_keypair *)pax_ctx)->grp.id = get_group_id(objectId, objectIdLen); |
| if (((mbedtls_ecp_keypair *)pax_ctx)->grp.id == MBEDTLS_ECP_DP_NONE) { |
| LOG_E(" sss_mbedtls_associate_keypair: Group id not found...\n"); |
| if (pax_ctx != NULL) { |
| mbedtls_free(pax_ctx); |
| } |
| return 1; |
| } |
| pkey->pk_ctx = pax_ctx; |
| } |
| #ifdef MBEDTLS_RSA_ALT |
| else if (pkeyObject->cipherType == kSSS_CipherType_RSA || pkeyObject->cipherType == kSSS_CipherType_RSA_CRT) { |
| uint8_t pbKey[1024]; |
| size_t pbKeyBitLen = 0; |
| size_t pbKeyBytetLen = sizeof(pbKey); |
| uint8_t *modulus = NULL; |
| size_t modlen = 0; |
| uint8_t *pubExp = NULL; |
| size_t pubExplen = 0; |
| |
| LOG_D("Associating RSA key-pair '0x%08X'", pkeyObject->keyId); |
| |
| pkey->pk_info = &ax_mbedtls_rsakeypair_info; |
| pax_ctx = (mbedtls_rsa_context *)mbedtls_calloc(1, sizeof(mbedtls_rsa_context)); |
| ((mbedtls_rsa_context *)pax_ctx)->pSSSObject = pkeyObject; |
| |
| status = sss_key_store_get_key(pkeyObject->keyStore, pkeyObject, pbKey, &pbKeyBytetLen, &pbKeyBitLen); |
| if (status != kStatus_SSS_Success) { |
| return 1; |
| } |
| |
| status = sss_util_asn1_rsa_parse_public(pbKey, pbKeyBytetLen, &modulus, &modlen, &pubExp, &pubExplen); |
| if (modulus != NULL) { |
| SSS_FREE(modulus); |
| modulus = NULL; |
| } |
| if (pubExp != NULL) { |
| SSS_FREE(pubExp); |
| pubExp = NULL; |
| } |
| if (status != kStatus_SSS_Success) { |
| return 1; |
| } |
| |
| ((mbedtls_rsa_context *)pax_ctx)->len = (modlen * 8); |
| } |
| #endif /* MBEDTLS_RSA_ALT */ |
| else { |
| return 1; |
| } |
| |
| pkey->pk_ctx = pax_ctx; |
| return 0; |
| } |
| |
| int sss_mbedtls_associate_pubkey(mbedtls_pk_context *pkey, sss_object_t *pkeyObject) |
| { |
| void *pax_ctx = NULL; |
| uint32_t objectId[16] = { |
| 0, |
| }; |
| uint8_t objectIdLen = sizeof(objectId); |
| sss_status_t status = kStatus_SSS_Fail; |
| |
| memset(pkey, 0, sizeof(*pkey)); |
| |
| if (pkeyObject->cipherType == kSSS_CipherType_EC_NIST_P || pkeyObject->cipherType == kSSS_CipherType_EC_NIST_K || |
| pkeyObject->cipherType == kSSS_CipherType_EC_BRAINPOOL || |
| pkeyObject->cipherType == kSSS_CipherType_EC_MONTGOMERY || |
| pkeyObject->cipherType == kSSS_CipherType_EC_TWISTED_ED) { |
| LOG_D("Associating ECC public key '0x%08X'", pkeyObject->keyId); |
| |
| pkey->pk_info = &ax_mbedtls_ecpubkey_info; |
| pax_ctx = (mbedtls_ecp_keypair *)mbedtls_calloc(1, sizeof(mbedtls_ecp_keypair)); |
| ((mbedtls_ecp_keypair *)pax_ctx)->grp.pSSSObject = pkeyObject; |
| |
| status = sss_util_asn1_get_oid_from_sssObj(pkeyObject, objectId, &objectIdLen); |
| if (status != kStatus_SSS_Success) { |
| if (pax_ctx != NULL) { |
| mbedtls_free(pax_ctx); |
| } |
| return 1; |
| } |
| |
| ((mbedtls_ecp_keypair *)pax_ctx)->grp.id = get_group_id(objectId, objectIdLen); |
| if (((mbedtls_ecp_keypair *)pax_ctx)->grp.id == MBEDTLS_ECP_DP_NONE) { |
| LOG_E(" sss_mbedtls_associate_pubkey: Group id not found...\n"); |
| if (pax_ctx != NULL) { |
| mbedtls_free(pax_ctx); |
| } |
| return 1; |
| } |
| } |
| #ifdef MBEDTLS_RSA_ALT |
| else if (pkeyObject->cipherType == kSSS_CipherType_RSA || pkeyObject->cipherType == kSSS_CipherType_RSA_CRT) { |
| uint8_t pbKey[1400]; |
| size_t pbKeyBitLen = 0; |
| size_t pbKeyBytetLen = sizeof(pbKey); |
| uint8_t *modulus = NULL; |
| size_t modlen = 0; |
| uint8_t *pubExp = NULL; |
| size_t pubExplen = 0; |
| |
| LOG_D("Associating RSA public key '0x%08X'", pkeyObject->keyId); |
| |
| pax_ctx = (mbedtls_rsa_context *)mbedtls_calloc(1, sizeof(mbedtls_rsa_context)); |
| pkey->pk_ctx = pax_ctx; |
| pkey->pk_info = &ax_mbedtls_rsapubkey_info; |
| ((mbedtls_rsa_context *)pax_ctx)->pSSSObject = pkeyObject; |
| |
| status = sss_key_store_get_key(pkeyObject->keyStore, pkeyObject, pbKey, &pbKeyBytetLen, &pbKeyBitLen); |
| if (status != kStatus_SSS_Success) { |
| return 1; |
| } |
| |
| status = sss_util_asn1_rsa_parse_public(pbKey, pbKeyBytetLen, &modulus, &modlen, &pubExp, &pubExplen); |
| if (modulus != NULL) { |
| SSS_FREE(modulus); |
| modulus = NULL; |
| } |
| if (pubExp != NULL) { |
| SSS_FREE(pubExp); |
| pubExp = NULL; |
| } |
| if (status != kStatus_SSS_Success) { |
| return 1; |
| } |
| |
| ((mbedtls_rsa_context *)pax_ctx)->len = (modlen * 8); |
| } |
| #endif /* MBEDTLS_RSA_ALT */ |
| else { |
| return 1; |
| } |
| |
| pkey->pk_ctx = pax_ctx; |
| return 0; |
| } |
| |
| int sss_mbedtls_associate_ecdhctx( |
| mbedtls_ssl_handshake_params *handshake, sss_object_t *pSSSObject, sss_key_store_t *hostKs) |
| { |
| sss_status_t status = kStatus_SSS_Fail; |
| uint32_t objectId[16] = { |
| 0, |
| }; |
| uint8_t objectIdLen = sizeof(objectId); |
| |
| status = sss_util_asn1_get_oid_from_sssObj(pSSSObject, objectId, &objectIdLen); |
| if (status != kStatus_SSS_Success) { |
| return 1; |
| } |
| |
| handshake->ecdh_ctx.grp.id = get_group_id(objectId, objectIdLen); |
| |
| handshake->ecdh_ctx.grp.pSSSObject = pSSSObject; |
| handshake->ecdh_ctx.grp.hostKs = hostKs; |
| #if LOG_API_CALLS > 1 |
| LOG_I("Associating ECC key-pair '%d' for handshake.\r\n", key_index); |
| #endif |
| return 0; |
| } |
| |
| static size_t sss_eckey_get_bitlen(const void *ctx) |
| { |
| return ((64 << 1) + 1); |
| } |
| |
| static int sss_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) |
| { |
| sss_status_t status = kStatus_SSS_Success; |
| sss_asymmetric_t asymVerifyCtx; |
| sss_object_t *sssObject = NULL; |
| sss_algorithm_t algorithm; |
| mbedtls_ecp_keypair *pax_ctx = (mbedtls_ecp_keypair *)ctx; |
| |
| sssObject = pax_ctx->grp.pSSSObject; |
| |
| switch (md_alg) { |
| case MBEDTLS_MD_SHA1: |
| algorithm = kAlgorithm_SSS_SHA1; |
| break; |
| case MBEDTLS_MD_SHA224: |
| algorithm = kAlgorithm_SSS_SHA224; |
| break; |
| case MBEDTLS_MD_SHA256: |
| algorithm = kAlgorithm_SSS_SHA256; |
| break; |
| case MBEDTLS_MD_SHA384: |
| algorithm = kAlgorithm_SSS_SHA384; |
| break; |
| case MBEDTLS_MD_SHA512: |
| algorithm = kAlgorithm_SSS_SHA512; |
| break; |
| default: |
| return 1; |
| } |
| |
| LOG_D("Using ECC key-pair '0x%08X'", pax_ctx->grp.pSSSObject->keyId); |
| |
| status = sss_asymmetric_context_init( |
| &asymVerifyCtx, sssObject->keyStore->session, sssObject, algorithm, kMode_SSS_Verify); |
| if (status != kStatus_SSS_Success) { |
| LOG_E(" sss_asymmetric_context_init verify context Failed...\n"); |
| return 1; |
| } |
| status = sss_asymmetric_verify_digest(&asymVerifyCtx, (uint8_t *)hash, hash_len, (uint8_t *)sig, sig_len); |
| if (status != kStatus_SSS_Success) { |
| LOG_E(" sss_asymmetric_verify_digest Failed...\n"); |
| return 1; |
| } |
| |
| return (0); |
| } |
| |
| static int sss_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; |
| size_t u16_sig_len = 1024; |
| sss_asymmetric_t asymVerifyCtx; |
| sss_status_t status = kStatus_SSS_Success; |
| sss_object_t *sssObject = NULL; |
| mbedtls_ecp_keypair *pax_ctx = (mbedtls_ecp_keypair *)ctx; |
| sss_algorithm_t algorithm; |
| |
| sssObject = pax_ctx->grp.pSSSObject; |
| switch (md_alg) { |
| case MBEDTLS_MD_SHA1: |
| algorithm = kAlgorithm_SSS_SHA1; |
| break; |
| case MBEDTLS_MD_SHA224: |
| algorithm = kAlgorithm_SSS_SHA224; |
| break; |
| case MBEDTLS_MD_SHA256: |
| algorithm = kAlgorithm_SSS_SHA256; |
| break; |
| case MBEDTLS_MD_SHA384: |
| algorithm = kAlgorithm_SSS_SHA384; |
| break; |
| case MBEDTLS_MD_SHA512: |
| algorithm = kAlgorithm_SSS_SHA512; |
| break; |
| default: |
| return 1; |
| } |
| |
| status = |
| sss_asymmetric_context_init(&asymVerifyCtx, sssObject->keyStore->session, sssObject, algorithm, kMode_SSS_Sign); |
| if (status != kStatus_SSS_Success) { |
| LOG_E(" sss_asymmetric_context_init verify context Failed...\n"); |
| return 1; |
| } |
| |
| LOG_D("Signing using key %08lX\r\n", pax_ctx->grp.pSSSObject->keyId); |
| |
| status = sss_asymmetric_sign_digest(&asymVerifyCtx, (uint8_t *)hash, hash_len, sig, &u16_sig_len); |
| if (status != kStatus_SSS_Success) { |
| LOG_W(" sss_asymmetric_sign_digest Failed...\n"); |
| return 1; |
| } |
| |
| *sig_len = u16_sig_len; |
| |
| return (ret); |
| } |
| |
| static int sss_eckey_check_pair(const void *pub, const void *prv) |
| { |
| return 0; |
| } |
| |
| static int sss_eckeypair_can_do(mbedtls_pk_type_t type) |
| { |
| return (type == MBEDTLS_PK_ECKEY || type == MBEDTLS_PK_ECKEY_DH || type == MBEDTLS_PK_ECDSA); |
| } |
| |
| static int sss_ecpubkey_can_do(mbedtls_pk_type_t type) |
| { |
| return (type == MBEDTLS_PK_ECKEY || type == MBEDTLS_PK_ECKEY_DH || type == MBEDTLS_PK_ECDSA); |
| } |
| |
| static void sss_eckeypair_free_func(void *ctx) |
| { |
| mbedtls_ecp_keypair *pax_ctx = (mbedtls_ecp_keypair *)ctx; |
| if (pax_ctx != NULL) { |
| mbedtls_free(ctx); |
| } |
| return; |
| } |
| |
| static void sss_ecpubkey_free_func(void *ctx) |
| { |
| mbedtls_ecp_keypair *pax_ctx = (mbedtls_ecp_keypair *)ctx; |
| if (pax_ctx != NULL) { |
| mbedtls_free(ctx); |
| } |
| return; |
| } |
| |
| /** @} */ |
| |
| #endif /* MBEDTLS_ECP_ALT */ |