#ifndef _UDS_FBL_SERVICE_27_SOURCE #define _UDS_FBL_SERVICE_27_SOURCE /******************************************************************************* ** Include Section ** *******************************************************************************/ #include "uds_fbl_mgr.h" #include "uds_fbl_service27.h" #include "../app/bl_task.h" #include /******************************************************************************* ** Version Information ** *******************************************************************************/ /******************************************************************************* ** Version Check ** *******************************************************************************/ /******************************************************************************* ** Macro definition ** *******************************************************************************/ #define LEARNMASK 0x27AB4C5E #define FBL_APPKEYCONST 0xA72364AA /******************************************************************************* ** Global Data ** *******************************************************************************/ static uint8_t org_seed_buf[UDS_SEED_LENGTH]; static uint8_t req_seed; static uint8_t fail_time; static bool delay_timer_active; /* when verified key failed for 3 times,delay 10s */ static uint8_t curr_sa; static uint8_t FAA_flag; /* stored in work flash */ /*Step1: Acquire 4 byte seed from ECU. Say Seed [4].*/ uint8_t u8Seed2[4]; /* The Code, AppKeyConst [4] of CHLI_L is 0xA72364AA. */ uint8_t u8AppKeyConst[4] = {0xA7,0x23,0x64,0xAA}; uint8_t u8key1[4]; uint8_t u8key2[4]; const uds_nrc nrc_2701[3] = { UDSincorrectMessageLengthOrInvalidFormat,\ UDSconditionNotCorrect,\ requiredTimeDelayNotExpired }; const uds_nrc nrc_2702[3] = { UDSincorrectMessageLengthOrInvalidFormat,\ UDSconditionNotCorrect,\ UDSrequestSequenceError }; /*--------- <0x11> sub function config start-------------*/ static const DIAG_sunfunction_t SessionSubfunction[] = { {0x01 ,2,false,2,6,NULL,{nrc_2701, 3}}, {0x02 ,2,false,6,2,NULL,{nrc_2702, 3}} }; /*--------- <0x11> sub function config end---------------*/ /*-------------------------------------------------------*/ /******************************************************************************* ** Function Definitions ** *******************************************************************************/ static uint8_t service27_SetFAAFlag(void); /*===============================================================================================*/ /* uint8_t service27_write_faaflag(uint8_t flag) */ /* ----------------------------------------------------------------------------------------------*/ /* Function: write FAA flag to workflash */ /* Arguments: flag : FAA flag */ /* Return: write status */ /*===============================================================================================*/ uint8_t service27_write_faaflag(uint8_t flag) { uint8_t enFAAflag[4] ={1,0,0,0}; uint8_t disFAAflag[4] ={0,0,0,0}; uint8_t result; if(TRUE == flag) { result = Dataflash_Common_WriteToRAM(DID_FAA_27_FAIL_FLAG,enFAAflag); } else { result = Dataflash_Common_WriteToRAM(DID_FAA_27_FAIL_FLAG,disFAAflag); } return result; } /*===============================================================================================*/ /* void service27_generate_seed(UDSpacket_t* qUDSpacket) */ /* ----------------------------------------------------------------------------------------------*/ /* Function: 27 service generate seed */ /* Arguments: qUDSpacket : CAN message structure pointer */ /* Return: - */ /*===============================================================================================*/ void service27_generate_seed(UDSpacket_t* qUDSpacket) { uint8_t i; uint8_t sendSeed[UDS_SEED_LENGTH]; if (curr_sa == UDS_SA_LV4) { for (i = 0; i < UDS_SEED_LENGTH; i++) { sendSeed[i] = 0; } } else { if(req_seed == 0) { for (i = 0; i < UDS_SEED_LENGTH; i++) { org_seed_buf[i] = service27_rand(); sendSeed[i] = org_seed_buf[i]; } req_seed = 1; /* the reqseed has received */ } else { for (i = 0; i < UDS_SEED_LENGTH; i++) { sendSeed[i] = org_seed_buf[i]; } service27_SetFAAFlag(); } } qUDSpacket->size = 6; qUDSpacket->Data.Byte[0] = UDS_GET_POSITIVE_RSP(qUDSpacket->Data.Byte[0]); memcpy(&qUDSpacket->Data.Byte[2],sendSeed,UDS_SEED_LENGTH); } /*===============================================================================================*/ /* void service27_calc_key(uint8_t *key) */ /* ----------------------------------------------------------------------------------------------*/ /* Function: 27 service calculate key according to seed */ /* Arguments: key : the calculated key */ /* Return: - */ /*===============================================================================================*/ void service27_calc_key(uint8_t *key) { uint8_t seed[4]; seed[0] = org_seed_buf[0]; seed[1] = org_seed_buf[1]; seed[2] = org_seed_buf[2]; seed[3] = org_seed_buf[3]; ASAP1A_CCP_ComputeKeyFromSeed(seed, 4, key, 0); } /*===============================================================================================*/ /* uds_nrc service27_verify_key(UDSpacket_t* qUDSpacket) */ /* ----------------------------------------------------------------------------------------------*/ /* Function: 27 service verify key between client and server */ /* Arguments: qUDSpacket : CAN message structure pointer */ /* Return: Response type */ /*===============================================================================================*/ uds_nrc service27_verify_key(UDSpacket_t* qUDSpacket) { uint8_t calcKeyBuffer[UDS_KEY_LENGTH]; uint8_t recvKeyBuffer[UDS_KEY_LENGTH]; uint32_t calcKey,recvKey; uds_nrc result; req_seed = 0; /* allow receiving request key request */ service27_calc_key(calcKeyBuffer); /* calc key */ service27_char2int(calcKeyBuffer,&calcKey); memcpy(recvKeyBuffer,&qUDSpacket->Data.Byte[2],UDS_KEY_LENGTH); /* get received key */ service27_char2int(recvKeyBuffer,&recvKey); if(calcKey == recvKey) /* security access success */ { if(fail_time >= 1) { fail_time = fail_time - 1; } else { /* do nothing */ } FAA_flag = 0; /* remove FAA flag */ service27_write_faaflag(FALSE); /* write FAA flag into work flash */ curr_sa = UDS_SA_LV4; udsFbl_Set_Security_Access_Sts(true); qUDSpacket->size = 2; qUDSpacket->Data.Byte[0] = UDS_GET_POSITIVE_RSP(qUDSpacket->Data.Byte[0]); result = UDSpositiveResp; } else /* security access fail */ { result = service27_SetFAAFlag(); } return result; } /*===============================================================================================*/ /* uint8_t service27_rand(void) */ /* ----------------------------------------------------------------------------------------------*/ /* Function: 27 service generate rand value */ /* Arguments: - */ /* Return: rand value */ /*===============================================================================================*/ uint8_t service27_rand(void) { uint16_t ticks = 0; uint8_t result; ticks = App_Get_SrandSeed(); /*srand() function used to set the random seed of rand() function,so that rand() function can generate different random data*/ srand(ticks); result = rand() % 255; App_Add_SrandSeed(result); return result; } /*===============================================================================================*/ /* void service27_char2int(uint8_t buf[], uint32_t *pval) */ /* ----------------------------------------------------------------------------------------------*/ /* Function: 27 service transfer unsigned char array to integer */ /* Arguments: buf : unsigned char array */ /* Arguments: pval : integer value */ /* Return: - */ /*===============================================================================================*/ void service27_char2int(uint8_t buf[], uint32_t *pval) { uint32_t val; if (buf == NULL || pval == NULL) return; val = 0; val |= ((uint32_t)buf[0]) << 24; val |= ((uint32_t)buf[1]) << 16; val |= ((uint32_t)buf[2]) << 8; val |= ((uint32_t)buf[3]) << 0; *pval = val; } /*===============================================================================================*/ /* void service27_init(void) */ /* ----------------------------------------------------------------------------------------------*/ /* Function: 27 service initial function */ /* Arguments: - */ /* Return: - */ /*===============================================================================================*/ void service27_init(void) { uint8_t i; uint8_t faa_init[4]; uint8_t read_status; for(i = 0; i < UDS_SEED_LENGTH; i++) { org_seed_buf[i] = 0; } req_seed = 0; if ((MEM_ADR_LR_DET == RIGHT_ECU)&&(MEM_ADR_LR_DET_INV == RIGHT_ECU_INV)) { /* The Code, AppKeyConst [4] of CHLI_R is 0xC54D8773. */ u8AppKeyConst[0] = 0xC5; u8AppKeyConst[1] = 0x4D; u8AppKeyConst[2] = 0x87; u8AppKeyConst[3] = 0x73; } else { /* do nothing */ } curr_sa = UDS_SA_NON; read_status = Dataflash_Common_Read(DID_FAA_27_FAIL_FLAG,faa_init); if(FALSE == read_status) { FAA_flag = (uint8_t)faa_init[0]; /* Get FFA flag from work flash */ } else { FAA_flag = 0; /* read work flash failed */ } if(FAA_flag == 1) { fail_time = 3; delay_timer_active = 1; udsFbl_StartTimer(TIMER_UDS_DELAY); /* start 10s delay timer */ } else { delay_timer_active = 0; fail_time = 0; } } /*===============================================================================================*/ /* uint8_t service27_get_currsa(void) */ /* ----------------------------------------------------------------------------------------------*/ /* Function: 27 service get current security access status */ /* Arguments: - */ /* Return: security access status */ /*===============================================================================================*/ uint8_t service27_get_currsa(void) { return curr_sa; } /*===============================================================================================*/ /* uint8_t service27_set_currsa(void) */ /* ----------------------------------------------------------------------------------------------*/ /* Function: 27 service set current security access status */ /* Arguments: - */ /* Return: security access status */ /*===============================================================================================*/ void service27_set_currsa(uint8_t CurrentSecLvl) { curr_sa = CurrentSecLvl; } /*===============================================================================================*/ /* uds_nrc service27_nrc_check(UDSpacket_t* qUDSpacket) */ /* ----------------------------------------------------------------------------------------------*/ /* Function: 27 service negative response judgment */ /* Arguments: qUDSpacket : CAN message structure pointer */ /* Return: Response type */ /*===============================================================================================*/ uds_nrc service27_nrc_check(UDSpacket_t* qUDSpacket) { uds_nrc returnType = 0; uint8_t const kwpdiag_num = (sizeof(SessionSubfunction)/sizeof(DIAG_sunfunction_t)); uint8_t index = 0; uint8_t requestsid = qUDSpacket->Data.Byte[1]; for (index = 0; index < kwpdiag_num; index++) { if(requestsid == SessionSubfunction[index].sub_requestsid) { break; } } if(index != kwpdiag_num) { nrc_table_t nrc_table = SessionSubfunction[index].nrc_table; uint16_t length = SessionSubfunction[index].rx_dataLen; uint8_t index_nrc = 0; uint8_t sid = SessionSubfunction[index].sub_requestsid; /* Check whether the sub-function is supported */ /* Judge abnormal situations according to NRC priority */ for (index_nrc = 0; (index_nrc < nrc_table.nrc_cnt) && (returnType == 0); index_nrc++) { switch (nrc_table.nrc_list[index_nrc]) { case UDSincorrectMessageLengthOrInvalidFormat: if (Uds_Nrc13_Occur(qUDSpacket->size, length)) { returnType = UDSincorrectMessageLengthOrInvalidFormat; } break; case UDSconditionNotCorrect: if (sid == requestsid) { uint8_t currentSession = 0; currentSession = udsFbl_GetCurrentSessionMode(); if ((currentSession & SessionSubfunction[index].session_mask) == 0) { returnType = UDSconditionNotCorrect; } } break; case UDSrequestSequenceError: if (req_seed == 0) { returnType = UDSrequestSequenceError; /* Received sendkey request without reqseed request */ } break; case requiredTimeDelayNotExpired: if (delay_timer_active == 1) { returnType = requiredTimeDelayNotExpired; /* Received security access request during delay time */ } break; default: break; } } } else { returnType = UDSsubfunctionNotSupported; } return returnType; /* return highest priority nrc*/ } /*===============================================================================================*/ /* uint8_t ApplDiag_SecurityAccess_27(UDSpacket_t* qUDSpacket) */ /* ----------------------------------------------------------------------------------------------*/ /* Function: 27 service entry processing function */ /* Arguments: qUDSpacket : CAN message structure pointer */ /* Return: Response type */ /*===============================================================================================*/ uint8_t ApplDiag_SecurityAccess_27(UDSpacket_t* qUDSpacket) { uds_nrc returnType = 0; uint8_t subFunction = qUDSpacket->Data.Byte[1]; returnType = service27_nrc_check(qUDSpacket); if (UDSpositiveResp == returnType) { switch (subFunction) { case 0x01: service27_generate_seed(qUDSpacket); break; case 0x02: returnType = service27_verify_key(qUDSpacket); break; default: break; } } return returnType; } /*Step2: Perform Bitwise Ex-OR operation of seed with a constant, AppKeyConst[4], to obtain Key1 [4].*/ bool ObtainKey1(uint8_t *seed1,uint8_t * key1) { key1[0] = seed1[0] ^ u8AppKeyConst[0]; key1[1] = seed1[1] ^ u8AppKeyConst[1]; key1[2] = seed1[2] ^ u8AppKeyConst[2]; key1[3] = seed1[3] ^ u8AppKeyConst[3]; return true; } /*Step3: Rotate the seed [4] by 16 bits to obtain Seed2 [4] as the Diagram 1.*/ uint32_t ReverseBit32(uint32_t u32ReverseInput) { u32ReverseInput = (((u32ReverseInput & 0xAAAAAAAA) >> 1) | ((u32ReverseInput & 0x55555555) << 1)); u32ReverseInput = (((u32ReverseInput & 0xCCCCCCCC) >> 2) | ((u32ReverseInput & 0x33333333) << 2)); u32ReverseInput = (((u32ReverseInput & 0xF0F0F0F0) >> 4) | ((u32ReverseInput & 0x0F0F0F0F) << 4)); u32ReverseInput = (((u32ReverseInput & 0xFF00FF00) >> 8) | ((u32ReverseInput & 0x00FF00FF) << 8)); return((u32ReverseInput >> 16) | (u32ReverseInput << 16)); } bool ObtainSeed2(uint8_t *seed1,uint8_t * Seed2) { uint32_t u32Seed1 = 0x0; uint32_t u32Seed2 = 0x0; u32Seed1 |= ((uint32_t)seed1[0]) << 24; u32Seed1 |= ((uint32_t)seed1[1]) << 16; u32Seed1 |= ((uint32_t)seed1[2]) << 8; u32Seed1 |= ((uint32_t)seed1[3]) << 0; u32Seed2 = ReverseBit32(u32Seed1); Seed2[0] = (uint8_t)((u32Seed2>>24)&0xFF); Seed2[1] = (uint8_t)((u32Seed2>>16)&0xFF); Seed2[2] = (uint8_t)((u32Seed2>>8)&0xFF); Seed2[3] = (uint8_t)((u32Seed2>>0)&0xFF); return true; } /*Step4: Perform Bitwise Ex-OR operation of seed2 with the same constant,AppKeyConst [4], to obtain Key2 [4]*/ bool ObtainKey2(uint8_t *seed2,uint8_t * key2) { key2[0] = seed2[0] ^ u8AppKeyConst[0]; key2[1] = seed2[1] ^ u8AppKeyConst[1]; key2[2] = seed2[2] ^ u8AppKeyConst[2]; key2[3] = seed2[3] ^ u8AppKeyConst[3]; return true; } /*Step5: 5) Add Key1 and Key2 and discard the final carry bit if any to obtain the key (Key [4])*/ bool CalculateFinalKey(uint8_t * key1,uint8_t * key2,uint8_t * key) { uint32_t u32Key1 = 0x0; uint32_t u32Key2 = 0x0; uint32_t u32Key = 0x0; /*Should confirm whether Zhixin MCU support uint64 type data*/ uint64_t u64KeyAdd = 0x0; u32Key1 |= ((uint32_t)key1[0]) << 24; u32Key1 |= ((uint32_t)key1[1]) << 16; u32Key1 |= ((uint32_t)key1[2]) << 8; u32Key1 |= ((uint32_t)key1[3]) << 0; u32Key2 |= ((uint32_t)key2[0]) << 24; u32Key2 |= ((uint32_t)key2[1]) << 16; u32Key2 |= ((uint32_t)key2[2]) << 8; u32Key2 |= ((uint32_t)key2[3]) << 0; u64KeyAdd = u32Key1 + u32Key2; u32Key = (uint32_t)(u64KeyAdd & 0xFFFFFFFF); key[0] = (uint8_t)((u32Key>>24)&0xFF); key[1] = (uint8_t)((u32Key>>16)&0xFF); key[2] = (uint8_t)((u32Key>>8)&0xFF); key[3] = (uint8_t)((u32Key>>0)&0xFF); return true; } /*==========================================================================================================*/ /* bool ASAP1A_CCP_ComputeKeyFromSeed(uint8_t *seed, uint16_t sizeSeed, uint8_t * key, uint16_t maxSizeKey) */ /* ---------------------------------------------------------------------------------------------------------*/ /* Function: compute key from seed */ /* Arguments: seed : the seed to be compute */ /* Arguments: sizeSeed : the length of seed */ /* Arguments: key : the computed result from the input seed */ /* Arguments: maxSizeKey : the max size of the key */ /* Return: compute result */ /*==========================================================================================================*/ bool ASAP1A_CCP_ComputeKeyFromSeed(uint8_t *seed, uint16_t sizeSeed, uint8_t * key, uint16_t maxSizeKey) { ObtainKey1(seed,&u8key1[0]); ObtainSeed2(seed,&u8Seed2[0]); ObtainKey2(&u8Seed2[0],&u8key2[0]); CalculateFinalKey(&u8key1[0],&u8key2[0],key); return true; } /*===============================================================================================*/ /* void delayTimerCounterCheck(uint16_t *pdelayTimerCounter) */ /* ----------------------------------------------------------------------------------------------*/ /* Function:service 27 01 delay timer */ /* Arguments: pdelayTimerCounter : delay timer counter */ /* Return: - */ /*===============================================================================================*/ void delayTimerCounterCheck(uint16_t *pdelayTimerCounter) { if((*pdelayTimerCounter)) { if((*pdelayTimerCounter) == 1) { delay_timer_active = 0; } else { (*pdelayTimerCounter)--; } } else { /* do nothing */ } } /*===============================================================================================*/ /* static uint8_t service27_SetFAAFlag(void) */ /* ----------------------------------------------------------------------------------------------*/ /* Function:service 27 set FAA flag */ /* Arguments: - */ /* Return: Response type */ /*===============================================================================================*/ static uint8_t service27_SetFAAFlag(void) { uint8_t result; if(fail_time < (uint8_t)0xFF) { fail_time = fail_time + 1; /* increased the fail times */ } else { /* do nothing */ } if(fail_time >= 3) /* after verifing failed for 3 times,delay 10s */ { delay_timer_active = 1; if(0 == FAA_flag) { service27_write_faaflag(TRUE); /* write FAA flag into work flash */ FAA_flag = 1; /* set FAA flag */ } else { /* do nothing */ } udsFbl_StartTimer(TIMER_UDS_DELAY); /* start 10s delay timer */ result = UDSexceedNumberOfAttempts; } else { result = UDSinvalidKey; } return result; } /******************************************************************************* ** End of File ** *******************************************************************************/ #endif /*_UDS_FBL_SERVICE_11_SOURCE*/