[FL-1934] Core: wipe memory after free. SubGhz: key encryption tool. (#797)
* Core: wipe memory after free. RFID,iButton: fix iterator use after invalidation. * Debug: support unix wildcards for register matching in svd, update MCU description file and minify it. * Toolbox: getter for File in FlipperFile. * Makefile: conditional flashing * SubGhz: keeloq_mfcodes encryption tool. * FuriHal: proper IV handling on CBC in crypto. SubGhz: add support for encrypted keeloq keys. Makefile: move formatting to top Makefile. * SubGhz: rename some function names to match naming scheme. * SubGhz: encryption tool, fix windows line endings Co-authored-by: DrZlo13 <who.just.the.doctor@gmail.com>
This commit is contained in:
		
							parent
							
								
									3f93a0ae46
								
							
						
					
					
						commit
						22a4bac448
					
				
							
								
								
									
										14
									
								
								Makefile
									
									
									
									
									
								
							
							
						
						
									
										14
									
								
								Makefile
									
									
									
									
									
								
							| @ -49,12 +49,16 @@ firmware_clean: | |||||||
| 
 | 
 | ||||||
| .PHONY: bootloader_flash | .PHONY: bootloader_flash | ||||||
| bootloader_flash: | bootloader_flash: | ||||||
|  | ifeq ($(FORCE), '1') | ||||||
| 	rm $(PROJECT_ROOT)/bootloader/.obj/f*/flash || true | 	rm $(PROJECT_ROOT)/bootloader/.obj/f*/flash || true | ||||||
|  | endif | ||||||
| 	$(MAKE) -C $(PROJECT_ROOT)/bootloader -j$(NPROCS) flash | 	$(MAKE) -C $(PROJECT_ROOT)/bootloader -j$(NPROCS) flash | ||||||
| 
 | 
 | ||||||
| .PHONY: firmware_flash | .PHONY: firmware_flash | ||||||
| firmware_flash: | firmware_flash: | ||||||
|  | ifeq ($(FORCE), '1') | ||||||
| 	rm $(PROJECT_ROOT)/firmware/.obj/f*/flash || true | 	rm $(PROJECT_ROOT)/firmware/.obj/f*/flash || true | ||||||
|  | endif | ||||||
| 	$(MAKE) -C $(PROJECT_ROOT)/firmware -j$(NPROCS) flash | 	$(MAKE) -C $(PROJECT_ROOT)/firmware -j$(NPROCS) flash | ||||||
| 
 | 
 | ||||||
| .PHONY: flash_radio | .PHONY: flash_radio | ||||||
| @ -73,8 +77,16 @@ flash_radio_fus: | |||||||
| 	@echo "================    JUST DON'T    ================" | 	@echo "================    JUST DON'T    ================" | ||||||
| 	@echo | 	@echo | ||||||
| 
 | 
 | ||||||
| .PHONY:  | .PHONY: flash_radio_fus_please_i_m_not_going_to_complain | ||||||
| flash_radio_fus_please_i_m_not_going_to_complain: | flash_radio_fus_please_i_m_not_going_to_complain: | ||||||
| 	$(PROJECT_ROOT)/scripts/flash.py core2fus 0x080EC000 --statement=AGREE_TO_LOOSE_FLIPPER_FEATURES_THAT_USES_CRYPTO_ENCLAVE $(COPRO_DIR)/stm32wb5x_FUS_fw_for_fus_0_5_3.bin | 	$(PROJECT_ROOT)/scripts/flash.py core2fus 0x080EC000 --statement=AGREE_TO_LOOSE_FLIPPER_FEATURES_THAT_USES_CRYPTO_ENCLAVE $(COPRO_DIR)/stm32wb5x_FUS_fw_for_fus_0_5_3.bin | ||||||
| 	$(PROJECT_ROOT)/scripts/flash.py core2fus 0x080EC000 --statement=AGREE_TO_LOOSE_FLIPPER_FEATURES_THAT_USES_CRYPTO_ENCLAVE $(COPRO_DIR)/stm32wb5x_FUS_fw.bin | 	$(PROJECT_ROOT)/scripts/flash.py core2fus 0x080EC000 --statement=AGREE_TO_LOOSE_FLIPPER_FEATURES_THAT_USES_CRYPTO_ENCLAVE $(COPRO_DIR)/stm32wb5x_FUS_fw.bin | ||||||
| 	$(PROJECT_ROOT)/scripts/ob.py set | 	$(PROJECT_ROOT)/scripts/ob.py set | ||||||
|  | 
 | ||||||
|  | FORMAT_SOURCES = $(shell find applications bootloader core -iname "*.h" -o -iname "*.c" -o -iname "*.cpp") | ||||||
|  | 
 | ||||||
|  | .PHONY: format | ||||||
|  | format: | ||||||
|  | 	@echo "Formatting sources with clang-format" | ||||||
|  | 	@clang-format -style=file -i $(FORMAT_SOURCES) | ||||||
|  | 
 | ||||||
|  | |||||||
| @ -48,8 +48,8 @@ iButtonApp::iButtonApp() | |||||||
| iButtonApp::~iButtonApp() { | iButtonApp::~iButtonApp() { | ||||||
|     for(std::map<Scene, iButtonScene*>::iterator it = scenes.begin(); it != scenes.end(); ++it) { |     for(std::map<Scene, iButtonScene*>::iterator it = scenes.begin(); it != scenes.end(); ++it) { | ||||||
|         delete it->second; |         delete it->second; | ||||||
|         scenes.erase(it); |  | ||||||
|     } |     } | ||||||
|  |     scenes.clear(); | ||||||
|     delete key_worker; |     delete key_worker; | ||||||
| 
 | 
 | ||||||
|     furi_hal_power_insomnia_exit(); |     furi_hal_power_insomnia_exit(); | ||||||
|  | |||||||
| @ -10,8 +10,9 @@ RfidTimerEmulator::~RfidTimerEmulator() { | |||||||
| 
 | 
 | ||||||
|     for(it = encoders.begin(); it != encoders.end(); ++it) { |     for(it = encoders.begin(); it != encoders.end(); ++it) { | ||||||
|         delete it->second; |         delete it->second; | ||||||
|         encoders.erase(it); |  | ||||||
|     } |     } | ||||||
|  | 
 | ||||||
|  |     encoders.clear(); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void RfidTimerEmulator::start(LfrfidKeyType type, const uint8_t* data, uint8_t data_size) { | void RfidTimerEmulator::start(LfrfidKeyType type, const uint8_t* data, uint8_t data_size) { | ||||||
|  | |||||||
| @ -3,26 +3,15 @@ | |||||||
| #include <furi.h> | #include <furi.h> | ||||||
| #include <furi-hal.h> | #include <furi-hal.h> | ||||||
| #include <stream_buffer.h> | #include <stream_buffer.h> | ||||||
|  | #include <lib/toolbox/args.h> | ||||||
| #include <lib/subghz/subghz_parser.h> | #include <lib/subghz/subghz_parser.h> | ||||||
|  | #include <lib/subghz/subghz_keystore.h> | ||||||
| #include <lib/subghz/protocols/subghz_protocol_common.h> | #include <lib/subghz/protocols/subghz_protocol_common.h> | ||||||
| #include <lib/subghz/protocols/subghz_protocol_princeton.h> | #include <lib/subghz/protocols/subghz_protocol_princeton.h> | ||||||
| 
 | 
 | ||||||
| #define SUBGHZ_FREQUENCY_RANGE_STR \ | #define SUBGHZ_FREQUENCY_RANGE_STR \ | ||||||
|     "299999755...348000000 or 386999938...464000000 or 778999847...928000000" |     "299999755...348000000 or 386999938...464000000 or 778999847...928000000" | ||||||
| 
 | 
 | ||||||
| void subghz_cli_init() { |  | ||||||
|     Cli* cli = furi_record_open("cli"); |  | ||||||
| 
 |  | ||||||
|     cli_add_command( |  | ||||||
|         cli, "subghz_tx_carrier", CliCommandFlagDefault, subghz_cli_command_tx_carrier, NULL); |  | ||||||
|     cli_add_command( |  | ||||||
|         cli, "subghz_rx_carrier", CliCommandFlagDefault, subghz_cli_command_rx_carrier, NULL); |  | ||||||
|     cli_add_command(cli, "subghz_tx", CliCommandFlagDefault, subghz_cli_command_tx, NULL); |  | ||||||
|     cli_add_command(cli, "subghz_rx", CliCommandFlagDefault, subghz_cli_command_rx, NULL); |  | ||||||
| 
 |  | ||||||
|     furi_record_close("cli"); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| void subghz_cli_command_tx_carrier(Cli* cli, string_t args, void* context) { | void subghz_cli_command_tx_carrier(Cli* cli, string_t args, void* context) { | ||||||
|     uint32_t frequency = 433920000; |     uint32_t frequency = 433920000; | ||||||
| 
 | 
 | ||||||
| @ -267,3 +256,88 @@ void subghz_cli_command_rx(Cli* cli, string_t args, void* context) { | |||||||
|     vStreamBufferDelete(instance->stream); |     vStreamBufferDelete(instance->stream); | ||||||
|     free(instance); |     free(instance); | ||||||
| } | } | ||||||
|  | 
 | ||||||
|  | void subghz_cli_command_print_usage() { | ||||||
|  |     printf("Usage:\r\n"); | ||||||
|  |     printf("subghz_crypto <cmd> <args>\r\n"); | ||||||
|  |     printf("Cmd list:\r\n"); | ||||||
|  |     printf( | ||||||
|  |         "\tkeeloq <plain_text_file> <encrypted_file> <IV:16 bytes in hex>\t - Encrypt keeloq manufacture keys\r\n"); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void subghz_cli_command_encrypt_keeloq(Cli* cli, string_t args) { | ||||||
|  |     uint8_t iv[16]; | ||||||
|  | 
 | ||||||
|  |     string_t source; | ||||||
|  |     string_t destination; | ||||||
|  |     string_init(source); | ||||||
|  |     string_init(destination); | ||||||
|  | 
 | ||||||
|  |     SubGhzKeystore* keystore = subghz_keystore_alloc(); | ||||||
|  | 
 | ||||||
|  |     do { | ||||||
|  |         if(!args_read_string_and_trim(args, source)) { | ||||||
|  |             subghz_cli_command_print_usage(); | ||||||
|  |             break; | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         if(!args_read_string_and_trim(args, destination)) { | ||||||
|  |             subghz_cli_command_print_usage(); | ||||||
|  |             break; | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         if(!args_read_hex_bytes(args, iv, 16)) { | ||||||
|  |             subghz_cli_command_print_usage(); | ||||||
|  |             break; | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         if(!subghz_keystore_load(keystore, string_get_cstr(source))) { | ||||||
|  |             printf("Failed to load Keystore"); | ||||||
|  |             break; | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         if(!subghz_keystore_save(keystore, string_get_cstr(destination), iv)) { | ||||||
|  |             printf("Failed to save Keystore"); | ||||||
|  |             break; | ||||||
|  |         } | ||||||
|  |     } while(false); | ||||||
|  | 
 | ||||||
|  |     subghz_keystore_free(keystore); | ||||||
|  |     string_clear(destination); | ||||||
|  |     string_clear(source); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void subghz_cli_command(Cli* cli, string_t args, void* context) { | ||||||
|  |     string_t cmd; | ||||||
|  |     string_init(cmd); | ||||||
|  | 
 | ||||||
|  |     do { | ||||||
|  |         if(!args_read_string_and_trim(args, cmd)) { | ||||||
|  |             subghz_cli_command_print_usage(); | ||||||
|  |             break; | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         if(string_cmp_str(cmd, "encrypt_keeloq") == 0) { | ||||||
|  |             subghz_cli_command_encrypt_keeloq(cli, args); | ||||||
|  |             break; | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         subghz_cli_command_print_usage(); | ||||||
|  |     } while(false); | ||||||
|  | 
 | ||||||
|  |     string_clear(cmd); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void subghz_cli_init() { | ||||||
|  |     Cli* cli = furi_record_open("cli"); | ||||||
|  | 
 | ||||||
|  |     cli_add_command( | ||||||
|  |         cli, "subghz_tx_carrier", CliCommandFlagDefault, subghz_cli_command_tx_carrier, NULL); | ||||||
|  |     cli_add_command( | ||||||
|  |         cli, "subghz_rx_carrier", CliCommandFlagDefault, subghz_cli_command_rx_carrier, NULL); | ||||||
|  |     cli_add_command(cli, "subghz_tx", CliCommandFlagDefault, subghz_cli_command_tx, NULL); | ||||||
|  |     cli_add_command(cli, "subghz_rx", CliCommandFlagDefault, subghz_cli_command_rx, NULL); | ||||||
|  |     cli_add_command(cli, "subghz", CliCommandFlagDefault, subghz_cli_command, NULL); | ||||||
|  | 
 | ||||||
|  |     furi_record_close("cli"); | ||||||
|  | } | ||||||
|  | |||||||
| @ -3,15 +3,3 @@ | |||||||
| #include <cli/cli.h> | #include <cli/cli.h> | ||||||
| 
 | 
 | ||||||
| void subghz_cli_init(); | void subghz_cli_init(); | ||||||
| 
 |  | ||||||
| void subghz_cli_command_tx_carrier(Cli* cli, string_t args, void* context); |  | ||||||
| 
 |  | ||||||
| void subghz_cli_command_rx_carrier(Cli* cli, string_t args, void* context); |  | ||||||
| 
 |  | ||||||
| void subghz_cli_command_tx_pt(Cli* cli, string_t args, void* context); |  | ||||||
| 
 |  | ||||||
| void subghz_cli_command_rx_pt(Cli* cli, string_t args, void* context); |  | ||||||
| 
 |  | ||||||
| void subghz_cli_command_tx(Cli* cli, string_t args, void* context); |  | ||||||
| 
 |  | ||||||
| void subghz_cli_command_rx(Cli* cli, string_t args, void* context); |  | ||||||
|  | |||||||
							
								
								
									
										311
									
								
								assets/resources/subghz/keeloq_mfcodes
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										311
									
								
								assets/resources/subghz/keeloq_mfcodes
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,311 @@ | |||||||
|  | Filetype: Flipper SubGhz Keystore File | ||||||
|  | Version: 0 | ||||||
|  | Encryption: 1 | ||||||
|  | IV: 7A 44 FE 5D C3 B3 65 13 73 A6 F4 2D 1E B6 7D F0 | ||||||
|  | 89153B35033574AAA06D7E792CB92A486B37A2CCDF0B0152BF1A563E321518C8 | ||||||
|  | F6583A3E4148439E8A8D7ED6A095ACC0C3E22A48F1637E78DF023CAC9272934E | ||||||
|  | AA0439E6B76CD43F3FCC27CF69C5F3B6508E8103B164E4ECDDF8B2FB222D46FF | ||||||
|  | A9826C663033D25AE21CB8790406997ADCE84360B258F2B989D967009659859C | ||||||
|  | 3474E7BBFA0173928F414CFD5EE19B27A558D9C171D96FE7B7840A01323A7E7446FAE3E98EA9A8C69B4A6B781BD7906A | ||||||
|  | 2873939A8E0EAC16D748967E987BB0F1079C106E4235B7D35B4BF37F54B21F8E | ||||||
|  | EF6F1DC0201FCB8CEBC5642A5194A1FDCFBE1FA772A79CEAD54D2F0DA3AC4F6C | ||||||
|  | 3F595EAA0E81E96C5D6DB41799D314E3E81E7F4197E19A3341C55592B1B6C4B0 | ||||||
|  | 7B2D75FE11B27E99CA7610E47D712C8CFB619EC69EBC976A70CFD9574C9F4FF8 | ||||||
|  | 39735CF1D009D132A33B9C546D95FA6D3E69BF3A57EF219392E57C9560E7B037 | ||||||
|  | D56FDDFB0C4E808143D3ED5F15D6FF47F6EDEBD01192FC7ACF3ACCE9FD5162FC297D0089D65ED2CBE3CE05DDA7B96446 | ||||||
|  | 2750D4F0650061C3AF72C88FD080BE241F2BDD8D8C1B0EFE781120EBEFFE2C72D0EECC42CDDED50CFE4AC51C48AE68C6 | ||||||
|  | F8CE64921CB73015F2672A9EF0A8359269CAE0E515D6DBB3130CFC9E5E1A98AD | ||||||
|  | ACF6ADB9E02D67B44EB6C6F126BF64BDAB37926B8BE39E27F323E8F5A0F8FC38 | ||||||
|  | FBB1302D697F94ECED681CE047819001EDE6E013850258F61E97091DD37D24F2 | ||||||
|  | D8CD53AB5A94898EB53D4FF46546ADBAA24691181A396052A58AAC657D6817AB | ||||||
|  | 43200E08C21747CABC59538888A259238E782545732A1A6EEE00A6929EC9DD97A8BA9812372374046AC66652CC561D60 | ||||||
|  | C38CBE29F22D0E83E58A52E94AA2485DA8E702FBDB89D27249473CB8A19AEF61 | ||||||
|  | 9F0EB580F7474985E8460E1682451E213778B77A9CAB4734B75C5386851050BF | ||||||
|  | 2364EBB8237363B21226565675B9F478482CADAE41E795C27287E26137797C10 | ||||||
|  | 775C9A28BA50D759FB438D0200121F01F7DB11986D44D3960F745EAA1E7A2CE2AD92AD718AFCD98BC3269C39F65ADC53 | ||||||
|  | 26FB0DDEF3E3AED16D6DBC93AD1A12F9F871AB9E73EA13DAD2715E22F7EE5D27 | ||||||
|  | 07BAF6D32302D597E31CB38A205A0D27C6EAE886BF1D7E5EAA911E07DFF9D71007E64F66D92CF3140F3308D35894E690 | ||||||
|  | 8AE3F4737608320BCD4FDC51336EBE8C40056D0ACC85D54A74C30F7087F1128F5021255EF36356EDEF1E789AB23541ED | ||||||
|  | E46E90AA42DD6E95020E31FA2AFE067DF4C47B2C5B101207DD13A72F56BCB2D66666E42B195EA7A800D27DB4469E198C | ||||||
|  | 5DA74C2C12F022379CB8359F11C465464570B822A7EE86B0426FA116F1B3E294 | ||||||
|  | 6192E98C705F08FD82BFF01315FBD219FC77E47C65F53668E8429FDF7FCC657A | ||||||
|  | 4EC88DC9084B4EA7DCB4AFDF63445CC8B842BC17821D108775FB8FA8DFFEB7F845B32F1C2536FEA4B2E6B8F8526C8FB0 | ||||||
|  | BBDA1F8A815C6586CFD235653B9E58F9AE3A97F4EBF5945F9EB6CA5C1BFE4FE3 | ||||||
|  | 060BBA81DBD222C312D4925A35B20D102FD77BF921EFB986BD776E9FF372A627 | ||||||
|  | F320DDB2963E06DCB2068E0BDDA207068EF43608521BD73965E72A86948CE6D53C7C3AE298C781C128E0FEEC2F5A3913 | ||||||
|  | 592BB6BEC2D30AD7BDFEB234F330C243313A4FE96D85BE27B457963574DD851A1255E8D0EA85BC1CDF132F3F3D0D6085 | ||||||
|  | 38E5E20E9A444453A932C0368E8A09048D4E592EB5F4505053223B67A9D80BFBCE2EEC96C4622B2EA9AFF35105F07BAA | ||||||
|  | 31BE3FC6E58EAE2778F96C18E8D79A23C3E0772B53AFC3F68382F7C3823ECE29 | ||||||
|  | CFBEA2A3468585001CA05D7402C48F59695FF312D294E2CBB3F1700EEFFFF85C | ||||||
|  | 9A712D7FAD46F68B1679B08CE47DE4A58D6AB76BC0ED3842B10CFE8B146AD43F | ||||||
|  | 77320813C638A37D3B6E7A172A1EEBA626E06D8A13F8193A0330921776CC90F7 | ||||||
|  | 20C422A7B35649176A5D3B2CEDA5A64C49ADA6F7774FF014173EC2CA256940BC | ||||||
|  | 81BC110B279FC7FD9F0FD2AB12360E3132F8B066F6D512FB11C93700B651D03F | ||||||
|  | 79097CEDE56399A19038DAE41C0D7840E676CECE7E860FF80F2AA016E1DB4C6E | ||||||
|  | FC29AB949C97B45DB4344670483D7D38DE4D969DC40B4A2D49D902CD867937F9 | ||||||
|  | 37358C7E2DFFFA7BB794B367C0DAC4474EFE1A2BC14EDC5F3DB3A796BB5C5E00 | ||||||
|  | FDD7E5E1ED52244B828D6D8E5BB06BB24B5E36EC29485EA25BCB44855168E6EE | ||||||
|  | DC97CD3B94036A1877AF836CBC6EEFFEF7A728119857787271B922316F36ACF4 | ||||||
|  | D947681EC3D77CA6DEF28647D6395E0334386C7BCBD60C24148A3299A08B25B2 | ||||||
|  | DC95208BC6206A7F1F388933BA89920E559BC02B57124A4C7AF4E3F150AC6909 | ||||||
|  | E399ACC6D617B0C84F0CCD3B2E017684971761A0E3998DFDD1212D1B3AFC833B | ||||||
|  | 7F28B85A66B4D1D3C56388C89E6AFF5F15F62EC43E1A0114B6EEF77B80E61A22 | ||||||
|  | 50B5825CB4A97CC8ED457F3851370723441583E6060BF5FCC707870DFCEE297F | ||||||
|  | DD8EB05EBC7D00585DAB70C7083C3EC1C688F6D638D663DB1A3B32B7DEDC8E8E | ||||||
|  | 5D7344AE669170A120B65D622B1EA1B774C391B4BF467862771CD187EAA2B526 | ||||||
|  | 7031F01CD763974734B95E3B466403C2032FCEB45A2EDC9B5E65B5E122C0CC8E | ||||||
|  | 91A9C77CE9C7BA309244ABB7685FEFD85EEC25416B166FEBF0E914C345BDE2E9 | ||||||
|  | 56B2CD788B62B4D69D7BE317444D1C49B098124FF2728129FDEAEE6C802F68A7 | ||||||
|  | 5070A127707CE7707265DBD50746D9BF98D5125B9EF57EE4687073EA06C329B0 | ||||||
|  | 23AE7B3F7F0C37D08E80182E1689BCDA9DFBC4D73F9AC2AC0064A9DA656E87E3 | ||||||
|  | 6018F724D158F64FD3AFD2D6FB1F45768DBBF8527292621B0C1E821DFEA601B1 | ||||||
|  | F337DD4907C18F55814A3733230988C6AACF4BB1FFBC34E83B0EE38EA7DD69EF | ||||||
|  | 6729CF64062453E9F258A2D57D5EA7ACC316E9D90A8DB3E0BCB8B945947C6C21 | ||||||
|  | DF3755632B2ED4E5F77AED01F656F075043A2B7AD5D1186D959BCEEAD09C745A | ||||||
|  | 784327D41235A105990E4698CCC45D7AEECC460011D045BA54234244466F5C47 | ||||||
|  | 2ECC93294BD18252B777A1859CD4E2C77BF8EE590BDC4D97D9EC516D85108889 | ||||||
|  | 84AA6F4A08EE665F3DFC9F58CA2E3FC1DF0F476AF8818031C6FE4A984B59AFC1 | ||||||
|  | A58DD957933CDF5F04FBAB6B5C71E6F8925B8BE383743752D720848C297E0DF0 | ||||||
|  | B9460B6133D8C231E13D6697555D10D3EB5E2758C549846BC7E5421A016D8D25 | ||||||
|  | B72A12B23AEA00362D758E1E2C829487A36A996D1F0030ACA4648912C98553A8 | ||||||
|  | EA9E2AFED722717FE35EB292CA54ABDB4140093DE8E86F72AE01C22D99F9CF40 | ||||||
|  | 5C4EE54D4273A76B7268231D7B6CC4B7EA6E8D2699B263C44A472AD2AF434BDA | ||||||
|  | 4D62CFCBFA3638E24DDC5FC6BC0CC45963B142027A5E44A6669590F5CE590BA0 | ||||||
|  | 1D282D45D1805BDB996E066807052FB7235A8E4C3EC6C440C5B576B3D32BFE4C | ||||||
|  | 4073AD510F89F3A95F73872D52B04000740F7DD52D3F6F56943071AEC41E26C4 | ||||||
|  | D527E0982438FDFE3C2C5EC8039EB97D4A7FFC7F2B13EDD0CCBB8B439B70ABD5 | ||||||
|  | E1DB0AF7B85889C917E4BA66ADF3DD832BC774B5C9531A17B3FDC35CCFAF2F9C | ||||||
|  | 5E631C5D400A99C7A3CC1456E912C3325C646428C9156DDC51D24809213EBABC | ||||||
|  | 9089344688AF4D740062963EA35B89FB71D9ABDB6E8D400551AABCA750F78B3E | ||||||
|  | A33596A074901E992109EE10E8E27A7F6669AA9024701E68446C6D46A2E1B07D | ||||||
|  | 76B97DD16853426AC75B14100453207C1725F0D78AF315FCA8FBED5C7BCC2D44 | ||||||
|  | E90409F8CE4940EA67B943E0848265BDA8648E07865C2054716CC8B03556E312 | ||||||
|  | 2577637463D510AA827AF03E2943A78AB18784B63E0EC17C2C5B6762511371C5 | ||||||
|  | 050D84D9BB5D04DD2674542872E77A065016D0F2D8582B1C1CB8178CEEC3AE53 | ||||||
|  | 98B127524AB0258075E20A5ACC08B94FAE31E87E402B49EA2172A6DDB3F0E991 | ||||||
|  | B754EA3DDBCB5173158E57C6BEB62B62ABAF239A3CC22543F6A80BC2BC1834D9 | ||||||
|  | 100FC4F5286A31E4B83517E6076D3F3B834DB0FD9CB4234212171367A9BBDAB8 | ||||||
|  | 836A9869AD8DD0AF53480BC2F39290438ED63F0F6C0376859F75E7D865F9E555 | ||||||
|  | 55FACDEB9C3276942B02B400F51BFF4A37948EE541242E7491CFC4D72AC18726 | ||||||
|  | F3EC80C3433F722969AC3328771379D19047A12793FDD007F07F41E3F5C8E5FC | ||||||
|  | 70753EC988773789983F9D6F2597A4101054E4DFFAC201485D572F7D726744A1 | ||||||
|  | 4F8E927318CEE32A75134EC9F480D402550B8260EA043CDE51CB3D262DF125E0 | ||||||
|  | EE087504CD1AB9631F3909C6D60A57E5C759320B377AD47EE73883292B98E6DC | ||||||
|  | 418C931303452A58352F0EEDB9C4CEF22C0464F51040DC30B5FDB81249303626 | ||||||
|  | 676B238AEA7798E4830A801B9A80C378B181A3D63AD737106A5CF8E4EBFC61C6 | ||||||
|  | 2B9D24BD81E95BD9CB4736257808DA32F7B8BC88A72CFCB4DD0AECBE9DA8AD2E | ||||||
|  | B7D705574C3F1D5537065F63AE2268465437773EE896D204835900C3938D4AE8 | ||||||
|  | 725FB4701EC3A2D25E46935760F4F50E3339D1B0291A602573AC53CEF95DC85E | ||||||
|  | 13B05A6904D3BED30EA84484E33404A63B69CFD862CB4F3912A72FA0ACBBC611 | ||||||
|  | 889F9AB8B3B0FBD7C1B0EB607C7ACE0F20FDBDE81399A2D9CF1D46E6A88F53C8 | ||||||
|  | 0040A2C446CC985C44FB1D99DAB13258CD1CEF6BA5F749F84334FEACABE335E4 | ||||||
|  | A1657A3F2BBC3DF62C40CC03EA0721AA574D489E77CAA27CFD3A8A627CB923A3 | ||||||
|  | 1388B81F9706A85809088778C42CDE23FAA9EAD0C2CFEB9B967589E90BDD00EC | ||||||
|  | 0EDD657448C00B5FCF5046F226BA492297F177768A1387DA43F864A90F1F1358 | ||||||
|  | 3A5A47B50BF72FBF84F86BC6332EB6270EB6BA20C24092F3D0B54B6C3B6AE637 | ||||||
|  | A25D8310CA1B07153858F34125D267A12D97B4DB528794AE87372F637BEAA9F0 | ||||||
|  | FCCFF2857D53F58DD24DEE5193B8613C9CACC924CBD4F33DADA772B3C2A0AF75 | ||||||
|  | A115C75BBF955E1F062E6DBEC171D8837BB6756F30E75818930AB776F80FC81E | ||||||
|  | 95083E751A4780170D8FAFEAAF96DF2E62102402024D4915FF6FA73E1CD9F0D5 | ||||||
|  | 980225891E9215A82BFEF6D3DB867D7C05F11575EBB8AED653E1C088A7294391 | ||||||
|  | 637160DA818D35774DDD0C375A04D6E0C7F98976FFBD8FFE39FC00E449523D89 | ||||||
|  | FF74098CF07EDFD4004467A7CEC8C8115DFE3D098F2C711882C3F13D6342BF46 | ||||||
|  | CF6E8EBD58DD777682BB9F674B419C6C8D68F5B2388C0486753717D213431E5F | ||||||
|  | 5A9BA50793C6EAA464ADB00910B896F90C548DAB18A45F434436792A56F988CC | ||||||
|  | 9FE1F19F8DC290BCB6B99490901D9E73D10A6EE2D1AA1A253297D66D05A08A19 | ||||||
|  | CDD197057D7B347FF474B58D838CAF614D392E8DED92B01B8C2AE16F79183A8C | ||||||
|  | DCFD8DC6D58663F0CB1285C49ABC501B13209425AF7436DC66B4D6F0529D09DA | ||||||
|  | F8956D6BACDA1F294222DDE8E28C6C791A77FF206286C648AA659149B247744A | ||||||
|  | C494E4123788BF65E95CC39C2F9BEA0C78BA2105D40689F3E7340FEECE0B5B94 | ||||||
|  | 5677786C1222C825BEB177E8E0C64D9B7909717E278C90FAEC70514B7034B5A3 | ||||||
|  | 4575A4397F19DCDEB0C7BB67819F257F6F2B5A53E7D9E08F9F68ED7D854175B4 | ||||||
|  | 29EC9B87DD201CCCFDD32AC67C0212A4C5E45C8188DFBBE97AFF531FDBD1BBA9 | ||||||
|  | 36676541800B391DF20F3A4B4A3DCAE018D85441A93B44F984D2EEB334FD5EDC | ||||||
|  | 278D8E83B662C96C69BE962E271CCD6FDAEB54F563C47997A53AD6960E8C182A | ||||||
|  | 5921F8F8D961B45657FB9965AFF8A567606780C336B42EDA1959F40CD57C1803 | ||||||
|  | 5AD31697C382622CFD185CC2C4F44D6DB1BAA60496AF0AEFDEB50CB0A5CF2EDA | ||||||
|  | 307CBE4B2460EE096CCF772B0CA56D645CA6C5EAE31FFE0C556ACF31DDE6167D | ||||||
|  | AE86EB56FF82199331F537BD7FF0CE23422EB046DA9C1D0B2A7C813A4D4A9581 | ||||||
|  | D5DDF54FF56E597AD788239811C57FB4DCCDDEB317F6BC9559040825072E3FD7 | ||||||
|  | 35EFA98E7357B81EB5C7F56DD7B2D1A483218BCE2907EED0CE4425C99288A058 | ||||||
|  | 0410EC96551233A745EAC2FA1BE834FEADCB68B9845F9E0512DFFEE6FE353DCB | ||||||
|  | 7E39E6D875FFB17AC2C5F74A3F44DFB5063E5510712B63E8BA7E083292F3DB7B | ||||||
|  | C83A67EC31B70AE70CBAC65E07EB69BF311889F5FD246B0D1588CE1A28AE5050 | ||||||
|  | C6FCE1BAF6D3CA19DEACD9987A1C01D9D519B65291F626AB44E1E269E9056BE8 | ||||||
|  | 1CDDAAFCE3C5A993B3C3652690429C942A318C973C691039AB876ADE2074BD9D | ||||||
|  | A241551F6F3043409C30923BF84CAED8713D817B6F41B2AC9C0119C66D30DA41 | ||||||
|  | 980C89F97CDB118F001B761D653C2E11A794E7ADB7F16008FC05F0A56035BF1C | ||||||
|  | 884FE309C42B674A2470163D701AF14C3D30ADF08666C760F9F3C34F1680441A | ||||||
|  | FB1FB9F2BA799C8DD5DAFFB1AC15DC46FAF478D46FDF9E12E7088DC77A422BF9 | ||||||
|  | DA01C3CDB758913DE16155BFDD65C65409810EC8E9867CEC02BCFD72E2B950D1 | ||||||
|  | 7534A560B93845A636858A8B28ED85A3ABB2AC4C41A5CD3165F25D24F24F3939 | ||||||
|  | 2DF741FA05AD1B9A37BD8C4FDD2BEB700EF725453E18B7759C4794A5B7EDE8EB | ||||||
|  | 43929E8F10B77E268830C7177D74BFDB66EF6B9905FB29431C84497CBD65F6D1 | ||||||
|  | 02E44D1195FBD103955697C717DD56FA528F1CF5070A8F8E18762DCCEDC3A962 | ||||||
|  | 8E87CDBD5F3C32DAFF141E319067AD16C9E21BA40D2415A170D18F52E5A62D22 | ||||||
|  | D486356DF83EBCF1F1640E92691E5AE4CCE3E152C220AE442DC0A775F6947AD6 | ||||||
|  | 1077A1B9328DB998042D2ADF38AD0106ADF46A77F32355754E452FBC0A469098 | ||||||
|  | 7B74AA4B2FAB2DC0EAD74D69C704AD38EEE36CC2D8AB2502EE343DA30196553F | ||||||
|  | 6740BA2FFFD10FDE150A5201C6CF7E1D9769F14F97B98862262D2635218CEF29 | ||||||
|  | 885DD977C1E12CCE8D6AD357B92FC6F63F83F05F5B86F394B6399966E61893CF | ||||||
|  | 64F67ED26DACF20A9E4A7A9EFA72FE7240A380E541B4002D73CF00B0ADC7B19A | ||||||
|  | DFEDE2DD576074FED8F73B02AE0210B0AA879A87F6D932271E8813DDC76AC77D | ||||||
|  | CE1AF48A5FFED24CC740C6F64E91C3685D728EC69C7F0688405AD4E99E634AED | ||||||
|  | CD63A5B50A65986A911CA3B3E1B7F9C771B01196ADAAD7C8EC6260210BC29B4E | ||||||
|  | 58EE98F41F78055175035D5CDDD21BED4053590625104B36413BAF3ADDD8229A | ||||||
|  | 959B154EF0AACC4F774C19638B44B66371DFE6EF1DF052E496A661DA59FE05FD | ||||||
|  | E335E0998DCF0E837E063681CFCDE4F8DDBF27AA6A8A35747CBF9C228DBAB702 | ||||||
|  | C49EEDB1E6C01D25EB8BAD188F037F19359E446D3A8F48B1C7E23E436DF1AE45 | ||||||
|  | DCC19EEE6456B084EA5BCA8F8A4AD9C47172B99BCC6169061AF41279B404238E | ||||||
|  | A8C973DC0B2F166735BEEC99A3ED20F85880B00510A45421C0F1D717BBF9A156 | ||||||
|  | 9B4D7E9E4DB69842677E2B6A9F213AA57F185B20DAB654EC67FF271E9487ED60 | ||||||
|  | 5DC7950E2C5BE03B8258B71CEC2058BF56828EFB9C4225B1EADD2FFDF0664386 | ||||||
|  | F2D860D71D3E42E7F72955A0CE11D61F2C90CE472CFD1D31ECAC2C8A509B50FE | ||||||
|  | ED2C41030278699235A3AC77C0B6319802ACC027CD8309856165AD00F0DAE4D9 | ||||||
|  | 1BF2E2829A3BFECE4ECF1CCC72CE6AAE2B56B452518BF3C9B17C8F8256AE928A | ||||||
|  | B969D1A53D4BD1A8F69155289C00C125AEE6C9E2F90AB25303ADD505802398C3 | ||||||
|  | ECACAEF175C463BE8453B2A066066E04889F7F0DFEC946395B978D6D4952AA2E | ||||||
|  | 8ADA7555CF7C4CE737C9BA757551AAEDD627384602855A0F1D821DE5842ADE21 | ||||||
|  | 3D1B18573858D2D0A8CB9B49DA0233D2842EB9F112BC770EE2F5A42F5EFD7590 | ||||||
|  | C3DAAB1F580B1362D2EC15A2BDEEAA4C896DD70BACDF0493ACB2FC8989EF0D2D | ||||||
|  | 23105727BC6574EE976182161CF1771D74593A7996C46073DD67FD33C9EC2CD7 | ||||||
|  | 260D8C270A2E1D2E7B2D27E95A67F8B055FB949EE0BA3F6633F6315F9452CB7B | ||||||
|  | 01EF784BD2C68C6F614DDEA3CA071E9198371B9E447CEFCA13FCF1D55FBCB43F | ||||||
|  | 137A61AA31C309B62554466772540A3E2D8AC39D355802FEB0B4774A4BAE1CFC | ||||||
|  | D0D1424ACC1DD84BB0F465527C5695BF51C5927A0D4B4E0C5618E4B6BD122997 | ||||||
|  | A855D26D665DC9F0330E18126D4DA2B8E9E3E19B759B8156E4754C4E857DBB64 | ||||||
|  | A724138E61049B6D8AB6E7184D1295FB9A69BF07B532DD0B3FDC023AB9A5FC82 | ||||||
|  | E2847126E66A64F7EA28127387748645E177076F10484C4CA45DE5B3EA7E9D6F | ||||||
|  | D76858E8B9BF7F2C0174FD09DF321E94679B48479CD0D587F54E3679553B619B | ||||||
|  | 36800839D131F70EE2068F96BB02643C7F426BEFAAF5856257972D8851D6E29C | ||||||
|  | 8B624C420FD61C8BC1E52A5CFAD5266E2D18C4FD5FF43DBF78C7A8226DEF6639 | ||||||
|  | AABC2B1A9B712DB66927C905BDEF2BA2ADCEEFE724AAF1632F31E39472676714 | ||||||
|  | 95218D5732BA5EBF6DEBAD1E6FA555E29984A7BE46E330BC20C37E70488C0444 | ||||||
|  | 3773E0A7C8D3414CC82B5AAE824CF8642D2EF7B4E43D3E83121B16965A64B258 | ||||||
|  | C42B0AB5D4BAB1492075DF0DE7F1FB50B456B051C8F6828CB065231BA26D7553 | ||||||
|  | 19556D3678712A5A4410B6BF8DBAC5FBAE150EA913C88D2B665F5E9368F624EC | ||||||
|  | DB36DBB87E90F7E634D75C7F1D805D0174682EF9735947C093AD71B1DD1D4CD8 | ||||||
|  | E2E65BC8940DD65A3667E6C97281288529DFE74FCFA2A81ECC380CA4B0205A9D | ||||||
|  | 3124EC9C34FC420B6CF558EFC6F26BD50F68C7BA05A955B70392A2B70FB4D846 | ||||||
|  | 84F1491142661D310717A0BD502A4C4F80E6899B1C87FDC299F7B36461C4ABBB | ||||||
|  | E8F2ABEAD6634B4F25394945E5A872B88A3290F2AF608098FAD12813F957F08D | ||||||
|  | 11DD782EF77044201D868480D4E214DB4F3444B287CDF220794248813D3976D8 | ||||||
|  | 186C13A3ECBEF66EF22C274C5BF70C69E983344ECB87CCE81D70BD8377E3F9FC | ||||||
|  | 5794C3EFDF643B966DEC9D4BD7346A21B50151E5D6F93C6128F254619D3E0E3E | ||||||
|  | E826D3CC27F4B6871D9F673C8BEE923C65C402C9796DC5DD97421A8DF41714F5 | ||||||
|  | 5D8FABA6A841153495CBC26BC1E1028E79A80968B21D3D9C8741C52326C6D984 | ||||||
|  | 522A8066B98D192BC0B382E63FA78BFA13E269017FD9D45654C4CC5C2CBC44DA | ||||||
|  | 4016C5AA79A9BC220B75DB3A567E96BE42187F16DA68978FB72372162A26B75F | ||||||
|  | 3E06036DE65F7B1939330F814D421C65CF554D96F51EEA6E234A9D6134FDAEBE | ||||||
|  | 9F1D109F1F2EA1B61165B37CF06DDB639DC5399910C32AEF018F13B2A2588AC4 | ||||||
|  | 9E03C05A4755ACEDD423F519C0A5BDE768A5E31A1D838E4291644DBCA13A5EAC | ||||||
|  | BAC85AD6C0AC38B1A2310B400B01C4123B2CFDC538970EFBFB7FA163E782A511 | ||||||
|  | 302582B243190740D35720296CC39677D8BD01D3CC64FF973AFD6E1F263B10D6 | ||||||
|  | 156F82DEFA0F67028A1F7991AF6B60E687906AFEA924DBC7101B39FC9A552D3A | ||||||
|  | 3404FB2E9E26EA75FC0528448E5B485DC778C251E9A3CE184F9D40F14EC6A9C3 | ||||||
|  | 8276A6D8AEAF0E03390D8E3CD9D7354278C6160F962676F34CB8B6CE28078885 | ||||||
|  | D8B1EEF27BBDF1969FAF22867AA6C279731EDF53EF04FF3B98F43694B4592343 | ||||||
|  | F2222B0270158E747AEC5EAA6B089A65226215493BE87FB91A3EAFC90A372687 | ||||||
|  | 1AB91DD2BE17F42854A07C9F38E695AA1E25522BFAEFE14F29F290AE2C71D922 | ||||||
|  | 1E1508CBCE833DB8C6646AC9AAF1887B810AB665D7F977EB9E58E93D019876F9 | ||||||
|  | 86244E8C0ED7F76958253EFB2CAB0DCCD29CB9938A782AFC750B2DBFA30A6E86 | ||||||
|  | 8F03E504FD67759F56654362A03D30EBA832906C707DE366D2805597B8AEB714 | ||||||
|  | C34E85BB66E31BCE7D67C01D798B6A7677DDE29E90C6C6C804D62BBBDB528AED | ||||||
|  | 75C3DFB504201558CFFE18747DE040C107352B1B948BDBE078B3F1424391BE12 | ||||||
|  | 28AE60B66E1DC10672C19F3BEBB3F1E8577572FD369C4222ABF86AFCD1FCD872 | ||||||
|  | BE7E570DDB7FBC182318B9E75E1A9E46608A8EE7F7A0F7F582447C0A069300D3 | ||||||
|  | 9585AC78D3A0A7F0D40F9627C036050CF4BDA47434C0A2859F39414B633A8440 | ||||||
|  | 9C26270AA00F380CEE6F3A0106AF660632A6958CBB74542EC180A1FFC6C446AB | ||||||
|  | 5C7E8D9DB28D6F75F018C1D97D8C5CC4001E6EAA9047B93FE68AC80627CBBEF9 | ||||||
|  | 5514AC7A222CF0E307D0B6005A925B48BDE8DEA13855927DA5283D50CA891E01 | ||||||
|  | CD7F74788986AE6B3A49BE66C9BCB944DDE8673803C4BDE9616B711BF2B3E026 | ||||||
|  | ED04B459CE1BA6ED357A4CF10415D1AC1894048018390349F046B4CBD8E5EEC2 | ||||||
|  | 360C271A88E83F0CBE5BED38165D4E2843042DAB6A432FC24D284B15D2DAF2E9 | ||||||
|  | FF75CB77B9D843B404427717DF7FEFEB334093543CB484C5D45CE3A948D7E566 | ||||||
|  | CB06B4D92F347F51F10F546C189E701947C36BA28E29DB610F2F412714563BC2 | ||||||
|  | E3053DF9589F15FEDD58194699A3D2E8770FAED7421DFE95C9EE190D96A56F0E | ||||||
|  | 08FBBAFFFAAD0161987AEEBED582AC906D969CE4DA8A56700DD9CDA8904222A9 | ||||||
|  | 4BBD08F49F4A595F4CE5B624E0392F76D5B581872399799B424D7030B28949E4 | ||||||
|  | 583702FFC046B709D75FB8BA08BDA5FBE20173310B85D5A211B89F1CDAFC215F | ||||||
|  | A1661573042C07AEF4D22D69F7D06C86870B9ABF412B1E8158D955CD7DE6DAC6 | ||||||
|  | 2602A0A40189C956B8031B7160175662EEF54988778743578BBF458E044E0A89 | ||||||
|  | 1D4449BC3803A85DBA19F3C15941299E19DCA38F79FDEB225CA05E7C4C3D271A | ||||||
|  | 0339877572DEE3392179798AB95C1F49B8078476CA03E0D060C021B17C23E7C1 | ||||||
|  | 63316028E9F85B0ADECEA6CAA05131FA252A2ED16816D8FA084B30167F29CF66 | ||||||
|  | 763A74DC68F8CE7CFE6A6CA58A88A3991FCB6BE92142196D9B045EC2EE146A4D | ||||||
|  | F7692816D9577DCFBC3180454D3538C670EE69A1FB9B40058A259A1CADAD4C69 | ||||||
|  | 3D0BC36BE57CF8D227E5D0451170B612878701140AB1A3FC0A1F3568F0EFE9B8 | ||||||
|  | 0A62EB499FC0926B90E59358BF0E3136E7D1CAEE53306FE9354F70A48E4A9D18 | ||||||
|  | DA814249505412CBBD8C3E318E6A62F03ED89C505B911089DADD57E5F6A0F379 | ||||||
|  | CBE56810D848B879FD7FB26FED0E67F6C3D989C5F0A562CD83442B16B69CE534 | ||||||
|  | 942F500D0A7DBE1DAA3FE8EE8C1291485948A1AA6E091F379F6F5E2AF5F9C73F | ||||||
|  | EACE2ACABA9DA57A3811BE7C177E2FA931B3B83EC95CA64E7238D16FBEFEAD2C | ||||||
|  | A0D63EAB75E08F2B49A451F128B25425D37C3338B862190B6566A49418CAA785 | ||||||
|  | 7FE6880200405E447F6C0F6A01C3074A66D2B47E185BBB0D5E29AEF072A01DD7 | ||||||
|  | 63A777F286A66A094AF1FFBC7EAA8161D37BCF49EF55F880C72C6906D8CD4F8B | ||||||
|  | 52703BA0637F01DFD4AF315BFA23CD41E52A155C35B9739BB57777DBC69CA455 | ||||||
|  | 3439F58AB810EC86F133A1206BD8BE84138CA2E70E4F96D8D24FC052B8EDB702 | ||||||
|  | D403A5A137735635F68254E6FEAD77B4F20A2756FD42E1F42A0583FD3D10C2B6 | ||||||
|  | 55D45AA25091B4638EF39AE9F3239DB441F17F9E138410C3C138E005ECEF49BF | ||||||
|  | 05C0589687E28E7D6614245F43B1B1E92421331C51D58B70C8778581041CE512 | ||||||
|  | 68D2C4D636160A0804902E166AD991D90987956D33EE3A8382F882E5A04087E4 | ||||||
|  | 2720A34E50C1D90C829BCC5E666E79B8C9EB3CCDBE1C234EB345533A3A53F910 | ||||||
|  | F064F519DB53109C4E086490462B587133B69A9FA417ADAD3ED1C97D85567838 | ||||||
|  | 7882B15818EAA42ACC3342C79841EF358524E49BA64EBB00AB574219BD369C77 | ||||||
|  | 0D819F1BCD04911D681633347D817A7E83887C3C037CE83330E9D3A2A97587BC | ||||||
|  | FD1048C43DF4F8EBF2E2D03A76C4AA37A74FCD64235AEAA861E5187041FC758B | ||||||
|  | F62D4A41A9BBA2653292A9F9252C34D408F6DCF7C31E0556C36F59119C77B685 | ||||||
|  | F83EE4DD3E93171DFB178BAA7D05ECEC54A65BA1DE7AA0B08D03BF59F9677568 | ||||||
|  | 4AE3EC337D3D5900D86998462C1AF19F056D16EDCDC135AF75F34E49B81AE48D | ||||||
|  | 24C1A8DC4730288BE4C3CFB2A7E71022B71AE5DD68A1B6E1CC36534183F9E797 | ||||||
|  | A9EBDBB7301E090C9C2629F8D854398C90E8052F482503851AACDACFF6F0070B | ||||||
|  | 4F5A864D898A77E02A8F181077751016D811B837DA3F33A2067EAE72A41EDD75 | ||||||
|  | A2D4B8D51FA8E1148A053C39005B0B8A9F0C5702A64750AC64BF353C4338F6E1 | ||||||
|  | C659ED65157E6FFBE4B956DFB95FBAEF1745F0314A9729179E92B3F1162B9495 | ||||||
|  | BC17D9D85193BDCA5FA50ABA581221BE6F5E8AAFAB2D90646AF6ABC501E60662 | ||||||
|  | E517B72076E211C90114FB9127B6CA57DE995355916602F3A50A0B61E6CACDA5 | ||||||
|  | 1C0E79317116FB017B19A47018B2F8EF078A8F6A51E49929E08D27E2ED31D3AB | ||||||
|  | E0502C15BF9D459326841DAB7617B58F482FA502CA5FB719D06CEBFC73FB5495 | ||||||
|  | 016187A2D8AA8BBB15DC34E3920930D96B372607D842624405EEAFC5A641FA5F | ||||||
|  | FA34C64218ED6CFB15307044B1C38123C939EB12A239E0C2C198D47B8799B99A | ||||||
|  | 5AC59ADA228C1E069CF9D106D3171465B150BBC004D138D451517473FB2E946F | ||||||
|  | C47F6CD3C8E4C373C43E448F3EC791956DEE7F06EDC3EAABFD96681DBF7CC160 | ||||||
|  | 82EB8353D5F481D0E3F3C1BE42EB6F6F80A452412C0C3C9FD951A1942322E8E3 | ||||||
|  | DF8CC0F85A18BEEFC613237F7D112DF23F2214E091F6C100A47093541F6A1920 | ||||||
|  | 0DCBC7478CD07868E1C10AD3626AC324230F328E4ED59C0F4CE98758C407C24B | ||||||
|  | AB1D1526799185CE4168A2BB0E98F4CEE8843EC95ADAFE4E00A369461317183D | ||||||
|  | 47FE38F4C59F6BD043D89A6A799864971A65370CB5AC7282D7169EBF31074753 | ||||||
|  | CB253FB6096DB3209054C21322A28E742B616BBA97B972043E4FF210A938B994 | ||||||
|  | 4FE2CDCB89E9DB6A98A6A7CA7374616B54517FE6C62867662727715A8D0995C0 | ||||||
|  | 45074540C5C990A33E7C3B7ECDD685829FF5ACAE75972F9F2E04CA1C2AB2D86F | ||||||
|  | 4D1A95CE69460FBBAF8F3ECF7C211F918D7AF8F99506E96D95C9091BEB9C0519 | ||||||
|  | 8D8501E5088AC8709AAEE23C83D6E9BADE67F8504A6BDE957AC244E2CF650041 | ||||||
|  | 3DE31455D33AD144D10914036D272A91D6D2EFE52BF413A5C3B9BFA171AECC64 | ||||||
|  | 2B02071E56B85BA4D231C18B9BCCD660B7C51ABAE0CECC4DC52A565360E1A42B | ||||||
|  | DF515620894AE9456652FF296426255EF9929D011990CF2839B41F450D063597 | ||||||
|  | 015075989DE322CB41085D8DD967C1D1589B478F6A45426636E792940317A384 | ||||||
|  | 29E64270826B9B1573F685493E91DD87A3AD9BF2D10D4E895022EBF7A4760C73 | ||||||
|  | F11566B2E6F30ED9B78E3B344668ACE41659796578FACE69C79B16E3D6494C31 | ||||||
|  | 130C0F515C26A04B6FAACE34268AB974F20DD4EF15054C0A15E34013CBBAF9CF | ||||||
|  | 2B11A8D043F717A2BD6A5F56715BA3C571FED25161591749334F32DA236E5856 | ||||||
|  | F03B8C9B647A4104BDEB577AAB033781CA2A8EACA243163D5A050BF874396559 | ||||||
|  | 334AB0839A8680289F1F297273467613CFCD834446DA52D7A2BA146EFDA4CD8E | ||||||
|  | C05E250AF0D5E82E417DD8394B8062DBBBC3C07E477A847F311D0CAC912EF9BB | ||||||
|  | 2345D436F59B669297DE8E80BD27FEA98A1DCE61AD4EEF729CDFAC5345EAB8A7 | ||||||
|  | D7DA143A0C5934D50F09EFF485F70D3C71C5BD5B5B57C4DC7F3414069432F24C | ||||||
|  | 1DF4BABBE29ADF834701C36A850F2EFA8DF92D3E28003F7760A87AB9D8BD91EB | ||||||
|  | 71E183330B18FBCF8ED091F2488D3D29B98258C89B6019DCE7C79F8CF5BDCA92 | ||||||
|  | EEBB58DE2561795984E933CBD2B4C4BD8EAFEF97C91539917370F7E9A2240265 | ||||||
|  | D62E7BF1A7C56653AAC132838C360B2D0DFC5BC800C726159FABD1263B7F19EC | ||||||
|  | 12104E12AE577D5437023F945C476FD1654FF9826244F3692C8C186A79566106 | ||||||
|  | 3805C3704EE0C994FCEAF24CCD9A45CDDF6F2DF60F63D6665742E74880804E1F | ||||||
|  | CCF7B9B5D0C6CFEBE487938ACFAE89884A6CAD16A51515EBA9FF272DC9A57DEC | ||||||
|  | FD4403D41887E6CAE505C2AD9631AD3779F95BF70137B61E9901B3B7058C7DB1 | ||||||
|  | EE31F0FC516D508AF085BB6F1CB0FDF73CC0BBD7F5EA9891E0D87D7832E4AB1F | ||||||
|  | A1C5A8391F4132A560CA4693DCF8104CB7F5888F33C7D6586729FD65F57D5158 | ||||||
|  | F92194BD8136F05EA48843C514F9465A9D0D7925A364D40B4853C666F726CEE5 | ||||||
|  | 3DE0E5D07EC75D4FC5B51AF56A371643F206B213263503B9DBE0D3EEE71D8B37 | ||||||
|  | E904F9A524C9541AC4CF7195AA3A8D8265BE1B93890D8549F2C9ACE4731733A9 | ||||||
|  | 4D1B906082ED3E8A59368BACFACEC1886EC52451EC8FF4C444F26DD668C101B9 | ||||||
|  | 840686B283654FADB08AF6F9E439359B6D41ACFC068845195769033D6618A823 | ||||||
|  | 8AF622CB10FFD2C85F113EF81F1FF542DD4435BA8ED93CEEBEC1E3A16AE0CE88 | ||||||
| @ -387,6 +387,7 @@ void vPortFree(void* pv) { | |||||||
|                     /* Add this block to the list of free blocks. */ |                     /* Add this block to the list of free blocks. */ | ||||||
|                     xFreeBytesRemaining += pxLink->xBlockSize; |                     xFreeBytesRemaining += pxLink->xBlockSize; | ||||||
|                     traceFREE(pv, pxLink->xBlockSize); |                     traceFREE(pv, pxLink->xBlockSize); | ||||||
|  |                     memset(pv, 0, pxLink->xBlockSize - xHeapStructSize); | ||||||
|                     prvInsertBlockIntoFreeList(((BlockLink_t*)pxLink)); |                     prvInsertBlockIntoFreeList(((BlockLink_t*)pxLink)); | ||||||
|                 } |                 } | ||||||
|                 (void)xTaskResumeAll(); |                 (void)xTaskResumeAll(); | ||||||
|  | |||||||
| @ -22,6 +22,7 @@ import math | |||||||
| import sys | import sys | ||||||
| import struct | import struct | ||||||
| import pkg_resources | import pkg_resources | ||||||
|  | import fnmatch | ||||||
| 
 | 
 | ||||||
| from .svd import SVDFile | from .svd import SVDFile | ||||||
| 
 | 
 | ||||||
| @ -101,13 +102,6 @@ class LoadSVD(gdb.Command): | |||||||
|             raise gdb.GdbError("Could not load SVD file {} : {}...\n".format(f, e)) |             raise gdb.GdbError("Could not load SVD file {} : {}...\n".format(f, e)) | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| if __name__ == "__main__": |  | ||||||
|     # This will also get executed by GDB |  | ||||||
| 
 |  | ||||||
|     # Create just the svd_load command |  | ||||||
|     LoadSVD() |  | ||||||
| 
 |  | ||||||
| 
 |  | ||||||
| class SVD(gdb.Command): | class SVD(gdb.Command): | ||||||
|     """The CMSIS SVD (System View Description) inspector command |     """The CMSIS SVD (System View Description) inspector command | ||||||
| 
 | 
 | ||||||
| @ -321,13 +315,19 @@ class SVD(gdb.Command): | |||||||
|                 container = peripheral.name + " > " + register.name |                 container = peripheral.name + " > " + register.name | ||||||
| 
 | 
 | ||||||
|                 self._print_register_fields(container, form, register) |                 self._print_register_fields(container, form, register) | ||||||
| 
 |  | ||||||
|             else: |             else: | ||||||
|                 gdb.write( |                 found = False | ||||||
|                     "Register/cluster {} in peripheral {} does not exist!\n".format( |                 for key in fnmatch.filter(peripheral.registers.keys(), s[1]): | ||||||
|                         s[1], peripheral.name |                     register = peripheral.registers[key] | ||||||
|  |                     container = peripheral.name + " > " + register.name | ||||||
|  |                     self._print_register_fields(container, form, register) | ||||||
|  |                     found = True | ||||||
|  |                 if not found: | ||||||
|  |                     gdb.write( | ||||||
|  |                         "Register/cluster {} in peripheral {} does not exist!\n".format( | ||||||
|  |                             s[1], peripheral.name | ||||||
|  |                         ) | ||||||
|                     ) |                     ) | ||||||
|                 ) |  | ||||||
|             return |             return | ||||||
| 
 | 
 | ||||||
|         if len(s) == 3: |         if len(s) == 3: | ||||||
|  | |||||||
							
								
								
									
										37019
									
								
								debug/STM32WB55_CM4.svd
									
									
									
									
									
								
							
							
						
						
									
										37019
									
								
								debug/STM32WB55_CM4.svd
									
									
									
									
									
								
							
										
											
												File diff suppressed because one or more lines are too long
											
										
									
								
							| @ -15,21 +15,21 @@ bool furi_hal_crypto_store_add_key(FuriHalCryptoKey* key, uint8_t* slot) { | |||||||
|     SHCI_C2_FUS_StoreUsrKey_Cmd_Param_t pParam; |     SHCI_C2_FUS_StoreUsrKey_Cmd_Param_t pParam; | ||||||
|     size_t key_data_size = 0; |     size_t key_data_size = 0; | ||||||
| 
 | 
 | ||||||
|     if (key->type == FuriHalCryptoKeyTypeMaster) { |     if(key->type == FuriHalCryptoKeyTypeMaster) { | ||||||
|         pParam.KeyType = KEYTYPE_MASTER; |         pParam.KeyType = KEYTYPE_MASTER; | ||||||
|     } else if (key->type == FuriHalCryptoKeyTypeSimple) { |     } else if(key->type == FuriHalCryptoKeyTypeSimple) { | ||||||
|         pParam.KeyType = KEYTYPE_SIMPLE; |         pParam.KeyType = KEYTYPE_SIMPLE; | ||||||
|     } else if (key->type == FuriHalCryptoKeyTypeEncrypted) { |     } else if(key->type == FuriHalCryptoKeyTypeEncrypted) { | ||||||
|         pParam.KeyType = KEYTYPE_ENCRYPTED; |         pParam.KeyType = KEYTYPE_ENCRYPTED; | ||||||
|         key_data_size += 12; |         key_data_size += 12; | ||||||
|     } else { |     } else { | ||||||
|         furi_crash("Incorrect key type"); |         furi_crash("Incorrect key type"); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     if (key->size == FuriHalCryptoKeySize128) { |     if(key->size == FuriHalCryptoKeySize128) { | ||||||
|         pParam.KeySize = KEYSIZE_16; |         pParam.KeySize = KEYSIZE_16; | ||||||
|         key_data_size += 16; |         key_data_size += 16; | ||||||
|     } else if (key->size == FuriHalCryptoKeySize256) { |     } else if(key->size == FuriHalCryptoKeySize256) { | ||||||
|         pParam.KeySize = KEYSIZE_32; |         pParam.KeySize = KEYSIZE_32; | ||||||
|         key_data_size += 32; |         key_data_size += 32; | ||||||
|     } else { |     } else { | ||||||
| @ -49,11 +49,12 @@ bool furi_hal_crypto_store_load_key(uint8_t slot, const uint8_t* iv) { | |||||||
|     crypt.Init.KeySize = CRYP_KEYSIZE_256B; |     crypt.Init.KeySize = CRYP_KEYSIZE_256B; | ||||||
|     crypt.Init.Algorithm = CRYP_AES_CBC; |     crypt.Init.Algorithm = CRYP_AES_CBC; | ||||||
|     crypt.Init.pInitVect = (uint32_t*)iv; |     crypt.Init.pInitVect = (uint32_t*)iv; | ||||||
|  |     crypt.Init.KeyIVConfigSkip = CRYP_KEYIVCONFIG_ONCE; | ||||||
|     crypt.Init.pKey = NULL; |     crypt.Init.pKey = NULL; | ||||||
| 
 | 
 | ||||||
|     furi_check(HAL_CRYP_Init(&crypt) == HAL_OK); |     furi_check(HAL_CRYP_Init(&crypt) == HAL_OK); | ||||||
| 
 | 
 | ||||||
|     if (SHCI_C2_FUS_LoadUsrKey(slot) == SHCI_Success) { |     if(SHCI_C2_FUS_LoadUsrKey(slot) == SHCI_Success) { | ||||||
|         return true; |         return true; | ||||||
|     } else { |     } else { | ||||||
|         furi_check(HAL_CRYP_DeInit(&crypt) == HAL_OK); |         furi_check(HAL_CRYP_DeInit(&crypt) == HAL_OK); | ||||||
| @ -66,10 +67,10 @@ bool furi_hal_crypto_store_unload_key(uint8_t slot) { | |||||||
|     return SHCI_C2_FUS_UnloadUsrKey(slot) == SHCI_Success; |     return SHCI_C2_FUS_UnloadUsrKey(slot) == SHCI_Success; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| bool furi_hal_crypto_encrypt(const uint8_t *input, uint8_t *output, size_t size) { | bool furi_hal_crypto_encrypt(const uint8_t* input, uint8_t* output, size_t size) { | ||||||
|     return HAL_CRYP_Encrypt(&crypt, (uint32_t*)input, size/4, (uint32_t*)output, 1000) == HAL_OK; |     return HAL_CRYP_Encrypt(&crypt, (uint32_t*)input, size / 4, (uint32_t*)output, 1000) == HAL_OK; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| bool furi_hal_crypto_decrypt(const uint8_t *input, uint8_t *output, size_t size) { | bool furi_hal_crypto_decrypt(const uint8_t* input, uint8_t* output, size_t size) { | ||||||
|     return HAL_CRYP_Decrypt(&crypt, (uint32_t*)input, size/4, (uint32_t*)output, 1000) == HAL_OK; |     return HAL_CRYP_Decrypt(&crypt, (uint32_t*)input, size / 4, (uint32_t*)output, 1000) == HAL_OK; | ||||||
| } | } | ||||||
|  | |||||||
| @ -15,21 +15,21 @@ bool furi_hal_crypto_store_add_key(FuriHalCryptoKey* key, uint8_t* slot) { | |||||||
|     SHCI_C2_FUS_StoreUsrKey_Cmd_Param_t pParam; |     SHCI_C2_FUS_StoreUsrKey_Cmd_Param_t pParam; | ||||||
|     size_t key_data_size = 0; |     size_t key_data_size = 0; | ||||||
| 
 | 
 | ||||||
|     if (key->type == FuriHalCryptoKeyTypeMaster) { |     if(key->type == FuriHalCryptoKeyTypeMaster) { | ||||||
|         pParam.KeyType = KEYTYPE_MASTER; |         pParam.KeyType = KEYTYPE_MASTER; | ||||||
|     } else if (key->type == FuriHalCryptoKeyTypeSimple) { |     } else if(key->type == FuriHalCryptoKeyTypeSimple) { | ||||||
|         pParam.KeyType = KEYTYPE_SIMPLE; |         pParam.KeyType = KEYTYPE_SIMPLE; | ||||||
|     } else if (key->type == FuriHalCryptoKeyTypeEncrypted) { |     } else if(key->type == FuriHalCryptoKeyTypeEncrypted) { | ||||||
|         pParam.KeyType = KEYTYPE_ENCRYPTED; |         pParam.KeyType = KEYTYPE_ENCRYPTED; | ||||||
|         key_data_size += 12; |         key_data_size += 12; | ||||||
|     } else { |     } else { | ||||||
|         furi_crash("Incorrect key type"); |         furi_crash("Incorrect key type"); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     if (key->size == FuriHalCryptoKeySize128) { |     if(key->size == FuriHalCryptoKeySize128) { | ||||||
|         pParam.KeySize = KEYSIZE_16; |         pParam.KeySize = KEYSIZE_16; | ||||||
|         key_data_size += 16; |         key_data_size += 16; | ||||||
|     } else if (key->size == FuriHalCryptoKeySize256) { |     } else if(key->size == FuriHalCryptoKeySize256) { | ||||||
|         pParam.KeySize = KEYSIZE_32; |         pParam.KeySize = KEYSIZE_32; | ||||||
|         key_data_size += 32; |         key_data_size += 32; | ||||||
|     } else { |     } else { | ||||||
| @ -49,11 +49,12 @@ bool furi_hal_crypto_store_load_key(uint8_t slot, const uint8_t* iv) { | |||||||
|     crypt.Init.KeySize = CRYP_KEYSIZE_256B; |     crypt.Init.KeySize = CRYP_KEYSIZE_256B; | ||||||
|     crypt.Init.Algorithm = CRYP_AES_CBC; |     crypt.Init.Algorithm = CRYP_AES_CBC; | ||||||
|     crypt.Init.pInitVect = (uint32_t*)iv; |     crypt.Init.pInitVect = (uint32_t*)iv; | ||||||
|  |     crypt.Init.KeyIVConfigSkip = CRYP_KEYIVCONFIG_ONCE; | ||||||
|     crypt.Init.pKey = NULL; |     crypt.Init.pKey = NULL; | ||||||
| 
 | 
 | ||||||
|     furi_check(HAL_CRYP_Init(&crypt) == HAL_OK); |     furi_check(HAL_CRYP_Init(&crypt) == HAL_OK); | ||||||
| 
 | 
 | ||||||
|     if (SHCI_C2_FUS_LoadUsrKey(slot) == SHCI_Success) { |     if(SHCI_C2_FUS_LoadUsrKey(slot) == SHCI_Success) { | ||||||
|         return true; |         return true; | ||||||
|     } else { |     } else { | ||||||
|         furi_check(HAL_CRYP_DeInit(&crypt) == HAL_OK); |         furi_check(HAL_CRYP_DeInit(&crypt) == HAL_OK); | ||||||
| @ -66,10 +67,10 @@ bool furi_hal_crypto_store_unload_key(uint8_t slot) { | |||||||
|     return SHCI_C2_FUS_UnloadUsrKey(slot) == SHCI_Success; |     return SHCI_C2_FUS_UnloadUsrKey(slot) == SHCI_Success; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| bool furi_hal_crypto_encrypt(const uint8_t *input, uint8_t *output, size_t size) { | bool furi_hal_crypto_encrypt(const uint8_t* input, uint8_t* output, size_t size) { | ||||||
|     return HAL_CRYP_Encrypt(&crypt, (uint32_t*)input, size/4, (uint32_t*)output, 1000) == HAL_OK; |     return HAL_CRYP_Encrypt(&crypt, (uint32_t*)input, size / 4, (uint32_t*)output, 1000) == HAL_OK; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| bool furi_hal_crypto_decrypt(const uint8_t *input, uint8_t *output, size_t size) { | bool furi_hal_crypto_decrypt(const uint8_t* input, uint8_t* output, size_t size) { | ||||||
|     return HAL_CRYP_Decrypt(&crypt, (uint32_t*)input, size/4, (uint32_t*)output, 1000) == HAL_OK; |     return HAL_CRYP_Decrypt(&crypt, (uint32_t*)input, size / 4, (uint32_t*)output, 1000) == HAL_OK; | ||||||
| } | } | ||||||
|  | |||||||
| @ -11,7 +11,7 @@ | |||||||
| /** FuriHalCryptoKey Type */ | /** FuriHalCryptoKey Type */ | ||||||
| typedef enum { | typedef enum { | ||||||
|     FuriHalCryptoKeyTypeMaster, /**< Master key */ |     FuriHalCryptoKeyTypeMaster, /**< Master key */ | ||||||
|     FuriHalCryptoKeyTypeSimple,  /**< Simple enencrypted key */ |     FuriHalCryptoKeyTypeSimple, /**< Simple enencrypted key */ | ||||||
|     FuriHalCryptoKeyTypeEncrypted, /**< Encrypted with Master key */ |     FuriHalCryptoKeyTypeEncrypted, /**< Encrypted with Master key */ | ||||||
| } FuriHalCryptoKeyType; | } FuriHalCryptoKeyType; | ||||||
| 
 | 
 | ||||||
| @ -59,7 +59,6 @@ bool furi_hal_crypto_store_load_key(uint8_t slot, const uint8_t* iv); | |||||||
|  */ |  */ | ||||||
| bool furi_hal_crypto_store_unload_key(uint8_t slot); | bool furi_hal_crypto_store_unload_key(uint8_t slot); | ||||||
| 
 | 
 | ||||||
| 
 |  | ||||||
| /** Encrypt data
 | /** Encrypt data
 | ||||||
|  * |  * | ||||||
|  * @param      input   pointer to input data |  * @param      input   pointer to input data | ||||||
| @ -68,7 +67,7 @@ bool furi_hal_crypto_store_unload_key(uint8_t slot); | |||||||
|  * |  * | ||||||
|  * @return     true on success |  * @return     true on success | ||||||
|  */ |  */ | ||||||
| bool furi_hal_crypto_encrypt(const uint8_t *input, uint8_t *output, size_t size); | bool furi_hal_crypto_encrypt(const uint8_t* input, uint8_t* output, size_t size); | ||||||
| 
 | 
 | ||||||
| /** Decrypt data
 | /** Decrypt data
 | ||||||
|  * |  * | ||||||
| @ -78,4 +77,4 @@ bool furi_hal_crypto_encrypt(const uint8_t *input, uint8_t *output, size_t size) | |||||||
|  * |  * | ||||||
|  * @return     true on success |  * @return     true on success | ||||||
|  */ |  */ | ||||||
| bool furi_hal_crypto_decrypt(const uint8_t *input, uint8_t *output, size_t size); | bool furi_hal_crypto_decrypt(const uint8_t* input, uint8_t* output, size_t size); | ||||||
|  | |||||||
| @ -1,10 +1,28 @@ | |||||||
| #include "subghz_keystore.h" | #include "subghz_keystore.h" | ||||||
| 
 | 
 | ||||||
| #include <furi.h> | #include <furi.h> | ||||||
|  | #include <furi-hal.h> | ||||||
|  | 
 | ||||||
| #include <storage/storage.h> | #include <storage/storage.h> | ||||||
|  | #include <lib/toolbox/hex.h> | ||||||
|  | #include <lib/toolbox/flipper-file.h> | ||||||
|  | 
 | ||||||
|  | #define SUBGHZ_KEYSTORE_TAG "SubGhzParser" | ||||||
| 
 | 
 | ||||||
| #define FILE_BUFFER_SIZE 64 | #define FILE_BUFFER_SIZE 64 | ||||||
| 
 | 
 | ||||||
|  | #define SUBGHZ_KEYSTORE_FILE_TYPE "Flipper SubGhz Keystore File" | ||||||
|  | #define SUBGHZ_KEYSTORE_FILE_VERSION 0 | ||||||
|  | 
 | ||||||
|  | #define SUBGHZ_KEYSTORE_FILE_ENCRYPTION_KEY_SLOT 1 | ||||||
|  | #define SUBGHZ_KEYSTORE_FILE_DECRYPTED_LINE_SIZE 512 | ||||||
|  | #define SUBGHZ_KEYSTORE_FILE_ENCRYPTED_LINE_SIZE (SUBGHZ_KEYSTORE_FILE_DECRYPTED_LINE_SIZE*2) | ||||||
|  | 
 | ||||||
|  | typedef enum { | ||||||
|  |     SubGhzKeystoreEncryptionNone, | ||||||
|  |     SubGhzKeystoreEncryptionAES256, | ||||||
|  | } SubGhzKeystoreEncryption; | ||||||
|  | 
 | ||||||
| struct SubGhzKeystore { | struct SubGhzKeystore { | ||||||
|     SubGhzKeyArray_t data; |     SubGhzKeyArray_t data; | ||||||
| }; | }; | ||||||
| @ -37,46 +55,260 @@ static void subghz_keystore_add_key(SubGhzKeystore* instance, const char* name, | |||||||
|     manufacture_code->type = type; |     manufacture_code->type = type; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| static void subghz_keystore_process_line(SubGhzKeystore* instance, string_t line) { | static bool subghz_keystore_process_line(SubGhzKeystore* instance, char* line) { | ||||||
|     uint64_t key = 0; |     uint64_t key = 0; | ||||||
|     uint16_t type = 0; |     uint16_t type = 0; | ||||||
|     char skey[17] = {0}; |     char skey[17] = {0}; | ||||||
|     char name[65] = {0}; |     char name[65] = {0}; | ||||||
|     int ret = sscanf(string_get_cstr(line), "%16s:%hu:%64s", skey, &type, name); |     int ret = sscanf(line, "%16s:%hu:%64s", skey, &type, name); | ||||||
|     key = strtoull(skey, NULL, 16); |     key = strtoull(skey, NULL, 16); | ||||||
|     if (ret == 3) { |     if (ret == 3) { | ||||||
|         subghz_keystore_add_key(instance, name, key, type); |         subghz_keystore_add_key(instance, name, key, type); | ||||||
|  |         return true; | ||||||
|     } else { |     } else { | ||||||
|         printf("Failed to load line: %s\r\n", string_get_cstr(line)); |         FURI_LOG_E(SUBGHZ_KEYSTORE_TAG, "Failed to load line: %s\r\n", line); | ||||||
|  |         return false; | ||||||
|     } |     } | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void subghz_keystore_load(SubGhzKeystore* instance, const char* file_name) { | static void subghz_keystore_mess_with_iv(uint8_t* iv) { | ||||||
|     File* manufacture_keys_file = storage_file_alloc(furi_record_open("storage")); |     // Please do not share decrypted manufacture keys
 | ||||||
|     string_t line; |     // Sharing them will bring some discomfort to legal owners
 | ||||||
|     string_init(line); |     // And potential legal action against you
 | ||||||
|     if(storage_file_open(manufacture_keys_file, file_name, FSAM_READ, FSOM_OPEN_EXISTING)) { |     // While you reading this code think about your own personal responsibility
 | ||||||
|         printf("Loading manufacture keys file %s\r\n", file_name); |     asm volatile( | ||||||
|         char buffer[FILE_BUFFER_SIZE]; |                 "movs   r0, #0x0    \n" | ||||||
|         uint16_t ret; |                 "movs   r1, #0x0    \n" | ||||||
|         do { |                 "movs   r2, #0x0    \n" | ||||||
|             ret = storage_file_read(manufacture_keys_file, buffer, FILE_BUFFER_SIZE); |                 "movs   r3, #0x0    \n" | ||||||
|             for (uint16_t i=0; i < ret; i++) { |                 "nani:              \n" | ||||||
|                 if (buffer[i] == '\n' && string_size(line) > 0) { |                 "ldrb   r1, [r0, %0]\n" | ||||||
|                     subghz_keystore_process_line(instance, line); |                 "mov    r2, r1      \n" | ||||||
|                     string_clean(line); |                 "add    r1, r3      \n" | ||||||
|  |                 "mov    r3, r2      \n" | ||||||
|  |                 "strb   r1, [r0, %0]\n" | ||||||
|  |                 "adds   r0, #0x1    \n" | ||||||
|  |                 "cmp    r0, #0xF    \n" | ||||||
|  |                 "bls    nani        \n" | ||||||
|  |                  :  | ||||||
|  |                  : "r"(iv) | ||||||
|  |                  : "r0", "r1", "r2", "r3", "memory"); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | static bool subghz_keystore_read_file(SubGhzKeystore* instance, File* file, uint8_t* iv) { | ||||||
|  |     bool result = true; | ||||||
|  |     char buffer[FILE_BUFFER_SIZE]; | ||||||
|  | 
 | ||||||
|  |     char* decrypted_line = furi_alloc(SUBGHZ_KEYSTORE_FILE_DECRYPTED_LINE_SIZE); | ||||||
|  |     char* encrypted_line = furi_alloc(SUBGHZ_KEYSTORE_FILE_ENCRYPTED_LINE_SIZE); | ||||||
|  |     size_t encrypted_line_cursor = 0; | ||||||
|  | 
 | ||||||
|  |     if (iv) furi_hal_crypto_store_load_key(SUBGHZ_KEYSTORE_FILE_ENCRYPTION_KEY_SLOT, iv); | ||||||
|  | 
 | ||||||
|  |     size_t ret = 0; | ||||||
|  |     do { | ||||||
|  |         ret = storage_file_read(file, buffer, FILE_BUFFER_SIZE); | ||||||
|  |         for (uint16_t i=0; i < ret; i++) { | ||||||
|  |             if (buffer[i] == '\n' && encrypted_line_cursor > 0) { | ||||||
|  |                 // Process line
 | ||||||
|  |                 if(iv) { | ||||||
|  |                     // Data alignment check, 32 instead of 16 because of hex encoding
 | ||||||
|  |                     size_t len = strlen(encrypted_line); | ||||||
|  |                     if (len % 32 == 0) { | ||||||
|  |                         // Inplace hex to bin conversion
 | ||||||
|  |                         for (size_t i=0; i<len; i+=2) { | ||||||
|  |                             uint8_t hi_nibble=0; | ||||||
|  |                             uint8_t lo_nibble=0; | ||||||
|  |                             hex_char_to_hex_nibble(encrypted_line[i], &hi_nibble); | ||||||
|  |                             hex_char_to_hex_nibble(encrypted_line[i+1], &lo_nibble); | ||||||
|  |                             encrypted_line[i/2] = (hi_nibble<<4) | lo_nibble; | ||||||
|  |                         } | ||||||
|  |                         len /= 2; | ||||||
|  | 
 | ||||||
|  |                         if(furi_hal_crypto_decrypt((uint8_t*)encrypted_line, (uint8_t*)decrypted_line, len)) { | ||||||
|  |                             subghz_keystore_process_line(instance, decrypted_line); | ||||||
|  |                         } else { | ||||||
|  |                             FURI_LOG_E(SUBGHZ_KEYSTORE_TAG, "Decryption failed"); | ||||||
|  |                             result = false; | ||||||
|  |                             break; | ||||||
|  |                         } | ||||||
|  |                     } else { | ||||||
|  |                         FURI_LOG_E(SUBGHZ_KEYSTORE_TAG, "Invalid encrypted data: %s", encrypted_line); | ||||||
|  |                     } | ||||||
|                 } else { |                 } else { | ||||||
|                     string_push_back(line, buffer[i]); |                     subghz_keystore_process_line(instance, encrypted_line); | ||||||
|  |                 } | ||||||
|  |                 // reset line buffer
 | ||||||
|  |                 memset(decrypted_line, 0, SUBGHZ_KEYSTORE_FILE_DECRYPTED_LINE_SIZE); | ||||||
|  |                 memset(encrypted_line, 0, SUBGHZ_KEYSTORE_FILE_ENCRYPTED_LINE_SIZE); | ||||||
|  |                 encrypted_line_cursor = 0; | ||||||
|  |             } else if (buffer[i] == '\r' || buffer[i] == '\n') { | ||||||
|  |                 // do not add line endings to the buffer
 | ||||||
|  |             } else { | ||||||
|  |                 if (encrypted_line_cursor < SUBGHZ_KEYSTORE_FILE_ENCRYPTED_LINE_SIZE) { | ||||||
|  |                     encrypted_line[encrypted_line_cursor] = buffer[i]; | ||||||
|  |                     encrypted_line_cursor++; | ||||||
|  |                 } else { | ||||||
|  |                     FURI_LOG_E(SUBGHZ_KEYSTORE_TAG, "Malformed file"); | ||||||
|  |                     result = false; | ||||||
|  |                     break; | ||||||
|                 } |                 } | ||||||
|             } |             } | ||||||
|         } while(ret > 0); |         } | ||||||
|     } else { |     } while(ret > 0 && result); | ||||||
|         printf("Manufacture keys file is not found: %s\r\n", file_name); | 
 | ||||||
|     } |     if (iv) furi_hal_crypto_store_unload_key(SUBGHZ_KEYSTORE_FILE_ENCRYPTION_KEY_SLOT); | ||||||
|     string_clear(line); | 
 | ||||||
|     storage_file_close(manufacture_keys_file); |     free(encrypted_line); | ||||||
|     storage_file_free(manufacture_keys_file); |     free(decrypted_line); | ||||||
|  | 
 | ||||||
|  |     return result; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | bool subghz_keystore_load(SubGhzKeystore* instance, const char* file_name) { | ||||||
|  |     furi_assert(instance); | ||||||
|  |     bool result = false; | ||||||
|  |     uint8_t iv[16]; | ||||||
|  |     uint32_t version; | ||||||
|  |     SubGhzKeystoreEncryption encryption; | ||||||
|  | 
 | ||||||
|  |     string_t filetype; | ||||||
|  |     string_init(filetype); | ||||||
|  | 
 | ||||||
|  |     Storage* storage = furi_record_open("storage"); | ||||||
|  | 
 | ||||||
|  |     FlipperFile* flipper_file = flipper_file_alloc(storage); | ||||||
|  |     do { | ||||||
|  |         if(!flipper_file_open_read(flipper_file, file_name)) { | ||||||
|  |             FURI_LOG_E(SUBGHZ_KEYSTORE_TAG, "Unable to open file for read: %s", file_name); | ||||||
|  |             break; | ||||||
|  |         } | ||||||
|  |         if(!flipper_file_read_header(flipper_file, filetype, &version)) { | ||||||
|  |             FURI_LOG_E(SUBGHZ_KEYSTORE_TAG, "Missing or incorrect header"); | ||||||
|  |             break; | ||||||
|  |         } | ||||||
|  |         if(!flipper_file_read_uint32(flipper_file, "Encryption", (uint32_t*)&encryption)) { | ||||||
|  |             FURI_LOG_E(SUBGHZ_KEYSTORE_TAG, "Missing encryption type"); | ||||||
|  |             break; | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         if (strcmp(string_get_cstr(filetype), SUBGHZ_KEYSTORE_FILE_TYPE) != 0 | ||||||
|  |             || version != SUBGHZ_KEYSTORE_FILE_VERSION) { | ||||||
|  |             FURI_LOG_E(SUBGHZ_KEYSTORE_TAG, "Type or version mismatch"); | ||||||
|  |             break; | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         File* file = flipper_file_get_file(flipper_file); | ||||||
|  |         if (encryption == SubGhzKeystoreEncryptionNone) { | ||||||
|  |             result = subghz_keystore_read_file(instance, file, NULL); | ||||||
|  |         }else if (encryption == SubGhzKeystoreEncryptionAES256) { | ||||||
|  |             if(!flipper_file_read_hex_array(flipper_file, "IV", iv, 16)) { | ||||||
|  |                 FURI_LOG_E(SUBGHZ_KEYSTORE_TAG, "Missing IV"); | ||||||
|  |                 break; | ||||||
|  |             } | ||||||
|  |             subghz_keystore_mess_with_iv(iv); | ||||||
|  |             result = subghz_keystore_read_file(instance, file, iv); | ||||||
|  |         } else { | ||||||
|  |             FURI_LOG_E(SUBGHZ_KEYSTORE_TAG, "Unknown encryption"); | ||||||
|  |             break; | ||||||
|  |         } | ||||||
|  |     } while(0); | ||||||
|  |     flipper_file_close(flipper_file); | ||||||
|  |     flipper_file_free(flipper_file); | ||||||
|  | 
 | ||||||
|     furi_record_close("storage"); |     furi_record_close("storage"); | ||||||
|  | 
 | ||||||
|  |     string_clear(filetype); | ||||||
|  | 
 | ||||||
|  |     return result; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | bool subghz_keystore_save(SubGhzKeystore* instance, const char* file_name, uint8_t* iv) { | ||||||
|  |     furi_assert(instance); | ||||||
|  |     bool result = false; | ||||||
|  | 
 | ||||||
|  |     Storage* storage = furi_record_open("storage"); | ||||||
|  |     char* decrypted_line = furi_alloc(SUBGHZ_KEYSTORE_FILE_DECRYPTED_LINE_SIZE); | ||||||
|  |     char* encrypted_line = furi_alloc(SUBGHZ_KEYSTORE_FILE_ENCRYPTED_LINE_SIZE); | ||||||
|  | 
 | ||||||
|  |     FlipperFile* flipper_file = flipper_file_alloc(storage); | ||||||
|  |     do { | ||||||
|  |         if(!flipper_file_new_write(flipper_file, file_name)) { | ||||||
|  |             FURI_LOG_E(SUBGHZ_KEYSTORE_TAG, "Unable to open file for write: %s", file_name); | ||||||
|  |             break; | ||||||
|  |         } | ||||||
|  |         if(!flipper_file_write_header_cstr(flipper_file, SUBGHZ_KEYSTORE_FILE_TYPE, SUBGHZ_KEYSTORE_FILE_VERSION)) { | ||||||
|  |             FURI_LOG_E(SUBGHZ_KEYSTORE_TAG, "Unable to add header"); | ||||||
|  |             break; | ||||||
|  |         } | ||||||
|  |         if(!flipper_file_write_uint32(flipper_file, "Encryption", SubGhzKeystoreEncryptionAES256)) { | ||||||
|  |             FURI_LOG_E(SUBGHZ_KEYSTORE_TAG, "Unable to add Encryption"); | ||||||
|  |             break; | ||||||
|  |         } | ||||||
|  |         if(!flipper_file_write_hex_array(flipper_file, "IV", iv, 16)) { | ||||||
|  |             FURI_LOG_E(SUBGHZ_KEYSTORE_TAG, "Unable to add IV"); | ||||||
|  |             break; | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         subghz_keystore_mess_with_iv(iv); | ||||||
|  | 
 | ||||||
|  |         if(!furi_hal_crypto_store_load_key(SUBGHZ_KEYSTORE_FILE_ENCRYPTION_KEY_SLOT, iv)) { | ||||||
|  |             FURI_LOG_E(SUBGHZ_KEYSTORE_TAG, "Unable to load encryption key"); | ||||||
|  |             break; | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         File* file = flipper_file_get_file(flipper_file); | ||||||
|  |         size_t encrypted_line_count = 0; | ||||||
|  |         for | ||||||
|  |             M_EACH( | ||||||
|  |                 key, | ||||||
|  |                 instance->data, | ||||||
|  |                 SubGhzKeyArray_t) { | ||||||
|  |                 // Wipe buffer before packing
 | ||||||
|  |                 memset(decrypted_line, 0, SUBGHZ_KEYSTORE_FILE_DECRYPTED_LINE_SIZE); | ||||||
|  |                 memset(encrypted_line, 0, SUBGHZ_KEYSTORE_FILE_ENCRYPTED_LINE_SIZE); | ||||||
|  |                 // Form unecreypted line
 | ||||||
|  |                 int len = snprintf( | ||||||
|  |                     decrypted_line, SUBGHZ_KEYSTORE_FILE_DECRYPTED_LINE_SIZE,  | ||||||
|  |                     "%08lX%08lX:%hu:%s", | ||||||
|  |                     (uint32_t)(key->key>>32), (uint32_t)key->key, key->type, string_get_cstr(key->name)); | ||||||
|  |                 // Verify length and align
 | ||||||
|  |                 furi_assert(len > 0); | ||||||
|  |                 if (len % 16 != 0) { | ||||||
|  |                     len += (16 - len % 16); | ||||||
|  |                 } | ||||||
|  |                 furi_assert(len % 16 == 0); | ||||||
|  |                 furi_assert(len <= SUBGHZ_KEYSTORE_FILE_DECRYPTED_LINE_SIZE); | ||||||
|  |                 // Form encrypted line
 | ||||||
|  |                 if(!furi_hal_crypto_encrypt((uint8_t*)decrypted_line, (uint8_t*)encrypted_line, len)) { | ||||||
|  |                     FURI_LOG_E(SUBGHZ_KEYSTORE_TAG, "Encryption failed"); | ||||||
|  |                     break; | ||||||
|  |                 } | ||||||
|  |                 // HEX Encode encrypted line
 | ||||||
|  |                 const char xx[]= "0123456789ABCDEF"; | ||||||
|  |                 for (size_t i=0; i<len; i++) { | ||||||
|  |                     size_t cursor = len - i - 1; | ||||||
|  |                     size_t hex_cursor = len*2 - i*2 - 1; | ||||||
|  |                     encrypted_line[hex_cursor] = xx[encrypted_line[cursor] & 0xF]; | ||||||
|  |                     encrypted_line[hex_cursor-1] = xx[(encrypted_line[cursor]>>4) & 0xF]; | ||||||
|  |                 } | ||||||
|  |                 storage_file_write(file, encrypted_line, strlen(encrypted_line)); | ||||||
|  |                 storage_file_write(file, "\n", 1); | ||||||
|  |                 encrypted_line_count++; | ||||||
|  | 
 | ||||||
|  |                 FURI_LOG_I(SUBGHZ_KEYSTORE_TAG, "Encrypted: `%s` -> `%s`", decrypted_line, encrypted_line); | ||||||
|  |             } | ||||||
|  |         furi_hal_crypto_store_unload_key(SUBGHZ_KEYSTORE_FILE_ENCRYPTION_KEY_SLOT); | ||||||
|  |         result = encrypted_line_count == SubGhzKeyArray_size(instance->data); | ||||||
|  |     } while(0); | ||||||
|  |     flipper_file_close(flipper_file); | ||||||
|  |     flipper_file_free(flipper_file); | ||||||
|  | 
 | ||||||
|  |     free(encrypted_line); | ||||||
|  |     free(decrypted_line); | ||||||
|  |     furi_record_close("storage"); | ||||||
|  | 
 | ||||||
|  |     return result; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| SubGhzKeyArray_t* subghz_keystore_get_data(SubGhzKeystore* instance) { | SubGhzKeyArray_t* subghz_keystore_get_data(SubGhzKeystore* instance) { | ||||||
|  | |||||||
| @ -33,7 +33,14 @@ void subghz_keystore_free(SubGhzKeystore* instance); | |||||||
|  * @param instance - SubGhzKeystore instance |  * @param instance - SubGhzKeystore instance | ||||||
|  * @param filename - const char* full path to the file |  * @param filename - const char* full path to the file | ||||||
|  */ |  */ | ||||||
| void subghz_keystore_load(SubGhzKeystore* instance, const char* filename); | bool subghz_keystore_load(SubGhzKeystore* instance, const char* filename); | ||||||
|  | 
 | ||||||
|  | /** Save manufacture key to file
 | ||||||
|  |  *  | ||||||
|  |  * @param instance - SubGhzKeystore instance | ||||||
|  |  * @param filename - const char* full path to the file | ||||||
|  |  */ | ||||||
|  | bool subghz_keystore_save(SubGhzKeystore* instance, const char* filename, uint8_t* iv); | ||||||
| 
 | 
 | ||||||
| /** Get array of keys and names manufacture
 | /** Get array of keys and names manufacture
 | ||||||
|  *  |  *  | ||||||
|  | |||||||
| @ -24,6 +24,8 @@ | |||||||
| #include <furi.h> | #include <furi.h> | ||||||
| #include <m-string.h> | #include <m-string.h> | ||||||
| 
 | 
 | ||||||
|  | #define SUBGHZ_PARSER_TAG "SubGhzParser" | ||||||
|  | 
 | ||||||
| typedef enum { | typedef enum { | ||||||
|     SubGhzProtocolTypeCame, |     SubGhzProtocolTypeCame, | ||||||
|     SubGhzProtocolTypeCameTwee, |     SubGhzProtocolTypeCameTwee, | ||||||
| @ -214,7 +216,11 @@ void subghz_parser_load_came_atomo_file(SubGhzParser* instance, const char* file | |||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void subghz_parser_load_keeloq_file(SubGhzParser* instance, const char* file_name) { | void subghz_parser_load_keeloq_file(SubGhzParser* instance, const char* file_name) { | ||||||
|     subghz_keystore_load(instance->keystore, file_name); |     if (subghz_keystore_load(instance->keystore, file_name)) { | ||||||
|  |         FURI_LOG_I(SUBGHZ_PARSER_TAG, "Successfully loaded keeloq keys from %s", file_name); | ||||||
|  |     } else { | ||||||
|  |         FURI_LOG_W(SUBGHZ_PARSER_TAG, "Failed to load keeloq keysfrom %s", file_name); | ||||||
|  |     } | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void subghz_parser_reset(SubGhzParser* instance) { | void subghz_parser_reset(SubGhzParser* instance) { | ||||||
|  | |||||||
| @ -461,4 +461,11 @@ bool flipper_file_read_hex_array( | |||||||
|         } |         } | ||||||
|     } |     } | ||||||
|     return result; |     return result; | ||||||
| } | } | ||||||
|  | 
 | ||||||
|  | File* flipper_file_get_file(FlipperFile* flipper_file) { | ||||||
|  |     furi_assert(flipper_file); | ||||||
|  |     furi_assert(flipper_file->file); | ||||||
|  | 
 | ||||||
|  |     return flipper_file->file; | ||||||
|  | } | ||||||
|  | |||||||
| @ -39,7 +39,7 @@ | |||||||
|  * Writing: |  * Writing: | ||||||
|  *  |  *  | ||||||
|  * ~~~~~~~~~~~~~~~~~~~~~ |  * ~~~~~~~~~~~~~~~~~~~~~ | ||||||
|  * FlipperFile file = flipper_file_alloc(storage); |  * FlipperFile* file = flipper_file_alloc(storage); | ||||||
|  *  |  *  | ||||||
|  * do { |  * do { | ||||||
|  *     const uint32_t version = 1; |  *     const uint32_t version = 1; | ||||||
| @ -65,7 +65,7 @@ | |||||||
|  * Reading: |  * Reading: | ||||||
|  *  |  *  | ||||||
|  * ~~~~~~~~~~~~~~~~~~~~~ |  * ~~~~~~~~~~~~~~~~~~~~~ | ||||||
|  * FlipperFile file = flipper_file_alloc(storage); |  * FlipperFile* file = flipper_file_alloc(storage); | ||||||
|  *  |  *  | ||||||
|  * do { |  * do { | ||||||
|  *     uint32_t version = 1; |  *     uint32_t version = 1; | ||||||
| @ -262,6 +262,17 @@ bool flipper_file_write_hex_array( | |||||||
|     const uint8_t* data, |     const uint8_t* data, | ||||||
|     const uint16_t data_size); |     const uint16_t data_size); | ||||||
| 
 | 
 | ||||||
|  | /** Get file descriptor.
 | ||||||
|  |  * | ||||||
|  |  * We higly don't recommend to use it. | ||||||
|  |  * This instance is owned by FlipperFile. | ||||||
|  |  * | ||||||
|  |  * @param      flipper_file pointer to FlipperFile instance | ||||||
|  |  * | ||||||
|  |  * @return     pointer to File instance | ||||||
|  |  */ | ||||||
|  | File* flipper_file_get_file(FlipperFile* flipper_file); | ||||||
|  | 
 | ||||||
| #ifdef __cplusplus | #ifdef __cplusplus | ||||||
| } | } | ||||||
| #endif | #endif | ||||||
| @ -129,14 +129,6 @@ zz: clean | |||||||
| zzz: clean | zzz: clean | ||||||
| 	$(MAKE) debug | 	$(MAKE) debug | ||||||
| 
 | 
 | ||||||
| FORMAT_SOURCES := $(shell find ../applications -iname "*.h" -o -iname "*.c" -o -iname "*.cpp") |  | ||||||
| FORMAT_SOURCES += $(shell find ../bootloader -iname "*.h" -o -iname "*.c" -o -iname "*.cpp") |  | ||||||
| FORMAT_SOURCES += $(shell find ../core -iname "*.h" -o -iname "*.c" -o -iname "*.cpp") |  | ||||||
| 
 |  | ||||||
| format: |  | ||||||
| 	@echo "Formatting sources with clang-format" |  | ||||||
| 	@clang-format -style=file -i $(FORMAT_SOURCES) |  | ||||||
| 
 |  | ||||||
| generate_cscope_db: | generate_cscope_db: | ||||||
| 	@echo "$(C_SOURCES) $(CPP_SOURCES) $(ASM_SOURCES)" | tr ' ' '\n' > $(OBJ_DIR)/source.list.p | 	@echo "$(C_SOURCES) $(CPP_SOURCES) $(ASM_SOURCES)" | tr ' ' '\n' > $(OBJ_DIR)/source.list.p | ||||||
| 	@cat ~/headers.list >> $(OBJ_DIR)/source.list.p | 	@cat ~/headers.list >> $(OBJ_DIR)/source.list.p | ||||||
|  | |||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user
	 あく
						あく