Просмотр исходного кода

Merge picopass from https://github.com/flipperdevices/flipperzero-good-faps

Willy-JL 2 лет назад
Родитель
Сommit
7f47af7a9c

+ 29 - 1
picopass/.catalog/README.md

@@ -19,7 +19,7 @@ NOTE: If the screen says “Got std key” AND stays on 0/18, then loclass isn't
 
 1. Download the loclass log (_sdcard/apps_data/picopass/.loclass.log_) from your Flipper Zero.
 2. Use [loclass.ericbetts.dev](https://loclass.ericbetts.dev/) or a tool of your choice to calculate the key
-3. Copy the key to _iclass_elite_dict_user.txt_ and place in _sdcard/apps_data/picopass/_
+3. Copy the key to _iclass_elite_dict_user.txt_ and place in _sdcard/apps_data/picopass/assets/_
 4. Run _Elite Dict. Attack_ from the picopass main menu
 5. Present card to the back of the Flipper Zero.
 
@@ -30,3 +30,31 @@ There are some situations when the offline loclass may not find a key, such as:
  * Readers configured with Standard-2 keyset
  * Custom keyed readers using Standard KDF
  * Custom keyed readers using SE KDF
+
+# NR-MAC read
+
+Due to the nature of how secure picopass works, it is possible to emulate some public fields from a card and capture the reader's response, which can be used to authenticate.  Two of the pieces involved in this are the NR and MAC.
+
+## Card Part 1
+
+1. Place card against Flipper Zero
+2. Run _Read_ from the picopass main menu
+3. Get a "Read Failed" message
+4. Select the "Menu" option
+5. Select "Save Partial"
+6. Name file something you'll remember
+
+## Reader Part
+
+1. Select _Saved_ from the picopass main menu
+2. Select the file name you saved in last step of Card Part 1
+3. Select _Emulate_
+4. Expose Flipper Zero to reader (It may work better a few inches from the reader, as opposed to physically touching)
+5. Flipper will buzz and screen will say "NR-MAC Saved!"
+
+## Card Part 2
+
+1. Place card against Flipper Zero
+2. Run _Read_ from the picopass main menu
+3. Card will authenticate and read
+

+ 9 - 0
picopass/.catalog/changelog.md

@@ -1,3 +1,12 @@
+## 1.11
+ - Update working with keys with new API
+ - Display more tag information
+ - Add additional keys to elite dict
+ - Correct config card detection so it doesn't happen for SE cards (read using nr-mac partial read)
+ - Have back button go to start menu instead of read retry
+## 1.10
+ - Fix missing folder in readme
+ - Allow partial save for any read failure
 ## 1.9
  - Fix bug (#77) with loclass
  - Better loclass notes

+ 1 - 1
picopass/application.fam

@@ -10,7 +10,7 @@ App(
     ],
     stack_size=4 * 1024,
     fap_description="App to communicate with NFC tags using the PicoPass(iClass) format",
-    fap_version="1.9",
+    fap_version="1.11",
     fap_icon="125_10px.png",
     fap_category="NFC",
     fap_libs=["mbedtls"],

+ 772 - 1
picopass/files/iclass_elite_dict.txt

@@ -34,8 +34,779 @@ C1B74D7478053AE2
 # default iCLASS RFIDeas
 6B65797374726B72
 
-# CTF key
+# CTF key (keyscan)
 5C100DF7042EAE64
 
 # iCopy-X DRM key (iCE product)
 2020666666668888
+
+## Pastebin keys (icopyx) https://pastebin.com/KWcu0ch6
+
+FB93B584A5064748
+0B361EDE24ED3625
+E49A2A1092A12148
+1CB2C054D0657700
+1DE69079350928E4
+5518848B2E911037
+D6204388A3C08982
+DCD2EB1FB841DCDF
+46F94E6F5D912E1C
+239D50BF09D9125C
+7CABABB46DFB93B5
+29536A124174096C
+6577009ADCD2EB1F
+199AF82DD18E0C68
+77009ADCD2EB1FB8
+6A121127DD422E07
+F2FA4E3F0F640479
+55B437FE2ACD5C79
+FE12DE53985046F9
+E49EDD4B30EAB0F0
+A3C089828CBDB3E6
+62C491C11B398C00
+A15C28B85EDFB515
+0CBE6CC4851B3ED4
+1E6CA194384AC919
+524556D8E2050B1F
+12DE53985046F94E
+BC287A74A9D174E8
+BC3B29536A124174
+515B00B7D428DAA6
+9C8C0863D32B98A4
+8237CC1E67823C23
+F18237CC1E67823C
+FA4E3F0F6404798F
+E142E32B7DF3807F
+ABE827F982DE18EF
+81493D660C2A5245
+3FAE7F61A83DB655
+D2EB1FB841DCDF08
+C919F18237CC1E67
+647AB9ED2DC9153F
+537FA5DF1FC70945
+FB5D78527086A60C
+CAC7490304A15C28
+E39D01515B00B7D4
+5B3FAE7F61A83DB6
+3C384BE84F5A6B78
+AE13DEBBD810AC40
+9F6E0B0CB425428E
+912E1CB2C054D065
+C071D91E0795BEBA
+4C1617AA1B7DA8EA
+74096CD12AF4C6B0
+48B6010B1D8BC24B
+3B29536A12417409
+240FAD647AB9ED2D
+56B3500C1092CC89
+AC40BF3FB59F6E0B
+C7490304A15C28B8
+8A3E680AF244E13F
+AFFAB4A6A2A566B8
+78527086A60CBE6C
+ED2DC9153F449B92
+E6FBE030F774B72D
+61A83DB6554C1617
+87B191CAC7490304
+19C73D0811EEE119
+680AF244E13FB60E
+27DD422E07D3DF18
+B841DCDF08E576BA
+FC22F72AC9C2E6DB
+5058C908068D67C0
+5D912E1CB2C054D0
+1FBD59936949B4C1
+01515B00B7D428DA
+16B256B79DFE12DE
+AD647AB9ED2DC915
+30F774B72DBC2FA1
+384AC919F18237CC
+0795BEBA8A3E680A
+691DE69079350928
+C15B3FAE7F61A83D
+823C239D50BF09D9
+AA1B7DA8EACC5B7C
+1D8BC24B16B256B7
+74B72DBC2FA15BB3
+2B03163830E3E9A9
+EACC5B7C62C491C1
+1162DD6A97FAC8D2
+5046F94E6F5D912E
+2DC9153F449B9226
+153F449B9226B12E
+BD59936949B4C15B
+BE6CC4851B3ED409
+793B5BB5A4528B0B
+10AC40BF3FB59F6E
+ABABB46DFB93B584
+204388A3C089828C
+71D91E0795BEBA8A
+2DBC2FA15BB30725
+B79DFE12DE539850
+8C0863D32B98A479
+1B3ED409B14E6C24
+B0C6E2677DBD2854
+C32634573C1798D0
+536A124174096CD1
+B883C57781CDC832
+30E3E9A967E142E3
+660C2A524556D8E2
+04B0C6E2677DBD28
+38A8911FC749FE23
+1FB841DCDF08E576
+CB941FBD59936949
+D428DAA6C5529FC9
+482562E49EDD4B30
+9D76908782D1A7FE
+976CE582C3263457
+2DD18E0C68FDAEFF
+B30725F2C49288F5
+9EDD4B30EAB0F02B
+0647482562E49EDD
+8F9F6C38A8911FC7
+B60E84963355B437
+6F8D453205DB962B
+0FAD647AB9ED2DC9
+94384AC919F18237
+7E14BD46BAD35522
+E78530CB941FBD59
+3DBA2A52E3C64870
+9079350928E49A2A
+B3E6FBE030F774B7
+BF2B03163830E3E9
+B584A50647482562
+AE7F61A83DB6554C
+3D660C2A524556D8
+7E5F3F43BA819F19
+3F7087B191CAC749
+04A15C28B85EDFB5
+DA7B6144B03E1BB1
+5BB5A4528B0B361E
+EDF90C1A4E0C7057
+529FC9493DBA2A52
+2ACD5C793B5BB5A4
+C8B2F9456B8D5897
+83E2AFFAB4A6A2A5
+48D0773590ADFA99
+1617AA1B7DA8EACC
+88A3C089828CBDB3
+F5B3F854EC33DA38
+B14E6C24F217AFC1
+6F5D912E1CB2C054
+5EDFB5157C2736C9
+A6A2A566B839BDC7
+6A3B86281DF16B36
+C24B16B256B79DFE
+9C01B7D4EEBDACBC
+C8D31E6CA194384A
+0C2A524556D8E205
+C69A1DC5A430FF6A
+0863D32B98A4793D
+A2A566B839BDC7DC
+8530CB941FBD5993
+706101BBEAB5FE1B
+DEFD1FED8E326B65
+0C68FDAEFFD62043
+1D65FB5D78527086
+93B584A506474825
+59929C8C0863D32B
+502B16173C05F181
+A4793D9C2F537FA5
+1A4E0C70579D5058
+EEBDACBC287A74A9
+07B7C106FCFCC8B2
+FE2ACD5C793B5BB5
+DEBBD810AC40BF3F
+105790EB34FCAFA9
+AEFFD6204388A3C0
+C11B398C000D9719
+24F217AFC12C7E7D
+0AE186B3AAE8271A
+CD36017CABABB46D
+1E0795BEBA8A3E68
+017CABABB46DFB93
+6CD12AF4C6B00155
+18EF875849BC3B29
+AFA9ED3807B7C106
+95BEBA8A3E680AF2
+225BA9C1A0FDAA48
+48706101BBEAB5FE
+BF09D9125CD1E8EF
+456B8D58976CE582
+99DBA4CD36017CAB
+EEE11930DA7E5F3F
+1E5EB656B3500C10
+86A60CBE6CC4851B
+B2F9456B8D58976C
+8C000D9719A19023
+1B0EC69A1DC5A430
+5849BC3B29536A12
+CC1E67823C239D50
+7DA8EACC5B7C62C4
+FCAFA9ED3807B7C1
+D9125CD1E8EFE808
+3B5BB5A4528B0B36
+EC6C67F210E78530
+5D78527086A60CBE
+E8225BA9C1A0FDAA
+819F199AF82DD18E
+28B85EDFB5157C27
+773590ADFA99DBA4
+9A2A1092A12148D0
+124174096CD12AF4
+03163830E3E9A967
+F25C100DF7042EAE
+D91E0795BEBA8A3E
+B72DBC2FA15BB307
+D1E8EFE808F3FD6E
+F774B72DBC2FA15B
+25E8225BA9C1A0FD
+7A4FE39D01515B00
+2E1CB2C054D06577
+8EF25C100DF7042E
+965D6E234471D87E
+FDAA48B6010B1D8B
+573C1798D0269B83
+B5FE1B0EC69A1DC5
+5B8CE0A0D8B6BF2B
+C6E2677DBD2854B8
+44E13FB60E849633
+5BB30725F2C49288
+9E4411D032C2507A
+8E0C68FDAEFFD620
+B2C054D06577009A
+DD66EC6C67F210E7
+06FCFCC8B2F9456B
+72EDF90C1A4E0C70
+0E84963355B437FE
+40BF3FB59F6E0B0C
+7650F272EDF90C1A
+2562E49EDD4B30EA
+C5529FC9493DBA2A
+4556D8E2050B1F1D
+453FB5A1FEDA63B7
+61C8D31E6CA19438
+A5DF1FC709457A4F
+24ED3625E8225BA9
+54B8403F7087B191
+F7042EAE64105790
+08F3FD6E9C01B7D4
+79350928E49A2A10
+F82DD18E0C68FDAE
+9D50BF09D9125CD1
+269B83E2AFFAB4A6
+52E3C648706101BB
+B191CAC7490304A1
+0F6404798F9F6C38
+828CBDB3E6FBE030
+3C05F181493D660C
+9719A190237BAE13
+91CAC7490304A15C
+A190237BAE13DEBB
+76BABC3D54B25C01
+63D32B98A4793D9C
+6C38A8911FC749FE
+A4528B0B361EDE24
+E3C648706101BBEA
+4B30EAB0F02B77CC
+B3500C1092CC8904
+FE1B0EC69A1DC5A4
+F02B77CC90AA19C7
+422E07D3DF184370
+2FA15BB30725F2C4
+19A190237BAE13DE
+7A74A9D174E8639E
+BEBA8A3E680AF244
+9ADCD2EB1FB841DC
+6B8D58976CE582C3
+911FC749FE231E5E
+0CB425428EF25C10
+89828CBDB3E6FBE0
+163830E3E9A967E1
+58C908068D67C071
+0AF244E13FB60E84
+5B00B7D428DAA6C5
+3E680AF244E13FB6
+8CBDB3E6FBE030F7
+73809262FEF07B22
+C7DC33D5ABE827F9
+1930DA7E5F3F43BA
+F181493D660C2A52
+FCFCC8B2F9456B8D
+B5A4528B0B361EDE
+9FC9493DBA2A52E3
+31FEAFF95861995F
+84A50647482562E4
+3D0811EEE11930DA
+ED3807B7C106FCFC
+EB1FB841DCDF08E5
+493D660C2A524556
+B6010B1D8BC24B16
+A6C5529FC9493DBA
+62E49EDD4B30EAB0
+A9ED3807B7C106FC
+63CD88555E147AFB
+ED3625E8225BA9C1
+1EDE24ED3625E822
+3FB60E84963355B4
+B256B79DFE12DE53
+3ED409B14E6C24F2
+FAE6F51186CF8D27
+DC33D5ABE827F982
+BABC3D54B25C0158
+0C1A4E0C70579D50
+13DEBBD810AC40BF
+639E59929C8C0863
+98A4793D9C2F537F
+F982DE18EF875849
+9C5A67AD8A7840AC
+6404798F9F6C38A8
+7BAE13DEBBD810AC
+BA2A52E3C6487061
+9AF82DD18E0C68FD
+6F0897459D936AC7
+AFA785A7DAB33378
+963355B437FE2ACD
+E11930DA7E5F3F43
+7C2736C901F3FF24
+DEFB3722DF096419
+43D0E12B39582062
+41DCDF08E576BABC
+CE670E1C4BDAEEEF
+5CD1E8EFE808F3FD
+9D5058C908068D67
+04798F9F6C38A891
+4E3F0F6404798F9F
+A566B839BDC7DC33
+90ADFA99DBA4CD36
+FAB4A6A2A566B839
+050B1F1D65FB5D78
+4FE39D01515B00B7
+3830E3E9A967E142
+92CC8904B0C6E267
+A194384AC919F182
+A9D174E8639E5992
+EFE808F3FD6E9C01
+0B1F1D65FB5D7852
+765D0B2EB5560D87
+1127DD422E07D3DF
+974CC752C4A8166E
+1B398C000D9719A1
+77CC90AA19C73D08
+173C05F181493D66
+579D5058C908068D
+121127DD422E07D3
+985046F94E6F5D91
+4E6C24F217AFC12C
+E2AFFAB4A6A2A566
+74929EB85B8CE0A0
+1ABDD3794309EAEA
+C6B0015532FDA9EC
+01B7D4EEBDACBC28
+D409B14E6C24F217
+096CD12AF4C6B001
+2AF4C6B0015532FD
+C901F3FF240FAD64
+A15BB30725F2C492
+30EAB0F02B77CC90
+793D9C2F537FA5DF
+E13FB60E84963355
+D0269B83E2AFFAB4
+16173C05F181493D
+807F40B07650F272
+554C1617AA1B7DA8
+81B3726676CB7DBB
+0D9719A190237BAE
+184370502B16173C
+EC04064B0CCF691D
+4E0C70579D5058C9
+49B4C15B3FAE7F61
+3F0F6404798F9F6C
+70502B16173C05F1
+E1E1B4AE3317463C
+009ADCD2EB1FB841
+493DBA2A52E3C648
+67C071D91E0795BE
+E8639E59929C8C08
+0CCF691DE6907935
+58F2FA4E3F0F6404
+31773C059A90CB65
+0304A15C28B85EDF
+5EA8BF8FEA56FDD6
+0DF7042EAE641057
+DFB5157C2736C901
+1950A6B44D689D4A
+2A52E3C648706101
+30FF6A121127DD42
+F96E53BDBE2CEC52
+E9A967E142E32B7D
+DE18EF875849BC3B
+9E59929C8C0863D3
+BC3D54B25C0158F2
+428EF25C100DF704
+DCDF08E576BABC3D
+2B77CC90AA19C73D
+F94E6F5D912E1CB2
+9D01515B00B7D428
+F574929EB85B8CE0
+D8D4682C053F9332
+5532FDA9EC04064B
+0158F2FA4E3F0F64
+125CD1E8EFE808F3
+BA819F199AF82DD1
+6A124174096CD12A
+68FDAEFFD6204388
+9B9226B12E8C61C8
+B12E8C61C8D31E6C
+3807B7C106FCFCC8
+7C62C491C11B398C
+C9153F449B9226B1
+D31E6CA194384AC9
+7AB9ED2DC9153F44
+D8E2050B1F1D65FB
+E827F982DE18EF87
+DBA4CD36017CABAB
+85F114CCBA145C43
+2F537FA5DF1FC709
+F4C6B0015532FDA9
+58976CE582C32634
+D5ABE827F982DE18
+B85EDFB5157C2736
+064B0CCF691DE690
+1092CC8904B0C6E2
+C054D06577009ADC
+3C1798D0269B83E2
+67823C239D50BF09
+26B12E8C61C8D31E
+ADFA99DBA4CD3601
+85A6D9ABE802C474
+34FCAFA9ED3807B7
+7F40B07650F272ED
+D3DF184370502B16
+DA7E5F3F43BA819F
+DF184370502B1617
+BB915C51A3258C76
+6C67F210E78530CB
+A967E142E32B7DF3
+E582C32634573C17
+F272EDF90C1A4E0C
+237BAE13DEBBD810
+6DFB93B584A50647
+FDAEFFD6204388A3
+A50647482562E49E
+01F3FF240FAD647A
+0928E49A2A1092A1
+D18E0C68FDAEFFD6
+C1A0FDAA48B6010B
+E576BABC3D54B25C
+1798D0269B83E2AF
+33D5ABE827F982DE
+56B79DFE12DE5398
+6CE582C32634573C
+CC90AA19C73D0811
+54D06577009ADCD2
+07D3DF184370502B
+8BC24B16B256B79D
+E8EFE808F3FD6E9C
+24719A973EDB54F0
+0205AE53351E8E7E
+30CB941FBD599369
+DD4B30EAB0F02B77
+B4A6A2A566B839BD
+B7C106FCFCC8B2F9
+0725F2C49288F574
+8D58976CE582C326
+7F61A83DB6554C16
+0811EEE11930DA7E
+AE64105790EB34FC
+AA19C73D0811EEE1
+5C0158F2FA4E3F0F
+ABB46DFB93B584A5
+2E07D3DF18437050
+34573C1798D0269B
+9EB85B8CE0A0D8B6
+C491C11B398C000D
+798F9F6C38A8911F
+32FDA9EC04064B0C
+B9ED2DC9153F449B
+361EDE24ED3625E8
+A12148D0773590AD
+A8911FC749FE231E
+0EC69A1DC5A430FF
+01BBEAB5FE1B0EC6
+A0D8B6BF2B031638
+4AC919F18237CC1E
+449B9226B12E8C61
+DE53985046F94E6F
+350928E49A2A1092
+DF08E576BABC3D54
+37FE2ACD5C793B5B
+010B1D8BC24B16B2
+6CA194384AC919F1
+9226B12E8C61C8D3
+B8F813F021E7FF16
+527086A60CBE6CC4
+67E142E32B7DF380
+1DEA896C15A01330
+FA99DBA4CD36017C
+36C901F3FF240FAD
+8B0B361EDE24ED36
+B59F6E0B0CB42542
+3D13F9F07B64D966
+40B07650F272EDF9
+C106FCFCC8B2F945
+C5A430FF6A121127
+21247DA2D5A1C085
+3D54B25C0158F2FA
+2148D0773590ADFA
+8C61C8D31E6CA194
+1092A12148D07735
+0C70579D5058C908
+09D9125CD1E8EFE8
+D32B98A4793D9C2F
+BBD810AC40BF3FB5
+BDC7DC33D5ABE827
+4388A3C089828CBD
+A8EACC5B7C62C491
+C709457A4FE39D01
+04064B0CCF691DE6
+B656B3500C1092CC
+2A524556D8E2050B
+42E32B7DF3807F40
+3625E8225BA9C1A0
+90EB34FCAFA9ED38
+66EC6C67F210E785
+A9EC04064B0CCF69
+B4C15B3FAE7F61A8
+50F272EDF90C1A4E
+B07650F272EDF90C
+64105790EB34FCAF
+B5157C2736C901F3
+96A1D7AB6138B339
+B85B8CE0A0D8B6BF
+67F210E78530CB94
+6CC4851B3ED409B1
+4370502B16173C05
+2634573C1798D026
+C908068D67C071D9
+B78C814C8EABC1F4
+875849BC3B29536A
+B6BF2B03163830E3
+2EAE64105790EB34
+C9493DBA2A52E3C6
+28E49A2A1092A121
+25428EF25C100DF7
+09457A4FE39D0151
+3F449B9226B12E8C
+CF691DE690793509
+EAB0F02B77CC90AA
+74E8639E59929C8C
+8CE0A0D8B6BF2B03
+BC2FA15BB30725F2
+1B7DA8EACC5B7C62
+E32B7DF3807F40B0
+C73D0811EEE11930
+B6554C1617AA1B7D
+7DF3807F40B07650
+91C11B398C000D97
+7D9A947DA370382D
+490304A15C28B85E
+7087B191CAC74903
+F9456B8D58976CE5
+FF6A121127DD422E
+D81512AEB57982DD
+7FA5DF1FC709457A
+042EAE64105790EB
+54B25C0158F2FA4E
+BDACBC287A74A9D1
+D06577009ADCD2EB
+F210E78530CB941F
+65FB5D78527086A6
+0C1092CC8904B0C6
+2E8C61C8D31E6CA1
+3F43BA819F199AF8
+92A12148D0773590
+09B14E6C24F217AF
+3C239D50BF09D912
+D174E8639E59929C
+3B321CDCADC5601D
+BD2854B8403F7087
+FE231E5EB656B350
+941FBD59936949B4
+2666EBDD351FDB4C
+9A1DC5A430FF6A12
+49BC3B29536A1241
+D810AC40BF3FB59F
+157C2736C901F3FF
+84963355B437FE2A
+FFD6204388A3C089
+66B839BDC7DC33D5
+E030F774B72DBC2F
+EAB5FE1B0EC69A1D
+2736C901F3FF240F
+528B0B361EDE24ED
+6E0B0CB425428EF2
+70579D5058C90806
+E808F3FD6E9C01B7
+398C000D9719A190
+851B3ED409B14E6C
+6949B4C15B3FAE7F
+9288F574929EB85B
+2A1092A12148D077
+7DBD2854B8403F70
+FB75A77DB568B117
+D8B6BF2B03163830
+ACBC287A74A9D174
+B8403F7087B191CA
+F3FD6E9C01B7D4EE
+929C8C0863D32B98
+06F3D1434297FE44
+A4CD36017CABABB4
+B7D4EEBDACBC287A
+DD422E07D3DF1843
+B46DFB93B584A506
+4174096CD12AF4C6
+53985046F94E6F5D
+500C1092CC8904B0
+2854B8403F7087B1
+2FADA9D2C7DFD116
+0B0CB425428EF25C
+2B98A4793D9C2F53
+88F574929EB85B8C
+3DB6554C1617AA1B
+C089828CBDB3E6FB
+E2677DBD2854B840
+90237BAE13DEBBD8
+90AA19C73D0811EE
+DAA6C5529FC9493D
+98D0269B83E2AFFA
+4B16B256B79DFE12
+9C2F537FA5DF1FC7
+E2050B1F1D65FB5D
+5C28B85EDFB5157C
+59936949B4C15B3F
+B437FE2ACD5C793B
+FCC8B2F9456B8D58
+C4851B3ED409B14E
+1DC5A430FF6A1211
+43BA819F199AF82D
+1FC749FE231E5EB6
+C749FE231E5EB656
+39BDC7DC33D5ABE8
+4B0CCF691DE69079
+F244E13FB60E8496
+231E5EB656B3500C
+3355B437FE2ACD5C
+47482562E49EDD4B
+A0FDAA48B6010B1D
+E69079350928E49A
+82C32634573C1798
+70174B4C55081B73
+F3807F40B07650F2
+3EAFC735E87AA7EB
+5C793B5BB5A4528B
+B0F02B77CC90AA19
+5BA9C1A0FDAA48B6
+A83DB6554C1617AA
+8D67C071D91E0795
+457A4FE39D01515B
+BA8A3E680AF244E1
+DE24ED3625E8225B
+27F982DE18EF8758
+D4EEBDACBC287A74
+D12AF4C6B0015532
+677DBD2854B8403F
+015532FDA9EC0406
+E9D181DCF3606E30
+F90C1A4E0C70579D
+7C81AB9730375860
+82DE18EF875849BC
+FD6E9C01B7D4EEBD
+A60CBE6CC4851B3E
+C49288F574929EB8
+08E576BABC3D54B2
+1FC709457A4FE39D
+2B16173C05F18149
+56D8E2050B1F1D65
+568880F8515A74CE
+AA48B6010B1D8BC2
+D0773590ADFA99DB
+2B7DF3807F40B076
+F217AFC12C7E7D8F
+4E6F5D912E1CB2C0
+287A74A9D174E863
+B0015532FDA9EC04
+3D2958F0F4014621
+FDA9EC04064B0CCF
+FB67D02F86DA35A2
+100DF7042EAE6410
+F3FF240FAD647AB9
+AFA785A7DAB33378
+448F839FF4788375
+936949B4C15B3FAE
+BDB3E6FBE030F774
+3FB59F6E0B0CB425
+7086A60CBE6CC485
+B839BDC7DC33D5AB
+5066F764A834474B
+5F3F43BA819F199A
+BF3FB59F6E0B0CB4
+BBEAB5FE1B0EC69A
+B25C0158F2FA4E3F
+B92B2F7E515DCAC1
+9DFE12DE53985046
+6CC2EF9F295C39DB
+5790EB34FCAFA9ED
+8904B0C6E2677DBD
+FBE030F774B72DBC
+DF1FC709457A4FE3
+FF240FAD647AB9ED
+F2C49288F574929E
+E3E9A967E142E32B
+5EB656B3500C1092
+068D67C071D91E07
+10E78530CB941FBD
+5B7C62C491C11B39
+EB34FCAFA9ED3807
+25F2C49288F57492
+74A9D174E8639E59
+3590ADFA99DBA4CD
+6E9C01B7D4EEBDAC
+50BF09D9125CD1E8
+929EB85B8CE0A0D8
+17AA1B7DA8EACC5B
+00B7D428DAA6C552
+CC8904B0C6E2677D
+6C24F217AFC12C7E
+E0A0D8B6BF2B0316
+05F181493D660C2A
+82D6B83D9150F82C
+A430FF6A121127DD
+9F6C38A8911FC749
+5B020E96A536B746
+C648706101BBEAB5
+0B1D8BC24B16B256
+08068D67C071D91E
+000D9719A190237B
+11EEE11930DA7E5F
+6101BBEAB5FE1B0E
+EF875849BC3B2953
+28DAA6C5529FC949
+36017CABABB46DFB
+19F18237CC1E6782
+1F1D65FB5D785270
+B425428EF25C100D
+B7D428DAA6C5529F
+49FE231E5EB656B3
+403F7087B191CAC7
+CD5C793B5BB5A452
+ECC7E9C999843102
+E4148EC936302E93
+30DA7E5F3F43BA81
+37CC1E67823C239D
+3D9C2F537FA5DF1F
+1E67823C239D50BF
+9F199AF82DD18E0C
+9B83E2AFFAB4A6A2
+A9C1A0FDAA48B601
+CC5B7C62C491C11B

+ 11 - 0
picopass/picopass.c

@@ -76,6 +76,12 @@ Picopass* picopass_alloc() {
         PicopassViewByteInput,
         byte_input_get_view(picopass->byte_input));
 
+    // TextBox
+    picopass->text_box = text_box_alloc();
+    view_dispatcher_add_view(
+        picopass->view_dispatcher, PicopassViewTextBox, text_box_get_view(picopass->text_box));
+    picopass->text_box_store = furi_string_alloc();
+
     // Custom Widget
     picopass->widget = widget_alloc();
     view_dispatcher_add_view(
@@ -123,6 +129,11 @@ void picopass_free(Picopass* picopass) {
     view_dispatcher_remove_view(picopass->view_dispatcher, PicopassViewByteInput);
     byte_input_free(picopass->byte_input);
 
+    // TextBox
+    view_dispatcher_remove_view(picopass->view_dispatcher, PicopassViewTextBox);
+    text_box_free(picopass->text_box);
+    furi_string_free(picopass->text_box_store);
+
     // Custom Widget
     view_dispatcher_remove_view(picopass->view_dispatcher, PicopassViewWidget);
     widget_free(picopass->widget);

+ 5 - 2
picopass/picopass_i.h

@@ -16,6 +16,7 @@
 #include <gui/modules/loading.h>
 #include <gui/modules/text_input.h>
 #include <gui/modules/byte_input.h>
+#include <gui/modules/text_box.h>
 #include <gui/modules/widget.h>
 
 #include <input/input.h>
@@ -31,7 +32,7 @@
 #include <assets_icons.h>
 
 #include <nfc/nfc.h>
-#include <nfc/helpers/nfc_dict.h>
+#include <toolbox/keys_dict.h>
 #include "protocol/picopass_poller.h"
 #include "protocol/picopass_listener.h"
 
@@ -90,7 +91,7 @@ struct Picopass {
     Nfc* nfc;
     PicopassPoller* poller;
     PicopassListener* listener;
-    NfcDict* dict;
+    KeysDict* dict;
 
     char text_store[PICOPASS_TEXT_STORE_SIZE];
     FuriString* text_box_store;
@@ -102,6 +103,7 @@ struct Picopass {
     Loading* loading;
     TextInput* text_input;
     ByteInput* byte_input;
+    TextBox* text_box;
     Widget* widget;
     DictAttack* dict_attack;
     Loclass* loclass;
@@ -117,6 +119,7 @@ typedef enum {
     PicopassViewLoading,
     PicopassViewTextInput,
     PicopassViewByteInput,
+    PicopassViewTextBox,
     PicopassViewWidget,
     PicopassViewDictAttack,
     PicopassViewLoclass,

+ 2 - 1
picopass/scenes/picopass_scene_card_menu.c

@@ -23,8 +23,9 @@ void picopass_scene_card_menu_on_enter(void* context) {
     PicopassBlock* AA1 = picopass->dev->dev_data.AA1;
 
     bool sio = 0x30 == AA1[PICOPASS_ICLASS_PACS_CFG_BLOCK_INDEX].data[0];
+    bool no_key = picopass_is_memset(pacs->key, 0x00, PICOPASS_BLOCK_LEN);
 
-    if(pacs->se_enabled) {
+    if(no_key) {
         if(sio) {
             submenu_add_item(
                 submenu,

+ 1 - 0
picopass/scenes/picopass_scene_config.h

@@ -20,3 +20,4 @@ ADD_SCENE(picopass, emulate, Emulate)
 ADD_SCENE(picopass, loclass, Loclass)
 ADD_SCENE(picopass, key_input, KeyInput)
 ADD_SCENE(picopass, nr_mac_saved, NrMacSaved)
+ADD_SCENE(picopass, more_info, MoreInfo)

+ 9 - 0
picopass/scenes/picopass_scene_device_info.c

@@ -77,6 +77,12 @@ void picopass_scene_device_info_on_enter(void* context) {
         "Back",
         picopass_scene_device_info_widget_callback,
         picopass);
+    widget_add_button_element(
+        picopass->widget,
+        GuiButtonTypeRight,
+        "More",
+        picopass_scene_device_info_widget_callback,
+        picopass);
 
     view_dispatcher_switch_to_view(picopass->view_dispatcher, PicopassViewWidget);
 }
@@ -88,6 +94,9 @@ bool picopass_scene_device_info_on_event(void* context, SceneManagerEvent event)
     if(event.type == SceneManagerEventTypeCustom) {
         if(event.event == GuiButtonTypeLeft) {
             consumed = scene_manager_previous_scene(picopass->scene_manager);
+        } else if(event.event == GuiButtonTypeRight) {
+            scene_manager_next_scene(picopass->scene_manager, PicopassSceneMoreInfo);
+            consumed = true;
         } else if(event.event == PicopassCustomEventViewExit) {
             view_dispatcher_switch_to_view(picopass->view_dispatcher, PicopassViewWidget);
             consumed = true;

+ 21 - 19
picopass/scenes/picopass_scene_elite_dict_attack.c

@@ -22,26 +22,26 @@ static bool picopass_elite_dict_attack_change_dict(Picopass* picopass) {
     do {
         uint32_t scene_state =
             scene_manager_get_scene_state(picopass->scene_manager, PicopassSceneEliteDictAttack);
-        nfc_dict_free(picopass->dict);
+        keys_dict_free(picopass->dict);
         picopass->dict = NULL;
         if(scene_state == PicopassSceneEliteDictAttackDictElite) break;
         if(scene_state == PicopassSceneEliteDictAttackDictEliteUser) {
-            if(!nfc_dict_check_presence(PICOPASS_ICLASS_STANDARD_DICT_FLIPPER_NAME)) break;
-            picopass->dict = nfc_dict_alloc(
+            if(!keys_dict_check_presence(PICOPASS_ICLASS_STANDARD_DICT_FLIPPER_NAME)) break;
+            picopass->dict = keys_dict_alloc(
                 PICOPASS_ICLASS_STANDARD_DICT_FLIPPER_NAME,
-                NfcDictModeOpenExisting,
+                KeysDictModeOpenExisting,
                 PICOPASS_KEY_LEN);
             scene_state = PicopassSceneEliteDictAttackDictStandard;
         } else if(scene_state == PicopassSceneEliteDictAttackDictStandard) {
-            if(!nfc_dict_check_presence(PICOPASS_ICLASS_ELITE_DICT_FLIPPER_NAME)) break;
-            picopass->dict = nfc_dict_alloc(
+            if(!keys_dict_check_presence(PICOPASS_ICLASS_ELITE_DICT_FLIPPER_NAME)) break;
+            picopass->dict = keys_dict_alloc(
                 PICOPASS_ICLASS_ELITE_DICT_FLIPPER_NAME,
-                NfcDictModeOpenExisting,
+                KeysDictModeOpenExisting,
                 PICOPASS_KEY_LEN);
             scene_state = PicopassSceneEliteDictAttackDictElite;
         }
         picopass->dict_attack_ctx.card_detected = true;
-        picopass->dict_attack_ctx.total_keys = nfc_dict_get_total_keys(picopass->dict);
+        picopass->dict_attack_ctx.total_keys = keys_dict_get_total_keys(picopass->dict);
         picopass->dict_attack_ctx.current_key = 0;
         picopass->dict_attack_ctx.name = picopass_dict_name[scene_state];
         scene_manager_set_scene_state(
@@ -63,9 +63,9 @@ NfcCommand picopass_elite_dict_attack_worker_callback(PicopassPollerEvent event,
     } else if(event.type == PicopassPollerEventTypeRequestKey) {
         uint8_t key[PICOPASS_KEY_LEN] = {};
         bool is_key_provided = true;
-        if(!nfc_dict_get_next_key(picopass->dict, key, PICOPASS_KEY_LEN)) {
+        if(!keys_dict_get_next_key(picopass->dict, key, PICOPASS_KEY_LEN)) {
             if(picopass_elite_dict_attack_change_dict(picopass)) {
-                is_key_provided = nfc_dict_get_next_key(picopass->dict, key, PICOPASS_KEY_LEN);
+                is_key_provided = keys_dict_get_next_key(picopass->dict, key, PICOPASS_KEY_LEN);
                 view_dispatcher_send_custom_event(
                     picopass->view_dispatcher, PicopassCustomEventDictAttackUpdateView);
             } else {
@@ -137,24 +137,26 @@ void picopass_scene_elite_dict_attack_on_enter(void* context) {
     // Setup dict attack context
     uint32_t state = PicopassSceneEliteDictAttackDictEliteUser;
 
-    bool use_user_dict = nfc_dict_check_presence(PICOPASS_ICLASS_ELITE_DICT_USER_NAME);
+    bool use_user_dict = keys_dict_check_presence(PICOPASS_ICLASS_ELITE_DICT_USER_NAME);
     if(use_user_dict) {
-        picopass->dict = nfc_dict_alloc(
-            PICOPASS_ICLASS_ELITE_DICT_USER_NAME, NfcDictModeOpenExisting, PICOPASS_KEY_LEN);
-        if(nfc_dict_get_total_keys(picopass->dict) == 0) {
-            nfc_dict_free(picopass->dict);
+        picopass->dict = keys_dict_alloc(
+            PICOPASS_ICLASS_ELITE_DICT_USER_NAME, KeysDictModeOpenExisting, PICOPASS_KEY_LEN);
+        if(keys_dict_get_total_keys(picopass->dict) == 0) {
+            keys_dict_free(picopass->dict);
             use_user_dict = false;
         }
     }
     if(use_user_dict) {
         state = PicopassSceneEliteDictAttackDictEliteUser;
     } else {
-        picopass->dict = nfc_dict_alloc(
-            PICOPASS_ICLASS_STANDARD_DICT_FLIPPER_NAME, NfcDictModeOpenExisting, PICOPASS_KEY_LEN);
+        picopass->dict = keys_dict_alloc(
+            PICOPASS_ICLASS_STANDARD_DICT_FLIPPER_NAME,
+            KeysDictModeOpenExisting,
+            PICOPASS_KEY_LEN);
         state = PicopassSceneEliteDictAttackDictStandard;
     }
     picopass->dict_attack_ctx.card_detected = true;
-    picopass->dict_attack_ctx.total_keys = nfc_dict_get_total_keys(picopass->dict);
+    picopass->dict_attack_ctx.total_keys = keys_dict_get_total_keys(picopass->dict);
     picopass->dict_attack_ctx.current_key = 0;
     picopass->dict_attack_ctx.name = picopass_dict_name[state];
     scene_manager_set_scene_state(picopass->scene_manager, PicopassSceneEliteDictAttack, state);
@@ -218,7 +220,7 @@ void picopass_scene_elite_dict_attack_on_exit(void* context) {
     Picopass* picopass = context;
 
     if(picopass->dict) {
-        nfc_dict_free(picopass->dict);
+        keys_dict_free(picopass->dict);
         picopass->dict = NULL;
     }
     picopass->dict_attack_ctx.current_key = 0;

+ 50 - 0
picopass/scenes/picopass_scene_more_info.c

@@ -0,0 +1,50 @@
+#include "../picopass_i.h"
+#include <dolphin/dolphin.h>
+
+void picopass_scene_more_info_widget_callback(GuiButtonType result, InputType type, void* context) {
+    Picopass* picopass = context;
+    if(type == InputTypeShort) {
+        view_dispatcher_send_custom_event(picopass->view_dispatcher, result);
+    }
+}
+
+void picopass_scene_more_info_on_enter(void* context) {
+    Picopass* picopass = context;
+    PicopassBlock* AA1 = picopass->dev->dev_data.AA1;
+
+    furi_string_reset(picopass->text_box_store);
+
+    size_t app_limit = MIN(AA1[PICOPASS_CONFIG_BLOCK_INDEX].data[0], PICOPASS_MAX_APP_LIMIT);
+    FuriString* str = picopass->text_box_store;
+
+    for(size_t i = 0; i < app_limit; i++) {
+        for(size_t j = 0; j < PICOPASS_BLOCK_LEN; j += 2) {
+            furi_string_cat_printf(str, "%02X%02X ", AA1[i].data[j], AA1[i].data[j + 1]);
+        }
+    }
+
+    text_box_set_font(picopass->text_box, TextBoxFontHex);
+    text_box_set_text(picopass->text_box, furi_string_get_cstr(picopass->text_box_store));
+    view_dispatcher_switch_to_view(picopass->view_dispatcher, PicopassViewTextBox);
+}
+
+bool picopass_scene_more_info_on_event(void* context, SceneManagerEvent event) {
+    Picopass* picopass = context;
+    bool consumed = false;
+
+    if(event.type == SceneManagerEventTypeCustom) {
+        if(event.event == GuiButtonTypeLeft) {
+            consumed = scene_manager_previous_scene(picopass->scene_manager);
+        }
+    } else if(event.type == SceneManagerEventTypeBack) {
+        consumed = scene_manager_previous_scene(picopass->scene_manager);
+    }
+    return consumed;
+}
+
+void picopass_scene_more_info_on_exit(void* context) {
+    Picopass* picopass = context;
+
+    // Clear views
+    widget_reset(picopass->widget);
+}

+ 9 - 9
picopass/scenes/picopass_scene_read_card.c

@@ -13,13 +13,13 @@ static bool picopass_read_card_change_dict(Picopass* picopass) {
     do {
         uint32_t scene_state =
             scene_manager_get_scene_state(picopass->scene_manager, PicopassSceneReadCard);
-        nfc_dict_free(picopass->dict);
+        keys_dict_free(picopass->dict);
         picopass->dict = NULL;
         if(scene_state == PicopassSceneReadCardDictElite) break;
-        if(!nfc_dict_check_presence(PICOPASS_ICLASS_ELITE_DICT_FLIPPER_NAME)) break;
+        if(!keys_dict_check_presence(PICOPASS_ICLASS_ELITE_DICT_FLIPPER_NAME)) break;
 
-        picopass->dict = nfc_dict_alloc(
-            PICOPASS_ICLASS_ELITE_DICT_FLIPPER_NAME, NfcDictModeOpenExisting, PICOPASS_KEY_LEN);
+        picopass->dict = keys_dict_alloc(
+            PICOPASS_ICLASS_ELITE_DICT_FLIPPER_NAME, KeysDictModeOpenExisting, PICOPASS_KEY_LEN);
         scene_manager_set_scene_state(
             picopass->scene_manager, PicopassSceneReadCard, PicopassSceneReadCardDictElite);
         success = true;
@@ -39,9 +39,9 @@ NfcCommand picopass_read_card_worker_callback(PicopassPollerEvent event, void* c
     } else if(event.type == PicopassPollerEventTypeRequestKey) {
         uint8_t key[PICOPASS_KEY_LEN] = {};
         bool is_key_provided = true;
-        if(!nfc_dict_get_next_key(picopass->dict, key, PICOPASS_KEY_LEN)) {
+        if(!keys_dict_get_next_key(picopass->dict, key, PICOPASS_KEY_LEN)) {
             if(picopass_read_card_change_dict(picopass)) {
-                is_key_provided = nfc_dict_get_next_key(picopass->dict, key, PICOPASS_KEY_LEN);
+                is_key_provided = keys_dict_get_next_key(picopass->dict, key, PICOPASS_KEY_LEN);
             } else {
                 is_key_provided = false;
             }
@@ -75,8 +75,8 @@ void picopass_scene_read_card_on_enter(void* context) {
     popup_set_header(popup, "Detecting\npicopass\ncard", 68, 30, AlignLeft, AlignTop);
     popup_set_icon(popup, 0, 3, &I_RFIDDolphinReceive_97x61);
 
-    picopass->dict = nfc_dict_alloc(
-        PICOPASS_ICLASS_STANDARD_DICT_FLIPPER_NAME, NfcDictModeOpenExisting, PICOPASS_KEY_LEN);
+    picopass->dict = keys_dict_alloc(
+        PICOPASS_ICLASS_STANDARD_DICT_FLIPPER_NAME, KeysDictModeOpenExisting, PICOPASS_KEY_LEN);
     scene_manager_set_scene_state(
         picopass->scene_manager, PicopassSceneReadCard, PicopassSceneReadCardDictStandard);
     // Start worker
@@ -111,7 +111,7 @@ void picopass_scene_read_card_on_exit(void* context) {
     Picopass* picopass = context;
 
     if(picopass->dict) {
-        nfc_dict_free(picopass->dict);
+        keys_dict_free(picopass->dict);
         picopass->dict = NULL;
     }
     picopass_poller_stop(picopass->poller);

+ 24 - 12
picopass/scenes/picopass_scene_read_card_success.c

@@ -43,7 +43,8 @@ void picopass_scene_read_card_success_on_enter(void* context) {
         AA1[PICOPASS_ICLASS_PACS_CFG_BLOCK_INDEX].data, 0x00, PICOPASS_BLOCK_LEN);
     bool empty = picopass_is_memset(
         AA1[PICOPASS_ICLASS_PACS_CFG_BLOCK_INDEX].data, 0xFF, PICOPASS_BLOCK_LEN);
-    bool sio = 0x30 == AA1[PICOPASS_ICLASS_PACS_CFG_BLOCK_INDEX].data[0];
+    bool SE = 0x30 == AA1[PICOPASS_ICLASS_PACS_CFG_BLOCK_INDEX].data[0];
+    bool configCard = (AA1[PICOPASS_ICLASS_PACS_CFG_BLOCK_INDEX].data[7] >> 2 & 3) == 2;
 
     if(no_key) {
         furi_string_cat_printf(wiegand_str, "Read Failed");
@@ -51,13 +52,6 @@ void picopass_scene_read_card_success_on_enter(void* context) {
 
         if(pacs->se_enabled) {
             furi_string_cat_printf(credential_str, "SE enabled");
-
-            widget_add_button_element(
-                widget,
-                GuiButtonTypeRight,
-                "More",
-                picopass_scene_read_card_success_widget_callback,
-                picopass);
         } else if(!hid_csn) {
             furi_string_cat_printf(credential_str, "Non-HID CSN");
         }
@@ -68,6 +62,23 @@ void picopass_scene_read_card_success_on_enter(void* context) {
             "Menu",
             picopass_scene_read_card_success_widget_callback,
             picopass);
+        widget_add_button_element(
+            widget,
+            GuiButtonTypeRight,
+            "More",
+            picopass_scene_read_card_success_widget_callback,
+            picopass);
+    } else if(pacs->se_enabled) {
+        furi_string_cat_printf(credential_str, "SE enabled");
+        furi_string_cat_printf(wiegand_str, "SIO");
+        widget_add_button_element(
+            widget,
+            GuiButtonTypeRight,
+            "More",
+            picopass_scene_read_card_success_widget_callback,
+            picopass);
+    } else if(configCard) {
+        furi_string_cat_printf(wiegand_str, "Config Card");
     } else if(empty) {
         furi_string_cat_printf(wiegand_str, "Empty");
         widget_add_button_element(
@@ -78,14 +89,11 @@ void picopass_scene_read_card_success_on_enter(void* context) {
             picopass);
     } else if(pacs->bitLength == 0 || pacs->bitLength == 255) {
         // Neither of these are valid.  Indicates the block was all 0x00 or all 0xff
-        if(sio) {
+        if(SE) {
             furi_string_cat_printf(wiegand_str, "SIO");
         } else {
             furi_string_cat_printf(wiegand_str, "Invalid PACS");
         }
-        if(pacs->se_enabled) {
-            furi_string_cat_printf(credential_str, "SE enabled");
-        }
         widget_add_button_element(
             widget,
             GuiButtonTypeCenter,
@@ -187,6 +195,10 @@ bool picopass_scene_read_card_success_on_event(void* context, SceneManagerEvent
             consumed = scene_manager_search_and_switch_to_another_scene(
                 picopass->scene_manager, PicopassSceneStart);
         }
+    } else if(event.type == SceneManagerEventTypeBack) {
+        scene_manager_search_and_switch_to_previous_scene(
+            picopass->scene_manager, PicopassSceneStart);
+        consumed = true;
     }
     return consumed;
 }