Author Topic: Bootloader application encryption  (Read 7516 times)

Offline mdkendall

  • Newbie
  • *
  • Posts: 4
    • View Profile
Bootloader application encryption
« on: May 02, 2014, 05:55:52 PM »
I'm still evaluating the "uTaskerSerialBoot" bootloader for use on Kinetis K60, particularly using SD cards as the main updating mechanism. I have the software building and running, and I am able to use it to bootload my application and update it from SD cards.

The one piece that I have not got working is encryption of the application. I see in ReleaseNotes-convert.txt that the conversion tool can be used to encrypt the application by giving it additional parameters. Presumably the encryption key chosen also has to be incorporated into the bootloader firmware, but I do not see where to enter it. I was looking in Loader.h and expecting it to be near the definitions of VALID_VERSION_MAGIC_NUMBER and _SECRET_KEY, but I don't see it.

The ReleaseNotes-convert.txt mentions uTaskerBoot_003.PDF, but I don't see any specific instructions in that document for how the incorporate the encryption key in the bootloader firmware.

Offline mark

  • Global Moderator
  • Hero Member
  • *****
  • Posts: 3236
    • View Profile
    • uTasker
Re: Bootloader application encryption
« Reply #1 on: May 02, 2014, 07:28:11 PM »
Hi

The encryption is supported as option in the "Bare-Minimum" boot loader and not in the serial boot loader.

When using SD card loading the file on the SD card is binary (with a small header so that it can be recognised that it is a valid file and not just one that happend to have the expected name). The same tool is used to add the header as used to encrypt and so the file can be encryptd by adding the encryption key settings, however the SD card loader would just copy the content directly to the Flash application area where it could of course not be able to operate.

It would be possible to work with the encrypted content if the algorithm used in the Bare-minimum (BM) loader code were inserted between the encrypted content and the internal flash. It would have to be used in two cases:
- when checking the content of the file to see whether it is the same as that already loader (to avoid always updating the code after every start with the card inserted)
- when programming the SD card content to the application area in Flash

Another method is to mix the BM-loader with the serial loader (that is, the BM loader boots the serial loader, which then boots the application) which is described in this document where SREC downloads are encyrpted http://www.utasker.com/docs/uTasker/uTaskerSecureSREC.pdf
The problem with this is that it requires intermediate storage space which can be a waste of flash in some cases.


I have just realised that I have been involved with a project where we keep a local copy of the 'last' software version so that it is possible to automatically restore to a previous SW in case a new version causes problems. This is stored in SPI Flash and also stored in its original encypted form. In order to know whether the code is the same as the one in Flash I read it and decrypt it a block at a time and compare with the application code. This means that I probably have the code required to do this already, whereby the only difference is that the buffers are filled from the source on a file on the SD card rather than from a buffer read from SPI Flash.

Is your question out of curiosity or due to a read requirement?

If a real requirement it is certainly possible but will need this extra code and a bit of testing in the new environment (maybe some configuration and adaptation for the SD card interface but nothing that should cause any big difficulties). The processor also needs to be protected of course (block Jtag andn Ezport access) so that the code is protected once it has been written to internal Flash but this involves just setting the Flash configuration bits in the boot loader to do this.

Regards

Mark



Offline mdkendall

  • Newbie
  • *
  • Posts: 4
    • View Profile
Re: Bootloader application encryption
« Reply #2 on: May 14, 2014, 08:33:01 PM »
Thanks for your feedback, Mark, and sorry for the delay in replying.

Yes, this is for a real application. I have the bootloader working right now and it's fine for development, but I expect that for production we would want firmware updates that are distributed on SD cards to be encrypted in some way.

I don't have enough space in the MCU Flash for a second copy of the firmware, and decrypting to any other attached memory (or even the SD card itself) would result in a plain-text copy existing in an unsecured location. So decrypting would have to be done on-the-fly during the update process, on a block-by-block basis.

As an aside, I made some changes to the SD card bootloader to support wildcard matching in the name of the firmware file - instead of requiring the update to be named "firmware.bin" (or some other fixed name) it can be named e.g. foo-r124.bin by setting NEW_SOFTWARE_FILE to "foo-*.bin". When doing that I was surprised not to find a function in the API for the filesystem that would list the contents of a directory, returning a set of file handles or similar. I ended up with a nasty hack using the DOS-format text output returned by the utListDir() function. I'm not sure if that was the best approach but anyway, it seems to work. Patch file attached.

Offline mark

  • Global Moderator
  • Hero Member
  • *****
  • Posts: 3236
    • View Profile
    • uTasker
Re: Bootloader application encryption
« Reply #3 on: May 15, 2014, 01:35:43 AM »
Hi

Thanks for the wildcard option!

I'll have a go at integrating the "on-the-fly" decryption so that this will be available shortly.

utListDir() is intended for directory listing since it lists one entry (rather than forcing all entries to be listed) and so a complete directory listing (optionally in DOS formatted or FTP formatted styles) just requires a loop:
while (utListDir(&utListDirectory, &fileList) != UTFAT_NO_MORE_LISTING_ITEMS_FOUND) {
    fnWrite(DebugHandle, (unsigned char *)cBuffer, (QUEUE_TRANSFER)fileList.usStringLength);
}


By setting fileList.usMaxItems to more than 1 it is also possible to list multiple entries but this is not that useful due to the fact that it is usually better to stop between each (otherwise it needs a big output buffer)

Each file handle is effectively (indirectly) in the utListDirectory object but the fact is that wild card searching will probably need to work with the file name and extension (at the end of the string buffer) and so this is probably also the simplest method (as you have done) - remembering that on the disk the file name and extension may be spread out over multiple file objects and some form of string analysis will alway be required (there is no thing as a file type that can be simply recognised but only strings - a file may be called "daft_file_name.and.daft.extension" and checking for this file extension is simple by using the string that is prepared: something like uStrEquiv(fileList.ptrBuffer[fileList.usStringLength - 19], ".and.daft.extension") would do it.

In the case of matching the complete file name I see that it may be convenient if there were a definite reference to where the name starts in the buffer, something like fileList.ucNameLength to go with fileList.usStringLength. This would probably avoid potential incorrect identification of the start of the file in the string when the file name includes numbers and spaces and could be confused with the file date/time. I see you use a fixed buffer offset to the start, which is exact as long as the formatting doesn't change in the future.

The file type could also be added to fileList (eg. fileList.ucFileAttributes) so that directores in the directoiry don't need to be opened if their names happend to match..

A final small modoification that I have seen could be useful are two new style flags:
#define NO_CR_LF_LISTING       0x08                                      // don't end output with CR/LF
#define NULL_TERMINATE_LISTING 0x10                                      // null-terminate the listing

These can be used to avoid the CR + LF being added at each line end and receive a string terminate line if preferred.


I have prepared the additional options above and had a go with them, which saved a few lines of code and remove dependency on the exact listing format (although the dependency is small and unlikely to break).

I note that the wild-card matching routine doesn't look to match file names that are not using the same upper/lower case letters. File names should match with either so it would be theoretically correct to allow this. I tried the method below and it passed various test cases I attempted with - it also avoids recursive calls which could otherwise get very deep if long strings are involved.

Attached are the files that I modifed; changes in utFAT are essentially the extra variables in fileList to make the interface a bit friendlier. I added the option WILDCARD_FILES which can be added in Loader.h to enable it. It also required the following (as you probably already know) to allow the listing function to be available.
#if defined WILDCARD_FILES
    #undef _REMOVE_FORMATTED_OUTPUT
#endif


I didn't verify this on the HW but I tested various combinations in the simulator and it looked OK.

Regards

Mark


Code: [Select]
// Perform a single character match, allowing small and capitals to be equal
//
static int fnMatchCharacters(CHAR cChar1, CHAR cChar2)
{
    if (cChar1 != cChar2) {                                              // check for character match
        if ((cChar1 >= 'A') && (cChar1 <= 'Z')) {                        // capital letter
            if (cChar1 != (cChar2 - ('a' - 'A'))) {                      // allow capital letters and small letters to be matched
                return -1;                                               // failed
            }
        }
        else if ((cChar1 >= 'a') && (cChar1 <= 'z')) {                   // capital letter
            if (cChar1 != (cChar2 + ('a' - 'A'))) {                      // allow capital letters and small letters to be matched
                return -1;                                               // failed
            }
        }
        else {
            return -1;                                                   // failed
        }
    }
    return 0;                                                            // match
}
// Perform a wildcard string match
//
static int fnWildcardMatch(CHAR *cPattern, CHAR *cString)
{
    while (*cPattern != 0) {                                             // until the end of the pattern is reached
        switch (*cPattern) {                                             // letter of fixed string to be matched with
        case '?':                                                        // single wildcard - always accept and move over single wildcard
            break;;
        case '*':                                                        // wildcard (multiple characters could be replaced)
            if (*cString == 0) {
                cPattern++;
            }
            else {
                cString++;                                               // always accept
            }
            if ((fnMatchCharacters(*(cPattern + 1), *cString)) == 0) {   // if next matches
                cPattern++;                                              // move over wildcard location
            }
            continue;
        default:
            if (fnMatchCharacters(*cPattern, *cString) != 0) {
                return -1;
            }
            break;
        }
        cPattern++;                                                      // move to next letter
        cString++;
    }
    if (*cString != 0) {                                                 // string too long
        return -1;
    }
    return 0;                                                            // successfully matched
}


« Last Edit: May 15, 2014, 01:39:11 AM by mark »