| /* Copyright 2019,2020 NXP |
| * SPDX-License-Identifier: Apache-2.0 |
| */ |
| |
| /** @file */ |
| |
| #if defined(FLOW_VERBOSE) |
| #define NX_LOG_ENABLE_SCP_DEBUG 1 |
| #endif |
| |
| #include <fsl_sss_se05x_apis.h> |
| |
| #if SSS_HAVE_APPLET_SE05X_IOT |
| #if SSS_HAVE_SCP_SCP03_SSS && SSSFTR_SE05X_AuthECKey |
| |
| #include <fsl_sss_se05x_scp03.h> |
| #include <nxEnsure.h> |
| #include <nxLog_scp.h> |
| #include <nxScp03_Apis.h> |
| #include <se05x_tlv.h> |
| #include <smCom.h> |
| #include <sm_const.h> |
| #include <string.h> |
| #if SSS_HAVE_MBEDTLS |
| #include "fsl_sss_mbedtls_types.h" |
| #elif SSS_HAVE_OPENSSL |
| #include "fsl_sss_openssl_types.h" |
| #endif |
| |
| /* ************************************************************************** */ |
| /* Functions : Private function declaration */ |
| /* ************************************************************************** */ |
| static sss_status_t nxECKey_InternalAuthenticate(pSe05xSession_t se05xSession, |
| SE05x_AuthCtx_ECKey_t *pAuthFScp, |
| uint8_t *hostEckaPubKey, |
| size_t hostEckaPubKeyLen, |
| uint8_t *rndData, |
| size_t *rndDataLen, |
| uint8_t *receipt, |
| size_t *receiptLen); |
| |
| static sss_status_t nxECKey_calculate_master_secret( |
| SE05x_AuthCtx_ECKey_t *pAuthFScp, uint8_t *rnd, size_t rndLen, uint8_t *sharedSecret, size_t sharedSecretLen); |
| |
| static sss_status_t nxECKey_HostLocal_CalculateSessionKeys(SE05x_AuthCtx_ECKey_t *pAuthFScp); |
| |
| static sss_status_t nxECKey_Calculate_Initial_Mac_Chaining_Value(SE05x_AuthCtx_ECKey_t *pAuthFScp); |
| |
| static sss_status_t nxECKey_Calculate_Shared_secret( |
| SE05x_AuthCtx_ECKey_t *pAuthFScp, uint8_t *sharedSecret, size_t *sharedSecretLen); |
| |
| #define TAG_PK_SE_ECKA 0x7F49 |
| #define TAG_SIG_SE_ECKA 0x5F37 |
| static sss_status_t nxECKey_GetVerify_SE_Ecka_Public( |
| pSe05xSession_t se05xSession, uint8_t *pSePubEcka, size_t *pSePubEckaLen); |
| |
| static void set_secp256r1nist_header(uint8_t *pbKey, size_t *pbKeyByteLen); |
| |
| int get_u8buf_2bTag(uint8_t *buf, size_t *pBufIndex, const size_t bufLen, uint16_t tag, uint8_t *rsp, size_t *pRspLen); |
| |
| /* ************************************************************************** */ |
| /* Functions : Function definition */ |
| /* ************************************************************************** */ |
| |
| sss_status_t nxECKey_AuthenticateChannel(pSe05xSession_t se05xSession, SE05x_AuthCtx_ECKey_t *pAuthFScp) |
| { |
| sss_status_t status = kStatus_SSS_Fail; |
| // Host public key to send to the SE for internal authenticate |
| uint8_t hostEckaPub[100]; |
| size_t hostEckaPubLen = sizeof(hostEckaPub); |
| size_t hostEckabitLen; |
| // Random bytes to retrive from SE in internal authenticate |
| uint8_t drSE[20]; |
| size_t drSELen = sizeof(drSE); |
| uint8_t receipt[16]; |
| size_t receiptLen = sizeof(receipt); |
| uint8_t shsSecret[32]; |
| size_t shsSecretLen = sizeof(shsSecret); |
| int offset = 0; |
| NXECKey03_StaticCtx_t *pStatic_ctx = pAuthFScp->pStatic_ctx; |
| NXSCP03_DynCtx_t *pDyn_ctx = pAuthFScp->pDyn_ctx; |
| uint8_t sePubkey[150] = { |
| 0, |
| }; // SE ECKA Public Key |
| size_t sePubkeyLen = sizeof(sePubkey); |
| uint8_t *pkSeEcka; |
| |
| /* clang-format off */ |
| const uint8_t commandCounter[16] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
| 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01}; |
| /* clang-format on */ |
| |
| /* Get the Host ephemeral key */ |
| uint8_t hostPubkey[100]; |
| status = sss_host_key_store_get_key( |
| pStatic_ctx->HostEcKeypair.keyStore, &pStatic_ctx->HostEcKeypair, hostPubkey, &hostEckaPubLen, &hostEckabitLen); |
| ENSURE_OR_GO_EXIT(status == kStatus_SSS_Success); |
| |
| /* Get Ecc public key in the plain form required for Security Storage |
| * according to GPCS Ammendment E For ECC Nist 256 key |
| */ |
| hostEckaPub[offset++] = GPCS_KEY_TYPE_ECC_NIST256; //Tag EC public key |
| hostEckaPub[offset++] = 0x41; // public key len |
| memcpy( |
| hostEckaPub + offset, hostPubkey + ASN_ECC_NIST_256_HEADER_LEN, hostEckaPubLen - ASN_ECC_NIST_256_HEADER_LEN); |
| offset += hostEckaPubLen - ASN_ECC_NIST_256_HEADER_LEN; |
| hostEckaPub[offset++] = KEY_PARAMETER_REFERENCE_TAG; |
| hostEckaPub[offset++] = KEY_PARAMETER_REFERENCE_VALUE_LEN; |
| hostEckaPub[offset++] = KEY_PARAMETER_REFERENCE_VALUE; |
| hostEckaPubLen = offset; |
| |
| /* Get SE ECKA Public Key*/ |
| status = nxECKey_GetVerify_SE_Ecka_Public(se05xSession, sePubkey, &sePubkeyLen); |
| ENSURE_OR_GO_EXIT(status == kStatus_SSS_Success); |
| |
| /* Create the Key in ASN1 Der format */ |
| pkSeEcka = &sePubkey[2]; // Exclude first two bytes Tag and len |
| sePubkeyLen = sePubkeyLen - 2; |
| set_secp256r1nist_header(pkSeEcka, &sePubkeyLen); |
| sePubkeyLen = sePubkeyLen - 2; // Exclude last three bytes Key parameter tag len and value |
| /*Set the key in Fast scp Host context*/ |
| status = sss_host_key_store_set_key( |
| pStatic_ctx->SeEcPubKey.keyStore, &pStatic_ctx->SeEcPubKey, pkSeEcka, sePubkeyLen, 256, NULL, 0); |
| ENSURE_OR_GO_EXIT(status == kStatus_SSS_Success); |
| |
| status = nxECKey_InternalAuthenticate( |
| se05xSession, pAuthFScp, hostEckaPub, hostEckaPubLen, drSE, &drSELen, receipt, &receiptLen); |
| ENSURE_OR_GO_EXIT(status == kStatus_SSS_Success); |
| |
| /*Calculate the Shared Secret */ |
| status = nxECKey_Calculate_Shared_secret(pAuthFScp, shsSecret, &shsSecretLen); |
| ENSURE_OR_GO_EXIT(status == kStatus_SSS_Success); |
| |
| /*Erase the host key pair as it is no longer needed*/ |
| memset(hostEckaPub, 0, sizeof(hostEckaPub)); |
| memset(hostPubkey, 0, sizeof(hostPubkey)); |
| sss_key_object_free(&pStatic_ctx->HostEcKeypair); |
| |
| status = nxECKey_calculate_master_secret(pAuthFScp, drSE, drSELen, shsSecret, shsSecretLen); |
| ENSURE_OR_GO_EXIT(status == kStatus_SSS_Success); |
| |
| status = nxECKey_HostLocal_CalculateSessionKeys(pAuthFScp); |
| ENSURE_OR_GO_EXIT(status == kStatus_SSS_Success); |
| /* Increment the command Encreption counter to 1*/ |
| memcpy(pDyn_ctx->cCounter, commandCounter, AES_KEY_LEN_nBYTE); |
| |
| /* compute the initial MAC chaining value */ |
| status = nxECKey_Calculate_Initial_Mac_Chaining_Value(pAuthFScp); |
| ENSURE_OR_GO_EXIT(status == kStatus_SSS_Success); |
| pDyn_ctx->SecurityLevel = (uint8_t)SECURITY_LEVEL; |
| exit: |
| return status; |
| } |
| |
| static sss_status_t nxECKey_Calculate_Initial_Mac_Chaining_Value(SE05x_AuthCtx_ECKey_t *pAuthFScp) |
| { |
| sss_status_t status = kStatus_SSS_Fail; |
| uint8_t ddA[128]; |
| uint16_t ddALen = sizeof(ddA); |
| uint8_t iniMacChaining[AES_KEY_LEN_nBYTE]; |
| uint32_t signatureLen = AES_KEY_LEN_nBYTE; |
| NXECKey03_StaticCtx_t *pStatic_ctx = pAuthFScp->pStatic_ctx; |
| NXSCP03_DynCtx_t *pDyn_ctx = pAuthFScp->pDyn_ctx; |
| |
| // Set the Derviation data |
| nxScp03_setDerivationData( |
| ddA, &ddALen, DATA_DERIVATION_INITIAL_MCV, DATA_DERIVATION_L_128BIT, DATA_DERIVATION_KDF_CTR, NULL, 0); |
| // Calculate the Initial MCV value |
| status = nxScp03_Generate_SessionKey(&pStatic_ctx->masterSec, ddA, ddALen, iniMacChaining, &signatureLen); |
| ENSURE_OR_GO_EXIT(status == kStatus_SSS_Success); |
| LOG_MAU8_D("Initial MCV", iniMacChaining, AES_KEY_LEN_nBYTE); |
| // Set the Initial MCV value |
| memcpy(pDyn_ctx->MCV, iniMacChaining, AES_KEY_LEN_nBYTE); |
| exit: |
| return status; |
| } |
| |
| static sss_status_t nxECKey_HostLocal_CalculateSessionKeys(SE05x_AuthCtx_ECKey_t *pAuthFScp) |
| { |
| sss_status_t status = kStatus_SSS_Fail; |
| uint8_t ddA[128]; |
| uint16_t ddALen = sizeof(ddA); |
| uint8_t sessionEncKey[AES_KEY_LEN_nBYTE]; |
| uint8_t sessionMacKey[AES_KEY_LEN_nBYTE]; |
| uint8_t sessionRmacKey[AES_KEY_LEN_nBYTE]; |
| uint32_t signatureLen = AES_KEY_LEN_nBYTE; |
| NXECKey03_StaticCtx_t *pStatic_ctx = pAuthFScp->pStatic_ctx; |
| NXSCP03_DynCtx_t *pDyn_ctx = pAuthFScp->pDyn_ctx; |
| |
| /* Generation and Creation of Session ENC SSS Key Object */ |
| |
| // Set the Derviation data |
| nxScp03_setDerivationData( |
| ddA, &ddALen, DATA_DERIVATION_SENC, DATA_DERIVATION_L_128BIT, DATA_DERIVATION_KDF_CTR, NULL, 0); |
| // Calculate the Session-ENC key |
| status = nxScp03_Generate_SessionKey(&pStatic_ctx->masterSec, ddA, ddALen, sessionEncKey, &signatureLen); |
| ENSURE_OR_GO_EXIT(status == kStatus_SSS_Success); |
| LOG_MAU8_D("sessionEncKey", sessionEncKey, AES_KEY_LEN_nBYTE); |
| // Set the Session-ENC key |
| status = sss_host_key_store_set_key(pDyn_ctx->Enc.keyStore, &pDyn_ctx->Enc, sessionEncKey, 16, (16) * 8, NULL, 0); |
| ENSURE_OR_GO_EXIT(status == kStatus_SSS_Success); |
| |
| /* Generation and Creation of Session MAC SSS Key Object */ |
| |
| // Set the Derviation data |
| nxScp03_setDerivationData( |
| ddA, &ddALen, DATA_DERIVATION_SMAC, DATA_DERIVATION_L_128BIT, DATA_DERIVATION_KDF_CTR, NULL, 0); |
| // Calculate the Session-MAC key |
| status = nxScp03_Generate_SessionKey(&pStatic_ctx->masterSec, ddA, ddALen, sessionMacKey, &signatureLen); |
| ENSURE_OR_GO_EXIT(status == kStatus_SSS_Success); |
| LOG_MAU8_D("sessionMacKey", sessionMacKey, AES_KEY_LEN_nBYTE); |
| // Set the Session-MAC key |
| status = sss_host_key_store_set_key(pDyn_ctx->Mac.keyStore, &pDyn_ctx->Mac, sessionMacKey, 16, (16) * 8, NULL, 0); |
| ENSURE_OR_GO_EXIT(status == kStatus_SSS_Success); |
| |
| /* Generation and Creation of Session RMAC SSS Key Object */ |
| |
| // Set the Derviation data |
| nxScp03_setDerivationData( |
| ddA, &ddALen, DATA_DERIVATION_SRMAC, DATA_DERIVATION_L_128BIT, DATA_DERIVATION_KDF_CTR, NULL, 0); |
| // Calculate the Session-RMAC key |
| status = nxScp03_Generate_SessionKey(&pStatic_ctx->masterSec, ddA, ddALen, sessionRmacKey, &signatureLen); |
| ENSURE_OR_GO_EXIT(status == kStatus_SSS_Success); |
| LOG_MAU8_D("sessionRmacKey", sessionRmacKey, AES_KEY_LEN_nBYTE); |
| // Set the Session-RMAC key |
| status = |
| sss_host_key_store_set_key(pDyn_ctx->Rmac.keyStore, &pDyn_ctx->Rmac, sessionRmacKey, 16, (16) * 8, NULL, 0); |
| ENSURE_OR_GO_EXIT(status == kStatus_SSS_Success); |
| exit: |
| return status; |
| } |
| |
| static sss_status_t nxECKey_calculate_master_secret( |
| SE05x_AuthCtx_ECKey_t *pAuthFScp, uint8_t *rnd, size_t rndLen, uint8_t *sharedSecret, size_t sharedSecretLen) |
| { |
| sss_status_t status = kStatus_SSS_Fail; |
| sss_digest_t md; |
| uint8_t derivationInput[100] = {0}; |
| uint8_t masterSk[32]; |
| size_t masterSkLen = sizeof(masterSk); |
| size_t derivationInputLen = 0; |
| NXECKey03_StaticCtx_t *pStatic_ctx = pAuthFScp->pStatic_ctx; |
| |
| if (pAuthFScp->pDyn_ctx->authType == kSSS_AuthType_INT_ECKey_Counter) { |
| const uint8_t kdf_counter[] = {0x00, 0x00, 0x00, 0x01}; |
| memcpy(&derivationInput[derivationInputLen], kdf_counter, sizeof(kdf_counter)); |
| derivationInputLen += sizeof(kdf_counter); |
| } |
| memcpy(&derivationInput[derivationInputLen], sharedSecret, sharedSecretLen); |
| derivationInputLen += sharedSecretLen; |
| memcpy(&derivationInput[derivationInputLen], rnd, rndLen); |
| derivationInputLen += rndLen; |
| |
| derivationInput[derivationInputLen++] = SCP_CONFIG; |
| derivationInput[derivationInputLen++] = SECURITY_LEVEL; |
| derivationInput[derivationInputLen++] = GPCS_KEY_TYPE_AES; |
| derivationInput[derivationInputLen++] = GPCS_KEY_LEN_AES; |
| |
| status = sss_host_digest_context_init( |
| &md, pStatic_ctx->HostEcdsaObj.keyStore->session, kAlgorithm_SSS_SHA256, kMode_SSS_Digest); |
| ENSURE_OR_GO_CLEANUP(status == kStatus_SSS_Success); |
| status = sss_host_digest_one_go(&md, derivationInput, derivationInputLen, masterSk, &masterSkLen); |
| ENSURE_OR_GO_CLEANUP(status == kStatus_SSS_Success); |
| sss_host_digest_context_free(&md); |
| masterSkLen = 16; |
| LOG_MAU8_D("Master Secret", masterSk, masterSkLen); |
| /*Set the Master secret as AES Key*/ |
| status = sss_host_key_store_set_key( |
| pStatic_ctx->masterSec.keyStore, &pStatic_ctx->masterSec, masterSk, masterSkLen, masterSkLen * 8, NULL, 0); |
| ENSURE_OR_GO_CLEANUP(status == kStatus_SSS_Success); |
| cleanup: |
| return status; |
| } |
| |
| static void set_secp256r1nist_header(uint8_t *pbKey, size_t *pbKeyByteLen) |
| { |
| unsigned int i = 0; |
| /* clang-format off */ |
| char temp[112] = { 0x30, 0x59, 0x30, 0x13, 0x06, 0x07, 0x2A, 0x86, 0x48, 0xCE, 0x3D, |
| 0x02, 0x01, 0x06, 0x08, 0x2A, 0x86, 0x48, 0xCE, 0x3D, 0x03, 0x01, |
| 0x07, 0x03, 0x42, 0x00 }; |
| /* clang-format on */ |
| |
| for (i = 0; i < *pbKeyByteLen; i++) { |
| temp[26 + i] = pbKey[i]; |
| } |
| |
| *pbKeyByteLen = *pbKeyByteLen + 26; |
| memcpy(pbKey, temp, *pbKeyByteLen); |
| } |
| |
| sss_status_t nxECKey_InternalAuthenticate(pSe05xSession_t se05xSession, |
| SE05x_AuthCtx_ECKey_t *pAuthFScp, |
| uint8_t *hostEckaPubKey, |
| size_t hostEckaPubKeyLen, |
| uint8_t *rndData, |
| size_t *rndDataLen, |
| uint8_t *receipt, |
| size_t *receiptLen) |
| { |
| sss_status_t status = kStatus_SSS_Fail; |
| smStatus_t retStatus = SM_NOT_OK; |
| int tlvRet = 0; |
| uint8_t cmdbuf[256]; |
| size_t cmdbufLen = 0; |
| uint8_t *pCmdbuf = NULL; |
| uint8_t rspbuf[256]; |
| uint8_t *pRspbuf = &rspbuf[0]; |
| size_t rspbufLen = ARRAY_SIZE(rspbuf); |
| sss_digest_t md; |
| uint8_t md_host5F37[32]; |
| size_t md_host5F37Len = sizeof(md_host5F37); |
| NXECKey03_StaticCtx_t *pStatic_ctx = pAuthFScp->pStatic_ctx; |
| |
| const uint8_t tagEpkSeEcka[] = {0x7F, 0x49}; |
| const uint8_t tagSigSeEcka[] = {0x5F, 0x37}; |
| |
| const tlvHeader_t hdr = {{CLA_GP_7816 | CLA_GP_SECURITY_BIT, INS_GP_INTERNAL_AUTHENTICATE, 00, 00}}; |
| uint8_t scpParms[3] = {0xAB, SCP_CONFIG, SECURITY_LEVEL}; |
| uint8_t appletName[APPLET_NAME_LEN] = APPLET_NAME; |
| sss_asymmetric_t asym; |
| uint8_t sig_host5F37[100]; |
| size_t sig_host5F37Len = sizeof(sig_host5F37); |
| |
| size_t cntrlRefTemp_Len = 0 + 1 + 1 + APPLET_NAME_LEN /*TLV AID */ + 1 + 1 + sizeof(scpParms) /* TLV SCP Params */ + |
| 1 + 1 + 1 /* TLV Keytype */ + 1 + 1 + 1 /* TLV KeyLEN */; |
| |
| #if NX_LOG_ENABLE_SCP_DEBUG |
| nLog("APDU", NX_LEVEL_DEBUG, "ECKey Internal authenticate []"); |
| #endif /* VERBOSE_APDU_LOGS */ |
| cmdbuf[0] = kSE05x_TAG_GP_CONTRL_REF_PARM; // Tag Control reference template |
| cmdbuf[1] = (uint8_t)cntrlRefTemp_Len; |
| cmdbufLen = 2; |
| pCmdbuf = &cmdbuf[2]; |
| tlvRet = TLVSET_u8buf("SE05x AID", &pCmdbuf, &cmdbufLen, kSE05x_GP_TAG_AID, appletName, APPLET_NAME_LEN); |
| ENSURE_OR_GO_CLEANUP(tlvRet == 0); |
| tlvRet = TLVSET_u8buf("SCP parameters", &pCmdbuf, &cmdbufLen, kSE05x_GP_TAG_SCP_PARMS, scpParms, sizeof(scpParms)); |
| ENSURE_OR_GO_CLEANUP(tlvRet == 0); |
| tlvRet = TLVSET_U8("Key Type", &pCmdbuf, &cmdbufLen, kSE05x_GP_TAG_KEY_TYPE, GPCS_KEY_TYPE_AES); |
| ENSURE_OR_GO_CLEANUP(tlvRet == 0); |
| tlvRet = TLVSET_U8("Key length", &pCmdbuf, &cmdbufLen, kSE05x_GP_TAG_KEY_LEN, GPCS_KEY_LEN_AES); |
| ENSURE_OR_GO_CLEANUP(tlvRet == 0); |
| |
| /*Put the ephemral host ECKA pub key */ |
| *pCmdbuf++ = tagEpkSeEcka[0]; //Tag is 2 byte */ |
| cmdbufLen++; |
| *pCmdbuf++ = tagEpkSeEcka[1]; |
| cmdbufLen++; |
| *pCmdbuf++ = (uint8_t)hostEckaPubKeyLen; |
| cmdbufLen++; |
| memcpy(pCmdbuf, hostEckaPubKey, hostEckaPubKeyLen); |
| cmdbufLen += hostEckaPubKeyLen; |
| |
| /* Get the sha256 hash of Control_refernce_template + host ECKA Pub key */ |
| status = sss_host_digest_context_init( |
| &md, pStatic_ctx->HostEcdsaObj.keyStore->session, kAlgorithm_SSS_SHA256, kMode_SSS_Digest); |
| ENSURE_OR_GO_CLEANUP(status == kStatus_SSS_Success); |
| status = sss_host_digest_one_go(&md, cmdbuf, cmdbufLen, md_host5F37, &md_host5F37Len); |
| ENSURE_OR_GO_CLEANUP(status == kStatus_SSS_Success); |
| sss_host_digest_context_free(&md); |
| |
| /* Get the signiture over hash*/ |
| status = sss_host_asymmetric_context_init(&asym, |
| pStatic_ctx->HostEcdsaObj.keyStore->session, |
| &pStatic_ctx->HostEcdsaObj, |
| kAlgorithm_SSS_SHA256, |
| kMode_SSS_Sign); |
| ENSURE_OR_GO_CLEANUP(status == kStatus_SSS_Success); |
| status = sss_host_asymmetric_sign_digest(&asym, md_host5F37, md_host5F37Len, sig_host5F37, &sig_host5F37Len); |
| ENSURE_OR_GO_CLEANUP(status == kStatus_SSS_Success); |
| sss_host_asymmetric_context_free(&asym); |
| |
| /* Put the Control refernce template Value signiture*/ |
| pCmdbuf = &cmdbuf[cmdbufLen]; |
| *pCmdbuf++ = tagSigSeEcka[0]; |
| cmdbufLen++; |
| *pCmdbuf++ = tagSigSeEcka[1]; |
| cmdbufLen++; |
| *pCmdbuf++ = (uint8_t)sig_host5F37Len; |
| cmdbufLen++; |
| memcpy(pCmdbuf, sig_host5F37, sig_host5F37Len); |
| cmdbufLen += sig_host5F37Len; |
| status = kStatus_SSS_Fail; |
| retStatus = DoAPDUTxRx_s_Case4(se05xSession, &hdr, cmdbuf, cmdbufLen, rspbuf, &rspbufLen); |
| if (retStatus == SM_OK) { |
| size_t rspIndex = 0; |
| tlvRet = tlvGet_u8buf( |
| pRspbuf, &rspIndex, rspbufLen, kSE05x_GP_TAG_DR_SE, rndData, rndDataLen); /* Get the Random No */ |
| ENSURE_OR_GO_CLEANUP(tlvRet == 0); |
| tlvRet = tlvGet_u8buf( |
| pRspbuf, &rspIndex, rspbufLen, kSE05x_GP_TAG_RECEIPT, receipt, receiptLen); /* Get the Receipt */ |
| ENSURE_OR_GO_CLEANUP(tlvRet == 0); |
| ENSURE_OR_GO_CLEANUP((rspIndex + 2) == rspbufLen); |
| retStatus = (pRspbuf[rspIndex] << 8) | (pRspbuf[rspIndex + 1]); |
| ENSURE_OR_GO_CLEANUP(retStatus == SM_OK); |
| status = kStatus_SSS_Success; |
| } |
| cleanup: |
| return status; |
| } |
| |
| sss_status_t nxECKey_GetVerify_SE_Ecka_Public(pSe05xSession_t se05xSession, uint8_t *pSePubEcka, size_t *pSePubEckaLen) |
| { |
| smStatus_t retStatus = SM_NOT_OK; |
| sss_status_t status = kStatus_SSS_Fail; |
| int tlvRet = 0; |
| uint8_t cmdbuf[100]; |
| uint8_t rspbuf[512]; |
| uint8_t *pRspbuf = &rspbuf[0]; |
| size_t rspbufLen = ARRAY_SIZE(rspbuf); |
| |
| uint8_t sigSePubkey[100]; |
| size_t sigSePubkeyLen = sizeof(sigSePubkey); |
| size_t i = 0; |
| |
| const tlvHeader_t hdr = {{CLA_GP_7816, INS_GP_GET_DATA, P1_GP_GET_DATA, P2_GP_GET_DATA}}; |
| size_t cntrlRefTemp_Len = 0 + 1 + 1 + 2; /*TLV Key */ |
| |
| cmdbuf[i++] = kSE05x_TAG_GP_CONTRL_REF_PARM; // Tag Control reference template |
| cmdbuf[i++] = (uint8_t)cntrlRefTemp_Len; |
| cmdbuf[i++] = kSE05x_GP_TAG_GET_DATA; |
| cmdbuf[i++] = 0x02; |
| cmdbuf[i++] = 0x00; //Key Identifier |
| cmdbuf[i++] = 0x00; //Key Version Number |
| |
| retStatus = DoAPDUTxRx_s_Case4(se05xSession, &hdr, cmdbuf, i, rspbuf, &rspbufLen); |
| ENSURE_OR_GO_CLEANUP(retStatus == SM_OK); |
| |
| i = 0; |
| /* Get the Public Key*/ |
| tlvRet = get_u8buf_2bTag(pRspbuf, &i, rspbufLen, (uint16_t)TAG_PK_SE_ECKA, pSePubEcka, pSePubEckaLen); |
| if (0 != tlvRet) { |
| goto cleanup; |
| } |
| /* Get the signiture */ |
| tlvRet = get_u8buf_2bTag(pRspbuf, &i, rspbufLen, (uint16_t)TAG_SIG_SE_ECKA, sigSePubkey, &sigSePubkeyLen); |
| if (0 != tlvRet) { |
| goto cleanup; |
| } |
| |
| ENSURE_OR_GO_CLEANUP((i + 2) == rspbufLen) |
| retStatus = (pRspbuf[i] << 8) | (pRspbuf[i + 1]); |
| ENSURE_OR_GO_CLEANUP(retStatus == SM_OK); |
| status = kStatus_SSS_Success; |
| cleanup: |
| return status; |
| } |
| |
| int get_u8buf_2bTag(uint8_t *buf, size_t *pBufIndex, const size_t bufLen, uint16_t tag, uint8_t *rsp, size_t *pRspLen) |
| { |
| int retVal = 1; |
| uint8_t *pBuf = buf + (*pBufIndex); |
| uint16_t got_tag; |
| got_tag = ((*pBuf++) << 8) & 0xFFFF; |
| got_tag |= ((*pBuf++)) & 0xFFFF; |
| size_t extendedLen; |
| size_t rspLen; |
| //size_t len; |
| if (got_tag != tag) |
| goto cleanup; |
| rspLen = *pBuf++; |
| |
| if (rspLen <= 0x7FU) { |
| extendedLen = rspLen; |
| *pBufIndex += (2 + 1); |
| } |
| else if (rspLen == 0x81) { |
| extendedLen = *pBuf++; |
| *pBufIndex += (2 + 1 + 1); |
| } |
| else if (rspLen == 0x82) { |
| extendedLen = *pBuf++; |
| extendedLen = (extendedLen << 8) | *pBuf++; |
| *pBufIndex += (2 + 1 + 2); |
| } |
| else { |
| goto cleanup; |
| } |
| |
| if (extendedLen > *pRspLen) |
| goto cleanup; |
| if (extendedLen > bufLen) |
| goto cleanup; |
| |
| *pRspLen = extendedLen; |
| *pBufIndex += extendedLen; |
| while (extendedLen-- > 0) { |
| *rsp++ = *pBuf++; |
| } |
| retVal = 0; |
| cleanup: |
| return retVal; |
| } |
| |
| sss_status_t nxECKey_Calculate_Shared_secret( |
| SE05x_AuthCtx_ECKey_t *pAuthFScp, uint8_t *sharedSecret, size_t *sharedSecretLen) |
| { |
| sss_status_t status = kStatus_SSS_Fail; |
| sss_derive_key_t dervCtx; |
| sss_object_t shsSecret; |
| |
| NXECKey03_StaticCtx_t *pStatic_ctx = pAuthFScp->pStatic_ctx; |
| size_t sharedSecBitLen = 0; |
| |
| status = sss_host_key_object_init(&shsSecret, pStatic_ctx->SeEcPubKey.keyStore); |
| ENSURE_OR_GO_CLEANUP(status == kStatus_SSS_Success); |
| |
| status = sss_host_key_object_allocate_handle( |
| &shsSecret, __LINE__, kSSS_KeyPart_Default, kSSS_CipherType_AES, 32, kKeyObject_Mode_Transient); |
| ENSURE_OR_GO_CLEANUP(status == kStatus_SSS_Success); |
| |
| status = sss_host_derive_key_context_init(&dervCtx, |
| pStatic_ctx->HostEcKeypair.keyStore->session, |
| &pStatic_ctx->HostEcKeypair, |
| kAlgorithm_SSS_ECDH, |
| kMode_SSS_ComputeSharedSecret); |
| ENSURE_OR_GO_CLEANUP(status == kStatus_SSS_Success); |
| |
| status = sss_host_derive_key_dh(&dervCtx, &pStatic_ctx->SeEcPubKey, &shsSecret); |
| ENSURE_OR_GO_CLEANUP(status == kStatus_SSS_Success); |
| |
| status = |
| sss_host_key_store_get_key(&shsSecret.keyStore, &shsSecret, sharedSecret, sharedSecretLen, &sharedSecBitLen); |
| ENSURE_OR_GO_CLEANUP(status == kStatus_SSS_Success); |
| |
| LOG_MAU8_D("Shared Secret", sharedSecret, *sharedSecretLen); |
| |
| cleanup: |
| sss_host_derive_key_context_free(&dervCtx); |
| sss_host_key_object_free(&shsSecret); |
| return status; |
| } |
| #endif /* defined SSS_HAVE_SCP_SCP03_SSS */ |
| #endif /* SSS_HAVE_APPLET_SE05X_IOT */ |