Digging through all this to better understand what is going on...
When CONTEXT_MANAGEMENT_ENABLED == 1
There are four areas of memory that we care about:
1. seNvmInit [section(".USER_embedded_Keys") in Flash]
2. Nvm [section(".bss.LW_NVM_RAM") uninitialised in RAM]
3. NvmBackup [section(".bss.LW_NVM_BACKUP_RAM") uninitialised in RAM]
4. Nvm Context [(@0x0803f000) in Flash]
The DevEUI, JoinEUI, AppKey/NwkKey values (the "Keys") we care about for production programming of the device are located in seNvmInit.
If the linker script is "original" (as generated by the ioc file), the location in flash of the seNvmInit is undefined because the .USER_embedded_Keys memory section is not defined.
When the firmware first starts up, MX_LoRaWAN_Init() calls LoRaWAN_Init() calls LmHandlerConfigure() calls LoRaMacInitialization() calls SecureElementInit() which copies the keys from flash (seNvmInit) to uninitialised RAM (Nvm)
Nvm structure in ram is the working copy of the Keys.
On start up, it looks like a check is done to see if Nvm is valid. If a chip reset has happened, this preserves the context.
If Nvm is not valid, a copy is made from the NvmBackup RAM. This backup only seems to be updated as a part of LoRaMacHalt(). I am guessing this is like a "last known good" configuration.
If the NvmBackup is not valid, the firmware tries to restore from a context saved in flash. It seems the operation to store the Keys in Nvm context flash is a deliberate act by the application with a call to StoreContext().
If everything else has failed, then the Nvm is initialised from the seNvmInit original set of Keys.
All this seems to be pretty reasonable.
The problems though are in the management of the memory allocations.
1. The location of seNvmCtx is undefined so it is necessary to add an explicit allocation mapping in the linker script for .USER_embedded_Keys. Once this is done, precise memory locations for the keys can be determined to allow them to be overwritten during production.
2. The location of the application-stored context is improperly defined as an absolute memory location (0x0803f000) instead of being properly mapped via the linker script. This means there is no protection from conflicting use of the memory. The presumption that the last couple of pages of flash are "available" is inherently unsafe.
This conflict is NOT theoretical.
If the additional LoRaWAN packages functionality is enabled, then the Fragmented Data Block Transport package is enabled. This package also explicit uses the same region of flash (0x0803F000) (see frag_decoder_if.h)
Amending a previous comment I made about generating a CRC32 value, it is not necessary for the seNvmInit data as the CRC field is not used there - it only seems to be relevant in the ram Nvm copy, backup ram Nvm and saved context in flash as an integrity check.