/* * * Copyright 2017-2019 NXP * SPDX-License-Identifier: Apache-2.0 */ /** * @par Description * Implementation of key association between NXP Secure Element and mbedtls. * *****************************************************************************/ #if !defined(MBEDTLS_CONFIG_FILE) #include "mbedtls/config.h" #else #include MBEDTLS_CONFIG_FILE #endif #if defined(MBEDTLS_ECDH_C) && defined(MBEDTLS_ECDH_ALT) && SSS_HAVE_ALT_SSS #include #include #include #include #include "mbedtls/ecdh.h" #include "mbedtls/version.h" #if defined(SSS_USE_FTR_FILE) #include "fsl_sss_ftr.h" #else #include "fsl_sss_ftr_default.h" #endif #if defined(FLOW_VERBOSE) && FLOW_VERBOSE == 1 #include "sm_printf.h" #include "sm_types.h" #endif /* FLOW_VERBOSE */ extern int mbedtls_ecdh_gen_public_o(mbedtls_ecp_group *grp, mbedtls_mpi *d, mbedtls_ecp_point *Q, int (*f_rng)(void *, unsigned char *, size_t), void *p_rng); extern int mbedtls_ecdh_compute_shared_o(mbedtls_ecp_group *grp, mbedtls_mpi *z, const mbedtls_ecp_point *Q, const mbedtls_mpi *d, int (*f_rng)(void *, unsigned char *, size_t), void *p_rng); extern int mbedtls_ecdh_get_params_o(mbedtls_ecdh_context *ctx, const mbedtls_ecp_keypair *key, mbedtls_ecdh_side side); int get_header_and_bit_Length(int groupid, int *headerLen, int *bitLen) { switch (groupid) { case MBEDTLS_ECP_DP_SECP192R1: if (headerLen != NULL) *headerLen = der_ecc_nistp192_header_len; if (bitLen != NULL) *bitLen = 192; break; case MBEDTLS_ECP_DP_SECP224R1: if (headerLen != NULL) *headerLen = der_ecc_nistp224_header_len; if (bitLen != NULL) *bitLen = 224; break; case MBEDTLS_ECP_DP_SECP256R1: if (headerLen != NULL) *headerLen = der_ecc_nistp256_header_len; if (bitLen != NULL) *bitLen = 256; break; case MBEDTLS_ECP_DP_SECP384R1: if (headerLen != NULL) *headerLen = der_ecc_nistp384_header_len; if (bitLen != NULL) *bitLen = 384; break; case MBEDTLS_ECP_DP_SECP521R1: if (headerLen != NULL) *headerLen = der_ecc_nistp521_header_len; if (bitLen != NULL) *bitLen = 521; break; case MBEDTLS_ECP_DP_BP256R1: if (headerLen != NULL) *headerLen = der_ecc_bp256_header_len; if (bitLen != NULL) *bitLen = 256; break; case MBEDTLS_ECP_DP_BP384R1: if (headerLen != NULL) *headerLen = der_ecc_bp384_header_len; if (bitLen != NULL) *bitLen = 384; break; case MBEDTLS_ECP_DP_BP512R1: if (headerLen != NULL) *headerLen = der_ecc_bp512_header_len; if (bitLen != NULL) *bitLen = 512; break; case MBEDTLS_ECP_DP_SECP192K1: if (headerLen != NULL) *headerLen = der_ecc_192k_header_len; if (bitLen != NULL) *bitLen = 192; break; case MBEDTLS_ECP_DP_SECP224K1: if (headerLen != NULL) *headerLen = der_ecc_224k_header_len; if (bitLen != NULL) *bitLen = 224; break; case MBEDTLS_ECP_DP_SECP256K1: if (headerLen != NULL) *headerLen = der_ecc_256k_header_len; if (bitLen != NULL) *bitLen = 256; break; case MBEDTLS_ECP_DP_CURVE25519: if (headerLen != NULL) *headerLen = 0; if (bitLen != NULL) *bitLen = 256; break; case MBEDTLS_ECP_DP_CURVE448: if (headerLen != NULL) *headerLen = 0; if (bitLen != NULL) *bitLen = 448; break; default: LOG_E("get_header_and_bit_Length: Group id not supported"); return 1; } return 0; } /* * Generate public key: simple wrapper around mbedtls_ecp_gen_keypair */ int mbedtls_ecdh_gen_public(mbedtls_ecp_group *grp, mbedtls_mpi *d, mbedtls_ecp_point *Q, int (*f_rng)(void *, unsigned char *, size_t), void *p_rng) { sss_status_t status = kStatus_SSS_Fail; uint8_t publickey[256] = { 0, }; int headerLen = 0; size_t publickeylen = sizeof(publickey); size_t publickeyBitLen = publickeylen * 8; if (grp->pSSSObject == NULL) { return mbedtls_ecdh_gen_public_o(grp, d, Q, f_rng, p_rng); } else if (grp->pSSSObject->objectType == kSSS_KeyPart_Pair && (grp->pSSSObject->cipherType == kSSS_CipherType_EC_NIST_P || grp->pSSSObject->cipherType == kSSS_CipherType_EC_NIST_K || grp->pSSSObject->cipherType == kSSS_CipherType_EC_BRAINPOOL || grp->pSSSObject->cipherType == kSSS_CipherType_EC_MONTGOMERY || grp->pSSSObject->cipherType == kSSS_CipherType_EC_TWISTED_ED)) { if (get_header_and_bit_Length(grp->id, &headerLen, NULL)) { return 1; } mbedtls_mpi_free(d); status = sss_key_store_get_key( grp->pSSSObject->keyStore, grp->pSSSObject, publickey, &publickeylen, &publickeyBitLen); if (kStatus_SSS_Success == status) { publickeylen -= headerLen; return mbedtls_ecp_point_read_binary(grp, Q, &publickey[headerLen], publickeylen); } else { return 1; } } return 1; } /* * Compute shared secret (SEC1 3.3.1) */ int mbedtls_ecdh_compute_shared(mbedtls_ecp_group *grp, mbedtls_mpi *z, const mbedtls_ecp_point *Q, const mbedtls_mpi *d, int (*f_rng)(void *, unsigned char *, size_t), void *p_rng) { int ret = 1; sss_key_part_t keyType = kSSS_KeyPart_NONE; sss_cipher_type_t cipherType = kSSS_CipherType_NONE; int headerLen = 0; uint8_t OtherPublicKey[256]; size_t OtherPublickeylen = sizeof(OtherPublicKey); int keyBitLen = 0; sss_status_t status; sss_object_t otherPartyKeyObject; sss_object_t derivedKeyObject; sss_derive_key_t context; uint8_t SharedSecret[128]; uint16_t SharedSecretlen = sizeof(SharedSecret); uint8_t buf[256]; size_t bitLen = 500; size_t bufByteLen = sizeof(buf); sss_cipher_type_t OtherPublickeycipherType = kSSS_CipherType_NONE; if (get_header_and_bit_Length(grp->id, &headerLen, &keyBitLen)) { return 1; } if (grp->pSSSObject == NULL) { ret = mbedtls_ecdh_compute_shared_o(grp, z, Q, d, f_rng, p_rng); } else if (grp->pSSSObject->cipherType == kSSS_CipherType_EC_NIST_P || grp->pSSSObject->cipherType == kSSS_CipherType_EC_NIST_K || grp->pSSSObject->cipherType == kSSS_CipherType_EC_BRAINPOOL || grp->pSSSObject->cipherType == kSSS_CipherType_EC_MONTGOMERY) { if (0 == mbedtls_ecp_point_write_binary(grp, Q, MBEDTLS_ECP_PF_UNCOMPRESSED, &OtherPublickeylen, (OtherPublicKey + headerLen), sizeof(OtherPublicKey))) { switch (grp->id) { case MBEDTLS_ECP_DP_SECP192R1: memcpy(OtherPublicKey, gecc_der_header_nist192, der_ecc_nistp192_header_len); OtherPublickeylen = OtherPublickeylen + der_ecc_nistp192_header_len; OtherPublickeycipherType = kSSS_CipherType_EC_NIST_P; break; case MBEDTLS_ECP_DP_SECP224R1: memcpy(OtherPublicKey, gecc_der_header_nist224, der_ecc_nistp224_header_len); OtherPublickeylen = OtherPublickeylen + der_ecc_nistp224_header_len; OtherPublickeycipherType = kSSS_CipherType_EC_NIST_P; break; case MBEDTLS_ECP_DP_SECP256R1: memcpy(OtherPublicKey, gecc_der_header_nist256, der_ecc_nistp256_header_len); OtherPublickeylen = OtherPublickeylen + der_ecc_nistp256_header_len; OtherPublickeycipherType = kSSS_CipherType_EC_NIST_P; break; case MBEDTLS_ECP_DP_SECP384R1: memcpy(OtherPublicKey, gecc_der_header_nist384, der_ecc_nistp384_header_len); OtherPublickeylen = OtherPublickeylen + der_ecc_nistp384_header_len; OtherPublickeycipherType = kSSS_CipherType_EC_NIST_P; break; case MBEDTLS_ECP_DP_SECP521R1: memcpy(OtherPublicKey, gecc_der_header_nist521, der_ecc_nistp521_header_len); OtherPublickeylen = OtherPublickeylen + der_ecc_nistp521_header_len; OtherPublickeycipherType = kSSS_CipherType_EC_NIST_P; break; case MBEDTLS_ECP_DP_BP256R1: memcpy(OtherPublicKey, gecc_der_header_bp256, der_ecc_bp256_header_len); OtherPublickeylen = OtherPublickeylen + der_ecc_bp256_header_len; OtherPublickeycipherType = kSSS_CipherType_EC_BRAINPOOL; break; case MBEDTLS_ECP_DP_BP384R1: memcpy(OtherPublicKey, gecc_der_header_bp384, der_ecc_bp384_header_len); OtherPublickeylen = OtherPublickeylen + der_ecc_bp384_header_len; OtherPublickeycipherType = kSSS_CipherType_EC_BRAINPOOL; break; case MBEDTLS_ECP_DP_BP512R1: memcpy(OtherPublicKey, gecc_der_header_bp512, der_ecc_bp512_header_len); OtherPublickeylen = OtherPublickeylen + der_ecc_bp512_header_len; OtherPublickeycipherType = kSSS_CipherType_EC_BRAINPOOL; break; case MBEDTLS_ECP_DP_SECP192K1: memcpy(OtherPublicKey, gecc_der_header_192k, der_ecc_192k_header_len); OtherPublickeylen = OtherPublickeylen + der_ecc_192k_header_len; OtherPublickeycipherType = kSSS_CipherType_EC_NIST_K; break; case MBEDTLS_ECP_DP_SECP224K1: memcpy(OtherPublicKey, gecc_der_header_224k, der_ecc_224k_header_len); OtherPublickeylen = OtherPublickeylen + der_ecc_224k_header_len; OtherPublickeycipherType = kSSS_CipherType_EC_NIST_K; break; case MBEDTLS_ECP_DP_SECP256K1: memcpy(OtherPublicKey, gecc_der_header_256k, der_ecc_256k_header_len); OtherPublickeylen = OtherPublickeylen + der_ecc_256k_header_len; OtherPublickeycipherType = kSSS_CipherType_EC_NIST_K; break; case MBEDTLS_ECP_DP_CURVE25519: memcpy(OtherPublicKey, gecc_der_header_mont_dh_25519, der_ecc_mont_dh_25519_header_len); OtherPublickeylen = OtherPublickeylen + der_ecc_mont_dh_25519_header_len; OtherPublickeycipherType = kSSS_CipherType_EC_MONTGOMERY; break; case MBEDTLS_ECP_DP_CURVE448: memcpy(OtherPublicKey, gecc_der_header_mont_dh_448, der_ecc_mont_dh_448_header_len); OtherPublickeylen = OtherPublickeylen + der_ecc_mont_dh_448_header_len; OtherPublickeycipherType = kSSS_CipherType_EC_MONTGOMERY; break; default: return 1; } do { //For The derived shared secret init and allocate status = sss_key_object_init(&derivedKeyObject, grp->hostKs); if (status != kStatus_SSS_Success) { printf( " sss_key_object_init for derivedKeyObject " "Failed...\n"); ret = MBEDTLS_ERR_ECP_BAD_INPUT_DATA; break; } keyType = kSSS_KeyPart_Default; cipherType = kSSS_CipherType_AES; status = sss_key_object_allocate_handle( &derivedKeyObject, (__LINE__), keyType, cipherType, SharedSecretlen, kKeyObject_Mode_Transient); if (status != kStatus_SSS_Success) { LOG_E( " sss_key_object_allocate_handle for derivedKeyObject " "Failed"); ret = MBEDTLS_ERR_ECP_ALLOC_FAILED; break; } // SSCP Transient Object for the othe party public key init and allocate status = sss_key_object_init(&otherPartyKeyObject, grp->hostKs); if (status != kStatus_SSS_Success) { LOG_E( " sss_key_object_init for otherPartyKeyObject " "Failed"); ret = MBEDTLS_ERR_ECP_BAD_INPUT_DATA; break; } status = sss_key_object_allocate_handle(&otherPartyKeyObject, (__LINE__), kSSS_KeyPart_Public, OtherPublickeycipherType, (sizeof(OtherPublicKey)), kKeyObject_Mode_Transient); if (status != kStatus_SSS_Success) { LOG_E( " sss_key_object_allocate_handle for " "otherPartyKeyObject Failed"); ret = MBEDTLS_ERR_ECP_ALLOC_FAILED; break; } //setting the other party public key status = sss_key_store_set_key( grp->hostKs, &otherPartyKeyObject, OtherPublicKey, OtherPublickeylen, keyBitLen, NULL, 0); if (status != kStatus_SSS_Success) { LOG_E(" sss_key_store_set_key for keyPair Failed"); ret = MBEDTLS_ERR_ECP_BAD_INPUT_DATA; break; } status = sss_derive_key_context_init(&context, grp->pSSSObject->keyStore->session, grp->pSSSObject, kAlgorithm_SSS_ECDH, kMode_SSS_ComputeSharedSecret); if (status != kStatus_SSS_Success) { printf(" sss_derive_key_context_init Failed...\n"); ret = MBEDTLS_ERR_ECP_BAD_INPUT_DATA; break; } status = sss_derive_key_dh(&context, &otherPartyKeyObject, &derivedKeyObject); if (status != kStatus_SSS_Success) { printf(" sss_derive_key_dh Failed...\n"); ret = MBEDTLS_ERR_ECP_BAD_INPUT_DATA; break; } status = sss_key_store_get_key(grp->hostKs, &derivedKeyObject, buf, &bufByteLen, &bitLen); if (status != kStatus_SSS_Success) { printf(" sss_key_store_get_key Failed...\n"); ret = MBEDTLS_ERR_ECP_BAD_INPUT_DATA; break; } ret = mbedtls_mpi_read_binary(z, buf, bufByteLen); } while (0); sss_key_object_free(&otherPartyKeyObject); sss_key_object_free(&derivedKeyObject); } } else { ret = 1; //Failed } return (ret); } /* * Get parameters from a keypair */ int mbedtls_ecdh_get_params(mbedtls_ecdh_context *ctx, const mbedtls_ecp_keypair *key, mbedtls_ecdh_side side) { int ret; sss_object_t *backup_type_SSS_Object = ctx->grp.pSSSObject; sss_key_store_t *backup_type_hostKs = ctx->grp.hostKs; ret = mbedtls_ecdh_get_params_o(ctx, key, side); ctx->grp.pSSSObject = backup_type_SSS_Object; ctx->grp.hostKs = backup_type_hostKs; return (ret); } #if defined(MBEDTLS_ECDH_LEGACY_CONTEXT) typedef mbedtls_ecdh_context mbedtls_ecdh_context_mbed; int ecdh_get_params_internal(mbedtls_ecdh_context_mbed *ctx, const mbedtls_ecp_keypair *key, mbedtls_ecdh_side side) { return mbedtls_ecdh_get_params(ctx, key, side); } #endif #endif /* defined(MBEDTLS_ECDH_C) && defined(MBEDTLS_ECDH_ALT) */