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:
Frank Voorburg 2017-10-26 14:06:17 +00:00
parent a16099de24
commit 32e11ecf9a
10 changed files with 856 additions and 8 deletions

View File

@ -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})

View File

@ -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

View File

@ -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;

View File

@ -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 *******************************/

View File

@ -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 *******************************/

View File

@ -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, &currentlyProtectedResources))
{
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.

View File

@ -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. */

View File

@ -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 *******************************/

View File

@ -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);

View File

@ -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.