Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

rBootHttpUpdate: Hooks added for signed and/or encrypted OTA #893

Merged
merged 5 commits into from
Jan 29, 2017

Conversation

tius2000
Copy link
Contributor

rboot_write_init(), rboot_write_flash() and rboot_write_end() moved to virtual methods. This allows a subclass to implement hooks to download signed or encrypted firmware files.

Hope I got it right ;-)

Copy link
Contributor

@slaff slaff left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@tius2000 Please, update the Basic_rBoot example to demo OTA with signed ROM.

@@ -50,6 +50,10 @@ class rBootHttpUpdate: private HttpClient {
void updateFailed();
void onItemDownloadCompleted(HttpClient& client, bool successful);

virtual void writeInit();
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why are those methods public instead of protected?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think you are right! I will move the methods to protected and test again.

@tius2000
Copy link
Contributor Author

Unfortunately, this is not so easy for me to provide a full working example at the moment. In order to get OTA running with the current SDK under Windows, I had to make changes in many other places. Therefore, my version is currently not portable.

However, using the hooks is quite easy. My own code currently looks like this:

#define PREFIX_MAGIC    0x54, 0x49, 0x55, 0x53
#define PREFIX_TYPE     0x00, 0x01
#define PREFIX_SIZE     sizeof(_my_prefix)
#define SIGNATURE_SIZE  64

const u8 _my_prefix[6] = { PREFIX_MAGIC, PREFIX_TYPE };    

typedef struct {
    u8  prefix[PREFIX_SIZE];
    u8  signature[SIGNATURE_SIZE];
} MyHdr;

//-----------------------------------------------------------------------------
class MyUpdate : public rBootHttpUpdate {

protected:
    virtual void writeInit();
    virtual bool writeFlash(const u8 *data, u16 size);
    virtual bool writeEnd();
    
private:
    Sha256 *sha256;
    u8      hdr_len;
    MyHdr   hdr;
};

//-----------------------------------------------------------------------------
void MyUpdate::writeInit() {
    rBootHttpUpdate::writeInit();
    sha256  = new Sha256;
    hdr_len = 0;
}

bool MyUpdate::writeFlash(const u8 *data, u16 size) {
    //  store header
    u8 missing = sizeof(hdr) - hdr_len;
    if (missing) {
        if (size < missing) missing = size;
        memcpy( &hdr, data, missing );
        size    -= missing;
        data    += missing;
        hdr_len += missing;
        
        //  check prefix
        if ( hdr_len >= PREFIX_SIZE ) {
            if ( memcmp(hdr.prefix, _my_prefix, PREFIX_SIZE) ) {
                debugf("invalid prefix");
                return 0;
            }
        }
    }

    //  update hash
    sha256->update(data, size);

    //  save data
    return rBootHttpUpdate::writeFlash(data, size);
}

bool MyUpdate::writeEnd() {
    if (!rBootHttpUpdate::writeEnd()) return 0;

    u8 hash[SHA256_BLOCK_SIZE];
    sha256->final( hash );

    bool sig_ok = /* add signature check here */;
    if (!sig_ok) {
        debugf("wrong signature");
        return 0;
    }
    return 1;
}

Hope this helps?

@slaff
Copy link
Contributor

slaff commented Jan 26, 2017

Unfortunately, this is not so easy for me to provide a full working example

@tius2000 Ok, I will consider this PR for the next version but you should add that information/example to the WIKI or to the code documentation.

@slaff slaff added this to the 3.0.2 milestone Jan 26, 2017
}

void rBootHttpUpdate::onTimer() {

if (TcpClient::isProcessing()) return; // Will wait

if (TcpClient::getConnectionState() == eTCS_Successful) {

// always call writeEnd()
if (!writeEnd()) writeError = 1;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@tius2000 May be a debug message on write error will be helpful here.

@tius2000
Copy link
Contributor Author

I moved the sample code to the wiki (https://github.com/SmingHub/Sming/wiki/Signed-OTA). May be this is useful for someone.

@@ -57,6 +57,10 @@ class rBootHttpUpdate: private HttpClient {
rboot_write_status rBootWriteStatus;
uint8 romSlot;
otaUpdateDelegate updateDelegate;

virtual void writeInit();
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Coding Style: Please, align the lines with the ones above.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Well, they are aligned in my editor - you are right, need to change my tab settings ;-)

Also changed the base class to protected to allow better http error handling within derived classes.

The git workflow is still very new to me and I really appreciate any feedback!

@slaff slaff merged commit 6e9b817 into SmingHub:develop Jan 29, 2017
@tius2000 tius2000 deleted the ota_hooks1701 branch January 29, 2017 17:05
@slaff slaff mentioned this pull request Jan 29, 2017
15 tasks
@slaff slaff removed the 3 - Review label Feb 2, 2017
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants