FreeCalypso > hg > tcs211-c139
diff g23m/condat/com/src/comlib/sec_drv_prim.c @ 0:509db1a7b7b8
initial import: leo2moko-r1
author | Space Falcon <falcon@ivan.Harhan.ORG> |
---|---|
date | Mon, 01 Jun 2015 03:24:05 +0000 |
parents | |
children |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/g23m/condat/com/src/comlib/sec_drv_prim.c Mon Jun 01 03:24:05 2015 +0000 @@ -0,0 +1,715 @@ +#include "general.h" +#include "typedefs.h" +#include "vsi.h" +#include <stdlib.h> +#include <string.h> +#include "sec_drv.h" +#include "sec_drv_prim.h" +#include "ffs/ffs.h" + +#ifndef NON_ENCRYPTED_MODE +#include "cl_des.h" +#include "cl_imei.h" +#endif + + +/* +Layout of flash: + T_SEC_DRV_GLOBAL_CONF + T_SEC_DRV_KEY (failure count) + T_SEC_DRV_CONFIGURATION + { + T_SEC_DRV_KEY + T_SEC_DRV_CATEGORY (T_SEC_DRV_CAT_HDR + SEC_DRV_CAT_MAX_SIZE*UINT8) + }[configuration -> number of categories] +*/ + + +/******************************************* + Global variables +*******************************************/ + +#ifndef FFS_MODE_ENABLED +/* SIM lock data area in flash */ +#pragma DATA_SECTION(d_mepd_data, ".mepd") +volatile const UINT8 d_mepd_data; // Adress of first byte in 8 kb buffer +#endif /* FFS_MODE_ENABLED */ + +static T_SEC_DRV_GLOBAL_CONF gGlobalConf; +static INT8 gGlobalConfRead = FALSE; +INT8 sec_drv_fast_write = FALSE; +static INT16 gMaxCategories = 0; + +#if (defined(RSA_HEAP_IS_INTERNAL) && defined(FIRSTBOOT_RSA_ENABLED)) || (defined(USE_RSAHEAP_FOR_FLASH) && !defined(FFS_MODE_ENABLED)) +#ifdef USE_RSAHEAP_FOR_FLASH +char sec_drv_buffer[SEC_FLASH_SIZE]; +#else /* USE_RSAHEAP_FOR_FLASH */ +char sec_drv_buffer[RSA_HEAP_SIZE]; +#endif /* USE_RSAHEAP_FOR_FLASH */ +#endif + + +/******************************************* + Trace functionality +*******************************************/ +#ifdef SEC_TRACES_ENABLED +static void _trace(const char *str) +{ + T_FFS_FD test_file; + test_file = ffs_open("/testfile.txt", FFS_O_CREATE | FFS_O_WRONLY | FFS_O_APPEND); + if (test_file > 0) + { + ffs_write(test_file, (char *)str, strlen((char *)str)); + ffs_close(test_file); + } +} +void test_trace(const char *str) +{ + char *s = (char *)str; + T_FFS_FD test_file; + test_file = ffs_open("/testfile.txt", FFS_O_CREATE | FFS_O_WRONLY | FFS_O_APPEND); + if (test_file > 0) + { + ffs_write(test_file, s, strlen(s)); + s = "\n"; + ffs_write(test_file, s, strlen(s)); + ffs_close(test_file); + } +} +void hex_trace(const char *str, const void *in, unsigned long int size) +{ + char buffer[4]; + unsigned long int i; + _trace(str); + for (i=0; i<size; i++) + { + sprintf(buffer, "%02x ", ((volatile unsigned char *)in)[i]); + _trace(buffer); + } + _trace("\n"); +} +#endif /* SEC_TRACES_ENABLED */ + + +#ifdef FFS_MODE_ENABLED +/******************************************* + FFS functions +*******************************************/ +void sec_drv_flash_backup(void) +{ } + + +void sec_drv_remove_backup(void) +{ } + + +void sec_drv_erase_flash(void) +{ } + + +void sec_drv_read_flash(UINT32 offset, void *pDest, UINT32 size) +{ + T_FFS_FD file; + file = ffs_open(FFS_MEPD_FILENAME, FFS_O_RDONLY); + if (file <= 0) + { + memset(pDest, 0, size); + TRACE("sec_drv_read_flash - FAILed opening file!"); + } + else + { + ffs_seek(file, offset, FFS_SEEK_SET); + ffs_read(file, pDest, size); + ffs_close(file); + } +} + + +void sec_drv_write_flash(UINT32 offset, const void *pSrc, UINT32 size) +{ + T_FFS_FD file; + file = ffs_open(FFS_MEPD_FILENAME, FFS_O_WRONLY ); + if (!(file <= 0)) + { + ffs_seek(file, offset, FFS_SEEK_SET); + ffs_write(file, (void *)pSrc, size); + ffs_close(file); + } + else + { + TRACE("sec_drv_write_flash - FAILed opening file!"); + } +} + +#else /* FFS_MODE_ENABLED */ + +/******************************************* + Memory functions +*******************************************/ +UINT32 gBackupOffset; + +void sec_drv_flash_backup(void) +{ + if (!sec_drv_fast_write) + { + TRACE("sec_drv_flash_backup"); +#ifdef USE_RSAHEAP_FOR_FLASH + sec_drv_read_flash(0, (void *)SEC_DRV_RSA_HEAP, SEC_FLASH_SIZE); +#else /* USE_RSAHEAP_FOR_FLASH */ +#error "QUESTION: what if we don't have the space required?" + T_FFS_FD file = ffs_open(FLASH_BACKUP_NAME, FFS_O_CREATE | FFS_O_WRONLY | FFS_O_TRUNC); + ffs_write(file, (void *)SEC_BASE, SEC_FLASH_SIZE); + ffs_close(file); +#endif /* USE_RSAHEAP_FOR_FLASH */ + gBackupOffset = 0; + } +} + + +void sec_drv_remove_backup(void) +{ + if (!sec_drv_fast_write) + { +#ifdef USE_RSAHEAP_FOR_FLASH + copy_to_flash(0, 0, 0, gBackupOffset, SEC_FLASH_SIZE); + TRACE("sec_drv_remove_backup"); + memset(SEC_DRV_RSA_HEAP, 0xFF, SEC_FLASH_SIZE); +#else /* USE_RSAHEAP_FOR_FLASH */ +#error "QUESTION: what if we don't have the space required?" + T_FFS_FD file; + void *buf; + + TRACE("sec_drv_remove_backup"); + buf = M_ALLOC(BACKUP_BUF_SIZE); + file = ffs_open(FLASH_BACKUP_NAME, FFS_O_RDONLY); + copy_to_flash(file, buf, BACKUP_BUF_SIZE, gBackupOffset, SEC_FLASH_SIZE); + ffs_close(file); + M_FREE(buf); + + ffs_remove(FLASH_BACKUP_NAME); +#endif /* USE_RSAHEAP_FOR_FLASH */ + } +} + + +void sec_drv_erase_flash(void) +{ + if (!sec_drv_fast_write) + { + TRACE("sec_drv_erase_flash"); + sec_drv_amd_erase(); + } +} + + +void sec_drv_read_flash(UINT32 offset, void *pDest, UINT32 size) +{ + void *pSrc = (void *)((UINT32)SEC_BASE + offset); + assert(pSrc != 0L); + assert(pDest != 0L); + assert(size > 0L); + assert(offset >= 0L && (offset+size) <= SEC_FLASH_SIZE); + + memcpy(pDest, pSrc, size); +} + + +static void copy_to_flash(T_FFS_FD file, void *pBuf, UINT32 bufSize, UINT32 offset, UINT32 maxOffset) +{ + UINT32 size = maxOffset-offset; + TRACE("copy_to_flash"); +#ifdef USE_RSAHEAP_FOR_FLASH + sec_drv_amd_write((void *)((UINT32)SEC_BASE+offset), (const void *)((UINT32)SEC_DRV_RSA_HEAP+offset), size); +#else /* USE_RSAHEAP_FOR_FLASH */ + ffs_seek(file, offset, FFS_SEEK_SET); + while(offset < maxOffset) + { + size = (maxOffset-offset > bufSize)? bufSize : maxOffset-offset; + ffs_read(file, pBuf, size); + sec_drv_amd_write((void *)(SEC_BASE + offset), pBuf, size); + offset += size; + } +#endif /* USE_RSAHEAP_FOR_FLASH */ +} + + +void sec_drv_write_flash(UINT32 offset, const void *pSrc, UINT32 size) +{ + assert(pSrc != 0L); + assert(size > 0L); + assert(offset >= 0L && (offset+size) <= SEC_FLASH_SIZE); + + if (sec_drv_fast_write) + { + TRACE("sec_drv_write_flash"); + sec_drv_amd_write((void *)((UINT32)SEC_BASE+offset), pSrc, size); + } + else + { +#ifdef USE_RSAHEAP_FOR_FLASH + copy_to_flash(0, 0, 0, gBackupOffset, offset); + HEXTRACE("sec_drv_write_flash - offset: ", &offset, sizeof(UINT32)); + sec_drv_amd_write((void *)((UINT32)SEC_BASE+offset), pSrc, size); + gBackupOffset = offset+size; +#else /* USE_RSAHEAP_FOR_FLASH */ + T_FFS_FD file; + void *buf; + TRACE("Using FFS"); + buf = M_ALLOC(BACKUP_BUF_SIZE); + file = ffs_open(FLASH_BACKUP_NAME, FFS_O_RDONLY); + copy_to_flash(file, buf, BACKUP_BUF_SIZE, gBackupOffset, offset); + sec_drv_amd_write((void *)((UINT32)SEC_BASE + offset), pSrc, size); + gBackupOffset += size; + ffs_close(file); + M_FREE(buf); +#endif /* USE_RSAHEAP_FOR_FLASH */ + } +} + +#endif /* FFS_MODE_ENABLED */ + + +/******************************************* + DES de-/encryption +*******************************************/ + +/** + * Returns the DES key from the DSP + * + * @return The DES key for use by de-encryption + */ +static const UINT8 *GetDESKey(void) +{ +#ifdef DSP_DES_KEY_ENABLED +#error "Not yet implemented" +#else /* DSP_DES_KEY_ENABLED */ +static const UINT8 desKey[8] = {0x12, 0x34, 0x56, 0x78, 0x12, 0x34, 0x56, 0x78}; +#ifndef NON_ENCRYPTED_MODE +#ifdef CL_IMEI_CALYPSO_PLATFORM +#ifdef FF_PROTECTED_IMEI + volatile USHORT *reg_p = (USHORT *) CL_IMEI_DIE_ID_REG; + USHORT *outBuf16 = (USHORT*)&desKey[0]; + INT8 i; + for (i = 0; i < CL_IMEI_DIE_ID_SIZE; i++) + { + /* Die ID is 4 BYTE long, extract it to 8 BYTE. */ + outBuf16[i] = (USHORT)(*(UINT8*)(reg_p)++); + } +#endif +#endif +#endif + return desKey; +#endif /* DSP_DES_KEY_ENABLED */ +} + + +/** + * Read a crypted block of the secure_area. + * + * @param offset Offset into the secure area from which to read the block. + * @param pDest Pointer to the receiving buffer. + * @param size Size of the block to read. Minimum 1. + */ +static void read_crypted_flash(UINT32 offset, void *pDest, UINT32 size) +{ +#ifndef NON_ENCRYPTED_MODE + UINT8 inbuffer[CRYPT_BLOCK_SIZE]; + UINT8 outbuffer[CRYPT_BLOCK_SIZE]; +#endif + UINT32 blocksize; + assert(offset != 0L); + assert(pDest != 0L); + assert(size > 0L); + assert(offset >= 0L && (offset+size) <= SEC_FLASH_SIZE); + do + { + blocksize = (size>CRYPT_BLOCK_SIZE)? CRYPT_BLOCK_SIZE : size; +#ifdef NON_ENCRYPTED_MODE + sec_drv_read_flash(offset, pDest, blocksize); +#else + sec_drv_read_flash(offset, inbuffer, CRYPT_BLOCK_SIZE); + cl_des((UBYTE *)inbuffer, (UBYTE *)GetDESKey(), (UBYTE *)outbuffer, (UBYTE)CL_DES_DECRYPTION); + memcpy(pDest, outbuffer, blocksize); +#endif + offset += blocksize; + pDest = (void *)((UINT32)pDest + blocksize); + size -= blocksize; + } while(size); +} + + +/** + * Write a crypted block of the secure_area. + * + * @param offset Offset into the secure area from which to write the block. + * @param pDest Pointer to the input buffer. + * @param size Size of the block to write. Minimum 1. + */ +static void write_crypted_flash(UINT32 offset, const void *pSrc, UINT32 size) +{ + UINT8 inbuffer[CRYPT_BLOCK_SIZE]; + UINT8 outbuffer[CRYPT_BLOCK_SIZE]; + UINT32 blocksize; + assert(offset != 0L); + assert(pSrc != 0L); + assert(size > 0L); + assert(offset >= 0L && (offset+size) <= SEC_FLASH_SIZE); + + sec_drv_flash_backup(); + sec_drv_erase_flash(); + do + { + blocksize = (size>CRYPT_BLOCK_SIZE)? CRYPT_BLOCK_SIZE : size; + memset(inbuffer, 0, CRYPT_BLOCK_SIZE); + memcpy(inbuffer, pSrc, blocksize); +#ifdef NON_ENCRYPTED_MODE + memcpy(outbuffer, inbuffer, CRYPT_BLOCK_SIZE); +#else + cl_des((UBYTE *)inbuffer, (UBYTE *)GetDESKey(), (UBYTE *)outbuffer, (UBYTE)CL_DES_ENCRYPTION); +#endif + /* write crypted datablock to flash */ + sec_drv_write_flash(offset, outbuffer, CRYPT_BLOCK_SIZE); + offset += blocksize; + pSrc = (void *)((UINT32)pSrc + blocksize); + size -= blocksize; + } while(size); + sec_drv_remove_backup(); +} + + +/******************************************* + Offset calculations +*******************************************/ + +static UINT32 offset_global_conf(void) +{ + return 0; +} + + +static UINT32 offset_fc_key(void) +{ + return ALIGN_CRYPT_BLOCK(sizeof(T_SEC_DRV_GLOBAL_CONF)); +} + + +static UINT32 offset_configuration(void) +{ + return ALIGN_CRYPT_BLOCK(sizeof(T_SEC_DRV_GLOBAL_CONF)) + + ALIGN_CRYPT_BLOCK(sizeof(T_SEC_DRV_KEY)); +} + + +static UINT32 offset_category_key(int rec_num) +{ + return ALIGN_CRYPT_BLOCK(sizeof(T_SEC_DRV_GLOBAL_CONF)) + + ALIGN_CRYPT_BLOCK(sizeof(T_SEC_DRV_KEY)) + + ALIGN_CRYPT_BLOCK(sizeof(T_SEC_DRV_CONFIGURATION)) + + rec_num * (ALIGN_CRYPT_BLOCK(sizeof(T_SEC_DRV_KEY)) + + ALIGN_CRYPT_BLOCK(sizeof(T_SEC_DRV_CAT_HDR)) + + ALIGN_CRYPT_BLOCK(SEC_DRV_CAT_MAX_SIZE)); +} + + +static UINT32 offset_category_header(int rec_num) +{ + return ALIGN_CRYPT_BLOCK(sizeof(T_SEC_DRV_GLOBAL_CONF)) + + ALIGN_CRYPT_BLOCK(sizeof(T_SEC_DRV_KEY)) + + ALIGN_CRYPT_BLOCK(sizeof(T_SEC_DRV_CONFIGURATION)) + + rec_num * (ALIGN_CRYPT_BLOCK(sizeof(T_SEC_DRV_KEY)) + + ALIGN_CRYPT_BLOCK(sizeof(T_SEC_DRV_CAT_HDR)) + + ALIGN_CRYPT_BLOCK(SEC_DRV_CAT_MAX_SIZE)) + + ALIGN_CRYPT_BLOCK(sizeof(T_SEC_DRV_KEY)); +} + + +static UINT32 offset_category_body(int rec_num) +{ + return ALIGN_CRYPT_BLOCK(sizeof(T_SEC_DRV_GLOBAL_CONF)) + + ALIGN_CRYPT_BLOCK(sizeof(T_SEC_DRV_KEY)) + + ALIGN_CRYPT_BLOCK(sizeof(T_SEC_DRV_CONFIGURATION)) + + rec_num * (ALIGN_CRYPT_BLOCK(sizeof(T_SEC_DRV_KEY)) + + ALIGN_CRYPT_BLOCK(sizeof(T_SEC_DRV_CAT_HDR)) + + ALIGN_CRYPT_BLOCK(SEC_DRV_CAT_MAX_SIZE)) + + ALIGN_CRYPT_BLOCK(sizeof(T_SEC_DRV_KEY)) + + ALIGN_CRYPT_BLOCK(sizeof(T_SEC_DRV_CAT_HDR)); +} + + +/******************************************* + Helper functions +*******************************************/ + +/** + * Check whether or not the secure area has been initialized. + * + * @return TRUE if the secure area has been initialized. + */ +static int check_firstboot_pattern_ok(void) +{ + sec_prim_get_global_conf(0); + if (gGlobalConf.firstboot_pattern != SEC_PATTERN_INITIALIZED) + { + TRACE("check_firstboot_pattern_ok - FAIL"); + return FALSE; + } + return TRUE; +} + + +/** + * Check whether or not the given number of categories is within bounds. + * + * @return TRUE if the given number of categories is within bounds. + */ +static int check_number_categories(int catNum) +{ + BOOL result; + if (!gMaxCategories) + { + T_SEC_DRV_CONFIGURATION conf; + if (sec_prim_get_configuration(&conf)) + { + gMaxCategories = conf.NumCategories; + HEXTRACE("check_number_categories - max: ", &gMaxCategories, sizeof(int)); + } + } + return (catNum >= 0) && (catNum < gMaxCategories); +} + + +/******************************************* + PRIMITIVES +*******************************************/ + +/** + * Read the global configuration for the secure flash area used to store + * SIM lock data. + * + * @param pGlobalConf Pointer where to store the global configuration. + * @return TRUE if the global configuration could be read. + */ +BOOL sec_prim_get_global_conf(T_SEC_DRV_GLOBAL_CONF *pGlobalConf) +{ + if (!gGlobalConfRead) + { + sec_drv_read_flash(offset_global_conf(), &gGlobalConf, sizeof(T_SEC_DRV_GLOBAL_CONF)); + HEXTRACE("sec_prim_get_global_conf: ", &gGlobalConf, sizeof(T_SEC_DRV_GLOBAL_CONF)); + gGlobalConfRead = TRUE; + } + if (pGlobalConf != 0L) + { + memcpy(pGlobalConf, &gGlobalConf, sizeof(T_SEC_DRV_GLOBAL_CONF)); + return TRUE; + } + return FALSE; +} + +/** + * Store the global configuration for the secure flash area used to store + * SIM lock data. + * + * @param pGlobalConf Pointer to a global configuration. + * @return TRUE if the global configuration could be written. + */ +BOOL sec_prim_set_global_conf(const T_SEC_DRV_GLOBAL_CONF *pGlobalConf) +{ + /* Calc total size needed for this configuration */ + if (pGlobalConf == 0L) return FALSE; + + HEXTRACE("sec_prim_set_global_conf: ", pGlobalConf, sizeof(T_SEC_DRV_GLOBAL_CONF)); + sec_drv_flash_backup(); + sec_drv_erase_flash(); + sec_drv_write_flash(offset_global_conf(), pGlobalConf, sizeof(T_SEC_DRV_GLOBAL_CONF)); + sec_drv_remove_backup(); + gGlobalConfRead = FALSE; + return TRUE; +} + + +/** + * Read the configuration for the MEPD structure. + * + * @param pConf Pointer to buffer where the result will be placed + * @Return 0 if flash area hasn't been configured. + */ +BOOL sec_prim_get_configuration(T_SEC_DRV_CONFIGURATION *pConf) +{ + if (! check_firstboot_pattern_ok()) return FALSE; + + read_crypted_flash(offset_configuration(), pConf, sizeof(T_SEC_DRV_CONFIGURATION)); + HEXTRACE("sec_prim_get_configuration: ", pConf, sizeof(T_SEC_DRV_CONFIGURATION)); + return TRUE; +} + + +/** + * Store the configuration for the MEPD structure. + * + * @param pConf Pointer to configuration to set + * @Return TRUE if ok. + */ +BOOL sec_prim_set_configuration(const T_SEC_DRV_CONFIGURATION *pConf) +{ + if (! check_firstboot_pattern_ok()) return FALSE; + if (pConf == 0L) return FALSE; + + HEXTRACE("sec_prim_set_configuration: ", pConf, sizeof(T_SEC_DRV_CONFIGURATION)); + write_crypted_flash(offset_configuration(), pConf, sizeof(T_SEC_DRV_CONFIGURATION)); + gMaxCategories = 0; + return TRUE; +} + + +/** + * Read the key for either the failure counter (category -1) or a + * lock-category (category 0..n). + * + * @param rec_num Category number to operate on + * @param pKey Pointer to keybuffer + * @Return TRUE if ok. + */ +BOOL sec_prim_get_key(int rec_num, T_SEC_DRV_KEY *pKey) +{ + if (pKey!=0L) + { + if ((rec_num == -1) && (check_firstboot_pattern_ok())) + { + /* failure counter key */ + read_crypted_flash(offset_fc_key(), pKey, sizeof(T_SEC_DRV_KEY)); + HEXTRACE("sec_prim_get_key: ", pKey, sizeof(T_SEC_DRV_KEY)); + return TRUE; + } + else if (check_number_categories(rec_num)) + { + /* category key */ + read_crypted_flash(offset_category_key(rec_num), pKey, sizeof(T_SEC_DRV_KEY)); + HEXTRACE("sec_prim_get_key: ", &rec_num, sizeof(int)); + HEXTRACE("sec_prim_get_key: ", pKey, sizeof(T_SEC_DRV_KEY)); + return TRUE; + } + } + return FALSE; +} + + +/** + * Store the key for either the failure counter (category -1) or a + * lock-category (category 0..n). + * + * @param rec_num Category number to operate on + * @param pKey Pointer to keybuffer + * @Return TRUE if ok. + */ +BOOL sec_prim_set_key(int rec_num, const T_SEC_DRV_KEY *pKey) +{ + if (pKey!=0L) + { + if ((rec_num == -1) && (check_firstboot_pattern_ok())) + { + /* failure counter key */ + HEXTRACE("sec_prim_set_key - FC: ", pKey, sizeof(T_SEC_DRV_KEY)); + write_crypted_flash(offset_fc_key(), pKey, sizeof(T_SEC_DRV_KEY)); + return TRUE; + } + else if (check_number_categories(rec_num)) + { + /* category key */ + HEXTRACE("sec_prim_set_key: ", &rec_num, sizeof(int)); + HEXTRACE("sec_prim_set_key: ", pKey, sizeof(T_SEC_DRV_KEY)); + write_crypted_flash(offset_category_key(rec_num), pKey, sizeof(T_SEC_DRV_KEY)); + return TRUE; + } + } + return FALSE; +} + + +/** + * Read a lock-category header. + * + * @param rec_num Category number to operate on + * @param pHdr Where to place the read category header? + * @Return TRUE if ok. + */ +BOOL sec_prim_get_cat_header(int rec_num, T_SEC_DRV_CAT_HDR *pHdr) +{ + if (!check_number_categories(rec_num)) return FALSE; + if (pHdr == 0L) return FALSE; + + read_crypted_flash(offset_category_header(rec_num), pHdr, sizeof(T_SEC_DRV_CAT_HDR)); + HEXTRACE("sec_prim_get_cat_header: ", &rec_num, sizeof(int)); + HEXTRACE("sec_prim_get_cat_header: ", pHdr, sizeof(T_SEC_DRV_CAT_HDR)); + return TRUE; +} + + +/** + * Store a lock-category header. + * + * @param rec_num Category number to operate on + * @param pHdr Pointer to the category header + * @Return TRUE if ok. + */ +BOOL sec_prim_set_cat_header(int rec_num, const T_SEC_DRV_CAT_HDR *pHdr) +{ + if (!check_number_categories(rec_num)) return FALSE; + if (pHdr == 0L) return FALSE; + + HEXTRACE("sec_prim_set_cat_header: ", &rec_num, sizeof(int)); + HEXTRACE("sec_prim_set_cat_header: ", pHdr, sizeof(T_SEC_DRV_CAT_HDR)); + write_crypted_flash(offset_category_header(rec_num), pHdr, sizeof(T_SEC_DRV_CAT_HDR)); + return TRUE; +} + + +/** + * Read a lock-category body (client data). + * + * @param rec_num Category number to operate on + * @param pBody Pointer to buffer where the result will be placed + * @param size Size of the buffer + * @Return TRUE if ok. + */ +BOOL sec_prim_get_cat_body(int rec_num, void *pBody, UINT16 size) +{ + if (!check_number_categories(rec_num)) return FALSE; + if (pBody == 0L) return FALSE; + if (size==0 || size>SEC_DRV_CAT_MAX_SIZE) return FALSE; + + read_crypted_flash(offset_category_body(rec_num), pBody, size); + HEXTRACE("sec_prim_get_cat_body: ", &rec_num, sizeof(int)); + HEXTRACE("sec_prim_get_cat_body: ", pBody, size); + return TRUE; +} + + +/** + * Store a lock-category body (client data). + * + * @param rec_num Category number to operate on + * @param pBody Pointer to data-buffer + * @param size Size of the buffer + * @Return TRUE if ok. + */ +BOOL sec_prim_set_cat_body(int rec_num, const void *pBody, UINT16 size) +{ + T_SEC_DRV_CAT_HDR hdr; + + if (!check_number_categories(rec_num)) return FALSE; + if (pBody == 0L) return FALSE; + + sec_prim_get_cat_header(rec_num, &hdr); + if (hdr.DataLen != size) + { + hdr.DataLen = size; + sec_prim_set_cat_header(rec_num, &hdr); + } + if (size) + { + HEXTRACE("sec_prim_set_cat_body: ", &rec_num, sizeof(int)); + HEXTRACE("sec_prim_set_cat_body: ", pBody, size); + write_crypted_flash(offset_category_body(rec_num), pBody, size); + } + return TRUE; +}