Compare commits

...

154 commits
v7.0 ... main

Author SHA1 Message Date
Pol Henarejos
4df616082e
Fix led for pimoroni boards.
Signed-off-by: Pol Henarejos <pol.henarejos@cttc.es>
2025-12-27 22:03:35 +01:00
Pol Henarejos
3bf035d68a
Zeroize pkey
Signed-off-by: Pol Henarejos <pol.henarejos@cttc.es>
2025-12-27 22:02:58 +01:00
Pol Henarejos
7dc7be0909
Add device public key recovery and upload attestation certification.
Signed-off-by: Pol Henarejos <pol.henarejos@cttc.es>
2025-12-15 14:34:04 +01:00
Pol Henarejos
015fb61759
Add sign with keydev to rescue.
Signed-off-by: Pol Henarejos <pol.henarejos@cttc.es>
2025-12-15 01:17:26 +01:00
Pol Henarejos
1f4d638119
Build minimal picokey app.
Signed-off-by: Pol Henarejos <pol.henarejos@cttc.es>
2025-12-14 18:45:02 +01:00
Pol Henarejos
05fe0596ef
Revert "Move EDDSA to another branch."
This reverts commit 09ec0767b6.
2025-12-11 15:42:30 +01:00
Pol Henarejos
d86371bb2c
Revert "Move Secure Boot to another branch."
This reverts commit 8cb2484aa3.
2025-12-11 15:42:21 +01:00
Pol Henarejos
8cb2484aa3
Move Secure Boot to another branch.
Signed-off-by: Pol Henarejos <pol.henarejos@cttc.es>
2025-12-09 21:37:36 +01:00
Pol Henarejos
7583ecff18
Fix applet cmp
Signed-off-by: Pol Henarejos <pol.henarejos@cttc.es>
2025-12-09 19:15:22 +01:00
Pol Henarejos
09ec0767b6
Move EDDSA to another branch.
Signed-off-by: Pol Henarejos <pol.henarejos@cttc.es>
2025-12-09 15:36:29 +01:00
Pol Henarejos
d0dea3d0c5
Fix MSOS/BOS descriptor.
Signed-off-by: Pol Henarejos <pol.henarejos@cttc.es>
2025-12-03 16:34:05 +01:00
Pol Henarejos
53d3a7ac91
Fix OTP button press in ESP32.
Signed-off-by: Pol Henarejos <pol.henarejos@cttc.es>
2025-12-02 14:38:07 +01:00
Pol Henarejos
2438356d83
Set anti-rollback version only when the binary is signed.
Signed-off-by: Pol Henarejos <pol.henarejos@cttc.es>
2025-12-02 09:39:17 +01:00
Pol Henarejos
79b69bfd7e
Add WHOLE_ARCHIVE property.
Signed-off-by: Pol Henarejos <pol.henarejos@cttc.es>
2025-12-02 09:29:34 +01:00
Pol Henarejos
d189c2978c
Add anti-rollback argument.
Signed-off-by: Pol Henarejos <pol.henarejos@cttc.es>
2025-12-01 23:41:29 +01:00
Pol Henarejos
c1cc33fd9d
Upodate mbedtls only when necessary.
Signed-off-by: Pol Henarejos <pol.henarejos@cttc.es>
2025-12-01 17:02:47 +01:00
Pol Henarejos
2d72a157d5
Fix on AID selection. It should support shorter AID if matches.
Signed-off-by: Pol Henarejos <pol.henarejos@cttc.es>
2025-12-01 01:44:29 +01:00
Pol Henarejos
711a4df490
Upgrade to v8.0
Signed-off-by: Pol Henarejos <pol.henarejos@cttc.es>
2025-11-30 18:30:24 +01:00
Pol Henarejos
66f31c15b6
Upgrade to mbedtls v3.6.5
Signed-off-by: Pol Henarejos <pol.henarejos@cttc.es>
2025-11-30 18:28:13 +01:00
Pol Henarejos
fa119d0c6e
Fix build for ESP32.
Signed-off-by: Pol Henarejos <pol.henarejos@cttc.es>
2025-11-28 00:12:26 +01:00
Pol Henarejos
b67e9ac143
Fix key generation for RP2040.
Signed-off-by: Pol Henarejos <pol.henarejos@cttc.es>
2025-11-28 00:12:18 +01:00
Pol Henarejos
5d3d10b62b
Fix declaration.
Signed-off-by: Pol Henarejos <pol.henarejos@cttc.es>
2025-11-28 00:12:06 +01:00
Pol Henarejos
27938f0d9b
Add reboot bootsel command.
Signed-off-by: Pol Henarejos <pol.henarejos@cttc.es>
2025-11-28 00:11:54 +01:00
Pol Henarejos
20117d1609
Add read secure boot status.
Signed-off-by: Pol Henarejos <pol.henarejos@cttc.es>
2025-11-18 01:06:44 +01:00
Pol Henarejos
8f4f5373cf
Do not use secboot in Phy.
Signed-off-by: Pol Henarejos <pol.henarejos@cttc.es>
2025-11-18 01:06:31 +01:00
Pol Henarejos
d4971bba19
Fix get secure boot status.
Signed-off-by: Pol Henarejos <pol.henarejos@cttc.es>
2025-11-18 01:06:20 +01:00
Pol Henarejos
2001006a16
Fix otp build.
Signed-off-by: Pol Henarejos <pol.henarejos@cttc.es>
2025-11-17 12:23:16 +01:00
Pol Henarejos
7c5f729b69
Add is_secure_boot_enable and is_secure_lock_enabled to PHY.
Signed-off-by: Pol Henarejos <pol.henarejos@cttc.es>
2025-11-17 12:20:44 +01:00
Pol Henarejos
07bbadf34c
Add support for reading memory status.
Signed-off-by: Pol Henarejos <pol.henarejos@cttc.es>
2025-11-17 11:52:25 +01:00
Pol Henarejos
ed848d005f
Fix curious bug when FIDO+OpenPGP+CCID connection is used in some circumstances.
Signed-off-by: Pol Henarejos <pol.henarejos@cttc.es>
2025-11-15 21:12:47 +01:00
Pol Henarejos
e6c0227996
Fix VIDPID PHY Read.
Signed-off-by: Pol Henarejos <pol.henarejos@cttc.es>
2025-11-15 21:11:57 +01:00
Pol Henarejos
84f7952817
Add support for PHY read.
Signed-off-by: Pol Henarejos <pol.henarejos@cttc.es>
2025-11-15 20:13:42 +01:00
Pol Henarejos
116aca7697
Fix #if/else logic.
Signed-off-by: Pol Henarejos <pol.henarejos@cttc.es>
2025-11-15 20:13:42 +01:00
Pol Henarejos
d410a4cfc2
Add support for RP2354.
Signed-off-by: Pol Henarejos <pol.henarejos@cttc.es>
2025-11-15 19:56:46 +01:00
Pol Henarejos
9b6d6f6736
Fix build
Signed-off-by: Pol Henarejos <pol.henarejos@cttc.es>
2025-10-28 09:36:41 +01:00
Pol Henarejos
8f907b25ba
Relicense project under the GNU Affero General Public License v3 (AGPLv3)
and add the Enterprise / Commercial licensing option.

Main changes:
- Replace GPLv3 headers with AGPLv3 headers in source files.
- Update LICENSE file to the full AGPLv3 text.
- Add ENTERPRISE.md describing the dual-licensing model:
  * Community Edition: AGPLv3 (strong copyleft, including network use).
  * Enterprise / Commercial Edition: proprietary license for production /
    multi-user / OEM use without the obligation to disclose derivative code.
- Update README with a new "License and Commercial Use" section pointing to
  ENTERPRISE.md and clarifying how companies can obtain a commercial license.

Why this change:
- AGPLv3 ensures that modified versions offered as a service or deployed
  in production environments must provide corresponding source code.
- The Enterprise / Commercial edition provides organizations with an
  alternative proprietary license that allows internal, large-scale, or OEM
  use (bulk provisioning, policy enforcement, inventory / revocation,
  custom attestation, signed builds) without AGPL disclosure obligations.

This commit formally marks the first release that is dual-licensed:
AGPLv3 for the Community Edition and a proprietary commercial license
for Enterprise customers.

Signed-off-by: Pol Henarejos <pol.henarejos@cttc.es>
2025-10-26 20:06:16 +01:00
Pol Henarejos
233e6594c6
Add casts to fix warnings.
Signed-off-by: Pol Henarejos <pol.henarejos@cttc.es>
2025-10-12 18:52:07 +02:00
Pol Henarejos
eca6807f8e
Fix win build.
Signed-off-by: Pol Henarejos <pol.henarejos@cttc.es>
2025-10-12 18:51:46 +02:00
Pol Henarejos
14d5a75571
Add some win compatibility.
Signed-off-by: Pol Henarejos <pol.henarejos@cttc.es>
2025-10-12 18:51:29 +02:00
Pol Henarejos
e56624948b
Expose gettimeofday.
Signed-off-by: Pol Henarejos <pol.henarejos@cttc.es>
2025-10-12 18:47:43 +02:00
Pol Henarejos
200d59f91b
ADd strlcpy when necessary.
Signed-off-by: Pol Henarejos <pol.henarejos@cttc.es>
2025-10-12 18:47:34 +02:00
Pol Henarejos
c165ae4838
Add set of secure functions to derive keys based on OTP, if available, and pico_serial as a fallback. PIN is also an input vector, which defines a separated domain.
Signed-off-by: Pol Henarejos <pol.henarejos@cttc.es>
2025-10-08 00:30:41 +02:00
Pol Henarejos
0ddfdf8134
Add sanity check.
Signed-off-by: Pol Henarejos <pol.henarejos@cttc.es>
2025-10-07 21:11:28 +02:00
Pol Henarejos
031d76737b
Add pico_serial_hash as a source of unique (almost) 32 bytes string.
Signed-off-by: Pol Henarejos <pol.henarejos@cttc.es>
2025-10-07 21:11:06 +02:00
Pol Henarejos
df94d10f8f
Fix print macro.
Signed-off-by: Pol Henarejos <pol.henarejos@cttc.es>
2025-10-07 21:10:19 +02:00
Pol Henarejos
b3b2b67034
Add const to OTP functions.
Signed-off-by: Pol Henarejos <pol.henarejos@cttc.es>
2025-10-06 14:21:41 +02:00
Pol Henarejos
3eff2442c6
Fix is_empty_otp_buffer when a register is invalid.
Signed-off-by: Pol Henarejos <pol.henarejos@cttc.es>
2025-10-06 14:21:41 +02:00
Pol Henarejos
a7e1cf028b
To prevent the PVC attack, MKEK and DEV keys are migrated to another OTP page.
Signed-off-by: Pol Henarejos <pol.henarejos@cttc.es>
2025-10-06 14:21:41 +02:00
Pol Henarejos
e14a12b002
Add OTP chaff to avoid passive voltage contrast (PVC) attacks.
Signed-off-by: Pol Henarejos <pol.henarejos@cttc.es>
2025-10-06 14:21:41 +02:00
Pol Henarejos
d39732c613
Allow data partition write only with secure code (not in BL).
Signed-off-by: Pol Henarejos <pol.henarejos@cttc.es>
2025-10-06 14:21:41 +02:00
Pol Henarejos
56c2ef0cc1
Fix alignment when programming OTP.
Signed-off-by: Pol Henarejos <pol.henarejos@cttc.es>
2025-10-06 14:21:41 +02:00
Pol Henarejos
9b294b9685
Fix build
Signed-off-by: Pol Henarejos <pol.henarejos@cttc.es>
2025-09-30 17:25:55 +02:00
Pol Henarejos
5048e07f81
Add hash functions using OTP as feed when available.
Signed-off-by: Pol Henarejos <pol.henarejos@cttc.es>
2025-09-28 20:28:28 +02:00
Pol Henarejos
d63ed56e0e
Fix phy_data idVendor/idProduct when not set.
Signed-off-by: Pol Henarejos <pol.henarejos@cttc.es>
2025-09-28 20:28:28 +02:00
Pol Henarejos
afe2b28fab
Merge remote-tracking branch 'origin/main' 2025-09-24 01:12:07 +02:00
Pol Henarejos
838f342877
Fix HID processing only for CTAP_HID.
Signed-off-by: Pol Henarejos <pol.henarejos@cttc.es>
2025-09-24 01:11:45 +02:00
Pol Henarejos
1a1d03ab2f
Add compatibility for non-pico boards.
Signed-off-by: Pol Henarejos <pol.henarejos@cttc.es>
2025-09-24 01:11:19 +02:00
Pol Henarejos
809dc3d16d
Add missing files.
Signed-off-by: Pol Henarejos <pol.henarejos@cttc.es>
2025-09-23 17:03:38 +02:00
Pol Henarejos
70c0c1bf81
Fix conditional build for non-pico platforms.
Signed-off-by: Pol Henarejos <pol.henarejos@cttc.es>
2025-09-23 16:59:59 +02:00
Pol Henarejos
cff3f8f677
Fix interface conditional builds.
Signed-off-by: Pol Henarejos <pol.henarejos@cttc.es>
2025-09-23 16:56:34 +02:00
Pol Henarejos
6f6004c57b
Fix build for non-pico boards.
Signed-off-by: Pol Henarejos <pol.henarejos@cttc.es>
2025-09-23 00:02:20 +02:00
Pol Henarejos
0b49fe4e1b
Fix build for non-pico boards.
Signed-off-by: Pol Henarejos <pol.henarejos@cttc.es>
2025-09-22 23:52:47 +02:00
Pol Henarejos
4edc506759
Fix build for non-pico boards.
Signed-off-by: Pol Henarejos <pol.henarejos@cttc.es>
2025-09-22 23:35:46 +02:00
Pol Henarejos
e55014cfb3
Fix set version for non-pico platforms.
Signed-off-by: Pol Henarejos <pol.henarejos@cttc.es>
2025-09-22 17:31:48 +02:00
Pol Henarejos
2211fafe32
Fix non-pico build.
Signed-off-by: Pol Henarejos <pol.henarejos@cttc.es>
2025-09-22 17:30:39 +02:00
Pol Henarejos
276f1b2ae8
Fix build for non-pico platforms.
Signed-off-by: Pol Henarejos <pol.henarejos@cttc.es>
2025-09-22 17:27:08 +02:00
Pol Henarejos
202d32d13d
Fix descriptor description when there are disabled interfaces.
Signed-off-by: Pol Henarejos <pol.henarejos@cttc.es>
2025-09-02 01:20:07 +02:00
Pol Henarejos
95f02b6ea7
Add dummy led driver to avoid crashes in case a non-supported board is built.
Signed-off-by: Pol Henarejos <pol.henarejos@cttc.es>
2025-09-01 22:02:08 +02:00
Pol Henarejos
2e2b78445c
Load led driver depending on PHY.
Signed-off-by: Pol Henarejos <pol.henarejos@cttc.es>
2025-09-01 21:27:43 +02:00
Pol Henarejos
da44fd21d4
Add support for led driver in PHY.
Signed-off-by: Pol Henarejos <pol.henarejos@cttc.es>
2025-09-01 21:27:15 +02:00
Pol Henarejos
365567d12b
Upgrade tinycbor to 0.6.1
Signed-off-by: Pol Henarejos <pol.henarejos@cttc.es>
2025-08-29 01:20:09 +02:00
Pol Henarejos
a3406572cd
Fix uint16 endianness that affected chained RAPDU.
Signed-off-by: Pol Henarejos <pol.henarejos@cttc.es>
2025-08-29 01:17:37 +02:00
Pol Henarejos
8321db1f67
Fix build for rp2350.
Signed-off-by: Pol Henarejos <pol.henarejos@cttc.es>
2025-08-25 01:39:06 +02:00
Pol Henarejos
5984d1f72d
NK compatibility improvements.
Signed-off-by: Pol Henarejos <pol.henarejos@cttc.es>
2025-08-25 01:33:46 +02:00
Pol Henarejos
685e660ec0
Call pico_sdk_init in the cmake.
Signed-off-by: Pol Henarejos <pol.henarejos@cttc.es>
2025-08-25 01:33:23 +02:00
Pol Henarejos
3863842536
Fix crash in case response buffer is not 16bit aligned.
Signed-off-by: Pol Henarejos <pol.henarejos@cttc.es>
2025-08-24 01:22:59 +02:00
Pol Henarejos
113e720fca
Merge remote-tracking branch 'origin/main' 2025-06-22 19:58:17 +02:00
Pol Henarejos
c45c97ee1f
Fix Pico Keys SDK build.
Signed-off-by: Pol Henarejos <pol.henarejos@cttc.es>
2025-06-22 19:57:15 +02:00
Pol Henarejos
d66d1c85b9
Add missing header.
Signed-off-by: Pol Henarejos <pol.henarejos@cttc.es>
2025-06-22 19:52:36 +02:00
Pol Henarejos
f01aca5518
Flash size is obtained dynamically rather than in build time. It will allow to reduce dramatically the number of builds.
Signed-off-by: Pol Henarejos <pol.henarejos@cttc.es>
2025-05-30 12:06:26 +02:00
Pol Henarejos
da3a7f25d0
Fix bool build.
Signed-off-by: Pol Henarejos <pol.henarejos@cttc.es>
2025-05-25 19:20:04 +02:00
Pol Henarejos
eb75ad4efa
Add app_exists() to check if an AID is loaded. 2025-05-25 19:07:20 +02:00
Pol Henarejos
11d8a5343c
Remove the tweak for packets multiple of 64 bytes. It was fixed in the USB stack handling (don't remember where).
Fixes #95.

Signed-off-by: Pol Henarejos <pol.henarejos@cttc.es>
2025-05-23 20:17:57 +02:00
Pol Henarejos
a324477a8a
Fix interface descriptor when HID is disabled.
Signed-off-by: Pol Henarejos <pol.henarejos@cttc.es>
2025-05-02 18:28:38 +02:00
Pol Henarejos
580b0acffa
Define MCU for emulation.
Signed-off-by: Pol Henarejos <pol.henarejos@cttc.es>
2025-04-07 01:24:03 +02:00
Pol Henarejos
3990e7643a
Fix EPNUM counting for ESP32. It fixes the problem of not sending KB.
Signed-off-by: Pol Henarejos <pol.henarejos@cttc.es>
2025-04-06 18:31:01 +02:00
Pol Henarejos
5718c83083
Upgrade TinyUSB for ESP32
Signed-off-by: Pol Henarejos <pol.henarejos@cttc.es>
2025-04-06 18:26:34 +02:00
Pol Henarejos
a75fd6b815
CTAP_RESP should be 0ed before sending.
Signed-off-by: Pol Henarejos <pol.henarejos@cttc.es>
2025-03-30 18:12:06 +02:00
Pol Henarejos
499e8fafaa
Upgrade to mbedtls v3.6.3 and fix git subscripts.
Signed-off-by: Pol Henarejos <pol.henarejos@cttc.es>
2025-03-24 23:58:53 +01:00
Pol Henarejos
5f79a8c8ed
Fix ESP32 dynamic USB interfaces.
Signed-off-by: Pol Henarejos <pol.henarejos@cttc.es>
2025-03-24 09:22:25 +01:00
Pol Henarejos
a08abaed0f
Enable each USB interface independently depending on PHY parameters.
Signed-off-by: Pol Henarejos <pol.henarejos@cttc.es>
2025-03-22 23:25:31 +01:00
Pol Henarejos
4ef641b8d3
Always build ccid if defined.
Signed-off-by: Pol Henarejos <pol.henarejos@cttc.es>
2025-03-22 23:25:04 +01:00
Pol Henarejos
c185b35ca3
Add enabled USB interfaces in PHY.
Signed-off-by: Pol Henarejos <pol.henarejos@cttc.es>
2025-03-22 23:24:36 +01:00
Pol Henarejos
f1b1382300
USB descriptors are now created dynamically.
Signed-off-by: Pol Henarejos <pol.henarejos@cttc.es>
2025-03-21 15:30:50 +01:00
Pol Henarejos
f18f761234
Restore led mode when finishing button press.
Signed-off-by: Pol Henarejos <pol.henarejos@cttc.es>
2025-03-19 01:19:17 +01:00
Pol Henarejos
1a4ca13cc7
Add get led mode.
Signed-off-by: Pol Henarejos <pol.henarejos@cttc.es>
2025-03-19 01:18:57 +01:00
Pol Henarejos
ef9b66f990
Use TLV for PHY serialization/unserialization.
Signed-off-by: Pol Henarejos <pol.henarejos@cttc.es>
2025-03-17 11:36:14 +01:00
Pol Henarejos
7191cda6d3
Add PHY option to enable specific curves. It's in the app side the management.
Signed-off-by: Pol Henarejos <pol.henarejos@cttc.es>
2025-03-11 18:43:08 +01:00
Pol Henarejos
2c3fe5bebf
Only pin to core in ESP32-S3 since it is multicore.
Signed-off-by: Pol Henarejos <pol.henarejos@cttc.es>
2025-03-07 19:35:13 +01:00
Pol Henarejos
9e9632f297
Fix commissioned values for LED.
Signed-off-by: Pol Henarejos <pol.henarejos@cttc.es>
2025-02-23 00:49:45 +01:00
Pol Henarejos
259c4854df
Fix LED for ESP32S3
Signed-off-by: Pol Henarejos <pol.henarejos@cttc.es>
2025-02-23 00:49:12 +01:00
Pol Henarejos
0a4c7b0981
Fix autobuild.
Signed-off-by: Pol Henarejos <pol.henarejos@cttc.es>
2025-02-21 19:56:19 +01:00
Pol Henarejos
db338842b9
Add git pull when switch
Signed-off-by: Pol Henarejos <pol.henarejos@cttc.es>
2025-02-21 19:12:19 +01:00
Pol Henarejos
71af710568
Add EDDSA support as a conditional build.
Signed-off-by: Pol Henarejos <pol.henarejos@cttc.es>
2025-02-21 19:00:21 +01:00
Pol Henarejos
e18f192edf
Fix ESP32 build.
Signed-off-by: Pol Henarejos <pol.henarejos@cttc.es>
2025-02-21 18:59:11 +01:00
Pol Henarejos
07415e6e8b
Fix emulation build.
Signed-off-by: Pol Henarejos <pol.henarejos@cttc.es>
2025-02-21 17:08:29 +01:00
Pol Henarejos
a9eff9fb17
Build cyw43 driver with RP2350.
Signed-off-by: Pol Henarejos <pol.henarejos@cttc.es>
2025-02-21 17:02:20 +01:00
Pol Henarejos
6e6b524878
Fix led driver build for Pimoroni.
Signed-off-by: Pol Henarejos <pol.henarejos@cttc.es>
2025-02-19 15:14:23 +01:00
Pol Henarejos
bfa085cae9
Take led_driver on build depending on defines.
Signed-off-by: Pol Henarejos <pol.henarejos@cttc.es>
2025-02-19 14:32:58 +01:00
Pol Henarejos
94a842fa04
Add file & line to debug info.
Signed-off-by: Pol Henarejos <pol.henarejos@cttc.es>
2025-02-19 11:43:47 +01:00
Pol Henarejos
90fb86be64
Add support for ESP32-S2 build.
Signed-off-by: Pol Henarejos <pol.henarejos@cttc.es>
2025-02-19 11:18:11 +01:00
Pol Henarejos
f06cb3a96d
Fix multiple interfaces in older PCSC versions.
Signed-off-by: Pol Henarejos <pol.henarejos@cttc.es>
2025-02-12 13:25:23 +01:00
Pol Henarejos
5985548c97
Merge pull request #7 from imkuang/limit-led-update-frequency
Limit the frequency of LED status updates
2025-02-09 19:16:29 +01:00
Pol Henarejos
3f5cbf6542
Merge pull request #8 from imkuang/update-led-ws2812-driver
Update ws2812 pio program and optimized the process of RGB color values
2025-02-09 19:12:39 +01:00
Ming Kuang
29c0d078c3
Update ws2812 pio program and optimized the process of RGB color values
1. Update ws2812 pio program to the latest version in pico-examples.
   References: https://github.com/raspberrypi/pico-examples/pull/486
2. Modify the rgbw type to false since we don't use the white channel.
3. Optimize the process of RGB color values to avoid a lot of shift
   operations and improve readability.
2025-02-09 16:51:22 +08:00
Ming Kuang
1723613b4e
Limit the frequency of LED status updates
Unrestricted refreshing of the LED status may cause the WS2812
controller to not work properly.
Observed on my waveshare_rp2040_one board where the LED remains
either constantly on or off, even though the workflow should
dim or turn off/on the LED.
2025-02-09 15:35:42 +08:00
Pol Henarejos
44ca760e1c
Added phy_save() and phy_load() to save and load PHY.
Signed-off-by: Pol Henarejos <pol.henarejos@cttc.es>
2025-01-29 17:09:20 +01:00
Pol Henarejos
4992d8e273
Added phy_save() and phy_load() to save and load PHY.
Signed-off-by: Pol Henarejos <pol.henarejos@cttc.es>
2025-01-29 17:06:55 +01:00
Pol Henarejos
80fa13a19c
Do not init PHY on unserialize.
Signed-off-by: Pol Henarejos <pol.henarejos@cttc.es>
2025-01-29 16:57:53 +01:00
Pol Henarejos
b4c67d2fa5
Add PHY option to keep LED steady.
Signed-off-by: Pol Henarejos <pol.henarejos@cttc.es>
2025-01-29 16:27:26 +01:00
Pol Henarejos
18eb3e6ef2
Fixed stack overflow on serializing PHY.
Signed-off-by: Pol Henarejos <pol.henarejos@cttc.es>
2025-01-29 15:16:13 +01:00
Pol Henarejos
350f0da763
Fix USB keyboard descriptor.
Signed-off-by: Pol Henarejos <pol.henarejos@cttc.es>
2025-01-29 13:21:17 +01:00
Pol Henarejos
a081a2bde6
LibCCID allows propietary class for CCID (ALLOW_PROPIETARY_CLASS in LibCCID). Then both interfaces are loaded but since both belong to same device, only the last is opened.
We change maxSlot value even it breaks the ICCD spec to cause a timeout in LibCCID and deactivate WebCCID interface.

Signed-off-by: Pol Henarejos <pol.henarejos@cttc.es>
2025-01-17 20:56:03 +01:00
Pol Henarejos
3d912878f1
Add OTP (dummy value) for emulation.
Signed-off-by: Pol Henarejos <pol.henarejos@cttc.es>
2025-01-08 13:25:43 +01:00
Pol Henarejos
68a816895e
Fix build for RP2040.
Signed-off-by: Pol Henarejos <pol.henarejos@cttc.es>
2024-12-30 21:37:38 +01:00
Pol Henarejos
1d89c14268
Compute flash memory bounds depending on the partition if available.
Signed-off-by: Pol Henarejos <pol.henarejos@cttc.es>
2024-12-30 21:27:46 +01:00
Pol Henarejos
5508c082e5
Add padding to align the struct in host build.
Signed-off-by: Pol Henarejos <pol.henarejos@cttc.es>
2024-12-30 21:27:27 +01:00
Pol Henarejos
0bed03e522
Reduce data partition to 2K. It start always at half of flash.
Signed-off-by: Pol Henarejos <pol.henarejos@cttc.es>
2024-12-30 21:27:00 +01:00
Pol Henarejos
9e2b6ac4b6
Remove comment
Signed-off-by: Pol Henarejos <pol.henarejos@cttc.es>
2024-12-24 02:05:50 +01:00
Pol Henarejos
046bac42e3
Update CCID descriptor to reflect max USB transport size.
Signed-off-by: Pol Henarejos <pol.henarejos@cttc.es>
2024-12-24 02:05:07 +01:00
Pol Henarejos
c59fb91540
Set stack size depending on the number of enabled interfaces.
Signed-off-by: Pol Henarejos <pol.henarejos@cttc.es>
2024-12-24 01:42:33 +01:00
Pol Henarejos
f8cb36c2cf
Use uint16 funcs.
Signed-off-by: Pol Henarejos <pol.henarejos@cttc.es>
2024-12-23 21:23:13 +01:00
Pol Henarejos
d78e977926
Use BE/LE functions for packing uint16.
Signed-off-by: Pol Henarejos <pol.henarejos@cttc.es>
2024-12-23 21:00:43 +01:00
Pol Henarejos
8e68e6cae9
Use BE/LE functions for packing uint16.
Signed-off-by: Pol Henarejos <pol.henarejos@cttc.es>
2024-12-23 21:00:38 +01:00
Pol Henarejos
d530ea6979
Add BE/LE functions.
Signed-off-by: Pol Henarejos <pol.henarejos@cttc.es>
2024-12-23 20:39:47 +01:00
Pol Henarejos
f509833a3c
Pack file struct for.
Signed-off-by: Pol Henarejos <pol.henarejos@cttc.es>
2024-12-23 20:39:31 +01:00
Pol Henarejos
4f5f2a8854
Add functions to pack/unpack uint32_t and uint64_t.
Signed-off-by: Pol Henarejos <pol.henarejos@cttc.es>
2024-12-23 20:26:52 +01:00
Pol Henarejos
ffaf20da5d
Add memory statistics.
Signed-off-by: Pol Henarejos <pol.henarejos@cttc.es>
2024-12-23 19:35:56 +01:00
Pol Henarejos
e627b3fc86
Fix with string termination.
Signed-off-by: Pol Henarejos <pol.henarejos@cttc.es>
2024-12-17 17:06:08 +01:00
Pol Henarejos
585a6d77e3
Use USB product field in the descriptor.
Signed-off-by: Pol Henarejos <pol.henarejos@cttc.es>
2024-12-17 16:27:11 +01:00
Pol Henarejos
7805131d92
Introduce USB product name as a dynamic field.
Signed-off-by: Pol Henarejos <pol.henarejos@cttc.es>
2024-12-17 16:25:47 +01:00
Pol Henarejos
86999d8cdd
Do not debug after write the buffer.
Signed-off-by: Pol Henarejos <pol.henarejos@cttc.es>
2024-12-16 18:42:42 +01:00
Pol Henarejos
6859cedcbf
Use PHY value for LED GPIO number.
Signed-off-by: Pol Henarejos <pol.henarejos@cttc.es>
2024-12-16 13:10:51 +01:00
Pol Henarejos
1431f91281
In pure U2F mode, no keepalive is sent by authenticator. Instead, client sends commands to know the status.
Signed-off-by: Pol Henarejos <pol.henarejos@cttc.es>
2024-12-11 22:36:24 +01:00
Pol Henarejos
f58bcaecf1
In pure U2F mode, no keepalive is sent by authenticator. Instead, client sends commands to know the status.
Signed-off-by: Pol Henarejos <pol.henarejos@cttc.es>
2024-12-11 22:36:09 +01:00
Pol Henarejos
cb4e2ba0eb
Fixes for ESP32-S3:
- It only supports 4 IN endpoints, so 1 EP must be removed (INT of CCID).
- It only supports 8 strings max.

Signed-off-by: Pol Henarejos <pol.henarejos@cttc.es>
2024-12-11 12:14:31 +01:00
Pol Henarejos
e9875b358c
Fix cancel command.
Signed-off-by: Pol Henarejos <pol.henarejos@cttc.es>
2024-12-03 08:35:20 +01:00
Pol Henarejos
fcae98eecc
Add support for tinyusb 0.17 in ESP32.
Signed-off-by: Pol Henarejos <pol.henarejos@cttc.es>
2024-12-01 01:23:56 +01:00
Pol Henarejos
a61f7683b6
Add option to disable power cycle on reset via Commissioner.
Signed-off-by: Pol Henarejos <pol.henarejos@cttc.es>
2024-12-01 01:07:25 +01:00
Pol Henarejos
a271785814
Fix build for RP2350.
Signed-off-by: Pol Henarejos <pol.henarejos@cttc.es>
2024-11-25 23:45:54 +01:00
Pol Henarejos
49758c6ac7
Fix ESP32 build.
Signed-off-by: Pol Henarejos <pol.henarejos@cttc.es>
2024-11-25 22:59:01 +01:00
Pol Henarejos
9f79693025
Fix for Pico SDK 2.1.0
Signed-off-by: Pol Henarejos <pol.henarejos@cttc.es>
2024-11-25 22:44:00 +01:00
Pol Henarejos
812f075ee4
Add UP button timeout to PHY.
Signed-off-by: Pol Henarejos <pol.henarejos@cttc.es>
2024-11-25 12:57:17 +01:00
Pol Henarejos
6a18e3aa83
Add CCID SET_DATA_RATE_AND_CLOCK command.
Signed-off-by: Pol Henarejos <pol.henarejos@cttc.es>
2024-11-25 12:54:57 +01:00
64 changed files with 2619 additions and 1077 deletions

View file

@ -17,66 +17,86 @@
cmake_minimum_required(VERSION 3.16)
if(ESP_PLATFORM)
set(EXTRA_COMPONENT_DIRS src)
include($ENV{IDF_PATH}/tools/cmake/project.cmake)
set(USB_ITF_CCID 1)
#set(USB_ITF_HID 1)
include(pico_keys_sdk_import.cmake)
project(pico_keys_sdk)
if(ESP_PLATFORM)
set(EXTRA_COMPONENT_DIRS src)
include($ENV{IDF_PATH}/tools/cmake/project.cmake)
else()
if(NOT ENABLE_EMULATION)
set(PICO_USE_FASTEST_SUPPORTED_CLOCK 1)
include(pico_sdk_import.cmake)
endif()
if(ENABLE_EMULATION)
else()
include(pico_sdk_import.cmake)
endif()
project(picokey C CXX ASM)
project(pico_keys C CXX ASM)
set(CMAKE_C_STANDARD 11)
set(CMAKE_CXX_STANDARD 17)
set(CMAKE_C_STANDARD 11)
set(CMAKE_CXX_STANDARD 17)
if(NOT DEFINED __FOR_CI)
set(__FOR_CI 0)
endif()
if(__FOR_CI)
add_definitions(-D__FOR_CI)
endif()
if(ENABLE_EMULATION)
else()
pico_sdk_init()
endif()
if (NOT DEFINED __FOR_CI)
set(__FOR_CI 0)
endif()
if (__FOR_CI)
add_definitions(-D__FOR_CI)
endif()
add_executable(picokey)
endif()
set(USB_ITF_CCID 1)
set(USB_ITF_HID 1)
set(USB_ITF_WCID 1)
include(cmake/version.cmake)
include(pico_keys_sdk_import.cmake)
add_executable(pico_keys_sdk_exe)
target_compile_options(pico_keys_sdk_exe PUBLIC
-Wall
-Werror
if(NOT ESP_PLATFORM)
set(SOURCES ${PICO_KEYS_SOURCES})
endif()
set(SOURCES ${SOURCES}
${CMAKE_CURRENT_LIST_DIR}/src/fs/files.c
${CMAKE_CURRENT_LIST_DIR}/src/version.c
)
if(ENABLE_EMULATION)
target_compile_options(pico_keys_sdk_exe PUBLIC
-fdata-sections
-ffunction-sections
)
if(APPLE)
target_link_options(pico_keys_sdk_exe PUBLIC
-Wl,-dead_strip
)
else()
target_link_options(pico_keys_sdk_exe PUBLIC
-Wl,--gc-sections
)
endif (APPLE)
else()
pico_add_extra_outputs(pico_keys_sdk_exe)
SET_VERSION(ver_major ver_minor "${CMAKE_CURRENT_LIST_DIR}/src/pico_keys_version.h" 2)
target_link_libraries(pico_keys_sdk_exe PRIVATE pico_keys_sdk pico_stdlib pico_multicore hardware_flash hardware_sync hardware_adc pico_unique_id hardware_rtc tinyusb_device tinyusb_board)
if(ESP_PLATFORM)
project(picokey)
endif()
if(NOT ESP_PLATFORM)
target_sources(picokey PUBLIC ${SOURCES})
target_include_directories(picokey PUBLIC ${INCLUDES})
target_compile_options(picokey PUBLIC
-Wall
)
if(NOT MSVC)
target_compile_options(picokey PUBLIC
-Werror
)
endif()
if(ENABLE_EMULATION)
if(NOT MSVC)
target_compile_options(picokey PUBLIC
-fdata-sections
-ffunction-sections
)
endif()
if(APPLE)
target_link_options(picokey PUBLIC
-Wl,-dead_strip
)
elseif(MSVC)
target_compile_options(picokey PUBLIC
-WX
)
target_link_libraries(picokey PUBLIC wsock32 ws2_32 Bcrypt)
else()
target_link_options(picokey PUBLIC
-Wl,--gc-sections
)
endif(APPLE)
target_link_libraries(picokey PRIVATE pthread m)
else()
pico_add_extra_outputs(${CMAKE_PROJECT_NAME})
endif()
endif()

143
LICENSE
View file

@ -1,5 +1,5 @@
GNU GENERAL PUBLIC LICENSE
Version 3, 29 June 2007
GNU AFFERO GENERAL PUBLIC LICENSE
Version 3, 19 November 2007
Copyright (C) 2007 Free Software Foundation, Inc. <https://fsf.org/>
Everyone is permitted to copy and distribute verbatim copies
@ -7,17 +7,15 @@
Preamble
The GNU General Public License is a free, copyleft license for
software and other kinds of works.
The GNU Affero General Public License is a free, copyleft license for
software and other kinds of works, specifically designed to ensure
cooperation with the community in the case of network server software.
The licenses for most software and other practical works are designed
to take away your freedom to share and change the works. By contrast,
the GNU General Public License is intended to guarantee your freedom to
our General Public Licenses are intended to guarantee your freedom to
share and change all versions of a program--to make sure it remains free
software for all its users. We, the Free Software Foundation, use the
GNU General Public License for most of our software; it applies also to
any other work released this way by its authors. You can apply it to
your programs, too.
software for all its users.
When we speak of free software, we are referring to freedom, not
price. Our General Public Licenses are designed to make sure that you
@ -26,44 +24,34 @@ them if you wish), that you receive source code or can get it if you
want it, that you can change the software or use pieces of it in new
free programs, and that you know you can do these things.
To protect your rights, we need to prevent others from denying you
these rights or asking you to surrender the rights. Therefore, you have
certain responsibilities if you distribute copies of the software, or if
you modify it: responsibilities to respect the freedom of others.
Developers that use our General Public Licenses protect your rights
with two steps: (1) assert copyright on the software, and (2) offer
you this License which gives you legal permission to copy, distribute
and/or modify the software.
For example, if you distribute copies of such a program, whether
gratis or for a fee, you must pass on to the recipients the same
freedoms that you received. You must make sure that they, too, receive
or can get the source code. And you must show them these terms so they
know their rights.
A secondary benefit of defending all users' freedom is that
improvements made in alternate versions of the program, if they
receive widespread use, become available for other developers to
incorporate. Many developers of free software are heartened and
encouraged by the resulting cooperation. However, in the case of
software used on network servers, this result may fail to come about.
The GNU General Public License permits making a modified version and
letting the public access it on a server without ever releasing its
source code to the public.
Developers that use the GNU GPL protect your rights with two steps:
(1) assert copyright on the software, and (2) offer you this License
giving you legal permission to copy, distribute and/or modify it.
The GNU Affero General Public License is designed specifically to
ensure that, in such cases, the modified source code becomes available
to the community. It requires the operator of a network server to
provide the source code of the modified version running there to the
users of that server. Therefore, public use of a modified version, on
a publicly accessible server, gives the public access to the source
code of the modified version.
For the developers' and authors' protection, the GPL clearly explains
that there is no warranty for this free software. For both users' and
authors' sake, the GPL requires that modified versions be marked as
changed, so that their problems will not be attributed erroneously to
authors of previous versions.
Some devices are designed to deny users access to install or run
modified versions of the software inside them, although the manufacturer
can do so. This is fundamentally incompatible with the aim of
protecting users' freedom to change the software. The systematic
pattern of such abuse occurs in the area of products for individuals to
use, which is precisely where it is most unacceptable. Therefore, we
have designed this version of the GPL to prohibit the practice for those
products. If such problems arise substantially in other domains, we
stand ready to extend this provision to those domains in future versions
of the GPL, as needed to protect the freedom of users.
Finally, every program is threatened constantly by software patents.
States should not allow patents to restrict development and use of
software on general-purpose computers, but in those that do, we wish to
avoid the special danger that patents applied to a free program could
make it effectively proprietary. To prevent this, the GPL assures that
patents cannot be used to render the program non-free.
An older license, called the Affero General Public License and
published by Affero, was designed to accomplish similar goals. This is
a different license, not a version of the Affero GPL, but Affero has
released a new version of the Affero GPL which permits relicensing under
this license.
The precise terms and conditions for copying, distribution and
modification follow.
@ -72,7 +60,7 @@ modification follow.
0. Definitions.
"This License" refers to version 3 of the GNU General Public License.
"This License" refers to version 3 of the GNU Affero General Public License.
"Copyright" also means copyright-like laws that apply to other kinds of
works, such as semiconductor masks.
@ -549,35 +537,45 @@ to collect a royalty for further conveying from those to whom you convey
the Program, the only way you could satisfy both those terms and this
License would be to refrain entirely from conveying the Program.
13. Use with the GNU Affero General Public License.
13. Remote Network Interaction; Use with the GNU General Public License.
Notwithstanding any other provision of this License, if you modify the
Program, your modified version must prominently offer all users
interacting with it remotely through a computer network (if your version
supports such interaction) an opportunity to receive the Corresponding
Source of your version by providing access to the Corresponding Source
from a network server at no charge, through some standard or customary
means of facilitating copying of software. This Corresponding Source
shall include the Corresponding Source for any work covered by version 3
of the GNU General Public License that is incorporated pursuant to the
following paragraph.
Notwithstanding any other provision of this License, you have
permission to link or combine any covered work with a work licensed
under version 3 of the GNU Affero General Public License into a single
under version 3 of the GNU General Public License into a single
combined work, and to convey the resulting work. The terms of this
License will continue to apply to the part which is the covered work,
but the special requirements of the GNU Affero General Public License,
section 13, concerning interaction through a network will apply to the
combination as such.
but the work with which it is combined will remain governed by version
3 of the GNU General Public License.
14. Revised Versions of this License.
The Free Software Foundation may publish revised and/or new versions of
the GNU General Public License from time to time. Such new versions will
be similar in spirit to the present version, but may differ in detail to
the GNU Affero General Public License from time to time. Such new versions
will be similar in spirit to the present version, but may differ in detail to
address new problems or concerns.
Each version is given a distinguishing version number. If the
Program specifies that a certain numbered version of the GNU General
Program specifies that a certain numbered version of the GNU Affero General
Public License "or any later version" applies to it, you have the
option of following the terms and conditions either of that numbered
version or of any later version published by the Free Software
Foundation. If the Program does not specify a version number of the
GNU General Public License, you may choose any version ever published
GNU Affero General Public License, you may choose any version ever published
by the Free Software Foundation.
If the Program specifies that a proxy can decide which future
versions of the GNU General Public License can be used, that proxy's
versions of the GNU Affero General Public License can be used, that proxy's
public statement of acceptance of a version permanently authorizes you
to choose that version for the Program.
@ -635,40 +633,29 @@ the "copyright" line and a pointer to where the full notice is found.
Copyright (C) <year> <name of author>
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
it under the terms of the GNU Affero General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
GNU Affero General Public License for more details.
You should have received a copy of the GNU General Public License
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>.
Also add information on how to contact you by electronic and paper mail.
If the program does terminal interaction, make it output a short
notice like this when it starts in an interactive mode:
<program> Copyright (C) <year> <name of author>
This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
This is free software, and you are welcome to redistribute it
under certain conditions; type `show c' for details.
The hypothetical commands `show w' and `show c' should show the appropriate
parts of the General Public License. Of course, your program's commands
might be different; for a GUI interface, you would use an "about box".
If your software can interact with users remotely through a computer
network, you should also make sure that it provides a way for users to
get its source. For example, if your program is a web application, its
interface could display a "Source" link that leads users to an archive
of the code. There are many ways you could offer source, and different
solutions will be better for different programs; see section 13 for the
specific requirements.
You should also get your employer (if you work as a programmer) or school,
if any, to sign a "copyright disclaimer" for the program, if necessary.
For more information on this, and how to apply and follow the GNU GPL, see
<https://www.gnu.org/licenses/>.
The GNU General Public License does not permit incorporating your program
into proprietary programs. If your program is a subroutine library, you
may consider it more useful to permit linking proprietary applications with
the library. If this is what you want to do, use the GNU Lesser General
Public License instead of this License. But first, please read
<https://www.gnu.org/licenses/why-not-lgpl.html>.
For more information on this, and how to apply and follow the GNU AGPL, see
<https://www.gnu.org/licenses/>.

View file

@ -1,70 +0,0 @@
include(pico-keys-sdk/cmake/dict.cmake)
dict(SET led_driver 0xcb_helios led_ws2812)
dict(SET led_driver adafruit_feather_rp2040_usb_host led_pico)
dict(SET led_driver adafruit_feather_rp2040 led_ws2812)
dict(SET led_driver adafruit_itsybitsy_rp2040 led_ws2812)
dict(SET led_driver adafruit_kb2040 led_ws2812)
dict(SET led_driver adafruit_macropad_rp2040 led_ws2812)
dict(SET led_driver adafruit_qtpy_rp2040 led_ws2812)
dict(SET led_driver adafruit_trinkey_qt2040 led_ws2812)
dict(SET led_driver amethyst_fpga led_pico)
dict(SET led_driver archi led_ws2812)
dict(SET led_driver arduino_nano_rp2040_connect led_pico)
dict(SET led_driver cytron_maker_pi_rp2040 led_ws2812)
dict(SET led_driver datanoisetv_rp2040_dsp led_pico)
dict(SET led_driver eetree_gamekit_rp2040 led_pico)
dict(SET led_driver garatronic_pybstick26_rp2040 led_pico)
dict(SET led_driver ilabs_challenger_rp2350_bconnect led_ws2812)
dict(SET led_driver ilabs_challenger_rp2350_wifi_ble led_pico)
dict(SET led_driver ilabs_opendec02 led_pico)
dict(SET led_driver melopero_perpetuo_rp2350_lora led_pico)
dict(SET led_driver melopero_shake_rp2040 led_ws2812)
dict(SET led_driver metrotech_xerxes_rp2040 led_pico)
dict(SET led_driver net8086_usb_interposer led_pico)
dict(SET led_driver nullbits_bit_c_pro led_pico) # rgb
dict(SET led_driver phyx_rick_tny_rp2350 led_ws2812)
dict(SET led_driver pi-plates_micropi led_pico)
dict(SET led_driver pico led_pico)
dict(SET led_driver pico_w led_cyw43)
dict(SET led_driver pico2 led_pico)
dict(SET led_driver pimoroni_badger2040 led_pico)
dict(SET led_driver pimoroni_interstate75 led_pico) # rgb
dict(SET led_driver pimoroni_motor2040 led_ws2812)
dict(SET led_driver pimoroni_pga2350 led_pico)
dict(SET led_driver pimoroni_pico_plus2_rp2350 led_pico)
dict(SET led_driver pimoroni_picolipo_4mb led_pico)
dict(SET led_driver pimoroni_picolipo_16mb led_pico)
dict(SET led_driver pimoroni_picosystem led_pico) # rgb
dict(SET led_driver pimoroni_plasma2040 led_pico) # rgb
dict(SET led_driver pimoroni_plasma2350 led_pico) # rgb
dict(SET led_driver pimoroni_servo2040 led_ws2812)
dict(SET led_driver pimoroni_tiny2040 led_pimoroni)
dict(SET led_driver pimoroni_tiny2040_2mb led_pimoroni)
dict(SET led_driver pimoroni_tiny2350 led_pimoroni)
dict(SET led_driver pololu_3pi_2040_robot led_pico)
dict(SET led_driver pololu_zumo_2040_robot led_pico)
dict(SET led_driver seeed_xiao_rp2040 led_ws2812)
dict(SET led_driver seeed_xiao_rp2350 led_ws2812)
dict(SET led_driver solderparty_rp2040_stamp led_ws2812)
dict(SET led_driver solderparty_rp2040_stamp_carrier led_ws2812)
dict(SET led_driver solderparty_rp2040_stamp_round_carrier led_ws2812)
dict(SET led_driver sparkfun_micromod led_pico)
dict(SET led_driver sparkfun_promicro led_ws2812)
dict(SET led_driver sparkfun_promicro_rp2350 led_ws2812)
dict(SET led_driver sparkfun_thingplus led_ws2812)
dict(SET led_driver switchscience_picossci2_conta_base led_pico)
dict(SET led_driver switchscience_picossci2_dev_board led_pico)
dict(SET led_driver switchscience_picossci2_rp2350_breakout led_pico)
dict(SET led_driver switchscience_picossci2_tiny led_pico)
dict(SET led_driver tinycircuits_thumby_color_rp2350 led_pico)
dict(SET led_driver vgaboard led_pico)
dict(SET led_driver waveshare_rp2040_one led_ws2812)
dict(SET led_driver waveshare_rp2040_plus_4mb led_pico)
dict(SET led_driver waveshare_rp2040_plus_16mb led_pico)
dict(SET led_driver waveshare_rp2040_zero led_ws2812)
dict(SET led_driver weact_studio_rp2040_2mb led_pico)
dict(SET led_driver weact_studio_rp2040_4mb led_pico)
dict(SET led_driver weact_studio_rp2040_8mb led_pico)
dict(SET led_driver weact_studio_rp2040_16mb led_pico)
dict(SET led_driver wiznet_w5100s_evb_pico led_pico)

View file

@ -33,7 +33,7 @@ macro(HEX2DEC VAR VAL)
endwhile()
endmacro(HEX2DEC)
macro(SET_VERSION MAJOR MINOR FILE)
macro(SET_VERSION MAJOR MINOR FILE ROLLBACK)
file(READ ${FILE} ver)
string(REGEX MATCHALL "0x([0-9A-F])([0-9A-F])([0-9A-F])([0-9A-F])" _ ${ver})
string(CONCAT ver_major ${CMAKE_MATCH_1}${CMAKE_MATCH_2})
@ -41,9 +41,14 @@ macro(SET_VERSION MAJOR MINOR FILE)
HEX2DEC(ver_major ${ver_major})
HEX2DEC(ver_minor ${ver_minor})
message(STATUS "Found version:\t\t ${ver_major}.${ver_minor}")
if(NOT ENABLE_EMULATION AND NOT ESP_PLATFORM)
pico_set_binary_version(${CMAKE_PROJECT_NAME} MAJOR ${ver_major} MINOR ${ver_minor})
if(PICO_PLATFORM)
if (PICO_RP2350 AND SECURE_BOOT_PKEY)
message(STATUS "Setting rollback version:\t ${ROLLBACK}")
pico_set_binary_version(${CMAKE_PROJECT_NAME} MAJOR ${ver_major} MINOR ${ver_minor} ROLLBACK ${ROLLBACK})
else()
pico_set_binary_version(${CMAKE_PROJECT_NAME} MAJOR ${ver_major} MINOR ${ver_minor})
endif()
endif()
SET(${MAJOR} ${ver_major})
SET(${MINOR} ${ver_minor})
set(${MAJOR} ${ver_major})
set(${MINOR} ${ver_minor})
endmacro(SET_VERSION)

View file

@ -3,16 +3,16 @@
* Copyright (c) 2022 Pol Henarejos.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, version 3.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
#include "common.h"

View file

@ -3,16 +3,16 @@
* Copyright (c) 2022 Pol Henarejos.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, version 3.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
#ifndef _SHA256_ALT_H_

View file

@ -24,12 +24,13 @@
{
"name": "Pico Keys Data",
"id": 1,
"start": "1024K",
"size": "3072K",
"families": ["data"],
"permissions": {
"secure": "rw",
"nonsecure": "rw",
"bootloader": "rw"
"nonsecure": "",
"bootloader": "r"
},
"link": ["owner", 0],
"ignored_during_arm_boot": true,

View file

@ -15,12 +15,7 @@
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
include(pico-keys-sdk/cmake/version.cmake)
include(pico-keys-sdk/cmake/boards.cmake)
if(PICO_BOARD)
dict(GET led_driver ${PICO_BOARD} LED_DRIVER)
endif()
include(pico-keys-sdk/cmake/version.cmake OPTIONAL)
option(VIDPID "Set specific VID/PID from a known platform {NitroHSM, NitroFIDO2, NitroStart, NitroPro, Nitro3, Yubikey5, YubikeyNeo, YubiHSM, Gnuk, GnuPG}" "None")
@ -113,6 +108,111 @@ endif()
message(STATUS "USB VID/PID:\t\t\t ${USB_VID}:${USB_PID}")
if(NOT ESP_PLATFORM)
set(NEED_UPDATE OFF)
option(ENABLE_EDDSA "Enable/disable EdDSA support" OFF)
if(ENABLE_EDDSA)
message(STATUS "EdDSA support:\t\t enabled")
else()
message(STATUS "EdDSA support:\t\t disabled")
endif(ENABLE_EDDSA)
set(MBEDTLS_PATH "${CMAKE_SOURCE_DIR}/pico-keys-sdk/mbedtls")
execute_process(
COMMAND git config --global --add safe.directory ${MBEDTLS_PATH}
WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}
OUTPUT_QUIET ERROR_QUIET
)
if(ENABLE_EDDSA)
set(MBEDTLS_ORIGIN "https://github.com/polhenarejos/mbedtls.git")
set(MBEDTLS_REF "mbedtls-3.6-eddsa")
execute_process(
COMMAND git -C ${MBEDTLS_PATH} symbolic-ref --quiet --short HEAD
OUTPUT_VARIABLE CURRENT_BRANCH
OUTPUT_STRIP_TRAILING_WHITESPACE
RESULT_VARIABLE BRANCH_ERR
)
message(STATUS "Current branch for mbedTLS: ${CURRENT_BRANCH}")
message(STATUS "Target branch for mbedTLS: ${MBEDTLS_REF}")
if(NOT BRANCH_ERR EQUAL 0 OR NOT "${CURRENT_BRANCH}" STREQUAL "${MBEDTLS_REF}")
set(NEED_UPDATE ON)
else()
set(NEED_UPDATE OFF)
endif()
add_definitions(-DMBEDTLS_ECP_DP_ED25519_ENABLED=1 -DMBEDTLS_ECP_DP_ED448_ENABLED=1 -DMBEDTLS_EDDSA_C=1 -DMBEDTLS_SHA3_C=1)
else()
set(MBEDTLS_ORIGIN "https://github.com/Mbed-TLS/mbedtls.git")
set(MBEDTLS_REF "v3.6.5")
execute_process(
COMMAND git -C ${MBEDTLS_PATH} describe --tags --exact-match
OUTPUT_VARIABLE CURRENT_TAG
OUTPUT_STRIP_TRAILING_WHITESPACE
RESULT_VARIABLE TAG_ERR
)
message(STATUS "Current tag for mbedTLS: ${CURRENT_TAG}")
message(STATUS "Target tag for mbedTLS: ${MBEDTLS_REF}")
if(NOT TAG_ERR EQUAL 0 OR NOT "${CURRENT_TAG}" STREQUAL "${MBEDTLS_REF}")
set(NEED_UPDATE ON)
else()
set(NEED_UPDATE OFF)
endif()
endif()
if(NEED_UPDATE)
message(STATUS "Updating mbedTLS source code...")
execute_process(
COMMAND git -C ${MBEDTLS_PATH} submodule update --init --recursive --remote pico-keys-sdk
WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}
OUTPUT_QUIET ERROR_QUIET
)
execute_process(
COMMAND git -C ${MBEDTLS_PATH} remote set-url origin ${MBEDTLS_ORIGIN}
OUTPUT_QUIET ERROR_QUIET
)
execute_process(
COMMAND git -C ${MBEDTLS_PATH} fetch origin +refs/heads/*:refs/remotes/origin/* --tags --force
WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}
OUTPUT_QUIET ERROR_QUIET
)
execute_process(
COMMAND rm -rf ${MBEDTLS_PATH}/framework
WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}
OUTPUT_QUIET ERROR_QUIET
)
if(ENABLE_EDDSA)
execute_process(
COMMAND git -C ${MBEDTLS_PATH} checkout -B ${MBEDTLS_REF} --track origin/${MBEDTLS_REF}
WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}
OUTPUT_QUIET ERROR_QUIET
)
else()
execute_process(
COMMAND git -C ${MBEDTLS_PATH} checkout ${MBEDTLS_REF}
WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}
OUTPUT_QUIET ERROR_QUIET
)
endif()
else()
message(STATUS "mbedTLS source code is up to date.")
endif()
endif(NOT ESP_PLATFORM)
set(MBEDTLS_SOURCES
${CMAKE_CURRENT_LIST_DIR}/mbedtls/library/aes.c
${CMAKE_CURRENT_LIST_DIR}/mbedtls/library/asn1parse.c
@ -153,7 +253,14 @@ set(MBEDTLS_SOURCES
${CMAKE_CURRENT_LIST_DIR}/mbedtls/library/pkwrite.c
)
set(SOURCES ${SOURCES}
if (ENABLE_EDDSA)
set(MBEDTLS_SOURCES ${MBEDTLS_SOURCES}
${CMAKE_CURRENT_LIST_DIR}/mbedtls/library/eddsa.c
${CMAKE_CURRENT_LIST_DIR}/mbedtls/library/sha3.c
)
endif()
set(PICO_KEYS_SOURCES ${PICO_KEYS_SOURCES}
${CMAKE_CURRENT_LIST_DIR}/src/main.c
${CMAKE_CURRENT_LIST_DIR}/src/usb/usb.c
${CMAKE_CURRENT_LIST_DIR}/src/fs/file.c
@ -172,11 +279,16 @@ set(SOURCES ${SOURCES}
)
if(ESP_PLATFORM)
set(LED_DRIVER led_neopixel)
endif()
if (LED_DRIVER)
message(STATUS "LED driver:\t\t\t ${LED_DRIVER}")
set(SOURCES ${SOURCES} ${CMAKE_CURRENT_LIST_DIR}/src/led/${LED_DRIVER}.c)
set(PICO_KEYS_SOURCES ${PICO_KEYS_SOURCES} ${CMAKE_CURRENT_LIST_DIR}/src/led/led_neopixel.c)
else()
if (NOT ENABLE_EMULATION)
set(PICO_KEYS_SOURCES ${PICO_KEYS_SOURCES}
${CMAKE_CURRENT_LIST_DIR}/src/led/led_cyw43.c
${CMAKE_CURRENT_LIST_DIR}/src/led/led_pico.c
${CMAKE_CURRENT_LIST_DIR}/src/led/led_pimoroni.c
${CMAKE_CURRENT_LIST_DIR}/src/led/led_ws2812.c
)
endif()
endif()
## mbedTLS reports an stringop overflow for cmac.c
@ -229,8 +341,15 @@ set(LIBRARIES
hardware_pio
)
if(PICO_BOARD STREQUAL "pico_w")
set(LIBRARIES ${LIBRARIES} pico_cyw43_arch_none)
set(IS_CYW43 0)
if (PICO_PLATFORM)
file(READ ${PICO_SDK_PATH}/src/boards/include/boards/${PICO_BOARD}.h content)
string(REGEX MATCHALL "CYW43_WL_GPIO_LED_PIN" _ ${content})
if (CMAKE_MATCH_0)
message(STATUS "Found cyw43 LED:\t\t true")
set(LIBRARIES ${LIBRARIES} pico_cyw43_arch_none)
set(IS_CYW43 1)
endif()
endif()
function(add_impl_library target)
@ -238,24 +357,39 @@ function(add_impl_library target)
string(TOUPPER ${target} TARGET_UPPER)
target_compile_definitions(${target} INTERFACE LIB_${TARGET_UPPER}=1)
endfunction()
if(${USB_ITF_HID})
set(SOURCES ${SOURCES}
if(USB_ITF_HID)
set(PICO_KEYS_SOURCES ${PICO_KEYS_SOURCES}
${CMAKE_CURRENT_LIST_DIR}/src/usb/hid/hid.c
)
set(INCLUDES ${INCLUDES}
${CMAKE_CURRENT_LIST_DIR}/src/usb/hid
)
endif()
if(USB_ITF_CCID)
set(PICO_KEYS_SOURCES ${PICO_KEYS_SOURCES}
${CMAKE_CURRENT_LIST_DIR}/src/usb/ccid/ccid.c
)
set(INCLUDES ${INCLUDES}
${CMAKE_CURRENT_LIST_DIR}/src/usb/ccid
)
endif()
if(NOT MSVC)
add_definitions("-fmacro-prefix-map=${CMAKE_CURRENT_LIST_DIR}/=")
endif()
if(MSVC)
set(PICO_KEYS_SOURCES ${PICO_KEYS_SOURCES}
${CMAKE_CURRENT_LIST_DIR}/src/fs/mman.c
)
endif()
if(ENABLE_EMULATION)
if(APPLE)
add_definitions("-Wno-deprecated-declarations")
elseif(MSVC)
set(SOURCES ${SOURCES}
${CMAKE_CURRENT_LIST_DIR}/src/fs/mman.c
)
endif()
add_definitions(-DENABLE_EMULATION)
set(SOURCES ${SOURCES}
set(PICO_KEYS_SOURCES ${PICO_KEYS_SOURCES}
${CMAKE_CURRENT_LIST_DIR}/src/usb/emulation/emulation.c
)
set(MBEDTLS_SOURCES ${MBEDTLS_SOURCES}
@ -265,15 +399,7 @@ if(ENABLE_EMULATION)
${CMAKE_CURRENT_LIST_DIR}/src/usb/emulation
)
else()
if(USB_ITF_CCID)
set(SOURCES ${SOURCES}
${CMAKE_CURRENT_LIST_DIR}/src/usb/ccid/ccid.c
)
set(INCLUDES ${INCLUDES}
${CMAKE_CURRENT_LIST_DIR}/src/usb/ccid
)
endif()
set(SOURCES ${SOURCES}
set(PICO_KEYS_SOURCES ${PICO_KEYS_SOURCES}
${CMAKE_CURRENT_LIST_DIR}/src/usb/usb_descriptors.c
)
endif()
@ -284,7 +410,7 @@ endif()
if(MSVC)
set(
CMAKE_C_FLAGS
"${CMAKE_C_FLAGS} -wd4820 -wd4255 -wd5045 -wd4706 -wd4061 -wd5105"
"${CMAKE_C_FLAGS} -wd4820 -wd4255 -wd5045 -wd4706 -wd4061 -wd5105 -wd4141 -wd4200"
)
add_compile_definitions(_CRT_SECURE_NO_WARNINGS
@ -296,17 +422,24 @@ if(MSVC)
_WIN32_WINNT_WIN10_RS4=0
_WIN32_WINNT_WIN10_RS5=0
_STRALIGN_USE_SECURE_CRT=0
NTDDI_WIN10_CU=0)
NTDDI_WIN11_DT=0)
set_source_files_properties(
${EXTERNAL_SOURCES}
PROPERTIES
COMPILE_FLAGS " -W3 -wd4242 -wd4065"
)
endif()
if(PICO_PLATFORM)
pico_sdk_init()
endif()
if(PICO_RP2350)
pico_set_uf2_family(${CMAKE_PROJECT_NAME} "rp2350-arm-s")
pico_embed_pt_in_binary(${CMAKE_PROJECT_NAME} "${CMAKE_CURRENT_LIST_DIR}/config/rp2350/pt.json")
pico_set_binary_type(${CMAKE_PROJECT_NAME} copy_to_ram)
if (NOT IS_CYW43)
pico_set_binary_type(${CMAKE_PROJECT_NAME} copy_to_ram)
endif()
if (SECURE_BOOT_PKEY)
message(STATUS "Secure Boot Key ${SECURE_BOOT_PKEY}")
pico_sign_binary(${CMAKE_PROJECT_NAME} ${SECURE_BOOT_PKEY})
@ -317,23 +450,23 @@ if(PICO_RP2350)
set(INCLUDES ${INCLUDES}
${CMAKE_CURRENT_LIST_DIR}/config/rp2350/alt
)
set(SOURCES ${SOURCES}
set(PICO_KEYS_SOURCES ${PICO_KEYS_SOURCES}
${CMAKE_CURRENT_LIST_DIR}/config/rp2350/alt/sha256_alt.c
)
set(LIBRARIES ${LIBRARIES} pico_sha256)
endif()
set(INTERNAL_SOURCES ${SOURCES})
set(SOURCES ${SOURCES} ${EXTERNAL_SOURCES})
set(INTERNAL_SOURCES ${PICO_KEYS_SOURCES})
set(PICO_KEYS_SOURCES ${PICO_KEYS_SOURCES} ${EXTERNAL_SOURCES})
if(NOT TARGET pico_keys_sdk)
if(ENABLE_EMULATION OR ESP_PLATFORM)
add_impl_library(pico_keys_sdk)
else()
if(PICO_PLATFORM)
pico_add_library(pico_keys_sdk)
pico_add_extra_outputs(${CMAKE_PROJECT_NAME})
target_link_libraries(${CMAKE_PROJECT_NAME} PRIVATE ${LIBRARIES})
else()
add_impl_library(pico_keys_sdk)
endif()
target_sources(pico_keys_sdk INTERFACE ${SOURCES})
target_sources(pico_keys_sdk INTERFACE ${PICO_KEYS_SOURCES})
target_include_directories(pico_keys_sdk INTERFACE ${INCLUDES})
target_link_libraries(pico_keys_sdk INTERFACE ${LIBRARIES})
endif()

View file

@ -1,5 +1,6 @@
idf_component_register(
SRCS ${INTERNAL_SOURCES}
INCLUDE_DIRS . fs rng usb led ../mbedtls/include ../tinycbor/src
REQUIRES bootloader_support esp_partition esp_tinyusb efuse
SRCS ${PICO_KEYS_SOURCES}
INCLUDE_DIRS . fs rng usb led ../tinycbor/src
REQUIRES bootloader_support esp_partition esp_tinyusb efuse mbedtls
)
idf_component_set_property(${COMPONENT_NAME} WHOLE_ARCHIVE ON)

View file

@ -3,16 +3,16 @@
* Copyright (c) 2022 Pol Henarejos.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, version 3.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
* Affero General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
#include "apdu.h"
@ -85,17 +85,17 @@ uint16_t apdu_process(uint8_t itf, const uint8_t *buffer, uint16_t buffer_size)
}
else if (apdu.header[4] == 0x0 && buffer_size >= 7) {
if (buffer_size == 7) {
apdu.ne = (apdu.header[5] << 8) | apdu.header[6];
apdu.ne = get_uint16_t_be(apdu.header + 5);
if (apdu.ne == 0) {
apdu.ne = 65536;
}
}
else {
apdu.ne = 0;
apdu.nc = (apdu.header[5] << 8) | apdu.header[6];
apdu.nc = get_uint16_t_be(apdu.header + 5);
apdu.data = apdu.header + 7;
if (apdu.nc + 7 + 2 == buffer_size) {
apdu.ne = (apdu.header[buffer_size - 2] << 8) | apdu.header[buffer_size - 1];
apdu.ne = get_uint16_t_be(apdu.header + buffer_size - 2);
if (apdu.ne == 0) {
apdu.ne = 65536;
}
@ -113,21 +113,22 @@ uint16_t apdu_process(uint8_t itf, const uint8_t *buffer, uint16_t buffer_size)
}
}
}
//printf("apdu.nc %ld, apdu.ne %ld\n",apdu.nc,apdu.ne);
//printf("apdu.nc %u, apdu.ne %u\n",apdu.nc,apdu.ne);
if (apdu.header[1] == 0xc0) {
//printf("apdu.ne %u, apdu.rlen %d, bk %x\n",apdu.ne,apdu.rlen,rdata_bk);
timeout_stop();
*(uint16_t *) rdata_gr = rdata_bk;
rdata_gr[0] = rdata_bk >> 8;
rdata_gr[1] = rdata_bk & 0xff;
if (apdu.rlen <= apdu.ne) {
#ifndef ENABLE_EMULATION
#ifdef USB_ITF_HID
if (itf == ITF_HID_CTAP) {
driver_exec_finished_cont_hid(itf, apdu.rlen + 2, rdata_gr - apdu.rdata);
driver_exec_finished_cont_hid(itf, apdu.rlen + 2, (uint16_t)(rdata_gr - apdu.rdata));
}
#endif
#ifdef USB_ITF_CCID
if (itf == ITF_SC_CCID || itf == ITF_SC_WCID) {
driver_exec_finished_cont_ccid(itf, apdu.rlen + 2, rdata_gr - apdu.rdata);
driver_exec_finished_cont_ccid(itf, apdu.rlen + 2, (uint16_t)(rdata_gr - apdu.rdata));
}
#endif
#else
@ -140,7 +141,7 @@ uint16_t apdu_process(uint8_t itf, const uint8_t *buffer, uint16_t buffer_size)
}
else {
rdata_gr += apdu.ne;
rdata_bk = *(uint16_t *) rdata_gr;
rdata_bk = (rdata_gr[0] << 8) | rdata_gr[1];
rdata_gr[0] = 0x61;
if (apdu.rlen - apdu.ne >= 256) {
rdata_gr[1] = 0;
@ -151,12 +152,12 @@ uint16_t apdu_process(uint8_t itf, const uint8_t *buffer, uint16_t buffer_size)
#ifndef ENABLE_EMULATION
#ifdef USB_ITF_HID
if (itf == ITF_HID_CTAP) {
driver_exec_finished_cont_hid(itf, apdu.ne + 2, rdata_gr - apdu.ne - apdu.rdata);
driver_exec_finished_cont_hid(itf, (uint16_t)(apdu.ne + 2), (uint16_t)(rdata_gr - apdu.ne - apdu.rdata));
}
#endif
#ifdef USB_ITF_CCID
if (itf == ITF_SC_CCID || itf == ITF_SC_WCID) {
driver_exec_finished_cont_ccid(itf, apdu.ne + 2, rdata_gr - apdu.ne - apdu.rdata);
driver_exec_finished_cont_ccid(itf, (uint16_t)(apdu.ne + 2), (uint16_t)(rdata_gr - apdu.ne - apdu.rdata));
}
#endif
#else
@ -175,14 +176,15 @@ uint16_t apdu_process(uint8_t itf, const uint8_t *buffer, uint16_t buffer_size)
}
uint16_t set_res_sw(uint8_t sw1, uint8_t sw2) {
apdu.sw = (sw1 << 8) | sw2;
apdu.sw = make_uint16_t_be(sw1, sw2);
if (sw1 != 0x90) {
res_APDU_size = 0;
}
return make_uint16_t(sw1, sw2);
return make_uint16_t_be(sw1, sw2);
}
void apdu_thread(void) {
void *apdu_thread(void *arg) {
(void)arg;
card_init_core1();
while (1) {
uint32_t m = 0;
@ -215,19 +217,17 @@ done: ;
current_app->unload();
current_app = NULL;
}
#ifdef ESP_PLATFORM
vTaskDelete(NULL);
#endif
return NULL;
}
void apdu_finish() {
apdu.rdata[apdu.rlen] = apdu.sw >> 8;
apdu.rdata[apdu.rlen + 1] = apdu.sw & 0xff;
put_uint16_t_be(apdu.sw, apdu.rdata + apdu.rlen);
// timeout_stop();
#ifndef ENABLE_EMULATION
if ((apdu.rlen + 2 + 10) % 64 == 0) { // FIX for strange behaviour with PSCS and multiple of 64
apdu.ne = apdu.rlen - 2;
}
/* It was fixed in the USB handling. Keep it just in case */
//if ((apdu.rlen + 2 + 10) % 64 == 0) { // FIX for strange behaviour with PSCS and multiple of 64
// apdu.ne = apdu.rlen - 2;
//}
#endif
}
@ -238,7 +238,7 @@ uint16_t apdu_next() {
}
else {
rdata_gr = apdu.rdata + apdu.ne;
rdata_bk = *(uint16_t *) rdata_gr;
rdata_bk = (rdata_gr[0] << 8) | rdata_gr[1];
rdata_gr[0] = 0x61;
if (apdu.rlen - apdu.ne >= 256) {
rdata_gr[1] = 0;

View file

@ -3,28 +3,29 @@
* Copyright (c) 2022 Pol Henarejos.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, version 3.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
* Affero General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
#ifndef _APDU_H_
#define _APDU_H_
#include <stdlib.h>
#if !defined(ENABLE_EMULATION) && !defined(ESP_PLATFORM)
#if defined(PICO_PLATFORM)
#include "pico/stdlib.h"
#endif
#include "compat.h"
#include <stdio.h>
#include <inttypes.h>
#include <stdbool.h>
typedef struct app {
const uint8_t *aid;
@ -33,6 +34,7 @@ typedef struct app {
int (*unload)();
} app_t;
extern bool app_exists(const uint8_t *aid, size_t aid_len);
extern int register_app(int (*)(app_t *, uint8_t), const uint8_t *);
extern int select_app(const uint8_t *aid, size_t aid_len);
@ -42,7 +44,7 @@ typedef struct cmd {
} cmd_t;
extern uint8_t num_apps;
extern app_t apps[8];
extern app_t apps[16];
extern app_t *current_app;
PACK(struct apdu {
@ -71,6 +73,6 @@ extern int process_apdu();
extern uint16_t apdu_process(uint8_t, const uint8_t *buffer, uint16_t buffer_size);
extern void apdu_finish();
extern uint16_t apdu_next();
extern void apdu_thread();
extern void *apdu_thread(void *);
#endif

View file

@ -3,16 +3,16 @@
* Copyright (c) 2022 Pol Henarejos.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, version 3.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
* Affero General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
#include "pico_keys.h"
@ -73,8 +73,7 @@ uint8_t format_tlv_len(uint16_t len, uint8_t *out) {
}
if (out) {
*out++ = 0x82;
*out++ = (len >> 8) & 0xff;
*out++ = len & 0xff;
put_uint16_t_be(len, out);
}
return 3;
}

View file

@ -3,23 +3,23 @@
* Copyright (c) 2022 Pol Henarejos.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, version 3.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
* Affero General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
#ifndef _ASN1_H_
#define _ASN1_H_
#include <stdlib.h>
#if !defined(ENABLE_EMULATION) && !defined(ESP_PLATFORM)
#if defined(PICO_PLATFORM)
#include "pico/stdlib.h"
#else
#include <stdint.h>

35
src/board.h Normal file
View file

@ -0,0 +1,35 @@
/*
* This file is part of the Pico Keys SDK distribution (https://github.com/polhenarejos/pico-keys-sdk).
* Copyright (c) 2022 Pol Henarejos.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, version 3.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
#ifndef _BOARD_H_
#define _BOARD_H_
#ifdef _MSC_VER
#include <windows.h>
struct timezone;
extern int gettimeofday(struct timeval *tp, struct timezone *tzp);
#else
#include <sys/time.h>
#endif
static inline uint32_t board_millis() {
struct timeval start;
gettimeofday(&start, NULL);
return start.tv_sec * 1000 + start.tv_usec / 1000;
}
#endif // _BOARD_H_

View file

@ -3,16 +3,16 @@
* Copyright (c) 2022 Pol Henarejos.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, version 3.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
* Affero General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
#ifndef _COMPAT_H_
@ -47,4 +47,23 @@
static void f(void)
#endif
#include <string.h>
#ifdef _MSC_VER
#ifndef HAVE_STRLCPY
static inline size_t strlcpy(char *dst, const char *src, size_t size)
{
size_t srclen = strlen(src);
if (size != 0) {
size_t copylen = (srclen >= size) ? size - 1 : srclen;
memcpy(dst, src, copylen);
dst[copylen] = '\0';
}
return srclen;
}
#endif
#endif
#endif // _COMPAT_H

View file

@ -3,39 +3,145 @@
* Copyright (c) 2022 Pol Henarejos.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, version 3.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
* Affero General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
#if defined(ENABLE_EMULATION)
#elif defined(ESP_PLATFORM)
#if defined(ESP_PLATFORM)
#include "esp_compat.h"
#else
#elif defined(PICO_PLATFORM)
#include <pico/unique_id.h>
#endif
#include "mbedtls/md.h"
#include "mbedtls/sha256.h"
#include "mbedtls/aes.h"
#include "mbedtls/hkdf.h"
#include "mbedtls/gcm.h"
#include "crypto_utils.h"
#include "pico_keys.h"
#include "otp.h"
#include "random.h"
#include <stdio.h>
int ct_memcmp(const void *a, const void *b, size_t n) {
const volatile uint8_t *x = (const volatile uint8_t *)a;
const volatile uint8_t *y = (const volatile uint8_t *)b;
uint8_t r = 0;
for (size_t i = 0; i < n; ++i) {
r |= x[i] ^ y[i];
}
return r;
}
static const mbedtls_md_info_t *SHA256(void) {
return mbedtls_md_info_from_type(MBEDTLS_MD_SHA256);
}
void derive_kbase(uint8_t kbase[32]) {
const uint8_t nootp_salt[] = "NO-OTP";
if (otp_key_1) {
mbedtls_hkdf(SHA256(), pico_serial_hash, sizeof(pico_serial_hash), otp_key_1, 32, (const uint8_t *)"DEVICE/ROOT", 12, kbase, 32);
}
else {
mbedtls_hkdf(SHA256(), nootp_salt, sizeof(nootp_salt)-1, pico_serial_hash, sizeof(pico_serial_hash), (const uint8_t *)"DEVICE/ROOT", 12, kbase, 32);
}
}
void derive_kver(const uint8_t *pin, size_t pin_len, uint8_t kver[32]) {
uint8_t kbase[32];
derive_kbase(kbase);
mbedtls_md_hmac(SHA256(), kbase, 32, pin, pin_len, kver);
mbedtls_platform_zeroize(kbase, sizeof(kbase));
}
void pin_derive_verifier(const uint8_t *pin, size_t pin_len, uint8_t verifier[32]) {
uint8_t kver[32];
derive_kver(pin, pin_len, kver);
mbedtls_hkdf(SHA256(), pico_serial_hash, sizeof(pico_serial_hash), kver, 32, (const uint8_t *)"PIN/VERIFY", 10, verifier, 32);
mbedtls_platform_zeroize(kver, sizeof(kver));
}
void pin_derive_session(const uint8_t *pin, size_t pin_len, uint8_t pin_token[32]) {
uint8_t kver[32];
derive_kver(pin, pin_len, kver);
mbedtls_hkdf(SHA256(), pico_serial_hash, sizeof(pico_serial_hash), kver, 32, (const uint8_t *)"PIN/TOKEN", 9, pin_token, 32);
mbedtls_platform_zeroize(kver, sizeof(kver));
}
void pin_derive_kenc(const uint8_t pin_token[32], uint8_t kenc[32]) {
mbedtls_hkdf(SHA256(), pico_serial_hash, sizeof(pico_serial_hash), pin_token, 32, (const uint8_t *)"PIN/ENC", 7, kenc, 32);
}
// ------------------------------------------------------------------
// Encrypt 32-byte device key using AES-256-GCM
// Output: [nonce|ciphertext|tag] = 12 + in_len + 16 = 60 bytes
// ------------------------------------------------------------------
int encrypt_with_aad(const uint8_t key[32], const uint8_t *in_buf, size_t in_len, uint8_t *out_buf) {
uint8_t *nonce = out_buf;
uint8_t *ct = out_buf + 12;
uint8_t *tag = out_buf + 12 + in_len;
random_gen(NULL, nonce, 12);
mbedtls_gcm_context gcm;
mbedtls_gcm_init(&gcm);
uint8_t kenc[32];
pin_derive_kenc(key, kenc);
int rc = mbedtls_gcm_setkey(&gcm, MBEDTLS_CIPHER_ID_AES, kenc, 256);
mbedtls_platform_zeroize(kenc, sizeof(kenc));
if (rc != 0) {
return rc;
}
rc = mbedtls_gcm_crypt_and_tag(&gcm, MBEDTLS_GCM_ENCRYPT, in_len, nonce, 12, pico_serial_hash, sizeof(pico_serial_hash), in_buf, ct, 16, tag);
mbedtls_gcm_free(&gcm);
return rc;
}
// ------------------------------------------------------------------
// Decrypt & verify 32-byte device key using AES-256-GCM
// Input: [nonce|ciphertext|tag] = in_len bytes
// Output: decrypted = in_len - 12 - 16 bytes
// ------------------------------------------------------------------
int decrypt_with_aad(const uint8_t key[32], const uint8_t *in_buf, size_t in_len, uint8_t *out_buf) {
const uint8_t *nonce = in_buf;
const uint8_t *ct = in_buf + 12;
const uint8_t *tag = in_buf + in_len - 16;
mbedtls_gcm_context gcm;
mbedtls_gcm_init(&gcm);
uint8_t kenc[32];
pin_derive_kenc(key, kenc);
int rc = mbedtls_gcm_setkey(&gcm, MBEDTLS_CIPHER_ID_AES, kenc, 256);
mbedtls_platform_zeroize(kenc, sizeof(kenc));
if (rc != 0) {
return rc;
}
rc = mbedtls_gcm_auth_decrypt(&gcm, in_len - 16 - 12, nonce, 12, pico_serial_hash, sizeof(pico_serial_hash), tag, 16, ct, out_buf);
mbedtls_gcm_free(&gcm);
return rc;
}
// Old functions, kept for compatibility. NOT SECURE, use the new ones above.
void double_hash_pin(const uint8_t *pin, uint16_t len, uint8_t output[32]) {
uint8_t o1[32];
hash_multi(pin, len, o1);
for (int i = 0; i < sizeof(o1); i++) {
for (size_t i = 0; i < sizeof(o1); i++) {
o1[i] ^= pin[i % len];
}
hash_multi(o1, sizeof(o1), output);
}
void hash_multi(const uint8_t *input, uint16_t len, uint8_t output[32]) {
mbedtls_sha256_context ctx;
mbedtls_sha256_init(&ctx);

View file

@ -3,16 +3,16 @@
* Copyright (c) 2022 Pol Henarejos.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, version 3.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
* Affero General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
#ifndef _CRYPTO_UTILS_H_
@ -38,6 +38,15 @@
#define IV_SIZE 16
extern int ct_memcmp(const void *a, const void *b, size_t n);
// Newer and safe functions
extern void derive_kbase(uint8_t kbase[32]);
extern void derive_kver(const uint8_t *pin, size_t pin_len, uint8_t kver[32]);
extern void pin_derive_kenc(const uint8_t pin_token[32], uint8_t kenc[32]);
extern void pin_derive_session(const uint8_t *pin, size_t pin_len, uint8_t pin_token[32]);
extern void pin_derive_verifier(const uint8_t *pin, size_t pin_len, uint8_t verifier[32]);
extern int encrypt_with_aad(const uint8_t key[32], const uint8_t *in_buf, size_t in_len, uint8_t *out_buf);
extern int decrypt_with_aad(const uint8_t key[32], const uint8_t *in_buf, size_t in_len, uint8_t *out_buf);
extern void double_hash_pin(const uint8_t *pin, uint16_t len, uint8_t output[32]);
extern void hash_multi(const uint8_t *input, uint16_t len, uint8_t output[32]);
extern void hash256(const uint8_t *input, size_t len, uint8_t output[32]);

View file

@ -3,16 +3,16 @@
* Copyright (c) 2022 Pol Henarejos.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, version 3.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
* Affero General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
#ifndef _DEBUG_H_
@ -20,16 +20,16 @@
#if defined(DEBUG_APDU) && DEBUG_APDU == 1
#define DEBUG_PAYLOAD(_p, _s) { \
printf("Payload %s (%d bytes):\n", #_p, (int) (_s)); \
for (int _i = 0; _i < _s; _i += 16) { \
printf("Payload %s (%zu bytes) [%s:%d]:\n", #_p, (size_t)(_s), __FILE__, __LINE__); \
for (size_t _i = 0; _i < (size_t)(_s); _i += 16) { \
printf("%" PRIxPTR "h : ", (uintptr_t) (_i + _p)); \
for (int _j = 0; _j < 16; _j++) { \
if (_j < _s - _i) printf("%02X ", (_p)[_i + _j]); \
for (size_t _j = 0; _j < 16; _j++) { \
if (_j < (size_t)(_s) - _i) printf("%02X ", (_p)[_i + _j]); \
else printf(" "); \
if (_j == 7) printf(" "); \
} printf(": "); \
for (int _j = 0; _j < 16; _j++) { \
if (_j < _s - _i && (_p)[_i + _j] > 32 && (_p)[_i + _j] != 127 && (_p)[_i + _j] < 176) printf("%c", (_p)[_i + _j]); \
for (size_t _j = 0; _j < 16; _j++) { \
if (_j < (size_t)(_s) - _i && (_p)[_i + _j] > 32 && (_p)[_i + _j] != 127 && (_p)[_i + _j] < 176) printf("%c", (_p)[_i + _j]); \
else printf(" "); \
if (_j == 7) printf(" "); \
} \
@ -37,9 +37,9 @@
} printf("\n"); \
}
#define DEBUG_DATA(_p, _s) { \
printf("Data %s (%d bytes):\n", #_p, (int) (_s)); \
char *_tmp = (char *) calloc(1, 2 * _s + 1); \
for (int _i = 0; _i < _s; _i++) { \
printf("Data %s (%zu bytes) [%s:%d]:\n", #_p, (size_t)(_s), __FILE__, __LINE__); \
char *_tmp = (char *) calloc(2 * (_s) + 1, sizeof(char)); \
for (size_t _i = 0; _i < (size_t)(_s); _i++) { \
sprintf(&_tmp[2 * _i], "%02X", (_p)[_i]); \
} \
printf("%s\n", _tmp); \

View file

@ -3,16 +3,16 @@
* Copyright (c) 2022 Pol Henarejos.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, version 3.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
* Affero General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
#include "eac.h"
@ -144,7 +144,7 @@ int sm_wrap() {
if (sm_indicator == 0) {
return PICOKEY_OK;
}
uint8_t input[4096];
uint8_t input[2048];
size_t input_len = 0;
memset(input, 0, sizeof(input));
mbedtls_mpi ssc;
@ -181,16 +181,15 @@ int sm_wrap() {
else {
memmove(res_APDU + 4, res_APDU, res_APDU_size);
res_APDU[1] = 0x82;
res_APDU[2] = (uint8_t)(res_APDU_size >> 8);
res_APDU[3] = (uint8_t)(res_APDU_size & 0xff);
put_uint16_t_be(res_APDU_size, res_APDU + 2);
res_APDU_size += 4;
}
res_APDU[0] = 0x87;
}
res_APDU[res_APDU_size++] = 0x99;
res_APDU[res_APDU_size++] = 2;
res_APDU[res_APDU_size++] = apdu.sw >> 8;
res_APDU[res_APDU_size++] = apdu.sw & 0xff;
put_uint16_t_be(apdu.sw, res_APDU + res_APDU_size);
res_APDU_size += 2;
memcpy(input + input_len, res_APDU, res_APDU_size);
input_len += res_APDU_size;
input[input_len++] = 0x80;
@ -233,16 +232,16 @@ void sm_update_iv() {
}
int sm_verify() {
uint8_t input[4096];
uint8_t input[2048];
memset(input, 0, sizeof(input));
uint16_t input_len = 0;
int r = 0;
bool add_header = (CLA(apdu) & 0xC) == 0xC;
int data_len = (int) (apdu.nc / sm_blocksize) * sm_blocksize;
size_t data_len = (size_t)(apdu.nc / sm_blocksize) * sm_blocksize;
if (data_len % sm_blocksize) {
data_len += sm_blocksize;
}
if (data_len + (add_header ? sm_blocksize : 0) > 4096) {
if (data_len + (add_header ? sm_blocksize : 0) > sizeof(input)) {
return PICOKEY_WRONG_LENGTH;
}
mbedtls_mpi ssc;

View file

@ -3,16 +3,16 @@
* Copyright (c) 2022 Pol Henarejos.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, version 3.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
* Affero General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
#ifndef _EAC_H_

View file

@ -3,16 +3,16 @@
* Copyright (c) 2022 Pol Henarejos.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, version 3.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
* Affero General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
#ifndef __ESP_COMPAT_H_
@ -30,7 +30,19 @@ typedef QueueHandle_t queue_t;
#define queue_is_empty(a) (uxQueueMessagesWaiting(*(a)) == 0)
#define queue_try_remove(a,b) xQueueReceive(*(a), b, 0)
extern TaskHandle_t hcore0, hcore1;
#define multicore_launch_core1(a) xTaskCreatePinnedToCore((void(*)(void *))a, "core1", 4096*5, NULL, CONFIG_TINYUSB_TASK_PRIORITY - 2, &hcore1, 1)
#ifdef CONFIG_IDF_TARGET_ESP32S3
#define ESP32_CORE0 0
#define ESP32_CORE1 1
#else
#define ESP32_CORE0 tskNO_AFFINITY
#define ESP32_CORE1 tskNO_AFFINITY
#endif
static inline void task_wrapper(void *arg) {
void* (*func)(void*) = (void* (*)(void*))arg;
func(NULL);
vTaskDelete(NULL);
}
#define multicore_launch_func_core1(func) xTaskCreatePinnedToCore(task_wrapper, "core1", 4096*ITF_TOTAL*2, (void *)func, CONFIG_TINYUSB_TASK_PRIORITY - 2, &hcore1, ESP32_CORE1)
#define multicore_reset_core1() do { if (hcore1) { eTaskState e = eTaskGetState(hcore1); if (e <= eSuspended) { vTaskDelete(hcore1); }} }while(0)
#define sleep_ms(a) vTaskDelay(a / portTICK_PERIOD_MS)
static inline uint32_t board_millis(void) {

View file

@ -3,16 +3,16 @@
* Copyright (c) 2022 Pol Henarejos.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, version 3.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
* Affero General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
#include "file.h"
@ -56,13 +56,11 @@ void process_fci(const file_t *pe, int fmd) {
if (pe->data) {
if ((pe->type & FILE_DATA_FUNC) == FILE_DATA_FUNC) {
uint16_t len = (uint16_t)((int (*)(const file_t *, int))(pe->data))(pe, 0);
res_APDU[res_APDU_size++] = (len >> 8) & 0xff;
res_APDU[res_APDU_size++] = len & 0xff;
res_APDU_size += put_uint16_t_be(len, res_APDU + res_APDU_size);
}
else {
uint16_t v = file_get_size(pe);
res_APDU[res_APDU_size++] = v >> 8;
res_APDU[res_APDU_size++] = v & 0xff;
res_APDU_size += put_uint16_t_be(v, res_APDU + res_APDU_size);
}
}
else {
@ -88,8 +86,7 @@ void process_fci(const file_t *pe, int fmd) {
res_APDU[res_APDU_size++] = 0x83;
res_APDU[res_APDU_size++] = 2;
put_uint16_t(pe->fid, res_APDU + res_APDU_size);
res_APDU_size += 2;
res_APDU_size += put_uint16_t_be(pe->fid, res_APDU + res_APDU_size);
if (pe->name) {
res_APDU[res_APDU_size++] = 0x84;
res_APDU[res_APDU_size++] = MIN(pe->name[0], 16);
@ -113,7 +110,6 @@ void process_fci(const file_t *pe, int fmd) {
}
}
#define MAX_DYNAMIC_FILES 128
uint16_t dynamic_files = 0;
file_t dynamic_file[MAX_DYNAMIC_FILES];
@ -177,13 +173,13 @@ uint8_t make_path_buf(const file_t *pe, uint8_t *buf, uint8_t buflen, const file
if (pe == top) { //MF or relative DF
return 0;
}
put_uint16_t(pe->fid, buf);
put_uint16_t_be(pe->fid, buf);
return make_path_buf(&file_entries[pe->parent], buf + 2, buflen - 2, top) + 2;
}
uint8_t make_path(const file_t *pe, const file_t *top, uint8_t *path) {
uint8_t buf[MAX_DEPTH * 2], *p = path;
put_uint16_t(pe->fid, buf);
put_uint16_t_be(pe->fid, buf);
uint8_t depth = make_path_buf(&file_entries[pe->parent], buf + 2, sizeof(buf) - 2, top) + 2;
for (int d = depth - 2; d >= 0; d -= 2) {
memcpy(p, buf + d, 2);
@ -245,29 +241,40 @@ void initialize_flash(bool hard) {
dynamic_files = 0;
}
void scan_region(bool persistent) {
extern uintptr_t last_base;
extern uint32_t num_files;
void scan_region(bool persistent)
{
uintptr_t endp = end_data_pool, startp = start_data_pool;
if (persistent) {
endp = end_rom_pool;
startp = start_rom_pool;
}
else {
last_base = endp;
num_files = 0;
}
for (uintptr_t base = flash_read_uintptr(endp); base >= startp; base = flash_read_uintptr(base)) {
if (base == 0x0) { //all is empty
break;
}
uint16_t fid = flash_read_uint16(base + sizeof(uintptr_t) + sizeof(uintptr_t));
printf("[%x] scan fid %x, len %d\n", (unsigned int) base, fid,
flash_read_uint16(base + sizeof(uintptr_t) + sizeof(uintptr_t) + sizeof(uint16_t)));
printf("[%x] scan fid %x, len %d\n", (unsigned int) base, fid, flash_read_uint16(base + sizeof(uintptr_t) + sizeof(uintptr_t) + sizeof(uint16_t)));
file_t *file = (file_t *) search_by_fid(fid, NULL, SPECIFY_EF);
if (!file) {
file = file_new(fid);
}
if (file) {
file->data =
(uint8_t *) (base + sizeof(uintptr_t) + sizeof(uintptr_t) + sizeof(uint16_t));
file->data = (uint8_t *) (base + sizeof(uintptr_t) + sizeof(uintptr_t) + sizeof(uint16_t));
}
if (!persistent) {
num_files++;
}
if (flash_read_uintptr(base) == 0x0) {
if (base < last_base) {
last_base = base;
}
break;
}
}
@ -275,7 +282,7 @@ void scan_region(bool persistent) {
void wait_flash_finish();
void scan_flash() {
initialize_flash(false); //soft initialization
uint32_t r1 = *(uintptr_t *) flash_read(end_rom_pool), r2 = *(uintptr_t *) flash_read(end_rom_pool + sizeof(uintptr_t));
uint32_t r1 = (uint32_t)(*(uintptr_t *) flash_read(end_rom_pool)), r2 = (uint32_t)(*(uintptr_t *) flash_read(end_rom_pool + sizeof(uintptr_t)));
if ((r1 == 0xffffffff || r1 == 0xefefefef) && (r2 == 0xffffffff || r2 == 0xefefefef)) {
printf("First initialization (or corrupted!)\n");
uint8_t empty[sizeof(uintptr_t) * 2 + sizeof(uint32_t)];
@ -383,7 +390,7 @@ uint16_t meta_find(uint16_t fid, uint8_t **out) {
if (tag_len < 2) {
continue;
}
uint16_t cfid = (tag_data[0] << 8 | tag_data[1]);
uint16_t cfid = get_uint16_t_be(tag_data);
if (cfid == fid) {
if (out) {
*out = tag_data + 2;
@ -409,7 +416,7 @@ int meta_delete(uint16_t fid) {
if (tag_len < 2) {
continue;
}
uint16_t cfid = (tag_data[0] << 8 | tag_data[1]);
uint16_t cfid = get_uint16_t_be(tag_data);
if (cfid == fid) {
uint16_t new_len = ctxi.len - 1 - tag_len - format_tlv_len(tag_len, NULL);
if (new_len == 0) {
@ -453,7 +460,7 @@ int meta_add(uint16_t fid, const uint8_t *data, uint16_t len) {
if (tag_len < 2) {
continue;
}
uint16_t cfid = (tag_data[0] << 8 | tag_data[1]);
uint16_t cfid = get_uint16_t_be(tag_data);
if (cfid == fid) {
if (tag_len - 2 == len) { //an update
memcpy(p - tag_len + 2, data, len);
@ -483,8 +490,7 @@ int meta_add(uint16_t fid, const uint8_t *data, uint16_t len) {
uint8_t *f = fdata + meta_offset;
*f++ = fid & 0xff;
f += format_tlv_len(len + 2, f);
*f++ = fid >> 8;
*f++ = fid & 0xff;
f += put_uint16_t_be(fid, f);
memcpy(f, data, len);
r = file_put_data(ef, fdata, ef_size);
free(fdata);
@ -499,8 +505,7 @@ int meta_add(uint16_t fid, const uint8_t *data, uint16_t len) {
uint8_t *f = fdata + ef_size;
*f++ = fid & 0x1f;
f += format_tlv_len(len + 2, f);
*f++ = fid >> 8;
*f++ = fid & 0xff;
f += put_uint16_t_be(fid, f);
memcpy(f, data, len);
r = file_put_data(ef, fdata, ef_size + (uint16_t)asn1_len_tag(fid & 0x1f, len + 2));
free(fdata);

View file

@ -3,23 +3,23 @@
* Copyright (c) 2022 Pol Henarejos.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, version 3.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
* Affero General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
#ifndef _FILE_H_
#define _FILE_H_
#include <stdlib.h>
#if !defined(ENABLE_EMULATION) && !defined(ESP_PLATFORM)
#if defined(PICO_PLATFORM)
#include "pico/stdlib.h"
#else
#include <stdbool.h>
@ -69,15 +69,29 @@
#define MAX_DEPTH 4
#define MAX_DYNAMIC_FILES 256
#ifdef _MSC_VER
__pragma( pack(push, 1) )
#endif
typedef struct file {
const uint16_t fid;
const uint8_t parent; //entry number in the whole table!!
const uint8_t *name;
uint8_t *data; //should include 2 bytes len at begining
const uint16_t fid;
const uint8_t acl[7];
const uint8_t parent; //entry number in the whole table!!
const uint8_t type;
const uint8_t ef_structure;
uint8_t *data; //should include 2 bytes len at begining
const uint8_t acl[7];
} file_t;
#ifdef ENABLE_EMULATION
uint32_t _padding;
#endif
}
#ifdef _MSC_VER
__pragma( pack(pop) )
#else
__attribute__ ((packed))
#endif
file_t;
extern bool file_has_data(file_t *);
@ -128,6 +142,12 @@ extern int meta_delete(uint16_t fid);
extern int meta_add(uint16_t fid, const uint8_t *data, uint16_t len);
extern int delete_file(file_t *ef);
extern uint32_t flash_free_space();
extern uint32_t flash_used_space();
extern uint32_t flash_total_space();
extern uint32_t flash_num_files();
extern uint32_t flash_size();
#ifndef ENABLE_EMULATION
extern file_t *ef_phy;
#endif

28
src/fs/files.c Normal file
View file

@ -0,0 +1,28 @@
/*
* This file is part of the Pico Keys SDK distribution (https://github.com/polhenarejos/pico-keys-sdk).
* Copyright (c) 2022 Pol Henarejos.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, version 3.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
#include "file.h"
file_t file_entries[] = {
/* 0 */ { .fid = 0x3f00, .parent = 0xff, .name = NULL, .type = FILE_TYPE_DF, .data = NULL,
.ef_structure = 0, .acl = { 0 } }, // MF
/* 1 */ { .fid = 0x0000, .parent = 0xff, .name = NULL, .type = FILE_TYPE_NOT_KNOWN, .data = NULL,
.ef_structure = 0, .acl = { 0 } } //end
};
const file_t *MF = &file_entries[0];
const file_t *file_last = &file_entries[sizeof(file_entries) / sizeof(file_t) - 1];

View file

@ -3,35 +3,36 @@
* Copyright (c) 2022 Pol Henarejos.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, version 3.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
* Affero General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
#include <stdint.h>
#include <string.h>
#include "pico_keys.h"
#if defined(ENABLE_EMULATION) || defined(ESP_PLATFORM)
#if !defined(PICO_PLATFORM)
#define XIP_BASE 0
#define FLASH_SECTOR_SIZE 4096
#ifdef ESP_PLATFORM
#define PICO_FLASH_SIZE_BYTES (1 * 1024 * 1024)
uint32_t FLASH_SIZE_BYTES = (1 * 1024 * 1024);
#else
#define PICO_FLASH_SIZE_BYTES (8 * 1024 * 1024)
#define FLASH_SIZE_BYTES (8 * 1024 * 1024)
#endif
#else
uint32_t FLASH_SIZE_BYTES = (2 * 1024 * 1024);
#include "pico/stdlib.h"
#include "hardware/flash.h"
#endif
#include "pico_keys.h"
#include "file.h"
#include <stdio.h>
@ -42,27 +43,12 @@
* | |
* ------------------------------------------------------
*/
#ifdef ESP_PLATFORM
#define FLASH_TARGET_OFFSET 0
#else
#define FLASH_TARGET_OFFSET (PICO_FLASH_SIZE_BYTES >> 1) // DATA starts at the mid of flash
#endif
#define FLASH_DATA_HEADER_SIZE (sizeof(uintptr_t) + sizeof(uint32_t))
#define FLASH_PERMANENT_REGION (4 * FLASH_SECTOR_SIZE) // 4 sectors (16kb) of permanent memory
//To avoid possible future allocations, data region starts at the end of flash and goes upwards to the center region
#ifdef PICO_RP2350
// Table partition for RP2350 needs 8kb
const uintptr_t end_flash = (XIP_BASE + PICO_FLASH_SIZE_BYTES - 2 * FLASH_SECTOR_SIZE);
#else
const uintptr_t end_flash = (XIP_BASE + PICO_FLASH_SIZE_BYTES);
#endif
const uintptr_t end_rom_pool = end_flash - FLASH_DATA_HEADER_SIZE - 4; //This is a fixed value. DO NOT CHANGE
const uintptr_t start_rom_pool = end_rom_pool - FLASH_PERMANENT_REGION; //This is a fixed value. DO NOT CHANGE
const uintptr_t end_data_pool = start_rom_pool - FLASH_DATA_HEADER_SIZE; //This is a fixed value. DO NOT CHANGE
const uintptr_t start_data_pool = (XIP_BASE + FLASH_TARGET_OFFSET);
uintptr_t end_flash, end_rom_pool, start_rom_pool, end_data_pool, start_data_pool;
extern int flash_program_block(uintptr_t addr, const uint8_t *data, size_t len);
extern int flash_program_halfword(uintptr_t addr, uint16_t data);
@ -73,12 +59,24 @@ extern uint8_t *flash_read(uintptr_t addr);
extern void low_flash_available();
uintptr_t last_base;
uint32_t num_files = 0;
void flash_set_bounds(uintptr_t start, uintptr_t end) {
end_flash = end;
end_rom_pool = end_flash - FLASH_DATA_HEADER_SIZE - 4;
start_rom_pool = end_rom_pool - FLASH_PERMANENT_REGION;
end_data_pool = start_rom_pool - FLASH_DATA_HEADER_SIZE;
start_data_pool = start;
last_base = end_data_pool;
}
uintptr_t allocate_free_addr(uint16_t size, bool persistent) {
if (size > FLASH_SECTOR_SIZE) {
return 0x0; //ERROR
}
size_t real_size = size + sizeof(uint16_t) + sizeof(uintptr_t) + sizeof(uint16_t) +
sizeof(uintptr_t); //len+len size+next address+fid+prev_addr size
size_t real_size = size + sizeof(uint16_t) + sizeof(uintptr_t) + sizeof(uint16_t) + sizeof(uintptr_t); //len+len size+next address+fid+prev_addr size
uintptr_t next_base = 0x0, endp = end_data_pool, startp = start_data_pool;
if (persistent) {
endp = end_rom_pool;
@ -108,14 +106,9 @@ uintptr_t allocate_free_addr(uint16_t size, bool persistent) {
return 0x0;
}
//we check if |base-(next_addr+size_next_addr)| > |base-potential_addr| only if fid != 1xxx (not size blocked)
else if (addr_alg <= potential_addr &&
base -
(next_base +
flash_read_uint16(next_base + sizeof(uintptr_t) + sizeof(uintptr_t) +
sizeof(uint16_t)) +
2 *
sizeof(uint16_t) + 2 * sizeof(uintptr_t)) > base - potential_addr &&
(flash_read_uint16(next_base + 2 * sizeof(uintptr_t)) & 0x1000) != 0x1000) {
else if (addr_alg <= potential_addr
&& base - (next_base + flash_read_uint16(next_base + sizeof(uintptr_t) + sizeof(uintptr_t) + sizeof(uint16_t)) + 2 * sizeof(uint16_t) + 2 * sizeof(uintptr_t)) > base - potential_addr
&& (flash_read_uint16(next_base + 2 * sizeof(uintptr_t)) & 0x1000) != 0x1000) {
flash_program_uintptr(potential_addr, next_base);
flash_program_uintptr(next_base + sizeof(uintptr_t), potential_addr);
flash_program_uintptr(potential_addr + sizeof(uintptr_t), base);
@ -130,8 +123,7 @@ int flash_clear_file(file_t *file) {
if (file == NULL || file->data == NULL) {
return PICOKEY_OK;
}
uintptr_t base_addr =
(uintptr_t)(file->data - sizeof(uintptr_t) - sizeof(uint16_t) - sizeof(uintptr_t));
uintptr_t base_addr = (uintptr_t)(file->data - sizeof(uintptr_t) - sizeof(uint16_t) - sizeof(uintptr_t));
uintptr_t prev_addr = flash_read_uintptr(base_addr + sizeof(uintptr_t));
uintptr_t next_addr = flash_read_uintptr(base_addr);
//printf("nc %lx->%lx %lx->%lx\n",prev_addr,flash_read_uintptr(prev_addr),base_addr,next_addr);
@ -143,12 +135,12 @@ int flash_clear_file(file_t *file) {
flash_program_uintptr(base_addr, 0);
flash_program_uintptr(base_addr + sizeof(uintptr_t), 0);
file->data = NULL;
num_files--;
//printf("na %lx->%lx\n",prev_addr,flash_read_uintptr(prev_addr));
return PICOKEY_OK;
}
int flash_write_data_to_file_offset(file_t *file, const uint8_t *data, uint16_t len,
uint16_t offset) {
int flash_write_data_to_file_offset(file_t *file, const uint8_t *data, uint16_t len, uint16_t offset) {
if (!file) {
return PICOKEY_ERR_NULL_PARAM;
}
@ -182,6 +174,9 @@ int flash_write_data_to_file_offset(file_t *file, const uint8_t *data, uint16_t
if (new_addr == 0x0) {
return PICOKEY_ERR_NO_MEMORY;
}
if (new_addr < last_base) {
last_base = new_addr;
}
file->data = (uint8_t *) new_addr + sizeof(uintptr_t) + sizeof(uint16_t) + sizeof(uintptr_t); //next addr+fid+prev addr
flash_program_halfword(new_addr + sizeof(uintptr_t) + sizeof(uintptr_t), file->fid);
flash_program_halfword((uintptr_t) file->data, len);
@ -191,8 +186,30 @@ int flash_write_data_to_file_offset(file_t *file, const uint8_t *data, uint16_t
if (old_data) {
free(old_data);
}
num_files++;
return PICOKEY_OK;
}
int flash_write_data_to_file(file_t *file, const uint8_t *data, uint16_t len) {
return flash_write_data_to_file_offset(file, data, len, 0);
}
uint32_t flash_free_space() {
return (uint32_t)(last_base - start_data_pool);
}
uint32_t flash_used_space() {
return (uint32_t)(end_data_pool - last_base);
}
uint32_t flash_total_space() {
return (uint32_t)(end_data_pool - start_data_pool);
}
uint32_t flash_num_files() {
return num_files;
}
uint32_t flash_size() {
return FLASH_SIZE_BYTES;
}

View file

@ -3,16 +3,16 @@
* Copyright (c) 2022 Pol Henarejos.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, version 3.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
* Affero General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
@ -29,46 +29,54 @@
#include "pico/mutex.h"
#include "pico/sem.h"
#include "pico/multicore.h"
#include "pico/bootrom.h"
#include "boot/picobin.h"
#else
#ifdef _MSC_VER
#include <windows.h>
#include <io.h>
#define O_RDWR _O_RDWR
#define O_CREAT _O_CREAT
#define open _open
#define write _write
#define mode_t unsigned short
#define lseek _lseek
#include "mman.h"
#ifdef ESP_PLATFORM
#include "esp_compat.h"
#include "esp_partition.h"
const esp_partition_t *part0;
#define save_and_disable_interrupts() 1
#define flash_range_erase(a,b) esp_partition_erase_range(part0, a, b)
#define flash_range_program(a,b,c) esp_partition_write(part0, a, b, c);
#define restore_interrupts(a) (void)a
#else
#ifdef ESP_PLATFORM
#include "esp_compat.h"
#include "esp_partition.h"
const esp_partition_t *part0;
#define save_and_disable_interrupts() 1
#define flash_range_erase(a,b) esp_partition_erase_range(part0, a, b)
#define flash_range_program(a,b,c) esp_partition_write(part0, a, b, c);
#define restore_interrupts(a) (void)a
#ifdef _MSC_VER
#include <windows.h>
#include <io.h>
#define O_RDWR _O_RDWR
#define O_CREAT _O_CREAT
#define open _open
#define write _write
#define mode_t unsigned short
#define lseek _lseek
#include "mman.h"
#else
#include <unistd.h>
#include <sys/mman.h>
#include "emulation.h"
#endif
#include "queue.h"
#endif
#define FLASH_SECTOR_SIZE 4096
#define PICO_FLASH_SIZE_BYTES (8 * 1024 * 1024)
#define XIP_BASE 0
int fd_map = 0;
uint8_t *map = NULL;
#include <fcntl.h>
#endif
#if defined(PICO_PLATFORM) || defined(ESP_PLATFORM)
extern uint32_t FLASH_SIZE_BYTES;
#else
#define FLASH_SIZE_BYTES (8 * 1024 * 1024)
#endif
#define TOTAL_FLASH_PAGES 6
#define FLASH_LOCKOUT_RETRIES 5
extern void flash_set_bounds(uintptr_t start, uintptr_t end);
extern const uintptr_t start_data_pool;
extern const uintptr_t end_rom_pool;
typedef struct page_flash {
uint8_t page[FLASH_SECTOR_SIZE];
uintptr_t address;
@ -100,18 +108,16 @@ void do_flash() {
//printf(" DO_FLASH AVAILABLE\n");
for (int r = 0; r < TOTAL_FLASH_PAGES; r++) {
if (flash_pages[r].ready == true) {
#ifndef ENABLE_EMULATION
#if defined(PICO_PLATFORM) || defined(ESP_PLATFORM)
//printf("WRITTING %X\n",flash_pages[r].address-XIP_BASE);
while (multicore_lockout_start_timeout_us(1000) == false) {
;
for (int retries = 0; retries < FLASH_LOCKOUT_RETRIES && multicore_lockout_start_timeout_us(1000) == false; retries++) {
}
//printf("WRITTING %X\n",flash_pages[r].address-XIP_BASE);
uint32_t ints = save_and_disable_interrupts();
flash_range_erase(flash_pages[r].address - XIP_BASE, FLASH_SECTOR_SIZE);
flash_range_program(flash_pages[r].address - XIP_BASE, flash_pages[r].page, FLASH_SECTOR_SIZE);
restore_interrupts(ints);
while (multicore_lockout_end_timeout_us(1000) == false) {
;
for (int retries = 0; retries < FLASH_LOCKOUT_RETRIES && multicore_lockout_end_timeout_us(1000) == false; retries++) {
}
//printf("WRITEN %X !\n",flash_pages[r].address);
#else
@ -121,17 +127,12 @@ void do_flash() {
ready_pages--;
}
else if (flash_pages[r].erase == true) {
#ifndef ENABLE_EMULATION
while (multicore_lockout_start_timeout_us(1000) == false) {
;
#if defined(PICO_PLATFORM) || defined(ESP_PLATFORM)
for (int retries = 0; retries < FLASH_LOCKOUT_RETRIES && multicore_lockout_start_timeout_us(1000) == false; retries++) {
}
//printf("WRITTING\n");
flash_range_erase(flash_pages[r].address - XIP_BASE,
flash_pages[r].page_size ? ((int) (flash_pages[r].page_size /
FLASH_SECTOR_SIZE)) *
FLASH_SECTOR_SIZE : FLASH_SECTOR_SIZE);
while (multicore_lockout_end_timeout_us(1000) == false) {
;
flash_range_erase(flash_pages[r].address - XIP_BASE, flash_pages[r].page_size ? ((int) (flash_pages[r].page_size / FLASH_SECTOR_SIZE)) * FLASH_SECTOR_SIZE : FLASH_SECTOR_SIZE);
for (int retries = 0; retries < FLASH_LOCKOUT_RETRIES && multicore_lockout_end_timeout_us(1000) == false; retries++) {
}
#else
memset(map + flash_pages[r].address, 0, FLASH_SECTOR_SIZE);
@ -140,8 +141,8 @@ void do_flash() {
ready_pages--;
}
}
#ifdef ENABLE_EMULATION
msync(map, PICO_FLASH_SIZE_BYTES, MS_SYNC);
#if !defined(PICO_PLATFORM) && !defined(ESP_PLATFORM)
msync(map, FLASH_SIZE_BYTES, MS_SYNC);
#endif
if (ready_pages != 0) {
printf("ERROR: DO FLASH DOES NOT HAVE ZERO PAGES\n");
@ -162,17 +163,60 @@ void low_flash_init() {
memset(flash_pages, 0, sizeof(page_flash_t) * TOTAL_FLASH_PAGES);
mutex_init(&mtx_flash);
sem_init(&sem_flash, 0, 1);
#if defined(ENABLE_EMULATION)
fd_map = open("memory.flash", O_RDWR | O_CREAT, (mode_t) 0600);
lseek(fd_map, PICO_FLASH_SIZE_BYTES - 1, SEEK_SET);
write(fd_map, "", 1);
map = mmap(0, PICO_FLASH_SIZE_BYTES, PROT_READ | PROT_WRITE, MAP_SHARED, fd_map, 0);
#else
uint32_t data_start_addr;
uint32_t data_end_addr;
#if defined(ESP_PLATFORM)
part0 = esp_partition_find_first(0x40, 0x1, "part0");
esp_partition_mmap(part0, 0, part0->size, ESP_PARTITION_MMAP_DATA, (const void **)&map, (esp_partition_mmap_handle_t *)&fd_map);
data_start_addr = 0;
data_end_addr = part0->size;
FLASH_SIZE_BYTES = part0->size;
#elif defined(PICO_PLATFORM)
uint8_t txbuf[6] = {0x9f};
uint8_t rxbuf[6] = {0};
flash_do_cmd(txbuf, rxbuf, 4);
FLASH_SIZE_BYTES = (1 << rxbuf[3]);
#ifdef PICO_RP2350
__attribute__((aligned(4))) uint8_t workarea[4 * 1024];
int rc = rom_load_partition_table(workarea, sizeof(workarea), false);
if (rc) {
reset_usb_boot(0, 0);
}
uint8_t boot_partition = 1;
rc = rom_get_partition_table_info((uint32_t*)workarea, 0x8, PT_INFO_PARTITION_LOCATION_AND_FLAGS | PT_INFO_SINGLE_PARTITION | (boot_partition << 24));
if (rc != 3) {
data_start_addr = (FLASH_SIZE_BYTES >> 1);
data_end_addr = FLASH_SIZE_BYTES;
} else {
uint16_t first_sector_number = (((uint32_t*)workarea)[1] & PICOBIN_PARTITION_LOCATION_FIRST_SECTOR_BITS) >> PICOBIN_PARTITION_LOCATION_FIRST_SECTOR_LSB;
uint16_t last_sector_number = (((uint32_t*)workarea)[1] & PICOBIN_PARTITION_LOCATION_LAST_SECTOR_BITS) >> PICOBIN_PARTITION_LOCATION_LAST_SECTOR_LSB;
data_start_addr = first_sector_number * FLASH_SECTOR_SIZE;
data_end_addr = (last_sector_number + 1) * FLASH_SECTOR_SIZE;
if (data_end_addr > FLASH_SIZE_BYTES) {
data_end_addr = FLASH_SIZE_BYTES;
}
}
data_end_addr -= 2 * FLASH_SECTOR_SIZE;
#else
data_start_addr = (FLASH_SIZE_BYTES >> 1);
data_end_addr = FLASH_SIZE_BYTES;
#endif
data_start_addr += XIP_BASE;
data_end_addr += XIP_BASE;
#else
fd_map = open("memory.flash", O_RDWR | O_CREAT, (mode_t) 0600);
lseek(fd_map, FLASH_SIZE_BYTES - 1, SEEK_SET);
write(fd_map, "", 1);
map = mmap(0, FLASH_SIZE_BYTES, PROT_READ | PROT_WRITE, MAP_SHARED, fd_map, 0);
data_start_addr = 0;
data_end_addr = FLASH_SIZE_BYTES;
#endif
flash_set_bounds(data_start_addr, data_end_addr);
}
void low_flash_init_core1() {
@ -205,10 +249,7 @@ page_flash_t *find_free_page(uintptr_t addr) {
#ifdef PICO_PLATFORM
memcpy(p->page, (uint8_t *) addr_alg, FLASH_SECTOR_SIZE);
#else
memcpy(p->page,
(addr >= start_data_pool &&
addr <= end_rom_pool + sizeof(uintptr_t)) ? (uint8_t *) (map + addr_alg) : (uint8_t *) addr_alg,
FLASH_SECTOR_SIZE);
memcpy(p->page, (addr >= start_data_pool && addr <= end_rom_pool + sizeof(uintptr_t)) ? (uint8_t *) (map + addr_alg) : (uint8_t *) addr_alg, FLASH_SECTOR_SIZE);
#endif
ready_pages++;
p->address = addr_alg;
@ -270,7 +311,7 @@ uint8_t *flash_read(uintptr_t addr) {
}
uint8_t *v = (uint8_t *) addr;
mutex_exit(&mtx_flash);
#if defined(ENABLE_EMULATION) || defined(ESP_PLATFORM)
#if !defined(PICO_PLATFORM)
if (addr >= start_data_pool && addr <= end_rom_pool + sizeof(uintptr_t)) {
v += (uintptr_t) map;
}
@ -281,7 +322,7 @@ uint8_t *flash_read(uintptr_t addr) {
uintptr_t flash_read_uintptr(uintptr_t addr) {
uint8_t *p = flash_read(addr);
uintptr_t v = 0x0;
for (int i = 0; i < sizeof(uintptr_t); i++) {
for (size_t i = 0; i < sizeof(uintptr_t); i++) {
v |= (uintptr_t) p[i] << (8 * i);
}
return v;
@ -289,7 +330,7 @@ uintptr_t flash_read_uintptr(uintptr_t addr) {
uint16_t flash_read_uint16(uintptr_t addr) {
uint8_t *p = flash_read(addr);
uint16_t v = 0x0;
for (int i = 0; i < sizeof(uint16_t); i++) {
for (size_t i = 0; i < sizeof(uint16_t); i++) {
v |= p[i] << (8 * i);
}
return v;

View file

@ -1,3 +1,20 @@
/*
* This file is part of the Pico Keys SDK distribution (https://github.com/polhenarejos/pico-keys-sdk).
* Copyright (c) 2022 Pol Henarejos.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, version 3.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
#include <windows.h>
#include <errno.h>

View file

@ -1,14 +1,27 @@
/*
* sys/mman.h
* mman-win32
* This file is part of the Pico Keys SDK distribution (https://github.com/polhenarejos/pico-keys-sdk).
* Copyright (c) 2022 Pol Henarejos.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, version 3.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
#ifndef _SYS_MMAN_H_
#define _SYS_MMAN_H_
#ifndef _WIN32_WINNT // Allow use of features specific to Windows XP or later.
#ifndef _WIN32_WINNT // Allow use of features specific to Windows XP or later.
#define _WIN32_WINNT 0x0501 // Change this to the appropriate value to target other versions of Windows.
#endif
#endif
/* All the headers include this file. */
#ifndef _MSC_VER

View file

@ -3,16 +3,16 @@
* Copyright (c) 2022 Pol Henarejos.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, version 3.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
* Affero General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
#include "file.h"
@ -27,6 +27,7 @@
#endif
#include "random.h"
#include "mbedtls/ecdsa.h"
#include <stdalign.h>
#ifdef PICO_RP2350
@ -39,35 +40,35 @@ static bool is_empty_buffer(const uint8_t *buffer, uint16_t buffer_len) {
return true;
}
static int otp_write_data_mode(uint16_t row, uint8_t *data, uint16_t len, bool is_ecc) {
static int otp_write_data_mode(uint16_t row, const uint8_t *data, uint16_t len, bool is_ecc) {
otp_cmd_t cmd = { .flags = row | (is_ecc ? OTP_CMD_ECC_BITS : 0) | OTP_CMD_WRITE_BITS };
uint32_t ret = rom_func_otp_access(data, len, cmd);
uint32_t ret = rom_func_otp_access((uint8_t *)data, len, cmd);
if (ret) {
printf("OTP Write failed with error: %ld\n", ret);
}
return ret;
}
int otp_write_data(uint16_t row, uint8_t *data, uint16_t len) {
int otp_write_data(uint16_t row, const uint8_t *data, uint16_t len) {
return otp_write_data_mode(row, data, len, true);
}
int otp_write_data_raw(uint16_t row, uint8_t *data, uint16_t len) {
int otp_write_data_raw(uint16_t row, const uint8_t *data, uint16_t len) {
return otp_write_data_mode(row, data, len, false);
}
uint8_t* otp_buffer(uint16_t row) {
const uint8_t* otp_buffer(uint16_t row) {
volatile uint32_t *p = ((uint32_t *)(OTP_DATA_BASE + (row*2)));
return (uint8_t *)p;
return (const uint8_t *)p;
}
uint8_t* otp_buffer_raw(uint16_t row) {
const uint8_t* otp_buffer_raw(uint16_t row) {
volatile uint32_t *p = ((uint32_t *)(OTP_DATA_RAW_BASE + (row*4)));
return (uint8_t *)p;
return (const uint8_t *)p;
}
bool is_empty_otp_buffer(uint16_t row, uint16_t len) {
return is_empty_buffer(otp_buffer(row), len);
return is_empty_buffer(otp_buffer_raw(row), len * 2);
}
static bool is_otp_locked_page(uint8_t page) {
@ -77,7 +78,7 @@ static bool is_otp_locked_page(uint8_t page) {
static void otp_lock_page(uint8_t page) {
if (!is_otp_locked_page(page)) {
uint32_t value = 0x3c3c3c;
alignas(4) uint32_t value = 0x3c3c3c;
otp_write_data_raw(OTP_DATA_PAGE0_LOCK0_ROW + page*2 + 1, (uint8_t *)&value, sizeof(value));
}
@ -112,7 +113,7 @@ typedef int otp_ret_t;
#define OTP_EMTPY(ROW, LEN) is_empty_otp_buffer(ROW, LEN)
#elif defined(ESP_PLATFORM)
typedef esp_err_t otp_ret_t;
#define OTP_WRITE(ROW, DATA, LEN) esp_efuse_write_key(ROW, ESP_EFUSE_KEY_PURPOSE_USER, DATA, LEN);
#define OTP_WRITE(ROW, DATA, LEN) esp_efuse_write_key(ROW, ESP_EFUSE_KEY_PURPOSE_USER, DATA, LEN)
#define OTP_READ(ROW, PTR) do { \
esp_err_t ret = read_key_from_efuse(ROW, _##PTR, sizeof(_##PTR)); \
if (ret != ESP_OK) { printf("Error reading OTP key 1 [%d]\n", ret); } \
@ -124,16 +125,70 @@ typedef esp_err_t otp_ret_t;
#define SECURE_BOOT_BOOTKEY_INDEX 0
#endif
bool otp_is_secure_boot_enabled(uint8_t *bootkey) {
#ifdef PICO_RP2350
const uint8_t *crit1 = otp_buffer(OTP_DATA_CRIT1_ROW);
if ((crit1[0] & (1 << OTP_DATA_CRIT1_SECURE_BOOT_ENABLE_LSB)) == 0) {
return false;
}
alignas(2) uint8_t BOOTKEY[] = "\xe1\xd1\x6b\xa7\x64\xab\xd7\x12\xd4\xef\x6e\x3e\xdd\x74\x4e\xd5\x63\x8c\x26\xb\x77\x1c\xf9\x81\x51\x11\xb\xaf\xac\x9b\xc8\x71";
uint8_t bootkey_idx = 0;
for (; bootkey_idx < 6; bootkey_idx++) {
const uint8_t *bootkey_row = otp_buffer(OTP_DATA_BOOTKEY0_0_ROW + 0x10 * bootkey_idx);
if (memcmp(bootkey_row, BOOTKEY, sizeof(BOOTKEY)) == 0) {
break;
}
}
if (bootkey_idx == 6) {
return false;
}
const uint8_t *boot_flags1 = otp_buffer(OTP_DATA_BOOT_FLAGS1_ROW);
if ((boot_flags1[0] & (1 << (bootkey_idx + OTP_DATA_BOOT_FLAGS1_KEY_VALID_LSB))) == 0) {
return false;
}
if (bootkey) {
*bootkey = bootkey_idx;
}
return true;
#elif defined(ESP_PLATFORM)
// TODO: Implement secure boot check for ESP32-S3
#endif
return false;
}
bool otp_is_secure_boot_locked() {
uint8_t bootkey_idx = 0xFF;
if (otp_is_secure_boot_enabled(&bootkey_idx) == false) {
return false;
}
#ifdef PICO_RP2350
const uint8_t *boot_flags1 = otp_buffer_raw(OTP_DATA_BOOT_FLAGS1_ROW);
if ((boot_flags1[1] & ((OTP_DATA_BOOT_FLAGS1_KEY_INVALID_BITS >> OTP_DATA_BOOT_FLAGS1_KEY_INVALID_LSB) & (~(1 << bootkey_idx)))) != ((OTP_DATA_BOOT_FLAGS1_KEY_INVALID_BITS >> OTP_DATA_BOOT_FLAGS1_KEY_INVALID_LSB) & (~(1 << bootkey_idx)))) {
return false;
}
const uint8_t *crit1 = otp_buffer_raw(OTP_DATA_CRIT1_ROW);
if ((crit1[0] & (1 << OTP_DATA_CRIT1_DEBUG_DISABLE_LSB)) == 0
|| (crit1[0] & (1 << OTP_DATA_CRIT1_GLITCH_DETECTOR_ENABLE_LSB)) == 0
|| ((crit1[0] & (3 << OTP_DATA_CRIT1_GLITCH_DETECTOR_SENS_LSB)) != (3 << OTP_DATA_CRIT1_GLITCH_DETECTOR_SENS_LSB))) {
return false;
}
return bootkey_idx != 0xFF;
#elif defined(ESP_PLATFORM)
// TODO: Implement secure boot lock check for ESP32-S3
#endif
return false;
}
int otp_enable_secure_boot(uint8_t bootkey, bool secure_lock) {
int ret = 0;
#ifdef PICO_RP2350
uint8_t BOOTKEY[] = "\xe1\xd1\x6b\xa7\x64\xab\xd7\x12\xd4\xef\x6e\x3e\xdd\x74\x4e\xd5\x63\x8c\x26\xb\x77\x1c\xf9\x81\x51\x11\xb\xaf\xac\x9b\xc8\x71";
alignas(2) uint8_t BOOTKEY[] = "\xe1\xd1\x6b\xa7\x64\xab\xd7\x12\xd4\xef\x6e\x3e\xdd\x74\x4e\xd5\x63\x8c\x26\xb\x77\x1c\xf9\x81\x51\x11\xb\xaf\xac\x9b\xc8\x71";
if (is_empty_otp_buffer(OTP_DATA_BOOTKEY0_0_ROW + 0x10*bootkey, 32)) {
PICOKEY_CHECK(otp_write_data(OTP_DATA_BOOTKEY0_0_ROW + 0x10*bootkey, BOOTKEY, sizeof(BOOTKEY)));
}
uint8_t *boot_flags1 = otp_buffer_raw(OTP_DATA_BOOT_FLAGS1_ROW);
uint8_t flagsb1[] = { boot_flags1[0] | (1 << (bootkey + OTP_DATA_BOOT_FLAGS1_KEY_VALID_LSB)), boot_flags1[1], boot_flags1[2], 0x00 };
const uint8_t *boot_flags1 = otp_buffer_raw(OTP_DATA_BOOT_FLAGS1_ROW);
alignas(4) uint8_t flagsb1[] = { boot_flags1[0] | (1 << (bootkey + OTP_DATA_BOOT_FLAGS1_KEY_VALID_LSB)), boot_flags1[1], boot_flags1[2], 0x00 };
if (secure_lock) {
flagsb1[1] |= ((OTP_DATA_BOOT_FLAGS1_KEY_INVALID_BITS >> OTP_DATA_BOOT_FLAGS1_KEY_INVALID_LSB) & (~(1 << bootkey)));
}
@ -142,8 +197,8 @@ int otp_enable_secure_boot(uint8_t bootkey, bool secure_lock) {
PICOKEY_CHECK(otp_write_data_raw(OTP_DATA_BOOT_FLAGS1_R1_ROW, flagsb1, sizeof(flagsb1)));
PICOKEY_CHECK(otp_write_data_raw(OTP_DATA_BOOT_FLAGS1_R2_ROW, flagsb1, sizeof(flagsb1)));
uint8_t *crit1 = otp_buffer_raw(OTP_DATA_CRIT1_ROW);
uint8_t flagsc1[] = { crit1[0] | (1 << OTP_DATA_CRIT1_SECURE_BOOT_ENABLE_LSB), crit1[1], crit1[2], 0x00 };
const uint8_t *crit1 = otp_buffer_raw(OTP_DATA_CRIT1_ROW);
alignas(4) uint8_t flagsc1[] = { crit1[0] | (1 << OTP_DATA_CRIT1_SECURE_BOOT_ENABLE_LSB), crit1[1], crit1[2], 0x00 };
if (secure_lock) {
flagsc1[0] |= (1 << OTP_DATA_CRIT1_DEBUG_DISABLE_LSB);
flagsc1[0] |= (1 << OTP_DATA_CRIT1_GLITCH_DETECTOR_ENABLE_LSB);
@ -159,17 +214,20 @@ int otp_enable_secure_boot(uint8_t bootkey, bool secure_lock) {
PICOKEY_CHECK(otp_write_data_raw(OTP_DATA_CRIT1_R7_ROW, flagsc1, sizeof(flagsc1)));
if (secure_lock) {
uint8_t *page1 = otp_buffer_raw(OTP_DATA_PAGE1_LOCK1_ROW);
const uint8_t *page1 = otp_buffer_raw(OTP_DATA_PAGE1_LOCK1_ROW);
uint8_t page1v = page1[0] | (OTP_DATA_PAGE1_LOCK1_LOCK_BL_VALUE_READ_ONLY << OTP_DATA_PAGE1_LOCK1_LOCK_BL_LSB);
uint8_t flagsp1[] = { page1v, page1v, page1v, 0x00 };
alignas(4) uint8_t flagsp1[] = { page1v, page1v, page1v, 0x00 };
PICOKEY_CHECK(otp_write_data_raw(OTP_DATA_PAGE1_LOCK1_ROW, flagsp1, sizeof(flagsp1)));
uint8_t *page2 = otp_buffer_raw(OTP_DATA_PAGE2_LOCK1_ROW);
const uint8_t *page2 = otp_buffer_raw(OTP_DATA_PAGE2_LOCK1_ROW);
uint8_t page2v = page2[0] | (OTP_DATA_PAGE2_LOCK1_LOCK_BL_VALUE_READ_ONLY << OTP_DATA_PAGE2_LOCK1_LOCK_BL_LSB);
uint8_t flagsp2[] = { page2v, page2v, page2v, 0x00 };
alignas(4) uint8_t flagsp2[] = { page2v, page2v, page2v, 0x00 };
PICOKEY_CHECK(otp_write_data_raw(OTP_DATA_PAGE2_LOCK1_ROW, flagsp2, sizeof(flagsp2)));
}
#elif defined(ESP_PLATFORM)
// TODO: Implement secure boot for ESP32-S3
#else
(void)bootkey;
(void)secure_lock;
#endif // PICO_RP2350
goto err;
err:
@ -179,8 +237,64 @@ int otp_enable_secure_boot(uint8_t bootkey, bool secure_lock) {
return PICOKEY_OK;
}
#ifdef PICO_RP2350
static void otp_invalidate_key(uint16_t row, uint16_t len) {
if (!is_empty_otp_buffer(row, len)) {
uint8_t *inval = (uint8_t *)calloc(len * 2, sizeof(uint8_t));
if (inval) {
memset(inval, 0xFF, len * 2);
otp_write_data_raw(row, inval, len * 2);
free(inval);
}
}
}
static otp_ret_t otp_chaff(uint16_t row, uint16_t len) {
const uint8_t *raw = otp_buffer_raw(row);
uint8_t *chaff = (uint8_t *)calloc(len * 2, sizeof(uint8_t));
if (chaff) {
memcpy(chaff, raw, len * 2);
for (int i = 0; i < len * 2; i++) {
chaff[i] ^= 0xFF;
}
otp_ret_t ret = otp_write_data_raw(row + 32, chaff, len * 2);
free(chaff);
return ret;
}
return BOOTROM_ERROR_INVALID_STATE;
}
static otp_ret_t otp_migrate_key(uint16_t new_row, uint16_t old_row, uint16_t len) {
if (is_empty_otp_buffer(new_row, len) && !is_empty_otp_buffer(old_row, len)) {
const uint8_t *key = otp_buffer(old_row);
uint8_t *new_key = (uint8_t *)calloc(len, sizeof(uint8_t));
if (new_key) {
memcpy(new_key, key, len);
otp_ret_t ret = otp_write_data(new_row, new_key, len);
if (ret == BOOTROM_OK) {
otp_chaff(new_row, len);
otp_invalidate_key(old_row, 32);
}
free(new_key);
return ret;
}
}
return BOOTROM_ERROR_INVALID_STATE;
}
void otp_migrate_chaff() {
otp_migrate_key(OTP_MKEK_ROW, OTP_OLD_MKEK_ROW, 32);
otp_migrate_key(OTP_DEVK_ROW, OTP_OLD_DEVK_ROW, 32);
otp_lock_page(OTP_MKEK_ROW >> 6);
}
#endif
void init_otp_files() {
#ifdef PICO_RP2350
otp_migrate_chaff();
#endif
#if defined(PICO_RP2350) || defined(ESP_PLATFORM)
otp_ret_t ret = 0;
uint16_t write_otp[2] = {0xFFFF, 0xFFFF};
@ -191,6 +305,9 @@ void init_otp_files() {
if (ret != 0) {
printf("Error writing OTP key 1 [%d]\n", ret);
}
#ifdef PICO_RP2350
otp_chaff(OTP_KEY_1, 32);
#endif
write_otp[0] = OTP_KEY_1;
}
OTP_READ(OTP_KEY_1, otp_key_1);
@ -210,6 +327,10 @@ void init_otp_files() {
if (ret != 0) {
printf("Error writing OTP key 2 [%d]\n", ret);
}
mbedtls_platform_zeroize(pkey, sizeof(pkey));
#ifdef PICO_RP2350
otp_chaff(OTP_KEY_2, 32);
#endif
write_otp[1] = OTP_KEY_2;
}
OTP_READ(OTP_KEY_2, otp_key_2);
@ -230,5 +351,11 @@ void init_otp_files() {
#endif
}
}
#endif // PICO_RP2350 || ESP_PLATFORM
#elif defined(ENABLE_EMULATION)
static uint8_t _otp1[32] = {0}, _otp2[32] = {0};
memset(_otp1, 0xAC, sizeof(_otp1));
memset(_otp2, 0xBE, sizeof(_otp2));
otp_key_1 = _otp1;
otp_key_2 = _otp2;
#endif
}

View file

@ -3,16 +3,16 @@
* Copyright (c) 2022 Pol Henarejos.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, version 3.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
* Affero General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
@ -21,17 +21,19 @@
#ifdef PICO_RP2350
#define OTP_MKEK_ROW 0xEF0
#define OTP_DEVK_ROW 0xED0
#define OTP_OLD_MKEK_ROW 0xEF0
#define OTP_OLD_DEVK_ROW 0xED0
#define OTP_MKEK_ROW 0xE90
#define OTP_DEVK_ROW 0xE80
#define OTP_KEY_1 OTP_MKEK_ROW
#define OTP_KEY_2 OTP_DEVK_ROW
extern uint8_t* otp_buffer(uint16_t row);
extern uint8_t* otp_buffer_raw(uint16_t row);
extern const uint8_t* otp_buffer(uint16_t row);
extern const uint8_t* otp_buffer_raw(uint16_t row);
extern bool is_empty_otp_buffer(uint16_t row, uint16_t len);
extern int otp_write_data(uint16_t row, uint8_t *data, uint16_t len);
extern int otp_write_data_raw(uint16_t row, uint8_t *data, uint16_t len);
extern int otp_write_data(uint16_t row, const uint8_t *data, uint16_t len);
extern int otp_write_data_raw(uint16_t row, const uint8_t *data, uint16_t len);
#elif defined(ESP_PLATFORM)
@ -48,4 +50,7 @@ extern void init_otp_files();
extern const uint8_t *otp_key_1;
extern const uint8_t *otp_key_2;
extern bool otp_is_secure_boot_enabled(uint8_t *bootkey);
extern bool otp_is_secure_boot_locked();
#endif // _OTP_H_

View file

@ -3,20 +3,21 @@
* Copyright (c) 2022 Pol Henarejos.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, version 3.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
* Affero General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
#include "pico_keys.h"
#include "file.h"
#include "otp.h"
#ifndef ENABLE_EMULATION
@ -29,6 +30,7 @@ int phy_serialize_data(const phy_data_t *phy, uint8_t *data, uint16_t *len) {
uint8_t *p = data;
if (phy->vidpid_present) {
*p++ = PHY_VIDPID;
*p++ = 4;
*p++ = phy->vidpid[1];
*p++ = phy->vidpid[0];
*p++ = phy->vidpid[3];
@ -36,62 +38,154 @@ int phy_serialize_data(const phy_data_t *phy, uint8_t *data, uint16_t *len) {
}
if (phy->led_gpio_present) {
*p++ = PHY_LED_GPIO;
*p++ = 1;
*p++ = phy->led_gpio;
}
if (phy->led_brightness_present) {
*p++ = PHY_LED_BTNESS;
*p++ = 1;
*p++ = phy->led_brightness;
}
*p++ = PHY_OPTS;
*p++ = phy->opts >> 8;
*p++ = phy->opts & 0xff;
*len = p - data;
*p++ = 2;
p += put_uint16_t_be(phy->opts, p);
if (phy->up_btn_present) {
*p++ = PHY_UP_BTN;
*p++ = 1;
*p++ = phy->up_btn;
}
if (phy->usb_product_present) {
*p++ = PHY_USB_PRODUCT;
*p++ = (uint8_t)strlen(phy->usb_product) + 1;
strcpy((char *)p, phy->usb_product);
p += strlen(phy->usb_product);
*p++ = '\0';
}
if (phy->enabled_curves_present) {
*p++ = PHY_ENABLED_CURVES;
*p++ = 4;
p += put_uint32_t_be(phy->enabled_curves, p);
}
if (phy->enabled_usb_itf_present) {
*p++ = PHY_ENABLED_USB_ITF;
*p++ = 1;
*p++ = phy->enabled_usb_itf;
}
if (phy->led_driver_present) {
*p++ = PHY_LED_DRIVER;
*p++ = 1;
*p++ = phy->led_driver;
}
*len = (uint8_t)(p - data);
return PICOKEY_OK;
}
#include <stdio.h>
int phy_unserialize_data(const uint8_t *data, uint16_t len, phy_data_t *phy) {
if (!phy || !data || !len) {
return PICOKEY_ERR_NULL_PARAM;
}
memset(phy, 0, sizeof(phy_data_t));
const uint8_t *p = data;
uint8_t tag, tlen;
while (p < data + len) {
switch (*p++) {
tag = *p++;
tlen = *p++;
switch (tag) {
case PHY_VIDPID:
memcpy(phy->vidpid, p, 4);
phy->vidpid[1] = *p++;
phy->vidpid[0] = *p++;
phy->vidpid[3] = *p++;
phy->vidpid[2] = *p++;
phy->vidpid_present = true;
if (tlen == 4) {
memcpy(phy->vidpid, p, 4);
phy->vidpid[1] = *p++;
phy->vidpid[0] = *p++;
phy->vidpid[3] = *p++;
phy->vidpid[2] = *p++;
phy->vidpid_present = true;
}
break;
case PHY_LED_GPIO:
phy->led_gpio = *p++;
phy->led_gpio_present = true;
if (tlen == 1) {
phy->led_gpio = *p++;
phy->led_gpio_present = true;
}
break;
case PHY_LED_BTNESS:
phy->led_brightness = *p++;
phy->led_brightness_present = true;
if (tlen == 1) {
phy->led_brightness = *p++;
phy->led_brightness_present = true;
}
break;
case PHY_OPTS:
phy->opts = (*p << 8) | *(p + 1);
p += 2;
if (tlen == 2) {
phy->opts = get_uint16_t_be(p);
p += 2;
}
break;
case PHY_UP_BTN:
if (tlen == 1) {
phy->up_btn = *p++;
phy->up_btn_present = true;
}
break;
case PHY_USB_PRODUCT:
if (tlen > 0 && tlen <= sizeof(phy->usb_product)) {
memset(phy->usb_product, 0, sizeof(phy->usb_product));
strlcpy(phy->usb_product, (const char *)p, sizeof(phy->usb_product));
phy->usb_product_present = true;
p += strlen(phy->usb_product) + 1;
}
break;
case PHY_ENABLED_CURVES:
if (tlen == 4) {
phy->enabled_curves = get_uint32_t_be(p);
p += 4;
phy->enabled_curves_present = true;
}
break;
case PHY_ENABLED_USB_ITF:
if (tlen == 1) {
phy->enabled_usb_itf = *p++;
phy->enabled_usb_itf_present = true;
}
break;
case PHY_LED_DRIVER:
if (tlen == 1) {
phy->led_driver = *p++;
phy->led_driver_present = true;
}
break;
default:
p += tlen;
break;
}
}
if (!phy_data.enabled_usb_itf_present) {
phy_data.enabled_usb_itf = PHY_USB_ITF_CCID | PHY_USB_ITF_WCID | PHY_USB_ITF_HID | PHY_USB_ITF_KB;
phy_data.enabled_usb_itf_present = true;
}
return PICOKEY_OK;
}
int phy_init() {
memset(&phy_data, 0, sizeof(phy_data_t));
if (file_has_data(ef_phy)) {
const uint8_t *data = file_get_data(ef_phy);
int ret = phy_unserialize_data(data, file_get_size(ef_phy), &phy_data);
if (ret != PICOKEY_OK) {
return ret;
}
}
return phy_load();
}
int phy_save() {
uint8_t tmp[PHY_MAX_SIZE] = {0};
uint16_t tmp_len = 0;
int ret = phy_serialize_data(&phy_data, tmp, &tmp_len);
if (ret != PICOKEY_OK) {
return ret;
}
file_put_data(ef_phy, tmp, tmp_len);
low_flash_available();
return PICOKEY_OK;
}
int phy_load() {
if (file_has_data(ef_phy)) {
return phy_unserialize_data(file_get_data(ef_phy), file_get_size(ef_phy), &phy_data);
}
return PICOKEY_OK;
}
#endif

View file

@ -3,16 +3,16 @@
* Copyright (c) 2022 Pol Henarejos.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, version 3.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
* Affero General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
#ifndef _PHY_H_
@ -24,9 +24,45 @@
#define PHY_LED_GPIO 0x4
#define PHY_LED_BTNESS 0x5
#define PHY_OPTS 0x6
#define PHY_UP_BTN 0x8
#define PHY_USB_PRODUCT 0x9
#define PHY_ENABLED_CURVES 0xA
#define PHY_ENABLED_USB_ITF 0xB
#define PHY_LED_DRIVER 0xC
#define PHY_OPT_WCID 0x1
#define PHY_OPT_DIMM 0x2
#define PHY_OPT_DISABLE_POWER_RESET 0x4
#define PHY_OPT_LED_STEADY 0x8
#define PHY_CURVE_SECP256R1 0x1
#define PHY_CURVE_SECP384R1 0x2
#define PHY_CURVE_SECP521R1 0x4
#define PHY_CURVE_SECP256K1 0x8
#define PHY_CURVE_BP256R1 0x10
#define PHY_CURVE_BP384R1 0x20
#define PHY_CURVE_BP512R1 0x40
#define PHY_CURVE_ED25519 0x80
#define PHY_CURVE_ED448 0x100
#define PHY_CURVE_CURVE25519 0x200
#define PHY_CURVE_CURVE448 0x400
#define PHY_USB_ITF_CCID 0x1
#define PHY_USB_ITF_WCID 0x2
#define PHY_USB_ITF_HID 0x4
#define PHY_USB_ITF_KB 0x8
#define PHY_LED_DRIVER_PICO 0x1
#define PHY_LED_DRIVER_PIMORONI 0x2
#define PHY_LED_DRIVER_WS2812 0x3
#ifdef CYW43_WL_GPIO_LED_PIN
#define PHY_LED_DRIVER_CYW43 0x4
#endif
#ifdef ESP_PLATFORM
#define PHY_LED_DRIVER_NEOPIXEL 0x5
#endif
#define PHY_LED_DRIVER_NONE 0xFF
#include <stdint.h>
#include <stdbool.h>
@ -39,22 +75,38 @@ typedef struct phy_data {
};
uint8_t vidpid[4];
};
uint32_t enabled_curves;
char usb_product[32];
uint16_t opts;
uint8_t led_gpio;
uint8_t led_brightness;
uint16_t opts;
uint8_t up_btn;
uint8_t enabled_usb_itf;
uint8_t led_driver;
bool vidpid_present;
bool led_gpio_present;
bool led_brightness_present;
bool up_btn_present;
bool usb_product_present;
bool enabled_curves_present;
bool enabled_usb_itf_present;
bool led_driver_present;
} phy_data_t;
#define PHY_OPT_MASK (PHY_OPT_SECURE_LOCK | PHY_OPT_SECURE_BOOT | PHY_OPT_DIMM | PHY_OPT_WCID)
#define PHY_MAX_SIZE 8
#define PHY_MAX_SIZE ((2+4)+(2+4)+(2+32)+(2+2)+(2+1)+(2+1)+(2+1)+(2+1)+(2+1))
#ifndef ENABLE_EMULATION
extern int phy_serialize_data(const phy_data_t *phy, uint8_t *data, uint16_t *len);
extern int phy_unserialize_data(const uint8_t *data, uint16_t len, phy_data_t *phy);
extern int phy_init();
extern int phy_save();
extern int phy_load();
extern phy_data_t phy_data;
#endif

View file

@ -1,5 +1,5 @@
## IDF Component Manager Manifest File
dependencies:
espressif/esp_tinyusb: "^1.4.4"
espressif/esp_tinyusb: "^1.7.6"
#espressif/tinyusb: "^0.15.0"
zorxx/neopixel: "^1.0.4"

View file

@ -1,19 +1,19 @@
/*
* This file is part of the Pico Keys SDK distribution (https://github.com/polhenarejos/pico-keys-sdk).
* Copyright (c) 2022 Pol Henarejos.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, version 3.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/*
* This file is part of the Pico Keys SDK distribution (https://github.com/polhenarejos/pico-keys-sdk).
* Copyright (c) 2022 Pol Henarejos.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, version 3.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
#include <stdio.h>
#include <stdlib.h>
@ -21,13 +21,13 @@
#ifdef PICO_PLATFORM
#include "bsp/board.h"
#elif defined(ESP_PLATFORM)
#include "driver/gpio.h"
#include "esp_compat.h"
#elif defined(ENABLE_EMULATION)
#include "emulation.h"
#endif
extern void led_driver_init();
extern void led_driver_color(uint8_t, uint32_t, float);
led_driver_t *led_driver = NULL;
static uint32_t led_mode = MODE_NOT_MOUNTED;
@ -35,10 +35,15 @@ void led_set_mode(uint32_t mode) {
led_mode = mode;
}
uint32_t led_get_mode() {
return led_mode;
}
void led_blinking_task() {
#ifndef ENABLE_EMULATION
#if defined(PICO_PLATFORM) || defined(ESP_PLATFORM)
static uint32_t start_ms = 0;
static uint32_t stop_ms = 0;
static uint32_t last_led_update_ms = 0;
static uint8_t led_state = false;
uint8_t state = led_state;
#ifdef PICO_DEFAULT_LED_PIN_INVERTED
@ -49,7 +54,6 @@ void led_blinking_task() {
uint32_t led_off = (led_mode & LED_OFF_MASK) >> LED_OFF_SHIFT;
uint32_t led_on = (led_mode & LED_ON_MASK) >> LED_ON_SHIFT;
// how far in the current state from 0 - 1
float progress = 0;
if (stop_ms > start_ms) {
@ -57,15 +61,17 @@ void led_blinking_task() {
}
if (!state) {
// fading down so 1 -> 0
progress = 1. - progress;
}
if (phy_data.opts & PHY_OPT_LED_STEADY) {
progress = 1;
}
// maybe quick return if progress didn't changed much ?
// current one from 0 - 1
led_driver_color(led_color, led_brightness, progress);
// limit the frequency of LED status updates
if (board_millis() - last_led_update_ms > 2) {
led_driver->set_color(led_color, led_brightness, progress);
last_led_update_ms = board_millis();
}
if (board_millis() >= stop_ms){
start_ms = stop_ms;
@ -76,14 +82,95 @@ void led_blinking_task() {
}
void led_off_all() {
#ifndef ENABLE_EMULATION
led_driver_color(LED_COLOR_OFF, 0, 0);
#if defined(PICO_PLATFORM) || defined(ESP_PLATFORM)
led_driver->set_color(LED_COLOR_OFF, 0, 0);
#endif
}
extern led_driver_t led_driver_pico;
extern led_driver_t led_driver_cyw43;
extern led_driver_t led_driver_ws2812;
extern led_driver_t led_driver_neopixel;
extern led_driver_t led_driver_pimoroni;
void led_driver_init_dummy() {
// Do nothing
}
void led_driver_color_dummy(uint8_t color, uint32_t led_brightness, float progress) {
(void)color;
(void)led_brightness;
(void)progress;
// Do nothing
}
led_driver_t led_driver_dummy = {
.init = led_driver_init_dummy,
.set_color = led_driver_color_dummy,
};
void led_init() {
#ifndef ENABLE_EMULATION
led_driver_init();
led_driver = &led_driver_dummy;
#if defined(PICO_PLATFORM) || defined(ESP_PLATFORM)
// Guess default driver
#if defined(PIMORONI_TINY2040) || defined(PIMORONI_TINY2350)
led_driver = &led_driver_pimoroni;
phy_data.led_driver = phy_data.led_driver_present ? phy_data.led_driver : PHY_LED_DRIVER_PIMORONI;
#elif defined(CYW43_WL_GPIO_LED_PIN)
led_driver = &led_driver_cyw43;
phy_data.led_driver = phy_data.led_driver_present ? phy_data.led_driver : PHY_LED_DRIVER_CYW43;
phy_data.led_gpio = phy_data.led_gpio_present ? phy_data.led_gpio : CYW43_WL_GPIO_LED_PIN;
#elif defined(PICO_DEFAULT_WS2812_PIN)
led_driver = &led_driver_ws2812;
phy_data.led_driver = phy_data.led_driver_present ? phy_data.led_driver : PHY_LED_DRIVER_WS2812;
phy_data.led_gpio = phy_data.led_gpio_present ? phy_data.led_gpio : PICO_DEFAULT_WS2812_PIN;
#elif defined(ESP_PLATFORM)
#if defined(CONFIG_IDF_TARGET_ESP32S3)
#define NEOPIXEL_PIN GPIO_NUM_48
#elif defined(CONFIG_IDF_TARGET_ESP32S2)
#define NEOPIXEL_PIN GPIO_NUM_15
#elif defined(CONFIG_IDF_TARGET_ESP32C6)
#define NEOPIXEL_PIN GPIO_NUM_8
#else
#define NEOPIXEL_PIN GPIO_NUM_27
#endif
led_driver = &led_driver_neopixel;
phy_data.led_driver = phy_data.led_driver_present ? phy_data.led_driver : PHY_LED_DRIVER_NEOPIXEL;
phy_data.led_gpio = phy_data.led_gpio_present ? phy_data.led_gpio : NEOPIXEL_PIN;
#elif defined(PICO_DEFAULT_LED_PIN)
led_driver = &led_driver_pico;
phy_data.led_driver = phy_data.led_driver_present ? phy_data.led_driver : PHY_LED_DRIVER_PICO;
phy_data.led_gpio = phy_data.led_gpio_present ? phy_data.led_gpio : PICO_DEFAULT_LED_PIN;
#endif
if (phy_data.led_driver_present) {
switch (phy_data.led_driver) {
#ifdef ESP_PLATFORM
case PHY_LED_DRIVER_NEOPIXEL:
led_driver = &led_driver_neopixel;
break;
#else
case PHY_LED_DRIVER_PICO:
led_driver = &led_driver_pico;
break;
#ifdef CYW43_WL_GPIO_LED_PIN
case PHY_LED_DRIVER_CYW43:
led_driver = &led_driver_cyw43;
break;
#endif
case PHY_LED_DRIVER_WS2812:
led_driver = &led_driver_ws2812;
break;
case PHY_LED_DRIVER_PIMORONI:
led_driver = &led_driver_pimoroni;
break;
#endif
default:
break;
}
}
phy_data.led_driver_present = true;
phy_data.led_gpio_present = true;
led_driver->init();
led_set_mode(MODE_NOT_MOUNTED);
#endif
}

View file

@ -3,16 +3,16 @@
* Copyright (c) 2022 Pol Henarejos.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, version 3.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
* Affero General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
#ifndef _LED_H_
@ -62,8 +62,16 @@ enum {
};
extern void led_set_mode(uint32_t mode);
extern uint32_t led_get_mode();
extern void led_blinking_task();
extern void led_off_all();
extern void led_init();
typedef struct {
void (*init)();
void (*set_color)(uint8_t color, uint32_t led_brightness, float progress);
} led_driver_t;
extern led_driver_t *led_driver;
#endif // _LED_H_

View file

@ -3,16 +3,16 @@
* Copyright (c) 2022 Pol Henarejos.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, version 3.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
* Affero General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
#include "pico_keys.h"
@ -21,13 +21,22 @@
#include "pico/cyw43_arch.h"
void led_driver_init() {
void led_driver_init_cyw43() {
cyw43_arch_init();
}
void led_driver_color(uint8_t color, uint32_t led_brightness, float progress) {
void led_driver_color_cyw43(uint8_t color, uint32_t led_brightness, float progress) {
(void)led_brightness;
cyw43_arch_gpio_put(CYW43_WL_GPIO_LED_PIN, progress >= 0.5);
uint8_t gpio = CYW43_WL_GPIO_LED_PIN;
if (phy_data.led_gpio_present) {
gpio = phy_data.led_gpio;
}
cyw43_arch_gpio_put(gpio, progress >= 0.5);
}
led_driver_t led_driver_cyw43 = {
.init = led_driver_init_cyw43,
.set_color = led_driver_color_cyw43,
};
#endif

View file

@ -3,16 +3,16 @@
* Copyright (c) 2022 Pol Henarejos.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, version 3.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
* Affero General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
#include "pico_keys.h"
@ -35,15 +35,25 @@ tNeopixel pixel[] = {
{ 0, NP_RGB(255, 255, 255) }, /* white */
};
void led_driver_init() {
uint8_t gpio = GPIO_NUM_48;
#if defined(CONFIG_IDF_TARGET_ESP32S3)
#define NEOPIXEL_PIN GPIO_NUM_48
#elif defined(CONFIG_IDF_TARGET_ESP32S2)
#define NEOPIXEL_PIN GPIO_NUM_15
#elif defined(CONFIG_IDF_TARGET_ESP32C6)
#define NEOPIXEL_PIN GPIO_NUM_8
#else
#define NEOPIXEL_PIN GPIO_NUM_27
#endif
void led_driver_init_neopixel() {
uint8_t gpio = NEOPIXEL_PIN;
if (phy_data.led_gpio_present) {
gpio = phy_data.led_gpio;
}
neopixel = neopixel_Init(1, gpio);
}
void led_driver_color(uint8_t color, uint32_t led_brightness, float progress) {
void led_driver_color_neopixel(uint8_t color, uint32_t led_brightness, float progress) {
static tNeopixel spx = {.index = 0, .rgb = 0};
if (!(phy_data.opts & PHY_OPT_DIMM)) {
progress = progress >= 0.5 ? 1 : 0;
@ -62,4 +72,9 @@ void led_driver_color(uint8_t color, uint32_t led_brightness, float progress) {
neopixel_SetPixel(neopixel, &spx, 1);
}
led_driver_t led_driver_neopixel = {
.init = led_driver_init_neopixel,
.set_color = led_driver_color_neopixel,
};
#endif

View file

@ -3,30 +3,43 @@
* Copyright (c) 2022 Pol Henarejos.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, version 3.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
* Affero General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
#include "pico_keys.h"
#if defined(PICO_DEFAULT_LED_PIN) && !defined(PICO_DEFAULT_WS2812_PIN)
#ifdef PICO_DEFAULT_LED_PIN
static uint8_t gpio = PICO_DEFAULT_LED_PIN;
#else
static uint8_t gpio = 0;
#endif
void led_driver_init() {
gpio_init(PICO_DEFAULT_LED_PIN);
gpio_set_dir(PICO_DEFAULT_LED_PIN, GPIO_OUT);
#ifdef PICO_PLATFORM
void led_driver_init_pico() {
if (phy_data.led_gpio_present) {
gpio = phy_data.led_gpio;
}
gpio_init(gpio);
gpio_set_dir(gpio, GPIO_OUT);
}
void led_driver_color(uint8_t color, uint32_t led_brightness, float progress) {
void led_driver_color_pico(uint8_t color, uint32_t led_brightness, float progress) {
(void)led_brightness;
gpio_put(PICO_DEFAULT_LED_PIN, progress >= 0.5);
gpio_put(gpio, progress >= 0.5);
}
led_driver_t led_driver_pico = {
.init = led_driver_init_pico,
.set_color = led_driver_color_pico,
};
#endif

View file

@ -3,30 +3,25 @@
* Copyright (c) 2022 Pol Henarejos.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, version 3.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
* Affero General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
#include "pico_keys.h"
#if defined(PIMORONI_TINY2040) || defined(PIMORONI_TINY2350)
#ifdef PIMORONI_TINY2040
#define LED_R_PIN TINY2040_LED_R_PIN
#define LED_G_PIN TINY2040_LED_G_PIN
#define LED_B_PIN TINY2040_LED_B_PIN
#elif defined(PIMORONI_TINY2350)
#define LED_R_PIN TINY2350_LED_R_PIN
#define LED_G_PIN TINY2350_LED_G_PIN
#define LED_B_PIN TINY2350_LED_B_PIN
#ifdef PICO_PLATFORM
#ifdef PICO_DEFAULT_LED_PIN
static uint8_t gpio = PICO_DEFAULT_LED_PIN;
#else
static uint8_t gpio = 0;
#endif
uint8_t pixel[][3] = {
@ -40,22 +35,30 @@ uint8_t pixel[][3] = {
{0, 0, 0} // 7: white
};
void led_driver_init() {
gpio_init(LED_R_PIN);
gpio_set_dir(LED_R_PIN, GPIO_OUT);
gpio_init(LED_G_PIN);
gpio_set_dir(LED_G_PIN, GPIO_OUT);
gpio_init(LED_B_PIN);
gpio_set_dir(LED_B_PIN, GPIO_OUT);
void led_driver_init_pimoroni() {
if (phy_data.led_gpio_present) {
gpio = phy_data.led_gpio;
}
gpio_init(gpio-1);
gpio_set_dir(gpio-1, GPIO_OUT);
gpio_init(gpio);
gpio_set_dir(gpio, GPIO_OUT);
gpio_init(gpio+1);
gpio_set_dir(gpio+1, GPIO_OUT);
}
void led_driver_color(uint8_t color, uint32_t led_brightness, float progress) {
void led_driver_color_pimoroni(uint8_t color, uint32_t led_brightness, float progress) {
if (progress < 0.5) {
color = LED_COLOR_OFF;
}
gpio_put(LED_R_PIN, pixel[color][0]);
gpio_put(LED_G_PIN, pixel[color][1]);
gpio_put(LED_B_PIN, pixel[color][2]);
gpio_put(gpio-1, pixel[color][0]);
gpio_put(gpio, pixel[color][1]);
gpio_put(gpio+1, pixel[color][2]);
}
led_driver_t led_driver_pimoroni = {
.init = led_driver_init_pimoroni,
.set_color = led_driver_color_pimoroni,
};
#endif

View file

@ -3,41 +3,49 @@
* Copyright (c) 2022 Pol Henarejos.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, version 3.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
* Affero General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
#include "pico_keys.h"
#ifdef PICO_DEFAULT_WS2812_PIN
#ifdef PICO_PLATFORM
#include "hardware/pio.h"
#include "hardware/clocks.h"
#define ws2812_wrap_target 0
#define ws2812_wrap 3
#define ws2812_T1 2
#define ws2812_T2 5
#define ws2812_T3 3
#define ws2812_pio_version 0
#define ws2812_T1 3
#define ws2812_T2 3
#define ws2812_T3 4
static const uint16_t ws2812_program_instructions[] = {
// .wrap_target
0x6221, // 0: out x, 1 side 0 [2]
0x1123, // 1: jmp !x, 3 side 1 [1]
0x1400, // 2: jmp 0 side 1 [4]
0xa442, // 3: nop side 0 [4]
// .wrap_target
0x6321, // 0: out x, 1 side 0 [3]
0x1223, // 1: jmp !x, 3 side 1 [2]
0x1200, // 2: jmp 0 side 1 [2]
0xa242, // 3: nop side 0 [2]
// .wrap
};
static const struct pio_program ws2812_program = {
.instructions = ws2812_program_instructions,
.length = 4,
.origin = -1,
.pio_version = ws2812_pio_version,
#if PICO_PIO_VERSION > 0
.used_gpio_ranges = 0x0
#endif
};
static inline pio_sm_config ws2812_program_get_default_config(uint offset) {
@ -46,6 +54,7 @@ static inline pio_sm_config ws2812_program_get_default_config(uint offset) {
sm_config_set_sideset(&c, 1, false, false);
return c;
}
static inline void ws2812_program_init(PIO pio, uint sm, uint offset, uint pin, float freq, bool rgbw) {
pio_gpio_init(pio, pin);
pio_sm_set_consecutive_pindirs(pio, sm, pin, 1, true);
@ -60,42 +69,70 @@ static inline void ws2812_program_init(PIO pio, uint sm, uint offset, uint pin,
pio_sm_set_enabled(pio, sm, true);
}
void led_driver_init() {
void led_driver_init_ws2812() {
PIO pio = pio0;
int sm = 0;
uint offset = pio_add_program(pio, &ws2812_program);
ws2812_program_init(pio, sm, offset, PICO_DEFAULT_WS2812_PIN, 800000, true);
uint8_t gpio = 0;
#ifdef PICO_DEFAULT_WS2812_PIN
gpio = PICO_DEFAULT_WS2812_PIN;
#endif
if (phy_data.led_gpio_present) {
gpio = phy_data.led_gpio;
}
ws2812_program_init(pio, sm, offset, gpio, 800000, false);
}
uint32_t pixel[] = {
0x00000000, // 0: off
0x00ff0000, // 1: red
0xff000000, // 2: green
0x0000ff00, // 3: blue
0xffff0000, // 4: yellow
0x00ffff00, // 5: magenta
0xff00ff00, // 6: cyan
0xffffff00 // 7: white
struct urgb_color {
uint8_t r;
uint8_t g;
uint8_t b;
};
void led_driver_color(uint8_t color, uint32_t led_brightness, float progress) {
static struct urgb_color urgb_color_table[] = {
{0x00, 0x00, 0x00}, // 0: off LED_COLOR_OFF
{0xff, 0x00, 0x00}, // 1: red LED_COLOR_RED
{0x00, 0xff, 0x00}, // 2: green LED_COLOR_GREEN
{0x00, 0x00, 0xff}, // 3: blue LED_COLOR_BLUE
{0xff, 0xff, 0x00}, // 4: yellow LED_COLOR_YELLOW
{0xff, 0x00, 0xff}, // 5: magenta LED_COLOR_MAGENTA
{0x00, 0xff, 0xff}, // 6: cyan LED_COLOR_CYAN
{0xff, 0xff, 0xff} // 7: white LED_COLOR_WHITE
};
static inline uint32_t urgb_u32(uint8_t r, uint8_t g, uint8_t b) {
return ((uint32_t) (r) << 8) | // For GRB data ordering WS2812
((uint32_t) (g) << 16) |
(uint32_t) (b);
#if 0 // TODO: How to adapt WS2812 with different data ordering ?
return ((uint32_t)(r) << 16) | // For RGB data ordering WS2812
((uint32_t)(g) << 8) |
(uint32_t)(b);
#endif
}
static inline void ws2812_put_pixel(uint32_t u32_pixel) {
pio_sm_put_blocking(pio0, 0, u32_pixel << 8u);
}
void led_driver_color_ws2812(uint8_t color, uint32_t led_brightness, float progress) {
if (!(phy_data.opts & PHY_OPT_DIMM)) {
progress = progress >= 0.5 ? 1 : 0;
}
uint32_t led_phy_btness = phy_data.led_brightness_present ? phy_data.led_brightness : MAX_BTNESS;
float brightness = ((float)led_brightness / MAX_BTNESS) * ((float)led_phy_btness / MAX_BTNESS) * progress;
uint32_t pixel_color = pixel[color];
uint8_t r = (pixel_color >> 16) & 0xFF;
uint8_t g = (pixel_color >> 24) & 0xFF;
uint8_t b = (pixel_color >> 8) & 0xFF;
struct urgb_color pixel_color = urgb_color_table[color];
pixel_color.r = (uint8_t)(pixel_color.r * brightness);
pixel_color.g = (uint8_t)(pixel_color.g * brightness);
pixel_color.b = (uint8_t)(pixel_color.b * brightness);
r = (uint8_t)(r * brightness);
g = (uint8_t)(g * brightness);
b = (uint8_t)(b * brightness);
pio_sm_put_blocking(pio0, 0, (g << 24) | (r << 16) | (b << 8));
ws2812_put_pixel(urgb_u32(pixel_color.r, pixel_color.g, pixel_color.b));
}
led_driver_t led_driver_ws2812 = {
.init = led_driver_init_ws2812,
.set_color = led_driver_color_ws2812,
};
#endif

View file

@ -3,33 +3,34 @@
* Copyright (c) 2022 Pol Henarejos.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, version 3.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
* Affero General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
#include <stdio.h>
#include <stdlib.h>
#include "pico_keys.h"
// Pico
#if !defined(ENABLE_EMULATION)
#include "tusb.h"
#endif
#if defined(ENABLE_EMULATION)
#include "emulation.h"
#elif defined(ESP_PLATFORM)
#include "tusb.h"
#include "driver/gpio.h"
#include "rom/gpio.h"
#include "tinyusb.h"
#include "esp_efuse.h"
#define BOOT_PIN GPIO_NUM_0
#else
#elif defined(PICO_PLATFORM)
#include "pico/stdlib.h"
#include "bsp/board.h"
#include "pico/aon_timer.h"
@ -40,21 +41,34 @@
#endif
#include "random.h"
#include "pico_keys.h"
#include "apdu.h"
#include "usb.h"
#include "mbedtls/sha256.h"
extern void do_flash();
extern void low_flash_init();
extern void init_otp_files();
app_t apps[8];
app_t apps[16];
uint8_t num_apps = 0;
app_t *current_app = NULL;
const uint8_t *ccid_atr = NULL;
bool app_exists(const uint8_t *aid, size_t aid_len) {
for (int a = 0; a < num_apps; a++) {
if (aid_len >= apps[a].aid[0] && !memcmp(apps[a].aid + 1, aid, apps[a].aid[0])) {
return true;
}
}
return false;
}
int register_app(int (*select_aid)(app_t *, uint8_t), const uint8_t *aid) {
if (app_exists(aid + 1, aid[0])) {
return 1;
}
if (num_apps < sizeof(apps) / sizeof(app_t)) {
apps[num_apps].select_aid = select_aid;
apps[num_apps].aid = aid;
@ -65,14 +79,14 @@ int register_app(int (*select_aid)(app_t *, uint8_t), const uint8_t *aid) {
}
int select_app(const uint8_t *aid, size_t aid_len) {
if (current_app && current_app->aid && (current_app->aid + 1 == aid || !memcmp(current_app->aid + 1, aid, aid_len))) {
if (current_app && current_app->aid && (current_app->aid + 1 == aid || (aid_len >= current_app->aid[0] && !memcmp(current_app->aid + 1, aid, current_app->aid[0])))) {
current_app->select_aid(current_app, 0);
return PICOKEY_OK;
}
for (int a = 0; a < num_apps; a++) {
if (!memcmp(apps[a].aid + 1, aid, MIN(aid_len, apps[a].aid[0]))) {
if (aid_len >= apps[a].aid[0] && !memcmp(apps[a].aid + 1, aid, apps[a].aid[0])) {
if (current_app) {
if (current_app->aid && !memcmp(current_app->aid + 1, aid, aid_len)) {
if (current_app->aid && aid_len >= current_app->aid[0] && !memcmp(current_app->aid + 1, aid, current_app->aid[0])) {
current_app->select_aid(current_app, 1);
return PICOKEY_OK;
}
@ -99,10 +113,8 @@ bool is_req_button_pending() {
return req_button_pending;
}
uint32_t button_timeout = 15000;
bool cancel_button = false;
#ifdef ENABLE_EMULATION
#ifdef _MSC_VER
#include <windows.h>
struct timezone
@ -132,13 +144,13 @@ int gettimeofday(struct timeval* tp, struct timezone* tzp)
return 0;
}
#endif
#else
#if !defined(ENABLE_EMULATION)
#ifdef ESP_PLATFORM
bool picok_board_button_read() {
int boot_state = gpio_get_level(BOOT_PIN);
return boot_state == 0;
}
#else
#elif defined(PICO_PLATFORM)
bool __no_inline_not_in_flash_func(picok_get_bootsel_button)() {
const uint CS_PIN_INDEX = 1;
@ -173,18 +185,29 @@ bool __no_inline_not_in_flash_func(picok_get_bootsel_button)() {
return button_state;
}
uint32_t picok_board_button_read(void)
{
bool picok_board_button_read(void) {
return picok_get_bootsel_button();
}
#else
bool picok_board_button_read(void) {
return true; // always unpressed
}
#endif
bool button_pressed_state = false;
uint32_t button_pressed_time = 0;
uint8_t button_press = 0;
bool wait_button() {
uint32_t button_timeout = 15000;
if (phy_data.up_btn_present) {
button_timeout = phy_data.up_btn * 1000;
if (button_timeout == 0) {
return false;
}
}
uint32_t start_button = board_millis();
bool timeout = false;
cancel_button = false;
uint32_t led_mode = led_get_mode();
led_set_mode(MODE_BUTTON);
req_button_pending = true;
while (picok_board_button_read() == false && cancel_button == false) {
@ -205,7 +228,7 @@ bool wait_button() {
}
}
}
led_set_mode(MODE_PROCESSING);
led_set_mode(led_mode);
req_button_pending = false;
return timeout || cancel_button;
}
@ -264,6 +287,7 @@ void core0_loop() {
}
char pico_serial_str[2 * PICO_UNIQUE_BOARD_ID_SIZE_BYTES + 1];
uint8_t pico_serial_hash[32];
pico_unique_board_id_t pico_serial;
#ifdef ESP_PLATFORM
#define pico_get_unique_board_id(a) do { uint32_t value; esp_efuse_read_block(EFUSE_BLK1, &value, 0, 32); memcpy((uint8_t *)(a), &value, sizeof(uint32_t)); esp_efuse_read_block(EFUSE_BLK1, &value, 32, 32); memcpy((uint8_t *)(a)+4, &value, sizeof(uint32_t)); } while(0)
@ -272,23 +296,23 @@ extern const uint8_t desc_config[];
TaskHandle_t hcore0 = NULL, hcore1 = NULL;
int app_main() {
#else
#ifdef ENABLE_EMULATION
#ifndef PICO_PLATFORM
#define pico_get_unique_board_id(a) memset(a, 0, sizeof(*(a)))
#endif
int main(void) {
#endif
pico_get_unique_board_id(&pico_serial);
memset(pico_serial_str, 0, sizeof(pico_serial_str));
for (int i = 0; i < sizeof(pico_serial); i++) {
for (size_t i = 0; i < sizeof(pico_serial); i++) {
snprintf(&pico_serial_str[2 * i], 3, "%02X", pico_serial.id[i]);
}
mbedtls_sha256(pico_serial.id, sizeof(pico_serial.id), pico_serial_hash, false);
#ifndef ENABLE_EMULATION
#ifndef ESP_PLATFORM
#ifdef PICO_PLATFORM
board_init();
stdio_init_all();
#endif
led_init();
#else
emul_init("127.0.0.1", 35963);
@ -308,6 +332,8 @@ int main(void) {
phy_init();
#endif
led_init();
usb_init();
#ifndef ENABLE_EMULATION
@ -317,6 +343,16 @@ int main(void) {
gpio_pulldown_dis(BOOT_PIN);
tusb_cfg.string_descriptor[3] = pico_serial_str;
if (phy_data.usb_product_present) {
tusb_cfg.string_descriptor[2] = phy_data.usb_product;
}
static char tmps[4][32];
for (int i = 4; i < tusb_cfg.string_descriptor_count; i++) {
strlcpy(tmps[i-4], tusb_cfg.string_descriptor[2], sizeof(tmps[0]));
strlcat(tmps[i-4], " ", sizeof(tmps[0]));
strlcat(tmps[i-4], tusb_cfg.string_descriptor[i], sizeof(tmps[0]));
tusb_cfg.string_descriptor[i] = tmps[i-4];
}
tusb_cfg.configuration_descriptor = desc_config;
tinyusb_driver_install(&tusb_cfg);
@ -326,7 +362,7 @@ int main(void) {
#endif
#ifdef ESP_PLATFORM
xTaskCreatePinnedToCore(core0_loop, "core0", 4096*5, NULL, CONFIG_TINYUSB_TASK_PRIORITY - 1, &hcore0, 0);
xTaskCreatePinnedToCore(core0_loop, "core0", 4096*ITF_TOTAL*2, NULL, CONFIG_TINYUSB_TASK_PRIORITY - 1, &hcore0, ESP32_CORE0);
#else
core0_loop();
#endif

View file

@ -3,16 +3,16 @@
* Copyright (c) 2022 Pol Henarejos.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, version 3.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
* Affero General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
#ifndef _PICO_KEYS_H_
@ -24,7 +24,6 @@
#include "file.h"
#include "led/led.h"
#if defined(ENABLE_EMULATION) || defined(ESP_PLATFORM)
#include <stdint.h>
#if !defined(MIN)
#if defined(_MSC_VER)
@ -46,7 +45,7 @@
_a > _b ? _a : _b; })
#endif
#endif
#else
#if defined(PICO_PLATFORM)
#include "pico/unique_id.h"
#endif
#include <string.h>
@ -56,7 +55,7 @@
#include <stdbool.h>
#elif defined(ESP_PLATFORM)
#include "esp_compat.h"
#else
#elif defined(PICO_PLATFORM)
#include "pico/util/queue.h"
#endif
@ -64,15 +63,89 @@ extern bool wait_button();
extern void low_flash_init_core1();
static inline uint16_t make_uint16_t(uint8_t b1, uint8_t b2) {
static inline uint16_t make_uint16_t_be(uint8_t b1, uint8_t b2) {
return (b1 << 8) | b2;
}
static inline uint16_t get_uint16_t(const uint8_t *b, uint16_t offset) {
return make_uint16_t(b[offset], b[offset + 1]);
static inline uint16_t make_uint16_t_le(uint8_t b1, uint8_t b2) {
return (b2 << 8) | b1;
}
static inline void put_uint16_t(uint16_t n, uint8_t *b) {
static inline uint16_t get_uint16_t_be(const uint8_t *b) {
return make_uint16_t_be(b[0], b[1]);
}
static inline uint16_t get_uint16_t_le(const uint8_t *b) {
return make_uint16_t_le(b[0], b[1]);
}
static inline uint8_t put_uint16_t_be(uint16_t n, uint8_t *b) {
*b++ = (n >> 8) & 0xff;
*b = n & 0xff;
return 2;
}
static inline uint8_t put_uint16_t_le(uint16_t n, uint8_t *b) {
*b++ = n & 0xff;
*b = (n >> 8) & 0xff;
return 2;
}
static inline uint32_t make_uint32_t_be(uint8_t b1, uint8_t b2, uint8_t b3, uint8_t b4) {
return (b1 << 24) | (b2 << 16) | (b3 << 8) | b4;
}
static inline uint32_t make_uint32_t_le(uint8_t b1, uint8_t b2, uint8_t b3, uint8_t b4) {
return (b4 << 24) | (b3 << 16) | (b2 << 8) | b1;
}
static inline uint32_t get_uint32_t_be(const uint8_t *b) {
return make_uint32_t_be(b[0], b[1], b[2], b[3]);
}
static inline uint32_t get_uint32_t_le(const uint8_t *b) {
return make_uint32_t_le(b[0], b[1], b[2], b[3]);
}
static inline uint32_t put_uint32_t_be(uint32_t n, uint8_t *b) {
*b++ = (n >> 24) & 0xff;
*b++ = (n >> 16) & 0xff;
*b++ = (n >> 8) & 0xff;
*b = n & 0xff;
return 4;
}
static inline uint32_t put_uint32_t_le(uint32_t n, uint8_t *b) {
*b++ = n & 0xff;
*b++ = (n >> 8) & 0xff;
*b++ = (n >> 16) & 0xff;
*b = (n >> 24) & 0xff;
return 4;
}
static inline uint64_t make_uint64_t_be(uint8_t b1, uint8_t b2, uint8_t b3, uint8_t b4, uint8_t b5, uint8_t b6, uint8_t b7, uint8_t b8) {
return ((uint64_t) b1 << 56) | ((uint64_t) b2 << 48) | ((uint64_t) b3 << 40) | ((uint64_t) b4 << 32) | ((uint64_t) b5 << 24) | ((uint64_t) b6 << 16) | ((uint64_t) b7 << 8) | b8;
}
static inline uint64_t make_uint64_t_le(uint8_t b1, uint8_t b2, uint8_t b3, uint8_t b4, uint8_t b5, uint8_t b6, uint8_t b7, uint8_t b8) {
return ((uint64_t) b8 << 56) | ((uint64_t) b7 << 48) | ((uint64_t) b6 << 40) | ((uint64_t) b5 << 32) | ((uint64_t) b4 << 24) | ((uint64_t) b3 << 16) | ((uint64_t) b2 << 8) | b1;
}
static inline uint64_t get_uint64_t_be(const uint8_t *b) {
return make_uint64_t_be(b[0], b[1], b[2], b[3], b[4], b[5], b[6], b[7]);
}
static inline uint64_t get_uint64_t_le(const uint8_t *b) {
return make_uint64_t_le(b[0], b[1], b[2], b[3], b[4], b[5], b[6], b[7]);
}
static inline uint32_t put_uint64_t_be(uint64_t n, uint8_t *b) {
*b++ = (n >> 56) & 0xff;
*b++ = (n >> 48) & 0xff;
*b++ = (n >> 40) & 0xff;
*b++ = (n >> 32) & 0xff;
*b++ = (n >> 24) & 0xff;
*b++ = (n >> 16) & 0xff;
*b++ = (n >> 8) & 0xff;
*b = n & 0xff;
return 8;
}
static inline uint32_t put_uint64_t_le(uint64_t n, uint8_t *b) {
*b++ = n & 0xff;
*b++ = (n >> 8) & 0xff;
*b++ = (n >> 16) & 0xff;
*b++ = (n >> 24) & 0xff;
*b++ = (n >> 32) & 0xff;
*b++ = (n >> 40) & 0xff;
*b++ = (n >> 48) & 0xff;
*b = (n >> 56) & 0xff;
return 8;
}
extern void low_flash_available();
@ -81,7 +154,6 @@ extern int flash_clear_file(file_t *file);
extern int (*button_pressed_cb)(uint8_t);
extern bool is_req_button_pending();
extern uint32_t button_timeout;
#define SW_BYTES_REMAINING_00() set_res_sw(0x61, 0x00)
#define SW_WARNING_STATE_UNCHANGED() set_res_sw(0x62, 0x00)
@ -156,11 +228,16 @@ extern uint32_t button_timeout;
#define PICOKEY_CHECK(x) do { ret = (x); if (ret != PICOKEY_OK) goto err; } while (0)
#if defined(ENABLE_EMULATION) || defined(ESP_PLATFORM)
#if !defined (PICO_PLATFORM)
#define PICO_UNIQUE_BOARD_ID_SIZE_BYTES 8
typedef struct { uint8_t id[PICO_UNIQUE_BOARD_ID_SIZE_BYTES]; } pico_unique_board_id_t;
#endif
extern pico_unique_board_id_t pico_serial;
extern char pico_serial_str[2 * PICO_UNIQUE_BOARD_ID_SIZE_BYTES + 1];
extern uint8_t pico_serial_hash[32];
#if defined(PICO_PLATFORM)
#define multicore_launch_func_core1(a) multicore_launch_core1((void (*) (void))a)
#endif
#endif

View file

@ -3,22 +3,22 @@
* Copyright (c) 2022 Pol Henarejos.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, version 3.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
* Affero General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
#ifndef __VERSION_H_
#define __VERSION_H_
#define PICO_KEYS_SDK_VERSION 0x0700
#define PICO_KEYS_SDK_VERSION 0x0800
#define PICO_KEYS_SDK_VERSION_MAJOR ((PICO_KEYS_SDK_VERSION >> 8) & 0xff)
#define PICO_KEYS_SDK_VERSION_MINOR (PICO_KEYS_SDK_VERSION & 0xff)

113
src/pthread_win32.h Normal file
View file

@ -0,0 +1,113 @@
/*
* This file is part of the Pico Keys SDK distribution (https://github.com/polhenarejos/pico-keys-sdk).
* Copyright (c) 2022 Pol Henarejos.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, version 3.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
#ifdef _MSC_VER
#ifndef _PTHREAD_H_
#define _PTHREAD_H_
#include <windows.h>
#include <stdint.h>
typedef HANDLE pthread_t;
typedef CRITICAL_SECTION pthread_mutex_t;
typedef struct {
CONDITION_VARIABLE cond;
} pthread_cond_t;
// Mutex
static inline int pthread_mutex_init(pthread_mutex_t *m, void *a) {
(void)a;
InitializeCriticalSection(m);
return 0;
}
static inline int pthread_mutex_lock(pthread_mutex_t *m) {
EnterCriticalSection(m);
return 0;
}
static inline int pthread_mutex_unlock(pthread_mutex_t *m) {
LeaveCriticalSection(m);
return 0;
}
static inline int pthread_mutex_destroy(pthread_mutex_t *m) {
DeleteCriticalSection(m);
return 0;
}
// Thread
static DWORD WINAPI thread_entry(LPVOID param) {
void **args = (void **)param;
void *(*fn)(void *) = (void *(*)(void *))(uintptr_t)args[0];
void *arg = args[1];
fn(arg);
free(param);
return 0;
}
static inline int pthread_create(pthread_t *t, void *a, void *(*fn)(void *), void *arg) {
(void)a;
void **params = malloc(2 * sizeof(void *));
if (!params) return -1;
params[0] = (void *)(uintptr_t)fn;
params[1] = arg;
*t = CreateThread(NULL, 0, thread_entry, params, 0, NULL);
return *t ? 0 : -1;
}
static inline int pthread_join(pthread_t t, void **ret) {
WaitForSingleObject(t, INFINITE);
CloseHandle(t);
if (ret) *ret = NULL;
return 0;
}
// Condition variable
static inline int pthread_cond_init(pthread_cond_t *c, void *a) {
(void)a;
InitializeConditionVariable(&c->cond);
return 0;
}
static inline int pthread_cond_destroy(pthread_cond_t *c) {
(void)c;
return 0;
}
static inline int pthread_cond_wait(pthread_cond_t *c, pthread_mutex_t *m) {
SleepConditionVariableCS(&c->cond, m, INFINITE);
return 0;
}
static inline int pthread_cond_signal(pthread_cond_t *c) {
WakeConditionVariable(&c->cond);
return 0;
}
static inline int pthread_cond_broadcast(pthread_cond_t *c) {
WakeAllConditionVariable(&c->cond);
return 0;
}
static inline int pthread_mutex_trylock(pthread_mutex_t *m){
return TryEnterCriticalSection(m) ? 0 : EBUSY;
}
#endif // _PTHREAD_H_
#endif // _MSC_VER

132
src/queue.h Normal file
View file

@ -0,0 +1,132 @@
/*
* This file is part of the Pico Keys SDK distribution (https://github.com/polhenarejos/pico-keys-sdk).
* Copyright (c) 2022 Pol Henarejos.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, version 3.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
#ifndef QUEUE_H
#define QUEUE_H
#ifdef _MSC_VER
#include "pthread_win32.h"
#include "semaphore_win32.h"
#else
#include <pthread.h>
#include <semaphore.h>
#endif
#include <stdbool.h>
typedef struct {
pthread_mutex_t mtx;
pthread_cond_t cnd;
size_t size_elem;
size_t num_elem;
size_t max_elem;
uint8_t buf[1024];
bool is_init;
} queue_t;
static inline void queue_free(queue_t *a) {
pthread_mutex_destroy(&a->mtx);
pthread_cond_destroy(&a->cnd);
a->is_init = false;
}
static inline void queue_init(queue_t *a, size_t size_elem, size_t max_elem) {
if (a->is_init) {
queue_free(a);
}
pthread_mutex_init(&a->mtx, NULL);
pthread_cond_init(&a->cnd, NULL);
a->size_elem = size_elem;
a->max_elem = max_elem;
a->num_elem = 0;
a->is_init = true;
}
static inline void queue_add_blocking(queue_t *a, const void *b) {
pthread_mutex_lock(&a->mtx);
while (a->num_elem == a->max_elem) {
pthread_cond_wait(&a->cnd, &a->mtx);
}
memcpy(a->buf + a->num_elem * a->size_elem, b, a->size_elem);
a->num_elem++;
pthread_cond_signal(&a->cnd);
pthread_mutex_unlock(&a->mtx);
}
static inline void queue_remove_blocking(queue_t *a, void *b) {
pthread_mutex_lock(&a->mtx);
while (a->num_elem == 0) {
pthread_cond_wait(&a->cnd, &a->mtx);
}
memcpy(b, a->buf, a->size_elem);
memmove(a->buf, a->buf + a->size_elem, a->size_elem * (a->num_elem - 1));
a->num_elem--;
pthread_cond_signal(&a->cnd);
pthread_mutex_unlock(&a->mtx);
}
static inline int queue_try_add(queue_t *a, const void *b) {
pthread_mutex_lock(&a->mtx);
if (a->num_elem == a->max_elem) {
pthread_mutex_unlock(&a->mtx);
return 0;
}
memcpy(a->buf + a->num_elem * a->size_elem, b, a->size_elem);
a->num_elem++;
pthread_cond_signal(&a->cnd);
pthread_mutex_unlock(&a->mtx);
return 1;
}
static inline int queue_try_remove(queue_t *a, void *b) {
pthread_mutex_lock(&a->mtx);
if (a->num_elem == 0) {
pthread_mutex_unlock(&a->mtx);
return 0;
}
memcpy(b, a->buf, a->size_elem);
memmove(a->buf, a->buf + a->size_elem, a->size_elem * (a->num_elem - 1));
a->num_elem--;
pthread_cond_signal(&a->cnd);
pthread_mutex_unlock(&a->mtx);
return 1;
}
static inline int queue_is_empty(queue_t *a) {
pthread_mutex_lock(&a->mtx);
bool ret = a->num_elem == 0;
pthread_mutex_unlock(&a->mtx);
return ret;
}
static inline int queue_is_full(queue_t *a) {
pthread_mutex_lock(&a->mtx);
bool ret = a->num_elem == a->max_elem;
pthread_mutex_unlock(&a->mtx);
return ret;
}
static inline void queue_clear(queue_t *a) {
pthread_mutex_lock(&a->mtx);
a->num_elem = 0;
pthread_mutex_unlock(&a->mtx);
}
extern pthread_t hcore0, hcore1;
#define multicore_launch_func_core1(a) pthread_create(&hcore1, NULL, (void *(*) (void *))a, NULL)
#define multicore_reset_core1()
typedef pthread_mutex_t mutex_t;
typedef sem_t semaphore_t;
#define mutex_init(a) pthread_mutex_init(a, NULL)
#define mutex_try_enter(a,b) (pthread_mutex_trylock(a) == 0)
#define mutex_enter_blocking(a) pthread_mutex_lock(a)
#define mutex_exit(a) pthread_mutex_unlock(a)
#define sem_release(a) sem_post(a)
#define sem_acquire_blocking(a) sem_wait(a)
#define multicore_lockout_victim_init() (void)0
#endif // QUEUE_H

View file

@ -3,22 +3,29 @@
* Copyright (c) 2022 Pol Henarejos.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, version 3.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
* Affero General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
#include "pico_keys.h"
#include "apdu.h"
#include "pico_keys_version.h"
#include "otp.h"
#ifdef PICO_PLATFORM
#include "pico/bootrom.h"
#include "hardware/watchdog.h"
#endif
#include "mbedtls/ecdsa.h"
#include "mbedtls/sha256.h"
#include "random.h"
int rescue_process_apdu();
int rescue_unload();
@ -32,11 +39,15 @@ const uint8_t rescue_aid[] = {
#define PICO_MCU 1
#elif defined(ESP_PLATFORM)
#define PICO_MCU 2
#elif defined(ENABLE_EMULATION)
#define PICO_MCU 3
#else
#define PICO_MCU 0
#endif
extern uint8_t PICO_PRODUCT;
extern uint8_t PICO_VERSION_MAJOR;
extern uint8_t PICO_VERSION_MINOR;
int rescue_select(app_t *a, uint8_t force) {
a->process_apdu = rescue_process_apdu;
@ -44,8 +55,10 @@ int rescue_select(app_t *a, uint8_t force) {
res_APDU_size = 0;
res_APDU[res_APDU_size++] = PICO_MCU;
res_APDU[res_APDU_size++] = PICO_PRODUCT;
res_APDU[res_APDU_size++] = PICO_KEYS_SDK_VERSION_MAJOR;
res_APDU[res_APDU_size++] = PICO_KEYS_SDK_VERSION_MINOR;
res_APDU[res_APDU_size++] = PICO_VERSION_MAJOR;
res_APDU[res_APDU_size++] = PICO_VERSION_MINOR;
memcpy(res_APDU + res_APDU_size, pico_serial.id, sizeof(pico_serial.id));
res_APDU_size += sizeof(pico_serial.id);
apdu.ne = res_APDU_size;
if (force) {
scan_flash();
@ -61,6 +74,89 @@ int rescue_unload() {
return PICOKEY_OK;
}
int cmd_keydev_sign() {
uint8_t p1 = P1(apdu);
if (p1 == 0x01) {
if (apdu.nc != 32) {
return SW_WRONG_LENGTH();
}
if (!otp_key_2) {
return SW_INS_NOT_SUPPORTED();
}
mbedtls_ecdsa_context ecdsa;
mbedtls_ecdsa_init(&ecdsa);
int ret = mbedtls_ecp_read_key(MBEDTLS_ECP_DP_SECP256K1, &ecdsa, otp_key_2, 32);
if (ret != 0) {
mbedtls_ecdsa_free(&ecdsa);
return SW_EXEC_ERROR();
}
uint16_t key_size = 2 * (int)((mbedtls_ecp_curve_info_from_grp_id(MBEDTLS_ECP_DP_SECP256K1)->bit_size + 7) / 8);
mbedtls_mpi r, s;
mbedtls_mpi_init(&r);
mbedtls_mpi_init(&s);
ret = mbedtls_ecdsa_sign(&ecdsa.MBEDTLS_PRIVATE(grp), &r, &s, &ecdsa.MBEDTLS_PRIVATE(d), apdu.data, apdu.nc, random_gen, NULL);
if (ret != 0) {
mbedtls_ecdsa_free(&ecdsa);
mbedtls_mpi_free(&r);
mbedtls_mpi_free(&s);
return SW_EXEC_ERROR();
}
mbedtls_mpi_write_binary(&r, res_APDU, key_size / 2); res_APDU_size = key_size / 2;
mbedtls_mpi_write_binary(&s, res_APDU + res_APDU_size, key_size / 2); res_APDU_size += key_size / 2;
mbedtls_ecdsa_free(&ecdsa);
mbedtls_mpi_free(&r);
mbedtls_mpi_free(&s);
}
else if (p1 == 0x02) {
// Return public key
if (!otp_key_2) {
return SW_INS_NOT_SUPPORTED();
}
if (apdu.nc != 0) {
return SW_WRONG_LENGTH();
}
mbedtls_ecp_keypair ecp;
mbedtls_ecp_keypair_init(&ecp);
int ret = mbedtls_ecp_read_key(MBEDTLS_ECP_DP_SECP256K1, &ecp, otp_key_2, 32);
if (ret != 0) {
mbedtls_ecp_keypair_free(&ecp);
return SW_EXEC_ERROR();
}
ret = mbedtls_ecp_mul(&ecp.MBEDTLS_PRIVATE(grp), &ecp.MBEDTLS_PRIVATE(Q), &ecp.MBEDTLS_PRIVATE(d), &ecp.MBEDTLS_PRIVATE(grp).G, random_gen, NULL);
if (ret != 0) {
mbedtls_ecp_keypair_free(&ecp);
return SW_EXEC_ERROR();
}
size_t olen = 0;
ret = mbedtls_ecp_point_write_binary(&ecp.MBEDTLS_PRIVATE(grp), &ecp.MBEDTLS_PRIVATE(Q), MBEDTLS_ECP_PF_UNCOMPRESSED, &olen, res_APDU, 4096);
if (ret != 0) {
mbedtls_ecp_keypair_free(&ecp);
return SW_EXEC_ERROR();
}
res_APDU_size = (uint16_t)olen;
mbedtls_ecp_keypair_free(&ecp);
}
else if (p1 == 0x03) {
// Upload device attestation certificate
if (apdu.nc == 0) {
return SW_WRONG_LENGTH();
}
file_t *ef_devcert = file_new(0x2F02); // EF_DEVCERT
if (!ef_devcert) {
return SW_FILE_NOT_FOUND();
}
file_put_data(ef_devcert, apdu.data, (uint16_t)apdu.nc);
res_APDU_size = 0;
low_flash_available();
}
else {
return SW_INCORRECT_P1P2();
}
return SW_OK();
}
int cmd_write() {
if (apdu.nc < 2) {
return SW_WRONG_LENGTH();
@ -68,13 +164,51 @@ int cmd_write() {
if (P1(apdu) == 0x1) { // PHY
#ifndef ENABLE_EMULATION
int ret = phy_unserialize_data(apdu.data, apdu.nc, &phy_data);
int ret = phy_unserialize_data(apdu.data, (uint16_t)apdu.nc, &phy_data);
if (ret == PICOKEY_OK) {
file_put_data(ef_phy, apdu.data, apdu.nc);
if (phy_save() != PICOKEY_OK) {
return SW_EXEC_ERROR();
}
}
#endif
}
low_flash_available();
return SW_OK();
}
int cmd_read() {
if (apdu.nc != 0) {
return SW_WRONG_LENGTH();
}
uint8_t p1 = P1(apdu);
if (p1 == 0x1) { // PHY
#ifndef ENABLE_EMULATION
uint16_t len = 0;
int ret = phy_serialize_data(&phy_data, apdu.rdata, &len);
if (ret != PICOKEY_OK) {
return SW_EXEC_ERROR();
}
res_APDU_size = len;
#endif
}
else if (p1 == 0x2) { // FLASH INFO
res_APDU_size = 0;
uint32_t free = flash_free_space(), total = flash_total_space(), used = flash_used_space(), nfiles = flash_num_files(), size = flash_size();
res_APDU_size += put_uint32_t_be(free, res_APDU + res_APDU_size);
res_APDU_size += put_uint32_t_be(used, res_APDU + res_APDU_size);
res_APDU_size += put_uint32_t_be(total, res_APDU + res_APDU_size);
res_APDU_size += put_uint32_t_be(nfiles, res_APDU + res_APDU_size);
res_APDU_size += put_uint32_t_be(size, res_APDU + res_APDU_size);
}
else if (p1 == 0x3) { // OTP SECURE BOOT STATUS
res_APDU_size = 0;
uint8_t bootkey = 0xFF;
bool enabled = otp_is_secure_boot_enabled(&bootkey);
bool locked = otp_is_secure_boot_locked();
res_APDU[res_APDU_size++] = enabled ? 0x1 : 0x0;
res_APDU[res_APDU_size++] = locked ? 0x1 : 0x0;
res_APDU[res_APDU_size++] = bootkey;
}
return SW_OK();
}
@ -95,13 +229,43 @@ int cmd_secure() {
}
#endif
#ifdef PICO_PLATFORM
int cmd_reboot_bootsel() {
if (apdu.nc != 0) {
return SW_WRONG_LENGTH();
}
if (P1(apdu) == 0x1) {
// Reboot to BOOTSEL
reset_usb_boot(0, 0);
}
else if (P1(apdu) == 0x0) {
// Reboot to normal mode
watchdog_reboot(0, 0, 100);
}
else {
return SW_INCORRECT_P1P2();
}
return SW_OK();
}
#endif
#define INS_KEYDEV_SIGN 0x10
#define INS_WRITE 0x1C
#define INS_SECURE 0x1D
#define INS_READ 0x1E
#define INS_REBOOT_BOOTSEL 0x1F
static const cmd_t cmds[] = {
{ INS_KEYDEV_SIGN, cmd_keydev_sign },
{ INS_WRITE, cmd_write },
#if defined(PICO_RP2350) || defined(ESP_PLATFORM)
{ INS_SECURE, cmd_secure },
#endif
{ INS_READ, cmd_read },
#ifdef PICO_PLATFORM
{ INS_REBOOT_BOOTSEL, cmd_reboot_bootsel },
#endif
{ 0x00, 0x0 }
};

View file

@ -3,35 +3,36 @@
* Copyright (c) 2022 Pol Henarejos.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, version 3.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
* Affero General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
#include <stdint.h>
#include <string.h>
#include <stdio.h>
#if defined(ENABLE_EMULATION)
#include <stdbool.h>
#include <stdlib.h>
#include <time.h>
#include "emulation.h"
#elif (ESP_PLATFORM)
#include "bootloader_random.h"
#include "esp_random.h"
#include "esp_compat.h"
#else
#if defined(PICO_PLATFORM)
#include "pico/stdlib.h"
#include "hwrng.h"
#include "bsp/board.h"
#include "pico/rand.h"
#elif defined(ESP_PLATFORM)
#include "bootloader_random.h"
#include "esp_random.h"
#include "esp_compat.h"
#else
#include <stdbool.h>
#include <stdlib.h>
#include <time.h>
#include "board.h"
#endif
void hwrng_start() {
@ -57,14 +58,14 @@ static int ep_process() {
}
uint64_t word = 0x0;
#if defined(ENABLE_EMULATION)
word = rand();
word <<= 32;
word |= rand();
#if defined(PICO_PLATFORM)
word = get_rand_64();
#elif defined(ESP_PLATFORM)
esp_fill_random((uint8_t *)&word, sizeof(word));
#else
word = get_rand_64();
word = rand();
word <<= 32;
word |= rand();
#endif
random_word ^= word ^ board_millis();
random_word *= 0x00000100000001B3;
@ -169,15 +170,13 @@ uint32_t neug_get() {
void neug_wait_full() {
struct rng_rb *rb = &the_ring_buffer;
#ifndef ENABLE_EMULATION
#ifdef ESP_PLATFORM
uint8_t core = xTaskGetCurrentTaskHandle() == hcore1 ? 1 : 0;
#else
#elif defined(PICO_PLATFORM)
uint core = get_core_num();
#endif
#endif
while (!rb->full) {
#ifndef ENABLE_EMULATION
#if defined(PICO_PLATFORM) || defined(ESP_PLATFORM)
if (core == 1) {
sleep_ms(1);
}

View file

@ -3,16 +3,16 @@
* Copyright (c) 2022 Pol Henarejos.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, version 3.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
* Affero General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
#ifndef _NEUG_H_
@ -21,7 +21,7 @@
#define NEUG_PRE_LOOP 32
#include <stdlib.h>
#if !defined(ENABLE_EMULATION) && !defined(ESP_PLATFORM)
#if defined(PICO_PLATFORM)
#include "pico/stdlib.h"
#endif

View file

@ -3,16 +3,16 @@
* Copyright (c) 2022 Pol Henarejos.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, version 3.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
* Affero General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/

View file

@ -3,16 +3,16 @@
* Copyright (c) 2022 Pol Henarejos.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, version 3.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
* Affero General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/

47
src/semaphore_win32.h Normal file
View file

@ -0,0 +1,47 @@
/*
* This file is part of the Pico Keys SDK distribution (https://github.com/polhenarejos/pico-keys-sdk).
* Copyright (c) 2022 Pol Henarejos.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, version 3.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
#ifdef _MSC_VER
#ifndef _SEMAPHORE_H_
#define _SEMAPHORE_H_
#include <windows.h>
typedef struct {
HANDLE handle;
} sem_t;
static inline int sem_init(sem_t *sem, int pshared, unsigned int value) {
(void)pshared;
sem->handle = CreateSemaphore(NULL, value, 0x7FFFFFFF, NULL);
return sem->handle ? 0 : -1;
}
static inline int sem_wait(sem_t *sem) {
return WaitForSingleObject(sem->handle, INFINITE) == WAIT_OBJECT_0 ? 0 : -1;
}
static inline int sem_post(sem_t *sem) {
return ReleaseSemaphore(sem->handle, 1, NULL) ? 0 : -1;
}
static inline int sem_destroy(sem_t *sem) {
return CloseHandle(sem->handle) ? 0 : -1;
}
#endif // _SEMAPHORE_H_
#endif // _MSC_VER

View file

@ -3,16 +3,16 @@
* Copyright (c) 2022 Pol Henarejos.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, version 3.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
* Affero General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
#include "random.h"
@ -48,6 +48,8 @@
#define CCID_DATA_BLOCK_RET 0x80
#define CCID_SLOT_STATUS_RET 0x81 /* non-ICCD result */
#define CCID_PARAMS_RET 0x82 /* non-ICCD result */
#define CCID_SETDATARATEANDCLOCKFREQUENCY 0x73
#define CCID_SETDATARATEANDCLOCKFREQUENCY_RET 0x84
#define CCID_MSG_SEQ_OFFSET 6
#define CCID_MSG_STATUS_OFFSET 7
@ -92,7 +94,7 @@ uint8_t ccid_status = 1;
static uint8_t itf_num;
#endif
static usb_buffer_t ccid_rx[ITF_SC_TOTAL] = {0}, ccid_tx[ITF_SC_TOTAL] = {0};
static usb_buffer_t *ccid_rx = NULL, *ccid_tx = NULL;
int driver_process_usb_packet_ccid(uint8_t itf, uint16_t rx_read);
@ -105,9 +107,9 @@ void ccid_write(uint8_t itf, uint16_t size) {
ccid_write_offset(itf, size, 0);
}
ccid_header_t *ccid_response[ITF_SC_TOTAL];
ccid_header_t *ccid_resp_fast[ITF_SC_TOTAL];
ccid_header_t *ccid_header[ITF_SC_TOTAL];
ccid_header_t **ccid_response = NULL;
ccid_header_t **ccid_resp_fast = NULL;
ccid_header_t **ccid_header = NULL;
uint8_t sc_itf_to_usb_itf(uint8_t itf) {
if (itf == ITF_SC_CCID) {
@ -119,6 +121,27 @@ uint8_t sc_itf_to_usb_itf(uint8_t itf) {
return itf;
}
void ccid_init_buffers() {
if (ITF_SC_TOTAL == 0) {
return;
}
if (ccid_rx == NULL) {
ccid_rx = (usb_buffer_t *)calloc(ITF_SC_TOTAL, sizeof(usb_buffer_t));
}
if (ccid_tx == NULL) {
ccid_tx = (usb_buffer_t *)calloc(ITF_SC_TOTAL, sizeof(usb_buffer_t));
}
if (ccid_header == NULL) {
ccid_header = (ccid_header_t **)calloc(ITF_SC_TOTAL, sizeof(ccid_header_t *));
}
if (ccid_response == NULL) {
ccid_response = (ccid_header_t **)calloc(ITF_SC_TOTAL, sizeof(ccid_header_t *));
}
if (ccid_resp_fast == NULL) {
ccid_resp_fast = (ccid_header_t **)calloc(ITF_SC_TOTAL, sizeof(ccid_header_t *));
}
}
int driver_init_ccid(uint8_t itf) {
ccid_header[itf] = (ccid_header_t *) (ccid_rx[itf].buffer + ccid_rx[itf].r_ptr);
ccid_resp_fast[itf] = (ccid_header_t *) (ccid_tx[itf].buffer + sizeof(ccid_tx[itf].buffer) - 64);
@ -133,7 +156,7 @@ int driver_init_ccid(uint8_t itf) {
return PICOKEY_OK;
}
void tud_vendor_rx_cb(uint8_t itf) {
void tud_vendor_rx_cb(uint8_t itf, const uint8_t *buffer, uint16_t bufsize) {
uint32_t len = tud_vendor_n_available(itf);
do {
uint16_t tlen = 0;
@ -150,11 +173,6 @@ void tud_vendor_rx_cb(uint8_t itf) {
} while (len > 0);
}
void tud_vendor_tx_cb(uint8_t itf, uint32_t sent_bytes) {
(void) sent_bytes;
tud_vendor_n_write_flush(itf);
}
int driver_write_ccid(uint8_t itf, const uint8_t *tx_buffer, uint16_t buffer_size) {
if (*tx_buffer != 0x81) {
DEBUG_PAYLOAD(tx_buffer, buffer_size);
@ -258,6 +276,16 @@ int driver_process_usb_packet_ccid(uint8_t itf, uint16_t rx_read) {
memcpy(&ccid_resp_fast[itf]->apdu, params, sizeof(params));
ccid_write_fast(itf, (const uint8_t *)ccid_resp_fast[itf], sizeof(params) + 10);
}
else if (ccid_header[itf]->bMessageType == CCID_SETDATARATEANDCLOCKFREQUENCY) {
ccid_resp_fast[itf]->bMessageType = CCID_SETDATARATEANDCLOCKFREQUENCY_RET;
ccid_resp_fast[itf]->dwLength = 8;
ccid_resp_fast[itf]->bSlot = 0;
ccid_resp_fast[itf]->bSeq = ccid_header[itf]->bSeq;
ccid_resp_fast[itf]->abRFU0 = ccid_status;
ccid_resp_fast[itf]->abRFU1 = 0;
memset(&ccid_resp_fast[itf]->apdu, 0, 8);
ccid_write_fast(itf, (const uint8_t *)ccid_resp_fast[itf], 18);
}
else if (ccid_header[itf]->bMessageType == CCID_XFR_BLOCK) {
apdu.rdata = &ccid_response[itf]->apdu;
apdu_sent = apdu_process(itf, &ccid_header[itf]->apdu, (uint16_t)ccid_header[itf]->dwLength);
@ -316,11 +344,16 @@ void ccid_task() {
}
}
void ccid_init() {
ccid_init_buffers();
}
#ifndef ENABLE_EMULATION
#define USB_CONFIG_ATT_ONE TU_BIT(7)
#define MAX_USB_POWER 1
void tud_vendor_tx_cb(uint8_t itf, uint32_t sent_bytes) {
(void) sent_bytes;
tud_vendor_n_write_flush(itf);
}
static void ccid_init_cb(void) {
vendord_init();
@ -336,17 +369,24 @@ static uint16_t ccid_open(uint8_t rhport, tusb_desc_interface_t const *itf_desc,
TU_VERIFY( itf_desc->bInterfaceClass == TUSB_CLASS_SMART_CARD && itf_desc->bInterfaceSubClass == 0 && itf_desc->bInterfaceProtocol == 0, 0);
//vendord_open expects a CLASS_VENDOR interface class
uint16_t const drv_len = sizeof(tusb_desc_interface_t) + sizeof(struct ccid_class_descriptor) + 3 * sizeof(tusb_desc_endpoint_t);
uint16_t const drv_len = sizeof(tusb_desc_interface_t) + sizeof(struct ccid_class_descriptor) + TUSB_SMARTCARD_CCID_EPS * sizeof(tusb_desc_endpoint_t);
memcpy(itf_vendor, itf_desc, sizeof(uint8_t) * max_len);
((tusb_desc_interface_t *) itf_vendor)->bInterfaceClass = TUSB_CLASS_VENDOR_SPECIFIC;
#if TUSB_SMARTCARD_CCID_EPS == 3
((tusb_desc_interface_t *) itf_vendor)->bNumEndpoints -= 1;
vendord_open(rhport, (tusb_desc_interface_t *) itf_vendor, max_len - sizeof(tusb_desc_endpoint_t));
vendord_open(rhport, (tusb_desc_interface_t *)itf_vendor, max_len - sizeof(tusb_desc_endpoint_t));
tusb_desc_endpoint_t const *desc_ep = (tusb_desc_endpoint_t const *)((uint8_t *)itf_desc + drv_len - sizeof(tusb_desc_endpoint_t));
TU_ASSERT(usbd_edpt_open(rhport, desc_ep), 0);
free(itf_vendor);
uint8_t msg[] = { 0x50, 0x03 };
#if defined(PICO_PLATFORM) || defined(ESP_PLATFORM)
usbd_edpt_xfer(rhport, desc_ep->bEndpointAddress, msg, sizeof(msg));
#else
usbd_edpt_xfer(rhport, desc_ep->bEndpointAddress, msg, sizeof(msg), sizeof(msg));
#endif
#else
vendord_open(rhport, (tusb_desc_interface_t *)itf_vendor, max_len);
#endif
free(itf_vendor);
TU_VERIFY(max_len >= drv_len, 0);

View file

@ -3,16 +3,16 @@
* Copyright (c) 2022 Pol Henarejos.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, version 3.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
* Affero General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
#ifndef _CCID_H_

View file

@ -3,18 +3,19 @@
* Copyright (c) 2022 Pol Henarejos.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, version 3.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
* Affero General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
#include "pico_keys.h"
#include "emulation.h"
#include <stdio.h>
#ifndef _MSC_VER
@ -41,7 +42,6 @@ typedef int socklen_t;
#include <errno.h>
#include <time.h>
#include "pico_keys.h"
#include "apdu.h"
#include "usb.h"
#include "ccid/ccid.h"
@ -303,28 +303,24 @@ uint16_t emul_read(uint8_t itf) {
driver_write_emul(itf, ccid_atr ? ccid_atr + 1 : NULL, ccid_atr ? ccid_atr[0] : 0);
}
}
else {
switch(itf) {
#ifdef USB_ITF_CCID
case ITF_CCID: {
uint16_t sent = 0;
DEBUG_PAYLOAD(emul_rx, len);
apdu.rdata = emul_tx;
if ((sent = apdu_process(itf, emul_rx, len)) > 0) {
process_apdu();
apdu_finish();
}
if (sent > 0) {
uint16_t ret = apdu_next();
DEBUG_PAYLOAD(apdu.rdata, ret);
driver_write_emul(itf, apdu.rdata, ret);
}
break;
else if (itf == ITF_CCID) {
uint16_t sent = 0;
DEBUG_PAYLOAD(emul_rx, len);
apdu.rdata = emul_tx;
if ((sent = apdu_process(itf, emul_rx, len)) > 0) {
process_apdu();
apdu_finish();
}
if (sent > 0) {
uint16_t ret = apdu_next();
DEBUG_PAYLOAD(apdu.rdata, ret);
driver_write_emul(itf, apdu.rdata, ret);
}
}
#endif
default:
emul_rx_size += valread;
}
else {
emul_rx_size += valread;
}
return (uint16_t)emul_rx_size;
}

View file

@ -3,16 +3,16 @@
* Copyright (c) 2022 Pol Henarejos.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, version 3.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
* Affero General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
#ifndef _EMULATION_H_
@ -20,11 +20,8 @@
#include <stdint.h>
#include <string.h>
#ifdef _MSC_VER
#include <windows.h>
#else
#include <sys/time.h>
#endif
#include "queue.h"
#include "board.h"
#include <stdbool.h>
#define USB_BUFFER_SIZE 2048
@ -34,12 +31,6 @@ extern uint16_t emul_rx_size, emul_tx_size;
extern uint16_t driver_write_emul(uint8_t itf, const uint8_t *buffer, uint16_t buffer_size);
extern uint16_t emul_read(uint8_t itf);
static inline uint32_t board_millis() {
struct timeval start;
gettimeofday(&start, NULL);
return start.tv_sec * 1000 + start.tv_usec / 1000;
}
#ifdef USB_ITF_HID
typedef uint8_t hid_report_type_t;
#endif
@ -71,109 +62,4 @@ extern void tud_hid_report_complete_cb(uint8_t instance, uint8_t const *report,
extern bool tud_hid_n_report(uint8_t itf, uint8_t report_id, const uint8_t *buffer, uint32_t n);
#endif
#include <pthread.h>
#include <semaphore.h>
typedef struct {
pthread_mutex_t mtx;
pthread_cond_t cnd;
size_t size_elem;
size_t num_elem;
size_t max_elem;
uint8_t buf[1024];
bool is_init;
} queue_t;
static inline void queue_free(queue_t *a) {
pthread_mutex_destroy(&a->mtx);
pthread_cond_destroy(&a->cnd);
a->is_init = false;
}
static inline void queue_init(queue_t *a, size_t size_elem, size_t max_elem) {
if (a->is_init) {
queue_free(a);
}
pthread_mutex_init(&a->mtx, NULL);
pthread_cond_init(&a->cnd, NULL);
a->size_elem = size_elem;
a->max_elem = max_elem;
a->num_elem = 0;
a->is_init = true;
}
static inline void queue_add_blocking(queue_t *a, const void *b) {
pthread_mutex_lock(&a->mtx);
while (a->num_elem == a->max_elem) {
pthread_cond_wait(&a->cnd, &a->mtx);
}
memcpy(a->buf + a->num_elem * a->size_elem, b, a->size_elem);
a->num_elem++;
pthread_cond_signal(&a->cnd);
pthread_mutex_unlock(&a->mtx);
}
static inline void queue_remove_blocking(queue_t *a, void *b) {
pthread_mutex_lock(&a->mtx);
while (a->num_elem == 0) {
pthread_cond_wait(&a->cnd, &a->mtx);
}
memcpy(b, a->buf, a->size_elem);
memmove(a->buf, a->buf + a->size_elem, a->size_elem * (a->num_elem - 1));
a->num_elem--;
pthread_cond_signal(&a->cnd);
pthread_mutex_unlock(&a->mtx);
}
static inline int queue_try_add(queue_t *a, const void *b) {
pthread_mutex_lock(&a->mtx);
if (a->num_elem == a->max_elem) {
pthread_mutex_unlock(&a->mtx);
return 0;
}
memcpy(a->buf + a->num_elem * a->size_elem, b, a->size_elem);
a->num_elem++;
pthread_cond_signal(&a->cnd);
pthread_mutex_unlock(&a->mtx);
return 1;
}
static inline int queue_try_remove(queue_t *a, void *b) {
pthread_mutex_lock(&a->mtx);
if (a->num_elem == 0) {
pthread_mutex_unlock(&a->mtx);
return 0;
}
memcpy(b, a->buf, a->size_elem);
memmove(a->buf, a->buf + a->size_elem, a->size_elem * (a->num_elem - 1));
a->num_elem--;
pthread_cond_signal(&a->cnd);
pthread_mutex_unlock(&a->mtx);
return 1;
}
static inline int queue_is_empty(queue_t *a) {
pthread_mutex_lock(&a->mtx);
bool ret = a->num_elem == 0;
pthread_mutex_unlock(&a->mtx);
return ret;
}
static inline int queue_is_full(queue_t *a) {
pthread_mutex_lock(&a->mtx);
bool ret = a->num_elem == a->max_elem;
pthread_mutex_unlock(&a->mtx);
return ret;
}
static inline void queue_clear(queue_t *a) {
pthread_mutex_lock(&a->mtx);
a->num_elem = 0;
pthread_mutex_unlock(&a->mtx);
}
extern pthread_t hcore0, hcore1;
#define multicore_launch_core1(a) pthread_create(&hcore1, NULL, (void *(*) (void *))a, NULL)
#define multicore_reset_core1()
typedef pthread_mutex_t mutex_t;
typedef sem_t semaphore_t;
#define mutex_init(a) pthread_mutex_init(a, NULL)
#define mutex_try_enter(a,b) (pthread_mutex_trylock(a) == 0)
#define mutex_enter_blocking(a) pthread_mutex_lock(a)
#define mutex_exit(a) pthread_mutex_unlock(a)
#define sem_release(a) sem_post(a)
#define sem_acquire_blocking(a) sem_wait(a)
#define multicore_lockout_victim_init() (void)0
#endif // _EMULATION_H_

View file

@ -3,16 +3,16 @@
* Copyright (c) 2022 Pol Henarejos.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, version 3.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
* Affero General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
#ifndef _CTAP_HID_H_
@ -159,7 +159,7 @@ typedef struct {
extern void add_keyboard_buffer(const uint8_t *, size_t, bool);
extern void append_keyboard_buffer(const uint8_t *data, size_t data_len);
extern bool is_nitrokey;
extern bool is_nk;
#ifdef __cplusplus
}

View file

@ -3,41 +3,40 @@
* Copyright (c) 2022 Pol Henarejos.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, version 3.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
* Affero General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
#include "pico_keys.h"
#ifndef ENABLE_EMULATION
#include "tusb.h"
#ifndef ESP_PLATFORM
#if defined(PICO_PLATFORM)
#include "bsp/board.h"
#else
#elif defined(ESP_PLATFORM)
static portMUX_TYPE mutex = portMUX_INITIALIZER_UNLOCKED;
#endif
#else
#include "emulation.h"
#endif
#include "ctap_hid.h"
#include "pico_keys.h"
#include "pico_keys_version.h"
#include "apdu.h"
#include "usb.h"
static bool mounted = false;
extern void init_fido();
bool is_nitrokey = false;
bool is_nk = false;
uint8_t (*get_version_major)() = NULL;
uint8_t (*get_version_minor)() = NULL;
static usb_buffer_t hid_rx[ITF_HID_TOTAL] = {0}, hid_tx[ITF_HID_TOTAL] = {0};
static usb_buffer_t *hid_rx = NULL, *hid_tx = NULL;
PACK(
typedef struct msg_packet {
@ -48,16 +47,8 @@ typedef struct msg_packet {
msg_packet_t msg_packet = { 0 };
void tud_mount_cb() {
mounted = true;
}
bool driver_mounted_hid() {
return mounted;
}
static uint16_t send_buffer_size[ITF_HID_TOTAL] = {0};
static write_status_t last_write_result[ITF_HID_TOTAL] = {0};
static uint16_t *send_buffer_size = NULL;
static write_status_t *last_write_result = NULL;
CTAPHID_FRAME *ctap_req = NULL, *ctap_resp = NULL;
void send_keepalive();
@ -65,6 +56,24 @@ int driver_process_usb_packet_hid(uint16_t read);
int driver_write_hid(uint8_t itf, const uint8_t *buffer, uint16_t buffer_size);
int driver_process_usb_nopacket_hid();
void hid_init() {
if (ITF_HID_TOTAL == 0) {
return;
}
if (send_buffer_size == NULL) {
send_buffer_size = (uint16_t *)calloc(ITF_HID_TOTAL, sizeof(uint16_t));
}
if (last_write_result == NULL) {
last_write_result = (write_status_t *)calloc(ITF_HID_TOTAL, sizeof(write_status_t));
}
if (hid_rx == NULL) {
hid_rx = (usb_buffer_t *)calloc(ITF_HID_TOTAL, sizeof(usb_buffer_t));
}
if (hid_tx == NULL) {
hid_tx = (usb_buffer_t *)calloc(ITF_HID_TOTAL, sizeof(usb_buffer_t));
}
}
int driver_init_hid() {
#ifndef ENABLE_EMULATION
static bool _init = false;
@ -78,11 +87,11 @@ int driver_init_hid() {
ctap_resp = (CTAPHID_FRAME *) (hid_tx[ITF_HID_CTAP].buffer);
apdu.rdata = ctap_resp->init.data;
//memset(ctap_resp, 0, sizeof(CTAPHID_FRAME));
memset(ctap_resp, 0, sizeof(CTAPHID_FRAME));
usb_set_timeout_counter(ITF_HID, 200);
is_nitrokey = false;
is_nk = false;
hid_tx[ITF_HID_CTAP].w_ptr = hid_tx[ITF_HID_CTAP].r_ptr = 0;
send_buffer_size[ITF_HID_CTAP] = 0;
@ -140,7 +149,7 @@ static bool sent_key = false;
static bool keyboard_encode = false;
void add_keyboard_buffer(const uint8_t *data, size_t data_len, bool encode) {
keyboard_buffer_len = MIN(sizeof(keyboard_buffer), data_len);
keyboard_buffer_len = (uint8_t)MIN(sizeof(keyboard_buffer), data_len);
memcpy(keyboard_buffer, data, keyboard_buffer_len);
keyboard_encode = encode;
}
@ -148,7 +157,7 @@ void add_keyboard_buffer(const uint8_t *data, size_t data_len, bool encode) {
void append_keyboard_buffer(const uint8_t *data, size_t data_len) {
if (keyboard_buffer_len + data_len < sizeof(keyboard_buffer)) {
memcpy(keyboard_buffer + keyboard_buffer_len, data, MIN(sizeof(keyboard_buffer) - keyboard_buffer_len, data_len));
keyboard_buffer_len += MIN(sizeof(keyboard_buffer) - keyboard_buffer_len, data_len);
keyboard_buffer_len += (uint8_t)MIN(sizeof(keyboard_buffer) - keyboard_buffer_len, data_len);
}
}
@ -268,11 +277,13 @@ void tud_hid_set_report_cb(uint8_t itf, uint8_t report_id, hid_report_type_t rep
printf("set_report %d %d %d\n", itf, report_id, report_type);
if (!hid_set_report_cb || hid_set_report_cb(itf, report_id, report_type, buffer, bufsize) == 0) {
//usb_rx(itf, buffer, bufsize);
memcpy(hid_rx[itf].buffer + hid_rx[itf].w_ptr, buffer, bufsize);
hid_rx[itf].w_ptr += bufsize;
int proc_pkt = driver_process_usb_packet_hid(64);
if (proc_pkt == 0) {
driver_process_usb_nopacket_hid();
if (itf == ITF_HID_CTAP) {
memcpy(hid_rx[itf].buffer + hid_rx[itf].w_ptr, buffer, bufsize);
hid_rx[itf].w_ptr += bufsize;
int proc_pkt = driver_process_usb_packet_hid(64);
if (proc_pkt == 0) {
driver_process_usb_nopacket_hid();
}
}
}
}
@ -307,8 +318,8 @@ int driver_process_usb_nopacket_hid() {
return 0;
}
extern const uint8_t fido_aid[], u2f_aid[];
extern void apdu_thread(void), cbor_thread(void);
extern const uint8_t fido_aid[], u2f_aid[], oath_aid[];
extern void *cbor_thread(void *);
int driver_process_usb_packet_hid(uint16_t read) {
int apdu_sent = 0;
@ -400,7 +411,7 @@ int driver_process_usb_packet_hid(uint16_t read) {
}
last_packet_time = 0;
memcpy(ctap_resp, ctap_req, sizeof(CTAPHID_FRAME));
#ifndef ENABLE_EMULATION
#if defined(PICO_PLATFORM) || defined(ESP_PLATFORM)
sleep_ms(1000); //For blinking the device during 1 seg
#endif
driver_write_hid(ITF_HID_CTAP, (const uint8_t *)ctap_resp, 64);
@ -472,8 +483,10 @@ int driver_process_usb_packet_hid(uint16_t read) {
(msg_packet.len == 0 ||
(msg_packet.len == msg_packet.current_len && msg_packet.len > 0))) {
if (last_cmd == CTAPHID_OTP) {
is_nitrokey = true;
select_app(fido_aid + 1, fido_aid[0]);
is_nk = true;
#ifdef ENABLE_OATH_APP
select_app(oath_aid + 1, oath_aid[0]);
#endif
}
else {
select_app(u2f_aid + 1, u2f_aid[0]);
@ -513,6 +526,7 @@ int driver_process_usb_packet_hid(uint16_t read) {
msg_packet.len = msg_packet.current_len = 0;
last_packet_time = 0;
cancel_button = true;
hid_tx[ITF_HID_CTAP].r_ptr = hid_tx[ITF_HID_CTAP].w_ptr = 0;
}
else {
if (msg_packet.len == 0) {
@ -536,6 +550,9 @@ int driver_process_usb_packet_hid(uint16_t read) {
}
void send_keepalive() {
if (thread_type == 1) {
return;
}
CTAPHID_FRAME *resp = (CTAPHID_FRAME *) (hid_tx[ITF_HID_CTAP].buffer + sizeof(hid_tx[ITF_HID_CTAP].buffer) - 64);
//memset(ctap_resp, 0, sizeof(CTAPHID_FRAME));
resp->cid = ctap_req->cid;
@ -552,10 +569,9 @@ void driver_exec_finished_hid(uint16_t size_next) {
ctap_error(apdu.sw & 0xff);
}
else {
if (is_nitrokey) {
if (is_nk) {
memmove(apdu.rdata + 2, apdu.rdata, size_next - 2);
apdu.rdata[0] = apdu.sw >> 8;
apdu.rdata[1] = apdu.sw & 0xff;
put_uint16_t_be(apdu.sw, apdu.rdata);
}
driver_exec_finished_cont_hid(ITF_HID_CTAP, size_next, 7);
}

View file

@ -58,6 +58,9 @@ extern "C" {
#define CFG_TUSB_OS OPT_OS_PICO
#elif CFG_TUSB_MCU == OPT_MCU_ESP32S2 || CFG_TUSB_MCU == OPT_MCU_ESP32S3
#define CFG_TUSB_OS OPT_OS_FREERTOS
#elif CFG_TUSB_MCU == OPT_MCU_NONE
#define CFG_TUSB_OS OPT_OS_NONE
#define TUP_DCD_ENDPOINT_MAX 16
#endif
#endif
@ -87,8 +90,12 @@ extern "C" {
#endif
#ifndef CFG_TUSB_MEM_ALIGN
#ifdef _MSC_VER
#define CFG_TUSB_MEM_ALIGN __declspec(align(4))
#else
#define CFG_TUSB_MEM_ALIGN __attribute__((aligned(4)))
#endif
#endif
//--------------------------------------------------------------------
// DEVICE CONFIGURATION
@ -99,7 +106,7 @@ extern "C" {
#endif
#define CFG_TUD_VENDOR_RX_BUFSIZE (TUD_OPT_HIGH_SPEED ? 512 : 64)
#define CFG_TUD_VENDOR_TX_BUFSIZE 4096
#define CFG_TUD_VENDOR_TX_BUFSIZE 2048
//------------- CLASS -------------//
#define CFG_TUD_CDC 0

View file

@ -3,27 +3,25 @@
* Copyright (c) 2022 Pol Henarejos.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, version 3.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
* Affero General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
#include <stdio.h>
// Pico
#if !defined(ENABLE_EMULATION) && !defined(ESP_PLATFORM)
#include "pico_keys.h"
#if defined(PICO_PLATFORM)
#include "pico/stdlib.h"
#include "pico/multicore.h"
#include "bsp/board.h"
#endif
#include "pico_keys.h"
#include "usb.h"
#include "apdu.h"
#ifndef ENABLE_EMULATION
@ -37,12 +35,34 @@
#include <stdlib.h>
// Device specific functions
static uint32_t timeout_counter[ITF_TOTAL] = { 0 };
static uint8_t card_locked_itf = ITF_TOTAL; // no locked
static void (*card_locked_func)(void) = NULL;
static uint32_t *timeout_counter = NULL;
static uint8_t card_locked_itf = 0; // no locked
static void *(*card_locked_func)(void *) = NULL;
#ifndef ENABLE_EMULATION
static mutex_t mutex;
extern void usb_desc_setup();
#endif
#if !defined(PICO_PLATFORM) && !defined(ENABLE_EMULATION) && !defined(ESP_PLATFORM)
#ifdef _MSC_VER
#include "pthread_win32.h"
#endif
pthread_t hcore0, hcore1;
#endif
#ifdef USB_ITF_HID
uint8_t ITF_HID_CTAP = ITF_INVALID, ITF_HID_KB = ITF_INVALID;
uint8_t ITF_HID = ITF_INVALID, ITF_KEYBOARD = ITF_INVALID;
uint8_t ITF_HID_TOTAL = 0;
extern void hid_init();
#endif
#ifdef USB_ITF_CCID
uint8_t ITF_SC_CCID = ITF_INVALID, ITF_SC_WCID = ITF_INVALID;
uint8_t ITF_CCID = ITF_INVALID, ITF_WCID = ITF_INVALID;
uint8_t ITF_SC_TOTAL = 0;
extern void ccid_init();
#endif
uint8_t ITF_TOTAL = 0;
void usb_set_timeout_counter(uint8_t itf, uint32_t v) {
timeout_counter[itf] = v;
@ -60,10 +80,67 @@ void usb_init() {
desc_device.idVendor = phy_data.vid;
desc_device.idProduct = phy_data.pid;
}
else {
phy_data.vid = desc_device.idVendor;
phy_data.pid = desc_device.idProduct;
phy_data.vidpid_present = true;
}
mutex_init(&mutex);
#endif
queue_init(&card_to_usb_q, sizeof(uint32_t), 64);
queue_init(&usb_to_card_q, sizeof(uint32_t), 64);
uint8_t enabled_usb_itf = PHY_USB_ITF_CCID | PHY_USB_ITF_WCID | PHY_USB_ITF_HID | PHY_USB_ITF_KB;
#ifndef ENABLE_EMULATION
if (phy_data.enabled_usb_itf_present) {
enabled_usb_itf = phy_data.enabled_usb_itf;
}
#endif
#ifdef USB_ITF_HID
ITF_HID_TOTAL = 0;
#endif
#ifdef USB_ITF_CCID
ITF_SC_TOTAL = 0;
#endif
ITF_TOTAL = 0;
#ifdef USB_ITF_HID
if (enabled_usb_itf & PHY_USB_ITF_HID) {
ITF_HID_CTAP = ITF_HID_TOTAL++;
ITF_HID = ITF_TOTAL++;
}
if (enabled_usb_itf & PHY_USB_ITF_KB) {
ITF_HID_KB = ITF_HID_TOTAL++;
ITF_KEYBOARD = ITF_TOTAL++;
}
#endif
#ifdef USB_ITF_CCID
if (enabled_usb_itf & PHY_USB_ITF_CCID) {
ITF_SC_CCID = ITF_SC_TOTAL++;
ITF_CCID = ITF_TOTAL++;
}
if (enabled_usb_itf & PHY_USB_ITF_WCID) {
ITF_SC_WCID = ITF_SC_TOTAL++;
ITF_WCID = ITF_TOTAL++;
}
#endif
card_locked_itf = ITF_TOTAL;
if (timeout_counter == NULL) {
timeout_counter = (uint32_t *)calloc(ITF_TOTAL, sizeof(uint32_t));
}
#ifdef USB_ITF_HID
if (ITF_HID_TOTAL > 0) {
hid_init();
}
#endif
#ifdef USB_ITF_CCID
if (ITF_SC_TOTAL > 0) {
ccid_init();
}
#endif
#ifdef ESP_PLATFORM
usb_desc_setup();
#endif
}
uint32_t timeout = 0;
@ -101,7 +178,7 @@ void card_init_core1() {
uint16_t finished_data_size = 0;
void card_start(uint8_t itf, void (*func)(void)) {
void card_start(uint8_t itf, void *(*func)(void *)) {
timeout_start();
if (card_locked_itf != itf || card_locked_func != func) {
if (card_locked_itf != ITF_TOTAL || card_locked_func != NULL) {
@ -109,7 +186,7 @@ void card_start(uint8_t itf, void (*func)(void)) {
}
if (func) {
multicore_reset_core1();
multicore_launch_core1(func);
multicore_launch_func_core1(func);
}
led_set_mode(MODE_MOUNTED);
card_locked_itf = itf;
@ -198,3 +275,11 @@ int card_status(uint8_t itf) {
}
return PICOKEY_ERR_FILE_NOT_FOUND;
}
#ifndef USB_ITF_CCID
#include "device/usbd_pvt.h"
usbd_class_driver_t const *usbd_app_driver_get_cb(uint8_t *driver_count) {
*driver_count = 0;
return NULL;
}
#endif

View file

@ -3,16 +3,16 @@
* Copyright (c) 2022 Pol Henarejos.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, version 3.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
* Affero General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
#ifndef _USB_H_
@ -22,8 +22,11 @@
#include "emulation.h"
#elif defined(ESP_PLATFORM)
#include "esp_compat.h"
#else
#elif defined(PICO_PLATFORM)
#include "pico/util/queue.h"
#else
#include "queue.h"
#include "board.h"
#endif
#include "compat.h"
@ -44,43 +47,37 @@
#define EV_BUTTON_TIMEOUT 16
#define EV_BUTTON_PRESSED 32
enum {
enum { ITF_INVALID = 0xFF };
#ifdef USB_ITF_HID
ITF_HID_CTAP = 0,
ITF_HID_KB,
extern uint8_t ITF_HID_CTAP, ITF_HID_KB;
extern uint8_t ITF_HID, ITF_KEYBOARD;
extern uint8_t ITF_HID_TOTAL;
#endif
ITF_HID_TOTAL
};
enum {
#ifdef USB_ITF_CCID
ITF_SC_CCID = 0,
ITF_SC_WCID,
extern uint8_t ITF_SC_CCID, ITF_SC_WCID;
extern uint8_t ITF_CCID, ITF_WCID;
extern uint8_t ITF_SC_TOTAL;
#endif
ITF_SC_TOTAL
};
extern uint8_t ITF_TOTAL;
enum {
#ifdef USB_ITF_HID
ITF_HID = ITF_HID_CTAP,
ITF_KEYBOARD = ITF_HID_KB,
#endif
#ifdef USB_ITF_CCID
ITF_CCID = ITF_SC_CCID + ITF_HID_TOTAL,
ITF_WCID = ITF_SC_WCID + ITF_HID_TOTAL,
#endif
ITF_TOTAL = ITF_HID_TOTAL + ITF_SC_TOTAL
};
enum {
REPORT_ID_KEYBOARD = 1,
REPORT_ID_KEYBOARD = 0,
REPORT_ID_COUNT
};
#if defined(ESP_PLATFORM) && defined(USB_ITF_HID) && defined(USB_ITF_CCID)
#define TUSB_SMARTCARD_CCID_EPS 2
#else
#define TUSB_SMARTCARD_CCID_EPS 3
#endif
extern void usb_task();
extern queue_t usb_to_card_q;
extern queue_t card_to_usb_q;
extern void card_start(uint8_t, void (*func)(void));
extern void card_start(uint8_t, void *(*func)(void *));
extern void card_exit();
extern int card_status(uint8_t itf);
extern void usb_init();
@ -109,7 +106,7 @@ extern void driver_exec_finished_emul(uint8_t itf, uint16_t size_next);
extern void driver_exec_finished_cont_emul(uint8_t itf, uint16_t size_next, uint16_t offset);
#endif
#define USB_BUFFER_SIZE 2048 // Size of USB buffer"
#define USB_BUFFER_SIZE 2048
PACK(
typedef struct {

View file

@ -3,21 +3,22 @@
* Copyright (c) 2022 Pol Henarejos.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, version 3.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
* Affero General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
#include "pico_keys.h"
#include "tusb.h"
#include "usb_descriptors.h"
#if !defined(ENABLE_EMULATION) && !defined(ESP_PLATFORM)
#if defined(PICO_PLATFORM)
#include "pico/unique_id.h"
#endif
#ifdef ESP_PLATFORM
@ -25,7 +26,6 @@
#endif
#include "pico_keys_version.h"
#include "usb.h"
#include "pico_keys.h"
#ifndef USB_VID
#define USB_VID 0xFEFF
@ -34,7 +34,11 @@
#define USB_PID 0xFCFD
#endif
#define USB_BCD 0x0200
#if defined(PICO_PLATFORM) || defined(ESP_PLATFORM)
#define USB_BCD 0x0210
#else
#define USB_BCD 0x0110
#endif
#define USB_CONFIG_ATT_ONE TU_BIT(7)
@ -76,19 +80,21 @@ uint8_t const *tud_descriptor_device_cb(void) {
#define TUD_INTERFACE_DESC_LEN 9
#define TUD_ENDPOINT_DESC_LEN 7
#define TUSB_SMARTCARD_LEN 54
#define TUSB_SMARTCARD_CCID_DESC_LEN (TUD_INTERFACE_DESC_LEN + TUSB_SMARTCARD_LEN + 3 * TUD_ENDPOINT_DESC_LEN)
#define TUSB_SMARTCARD_WCID_DESC_LEN (TUD_INTERFACE_DESC_LEN + TUSB_SMARTCARD_LEN + 2 * TUD_ENDPOINT_DESC_LEN)
#define TUSB_WSMARTCARD_LEN 53
#define TUSB_SMARTCARD_CCID_DESC_LEN (TUD_INTERFACE_DESC_LEN + TUSB_SMARTCARD_LEN + TUSB_SMARTCARD_CCID_EPS * TUD_ENDPOINT_DESC_LEN)
#define TUSB_SMARTCARD_WCID_DESC_LEN (TUD_INTERFACE_DESC_LEN + TUSB_WSMARTCARD_LEN + 2 * TUD_ENDPOINT_DESC_LEN)
uint16_t TUSB_DESC_TOTAL_LEN = TUD_CONFIG_DESC_LEN;
enum {
TUSB_DESC_TOTAL_LEN = TUD_CONFIG_DESC_LEN
MAX_TUSB_DESC_TOTAL_LEN = (TUD_CONFIG_DESC_LEN
#ifdef USB_ITF_HID
+ TUD_HID_INOUT_DESC_LEN
+ TUD_HID_DESC_LEN
+ TUD_HID_INOUT_DESC_LEN + TUD_HID_DESC_LEN
#endif
#ifdef USB_ITF_CCID
+ TUSB_SMARTCARD_CCID_DESC_LEN
+ TUSB_SMARTCARD_WCID_DESC_LEN
+ TUSB_SMARTCARD_CCID_DESC_LEN + TUSB_SMARTCARD_WCID_DESC_LEN
#endif
)
};
#ifdef USB_ITF_HID
@ -96,35 +102,49 @@ uint8_t const desc_hid_report[] = {
TUD_HID_REPORT_DESC_FIDO_U2F(CFG_TUD_HID_EP_BUFSIZE)
};
uint8_t const desc_hid_report_kb[] = {
TUD_HID_REPORT_DESC_KEYBOARD(HID_REPORT_ID(REPORT_ID_KEYBOARD))
TUD_HID_REPORT_DESC_KEYBOARD(HID_USAGE_PAGE(HID_USAGE_DESKTOP_KEYBOARD), HID_USAGE_MIN(0), HID_USAGE_MAX_N(255,2), HID_LOGICAL_MIN(0), HID_LOGICAL_MAX_N(255, 2), HID_REPORT_COUNT(8), HID_REPORT_SIZE(8), HID_FEATURE( HID_DATA | HID_VARIABLE | HID_ABSOLUTE),)
};
#define EPNUM_HID 0x04
#endif
enum {
EPNUM_DUMMY = 0,
#ifdef USB_ITF_CCID
EPNUM_CCID,
#if TUSB_SMARTCARD_CCID_EPS == 3
EPNUM_CCID_INT,
#endif
EPNUM_WCID,
#endif
#ifdef USB_ITF_HID
EPNUM_HID,
EPNUM_HID_KB,
#endif
EPNUM_TOTAL
};
#ifdef USB_ITF_CCID
#define TUD_SMARTCARD_DESCRIPTOR_WEB(_itf, _strix, _epout, _epin, _epsize) \
9, TUSB_DESC_INTERFACE, _itf, 0, 2, 0xFF, 0, 0, _strix, \
54, 0x21, U16_TO_U8S_LE(0x0110), 0, 0x1, U32_TO_U8S_LE(0x01|0x2), U32_TO_U8S_LE(0xDFC), U32_TO_U8S_LE(0xDFC), 0, U32_TO_U8S_LE(0x2580), U32_TO_U8S_LE(0x2580), 0, U32_TO_U8S_LE(0xFE), U32_TO_U8S_LE(0), U32_TO_U8S_LE(0), U32_TO_U8S_LE(0x40840), U32_TO_U8S_LE(65544+10), 0xFF, 0xFF, U16_TO_U8S_LE(0x0), 0, 0x1, \
TUSB_WSMARTCARD_LEN, 0x21, U16_TO_U8S_LE(0x0110), 0, 0x1, U32_TO_U8S_LE(0x01|0x2), U32_TO_U8S_LE(0xDFC), U32_TO_U8S_LE(0xDFC), 0, U32_TO_U8S_LE(0x2580), U32_TO_U8S_LE(0x2580), 0, U32_TO_U8S_LE(0xFE), U32_TO_U8S_LE(0), U32_TO_U8S_LE(0), U32_TO_U8S_LE(0x40840), U32_TO_U8S_LE(USB_BUFFER_SIZE), 0xFF, 0xFF, U16_TO_U8S_LE(0x0), 0, \
7, TUSB_DESC_ENDPOINT, _epout, TUSB_XFER_BULK, U16_TO_U8S_LE(_epsize), 0, \
7, TUSB_DESC_ENDPOINT, _epin, TUSB_XFER_BULK, U16_TO_U8S_LE(_epsize), 0
#define TUD_SMARTCARD_DESCRIPTOR(_itf, _strix, _epout, _epin, _epint, _epsize) \
9, TUSB_DESC_INTERFACE, _itf, 0, 3, TUSB_CLASS_SMART_CARD, 0, 0, _strix, \
54, 0x21, U16_TO_U8S_LE(0x0110), 0, 0x1, U32_TO_U8S_LE(0x01|0x2), U32_TO_U8S_LE(0xDFC), U32_TO_U8S_LE(0xDFC), 0, U32_TO_U8S_LE(0x2580), U32_TO_U8S_LE(0x2580), 0, U32_TO_U8S_LE(0xFE), U32_TO_U8S_LE(0), U32_TO_U8S_LE(0), U32_TO_U8S_LE(0x40840), U32_TO_U8S_LE(65544+10), 0xFF, 0xFF, U16_TO_U8S_LE(0x0), 0, 0x1, \
#define TUD_SMARTCARD_DESCRIPTOR_2EP(_itf, _strix, _epout, _epin, _epsize) \
9, TUSB_DESC_INTERFACE, _itf, 0, TUSB_SMARTCARD_CCID_EPS, TUSB_CLASS_SMART_CARD, 0, 0, _strix, \
TUSB_SMARTCARD_LEN, 0x21, U16_TO_U8S_LE(0x0110), 0, 0x1, U32_TO_U8S_LE(0x01|0x2), U32_TO_U8S_LE(0xDFC), U32_TO_U8S_LE(0xDFC), 0, U32_TO_U8S_LE(0x2580), U32_TO_U8S_LE(0x2580), 0, U32_TO_U8S_LE(0xFE), U32_TO_U8S_LE(0), U32_TO_U8S_LE(0), U32_TO_U8S_LE(0x40840), U32_TO_U8S_LE(USB_BUFFER_SIZE), 0xFF, 0xFF, U16_TO_U8S_LE(0x0), 0, 0x1, \
7, TUSB_DESC_ENDPOINT, _epout, TUSB_XFER_BULK, U16_TO_U8S_LE(_epsize), 0, \
7, TUSB_DESC_ENDPOINT, _epin, TUSB_XFER_BULK, U16_TO_U8S_LE(_epsize), 0, \
7, TUSB_DESC_ENDPOINT, _epint, TUSB_XFER_INTERRUPT, U16_TO_U8S_LE(_epsize), 0
7, TUSB_DESC_ENDPOINT, _epin, TUSB_XFER_BULK, U16_TO_U8S_LE(_epsize), 0
#if TUSB_SMARTCARD_CCID_EPS == 3
#define TUD_SMARTCARD_DESCRIPTOR(_itf, _strix, _epout, _epin, _epint, _epsize) \
TUD_SMARTCARD_DESCRIPTOR_2EP(_itf, _strix, _epout, _epin, _epsize), \
7, TUSB_DESC_ENDPOINT, _epint, TUSB_XFER_INTERRUPT, U16_TO_U8S_LE(_epsize), 10
#else
#define TUD_SMARTCARD_DESCRIPTOR(_itf, _strix, _epout, _epin, _epint, _epsize) \
TUD_SMARTCARD_DESCRIPTOR_2EP(_itf, _strix, _epout, _epin, _epsize)
#endif
#endif
const uint8_t desc_config[] = {
TUD_CONFIG_DESCRIPTOR(1, ITF_TOTAL, 4, TUSB_DESC_TOTAL_LEN, USB_CONFIG_ATT_ONE | TUSB_DESC_CONFIG_ATT_REMOTE_WAKEUP, MAX_USB_POWER),
#ifdef USB_ITF_HID
TUD_HID_INOUT_DESCRIPTOR(ITF_HID, ITF_HID + 5, HID_ITF_PROTOCOL_NONE, sizeof(desc_hid_report), EPNUM_HID, TUSB_DIR_IN_MASK | EPNUM_HID, CFG_TUD_HID_EP_BUFSIZE, 10),
TUD_HID_DESCRIPTOR(ITF_KEYBOARD, ITF_KEYBOARD + 5, HID_ITF_PROTOCOL_NONE, sizeof(desc_hid_report_kb), TUSB_DIR_IN_MASK | (EPNUM_HID + 1), 16, 5),
#endif
#ifdef USB_ITF_CCID
TUD_SMARTCARD_DESCRIPTOR(ITF_CCID, ITF_CCID+5, 1, TUSB_DIR_IN_MASK | 1, TUSB_DIR_IN_MASK | 2, 64),
TUD_SMARTCARD_DESCRIPTOR_WEB(ITF_WCID, ITF_WCID+5, 3, TUSB_DIR_IN_MASK | 3, 64),
#endif
uint8_t desc_config[MAX_TUSB_DESC_TOTAL_LEN] = {
TUD_CONFIG_DESCRIPTOR(1, 0, 4, 0, USB_CONFIG_ATT_ONE | TUSB_DESC_CONFIG_ATT_REMOTE_WAKEUP, MAX_USB_POWER)
};
#ifdef USB_ITF_HID
@ -139,13 +159,53 @@ uint8_t const *tud_hid_descriptor_report_cb(uint8_t itf) {
return NULL;
}
#endif
void usb_desc_setup() {
desc_config[4] = ITF_TOTAL;
TUSB_DESC_TOTAL_LEN = TUD_CONFIG_DESC_LEN;
uint8_t *p = desc_config + TUD_CONFIG_DESC_LEN;
#ifdef USB_ITF_HID
if (ITF_HID != ITF_INVALID) {
TUSB_DESC_TOTAL_LEN += TUD_HID_INOUT_DESC_LEN;
const uint8_t desc[] = { TUD_HID_INOUT_DESCRIPTOR(ITF_HID, ITF_HID + 5, HID_ITF_PROTOCOL_NONE, sizeof(desc_hid_report), EPNUM_HID, (uint8_t)TUSB_DIR_IN_MASK | EPNUM_HID, CFG_TUD_HID_EP_BUFSIZE, 10) };
memcpy(p, desc, sizeof(desc));
p += sizeof(desc);
}
if (ITF_KEYBOARD != ITF_INVALID) {
TUSB_DESC_TOTAL_LEN += TUD_HID_DESC_LEN;
const uint8_t desc_kb[] = { TUD_HID_DESCRIPTOR(ITF_KEYBOARD, ITF_KEYBOARD + 5, HID_ITF_PROTOCOL_NONE, sizeof(desc_hid_report_kb), (uint8_t)TUSB_DIR_IN_MASK | EPNUM_HID_KB, 16, 5) };
memcpy(p, desc_kb, sizeof(desc_kb));
p += sizeof(desc_kb);
}
#endif
#ifdef USB_ITF_CCID
if (ITF_CCID != ITF_INVALID) {
TUSB_DESC_TOTAL_LEN += TUSB_SMARTCARD_CCID_DESC_LEN;
const uint8_t desc_ccid[] = { TUD_SMARTCARD_DESCRIPTOR(ITF_CCID, ITF_CCID + 5, EPNUM_CCID, TUSB_DIR_IN_MASK | EPNUM_CCID, TUSB_DIR_IN_MASK | EPNUM_CCID_INT, 64) };
memcpy(p, desc_ccid, sizeof(desc_ccid));
p += sizeof(desc_ccid);
}
if (ITF_WCID != ITF_INVALID) {
TUSB_DESC_TOTAL_LEN += TUSB_SMARTCARD_WCID_DESC_LEN;
const uint8_t desc_wcid[] = { TUD_SMARTCARD_DESCRIPTOR_WEB(ITF_WCID, ITF_WCID + 5, EPNUM_WCID, TUSB_DIR_IN_MASK | EPNUM_WCID, 64) };
memcpy(p, desc_wcid, sizeof(desc_wcid));
p += sizeof(desc_wcid);
}
#endif
desc_config[2] = TUSB_DESC_TOTAL_LEN & 0xFF;
desc_config[3] = TUSB_DESC_TOTAL_LEN >> 8;
}
#ifndef ESP_PLATFORM
uint8_t const *tud_descriptor_configuration_cb(uint8_t index) {
(void) index; // for multiple configurations
usb_desc_setup();
return desc_config;
}
#endif
#ifdef USB_ITF_WCID
#define BOS_TOTAL_LEN (TUD_BOS_DESC_LEN + TUD_BOS_WEBUSB_DESC_LEN + TUD_BOS_MICROSOFT_OS_DESC_LEN)
#define MS_OS_20_DESC_LEN 0xB2
@ -167,7 +227,7 @@ const tusb_desc_webusb_url_t desc_url =
#define BOS_TOTAL_LEN (TUD_BOS_DESC_LEN + TUD_BOS_WEBUSB_DESC_LEN + TUD_BOS_MICROSOFT_OS_DESC_LEN)
#define MS_OS_20_DESC_LEN 0xB2
uint8_t const desc_ms_os_20[] = {
uint8_t desc_ms_os_20[] = {
// Set header: length, type, windows version, total length
U16_TO_U8S_LE(0x000A), U16_TO_U8S_LE(MS_OS_20_SET_HEADER_DESCRIPTOR), U32_TO_U8S_LE(0x06030000), U16_TO_U8S_LE(MS_OS_20_DESC_LEN),
@ -175,7 +235,7 @@ uint8_t const desc_ms_os_20[] = {
U16_TO_U8S_LE(0x0008), U16_TO_U8S_LE(MS_OS_20_SUBSET_HEADER_CONFIGURATION), 0, 0, U16_TO_U8S_LE(MS_OS_20_DESC_LEN-0x0A),
// Function Subset header: length, type, first interface, reserved, subset length
U16_TO_U8S_LE(0x0008), U16_TO_U8S_LE(MS_OS_20_SUBSET_HEADER_FUNCTION), ITF_WCID, 0, U16_TO_U8S_LE(MS_OS_20_DESC_LEN-0x0A-0x08),
U16_TO_U8S_LE(0x0008), U16_TO_U8S_LE(MS_OS_20_SUBSET_HEADER_FUNCTION), 0/*ITF_WCID*/, 0, U16_TO_U8S_LE(MS_OS_20_DESC_LEN-0x0A-0x08),
// MS OS 2.0 Compatible ID descriptor: length, type, compatible ID, sub compatible ID
U16_TO_U8S_LE(0x0014), U16_TO_U8S_LE(MS_OS_20_FEATURE_COMPATBLE_ID), 'W', 'I', 'N', 'U', 'S', 'B', 0x00, 0x00,
@ -208,6 +268,7 @@ bool tud_vendor_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb_control_requ
if (request->wIndex == 7) {
// Get Microsoft OS 2.0 compatible descriptor
uint16_t total_len;
desc_ms_os_20[22] = ITF_WCID;
memcpy(&total_len, desc_ms_os_20+8, 2);
return tud_control_xfer(rhport, request, (void*)(uintptr_t) desc_ms_os_20, total_len);
}
@ -248,6 +309,8 @@ uint8_t const *tud_descriptor_bos_cb(void) {
return desc_bos;
}
#endif
//--------------------------------------------------------------------+
// String Descriptors
//--------------------------------------------------------------------+
@ -258,14 +321,14 @@ char const *string_desc_arr [] = {
"Pol Henarejos", // 1: Manufacturer
"Pico Key", // 2: Product
"11223344", // 3: Serials, should use chip ID
"Pico Key Config" // 4: Vendor Interface
"Config" // 4: Vendor Interface
#ifdef USB_ITF_HID
, "Pico Key HID Interface"
, "Pico Key HID Keyboard Interface"
, "HID Interface"
, "HID Keyboard Interface"
#endif
#ifdef USB_ITF_CCID
, "Pico Key CCID Interface"
, "Pico Key WebCCID Interface"
, "CCID OTP FIDO Interface"
, "WebCCID Interface"
#endif
};
@ -273,7 +336,7 @@ char const *string_desc_arr [] = {
tinyusb_config_t tusb_cfg = {
.device_descriptor = &desc_device,
.string_descriptor = string_desc_arr,
.string_descriptor_count = sizeof(string_desc_arr) / sizeof(string_desc_arr[0]),
.string_descriptor_count = (sizeof(string_desc_arr) / sizeof(string_desc_arr[0])) > 8 ? 8 : (sizeof(string_desc_arr) / sizeof(string_desc_arr[0])),
.external_phy = false,
.configuration_descriptor = desc_config,
};
@ -283,7 +346,7 @@ static uint16_t _desc_str[32];
uint16_t const *tud_descriptor_string_cb(uint8_t index, uint16_t langid) {
(void) langid;
uint8_t chr_count;
uint8_t chr_count = 0;
if (index == 0) {
memcpy(&_desc_str[1], string_desc_arr[0], 2);
@ -301,15 +364,27 @@ uint16_t const *tud_descriptor_string_cb(uint8_t index, uint16_t langid) {
if (index == 3) {
str = pico_serial_str;
}
chr_count = strlen(str);
if (chr_count > 31) {
chr_count = 31;
else if (index == 2) {
if (phy_data.usb_product_present) {
str = phy_data.usb_product;
}
}
// Convert ASCII string into UTF-16
for (uint8_t i = 0; i < chr_count; i++) {
_desc_str[1 + i] = str[i];
uint8_t buff_avail = sizeof(_desc_str) / sizeof(_desc_str[0]) - 1;
if (index >= 4) {
const char *product = phy_data.usb_product_present ? phy_data.usb_product : string_desc_arr[2];
uint8_t len = (uint8_t)MIN(strlen(product), buff_avail);
for (size_t ix = 0; ix < len; chr_count++, ix++) {
_desc_str[1 + chr_count] = product[ix];
}
buff_avail -= len;
if (buff_avail > 0) {
_desc_str[1 + chr_count++] = ' ';
buff_avail--;
}
}
for (size_t ix = 0; ix < MIN(strlen(str), buff_avail); chr_count++, ix++) {
_desc_str[1 + chr_count] = str[ix];
}
}

View file

@ -3,16 +3,16 @@
* Copyright (c) 2022 Pol Henarejos.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, version 3.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
* Affero General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
#ifndef USB_DESCRIPTORS_H_

23
src/version.c Normal file
View file

@ -0,0 +1,23 @@
/*
* This file is part of the Pico Keys SDK distribution (https://github.com/polhenarejos/pico-keys-sdk).
* Copyright (c) 2022 Pol Henarejos.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, version 3.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
#include "pico_keys.h"
#include "pico_keys_version.h"
const uint8_t PICO_PRODUCT = 0;
const uint8_t PICO_VERSION_MAJOR = PICO_KEYS_SDK_VERSION_MAJOR;
const uint8_t PICO_VERSION_MINOR = PICO_KEYS_SDK_VERSION_MINOR;

@ -1 +1 @@
Subproject commit e27261ed5e2ed059d160f16ae776951a08a861fc
Subproject commit c0aad2fb2137a31b9845fbaae3653540c410f215