bootloader verifies signature

This commit is contained in:
Conor Patrick 2018-07-15 01:23:38 -04:00
parent ed1d5d4570
commit dad7d90481
9 changed files with 73 additions and 12 deletions

1
.gitignore vendored
View File

@ -70,3 +70,4 @@ efm32/hw
mbedtls/
sl_crypto/
tools/python-fido2/*
*.pem

View File

@ -37,7 +37,7 @@
<targetPlatform binaryParser="org.eclipse.cdt.core.ELF;org.eclipse.cdt.core.GNU_ELF;com.silabs.ss.framework.debugger.core.BIN;com.silabs.ss.framework.debugger.core.HEX;com.silabs.ss.framework.debugger.core.S37;com.silabs.ss.framework.debugger.core.EBL;com.silabs.ss.framework.debugger.core.GBL" id="com.silabs.ide.si32.gcc.cdt.managedbuild.target.gnu.platform.base.613101530" isAbstract="false" name="Debug Platform" osList="win32,linux,macosx" superClass="com.silabs.ide.si32.gcc.cdt.managedbuild.target.gnu.platform.base"/>
<builder buildPath="${workspace_loc:/efm32boot}/GNU ARM v7.2.1 - Debug" id="com.silabs.ide.si32.gcc.cdt.managedbuild.target.gnu.builder.base.2113865201" keepEnvironmentInBuildfile="false" managedBuildOn="true" name="Si32 GNU ARM Builder" parallelBuildOn="true" parallelizationNumber="optimal" superClass="com.silabs.ide.si32.gcc.cdt.managedbuild.target.gnu.builder.base"/>
<tool id="com.silabs.ide.si32.gcc.cdt.managedbuild.tool.gnu.c.compiler.base.981192541" name="GNU ARM C Compiler" superClass="com.silabs.ide.si32.gcc.cdt.managedbuild.tool.gnu.c.compiler.base">
<option id="gnu.c.compiler.option.optimization.level.1400029735" name="Optimization Level" superClass="gnu.c.compiler.option.optimization.level" value="gnu.c.optimization.level.none" valueType="enumerated"/>
<option id="gnu.c.compiler.option.optimization.level.1400029735" name="Optimization Level" superClass="gnu.c.compiler.option.optimization.level" value="gnu.c.optimization.level.size" valueType="enumerated"/>
<option id="com.silabs.ide.si32.gcc.cdt.managedbuild.tool.gnu.c.compiler.def.symbols.115820704" name="Defined symbols (-D)" superClass="com.silabs.ide.si32.gcc.cdt.managedbuild.tool.gnu.c.compiler.def.symbols" valueType="definedSymbols">
<listOptionValue builtIn="false" value="DEBUG=1"/>
<listOptionValue builtIn="false" value="EFM32PG1B200F256GM48=1"/>

View File

@ -30,4 +30,6 @@ int bootloader_bridge(uint8_t klen, uint8_t * keyh);
int is_authorized_to_boot();
extern uint8_t REBOOT_FLAG;
#endif /* SRC_APP_H_ */

View File

@ -51,7 +51,7 @@ __asm void BOOT_jump(uint32_t sp, uint32_t pc)
bx r1
}
#else
void BOOT_jump(uint32_t sp, uint32_t pc)
void __attribute__((optimize("O0"))) BOOT_jump(uint32_t sp, uint32_t pc)
{
(void) sp;
(void) pc;
@ -78,7 +78,7 @@ static void resetPeripherals(void)
* Boots the firmware. This function will activate the vector table
* of the firmware application and set the PC and SP from this table.
*****************************************************************************/
void BOOT_boot(void)
void __attribute__((optimize("O0"))) BOOT_boot(void)
{
uint32_t pc, sp;

View File

@ -8,7 +8,7 @@
#include "InitDevice.h"
void bootloader_init(void);
uint8_t REBOOT_FLAG;
int main(void)
{
@ -81,7 +81,7 @@ bootmode:
// printf("accum: %d\n", (uint32_t)accum);
// printf("dt: %d\n", t2 - dt);
// dt = t2;
memset(hidmsg, 0, sizeof(hidmsg));
// memset(hidmsg, 0, sizeof(hidmsg));
}
else
{
@ -89,7 +89,11 @@ bootmode:
}
ctaphid_check_timeouts();
if (REBOOT_FLAG) break;
}
// delay(100);
}
}

20
tools/gen_keys.py Normal file
View File

@ -0,0 +1,20 @@
from ecdsa import SigningKey, NIST256p
sk = SigningKey.generate(curve = NIST256p)
sk_name = 'signing_key.pem'
print('Signing key for signing device firmware: '+sk_name)
open(sk_name,'wb+').write(sk.to_pem())
vk = sk.get_verifying_key()
print('Public key in various formats:')
print()
print([c for c in vk.to_string()])
print()
print(''.join(['%02x'%c for c in vk.to_string()]))
print()
print('"\\x' + '\\x'.join(['%02x'%c for c in vk.to_string()]) + '"')
print()

View File

@ -8,9 +8,13 @@ from fido2.ctap import CtapError
from fido2.ctap1 import CTAP1
from fido2.ctap2 import *
from fido2.cose import *
from fido2.utils import Timeout
from fido2.utils import Timeout, sha256
import socket,json,base64,ssl
from intelhex import IntelHex
from ecdsa import SigningKey, NIST256p
import socket,json,base64,ssl,array,binascii
httpport = 8080
udpport = 8111
@ -111,10 +115,32 @@ class UDPBridge(BaseHTTPRequestHandler):
self.send_response(200)
self.send_header('Content-type','text/json')
sk = SigningKey.from_pem(open("signing_key.pem").read())
h = open(HEX_FILE,'r').read()
h = base64.b64encode(h.encode())
h = to_websafe(h.decode())
sig = [1,2,3,4]
START = 0x8000
END = 2048 * 125 - 4
ih = IntelHex(HEX_FILE)
segs = ih.segments()
arr = ih.tobinarray(start = START, size = END-START)
im_size = END-START
print('im_size: ', im_size)
print('firmware_size: ', len(arr))
sig = sha256((arr).tobytes())
print('hash', binascii.hexlify(sig))
sig = sk.sign_digest(sig)
print('sig', binascii.hexlify(sig))
sig = base64.b64encode(sig)
sig = to_websafe(sig.decode())
#msg = {'data': read()}
msg = {'firmware': h, 'signature':sig}

2
tools/requirements.txt Normal file
View File

@ -0,0 +1,2 @@
ecdsa
intelhex

View File

@ -881,9 +881,9 @@ var is_bootloader_ = function(func){
});
};
var bootloader_finish_ = function(func){
var bootloader_finish_ = function(sig,func){
var req = formatBootRequest(CMD.boot_done);
var req = formatBootRequest(CMD.boot_done, 0x8000, sig);
send_msg(req, function(resp){
if (func)func(resp);
@ -1338,6 +1338,9 @@ async function run_tests() {
p = await get_firmware_http();
var sig = websafe2array(p.signature);
var badsig = websafe2array(p.signature);
badsig[40] = badsig[40] ^ 1;
var blocks = MemoryMap.fromHex(p.firmware);
var addresses = blocks.keys();
@ -1358,8 +1361,11 @@ async function run_tests() {
addr = addresses.next();
}
p = await dev.bootloader_finish();
console.log(p);
p = await dev.bootloader_finish(badsig);
TEST(p.status == 'CTAP2_ERR_OPERATION_DENIED', 'Device rejected new image with bad signature');
p = await dev.bootloader_finish(sig);
TEST(p.status == 'CTAP1_SUCCESS', 'Device booted new image with correct signature');
}