Mercurial > pihelp
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 |