comparison main.c @ 45:a0f2fcc6d9dd

add buildid
author Matt Johnston <matt@ucc.asn.au>
date Sat, 29 Jun 2013 23:46:39 +0800
parents 69cbf9ce72b5
children b1c27f1d6289
comparison
equal deleted inserted replaced
44:2a47c458d6ed 45:a0f2fcc6d9dd
11 #include <avr/eeprom.h> 11 #include <avr/eeprom.h>
12 #include <avr/wdt.h> 12 #include <avr/wdt.h>
13 #include <util/atomic.h> 13 #include <util/atomic.h>
14 #include <util/crc16.h> 14 #include <util/crc16.h>
15 15
16 #include "buildid.h"
17
16 #include "hmac-sha1.h" 18 #include "hmac-sha1.h"
17 #include "aes.h" 19 #include "aes.h"
18 20
19 #include "fat.h" 21 #include "fat.h"
20 #include "fat_config.h" 22 #include "fat_config.h"
38 #define SLEEP_COMPARE (F_CPU/256) // == 19200 for 4915200mhz 40 #define SLEEP_COMPARE (F_CPU/256) // == 19200 for 4915200mhz
39 #define NKEYS 10 41 #define NKEYS 10
40 #define HMACLEN 20 42 #define HMACLEN 20
41 #define AESLEN 16 43 #define AESLEN 16
42 #define KEYLEN HMACLEN 44 #define KEYLEN HMACLEN
45 // 64 bits is enough for a realtime challenge
46 #define CHALLEN 8
43 47
44 #define BAUD 115200 48 #define BAUD 115200
45 #define UBRR ((F_CPU)/(16*(BAUD))-1) 49 #define UBRR ((F_CPU)/(16*(BAUD))-1)
46 50
47 #define PORT_PI_BOOT PORTD 51 #define PORT_PI_BOOT PORTD
118 // flips between 0 and 1 each watchdog_long_hit, so eventually a 122 // flips between 0 and 1 each watchdog_long_hit, so eventually a
119 // working firmware should boot. set back to 0 for each 'alive' 123 // working firmware should boot. set back to 0 for each 'alive'
120 // command 124 // command
121 static uint8_t long_reboot_mode = 0; 125 static uint8_t long_reboot_mode = 0;
122 126
127 static uint8_t boot_id_set = 0;
128 static uint8_t boot_id[HMACLEN];
129
123 static uint8_t readpos; 130 static uint8_t readpos;
124 static char readbuf[150]; 131 static char readbuf[150];
125 static uint8_t have_cmd; 132 static uint8_t have_cmd;
126 133
127 int uart_putchar(char c, FILE *stream); 134 int uart_putchar(char c, FILE *stream);
129 static void blink(); 136 static void blink();
130 static uint16_t adc_vcc(); 137 static uint16_t adc_vcc();
131 static uint16_t adc_5v(uint16_t vcc); 138 static uint16_t adc_5v(uint16_t vcc);
132 static uint16_t adc_temp(); 139 static uint16_t adc_temp();
133 static void set_pi_boot_normal(uint8_t normal); 140 static void set_pi_boot_normal(uint8_t normal);
134 141 static void adc_random(uint8_t admux,
142 uint8_t *out, uint16_t num, uint32_t *tries);
135 143
136 static FILE mystdout = FDEV_SETUP_STREAM(uart_putchar, NULL, 144 static FILE mystdout = FDEV_SETUP_STREAM(uart_putchar, NULL,
137 _FDEV_SETUP_WRITE); 145 _FDEV_SETUP_WRITE);
138 146
139 // thanks to http://projectgus.com/2010/07/eeprom-access-with-arduino/ 147 // thanks to http://projectgus.com/2010/07/eeprom-access-with-arduino/
272 UDR0 = '\n'; 280 UDR0 = '\n';
273 } 281 }
274 return (unsigned char)c; 282 return (unsigned char)c;
275 } 283 }
276 284
285 #if 0
286
277 uint8_t find_file_in_dir(struct fat_fs_struct* fs, struct fat_dir_struct* dd, const char* name, struct fat_dir_entry_struct* dir_entry) 287 uint8_t find_file_in_dir(struct fat_fs_struct* fs, struct fat_dir_struct* dd, const char* name, struct fat_dir_entry_struct* dir_entry)
278 { 288 {
279 while(fat_read_dir(dd, dir_entry)) 289 while(fat_read_dir(dd, dir_entry))
280 { 290 {
281 if(strcmp(dir_entry->long_name, name) == 0) 291 if(strcmp(dir_entry->long_name, name) == 0)
372 382
373 383
374 static void 384 static void
375 cmd_testsd(const char *param) 385 cmd_testsd(const char *param)
376 { 386 {
387 boot_id_set = 0;
377 PORT_PI_RESET &= ~_BV(PIN_PI_RESET); 388 PORT_PI_RESET &= ~_BV(PIN_PI_RESET);
378 DDR_PI_RESET |= _BV(PIN_PI_RESET); 389 DDR_PI_RESET |= _BV(PIN_PI_RESET);
379 long_delay(200); 390 long_delay(200);
380 391
381 printf_P(PSTR("about to raw init\n")); 392 printf_P(PSTR("about to raw init\n"));
388 399
389 long_delay(200); 400 long_delay(200);
390 401
391 DDR_PI_RESET &= ~_BV(PIN_PI_RESET); 402 DDR_PI_RESET &= ~_BV(PIN_PI_RESET);
392 } 403 }
404 #endif
393 405
394 static void cmd_reset() __attribute__ ((noreturn)); 406 static void cmd_reset() __attribute__ ((noreturn));
395 static void 407 static void
396 cmd_reset() 408 cmd_reset()
397 { 409 {
398 printf_P(PSTR("reset\n")); 410 printf_P(PSTR("reset\n"));
399 _delay_ms(100); 411 long_delay(100);
400 cli(); // disable interrupts 412 cli(); // disable interrupts
401 wdt_enable(WDTO_15MS); // enable watchdog 413 wdt_enable(WDTO_15MS); // enable watchdog
402 while(1); // wait for watchdog to reset processor 414 while(1); // wait for watchdog to reset processor
403 } 415 }
404 416
446 "watchdog_short %lu (%lu)\n" 458 "watchdog_short %lu (%lu)\n"
447 "newboot %lu (%lu)\n" 459 "newboot %lu (%lu)\n"
448 "oneshot (%lu)\n" 460 "oneshot (%lu)\n"
449 "uptime %lu rem %u\n" 461 "uptime %lu rem %u\n"
450 "boot normal %hhu\n" 462 "boot normal %hhu\n"
451 "disk serial %lx\n"
452 "disk start '%s'\n"
453 ), 463 ),
454 watchdog_long_limit, cur_watchdog_long, long_reboot_mode, 464 watchdog_long_limit, cur_watchdog_long, long_reboot_mode,
455 watchdog_short_limit, cur_watchdog_short, 465 watchdog_short_limit, cur_watchdog_short,
456 newboot_limit, cur_newboot, 466 newboot_limit, cur_newboot,
457 cur_oneshot, 467 cur_oneshot,
458 t.ticks, t.rem, 468 t.ticks, t.rem,
459 boot_normal_status, 469 boot_normal_status);
460 sd_serial,
461 conf_start);
462 } 470 }
463 471
464 static void 472 static void
465 cmd_set_params(const char *params) 473 cmd_set_params(const char *params)
466 { 474 {
742 "temp: %u mV (%dºC)\n" 750 "temp: %u mV (%dºC)\n"
743 ), 751 ),
744 vcc, v5, temp, temp_deg); 752 vcc, v5, temp, temp_deg);
745 } 753 }
746 754
755 static void
756 get_random(uint8_t *out)
757 {
758 uint32_t tries;
759 uint8_t rnd[20];
760 adc_random(0x44, rnd, sizeof(rnd), &tries);
761 hmac_sha1(out, buildid, sizeof(buildid)*8, rnd, sizeof(rnd)*8);
762 }
763
764 static void
765 cmd_bootid(const char *arg)
766 {
767 uint8_t hmac[HMACLEN];
768 uint8_t input[CHALLEN+sizeof(boot_id)];
769
770 if (strlen(arg) != CHALLEN*2)
771 {
772 printf_P(PSTR("Bad challenge\n"));
773 }
774 for (int i = 0, p = 0; i < CHALLEN; i++, p += 2)
775 {
776 input[i] = (from_hex(arg[p]) << 4) | from_hex(arg[p+1]);
777 }
778 memcpy(&input[CHALLEN], boot_id, sizeof(boot_id));
779
780 if (!boot_id_set)
781 {
782 _Static_assert(sizeof(boot_id) == HMACLEN, "boot_id size correct");
783 get_random(boot_id);
784 boot_id_set = 1;
785 }
786 hmac_sha1(hmac, avr_keys[0], KEYLEN*8, input, sizeof(input)*8);
787 printf_P(PSTR("bootid: "));
788 printhex(boot_id, sizeof(boot_id), stdout);
789 putchar(' ');
790 printhex(hmac, sizeof(hmac), stdout);
791 putchar('\n');
792 }
747 793
748 void(*bootloader)() __attribute__ ((noreturn)) = (void*)0x7800; 794 void(*bootloader)() __attribute__ ((noreturn)) = (void*)0x7800;
749 795
750 #ifndef PROG_PASSWORD 796 #ifndef PROG_PASSWORD
751 #define PROG_PASSWORD "Y2vvjxO5" 797 #define PROG_PASSWORD "Y2vvjxO5"
1007 LOCAL_PSTR(newboot); 1053 LOCAL_PSTR(newboot);
1008 LOCAL_PSTR(oldboot); 1054 LOCAL_PSTR(oldboot);
1009 LOCAL_PSTR(status); 1055 LOCAL_PSTR(status);
1010 LOCAL_PSTR(random); 1056 LOCAL_PSTR(random);
1011 LOCAL_PSTR(prog); 1057 LOCAL_PSTR(prog);
1012 LOCAL_PSTR(testsd); 1058 LOCAL_PSTR(bootid);
1013 LOCAL_HELP(set_params, "<long_limit> <short_limit> <newboot_limit>"); 1059 LOCAL_HELP(set_params, "<long_limit> <short_limit> <newboot_limit>");
1014 LOCAL_HELP(set_key, "20_byte_hex>"); 1060 LOCAL_HELP(set_key, "20_byte_hex>");
1015 LOCAL_HELP(oneshot, "<timeout>"); 1061 LOCAL_HELP(oneshot, "<timeout>");
1016 LOCAL_HELP(prog, "<password>"); 1062 LOCAL_HELP(prog, "<password>");
1017 LOCAL_HELP(random, "<admux> <nbytes>"); 1063 LOCAL_HELP(random, "<admux> <nbytes>");
1018 LOCAL_HELP(hmac, "<key_index> <20_byte_hex_data>"); 1064 LOCAL_HELP(hmac, "<key_index> <20_byte_hex_data>");
1019 LOCAL_HELP(decrypt, "<key_index> <20_byte_hmac|16_byte_aes_block>"); 1065 LOCAL_HELP(decrypt, "<key_index> <20_byte_hmac|16_byte_aes_block>");
1020 LOCAL_HELP(testsd, "<filename>"); 1066 LOCAL_HELP(bootid, "<8_byte_challenge>")
1021 1067
1022 static const struct handler { 1068 static const struct handler {
1023 PGM_P name; 1069 PGM_P name;
1024 void(*cmd)(const char *param); 1070 void(*cmd)(const char *param);
1025 // existence of arg_help indicates if the cmd takes a parameter. 1071 // existence of arg_help indicates if the cmd takes a parameter.
1037 {set_params_str, cmd_set_params, set_params_help}, 1083 {set_params_str, cmd_set_params, set_params_help},
1038 {set_key_str, cmd_set_avr_key, set_key_help}, 1084 {set_key_str, cmd_set_avr_key, set_key_help},
1039 {random_str, cmd_random, random_help}, 1085 {random_str, cmd_random, random_help},
1040 {vcc_str, cmd_vcc, NULL}, 1086 {vcc_str, cmd_vcc, NULL},
1041 {reset_str, cmd_reset, NULL}, 1087 {reset_str, cmd_reset, NULL},
1042 {testsd_str, cmd_testsd, testsd_help},
1043 {prog_str, cmd_prog, prog_help}, 1088 {prog_str, cmd_prog, prog_help},
1089 {bootid_str, cmd_bootid, bootid_help},
1044 }; 1090 };
1045 1091
1046 if (readbuf[0] == '\0') 1092 if (readbuf[0] == '\0')
1047 { 1093 {
1048 return; 1094 return;
1099 } 1145 }
1100 1146
1101 ISR(INT0_vect) 1147 ISR(INT0_vect)
1102 { 1148 {
1103 blink(); 1149 blink();
1104 _delay_ms(100); 1150 long_delay(100);
1105 blink(); 1151 blink();
1106 } 1152 }
1107 1153
1108 ISR(USART_RX_vect) 1154 ISR(USART_RX_vect)
1109 { 1155 {
1197 1243
1198 static void 1244 static void
1199 reboot_pi() 1245 reboot_pi()
1200 { 1246 {
1201 printf_P(PSTR("Real reboot now\n")); 1247 printf_P(PSTR("Real reboot now\n"));
1248 boot_id_set = 0;
1202 // pull it low for 200ms 1249 // pull it low for 200ms
1203 PORT_PI_RESET &= ~_BV(PIN_PI_RESET); 1250 PORT_PI_RESET &= ~_BV(PIN_PI_RESET);
1204 DDR_PI_RESET |= _BV(PIN_PI_RESET); 1251 DDR_PI_RESET |= _BV(PIN_PI_RESET);
1205 _delay_ms(200); 1252 long_delay(200);
1206 1253
1207 PORT_PI_WARNING &= ~_BV(PIN_PI_WARNING); 1254 PORT_PI_WARNING &= ~_BV(PIN_PI_WARNING);
1208 DDR_PI_RESET &= ~_BV(PIN_PI_RESET); 1255 DDR_PI_RESET &= ~_BV(PIN_PI_RESET);
1209 } 1256 }
1210 1257