30
30
#include <stdlib.h>
31
31
32
32
const char RomBOOT_Version [] = SAM_BA_VERSION ;
33
- const char RomBOOT_ExtendedCapabilities [] = "[Arduino:XYZ]" ;
33
+ // X = Chip Erase, Y = Write Buffer, Z = Checksum Buffer, P = Secure Bit Aware
34
+ const char RomBOOT_ExtendedCapabilities [] = "[Arduino:XYZP]" ;
34
35
35
36
/* Provides one common interface to handle both USART and USB-CDC */
36
37
typedef struct
@@ -83,6 +84,12 @@ const t_monitor_if usbcdc_if =
83
84
/* The pointer to the interface object use by the monitor */
84
85
t_monitor_if * ptr_monitor_if ;
85
86
87
+ #ifdef SECURE_BY_DEFAULT
88
+ bool b_security_enabled = true;
89
+ #else
90
+ bool b_security_enabled = false;
91
+ #endif
92
+
86
93
/* b_terminal_mode mode (ascii) or hex mode */
87
94
volatile bool b_terminal_mode = false;
88
95
volatile bool b_sam_ba_interface_usart = false;
@@ -222,9 +229,12 @@ void sam_ba_putdata_term(uint8_t* data, uint32_t length)
222
229
return ;
223
230
}
224
231
232
+ #ifndef SECURE_BY_DEFAULT
225
233
volatile uint32_t sp ;
226
234
void call_applet (uint32_t address )
227
235
{
236
+ if (b_security_enabled ) return ;
237
+
228
238
uint32_t app_start_address ;
229
239
230
240
__disable_irq ();
@@ -240,8 +250,10 @@ void call_applet(uint32_t address)
240
250
/* Jump to application Reset Handler in the application */
241
251
asm("bx %0" ::"r" (app_start_address ));
242
252
}
253
+ #endif
243
254
244
255
uint32_t current_number ;
256
+ uint32_t erased_from = 0 ;
245
257
uint32_t i , length ;
246
258
uint8_t command , * ptr_data , * ptr , data [SIZEBUFMAX ];
247
259
uint8_t j ;
@@ -264,11 +276,26 @@ static void put_uint32(uint32_t n)
264
276
sam_ba_putdata ( ptr_monitor_if , buff , 8 );
265
277
}
266
278
279
+ static void eraseFlash (uint32_t dst_addr )
280
+ {
281
+ erased_from = dst_addr ;
282
+ while (dst_addr < MAX_FLASH )
283
+ {
284
+ // Execute "ER" Erase Row
285
+ NVMCTRL -> ADDR .reg = dst_addr / 2 ;
286
+ NVMCTRL -> CTRLA .reg = NVMCTRL_CTRLA_CMDEX_KEY | NVMCTRL_CTRLA_CMD_ER ;
287
+ while (NVMCTRL -> INTFLAG .bit .READY == 0 )
288
+ ;
289
+ dst_addr += PAGE_SIZE * 4 ; // Skip a ROW
290
+ }
291
+ }
292
+
267
293
#ifdef ENABLE_JTAG_LOAD
268
294
static uint32_t offset = __UINT32_MAX__ ;
269
295
static bool flashNeeded = false;
270
296
#endif
271
297
298
+
272
299
static void sam_ba_monitor_loop (void )
273
300
{
274
301
length = sam_ba_getdata (ptr_monitor_if , data , SIZEBUFMAX );
@@ -284,7 +311,7 @@ static void sam_ba_monitor_loop(void)
284
311
{
285
312
sam_ba_putdata (ptr_monitor_if , "\n\r" , 2 );
286
313
}
287
- if (command == 'S' )
314
+ if (command == 'S' ) // Write memory (normally RAM, but might be flash, if client handles the Flash MCU commands?)
288
315
{
289
316
//Check if some data are remaining in the "data" buffer
290
317
if (length > i )
@@ -318,37 +345,65 @@ static void sam_ba_monitor_loop(void)
318
345
319
346
__asm("nop" );
320
347
}
321
- else if (command == 'R' )
348
+ else if (command == 'R' ) // Read memory (flash or RAM)
322
349
{
323
- sam_ba_putdata_xmd (ptr_monitor_if , ptr_data , current_number );
350
+ // Flash memory starts at address 0 and runs to flash size 0x40000 (256 KByte)
351
+
352
+ // Internal RWW section is at adress 0x400000. RWW is flash used for EEPROM emulation. Will not let anyone read that, when in secure mode, either.
353
+ // Bootloader ends at 0x1FFF, so user programs start at 0x2000
354
+ // RAM starts at 0x20000000, so redirect FLASH reads into RAM reads, when in secure mode
355
+ if (b_security_enabled && ((uint32_t )ptr_data >= 0x0000 && (uint32_t )ptr_data < 0x20000000 ))
356
+ ptr_data = (uint8_t * )0x20005000 ;
357
+ sam_ba_putdata_xmd (ptr_monitor_if , ptr_data , current_number );
324
358
}
325
- else if (command == 'O' )
359
+ else if (command == 'O' ) // write byte
326
360
{
327
361
* ptr_data = (char ) current_number ;
328
362
}
329
- else if (command == 'H' )
363
+ else if (command == 'H' ) // Write half word
330
364
{
331
365
* ((uint16_t * ) ptr_data ) = (uint16_t ) current_number ;
332
366
}
333
- else if (command == 'W' )
367
+ else if (command == 'W' ) // Write word
334
368
{
335
369
* ((int * ) ptr_data ) = current_number ;
336
370
}
337
- else if (command == 'o' )
371
+ else if (command == 'o' ) // Read byte
338
372
{
339
- sam_ba_putdata_term (ptr_data , 1 );
373
+ // Flash memory starts at address 0 and runs to flash size 0x40000 (256 KByte). RAM starts at 0x20000000.
374
+ // Intern RWW section is at adress 0x400000. RWW is flash used for EEPROM emulation. Will not let anyone read that, when in secure mode, either.
375
+ // BOSSA reads address 0 to check something, but using read word instead of read byte, but in any case allow reading first byte
376
+ // Bootloader ends at 0x1FFF, so user programs start at 0x2000
377
+ if (b_security_enabled && ((uint32_t )ptr_data > 0x0003 && (uint32_t )ptr_data < 0x20000000 ))
378
+ ptr_data = (uint8_t * ) & current_number ;
379
+ sam_ba_putdata_term (ptr_data , 1 );
340
380
}
341
- else if (command == 'h' )
381
+ else if (command == 'h' ) // Read half word
342
382
{
343
- current_number = * ((uint16_t * ) ptr_data );
383
+ // Flash memory starts at address 0 and runs to flash size 0x40000 (256 KByte). RAM starts at 0x20000000.
384
+ // Intern RWW section is at adress 0x400000. RWW is flash used for EEPROM emulation. Will not let anyone read that, when in secure mode, either.
385
+ // BOSSA reads address 0 to check something, but using read word instead of read byte, but in any case allow reading first byte
386
+ // Bootloader ends at 0x1FFF, so user programs start at 0x2000
387
+ if (b_security_enabled && ((uint32_t )ptr_data > 0x0003 && (uint32_t )ptr_data < 0x20000000 ))
388
+ current_number = 0 ;
389
+ else
390
+ current_number = * ((uint16_t * ) ptr_data );
344
391
sam_ba_putdata_term ((uint8_t * ) & current_number , 2 );
345
392
}
346
- else if (command == 'w' )
393
+ else if (command == 'w' ) // Read word
347
394
{
348
- current_number = * ((uint32_t * ) ptr_data );
395
+ // Flash memory starts at address 0 and runs to flash size 0x40000 (256 KByte). RAM starts at 0x20000000.
396
+ // Intern RWW section is at adress 0x400000. RWW is flash used for EEPROM emulation. Will not let anyone read that, when in secure mode, either.
397
+ // BOSSA reads address 0 to check something, but using read word instead of read byte, but in any case allow reading first byte
398
+ // Bootloader ends at 0x1FFF, so user programs start at 0x2000
399
+ if (b_security_enabled && ((uint32_t )ptr_data > 0x0003 && (uint32_t )ptr_data < 0x20000000 ))
400
+ current_number = 0 ;
401
+ else
402
+ current_number = * ((uint32_t * ) ptr_data );
349
403
sam_ba_putdata_term ((uint8_t * ) & current_number , 4 );
350
404
}
351
- else if (command == 'G' )
405
+ #ifndef SECURE_BY_DEFAULT
406
+ else if (!b_security_enabled && command == 'G' ) // Execute code. Will not allow when security is enabled.
352
407
{
353
408
call_applet (current_number );
354
409
/* Rebase the Stack Pointer */
@@ -358,40 +413,30 @@ static void sam_ba_monitor_loop(void)
358
413
ptr_monitor_if -> put_c (0x6 );
359
414
}
360
415
}
361
- else if (command == 'T' )
416
+ #endif
417
+ else if (command == 'T' ) // Turn on terminal mode
362
418
{
363
419
b_terminal_mode = 1 ;
364
420
sam_ba_putdata (ptr_monitor_if , "\n\r" , 2 );
365
421
}
366
- else if (command == 'N' )
422
+ else if (command == 'N' ) // Turn off terminal mode
367
423
{
368
424
if (b_terminal_mode == 0 )
369
425
{
370
426
sam_ba_putdata ( ptr_monitor_if , "\n\r" , 2 );
371
427
}
372
428
b_terminal_mode = 0 ;
373
429
}
374
- else if (command == 'V' )
430
+ else if (command == 'V' ) // Read version information
375
431
{
376
432
sam_ba_putdata ( ptr_monitor_if , "v" , 1 );
377
433
sam_ba_putdata ( ptr_monitor_if , (uint8_t * ) RomBOOT_Version , strlen (RomBOOT_Version ));
378
434
sam_ba_putdata ( ptr_monitor_if , " " , 1 );
379
435
sam_ba_putdata ( ptr_monitor_if , (uint8_t * ) RomBOOT_ExtendedCapabilities , strlen (RomBOOT_ExtendedCapabilities ));
380
- sam_ba_putdata ( ptr_monitor_if , " " , 1 );
381
- ptr = (uint8_t * ) & (__DATE__ );
382
- i = 0 ;
383
- while (* ptr ++ != '\0' )
384
- i ++ ;
385
- sam_ba_putdata ( ptr_monitor_if , (uint8_t * ) & (__DATE__ ), i );
386
- sam_ba_putdata ( ptr_monitor_if , " " , 1 );
387
- i = 0 ;
388
- ptr = (uint8_t * ) & (__TIME__ );
389
- while (* ptr ++ != '\0' )
390
- i ++ ;
391
- sam_ba_putdata ( ptr_monitor_if , (uint8_t * ) & (__TIME__ ), i );
392
- sam_ba_putdata ( ptr_monitor_if , "\n\r" , 2 );
436
+ ptr = (uint8_t * ) & (" " __DATE__ " " __TIME__ "\n\r" );
437
+ sam_ba_putdata ( ptr_monitor_if , ptr , strlen (ptr ));
393
438
}
394
- else if (command == 'X' )
439
+ else if (command == 'X' ) // Erase flash
395
440
{
396
441
// Syntax: X[ADDR]#
397
442
// Erase the flash memory starting from ADDR to the end of flash.
@@ -400,22 +445,13 @@ static void sam_ba_monitor_loop(void)
400
445
// Even if the starting address is the last byte of a ROW the entire
401
446
// ROW is erased anyway.
402
447
403
- uint32_t dst_addr = current_number ; // starting address
404
-
405
- while (dst_addr < MAX_FLASH )
406
- {
407
- // Execute "ER" Erase Row
408
- NVMCTRL -> ADDR .reg = dst_addr / 2 ;
409
- NVMCTRL -> CTRLA .reg = NVMCTRL_CTRLA_CMDEX_KEY | NVMCTRL_CTRLA_CMD_ER ;
410
- while (NVMCTRL -> INTFLAG .bit .READY == 0 )
411
- ;
412
- dst_addr += PAGE_SIZE * 4 ; // Skip a ROW
413
- }
414
-
448
+ // BOSSAC.exe always erase with 0x2000 as argument, but an attacker might try to erase just parts of the flash, to be able to copy or analyze the untouched parts.
449
+ // To mitigate this, always erase all sketch flash, that is, starting from address 0x2000. This butloader always assume 8 KByte for itself, and sketch starting at 0x2000.
450
+ eraseFlash (b_security_enabled ? 0x2000 : current_number );
415
451
// Notify command completed
416
452
sam_ba_putdata ( ptr_monitor_if , "X\n\r" , 3 );
417
453
}
418
- else if (command == 'Y' )
454
+ else if (command == 'Y' ) // Write buffer to flash
419
455
{
420
456
// This command writes the content of a buffer in SRAM into flash memory.
421
457
@@ -435,6 +471,13 @@ static void sam_ba_monitor_loop(void)
435
471
}
436
472
else
437
473
{
474
+ if (b_security_enabled ) {
475
+ // To mitigate that an attacker might not use the ordinary BOSSA method of erasing flash before programming,
476
+ // always erase flash, if it hasn't been done already.
477
+ if (erased_from != 0x2000 )
478
+ eraseFlash (0x2000 );
479
+ }
480
+
438
481
// Write to flash
439
482
uint32_t size = current_number /4 ;
440
483
uint32_t * src_addr = src_buff_addr ;
@@ -546,7 +589,7 @@ static void sam_ba_monitor_loop(void)
546
589
// Notify command completed
547
590
sam_ba_putdata ( ptr_monitor_if , "Y\n\r" , 3 );
548
591
}
549
- else if (command == 'Z' )
592
+ else if (command == 'Z' ) // Calculate CRC16
550
593
{
551
594
// This command calculate CRC for a given area of memory.
552
595
// It's useful to quickly check if a transfer has been done
@@ -648,6 +691,12 @@ void sam_ba_monitor_run(void)
648
691
PAGES = NVMCTRL -> PARAM .bit .NVMP ;
649
692
MAX_FLASH = PAGE_SIZE * PAGES ;
650
693
694
+ #ifdef SECURE_BY_DEFAULT
695
+ b_security_enabled = true;
696
+ #else
697
+ b_security_enabled = NVMCTRL -> STATUS .bit .SB != 0 ;
698
+ #endif
699
+
651
700
ptr_data = NULL ;
652
701
command = 'z' ;
653
702
while (1 )
0 commit comments