Skip to content

Occasional hard falt when using the mbedtls entropy fucntion in parrallel threads (K64F) #9513

@adamelhakham

Description

@adamelhakham

Description

I am part of the group that develops the Pelion Device Management Client. We use mbed-os with KVSTORE and in our testing we do a lot of seeding of a DRBG, which calls the mbedtls mbedtls_entropy_func function, which calls the mbedtls_hardware_poll function to generate random entropy from the K64F hardware.
In addition, the Pelion device management client runs a thread that every number of seconds tries to generate random data from the mbedtls_hardware_poll API. The problem is that the mbedtls_hardware_poll API is not thread safe and we occationally get the following hard fault:

++ MbedOS Fault Handler ++

FaultType: HardFault

Context:
R0   : 20008CF5
R1   : 00000005
R2   : 40029004
R3   : 00010000
R4   : 00000030
R5   : 0000001B
R6   : 20008CF5
R7   : 40029000
R8   : 20008CDC
R9   : 00000000
R10  : 00000000
R11  : 00000000
R12  : 00000010
SP   : 20008CA8
LR   : 0001CC0B
PC   : 0001CBDC
xPSR : 41000000
PSP  : 20008C88
MSP  : 2002FFB8
CPUID: 410FC241
HFSR : 40000000
MMFSR: 00000000
BFSR : 00000082
UFSR : 00000000
DFSR : 00000008
AFSR : 00000000
BFAR : 40029004
Mode : Thread
Priv : Privileged
Stack: PSP

-- MbedOS Fault Handler --



++ MbedOS Error Info ++
Error Status: 0x80FF013D Code: 317 Module: 255
Error Message: Fault exception
Location: 0x16441
Error Value: 0x1CBDC
Current Thread: 20008d60  Id: 0x20008D88 Entry: 0x83CD StackSize: 0x11B8 StackMem: 0x20007B80 SP: 0x2002FF10
For more info, visit: https://armmbed.github.io/mbedos-error/?error=0x80FF013D
-- MbedOS Error Info --

After disassembling the code, program counter points to the following instruction (the disasse:

0001cbb4 <trng_get_byte>:
   1cbb4:	2100      	movs	r1, #0
   1cbb6:	7001      	strb	r1, [r0, #0]
   1cbb8:	f249 0204 	movw	r2, #36868	; 0x9004
   1cbbc:	f2c4 0202 	movt	r2, #16386	; 0x4002
   1cbc0:	e00c      	b.n	1cbdc <trng_get_byte+0x28>
   1cbc2:	6893      	ldr	r3, [r2, #8]
   1cbc4:	f003 0301 	and.w	r3, r3, #1
   1cbc8:	fa03 fc01 	lsl.w	ip, r3, r1
   1cbcc:	7803      	ldrb	r3, [r0, #0]
   1cbce:	ea43 030c 	orr.w	r3, r3, ip
   1cbd2:	7003      	strb	r3, [r0, #0]
   1cbd4:	3101      	adds	r1, #1
   1cbd6:	2908      	cmp	r1, #8
   1cbd8:	bf08      	it	eq
   1cbda:	4770      	bxeq	lr
   *PC POINTS HERE* -> 1cbdc:	6813      	ldr	r3, [r2, #0]
   1cbde:	f413 4f7f 	tst.w	r3, #65280	; 0xff00
   1cbe2:	d0fb      	beq.n	1cbdc <trng_get_byte+0x28>
   1cbe4:	e7ed      	b.n	1cbc2 <trng_get_byte+0xe>

from looking at the following file:
targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_MCU_K64F/trng_api.c
I see that the trng_get_byte() API polls the TRNG status register and when it is set, the function reads from the output register. Now, it is possible for 2 threads to read that the status register has been set and then one thread will read the output register, while the next thread will try to read from the output register while the status register has been set back to 0 (after the first thread read), which according to the K64F reference manual, will raise a hardware exception.
Not sure that that is in fact what is happening but is possible.

Shouldn't the trng_get_byte function protect from that situation?

  • Another question, mbedtls does provide multi-thread protection (MBEDTLS_THREADING_C flag) but I don't see that mbed-os provides a port for that. Shouldn't it?

Reproducing
Our issue can easily be reproduced by creating two threads that simply call mbedtls_hardware_poll(). The dump I added was from the ARMC compiler but the same happens with GCC ARM.

Issue request type

[ ] Question
[ ] Enhancement
[x ] Bug

Metadata

Metadata

Assignees

Labels

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions