1
0
mirror of https://github.com/wolfSSL/wolfssl.git synced 2026-10-24 04:09:07 +03:00

Fix QNX CAAM partition ownership tracking

This commit is contained in:
Aidan Garske
2026-09-01 15:29:49 -07:00
parent 10df338fa6
commit b47b771563
3 changed files with 189 additions and 35 deletions

View File

@@ -125,6 +125,7 @@ static int caamTestFreeCalls;
static int caamTestGetPartitionCalls;
static int caamTestEcdsaCalls;
static unsigned int caamTestEcdsaPartition;
static CAAM_ADDRESS caamTestPartitionAddress;
static const unsigned char* caamTestReadData;
static size_t caamTestReadDataSz;
static unsigned char caamTestMappedBuffer[64];
@@ -270,7 +271,7 @@ static CAAM_ADDRESS caamTestGetPartition(unsigned int part, int partSz,
(void)partSz;
(void)flag;
caamTestGetPartitionCalls++;
return 0;
return caamTestPartitionAddress;
}
static int caamTestFreePart(unsigned int part)
@@ -469,8 +470,10 @@ static int testRejectInvalidPartitionIndex(void)
memset(&ctp, 0, sizeof(ctp));
memset(&msg, 0, sizeof(msg));
memset(&ocb, 0, sizeof(ocb));
for (i = 0; i < MAX_OWNER_PART; i++)
for (i = 0; i < MAX_OWNER_PART; i++) {
sm_ownerId[i] = 0;
sm_pagePart[i] = NO_OWNER_PART;
}
if (!CAAM_QNX_PARTITION_IS_VALID(0U) ||
!CAAM_QNX_PARTITION_IS_VALID(CAAM_QNX_MAX_PARTITIONS - 1U) ||
@@ -538,6 +541,11 @@ static int testRejectOtherOwnerPartitionAccess(void)
ctp.size = sizeof(msg.i) + sizeof(args);
msg.o.nbytes = 1U;
for (i = 0; i < MAX_OWNER_PART; i++) {
sm_ownerId[i] = 0;
sm_pagePart[i] = NO_OWNER_PART;
}
for (i = 0; i < 3; i++) {
memset(args, 0, sizeof(args));
if (commands[i] == WC_CAAM_FREE_PART) {
@@ -550,6 +558,7 @@ static int testRejectOtherOwnerPartitionAccess(void)
msg.i.dcmd = commands[i];
sm_ownerId[0] = (CAAM_ADDRESS)&owner;
sm_pagePart[0] = 0U;
caamTestFreeCalls = 0;
caamTestReadData = (const unsigned char*)args;
caamTestReadDataSz = sizeof(args);
@@ -567,6 +576,66 @@ static int testRejectOtherOwnerPartitionAccess(void)
return 0;
}
static int testPartitionOwnerMapping(void)
{
resmgr_context_t ctp;
io_devctl_t msg;
iofunc_ocb_t owner;
iofunc_ocb_t other;
CAAM_ADDRESS partAddr;
unsigned int args[4];
int ret;
int i;
memset(&ctp, 0, sizeof(ctp));
memset(&msg, 0, sizeof(msg));
memset(&owner, 0, sizeof(owner));
memset(&other, 0, sizeof(other));
for (i = 0; i < MAX_OWNER_PART; i++) {
sm_ownerId[i] = 0;
sm_pagePart[i] = NO_OWNER_PART;
}
partAddr = CAAM_PAGE + (5U * CAAM_PAGE_SZ);
memset(args, 0, sizeof(args));
args[0] = 3U;
args[1] = 1U;
caamTestPartitionAddress = partAddr;
caamTestGetPartitionCalls = 0;
ret = doGET_PART(&ctp, &msg, args, 0U, &owner);
if (ret != EOK || caamTestGetPartitionCalls != 1 ||
sm_ownerId[args[0]] != (CAAM_ADDRESS)&owner) {
return 1;
}
if (checkPartitionOwner(partAddr + 1U, &owner) != EOK ||
checkPartitionOwner(partAddr + 1U, &other) != EACCES) {
return 1;
}
ret = doGET_PART(&ctp, &msg, args, 0U, &other);
if (ret != EACCES || caamTestGetPartitionCalls != 1 ||
sm_ownerId[args[0]] != (CAAM_ADDRESS)&owner) {
return 1;
}
ctp.size = sizeof(msg.i) + sizeof(args);
msg.i.dcmd = WC_CAAM_FREE_PART;
caamTestFreeCalls = 0;
caamTestReadData = (const unsigned char*)args;
caamTestReadDataSz = sizeof(args);
caamTestReadSz = sizeof(args);
ret = io_devctl(&ctp, &msg, &owner);
caamTestReadData = NULL;
caamTestReadDataSz = 0U;
if (ret != EOK || caamTestFreeCalls != 1 || sm_ownerId[args[0]] != 0 ||
sm_pagePart[5] != NO_OWNER_PART) {
return 1;
}
return 0;
}
static int testRejectInvalidPartitionRange(void)
{
CAAM_ADDRESS lastPart;
@@ -597,8 +666,14 @@ static int testRejectInvalidPartitionRange(void)
int main(void)
{
int i;
if (pthread_mutex_init(&sm_mutex, NULL) != EOK)
return 1;
for (i = 0; i < MAX_OWNER_PART; i++) {
sm_ownerId[i] = 0;
sm_pagePart[i] = NO_OWNER_PART;
}
if (testRejectIncompleteRequest() != 0) {
printf("testRejectIncompleteRequest: FAIL\n");
return 1;
@@ -619,6 +694,10 @@ int main(void)
printf("testRejectOtherOwnerPartitionAccess: FAIL\n");
return 1;
}
if (testPartitionOwnerMapping() != 0) {
printf("testPartitionOwnerMapping: FAIL\n");
return 1;
}
if (testRejectInvalidPartitionRange() != 0) {
printf("testRejectInvalidPartitionRange: FAIL\n");
return 1;
@@ -631,6 +710,7 @@ int main(void)
printf("testRejectOversizedRequest: PASS\n");
printf("testRejectInvalidPartitionIndex: PASS\n");
printf("testRejectOtherOwnerPartitionAccess: PASS\n");
printf("testPartitionOwnerMapping: PASS\n");
printf("testRejectInvalidPartitionRange: PASS\n");
return 0;
}

View File

@@ -84,11 +84,11 @@ static struct CAAM_DEVICE caam;
#if defined(__QNX__) || defined(__QNXNTO__)
static unsigned int caamGetPartitionCount(void)
{
unsigned int count;
unsigned int lastPartition;
count = (CAAM_READ(caam.ring.BaseAddr + CAAM_SM_SMVID_MS) >> 12U) &
lastPartition = (CAAM_READ(caam.ring.BaseAddr + CAAM_SM_SMVID_MS) >> 12U) &
0xFU;
return count + 1U;
return lastPartition + 1U;
}
#endif
@@ -183,7 +183,7 @@ static void printSecureMemoryInfo()
printf("SMPO = 0x%08X\n", CAAM_READ(caam.ring.BaseAddr + CAAM_SM_SMPO));
SMVID_MS = CAAM_READ(caam.ring.BaseAddr + CAAM_SM_SMVID_MS);
SMVID_LS = CAAM_READ(caam.ring.BaseAddr + CAAM_SM_SMVID_LS);
printf("\tNumber Partitions : %d\n", ((SMVID_MS >> 12) & 0xFU));
printf("\tHighest Partition : %d\n", ((SMVID_MS >> 12) & 0xFU));
printf("\tNumber Pages : %d\n", (SMVID_MS & 0x3FFU));
printf("\tPage Size : 2^%d\n", ((SMVID_LS >> 16) & 0x7U));
}
@@ -1320,6 +1320,7 @@ int caamECDSAMake(DESCSTRUCT* desc, CAAM_BUFFER* buf, unsigned int args[4])
void *vaddr[2];
#ifndef WOLFSSL_CAAM_NO_SM
unsigned int part = 0;
unsigned int page = 0;
unsigned int phys;
#endif
@@ -1345,8 +1346,9 @@ int caamECDSAMake(DESCSTRUCT* desc, CAAM_BUFFER* buf, unsigned int args[4])
return -1;
}
/* create and claim the partition */
err = caamCreatePartition(&part, part, CAAM_SM_CSP | CAAM_SM_SMAP_LOCK |
/* create and claim the partition, the allocated page is returned in
* page while part keeps the partition number */
err = caamCreatePartition(&page, part, CAAM_SM_CSP | CAAM_SM_SMAP_LOCK |
CAAM_SM_CSP | CAAM_SM_ALL_RW);
if (err != Success) {
WOLFSSL_MSG("error creating partition for secure ecc key");
@@ -1354,7 +1356,7 @@ int caamECDSAMake(DESCSTRUCT* desc, CAAM_BUFFER* buf, unsigned int args[4])
}
/* map secure partition to virtual address */
phys = (CAAM_PAGE + (part << 12));
phys = (CAAM_PAGE + (page << 12));
pt = (unsigned char*)buf[0].TheAddress;
pt[0] = (phys >> 24) & 0xFF;
pt[1] = (phys >> 16) & 0xFF;

View File

@@ -92,8 +92,10 @@ static void caamZeroMemory(void* mem, size_t len)
/* keep track of which ID memory belongs to so it can be free'd up */
#define MAX_OWNER_PART CAAM_QNX_MAX_PARTITIONS
#define NO_OWNER_PART MAX_OWNER_PART
pthread_mutex_t sm_mutex;
CAAM_ADDRESS sm_ownerId[MAX_OWNER_PART];
unsigned int sm_pagePart[MAX_OWNER_PART];
/* variables for I/O of resource manager */
resmgr_connect_funcs_t connect_funcs;
@@ -363,19 +365,23 @@ static int sanityCheckPartitionAddress(CAAM_ADDRESS partAddr, int partSz)
static int checkPartitionOwner(CAAM_ADDRESS partAddr, iofunc_ocb_t *ocb)
{
unsigned int pageNumber;
unsigned int partNumber;
int ret = EOK;
partNumber = (unsigned int)((partAddr - CAAM_PAGE) / CAAM_PAGE_SZ);
if (!CAAM_QNX_PARTITION_IS_VALID(partNumber))
pageNumber = (unsigned int)((partAddr - CAAM_PAGE) / CAAM_PAGE_SZ);
if (!CAAM_QNX_PARTITION_IS_VALID(pageNumber))
return EBADMSG;
if (pthread_mutex_lock(&sm_mutex) != EOK) {
return ECANCELED;
}
else {
if (sm_ownerId[partNumber] != (CAAM_ADDRESS)ocb)
partNumber = sm_pagePart[pageNumber];
if (!CAAM_QNX_PARTITION_IS_VALID(partNumber) ||
sm_ownerId[partNumber] != (CAAM_ADDRESS)ocb) {
ret = EACCES;
}
pthread_mutex_unlock(&sm_mutex);
}
@@ -383,6 +389,18 @@ static int checkPartitionOwner(CAAM_ADDRESS partAddr, iofunc_ocb_t *ocb)
}
static void clearPartitionOwner(unsigned int partNumber)
{
unsigned int i;
sm_ownerId[partNumber] = 0;
for (i = 0; i < MAX_OWNER_PART; i++) {
if (sm_pagePart[i] == partNumber)
sm_pagePart[i] = NO_OWNER_PART;
}
}
/* return 0 on success */
static int getArgs(unsigned int args[4], resmgr_context_t *ctp, io_devctl_t *msg,
unsigned int *idx, unsigned int maxIdx)
@@ -896,7 +914,7 @@ static int doAES(resmgr_context_t *ctp, io_devctl_t *msg, unsigned int args[4],
totalSz = (unsigned int)expectedReadSz + (unsigned int)outSz;
if (totalSz < WOLFSSL_CAAM_QNX_MEMORY) {
if (sem_trywait(&localMemSem) == 0) {
if (localMemory != NULL && sem_trywait(&localMemSem) == 0) {
key = localMemory;
phyMem = localPhy;
useLocalMem = 1;
@@ -1013,14 +1031,17 @@ static int doAES(resmgr_context_t *ctp, io_devctl_t *msg, unsigned int args[4],
}
if (pt != NULL) {
caamZeroMemory(key, (size_t)expectedReadSz);
/* wipe the whole buffer, including the output region, so decrypted
* data does not stay resident in the mapping being released */
caamZeroMemory(key, (size_t)totalSz);
CAAM_ADR_UNMAP(pt, 0, totalSz, 0);
}
if (useLocalMem) {
/* done using local mapped memory */
/* done using local mapped memory, wipe the whole buffer including the
* output region since this memory persists between operations */
if (key != NULL)
caamZeroMemory(key, (size_t)expectedReadSz);
caamZeroMemory(key, (size_t)totalSz);
sem_post(&localMemSem);
}
@@ -1037,6 +1058,9 @@ static int doECDSA_KEYPAIR(resmgr_context_t *ctp, io_devctl_t *msg,
int ret = EOK;
int keySz;
int privSz;
unsigned int partNumber;
unsigned int pageNumber;
CAAM_ADDRESS keyAddr;
DESCSTRUCT desc;
CAAM_BUFFER tmp[2];
iov_t out_iovs[3];
@@ -1089,13 +1113,23 @@ static int doECDSA_KEYPAIR(resmgr_context_t *ctp, io_devctl_t *msg,
}
}
/* claim ownership of a secure memory location */
/* claim ownership so later sign/ECDH can check the caller. args[2] is the
* partition, priv holds the key's physical address used to find the page */
if (ret == EOK && args[0] == CAAM_BLACK_KEY_SM) {
if (pthread_mutex_lock(&sm_mutex) != EOK) {
partNumber = args[2];
keyAddr = ((CAAM_ADDRESS)priv[0] << 24) | ((CAAM_ADDRESS)priv[1] << 16) |
((CAAM_ADDRESS)priv[2] << 8) | (CAAM_ADDRESS)priv[3];
pageNumber = (unsigned int)((keyAddr - CAAM_PAGE) / CAAM_PAGE_SZ);
if (!CAAM_QNX_PARTITION_IS_VALID(partNumber) ||
!CAAM_QNX_PARTITION_IS_VALID(pageNumber)) {
ret = EBADMSG;
}
else if (pthread_mutex_lock(&sm_mutex) != EOK) {
ret = ECANCELED;
}
else {
sm_ownerId[args[2]] = (CAAM_ADDRESS)ocb;
sm_ownerId[partNumber] = (CAAM_ADDRESS)ocb;
sm_pagePart[pageNumber] = partNumber;
pthread_mutex_unlock(&sm_mutex);
}
}
@@ -1218,7 +1252,7 @@ static int doECDSA_VERIFY(resmgr_context_t *ctp, io_devctl_t *msg,
* returns EOK on success
*/
static int doECDSA_SIGN(resmgr_context_t *ctp, io_devctl_t *msg,
unsigned int args[4], unsigned int idx)
unsigned int args[4], unsigned int idx, iofunc_ocb_t *ocb)
{
int ret, keySz;
DESCSTRUCT desc;
@@ -1261,6 +1295,15 @@ static int doECDSA_SIGN(resmgr_context_t *ctp, io_devctl_t *msg,
return EOVERFLOW;
}
/* a secure memory key is referenced only by its address, reject one that
* the caller does not own so it can not sign with another client's key */
if (args[0] == CAAM_BLACK_KEY_SM) {
ret = checkPartitionOwner(blackKey, ocb);
if (ret != EOK) {
CAAM_ADR_UNMAP(hash, 0, args[2], 0);
return ret;
}
}
/* setup CAAM buffers to pass to driver */
if (args[0] == CAAM_BLACK_KEY_SM) {
@@ -1332,7 +1375,7 @@ static int doECDSA_SIGN(resmgr_context_t *ctp, io_devctl_t *msg,
* returns EOK on success
*/
static int doECDSA_ECDH(resmgr_context_t *ctp, io_devctl_t *msg,
unsigned int args[4], unsigned int idx)
unsigned int args[4], unsigned int idx, iofunc_ocb_t *ocb)
{
int ret;
DESCSTRUCT desc;
@@ -1394,6 +1437,18 @@ static int doECDSA_ECDH(resmgr_context_t *ctp, io_devctl_t *msg,
return ECANCELED;
}
/* a secure memory private key is referenced only by its address, reject
* one the caller does not own so it can not derive with another client's
* key */
if (args[0] == CAAM_BLACK_KEY_SM) {
ret = checkPartitionOwner(blackKey, ocb);
if (ret != EOK) {
if (pubkey != NULL)
CAAM_ADR_UNMAP(pubkey, 0, args[3]*2, 0);
return ret;
}
}
/* setup CAAM buffers to pass to driver */
if (args[1] == CAAM_BLACK_KEY_SM) {
tmp[0].TheAddress = securePub;
@@ -1509,6 +1564,7 @@ static int doGET_PART(resmgr_context_t *ctp, io_devctl_t *msg,
unsigned int args[4], unsigned int idx, iofunc_ocb_t *ocb)
{
unsigned int partNumber;
unsigned int pageNumber;
int partSz;
CAAM_ADDRESS partAddr;
iov_t out_iov;
@@ -1519,21 +1575,36 @@ static int doGET_PART(resmgr_context_t *ctp, io_devctl_t *msg,
if (!CAAM_QNX_PARTITION_IS_VALID(partNumber))
return EBADMSG;
partAddr = caamGetPartition(partNumber, partSz, 0);
if (partAddr == 0) {
return EBADMSG;
}
SETIOV(&out_iov, &partAddr, sizeof(CAAM_ADDRESS));
resmgr_msgwritev(ctp, &out_iov, 1, sizeof(msg->o));
if (pthread_mutex_lock(&sm_mutex) != EOK) {
return ECANCELED;
}
else {
sm_ownerId[partNumber] = (CAAM_ADDRESS)ocb;
if (sm_ownerId[partNumber] != 0 &&
sm_ownerId[partNumber] != (CAAM_ADDRESS)ocb) {
pthread_mutex_unlock(&sm_mutex);
return EACCES;
}
partAddr = caamGetPartition(partNumber, partSz, 0);
if (partAddr == 0) {
pthread_mutex_unlock(&sm_mutex);
return EBADMSG;
}
pageNumber = (unsigned int)((partAddr - CAAM_PAGE) / CAAM_PAGE_SZ);
if (!CAAM_QNX_PARTITION_IS_VALID(pageNumber) ||
(sm_pagePart[pageNumber] != NO_OWNER_PART &&
sm_pagePart[pageNumber] != partNumber)) {
pthread_mutex_unlock(&sm_mutex);
return ECANCELED;
}
sm_ownerId[partNumber] = (CAAM_ADDRESS)ocb;
sm_pagePart[pageNumber] = partNumber;
pthread_mutex_unlock(&sm_mutex);
SETIOV(&out_iov, &partAddr, sizeof(CAAM_ADDRESS));
resmgr_msgwritev(ctp, &out_iov, 1, sizeof(msg->o));
return EOK;
}
@@ -1703,11 +1774,11 @@ int io_devctl (resmgr_context_t *ctp, io_devctl_t *msg, iofunc_ocb_t *ocb)
break;
case WC_CAAM_ECDSA_SIGN:
ret = doECDSA_SIGN(ctp, msg, args, idx);
ret = doECDSA_SIGN(ctp, msg, args, idx, ocb);
break;
case WC_CAAM_ECDSA_ECDH:
ret = doECDSA_ECDH(ctp, msg, args, idx);
ret = doECDSA_ECDH(ctp, msg, args, idx, ocb);
break;
case WC_CAAM_FIFO_S:
@@ -1736,7 +1807,7 @@ int io_devctl (resmgr_context_t *ctp, io_devctl_t *msg, iofunc_ocb_t *ocb)
ret = ECANCELED;
}
else {
sm_ownerId[args[0]] = 0;
clearPartitionOwner(args[0]);
pthread_mutex_unlock(&sm_mutex);
ret = EOK;
}
@@ -1791,7 +1862,7 @@ int io_close_ocb(resmgr_context_t *ctp, void *reserved, RESMGR_OCB_T *ocb)
else {
for (i = 0; i < MAX_OWNER_PART; i++) {
if (sm_ownerId[i] == (CAAM_ADDRESS)ocb) {
sm_ownerId[i] = 0;
clearPartitionOwner((unsigned int)i);
#if defined(WOLFSSL_CAAM_DEBUG) || defined(WOLFSSL_CAAM_PRINT)
printf("found dangiling partition at index %d\n", i);
#endif
@@ -1880,6 +1951,7 @@ int main(int argc, char *argv[])
pthread_mutex_init(&sm_mutex, NULL);
for (i = 0; i < MAX_OWNER_PART; i++) {
sm_ownerId[i] = 0;
sm_pagePart[i] = NO_OWNER_PART;
}
if (InitCAAM() != 0) {