diff --git a/ReadMe.md b/ReadMe.md index d4357336f..c4464bff1 100644 --- a/ReadMe.md +++ b/ReadMe.md @@ -44,13 +44,16 @@ Our Discord Community: Also check changelog in releases for latest updates! ### Current modified and new SubGHz protocols list: -- HCS101 -- An-Motors +- Keeloq [Not ALL systems supported for decode or emulation yet!] - [Supported manufacturers list](https://0bin.net/paste/VwR2lNJY#WH9vnPgvcp7w6zVKucFCuNREKAcOij8KsJ6vqLfMn3b) +- Keeloq: HCS101 +- Keeloq: An-Motors +- Keeloq: JCM Tech +- Keeloq: MHouse +- Keeloq: Nice Smilo - CAME Atomo -- FAAC SLH (Spa) [External seed calculation required] -- BFT Mitto [External seed calculation required] -- Keeloq [Not ALL systems supported yet!] - Nice Flor S +- FAAC SLH (Spa) [External seed calculation required (For info conatct me in Discord: Nano#8998)] +- BFT Mitto [External seed calculation required (For info conatct me in Discord: Nano#8998)] - Security+ v1 & v2 - Star Line (saving only) diff --git a/applications/main/subghz/subghz_i.c b/applications/main/subghz/subghz_i.c index 1b6496bbc..e3d22ed73 100644 --- a/applications/main/subghz/subghz_i.c +++ b/applications/main/subghz/subghz_i.c @@ -431,7 +431,7 @@ bool subghz_save_protocol_to_file( do { //removing additional fields flipper_format_delete_key(flipper_format, "Repeat"); - flipper_format_delete_key(flipper_format, "Manufacture"); + //flipper_format_delete_key(flipper_format, "Manufacture"); // Create subghz folder directory if necessary if(!storage_simply_mkdir(storage, furi_string_get_cstr(file_dir))) { diff --git a/applications/main/unirfremix/unirfremix_app.c b/applications/main/unirfremix/unirfremix_app.c index 6d0fa60b4..6fee8ebd9 100644 --- a/applications/main/unirfremix/unirfremix_app.c +++ b/applications/main/unirfremix/unirfremix_app.c @@ -562,7 +562,7 @@ bool unirfremix_save_protocol_to_file(FlipperFormat* fff_file, const char* dev_f path_extract_dirname(dev_file_name, file_dir); do { flipper_format_delete_key(fff_file, "Repeat"); - flipper_format_delete_key(fff_file, "Manufacture"); + //flipper_format_delete_key(fff_file, "Manufacture"); if(!storage_simply_mkdir(storage, furi_string_get_cstr(file_dir))) { FURI_LOG_E(TAG, "(save) Cannot mkdir"); diff --git a/assets/resources/subghz/assets/keeloq_mfcodes b/assets/resources/subghz/assets/keeloq_mfcodes index 0c0e15a62..06078ffb1 100644 --- a/assets/resources/subghz/assets/keeloq_mfcodes +++ b/assets/resources/subghz/assets/keeloq_mfcodes @@ -1,51 +1,51 @@ Filetype: Flipper SubGhz Keystore File Version: 0 Encryption: 1 -IV: 2A 34 F1 5A AF 6F F5 1A 83 A6 1E DA DE B7 3D F1 -06B63DF24AE073A2F2B19C55CA9E8364FBECD26E49C551990153F6513BDE5267 -6139C78C74C341EB7474085CF1D047BD6FB005F80A72AF3EF3F89D58EF5DF500 -D85F11689020ECA47FBE9C2B67EE41A81E1F06DE2A35AF958965E3ECE29EA701 -1AE9073A42FE0E439544FE6945F6B33CF15A7A4A279020B5E0B3BE33FD189A7E -E161F007854BB33E0056FA09A2E2DEE66789B5C87C8D6D3DE2C8C1BD2B48983EB9D1C5697CA6E95996918F7C47B761B0 -59AE4644DCB3D720C38B5115F230DA58E7BE0A697907F6174BB05AB7886ACDB1 -634DF0BCC185C4C1F7E1B1594B4438D051ABAE092433078963063B51D961D08C -1EBEBCB49E498B9BE977D53EC21B9A546155B627737BD0AA832D496035729346 -4DFA93E639197772D57E8ACE04512CEFC045B8CC965C175A25ED525B630CBB63 -C2D5235D1014A319B249EAE8A5EE350F18D5AB8A498EF222704BD4EB1435F388 -F66D1937160E1392197F463A52E87FCE938A92070892113443C348D7553327A5715CF615CE2F2C96284F47759E043419 -841D29E7CBE040188E2283BFBA9F26EF2F65CCB085B56C3515E8C46C3F20BD75BAA963550869435FDAF509CEEE66A2C4 -7D87E24487D307635E7A17B989B8547EE11F3BF3468D055F0B44633B631BA42C -B4916043973501B95A82B329196D6EBA69FBBC3AF8FD914583104E0E18CE82F6 -E4649F9C2A5465D2EA6F3E9724DD06CD6962FE2BAEB14F1453C14D1559232AE1 -96E15D890DF7FD348441F5E429A875754C6BF0520A787F8E9D8C5415674783CC -CB52005EDED47B57F795BC92FB0522EAB18D23EE028B8D10ED57828C250EB285BFEC6E4A4BE8DABCE0D57ECAA20D90C3 -8E5A50C7D5C374445E88752301D20F0B3D6E4988B61D90FD63779B0EDEF9C60D -49D6CB276A0E5FF134A38062503F01351F44CD6455708B50B5F07D03FC477C33 -CB45B56613DF208E79E4E10A6510F07DC1AA49210C7B94E8BBAECD2C35EC6ABC99FB10FD7C96DD6BB6A6685E9FAD93FB -0743F3CC51200F763C242F1956B4D775C092ADF1A5C19ACAE96EB60C2990CF214F8FEA8FC6749286F6BDAB67657C479A -E5608B28A058787D64A145F0362DEFD98CAE0B5A0F22C6DA7C6D278C7B5F95E3 -D4C113D43E7FB6D2EFA9E87471AA76A61B26872607B4AF5B87F9D72113835CE6 -2DC502800BFD21B76126390CA64A08C5432A2254E822F214CDE1EA11430084C5 -CA22C73010B0F1CB8009601BE2AF0B3674D83D5880E4A26C2A3FF0EA0A098CEA -E53B2B102FDB000E9BB747F957156976E5A0C0E3898AA844C13AE8A9CEE7013B -EFB27324B5661419265804ABD130C13DC9DF9CD4D2AC2011CB4FD43D56304AD1 -491D75A82ACE8CE216FBE4F0D2D0133BAC7EA8F4A5304337D5E8611AD9C72523 -BBFA2B00827E0BCC8AC5CE12C972BB58DFA2EA59DFEFF5A538398FCF970F58A7 -6BAF9C855926B683BEDC11883543B2C0E0866FF6B06C46CC09B3C4E1200E7716 -B35A4D25FF4D5CFF93B9C4C07B78FCF7E2646138DAB7C090A938C8055CCCE3D8 -71CC3C0180771E6B304CE984F5A9962EB35D1965CB78EBAE6F4DDFA44E5E02A2 -3DCF52C549FEFCCE2831DB74579AA2C157A4BEE70C43905664C9A6491A171F5D -F7E45AF200F7663DCCE54C14118D2CDFD1228ED0BFF7F70CFBCE15B6F9DF3D40 -C44E048AD5C003E68DCF0111317D109CF2B7DD79299692CDA7DA2A12EC9A295A -2B3E6778A97B251A5FEB190991B8AE8EC48F5FC6E94C2ECB8DFADFDD9D8E21FEE5DCCEDD9A1EB8C5212DEAE36FBBDF92 -1DD4756E681528CBBDBA6C7BF8833DF556D41E5EA4E4DE52CAD3544C946CD8CA -F903D388CF2016B40B492494F7475E71C50E9FDD63304558212DAF6FBC4E1BA4 -9E9F24951DB27917668CD6366795052306022F6F8BA11B08A970691C6857E6C5 -C88461104FA0EAA68001B0C2D0483D1A53D6AE04F4CB291C76CEF3A1A5C5DC10 -8345B2B9F08B018FEAC2F74D76747FF30DBF426C9B390ACD42AD48104C12042E -087269DC66C76E1D6449831A2C3B6F0006C0F8B1861062B95708C6B222C58A9C -4D31DE05DB12E552D43B1017C68AF3F52B6FE8063E4AD82CB568CDAF22950BCC26FF21EE968FB57650111B617A84DEF7 -769BAA780F84797431B6E9DD5180AF3848E03C942C67040B39CC6384E2A8F4C6 -1844AAAAD6A6AFB2623DF1452DF940715E6EB92F54C49F408872EC4B2156DDB2 -23EB39CD7F3921081199BA8B63D4C19F74365F8D8E71D486576DC900E5EFEEA3 -45958B93A16A73CA2578ADCFB1EADAA983BB7015321B0592B67CDF573B084194 +IV: 3B 23 A4 2B B1 5D D3 2C 45 B7 3D AF AE B1 D8 53 +FA10AAD920563C9F593B7CDDBB544A0F3F2D372854A3A9AB69D10199E7CCFA54 +92423F7ED2493A8015BE619D2983056022FC634B68F17EB1260670497FDFB189 +6AB9C91E650D048078F87D7DACB278F52EC84CA7F2AECC4338D6A6B456BDE934 +84EF6BCCB35F1FCCE0EAC6344D4E4E37A263F04B1FDE79A1D0884BE1FCB8A664 +BEC8FBBE9CB4C8C894DD8F2D63A49E76F0363203154710FE8762592858CAD6AF47B9E4BC7ADA14D77F8A82BF9BACE6C6 +FB558B51A1DCAB34D119C9D3AC0B0F681E152ED3F9D00E3D40C4B868EEEF8F73 +A6E060649AB62907D3B584F1AAC27C2BA1D4BC964BE527A5B901A46C5CADD9BB +7E2E6B38427BFCDB5CD9ED52CF342181446EA6B61192DF28928B64440364F77D +0E3F30701EA2071F9291FA3783149181B27E7B83FF8E259AB458ED3997EE649B +A8ABE616CFF13397BA3D21992C14E43B42FE496C84B97CB7FF0FD4611DAEC8A3 +EBBB491879A73FD43718C6851855F621B0AE986C728A8F8D99359F882406132BFB2CF9811BA464D878F36E5712759869 +ED4EEF947C6E3475F5FF9905352C7D78F153C65A9AB418892069202C6677002EA2AFC55462797DEE0B69375283D84A26 +A27B11AD0DDB5E96B68EB1A016598152FE27C966CF675F7BF17990DEAFF58B62 +0BF77CB175A18ADCBDAEA31EAF80ABD886D6BF5034088A25722BC8BB6F7E65FD +66B3C2C98F8154F0B54887B251F8C583199D06ADE895DCEE324213EF3701A44D +A00342176255312C795DD2048087E5B93C28A11BE39E44E2F60B27A1D1B0532F +E6C8A79585A0E091C17E3633ED3074FFA3A5093142B5FB0921873B006257C5F7258B7094F38ACC0D77EA01F31967D2CB +0A2D80FFD35E8D0FD9D728594E91FC8930C7F28EDF59DA2EC896F76A7D71AAF3 +0520C7F9BB04EADAF8A74CF89E8EF7AF2B445EB30E5044448B6B8E58CB2467CB +1B7A5310AA25A22042320874ABDF28A7C49432B8364CBF8AB4F04B954D7198C4274F684E4265F82317AB46ACAEA4E849 +F0B462179B43E94C50CA2AC75D8C37C0FB606FB0A5380E2BE9F7C5BF24EF3CEFE12E36B41961626F83F9458735AE0A28 +9D3A735349C6D83E22C84088DE19EDAD877CBF8E485ED20D25019580354B51B5 +4285797E07FF121D73926DFB11B4CE0E7914FD7AECD62381F45A26091ED1EB3D +63787A106DB07DBECB108A45959E15F7DEB04858989DE536483DA06D3F0D1509 +A64DF8135E264E799DFB8C8063F665890BDE3CE671FC9878E96516386B1421DB +CCF9B4EF4D817F0A38D023937AD4CE201B0A84AF480CB9FC797AFE8AE9D7C50A +D8DDE6F46CDC89283BAB72171A0F0E470A434F3973CC5FD5617E3F9E0B469048 +F08C5ECAC04171983A3923CFFC22BA5CC0C9EECA20D7D5EB2D9495FB9F3B7E80 +5AEB9E25A24FA3BF5715D264610E0A6D68197B376555470DA19743569B2CA52C +95E621103E87C52397A53053045FE7B916E43B153F9140144DEEB840F2C43D02 +12DFA9AFC04287DE60E540EA46472BE1283012646F3614A501CEA416B591BB89 +9375214B3188DE8E4FBA9BB746323B10862B906B8250B6F49E6A3E6400AC5DA6 +047BA7E96986B6054F44F2A20AA338C145FE53099BE77481A635D6E73CEC97FB +42115D1C01E03A411D4940644472FC6F6BC85D90305995D00B1839D5FA6B18CC +A962C5FA4F0D5443C8E7555C1F9563588D206B0EA60886B0C44E6EB1EC733971 +62E66CDD2FE2ABCA8997D8D8DE24F81C8051C9371F2DB7C8BB6E8DC54A342F9FB09E896133D7F50B8DC058812C90A122 +B6E6DEEA620F723D2F7E0325F558F4590DB33553E7680447FA17EEDC1B7C37DF +15621585B61B3EF2858777E0649801F9AE45FEEBC350786E015E8B669E40453F +60D5FEABB8D4C371BF8F700A2C06B15E26CA940FF7990892DDED3D1898787D03 +AB0B79C7F5B7BA414E5091CEE9E7F186185A04A9C2E89B4F7C0FA1EB2212EA8C +96065C37BD3B8FBCAA987E8242DB2BDEDE97B3A0F9D7B4C5E753B77989FDE01F +9B9F6302870EF6724F9F7501BC69D4A994485639FB5C437A1461A79D5700D6EF +2D0042C0215561D6E991EDC884477ABA85800D60714CC05FB964A756F2EB05E8 +61B88BBB34E93B215CC17C39F2B848AA3CC37EF946FBC467C53873E79985276DB86FF1508972758FE7FC9047B87A7C91 +02401832ACADB1DC195902ABD1219965DBA9D38FF651553D18F158A54D98562F +BB5E86C8CB07ACA72B27DCBE578C71080AA1D4071E088E0A6E5CD3DBB0BBB95E +0E86D4024CDBF883C701CBCEA75501158FCB442E0EC30FB592D2F8BBCBF24F4F diff --git a/lib/subghz/protocols/keeloq.c b/lib/subghz/protocols/keeloq.c index b43a60e4d..65927d7b1 100644 --- a/lib/subghz/protocols/keeloq.c +++ b/lib/subghz/protocols/keeloq.c @@ -28,6 +28,8 @@ struct SubGhzProtocolDecoderKeeloq { uint16_t header_count; SubGhzKeystore* keystore; const char* manufacture_name; + + FuriString* manufacture_from_file; }; struct SubGhzProtocolEncoderKeeloq { @@ -38,6 +40,8 @@ struct SubGhzProtocolEncoderKeeloq { SubGhzKeystore* keystore; const char* manufacture_name; + + FuriString* manufacture_from_file; }; typedef enum { @@ -113,12 +117,16 @@ void* subghz_protocol_encoder_keeloq_alloc(SubGhzEnvironment* environment) { instance->encoder.size_upload = 256; instance->encoder.upload = malloc(instance->encoder.size_upload * sizeof(LevelDuration)); instance->encoder.is_running = false; + + instance->manufacture_from_file = furi_string_alloc(); + return instance; } void subghz_protocol_encoder_keeloq_free(void* context) { furi_assert(context); SubGhzProtocolEncoderKeeloq* instance = context; + furi_string_free(instance->manufacture_from_file); free(instance->encoder.upload); free(instance); } @@ -143,6 +151,13 @@ static bool subghz_protocol_keeloq_gen_data(SubGhzProtocolEncoderKeeloq* instanc instance->manufacture_name = ""; } + // Nice Smilo, MHouse, JCM has 8bit serial - simple learning + if((strcmp(instance->manufacture_name, "NICE_Smilo") == 0) || + (strcmp(instance->manufacture_name, "NICE_MHOUSE") == 0) || + (strcmp(instance->manufacture_name, "JCM_Tech") == 0)) { + decrypt = btn << 28 | (instance->generic.serial & 0xFF) << 16 | instance->generic.cnt; + } + if(strcmp(instance->manufacture_name, "Unknown") == 0) { code_found_reverse = subghz_protocol_blocks_reverse_key( instance->generic.data, instance->generic.data_count_bit); @@ -347,6 +362,16 @@ bool subghz_protocol_encoder_keeloq_deserialize(void* context, FlipperFormat* fl FURI_LOG_E(TAG, "Wrong number of bits in key"); break; } + + // Read manufacturer from file + if(flipper_format_read_string( + flipper_format, "Manufacture", instance->manufacture_from_file)) { + instance->manufacture_name = furi_string_get_cstr(instance->manufacture_from_file); + mfname = furi_string_get_cstr(instance->manufacture_from_file); + } else { + FURI_LOG_D(TAG, "ENCODER: Missing Manufacture"); + } + uint8_t seed_data[sizeof(uint32_t)] = {0}; for(size_t i = 0; i < sizeof(uint32_t); i++) { seed_data[sizeof(uint32_t) - i - 1] = (instance->generic.seed >> i * 8) & 0xFF; @@ -415,6 +440,7 @@ void* subghz_protocol_decoder_keeloq_alloc(SubGhzEnvironment* environment) { instance->base.protocol = &subghz_protocol_keeloq; instance->generic.protocol_name = instance->base.protocol->name; instance->keystore = subghz_environment_get_keystore(environment); + instance->manufacture_from_file = furi_string_alloc(); return instance; } @@ -422,6 +448,7 @@ void* subghz_protocol_decoder_keeloq_alloc(SubGhzEnvironment* environment) { void subghz_protocol_decoder_keeloq_free(void* context) { furi_assert(context); SubGhzProtocolDecoderKeeloq* instance = context; + furi_string_free(instance->manufacture_from_file); free(instance); } @@ -950,6 +977,16 @@ bool subghz_protocol_decoder_keeloq_deserialize(void* context, FlipperFormat* fl FURI_LOG_E(TAG, "Rewind error"); break; } + + // Read manufacturer from file + if(flipper_format_read_string( + flipper_format, "Manufacture", instance->manufacture_from_file)) { + instance->manufacture_name = furi_string_get_cstr(instance->manufacture_from_file); + mfname = furi_string_get_cstr(instance->manufacture_from_file); + } else { + FURI_LOG_D(TAG, "DECODER: Missing Manufacture"); + } + uint8_t seed_data[sizeof(uint32_t)] = {0}; for(size_t i = 0; i < sizeof(uint32_t); i++) { seed_data[sizeof(uint32_t) - i - 1] = (instance->generic.seed >> i * 8) & 0xFF; diff --git a/lib/subghz/protocols/star_line.c b/lib/subghz/protocols/star_line.c index d6c9c0ae0..f91e9ad18 100644 --- a/lib/subghz/protocols/star_line.c +++ b/lib/subghz/protocols/star_line.c @@ -28,6 +28,8 @@ struct SubGhzProtocolDecoderStarLine { uint16_t header_count; SubGhzKeystore* keystore; const char* manufacture_name; + + FuriString* manufacture_from_file; }; struct SubGhzProtocolEncoderStarLine { @@ -38,6 +40,8 @@ struct SubGhzProtocolEncoderStarLine { SubGhzKeystore* keystore; const char* manufacture_name; + + FuriString* manufacture_from_file; }; typedef enum { @@ -109,16 +113,20 @@ void* subghz_protocol_encoder_star_line_alloc(SubGhzEnvironment* environment) { instance->generic.protocol_name = instance->base.protocol->name; instance->keystore = subghz_environment_get_keystore(environment); + instance->manufacture_from_file = furi_string_alloc(); + instance->encoder.repeat = 10; instance->encoder.size_upload = 256; instance->encoder.upload = malloc(instance->encoder.size_upload * sizeof(LevelDuration)); instance->encoder.is_running = false; + return instance; } void subghz_protocol_encoder_star_line_free(void* context) { furi_assert(context); SubGhzProtocolEncoderStarLine* instance = context; + furi_string_free(instance->manufacture_from_file); free(instance->encoder.upload); free(instance); } @@ -274,6 +282,15 @@ bool subghz_protocol_encoder_star_line_deserialize(void* context, FlipperFormat* break; } + // Read manufacturer from file + if(flipper_format_read_string( + flipper_format, "Manufacture", instance->manufacture_from_file)) { + instance->manufacture_name = furi_string_get_cstr(instance->manufacture_from_file); + mfname = furi_string_get_cstr(instance->manufacture_from_file); + } else { + FURI_LOG_D(TAG, "ENCODER: Missing Manufacture"); + } + subghz_protocol_star_line_check_remote_controller( &instance->generic, instance->keystore, &instance->manufacture_name); @@ -331,6 +348,9 @@ void* subghz_protocol_decoder_star_line_alloc(SubGhzEnvironment* environment) { SubGhzProtocolDecoderStarLine* instance = malloc(sizeof(SubGhzProtocolDecoderStarLine)); instance->base.protocol = &subghz_protocol_star_line; instance->generic.protocol_name = instance->base.protocol->name; + + instance->manufacture_from_file = furi_string_alloc(); + instance->keystore = subghz_environment_get_keystore(environment); return instance; @@ -339,6 +359,7 @@ void* subghz_protocol_decoder_star_line_alloc(SubGhzEnvironment* environment) { void subghz_protocol_decoder_star_line_free(void* context) { furi_assert(context); SubGhzProtocolDecoderStarLine* instance = context; + furi_string_free(instance->manufacture_from_file); free(instance); } @@ -705,6 +726,16 @@ bool subghz_protocol_decoder_star_line_deserialize(void* context, FlipperFormat* FURI_LOG_E(TAG, "Deserialize error"); break; } + + // Read manufacturer from file + if(flipper_format_read_string( + flipper_format, "Manufacture", instance->manufacture_from_file)) { + instance->manufacture_name = furi_string_get_cstr(instance->manufacture_from_file); + mfname = furi_string_get_cstr(instance->manufacture_from_file); + } else { + FURI_LOG_D(TAG, "DECODER: Missing Manufacture"); + } + res = true; } while(false);