Compare commits
154 commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
4df616082e | ||
|
|
3bf035d68a | ||
|
|
7dc7be0909 | ||
|
|
015fb61759 | ||
|
|
1f4d638119 | ||
|
|
05fe0596ef | ||
|
|
d86371bb2c | ||
|
|
8cb2484aa3 | ||
|
|
7583ecff18 | ||
|
|
09ec0767b6 | ||
|
|
d0dea3d0c5 | ||
|
|
53d3a7ac91 | ||
|
|
2438356d83 | ||
|
|
79b69bfd7e | ||
|
|
d189c2978c | ||
|
|
c1cc33fd9d | ||
|
|
2d72a157d5 | ||
|
|
711a4df490 | ||
|
|
66f31c15b6 | ||
|
|
fa119d0c6e | ||
|
|
b67e9ac143 | ||
|
|
5d3d10b62b | ||
|
|
27938f0d9b | ||
|
|
20117d1609 | ||
|
|
8f4f5373cf | ||
|
|
d4971bba19 | ||
|
|
2001006a16 | ||
|
|
7c5f729b69 | ||
|
|
07bbadf34c | ||
|
|
ed848d005f | ||
|
|
e6c0227996 | ||
|
|
84f7952817 | ||
|
|
116aca7697 | ||
|
|
d410a4cfc2 | ||
|
|
9b6d6f6736 | ||
|
|
8f907b25ba | ||
|
|
233e6594c6 | ||
|
|
eca6807f8e | ||
|
|
14d5a75571 | ||
|
|
e56624948b | ||
|
|
200d59f91b | ||
|
|
c165ae4838 | ||
|
|
0ddfdf8134 | ||
|
|
031d76737b | ||
|
|
df94d10f8f | ||
|
|
b3b2b67034 | ||
|
|
3eff2442c6 | ||
|
|
a7e1cf028b | ||
|
|
e14a12b002 | ||
|
|
d39732c613 | ||
|
|
56c2ef0cc1 | ||
|
|
9b294b9685 | ||
|
|
5048e07f81 | ||
|
|
d63ed56e0e | ||
|
|
afe2b28fab | ||
|
|
838f342877 | ||
|
|
1a1d03ab2f | ||
|
|
809dc3d16d | ||
|
|
70c0c1bf81 | ||
|
|
cff3f8f677 | ||
|
|
6f6004c57b | ||
|
|
0b49fe4e1b | ||
|
|
4edc506759 | ||
|
|
e55014cfb3 | ||
|
|
2211fafe32 | ||
|
|
276f1b2ae8 | ||
|
|
202d32d13d | ||
|
|
95f02b6ea7 | ||
|
|
2e2b78445c | ||
|
|
da44fd21d4 | ||
|
|
365567d12b | ||
|
|
a3406572cd | ||
|
|
8321db1f67 | ||
|
|
5984d1f72d | ||
|
|
685e660ec0 | ||
|
|
3863842536 | ||
|
|
113e720fca | ||
|
|
c45c97ee1f | ||
|
|
d66d1c85b9 | ||
|
|
f01aca5518 | ||
|
|
da3a7f25d0 | ||
|
|
eb75ad4efa | ||
|
|
11d8a5343c | ||
|
|
a324477a8a | ||
|
|
580b0acffa | ||
|
|
3990e7643a | ||
|
|
5718c83083 | ||
|
|
a75fd6b815 | ||
|
|
499e8fafaa | ||
|
|
5f79a8c8ed | ||
|
|
a08abaed0f | ||
|
|
4ef641b8d3 | ||
|
|
c185b35ca3 | ||
|
|
f1b1382300 | ||
|
|
f18f761234 | ||
|
|
1a4ca13cc7 | ||
|
|
ef9b66f990 | ||
|
|
7191cda6d3 | ||
|
|
2c3fe5bebf | ||
|
|
9e9632f297 | ||
|
|
259c4854df | ||
|
|
0a4c7b0981 | ||
|
|
db338842b9 | ||
|
|
71af710568 | ||
|
|
e18f192edf | ||
|
|
07415e6e8b | ||
|
|
a9eff9fb17 | ||
|
|
6e6b524878 | ||
|
|
bfa085cae9 | ||
|
|
94a842fa04 | ||
|
|
90fb86be64 | ||
|
|
f06cb3a96d | ||
|
|
5985548c97 | ||
|
|
3f5cbf6542 | ||
|
|
29c0d078c3 | ||
|
|
1723613b4e | ||
|
|
44ca760e1c | ||
|
|
4992d8e273 | ||
|
|
80fa13a19c | ||
|
|
b4c67d2fa5 | ||
|
|
18eb3e6ef2 | ||
|
|
350f0da763 | ||
|
|
a081a2bde6 | ||
|
|
3d912878f1 | ||
|
|
68a816895e | ||
|
|
1d89c14268 | ||
|
|
5508c082e5 | ||
|
|
0bed03e522 | ||
|
|
9e2b6ac4b6 | ||
|
|
046bac42e3 | ||
|
|
c59fb91540 | ||
|
|
f8cb36c2cf | ||
|
|
d78e977926 | ||
|
|
8e68e6cae9 | ||
|
|
d530ea6979 | ||
|
|
f509833a3c | ||
|
|
4f5f2a8854 | ||
|
|
ffaf20da5d | ||
|
|
e627b3fc86 | ||
|
|
585a6d77e3 | ||
|
|
7805131d92 | ||
|
|
86999d8cdd | ||
|
|
6859cedcbf | ||
|
|
1431f91281 | ||
|
|
f58bcaecf1 | ||
|
|
cb4e2ba0eb | ||
|
|
e9875b358c | ||
|
|
fcae98eecc | ||
|
|
a61f7683b6 | ||
|
|
a271785814 | ||
|
|
49758c6ac7 | ||
|
|
9f79693025 | ||
|
|
812f075ee4 | ||
|
|
6a18e3aa83 |
64 changed files with 2619 additions and 1077 deletions
118
CMakeLists.txt
118
CMakeLists.txt
|
|
@ -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
143
LICENSE
|
|
@ -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/>.
|
||||
|
|
@ -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)
|
||||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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"
|
||||
|
|
|
|||
|
|
@ -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_
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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()
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
52
src/apdu.c
52
src/apdu.c
|
|
@ -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;
|
||||
|
|
|
|||
16
src/apdu.h
16
src/apdu.h
|
|
@ -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
|
||||
|
|
|
|||
11
src/asn1.c
11
src/asn1.c
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
10
src/asn1.h
10
src/asn1.h
|
|
@ -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
35
src/board.h
Normal 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_
|
||||
27
src/compat.h
27
src/compat.h
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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]);
|
||||
|
|
|
|||
26
src/debug.h
26
src/debug.h
|
|
@ -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); \
|
||||
|
|
|
|||
23
src/eac.c
23
src/eac.c
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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_
|
||||
|
|
|
|||
|
|
@ -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) {
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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
28
src/fs/files.c
Normal 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];
|
||||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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>
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
177
src/fs/otp.c
177
src/fs/otp.c
|
|
@ -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
|
||||
}
|
||||
|
|
|
|||
25
src/fs/otp.h
25
src/fs/otp.h
|
|
@ -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_
|
||||
|
|
|
|||
152
src/fs/phy.c
152
src/fs/phy.c
|
|
@ -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
|
||||
|
|
|
|||
68
src/fs/phy.h
68
src/fs/phy.h
|
|
@ -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
|
||||
|
||||
|
|
|
|||
|
|
@ -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"
|
||||
|
|
|
|||
147
src/led/led.c
147
src/led/led.c
|
|
@ -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
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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_
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
86
src/main.c
86
src/main.c
|
|
@ -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
|
||||
|
|
|
|||
103
src/pico_keys.h
103
src/pico_keys.h
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
113
src/pthread_win32.h
Normal 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
132
src/queue.h
Normal 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
|
||||
182
src/rescue.c
182
src/rescue.c
|
|
@ -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 }
|
||||
};
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
||||
|
|
|
|||
|
|
@ -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/>.
|
||||
*/
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -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
47
src/semaphore_win32.h
Normal 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
|
||||
|
|
@ -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);
|
||||
|
||||
|
|
|
|||
|
|
@ -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_
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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_
|
||||
|
|
|
|||
|
|
@ -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
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
111
src/usb/usb.c
111
src/usb/usb.c
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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 {
|
||||
|
|
|
|||
|
|
@ -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];
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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
23
src/version.c
Normal 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;
|
||||
2
tinycbor
2
tinycbor
|
|
@ -1 +1 @@
|
|||
Subproject commit e27261ed5e2ed059d160f16ae776951a08a861fc
|
||||
Subproject commit c0aad2fb2137a31b9845fbaae3653540c410f215
|
||||
Loading…
Add table
Reference in a new issue