mirror of https://github.com/rusefi/openblt.git
Refs #320. Implemented support for the seed/key protection in the XCP loader module.
git-svn-id: https://svn.code.sf.net/p/openblt/code/trunk@381 5dc33758-31d5-4daf-9ae8-b24bf3d40d73
This commit is contained in:
parent
a16099de24
commit
32e11ecf9a
|
@ -136,7 +136,9 @@ add_executable(
|
|||
if(CMAKE_C_COMPILER_ID MATCHES GNU)
|
||||
# According to the CMake docs, item names starting with '-', but not '-l' or
|
||||
# '-framework', are treated as linker flags. This means "-Wl" type linker flags can be
|
||||
# specified here.
|
||||
# specified here. Use this to add the path of the executable to the library search
|
||||
# path. This way the LibOpenBLT shared library can simply be in the same directory as
|
||||
# the BootCommander executable.
|
||||
target_link_libraries(BootCommander ${LIBOPENBLT_LIBNAME} "-Wl,-rpath,.")
|
||||
elseif(CMAKE_C_COMPILER_ID MATCHES MSVC)
|
||||
target_link_libraries(BootCommander ${LIBOPENBLT_LIBNAME})
|
||||
|
|
|
@ -144,8 +144,8 @@ set(
|
|||
# Only generate the static library taget if the option is enabled. Use
|
||||
# "make openblt_static" to individually build the static library.
|
||||
# Note that when you link your own application to the static library of LibOpenBLT under
|
||||
# Unix, you need to also link the LibUsb library by adding usb-1.0 to the linker library
|
||||
# dependencies.
|
||||
# Unix, you need to also link the LibUsb and LibDL libraries by adding usb-1.0 and dl to
|
||||
# the linker library dependencies.
|
||||
if(BUILD_STATIC)
|
||||
add_library(openblt_static STATIC ${LIB_SRCS})
|
||||
SET_TARGET_PROPERTIES(openblt_static PROPERTIES OUTPUT_NAME openblt CLEAN_DIRECT_OUTPUT 1)
|
||||
|
@ -160,7 +160,13 @@ if(BUILD_SHARED)
|
|||
# Make sure the libusb-1.0-0 and libusb-1.0-0-dev packages are installed to be able to
|
||||
# build LibOpenBLT. Example under Debian/Ubuntu:
|
||||
# sudo apt-get install libusb-1.0-0 libusb-1.0-0-dev
|
||||
target_link_libraries(openblt_shared usb-1.0)
|
||||
# Additionally, the LibDL is needed for dynamic library loading.
|
||||
# According to the CMake docs, item names starting with '-', but not '-l' or
|
||||
# '-framework', are treated as linker flags. This means "-Wl" type linker flags can be
|
||||
# specified here. Use this to add the path of the shared library to the library search
|
||||
# path. This way an (optional) seed and key shared library file can simply be in the
|
||||
# same directory as the LibOpenBLT shared library.
|
||||
target_link_libraries(openblt_shared usb-1.0 dl "-Wl,-rpath,.")
|
||||
endif(UNIX)
|
||||
if(CMAKE_C_COMPILER_ID MATCHES MSVC)
|
||||
# Microsoft Visual Studio does not add "lib" to the name of the DLL, whereas GCC
|
||||
|
|
|
@ -139,6 +139,7 @@ LIBOPENBLT_EXPORT void BltSessionInit(uint32_t sessionType,
|
|||
xcpLoaderSettings.timeoutT4 = bltSessionSettingsXcpV10Ptr->timeoutT4;
|
||||
xcpLoaderSettings.timeoutT5 = bltSessionSettingsXcpV10Ptr->timeoutT5;
|
||||
xcpLoaderSettings.timeoutT7 = bltSessionSettingsXcpV10Ptr->timeoutT7;
|
||||
xcpLoaderSettings.seedKeyFile = bltSessionSettingsXcpV10Ptr->seedKeyFile;
|
||||
xcpLoaderSettings.connectMode = bltSessionSettingsXcpV10Ptr->connectMode;
|
||||
xcpLoaderSettings.transport = NULL;
|
||||
xcpLoaderSettings.transportSettings = NULL;
|
||||
|
|
|
@ -0,0 +1,194 @@
|
|||
/************************************************************************************//**
|
||||
* \file port/linux/xcpprotect.c
|
||||
* \brief XCP Protection module source file.
|
||||
* \ingroup XcpLoader
|
||||
* \internal
|
||||
*----------------------------------------------------------------------------------------
|
||||
* C O P Y R I G H T
|
||||
*----------------------------------------------------------------------------------------
|
||||
* Copyright (c) 2017 by Feaser http://www.feaser.com All rights reserved
|
||||
*
|
||||
*----------------------------------------------------------------------------------------
|
||||
* L I C E N S E
|
||||
*----------------------------------------------------------------------------------------
|
||||
* This file is part of OpenBLT. OpenBLT is free software: you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License as published by the Free
|
||||
* Software Foundation, either version 3 of the License, or (at your option) any later
|
||||
* version.
|
||||
*
|
||||
* OpenBLT is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
|
||||
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
|
||||
* PURPOSE. See the GNU General Public License for more details.
|
||||
*
|
||||
* You have received a copy of the GNU General Public License along with OpenBLT. It
|
||||
* should be located in ".\Doc\license.html". If not, contact Feaser to obtain a copy.
|
||||
*
|
||||
* \endinternal
|
||||
****************************************************************************************/
|
||||
|
||||
/****************************************************************************************
|
||||
* Include files
|
||||
****************************************************************************************/
|
||||
#include <assert.h> /* for assertions */
|
||||
#include <stdint.h> /* for standard integer types */
|
||||
#include <stddef.h> /* for NULL declaration */
|
||||
#include <stdbool.h> /* for boolean type */
|
||||
#include <dlfcn.h> /* for dynamic loading */
|
||||
#include "xcpprotect.h" /* XCP protection module */
|
||||
|
||||
|
||||
/****************************************************************************************
|
||||
* Type definitions
|
||||
****************************************************************************************/
|
||||
/* Seed and key shared library function types. */
|
||||
typedef uint32_t ( * tXcpProtectLibComputeKey)(uint8_t resource, uint8_t seedLen,
|
||||
uint8_t const * seedPtr,
|
||||
uint8_t * keyLenPtr, uint8_t * keyPtr);
|
||||
typedef uint32_t ( * tXcpProtectLibGetPrivileges)(uint8_t * resourcePtr);
|
||||
|
||||
|
||||
/****************************************************************************************
|
||||
* Local data declarations
|
||||
****************************************************************************************/
|
||||
/** \brief Handle to the dynamically loaded seed and key shared library. It can also be
|
||||
* used as a flag to determine if the shared library was specified and success-
|
||||
* fully loaded.
|
||||
*/
|
||||
static void * seedNKeyLibraryHandle;
|
||||
|
||||
/** \brief Function pointer to the XCP_ComputeKeyFromSeed shared library function. */
|
||||
static tXcpProtectLibComputeKey xcpProtectLibComputeKey;
|
||||
|
||||
/** \brief Function pointer to the XCP_GetAvailablePrivileges shared library function. */
|
||||
static tXcpProtectLibGetPrivileges xcpProtectLibGetPrivileges;
|
||||
|
||||
|
||||
/************************************************************************************//**
|
||||
** \brief Initializes the XCP protection module.
|
||||
** \param seedKeyFile Filename of the seed and key shared library that contains the
|
||||
** following functions:
|
||||
** - XCP_ComputeKeyFromSeed()
|
||||
** - XCP_GetAvailablePrivileges()
|
||||
**
|
||||
****************************************************************************************/
|
||||
void XcpProtectInit(char const * seedKeyFile)
|
||||
{
|
||||
/* Init locals. */
|
||||
seedNKeyLibraryHandle = NULL;
|
||||
/* Reset library function pointers. */
|
||||
xcpProtectLibComputeKey = NULL;
|
||||
xcpProtectLibGetPrivileges = NULL;
|
||||
|
||||
/* Only load the shared library is a valid file was specified. */
|
||||
if (seedKeyFile != NULL)
|
||||
{
|
||||
/* Attempt to load the shared library. */
|
||||
seedNKeyLibraryHandle = dlopen(seedKeyFile, RTLD_LAZY);
|
||||
/* Load the function pointers from the shared library. */
|
||||
if (seedNKeyLibraryHandle != NULL)
|
||||
{
|
||||
xcpProtectLibComputeKey = dlsym(seedNKeyLibraryHandle,
|
||||
"XCP_ComputeKeyFromSeed");
|
||||
xcpProtectLibGetPrivileges = dlsym(seedNKeyLibraryHandle,
|
||||
"XCP_GetAvailablePrivileges");
|
||||
}
|
||||
}
|
||||
} /*** end of XcpProtectInit ***/
|
||||
|
||||
|
||||
/************************************************************************************//**
|
||||
** \brief Terminates the XCP protection module.
|
||||
**
|
||||
****************************************************************************************/
|
||||
void XcpProtectTerminate(void)
|
||||
{
|
||||
/* Reset library function pointers. */
|
||||
xcpProtectLibComputeKey = NULL;
|
||||
xcpProtectLibGetPrivileges = NULL;
|
||||
/* Only unload the shared library if one was loaded. */
|
||||
if (seedNKeyLibraryHandle != NULL)
|
||||
{
|
||||
/* Unload the shared library. */
|
||||
(void)dlclose(seedNKeyLibraryHandle);
|
||||
/* Reset the handle. */
|
||||
seedNKeyLibraryHandle = NULL;
|
||||
}
|
||||
} /*** end of XcpProtectTerminate ***/
|
||||
|
||||
|
||||
/************************************************************************************//**
|
||||
** \brief Computes the key for the requested resource.
|
||||
** \param resource resource for which the unlock key is requested
|
||||
** \param seedLen length of the seed
|
||||
** \param seedPtr pointer to the seed data
|
||||
** \param keyLenPtr pointer where to store the key length
|
||||
** \param keyPtr pointer where to store the key data
|
||||
** \return True if successful, false otherwise.
|
||||
**
|
||||
****************************************************************************************/
|
||||
bool XCPProtectComputeKeyFromSeed(uint8_t resource, uint8_t seedLen,
|
||||
uint8_t const * seedPtr, uint8_t * keyLenPtr,
|
||||
uint8_t * keyPtr)
|
||||
{
|
||||
bool result = false;
|
||||
|
||||
/* Check parameters. */
|
||||
assert(seedLen > 0);
|
||||
assert(seedPtr != NULL);
|
||||
assert(keyLenPtr != NULL);
|
||||
assert(keyPtr != NULL);
|
||||
|
||||
/* Only continue if the parameters are valid. */
|
||||
if ( (seedLen > 0) && (seedPtr != NULL) && (keyLenPtr != NULL) &&
|
||||
(keyPtr != NULL) ) /*lint !e774 */
|
||||
{
|
||||
/* Only continue with a valid function pointer into the shared library. */
|
||||
if (xcpProtectLibComputeKey != NULL)
|
||||
{
|
||||
/* Call the library function. */
|
||||
if (xcpProtectLibComputeKey(resource, seedLen, seedPtr, keyLenPtr, keyPtr) == 0)
|
||||
{
|
||||
/* All good so update the result value accordingly. */
|
||||
result = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
/* Give the result back to the caller. */
|
||||
return result;
|
||||
} /*** end of XCPProtectComputeKeyFromSeed ***/
|
||||
|
||||
|
||||
/************************************************************************************//**
|
||||
** \brief Obtains a bitmask of the resources for which an key algorithm is available.
|
||||
** \param resourcePtr pointer where to store the supported resources for the key
|
||||
** computation.
|
||||
** \return XCP_RESULT_OK on success, otherwise XCP_RESULT_ERROR.
|
||||
**
|
||||
****************************************************************************************/
|
||||
bool XcpProtectGetPrivileges(uint8_t * resourcePtr)
|
||||
{
|
||||
bool result = false;
|
||||
|
||||
/* Check parameters. */
|
||||
assert(resourcePtr != NULL);
|
||||
|
||||
/* Only continue if the parameter is valid. */
|
||||
if (resourcePtr != NULL) /*lint !e774 */
|
||||
{
|
||||
/* Only continue with a valid function pointer into the shared library. */
|
||||
if (xcpProtectLibGetPrivileges != NULL)
|
||||
{
|
||||
/* Call the library function. */
|
||||
if (xcpProtectLibGetPrivileges(resourcePtr) == 0)
|
||||
{
|
||||
/* All good so update the result value accordingly. */
|
||||
result = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
/* Give the result back to the caller. */
|
||||
return result;
|
||||
} /*** end of XcpProtectGetPrivileges ***/
|
||||
|
||||
|
||||
/*********************************** end of xcpprotect.c *******************************/
|
|
@ -0,0 +1,198 @@
|
|||
/************************************************************************************//**
|
||||
* \file port/windows/xcpprotect.c
|
||||
* \brief XCP Protection module source file.
|
||||
* \ingroup XcpLoader
|
||||
* \internal
|
||||
*----------------------------------------------------------------------------------------
|
||||
* C O P Y R I G H T
|
||||
*----------------------------------------------------------------------------------------
|
||||
* Copyright (c) 2017 by Feaser http://www.feaser.com All rights reserved
|
||||
*
|
||||
*----------------------------------------------------------------------------------------
|
||||
* L I C E N S E
|
||||
*----------------------------------------------------------------------------------------
|
||||
* This file is part of OpenBLT. OpenBLT is free software: you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License as published by the Free
|
||||
* Software Foundation, either version 3 of the License, or (at your option) any later
|
||||
* version.
|
||||
*
|
||||
* OpenBLT is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
|
||||
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
|
||||
* PURPOSE. See the GNU General Public License for more details.
|
||||
*
|
||||
* You have received a copy of the GNU General Public License along with OpenBLT. It
|
||||
* should be located in ".\Doc\license.html". If not, contact Feaser to obtain a copy.
|
||||
*
|
||||
* \endinternal
|
||||
****************************************************************************************/
|
||||
|
||||
/****************************************************************************************
|
||||
* Include files
|
||||
****************************************************************************************/
|
||||
#include <assert.h> /* for assertions */
|
||||
#include <stdint.h> /* for standard integer types */
|
||||
#include <stddef.h> /* for NULL declaration */
|
||||
#include <stdbool.h> /* for boolean type */
|
||||
#include <windows.h> /* for Windows API */
|
||||
#include "xcpprotect.h" /* XCP protection module */
|
||||
|
||||
|
||||
/****************************************************************************************
|
||||
* Type definitions
|
||||
****************************************************************************************/
|
||||
/* Seed and key shared library function types. */
|
||||
typedef uint32_t (* tXcpProtectLibComputeKey)(uint8_t resource,
|
||||
uint8_t seedLen,
|
||||
uint8_t const * seedPtr,
|
||||
uint8_t * keyLenPtr,
|
||||
uint8_t * keyPtr);
|
||||
typedef uint32_t (* tXcpProtectLibGetPrivileges)(uint8_t * resourcePtr);
|
||||
|
||||
|
||||
/****************************************************************************************
|
||||
* Local data declarations
|
||||
****************************************************************************************/
|
||||
/** \brief Handle to the dynamically loaded seed and key shared library. It can also be
|
||||
* used as a flag to determine if the shared library was specified and success-
|
||||
* fully loaded.
|
||||
*/
|
||||
static HINSTANCE seedNKeyLibraryHandle;
|
||||
|
||||
/** \brief Function pointer to the XCP_ComputeKeyFromSeed shared library function. */
|
||||
static tXcpProtectLibComputeKey xcpProtectLibComputeKey;
|
||||
|
||||
/** \brief Function pointer to the XCP_GetAvailablePrivileges shared library function. */
|
||||
static tXcpProtectLibGetPrivileges xcpProtectLibGetPrivileges;
|
||||
|
||||
|
||||
/************************************************************************************//**
|
||||
** \brief Initializes the XCP protection module.
|
||||
** \param seedKeyFile Filename of the seed and key shared library that contains the
|
||||
** following functions:
|
||||
** - XCP_ComputeKeyFromSeed()
|
||||
** - XCP_GetAvailablePrivileges()
|
||||
**
|
||||
****************************************************************************************/
|
||||
void XcpProtectInit(char const * seedKeyFile)
|
||||
{
|
||||
/* Init locals. */
|
||||
seedNKeyLibraryHandle = NULL;
|
||||
/* Reset library function pointers. */
|
||||
xcpProtectLibComputeKey = NULL;
|
||||
xcpProtectLibGetPrivileges = NULL;
|
||||
|
||||
/* Only load the shared library is a valid file was specified. */
|
||||
if (seedKeyFile != NULL)
|
||||
{
|
||||
/* Attempt to load the shared library. */
|
||||
seedNKeyLibraryHandle = LoadLibrary(seedKeyFile);
|
||||
/* Load the function pointers from the shared library. */
|
||||
if (seedNKeyLibraryHandle != NULL)
|
||||
{
|
||||
xcpProtectLibComputeKey = (tXcpProtectLibComputeKey)GetProcAddress(
|
||||
seedNKeyLibraryHandle,
|
||||
"XCP_ComputeKeyFromSeed");
|
||||
xcpProtectLibGetPrivileges = (tXcpProtectLibGetPrivileges)GetProcAddress(
|
||||
seedNKeyLibraryHandle,
|
||||
"XCP_GetAvailablePrivileges");
|
||||
}
|
||||
}
|
||||
} /*** end of XcpProtectInit ***/
|
||||
|
||||
|
||||
/************************************************************************************//**
|
||||
** \brief Terminates the XCP protection module.
|
||||
**
|
||||
****************************************************************************************/
|
||||
void XcpProtectTerminate(void)
|
||||
{
|
||||
/* Reset library function pointers. */
|
||||
xcpProtectLibComputeKey = NULL;
|
||||
xcpProtectLibGetPrivileges = NULL;
|
||||
/* Only unload the shared library if one was loaded. */
|
||||
if (seedNKeyLibraryHandle != NULL)
|
||||
{
|
||||
/* Unload the shared library. */
|
||||
(void)FreeLibrary(seedNKeyLibraryHandle);
|
||||
/* Reset the handle. */
|
||||
seedNKeyLibraryHandle = NULL;
|
||||
}
|
||||
} /*** end of XcpProtectTerminate ***/
|
||||
|
||||
|
||||
/************************************************************************************//**
|
||||
** \brief Computes the key for the requested resource.
|
||||
** \param resource resource for which the unlock key is requested
|
||||
** \param seedLen length of the seed
|
||||
** \param seedPtr pointer to the seed data
|
||||
** \param keyLenPtr pointer where to store the key length
|
||||
** \param keyPtr pointer where to store the key data
|
||||
** \return True if successful, false otherwise.
|
||||
**
|
||||
****************************************************************************************/
|
||||
bool XCPProtectComputeKeyFromSeed(uint8_t resource, uint8_t seedLen,
|
||||
uint8_t const * seedPtr, uint8_t * keyLenPtr,
|
||||
uint8_t * keyPtr)
|
||||
{
|
||||
bool result = false;
|
||||
|
||||
/* Check parameters. */
|
||||
assert(seedLen > 0);
|
||||
assert(seedPtr != NULL);
|
||||
assert(keyLenPtr != NULL);
|
||||
assert(keyPtr != NULL);
|
||||
|
||||
/* Only continue if the parameters are valid. */
|
||||
if ( (seedLen > 0) && (seedPtr != NULL) && (keyLenPtr != NULL) &&
|
||||
(keyPtr != NULL) ) /*lint !e774 */
|
||||
{
|
||||
/* Only continue with a valid function pointer into the shared library. */
|
||||
if (xcpProtectLibComputeKey != NULL)
|
||||
{
|
||||
/* Call the library function. */
|
||||
if (xcpProtectLibComputeKey(resource, seedLen, seedPtr, keyLenPtr, keyPtr) == 0)
|
||||
{
|
||||
/* All good so update the result value accordingly. */
|
||||
result = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
/* Give the result back to the caller. */
|
||||
return result;
|
||||
} /*** end of XCPProtectComputeKeyFromSeed ***/
|
||||
|
||||
|
||||
/************************************************************************************//**
|
||||
** \brief Obtains a bitmask of the resources for which an key algorithm is available.
|
||||
** \param resourcePtr pointer where to store the supported resources for the key
|
||||
** computation.
|
||||
** \return XCP_RESULT_OK on success, otherwise XCP_RESULT_ERROR.
|
||||
**
|
||||
****************************************************************************************/
|
||||
bool XcpProtectGetPrivileges(uint8_t * resourcePtr)
|
||||
{
|
||||
bool result = false;
|
||||
|
||||
/* Check parameters. */
|
||||
assert(resourcePtr != NULL);
|
||||
|
||||
/* Only continue if the parameter is valid. */
|
||||
if (resourcePtr != NULL) /*lint !e774 */
|
||||
{
|
||||
/* Only continue with a valid function pointer into the shared library. */
|
||||
if (xcpProtectLibGetPrivileges != NULL)
|
||||
{
|
||||
/* Call the library function. */
|
||||
if (xcpProtectLibGetPrivileges(resourcePtr) == 0)
|
||||
{
|
||||
/* All good so update the result value accordingly. */
|
||||
result = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
/* Give the result back to the caller. */
|
||||
return result;
|
||||
} /*** end of XcpProtectGetPrivileges ***/
|
||||
|
||||
|
||||
/*********************************** end of xcpprotect.c *******************************/
|
|
@ -33,8 +33,11 @@
|
|||
#include <stdint.h> /* for standard integer types */
|
||||
#include <stddef.h> /* for NULL declaration */
|
||||
#include <stdbool.h> /* for boolean type */
|
||||
#include <stdlib.h> /* for standard library */
|
||||
#include <string.h> /* for string library */
|
||||
#include "session.h" /* Communication session module */
|
||||
#include "xcploader.h" /* XCP loader module */
|
||||
#include "xcpprotect.h" /* XCP protection module */
|
||||
|
||||
|
||||
/****************************************************************************************
|
||||
|
@ -42,6 +45,9 @@
|
|||
****************************************************************************************/
|
||||
/* XCP command codes as defined by the protocol currently supported by this module */
|
||||
#define XCPLOADER_CMD_CONNECT (0xFFu) /**< XCP connect command code. */
|
||||
#define XCPLOADER_CMD_GET_STATUS (0xFDu) /**< XCP get status command code. */
|
||||
#define XCPLOADER_CMD_GET_SEED (0xF8u) /**< XCP get seed command code. */
|
||||
#define XCPLOADER_CMD_UNLOCK (0xF7u) /**< XCP unlock command code. */
|
||||
#define XCPLOADER_CMD_SET_MTA (0xF6u) /**< XCP set mta command code. */
|
||||
#define XCPLOADER_CMD_UPLOAD (0xF5u) /**< XCP upload command code. */
|
||||
#define XCPLOADER_CMD_PROGRAM_START (0xD2u) /**< XCP program start command code. */
|
||||
|
@ -73,8 +79,14 @@ static bool XcpLoaderWriteData(uint32_t address, uint32_t len, uint8_t const * d
|
|||
static bool XcpLoaderReadData(uint32_t address, uint32_t len, uint8_t * data);
|
||||
/* General module specific utility functions. */
|
||||
static void XcpLoaderSetOrderedLong(uint32_t value, uint8_t *data);
|
||||
static uint16_t XcpLoaderGetOrderedWord(uint8_t const * data);
|
||||
/* XCP command functions. */
|
||||
static bool XcpLoaderSendCmdConnect(void);
|
||||
static bool XcpLoaderSendCmdGetStatus(uint8_t * session, uint8_t * protectedResources,
|
||||
uint16_t * configId);
|
||||
static bool XcpLoaderSendCmdGetSeed(uint8_t resource, uint8_t * seed, uint8_t * seedLen);
|
||||
static bool XcpLoaderSendCmdUnlock(uint8_t const * key, uint8_t keyLen,
|
||||
uint8_t * protectedResources);
|
||||
static bool XcpLoaderSendCmdSetMta(uint32_t address);
|
||||
static bool XcpLoaderSendCmdUpload(uint8_t * data, uint8_t length);
|
||||
static bool XcpLoaderSendCmdProgramStart(void);
|
||||
|
@ -143,6 +155,8 @@ tSessionProtocol const * XcpLoaderGetProtocol(void)
|
|||
****************************************************************************************/
|
||||
static void XcpLoaderInit(void const * settings)
|
||||
{
|
||||
char * seedNKeyFileName;
|
||||
|
||||
/* Initialize locals. */
|
||||
xcpConnected = false;
|
||||
xcpSlaveIsIntel = false;
|
||||
|
@ -150,14 +164,39 @@ static void XcpLoaderInit(void const * settings)
|
|||
xcpMaxProgCto = 0;
|
||||
xcpMaxDto = 0;
|
||||
|
||||
/* Reset the XCP session layer settings. */
|
||||
xcpSettings.timeoutT1 = 1000;
|
||||
xcpSettings.timeoutT3 = 2000;
|
||||
xcpSettings.timeoutT4 = 10000;
|
||||
xcpSettings.timeoutT5 = 1000;
|
||||
xcpSettings.timeoutT7 = 2000;
|
||||
xcpSettings.connectMode = 0;
|
||||
xcpSettings.seedKeyFile = NULL;
|
||||
xcpSettings.transport = NULL;
|
||||
xcpSettings.transportSettings = NULL;
|
||||
|
||||
/* Check parameter. */
|
||||
assert(settings != NULL);
|
||||
|
||||
/* Only continue with valid parameter. */
|
||||
if (settings != NULL) /*lint !e774 */
|
||||
{
|
||||
/* shallow copy the XCP settings for later usage */
|
||||
xcpSettings = *(tXcpLoaderSettings *)settings;
|
||||
|
||||
/* The seedKeyFile is a pointer and it is not guaranteed that it stays valid so we
|
||||
* need to deep copy this one. note the +1 for '\0' in malloc. Note that it is okay
|
||||
* for this value to be NULL.
|
||||
*/
|
||||
if (((tXcpLoaderSettings *)settings)->seedKeyFile != NULL) /*lint !e774 */
|
||||
{
|
||||
seedNKeyFileName = malloc(strlen(((tXcpLoaderSettings *)settings)->seedKeyFile) + 1);
|
||||
assert(seedNKeyFileName != NULL);
|
||||
if (seedNKeyFileName != NULL) /*lint !e774 */
|
||||
{
|
||||
strcpy(seedNKeyFileName, ((tXcpLoaderSettings *)settings)->seedKeyFile);
|
||||
xcpSettings.seedKeyFile = seedNKeyFileName;
|
||||
}
|
||||
}
|
||||
/* Check that a valid transport layer was specified. */
|
||||
assert(xcpSettings.transport != NULL);
|
||||
/* Only access the transport layer if it is valid. */
|
||||
|
@ -171,6 +210,8 @@ static void XcpLoaderInit(void const * settings)
|
|||
*/
|
||||
xcpSettings.transportSettings = NULL;
|
||||
}
|
||||
/* Initialize the XCP protection module. */
|
||||
XcpProtectInit(xcpSettings.seedKeyFile);
|
||||
} /*** end of XcpLoaderInit ***/
|
||||
|
||||
|
||||
|
@ -183,6 +224,8 @@ static void XcpLoaderTerminate(void)
|
|||
/* Make sure a valid transport layer is linked. */
|
||||
assert(xcpSettings.transport != NULL);
|
||||
|
||||
/* Terminate the XCP protection module. */
|
||||
XcpProtectTerminate();
|
||||
/* Only continue with a valid transport layer. */
|
||||
if (xcpSettings.transport != NULL) /*lint !e774 */
|
||||
{
|
||||
|
@ -193,6 +236,21 @@ static void XcpLoaderTerminate(void)
|
|||
/* Unlink the transport layer. */
|
||||
xcpSettings.transport = NULL;
|
||||
}
|
||||
/* Release memory that was allocated for storing the seedKeyFile. */
|
||||
if (xcpSettings.seedKeyFile != NULL)
|
||||
{
|
||||
free((char *)xcpSettings.seedKeyFile);
|
||||
}
|
||||
/* Reset the XCP session layer settings. */
|
||||
xcpSettings.timeoutT1 = 1000;
|
||||
xcpSettings.timeoutT3 = 2000;
|
||||
xcpSettings.timeoutT4 = 10000;
|
||||
xcpSettings.timeoutT5 = 1000;
|
||||
xcpSettings.timeoutT7 = 2000;
|
||||
xcpSettings.connectMode = 0;
|
||||
xcpSettings.seedKeyFile = NULL;
|
||||
xcpSettings.transport = NULL;
|
||||
xcpSettings.transportSettings = NULL;
|
||||
} /*** end of XcpLoaderTerminate ***/
|
||||
|
||||
|
||||
|
@ -206,6 +264,7 @@ static bool XcpLoaderStart(void)
|
|||
{
|
||||
bool result = false;
|
||||
uint8_t retryCnt;
|
||||
uint8_t protectedResources = 0;
|
||||
|
||||
/* Make sure a valid transport layer is linked. */
|
||||
assert(xcpSettings.transport != NULL);
|
||||
|
@ -248,7 +307,79 @@ static bool XcpLoaderStart(void)
|
|||
result = false;
|
||||
}
|
||||
}
|
||||
|
||||
/* Obtain the current resource protection status. */
|
||||
if (result)
|
||||
{
|
||||
if (!XcpLoaderSendCmdGetStatus(NULL, &protectedResources, NULL))
|
||||
{
|
||||
result = false;
|
||||
}
|
||||
}
|
||||
/* Check if the programming resource needs to be unlocked. */
|
||||
if ( (protectedResources & XCPPROTECT_RESOURCE_PGM) != 0)
|
||||
{
|
||||
uint8_t availableResources = 0;
|
||||
uint8_t seed[XCPLOADER_PACKET_SIZE_MAX-2] = { 0 };
|
||||
uint8_t seedLen = 0;
|
||||
uint8_t key[XCPLOADER_PACKET_SIZE_MAX-2] = { 0 };
|
||||
uint8_t keyLen = 0;
|
||||
/* Make sure the XCP protection module contains an unlock algorithm for the
|
||||
* programming resource.
|
||||
*/
|
||||
if (result)
|
||||
{
|
||||
if (!XcpProtectGetPrivileges(&availableResources))
|
||||
{
|
||||
/* Could not obtain the supported resource privileges from the XCP protection
|
||||
* module.
|
||||
*/
|
||||
result = false;
|
||||
}
|
||||
else if ((availableResources & XCPPROTECT_RESOURCE_PGM) == 0)
|
||||
{
|
||||
/* No unlock algorithm available for the programming resource in the XCP
|
||||
* protection module.
|
||||
*/
|
||||
result = false;
|
||||
}
|
||||
}
|
||||
/* Request the seed for unlocking the programming resources. */
|
||||
if (result)
|
||||
{
|
||||
if (!XcpLoaderSendCmdGetSeed(XCPPROTECT_RESOURCE_PGM, seed, &seedLen))
|
||||
{
|
||||
result = false;
|
||||
}
|
||||
}
|
||||
/* Only continue with resource unlock operation if not already unlocked, which
|
||||
* is indicated by a seed length of 0.
|
||||
*/
|
||||
if ( (result) && (seedLen > 0) )
|
||||
{
|
||||
/* Compute the key using the XCP protection module. */
|
||||
if (!XCPProtectComputeKeyFromSeed(XCPPROTECT_RESOURCE_PGM, seedLen, seed,
|
||||
&keyLen, key))
|
||||
{
|
||||
result = false;
|
||||
}
|
||||
/* Unlock the resource now that the key is available. */
|
||||
if (result)
|
||||
{
|
||||
uint8_t currentlyProtectedResources = 0;
|
||||
/* Send the key to unlock the resource. */
|
||||
if (!XcpLoaderSendCmdUnlock(key, keyLen, ¤tlyProtectedResources))
|
||||
{
|
||||
result = false;
|
||||
}
|
||||
/* Double-check that the programming resource is now unlocked. */
|
||||
else if ((currentlyProtectedResources & XCPPROTECT_RESOURCE_PGM) != 0)
|
||||
{
|
||||
/* Programming resource unlock operation failed. */
|
||||
result = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
/* Place the target in programming mode if connected. */
|
||||
if (result)
|
||||
{
|
||||
|
@ -508,6 +639,39 @@ static void XcpLoaderSetOrderedLong(uint32_t value, uint8_t *data)
|
|||
} /*** end of XcpLoaderSetOrderedLong ***/
|
||||
|
||||
|
||||
/************************************************************************************//**
|
||||
** \brief Obtains a 16-bit value from a byte buffer taking into account Intel
|
||||
** or Motorola byte ordering.
|
||||
** \param data Array to the buffer with the word value stored as bytes.
|
||||
** \return The 16-bit value.
|
||||
**
|
||||
****************************************************************************************/
|
||||
static uint16_t XcpLoaderGetOrderedWord(uint8_t const * data)
|
||||
{
|
||||
uint16_t result = 0;
|
||||
|
||||
/* Check parameters. */
|
||||
assert(data != NULL);
|
||||
|
||||
/* Only continue with valid parameters. */
|
||||
if (data != NULL) /*lint !e774 */
|
||||
{
|
||||
if (xcpSlaveIsIntel)
|
||||
{
|
||||
result |= (uint16_t)data[0];
|
||||
result |= (uint16_t)(data[1] << 8);
|
||||
}
|
||||
else
|
||||
{
|
||||
result |= (uint16_t)data[1];
|
||||
result |= (uint16_t)(data[0] << 8);
|
||||
}
|
||||
}
|
||||
/* Give the result back to the caller. */
|
||||
return result;
|
||||
} /*** end of XcpLoaderGetOrderedWord ***/
|
||||
|
||||
|
||||
/************************************************************************************//**
|
||||
** \brief Sends the XCP Connect command.
|
||||
** \return True if successful, false otherwise.
|
||||
|
@ -592,6 +756,226 @@ static bool XcpLoaderSendCmdConnect(void)
|
|||
} /*** end of XcpLoaderSendCmdConnect ***/
|
||||
|
||||
|
||||
/************************************************************************************//**
|
||||
** \brief Sends the XCP Get Status command. Note that it is okay to specify a NULL
|
||||
** value for the parameters if you are not interested in a particular one.
|
||||
** \param session Current session status.
|
||||
** \param protectedResources Current resource protection status.
|
||||
** \param configId Session configuration identifier.
|
||||
** \return True if successful, false otherwise.
|
||||
**
|
||||
****************************************************************************************/
|
||||
static bool XcpLoaderSendCmdGetStatus(uint8_t * session, uint8_t * protectedResources,
|
||||
uint16_t * configId)
|
||||
{
|
||||
bool result = false;
|
||||
tXcpTransportPacket cmdPacket;
|
||||
tXcpTransportPacket resPacket;
|
||||
|
||||
/* Make sure a valid transport layer is linked. */
|
||||
assert(xcpSettings.transport != NULL);
|
||||
|
||||
/* Only continue with a valid transport layer. */
|
||||
if (xcpSettings.transport != NULL) /*lint !e774 */
|
||||
{
|
||||
/* Init the result value to okay and only set it to error when a problem occurred. */
|
||||
result = true;
|
||||
/* Prepare the command packet. */
|
||||
cmdPacket.data[0] = XCPLOADER_CMD_GET_STATUS;
|
||||
cmdPacket.len = 1;
|
||||
/* Send the packet. */
|
||||
if (!xcpSettings.transport->SendPacket(&cmdPacket, &resPacket,
|
||||
xcpSettings.timeoutT1))
|
||||
{
|
||||
/* Could not send packet or receive response within the specified timeout. */
|
||||
result = false;
|
||||
}
|
||||
/* Only continue if a response was received. */
|
||||
if (result)
|
||||
{
|
||||
/* Check if the response was valid. */
|
||||
if ( (resPacket.len != 6) || (resPacket.data[0] != XCPLOADER_CMD_PID_RES) )
|
||||
{
|
||||
/* Not a valid or positive response. */
|
||||
result = false;
|
||||
}
|
||||
}
|
||||
/* Extract and store the received status information. */
|
||||
if (result)
|
||||
{
|
||||
/* Store the current session status. */
|
||||
if (session != NULL)
|
||||
{
|
||||
*session = resPacket.data[1];
|
||||
}
|
||||
/* Store the current resource protection status. */
|
||||
if (protectedResources != NULL)
|
||||
{
|
||||
*protectedResources = resPacket.data[2];
|
||||
}
|
||||
/* Store the session configuration id. */
|
||||
if (configId != NULL)
|
||||
{
|
||||
*configId = XcpLoaderGetOrderedWord(&resPacket.data[4]);
|
||||
}
|
||||
}
|
||||
}
|
||||
/* Give the result back to the caller. */
|
||||
return result;
|
||||
} /*** end of XcpLoaderSendCmdGetStatus ***/
|
||||
|
||||
|
||||
/************************************************************************************//**
|
||||
** \brief Sends the XCP Get Seed command.
|
||||
** \param resource The resource to unlock (XCPPROTECT_RESOURCE_xxx).
|
||||
** \param seed Pointer to byte array where the received seed is stored.
|
||||
** \param seedLen Length of the seed in bytes.
|
||||
** \return True if successful, false otherwise.
|
||||
**
|
||||
****************************************************************************************/
|
||||
static bool XcpLoaderSendCmdGetSeed(uint8_t resource, uint8_t * seed, uint8_t * seedLen)
|
||||
{
|
||||
bool result = false;
|
||||
tXcpTransportPacket cmdPacket;
|
||||
tXcpTransportPacket resPacket;
|
||||
|
||||
/* Make sure a valid transport layer is linked and that the parameters are valid. */
|
||||
assert(xcpSettings.transport != NULL);
|
||||
assert(seed != NULL);
|
||||
assert(seedLen != NULL);
|
||||
|
||||
/* Only continue with a valid transport layer and parameters. */
|
||||
if ( (xcpSettings.transport != NULL) && (seed != NULL) &&
|
||||
(seedLen != NULL) ) /*lint !e774 */
|
||||
{
|
||||
/* Only continue with a valid resource value. */
|
||||
if ( (resource == XCPPROTECT_RESOURCE_PGM) ||
|
||||
(resource == XCPPROTECT_RESOURCE_STIM)||
|
||||
(resource == XCPPROTECT_RESOURCE_DAQ) ||
|
||||
(resource == XCPPROTECT_RESOURCE_CALPAG))
|
||||
{
|
||||
/* Init the result value to okay and only set it to error when a problem
|
||||
* occurred.
|
||||
*/
|
||||
result = true;
|
||||
/* Prepare the command packet. */
|
||||
cmdPacket.data[0] = XCPLOADER_CMD_GET_SEED;
|
||||
/* Always use mode 0 because only seeds up to 48-bit are supported currently.
|
||||
* This fits in 6-bytes, making it work with the all currently supported transport
|
||||
* layers. CAN is the limiting one, because the max packet length is 8-bytes for
|
||||
* this transport layer.
|
||||
*/
|
||||
cmdPacket.data[1] = 0;
|
||||
cmdPacket.data[2] = resource;
|
||||
cmdPacket.len = 3;
|
||||
/* Send the packet. */
|
||||
if (!xcpSettings.transport->SendPacket(&cmdPacket, &resPacket,
|
||||
xcpSettings.timeoutT1))
|
||||
{
|
||||
/* Could not send packet or receive response within the specified timeout. */
|
||||
result = false;
|
||||
}
|
||||
/* Only continue if a response was received. */
|
||||
if (result)
|
||||
{
|
||||
/* Check if the response was valid. */
|
||||
if ( (resPacket.len <= 2) || (resPacket.len > xcpMaxCto) ||
|
||||
(resPacket.data[0] != XCPLOADER_CMD_PID_RES) )
|
||||
{
|
||||
/* Not a valid or positive response. */
|
||||
result = false;
|
||||
}
|
||||
}
|
||||
/* Extract and store the seed. */
|
||||
if (result)
|
||||
{
|
||||
/* Make sure the seed length is valid. */
|
||||
if (resPacket.data[1] > (xcpMaxCto - 2))
|
||||
{
|
||||
result = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Store the seed length. */
|
||||
*seedLen = resPacket.data[1];
|
||||
/* Store the seed. */
|
||||
for (uint8_t idx = 0; idx < *seedLen; idx++)
|
||||
{
|
||||
seed[idx] = resPacket.data[idx + 2];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
/* Give the result back to the caller. */
|
||||
return result;
|
||||
} /*** end of XcpLoaderSendCmdGetSeed ***/
|
||||
|
||||
|
||||
/************************************************************************************//**
|
||||
** \brief Sends the XCP Unlock command.
|
||||
** \param key Pointer to a byte array containing the key.
|
||||
** \param keyLen The length of the key in bytes.
|
||||
** \param protectedResources Current resource protection status.
|
||||
** \return True if successful, false otherwise.
|
||||
**
|
||||
****************************************************************************************/
|
||||
static bool XcpLoaderSendCmdUnlock(uint8_t const * key, uint8_t keyLen,
|
||||
uint8_t * protectedResources)
|
||||
{
|
||||
bool result = false;
|
||||
tXcpTransportPacket cmdPacket;
|
||||
tXcpTransportPacket resPacket;
|
||||
|
||||
/* Make sure a valid transport layer is linked and that the parameters are valid. */
|
||||
assert(xcpSettings.transport != NULL);
|
||||
assert(key != NULL);
|
||||
assert(keyLen > 0);
|
||||
assert(keyLen < (xcpMaxCto - 2));
|
||||
assert(protectedResources != NULL);
|
||||
|
||||
/* Only continue with a valid transport layer and parameters. */
|
||||
if ( (xcpSettings.transport != NULL) && (key != NULL) && (keyLen > 0) &&
|
||||
(keyLen < (xcpMaxCto - 2)) && (protectedResources != NULL) ) /*lint !e774 */
|
||||
{
|
||||
/* Init the result value to okay and only set it to error when a problem occurred. */
|
||||
result = true;
|
||||
/* Prepare the command packet. */
|
||||
cmdPacket.data[0] = XCPLOADER_CMD_UNLOCK;
|
||||
cmdPacket.data[1] = keyLen;
|
||||
for (uint8_t idx = 0; idx < keyLen; idx++)
|
||||
{
|
||||
cmdPacket.data[idx + 2] = key[idx];
|
||||
}
|
||||
cmdPacket.len = keyLen + 2;
|
||||
/* Send the packet. */
|
||||
if (!xcpSettings.transport->SendPacket(&cmdPacket, &resPacket,
|
||||
xcpSettings.timeoutT1))
|
||||
{
|
||||
/* Could not send packet or receive response within the specified timeout. */
|
||||
result = false;
|
||||
}
|
||||
/* Only continue if a response was received. */
|
||||
if (result)
|
||||
{
|
||||
/* Check if the response was valid. */
|
||||
if ( (resPacket.len != 2) || (resPacket.data[0] != XCPLOADER_CMD_PID_RES) )
|
||||
{
|
||||
/* Not a valid or positive response. */
|
||||
result = false;
|
||||
}
|
||||
}
|
||||
/* Store the current resource protection status. */
|
||||
if (result)
|
||||
{
|
||||
*protectedResources = resPacket.data[1];
|
||||
}
|
||||
}
|
||||
/* Give the result back to the caller. */
|
||||
return result;
|
||||
} /*** end of XcpLoaderSendCmdUnlock ***/
|
||||
|
||||
|
||||
/************************************************************************************//**
|
||||
** \brief Sends the XCP Set MTA command.
|
||||
** \param address New MTA address for the slave.
|
||||
|
|
|
@ -94,6 +94,8 @@ typedef struct t_xcp_loader_settings
|
|||
uint16_t timeoutT7;
|
||||
/** \brief Connection mode used in the XCP connect command. */
|
||||
uint8_t connectMode;
|
||||
/** \brief Seed/key algorithm library filename. */
|
||||
char const * seedKeyFile;
|
||||
/** \brief Pointer to the transport layer to use during protocol communications. */
|
||||
tXcpTransport const * transport;
|
||||
/** \brief Pointer to the settings for the transport layer. */
|
||||
|
|
|
@ -0,0 +1,61 @@
|
|||
/************************************************************************************//**
|
||||
* \file xcpprotect.h
|
||||
* \brief XCP Protection module header file.
|
||||
* \ingroup XcpLoader
|
||||
* \internal
|
||||
*----------------------------------------------------------------------------------------
|
||||
* C O P Y R I G H T
|
||||
*----------------------------------------------------------------------------------------
|
||||
* Copyright (c) 2017 by Feaser http://www.feaser.com All rights reserved
|
||||
*
|
||||
*----------------------------------------------------------------------------------------
|
||||
* L I C E N S E
|
||||
*----------------------------------------------------------------------------------------
|
||||
* This file is part of OpenBLT. OpenBLT is free software: you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License as published by the Free
|
||||
* Software Foundation, either version 3 of the License, or (at your option) any later
|
||||
* version.
|
||||
*
|
||||
* OpenBLT is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
|
||||
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
|
||||
* PURPOSE. See the GNU General Public License for more details.
|
||||
*
|
||||
* You have received a copy of the GNU General Public License along with OpenBLT. It
|
||||
* should be located in ".\Doc\license.html". If not, contact Feaser to obtain a copy.
|
||||
*
|
||||
* \endinternal
|
||||
****************************************************************************************/
|
||||
#ifndef XCPPROTECT_H
|
||||
#define XCPPROTECT_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/****************************************************************************************
|
||||
* Macro definitions
|
||||
****************************************************************************************/
|
||||
/* XCP supported resources. */
|
||||
#define XCPPROTECT_RESOURCE_PGM (0x10u) /**< ProGraMing resource. */
|
||||
#define XCPPROTECT_RESOURCE_STIM (0x08u) /**< data STIMulation resource. */
|
||||
#define XCPPROTECT_RESOURCE_DAQ (0x04u) /**< Data AcQuisition resource. */
|
||||
#define XCPPROTECT_RESOURCE_CALPAG (0x01u) /**< CALibration and PAGing resource. */
|
||||
|
||||
|
||||
/****************************************************************************************
|
||||
* Function prototypes
|
||||
****************************************************************************************/
|
||||
void XcpProtectInit(char const * seedKeyFile);
|
||||
void XcpProtectTerminate(void);
|
||||
bool XCPProtectComputeKeyFromSeed(uint8_t resource, uint8_t seedLen,
|
||||
uint8_t const * seedPtr, uint8_t * keyLenPtr,
|
||||
uint8_t * keyPtr);
|
||||
bool XcpProtectGetPrivileges(uint8_t * resourcePtr);
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* XCPPROTECT_H */
|
||||
/*********************************** end of xcpprotect.h *******************************/
|
|
@ -108,7 +108,7 @@ static void XcpTpUartInit(void const * settings)
|
|||
{
|
||||
/* Shallow copy the transport layer settings for layer usage. */
|
||||
tpUartSettings = *((tXcpTpUartSettings *)settings);
|
||||
/* The portname is a pointer and it is not gauranteed that it stays valid so we need
|
||||
/* The portname is a pointer and it is not guaranteed that it stays valid so we need
|
||||
* to deep copy this one. note the +1 for '\0' in malloc.
|
||||
*/
|
||||
assert(((tXcpTpUartSettings *)settings)->portname != NULL);
|
||||
|
|
|
@ -85,7 +85,7 @@ LIBOPENBLT_EXPORT uint32_t XCP_ComputeKeyFromSeed(uint8_t resource, uint8_t seed
|
|||
|
||||
|
||||
/************************************************************************************//**
|
||||
** \brief Computes the key for the requested resource.
|
||||
** \brief Obtains a bitmask of the resources for which an key algorithm is available.
|
||||
** \param resourcePtr pointer where to store the supported resources for the key
|
||||
** computation.
|
||||
** \return XCP_RESULT_OK on success, otherwise XCP_RESULT_ERROR.
|
||||
|
|
Loading…
Reference in New Issue