| /* |
| * |
| * Copyright 2018-2020 NXP |
| * SPDX-License-Identifier: Apache-2.0 |
| */ |
| |
| /** @file */ |
| |
| #if defined(SSS_USE_FTR_FILE) |
| #include "fsl_sss_ftr.h" |
| #else |
| #include "fsl_sss_ftr_default.h" |
| #endif |
| |
| #if SSS_HAVE_APPLET_SE05X_IOT |
| |
| #if SSS_HAVE_HOSTCRYPTO_USER |
| #include <fsl_sss_user_apis.h> |
| #endif |
| |
| #if defined(FLOW_VERBOSE) |
| #define NX_LOG_ENABLE_SCP_DEBUG 1 |
| #endif |
| |
| #if SSS_HAVE_HOSTCRYPTO_ANY |
| |
| #include <fsl_sss_se05x_scp03.h> |
| #include <nxLog_scp.h> |
| #include <se05x_tlv.h> |
| #include <string.h> |
| |
| #include "nxEnsure.h" |
| #include "nxScp03_Apis.h" |
| #include "smCom.h" |
| #include "fsl_sss_lpc55s_apis.h" |
| |
| /* ************************************************************************** */ |
| /* Functions : Private function declaration */ |
| /* ************************************************************************** */ |
| |
| //#define INITIAL_HOST_CHALLANGE {0xAF,0x28,0xE1,0x16,0xD1,0x58,0x1E,0x89} |
| |
| /** |
| * To Initiate secure channel |
| */ |
| static sss_status_t nxScp03_GP_InitializeUpdate(pSe05xSession_t se05xSession, |
| uint8_t *hostChallenge, |
| uint16_t hostChallengeLen, |
| uint8_t *keyDivData, |
| uint16_t *pKeyDivDataLen, |
| uint8_t *keyInfo, |
| uint16_t *pKeyInfoLen, |
| uint8_t *cardChallenge, |
| uint16_t *pCardChallengeLen, |
| uint8_t *cardCryptoGram, |
| uint16_t *pCardCryptoGramLen, |
| uint8_t *seqCounter, |
| uint16_t *pSeqCounterLen, |
| uint8_t keyVerNo); |
| |
| static sss_status_t nxScp03_HostLocal_CalculateSessionKeys( |
| NXSCP03_AuthCtx_t *pAuthScp03, uint8_t *hostChallenge, uint8_t *cardChallenge); |
| |
| /** |
| * To authenticate the initiated secure channel |
| */ |
| static sss_status_t nxScp03_GP_ExternalAuthenticate( |
| pSe05xSession_t se05xSession, sss_object_t *keyObj, uint8_t *updateMCV, uint8_t *hostCryptogram); |
| |
| sss_status_t nxScp03_AuthenticateChannel(pSe05xSession_t se05xSession, NXSCP03_AuthCtx_t *pAuthScp03) |
| { |
| #ifdef INITIAL_HOST_CHALLANGE |
| uint8_t hostChallenge[] = INITIAL_HOST_CHALLANGE; |
| #else |
| uint8_t hostChallenge[SCP_GP_HOST_CHALLENGE_LEN]; |
| sss_rng_context_t rngctx; |
| #endif |
| uint8_t keyDivData[SCP_GP_IU_KEY_DIV_DATA_LEN]; |
| uint16_t keyDivDataLen = sizeof(keyDivData); |
| uint8_t keyInfo[SCP_GP_IU_KEY_INFO_LEN]; |
| uint16_t keyInfoLen = sizeof(keyInfo); |
| uint8_t cardChallenge[SCP_GP_CARD_CHALLENGE_LEN]; |
| uint16_t cardChallengeLen = sizeof(cardChallenge); |
| uint8_t cardCryptoGram[SCP_GP_IU_CARD_CRYPTOGRAM_LEN]; |
| uint16_t cardCryptoGramLen = sizeof(cardCryptoGram); |
| uint8_t seqCounter[SCP_GP_IU_SEQ_COUNTER_LEN]; |
| uint16_t seqCounterLen = sizeof(seqCounter); |
| uint8_t hostCryptogram[SCP_GP_IU_CARD_CRYPTOGRAM_LEN]; |
| |
| NXSCP03_StaticCtx_t *pStatic_ctx = pAuthScp03->pStatic_ctx; |
| NXSCP03_DynCtx_t *pDyn_ctx = pAuthScp03->pDyn_ctx; |
| |
| /* 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 */ |
| sss_status_t status = kStatus_SSS_Fail; |
| |
| if ((pStatic_ctx->Enc.keyStore == NULL) || (pStatic_ctx->Mac.keyStore == NULL) || |
| (pStatic_ctx->Dek.keyStore == NULL) || (pDyn_ctx->Enc.keyStore == NULL) || (pDyn_ctx->Mac.keyStore == NULL) || |
| (pDyn_ctx->Rmac.keyStore == NULL)) { |
| LOG_E("nxScp03_GP_InitializeUpdate fails Invalid objects sent %04X", status); |
| return status; |
| } |
| LOG_D("FN: %s", __FUNCTION__); |
| /* Get a random host challenge */ |
| #ifndef INITIAL_HOST_CHALLANGE |
| status = sss_host_rng_context_init(&rngctx, pStatic_ctx->Enc.keyStore->session); |
| ENSURE_OR_GO_EXIT(status == kStatus_SSS_Success); |
| |
| status = sss_host_rng_get_random(&rngctx, hostChallenge, SCP_GP_HOST_CHALLENGE_LEN); |
| LOG_MAU8_D(" Output: hostChallenge", hostChallenge, SCP_GP_HOST_CHALLENGE_LEN); |
| |
| sss_host_rng_context_free(&rngctx); |
| ENSURE_OR_GO_EXIT(status == kStatus_SSS_Success); |
| #endif |
| |
| status = nxScp03_GP_InitializeUpdate(se05xSession, |
| hostChallenge, |
| sizeof(hostChallenge), |
| keyDivData, |
| &keyDivDataLen, |
| keyInfo, |
| &keyInfoLen, |
| cardChallenge, |
| &cardChallengeLen, |
| cardCryptoGram, |
| &cardCryptoGramLen, |
| seqCounter, |
| &seqCounterLen, |
| pStatic_ctx->keyVerNo); |
| |
| if (status != kStatus_SSS_Success) { |
| LOG_E("nxScp03_GP_InitializeUpdate fails with Status %04X", status); |
| return status; |
| } |
| |
| status = nxScp03_HostLocal_CalculateSessionKeys(pAuthScp03, hostChallenge, cardChallenge); |
| ENSURE_OR_GO_EXIT(status == kStatus_SSS_Success); |
| |
| status = nxScp03_HostLocal_VerifyCardCryptogram(&pDyn_ctx->Mac, hostChallenge, cardChallenge, cardCryptoGram); |
| ENSURE_OR_GO_EXIT(status == kStatus_SSS_Success); |
| LOG_MAU8_D("cardCryptoGram", cardCryptoGram, SCP_GP_IU_CARD_CRYPTOGRAM_LEN); |
| |
| LOG_D("CardCryptogram verified successfully...Calculate HostCryptogram"); |
| status = nxScp03_HostLocal_CalculateHostCryptogram(&pDyn_ctx->Mac, hostChallenge, cardChallenge, hostCryptogram); |
| ENSURE_OR_GO_EXIT(status == kStatus_SSS_Success); |
| LOG_AU8_D(hostCryptogram, SCP_GP_IU_CARD_CRYPTOGRAM_LEN); |
| |
| status = nxScp03_GP_ExternalAuthenticate(se05xSession, &pDyn_ctx->Mac, pDyn_ctx->MCV, hostCryptogram); |
| if (status != kStatus_SSS_Success) { |
| LOG_E("GP_ExternalAuthenticate fails with Status %04X", status); |
| return status; |
| } |
| else { |
| // At this stage we have authenticated successfully. |
| status = kStatus_SSS_Success; |
| pDyn_ctx->SecurityLevel = (C_MAC | C_ENC | R_MAC | R_ENC); |
| memcpy(pDyn_ctx->cCounter, commandCounter, AES_KEY_LEN_nBYTE); |
| LOG_D("Authentication Successful!!!"); |
| } |
| |
| exit: |
| return status; |
| } |
| |
| static sss_status_t nxScp03_GP_ExternalAuthenticate( |
| pSe05xSession_t se05xSession, sss_object_t *keyObj, uint8_t *updateMCV, uint8_t *hostCryptogram) |
| { |
| smStatus_t st = 0; |
| uint8_t txBuf[64]; |
| uint8_t macToAdd[AES_KEY_LEN_nBYTE]; |
| |
| sss_mac_t macCtx; |
| sss_algorithm_t algorithm = kAlgorithm_SSS_CMAC_AES; |
| sss_mode_t mode = kMode_SSS_Mac; |
| size_t signatureLen = sizeof(macToAdd); |
| sss_status_t status = kStatus_SSS_Fail; |
| |
| tlvHeader_t hdr = { |
| {CLA_GP_7816 | CLA_GP_SECURITY_BIT, INS_GP_EXTERNAL_AUTHENTICATE, SECLVL_CDEC_RENC_CMAC_RMAC, 0x00}}; |
| |
| LOG_D("FN: %s", __FUNCTION__); |
| LOG_MAU8_D(" Input: hostCryptogram", hostCryptogram, SCP_COMMAND_MAC_SIZE); |
| |
| txBuf[0] = CLA_GP_7816 | CLA_GP_SECURITY_BIT; //Set CLA Byte |
| |
| txBuf[1] = INS_GP_EXTERNAL_AUTHENTICATE; //Set INS Byte |
| txBuf[2] = SECLVL_CDEC_RENC_CMAC_RMAC; //Set Security Level |
| |
| txBuf[3] = 0x00; |
| txBuf[4] = 0x10; // The Lc value is set as-if the MAC has already been appended (SCP03 spec p16. Fig.6-1) |
| memcpy(&txBuf[5], hostCryptogram, SCP_GP_IU_CARD_CRYPTOGRAM_LEN); |
| |
| LOG_D("Calculate the MAC on data"); |
| // Calculate the MAC value |
| status = sss_host_mac_context_init(&macCtx, keyObj->keyStore->session, keyObj, algorithm, mode); |
| ENSURE_OR_GO_EXIT(status == kStatus_SSS_Success); |
| |
| status = sss_host_mac_init(&macCtx); |
| ENSURE_OR_GO_EXIT(status == kStatus_SSS_Success); |
| |
| /* |
| * For the EXTERNAL AUTHENTICATE command MAC verification, the "MAC chaining value" is set to 16 |
| * bytes '00'. (SCP03 spec p16) |
| */ |
| memset(updateMCV, 0, SCP_MCV_LEN); |
| |
| status = sss_host_mac_update(&macCtx, updateMCV, AES_KEY_LEN_nBYTE); |
| ENSURE_OR_GO_EXIT(status == kStatus_SSS_Success); |
| |
| status = sss_host_mac_update(&macCtx, txBuf, 13); |
| ENSURE_OR_GO_EXIT(status == kStatus_SSS_Success); |
| |
| status = sss_host_mac_finish(&macCtx, macToAdd, &signatureLen); |
| ENSURE_OR_GO_EXIT(status == kStatus_SSS_Success); |
| |
| LOG_MAU8_D(" Output: Calculated MAC", macToAdd, SCP_COMMAND_MAC_SIZE); |
| sss_host_mac_context_free(&macCtx); |
| |
| LOG_D("Add calculated MAC Value to cmd Data"); |
| memcpy(updateMCV, macToAdd, AES_KEY_LEN_nBYTE); |
| memcpy(&txBuf[5 + SCP_GP_IU_CARD_CRYPTOGRAM_LEN], macToAdd, SCP_GP_IU_CARD_CRYPTOGRAM_LEN); |
| |
| LOG_D("Sending GP External Authenticate Command !!!"); |
| st = DoAPDUTx_s_Case3(se05xSession, &hdr, &txBuf[5], 16); |
| if (st != SM_OK) { |
| LOG_E("GP_ExternalAuthenticate returns %lX", st); |
| status = kStatus_SSS_Fail; |
| } |
| else { |
| status = kStatus_SSS_Success; |
| } |
| |
| exit: |
| return status; |
| } |
| |
| sss_status_t nxScp03_HostLocal_CalculateHostCryptogram( |
| sss_object_t *keyObj, uint8_t *hostChallenge, uint8_t *cardChallenge, uint8_t *hostCryptogram) |
| { |
| uint8_t ddA[128]; |
| uint16_t ddALen = sizeof(ddA); |
| uint8_t context[128]; |
| uint16_t contextLen = 0; |
| uint8_t hostCryptogramFullLength[AES_KEY_LEN_nBYTE]; |
| uint32_t signatureLen = sizeof(hostCryptogramFullLength); |
| sss_status_t status = kStatus_SSS_Fail; |
| |
| LOG_D("FN: %s", __FUNCTION__); |
| LOG_MAU8_D(" Input:hostChallenge", hostChallenge, SCP_GP_HOST_CHALLENGE_LEN); |
| LOG_MAU8_D(" Input:cardChallenge", cardChallenge, SCP_GP_CARD_CHALLENGE_LEN); |
| |
| memcpy(context, hostChallenge, SCP_GP_HOST_CHALLENGE_LEN); |
| memcpy(&context[SCP_GP_HOST_CHALLENGE_LEN], cardChallenge, SCP_GP_CARD_CHALLENGE_LEN); |
| contextLen = SCP_GP_HOST_CHALLENGE_LEN + SCP_GP_CARD_CHALLENGE_LEN; |
| |
| nxScp03_setDerivationData( |
| ddA, &ddALen, DATA_HOST_CRYPTOGRAM, DATA_DERIVATION_L_64BIT, DATA_DERIVATION_KDF_CTR, context, contextLen); |
| |
| status = nxScp03_Generate_SessionKey(keyObj, ddA, ddALen, hostCryptogramFullLength, &signatureLen); |
| ENSURE_OR_GO_EXIT(status == kStatus_SSS_Success); |
| |
| LOG_MAU8_D(" Output:hostCryptogram", hostCryptogramFullLength, AES_KEY_LEN_nBYTE); |
| |
| // Chop of the tail of the hostCryptogramFullLength |
| memcpy(hostCryptogram, hostCryptogramFullLength, SCP_GP_IU_CARD_CRYPTOGRAM_LEN); |
| exit: |
| return status; |
| } |
| |
| sss_status_t nxScp03_HostLocal_VerifyCardCryptogram( |
| sss_object_t *keyObj, uint8_t *hostChallenge, uint8_t *cardChallenge, uint8_t *cardCryptogram) |
| { |
| uint8_t ddA[128]; |
| uint16_t ddALen = sizeof(ddA); |
| uint8_t context[128]; |
| uint16_t contextLen = 0; |
| uint8_t cardCryptogramFullLength[AES_KEY_LEN_nBYTE]; |
| uint32_t signatureLen = sizeof(cardCryptogramFullLength); |
| sss_status_t status = kStatus_SSS_Fail; |
| |
| LOG_D("FN: %s", __FUNCTION__); |
| LOG_MAU8_D(" Input:hostChallenge", hostChallenge, SCP_GP_HOST_CHALLENGE_LEN); |
| LOG_MAU8_D(" Input:cardChallenge", cardChallenge, SCP_GP_CARD_CHALLENGE_LEN); |
| |
| memcpy(context, hostChallenge, SCP_GP_HOST_CHALLENGE_LEN); |
| memcpy(&context[SCP_GP_HOST_CHALLENGE_LEN], cardChallenge, SCP_GP_CARD_CHALLENGE_LEN); |
| contextLen = SCP_GP_HOST_CHALLENGE_LEN + SCP_GP_CARD_CHALLENGE_LEN; |
| |
| nxScp03_setDerivationData( |
| ddA, &ddALen, DATA_CARD_CRYPTOGRAM, DATA_DERIVATION_L_64BIT, DATA_DERIVATION_KDF_CTR, context, contextLen); |
| |
| status = nxScp03_Generate_SessionKey(keyObj, ddA, ddALen, cardCryptogramFullLength, &signatureLen); |
| ENSURE_OR_GO_EXIT(status == kStatus_SSS_Success); |
| |
| LOG_MAU8_D(" Output:cardCryptogram", cardCryptogramFullLength, AES_KEY_LEN_nBYTE); |
| |
| // Verify whether the 8 left most byte of cardCryptogramFullLength match cardCryptogram |
| if (memcmp(cardCryptogramFullLength, cardCryptogram, SCP_GP_IU_CARD_CRYPTOGRAM_LEN) != 0) |
| status = kStatus_SSS_Fail; |
| exit: |
| return status; |
| } |
| |
| static sss_status_t nxScp03_HostLocal_CalculateSessionKeys( |
| NXSCP03_AuthCtx_t *pAuthScp03, uint8_t *hostChallenge, uint8_t *cardChallenge) |
| { |
| uint8_t ddA[128]; |
| uint16_t ddALen = sizeof(ddA); |
| uint8_t context[128]; |
| uint16_t contextLen = 0; |
| 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; |
| sss_status_t status = kStatus_SSS_Fail; |
| NXSCP03_StaticCtx_t *pStatic_ctx = pAuthScp03->pStatic_ctx; |
| NXSCP03_DynCtx_t *pDyn_ctx = pAuthScp03->pDyn_ctx; |
| |
| // Calculate the Derviation data |
| memcpy(context, hostChallenge, SCP_GP_HOST_CHALLENGE_LEN); |
| memcpy(&context[SCP_GP_HOST_CHALLENGE_LEN], cardChallenge, SCP_GP_CARD_CHALLENGE_LEN); |
| contextLen = SCP_GP_HOST_CHALLENGE_LEN + SCP_GP_CARD_CHALLENGE_LEN; |
| LOG_D("FN: %s", __FUNCTION__); |
| LOG_MAU8_D(" Input:hostChallenge", hostChallenge, SCP_GP_HOST_CHALLENGE_LEN); |
| LOG_MAU8_D(" Input:cardChallenge", cardChallenge, SCP_GP_CARD_CHALLENGE_LEN); |
| |
| /* Generation and Creation of Session ENC SSS Key Object */ |
| |
| // Set the Derviation data |
| LOG_D("Set the Derviation data to generate Session ENC key"); |
| nxScp03_setDerivationData( |
| ddA, &ddALen, DATA_DERIVATION_SENC, DATA_DERIVATION_L_128BIT, DATA_DERIVATION_KDF_CTR, context, contextLen); |
| // Calculate the Session-ENC key |
| status = nxScp03_Generate_SessionKey(&pStatic_ctx->Enc, ddA, ddALen, sessionEncKey, &signatureLen); |
| ENSURE_OR_GO_EXIT(status == kStatus_SSS_Success); |
| LOG_MAU8_D(" Output: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 |
| LOG_D("Set the Derviation data to generate Session MAC key"); |
| nxScp03_setDerivationData( |
| ddA, &ddALen, DATA_DERIVATION_SMAC, DATA_DERIVATION_L_128BIT, DATA_DERIVATION_KDF_CTR, context, contextLen); |
| // Calculate the Session-MAC key |
| status = nxScp03_Generate_SessionKey(&pStatic_ctx->Mac, ddA, ddALen, sessionMacKey, &signatureLen); |
| ENSURE_OR_GO_EXIT(status == kStatus_SSS_Success); |
| LOG_MAU8_D(" Output: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 |
| LOG_D("Set the Derviation data to generate Session RMAC key"); |
| nxScp03_setDerivationData( |
| ddA, &ddALen, DATA_DERIVATION_SRMAC, DATA_DERIVATION_L_128BIT, DATA_DERIVATION_KDF_CTR, context, contextLen); |
| // Calculate the Session-RMAC key |
| status = nxScp03_Generate_SessionKey(&pStatic_ctx->Mac, ddA, ddALen, sessionRmacKey, &signatureLen); |
| ENSURE_OR_GO_EXIT(status == kStatus_SSS_Success); |
| LOG_MAU8_D(" Output: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); |
| exit: |
| return status; |
| } |
| |
| sss_status_t nxScp03_Generate_SessionKey( |
| sss_object_t *keyObj, uint8_t *inData, uint32_t inDataLen, uint8_t *outSignature, uint32_t *outSignatureLen) |
| { |
| sss_mac_t macCtx; |
| sss_algorithm_t algorithm = kAlgorithm_SSS_CMAC_AES; |
| sss_mode_t mode = kMode_SSS_Mac; |
| sss_status_t status = kStatus_SSS_Fail; |
| size_t sigLen = *outSignatureLen; |
| LOG_D("FN: %s", __FUNCTION__); |
| LOG_MAU8_D(" Input: inData", inData, inDataLen); |
| // Init MAC Context |
| status = sss_host_mac_context_init(&macCtx, keyObj->keyStore->session, keyObj, algorithm, mode); |
| ENSURE_OR_GO_EXIT(status == kStatus_SSS_Success); |
| |
| // Calculate Session key with MAC one go |
| status = sss_host_mac_one_go(&macCtx, inData, inDataLen, outSignature, &sigLen); |
| *outSignatureLen = (uint32_t)sigLen; |
| ENSURE_OR_GO_EXIT(status == kStatus_SSS_Success); |
| |
| LOG_MAU8_D(" Output:outSignature", outSignature, *outSignatureLen); |
| |
| // Free MAC context |
| sss_host_mac_context_free(&macCtx); |
| exit: |
| return status; |
| } |
| |
| static sss_status_t nxScp03_GP_InitializeUpdate(pSe05xSession_t se05xSession, |
| uint8_t *hostChallenge, |
| uint16_t hostChallengeLen, |
| uint8_t *keyDivData, |
| uint16_t *pKeyDivDataLen, |
| uint8_t *keyInfo, |
| uint16_t *pKeyInfoLen, |
| uint8_t *cardChallenge, |
| uint16_t *pCardChallengeLen, |
| uint8_t *cardCryptoGram, |
| uint16_t *pCardCryptoGramLen, |
| uint8_t *seqCounter, |
| uint16_t *pSeqCounterLen, |
| uint8_t keyVerNo) |
| { |
| smStatus_t st = 0; |
| uint8_t response[64]; |
| size_t responseLen = 64; |
| uint16_t parsePos = 0; |
| uint16_t sw = 0; |
| uint32_t iuResponseLenSmall = SCP_GP_IU_KEY_DIV_DATA_LEN + SCP_GP_IU_KEY_INFO_LEN + SCP_GP_CARD_CHALLENGE_LEN + |
| SCP_GP_IU_CARD_CRYPTOGRAM_LEN + SCP_GP_SW_LEN; |
| uint32_t iuResponseLenBig = SCP_GP_IU_KEY_DIV_DATA_LEN + SCP_GP_IU_KEY_INFO_LEN + SCP_GP_CARD_CHALLENGE_LEN + |
| SCP_GP_IU_CARD_CRYPTOGRAM_LEN + SCP_GP_IU_SEQ_COUNTER_LEN + SCP_GP_SW_LEN; |
| sss_status_t status = kStatus_SSS_Fail; |
| /* Default Key version no for applet scp is 0x00*/ |
| uint8_t keyVersion = 0x00; |
| if (se05xSession->authType == kSSS_AuthType_SCP03) { |
| /* Key version no. for Platform SCP03 passed by user*/ |
| keyVersion = keyVerNo; |
| /*Initialise update and external authenticate should go with auth type None |
| For Platform SCP03 as this is the authentication without session with JCOP */ |
| se05xSession->authType = kSSS_AuthType_None; |
| } |
| |
| tlvHeader_t hdr = {{CLA_GP_7816, INS_GP_INITIALIZE_UPDATE, keyVersion, 0x00}}; |
| |
| uint8_t cmdBuf[60]; |
| ENSURE_OR_GO_CLEANUP(hostChallengeLen == SCP_GP_HOST_CHALLENGE_LEN); |
| ENSURE_OR_GO_CLEANUP(*pKeyDivDataLen == SCP_GP_IU_KEY_DIV_DATA_LEN); |
| ENSURE_OR_GO_CLEANUP(*pKeyInfoLen == SCP_GP_IU_KEY_INFO_LEN); |
| ENSURE_OR_GO_CLEANUP(*pCardChallengeLen == SCP_GP_CARD_CHALLENGE_LEN); |
| ENSURE_OR_GO_CLEANUP(*pCardCryptoGramLen == SCP_GP_IU_CARD_CRYPTOGRAM_LEN); |
| |
| LOG_D("FN: %s", __FUNCTION__); |
| LOG_D("Input:keyVersion %02x", keyVersion); |
| LOG_MAU8_D(" Input: hostChallenge", hostChallenge, hostChallengeLen); |
| LOG_D("Sending GP Initialize Update Command !!!"); |
| memcpy(cmdBuf, hostChallenge, hostChallengeLen); |
| st = DoAPDUTxRx_s_Case4(se05xSession, &hdr, cmdBuf, hostChallengeLen, response, &responseLen); |
| if (st != SM_OK) { |
| LOG_E("GP_InitializeUpdate Failure on communication Link %04X", st); |
| return status; |
| } |
| |
| // Parse Response |
| // The expected result length depends on random (HOST-Channel) or pseudo-random (ADMIN-Channel) challenge type. |
| // The pseudo-random challenge case also includes a 3 byte sequence counter |
| if ((responseLen != iuResponseLenSmall) && (responseLen != iuResponseLenBig)) { |
| // Note: A response of length 2 (a proper SW) is also collapsed into return code SCP_FAIL |
| LOG_E("GP_InitializeUpdate Unexpected amount of data returned: %04X", responseLen); |
| return status; |
| } |
| |
| memcpy(keyDivData, response, SCP_GP_IU_KEY_DIV_DATA_LEN); |
| parsePos = SCP_GP_IU_KEY_DIV_DATA_LEN; |
| memcpy(keyInfo, &(response[parsePos]), SCP_GP_IU_KEY_INFO_LEN); |
| parsePos += SCP_GP_IU_KEY_INFO_LEN; |
| memcpy(cardChallenge, &(response[parsePos]), SCP_GP_CARD_CHALLENGE_LEN); |
| parsePos += SCP_GP_CARD_CHALLENGE_LEN; |
| memcpy(cardCryptoGram, &(response[parsePos]), SCP_GP_IU_CARD_CRYPTOGRAM_LEN); |
| parsePos += SCP_GP_IU_CARD_CRYPTOGRAM_LEN; |
| |
| // Construct Return Value |
| sw = (response[responseLen - 2] << 8) + response[responseLen - 1]; |
| if (sw == SM_OK) { |
| LOG_MAU8_D(" Output: keyDivData", keyDivData, *pKeyDivDataLen); |
| LOG_MAU8_D(" Output: keyInfo", keyInfo, *pKeyInfoLen); |
| LOG_MAU8_D(" Output: cardChallenge", cardChallenge, *pCardChallengeLen); |
| LOG_MAU8_D(" Output: cardCryptoGram", cardCryptoGram, *pCardCryptoGramLen); |
| status = kStatus_SSS_Success; |
| } |
| cleanup: |
| return status; |
| } |
| |
| void nxScp03_setDerivationData(uint8_t ddA[], |
| uint16_t *pDdALen, |
| uint8_t ddConstant, |
| uint16_t ddL, |
| uint8_t iCounter, |
| uint8_t *context, |
| uint16_t contextLen) |
| { |
| LOG_D("FN: %s", __FUNCTION__); |
| LOG_D("Input:ddConstant %02x", ddConstant); |
| LOG_D("Input:ddL %02x", ddL); |
| LOG_D("Input:iCounter %02x", iCounter); |
| LOG_MAU8_D(" Input: keyInfo", context, contextLen); |
| // SCPO3 spec p9&10 |
| memset(ddA, 0, DD_LABEL_LEN - 1); |
| ddA[DD_LABEL_LEN - 1] = ddConstant; |
| ddA[DD_LABEL_LEN] = 0x00; // Separation Indicator |
| ddA[DD_LABEL_LEN + 1] = (uint8_t)(ddL >> 8); |
| ddA[DD_LABEL_LEN + 2] = (uint8_t)ddL; |
| ddA[DD_LABEL_LEN + 3] = iCounter; |
| memcpy(&ddA[DD_LABEL_LEN + 4], context, contextLen); |
| *pDdALen = DD_LABEL_LEN + 4 + contextLen; |
| |
| LOG_MAU8_D("Output: KeyDivData", ddA, *pDdALen); |
| } |
| |
| #endif // SSS_HAVE_HOSTCRYPTO_ANY |
| |
| #endif // SSS_HAVE_APPLET_SE05X_IOT |