Runtime "change protection" mechanisms - good, bad or what? - Page 1
Forum section: electronics / general

author: igendel
author_rank: Frequent Contributor
timestamp: February 17, 2018, 09:17:15 pm
content: Hi all,Quite a few MCUs force the programmer to "unlock" something in order to change an important feature during runtime. For instance, you have to write 0x55 to register XYZ, or set bit ABC, and only then you can select a different clock source, turn off the WDT etc.The rationale given for this is that you don't want your code to accidentally mess with these critical features. That's true all right, but I don't want my code to mess upanythingaccidentally. If I was careless enough to allow these accidents to happen, is it really a good idea to provide "patches" to hide them? Doesn't this just hide dangerous bugs from the developer and later makes debugging a lot harder?Mind you, I'm not talking about chips that go to outer space, or devices that run OSs and manage third-party applications or something. Just plain old MCUs, small 8-bit and such.I think a better approach would have been to provide, in addition to the lock mechanism, some alert mechanism (e.g. dedicated interrupt) that will tell me something tried to access a locked resource. Then it's much easier to spot and debug the issue, or - if the system is already deployed - deal with it in a safer manner.What do you think (/know better than me) on this matter?

author: agehall
author_rank: Frequent Contributor
timestamp: February 17, 2018, 09:26:30 pm
content: Those protections are usually in place to prevent bugs in your code from locking you out of your MCU. If you change certain things, you might not be able to reprogram it with your current equipment etc. I don't really see them as security features that are there to prevent anything except silly bugs that may screw up your system.Let's say you've written a loop that modifies some memory range. Due to a bug in the code elsewhere, the parameters happen to specify a range that includes the area where the critical registers resides, or maybe the loop conditions are just flawed and your function goes on a rampage modifying all your memory. If no protections are in place, you may easily end up with are really screwed up MCU. But due to simple protection mechanisms like you mention, chances are your program will just crash and you can still access the MCU using debugging tools and fix the problem before you send your system into production.Really, look at these things more as "this is the procedure you have to follow to modify X" rather than a security feature.

author: igendel
author_rank: Frequent Contributor
timestamp: February 17, 2018, 09:58:48 pm
content: Quote from: agehall on February 17, 2018, 09:26:30 pmI would have agreed, except that in most cases I've seen, the "protected" parts are not irreversible, i.e. they will not actually brick the MCU, you'll just have to reset it. It's true that live debugging becomes harder if the clock is stoppedbut it's not much easier if your first sign of the bug appears some 1K cycles after it actually started, when itshouldhave stopped that clock...

author: NorthGuy
author_rank: Super Contributor
timestamp: February 17, 2018, 10:02:49 pm
content: I've never came across MCU which you can brick by writing to registers (you can brick a bootloader perhaps, but not the MCU). IMHO, if such a thing exists, it's a major manufacturer's flaw.@OP: The protections you're asking about look like complete idiocy to me. I don't see any technical reasons. People get more problems because of the locks, since if something doesn't unlock correctly it's just as bad as if you accidentally change it, perhaps even worse. May be there are some marketing reasons, I don't know.

author: andersm
author_rank: Super Contributor
timestamp: February 17, 2018, 10:29:12 pm
content: Those kinds of features are probably included to help meet various safety standards, which dictate that systems must be protected against certain kinds of corruption. Declaring that you don't intend on making any mistakes isn't going to cut it with authorities, maybe unless you can mathematically prove you haven't. It also may not even be your fault, eg. most commodity microcontrollers don't have error-detecting, or -correcting memory to protect against cosmic rays or power glitches.The most paranoid code would also contain software-level checks, eg. testing that some memory location contained a certain value before proceeding with anything dangerous, just in case it was executing as a result of for example a stack overflow rather than an explicit call.

author: igendel
author_rank: Frequent Contributor
timestamp: February 17, 2018, 10:48:41 pm
content: Quote from: andersm on February 17, 2018, 10:29:12 pmFair enough, but then why is every MCU protected differently?Quote from: andersm on February 17, 2018, 10:29:12 pmActually I'm quite certain I'm making tons of mistakesbut it's harder to test for them and fix them if their direct consequences are hidden from me by these "protections". So maybe I can guarantee to the authorities that my system's clock will always be 10MHz... but there are so many other things that can go wrong - my fault or Act of God - that this kind of guarantee seems pointless.Quote from: andersm on February 17, 2018, 10:29:12 pmYes - and such a code can also do something meaningful if it discovers the value is incorrect, unlike the locking mechanism that just ignores the request and leaves you no smarter.

author: John Coloccia
author_rank: Super Contributor
timestamp: February 17, 2018, 11:58:49 pm
content: Some times they are actually read protections to keep someone from stealing your software. If you don't have right lock bit, your only option is to erase and reprogram. It looks like you're locked out because you can't do anything but erase, but that's just a side effect of not being able to read.Write protects are convenient on safety critical systems. It's nice to be able to show that once you're started up and validated your own code, it's not possible to change it.

author: igendel
author_rank: Frequent Contributor
timestamp: February 18, 2018, 12:18:37 am
content: Quote from: John Coloccia on February 17, 2018, 11:58:49 pmLocking the code itself is a different matter, I have no issue with thatMy question is about when your own code, while running, has to do voodoo rituals to write to some registers.

author: John Coloccia
author_rank: Super Contributor
timestamp: February 18, 2018, 12:37:42 am
content: Quote from: igendel on February 18, 2018, 12:18:37 amThink of it this way:1) sometimes it's convenient because you want to be able to write any value to a register, but after you go through the song and dance some values become special2) You're right that your code shouldn't do things accidentally, and in the final version hopefully it won't, but when you're in development it's not a bad idea to lock some basic functionality down so that a bug doesn't completely lock up the system to the point that it's extremely difficult to debug.Other than that, I'm not really sure what the rationale is. I guess I've always just followed the datasheet and not really thought about it too much. Maybe a chip designer will weigh in and give a real answer.

author: andyturk
author_rank: Frequent Contributor
timestamp: February 18, 2018, 01:17:08 am
content: Quote from: igendel on February 17, 2018, 09:17:15 pmYup. The Tiva mcus from TI have a couple of "locked" pins that can't be reconfigured unless you click your heels three times. That resulted in some head scratching during development until we realized what had to happen--and it resulted in some special cases for our previously "general purpose" GPIO configuration code.More recently, I've been bit by Nordic's pin config paranoia around the mcu reset pin. It's configurable, but you can't do it at run time because the magic is read from a location in flash *before* the reset handler runs. There's a similar issue with a couple of pins that default to having NFC capability unless you sacrifice a chicken.I'm sure the silicon engineers are sitting around a table saying, "We'll protect those hapless firmware engineers from their own stupidity by making this difficult."

author: igendel
author_rank: Frequent Contributor
timestamp: February 18, 2018, 01:38:10 am
content: Quote from: andyturk on February 18, 2018, 01:17:08 amQuote from: andyturk on February 18, 2018, 01:17:08 amGood examples!Quote from: andyturk on February 18, 2018, 01:17:08 amIf I understand correctly, on 8051 MCUs, to turn off the WDT you need to assign the values 0xDE,0xAD to the control register. Which at least shows someone had a sense of humor. But seriously, it must take time and effort and silicon to design these features, what am I missing?

author: ejeffrey
author_rank: Super Contributor
timestamp: February 18, 2018, 05:27:46 am
content: Quote from: igendel on February 17, 2018, 09:58:48 pmIn the ones I have seen, attempting to modify such a register without performing the interlock sequence produces a fault which is easily caught by the debugger.

author: abyrvalg
author_rank: Frequent Contributor
timestamp: February 18, 2018, 10:11:55 am
content: Protecting the watchdog disable looks reasonable in some cases - your device (in the hands of a clueless end user) will have more chances to reset and go back to normal operation. The developer will start getting ambiguous complains like "my coffee machine refuses to make coffe sometimes" until he gets something more precise like "machine restarts when i press Ristretto button having an empty water tank and milling size set to 4". A bit better than "sometimes it hangs and i need to pull out the mains and wait 5 minutes".

author: igendel
author_rank: Frequent Contributor
timestamp: February 18, 2018, 10:17:05 am
content: Quote from: ejeffrey on February 18, 2018, 05:27:46 amThat's interesting. Which MCUs have this feature?

author: donotdespisethesnake
author_rank: Super Contributor
timestamp: February 18, 2018, 12:56:25 pm
content: Just a random example, SAMD10.http://ww1.microchip.com/downloads/en/DeviceDoc/Atmel-42242-SAM-D10_Datasheet.pdfpage 30Quote

author: igendel
author_rank: Frequent Contributor
timestamp: February 18, 2018, 01:49:43 pm
content: Quote from: donotdespisethesnake on February 18, 2018, 12:56:25 pmCool, this is exactly the notification I think is needed wherever there's a "change protection" feature.In the tinyAVR 1-Series I'm studying now, when you unlock access to a protected register, you get 4 clock cycles to complete the write - and during that time all interrupts are automatically disabled (put on hold), which kind of makes sense too.

author: igendel
author_rank: Frequent Contributor
timestamp: February 18, 2018, 01:55:38 pm
content: Quote from: abyrvalg on February 18, 2018, 10:11:55 amTrue, but then again, if your code can go haywire enough to try to disable the watchdog, it's just as likely to do all other kinds of damage - e.g. changing the timer values so that the water flow to the coffee cup doesn't stop on time...

author: NorthGuy
author_rank: Super Contributor
timestamp: February 18, 2018, 02:09:24 pm
content: Quote from: igendel on February 18, 2018, 01:49:43 pmThis increases the interrupt latency ...

author: igendel
author_rank: Frequent Contributor
timestamp: February 18, 2018, 03:40:14 pm
content: Quote from: NorthGuy on February 18, 2018, 02:09:24 pmHence the "kind of"These events are supposed to be rare and usually related to significant changes in functionality (e.g. change of clock frequency), so I'm not sure the interrupt latency is a significant issue here.

author: dgtl
author_rank: Regular Contributor
timestamp: February 18, 2018, 03:49:09 pm
content: Most of the locked fields i've come across are the most critical peripherals - watchdog, flash write, RTC, battery-powered SRAM. Even if your code is correct, the hardware never is. There can be power glitches, brownouts, esd-caused pulses, cosmic rays etc, that can cause the hardware to malfunction. When these happen, you want the device to fail safely - a reboot is better than lockup due to a runaway code, malicious write of code flash or battery-backed SRAM where you hold calibration values or encryption keys. When one of such happens, debugging it can really mess up your day. Having another peripheral misconfigured by a runaway code is not that critical as the watchdog would take care of it... as long as the wdt is still running and the program flash is not corrupted.The ones built into the uc are the bare minimum. For most cortex-m3 and above devices, there is a built-in memory protection unit, that you can use to disable access to address regions for either user mode or privileged mode. If thats not enough, there are cortex-r controllers with multiple cores running in lockstep etc. As with any other decisions, there is a compromise of safety and project cost, so there is no need of developing aircraft autopilot-grade quality washing machine.

author: rstofer
author_rank: Super Contributor
timestamp: February 18, 2018, 06:57:19 pm
content: Quote from: igendel on February 18, 2018, 01:38:10 amI don't care who wrote the program, it is still possible that some sequence of inputs will result in the program running amok. Yes, we are all exceptional programmers but, seriously, any time you branch through a pointer, you are looking for trouble. If the branch table got hosed, who knows where you will wind up? Hopefully, the program code and branch tables are all in flash. Copying flash to RAM to get higher performance takes away all of the nice features of flash (read only unless deliberately unlocked).Protecting certain resources is important. More so during development, I suppose, but even in real life it is best to have the CPU protect itself as much as it can.

author: NorthGuy
author_rank: Super Contributor
timestamp: February 18, 2018, 07:05:02 pm
content: Quote from: dgtl on February 18, 2018, 03:49:09 pmYou have a function which does the unlocks and writes. If your run-away code runs through this function, it will successfully unlock everything and will do its bad job just as well as if the hardware didn't have locks. I'd say the probability of such event is far greater than a random code suddenly morphing into something which produces bad flash writes. These checks are completely useless in mission-critical applications.

author: igendel
author_rank: Frequent Contributor
timestamp: February 18, 2018, 08:49:09 pm
content: Quote from: dgtl on February 18, 2018, 03:49:09 pmYes, but with the exception of the watchdog, it won't so much "fail safely" as "fail silently". I mean, what are the chances that the one and only effect of a hardware glitch will be an attempt to change a locked resource?

author: Kalvin
author_rank: Super Contributor
timestamp: February 18, 2018, 08:57:42 pm
content: I have also seen another kind of runtime "change protection" which refreshes the on-chip peripheral configuration registers continuously per current device operating state or mode. If some registers get corrupted for a reason or another, the correct configuration would be written by the firmware some time after. This strategy (pattern) has been used successfully in some products that require very high up-time without service loss.

author: splin
author_rank: Frequent Contributor
timestamp: February 19, 2018, 01:19:51 am
content: For the utmost reliability it's hard to beat a periodic hardware reset to force it back into a known state - s/w resets of peripherals are not guaranteed to fully reset a device/function. Simple devices consisting of standard combinatorial logic or flip-flops with resets are probably ok, but more complex parts may have state machines which rely on the h/w reset logic to fully initialise the device, or even be implemented in 'microcode' in an embedded microcontroller. None of this is going to be detailed in any documentation available to anyone other than the designers of the part or the most important customers.This does require some state to be maintained across the reset so that the boot code can differentiate from continued operation as normal and a genuine cold start and obviously it requires the application to be able to handle loss of control for the duration of the reset.Better still is to periodically cycle the power to recover devices which even a reset won't resolve such as a latched up part - perhaps due to events which can't reasonably be avoided or anticipated such as cosmic rays, a nearby lightning strike, or high level RFI events due to local high power flashovers etc. Maintaining state across the power cycling is more difficut than in the periodic reset case however.There are many problems with both these techniques of course, apart from the duration of the reset/power cycle where control is lost. The hardware has to be able to maintain the state of critical outputs during the reset - eg. by using latches/registers for such output ports which are not themselves subject to the periodic reset/power cycling, but could still be reset/power cycled by the controller and/or a watchdog function as a last resort.

author: Vic20
author_rank: Contributor
timestamp: February 20, 2018, 09:29:02 am
content: Quote from: igendel on February 18, 2018, 01:38:10 amThe rationale on watchdogs is that a stray code should not be able to disable it. So you need to use a sequence practically impossible to happen at random. It usually means writting two different enough values in a time contrained window.It happens that 0xDE and 0xAD have 5 different bits but are not an exact complement of each other, so it suits the purpose. It is also evident that someone has some sense of humor, but the selected codes suit the purpose.The watchdog is a quite important security element and it is of most importance that it only can be disabled by legit code. Most people in non critical systems the first thing that do is disable the WD, but it crytical systems it is very important if handled correctly.

author: Siwastaja
author_rank: Super Contributor
timestamp: February 20, 2018, 10:03:53 am
content: Quote from: rstofer on February 18, 2018, 06:57:19 pmIndeed - you may end up somewhere you don't want - for example to your function that unlocks the resource and uses it.In this case, having your function to sanity-check the memory addresses, data, etc., will offer much better protection against accidents.But most of the time, we just unlock whatever resource when we need it. The result is approximately equally unsafe than not having any "locks" in the first place.Utilizing the locking features so that theyactually helprequires a lot of thought - and when you do that, you'll often note that the locking mechanism is quite lame, and you need to implement something better anyway. On the other hand, powerless safety features do cause two effects, affecting overall code quality and reliability: (1) false sense of security, (2) increased complexity, reducing development time available to make things more robust in the right way.For example, in many MCU's, for successfull FLASH write operation, you need to supply right control registers with:- Unlocking keys- the right control register bits with right settings to enable write access- then write the data to the right memory area.Even without unlocking keys, it's extremely unlikely your accidental memory access would first write to the exactly right control register bit (in a totally different memory region; peripheral address space), then to the flash memory region to actually do the write there. So the only way this will happen, is by having runaway program counter (or accidentally calling the wrong function), where your program ends up in the flashing function. And when you are there, requiring the keys won't help the slightest - most likely, you have written the flasher function to unlock the flash in the very same place! Why would you do it elsewhere? You'dthinkthat it'ssafestto unlockjust beforeaccessing.Youcouldutilize the key thing so that there would be some separate code doing the unlocking, and this code would only be called through the interactions of some completely different logic - for example, a separate "enable flashing" pushbutton. But, given that thefinalinput to actually do some things comes from the end user (for example, requesting a firmware update), the things need to combine at some point, and some actual code will always end up first calling unlock_flash(); then program_flash();. Making it more complex by adding intermediate steps will just hide the problem and make it even worse to debug. And, the KEYs still won't help.In general, I think that in typical MCU's, these "protection features" are,in 80% cases, completely irrelevant or harmful,in 10% cases, might have some use when used correctlyin 10% cases, very usable.MCU designers are not always very bright-minded. That can be easily seen when you look at the typical peripheral implementations in almost any MCU. There are exceptions of course, but over 50% of the time, developing on any MCU is kind of facepalming: "why on earth did they design it like this..."

author: andyturk
author_rank: Frequent Contributor
timestamp: February 20, 2018, 07:08:09 pm
content: Quote from: Siwastaja on February 20, 2018, 10:03:53 amThere's another thread somewhere talking about EEs who end up writing code (rather than doing EE stuff)... I wish more mcu designers spent time writing code so they might understand the problems they can cause by making life unnecessarily complicated.E.g., the dumpster fire of Nordic's GPIO DETECT mechanism.