Compare commits

..

879 Commits

Author SHA1 Message Date
f4b729ee14 docs: update .all-contributorsrc 2019-11-07 13:28:36 +00:00
74a782c3f4 docs: update README.md 2019-11-07 13:28:35 +00:00
975cdf02f2 bump 3.0.0 2019-10-28 13:19:11 -04:00
21f3a0d10f remove hacker constraint for booting into bootloader 2019-10-28 12:55:38 -04:00
b535b41d92 docs: update .all-contributorsrc 2019-10-28 11:09:54 -04:00
fd32cc0761 docs: update README.md 2019-10-28 11:09:54 -04:00
78dd2a10d3 remove binary count check 2019-10-28 10:51:35 -04:00
fa1bb0dce5 update docs 2019-10-28 10:51:35 -04:00
169dfd2f0d check attestation tag 2019-10-28 10:51:35 -04:00
dafd974d93 do not lock flash when booting to dfu 2019-10-28 10:51:35 -04:00
712fde6858 add git 2019-10-28 10:51:35 -04:00
fcc2e86a6d remove hacker/secure builds 2019-10-28 10:51:35 -04:00
8b146c4a16 fix issue with bootloader not replying data 2019-10-28 10:51:35 -04:00
a1a79b05fd fix solo locked flag for bootloader 2019-10-27 10:25:00 -04:00
c0df8b680d fix build 2019-10-27 10:25:00 -04:00
9ac2aa90c3 store all info in same page, dont use authenticator state 2019-10-27 10:25:00 -04:00
d33749fc16 add locked variable to GETVERSION hid command 2019-10-27 10:25:00 -04:00
96a2cbcb41 remove logs 2019-10-27 10:25:00 -04:00
7212982385 remove hacker macros 2019-10-27 10:25:00 -04:00
89e218e561 lock flash based on state setting 2019-10-27 10:25:00 -04:00
666cd6a0ba migrate certs 2019-10-27 10:25:00 -04:00
b4f59ec355 pull certificate from flash page 2019-10-27 10:25:00 -04:00
b7d74cc99f Add default git describe in makefile 2019-10-27 10:11:39 -04:00
375a607356 Add test for docker in travis 2019-10-27 10:11:39 -04:00
ea8409c072 Fixing Travis 2019-10-27 10:11:39 -04:00
04f06b3b0d Updating README: adding more details on how to compile the solo firmware (especially Docker) 2019-10-27 10:11:39 -04:00
a57c5170e1 Add .sha2 to .gitignore 2019-10-27 10:11:39 -04:00
aaffce4021 Make dependency on git optinal in the target/stm32l432/Makefile
"git describe" is used to get the version of the firmware from GIT tags ans it is used for build artifacts' names
We would prefer not to have this depency inside Docker
2019-10-27 10:11:39 -04:00
463a8b444d Splitting toolchain creation from firmware compilation 2019-10-27 10:11:39 -04:00
44ed3ceea5 Optimize Dockerfile 2019-10-27 10:11:39 -04:00
30f73b41e4 Move python install in the docker file 2019-10-27 10:11:39 -04:00
6f6e831fba Upgrade to the latest ARM compiler 2019-10-27 10:11:39 -04:00
9fd608d3ee Use local copy of the files 2019-10-27 10:11:39 -04:00
765dc27b15 Fix docker build 2019-10-27 10:10:27 -04:00
48147a39df Remove Somu campaign from readme 2019-10-24 12:53:03 +02:00
6c48d75e44 Merge pull request #324 from jolo1581/document_application_ideas
Document application ideas
2019-10-23 13:01:49 +02:00
fca1e9d405 Added new document for Application Ideas.
Added manual how to setup Linux to use Solo for passwordless login or as
second factor by pressing button after password login. Added chapter
"Application Ideas" below chapter "Solo Extras" in official
documentation.
2019-10-18 11:44:03 +02:00
0fbc28fbc1 fix pc build 2019-10-08 16:10:29 -04:00
2a02d0de33 small errors 2019-10-08 16:10:29 -04:00
00b09e0d40 add u2f length arg 2019-10-08 16:10:29 -04:00
26db2b3f6b check FIDO2 credential IDs in U2F 2019-10-08 16:10:29 -04:00
ff88660027 fix const qualifer warnings 2019-10-08 14:43:24 -04:00
9ecfda02c5 remove atomic counter from bootloader to save space 2019-10-08 14:43:24 -04:00
9158453830 Merge pull request #238 from Nitrokey/bootloader-downgrade-protection
Bootloader downgrade protection
2019-10-08 13:53:57 -04:00
08658eb11e Merge branch 'master' into bootloader-downgrade-protection 2019-10-08 13:44:20 -04:00
49d79fa5da reduce lines/size 2019-10-08 13:42:37 -04:00
69a7191860 fix warnings 2019-10-08 13:42:37 -04:00
a2fd507f45 typo 2019-10-08 13:42:37 -04:00
a58658e35d fix pointer 2019-10-08 13:42:37 -04:00
bb2929b28f change ctap_atomic_count to increase by user-specified amount 2019-10-08 13:42:37 -04:00
8e0eda8ed4 refactor custom commands and add LOADKEY 2019-10-08 13:42:37 -04:00
0ebe0ff502 add ctap function to overwrite key bytes 2019-10-08 13:42:37 -04:00
7bcb7ea840 docs: update .all-contributorsrc 2019-10-08 13:42:23 -04:00
811a57f7ab docs: update README.md 2019-10-08 13:42:23 -04:00
5168afa16e Code cosmetics, added missing void statement to empty parameter of
functions
2019-10-08 12:31:08 -04:00
208d26be89 Merge pull request #315 from My1/patch-1
clone using https instead
2019-09-26 23:01:42 +02:00
My1
45293fe998 clone using https instead
not everyone has a github account, wants one or wants to setup ssh keys.
2019-09-26 16:11:40 +02:00
a1a42fec5c Bump stable version to 2.5.3 2019-09-17 17:22:15 +08:00
8c256298ae default up to enabled 2019-09-17 00:13:57 +08:00
01b928c0ec allow in bootloader as well 2019-09-17 00:13:57 +08:00
018a4d394c add get_version command to hid 2019-09-17 00:13:57 +08:00
7a75fba6d3 delete old code 2019-09-17 00:13:57 +08:00
c61f15a090 allow get_assertion with disabled UP 2019-09-17 00:13:57 +08:00
f072561899 properly check the rpId in request 2019-09-17 00:13:57 +08:00
6652feb4a2 added CID transfer and NAK-ACK sequence 2019-09-05 23:26:15 +08:00
fc7ea68d4a Bump STABLE_VERSION to 2.5.2 2019-09-05 00:30:59 +02:00
cb116efcc9 Merge pull request #303 from StoyanDimitrov/patch-3
Typo
2019-09-03 00:48:23 +02:00
80b9df3e04 Merge pull request #302 from StoyanDimitrov/patch-2
Highlight command and few file names
2019-09-03 00:48:08 +02:00
194ef5edcf Merge pull request #304 from StoyanDimitrov/patch-4
Fix broken formating
2019-09-03 00:47:21 +02:00
006117bb6b Fix broken formating 2019-09-02 20:56:55 +00:00
75c75fa897 Hilight file name 2019-09-02 20:41:42 +00:00
2969d09ffa Typo 2019-09-02 20:36:02 +00:00
b871e10d08 Highlight command and few file names 2019-09-02 20:34:20 +00:00
18d39a7047 Merge pull request #240 from Nitrokey/remove-pin-storage
Replace FIDO2 PIN storage with its hash
2019-09-02 21:50:44 +08:00
a9bbdee35b Merge branch 'master' into remove-pin-storage 2019-09-02 21:45:21 +08:00
321bbe3691 Merge pull request #293 from solokeys/ccid
Ccid
2019-09-02 21:42:38 +08:00
1ce191343f add checking some rare case in iso14443-4 chaining. add NAK checking and aborting the data sending. 2019-08-31 02:12:05 +08:00
9041e5903c return SW_WRONG_LENGTH for incorrect lc 2019-08-30 16:37:17 +08:00
689d471688 docs: update .all-contributorsrc 2019-08-30 01:46:40 +02:00
8b9e44c3ed docs: update README.md 2019-08-30 01:46:40 +02:00
83dd92d9ba Update STABLE_VERSION 2019-08-29 22:05:10 +08:00
a5e1dc2a0c Correct linker documentation 2019-08-24 11:27:28 +02:00
a053bbc669 Do not verify version for the hacker edition 2019-08-24 10:26:44 +02:00
3621f2ed4f Add missed doc update in the linker script 2019-08-24 10:26:41 +02:00
3c7bf5a264 Remove obsolete debug messages 2019-08-24 10:26:38 +02:00
8bf1921263 dont reference not-enabled ccid 2019-08-24 16:20:52 +08:00
e3ff136196 Remove obsolete region for the app static firmware version address 2019-08-24 10:17:59 +02:00
74181406fe Rename last_addr->last_written_app_address 2019-08-24 10:17:55 +02:00
987b04523d Correct memory layout 2019-08-24 10:17:52 +02:00
8023347c8e Makefile: add debug info 2019-08-24 10:17:49 +02:00
9dae7b2e7c Makefile: fix flashboot recipe 2019-08-24 10:17:46 +02:00
cb13fb65de Store version in the bootloader. Debug code. 2019-08-24 10:17:43 +02:00
7fddd58704 Bootloader: get uploaded application version from the 4 last bytes of its firmware 2019-08-24 10:17:40 +02:00
3a1ea275cc Move _extra* debug linker scripts content to main 2019-08-24 10:17:37 +02:00
22293f82f2 Rename flash2 -> flash_cfg 2019-08-24 10:17:34 +02:00
40c3c13b07 Correct flash2 region. Rename _bconfig_start->bootloader_configuration. 2019-08-24 10:17:30 +02:00
7042b0b656 Move app version to the end of the firmware code, without specific address. Move bootloader config 8B forward. 2019-08-24 10:17:27 +02:00
ea803aab95 Make the flash memory structure depend on the APPLICATION_START_PAGE macro 2019-08-24 10:17:24 +02:00
1100b159a9 Refactor. Add debug code. Use %u for unsigned. Use volatile pointer instead of memory storage. 2019-08-24 10:17:21 +02:00
9ddba5dfc3 Add extra linker script changes 2019-08-24 10:17:18 +02:00
35e52f4968 Initial modification to move bootloader data after the application 2019-08-24 10:17:15 +02:00
efddd2f3a8 Use the same public bootloader key as before 2019-08-24 10:17:12 +02:00
17ceb7b9e8 Make the public key generic 2019-08-24 10:17:09 +02:00
188a34d1da Add missing Makefile entry. Rename pubkey file. 2019-08-24 10:17:05 +02:00
9248c6462c Add missing is_newer and pubkey 2019-08-24 10:17:02 +02:00
118e129152 Set firmware version in the flash 2019-08-24 10:16:59 +02:00
beb5a5892c Add linker scripts 2019-08-24 10:16:56 +02:00
d618081dd0 Add version code 2019-08-24 10:16:53 +02:00
e4e0a3a84e Add code responsible for firmware version verification in the bootloader 2019-08-24 10:16:50 +02:00
3ba9b671fc dont use composit for bootloader 2019-08-24 16:01:44 +08:00
69c34f9ca9 Merge branch 'master' into ccid 2019-08-24 15:54:51 +08:00
3b4c154fd1 add enable macro for CCID interface 2019-08-24 15:49:02 +08:00
ccd9a04146 add ccid log tag 2019-08-24 15:08:14 +08:00
bde4c09c21 CCID basics working 2019-08-24 15:06:16 +08:00
5d3914bc5e remove delays 2019-08-23 22:25:22 +08:00
abe306a649 Merge branch 'master' of github.com:solokeys/solo 2019-08-23 14:53:22 +08:00
41ceb78f6c add user presence to flags 2019-08-23 14:48:21 +08:00
8e192f2363 do not delay bootloader 2019-08-23 14:41:26 +08:00
affc256ca2 add delay to cap button improve reliability 2019-08-23 14:41:26 +08:00
b3ac739a35 make touch sensor edge based to avoid approving >1 transaction 2019-08-23 13:44:06 +08:00
3b53537077 refactor fido2 user presence handling & increase timeout to 29s 2019-08-23 13:19:28 +08:00
3fad9a7a7d add response to reset command and delete debug 2019-08-23 10:43:09 +08:00
8973608f59 docs: update .all-contributorsrc 2019-08-22 22:42:17 +02:00
8af6505f6d docs: update README.md 2019-08-22 22:42:17 +02:00
d39d7978fd small fix 2019-08-22 21:04:01 +08:00
c972a13034 fix reboot 2019-08-22 20:55:25 +08:00
a95e62e2ea reset 2019-08-22 20:55:25 +08:00
c79b7abfb6 add reset placeholder 2019-08-22 20:55:25 +08:00
dfb124dc8b refactoring 2019-08-22 20:55:12 +08:00
972760eb78 added APDU input chaining 2019-08-22 20:55:12 +08:00
0d621d13f9 fix decoding apdu 2019-08-22 20:55:12 +08:00
32f920e372 compile/crash fixes 2019-08-22 19:52:21 +08:00
a5aff478dd Merge branch 'master' into ccid 2019-08-22 17:13:55 +08:00
728acc1671 chaining not needs to go to the start 2019-08-21 12:13:16 +08:00
62b4418dac fix pck length math 2019-08-21 12:13:16 +08:00
8059a9765f was wrong buffer 2019-08-21 12:13:16 +08:00
b743d5fac5 sketch 2019-08-21 12:13:16 +08:00
dccfb0d1b3 stub pc build 2019-08-21 12:06:06 +08:00
a72f0ede05 take a lazy approach to key agreement generation to not hold up boot time for nfc 2019-08-21 12:06:06 +08:00
adcbd3aeb8 speed up public key derivation slightly for nfc 2019-08-21 12:06:06 +08:00
d931954a13 remove WTX, move debug log 2019-08-21 12:06:06 +08:00
b706cc30b0 for now, always gen key agreement 2019-08-21 12:06:06 +08:00
57fe39704b Merge pull request #282 from solokeys/update-udev-docs
Update udev docs
2019-08-21 02:48:33 +02:00
4b6619b705 Update udev docs 2019-08-21 02:37:15 +02:00
a5877f518f Additional assertions and reordering 2019-08-20 12:42:46 +02:00
5a0cc0d02c Version used STATE data structures 2019-08-20 11:57:32 +02:00
b452e3dfe4 Correct doc 2019-08-20 11:47:14 +02:00
7f82233d17 Add missing unit for firmware compilation 2019-08-20 11:38:29 +02:00
8e3753e711 Add initial STATE migration code (2) 2019-08-20 11:34:51 +02:00
816ca21f08 Correct writing salted hash
pinHashEnc is 16 bytes, which is too small to store sha256 result.
2019-08-20 11:34:48 +02:00
6c60a37e8a Add initial STATE migration code 2019-08-20 11:34:45 +02:00
ee351421cb Add missing definition for the simulation to run 2019-08-20 11:34:42 +02:00
bac576f3a0 Make the state structure backward-compatible. Add version. 2019-08-20 11:34:39 +02:00
6e637299e5 Add missing declaration, and comment out wallet message 2019-08-20 11:34:35 +02:00
43b3e93854 Modify state struct 2019-08-20 11:34:32 +02:00
5a448d636c Add comments 2019-08-20 11:34:29 +02:00
7be0553377 Replace FIDO2 PIN storage with its hash 2019-08-20 11:34:26 +02:00
095b08e3d9 add some stability in small responses 2019-08-19 22:33:32 +08:00
89e021003a small fix for HID readers 2019-08-19 22:33:32 +08:00
4f3d4b09eb Update README.md 2019-08-16 17:22:46 -04:00
3f4843b03a Merge pull request #270 from solokeys/bump_2.4.3
Update STABLE_VERSION
2019-08-16 21:07:59 +02:00
26af0c423e Update solo-extras.md 2019-08-16 14:04:43 +08:00
19422d9daa add info for rng use 2019-08-16 14:04:43 +08:00
b7a4cf001a run through fixes 2019-08-16 14:04:43 +08:00
3927aec06d dont remove solo.hex bootloader.hex 2019-08-16 14:04:43 +08:00
f5794481ae initial draft 2019-08-16 14:04:43 +08:00
caac9d0cc1 add secure build that uses default attestation key 2019-08-16 14:04:43 +08:00
ffadab05a3 Update STABLE_VERSION 2019-08-15 19:35:54 +08:00
2423154fee fix warning 2019-08-15 18:07:40 +08:00
cf79b7865d small fix 2019-08-15 17:50:16 +08:00
6f0cf99c92 PPS implementation 2019-08-15 17:50:16 +08:00
7ef68fd5d3 Merge pull request #265 from solokeys/fix_cdc_interfaces
Fix cdc interfaces
2019-08-15 17:49:53 +08:00
3be8611fcf remove duplicate from merge 2019-08-15 17:44:09 +08:00
21489658a7 Merge branch 'master' into fix_cdc_interfaces 2019-08-15 17:38:57 +08:00
a07a3dee8d refactor user_presence handling 2019-08-15 17:36:35 +08:00
416da63a9a not for bootloader 2019-08-15 17:36:35 +08:00
027fa791a3 only 1 user presence auth per button press 2019-08-15 17:36:35 +08:00
3e52d7b42b cache button press for 2s 2019-08-15 17:36:35 +08:00
301e18c6a2 add some int0 logic to main cycle 2019-08-14 14:32:03 +08:00
44205141eb add one place for int0 2019-08-14 14:32:03 +08:00
6e1110ca9b fix bug with ams_wait_for_tx 2019-08-14 14:32:03 +08:00
9105b988e2 fix some warnings 2019-08-14 14:32:03 +08:00
14c94ea8f5 minor typo 2019-08-14 14:26:45 +08:00
435b908c17 Merge pull request #241 from Wesseldr/feature/STM32L432_documentation_update
Added OsX arm install, updated FIDO2 test site links
2019-08-14 14:23:41 +08:00
78280e570b adjust whitespace 2019-08-12 16:18:47 +08:00
36aec9f20b separate interface into two and add "IAD" descriptor 2019-08-12 16:18:30 +08:00
b5d3276df6 not for bootloader 2019-08-11 18:16:58 +08:00
ffd854a303 only 1 user presence auth per button press 2019-08-11 18:05:08 +08:00
349a84dcec cache button press for 2s 2019-08-11 17:59:31 +08:00
6c6a9bc5b6 Merge pull request #260 from solokeys/all-contributors/add-szszszsz
docs: add szszszsz as a contributor
2019-08-08 01:14:36 +02:00
e1528cb248 docs: update .all-contributorsrc 2019-08-07 23:14:18 +00:00
e0955c190e docs: update README.md 2019-08-07 23:14:17 +00:00
ef1e9bc1a1 Merge pull request #259 from solokeys/all-contributors/add-hughsie
docs: add hughsie as a contributor
2019-08-08 01:05:29 +02:00
f6c7dbdbdd docs: update .all-contributorsrc 2019-08-07 23:05:02 +00:00
ea1969ca94 docs: update README.md 2019-08-07 23:05:01 +00:00
c14bc76ddf Merge pull request #258 from solokeys/all-contributors/add-m3hm00d
docs: add m3hm00d as a contributor
2019-08-08 00:59:52 +02:00
f7fd30b9ae docs: update .all-contributorsrc 2019-08-07 22:59:27 +00:00
11763b6502 docs: update README.md 2019-08-07 22:59:26 +00:00
ae5d341c72 Merge pull request #255 from solokeys/all-contributors/add-rgerganov
docs: add rgerganov as a contributor
2019-08-08 00:57:23 +02:00
afed99bae9 Merge branch 'master' into all-contributors/add-rgerganov 2019-08-08 00:57:16 +02:00
d6078ce015 Merge pull request #257 from solokeys/all-contributors/add-esden
docs: add esden as a contributor
2019-08-08 00:55:01 +02:00
d630254224 docs: update .all-contributorsrc 2019-08-07 22:53:47 +00:00
b2ac7b5479 docs: update README.md 2019-08-07 22:53:46 +00:00
c050b82210 editing fail 2019-08-08 00:53:23 +02:00
ba8119b370 Merge pull request #256 from solokeys/all-contributors/add-manuel-domke
docs: add manuel-domke as a contributor
2019-08-08 00:51:24 +02:00
d350f9a638 Update .all-contributorsrc 2019-08-08 00:50:53 +02:00
53275e0182 docs: update .all-contributorsrc 2019-08-07 22:49:29 +00:00
2e14ac5b11 docs: update README.md 2019-08-07 22:49:28 +00:00
a760bed29f docs: update .all-contributorsrc 2019-08-07 22:45:57 +00:00
e854184a11 docs: update README.md 2019-08-07 22:45:56 +00:00
87c2076107 Merge pull request #254 from solokeys/all-contributors/add-alphathegeek
docs: add alphathegeek as a contributor
2019-08-08 00:44:46 +02:00
9be192b82f docs: update .all-contributorsrc 2019-08-07 22:44:17 +00:00
e95233bb5f docs: update README.md 2019-08-07 22:44:16 +00:00
2a2145b7f2 Merge pull request #253 from solokeys/all-contributors/add-StoyanDimitrov
docs: add StoyanDimitrov as a contributor
2019-08-08 00:43:09 +02:00
7cfd0ccb19 docs: update .all-contributorsrc 2019-08-07 22:42:57 +00:00
7d84caa754 docs: update README.md 2019-08-07 22:42:56 +00:00
f7dd595d84 Merge pull request #252 from solokeys/all-contributors/add-yparitcher
docs: add yparitcher as a contributor
2019-08-08 00:42:34 +02:00
04570aaf15 docs: update .all-contributorsrc 2019-08-07 22:42:17 +00:00
1a3aad9761 docs: update README.md 2019-08-07 22:42:16 +00:00
9545dacc5d Merge pull request #251 from solokeys/all-contributors/add-pjz
docs: add pjz as a contributor
2019-08-08 00:41:00 +02:00
b5e592adc9 docs: update .all-contributorsrc 2019-08-07 22:40:47 +00:00
1cd6692246 docs: update README.md 2019-08-07 22:40:46 +00:00
17884505b4 Merge pull request #250 from solokeys/all-contributors/add-YakBizzarro
docs: add YakBizzarro as a contributor
2019-08-08 00:38:06 +02:00
c2312fa69a docs: update .all-contributorsrc 2019-08-07 22:37:54 +00:00
832f06b6b4 docs: update README.md 2019-08-07 22:37:53 +00:00
4ab5477f96 Merge pull request #249 from solokeys/all-contributors/add-ehershey
docs: add ehershey as a contributor
2019-08-08 00:36:13 +02:00
434f2f89ec docs: update .all-contributorsrc 2019-08-07 22:35:54 +00:00
9174c00abf docs: update README.md 2019-08-07 22:35:53 +00:00
46111e27e3 Merge pull request #248 from solokeys/all-contributors/add-dschuermann
docs: add dschuermann as a contributor
2019-08-08 00:33:51 +02:00
763995763f docs: update .all-contributorsrc 2019-08-07 22:33:40 +00:00
4f317863e9 docs: update README.md 2019-08-07 22:33:39 +00:00
8f9aeebb9b Merge pull request #247 from solokeys/all-contributors/add-aseigler
docs: add aseigler as a contributor
2019-08-08 00:32:18 +02:00
86c6b3cbc8 docs: update .all-contributorsrc 2019-08-07 22:32:05 +00:00
a53dfb2812 docs: update README.md 2019-08-07 22:32:05 +00:00
04d6cffcb6 Merge pull request #246 from solokeys/all-contributors/add-agl
docs: add agl as a contributor
2019-08-08 00:29:03 +02:00
76e46605e3 Merge branch 'master' into all-contributors/add-agl 2019-08-08 00:28:36 +02:00
dc94e73c62 Merge pull request #245 from solokeys/all-contributors/add-merlokk
docs: add merlokk as a contributor
2019-08-08 00:26:09 +02:00
018311cfab docs: update .all-contributorsrc 2019-08-07 22:24:54 +00:00
c37638d4cb docs: update README.md 2019-08-07 22:24:53 +00:00
81a67eda24 docs: update .all-contributorsrc 2019-08-07 22:23:26 +00:00
70c176e9ef docs: update README.md 2019-08-07 22:23:25 +00:00
7e39425e98 Merge pull request #243 from solokeys/all-contributors/add-Wesseldr
docs: add Wesseldr as a contributor
2019-08-07 23:59:00 +02:00
25bf9d8e54 docs: update .all-contributorsrc 2019-08-07 21:58:17 +00:00
2e67a5f772 docs: update README.md 2019-08-07 21:58:16 +00:00
66befb96b8 Clarify that code contributions are assumed to be dual-licensed 2019-08-07 23:55:44 +02:00
257f6d1ed5 Merge pull request #242 from solokeys/all-contributors/add-szszszsz
docs: add szszszsz as a contributor
2019-08-07 23:54:17 +02:00
b4b59a6d4d Merge all-contributors with existing Contributors section 2019-08-07 23:52:52 +02:00
c18a08b14b docs: create .all-contributorsrc 2019-08-07 21:26:37 +00:00
c249148d80 docs: update README.md 2019-08-07 21:26:36 +00:00
02a51454b7 Added OsX arm install, updated FIDO2 test site links 2019-08-07 18:35:41 +02:00
4e3420f19f Merge pull request #236 from Wesseldr/patch-3
Cleaned nucleo32-board.md
2019-08-06 13:48:00 +02:00
6b8e575fac Merge branch 'master' into patch-3 2019-08-06 13:43:13 +02:00
28788d1eeb Merge pull request #237 from solokeys/remove_tests
Remove tests
2019-08-06 13:22:29 +02:00
1ee031ae9c Merge pull request #65 from Nitrokey/docs-nucleo32-board
Describe running Solo on the Nucleo board
2019-08-06 13:20:19 +02:00
6dfe42e486 All cleaned up now ? 2019-08-06 13:11:51 +02:00
29b2032dae fixing final-definitions and misc 2019-08-06 13:06:06 +02:00
f9f1e96c73 Update README.md 2019-08-06 18:54:57 +08:00
e2738d11d3 remove tests 2019-08-06 18:50:05 +08:00
a8c7c43e14 Cleaned nucleo32-board.md
The original pull request #65 was not completely compliant. hopefully this one is.
2019-08-06 12:40:05 +02:00
db479850a6 OsX path for STM32_Programmer_CLI
Added how to add the STM32_Programmer_CLI to your OsX path

Fixes https://github.com/Nitrokey/nitrokey-fido2-firmware/pull/20
2019-08-05 16:06:20 +02:00
09d450ed02 Little typo
Fixes https://github.com/Nitrokey/nitrokey-fido2-firmware/pull/19
2019-08-05 16:04:19 +02:00
be37ed46f7 Add instruction for manual flashing of the Nucleo board
Signed-off-by: Szczepan Zalega <szczepan@nitrokey.com>
2019-08-05 16:00:30 +02:00
420d052ac9 Describe running Solo on the Nucleo32 board
Signed-off-by: Szczepan Zalega <szczepan@nitrokey.com>
2019-08-05 16:00:27 +02:00
3698c942a2 Merge pull request #233 from solokeys/bump
Update STABLE_VERSION
2019-07-29 22:40:20 +02:00
17a170bb90 Update STABLE_VERSION 2019-07-29 14:58:30 -04:00
d4e61421b6 Merge pull request #232 from solokeys/windows_hello_error_codes
Windows hello response codes
2019-07-29 14:09:48 -04:00
690d7c716a move CTAPHID_STATUS_PROCESSING to after UP 2019-07-29 12:39:59 -04:00
78e3b291c2 make sure device status is set in all user presence tests 2019-07-28 22:10:56 -04:00
b47854c335 use error code PIN_AUTH_INVALID 2019-07-28 21:41:11 -04:00
2af747ddaa Merge pull request #229 from solokeys/fix-hmac-secret
Fix hmac secret
2019-07-27 12:49:30 -04:00
9ead11de8d Merge pull request #224 from solokeys/fault_tolerance
limit length of wLength
2019-07-27 12:47:28 -04:00
f17faca689 use correct size for auth_data for signature 2019-07-26 23:53:20 -04:00
ca66b6e43b verify signature for hmac-secret 2019-07-26 23:51:39 -04:00
1cd1b3c295 check attestation signature on all MC requests 2019-07-26 23:50:23 -04:00
df2cff2350 patch hmac final to use correct key 2019-07-26 23:49:55 -04:00
f5d50e001d test assertions work post reboot 2019-07-26 19:00:07 -04:00
235785b225 Bump stable version to 2.4.0 2019-07-17 23:42:56 +02:00
303c42901a limit length of wLength 2019-07-15 11:32:02 -04:00
df2f950e69 Merge pull request #217 from merlokk/extapdu
Extended length apdu, iso14443 chaining and select
2019-07-08 22:03:02 -04:00
10bf4242e1 fail with more import related info 2019-07-08 21:54:48 -04:00
9e95b0075c default no serial printing 2019-07-08 21:54:36 -04:00
ddbe31776c Merge pull request #220 from merlokk/obt_src
added text how to obtain source code
2019-07-08 21:22:48 -04:00
645ca6a5a0 add 3-space list 2019-07-08 18:12:28 +03:00
15fc39faed added text how to obtain source code 2019-07-08 17:58:57 +03:00
a1eedc0048 small fix 2019-07-06 13:09:19 +03:00
89e00482e4 some improvements 2019-07-06 12:52:23 +03:00
533ce39237 fix nfc_cc length 2019-07-06 00:15:21 +03:00
63ee003535 Merge pull request #202 from winksaville/patch-1
Update building.md
2019-07-05 10:29:40 -04:00
fa9408d5d6 fix u2f tests 2019-07-05 12:39:32 +03:00
ed9689435d APDU_FIDO_U2F_VERSION 2019-07-05 12:33:23 +03:00
24a006068d fix extended apdu decode 2019-07-05 12:25:46 +03:00
315b6564ab u2f works with extended apdu and now user presence not needs if request come from nfc and power from usb 2019-07-04 23:12:31 +03:00
4d9285085f fix tests 2019-07-04 20:42:24 +03:00
2272e69e15 fix tests 2019-07-04 20:14:24 +03:00
151e1d0e9b fix some errors in tests 2019-07-04 20:09:47 +03:00
d1df8b8b77 u2f authenticate fix 2019-07-04 19:54:00 +03:00
cb76c34ed2 fix addressing 2019-07-04 19:45:09 +03:00
f2ebaf6abe invalid cla and r-block works 2019-07-04 19:14:26 +03:00
4845d2c172 fix 14443 apdu decode and select 2019-07-04 17:52:00 +03:00
75b1d9cd01 offset calc refactoring 2019-07-04 17:38:34 +03:00
26bc8a2889 apdu decoding works 2019-07-04 17:27:03 +03:00
88a8eba424 gitignore 2019-07-04 16:32:11 +03:00
d2c85881e6 applet selection and apdu check 2019-07-04 16:29:30 +03:00
236498ee03 add make 2019-07-04 16:27:57 +03:00
a51c9192b1 add apdu_decode 2019-07-04 16:27:33 +03:00
4dc6bcf771 apdu decode sketch 2019-07-03 23:01:37 +03:00
cce81b23d9 Merge branch 'master' of https://github.com/merlokk/solo into extapdu 2019-07-03 22:59:41 +03:00
8c2e2386a9 fix NFC applet selection does not work correctly #213 2019-07-03 20:35:50 +03:00
c783a1442a Merge pull request #215 from merlokk/nfc-testing
Nfc testing
2019-07-03 11:37:19 -04:00
b61e5db736 style 2019-07-03 17:57:27 +03:00
b41cd5d5b8 add nfc test force flag 2019-07-03 17:54:53 +03:00
b42e990f67 format fix 2019-07-03 01:39:38 +03:00
ff53bb1e32 fix style 2019-07-03 01:16:55 +03:00
2d72e02051 remove unused lib 2019-07-03 01:03:34 +03:00
91c77da179 cbor.loads changed to cbor.decode_from 2019-07-03 00:43:51 +03:00
795cf5c4a1 selecting NFC key works 2019-07-02 19:55:04 +03:00
d1722b85af add library not found error 2019-07-02 19:45:46 +03:00
2c500fe25a check pyscard module first 2019-06-28 12:32:52 +03:00
751b2fd69c add nfc device search 2019-06-28 12:16:59 +03:00
c2216929a9 Create SECURITY.md 2019-06-14 00:19:14 +02:00
a51417bf61 fix epout connection 2019-05-31 15:58:13 -04:00
3f225f362f Update building.md
Adding `solo` as a prerequesite, it's required by `make build-hacker` to merge the hex files.
2019-05-29 15:11:18 -07:00
dd4ff920ad Merge pull request #200 from solokeys/persistedkey
use persisted key info
2019-05-28 18:36:50 -04:00
bddd60c080 use persisted key info 2019-05-27 13:54:29 -04:00
ba581db49c delete excess 2019-05-21 20:17:44 -04:00
3a5cd786dc enumerates correctly 2019-05-21 20:17:37 -04:00
5f878ff022 Merge pull request #196 from solokeys/fido2-conformance
Fido2 conformance
2019-05-19 12:24:36 -04:00
14f91a6e15 add screenshots of tests passing 2019-05-19 12:24:15 -04:00
4fad28ea47 compile new class 2019-05-18 21:47:51 -04:00
0ff9870612 add interface descriptor 2019-05-18 21:26:18 -04:00
cd29a0e0fe python black 2019-05-18 21:11:22 -04:00
46b7f9a778 add UP as UV method for when PIN is not set 2019-05-18 14:35:30 -04:00
31328fe7e7 dont fail when public key type is too large 2019-05-18 14:34:54 -04:00
035b1a8632 Merge pull request #195 from solokeys/bump_2.3.0
Update STABLE_VERSION
2019-05-13 23:11:33 +02:00
b1563dbe94 Update STABLE_VERSION 2019-05-13 16:43:14 -04:00
2a9e3ac576 Merge pull request #194 from solokeys/sanitize
fix potential memory leaks
2019-05-13 16:10:42 -04:00
e1474e8e8e fix potential memory leaks 2019-05-13 15:32:04 -04:00
1564df5305 Merge pull request #192 from solokeys/cap
Capacitive touch sensing
2019-05-13 14:30:37 -04:00
1f3db3fe51 Fix image in README 2019-05-12 09:41:12 -07:00
36876e1528 fix build 2019-05-10 15:57:57 -04:00
0f50ae7d63 change u2f to return early if button not immediately pressed 2019-05-10 15:56:52 -04:00
4854192c63 decrease sensitivity slightly 2019-05-09 18:37:17 -04:00
e105afd647 fix build 2019-05-09 17:51:41 -04:00
9fb02d4da3 add UP wait HID messages to U2F for windows 2019-05-09 17:46:01 -04:00
e402d36bf1 fix user presence skipping for nfc 2019-05-09 17:26:28 -04:00
54792b345c status fix 2019-05-09 16:07:05 -04:00
84740f3d6a changes to make firmware interop on all hw models 2019-05-09 16:01:07 -04:00
4ac61f7f18 slight cleanup 2019-05-09 14:53:22 -04:00
30cfa46186 fix gpio pin reading 2019-05-09 14:17:50 -04:00
aca28fde61 add to bootloader 2019-05-09 02:44:17 -04:00
60e3d01e0d refactor 2019-05-09 02:44:04 -04:00
aff8d10432 connect to application 2019-05-09 02:26:32 -04:00
898d45f871 bugfix 2019-05-09 01:34:54 -04:00
2b2835b823 initial cap sensing boilerplate 2019-05-08 22:26:57 -04:00
f9202b2b6a Merge pull request #186 from solokeys/bump2.2.2
bump
2019-04-24 20:39:00 -04:00
1b74f6a93b bump 2019-04-24 20:38:00 -04:00
0dfda6fce2 Merge pull request #185 from solokeys/wallet-api
Fix FIDO2 get assertion issues with "custom" requests
2019-04-24 20:25:19 -04:00
09b73d694f fix build 2019-04-24 19:33:26 -04:00
9ab5e761c3 Update tinycbor 2019-04-24 19:04:33 -04:00
b3604f49ba use ctap2 instead of client 2019-04-24 19:00:32 -04:00
6ae1cd3865 remove not-useful logs 2019-04-24 18:36:36 -04:00
f9d3b9561d test that getassertions are correct for solo ext 2019-04-24 18:27:11 -04:00
ec98af115f restore button in ctap_make_auth_data 2019-04-24 16:54:26 -04:00
fecf258116 disable wallet by default 2019-04-24 16:44:25 -04:00
437f691d12 Update solo.c 2019-04-24 16:41:22 -04:00
55aadfd78e add delay implementation 2019-04-24 11:45:41 -04:00
813eb97d2f reuse memory for allow_list of creds 2019-04-24 11:45:30 -04:00
32afdccfb3 Rebump 2019-04-24 17:41:08 +02:00
41ae0e4a2c Update application.mk 2019-04-24 00:16:19 -04:00
b0baace2e7 move custom credid to different location 2019-04-24 00:15:32 -04:00
6ff4200f5d unbump 2019-04-23 21:58:26 -04:00
1fab0b8f1f add wallet api in as compile option 2019-04-23 21:57:50 -04:00
ce96fffddd add info to authData for ext reqs 2019-04-23 21:57:27 -04:00
4fb25e165a remove old web assets 2019-04-23 21:15:11 -04:00
8fc0da7934 move args to device_init 2019-04-23 21:12:40 -04:00
494e856198 Merge pull request #131 from rgerganov/hidg
Add support for hidg devices on Linux
2019-04-23 20:22:33 -04:00
472b094acb bump 2019-04-23 20:21:19 -04:00
e0ce23034f Merge pull request #180 from solokeys/test_pin_fixes
Test pin fixes
2019-04-23 19:58:44 -04:00
5f3974a4e6 Merge pull request #182 from solokeys/nfc_adjustments
Nfc adjustments
2019-04-23 19:42:14 -04:00
26adac1730 size optimize tinycbor 2019-04-23 19:17:18 -04:00
eab8b81c95 include nfc in user presence test 2019-04-23 14:05:18 -04:00
325396d518 dont change clock freq if powered 2019-04-23 13:54:23 -04:00
6d04c86018 update lowFreq flag correctly 2019-04-23 13:54:10 -04:00
56d6624e4e Test correct alg parameter #179 2019-04-22 16:26:26 -04:00
3094c87b0a Test empty pinAuth in MC and GA #179 2019-04-22 16:25:08 -04:00
212f98e384 Merge pull request #179 from agl/pinfixes
Couple of fixes for PIN support
2019-04-22 16:11:34 -04:00
73f538dd0e Fix COSE type of key-agreement keys.
The key-agreement keys in the PIN protocol use COSE type -25. I'm not
sure if that's written down anywhere, but it's what everything else does
and it's an ECDH type rather than an ECDSA type.
2019-04-20 16:45:04 -07:00
a5f794c0ff Handle empty pinAuth fields.
CTAP2 specifies that an empty pinAuth field is special: it indicates
that the device should block for touch, i.e. it's just a way of letting
a user select from multiple authenticators[1].

This change handles empty pinAuth fields in GetAssertion and
MakeCredential commands.

[1] https://fidoalliance.org/specs/fido-v2.0-ps-20190130/fido-client-to-authenticator-protocol-v2.0-ps-20190130.html#using-pinToken-in-authenticatorMakeCredential
2019-04-20 16:26:32 -07:00
f28cf9c6d0 new release 2019-04-18 20:41:18 -07:00
6068fb9868 Merge pull request #173 from solokeys/fix_u2f_on_fido2
Fix u2f on fido2
2019-04-17 22:42:38 -04:00
6a288243c1 Add Makefile for installing a HID gadget
The Makefile has targets for building, installing and uninstalling a HID
gadget which acts as FIDO2 authenticator.

Tested on Ubuntu 18.04 but should work on other distros as well. The
only assumption being made is that kernel source is available at
/usr/src/linux-source-$(KERNEL_VERSION).tar.bz2. A possible improvement
would be to have a configure script which finds the correct kernel
source archive.
2019-04-16 10:54:49 +03:00
955d4f76ef Add support for hidg devices on Linux
There is a HID gadget driver on Linux which provides emulation of USB
HID devices. This could be very useful for testing the Solo firmware
without actual hardware, using only a Linux box.

This patch adds a command line argument which specifies whether the
existing UDP backing should be used or the new one which reads and
writes to /dev/hidg0.

Testing done:
 1. Created HID device with configfs
 2. Started "./main -b hidg" as root
 3. Successfully executed Webauthn registration and authentication on
 the same Linux machine

Closes: #122
2019-04-16 10:54:46 +03:00
74cbe00e3b Enable debug logs for >0 2019-04-14 15:13:39 -04:00
7e490f17fc delete 2019-04-13 22:42:16 -04:00
9bb706987f solo ext bugfix 2019-04-13 22:42:05 -04:00
88a759566d Improve testing 2019-04-13 22:37:47 -04:00
44fa3bbb8e Add checks to use U2F key if necessary 2019-04-13 22:37:31 -04:00
89e9296825 Add test 2019-04-13 20:43:26 -04:00
873d65b823 Merge pull request #172 from StoyanDimitrov/patch-1
Improve readability of code filenames
2019-04-13 11:54:55 -04:00
eb8e3ed46a Improve readability of code filenames 2019-04-13 15:31:35 +00:00
8b97276e32 Merge pull request #171 from solokeys/fix_cbor
Fix cbor
2019-04-12 12:04:01 -04:00
78579c27dc Refactor and self test the CBOR sorting 2019-04-11 13:42:17 -04:00
ca80329b4c Compare string length and sort from start of string 2019-04-11 13:22:55 -04:00
7a49169492 consider major type and refactor 2019-04-11 00:04:33 -04:00
46dd4fe818 unused import 2019-04-10 13:56:23 -04:00
c71bbd8689 re-enable all tests 2019-04-10 13:42:38 -04:00
7068be9cd5 reorder options 2019-04-10 13:13:38 -04:00
f8635f1682 refactor tests 2019-04-10 13:12:33 -04:00
ffa9ad4923 refactor cbor sorting test 2019-04-10 12:47:39 -04:00
5fc8d214fd remove add_user param 2019-04-10 12:47:23 -04:00
5f49f4680e re-order items in get_assertion response 2019-04-10 12:22:35 -04:00
86393c46b4 Test it is correct 2019-04-10 12:11:43 -04:00
4cc72bcd97 rearrange cbor encoding order in make_credential and get_info 2019-04-10 12:11:31 -04:00
5e0edf3e11 Update index.md 2019-04-06 21:45:51 +02:00
bd810fff87 Merge pull request #165 from ehershey/patch-3
More docs fixups
2019-04-06 21:41:19 +02:00
d9fb508949 Merge pull request #166 from ehershey/patch-2
include markdown-include mkdocs dependency
2019-04-06 21:40:13 +02:00
c2b7acb6aa include markdown-include mkdocs dependency 2019-04-06 15:29:16 -04:00
4690a7ce65 More docs fixups 2019-04-06 13:50:51 -04:00
61f24d142d Merge pull request #163 from ehershey/patch-1
link to readme and reference TC in docs start page
2019-04-06 13:41:54 -04:00
f5c6f99423 Merge pull request #164 from ehershey/patch-2
Docs fixups
2019-04-06 13:40:51 -04:00
96de4f0850 Docs fixups
Spelling, grammar
2019-04-06 13:28:16 -04:00
331ebdfccf link to readme and reference TC in docs start page 2019-04-06 13:20:10 -04:00
a6a6d653ad Update README.md 2019-04-06 14:49:44 +02:00
928bc0216d Merge pull request #161 from solokeys/bump_2.1.0
bump to 2.1.0
2019-04-02 01:31:48 +02:00
6d52c9ede7 bump to 2.1.0 2019-03-31 23:49:29 -04:00
89769ecc18 fix u2f counter for real 2019-03-31 23:29:00 -04:00
3b3f47bfcf Merge pull request #155 from solokeys/pin_lockout_ga
Pin lockout ga
2019-03-29 17:11:48 -04:00
6fa443b0bc tests for GA without pin 2019-03-26 19:00:42 -04:00
893d4131b2 change how pin is enforced for GA 2019-03-26 19:00:12 -04:00
4e21c0bd8f Merge pull request #152 from solokeys/testing_yubikey
Testing yubikey
2019-03-26 18:33:03 -04:00
251eb6bf64 Merge branch 'master' into testing_yubikey 2019-03-26 16:36:08 -04:00
08e236df69 fix code quality issues x/2 2019-03-26 16:14:28 -04:00
d2091563ab fix code quality issues 2019-03-26 16:09:30 -04:00
54a6a82ca0 Merge pull request #153 from solokeys/rng-fix
Fix buffer overrun and use correct size for random u32
2019-03-26 15:37:51 -04:00
40b9dae38a Fix buffer overrun and use correct size for random u32 2019-03-26 01:55:42 +01:00
98a209e330 make target to flash firmware via bootloader 2019-03-23 13:54:04 +01:00
d3b5fb68ee Build debug 1/2 versions of hacker firmware and bundle 2019-03-23 13:52:47 +01:00
74a1f0e21b Merge pull request #143 from solokeys/paranoid-modemmanager
Do not signal "AT modem" for ACM-CDC serial
2019-03-23 01:48:18 -04:00
e21172fff8 Merge pull request #149 from solokeys/hmac-secret
Hmac-secret
2019-03-22 22:05:41 +01:00
9d3144e9b1 oops. black 2019-03-22 21:56:18 +01:00
a2a774125f Fix usage and display fido2-ext in it 2019-03-22 21:40:55 +01:00
349ea5343a Remove paranoid MM stuff, not signaling AT modem is enough + better 2019-03-22 20:01:31 +01:00
c851807376 Do not advertise AT modem capabilities 2019-03-22 20:00:02 +01:00
84d1629aa3 Allow toggling between strict and paranoid ModemManager filter-policy 2019-03-22 20:00:02 +01:00
8f6ae29163 Fix ModemManager udev rule for some distros 2019-03-22 20:00:02 +01:00
a0d27c2c56 add memory layout commment, undo -8 simplification 2019-03-22 19:55:25 +01:00
3a10427bd9 remove unused files 2019-03-22 19:55:25 +01:00
f3b591e570 Apply suggestions from code review
Co-Authored-By: conorpp <conorpp94@gmail.com>
2019-03-22 19:55:25 +01:00
175f59d206 paste into other linker scripts 2019-03-22 19:55:25 +01:00
f5ff6a11f0 rewrite base linker script 2019-03-22 19:55:25 +01:00
d979420324 u2f work with yubikey5 2019-03-22 01:59:19 -04:00
5076af1be4 works with yubikey5 2019-03-22 01:22:55 -04:00
0a7845459c breakup test_fido2 2019-03-22 00:45:28 -04:00
c4262b0f5b rename 2019-03-22 00:20:48 -04:00
53fb0059a7 break into separate files 2019-03-22 00:20:20 -04:00
a1a75e4ab5 check errors 2019-03-21 12:47:15 -04:00
d68011ef04 remove warnings 2019-03-21 00:01:37 -04:00
02e83073e0 add hmac-secret to reg response 2019-03-20 23:58:42 -04:00
3a48756f96 remove extra layer of map 2019-03-20 23:40:58 -04:00
946e932b1e refactor to use less ram 2019-03-20 23:28:45 -04:00
142d4002e5 remove warning, reduce memory 2019-03-20 23:14:17 -04:00
dbe5283e1f test solo commands on fido2 layer 2019-03-20 21:06:18 -04:00
2d233f164e small bug fixes 2019-03-20 21:03:03 -04:00
b62e9906c7 make new function 2019-03-20 20:13:16 -04:00
e22e636475 hmac-secret tested 2019-03-20 20:03:25 -04:00
074225d87a hmac-secret fully functional 2019-03-20 20:03:12 -04:00
bb9b2ea9d4 validate saltAuth 2019-03-20 18:10:52 -04:00
e8d5bc5829 refactor ctap_make_auth_data arguments 2019-03-20 17:43:50 -04:00
850381a633 test parsing 2019-03-20 16:52:10 -04:00
ce3ad0e56f bugfix 2019-03-20 16:51:58 -04:00
00d86379e5 parse full hmac-secret 2019-03-20 16:21:21 -04:00
6098810167 start to test hmac-secret 2019-03-20 15:45:35 -04:00
821880a8d6 parse extension info in MC 2019-03-20 15:45:10 -04:00
44f96f5843 Merge pull request #148 from solokeys/testing_refactor
Testing refactor
2019-03-20 15:06:12 -04:00
6ec9fb962a delay send_raw in test 2019-03-20 14:59:31 -04:00
c9bfe001ee refactored version, previously lost 2019-03-20 14:56:52 -04:00
5e46fd96ac Create LICENSE 2019-03-19 16:29:39 +01:00
103cc3cfb0 Some fun with shields 2019-03-19 16:28:47 +01:00
9544330dc3 delay send_raw in test 2019-03-18 04:36:02 +01:00
0964ff69b7 refactor a bit 2019-03-18 04:36:02 +01:00
e4a2b9e1ca Get udev instructions up to date 2019-03-18 02:52:34 +01:00
d29fa34da1 Update README.md 2019-03-15 22:08:07 -04:00
6ed2610a5c Merge pull request #145 from solokeys/stable-v2.0.0
Set STABLE_VERSION to 2.0.0
2019-03-14 19:39:43 -04:00
3b9d4e5023 Set STABLE_VERSION to 2.0.0 2019-03-15 00:35:50 +01:00
2da083c18a Merge pull request #138 from solokeys/fix-warning
I think this does it
2019-03-11 14:33:02 -04:00
50bfbc1eff I think this does it 2019-03-10 15:26:45 +01:00
86739df7a1 Improvements to Docker build 2019-03-10 15:19:16 +01:00
c7f0d050d7 Fix udev rule for STM bootloader 2019-03-08 14:25:29 +01:00
b79670a447 Merge pull request #133 from solokeys/more_testing
More testing
2019-03-07 21:25:53 -05:00
169ba59ed4 use alpha 2019-03-07 21:19:10 -05:00
f3003c58c9 new release 2.0.0 2019-03-07 20:33:20 -05:00
084e518018 refactor 2019-03-06 17:43:28 -05:00
6674f0a8ff add more tests 2019-03-06 16:17:12 -05:00
f704851419 add bootloader tests 2019-03-06 14:23:56 -05:00
0d5e1ee872 Test solo specific commands 2019-03-06 14:06:07 -05:00
5cb81c753d Add version/extensions to PC build 2019-03-06 14:05:44 -05:00
b0b0564df9 fix imports 2019-03-06 13:13:43 -05:00
195dc2a8ae use 0x7f as upper counter byte 2019-03-04 02:36:47 -05:00
4982b13f64 Merge pull request #129 from solokeys/testing_fido2
Testing fido2
2019-03-04 02:26:06 -05:00
63a93f6ec2 test pin lock out 2019-03-03 19:01:08 -05:00
7b8ec18e76 add reboot capability for tests 2019-03-03 18:43:14 -05:00
67faef0117 tests for client pin 2019-03-03 17:17:04 -05:00
0b9f0af3c7 spin pc less 2019-03-03 17:15:26 -05:00
880d54a4f0 more fido2 tests 2019-03-03 03:43:15 -05:00
1507758ad1 bring pc crypto impl up to date 2019-03-02 23:10:43 -05:00
e883c5aa6e add many fido2 tests 2019-03-02 22:40:51 -05:00
afc85e0d2e update log message 2019-03-02 22:40:27 -05:00
a40dcf3f17 reduce nfc detect period to 10ms 2019-03-02 20:08:28 -05:00
4b82e80d7a init device with nfc detection 2019-03-02 20:08:15 -05:00
246dea8a44 fix clock init by setting flash latency last for low freqs 2019-03-02 20:05:27 -05:00
7a98764a5b organize ECC flags 2019-03-02 19:48:09 -05:00
dc946f5b35 centralize reset key agreement 2019-03-02 19:38:27 -05:00
0232893611 increase buffer size for USB strings, check string length 2019-03-02 19:38:03 -05:00
5995f84822 buffering logs sometimes freezes, stop for now 2019-03-02 15:43:12 -05:00
1ff00895b1 init nfc, fix freeze 2019-03-02 02:02:01 -05:00
83641b3789 disable clock settings for NFC passive for now 2019-03-02 01:30:09 -05:00
9b356076c5 Merge pull request #127 from solokeys/testing
Testing
2019-03-02 01:12:48 -05:00
6c96521c7d slight cleanup 2019-03-02 00:55:46 -05:00
35707c3797 wrong size, causes RK's to be overwritten 2019-03-02 00:55:25 -05:00
e31e703afd minor improvements 2019-03-01 23:42:22 -05:00
3a8be9eef7 add more u2f tests 2019-03-01 23:16:48 -05:00
e2b30ec087 basic interface 2019-03-01 22:35:50 -05:00
495e10f3a1 add basic rk support for pc 2019-03-01 22:28:25 -05:00
11ca6bd517 fix pc testing 2019-03-01 22:11:36 -05:00
a265da09fb Update u2f.c 2019-03-01 22:00:17 -05:00
1b4d1be9ee Merge pull request #119 from solokeys/udev
Cleanup udev rules, keep 99-solo.rules as symlink
2019-03-01 21:44:45 -05:00
32f2436380 Merge pull request #120 from nickray/sha512
SHA512 (via Cifra)
2019-03-01 21:44:13 -05:00
7255c4f8db Merge pull request #121 from solokeys/nfc
Nfc
2019-03-01 21:43:12 -05:00
4e215db42a start from 0 2019-02-28 23:13:12 -05:00
a1ad641076 Merge branch 'master' of github.com:solokeys/solo 2019-02-28 22:47:25 -05:00
daf56b0cc7 Silence warning about out of date pip in Travis 2019-02-28 01:06:06 +01:00
5859073cb8 Build bundle-hacker-{version}.hex 2019-02-28 01:06:06 +01:00
ff5207ba77 First attempt 2019-02-27 21:43:20 +01:00
324b4a89cc Remove python-fido2 submodule 2019-02-27 21:43:20 +01:00
9f60caf9c1 for docker on windows 2019-02-26 22:00:21 -05:00
0865f2a660 do not probe bootloader 2019-02-27 03:18:12 +01:00
b1c72c9d94 for docker on windows 2019-02-26 21:11:33 -05:00
5e70c11b54 Hide onboard crypto tests behind a reserved ctaphid command 2019-02-27 02:58:56 +01:00
46ada5a8b9 WRONG_DATA apdu error code fix 2019-02-26 20:34:07 -05:00
0eac67259d remove stm32l442 target 2019-02-26 18:24:40 -05:00
9399a5f195 Cleanup udev rules, keep 99-solo.rules as symlink 2019-02-27 00:00:49 +01:00
47aa287480 Vanilla cifra needs more includes 2019-02-26 23:50:01 +01:00
865b698bed ...and bootloader 2019-02-26 23:33:57 +01:00
14974e0ebe fix compile issues 2019-02-26 15:30:57 -05:00
1ed7833c9f fix pc build 2019-02-26 15:08:09 -05:00
e8d0ad5e7c autodetect passive nfc operation or usb operation 2019-02-26 15:04:23 -05:00
e2ca7f52db optimize ecc for arm 2019-02-26 14:19:07 -05:00
c97b9f9b8f Need includes in main Makefile too 2019-02-26 20:16:38 +01:00
ecf994b647 fix warnings and compile errors 2019-02-26 14:13:29 -05:00
347d0942b1 refactor fromNFC 2019-02-26 14:07:27 -05:00
ff0d42c8d5 refactor clock rates, fix warnings 2019-02-26 13:56:06 -05:00
a6673b0917 Use our cifra fork, rename command, keep room for sha256 2019-02-26 19:52:59 +01:00
0c296bba30 First go at using cifra for SHA512 2019-02-26 19:52:59 +01:00
57930aaa13 fix compilation errors 2019-02-26 13:27:25 -05:00
1a6895ca25 merge 2019-02-26 13:10:16 -05:00
54241ecd42 add option 'sim' to select UDP/simulated backend 2019-02-26 18:37:42 +01:00
e537d00173 update to new fido2 version 2019-02-26 18:37:42 +01:00
a195408a11 scale up to 24 MHz only for register 2019-02-26 01:51:07 -05:00
54b7f42056 passive operation works as is (refactor needed) 2019-02-26 01:19:35 -05:00
6128e86da2 Merge pull request #114 from merlokk/nfc4
NFC. added hardware part of UID
2019-02-19 22:05:15 -05:00
fed9f473aa added hardware part of UID 2019-02-19 18:12:01 +02:00
f6ff3c1b87 Fetch tags in docker build script. More robust udev rules in docs 2019-02-19 00:32:07 +01:00
afd3218358 Create CHANGELOG.md 2019-02-17 18:19:30 -05:00
ed6da0ba1e Merge pull request #111 from solokeys/fido2-ext
Fido2 ext
2019-02-17 15:51:57 -05:00
46d7be865d fix upper byte U2F for backwards compatibility 2019-02-17 15:33:24 -05:00
596c6c1077 manually specify order for reproducible builds 2019-02-16 22:30:49 -05:00
6c3014575f Update application.mk 2019-02-16 22:02:26 -05:00
190ecc8fd8 make work for windows 2019-02-16 21:27:56 -05:00
0d2e03a5a9 Change firmware-hacker ROP level, add ST DFU udev
- later we can set ROP=1 for hacker firmware builds again,
  right now it causes issues in solo-python tool
2019-02-17 02:30:16 +01:00
991530f88b generate the serial number same as DFU 2019-02-16 14:08:59 -05:00
de31924be3 Lock down reproducible make targets and use in docker build 2019-02-16 18:46:13 +01:00
6b97807f51 Easier hex make targets for docker build 2019-02-16 18:36:04 +01:00
35022775cd Ensure the docker image has all public commits to build from 2019-02-16 18:10:16 +01:00
6fecb3c035 base serial number off of chip Unique device ID 2019-02-16 00:23:11 -05:00
3fed8cebdf reduce RNG to 71 2019-02-14 18:01:23 -05:00
c81bc9fb98 Detailed version in product name 2019-02-14 23:13:06 +01:00
99f09790f1 deterministic 2019-02-14 16:03:19 -05:00
6745c9a0cb bugfix/skip-auth for fido2 extension 2019-02-14 15:53:02 -05:00
0651316da5 catch U2F check by extension 2019-02-14 15:16:13 -05:00
f48becc6dc bridge extension to fido2 interface 2019-02-14 15:15:58 -05:00
85c58e9d5b TAG_EXT typo 2019-02-14 15:15:24 -05:00
c9862977bf delete old key 2019-02-13 19:22:45 -05:00
1a40299dcb add solokeys cert 2019-02-13 19:16:44 -05:00
8f9ff17bef ability to build solo versions via make docker-build SOLO_VERSION=... 2019-02-14 00:35:28 +01:00
9e9d26e604 Split building and merging firmware in two, use volumes 2019-02-14 00:35:28 +01:00
b3d76d56e0 Add docker-build make target, adjust instructions, remove Python2 support 2019-02-14 00:35:28 +01:00
13424fdbcd add Dockerfile 2019-02-14 00:35:28 +01:00
2327247c29 Merge pull request #110 from yparitcher/Bootloader_version
fix bootloader versions
2019-02-13 00:14:53 -05:00
85004370b7 fix bootloader versions 2019-02-12 23:10:36 -05:00
8f6f8a34e1 Merge pull request #109 from solokeys/minor-cleanup
Cleanup makefile, minor typos
2019-02-12 22:29:02 -05:00
f0f0aaaaa4 test u2f 2019-02-12 22:27:06 -05:00
5fddde240f fix env3 reference to venv in README 2019-02-13 04:14:55 +01:00
b212c71da6 fix .envrc 2019-02-13 04:13:15 +01:00
1ea4a2776b remove .clabot 2019-02-13 04:12:31 +01:00
41f1d5efed udev fix 2019-02-13 04:03:55 +01:00
6e497ad04e VERSION macro was colliding with something 2019-02-12 22:02:11 -05:00
34fb8c9c24 udev fix 2019-02-13 03:54:06 +01:00
8386ae56d2 Cleanup makefile, minor typos 2019-02-13 03:25:12 +01:00
d38d3a8342 Merge pull request #108 from yparitcher/f2ext_fixes
fix typo
2019-02-12 20:55:15 -05:00
ce364e5e87 Merge branch 'master' of github.com:solokeys/solo 2019-02-12 20:52:12 -05:00
c482d6cc74 typo 2019-02-12 20:52:03 -05:00
2cb96cb793 fix typo 2019-02-12 20:47:28 -05:00
a32bea2697 Merge pull request #64 from Nitrokey/code-comments
Describe operations done in the bootloader
2019-02-12 20:34:16 -05:00
7df402a20a Merge branch 'master' into code-comments 2019-02-12 20:34:03 -05:00
650e0b26cc change assignment, else this evaluates for every file 2019-02-12 20:29:33 -05:00
831976f3a2 replace macros with DEBUG_LEVEL aware timestamp function 2019-02-12 20:28:48 -05:00
e7e83820a9 Merge pull request #51 from yparitcher/clean_build
clean up code: GCC warnings; add black to travis; fix linux build errors
2019-02-12 20:08:24 -05:00
8dd211d557 merge upstream 2019-02-12 19:49:47 -05:00
747d9a194d Merge pull request #86 from pjz/black
Add black to travis checking
2019-02-12 19:37:57 -05:00
bfd8827073 fix Makfile: bootloader 2019-02-12 19:35:33 -05:00
ce92c7634e fix bootloader version 2019-02-12 19:34:46 -05:00
f97d9ab34f fixes 2019-02-12 19:22:35 -05:00
a2611fb013 run python black 2019-02-12 18:45:01 -05:00
3b320e0aeb initialize at 24 MHz at very start instead of 16 2019-02-12 18:34:13 -05:00
f2d0e3d275 Revert "Travis: use python 3.6" Hopefuly we dont need this
This reverts commit e10ad70b2b8e15de5fcace7af3f8e1cc9a6ca2f0.
2019-02-12 18:27:11 -05:00
c1631c7172 Travis: try to get python to work 2019-02-12 18:27:11 -05:00
259020ece0 Travis: use python 3.6 2019-02-12 18:27:10 -05:00
589b17c596 Travis: install venv 2019-02-12 18:27:10 -05:00
ad4e526497 Travis: install toolchain 2019-02-12 18:27:10 -05:00
f005ea438c spacing 2019-02-12 18:27:10 -05:00
2615fd39ac spacing 2019-02-12 18:27:10 -05:00
eba9ce8475 fix usbd_hid.c 2019-02-12 18:27:10 -05:00
a4f01c3f23 PHONY targets 2019-02-12 18:27:09 -05:00
c2342834dd optimize venv 2019-02-12 18:27:09 -05:00
be212fd8b1 stm32l432: clean .map files 2019-02-12 18:25:48 -05:00
ee817ea8bb automate building cbor 2019-02-12 18:24:29 -05:00
6c6f0a0068 fix Makefile, Travis make 2019-02-12 18:24:28 -05:00
5862a8a5ac hacker VID/PID pair 2019-02-12 18:24:28 -05:00
a966ea3a58 tweak Makefile 2019-02-12 18:22:50 -05:00
eed418ea33 add black to travis build 2019-02-12 18:22:50 -05:00
9a037279c8 fix travis build 2019-02-12 18:22:50 -05:00
727e1f2fd9 fix travis build 2019-02-12 18:22:49 -05:00
5afdef463e add stm32l432 build test 2019-02-12 18:22:49 -05:00
1dd835d698 add -Wextra: further code cleanup
please fix Wno-unused-parameter -Wno-missing-field-initializers in the future
2019-02-12 18:22:03 -05:00
400b37a96a clean up build: GCC warnings 2019-02-12 18:19:38 -05:00
23c140fd99 Merge pull request #107 from solokeys/license-change
License change
2019-02-12 17:47:43 -05:00
894f6f7ee1 Merge branch 'master' into license-change 2019-02-12 17:47:28 -05:00
b9e6d552f8 Merge pull request #105 from solokeys/versioning
Versioning
2019-02-12 17:46:45 -05:00
828a8fc0b5 Update README.md 2019-02-12 17:21:37 -05:00
45eaef2663 delete non-supported platforms 2019-02-12 17:18:44 -05:00
ed676151f1 update license to apache2 + mit 2019-02-12 17:18:17 -05:00
45da2f0b32 Update solotool.py 2019-02-12 16:37:40 -05:00
6c23532f08 use 3-byte version 2019-02-12 16:37:32 -05:00
bc8984aac3 pass version to gcc derived from git describe 2019-02-12 16:37:09 -05:00
020fe21546 organize version header info 2019-02-12 16:11:06 -05:00
9957a83746 organize makefiles 2019-02-12 16:03:04 -05:00
72bca0765a see firmware version from solotool 2019-02-12 15:11:48 -05:00
ba4f9ed7ae bug fix 2019-02-12 15:00:01 -05:00
eb2d377ffb add extension to solo to get version and RNG 2019-02-12 14:00:05 -05:00
8303bb04d3 write bootloader version from bootloader 2019-02-12 13:59:36 -05:00
d23bf0a144 change product name, include version string 2019-02-12 13:59:16 -05:00
a6446e67bc Merge pull request #80 from merlokk/led_normalization
led emission normalization
2019-02-11 22:12:24 -05:00
529b879c08 init in device_init 2019-02-11 22:02:41 -05:00
2893cd7ce3 move inits to device_init 2019-02-11 22:00:18 -05:00
0634510b92 Merge pull request #81 from merlokk/fix_flash_lock
flash_lock() must be at beginning
2019-02-11 21:57:40 -05:00
858545c0c8 Merge pull request #98 from Nitrokey/94-buffer_overread
Fix buffer overread in ctap_encode_der_sig()
2019-02-11 21:44:57 -05:00
120fb95541 compile for bootloader 2019-02-08 13:09:32 -05:00
665e84d183 delay to allow spi interface to initialize 2019-02-08 13:09:12 -05:00
13d9885da4 initialize at 16MHz, add 24 and 32 options 2019-02-08 13:08:28 -05:00
e230a9464e enable ctap from usb 2019-02-07 20:09:13 -05:00
342af18b1f initialize ctap 2019-02-07 20:09:00 -05:00
be9bd941c8 simplify ams init 2019-02-07 19:45:02 -05:00
0f6be6740b Merge pull request #101 from merlokk/nfc2
Nfc2
2019-02-07 19:14:12 -05:00
9054736e0e delete debugging code 2019-02-07 19:03:45 -05:00
c6d946136e small fix 2019-02-07 16:05:08 +02:00
32400c8d09 Merge branch 'nfc' into nfc2 2019-02-07 14:49:47 +02:00
587c9aad14 refactor 2019-02-06 18:09:53 -05:00
c624a32ef6 default 8 thread build 2019-02-06 18:07:38 -05:00
3005a63938 re-arrange some logic for better passive operation 2019-02-06 18:07:09 -05:00
f470e9a9cd dont need to init clock at first in bootloader 2019-02-06 18:05:22 -05:00
e3971a5e0f change ams init, read less regs 2019-02-06 17:56:53 -05:00
2ed8667f18 immedately change clock rate to load data sections faster 2019-02-06 17:55:27 -05:00
765d532f82 add low freq clocking options 4,8,16MHz 2019-02-06 17:54:52 -05:00
ca05385513 log fixing 2019-02-06 20:06:46 +02:00
5328610ff1 delete debug messages 2019-02-06 19:51:32 +02:00
bc1bb3509f move APDU dumps to separate log channel 2019-02-06 19:21:06 +02:00
375db69e3a fido2 works 2019-02-06 19:06:49 +02:00
771fffe329 WTX works. todo: clean debug unneeded messages 2019-02-06 17:12:22 +02:00
4611f05051 small fix in AMS3956 debug texts 2019-02-06 15:17:52 +02:00
e657e26886 check AMS product type 2019-02-06 15:15:37 +02:00
3ffcc47374 fix logger 2019-02-06 14:11:49 +02:00
102f2f261b better capitalisation 2019-02-03 02:27:25 +01:00
24d8abf820 add an .envrc for those using direnv 2019-02-03 02:21:50 +01:00
449faea7d3 Fix buffer overread in ctap_encode_der_sig()
Take into account leading zeroes in the size to copy, for both R and S
ingredients of the signature.
Issue was occuring only in cases, when there was a leading zero for the
S part.

Refactor ctap_encode_der_sig():
- add in_ and out_ prefixes to the function arguments
- mark pointers const
- clear out buffer

Tested via simulated device on:
- Fedora 29
- gcc (GCC) 8.2.1 20181215 (Red Hat 8.2.1-6)
- libasan 8.2.1 / 6.fc29
(same machine, as in the related issue description)
by running ctap_test() Python test in a loop for 20 minutes (dev's
counter 400k+). Earlier issue was occuring in first minutes.

Tested on Nucleo32 board, by running the ctap_test() 20 times.

Fixes https://github.com/solokeys/solo/issues/94

Signed-off-by: Szczepan Zalega <szczepan@nitrokey.com>
2019-02-02 18:33:10 +01:00
1b5e230d45 merge u2f endian fix 2019-02-02 00:32:36 -05:00
81a89ed6aa go back to high freq 2019-02-02 00:29:32 -05:00
ca2074de36 Update Makefile 2019-02-02 00:25:01 -05:00
ee98340a03 temporarily remove prints at start 2019-02-02 00:24:42 -05:00
3d0d91fa5c lf param 2019-02-02 00:24:11 -05:00
38171dba06 low freq init 2019-02-02 00:23:51 -05:00
4ba57ccc85 refactor init functions 2019-02-02 00:23:01 -05:00
c3bddee814 dont do this when powered by nfc 2019-02-02 00:21:26 -05:00
b7bc50bc4f Merge pull request #96 from merlokk/nfc2
small fixes in NFC branch
2019-02-02 00:16:07 -05:00
19627a959a some TODOs 2019-02-01 21:35:45 +02:00
429e4b2a77 add WTX_clear(); 2019-02-01 21:33:57 +02:00
6e5de7bd6b read data if we sent WTX 2019-02-01 21:31:20 +02:00
c6daa4acc9 more WTX sketch 2019-02-01 21:27:43 +02:00
ab01d0c73d delete comment 2019-02-01 21:02:02 +02:00
0ef42b2df7 added WTX sending sketch 2019-02-01 20:45:36 +02:00
f6e2bfa683 yubikey answers U2F_SW_WRONG_PAYLOAD instead of U2F_SW_WRONG_DATA 2019-02-01 20:06:19 +02:00
5c8acdd666 fix u2f user presence check, added dont-enforce-user-presence-and-sign, fix counter 2019-02-01 20:00:13 +02:00
e996d470f9 small fixes 2019-02-01 19:15:48 +02:00
4c36a752cb Fix vendor and product id 2019-01-31 02:56:42 +01:00
e2e29492e6 point to website 2019-01-29 22:39:49 -05:00
5f637992b1 implement capability container and ndef tag to work with nexus 6 2019-01-29 22:12:38 -05:00
91d092a27a tell AMS to go to sleep if deselected 2019-01-27 23:55:11 -05:00
23cbfde312 Merge pull request #88 from merlokk/nfc
merging so I can test out in my branch
2019-01-27 21:11:57 -05:00
cce25b2a1c u2f auth works 2019-01-28 00:04:17 +02:00
f24058d2e8 u2f authenticate wrong length fix 2019-01-27 23:58:35 +02:00
4c941997b4 check as3956 on startup 2019-01-27 23:35:20 +02:00
37f1790028 Add metadata statements and include in documentation 2019-01-27 20:08:15 +01:00
91066292ae move fido2-impl.md 2019-01-27 19:57:48 +01:00
1ffe85f083 update attestation verification 2019-01-27 11:18:50 -05:00
2049020b92 refactoring 2019-01-27 11:44:33 +02:00
7a6abdfd0c add command to verify SoloKeys attestation cert 2019-01-26 18:06:01 -05:00
ff4cb32bc3 Update solotool.py 2019-01-26 17:15:40 -05:00
1857482617 add some len check 2019-01-27 00:01:04 +02:00
2feef8b043 add some profiling... 2019-01-26 23:53:13 +02:00
3eddfbf8a9 u2f register works 2019-01-26 23:44:51 +02:00
a662a9a619 remove dump 2019-01-26 23:36:45 +02:00
1a656d60e4 register works. but it needs to press a button.... 2019-01-26 23:35:45 +02:00
e235402fb8 u2f register 2019-01-26 21:34:53 +02:00
6ca9f1946b I block on receive 2019-01-26 21:08:18 +02:00
df671775ba add some profiling. looks good. 2019-01-26 19:30:03 +02:00
3ba83f6407 remove debug msg 2019-01-26 19:11:51 +02:00
ffa4225827 chip have too less memory. so reusing ctap_resp buffer. 2019-01-26 19:07:12 +02:00
cde6bc107a GetVersion works. not so clean. needs additional memory.... 2019-01-25 19:54:02 +02:00
15de8dc4a6 send response from key to pc in chaining mode. partially works.
GetVersion must work with pc (proxmark have errors)
2019-01-25 19:32:42 +02:00
94fe58d020 small fix 2019-01-24 20:09:57 +02:00
e8634a2d61 add u2f errors 2019-01-24 20:04:44 +02:00
67b0abde4b some refactoring 2019-01-24 19:56:18 +02:00
d713167ec4 works. needs to add chaining 2019-01-24 19:21:31 +02:00
45888c9a25 ins check is ok 2019-01-24 18:22:58 +02:00
d02206ba09 SELECT works as expected and U2F GetVersion command done 2019-01-24 18:19:23 +02:00
ad9186c13b SELECT works 2019-01-24 17:57:42 +02:00
4e0dc15dfd add historical bytes 2019-01-24 16:56:38 +02:00
a75d272f4a move files, not yet implemented masked aes 2019-01-23 19:53:58 -05:00
15c3383249 be more clear that these aren't implemented yet 2019-01-23 19:23:21 -05:00
c556fcd8c3 Merge pull request #58 from Nitrokey/fix_simulation
Avoid 2nd start of the simulation server
2019-01-23 19:02:30 -05:00
b4bfe5e3b9 Add black to travis checking 2019-01-22 01:44:33 -05:00
29d4d88259 upgrade to xenial for a newer cppcheck 2019-01-21 19:37:22 +01:00
7bd5f29a79 add cppcheck to travis 2019-01-21 19:37:22 +01:00
a72f5029dc Make solotool complain if it's run with py2 2019-01-21 19:24:58 +01:00
81e58a92f2 flash_lock() must be at beginning 2019-01-21 17:38:56 +02:00
c3b4806e85 add led emission normalization 2019-01-21 17:09:51 +02:00
dffc1833cb Update contributing.md 2019-01-19 03:53:28 +01:00
31538faab1 Add license scan report and status
Signed-off-by: fossabot <badges@fossa.io>
2019-01-19 00:37:24 +01:00
1866d366fb Add cla-bot configuration 2019-01-18 18:05:41 +01:00
dcf7940b3d basic ndef message works 2019-01-13 17:25:32 -05:00
1874e11fba organize 2019-01-13 00:02:37 -05:00
302ce75ce6 responds to RATS correctly 2019-01-12 20:20:47 -05:00
178c25710b Merge pull request #60 from Nitrokey/doc_update
Udev rules related docs update
2019-01-12 17:12:28 -05:00
62cd7cc728 enable energy harvesting and tunneling in eeprom 2019-01-12 16:20:11 -05:00
20f8aac768 option to boot at 4MHz with no USB 2019-01-12 16:19:44 -05:00
5806b25fd1 Prevent Solo's debug serial port use by ModemManager
This Udev rule marks the device to be ignored by the MM.
Otherwise using the CDC ACM serial port interface will not be
possible, while its service is running.

Tested on Fedora 29, with ModemManager enabled, using:
$ solotool.py monitor /dev/solokey-serial
Fixes https://github.com/solokeys/solo/issues/62

As provided by @yparitcher in:
https://github.com/solokeys/solo/pull/60#issuecomment-452428432

Signed-off-by: Szczepan Zalega <szczepan@nitrokey.com>
2019-01-09 11:41:23 +01:00
4110434e33 Add Udev symlink for Solo's serial port
Signed-off-by: Szczepan Zalega <szczepan@nitrokey.com>
2019-01-09 11:41:20 +01:00
8c103be5c0 Udev rules related docs update
Signed-off-by: Szczepan Zalega <szczepan@nitrokey.com>
2019-01-09 11:41:16 +01:00
9ff52fcdb4 Update u2f.c 2019-01-08 21:37:15 -05:00
e7f01f4e55 disable CDC ACM when not debugging 2019-01-08 21:18:18 -05:00
04a85db303 serial number 2019-01-08 20:50:14 -05:00
61ad141830 Merge branch 'master' of github.com:solokeys/solo 2019-01-08 20:46:30 -05:00
f38b29256b Describe operations done in the bootloader
Signed-off-by: Szczepan Zalega <szczepan@nitrokey.com>
2019-01-08 19:31:33 +01:00
121070822f Update main.c 2019-01-07 21:20:07 -05:00
96f65be9c2 disable main app for now 2019-01-07 21:19:56 -05:00
78c40976c3 log interrupts and recv'd data 2019-01-07 21:19:45 -05:00
8eacfa6717 Fix docs again 2019-01-08 02:14:46 +01:00
aa978abfc7 cleanup 2019-01-07 19:40:20 -05:00
80f2b487f0 Merge branch 'int3l-patch-1' 2019-01-08 01:10:54 +01:00
a0f8b27841 Merge branch 'master' into patch-1 2019-01-08 01:09:46 +01:00
b7c0e4ea92 no delays 2019-01-07 19:05:39 -05:00
d89fe933f3 Merge branch 'robbiemacg-patch-1' 2019-01-08 01:04:32 +01:00
794c231b0d Merge branch 'patch-1' of git://github.com/robbiemacg/solo into robbiemacg-patch-1 2019-01-08 01:03:54 +01:00
6ffba7d472 move to new file 2019-01-07 18:50:01 -05:00
c330346c31 add nfc log tag 2019-01-07 18:29:38 -05:00
eda26e3c93 add ST spi LL driver 2019-01-07 18:17:33 -05:00
fa4da6e9d7 Merge branch 'master' of github.com:solokeyssec/solo 2019-01-07 18:09:03 -05:00
6d3313bd3f Update building.md 2019-01-07 18:08:59 -05:00
ea210320c6 Fix some old links 2019-01-07 23:07:55 +01:00
bdc4c8f9df Move to solokeys org, host docs under docs.solokeys.io 2019-01-07 22:39:36 +01:00
8c1d716632 Update fido2-impl.md
Fixed small apparent typo.
2019-01-07 13:47:03 -04:00
ca27b26c6b Avoid 2nd start of the simulation server
udp_server() is being called second time during the simulated run, which
fails due to trying to claim already used port. This patch adds cache to
the udp_server() result.

Signed-off-by: Szczepan Zalega <szczepan@nitrokey.com>
2019-01-07 18:47:01 +01:00
600b2a61fe Enable custom favicon 2019-01-07 02:24:27 +01:00
2f61c061b7 Add favicon asset
Same asset icon file as solokeys.com
2019-01-07 02:24:27 +01:00
44077a4f2f spi interface WORKS 2019-01-06 17:12:26 -05:00
ba4ca96253 Update mkdocs config
- adjust the copyright text
- rename and reorder some of the menu items for the sake of better SEO and user experience
2019-01-06 20:12:33 +02:00
a48a962653 Fix badges and hint Python setup 2019-01-06 03:44:05 +01:00
4c6f0969c1 add spi 2019-01-05 20:58:39 -05:00
ccac725b7f pass prefix option 2019-01-05 19:56:23 -05:00
41ed68eb44 Update bootloader.mk 2019-01-05 19:52:59 -05:00
3d9dd08208 non-c99 compatibility 2019-01-05 19:42:28 -05:00
83d59dfc54 force static link ... 2019-01-05 19:36:00 -05:00
ce11e4173f dont skip button by default 2019-01-05 19:34:59 -05:00
f15ba1d3dc change serial number 2019-01-05 19:34:11 -05:00
c0a2b677f0 Update README.md 2019-01-05 15:36:30 -05:00
f8f895df4f Merge pull request #48 from SoloKeysSec/python-cleanup
Python cleanup
2019-01-05 02:27:36 +01:00
de3d6fd5ba Merge branch 'master' into python-cleanup 2019-01-05 02:06:09 +01:00
4072a51a5b Merge pull request #49 from SoloKeysSec/its-stm32l432
we use l432, not l442
2019-01-05 02:04:38 +01:00
5f3c50e690 we use l432, not l442 2019-01-05 01:44:53 +01:00
6ca7076fe5 update docs 2019-01-04 00:25:07 -05:00
dd320d049f add easy recipes 2019-01-03 23:46:48 -05:00
a8e1060eee fix some more scripts 2019-01-04 04:30:00 +01:00
8210e9ecd9 give up on travis 2019-01-04 04:28:05 +01:00
59503c775e minor changes 2019-01-04 02:02:27 +01:00
2f9987a28a be systematic with coding and shebang 2019-01-04 02:01:59 +01:00
cbc422b817 ble 2019-01-03 15:19:54 +01:00
c7f1aecd61 ble 2019-01-03 15:16:57 +01:00
f2f71e2cbf ... 2019-01-03 15:15:23 +01:00
a1d3205011 ... 2019-01-03 15:09:30 +01:00
b01b37d86b ... 2019-01-03 15:01:59 +01:00
e63462cd86 ... 2019-01-03 15:00:09 +01:00
4136853e76 And so the Travis dance begins 2019-01-03 14:57:50 +01:00
c58c8300ac Try and run some python tests in Travis 2019-01-03 14:53:44 +01:00
89de3738c0 Ensure python2 for env2 make target 2019-01-03 14:30:19 +01:00
6a5449b8cb Pass tools/ through black 2019-01-03 14:27:21 +01:00
b2c78ca7c0 Start some cleanup
- add an editorconfig
- fix requirements.txt and the UTF-8 issue (lost in pull/47)
- two clean environments
- make black usable
- two test targets (wink2/wink3)
2019-01-03 14:24:34 +01:00
fa810ff54d Merge pull request #47 from SoloKeysSec/solotool
Solotool
2019-01-03 14:00:56 +01:00
de900dec2c Update solotool.py 2019-01-02 21:16:29 -05:00
9565ae4cda combined merge_hex 2019-01-02 21:07:56 -05:00
b8a27eadca small improvements 2019-01-02 20:59:37 -05:00
a4d79d12dd Separate symlinks for hacker and non-hacker 2019-01-01 13:44:55 +01:00
8e8d74c5ad Update solotool.py 2018-12-31 15:23:47 -05:00
1f380b0264 patch issue with del on windows 2018-12-31 15:20:02 -05:00
58605fd278 add dfu functionality 2018-12-31 15:06:31 -05:00
d726465b67 combine into solotool.py for simplicity 2018-12-31 14:27:15 -05:00
4fe98ef560 rename to solotool 2018-12-31 13:11:23 -05:00
ea7ab508bc Merge pull request #46 from SoloKeysSec/usb-cdc
Usb cdc
2018-12-31 13:06:38 -05:00
f2a04ff1ff add license 2018-12-31 13:06:02 -05:00
c8531d3870 Update udev.md 2018-12-31 14:39:16 +01:00
ff2600a1fc Update udev.md 2018-12-31 14:36:11 +01:00
a4f0744a6e Create 99-solo.rules 2018-12-31 14:35:09 +01:00
71fbf37f69 Update udev.md 2018-12-31 14:32:13 +01:00
a219b4f7d9 Add udev rule for Solo 2018-12-31 14:28:53 +01:00
00ad1dd0ce add serial script 2018-12-30 23:52:14 -05:00
2144816e0b Update device.c 2018-12-30 23:08:35 -05:00
80934f3e3b dont trust wIndex 2018-12-30 23:08:03 -05:00
05d99120cd add CDC USB profile, now can see debug messages from just USB 2018-12-30 23:04:39 -05:00
57879291cc Update usbd_desc.c 2018-12-30 16:06:30 -05:00
fbddf051c8 Nit: hacker documentation 2018-12-20 19:24:19 -08:00
ebd24e6181 Merge pull request #42 from 0x0ece/readme
New README and license
2018-12-18 17:45:18 -05:00
bbc61d5743 New README and license 2018-12-16 16:19:40 -08:00
ab06837628 update solo hacker key + cert 2018-12-10 21:22:48 -05:00
2a8498210c update solo hacker key 2018-12-10 21:21:56 -05:00
db0642eeab make different USB name for solo hacker 2018-12-10 20:37:32 -05:00
a96ff8eb63 move attestion key to not be part of firmware 2018-12-10 20:37:12 -05:00
94140a0aa9 pubkey 2018-12-08 23:29:29 -05:00
09778c7c51 small script fixes 2018-12-08 23:28:43 -05:00
5dd3355bd8 add wink command 2018-12-08 20:37:30 -05:00
51cf2d5ec9 Merge pull request #39 from SoloKeysSec/bootloader
Bootloader
2018-12-08 14:44:27 -05:00
15a1fb1e5b fix pc build 2018-12-06 23:48:46 -05:00
e360fa0097 document 2018-12-06 23:40:18 -05:00
827a7da443 less obfuscated mkdocs 2018-12-06 22:38:48 -05:00
1a07b4a73a add rng command 2018-12-05 19:35:22 -05:00
beedc24839 option to disable solo bootloader 2018-12-05 00:14:28 -05:00
b9ebde22e5 memory org and solo hacker build recipe 2018-12-05 00:13:34 -05:00
cbf021c7a8 official solo pid 2018-12-04 23:11:48 -05:00
5ee91048e2 organize memory layout options for debug/release 2018-12-04 21:12:21 -05:00
173b8833ce booting to dfu, detaching, fast flash write 2018-12-04 20:23:06 -05:00
b475c8391a this shouldnt run twice in a row or device can get bricked 2018-12-04 19:34:30 -05:00
5a636d1ebe boot directly st bootlaoder 2018-12-04 19:14:11 -05:00
97b715881b boot directly to solo bootloader for solo hacker 2018-12-04 01:30:53 -05:00
b0cc9cf582 program using just hid protocol, quicker 2018-12-04 00:15:58 -05:00
5a96e82f4d python script for progamming via solo bootloader 2018-12-03 23:01:51 -05:00
9b4b18e1a4 more configurable led 2018-12-03 20:30:35 -05:00
e107a9aa86 refactor 2018-12-03 20:06:44 -05:00
aece05b2e8 remove dead code 2018-12-03 00:14:26 -05:00
eb39e0f2c4 reboot and pass tests 2018-12-03 00:01:41 -05:00
bfa2d2830d signed update working 2018-12-02 23:31:34 -05:00
0c461bb5d8 refactor makefiles, document how to build 2018-12-02 21:58:15 -05:00
9ff5dc6373 bug fixes, now it boots application 2018-12-02 20:30:28 -05:00
ac7950f4c4 remove printf references, add bootloader script, merge hex files 2018-12-01 17:10:49 -05:00
93d4112bc3 bootloader compiles 2018-12-01 14:42:49 -05:00
5ba11b1c40 Merge pull request #37 from tiena2cva/tiena2cva-edit-readme
Update README.md. Edit typo mistake.
2018-11-29 13:46:45 +01:00
673470540d Update README.md. Edit typo mistake. 2018-11-29 10:30:05 +07:00
1a9548c0f0 Update README.md 2018-11-25 08:41:58 -05:00
50f565895f Merge pull request #33 from SoloKeysSec/fix-pc
Fix pc
2018-11-23 06:55:15 -05:00
296d2e6c74 fix issues with tests 2018-11-23 11:51:54 -05:00
d402df42e2 remove un-used recipes 2018-11-23 11:51:38 -05:00
eb4a29edc6 update pc build 2018-11-23 11:51:11 -05:00
ff682d6b5e remove debug statements 2018-11-23 11:50:51 -05:00
341 changed files with 17162 additions and 74798 deletions

228
.all-contributorsrc Normal file
View File

@ -0,0 +1,228 @@
{
"files": [
"README.md"
],
"imageSize": 100,
"commit": false,
"contributors": [
{
"login": "szszszsz",
"name": "Szczepan Zalega",
"avatar_url": "https://avatars0.githubusercontent.com/u/17005426?v=4",
"profile": "https://github.com/szszszsz",
"contributions": [
"code",
"doc",
"ideas"
]
},
{
"login": "Wesseldr",
"name": "Wessel dR",
"avatar_url": "https://avatars1.githubusercontent.com/u/4012809?v=4",
"profile": "https://github.com/Wesseldr",
"contributions": [
"doc"
]
},
{
"login": "agl",
"name": "Adam Langley",
"avatar_url": "https://avatars3.githubusercontent.com/u/21203?v=4",
"profile": "https://www.imperialviolet.org",
"contributions": [
"bug",
"code"
]
},
{
"login": "merlokk",
"name": "Oleg Moiseenko",
"avatar_url": "https://avatars2.githubusercontent.com/u/807634?v=4",
"profile": "http://www.lotteam.com",
"contributions": [
"code"
]
},
{
"login": "aseigler",
"name": "Alex Seigler",
"avatar_url": "https://avatars1.githubusercontent.com/u/6605560?v=4",
"profile": "https://github.com/aseigler",
"contributions": [
"bug"
]
},
{
"login": "dschuermann",
"name": "Dominik Schürmann",
"avatar_url": "https://avatars3.githubusercontent.com/u/321888?v=4",
"profile": "https://www.cotech.de/services/",
"contributions": [
"bug"
]
},
{
"login": "ehershey",
"name": "Ernie Hershey",
"avatar_url": "https://avatars0.githubusercontent.com/u/286008?v=4",
"profile": "https://github.com/ehershey",
"contributions": [
"doc"
]
},
{
"login": "YakBizzarro",
"name": "Andrea Corna",
"avatar_url": "https://avatars1.githubusercontent.com/u/767740?v=4",
"profile": "https://github.com/YakBizzarro",
"contributions": [
"infra"
]
},
{
"login": "pjz",
"name": "Paul Jimenez",
"avatar_url": "https://avatars3.githubusercontent.com/u/11100?v=4",
"profile": "https://place.org/~pj/",
"contributions": [
"infra",
"code"
]
},
{
"login": "yparitcher",
"name": "yparitcher",
"avatar_url": "https://avatars0.githubusercontent.com/u/38916402?v=4",
"profile": "https://github.com/yparitcher",
"contributions": [
"ideas",
"maintenance"
]
},
{
"login": "StoyanDimitrov",
"name": "StoyanDimitrov",
"avatar_url": "https://avatars1.githubusercontent.com/u/10962709?v=4",
"profile": "https://github.com/StoyanDimitrov",
"contributions": [
"doc"
]
},
{
"login": "alphathegeek",
"name": "alphathegeek",
"avatar_url": "https://avatars2.githubusercontent.com/u/51253712?v=4",
"profile": "https://github.com/alphathegeek",
"contributions": [
"ideas"
]
},
{
"login": "rgerganov",
"name": "Radoslav Gerganov",
"avatar_url": "https://avatars2.githubusercontent.com/u/271616?v=4",
"profile": "https://xakcop.com",
"contributions": [
"ideas",
"code"
]
},
{
"login": "manuel-domke",
"name": "Manuel Domke",
"avatar_url": "https://avatars3.githubusercontent.com/u/10274356?v=4",
"profile": "http://13-37.org",
"contributions": [
"ideas",
"code",
"business"
]
},
{
"login": "esden",
"name": "Piotr Esden-Tempski",
"avatar_url": "https://avatars3.githubusercontent.com/u/17334?v=4",
"profile": "http://1bitsquared.com",
"contributions": [
"business"
]
},
{
"login": "m3hm00d",
"name": "f.m3hm00d",
"avatar_url": "https://avatars1.githubusercontent.com/u/42179593?v=4",
"profile": "https://github.com/m3hm00d",
"contributions": [
"doc"
]
},
{
"login": "hughsie",
"name": "Richard Hughes",
"avatar_url": "https://avatars0.githubusercontent.com/u/151380?v=4",
"profile": "http://blogs.gnome.org/hughsie/",
"contributions": [
"ideas",
"code",
"infra",
"tool"
]
},
{
"login": "kimusan",
"name": "Kim Schulz",
"avatar_url": "https://avatars1.githubusercontent.com/u/1150049?v=4",
"profile": "http://www.schulz.dk",
"contributions": [
"business",
"ideas"
]
},
{
"login": "oplik0",
"name": "Jakub",
"avatar_url": "https://avatars2.githubusercontent.com/u/25460763?v=4",
"profile": "https://github.com/oplik0",
"contributions": [
"bug"
]
},
{
"login": "jolo1581",
"name": "Jan A.",
"avatar_url": "https://avatars1.githubusercontent.com/u/53423977?v=4",
"profile": "https://github.com/jolo1581",
"contributions": [
"code",
"doc"
]
},
{
"login": "ccinelli",
"name": "ccinelli",
"avatar_url": "https://avatars0.githubusercontent.com/u/38021940?v=4",
"profile": "https://github.com/ccinelli",
"contributions": [
"infra",
"test"
]
},
{
"login": "Nitrokey",
"name": "Nitrokey",
"avatar_url": "https://avatars1.githubusercontent.com/u/9438831?v=4",
"profile": "https://www.nitrokey.com",
"contributions": [
"code",
"test",
"ideas"
]
}
],
"contributorsPerLine": 7,
"projectName": "solo",
"projectOwner": "solokeys",
"repoType": "github",
"repoHost": "https://github.com"
}

19
.editorconfig Normal file
View File

@ -0,0 +1,19 @@
https://github.com/editorconfig/editorconfig/wiki/EditorConfig-Properties
# editorconfig.org
root = true
[*]
charset = utf-8
end_of_line = lf
indent_style = space
indent_size = 4
tab_width = 4
trim_trailing_whitespace = true
insert_final_newline = true
[Makefile]
indent_style = tab
[*.{yml,yaml}]
indent_size = 2

1
.envrc Normal file
View File

@ -0,0 +1 @@
source venv/bin/activate

9
.gitignore vendored
View File

@ -34,7 +34,8 @@
*.app
*.i*86
*.x86_64
*.hex
targets/*/*.hex
targets/*/*.sha2
# Debug files
*.dSYM/
@ -75,7 +76,13 @@ tools/python-fido2/*
site/
_site/
venv/
env2/
env3/
.project
.tags*
targets/*/docs/
main
builds/*
tools/testing/.idea/*
tools/testing/tests/__pycache__/*

8
.gitmodules vendored
View File

@ -1,9 +1,6 @@
[submodule "tinycbor"]
path = tinycbor
url = https://github.com/intel/tinycbor
[submodule "python-fido2"]
path = python-fido2
url = https://github.com/SoloKeysSec/python-fido2
[submodule "crypto/micro-ecc"]
path = crypto/micro-ecc
url = https://github.com/kmackay/micro-ecc.git
@ -12,4 +9,7 @@
url = https://github.com/kokke/tiny-AES-c
[submodule "targets/stm32l442/dfuse-tool"]
path = targets/stm32l442/dfuse-tool
url = https://github.com/SoloKeysSec/dfuse-tool
url = https://github.com/solokeys/dfuse-tool
[submodule "crypto/cifra"]
path = crypto/cifra
url = https://github.com/solokeys/cifra.git

View File

@ -1,4 +1,4 @@
dist: trusty
dist: xenial
language: c
compiler: gcc
addons:
@ -6,7 +6,15 @@ addons:
sources:
- ubuntu-toolchain-r-test
packages:
- gcc-7
- gcc-8
- cppcheck
services:
- docker
before_install:
- sudo add-apt-repository -y ppa:team-gcc-arm-embedded/ppa
- sudo apt-get update -q
- sudo apt-get install -y gcc-arm-embedded python3-venv
script:
- export CC=gcc-7
- make test
- export CC=gcc-8
- pyenv shell 3.6.7
- make travis

1
99-solo.rules Symbolic link
View File

@ -0,0 +1 @@
udev/70-solokeys-access.rules

1
ALPHA_VERSION Normal file
View File

@ -0,0 +1 @@
2.0.0

38
Dockerfile Normal file
View File

@ -0,0 +1,38 @@
FROM debian:9.11-slim
MAINTAINER SoloKeys <hello@solokeys.com>
# Install necessary packages
RUN apt-get update \
&& apt-get install -y --no-install-recommends \
ca-certificates \
make \
wget \
bzip2 \
git \
&& rm -rf /var/lib/apt/lists/*
# Install ARM compiler
RUN set -eux; \
url="https://developer.arm.com/-/media/Files/downloads/gnu-rm/8-2019q3/RC1.1/gcc-arm-none-eabi-8-2019-q3-update-linux.tar.bz2?revision=c34d758a-be0c-476e-a2de-af8c6e16a8a2?product=GNU%20Arm%20Embedded%20Toolchain,64-bit,,Linux,8-2019-q3-update"; \
wget -O gcc.tar.bz2 "$url"; \
echo "6341f11972dac8de185646d0fbd73bfc gcc.tar.bz2" | md5sum -c -; \
echo "b50b02b0a16e5aad8620e9d7c31110ef285c1dde28980b1a9448b764d77d8f92 gcc.tar.bz2" | sha256sum -c -; \
tar -C /opt -xf gcc.tar.bz2; \
rm gcc.tar.bz2;
# Python3.7: for solo-python (merging etc.)
RUN set -eux; \
url="https://repo.anaconda.com/miniconda/Miniconda3-4.5.12-Linux-x86_64.sh"; \
wget -O miniconda.sh "$url"; \
echo "866ae9dff53ad0874e1d1a60b1ad1ef8 miniconda.sh" | md5sum -c -; \
echo "e5e5b4cd2a918e0e96b395534222773f7241dc59d776db1b9f7fedfcb489157a miniconda.sh" | sha256sum -c -; \
bash ./miniconda.sh -b -p /opt/conda; \
ln -s /opt/conda/bin/python /usr/local/bin/python3; \
ln -s /opt/conda/bin/python /usr/local/bin/python; \
ln -s /opt/conda/bin/pip /usr/local/bin/pip3; \
ln -s /opt/conda/bin/pip /usr/local/bin/pip; \
rm miniconda.sh; \
pip install -U pip
# solo-python (Python3.7 script for merging etc.)
RUN pip install -U solo-python

20
LICENSE
View File

@ -1,19 +1 @@
Copyright 2018 Conor Patrick
Permission is hereby granted, free of charge, to any person obtaining a copy of
this software and associated documentation files (the "Software"), to deal in
the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
of the Software, and to permit persons to whom the Software is furnished to do
so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
Apache-2.0 OR MIT

201
LICENSE-APACHE Normal file
View File

@ -0,0 +1,201 @@
Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
1. Definitions.
"License" shall mean the terms and conditions for use, reproduction,
and distribution as defined by Sections 1 through 9 of this document.
"Licensor" shall mean the copyright owner or entity authorized by
the copyright owner that is granting the License.
"Legal Entity" shall mean the union of the acting entity and all
other entities that control, are controlled by, or are under common
control with that entity. For the purposes of this definition,
"control" means (i) the power, direct or indirect, to cause the
direction or management of such entity, whether by contract or
otherwise, or (ii) ownership of fifty percent (50%) or more of the
outstanding shares, or (iii) beneficial ownership of such entity.
"You" (or "Your") shall mean an individual or Legal Entity
exercising permissions granted by this License.
"Source" form shall mean the preferred form for making modifications,
including but not limited to software source code, documentation
source, and configuration files.
"Object" form shall mean any form resulting from mechanical
transformation or translation of a Source form, including but
not limited to compiled object code, generated documentation,
and conversions to other media types.
"Work" shall mean the work of authorship, whether in Source or
Object form, made available under the License, as indicated by a
copyright notice that is included in or attached to the work
(an example is provided in the Appendix below).
"Derivative Works" shall mean any work, whether in Source or Object
form, that is based on (or derived from) the Work and for which the
editorial revisions, annotations, elaborations, or other modifications
represent, as a whole, an original work of authorship. For the purposes
of this License, Derivative Works shall not include works that remain
separable from, or merely link (or bind by name) to the interfaces of,
the Work and Derivative Works thereof.
"Contribution" shall mean any work of authorship, including
the original version of the Work and any modifications or additions
to that Work or Derivative Works thereof, that is intentionally
submitted to Licensor for inclusion in the Work by the copyright owner
or by an individual or Legal Entity authorized to submit on behalf of
the copyright owner. For the purposes of this definition, "submitted"
means any form of electronic, verbal, or written communication sent
to the Licensor or its representatives, including but not limited to
communication on electronic mailing lists, source code control systems,
and issue tracking systems that are managed by, or on behalf of, the
Licensor for the purpose of discussing and improving the Work, but
excluding communication that is conspicuously marked or otherwise
designated in writing by the copyright owner as "Not a Contribution."
"Contributor" shall mean Licensor and any individual or Legal Entity
on behalf of whom a Contribution has been received by Licensor and
subsequently incorporated within the Work.
2. Grant of Copyright License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
copyright license to reproduce, prepare Derivative Works of,
publicly display, publicly perform, sublicense, and distribute the
Work and such Derivative Works in Source or Object form.
3. Grant of Patent License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
(except as stated in this section) patent license to make, have made,
use, offer to sell, sell, import, and otherwise transfer the Work,
where such license applies only to those patent claims licensable
by such Contributor that are necessarily infringed by their
Contribution(s) alone or by combination of their Contribution(s)
with the Work to which such Contribution(s) was submitted. If You
institute patent litigation against any entity (including a
cross-claim or counterclaim in a lawsuit) alleging that the Work
or a Contribution incorporated within the Work constitutes direct
or contributory patent infringement, then any patent licenses
granted to You under this License for that Work shall terminate
as of the date such litigation is filed.
4. Redistribution. You may reproduce and distribute copies of the
Work or Derivative Works thereof in any medium, with or without
modifications, and in Source or Object form, provided that You
meet the following conditions:
(a) You must give any other recipients of the Work or
Derivative Works a copy of this License; and
(b) You must cause any modified files to carry prominent notices
stating that You changed the files; and
(c) You must retain, in the Source form of any Derivative Works
that You distribute, all copyright, patent, trademark, and
attribution notices from the Source form of the Work,
excluding those notices that do not pertain to any part of
the Derivative Works; and
(d) If the Work includes a "NOTICE" text file as part of its
distribution, then any Derivative Works that You distribute must
include a readable copy of the attribution notices contained
within such NOTICE file, excluding those notices that do not
pertain to any part of the Derivative Works, in at least one
of the following places: within a NOTICE text file distributed
as part of the Derivative Works; within the Source form or
documentation, if provided along with the Derivative Works; or,
within a display generated by the Derivative Works, if and
wherever such third-party notices normally appear. The contents
of the NOTICE file are for informational purposes only and
do not modify the License. You may add Your own attribution
notices within Derivative Works that You distribute, alongside
or as an addendum to the NOTICE text from the Work, provided
that such additional attribution notices cannot be construed
as modifying the License.
You may add Your own copyright statement to Your modifications and
may provide additional or different license terms and conditions
for use, reproduction, or distribution of Your modifications, or
for any such Derivative Works as a whole, provided Your use,
reproduction, and distribution of the Work otherwise complies with
the conditions stated in this License.
5. Submission of Contributions. Unless You explicitly state otherwise,
any Contribution intentionally submitted for inclusion in the Work
by You to the Licensor shall be under the terms and conditions of
this License, without any additional terms or conditions.
Notwithstanding the above, nothing herein shall supersede or modify
the terms of any separate license agreement you may have executed
with Licensor regarding such Contributions.
6. Trademarks. This License does not grant permission to use the trade
names, trademarks, service marks, or product names of the Licensor,
except as required for reasonable and customary use in describing the
origin of the Work and reproducing the content of the NOTICE file.
7. Disclaimer of Warranty. Unless required by applicable law or
agreed to in writing, Licensor provides the Work (and each
Contributor provides its Contributions) on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
implied, including, without limitation, any warranties or conditions
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
PARTICULAR PURPOSE. You are solely responsible for determining the
appropriateness of using or redistributing the Work and assume any
risks associated with Your exercise of permissions under this License.
8. Limitation of Liability. In no event and under no legal theory,
whether in tort (including negligence), contract, or otherwise,
unless required by applicable law (such as deliberate and grossly
negligent acts) or agreed to in writing, shall any Contributor be
liable to You for damages, including any direct, indirect, special,
incidental, or consequential damages of any character arising as a
result of this License or out of the use or inability to use the
Work (including but not limited to damages for loss of goodwill,
work stoppage, computer failure or malfunction, or any and all
other commercial damages or losses), even if such Contributor
has been advised of the possibility of such damages.
9. Accepting Warranty or Additional Liability. While redistributing
the Work or Derivative Works thereof, You may choose to offer,
and charge a fee for, acceptance of support, warranty, indemnity,
or other liability obligations and/or rights consistent with this
License. However, in accepting such obligations, You may act only
on Your own behalf and on Your sole responsibility, not on behalf
of any other Contributor, and only if You agree to indemnify,
defend, and hold each Contributor harmless for any liability
incurred by, or claims asserted against, such Contributor by reason
of your accepting any such warranty or additional liability.
END OF TERMS AND CONDITIONS
APPENDIX: How to apply the Apache License to your work.
To apply the Apache License to your work, attach the following
boilerplate notice, with the fields enclosed by brackets "[]"
replaced with your own identifying information. (Don't include
the brackets!) The text should be enclosed in the appropriate
comment syntax for the file format. We also recommend that a
file or class name and description of purpose be included on the
same "printed page" as the copyright notice for easier
identification within third-party archives.
Copyright [yyyy] [name of copyright owner]
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.

23
LICENSE-MIT Normal file
View File

@ -0,0 +1,23 @@
Permission is hereby granted, free of charge, to any
person obtaining a copy of this software and associated
documentation files (the "Software"), to deal in the
Software without restriction, including without
limitation the rights to use, copy, modify, merge,
publish, distribute, sublicense, and/or sell copies of
the Software, and to permit persons to whom the Software
is furnished to do so, subject to the following
conditions:
The above copyright notice and this permission notice
shall be included in all copies or substantial portions
of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF
ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT
SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR
IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
DEALINGS IN THE SOFTWARE.

154
Makefile
View File

@ -7,13 +7,12 @@
#define uECC_arm64 6
#define uECC_avr 7
platform=2
ecc_platform=2
EFM32_DEBUGGER= -s 440083537 --device EFM32JG1B200F128GM32
#EFM32_DEBUGGER= -s 440121060 #dev board
src = $(wildcard pc/*.c) $(wildcard fido2/*.c) $(wildcard fido2/extensions/*.c) \
$(wildcard crypto/sha256/*.c) crypto/tiny-AES-c/aes.c
src = $(wildcard pc/*.c) $(wildcard fido2/*.c) $(wildcard crypto/sha256/*.c) crypto/tiny-AES-c/aes.c
obj = $(src:.c=.o) uECC.o
obj = $(src:.c=.o) crypto/micro-ecc/uECC.o
LIBCBOR = tinycbor/lib/libtinycbor.a
@ -23,24 +22,29 @@ else
export LDFLAGS = -Wl,--gc-sections
endif
LDFLAGS += $(LIBCBOR)
CFLAGS = -O2 -fdata-sections -ffunction-sections
VERSION_FULL:=$(shell git describe)
VERSION:=$(shell python -c 'print("$(VERSION_FULL)".split("-")[0])')
VERSION_MAJ:=$(shell python -c 'print("$(VERSION)".split(".")[0])')
VERSION_MIN:=$(shell python -c 'print("$(VERSION)".split(".")[1])')
VERSION_PAT:=$(shell python -c 'print("$(VERSION)".split(".")[2])')
VERSION_FLAGS= -DSOLO_VERSION_MAJ=$(VERSION_MAJ) -DSOLO_VERSION_MIN=$(VERSION_MIN) \
-DSOLO_VERSION_PATCH=$(VERSION_PAT) -DSOLO_VERSION=\"$(VERSION_FULL)\"
CFLAGS = -O2 -fdata-sections -ffunction-sections $(VERSION_FLAGS) -g
INCLUDES = -I./tinycbor/src -I./crypto/sha256 -I./crypto/micro-ecc/ -Icrypto/tiny-AES-c/ -I./fido2/ -I./pc -I./fido2/extensions
INCLUDES += -I./crypto/cifra/src
CFLAGS += $(INCLUDES)
# for crypto/tiny-AES-c
CFLAGS += -DAES256=1
CFLAGS += -DAES256=1 -DAPP_CONFIG=\"app.h\" -DSOLO_EXPERIMENTAL=1
name = main
.PHONY: all
all: python-fido2 main
.PHONY: test
test:
$(MAKE) -C . main
$(MAKE) -C . testgcm
./testgcm
.PHONY: all $(LIBCBOR) black blackcheck cppcheck wink fido2-test clean full-clean travis test clean version
all: main
tinycbor/Makefile crypto/tiny-AES-c/aes.c:
git submodule update --init
@ -48,72 +52,94 @@ tinycbor/Makefile crypto/tiny-AES-c/aes.c:
.PHONY: cbor
cbor: $(LIBCBOR)
$(LIBCBOR): tinycbor/Makefile
cd tinycbor/ && $(MAKE) clean && $(MAKE) -j8
$(LIBCBOR):
cd tinycbor/ && $(MAKE) clean && $(MAKE) LDFLAGS='' -j8
.PHONY: efm8prog
efm8prog:
cd './targets/efm8\Keil 8051 v9.53 - Debug' && $(MAKE) all
flashefm8.exe -part EFM8UB10F8G -sn 440105518 -erase
flashefm8.exe -part EFM8UB10F8G -sn 440105518 -upload './targets/efm8/Keil 8051 v9.53 - Debug/efm8.hex'
version:
@git describe
.PHONY: efm32com efm32prog efm32read efm32bootprog
efm32com:
cd './targets/efm32/GNU ARM v7.2.1 - Debug' && $(MAKE) all
efm32prog: efm32com
commander flash './targets/efm32/GNU ARM v7.2.1 - Debug/EFM32.hex' $(EFM32_DEBUGGER) -p "0x1E7FC:0x00000000:4"
efm32read: efm32com
commander swo read $(EFM32_DEBUGGER)
efm32bootprog: efm32com
commander flash './efm32boot/GNU ARM v7.2.1 - Debug/efm32boot.hex' $(EFM32_DEBUGGER) --masserase
test: venv
$(MAKE) clean
$(MAKE) -C . main
$(MAKE) clean
$(MAKE) -C ./targets/stm32l432 test PREFIX=$(PREFIX) "VENV=$(VENV)" VERSION_FULL=${VERSION_FULL}
$(MAKE) clean
$(MAKE) cppcheck
$(name): $(obj) $(LIBCBOR)
$(CC) $(LDFLAGS) -o $@ $(obj) $(LDFLAGS)
crypto/aes-gcm/aes_gcm.o:
$(CC) -c crypto/aes-gcm/aes_gcm.c $(CFLAGS) -DTEST -o crypto/aes-gcm/aes_gcm.o
testgcm: $(obj) $(LIBCBOR) crypto/aes-gcm/aes_gcm.o
$(CC) -c fido2/main.c $(CFLAGS) -DTEST -o fido2/main.o
$(CC) $(LDFLAGS) -o $@ $^ $(LDFLAGS)
uECC.o: ./crypto/micro-ecc/uECC.c
$(CC) -c -o $@ $^ -O2 -fdata-sections -ffunction-sections -DuECC_PLATFORM=$(platform) -I./crypto/micro-ecc/
# python virtualenv
crypto/micro-ecc/uECC.o: ./crypto/micro-ecc/uECC.c
$(CC) -c -o $@ $^ -O2 -fdata-sections -ffunction-sections -DuECC_PLATFORM=$(ecc_platform) -I./crypto/micro-ecc/
venv:
@if ! which virtualenv >/dev/null ; then \
echo "ERR: Sorry, no python virtualenv found. Please consider installing " ;\
echo " it via something like:" ;\
echo " sudo apt install python-virtualenv" ;\
echo " or maybe:" ;\
echo " pip install virtualenv" ;\
fi
virtualenv venv
./venv/bin/pip install wheel
python3 -m venv venv
venv/bin/pip -q install --upgrade pip
venv/bin/pip -q install --upgrade -r tools/requirements.txt
venv/bin/pip -q install --upgrade black
.PHONY: python-fido2
python-fido2: venv
cd python-fido2/ && ../venv/bin/python setup.py install
# selectively reformat our own code
black: venv
venv/bin/black --skip-string-normalization --check tools/
venv/bin/mkdocs: venv
./venv/bin/pip install mkdocs mkdocs-material
wink: venv
venv/bin/solo key wink
.PHONY: docsrv
docsrv: venv/bin/mkdocs
./venv/bin/mkdocs serve
fido2-test: venv
venv/bin/python tools/ctap_test.py
.PHONY: fido2-test
fido2-test:
./venv/bin/python tools/ctap_test.py
update:
git fetch --tags
git checkout master
git rebase origin/master
git submodule update --init --recursive
DOCKER_TOOLCHAIN_IMAGE := "solokeys/solo-firmware-toolchain"
docker-build-toolchain:
docker build -t $(DOCKER_TOOLCHAIN_IMAGE) .
docker tag $(DOCKER_TOOLCHAIN_IMAGE):latest $(DOCKER_TOOLCHAIN_IMAGE):${VERSION}
docker tag $(DOCKER_TOOLCHAIN_IMAGE):latest $(DOCKER_TOOLCHAIN_IMAGE):${VERSION_MAJ}
docker tag $(DOCKER_TOOLCHAIN_IMAGE):latest $(DOCKER_TOOLCHAIN_IMAGE):${VERSION_MAJ}.${VERSION_MIN}
uncached-docker-build-toolchain:
docker build --no-cache -t $(DOCKER_TOOLCHAIN_IMAGE) .
docker tag $(DOCKER_TOOLCHAIN_IMAGE):latest $(DOCKER_TOOLCHAIN_IMAGE):${VERSION}
docker tag $(DOCKER_TOOLCHAIN_IMAGE):latest $(DOCKER_TOOLCHAIN_IMAGE):${VERSION_MAJ}
docker tag $(DOCKER_TOOLCHAIN_IMAGE):latest $(DOCKER_TOOLCHAIN_IMAGE):${VERSION_MAJ}.${VERSION_MIN}
docker-build-all:
docker run --rm -v "$(CURDIR)/builds:/builds" \
-v "$(CURDIR):/solo" \
$(DOCKER_TOOLCHAIN_IMAGE) "solo/in-docker-build.sh" ${VERSION_FULL}
CPPCHECK_FLAGS=--quiet --error-exitcode=2
cppcheck:
cppcheck $(CPPCHECK_FLAGS) crypto/aes-gcm
cppcheck $(CPPCHECK_FLAGS) crypto/sha256
cppcheck $(CPPCHECK_FLAGS) fido2
cppcheck $(CPPCHECK_FLAGS) pc
clean:
rm -f *.o main.exe main testgcm $(obj)
rm -f *.o main.exe main $(obj)
for f in crypto/tiny-AES-c/Makefile tinycbor/Makefile ; do \
if [ -f "$$f" ]; then \
(cd `dirname $$f` ; git checkout -- .) ;\
fi ;\
done
full-clean: clean
rm -rf venv
test-docker:
rm -rf builds/*
$(MAKE) uncached-docker-build-toolchain
# Check if there are 4 docker images/tas named "solokeys/solo-firmware-toolchain"
NTAGS=$$(docker images | grep -c "solokeys/solo-firmware-toolchain") && [ $$NTAGS -eq 4 ]
$(MAKE) docker-build-all
travis:
$(MAKE) test VENV=". ../../venv/bin/activate;"
$(MAKE) test-docker
$(MAKE) black

279
README.md
View File

@ -1,145 +1,216 @@
![GitHub](https://img.shields.io/github/license/mashape/apistatus.svg)
[![Kickstarter](https://img.shields.io/badge/kickstarter-back%20us-red.svg)](https://solokeys.com/kickstarter)
[![Build Status](https://travis-ci.com/SoloKeysSec/solo.svg?branch=master)](https://travis-ci.com/SoloKeysSec/solo)
[![Discourse Status](https://img.shields.io/discourse/https/meta.discourse.org/status.svg)](https://discourse.solokeys.com)
[![latest release](https://img.shields.io/github/release/solokeys/solo.svg)](https://update.solokeys.com/)
[![Keybase Chat](https://img.shields.io/badge/chat-on%20keybase-brightgreen.svg)](https://keybase.io/team/solokeys.public)
[![Build Status](https://travis-ci.com/solokeys/solo.svg?style=flat-square&branch=master)](https://travis-ci.com/solokeys/solo)
Solo is an open source security key, and you can get one at [solokeys.com](https://solokeys.com).
# Solo
[<img src="https://static.solokeys.com/images/photos/hero-on-white-cropped.png" width="600">](https://solokeys.com)
Solo is an affordable security key that implements FIDO2/U2F and supports USB, NFC, and extensions. Extensions
include SSH, GPG, and cryptocurrency. Solo is an upgrade to [U2F Zero](https://github.com/conorpp/u2f-zero) and is a work in progress.
Solo supports FIDO2 and U2F standards for strong two-factor authentication and password-less login, and it will protect you against phishing and other online attacks. With colored cases and multilingual guides we want to make secure login more personable and accessible to everyone around the globe.
> Technical documentation for this project is contained in [docs/](https://github.com/SoloKeysSec/solo/tree/master/docs), built with [MkDocs](https://solo.solokeys.io/documenting/) and deployed automatically to <https://solo.solokeys.io>, part of our technical documentation suite hosted at <https://docs.solokeys.io>.
This repo contains the Solo firmware, including implementations of FIDO2 and U2F (CTAP2 and CTAP) over USB and NFC. The main implementation is for STM32L432, but it is easily portable.
![](https://i.imgur.com/cXWtI1D.png)
![](https://i.imgur.com/vwFbsQW.png?1)
For development no hardware is needed, Solo also runs as a standalone application for Windows, Linux, and Mac OSX. If you like (or want to learn) hardware instead, you can run Solo on the NUCLEO-L432KC development board, or we make Solo for Hacker, an unlocked version of Solo that lets you customize its firmware.
The Solo FIDO2/U2F code base is designed to be easily ported to different embedded systems.
Right now, it has been ported to the NRF52840 and EFM32J. Soon to be supported is the STM32L442.
No hardware is needed for development. You can run and extend the FIDO2 code base
using just your PC.
# Security
Solo is based on the STM32L442 microcontroller. It offers the following security features.
Solo is based on the STM32L432 microcontroller. It offers the following security features.
- True random number generation to guarantee random keys.
- Firewall feature for code and secret data isolation.
- Locked flash
It also has up to 256 KB of memory, meaning it has room for side channel and fault resistant crypto implementations, plus other features.
Each chip ships with a read-only USB bootloader, put in place by ST. This can be leveraged to completely reset and reprogram the device, to make sure you can trust it's running the right code. The bootloader can be disabled.
# How do I get one?
We are still working on open sourcing an implementation that anyone can cheaply
build and program, just like with U2F Zero. This will be released soon. It will be easy to solder :)
In the meantime, you can port the code to your favorite microcontroller, or support
us by [signing up for our Kickstarter](https://solokeys.com/kickstarter). Our aim is to crowdfund enough to make an economic
bulk order and provide open source security tokens for everyone that is interested. We will offer
"hackable" tokens that come with USB bootloaders and are reprogrammable.
[Sign up here](https://solokeys.com/kickstarter)!
- Security isolation so only simple & secure parts of code can handle keys.
- Flash protection from both external use and untrusted code segments.
- 256 KB of memory to support hardened crypto implementations and, later, additional features such as OpenPGP or SSH.
- No NDA needed to develop for.
# Setting up
# Solo for Hackers
Clone solo and build it
Solo for Hacker is a special version of Solo that let you customize its firmware, for example you can change the LED color, and even build advanced applications.
Check out [solokeys.com](https://solokeys.com), for options on where to buy Solo. Solo Hacker can be converted to a secure version, but normal Solo cannot be converted to a Hacker version.
If you have a Solo for Hacker, here's how you can load your own code on it. You can find more details, including how to permanently lock it, in our [documentation](https://docs.solokeys.io/solo/building/). We support Python3.
For example, if you want to turn off any blue light emission, you can edit [`led_rgb()`](https://github.com/solokeys/solo/blob/master/targets/stm32l432/src/app.h#L48) and change `LED_INIT_VALUE`
to be a different hex color.
Then recompile, load your new firmware, and enjoy a different LED color Solo.
In the Hacker version, hardware is the same but the firmware is unlocked, so you can 1) load an unsigned application, or 2) entirely reflash the key. By contrast, in a regular Solo you can only upgrade to a firmware signed by SoloKeys, and flash is locked and debug disabled permanently.
Hacker Solo isn't really secure so you should only use it for development. An attacker with physical access to a Solo for Hacker can reflash it following the steps above, and even a malware on your computer could possibly reflash it.
## Checking out the code
```bash
git clone --recurse-submodules https://github.com/solokeys/solo
cd solo
```
If you forgot the `--recurse-submodules` while cloning, simply run `git submodule update --init --recursive`.
`make update` will also checkout the latest code on `master` and submodules.
## Checking out the code to build a specific version
You can checkout the code to build a specific version of the firmware with:
```
VERSION_TO_BUILD=2.5.3
git fetch --tags
git checkout ${VERSION_TO_BUILD}
git submodule update --init --recursive
```
## Installing the toolchain
In order to compile ARM code, you need the ARM compiler and other things like bundling bootloader and firmware require the `solo-python` python package. Check our [documentation](https://docs.solokeys.io/solo/) for details
## Installing the toolkit and compiling in Docker
Alternatively, you can use Docker to create a container with the toolchain.
You can run:
```bash
git clone --recurse-submodules https://github.com/SoloKeysSec/solo
cd solo/
# Build the toolchain container
make docker-build-toolchain
git submodules init
git submodules update
# Build all versions of the firmware in the "builds" folder
make docker-build-all
```
The `builds` folder will contain all the variation on the firmware in `.hex` files.
## Build locally
If you have the toolchain installed on your machine you can build the firmware with:
```bash
cd targets/stm32l432
make cbor
make build-hacker
cd ../..
make venv
source venv/bin/activate
solo program aux enter-bootloader
solo program bootloader targets/stm32l432/solo.hex
```
# Developing Solo (No Hardware Needed)
Clone Solo and build it
```bash
git clone --recurse-submodules https://github.com/solokeys/solo
cd solo
make all
```
This builds our FIDO 2.0 and the U2F authenticator, as well as making a virtualenv in venv/
that has our python-fido2 fork installed.
This builds Solo as a standalone application. Solo application is set up to send and recv USB HID messages over UDP to ease development and reduce need for hardware.
Note that our python-fido2 fork will only connect to the software FIDO2 application,
not a hardware authenticator. Install Yubico's fork to do that.
Testing can be done using our fork of Yubico's client software, python-fido2. Our fork of python-fido2 has small changes to make it send USB HID over UDP to the authenticator application. You can install our fork by running the following:
```bash
pip install -r tools/requirements.txt
```
# Testing and development
The application is set up to send and recv USB HID messages over UDP to ease
development and reduce need for hardware.
Testing can be done using our fork of Yubico's client software, `python-fido2`.
Our fork of `python-fido2` has small changes to make it send
USB HID over UDP to the authenticator application.
Run FIDO 2 / U2F application.
Run the Solo application:
```bash
./main
```
Run example client software. This runs through a registration and authentication.
In another shell, you can run our [test suite](https://github.com/solokeys/fido2-tests).
```
./venv/bin/python python-fido2/examples/credential.py
```
You can find more details in our [documentation](https://docs.solokeys.io/solo/), including how to build on the the NUCLEO-L432KC development board.
Run the FIDO2 tests.
```
make fido2-test
```
Follow specifications to really dig in.
[https://fidoalliance.org/specs/fido-v2.0-ps-20170927/fido-client-to-authenticator-protocol-v2.0-ps-20170927.html](https://fidoalliance.org/specs/fido-v2.0-ps-20170927/fido-client-to-authenticator-protocol-v2.0-ps-20170927.html)
## Extensions
Extensions can be added to FIDO2/U2F to support things like SSH, GPG, and cryptocurrency.
Right now, an experimental cryptocurrency extension can be found in `fido2/extensions` and `web/index.html`.
More documentation to come.
The main goal is to expose an extensible API on Solo, like the following:
- Command to store private key
- Command to sign arbitrary hash
- Command to derive a public key
- Commands for setting/changing/authenticating a pin code (like in FIDO2)
- Command to expose entropy from TRNG.
Using these generic commands, various external programs can be implemented for the security key.
Since FIDO2/U2F are implemented, these programs can potentially work in the browser on desktops
and mobile devices, with no drivers needed to be installed.
## Porting
The main code base is in `fido2/`. See `targets/nrf52840`, `targets/efm32/src`, and `pc/`
for examples of FIDO2/U2F ports. In essence, you just need to reimplement `device.c`. Optionally you can
re-implement `crypto.c` to accelerate operations and/or add other security features.
More documentation to come.
# Documentation
Check out our [official documentation](https://solo.solokeys.io/).
Check out our [official documentation](https://docs.solokeys.io/solo/).
# Contributors
Contributors are welcome. The ultimate goal is to have a FIDO 2 hardware token
capable of USB, Bluetooth, and NFC interfaces. There could be multiple tokens
for each interface.
Look at the issues to see what is currently being worked on. Feel free to add issues as well.
# Contributors
Solo is an upgrade to [U2F Zero](https://github.com/conorpp/u2f-zero). It was born from Conor's passion for making secure hardware, and from our shared belief that security should be open to be trustworthy, in hardware like in software.
This project follows the [all-contributors](https://github.com/all-contributors/all-contributors) specification. Contributions of any kind welcome!
The ultimate goal is to have a FIDO2 security key supporting USB, NFC, and BLE interfaces, that can run on a variety of MCUs.
Look at the issues to see what is currently being worked on. Feel free to add issues as well.
Thanks goes to these wonderful people ([emoji key](https://allcontributors.org/docs/en/emoji-key)):
<!-- ALL-CONTRIBUTORS-LIST:START - Do not remove or modify this section -->
<!-- prettier-ignore -->
<table>
<tr>
<td align="center"><a href="https://github.com/szszszsz"><img src="https://avatars0.githubusercontent.com/u/17005426?v=4" width="100px;" alt="Szczepan Zalega"/><br /><sub><b>Szczepan Zalega</b></sub></a><br /><a href="https://github.com/solokeys/solo/commits?author=szszszsz" title="Code">💻</a> <a href="https://github.com/solokeys/solo/commits?author=szszszsz" title="Documentation">📖</a> <a href="#ideas-szszszsz" title="Ideas, Planning, & Feedback">🤔</a></td>
<td align="center"><a href="https://github.com/Wesseldr"><img src="https://avatars1.githubusercontent.com/u/4012809?v=4" width="100px;" alt="Wessel dR"/><br /><sub><b>Wessel dR</b></sub></a><br /><a href="https://github.com/solokeys/solo/commits?author=Wesseldr" title="Documentation">📖</a></td>
<td align="center"><a href="https://www.imperialviolet.org"><img src="https://avatars3.githubusercontent.com/u/21203?v=4" width="100px;" alt="Adam Langley"/><br /><sub><b>Adam Langley</b></sub></a><br /><a href="https://github.com/solokeys/solo/issues?q=author%3Aagl" title="Bug reports">🐛</a> <a href="https://github.com/solokeys/solo/commits?author=agl" title="Code">💻</a></td>
<td align="center"><a href="http://www.lotteam.com"><img src="https://avatars2.githubusercontent.com/u/807634?v=4" width="100px;" alt="Oleg Moiseenko"/><br /><sub><b>Oleg Moiseenko</b></sub></a><br /><a href="https://github.com/solokeys/solo/commits?author=merlokk" title="Code">💻</a></td>
<td align="center"><a href="https://github.com/aseigler"><img src="https://avatars1.githubusercontent.com/u/6605560?v=4" width="100px;" alt="Alex Seigler"/><br /><sub><b>Alex Seigler</b></sub></a><br /><a href="https://github.com/solokeys/solo/issues?q=author%3Aaseigler" title="Bug reports">🐛</a></td>
<td align="center"><a href="https://www.cotech.de/services/"><img src="https://avatars3.githubusercontent.com/u/321888?v=4" width="100px;" alt="Dominik Schürmann"/><br /><sub><b>Dominik Schürmann</b></sub></a><br /><a href="https://github.com/solokeys/solo/issues?q=author%3Adschuermann" title="Bug reports">🐛</a></td>
<td align="center"><a href="https://github.com/ehershey"><img src="https://avatars0.githubusercontent.com/u/286008?v=4" width="100px;" alt="Ernie Hershey"/><br /><sub><b>Ernie Hershey</b></sub></a><br /><a href="https://github.com/solokeys/solo/commits?author=ehershey" title="Documentation">📖</a></td>
</tr>
<tr>
<td align="center"><a href="https://github.com/YakBizzarro"><img src="https://avatars1.githubusercontent.com/u/767740?v=4" width="100px;" alt="Andrea Corna"/><br /><sub><b>Andrea Corna</b></sub></a><br /><a href="#infra-YakBizzarro" title="Infrastructure (Hosting, Build-Tools, etc)">🚇</a></td>
<td align="center"><a href="https://place.org/~pj/"><img src="https://avatars3.githubusercontent.com/u/11100?v=4" width="100px;" alt="Paul Jimenez"/><br /><sub><b>Paul Jimenez</b></sub></a><br /><a href="#infra-pjz" title="Infrastructure (Hosting, Build-Tools, etc)">🚇</a> <a href="https://github.com/solokeys/solo/commits?author=pjz" title="Code">💻</a></td>
<td align="center"><a href="https://github.com/yparitcher"><img src="https://avatars0.githubusercontent.com/u/38916402?v=4" width="100px;" alt="yparitcher"/><br /><sub><b>yparitcher</b></sub></a><br /><a href="#ideas-yparitcher" title="Ideas, Planning, & Feedback">🤔</a> <a href="#maintenance-yparitcher" title="Maintenance">🚧</a></td>
<td align="center"><a href="https://github.com/StoyanDimitrov"><img src="https://avatars1.githubusercontent.com/u/10962709?v=4" width="100px;" alt="StoyanDimitrov"/><br /><sub><b>StoyanDimitrov</b></sub></a><br /><a href="https://github.com/solokeys/solo/commits?author=StoyanDimitrov" title="Documentation">📖</a></td>
<td align="center"><a href="https://github.com/alphathegeek"><img src="https://avatars2.githubusercontent.com/u/51253712?v=4" width="100px;" alt="alphathegeek"/><br /><sub><b>alphathegeek</b></sub></a><br /><a href="#ideas-alphathegeek" title="Ideas, Planning, & Feedback">🤔</a></td>
<td align="center"><a href="https://xakcop.com"><img src="https://avatars2.githubusercontent.com/u/271616?v=4" width="100px;" alt="Radoslav Gerganov"/><br /><sub><b>Radoslav Gerganov</b></sub></a><br /><a href="#ideas-rgerganov" title="Ideas, Planning, & Feedback">🤔</a> <a href="https://github.com/solokeys/solo/commits?author=rgerganov" title="Code">💻</a></td>
<td align="center"><a href="http://13-37.org"><img src="https://avatars3.githubusercontent.com/u/10274356?v=4" width="100px;" alt="Manuel Domke"/><br /><sub><b>Manuel Domke</b></sub></a><br /><a href="#ideas-manuel-domke" title="Ideas, Planning, & Feedback">🤔</a> <a href="https://github.com/solokeys/solo/commits?author=manuel-domke" title="Code">💻</a> <a href="#business-manuel-domke" title="Business development">💼</a></td>
</tr>
<tr>
<td align="center"><a href="http://1bitsquared.com"><img src="https://avatars3.githubusercontent.com/u/17334?v=4" width="100px;" alt="Piotr Esden-Tempski"/><br /><sub><b>Piotr Esden-Tempski</b></sub></a><br /><a href="#business-esden" title="Business development">💼</a></td>
<td align="center"><a href="https://github.com/m3hm00d"><img src="https://avatars1.githubusercontent.com/u/42179593?v=4" width="100px;" alt="f.m3hm00d"/><br /><sub><b>f.m3hm00d</b></sub></a><br /><a href="https://github.com/solokeys/solo/commits?author=m3hm00d" title="Documentation">📖</a></td>
<td align="center"><a href="http://blogs.gnome.org/hughsie/"><img src="https://avatars0.githubusercontent.com/u/151380?v=4" width="100px;" alt="Richard Hughes"/><br /><sub><b>Richard Hughes</b></sub></a><br /><a href="#ideas-hughsie" title="Ideas, Planning, & Feedback">🤔</a> <a href="https://github.com/solokeys/solo/commits?author=hughsie" title="Code">💻</a> <a href="#infra-hughsie" title="Infrastructure (Hosting, Build-Tools, etc)">🚇</a> <a href="#tool-hughsie" title="Tools">🔧</a></td>
<td align="center"><a href="http://www.schulz.dk"><img src="https://avatars1.githubusercontent.com/u/1150049?v=4" width="100px;" alt="Kim Schulz"/><br /><sub><b>Kim Schulz</b></sub></a><br /><a href="#business-kimusan" title="Business development">💼</a> <a href="#ideas-kimusan" title="Ideas, Planning, & Feedback">🤔</a></td>
<td align="center"><a href="https://github.com/oplik0"><img src="https://avatars2.githubusercontent.com/u/25460763?v=4" width="100px;" alt="Jakub"/><br /><sub><b>Jakub</b></sub></a><br /><a href="https://github.com/solokeys/solo/issues?q=author%3Aoplik0" title="Bug reports">🐛</a></td>
<td align="center"><a href="https://github.com/jolo1581"><img src="https://avatars1.githubusercontent.com/u/53423977?v=4" width="100px;" alt="Jan A."/><br /><sub><b>Jan A.</b></sub></a><br /><a href="https://github.com/solokeys/solo/commits?author=jolo1581" title="Code">💻</a> <a href="https://github.com/solokeys/solo/commits?author=jolo1581" title="Documentation">📖</a></td>
<td align="center"><a href="https://github.com/ccinelli"><img src="https://avatars0.githubusercontent.com/u/38021940?v=4" width="100px;" alt="ccinelli"/><br /><sub><b>ccinelli</b></sub></a><br /><a href="#infra-ccinelli" title="Infrastructure (Hosting, Build-Tools, etc)">🚇</a> <a href="https://github.com/solokeys/solo/commits?author=ccinelli" title="Tests">⚠️</a></td>
</tr>
<tr>
<td align="center"><a href="https://www.nitrokey.com"><img src="https://avatars1.githubusercontent.com/u/9438831?v=4" width="100px;" alt="Nitrokey"/><br /><sub><b>Nitrokey</b></sub></a><br /><a href="https://github.com/solokeys/solo/commits?author=Nitrokey" title="Code">💻</a> <a href="https://github.com/solokeys/solo/commits?author=Nitrokey" title="Tests">⚠️</a> <a href="#ideas-Nitrokey" title="Ideas, Planning, & Feedback">🤔</a></td>
</tr>
</table>
<!-- ALL-CONTRIBUTORS-LIST:END -->
This is an upgrade to [U2F Zero](https://github.com/conorpp/u2f-zero).
# License
Everything in this repo is open source and licensed under the MIT License.
Solo is fully open source.
All software, unless otherwise noted, is dual licensed under Apache 2.0 and MIT.
You may use Solo software under the terms of either the Apache 2.0 license or MIT license.
Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in the work by you, as defined in the Apache-2.0 license, shall be dual licensed as above, without any additional terms or conditions.
All hardware, unless otherwise noted, is dual licensed under CERN and CC-BY-SA.
You may use Solo hardware under the terms of either the CERN 2.1 license or CC-BY-SA 4.0 license.
All documentation, unless otherwise noted, is licensed under CC-BY-SA.
You may use Solo documentation under the terms of the CC-BY-SA 4.0 license
[![FOSSA Status](https://app.fossa.io/api/projects/git%2Bgithub.com%2Fsolokeys%2Fsolo.svg?type=large)](https://app.fossa.io/projects/git%2Bgithub.com%2Fsolokeys%2Fsolo?ref=badge_large)
# Where To Buy Solo
You can buy Solo, Solo Tap, and Solo for Hackers at [solokeys.com](https://solokeys.com).
<br/>
<hr/>
<br/>
[![License](https://img.shields.io/github/license/solokeys/solo.svg)](https://github.com/solokeys/solo/blob/master/LICENSE)
[![All Contributors](https://img.shields.io/badge/all_contributors-22-orange.svg?style=flat-square)](#contributors)
[![Build Status](https://travis-ci.com/solokeys/solo.svg?branch=master)](https://travis-ci.com/solokeys/solo)
[![Discourse Users](https://img.shields.io/discourse/https/discourse.solokeys.com/users.svg)](https://discourse.solokeys.com)
[![Keybase Chat](https://img.shields.io/badge/chat-on%20keybase-brightgreen.svg)](https://keybase.io/team/solokeys.public)
[![FOSSA Status](https://app.fossa.io/api/projects/git%2Bgithub.com%2Fsolokeys%2Fsolo.svg?type=shield)](https://app.fossa.io/projects/git%2Bgithub.com%2Fsolokeys%2Fsolo?ref=badge_shield)
[![latest release](https://img.shields.io/github/release/solokeys/solo.svg)](https://github.com/solokeys/solo/releases)
[![commits since last release](https://img.shields.io/github/commits-since/solokeys/solo/latest.svg)](https://github.com/solokeys/solo/commits/master)
[![last commit](https://img.shields.io/github/last-commit/solokeys/solo.svg)](https://github.com/solokeys/solo/commits/master)
[![commit activity](https://img.shields.io/github/commit-activity/m/solokeys/solo.svg)](https://github.com/solokeys/solo/commits/master)
[![contributors](https://img.shields.io/github/contributors/solokeys/solo.svg)](https://github.com/solokeys/solo/graphs/contributors)

32
SECURITY.md Normal file
View File

@ -0,0 +1,32 @@
# Security Policy
## Supported Versions
We fix security issues as soon as they are found, and release firmware updates.
Each such release is accompanied by release notes, see <https://github.com/solokeys/solo/releases>.
The latest version can be determined using the file <https://github.com/solokeys/solo/blob/master/STABLE_VERSION>.
To update your key:
- either visit <https://update.solokeys.com>, or
- use our commandline tool <https://github.com/solokeys/solo-python>:
```
solo key update [--secure|--hacker]
```
## Reporting a Vulnerability
To report vulnerabilities you have found:
- preferably contact [@conor1](https://keybase.io/conor1), [@0x0ece](https://keybase.io/0x0ece) or [@nickray](https://keybase.io/nickray) via Keybase, or
- send us e-mail using OpenPGP to [security@solokeys.com](mailto:security@solokeys.com).
<https://keys.openpgp.org/vks/v1/by-fingerprint/85AFA2769F4381E5712C36A04DDFC46FEF1F7F3F>
We do not currently run a paid bug bounty program, but are happy to provide you with a bunch of Solo keys in recognition of your findings.
## Mailing List
Join our release notification mailing list to be informed about each release:
https://sendy.solokeys.com/subscription?f=9MLIqMDmox1Ucz89C892Kq09IqYMM7OB8UrBrkvtTkDI763QF3L5PMYlRhlVNo2AI892mO

1
STABLE_VERSION Normal file
View File

@ -0,0 +1 @@
3.0.0

0
builds/.gitkeep Normal file
View File

1
crypto/cifra Submodule

Submodule crypto/cifra added at d04dd31860

View File

@ -1,28 +0,0 @@
To build, develop and debug the firmware for the STM32L442 (WIP!) via cross-compilation on Linux, no vendor-specific software is necessary.
There exists a development board [NUCLEO-L432KC](https://www.st.com/en/evaluation-tools/nucleo-l432kc.html) you can use; the L432 chip differs from the L442 used for Solo only in that it lacks a cryptographic accelerator. The board does contain a debugger, so all you need is a USB cable (and some [udev](/udev) [rules](https://rust-embedded.github.io/book/intro/install/linux.html#udev-rules)).
You will need the following packages (naming given for Arch Linux):
- arm-none-eabi-gcc
- arm-none-eabi-newlib
- arm-none-eabi-binutils
and one of
- [openocd](http://openocd.org)
- [stlink](https://github.com/texane/stlink)
If you remove the `.exe` extensions in the [Makefile](https://github.com/SoloKeysSec/solo/blob/master/targets/stm32l442/Makefile), and possibly add a `-g` flag, compilation runs through.
To flash and step through the code:
* connect the Nucleo to your PC
* attach one of the debuggers: `st-util` (for stlink), or `openocd -f interface/stlink-v2-1.cfg -f target/stm32l4x.cfg` (for openocd)
* launch `gdb` via `arm-none-eabi-gdb -q solo.elf`
* connect gdb to the debugger via `target extended-remote :4242` (for stlink), or `target remote :3333` (for openocd)
* flash the firmware via `load`
* optionally set a breakpoint via `break main`
* `continue`, and start stepping 🙌
Note that the code for `targets/stm32l442` currently consists of only a blinky hello world...

View File

@ -1,15 +0,0 @@
We are very open to contributions!
[Currently](https://github.com/solokeyssec/solo/issues), most work will go towards
* implementing STM32L442
* implementing NFC
* adding documentation and improving accessability of the code
In the future, we would love to see creative plugins/extensions, putting the TRNG and other features of the STM32L442 to good use!
Feel free to send a [pull request](https://github.com/SoloKeysSec/solo/pulls) at any time, we don't currently have a formal contribution process.
If you want to discuss your plans in quasi-realtime beforehand, you can also join our [solokeys.public](https://keybase.io/team/solokeys.public) Keybase team.
But first: [join our mailing list!](https://solokeys.us19.list-manage.com/subscribe/post?u=cc0c298fb99cd136bdec8294b&id=b9cb3de62d)

View File

@ -1,4 +0,0 @@
Welcome to the technical documentation for [solokeyssec/solo](https://github.com/solokeyssec/solo).
For now, you can read the repository `README.md`, more documentation to come!

View File

@ -1 +0,0 @@
../README.md

Binary file not shown.

View File

@ -0,0 +1,99 @@
# Using Solo for passwordless or second factor login on Linux
## Setup on Ubuntu 18.04
Before you can use Solo for passwordless or second factor login in your Linux system you have to install some packages.
This was tested under **Linux Mint 19.2**.
First you have to install PAM modules for u2f.
```
sudo apt install libpam-u2f pamu2fcfg
```
## Setting up key
To use Solo as passwordless or second factor login, you have to setup your system with your Solo.
First create a new folder named **Yubico** in your **.config** folder in your **home** directory
```
mkdir ~/.config/Yubico
```
Then create a new key for PAM U2F module. If it is your first key you want to register use following command:
```
pamu2fcfg > ~/.config/Yubico/u2f_keys
```
If you want to register an additional key use this command instead:
```
pamu2fcfg >> ~/.config/Yubico/u2f_keys
```
Now press the button on your Solo.
If you can't generate your key (error message), you may add Yubico Team from PPA and install latest libpam-u2f and pamu2fcfg and try again.
```
sudo add-apt-repository ppa:yubico/stable
sudo apt-get update
sudo apt-get upgrade
```
## Login into Linux
### Passwordless
To login passwordless into your Linux system, you have to edit the file **lightdm** (or **gdm** or which display manager you prefered).
In case of lightdm:
```
sudo vim /etc/pam.d/lightdm
```
Now search following entry:
```
@include common-auth
```
and add
```
auth sufficient pam_u2f.so
```
**before** @include common-auth.
Save the file and test it.<br>
Insert Solo in your USB port and logout.
Now you should be able to login into Linux without password, only with pressing your button on Solo and press enter.
Why **sufficient**? The difference between the keyword sufficient and required is, if you don't have your Solo available, you can also login, because the system falls back to password mode.
The login mechanism can be also used for additional features like:
: - Login after screen timeout - edit /etc/pam.d/mate-screensaver (or kde-screensaver, ...)
- Passwordless sudo - edit /etc/pam.d/sudo
Check out your folder **/etc/pam.d/** and do some experiments.
**But remember:** <br>
The login passwordless won't make your system more secure, but maybe more comfortable. If somebody have access to your Solo, this person will be also able to login into your system.
### Solo as second factor
To use Solo as second factor, for login into your Linux system, is nearly the same.
```
sudo vim /etc/pam.d/lightdm
```
Now search following entry:
```
@include common-auth
```
and add
```
auth required pam_u2f.so
```
**after** @include common-auth.
Save the file and test it. <br>
In case your Solo is not present, your password will be incrorrect. If Solo is plugged into your USB port, it will signal pressing the button and you will be able to login into Linux.
Why **required**? If you choose the option **sufficent** your Solo is optional. You could also login without second factor if your Solo is not connected.
**But remember:**<br>
If you loose your Solo you won't be able to login into your system.

View File

@ -0,0 +1,53 @@
# Booting into bootloader mode
If you have a recent version of Solo, you can put it into bootloader mode by running this command.
```bash
solo program aux enter-bootloader
```
If your Solo is a bit older (<=2.5.3) You can put Solo into bootloader mode by using the button method:
Hold down button while plugging in Solo. After 2 seconds, bootloader mode will activate.
You'll see a yellowish flashing light and you can let go of the button.
Now Solo is ready to [accept firmware updates](/solo/signed-updates). If the Solo is a secured model, it can only accept signed updates, typically in the `firmware-*.json` format.
# The boot stages of Solo
Solo has 3 boot stages.
## DFU
The first stage is the DFU (Device Firmware Update) which is in a ROM on Solo. It is baked into the chip and is not implemented by us.
This is what allows the entire firmware of Solo to be programmed. **It's not recommended to develop for Solo using the DFU because
if you program broken firmware, you could brick your device**.
On hacker/nonverifying-bootloader devices, you can boot into the DFU by holding down the button for 5 seconds,
when Solo is already in bootloader mode.
You can also run this command when Solo is in bootloader mode to put it in DFU mode.
```bash
solo program aux enter-dfu
```
Note it will stay in DFU mode until you to tell it to boot again. You can boot it again by running the following.
```bash
solo program aux leave-dfu
```
*Warning*: If you change the firmware to something broken, and you tell the DFU to boot it, you could brick your device.
## Solo Bootloader
The next boot stage is the "Solo bootloader". So when we say to put your Solo into bootloader mode, it is this stage.
This bootloader is written by us and allows signed firmware updates to be written. On Solo Hackers, there is no signature checking
and will allow any firmware updates.
It is safe to develop for Solo using our Solo bootloader. If broken firmware is uploaded to the device, then the Solo
bootloader can always be booted again by holding down the button when plugging in.
## Solo application
This is what contains all the important functionality of Solo. FIDO2, U2F, etc. This is what Solo will boot to by default.

126
docs/solo/building.md Normal file
View File

@ -0,0 +1,126 @@
# Building solo
To build, develop and debug the firmware for the STM32L432. This will work
for Solo Hacker, the Nucleo development board, or your own homemade Solo.
There exists a development board [NUCLEO-L432KC](https://www.st.com/en/evaluation-tools/nucleo-l432kc.html) you can use; The board does contain a debugger, so all you need is a USB cable (and some [udev](/udev) [rules](https://rust-embedded.github.io/book/intro/install/linux.html#udev-rules)).
## Prerequisites
Install the [latest ARM compiler toolchain](https://developer.arm.com/open-source/gnu-toolchain/gnu-rm/downloads) for your system. We recommend getting the latest compilers from ARM.
You can also install the ARM toolchain using a package manager like `apt-get` or `pacman`,
but be warned they might be out of date. Typically it will be called `gcc-arm-none-eabi binutils-arm-none-eabi`.
Install `solo-python` usually with `pip3 install solo-python`. The `solo` python application may also be used for [programming](#programming).
## Obtain source code and solo tool
Source code can be downloaded from:
- [github releases list](https://github.com/solokeys/solo/releases)
- [github repository](https://github.com/solokeys/solo)
**solo** tool can be downloaded from:
- from python programs [repository](https://pypi.org/project/solo-python/) `pip install solo-python`
- from installing prerequisites `pip3 install -r tools/requirements.txt`
- github repository: [repository](https://github.com/solokeys/solo-python)
- installation python enviroment with command `make venv` from root directory of source code
## Compilation
Enter the `stm32l4xx` target directory.
```
cd targets/stm32l432
```
Now build the Solo application.
```
make firmware
```
The `firmware` recipe builds the solo application, and outputs `solo.hex`. You can use this
to reprogram any unlocked/hacker Solo model. Note that it does not include the Solo bootloader,
so it is not a full reprogram.
<!-- First it builds the bootloader, with
signature checking disabled. Then it builds the Solo application with "hacker" features
enabled, like being able to jump to the bootloader on command. It then merges bootloader
and solo builds into the same binary. I.e. it combines `bootloader.hex` and `solo.hex`
into `all.hex`. -->
If you're just planning to do development, **please don't try to reprogram the bootloader**,
as this can be risky if done often. Just use `solo.hex`.
### Building with debug messages
If you're developing, you probably want to see debug messages! Solo has a USB
Serial port that it will send debug messages through (from `printf`). You can read them using
a normal serial terminal like `picocom` or `putty`.
Just add `-debug-1` or `-debug-2` to your build recipe, like this.
```
make firmware-debug-1
```
If you use `debug-2`, that means Solo will not boot until something starts reading
its debug messages. So it basically waits to tether to a serial terminal so that you don't
miss any debug messages.
We recommend using our `solo` tool as a serial emulator since it will automatically
reconnect each time you program Solo.
```
solo monitor <serial-port>
```
#### Linux Users:
[See issue 62](https://github.com/solokeys/solo/issues/62).
### Building a complete Solo build (application + bootloader + certificate)
To make a complete Solo build, you need to build the bootloader. We provide
two easy recipes:
* `bootloader-nonverifying`: bootloader with no signature checking on updates. I.e. "unlocked".
* `bootloader-verifying`: bootloader with signature checking enforced on updated. I.e. "Locked".
To be safe, let's use the `-nonverifying` build.
```
make bootloader-nonverifying
```
This outputs `bootloader.hex`. We can then merge the bootloader and application.
```
solo mergehex bootloader.hex solo.hex bundle.hex
```
`bundle.hex` is our complete firmware build. Note it is in this step that you can
include a custom attestation certificate or lock the device from debugging/DFU.
By default the "hacker" attestation certifcate and key is used.
```
solo mergehex \
--attestation-key "0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF" \
--attestation-cert attestation.der \
--lock \
solo.hex \
bootloader.hex \
bundle.hex
```
See [here for more information on custom attestation](/solo/customization/).
If you use `--lock`, this will permanently lock the device to this new bootloader. You
won't be able to program the bootloader again or be able to connect a hardware debugger.
The new bootloader may be able to accept (signed) updates still, depending on how you configured it.
To learn more about normal updates or a "full" update, you should [read more on Solo's boot stages](/solo/bootloader-mode).

View File

@ -5,22 +5,22 @@ and easy to understand, especially when paired with a high level overview.
## FIDO2 codebase
* main.c - calls high level functions and implements event loop.
* `main.c` - calls high level functions and implements event loop.
* ctaphid.c - implements [USBHID protocol](https://fidoalliance.org/specs/fido-v2.0-id-20180227/fido-client-to-authenticator-protocol-v2.0-id-20180227.html#usb) for FIDO.
* `ctaphid.c` - implements [USBHID protocol](https://fidoalliance.org/specs/fido-v2.0-id-20180227/fido-client-to-authenticator-protocol-v2.0-id-20180227.html#usb) for FIDO.
* u2f.c - implements [U2F protocol](https://fidoalliance.org/specs/fido-u2f-v1.2-ps-20170411/fido-u2f-raw-message-formats-v1.2-ps-20170411.html).
* `u2f.c` - implements [U2F protocol](https://fidoalliance.org/specs/fido-u2f-v1.2-ps-20170411/fido-u2f-raw-message-formats-v1.2-ps-20170411.html).
* ctap.c - implements [CTAP2 protocol](https://fidoalliance.org/specs/fido-v2.0-id-20180227/fido-client-to-authenticator-protocol-v2.0-id-20180227.html).
* `ctap.c` - implements [CTAP2 protocol](https://fidoalliance.org/specs/fido-v2.0-id-20180227/fido-client-to-authenticator-protocol-v2.0-id-20180227.html).
* ctap_parse.c - implements parsing for CTAP protocol.
* `ctap_parse.c` - implements parsing for CTAP protocol.
* this could use some work minimizing.
* log.c - embedded friendly debug logging.
* `log.c` - embedded friendly debug logging.
* crypto.c - software implementation of the crypto needs of the application. Generally this will be copied and edited for different platforms. API defined in crypto.h should be the same.
* `crypto.c` - software implementation of the crypto needs of the application. Generally this will be copied and edited for different platforms. API defined in `crypto.h` should be the same.
* device.h - definitions of functions that are platform specific and should be implemented separately. See device.c in any of the implementations to see examples.
* `device.h` - definitions of functions that are platform specific and should be implemented separately. See `device.c` in any of the implementations to see examples.
## Data flow

15
docs/solo/contributing.md Normal file
View File

@ -0,0 +1,15 @@
We are very open to contributions!
[Currently](https://github.com/solokeys/solo/issues), most work will go towards
* ~~implementing STM32L432~~
* implementing NFC
* adding documentation and improving accessability of the code
In the future, we would love to see creative plugins/extensions, putting the TRNG and other features of the STM32L432 to good use!
Feel free to send a [pull request](https://github.com/solokeys/solo/pulls) at any time, please note that we do require a lightweight copyright license agreement in order to accept contributions. Reason and procedure: <https://solokeys.com/legal/contributors/>.
If you want to discuss your plans in quasi-realtime beforehand, you can also join our [solokeys.public](https://keybase.io/team/solokeys.public) Keybase team.
But first: [join our mailing list!](https://solokeys.us19.list-manage.com/subscribe/post?u=cc0c298fb99cd136bdec8294b&id=6550fc947a)

140
docs/solo/customization.md Normal file
View File

@ -0,0 +1,140 @@
# Customization
If you are interested in customizing parts of your Solo, and you have a Solo Hacker, this page is for you.
## Custom Attestation key
The attestation key is used in the FIDO2 *makeCredential* or U2F *register* requests. It signs
newly generated credentials. The certificate associated with the attestation key is output with newly created credentials.
Platforms or services can use the attestation feature to enforce specific authenticators to be used.
This is typically a use case for organizations and isn't seen in the wild for consumer use cases.
Attestation keys are typically the same for at least 100K units of a particular authenticator model.
This is so they don't contribute a significant fingerprint that platforms could use to identify the user.
If you don't want to use the default attestation key that Solo builds with, you can create your own
and program it.
### Creating your attestation key pair
Since we are generating keys, it's important to use a good entropy source.
You can use the [True RNG on your Solo](/solo/solo-extras) to generate some good random numbers.
```
# Run for 1 second, then hit control-c
solo key rng raw > seed.bin
```
First we will create a self signed key pair that acts as the root of trust. This
won't go on the authenticator, but will sign the keypair that does.
Please change the root certification information as needed. You may change the ECC curve.
```
curve=prime256v1
country=US
state=Maine
organization=OpenSourceSecurity
unit="Root CA"
CN=example.com
email=example@example.com
# generate EC private key
openssl ecparam -genkey -name "$curve" -out root_key.pem -rand seed.bin
# generate a "signing request"
openssl req -new -key root_key.pem -out root_key.pem.csr -subj "/C=$country/ST=$state/O=$organization/OU=$unit/CN=example.com/emailAddress=$email"
# self sign the request
openssl x509 -trustout -req -days 18250 -in root_key.pem.csr -signkey root_key.pem -out root_cert.pem -sha256
# convert to smaller size format DER
openssl x509 -in root_cert.pem -outform der -out root_cert.der
# print out information and verify
openssl x509 -in root_cert.pem -text -noout
```
You need to create a extended certificate for the device certificate to work with FIDO2. You need to create this
file, `v3.ext`, and add these options to it.
```
subjectKeyIdentifier=hash
authorityKeyIdentifier=keyid,issuer
basicConstraints=CA:FALSE
keyUsage = digitalSignature, nonRepudiation, keyEncipherment, dataEncipherment
```
Now to generate & sign the attestation key pair that will go on your device, or maybe 100,000 devices :).
Note you must use a prime256v1 curve for this step, and you must leave the unit/OU as "Authenticator Attestation".
```
country=US
state=Maine
organization=OpenSourceSecurity
unit="Authenticator Attestation"
CN=example.com
email=example@example.com
# generate EC private key
openssl ecparam -genkey -name "$curve" -out device_key.pem -rand seed.bin
# generate a "signing request"
openssl req -new -key device_key.pem -out device_key.pem.csr -subj "/C=$country/ST=$state/O=$organization/OU=$unit/CN=example.com/emailAddress=$email"
# sign the request
openssl x509 -req -days 18250 -in device_key.pem.csr -extfile v3.ext -CA root_cert.pem -CAkey root_key.pem -set_serial 01 -out device_cert.pem -sha256
# convert to smaller size format DER
openssl x509 -in device_cert.pem -outform der -out device_cert.der
# Verify the device certificate details
openssl x509 -in device_cert.pem -text -noout
```
Let's verify that the attestation key and certificate are valid, and that they can be verified with the root key pair.
```
echo 'challenge $RANDOM' > chal.txt
# check that they are valid key pairs
openssl dgst -sha256 -sign device_key.pem -out sig.txt chal.txt
openssl dgst -sha256 -verify <(openssl x509 -in device_cert.pem -pubkey -noout) -signature sig.txt chal.txt
openssl dgst -sha256 -sign "root_key.pem" -out sig.txt chal.txt
openssl dgst -sha256 -verify <(openssl x509 -in root_cert.pem -pubkey -noout) -signature sig.txt chal.txt
# Check they are a chain
openssl verify -verbose -CAfile "root_cert.pem" "device_cert.pem"
```
If the checks succeed, you are ready to program the device attestation key and certificate.
### Programming an attestation key and certificate
First, [Build your solo application and bootloader](/solo/building).
Print your attestation key in a hex string format. Using our utility script:
```
python tools/print_x_y.py device_key.pem
```
Merge the `bootloader.hex`, `solo.hex`, attestion key, and certificate into one firmware file.
```
solo mergehex \
--attestation-key "(The 32-byte hex string extracted from device_key.pem)" \
--attestation-cert device_cert.der \
--lock \
solo.hex \
bootloader.hex \
bundle.hex
```
Now you have a newly created `bundle.hex` file with a custom attestation key and cert. You can [program this `bundle.hex` file
with Solo in DFU mode](/solo/programming#procedure).
Are you interested in customizing in bulk? Contact hello@solokeys.com and we can help.

View File

@ -3,9 +3,9 @@ Documentation of the `master` branch is deployed to Netlify automatically.
To host or develop locally:
```
pip install mkdocs mkdocs-material
pip install mkdocs mkdocs-material markdown-include
```
`make docsrv` and visit [localhost:8000](http://localhost:8000).
`mkdocs serve` and visit [localhost:8000](http://localhost:8000).
The file `runtime.txt` is necessary to tell Netlify to use Python3.

View File

@ -15,13 +15,15 @@ A master secret, `M`, is generated at initialization. This is only used for
all key generation and derivation in FIDO2. Solo uses a key wrapping method
for FIDO2 operation.
** NOTE: The masked implementation of AES is planned, but not yet implemented. Currently it is normal AES. **
## Key wrapping
When you register a service with a FIDO2 or U2F authenticator, the
authenticator must generate a new keypair unique to that service. This keypair
could be stored on the authenticator to be used in subsequent authentications,
but now a certain amount of memory needs to be allocated for this. On embedded
devices, there isn't much memory to spare and users will allows frustratingly
but a certain amount of memory would need to be allocated for this. On embedded
devices, there isn't much memory to spare and users would frustratingly
hit the limit of this memory.
The answer to this problem is to do key wrapping. The authenticator just
@ -37,7 +39,7 @@ In essence, the following happens at registration.
3. Return `P` and `R` to service. (`R` is in `KEYID` parameter)
4. Service stores `P` and `R`.
Now on authenication.
Now on authentication.
1. Service issues authentication request with `R` in `KEYID` parameter.
2. \* Authenticator generates `K` by calculating `HMAC(M,R)`.
@ -55,6 +57,8 @@ keys which are then used for FIDO2/U2F. -->
## Key derivation
** Planned, but not yet implemented. **
Master secret `M` consists of 64 bytes, split into equal parts `M1` and `M2`.
In theory, we should only need 32 bytes to achieve 256 security, but we also
plan to have side channel security hence the added bytes.

Binary file not shown.

After

Width:  |  Height:  |  Size: 134 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB

View File

Before

Width:  |  Height:  |  Size: 3.9 KiB

After

Width:  |  Height:  |  Size: 3.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 129 KiB

4
docs/solo/index.md Normal file
View File

@ -0,0 +1,4 @@
Welcome to the technical documentation for [solokeys/solo](https://github.com/solokeys/solo).
Use the table of contents on the left to browse this documentation.

View File

@ -0,0 +1,12 @@
For information on what this is, see the [spec](https://fidoalliance.org/specs/fido-v2.0-rd-20180702/fido-metadata-statement-v2.0-rd-20180702.html#fido2-example).
## CTAP2
```
{!metadata/Solo-FIDO2-CTAP2-Authenticator.json!}
```
## U2F
```
{!metadata/Solo-FIDO2-U2F-Authenticator.json!}
```

257
docs/solo/nucleo32-board.md Normal file
View File

@ -0,0 +1,257 @@
# Nucleo32 board preparation
Additional steps are required to run the firmware on the Nucleo32 board.
## USB-A cable
Board does not provide an USB cable / socket for the target MCU communication.
Own provided USB plug has to be connected in the following way:
| PIN / Arduino PIN | MCU leg | USB wire color | Signal |
| ----------------- | ------- | -------------- | ------ |
| D10 / PA11 | 21 | white | D- |
| D2 / PA12 | 22 | green | D+ |
| GND (near D2) | ------- | black | GND |
| **not connected** | ------- | red | 5V |
Each USB plug pin should be connected via the wire in a color defined by the standard. It might be confirmed with a
multimeter for additional safety. USB plug description:
| PIN | USB wire color | Signal |
| --- | -------------- | ------ |
| 4 | black | GND |
| 3 | green | D+ |
| 2 | white | D- |
| 1 | red | 5V |
See this [USB plug] image, and Wikipedia's [USB plug description].
Plug in [USB-A_schematic.pdf] has wrong wire order, registered as [solo-hw#1].
The power is taken from the debugger / board (unless the board is configured in another way).
Make sure 5V is not connected, and is covered from contacting with the board elements.
Based on [USB-A_schematic.pdf].
## Firmware modification
Following patch has to be applied to skip the user presence confirmation, for tests. Might be applied at a later stage.
```text
diff --git a/targets/stm32l432/src/app.h b/targets/stm32l432/src/app.h
index c14a7ed..c89c3b5 100644
--- a/targets/stm32l432/src/app.h
+++ b/targets/stm32l432/src/app.h
@@ -71,6 +71,6 @@ void hw_init(void);
#define SOLO_BUTTON_PIN LL_GPIO_PIN_0
#define SKIP_BUTTON_CHECK_WITH_DELAY 0
-#define SKIP_BUTTON_CHECK_FAST 0
+#define SKIP_BUTTON_CHECK_FAST 1
#endif
```
It is possible to provide a button and connect it to the MCU pins, as instructed in [USB-A_schematic.pdf]&#x3A;
```text
PA0 / pin 6 --> button --> GND
```
In that case the mentioned patch would not be required.
## Development environment setup
Environment: Fedora 29 x64, Linux 4.19.9
See <https://docs.solokeys.io/solo/building/> for the original guide. Here details not included there will be covered.
### Install ARM tools Linux
1. Download current [ARM tools] package: [gcc-arm-none-eabi-8-2018-q4-major-linux.tar.bz2].
2. Extract the archive.
3. Add full path to the `./bin` directory as first entry to the `$PATH` variable,
as in `~/gcc-arm/gcc-arm-none-eabi-8-2018-q4-major/bin/:$PATH`.
### Install ARM tools OsX using brew package manager
```bash
brew tap ArmMbed/homebrew-formulae
brew install arm-none-eabi-gcc
```
### Install flashing software
ST provides a CLI flashing tool - `STM32_Programmer_CLI`. It can be downloaded directly from the vendor's site:
1. Go to [download site URL](https://www.st.com/content/st_com/en/products/development-tools/software-development-tools/stm32-software-development-tools/stm32-programmers/stm32cubeprog.html), go to bottom page and from STM32CubeProg row select Download button.
2. Unzip contents of the archive.
3. Run \*Linux setup
4. In installation directory go to `./bin` - there the `./STM32_Programmer_CLI` is located
5. Add symlink to the STM32 CLI binary to `.local/bin`. Make sure the latter it is in `$PATH`.
If you're on MacOS X and installed the STM32CubeProg, you need to add the following to your path:
```bash
# ~/.bash_profile
export PATH="/Applications/STMicroelectronics/STM32Cube/STM32CubeProgrammer/STM32CubeProgrammer.app/Contents/MacOs/bin/":$PATH
```
## Building and flashing
### Building
Please follow <https://docs.solokeys.io/solo/building/>, as the build way changes rapidly.
Currently (8.1.19) to build the firmware, following lines should be executed
```bash
# while in the main project directory
cd targets/stm32l432
make cbor
make build-hacker DEBUG=1
```
Note: `DEBUG=2` stops the device initialization, until a serial client will be attached to its virtual port.
Do not use it, if you do not plan to do so.
### Flashing via the Makefile command
```bash
# while in the main project directory
# create Python virtual environment with required packages, and activate
make venv
. venv/bin/activate
# Run flashing
cd ./targets/stm32l432
make flash
# which runs:
# flash: solo.hex bootloader.hex
# python merge_hex.py solo.hex bootloader.hex all.hex (intelhex library required)
# STM32_Programmer_CLI -c port=SWD -halt -e all --readunprotect
# STM32_Programmer_CLI -c port=SWD -halt -d all.hex -rst
```
### Manual flashing
In case you already have a firmware to flash (named `all.hex`), please run the following:
```bash
STM32_Programmer_CLI -c port=SWD -halt -e all --readunprotect
STM32_Programmer_CLI -c port=SWD -halt -d all.hex -rst
```
## Testing
### Internal
Project-provided tests.
#### Simulated device
A simulated device is provided to test the HID layer.
##### Build
```bash
make clean
cd tinycbor
make
cd ..
make env2
```
##### Execution
```bash
# run simulated device (will create a network UDP server)
./main
# run test 1
./env2/bin/python tools/ctap_test.py
# run test 2 (or other files in the examples directory)
./env2/bin/python python-fido2/examples/credential.py
```
#### Real device
```bash
# while in the main project directory
# not passing as of 8.1.19, due to test solution issues
make fido2-test
```
### External
#### FIDO2 test sites
1. <https://www.passwordless.dev/overview>
2. <https://webauthn.bin.coffee/>
3. <https://webauthn.org/>
#### U2F test sites
1. <https://u2f.bin.coffee/>
2. <https://demo.yubico.com/u2f>
#### FIDO2 standalone clients
1. <https://github.com/Nitrokey/u2f-ref-code>
2. <https://github.com/Yubico/libfido2>
3. <https://github.com/Yubico/python-fido2>
4. <https://github.com/google/pyu2f>
## USB serial console reading
Device opens an USB-emulated serial port to output its messages. While Nucleo board offers such already,
the Solo device provides its own.
- Provided Python tool
```bash
python3 ../../tools/solotool.py monitor /dev/solokey-serial
```
- External application
```bash
sudo picocom -b 115200 /dev/solokey-serial
```
where `/dev/solokey-serial` is an udev symlink to `/dev/ttyACM1`.
## Other
### Dumping firmware
Size is calculated using bash arithmetic.
```bash
STM32_Programmer_CLI -c port=SWD -halt -u 0x0 $((256*1024)) current.hex
```
### Software reset
```bash
STM32_Programmer_CLI -c port=SWD -rst
```
### Installing required Python packages
Client script requires some Python packages, which could be easily installed locally to the project
via the Makefile command. It is sufficient to run:
```bash
make env3
```
[solo-hw#1]: https://github.com/solokeys/solo-hw/issues/1
[usb plug]: https://upload.wikimedia.org/wikipedia/commons/thumb/6/67/USB.svg/1200px-USB.svg.png
[usb plug description]: https://en.wikipedia.org/wiki/USB#Receptacle_(socket)_identification
[usb-a_schematic.pdf]: https://github.com/solokeys/solo-hw/releases/download/1.2/USB-A_schematic.pdf
[arm tools]: https://developer.arm.com/open-source/gnu-toolchain/gnu-rm/downloads
[gcc-arm-none-eabi-8-2018-q4-major-linux.tar.bz2]: https://developer.arm.com/-/media/Files/downloads/gnu-rm/8-2018q4/gcc-arm-none-eabi-8-2018-q4-major-linux.tar.bz2?revision=d830f9dd-cd4f-406d-8672-cca9210dd220?product=GNU%20Arm%20Embedded%20Toolchain,64-bit,,Linux,8-2018-q4-major

112
docs/solo/programming.md Normal file
View File

@ -0,0 +1,112 @@
# Programming
This page documents how to update or program your Solo.
## Prerequisites
To program Solo, you'll likely only need to use our Solo tool.
```python
pip3 install solo-python
```
## Updating the firmware
If you just want to update the firmware, you can run one of the following commands.
Make sure your key [is in bootloader mode](/solo/bootloader-mode#solo-bootloader) first.
```bash
solo key update <--secure | --hacker>
```
You can manually install the [latest release](https://github.com/solokeys/solo/releases), or use a build that you made.
```bash
solo program bootloader <firmware.hex | firmware.json>
```
Note you won't be able to use `all.hex` or the `bundle-*.hex` builds, as these include the solo bootloader. You shouldn't
risk changing the Solo bootloader unless you want to make it a secure device, or [make other customizations](/solo/customization/).
## Updating a Hacker to a Secure Solo
Updating a hacker to be a secure build overwrites the [Solo bootloader](/solo/bootloader-mode#solo-bootloader).
So it's important to not mess this up or you may brick your device.
You can use a firmware build from the [latest release](https://github.com/solokeys/solo/releases) or use
a build that you made yourself.
You need to use a firmware file that has the combined bootloader and application (or at the very least just the bootloader).
This means using the `bundle-*.hex` file or the `bundle.hex` from your build. If you overwrite the Solo flash with a missing bootloader,
it will be bricked.
We provide two types of bundled builds. The `bundle-hacker-*.hex` build is the hacker build. If you update with this,
you will update the bootloader and application, but nothing will be secured. The `bundle-secure-non-solokeys.hex`
is a secured build that will lock your device and it will behave just like a Secure Solo. The main difference is that
it uses a "default" attestation key in the device, rather than the SoloKeys attestation key. There is no security
concern with using our default attestation key, aside from a small privacy implication that services can distinguish it from Solo Secure.
### Procedure
1. Boot into DFU mode.
# Enter Solo bootloader
solo program aux enter-bootloader
# Enter DFU
solo program aux enter-dfu
The device should be turned off.
2. Program the device
solo program dfu <bundle-secure-non-solokeys.hex | bundle.hex>
Double check you programmed it with bootloader + application (or just bootloader).
If you messed it up, simply don't do the next step and repeat this step correctly.
3. Boot the device
Once Solo boots a secure build, it will lock the flash permantly from debugger access. Also the bootloader
will only accept signed firmware updates.
solo program aux leave-dfu
If you are having problems with solo tool and DFU mode, you could alternatively try booting into DFU
by holding down the button while Solo is in bootloader mode. Then try another programming tool that works
with ST DFU:
* STM32CubeProg
* openocd
* stlink
Windows users need to install [libusb](https://sourceforge.net/projects/libusb-win32/files/libusb-win32-releases/1.2.6.0/)
for solo-python to work with Solo's DFU.
## Programming a Solo that hasn't been programmed
A Solo that hasn't been programmed will boot into DFU mode. You can program
it by following a bootloader, or combined bootloader + application.
```
solo program dfu <bundle-*.hex | all.hex>
```
Then boot the device. Make sure it has a bootloader to boot to.
```
solo program aux leave-dfu
```
## Disable signed firmware updates
If you'd like to also permanently disable signed updates, plug in your programmed Solo and run the following:
```bash
# WARNING: No more signed updates.
solo program disable-bootloader
```
You won't be able to update to any new releases.

1
docs/solo/repo-readme.md Symbolic link
View File

@ -0,0 +1 @@
../../README.md

View File

@ -2,7 +2,7 @@
Solo has a bootloader that's fixed in memory to allow for signed firmware updates. It is not a built-in bootloader provided by the chip
manufacturer, it is our own. We plan to use Ed25519 signatures, which have [efficient constant-time implementations on Cortex-M4 chips](http://www.cs.haifa.ac.il/~orrd/LC17/paper39.pdf).
On the STM32L442, there is 256 KB of memory. The first 14 KB of memory is reserved for the bootloader.
On the STM32L432, there is 256 KB of memory. The first 14 KB of memory is reserved for the bootloader.
The bootloader is the first thing that boots, and if the button of the device is not held for 2 seconds, the
application is immediately booted.
@ -22,5 +22,5 @@ In order to boot the application, a valid signature must be provided to the boot
signature using a public key stored in the bootloader section, and the data in the application section. If the signature
is valid, the boot flag in the data section will be changed to allow boot.
Signature checks and checks to the data section boot flag are made redundantly to make glitching attacks more difficult. Random delays
between redundant checks are also made.
We are working to make the signature checking process redundantly to make glitching attacks more difficult. Also random delays
between redundant checks.

19
docs/solo/solo-extras.md Normal file
View File

@ -0,0 +1,19 @@
# Solo Extras
## Random number generation
Solo contains a True Random Number Generator (TRNG). A TRNG is a hardware based mechanism
that leverages natural phenomenon to generate random numbers, which can be better than a traditional
RNG that has state and updates deterministically using cryptographic methods.
You can easily access the TRNG stream on Solo using our python tool [`solo-python`](https://github.com/solokeys/solo-python).
```
solo key rng raw > random.bin
```
Or you can seed the state of the RNG on your kernel (`/dev/random`).
```
solo key rng feedkernel
```

View File

@ -1,16 +1,32 @@
# tl;dr
# Summary
Create `/etc/udev/fido.rules` and add the following.
On Linux, by default USB dongles can't be accessed by users, for security reasons. To allow user access, so-called "udev rules" must be installed.
For some users, things will work automatically:
- Fedora seems to use a ["universal" udev rule for FIDO devices](https://github.com/amluto/u2f-hidraw-policy)
- Our udev rule made it into [libu2f-host](https://github.com/Yubico/libu2f-host/) v1.1.10
- Arch Linux [has this package](https://www.archlinux.org/packages/community/x86_64/libu2f-host/)
- [Debian sid](https://packages.debian.org/sid/libu2f-udev) and [Ubuntu Eon](https://packages.ubuntu.com/eoan/libu2f-udev) can use the `libu2f-udev` package
- Debian Buster and Ubuntu Disco still distribute v1.1.10, so need the manual rule
- FreeBSD has support in [u2f-devd](https://github.com/solokeys/solo/issues/144#issuecomment-500216020)
There is hope that `udev` itself will adopt the Fedora approach (which is to check for HID usage page `F1D0`, and avoids manually whitelisting each U2F/FIDO2 key): <https://github.com/systemd/systemd/issues/11996>.
Further progress is tracked in: <https://github.com/solokeys/solo/issues/144>.
If you still need to setup a rule, a simple way to do it is:
```
# U2F Zero
KERNEL=="hidraw*", SUBSYSTEM=="hidraw", ATTRS{idVendor}=="10c4", ATTRS{idProduct}=="8acf", TAG+="uaccess"
git clone https://github.com/solokeys/solo.git
cd solo/udev
make setup
```
Then run
Or, manually, create a file like [`70-solokeys-access.rules`](https://github.com/solokeys/solo/blob/master/udev/70-solokeys-access.rules) in your `/etc/udev/rules.d` directory.
Additionally, run the following command after you create this file (it is not necessary to do this again in the future):
```
udevadm trigger
sudo udevadm control --reload-rules && sudo udevadm trigger
```
# How do udev rules work and why are they needed
@ -30,13 +46,13 @@ You can either compare `ls /dev` before and after inserting, or use the `udevadm
```
udevadm monitor --environment --udev | grep DEVNAME
```
Typically, you will detect `/dev/hidraw0`.
Typically, you will detect `/dev/hidraw0`. Using the symlinks above, you can follow symlinks from `/dev/solokey` and `/dev/u2fzero`.
## How do you know if your system is configured correctly?
Try reading and writing to the device node you identified in the previous step. Assuming the node is called `/dev/hidraw0`:
* read: try `cat /dev/hidraw0`, if you don't get "permission denied", you can access.
* write: try `echo "hello, Solo" > /dev/hidraw0`. Again, if you don't get denied permission, you're OK.
* read: try `cat /dev/solokey`, if you don't get "permission denied", you can access.
* write: try `echo "hello, Solo" > /dev/solokey`. Again, if you don't get denied permission, you're OK.
## Which rule should I use, and how do I do it?
Simplest is probably to copy [Yubico's rule file](https://github.com/Yubico/libu2f-host/blob/master/70-u2f.rules) to `/etc/udev/rules.d/fido.rules` on your system, for instance:
@ -47,7 +63,7 @@ This contains rules for Yubico's keys, the U2F Zero, and many others. The releva
```
KERNEL=="hidraw*", SUBSYSTEM=="hidraw", ATTRS{idVendor}=="10c4", ATTRS{idProduct}=="8acf", TAG+="uaccess"
```
It matches on the correct vendor/product IDs of 10c4/8acf, and adds the TAG `uaccess`. Older versions of udev use rules such as
It matches on the correct vendor/product IDs of 10c4/8acf, and adds the TAG `uaccess`. Older versions of udev use rules such as
```
KERNEL=="hidraw*", SUBSYSTEM=="hidraw", ATTRS{idVendor}=="10c4", MODE="0644", GROUP="plugdev"
```
@ -60,7 +76,10 @@ udevadm trigger
```
## What about vendor and product ID for Solo?
Current prototypes reuse the IDs of the U2F Zero (10c4/8acf). The final Solo will probably be assigned new IDs; read about it here first :)
| Key | Vendor ID | Product ID |
| --- | --- | --- |
| Solo | 0483 | a2ca |
| U2F Zero | 10c4 | 8acf |
## You got this all wrong, I can't believe it!
Are you suffering from [us being wrong](https://xkcd.com/386/)? Please, send us a [pull request](https://github.com/SoloKeysSec/solo/pulls) and prove us wrong :D
Are you suffering from [us being wrong](https://xkcd.com/386/)? Please, send us a [pull request](https://github.com/solokeys/solo/pulls) and prove us wrong :D

136
fido2/apdu.c Normal file
View File

@ -0,0 +1,136 @@
// Copyright 2019 SoloKeys Developers
//
// Licensed under the Apache License, Version 2.0, <LICENSE-APACHE or
// http://apache.org/licenses/LICENSE-2.0> or the MIT license <LICENSE-MIT or
// http://opensource.org/licenses/MIT>, at your option. This file may not be
// copied, modified, or distributed except according to those terms.
// iso7816:2013. 5.3.2 Decoding conventions for command bodies
#include "apdu.h"
uint16_t apdu_decode(uint8_t *data, size_t len, APDU_STRUCT *apdu)
{
EXT_APDU_HEADER *hapdu = (EXT_APDU_HEADER *)data;
apdu->cla = hapdu->cla & 0xef; // mask chaining bit if any
apdu->ins = hapdu->ins;
apdu->p1 = hapdu->p1;
apdu->p2 = hapdu->p2;
apdu->lc = 0;
apdu->data = NULL;
apdu->le = 0;
apdu->extended_apdu = false;
apdu->case_type = 0x00;
uint8_t b0 = hapdu->lc[0];
// case 1
if (len == 4)
{
apdu->case_type = 0x01;
}
// case 2S (Le)
if (len == 5)
{
apdu->case_type = 0x02;
apdu->le = b0;
if (!apdu->le)
apdu->le = 0x100;
}
// case 3S (Lc + data)
if (len == 5U + b0 && b0 != 0)
{
apdu->case_type = 0x03;
apdu->lc = b0;
}
// case 4S (Lc + data + Le)
if (len == 5U + b0 + 1U && b0 != 0)
{
apdu->case_type = 0x04;
apdu->lc = b0;
apdu->le = data[len - 1];
if (!apdu->le)
apdu->le = 0x100;
}
// extended length apdu
if (len >= 7 && b0 == 0)
{
uint16_t extlen = (hapdu->lc[1] << 8) + hapdu->lc[2];
if (len - 7 < extlen)
{
return SW_WRONG_LENGTH;
}
// case 2E (Le) - extended
if (len == 7)
{
apdu->case_type = 0x12;
apdu->extended_apdu = true;
apdu->le = extlen;
if (!apdu->le)
apdu->le = 0x10000;
}
// case 3E (Lc + data) - extended
if (len == 7U + extlen)
{
apdu->case_type = 0x13;
apdu->extended_apdu = true;
apdu->lc = extlen;
}
// case 4E (Lc + data + Le) - extended 2-byte Le
if (len == 7U + extlen + 2U)
{
apdu->case_type = 0x14;
apdu->extended_apdu = true;
apdu->lc = extlen;
apdu->le = (data[len - 2] << 8) + data[len - 1];
if (!apdu->le)
apdu->le = 0x10000;
}
// case 4E (Lc + data + Le) - extended 3-byte Le
if (len == 7U + extlen + 3U && data[len - 3] == 0)
{
apdu->case_type = 0x24;
apdu->extended_apdu = true;
apdu->lc = extlen;
apdu->le = (data[len - 2] << 8) + data[len - 1];
if (!apdu->le)
apdu->le = 0x10000;
}
}
else
{
if ((len > 5) && (len - 5 < hapdu->lc[0]))
{
return SW_WRONG_LENGTH;
}
}
if (!apdu->case_type)
{
return SW_COND_USE_NOT_SATISFIED;
}
if (apdu->lc)
{
if (apdu->extended_apdu)
{
apdu->data = data + 7;
} else {
apdu->data = data + 5;
}
}
return 0;
}

63
fido2/apdu.h Normal file
View File

@ -0,0 +1,63 @@
#ifndef _APDU_H_
#define _APDU_H_
#include <stdint.h>
#include <stdbool.h>
#include <stddef.h>
typedef struct
{
uint8_t cla;
uint8_t ins;
uint8_t p1;
uint8_t p2;
uint8_t lc;
} __attribute__((packed)) APDU_HEADER;
typedef struct
{
uint8_t cla;
uint8_t ins;
uint8_t p1;
uint8_t p2;
uint8_t lc[3];
} __attribute__((packed)) EXT_APDU_HEADER;
typedef struct
{
uint8_t cla;
uint8_t ins;
uint8_t p1;
uint8_t p2;
uint16_t lc;
uint8_t *data;
uint32_t le;
bool extended_apdu;
uint8_t case_type;
} __attribute__((packed)) APDU_STRUCT;
extern uint16_t apdu_decode(uint8_t *data, size_t len, APDU_STRUCT *apdu);
#define APDU_FIDO_U2F_REGISTER 0x01
#define APDU_FIDO_U2F_AUTHENTICATE 0x02
#define APDU_FIDO_U2F_VERSION 0x03
#define APDU_FIDO_NFCCTAP_MSG 0x10
#define APDU_FIDO_U2F_VENDOR_FIRST 0xc0 // First vendor defined command
#define APDU_FIDO_U2F_VENDOR_LAST 0xff // Last vendor defined command
#define APDU_SOLO_RESET 0xee
#define APDU_INS_SELECT 0xA4
#define APDU_INS_READ_BINARY 0xB0
#define APDU_GET_RESPONSE 0xC0
#define SW_SUCCESS 0x9000
#define SW_GET_RESPONSE 0x6100 // Command successfully executed; 'XX' bytes of data are available and can be requested using GET RESPONSE.
#define SW_WRONG_LENGTH 0x6700
#define SW_COND_USE_NOT_SATISFIED 0x6985
#define SW_FILE_NOT_FOUND 0x6a82
#define SW_INCORRECT_P1P2 0x6a86
#define SW_INS_INVALID 0x6d00 // Instruction code not supported or invalid
#define SW_CLA_INVALID 0x6e00
#define SW_INTERNAL_EXCEPTION 0x6f00
#endif //_APDU_H_

View File

@ -1,24 +1,9 @@
/*
Copyright 2018 Conor Patrick
Permission is hereby granted, free of charge, to any person obtaining a copy of
this software and associated documentation files (the "Software"), to deal in
the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
of the Software, and to permit persons to whom the Software is furnished to do
so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
// Copyright 2019 SoloKeys Developers
//
// Licensed under the Apache License, Version 2.0, <LICENSE-APACHE or
// http://apache.org/licenses/LICENSE-2.0> or the MIT license <LICENSE-MIT or
// http://opensource.org/licenses/MIT>, at your option. This file may not be
// copied, modified, or distributed except according to those terms.
#ifndef _COSE_KEY_H
#define _COSE_KEY_H
@ -31,7 +16,7 @@
#define COSE_KEY_KTY_EC2 2
#define COSE_KEY_CRV_P256 1
#define COSE_ALG_ES256 -7
#define COSE_ALG_ES256 -7
#define COSE_ALG_ECDH_ES_HKDF_256 -25
#endif

View File

@ -1,3 +1,9 @@
// Copyright 2019 SoloKeys Developers
//
// Licensed under the Apache License, Version 2.0, <LICENSE-APACHE or
// http://apache.org/licenses/LICENSE-2.0> or the MIT license <LICENSE-MIT or
// http://opensource.org/licenses/MIT>, at your option. This file may not be
// copied, modified, or distributed except according to those terms.
/*
* Wrapper for crypto implementation on device
*
@ -18,7 +24,8 @@
#include "aes.h"
#include "ctap.h"
#include "device.h"
#include "app.h"
#include "log.h"
#include APP_CONFIG
#ifdef USING_PC
typedef enum
@ -40,7 +47,7 @@ typedef enum
#endif
const uint8_t attestation_cert_der[];
const uint8_t * attestation_cert_der;
const uint16_t attestation_cert_der_size;
const uint8_t attestation_key[];
const uint16_t attestation_key_size;
@ -53,7 +60,7 @@ static const uint8_t * _signing_key = NULL;
static int _key_len = 0;
// Secrets for testing only
static uint8_t master_secret[32];
static uint8_t master_secret[64];
static uint8_t transport_secret[32];
@ -66,13 +73,17 @@ void crypto_sha256_init()
void crypto_reset_master_secret()
{
ctap_generate_rng(master_secret, 32);
ctap_generate_rng(master_secret, 64);
ctap_generate_rng(transport_secret, 32);
}
void crypto_load_master_secret(uint8_t * key)
{
memmove(master_secret, key, 32);
memmove(transport_secret, key+32, 32);
#if KEY_SPACE_BYTES < 96
#error "need more key bytes"
#endif
memmove(master_secret, key, 64);
memmove(transport_secret, key+64, 32);
}
void crypto_sha256_update(uint8_t * data, size_t len)
@ -101,10 +112,15 @@ void crypto_sha256_hmac_init(uint8_t * key, uint32_t klen, uint8_t * hmac)
key = master_secret;
klen = sizeof(master_secret);
}
else if (key == CRYPTO_TRANSPORT_KEY)
{
key = transport_secret;
klen = 32;
}
if(klen > 64)
{
printf("Error, key size must be <= 64\n");
printf2(TAG_ERR,"Error, key size must be <= 64\n");
exit(1);
}
@ -134,7 +150,7 @@ void crypto_sha256_hmac_final(uint8_t * key, uint32_t klen, uint8_t * hmac)
if(klen > 64)
{
printf("Error, key size must be <= 64\n");
printf2(TAG_ERR,"Error, key size must be <= 64\n");
exit(1);
}
memmove(buf, key, klen);
@ -168,7 +184,7 @@ void crypto_ecc256_sign(uint8_t * data, int len, uint8_t * sig)
{
if ( uECC_sign(_signing_key, data, len, sig, _es256_curve) == 0)
{
printf("error, uECC failed\n");
printf2(TAG_ERR,"error, uECC failed\n");
exit(1);
}
}
@ -205,19 +221,19 @@ void crypto_ecdsa_sign(uint8_t * data, int len, uint8_t * sig, int MBEDTLS_ECP_I
if (_key_len != 32) goto fail;
break;
default:
printf("error, invalid ECDSA alg specifier\n");
printf2(TAG_ERR,"error, invalid ECDSA alg specifier\n");
exit(1);
}
if ( uECC_sign(_signing_key, data, len, sig, curve) == 0)
{
printf("error, uECC failed\n");
printf2(TAG_ERR,"error, uECC failed\n");
exit(1);
}
return;
fail:
printf("error, invalid key length\n");
printf2(TAG_ERR,"error, invalid key length\n");
exit(1);
}
@ -246,6 +262,11 @@ void crypto_ecc256_derive_public_key(uint8_t * data, int len, uint8_t * x, uint8
memmove(y,pubkey+32,32);
}
void crypto_ecc256_compute_public_key(uint8_t * privkey, uint8_t * pubkey)
{
uECC_compute_public_key(privkey, pubkey, _es256_curve);
}
void crypto_load_external_key(uint8_t * key, int len)
{
_signing_key = key;
@ -257,7 +278,7 @@ void crypto_ecc256_make_key_pair(uint8_t * pubkey, uint8_t * privkey)
{
if (uECC_make_key(pubkey, privkey, _es256_curve) != 1)
{
printf("Error, uECC_make_key failed\n");
printf2(TAG_ERR,"Error, uECC_make_key failed\n");
exit(1);
}
}
@ -266,7 +287,7 @@ void crypto_ecc256_shared_secret(const uint8_t * pubkey, const uint8_t * privkey
{
if (uECC_shared_secret(pubkey, privkey, shared_secret, _es256_curve) != 1)
{
printf("Error, uECC_shared_secret failed\n");
printf2(TAG_ERR,"Error, uECC_shared_secret failed\n");
exit(1);
}
@ -317,7 +338,7 @@ void crypto_aes256_encrypt(uint8_t * buf, int length)
}
const uint8_t attestation_cert_der[] =
const uint8_t _attestation_cert_der[] =
"\x30\x82\x01\xfb\x30\x82\x01\xa1\xa0\x03\x02\x01\x02\x02\x01\x00\x30\x0a\x06\x08"
"\x2a\x86\x48\xce\x3d\x04\x03\x02\x30\x2c\x31\x0b\x30\x09\x06\x03\x55\x04\x06\x13"
"\x02\x55\x53\x31\x0b\x30\x09\x06\x03\x55\x04\x08\x0c\x02\x4d\x44\x31\x10\x30\x0e"
@ -344,9 +365,11 @@ const uint8_t attestation_cert_der[] =
"\x7e\x74\x64\x1b\xa3\x7b\xf7\xe6\xd3\xaf\x79\x28\xdb\xdc\xa5\x88\x02\x21\x00\xcd"
"\x06\xf1\xe3\xab\x16\x21\x8e\xd8\xc0\x14\xaf\x09\x4f\x5b\x73\xef\x5e\x9e\x4b\xe7"
"\x35\xeb\xdd\x9b\x6d\x8f\x7d\xf3\xc4\x3a\xd7";
const uint8_t * attestation_cert_der = (const uint8_t *)_attestation_cert_der;
const uint16_t attestation_cert_der_size = sizeof(attestation_cert_der)-1;
uint16_t attestation_cert_der_get_size(){
return sizeof(_attestation_cert_der)-1;
}
const uint8_t attestation_key[] = "\xcd\x67\xaa\x31\x0d\x09\x1e\xd1\x6e\x7e\x98\x92\xaa\x07\x0e\x19\x94\xfc\xd7\x14\xae\x7c\x40\x8f\xb9\x46\xb7\x2e\x5f\xe7\x5d\x30";

View File

@ -1,24 +1,9 @@
/*
Copyright 2018 Conor Patrick
Permission is hereby granted, free of charge, to any person obtaining a copy of
this software and associated documentation files (the "Software"), to deal in
the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
of the Software, and to permit persons to whom the Software is furnished to do
so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
// Copyright 2019 SoloKeys Developers
//
// Licensed under the Apache License, Version 2.0, <LICENSE-APACHE or
// http://apache.org/licenses/LICENSE-2.0> or the MIT license <LICENSE-MIT or
// http://opensource.org/licenses/MIT>, at your option. This file may not be
// copied, modified, or distributed except according to those terms.
#ifndef _CRYPTO_H
#define _CRYPTO_H
@ -34,9 +19,14 @@ void crypto_sha256_final(uint8_t * hash);
void crypto_sha256_hmac_init(uint8_t * key, uint32_t klen, uint8_t * hmac);
void crypto_sha256_hmac_final(uint8_t * key, uint32_t klen, uint8_t * hmac);
void crypto_sha512_init();
void crypto_sha512_update(const uint8_t * data, size_t len);
void crypto_sha512_final(uint8_t * hash);
void crypto_ecc256_init();
void crypto_ecc256_derive_public_key(uint8_t * data, int len, uint8_t * x, uint8_t * y);
void crypto_ecc256_compute_public_key(uint8_t * privkey, uint8_t * pubkey);
void crypto_ecc256_load_key(uint8_t * data, int len, uint8_t * data2, int len2);
void crypto_ecc256_load_attestation_key();
@ -49,6 +39,7 @@ void generate_private_key(uint8_t * data, int len, uint8_t * data2, int len2, ui
void crypto_ecc256_make_key_pair(uint8_t * pubkey, uint8_t * privkey);
void crypto_ecc256_shared_secret(const uint8_t * pubkey, const uint8_t * privkey, uint8_t * shared_secret);
#define CRYPTO_TRANSPORT_KEY2 ((uint8_t*)2)
#define CRYPTO_TRANSPORT_KEY ((uint8_t*)1)
#define CRYPTO_MASTER_KEY ((uint8_t*)0)
@ -63,10 +54,7 @@ void crypto_reset_master_secret();
void crypto_load_master_secret(uint8_t * key);
extern const uint8_t attestation_cert_der[];
extern const uint16_t attestation_cert_der_size;
extern const uint8_t attestation_key[];
extern const uint16_t attestation_key_size;
extern const uint8_t * attestation_cert_der;
uint16_t attestation_cert_der_get_size();
#endif

File diff suppressed because it is too large Load Diff

View File

@ -1,24 +1,9 @@
/*
Copyright 2018 Conor Patrick
Permission is hereby granted, free of charge, to any person obtaining a copy of
this software and associated documentation files (the "Software"), to deal in
the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
of the Software, and to permit persons to whom the Software is furnished to do
so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
// Copyright 2019 SoloKeys Developers
//
// Licensed under the Apache License, Version 2.0, <LICENSE-APACHE or
// http://apache.org/licenses/LICENSE-2.0> or the MIT license <LICENSE-MIT or
// http://opensource.org/licenses/MIT>, at your option. This file may not be
// copied, modified, or distributed except according to those terms.
#ifndef _CTAP_H
#define _CTAP_H
@ -69,6 +54,13 @@
#define CP_getKeyAgreement 0x07
#define CP_getRetries 0x08
#define EXT_HMAC_SECRET_COSE_KEY 0x01
#define EXT_HMAC_SECRET_SALT_ENC 0x02
#define EXT_HMAC_SECRET_SALT_AUTH 0x03
#define EXT_HMAC_SECRET_REQUESTED 0x01
#define EXT_HMAC_SECRET_PARSED 0x02
#define RESP_versions 0x1
#define RESP_extensions 0x2
#define RESP_aaguid 0x3
@ -120,6 +112,8 @@
#define CREDENTIAL_ENC_SIZE 176 // pad to multiple of 16 bytes
#define PUB_KEY_CRED_PUB_KEY 0x01
#define PUB_KEY_CRED_CTAP1 0x41
#define PUB_KEY_CRED_CUSTOM 0x42
#define PUB_KEY_CRED_UNKNOWN 0x3F
#define CREDENTIAL_IS_SUPPORTED 1
@ -137,6 +131,8 @@
#define PIN_LOCKOUT_ATTEMPTS 8 // Number of attempts total
#define PIN_BOOT_ATTEMPTS 3 // number of attempts per boot
#define CTAP2_UP_DELAY_MS 29000
typedef struct
{
uint8_t id[USER_ID_MAX_SIZE];
@ -157,9 +153,13 @@ struct Credential {
CredentialId id;
CTAP_userEntity user;
};
typedef struct Credential CTAP_residentKey;
typedef struct
{
uint8_t type;
struct Credential credential;
} CTAP_credentialDescriptor;
typedef struct
{
@ -196,34 +196,67 @@ struct rpId
uint8_t name[RP_NAME_LIMIT];
};
typedef struct
{
struct{
uint8_t x[32];
uint8_t y[32];
} pubkey;
int kty;
int crv;
} COSE_key;
typedef struct
{
uint8_t saltLen;
uint8_t saltEnc[64];
uint8_t saltAuth[32];
COSE_key keyAgreement;
struct Credential * credential;
} CTAP_hmac_secret;
typedef struct
{
uint8_t hmac_secret_present;
CTAP_hmac_secret hmac_secret;
} CTAP_extensions;
typedef struct
{
CTAP_userEntity user;
uint8_t publicKeyCredentialType;
int32_t COSEAlgorithmIdentifier;
uint8_t rk;
} CTAP_credInfo;
typedef struct
{
uint32_t paramsParsed;
uint8_t clientDataHash[CLIENT_DATA_HASH_SIZE];
struct rpId rp;
CTAP_userEntity user;
uint8_t publicKeyCredentialType;
int32_t COSEAlgorithmIdentifier;
CTAP_credInfo credInfo;
CborValue excludeList;
size_t excludeListSize;
uint8_t rk;
uint8_t uv;
uint8_t up;
uint8_t pinAuth[16];
uint8_t pinAuthPresent;
// pinAuthEmpty is true iff an empty bytestring was provided as pinAuth.
// This is exclusive with |pinAuthPresent|. It exists because an empty
// pinAuth is a special signal to block for touch. See
// https://fidoalliance.org/specs/fido-v2.0-ps-20190130/fido-client-to-authenticator-protocol-v2.0-ps-20190130.html#using-pinToken-in-authenticatorMakeCredential
uint8_t pinAuthEmpty;
int pinProtocol;
CTAP_extensions extensions;
} CTAP_makeCredential;
typedef struct
{
uint8_t type;
struct Credential credential;
} CTAP_credentialDescriptor;
typedef struct
{
@ -241,26 +274,25 @@ typedef struct
uint8_t pinAuth[16];
uint8_t pinAuthPresent;
// pinAuthEmpty is true iff an empty bytestring was provided as pinAuth.
// This is exclusive with |pinAuthPresent|. It exists because an empty
// pinAuth is a special signal to block for touch. See
// https://fidoalliance.org/specs/fido-v2.0-ps-20190130/fido-client-to-authenticator-protocol-v2.0-ps-20190130.html#using-pinToken-in-authenticatorGetAssertion
uint8_t pinAuthEmpty;
int pinProtocol;
CTAP_credentialDescriptor creds[ALLOW_LIST_MAX_SIZE];
CTAP_credentialDescriptor * creds;
uint8_t allowListPresent;
CTAP_extensions extensions;
} CTAP_getAssertion;
typedef struct
{
int pinProtocol;
int subCommand;
struct
{
struct{
uint8_t x[32];
uint8_t y[32];
} pubkey;
int kty;
int crv;
} keyAgreement;
COSE_key keyAgreement;
uint8_t keyAgreementPresent;
uint8_t pinAuth[16];
uint8_t pinAuthPresent;
@ -273,13 +305,26 @@ typedef struct
} CTAP_clientPin;
struct _getAssertionState {
CTAP_authDataHeader authData;
uint8_t clientDataHash[CLIENT_DATA_HASH_SIZE];
CTAP_credentialDescriptor creds[ALLOW_LIST_MAX_SIZE];
uint8_t lastcmd;
uint32_t count;
uint32_t index;
uint32_t time;
uint8_t user_verified;
uint8_t customCredId[256];
uint8_t customCredIdSize;
};
void ctap_response_init(CTAP_RESPONSE * resp);
uint8_t ctap_request(uint8_t * pkt_raw, int length, CTAP_RESPONSE * resp);
// Encodes R,S signature to 2 der sequence of two integers. Sigder must be at least 72 bytes.
// @return length of der signature
int ctap_encode_der_sig(uint8_t * sigbuf, uint8_t * sigder);
int ctap_encode_der_sig(uint8_t const * const in_sigbuf, uint8_t * const out_sigder);
// Run ctap related power-up procedures (init pinToken, generate shared secret)
void ctap_init();
@ -314,5 +359,8 @@ uint16_t ctap_key_len(uint8_t index);
extern uint8_t PIN_TOKEN[PIN_TOKEN_SIZE];
extern uint8_t KEY_AGREEMENT_PUB[64];
void lock_device_permanently();
void ctap_load_external_keys(uint8_t * keybytes);
#endif

View File

@ -1,24 +1,9 @@
/*
Copyright 2018 Conor Patrick
Permission is hereby granted, free of charge, to any person obtaining a copy of
this software and associated documentation files (the "Software"), to deal in
the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
of the Software, and to permit persons to whom the Software is furnished to do
so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
// Copyright 2019 SoloKeys Developers
//
// Licensed under the Apache License, Version 2.0, <LICENSE-APACHE or
// http://apache.org/licenses/LICENSE-2.0> or the MIT license <LICENSE-MIT or
// http://opensource.org/licenses/MIT>, at your option. This file may not be
// copied, modified, or distributed except according to those terms.
#define CTAP1_ERR_SUCCESS 0x00
#define CTAP1_ERR_INVALID_COMMAND 0x01
#define CTAP1_ERR_INVALID_PARAMETER 0x02
@ -64,6 +49,7 @@
#define CTAP2_ERR_PIN_POLICY_VIOLATION 0x37
#define CTAP2_ERR_PIN_TOKEN_EXPIRED 0x38
#define CTAP2_ERR_REQUEST_TOO_LARGE 0x39
#define CTAP2_ERR_ACTION_TIMEOUT 0x3A
#define CTAP1_ERR_OTHER 0x7F
#define CTAP2_ERR_SPEC_LAST 0xDF
#define CTAP2_ERR_EXTENSION_FIRST 0xE0

View File

@ -1,35 +1,22 @@
/*
Copyright 2018 Conor Patrick
Permission is hereby granted, free of charge, to any person obtaining a copy of
this software and associated documentation files (the "Software"), to deal in
the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
of the Software, and to permit persons to whom the Software is furnished to do
so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
// Copyright 2019 SoloKeys Developers
//
// Licensed under the Apache License, Version 2.0, <LICENSE-APACHE or
// http://apache.org/licenses/LICENSE-2.0> or the MIT license <LICENSE-MIT or
// http://opensource.org/licenses/MIT>, at your option. This file may not be
// copied, modified, or distributed except according to those terms.
#include <stdint.h>
#include "cbor.h"
#include "ctap.h"
#include "u2f.h"
#include "ctap_parse.h"
#include "ctap_errors.h"
#include "cose_key.h"
#include "util.h"
#include "log.h"
extern struct _getAssertionState getAssertionState;
void _check_ret(CborError ret, int line, const char * filename)
{
@ -94,7 +81,7 @@ uint8_t parse_user(CTAP_makeCredential * MC, CborValue * val)
size_t sz, map_length;
uint8_t key[24];
int ret;
int i;
unsigned int i;
CborValue map;
@ -143,14 +130,13 @@ uint8_t parse_user(CTAP_makeCredential * MC, CborValue * val)
}
sz = USER_ID_MAX_SIZE;
ret = cbor_value_copy_byte_string(&map, MC->user.id, &sz, NULL);
ret = cbor_value_copy_byte_string(&map, MC->credInfo.user.id, &sz, NULL);
if (ret == CborErrorOutOfMemory)
{
printf2(TAG_ERR,"Error, USER_ID is too large\n");
return CTAP2_ERR_LIMIT_EXCEEDED;
}
MC->user.id_size = sz;
printf1(TAG_GREEN,"parsed id_size: %d\r\n", MC->user.id_size);
MC->credInfo.user.id_size = sz;
check_ret(ret);
}
else if (strcmp((const char *)key, "name") == 0)
@ -161,12 +147,12 @@ uint8_t parse_user(CTAP_makeCredential * MC, CborValue * val)
return CTAP2_ERR_INVALID_CBOR_TYPE;
}
sz = USER_NAME_LIMIT;
ret = cbor_value_copy_text_string(&map, (char *)MC->user.name, &sz, NULL);
ret = cbor_value_copy_text_string(&map, (char *)MC->credInfo.user.name, &sz, NULL);
if (ret != CborErrorOutOfMemory)
{ // Just truncate the name it's okay
check_ret(ret);
}
MC->user.name[USER_NAME_LIMIT - 1] = 0;
MC->credInfo.user.name[USER_NAME_LIMIT - 1] = 0;
}
else if (strcmp((const char *)key, "displayName") == 0)
{
@ -176,12 +162,12 @@ uint8_t parse_user(CTAP_makeCredential * MC, CborValue * val)
return CTAP2_ERR_INVALID_CBOR_TYPE;
}
sz = DISPLAY_NAME_LIMIT;
ret = cbor_value_copy_text_string(&map, (char *)MC->user.displayName, &sz, NULL);
ret = cbor_value_copy_text_string(&map, (char *)MC->credInfo.user.displayName, &sz, NULL);
if (ret != CborErrorOutOfMemory)
{ // Just truncate the name it's okay
check_ret(ret);
}
MC->user.displayName[DISPLAY_NAME_LIMIT - 1] = 0;
MC->credInfo.user.displayName[DISPLAY_NAME_LIMIT - 1] = 0;
}
else if (strcmp((const char *)key, "icon") == 0)
{
@ -191,12 +177,12 @@ uint8_t parse_user(CTAP_makeCredential * MC, CborValue * val)
return CTAP2_ERR_INVALID_CBOR_TYPE;
}
sz = ICON_LIMIT;
ret = cbor_value_copy_text_string(&map, (char *)MC->user.icon, &sz, NULL);
ret = cbor_value_copy_text_string(&map, (char *)MC->credInfo.user.icon, &sz, NULL);
if (ret != CborErrorOutOfMemory)
{ // Just truncate the name it's okay
check_ret(ret);
}
MC->user.icon[ICON_LIMIT - 1] = 0;
MC->credInfo.user.icon[ICON_LIMIT - 1] = 0;
}
else
@ -285,7 +271,7 @@ uint8_t parse_pub_key_cred_params(CTAP_makeCredential * MC, CborValue * val)
uint8_t cred_type;
int32_t alg_type;
int ret;
int i;
unsigned int i;
CborValue arr;
@ -320,8 +306,8 @@ uint8_t parse_pub_key_cred_params(CTAP_makeCredential * MC, CborValue * val)
{
if (pub_key_cred_param_supported(cred_type, alg_type) == CREDENTIAL_IS_SUPPORTED)
{
MC->publicKeyCredentialType = cred_type;
MC->COSEAlgorithmIdentifier = alg_type;
MC->credInfo.publicKeyCredentialType = cred_type;
MC->credInfo.COSEAlgorithmIdentifier = alg_type;
MC->paramsParsed |= PARAM_pubKeyCredParams;
return 0;
}
@ -334,7 +320,7 @@ uint8_t parse_pub_key_cred_params(CTAP_makeCredential * MC, CborValue * val)
return CTAP2_ERR_UNSUPPORTED_ALGORITHM;
}
uint8_t parse_fixed_byte_string(CborValue * map, uint8_t * dst, int len)
uint8_t parse_fixed_byte_string(CborValue * map, uint8_t * dst, unsigned int len)
{
size_t sz;
int ret;
@ -359,7 +345,7 @@ uint8_t parse_fixed_byte_string(CborValue * map, uint8_t * dst, int len)
uint8_t parse_verify_exclude_list(CborValue * val)
{
int i;
unsigned int i;
int ret;
CborValue arr;
size_t size;
@ -408,7 +394,7 @@ uint8_t parse_rp(struct rpId * rp, CborValue * val)
size_t sz, map_length;
char key[8];
int ret;
int i;
unsigned int i;
CborValue map;
@ -496,7 +482,7 @@ uint8_t parse_options(CborValue * val, uint8_t * rk, uint8_t * uv, uint8_t * up)
size_t sz, map_length;
char key[8];
int ret;
int i;
unsigned int i;
_Bool b;
CborValue map;
@ -536,7 +522,7 @@ uint8_t parse_options(CborValue * val, uint8_t * rk, uint8_t * uv, uint8_t * up)
if (cbor_value_get_type(&map) != CborBooleanType)
{
printf2(TAG_ERR,"Error, expecting text string type for rp map value\n");
printf2(TAG_ERR,"Error, expecting bool type for option map value\n");
return CTAP2_ERR_INVALID_CBOR_TYPE;
}
@ -571,16 +557,165 @@ uint8_t parse_options(CborValue * val, uint8_t * rk, uint8_t * uv, uint8_t * up)
return 0;
}
uint8_t ctap_parse_hmac_secret(CborValue * val, CTAP_hmac_secret * hs)
{
size_t map_length;
size_t salt_len;
uint8_t parsed_count = 0;
int key;
int ret;
unsigned int i;
CborValue map;
if (cbor_value_get_type(val) != CborMapType)
{
printf2(TAG_ERR,"error, wrong type\n");
return CTAP2_ERR_INVALID_CBOR_TYPE;
}
ret = cbor_value_enter_container(val,&map);
check_ret(ret);
ret = cbor_value_get_map_length(val, &map_length);
check_ret(ret);
for (i = 0; i < map_length; i++)
{
if (cbor_value_get_type(&map) != CborIntegerType)
{
printf2(TAG_ERR,"Error, expecting CborIntegerTypefor hmac-secret map key, got %s\n", cbor_value_get_type_string(&map));
return CTAP2_ERR_INVALID_CBOR_TYPE;
}
ret = cbor_value_get_int(&map, &key);
check_ret(ret);
ret = cbor_value_advance(&map);
check_ret(ret);
switch(key)
{
case EXT_HMAC_SECRET_COSE_KEY:
ret = parse_cose_key(&map, &hs->keyAgreement);
check_retr(ret);
parsed_count++;
break;
case EXT_HMAC_SECRET_SALT_ENC:
salt_len = 64;
ret = cbor_value_copy_byte_string(&map, hs->saltEnc, &salt_len, NULL);
if ((salt_len != 32 && salt_len != 64) || ret == CborErrorOutOfMemory)
{
return CTAP1_ERR_INVALID_LENGTH;
}
check_ret(ret);
hs->saltLen = salt_len;
parsed_count++;
break;
case EXT_HMAC_SECRET_SALT_AUTH:
salt_len = 32;
ret = cbor_value_copy_byte_string(&map, hs->saltAuth, &salt_len, NULL);
check_ret(ret);
parsed_count++;
break;
}
ret = cbor_value_advance(&map);
check_ret(ret);
}
if (parsed_count != 3)
{
printf2(TAG_ERR, "ctap_parse_hmac_secret missing parameter. Got %d.\r\n", parsed_count);
return CTAP2_ERR_MISSING_PARAMETER;
}
return 0;
}
uint8_t ctap_parse_extensions(CborValue * val, CTAP_extensions * ext)
{
CborValue map;
size_t sz, map_length;
char key[16];
int ret;
unsigned int i;
bool b;
if (cbor_value_get_type(val) != CborMapType)
{
printf2(TAG_ERR,"error, wrong type\n");
return CTAP2_ERR_INVALID_CBOR_TYPE;
}
ret = cbor_value_enter_container(val, &map);
check_ret(ret);
ret = cbor_value_get_map_length(val, &map_length);
check_ret(ret);
for (i = 0; i < map_length; i++)
{
if (cbor_value_get_type(&map) != CborTextStringType)
{
printf2(TAG_ERR,"Error, expecting text string type for options map key, got %s\n", cbor_value_get_type_string(&map));
return CTAP2_ERR_INVALID_CBOR_TYPE;
}
sz = sizeof(key);
ret = cbor_value_copy_text_string(&map, key, &sz, NULL);
if (ret == CborErrorOutOfMemory)
{
printf2(TAG_ERR,"Error, rp map key is too large. Ignoring.\n");
cbor_value_advance(&map);
cbor_value_advance(&map);
continue;
}
check_ret(ret);
key[sizeof(key) - 1] = 0;
ret = cbor_value_advance(&map);
check_ret(ret);
if (strncmp(key, "hmac-secret",11) == 0)
{
if (cbor_value_get_type(&map) == CborBooleanType)
{
ret = cbor_value_get_boolean(&map, &b);
check_ret(ret);
if (b) ext->hmac_secret_present = EXT_HMAC_SECRET_REQUESTED;
printf1(TAG_CTAP, "set hmac_secret_present to %d\r\n", b);
}
else if (cbor_value_get_type(&map) == CborMapType)
{
ret = ctap_parse_hmac_secret(&map, &ext->hmac_secret);
check_retr(ret);
ext->hmac_secret_present = EXT_HMAC_SECRET_PARSED;
printf1(TAG_CTAP, "parsed hmac_secret request\r\n");
}
else
{
printf1(TAG_RED, "warning: hmac_secret request ignored for being wrong type\r\n");
}
}
ret = cbor_value_advance(&map);
check_ret(ret);
}
return 0;
}
uint8_t ctap_parse_make_credential(CTAP_makeCredential * MC, CborEncoder * encoder, uint8_t * request, int length)
{
int ret;
int i;
unsigned int i;
int key;
size_t map_length;
CborParser parser;
CborValue it,map;
memset(MC, 0, sizeof(CTAP_makeCredential));
MC->up = 0xff;
ret = cbor_parser_init(request, length, CborValidateCanonicalFormat, &parser, &it);
check_retr(ret);
@ -646,8 +781,8 @@ uint8_t ctap_parse_make_credential(CTAP_makeCredential * MC, CborEncoder * encod
ret = parse_user(MC, &map);
printf1(TAG_MC," ID: "); dump_hex1(TAG_MC, MC->user.id, MC->user.id_size);
printf1(TAG_MC," name: %s\n", MC->user.name);
printf1(TAG_MC," ID: "); dump_hex1(TAG_MC, MC->credInfo.user.id, MC->credInfo.user.id_size);
printf1(TAG_MC," name: %s\n", MC->credInfo.user.name);
break;
case MC_pubKeyCredParams:
@ -655,8 +790,8 @@ uint8_t ctap_parse_make_credential(CTAP_makeCredential * MC, CborEncoder * encod
ret = parse_pub_key_cred_params(MC, &map);
printf1(TAG_MC," cred_type: 0x%02x\n", MC->publicKeyCredentialType);
printf1(TAG_MC," alg_type: %d\n", MC->COSEAlgorithmIdentifier);
printf1(TAG_MC," cred_type: 0x%02x\n", MC->credInfo.publicKeyCredentialType);
printf1(TAG_MC," alg_type: %d\n", MC->credInfo.COSEAlgorithmIdentifier);
break;
case MC_excludeList:
@ -680,21 +815,31 @@ uint8_t ctap_parse_make_credential(CTAP_makeCredential * MC, CborEncoder * encod
{
return CTAP2_ERR_INVALID_CBOR_TYPE;
}
ret = ctap_parse_extensions(&map, &MC->extensions);
check_retr(ret);
break;
case MC_options:
printf1(TAG_MC,"CTAP_options\n");
ret = parse_options(&map, &MC->rk, &MC->uv, &MC->up);
ret = parse_options(&map, &MC->credInfo.rk, &MC->uv, &MC->up);
check_retr(ret);
break;
case MC_pinAuth:
case MC_pinAuth: {
printf1(TAG_MC,"CTAP_pinAuth\n");
size_t pinSize;
if (cbor_value_get_type(&map) == CborByteStringType &&
cbor_value_get_string_length(&map, &pinSize) == CborNoError &&
pinSize == 0)
{
MC->pinAuthEmpty = 1;
break;
}
ret = parse_fixed_byte_string(&map, MC->pinAuth, 16);
if (CTAP1_ERR_INVALID_LENGTH != ret) // damn microsoft
{
check_retr(ret);
}
else
{
@ -702,6 +847,7 @@ uint8_t ctap_parse_make_credential(CTAP_makeCredential * MC, CborEncoder * encod
}
MC->pinAuthPresent = 1;
break;
}
case MC_pinProtocol:
printf1(TAG_MC,"CTAP_pinProtocol\n");
if (cbor_value_get_type(&map) == CborIntegerType)
@ -738,6 +884,8 @@ uint8_t parse_credential_descriptor(CborValue * arr, CTAP_credentialDescriptor *
size_t buflen;
char type[12];
CborValue val;
cred->type = 0;
if (cbor_value_get_type(arr) != CborMapType)
{
printf2(TAG_ERR,"Error, CborMapType expected in credential\n");
@ -754,12 +902,22 @@ uint8_t parse_credential_descriptor(CborValue * arr, CTAP_credentialDescriptor *
}
buflen = sizeof(CredentialId);
cbor_value_copy_byte_string(&val, (uint8_t*)&cred->credential.id, &buflen, NULL);
if (buflen != sizeof(CredentialId))
ret = cbor_value_copy_byte_string(&val, (uint8_t*)&cred->credential.id, &buflen, NULL);
if (buflen == U2F_KEY_HANDLE_SIZE)
{
printf2(TAG_ERR,"Ignoring credential is incorrect length\n");
//return CTAP2_ERR_CBOR_UNEXPECTED_TYPE; // maybe just skip it instead of fail?
printf2(TAG_PARSE,"CTAP1 credential\n");
cred->type = PUB_KEY_CRED_CTAP1;
}
else if (buflen != sizeof(CredentialId))
{
printf2(TAG_ERR,"Ignoring credential is incorrect length, treating as custom\n");
cred->type = PUB_KEY_CRED_CUSTOM;
buflen = 256;
ret = cbor_value_copy_byte_string(&val, getAssertionState.customCredId, &buflen, NULL);
getAssertionState.customCredIdSize = buflen;
}
check_ret(ret);
ret = cbor_value_map_find_value(arr, "type", &val);
check_ret(ret);
@ -771,11 +929,23 @@ uint8_t parse_credential_descriptor(CborValue * arr, CTAP_credentialDescriptor *
}
buflen = sizeof(type);
cbor_value_copy_text_string(&val, type, &buflen, NULL);
ret = cbor_value_copy_text_string(&val, type, &buflen, NULL);
if (ret == CborErrorOutOfMemory)
{
cred->type = PUB_KEY_CRED_UNKNOWN;
}
else
{
check_ret(ret);
}
if (strncmp(type, "public-key",11) == 0)
{
cred->type = PUB_KEY_CRED_PUB_KEY;
if (0 == cred->type)
{
cred->type = PUB_KEY_CRED_PUB_KEY;
}
}
else
{
@ -790,7 +960,8 @@ uint8_t parse_allow_list(CTAP_getAssertion * GA, CborValue * it)
{
CborValue arr;
size_t len;
int i,ret;
int ret;
unsigned int i;
CTAP_credentialDescriptor * cred;
if (cbor_value_get_type(it) != CborArrayType)
@ -832,13 +1003,16 @@ uint8_t parse_allow_list(CTAP_getAssertion * GA, CborValue * it)
uint8_t ctap_parse_get_assertion(CTAP_getAssertion * GA, uint8_t * request, int length)
{
int ret;
int i;
unsigned int i;
int key;
size_t map_length;
CborParser parser;
CborValue it,map;
memset(GA, 0, sizeof(CTAP_getAssertion));
GA->creds = getAssertionState.creds; // Save stack memory
GA->up = 0xff;
ret = cbor_parser_init(request, length, CborValidateCanonicalFormat, &parser, &it);
check_ret(ret);
@ -900,6 +1074,8 @@ uint8_t ctap_parse_get_assertion(CTAP_getAssertion * GA, uint8_t * request, int
break;
case GA_extensions:
printf1(TAG_GA,"GA_extensions\n");
ret = ctap_parse_extensions(&map, &GA->extensions);
check_retr(ret);
break;
case GA_options:
@ -907,9 +1083,18 @@ uint8_t ctap_parse_get_assertion(CTAP_getAssertion * GA, uint8_t * request, int
ret = parse_options(&map, &GA->rk, &GA->uv, &GA->up);
check_retr(ret);
break;
case GA_pinAuth:
case GA_pinAuth: {
printf1(TAG_GA,"CTAP_pinAuth\n");
size_t pinSize;
if (cbor_value_get_type(&map) == CborByteStringType &&
cbor_value_get_string_length(&map, &pinSize) == CborNoError &&
pinSize == 0)
{
GA->pinAuthEmpty = 1;
break;
}
ret = parse_fixed_byte_string(&map, GA->pinAuth, 16);
if (CTAP1_ERR_INVALID_LENGTH != ret) // damn microsoft
{
@ -925,6 +1110,7 @@ uint8_t ctap_parse_get_assertion(CTAP_getAssertion * GA, uint8_t * request, int
GA->pinAuthPresent = 1;
break;
}
case GA_pinProtocol:
printf1(TAG_GA,"CTAP_pinProtocol\n");
if (cbor_value_get_type(&map) == CborIntegerType)
@ -954,14 +1140,15 @@ uint8_t ctap_parse_get_assertion(CTAP_getAssertion * GA, uint8_t * request, int
return 0;
}
uint8_t parse_cose_key(CborValue * it, uint8_t * x, uint8_t * y, int * kty, int * crv)
uint8_t parse_cose_key(CborValue * it, COSE_key * cose)
{
CborValue map;
size_t map_length;
int i,ret,key;
int ret,key;
unsigned int i;
int xkey = 0,ykey = 0;
*kty = 0;
*crv = 0;
cose->kty = 0;
cose->crv = 0;
CborType type = cbor_value_get_type(it);
@ -999,7 +1186,7 @@ uint8_t parse_cose_key(CborValue * it, uint8_t * x, uint8_t * y, int * kty, int
printf1(TAG_PARSE,"COSE_KEY_LABEL_KTY\n");
if (cbor_value_get_type(&map) == CborIntegerType)
{
ret = cbor_value_get_int_checked(&map, kty);
ret = cbor_value_get_int_checked(&map, &cose->kty);
check_ret(ret);
}
else
@ -1014,7 +1201,7 @@ uint8_t parse_cose_key(CborValue * it, uint8_t * x, uint8_t * y, int * kty, int
printf1(TAG_PARSE,"COSE_KEY_LABEL_CRV\n");
if (cbor_value_get_type(&map) == CborIntegerType)
{
ret = cbor_value_get_int_checked(&map, crv);
ret = cbor_value_get_int_checked(&map, &cose->crv);
check_ret(ret);
}
else
@ -1024,14 +1211,14 @@ uint8_t parse_cose_key(CborValue * it, uint8_t * x, uint8_t * y, int * kty, int
break;
case COSE_KEY_LABEL_X:
printf1(TAG_PARSE,"COSE_KEY_LABEL_X\n");
ret = parse_fixed_byte_string(&map, x, 32);
ret = parse_fixed_byte_string(&map, cose->pubkey.x, 32);
check_retr(ret);
xkey = 1;
break;
case COSE_KEY_LABEL_Y:
printf1(TAG_PARSE,"COSE_KEY_LABEL_Y\n");
ret = parse_fixed_byte_string(&map, y, 32);
ret = parse_fixed_byte_string(&map, cose->pubkey.y, 32);
check_retr(ret);
ykey = 1;
@ -1043,7 +1230,7 @@ uint8_t parse_cose_key(CborValue * it, uint8_t * x, uint8_t * y, int * kty, int
ret = cbor_value_advance(&map);
check_ret(ret);
}
if (xkey == 0 || ykey == 0 || *kty == 0 || *crv == 0)
if (xkey == 0 || ykey == 0 || cose->kty == 0 || cose->crv == 0)
{
return CTAP2_ERR_MISSING_PARAMETER;
}
@ -1053,7 +1240,7 @@ uint8_t parse_cose_key(CborValue * it, uint8_t * x, uint8_t * y, int * kty, int
uint8_t ctap_parse_client_pin(CTAP_clientPin * CP, uint8_t * request, int length)
{
int ret;
int i;
unsigned int i;
int key;
size_t map_length;
size_t sz;
@ -1123,7 +1310,7 @@ uint8_t ctap_parse_client_pin(CTAP_clientPin * CP, uint8_t * request, int length
break;
case CP_keyAgreement:
printf1(TAG_CP,"CP_keyAgreement\n");
ret = parse_cose_key(&map, CP->keyAgreement.pubkey.x, CP->keyAgreement.pubkey.y, &CP->keyAgreement.kty, &CP->keyAgreement.crv);
ret = parse_cose_key(&map, &CP->keyAgreement);
check_retr(ret);
CP->keyAgreementPresent = 1;
break;

View File

@ -1,24 +1,9 @@
/*
Copyright 2018 Conor Patrick
Permission is hereby granted, free of charge, to any person obtaining a copy of
this software and associated documentation files (the "Software"), to deal in
the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
of the Software, and to permit persons to whom the Software is furnished to do
so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
// Copyright 2019 SoloKeys Developers
//
// Licensed under the Apache License, Version 2.0, <LICENSE-APACHE or
// http://apache.org/licenses/LICENSE-2.0> or the MIT license <LICENSE-MIT or
// http://opensource.org/licenses/MIT>, at your option. This file may not be
// copied, modified, or distributed except according to those terms.
#ifndef _CTAP_PARSE_H
#define _CTAP_PARSE_H
@ -39,13 +24,13 @@ const char * cbor_value_get_type_string(const CborValue *value);
uint8_t parse_user(CTAP_makeCredential * MC, CborValue * val);
uint8_t parse_pub_key_cred_param(CborValue * val, uint8_t * cred_type, int32_t * alg_type);
uint8_t parse_pub_key_cred_params(CTAP_makeCredential * MC, CborValue * val);
uint8_t parse_fixed_byte_string(CborValue * map, uint8_t * dst, int len);
uint8_t parse_fixed_byte_string(CborValue * map, uint8_t * dst, unsigned int len);
uint8_t parse_rp_id(struct rpId * rp, CborValue * val);
uint8_t parse_rp(struct rpId * rp, CborValue * val);
uint8_t parse_options(CborValue * val, uint8_t * rk, uint8_t * uv, uint8_t * up);
uint8_t parse_allow_list(CTAP_getAssertion * GA, CborValue * it);
uint8_t parse_cose_key(CborValue * it, uint8_t * x, uint8_t * y, int * kty, int * crv);
uint8_t parse_cose_key(CborValue * it, COSE_key * cose);
uint8_t ctap_parse_make_credential(CTAP_makeCredential * MC, CborEncoder * encoder, uint8_t * request, int length);

View File

@ -1,24 +1,9 @@
/*
Copyright 2018 Conor Patrick
Permission is hereby granted, free of charge, to any person obtaining a copy of
this software and associated documentation files (the "Software"), to deal in
the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
of the Software, and to permit persons to whom the Software is furnished to do
so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
// Copyright 2019 SoloKeys Developers
//
// Licensed under the Apache License, Version 2.0, <LICENSE-APACHE or
// http://apache.org/licenses/LICENSE-2.0> or the MIT license <LICENSE-MIT or
// http://opensource.org/licenses/MIT>, at your option. This file may not be
// copied, modified, or distributed except according to those terms.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
@ -30,7 +15,15 @@
#include "time.h"
#include "util.h"
#include "log.h"
#include "app.h"
#include "extensions.h"
#include "version.h"
// move custom SHA512 command out,
// and the following headers too
#include "sha2.h"
#include "crypto.h"
#include APP_CONFIG
typedef enum
{
@ -112,7 +105,7 @@ static uint32_t get_new_cid()
static int8_t add_cid(uint32_t cid)
{
int i;
uint32_t i;
for(i = 0; i < CID_MAX-1; i++)
{
if (!CIDS[i].busy)
@ -128,7 +121,7 @@ static int8_t add_cid(uint32_t cid)
static int8_t cid_exists(uint32_t cid)
{
int i;
uint32_t i;
for(i = 0; i < CID_MAX-1; i++)
{
if (CIDS[i].cid == cid)
@ -141,7 +134,7 @@ static int8_t cid_exists(uint32_t cid)
static int8_t cid_refresh(uint32_t cid)
{
int i;
uint32_t i;
for(i = 0; i < CID_MAX-1; i++)
{
if (CIDS[i].cid == cid)
@ -156,7 +149,7 @@ static int8_t cid_refresh(uint32_t cid)
static int8_t cid_del(uint32_t cid)
{
int i;
uint32_t i;
for(i = 0; i < CID_MAX-1; i++)
{
if (CIDS[i].cid == cid)
@ -394,7 +387,7 @@ static int ctaphid_buffer_packet(uint8_t * pkt_raw, uint8_t * cmd, uint32_t * ci
printf1(TAG_HID, "Recv packet\n");
printf1(TAG_HID, " CID: %08x \n", pkt->cid);
printf1(TAG_HID, " cmd: %02x\n", pkt->pkt.init.cmd);
if (!is_cont_pkt(pkt)) printf1(TAG_HID, " length: %d\n", ctaphid_packet_len(pkt));
if (!is_cont_pkt(pkt)) {printf1(TAG_HID, " length: %d\n", ctaphid_packet_len(pkt));}
int ret;
uint32_t oldcid;
@ -542,20 +535,31 @@ static int ctaphid_buffer_packet(uint8_t * pkt_raw, uint8_t * cmd, uint32_t * ci
return buffer_status();
}
extern void _check_ret(CborError ret, int line, const char * filename);
#define check_hardcore(r) _check_ret(r,__LINE__, __FILE__);\
if ((r) != CborNoError) exit(1);
uint8_t ctaphid_custom_command(int len, CTAP_RESPONSE * ctap_resp, CTAPHID_WRITE_BUFFER * wb);
uint8_t ctaphid_handle_packet(uint8_t * pkt_raw)
{
uint8_t cmd;
uint8_t cmd = 0;
uint32_t cid;
int len;
int len = 0;
#ifndef DISABLE_CTAPHID_CBOR
int status;
#endif
static uint8_t is_busy = 0;
static CTAPHID_WRITE_BUFFER wb;
CTAP_RESPONSE ctap_resp;
uint32_t t1,t2;
int bufstatus = ctaphid_buffer_packet(pkt_raw, &cmd, &cid, &len);
ctaphid_write_buffer_init(&wb);
wb.cid = cid;
wb.cmd = cmd;
if (bufstatus == HID_IGNORE)
{
@ -591,25 +595,20 @@ uint8_t ctaphid_handle_packet(uint8_t * pkt_raw)
case CTAPHID_PING:
printf1(TAG_HID,"CTAPHID_PING\n");
ctaphid_write_buffer_init(&wb);
wb.cid = cid;
wb.cmd = CTAPHID_PING;
wb.bcnt = len;
t1 = millis();
timestamp();
ctaphid_write(&wb, ctap_buffer, len);
ctaphid_write(&wb, NULL,0);
t2 = millis();
printf1(TAG_TIME,"PING writeback: %d ms\n",(uint32_t)(t2-t1));
printf1(TAG_TIME,"PING writeback: %d ms\n",timestamp());
break;
#endif
#ifndef DISABLE_CTAPHID_WINK
case CTAPHID_WINK:
printf1(TAG_HID,"CTAPHID_WINK\n");
ctaphid_write_buffer_init(&wb);
wb.cid = cid;
wb.cmd = CTAPHID_WINK;
device_wink();
ctaphid_write(&wb,NULL,0);
@ -635,18 +634,14 @@ uint8_t ctaphid_handle_packet(uint8_t * pkt_raw)
ctap_response_init(&ctap_resp);
status = ctap_request(ctap_buffer, len, &ctap_resp);
ctaphid_write_buffer_init(&wb);
wb.cid = cid;
wb.cmd = CTAPHID_CBOR;
wb.bcnt = (ctap_resp.length+1);
t1 = millis();
timestamp();
ctaphid_write(&wb, &status, 1);
ctaphid_write(&wb, ctap_resp.data, ctap_resp.length);
ctaphid_write(&wb, NULL, 0);
t2 = millis();
printf1(TAG_TIME,"CBOR writeback: %d ms\n",(uint32_t)(t2-t1));
printf1(TAG_TIME,"CBOR writeback: %d ms\n",timestamp());
is_busy = 0;
break;
#endif
@ -669,9 +664,6 @@ uint8_t ctaphid_handle_packet(uint8_t * pkt_raw)
ctap_response_init(&ctap_resp);
u2f_request((struct u2f_request_apdu*)ctap_buffer, &ctap_resp);
ctaphid_write_buffer_init(&wb);
wb.cid = cid;
wb.cmd = CTAPHID_MSG;
wb.bcnt = (ctap_resp.length);
ctaphid_write(&wb, ctap_resp.data, ctap_resp.length);
@ -682,10 +674,14 @@ uint8_t ctaphid_handle_packet(uint8_t * pkt_raw)
printf1(TAG_HID,"CTAPHID_CANCEL\n");
is_busy = 0;
break;
default:
printf2(TAG_ERR,"error, unimplemented HID cmd: %02x\r\n", buffer_cmd());
ctaphid_send_error(cid, CTAP1_ERR_INVALID_COMMAND);
break;
if (ctaphid_custom_command(len, &ctap_resp, &wb) != 0){
is_busy = 0;
}else{
printf2(TAG_ERR, "error, unimplemented HID cmd: %02x\r\n", buffer_cmd());
ctaphid_send_error(cid, CTAP1_ERR_INVALID_COMMAND);
}
}
cid_del(cid);
buffer_reset();
@ -695,3 +691,114 @@ uint8_t ctaphid_handle_packet(uint8_t * pkt_raw)
else return 0;
}
uint8_t ctaphid_custom_command(int len, CTAP_RESPONSE * ctap_resp, CTAPHID_WRITE_BUFFER * wb)
{
ctap_response_init(ctap_resp);
#if !defined(IS_BOOTLOADER) && (defined(SOLO_EXPERIMENTAL))
uint32_t param;
#endif
#if defined(IS_BOOTLOADER)
uint8_t is_busy;
#endif
switch(wb->cmd)
{
#if defined(IS_BOOTLOADER)
case CTAPHID_BOOT:
printf1(TAG_HID,"CTAPHID_BOOT\n");
u2f_set_writeback_buffer(ctap_resp);
is_busy = bootloader_bridge(len, ctap_buffer);
wb->bcnt = 1 + ctap_resp->length;
ctaphid_write(wb, &is_busy, 1);
ctaphid_write(wb, ctap_resp->data, ctap_resp->length);
ctaphid_write(wb, NULL, 0);
return 1;
#endif
#if defined(SOLO)
case CTAPHID_ENTERBOOT:
printf1(TAG_HID,"CTAPHID_ENTERBOOT\n");
boot_solo_bootloader();
wb->bcnt = 0;
ctaphid_write(wb, NULL, 0);
return 1;
#endif
#if !defined(IS_BOOTLOADER)
case CTAPHID_GETRNG:
printf1(TAG_HID,"CTAPHID_GETRNG\n");
wb->bcnt = ctap_buffer[0];
if (!wb->bcnt)
wb->bcnt = 57;
memset(ctap_buffer,0,wb->bcnt);
ctap_generate_rng(ctap_buffer, wb->bcnt);
ctaphid_write(wb, ctap_buffer, wb->bcnt);
ctaphid_write(wb, NULL, 0);
return 1;
break;
#endif
case CTAPHID_GETVERSION:
printf1(TAG_HID,"CTAPHID_GETVERSION\n");
wb->bcnt = 4;
ctap_buffer[0] = SOLO_VERSION_MAJ;
ctap_buffer[1] = SOLO_VERSION_MIN;
ctap_buffer[2] = SOLO_VERSION_PATCH;
#if defined(SOLO)
ctap_buffer[3] = solo_is_locked();
#else
ctap_buffer[3] = 0;
#endif
ctaphid_write(wb, ctap_buffer, 4);
ctaphid_write(wb, NULL, 0);
return 1;
break;
#if !defined(IS_BOOTLOADER) && (defined(SOLO_EXPERIMENTAL))
case CTAPHID_LOADKEY:
/**
* Load external key. Useful for enabling backups.
* bytes: 4 96
* payload: | counter_increase (BE) | master_key |
*
* Counter should be increased by a large amount, e.g. (0x10000000)
* to outdo any previously lost/broken keys.
*/
printf1(TAG_HID,"CTAPHID_LOADKEY\n");
if (len != 100)
{
printf2(TAG_ERR,"Error, invalid length.\n");
ctaphid_send_error(wb->cid, CTAP1_ERR_INVALID_LENGTH);
return 1;
}
// Ask for THREE button presses
if (ctap_user_presence_test(8000) > 0)
if (ctap_user_presence_test(8000) > 0)
if (ctap_user_presence_test(8000) > 0)
{
ctap_load_external_keys(ctap_buffer + 4);
param = ctap_buffer[3];
param |= ctap_buffer[2] << 8;
param |= ctap_buffer[1] << 16;
param |= ctap_buffer[0] << 24;
ctap_atomic_count(param);
wb->bcnt = 0;
ctaphid_write(wb, NULL, 0);
return 1;
}
printf2(TAG_ERR, "Error, invalid length.\n");
ctaphid_send_error(wb->cid, CTAP2_ERR_OPERATION_DENIED);
return 1;
#endif
}
return 0;
}

View File

@ -1,24 +1,9 @@
/*
Copyright 2018 Conor Patrick
Permission is hereby granted, free of charge, to any person obtaining a copy of
this software and associated documentation files (the "Software"), to deal in
the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
of the Software, and to permit persons to whom the Software is furnished to do
so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
// Copyright 2019 SoloKeys Developers
//
// Licensed under the Apache License, Version 2.0, <LICENSE-APACHE or
// http://apache.org/licenses/LICENSE-2.0> or the MIT license <LICENSE-MIT or
// http://opensource.org/licenses/MIT>, at your option. This file may not be
// copied, modified, or distributed except according to those terms.
#ifndef _CTAPHID_H_H
#define _CTAPHID_H_H
@ -38,6 +23,16 @@
#define CTAPHID_ERROR (TYPE_INIT | 0x3f)
#define CTAPHID_KEEPALIVE (TYPE_INIT | 0x3b)
// Custom commands between 0x40-0x7f
#define CTAPHID_BOOT (TYPE_INIT | 0x50)
#define CTAPHID_ENTERBOOT (TYPE_INIT | 0x51)
#define CTAPHID_ENTERSTBOOT (TYPE_INIT | 0x52)
#define CTAPHID_GETRNG (TYPE_INIT | 0x60)
#define CTAPHID_GETVERSION (TYPE_INIT | 0x61)
#define CTAPHID_LOADKEY (TYPE_INIT | 0x62)
// reserved for debug, not implemented except for HACKER and DEBUG_LEVEl > 0
#define CTAPHID_PROBE (TYPE_INIT | 0x70)
#define ERR_INVALID_CMD 0x01
#define ERR_INVALID_PAR 0x02
#define ERR_INVALID_SEQ 0x04

91
fido2/data_migration.c Normal file
View File

@ -0,0 +1,91 @@
// Copyright 2019 SoloKeys Developers
//
// Licensed under the Apache License, Version 2.0, <LICENSE-APACHE or
// http://apache.org/licenses/LICENSE-2.0> or the MIT license <LICENSE-MIT or
// http://opensource.org/licenses/MIT>, at your option. This file may not be
// copied, modified, or distributed except according to those terms.
#include "data_migration.h"
#include "log.h"
#include "device.h"
#include "crypto.h"
// TODO move from macro to function/assert for better readability?
#define check(x) assert(state_prev_0xff->x == state_tmp_ptr->x);
#define check_buf(x) assert(memcmp(state_prev_0xff->x, state_tmp_ptr->x, sizeof(state_tmp_ptr->x)) == 0);
bool migrate_from_FF_to_01(AuthenticatorState_0xFF* state_prev_0xff, AuthenticatorState_0x01* state_tmp_ptr){
// Calculate PIN hash, and replace PIN raw storage with it; add version to structure
// other ingredients do not change
if (state_tmp_ptr->data_version != 0xFF)
return false;
static_assert(sizeof(AuthenticatorState_0xFF) <= sizeof(AuthenticatorState_0x01), "New state structure is smaller, than current one, which is not handled");
if (ctap_generate_rng(state_tmp_ptr->PIN_SALT, sizeof(state_tmp_ptr->PIN_SALT)) != 1) {
printf2(TAG_ERR, "Error, rng failed\n");
return false;
}
if (state_prev_0xff->is_pin_set){
crypto_sha256_init();
crypto_sha256_update(state_prev_0xff->pin_code, state_prev_0xff->pin_code_length);
uint8_t intermediateHash[32];
crypto_sha256_final(intermediateHash);
crypto_sha256_init();
crypto_sha256_update(intermediateHash, 16);
memset(intermediateHash, 0, sizeof(intermediateHash));
crypto_sha256_update(state_tmp_ptr->PIN_SALT, sizeof(state_tmp_ptr->PIN_SALT));
crypto_sha256_final(state_tmp_ptr->PIN_CODE_HASH);
}
assert(state_tmp_ptr->_reserved == state_prev_0xff->pin_code_length);
state_tmp_ptr->_reserved = 0xFF;
state_tmp_ptr->data_version = 1;
check(is_initialized);
check(is_pin_set);
check(remaining_tries);
check(rk_stored);
check_buf(key_lens);
check_buf(key_space);
assert(state_tmp_ptr->data_version != 0xFF);
return true;
}
void save_migrated_state(AuthenticatorState *state_tmp_ptr) {
memmove(&STATE, state_tmp_ptr, sizeof(AuthenticatorState));
authenticator_write_state(state_tmp_ptr, 0);
authenticator_write_state(state_tmp_ptr, 1);
}
void do_migration_if_required(AuthenticatorState* state_current){
// Currently handles only state structures with the same size, or bigger
// FIXME rework to raw buffers with fixed size to allow state structure size decrease
if(!state_current->is_initialized)
return;
AuthenticatorState state_tmp;
AuthenticatorState state_previous;
authenticator_read_state(&state_previous);
authenticator_read_state(&state_tmp);
if(state_current->data_version == 0xFF){
printf2(TAG_ERR, "Running migration\n");
bool success = migrate_from_FF_to_01((AuthenticatorState_0xFF *) &state_previous, &state_tmp);
if (!success){
printf2(TAG_ERR, "Failed migration from 0xFF to 1\n");
// FIXME discuss migration failure behavior
goto return_cleanup;
}
dump_hex1(TAG_ERR, (void*)&state_tmp, sizeof(state_tmp));
dump_hex1(TAG_ERR, (void*)&state_previous, sizeof(state_previous));
save_migrated_state(&state_tmp);
}
assert(state_current->data_version == STATE_VERSION);
return_cleanup:
memset(&state_tmp, 0, sizeof(AuthenticatorState));
memset(&state_previous, 0, sizeof(AuthenticatorState));
}

15
fido2/data_migration.h Normal file
View File

@ -0,0 +1,15 @@
// Copyright 2019 SoloKeys Developers
//
// Licensed under the Apache License, Version 2.0, <LICENSE-APACHE or
// http://apache.org/licenses/LICENSE-2.0> or the MIT license <LICENSE-MIT or
// http://opensource.org/licenses/MIT>, at your option. This file may not be
// copied, modified, or distributed except according to those terms.
#ifndef FIDO2_PR_DATA_MIGRATION_H
#define FIDO2_PR_DATA_MIGRATION_H
#include "storage.h"
void do_migration_if_required(AuthenticatorState* state_current);
#endif //FIDO2_PR_DATA_MIGRATION_H

View File

@ -1,30 +1,15 @@
/*
Copyright 2018 Conor Patrick
Permission is hereby granted, free of charge, to any person obtaining a copy of
this software and associated documentation files (the "Software"), to deal in
the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
of the Software, and to permit persons to whom the Software is furnished to do
so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
// Copyright 2019 SoloKeys Developers
//
// Licensed under the Apache License, Version 2.0, <LICENSE-APACHE or
// http://apache.org/licenses/LICENSE-2.0> or the MIT license <LICENSE-MIT or
// http://opensource.org/licenses/MIT>, at your option. This file may not be
// copied, modified, or distributed except according to those terms.
#ifndef _DEVICE_H
#define _DEVICE_H
#include "storage.h"
void device_init();
void device_init(int argc, char *argv[]);
uint32_t millis();
@ -45,6 +30,8 @@ void main_loop_delay();
void heartbeat();
void device_reboot();
void authenticator_read_state(AuthenticatorState * );
void authenticator_read_backup_state(AuthenticatorState * );
@ -60,27 +47,30 @@ void device_manage();
// sets status that's uses for sending status updates ~100ms.
// A timer should be set up to call `ctaphid_update_status`
void device_set_status(int status);
void device_set_status(uint32_t status);
// Returns if button is currently pressed
int device_is_button_pressed();
// Test for user presence
// Return 1 for user is present, 0 user not present, -1 if cancel is requested.
extern int ctap_user_presence_test();
// Return 2 for disabled, 1 for user is present, 0 user not present, -1 if cancel is requested.
int ctap_user_presence_test(uint32_t delay);
// Generate @num bytes of random numbers to @dest
// return 1 if success, error otherwise
extern int ctap_generate_rng(uint8_t * dst, size_t num);
int ctap_generate_rng(uint8_t * dst, size_t num);
// Increment atomic counter and return it.
// Must support two counters, @sel selects counter0 or counter1.
uint32_t ctap_atomic_count(int sel);
// @param amount the amount to increase the counter by.
uint32_t ctap_atomic_count(uint32_t amount);
// Verify the user
// return 1 if user is verified, 0 if not
extern int ctap_user_verification(uint8_t arg);
int ctap_user_verification(uint8_t arg);
// Must be implemented by application
// data is HID_MESSAGE_SIZE long in bytes
extern void ctaphid_write_block(uint8_t * data);
void ctaphid_write_block(uint8_t * data);
// Resident key
@ -90,4 +80,34 @@ void ctap_store_rk(int index,CTAP_residentKey * rk);
void ctap_load_rk(int index,CTAP_residentKey * rk);
void ctap_overwrite_rk(int index,CTAP_residentKey * rk);
// For Solo hacker
void boot_solo_bootloader();
void boot_st_bootloader();
// HID wink command
void device_wink();
typedef enum {
DEVICE_LOW_POWER_IDLE = 0,
DEVICE_LOW_POWER_FAST = 1,
DEVICE_FAST = 2,
} DEVICE_CLOCK_RATE;
// Set the clock rate for the device.
// Three modes are targetted for Solo.
// 0: Lowest clock rate for NFC.
// 1: fastest clock rate supported at a low power setting for NFC FIDO.
// 2: fastest clock rate. Generally for USB interface.
void device_set_clock_rate(DEVICE_CLOCK_RATE param);
// Returns NFC_IS_NA, NFC_IS_ACTIVE, or NFC_IS_AVAILABLE
#define NFC_IS_NA 0
#define NFC_IS_ACTIVE 1
#define NFC_IS_AVAILABLE 2
int device_is_nfc();
void device_disable_up(bool request_active);
void device_init_button();
#endif

View File

@ -1,35 +1,121 @@
/*
Copyright 2018 Conor Patrick
// Copyright 2019 SoloKeys Developers
//
// Licensed under the Apache License, Version 2.0, <LICENSE-APACHE or
// http://apache.org/licenses/LICENSE-2.0> or the MIT license <LICENSE-MIT or
// http://opensource.org/licenses/MIT>, at your option. This file may not be
// copied, modified, or distributed except according to those terms.
Permission is hereby granted, free of charge, to any person obtaining a copy of
this software and associated documentation files (the "Software"), to deal in
the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
of the Software, and to permit persons to whom the Software is furnished to do
so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
#include <stdint.h>
#include "extensions.h"
#include "u2f.h"
#include "ctap.h"
#include "wallet.h"
#include "solo.h"
#include "device.h"
#include "log.h"
int16_t extend_u2f(struct u2f_request_apdu* req, uint32_t len)
#define htonl(x) (((x & 0xff) << 24) | ((x & 0xff00) << 8) \
| ((x & 0xff0000) >> 8) | ((x & 0xff000000) >> 24) )
int is_extension_request(uint8_t * kh, int len)
{
wallet_request * req = (wallet_request *) kh;
if (len < WALLET_MIN_LENGTH)
return 0;
return memcmp(req->tag, WALLET_TAG, sizeof(WALLET_TAG)-1) == 0;
}
int extension_needs_atomic_count(uint8_t klen, uint8_t * keyh)
{
return ((wallet_request *) keyh)->operation == WalletRegister
|| ((wallet_request *) keyh)->operation == WalletSign;
}
static uint8_t * output_buffer_ptr;
uint8_t output_buffer_offset;
uint8_t output_buffer_size;
void extension_writeback_init(uint8_t * buffer, uint8_t size)
{
output_buffer_ptr = buffer;
output_buffer_offset = 0;
output_buffer_size = size;
}
void extension_writeback(uint8_t * buf, uint8_t size)
{
if ((output_buffer_offset + size) > output_buffer_size)
{
return;
}
memmove(output_buffer_ptr + output_buffer_offset, buf, size);
output_buffer_offset += size;
}
int16_t bridge_u2f_to_extensions(uint8_t * _chal, uint8_t * _appid, uint8_t klen, uint8_t * keyh)
{
int8_t ret = 0;
uint32_t count;
uint8_t up = 1;
uint8_t sig[72];
if (extension_needs_atomic_count(klen, keyh))
{
count = htonl(ctap_atomic_count(0));
}
else
{
count = htonl(10);
}
u2f_response_writeback(&up,1);
u2f_response_writeback((uint8_t *)&count,4);
u2f_response_writeback((uint8_t *)&ret,1);
#ifdef IS_BOOTLOADER
ret = bootloader_bridge(klen, keyh);
#else
ret = bridge_u2f_to_solo(sig, keyh, klen);
u2f_response_writeback(sig,72);
#endif
if (ret != 0)
{
u2f_reset_response();
u2f_response_writeback(&up,1);
u2f_response_writeback((uint8_t *)&count,4);
memset(sig,0,sizeof(sig));
sig[0] = ret;
u2f_response_writeback(sig,72);
}
return U2F_SW_NO_ERROR;
}
// Returns 1 if this is a extension request.
// Else 0 if nothing is done.
int16_t extend_fido2(CredentialId * credid, uint8_t * output)
{
if (is_extension_request((uint8_t*)credid, sizeof(CredentialId)))
{
printf1(TAG_EXT,"IS EXT REQ\r\n");
output[0] = bridge_u2f_to_solo(output+1, (uint8_t*)credid, sizeof(CredentialId));
return 1;
}
else
{
return 0;
}
}
int16_t extend_u2f(APDU_HEADER * req, uint8_t * payload, uint32_t len)
{
struct u2f_authenticate_request * auth = (struct u2f_authenticate_request *) req->payload;
struct u2f_authenticate_request * auth = (struct u2f_authenticate_request *) payload;
uint16_t rcode;
if (req->ins == U2F_AUTHENTICATE)
@ -37,7 +123,7 @@ int16_t extend_u2f(struct u2f_request_apdu* req, uint32_t len)
if (req->p1 == U2F_AUTHENTICATE_CHECK)
{
if (is_wallet_device((uint8_t *) &auth->kh, auth->khl)) // Pin requests
if (is_extension_request((uint8_t *) &auth->kh, auth->khl)) // Pin requests
{
rcode = U2F_SW_CONDITIONS_NOT_SATISFIED;
}
@ -45,23 +131,25 @@ int16_t extend_u2f(struct u2f_request_apdu* req, uint32_t len)
{
rcode = U2F_SW_WRONG_DATA;
}
printf1(TAG_WALLET,"Ignoring U2F request\n");
printf1(TAG_EXT,"Ignoring U2F check request\n");
dump_hex1(TAG_EXT, (uint8_t *) &auth->kh, auth->khl);
goto end;
}
else
{
if ( ! is_wallet_device((uint8_t *) &auth->kh, auth->khl)) // Pin requests
if ( ! is_extension_request((uint8_t *) &auth->kh, auth->khl)) // Pin requests
{
rcode = U2F_SW_WRONG_PAYLOAD;
printf1(TAG_WALLET,"Ignoring U2F request\n");
rcode = U2F_SW_WRONG_DATA;
printf1(TAG_EXT, "Ignoring U2F auth request\n");
dump_hex1(TAG_EXT, (uint8_t *) &auth->kh, auth->khl);
goto end;
}
rcode = bridge_u2f_to_wallet(auth->chal, auth->app, auth->khl, (uint8_t*)&auth->kh);
rcode = bridge_u2f_to_extensions(auth->chal, auth->app, auth->khl, (uint8_t*)&auth->kh);
}
}
else if (req->ins == U2F_VERSION)
{
printf1(TAG_U2F, "U2F_VERSION\n");
printf1(TAG_EXT, "U2F_VERSION\n");
if (len)
{
rcode = U2F_SW_WRONG_LENGTH;

View File

@ -1,28 +1,29 @@
/*
Copyright 2018 Conor Patrick
Permission is hereby granted, free of charge, to any person obtaining a copy of
this software and associated documentation files (the "Software"), to deal in
the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
of the Software, and to permit persons to whom the Software is furnished to do
so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
// Copyright 2019 SoloKeys Developers
//
// Licensed under the Apache License, Version 2.0, <LICENSE-APACHE or
// http://apache.org/licenses/LICENSE-2.0> or the MIT license <LICENSE-MIT or
// http://opensource.org/licenses/MIT>, at your option. This file may not be
// copied, modified, or distributed except according to those terms.
#ifndef EXTENSIONS_H_
#define EXTENSIONS_H_
#include "u2f.h"
#include "apdu.h"
int16_t extend_u2f(struct u2f_request_apdu* req, uint32_t len);
int16_t bridge_u2f_to_extensions(uint8_t * chal, uint8_t * appid, uint8_t klen, uint8_t * keyh);
// return 1 if request is a wallet request
int is_extension_request(uint8_t * req, int len);
int16_t extend_u2f(APDU_HEADER * req, uint8_t * payload, uint32_t len);
int16_t extend_fido2(CredentialId * credid, uint8_t * output);
int bootloader_bridge(int klen, uint8_t * keyh);
int is_extension_request(uint8_t * kh, int len);
void extension_writeback_init(uint8_t * buffer, uint8_t size);
void extension_writeback(uint8_t * buf, uint8_t size);
#endif /* EXTENSIONS_H_ */

84
fido2/extensions/solo.c Normal file
View File

@ -0,0 +1,84 @@
/*
* Copyright (C) 2018 SoloKeys, Inc. <https://solokeys.com/>
*
* This file is part of Solo.
*
* Solo 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, either version 3 of the License, or
* (at your option) any later version.
*
* Solo 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 Solo. If not, see <https://www.gnu.org/licenses/>
*
* This code is available under licenses for commercial use.
* Please contact SoloKeys for more information.
*/
#include <stdint.h>
#include "extensions.h"
#include "u2f.h"
#include "wallet.h"
#include "device.h"
#include "ctap.h"
#include "ctap_errors.h"
#include "log.h"
#include APP_CONFIG
// output must be at least 71 bytes
int16_t bridge_u2f_to_solo(uint8_t * output, uint8_t * keyh, int keylen)
{
int8_t ret = 0;
wallet_request * req = (wallet_request *) keyh;
extension_writeback_init(output, 71);
printf1(TAG_WALLET, "u2f-solo [%d]: ", keylen); dump_hex1(TAG_WALLET, keyh, keylen);
switch(req->operation)
{
case WalletVersion:
output[0] = SOLO_VERSION_MAJ;
output[1] = SOLO_VERSION_MIN;
output[2] = SOLO_VERSION_PATCH;
break;
case WalletRng:
printf1(TAG_WALLET,"SoloRng\n");
ret = ctap_generate_rng(output, 71);
if (ret != 1)
{
printf1(TAG_WALLET,"Rng failed\n");
ret = CTAP2_ERR_PROCESSING;
goto cleanup;
}
ret = 0;
break;
#ifdef ENABLE_WALLET
case WalletSign:
case WalletRegister:
case WalletPin:
case WalletReset:
return bridge_to_wallet(keyh, keylen);
#endif
default:
printf2(TAG_ERR,"Invalid wallet command: %x\n",req->operation);
ret = CTAP1_ERR_INVALID_COMMAND;
break;
}
cleanup:
return ret;
}

27
fido2/extensions/solo.h Normal file
View File

@ -0,0 +1,27 @@
/*
* Copyright (C) 2018 SoloKeys, Inc. <https://solokeys.com/>
*
* This file is part of Solo.
*
* Solo 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, either version 3 of the License, or
* (at your option) any later version.
*
* Solo 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 Solo. If not, see <https://www.gnu.org/licenses/>
*
* This code is available under licenses for commercial use.
* Please contact SoloKeys for more information.
*/
#ifndef SOLO_H_
#define SOLO_H_
int16_t bridge_u2f_to_solo(uint8_t * output, uint8_t * keyh, int keylen);
#endif

View File

@ -1,26 +1,11 @@
/*
Copyright 2018 Conor Patrick
Permission is hereby granted, free of charge, to any person obtaining a copy of
this software and associated documentation files (the "Software"), to deal in
the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
of the Software, and to permit persons to whom the Software is furnished to do
so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
// Copyright 2019 SoloKeys Developers
//
// Licensed under the Apache License, Version 2.0, <LICENSE-APACHE or
// http://apache.org/licenses/LICENSE-2.0> or the MIT license <LICENSE-MIT or
// http://opensource.org/licenses/MIT>, at your option. This file may not be
// copied, modified, or distributed except according to those terms.
#include "wallet.h"
#include "app.h"
#include APP_CONFIG
#include "ctap.h"
#include "ctap_errors.h"
#include "crypto.h"
@ -29,8 +14,8 @@
#include "util.h"
#include "storage.h"
#include "device.h"
#include "extensions.h"
#if defined(USING_PC) || defined(IS_BOOTLOADER)
typedef enum
{
MBEDTLS_ECP_DP_NONE = 0,
@ -47,30 +32,8 @@ typedef enum
MBEDTLS_ECP_DP_SECP224K1, /*!< 224-bits "Koblitz" curve */
MBEDTLS_ECP_DP_SECP256K1, /*!< 256-bits "Koblitz" curve */
} mbedtls_ecp_group_id;
#else
#include "ecp.h"
#endif
typedef enum
{
WalletSign = 0x10,
WalletRegister = 0x11,
WalletPin = 0x12,
WalletReset= 0x13,
WalletVersion= 0x14,
WalletRng = 0x15,
} WalletOperation;
int is_wallet_device(uint8_t * kh, int len)
{
wallet_request * req = (wallet_request *) kh;
if (len < WALLET_MIN_LENGTH)
return 0;
return memcmp(req->tag, WALLET_TAG, sizeof(WALLET_TAG)-1) == 0;
}
// return 1 if hash is valid, 0 otherwise
int check_pinhash(uint8_t * pinAuth, uint8_t * msg, uint8_t len)
@ -105,14 +68,14 @@ int8_t wallet_pin(uint8_t subcmd, uint8_t * pinAuth, uint8_t * arg1, uint8_t * a
return CTAP2_ERR_NOT_ALLOWED;
}
u2f_response_writeback(KEY_AGREEMENT_PUB,sizeof(KEY_AGREEMENT_PUB));
extension_writeback(KEY_AGREEMENT_PUB,sizeof(KEY_AGREEMENT_PUB));
printf1(TAG_WALLET,"pubkey: "); dump_hex1(TAG_WALLET,KEY_AGREEMENT_PUB,64);
break;
case CP_cmdGetRetries:
printf1(TAG_WALLET,"cmdGetRetries\n");
pinTokenEnc[0] = ctap_leftover_pin_attempts();
u2f_response_writeback(pinTokenEnc,1);
extension_writeback(pinTokenEnc,1);
break;
case CP_cmdSetPin:
@ -122,7 +85,7 @@ int8_t wallet_pin(uint8_t subcmd, uint8_t * pinAuth, uint8_t * arg1, uint8_t * a
return CTAP2_ERR_NOT_ALLOWED;
}
if (!ctap_user_presence_test())
if (!ctap_user_presence_test(5000))
{
return CTAP2_ERR_OPERATION_DENIED;
}
@ -132,7 +95,7 @@ int8_t wallet_pin(uint8_t subcmd, uint8_t * pinAuth, uint8_t * arg1, uint8_t * a
if (ret != 0)
return ret;
printf1(TAG_WALLET,"Success. Pin = %s\n", STATE.pin_code);
// printf1(TAG_WALLET,"Success. Pin = %s\n", STATE.pin_code);
break;
case CP_cmdChangePin:
@ -148,7 +111,7 @@ int8_t wallet_pin(uint8_t subcmd, uint8_t * pinAuth, uint8_t * arg1, uint8_t * a
return CTAP2_ERR_NOT_ALLOWED;
}
if (!ctap_user_presence_test())
if (!ctap_user_presence_test(5000))
{
return CTAP2_ERR_OPERATION_DENIED;
}
@ -170,7 +133,7 @@ int8_t wallet_pin(uint8_t subcmd, uint8_t * pinAuth, uint8_t * arg1, uint8_t * a
return CTAP2_ERR_NOT_ALLOWED;
}
if (!ctap_user_presence_test())
if (!ctap_user_presence_test(5000))
{
return CTAP2_ERR_OPERATION_DENIED;
}
@ -180,7 +143,7 @@ int8_t wallet_pin(uint8_t subcmd, uint8_t * pinAuth, uint8_t * arg1, uint8_t * a
return ret;
printf1(TAG_WALLET,"pinToken: "); dump_hex1(TAG_WALLET, PIN_TOKEN, 16);
u2f_response_writeback(pinTokenEnc, PIN_TOKEN_SIZE);
extension_writeback(pinTokenEnc, PIN_TOKEN_SIZE);
break;
@ -194,14 +157,13 @@ int8_t wallet_pin(uint8_t subcmd, uint8_t * pinAuth, uint8_t * arg1, uint8_t * a
return 0;
}
int16_t bridge_u2f_to_wallet(uint8_t * _chal, uint8_t * _appid, uint8_t klen, uint8_t * keyh)
int16_t bridge_to_wallet(uint8_t * keyh, uint8_t klen)
{
static uint8_t msg_buf[WALLET_MAX_BUFFER];
int reqlen = klen;
int i;
int8_t ret = 0;
uint32_t count;
uint8_t up = 1;
uint8_t sig[200];
uint8_t * args[5] = {NULL,NULL,NULL,NULL,NULL};
@ -222,21 +184,6 @@ int16_t bridge_u2f_to_wallet(uint8_t * _chal, uint8_t * _appid, uint8_t klen, ui
printf1(TAG_WALLET, "u2f2wallet [%d]: ",reqlen); dump_hex1(TAG_WALLET, msg_buf,reqlen);
if (req->operation == WalletRegister || req->operation == WalletSign)
{
count = ctap_atomic_count(0);
}
else
{
count = 10;
}
u2f_response_writeback(&up,1);
u2f_response_writeback((uint8_t *)&count,4);
u2f_response_writeback((uint8_t *)&ret,1);
#ifndef IS_BOOTLOADER
int offset = 0;
for (i = 0; i < MIN(5,req->numArgs); i++)
{
@ -310,7 +257,7 @@ int16_t bridge_u2f_to_wallet(uint8_t * _chal, uint8_t * _appid, uint8_t klen, ui
crypto_load_external_key(key, keysize);
crypto_ecdsa_sign(args[0], lens[0], sig, MBEDTLS_ECP_DP_SECP256K1);
u2f_response_writeback(sig,64);
extension_writeback(sig,64);
break;
case WalletRegister:
@ -348,8 +295,6 @@ int16_t bridge_u2f_to_wallet(uint8_t * _chal, uint8_t * _appid, uint8_t klen, ui
memmove(chksum, args[0] + lens[0] - 4, 4);
lens[0] -= 4;
/*printf("chksum: "); dump_hex1(TAG_WALLET, chksum, 4);*/
// perform integrity check
/*printf1(TAG_WALLET,"shasum on [%d]: ",lens[0]); dump_hex1(TAG_WALLET, args[0], lens[0]);*/
crypto_sha256_init();
@ -414,7 +359,7 @@ int16_t bridge_u2f_to_wallet(uint8_t * _chal, uint8_t * _appid, uint8_t klen, ui
}
}
if (ctap_user_presence_test())
if (ctap_user_presence_test(5000))
{
printf1(TAG_WALLET,"Reseting device!\n");
ctap_reset();
@ -427,63 +372,15 @@ int16_t bridge_u2f_to_wallet(uint8_t * _chal, uint8_t * _appid, uint8_t klen, ui
break;
case WalletVersion:
u2f_response_writeback((uint8_t*)WALLET_VERSION, sizeof(WALLET_VERSION)-1);
break;
case WalletRng:
printf1(TAG_WALLET,"WalletRng\n");
if ( ctap_device_locked() )
{
printf1(TAG_ERR,"device locked\n");
ret = CTAP2_ERR_NOT_ALLOWED;
goto cleanup;
}
if ( ctap_is_pin_set() )
{
if ( ! check_pinhash(req->pinAuth, msg_buf, reqlen))
{
printf2(TAG_ERR,"pinAuth is NOT valid\n");
dump_hex1(TAG_ERR,msg_buf,reqlen);
ret = CTAP2_ERR_PIN_AUTH_INVALID;
goto cleanup;
}
}
ret = ctap_generate_rng(sig, 72);
if (ret != 1)
{
printf1(TAG_WALLET,"Rng failed\n");
ret = CTAP2_ERR_PROCESSING;
goto cleanup;
}
ret = 0;
u2f_response_writeback((uint8_t *)sig,72);
break;
default:
printf2(TAG_ERR,"Invalid wallet command: %x\n",req->operation);
ret = CTAP1_ERR_INVALID_COMMAND;
break;
}
#else
ret = bootloader_bridge(klen, keyh);
#endif
cleanup:
if (ret != 0)
{
u2f_reset_response();
u2f_response_writeback(&up,1);
u2f_response_writeback((uint8_t *)&count,4);
memset(sig,0,sizeof(sig));
sig[0] = ret;
u2f_response_writeback(sig,72);
}
else
{
/*u2f_response_writeback(sig,sizeof(sig));*/
}
return U2F_SW_NO_ERROR;
return ret;
}

View File

@ -1,25 +1,9 @@
/*
Copyright 2018 Conor Patrick
Permission is hereby granted, free of charge, to any person obtaining a copy of
this software and associated documentation files (the "Software"), to deal in
the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
of the Software, and to permit persons to whom the Software is furnished to do
so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
// Copyright 2019 SoloKeys Developers
//
// Licensed under the Apache License, Version 2.0, <LICENSE-APACHE or
// http://apache.org/licenses/LICENSE-2.0> or the MIT license <LICENSE-MIT or
// http://opensource.org/licenses/MIT>, at your option. This file may not be
// copied, modified, or distributed except according to those terms.
#ifndef WALLET_H_
#define WALLET_H_
@ -92,10 +76,18 @@ typedef struct
}__attribute__((packed)) wallet_request;
int16_t bridge_u2f_to_wallet(uint8_t * chal, uint8_t * appid, uint8_t klen, uint8_t * keyh);
typedef enum
{
WalletSign = 0x10,
WalletRegister = 0x11,
WalletPin = 0x12,
WalletReset= 0x13,
WalletVersion= 0x14,
WalletRng = 0x15,
} WalletOperation;
// return 1 if request is a wallet request
int is_wallet_device(uint8_t * req, int len);
int16_t bridge_to_wallet(uint8_t * keyh, uint8_t klen);
void wallet_init();

View File

@ -1,36 +1,27 @@
/*
Copyright 2018 Conor Patrick
Permission is hereby granted, free of charge, to any person obtaining a copy of
this software and associated documentation files (the "Software"), to deal in
the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
of the Software, and to permit persons to whom the Software is furnished to do
so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
// Copyright 2019 SoloKeys Developers
//
// Licensed under the Apache License, Version 2.0, <LICENSE-APACHE or
// http://apache.org/licenses/LICENSE-2.0> or the MIT license <LICENSE-MIT or
// http://opensource.org/licenses/MIT>, at your option. This file may not be
// copied, modified, or distributed except according to those terms.
#include <stdio.h>
#include <stdlib.h>
#include <stdarg.h>
#include "log.h"
#include "util.h"
#include "device.h"
#if DEBUG_LEVEL > 0
static uint32_t LOGMASK = TAG_FILENO;
void set_logging_mask(uint32_t mask)
{
LOGMASK = mask;
}
struct logtag
{
uint32_t tagn;
@ -55,6 +46,11 @@ struct logtag tagtable[] = {
{TAG_TIME,"TIME"},
{TAG_WALLET,"WALLET"},
{TAG_STOR,"STOR"},
{TAG_BOOT,"BOOT"},
{TAG_EXT,"EXT"},
{TAG_NFC,"NFC"},
{TAG_NFC_APDU, "NAPDU"},
{TAG_CCID, "CCID"},
};
@ -65,7 +61,7 @@ __attribute__((weak)) void set_logging_tag(uint32_t tag)
void LOG(uint32_t tag, const char * filename, int num, const char * fmt, ...)
{
int i;
unsigned int i;
if (((tag & 0x7fffffff) & LOGMASK) == 0)
{
@ -75,7 +71,7 @@ void LOG(uint32_t tag, const char * filename, int num, const char * fmt, ...)
{
if (tag & tagtable[i].tagn)
{
if (tagtable[i].tag[0]) printf("[%s] ", tagtable[i].tag);
if (tagtable[i].tag[0] && !(tag & TAG_NO_TAG)) printf("[%s] ", tagtable[i].tag);
i = 0;
break;
}
@ -107,3 +103,14 @@ void LOG_HEX(uint32_t tag, uint8_t * data, int length)
set_logging_tag(tag);
dump_hex(data,length);
}
uint32_t timestamp()
{
static uint32_t t1 = 0;
uint32_t t2 = millis();
uint32_t diff = t2 - t1;
t1 = t2;
return diff;
}
#endif

View File

@ -1,28 +1,13 @@
/*
Copyright 2018 Conor Patrick
Permission is hereby granted, free of charge, to any person obtaining a copy of
this software and associated documentation files (the "Software"), to deal in
the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
of the Software, and to permit persons to whom the Software is furnished to do
so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
// Copyright 2019 SoloKeys Developers
//
// Licensed under the Apache License, Version 2.0, <LICENSE-APACHE or
// http://apache.org/licenses/LICENSE-2.0> or the MIT license <LICENSE-MIT or
// http://opensource.org/licenses/MIT>, at your option. This file may not be
// copied, modified, or distributed except according to those terms.
#ifndef _LOG_H
#define _LOG_H
#include "app.h"
#include APP_CONFIG
#include <stdint.h>
#ifndef DEBUG_LEVEL
@ -33,46 +18,57 @@
void LOG(uint32_t tag, const char * filename, int num, const char * fmt, ...);
void LOG_HEX(uint32_t tag, uint8_t * data, int length);
void set_logging_mask(uint32_t mask);
void set_logging_tag(uint32_t tag);
typedef enum
{
TAG_GEN = (1 << 0),
TAG_MC = (1 << 1),
TAG_GA = (1 << 2),
TAG_CP = (1 << 3),
TAG_ERR = (1 << 4),
TAG_PARSE= (1 << 5),
TAG_CTAP = (1 << 6),
TAG_U2F = (1 << 7),
TAG_DUMP = (1 << 8),
TAG_GREEN = (1 << 9),
TAG_RED= (1 << 10),
TAG_TIME= (1 << 11),
TAG_HID = (1 << 12),
TAG_USB = (1 << 13),
TAG_WALLET = (1 << 14),
TAG_STOR = (1 << 15),
TAG_DUMP2 = (1 << 16),
TAG_GEN = (1 << 0),
TAG_MC = (1 << 1),
TAG_GA = (1 << 2),
TAG_CP = (1 << 3),
TAG_ERR = (1 << 4),
TAG_PARSE = (1 << 5),
TAG_CTAP = (1 << 6),
TAG_U2F = (1 << 7),
TAG_DUMP = (1 << 8),
TAG_GREEN = (1 << 9),
TAG_RED = (1 << 10),
TAG_TIME = (1 << 11),
TAG_HID = (1 << 12),
TAG_USB = (1 << 13),
TAG_WALLET = (1 << 14),
TAG_STOR = (1 << 15),
TAG_DUMP2 = (1 << 16),
TAG_BOOT = (1 << 17),
TAG_EXT = (1 << 18),
TAG_NFC = (1 << 19),
TAG_NFC_APDU = (1 << 20),
TAG_CCID = (1 << 21),
TAG_FILENO = (1<<31)
TAG_NO_TAG = (1UL << 30),
TAG_FILENO = (1UL << 31)
} LOG_TAG;
#if DEBUG_LEVEL == 1
#if DEBUG_LEVEL > 0
void set_logging_mask(uint32_t mask);
#define printf1(tag,fmt, ...) LOG(tag & ~(TAG_FILENO), NULL, 0, fmt, ##__VA_ARGS__)
#define printf2(tag,fmt, ...) LOG(tag | TAG_FILENO,__FILE__, __LINE__, fmt, ##__VA_ARGS__)
#define printf3(tag,fmt, ...) LOG(tag | TAG_FILENO,__FILE__, __LINE__, fmt, ##__VA_ARGS__)
#define dump_hex1(tag,data,len) LOG_HEX(tag,data,len)
uint32_t timestamp();
#else
#define printf1(fmt, ...)
#define printf2(fmt, ...)
#define printf3(fmt, ...)
#define set_logging_mask(mask)
#define printf1(tag,fmt, ...)
#define printf2(tag,fmt, ...)
#define printf3(tag,fmt, ...)
#define dump_hex1(tag,data,len)
#define timestamp()
#endif

View File

@ -1,27 +1,14 @@
/*
Copyright 2018 Conor Patrick
Permission is hereby granted, free of charge, to any person obtaining a copy of
this software and associated documentation files (the "Software"), to deal in
the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
of the Software, and to permit persons to whom the Software is furnished to do
so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
// Copyright 2019 SoloKeys Developers
//
// Licensed under the Apache License, Version 2.0, <LICENSE-APACHE or
// http://apache.org/licenses/LICENSE-2.0> or the MIT license <LICENSE-MIT or
// http://opensource.org/licenses/MIT>, at your option. This file may not be
// copied, modified, or distributed except according to those terms.
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <stdbool.h>
#include <unistd.h>
#include "cbor.h"
#include "device.h"
@ -30,53 +17,48 @@
#include "util.h"
#include "log.h"
#include "ctap.h"
#include "app.h"
#include APP_CONFIG
#if !defined(TEST)
int main(int argc, char * argv[])
int main(int argc, char *argv[])
{
uint8_t hidmsg[64];
uint32_t t1 = 0;
set_logging_mask(
/*0*/
// TAG_GEN|
// TAG_MC |
// TAG_GA |
// TAG_WALLET |
TAG_STOR |
// TAG_CP |
// TAG_CTAP|
// TAG_HID|
/*TAG_U2F|*/
// TAG_PARSE |
// TAG_TIME|
// TAG_DUMP|
TAG_GREEN|
TAG_RED|
TAG_ERR
);
/*0*/
//TAG_GEN|
// TAG_MC |
// TAG_GA |
TAG_WALLET |
TAG_STOR |
//TAG_NFC_APDU |
TAG_NFC |
//TAG_CP |
// TAG_CTAP|
//TAG_HID|
TAG_U2F|
//TAG_PARSE |
//TAG_TIME|
// TAG_DUMP|
TAG_GREEN|
TAG_RED|
TAG_EXT|
TAG_CCID|
TAG_ERR
);
device_init();
printf1(TAG_GEN,"init device\n");
printf1(TAG_GEN,"init ctaphid\n");
ctaphid_init();
printf1(TAG_GEN,"init ctap\n");
ctap_init();
device_init(argc, argv);
memset(hidmsg,0,sizeof(hidmsg));
printf1(TAG_GEN,"recv'ing hid msg \n");
while(1)
{
if (millis() - t1 > 100)
if (millis() - t1 > HEARTBEAT_PERIOD)
{
/*printf("heartbeat %ld\n", beat++);*/
heartbeat();
t1 = millis();
}
@ -92,6 +74,7 @@ int main(int argc, char * argv[])
{
}
ctaphid_check_timeouts();
}
// Should never get here

View File

@ -1,24 +1,9 @@
/*
Copyright 2018 Conor Patrick
Permission is hereby granted, free of charge, to any person obtaining a copy of
this software and associated documentation files (the "Software"), to deal in
the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
of the Software, and to permit persons to whom the Software is furnished to do
so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
// Copyright 2019 SoloKeys Developers
//
// Licensed under the Apache License, Version 2.0, <LICENSE-APACHE or
// http://apache.org/licenses/LICENSE-2.0> or the MIT license <LICENSE-MIT or
// http://opensource.org/licenses/MIT>, at your option. This file may not be
// copied, modified, or distributed except according to those terms.
#ifndef _STORAGE_H
#define _STORAGE_H
@ -26,6 +11,9 @@
#define KEY_SPACE_BYTES 128
#define MAX_KEYS (1)
#define PIN_SALT_LEN (32)
#define STATE_VERSION (1)
#define BACKUP_MARKER 0x5A
#define INITIALIZED_MARKER 0xA5
@ -34,20 +22,40 @@
#define ERR_KEY_SPACE_TAKEN (-2)
#define ERR_KEY_SPACE_EMPTY (-2)
typedef struct
{
// Pin information
uint8_t is_initialized;
uint8_t is_pin_set;
uint8_t pin_code[NEW_PIN_ENC_MIN_SIZE];
int pin_code_length;
int8_t remaining_tries;
uint16_t rk_stored;
uint16_t key_lens[MAX_KEYS];
uint8_t key_space[KEY_SPACE_BYTES];
} AuthenticatorState_0xFF;
typedef struct
{
// Pin information
uint8_t is_initialized;
uint8_t is_pin_set;
uint8_t pin_code[NEW_PIN_ENC_MIN_SIZE];
int pin_code_length;
uint8_t PIN_CODE_HASH[32];
uint8_t PIN_SALT[PIN_SALT_LEN];
int _reserved;
int8_t remaining_tries;
uint16_t rk_stored;
uint16_t key_lens[MAX_KEYS];
uint8_t key_space[KEY_SPACE_BYTES];
} AuthenticatorState;
uint8_t data_version;
} AuthenticatorState_0x01;
typedef AuthenticatorState_0x01 AuthenticatorState;
typedef struct

View File

@ -1,24 +1,9 @@
/*
Copyright 2018 Conor Patrick
Permission is hereby granted, free of charge, to any person obtaining a copy of
this software and associated documentation files (the "Software"), to deal in
the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
of the Software, and to permit persons to whom the Software is furnished to do
so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
// Copyright 2019 SoloKeys Developers
//
// Licensed under the Apache License, Version 2.0, <LICENSE-APACHE or
// http://apache.org/licenses/LICENSE-2.0> or the MIT license <LICENSE-MIT or
// http://opensource.org/licenses/MIT>, at your option. This file may not be
// copied, modified, or distributed except according to those terms.
#include <stdio.h>
#include "device.h"
#include "util.h"
@ -31,18 +16,18 @@
void ctap_init()
{
printf("STUB: ctap_init\n");
printf1(TAG_GEN,"STUB: ctap_init\n");
}
#endif
#if defined(STUB_CTAPHID)
void ctaphid_init()
{
printf("STUB: ctaphid_init\n");
printf1(TAG_GEN,"STUB: ctaphid_init\n");
}
void ctaphid_handle_packet(uint8_t * hidmsg)
{
printf("STUB: ctaphid_handle_packet\n");
printf1(TAG_GEN,"STUB: ctaphid_handle_packet\n");
}
void ctaphid_check_timeouts()
@ -57,7 +42,7 @@ void ctaphid_check_timeouts()
void ctap_reset_state()
{
printf("STUB: ctap_reset_state\n");
printf1(TAG_GEN,"STUB: ctap_reset_state\n");
}
void ctap_response_init(CTAP_RESPONSE * resp)
@ -66,12 +51,12 @@ void ctap_response_init(CTAP_RESPONSE * resp)
void u2f_request(struct u2f_request_apdu* req, CTAP_RESPONSE * resp)
{
printf("STUB: u2f_request\n");
printf1(TAG_GEN,"STUB: u2f_request\n");
}
uint8_t ctap_request(uint8_t * pkt_raw, int length, CTAP_RESPONSE * resp)
{
printf("STUB: ctap_request\n");
printf1(TAG_GEN,"STUB: ctap_request\n");
return 0;
}
#endif

View File

@ -1,25 +1,10 @@
/*
Copyright 2018 Conor Patrick
Permission is hereby granted, free of charge, to any person obtaining a copy of
this software and associated documentation files (the "Software"), to deal in
the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
of the Software, and to permit persons to whom the Software is furnished to do
so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
#include "app.h"
// Copyright 2019 SoloKeys Developers
//
// Licensed under the Apache License, Version 2.0, <LICENSE-APACHE or
// http://apache.org/licenses/LICENSE-2.0> or the MIT license <LICENSE-MIT or
// http://opensource.org/licenses/MIT>, at your option. This file may not be
// copied, modified, or distributed except according to those terms.
#include APP_CONFIG
#ifdef TEST_POWER
/*

View File

@ -1,49 +1,42 @@
/*
Copyright 2018 Conor Patrick
Permission is hereby granted, free of charge, to any person obtaining a copy of
this software and associated documentation files (the "Software"), to deal in
the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
of the Software, and to permit persons to whom the Software is furnished to do
so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
// Copyright 2019 SoloKeys Developers
//
// Licensed under the Apache License, Version 2.0, <LICENSE-APACHE or
// http://apache.org/licenses/LICENSE-2.0> or the MIT license <LICENSE-MIT or
// http://opensource.org/licenses/MIT>, at your option. This file may not be
// copied, modified, or distributed except according to those terms.
#include <stdlib.h>
#include "u2f.h"
#include "ctap.h"
#include "ctaphid.h"
#include "crypto.h"
#include "log.h"
#include "device.h"
#include "apdu.h"
#include "wallet.h"
#include "app.h"
#ifdef ENABLE_U2F_EXTENSIONS
#include "extensions.h"
#endif
#include APP_CONFIG
// void u2f_response_writeback(uint8_t * buf, uint8_t len);
#ifdef ENABLE_U2F
static int16_t u2f_register(struct u2f_register_request * req);
static int16_t u2f_authenticate(struct u2f_authenticate_request * req, uint8_t control);
#endif
int8_t u2f_response_writeback(const uint8_t * buf, uint16_t len);
void u2f_reset_response();
void make_auth_tag(uint8_t * rpIdHash, uint8_t * nonce, uint32_t count, uint8_t * tag);
static CTAP_RESPONSE * _u2f_resp = NULL;
void u2f_request(struct u2f_request_apdu* req, CTAP_RESPONSE * resp)
void u2f_request_ex(APDU_HEADER *req, uint8_t *payload, uint32_t len, CTAP_RESPONSE * resp)
{
uint16_t rcode = 0;
uint64_t t1,t2;
uint32_t len = ((req->LC3) | ((uint32_t)req->LC2 << 8) | ((uint32_t)req->LC1 << 16));
uint8_t byte;
_u2f_resp = resp;
ctap_response_init(resp);
u2f_set_writeback_buffer(resp);
if (req->cla != 0)
{
@ -52,9 +45,9 @@ void u2f_request(struct u2f_request_apdu* req, CTAP_RESPONSE * resp)
goto end;
}
#ifdef ENABLE_U2F_EXTENSIONS
rcode = extend_u2f(req, len);
rcode = extend_u2f(req, payload, len);
#endif
if (rcode != U2F_SW_NO_ERROR) // If the extension didn't do anything...
if (rcode != U2F_SW_NO_ERROR && rcode != U2F_SW_CONDITIONS_NOT_SATISFIED) // If the extension didn't do anything...
{
#ifdef ENABLE_U2F
switch(req->ins)
@ -67,18 +60,18 @@ void u2f_request(struct u2f_request_apdu* req, CTAP_RESPONSE * resp)
}
else
{
t1 = millis();
rcode = u2f_register((struct u2f_register_request*)req->payload);
t2 = millis();
printf1(TAG_TIME,"u2f_register time: %d ms\n", t2-t1);
timestamp();
rcode = u2f_register((struct u2f_register_request*)payload);
printf1(TAG_TIME,"u2f_register time: %d ms\n", timestamp());
}
break;
case U2F_AUTHENTICATE:
printf1(TAG_U2F, "U2F_AUTHENTICATE\n");
t1 = millis();
rcode = u2f_authenticate((struct u2f_authenticate_request*)req->payload, req->p1);
t2 = millis();
printf1(TAG_TIME,"u2f_authenticate time: %d ms\n", t2-t1);
timestamp();
rcode = u2f_authenticate((struct u2f_authenticate_request*)payload, req->p1);
printf1(TAG_TIME,"u2f_authenticate time: %d ms\n", timestamp());
break;
case U2F_VERSION:
printf1(TAG_U2F, "U2F_VERSION\n");
@ -104,6 +97,8 @@ void u2f_request(struct u2f_request_apdu* req, CTAP_RESPONSE * resp)
#endif
}
device_set_status(CTAPHID_STATUS_IDLE);
end:
if (rcode != U2F_SW_NO_ERROR)
{
@ -119,6 +114,22 @@ end:
printf1(TAG_U2F,"u2f resp: "); dump_hex1(TAG_U2F, _u2f_resp->data, _u2f_resp->length);
}
void u2f_request_nfc(uint8_t * header, uint8_t * data, int datalen, CTAP_RESPONSE * resp)
{
if (!header)
return;
device_disable_up(true); // disable presence test
u2f_request_ex((APDU_HEADER *)header, data, datalen, resp);
device_disable_up(false); // enable presence test
}
void u2f_request(struct u2f_request_apdu* req, CTAP_RESPONSE * resp)
{
uint32_t len = ((req->LC3) | ((uint32_t)req->LC2 << 8) | ((uint32_t)req->LC1 << 16));
u2f_request_ex((APDU_HEADER *)req, req->payload, len, resp);
}
int8_t u2f_response_writeback(const uint8_t * buf, uint16_t len)
{
@ -137,7 +148,12 @@ void u2f_reset_response()
ctap_response_init(_u2f_resp);
}
void u2f_set_writeback_buffer(CTAP_RESPONSE * resp)
{
_u2f_resp = resp;
}
#ifdef ENABLE_U2F
static void dump_signature_der(uint8_t * sig)
{
uint8_t sigder[72];
@ -145,9 +161,9 @@ static void dump_signature_der(uint8_t * sig)
len = ctap_encode_der_sig(sig, sigder);
u2f_response_writeback(sigder, len);
}
static int8_t u2f_load_key(struct u2f_key_handle * kh, uint8_t * appid)
static int8_t u2f_load_key(struct u2f_key_handle * kh, uint8_t khl, uint8_t * appid)
{
crypto_ecc256_load_key((uint8_t*)kh, U2F_KEY_HANDLE_SIZE, NULL, 0);
crypto_ecc256_load_key((uint8_t*)kh, khl, NULL, 0);
return 0;
}
@ -161,7 +177,7 @@ static void u2f_make_auth_tag(struct u2f_key_handle * kh, uint8_t * appid, uint8
memmove(tag, hashbuf, CREDENTIAL_TAG_SIZE);
}
static int8_t u2f_new_keypair(struct u2f_key_handle * kh, uint8_t * appid, uint8_t * pubkey)
int8_t u2f_new_keypair(struct u2f_key_handle * kh, uint8_t * appid, uint8_t * pubkey)
{
ctap_generate_rng(kh->key, U2F_KEY_HANDLE_KEY_SIZE);
u2f_make_auth_tag(kh, appid, kh->tag);
@ -171,24 +187,43 @@ static int8_t u2f_new_keypair(struct u2f_key_handle * kh, uint8_t * appid, uint8
}
static int8_t u2f_appid_eq(struct u2f_key_handle * kh, uint8_t * appid)
// Return 1 if authenticate, 0 if not.
int8_t u2f_authenticate_credential(struct u2f_key_handle * kh, uint8_t key_handle_len, uint8_t * appid)
{
printf1(TAG_U2F, "checked CRED SIZE %d. (FIDO2: %d)\n", key_handle_len, sizeof(CredentialId));
uint8_t tag[U2F_KEY_HANDLE_TAG_SIZE];
u2f_make_auth_tag(kh, appid, tag);
if (memcmp(kh->tag, tag, U2F_KEY_HANDLE_TAG_SIZE) == 0)
{
return 0;
}
else
{
printf1(TAG_U2F, "key handle + appid not authentic\n");
printf1(TAG_U2F, "calc tag: \n"); dump_hex1(TAG_U2F,tag, U2F_KEY_HANDLE_TAG_SIZE);
printf1(TAG_U2F, "inp tag: \n"); dump_hex1(TAG_U2F,kh->tag, U2F_KEY_HANDLE_TAG_SIZE);
return -1;
}
}
if (key_handle_len == sizeof(CredentialId))
{
printf1(TAG_U2F, "FIDO2 key handle detected.\n");
CredentialId * cred = (CredentialId *) kh;
// FIDO2 credential.
if (memcmp(cred->rpIdHash, appid, 32) != 0)
{
printf1(TAG_U2F, "APPID does not match rpIdHash.\n");
return 0;
}
make_auth_tag(appid, cred->nonce, cred->count, tag);
if (memcmp(cred->tag, tag, CREDENTIAL_TAG_SIZE) == 0){
return 1;
}
}else if (key_handle_len == U2F_KEY_HANDLE_SIZE)
{
u2f_make_auth_tag(kh, appid, tag);
if (memcmp(kh->tag, tag, U2F_KEY_HANDLE_TAG_SIZE) == 0)
{
return 1;
}
}
printf1(TAG_U2F, "key handle + appid not authentic\n");
printf1(TAG_U2F, "calc tag: \n"); dump_hex1(TAG_U2F,tag, U2F_KEY_HANDLE_TAG_SIZE);
printf1(TAG_U2F, "inp tag: \n"); dump_hex1(TAG_U2F,kh->tag, U2F_KEY_HANDLE_TAG_SIZE);
return 0;
}
static int16_t u2f_authenticate(struct u2f_authenticate_request * req, uint8_t control)
@ -201,7 +236,8 @@ static int16_t u2f_authenticate(struct u2f_authenticate_request * req, uint8_t c
if (control == U2F_AUTHENTICATE_CHECK)
{
if (u2f_appid_eq(&req->kh, req->app) == 0)
printf1(TAG_U2F, "CHECK-ONLY\r\n");
if (u2f_authenticate_credential(&req->kh, req->khl, req->app))
{
return U2F_SW_CONDITIONS_NOT_SATISFIED;
}
@ -211,39 +247,50 @@ static int16_t u2f_authenticate(struct u2f_authenticate_request * req, uint8_t c
}
}
if (
control != U2F_AUTHENTICATE_SIGN ||
req->khl != U2F_KEY_HANDLE_SIZE ||
u2f_appid_eq(&req->kh, req->app) != 0 || // Order of checks is important
u2f_load_key(&req->kh, req->app) != 0
(control != U2F_AUTHENTICATE_SIGN && control != U2F_AUTHENTICATE_SIGN_NO_USER) ||
(!u2f_authenticate_credential(&req->kh, req->khl, req->app)) || // Order of checks is important
u2f_load_key(&req->kh, req->khl, req->app) != 0
)
{
return U2F_SW_WRONG_PAYLOAD;
return U2F_SW_WRONG_DATA;
}
// dont-enforce-user-presence-and-sign
if (control == U2F_AUTHENTICATE_SIGN_NO_USER)
up = 0;
if (ctap_user_presence_test() == 0)
{
return U2F_SW_CONDITIONS_NOT_SATISFIED;
}
if(up)
{
if (ctap_user_presence_test(750) == 0)
{
return U2F_SW_CONDITIONS_NOT_SATISFIED;
}
}
count = ctap_atomic_count(0);
hash[0] = (count >> 24) & 0xff;
hash[1] = (count >> 16) & 0xff;
hash[2] = (count >> 8) & 0xff;
hash[3] = (count >> 0) & 0xff;
crypto_sha256_init();
crypto_sha256_update(req->app,32);
crypto_sha256_update(&up,1);
crypto_sha256_update((uint8_t *)&count,4);
crypto_sha256_update(req->chal,32);
crypto_sha256_update(req->app, 32);
crypto_sha256_update(&up, 1);
crypto_sha256_update(hash, 4);
crypto_sha256_update(req->chal, 32);
crypto_sha256_final(hash);
printf1(TAG_U2F, "sha256: "); dump_hex1(TAG_U2F,hash,32);
printf1(TAG_U2F, "sha256: "); dump_hex1(TAG_U2F, hash, 32);
crypto_ecc256_sign(hash, 32, sig);
u2f_response_writeback(&up,1);
u2f_response_writeback((uint8_t *)&count,4);
hash[0] = (count >> 24) & 0xff;
hash[1] = (count >> 16) & 0xff;
hash[2] = (count >> 8) & 0xff;
hash[3] = (count >> 0) & 0xff;
u2f_response_writeback(hash,4);
dump_signature_der(sig);
return U2F_SW_NO_ERROR;
@ -259,12 +306,12 @@ static int16_t u2f_register(struct u2f_register_request * req)
uint8_t * sig = (uint8_t*)req;
const uint16_t attest_size = attestation_cert_der_size;
const uint16_t attest_size = attestation_cert_der_get_size();
if ( ! ctap_user_presence_test())
{
return U2F_SW_CONDITIONS_NOT_SATISFIED;
}
if ( ! ctap_user_presence_test(750))
{
return U2F_SW_CONDITIONS_NOT_SATISFIED;
}
if ( u2f_new_keypair(&key_handle, req->app, pubkey) == -1)
{
@ -284,8 +331,6 @@ static int16_t u2f_register(struct u2f_register_request * req)
crypto_ecc256_load_attestation_key();
/*printf("check key handle size: %d vs %d\n", U2F_KEY_HANDLE_SIZE, sizeof(struct u2f_key_handle));*/
printf1(TAG_U2F, "sha256: "); dump_hex1(TAG_U2F,hash,32);
crypto_ecc256_sign(hash, 32, sig);
@ -300,11 +345,10 @@ static int16_t u2f_register(struct u2f_register_request * req)
dump_signature_der(sig);
/*printf1(TAG_U2F, "dersig: "); dump_hex1(TAG_U2F,sig,74);*/
return U2F_SW_NO_ERROR;
}
#endif
int16_t u2f_version()
{

View File

@ -1,24 +1,9 @@
/*
Copyright 2018 Conor Patrick
Permission is hereby granted, free of charge, to any person obtaining a copy of
this software and associated documentation files (the "Software"), to deal in
the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
of the Software, and to permit persons to whom the Software is furnished to do
so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
// Copyright 2019 SoloKeys Developers
//
// Licensed under the Apache License, Version 2.0, <LICENSE-APACHE or
// http://apache.org/licenses/LICENSE-2.0> or the MIT license <LICENSE-MIT or
// http://opensource.org/licenses/MIT>, at your option. This file may not be
// copied, modified, or distributed except according to those terms.
#ifndef _U2F_H_
#define _U2F_H_
@ -53,16 +38,16 @@
// U2F Authenticate
#define U2F_AUTHENTICATE_CHECK 0x7
#define U2F_AUTHENTICATE_SIGN 0x3
#define U2F_AUTHENTICATE_SIGN_NO_USER 0x8
// Command status responses
#define U2F_SW_NO_ERROR 0x9000
#define U2F_SW_WRONG_DATA 0x6984
#define U2F_SW_CONDITIONS_NOT_SATISFIED 0x6985
#define U2F_SW_INS_NOT_SUPPORTED 0x6d00
#define U2F_SW_WRONG_LENGTH 0x6700
#define U2F_SW_CLASS_NOT_SUPPORTED 0x6E00
#define U2F_SW_WRONG_PAYLOAD 0x6a80
#define U2F_SW_WRONG_DATA 0x6a80
#define U2F_SW_INSUFFICIENT_MEMORY 0x9210
// Delay in milliseconds to wait for user input
@ -110,12 +95,19 @@ struct u2f_authenticate_request
};
// u2f_request send a U2F message to U2F protocol
// @req U2F message
// @req U2F message
void u2f_request(struct u2f_request_apdu* req, CTAP_RESPONSE * resp);
// u2f_request send a U2F message to NFC protocol
// @req data with iso7816 apdu message
// @len data length
void u2f_request_nfc(uint8_t * header, uint8_t * data, int datalen, CTAP_RESPONSE * resp);
int8_t u2f_authenticate_credential(struct u2f_key_handle * kh, uint8_t key_handle_len, uint8_t * appid);
int8_t u2f_response_writeback(const uint8_t * buf, uint16_t len);
void u2f_reset_response();
void u2f_set_writeback_buffer(CTAP_RESPONSE * resp);
int16_t u2f_version();

View File

@ -1,24 +1,9 @@
/*
Copyright 2018 Conor Patrick
Permission is hereby granted, free of charge, to any person obtaining a copy of
this software and associated documentation files (the "Software"), to deal in
the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
of the Software, and to permit persons to whom the Software is furnished to do
so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
// Copyright 2019 SoloKeys Developers
//
// Licensed under the Apache License, Version 2.0, <LICENSE-APACHE or
// http://apache.org/licenses/LICENSE-2.0> or the MIT license <LICENSE-MIT or
// http://opensource.org/licenses/MIT>, at your option. This file may not be
// copied, modified, or distributed except according to those terms.
#include <stdint.h>
#include <stdio.h>
@ -30,5 +15,3 @@ void dump_hex(uint8_t * buf, int size)
}
printf("\n");
}

View File

@ -1,24 +1,9 @@
/*
Copyright 2018 Conor Patrick
Permission is hereby granted, free of charge, to any person obtaining a copy of
this software and associated documentation files (the "Software"), to deal in
the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
of the Software, and to permit persons to whom the Software is furnished to do
so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
// Copyright 2019 SoloKeys Developers
//
// Licensed under the Apache License, Version 2.0, <LICENSE-APACHE or
// http://apache.org/licenses/LICENSE-2.0> or the MIT license <LICENSE-MIT or
// http://opensource.org/licenses/MIT>, at your option. This file may not be
// copied, modified, or distributed except according to those terms.
#ifndef _UTIL_H
#define _UTIL_H

13
fido2/version.c Normal file
View File

@ -0,0 +1,13 @@
#include "version.h"
const version_t firmware_version __attribute__ ((section (".flag"))) __attribute__ ((__used__)) = {
.major = SOLO_VERSION_MAJ,
.minor = SOLO_VERSION_MIN,
.patch = SOLO_VERSION_PATCH,
.reserved = 0
};
// from tinycbor, for a quick static_assert
#include <compilersupport_p.h>
cbor_static_assert(sizeof(version_t) == 4);

39
fido2/version.h Normal file
View File

@ -0,0 +1,39 @@
#ifndef _VERSION_H_
#define _VERSION_H_
#ifndef SOLO_VERSION_MAJ
#define SOLO_VERSION_MAJ 0
#define SOLO_VERSION_MIN 0
#define SOLO_VERSION_PATCH 0
#endif
#define __STR_HELPER(x) #x
#define __STR(x) __STR_HELPER(x)
#ifndef SOLO_VERSION
#define SOLO_VERSION __STR(SOLO_VERSION_MAJ) "." __STR(SOLO_VERSION_MIN) "." __STR(SOLO_VERSION_PATCH)
#endif
#include <stdint.h>
#include <stdbool.h>
typedef struct {
union{
uint32_t raw;
struct {
uint8_t major;
uint8_t minor;
uint8_t patch;
uint8_t reserved;
};
};
} version_t;
bool is_newer(const version_t* const newer, const version_t* const older);
const version_t firmware_version ;
#endif

53
in-docker-build.sh Executable file
View File

@ -0,0 +1,53 @@
#!/bin/bash -xe
version=$1
export PREFIX=/opt/gcc-arm-none-eabi-8-2019-q3-update/bin/
cd /solo/targets/stm32l432
ls
make cbor
out_dir="/builds"
function build() {
part=${1}
output=${2}
what="${part}"
make full-clean
make ${what} VERSION_FULL=${version}
out_hex="${what}-${version}.hex"
out_sha2="${what}-${version}.sha2"
mv ${output}.hex ${out_hex}
sha256sum ${out_hex} > ${out_sha2}
cp ${out_hex} ${out_sha2} ${out_dir}
}
build bootloader-nonverifying bootloader
build bootloader-verifying bootloader
build firmware solo
build firmware-debug-1 solo
build firmware-debug-2 solo
build firmware solo
cd ${out_dir}
bundle="bundle-hacker-${version}"
/opt/conda/bin/solo mergehex bootloader-nonverifying-${version}.hex firmware-${version}.hex ${bundle}.hex
sha256sum ${bundle}.hex > ${bundle}.sha2
bundle="bundle-hacker-debug-1-${version}"
/opt/conda/bin/solo mergehex bootloader-nonverifying-${version}.hex firmware-debug-1-${version}.hex ${bundle}.hex
sha256sum ${bundle}.hex > ${bundle}.sha2
bundle="bundle-hacker-debug-2-${version}"
/opt/conda/bin/solo mergehex bootloader-nonverifying-${version}.hex firmware-debug-2-${version}.hex ${bundle}.hex
sha256sum ${bundle}.hex > ${bundle}.sha2
bundle="bundle-secure-non-solokeys-${version}"
/opt/conda/bin/solo mergehex --lock bootloader-verifying-${version}.hex firmware-${version}.hex ${bundle}.hex
sha256sum ${bundle}.hex > ${bundle}.sha2

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -1,21 +1,33 @@
site_name: Solo
site_name: Solo Technical Documentation
site_author: SoloKeys
site_description: 'Documentation for the SoloKeys solo software'
repo_url: 'https://github.com/solokeyssec/solo'
repo_name: 'solokeyssec/solo'
copyright: 'Copyright &copy; 2018 SoloKeys'
site_url: 'https://docs.solokeys.io/solo/'
repo_url: 'https://github.com/solokeys/solo'
repo_name: 'solokeys/solo'
copyright: 'Copyright &copy; 2018 - 2019 SoloKeys'
nav:
- Home: index.md
- README.md: repo-readme.md
- FIDO2 Implementation: fido2-impl.md
- Signed update process: signed-updates.md
- Building: building.md
- Code documentation: code-overview.md
- Contributing Code: contributing.md
- Contributing Docs: documenting.md
- What the udev?!: udev.md
- Home: solo/index.md
- FIDO2 Implementation: solo/fido2-impl.md
- Metadata Statements: solo/metadata-statements.md
- Build instructions: solo/building.md
- Programming instructions: solo/programming.md
- Bootloader mode: solo/bootloader-mode.md
- Customization: solo/customization.md
- Solo Extras: solo/solo-extras.md
- Application Ideas: solo/application-ideas.md
- Running on Nucleo32 board: solo/nucleo32-board.md
- Signed update process: solo/signed-updates.md
- Code documentation: solo/code-overview.md
- Contributing Code: solo/contributing.md
- Contributing Docs: solo/documenting.md
- udev Rules: solo/udev.md
- About: solo/repo-readme.md
theme:
name: material
logo: 'images/logo.svg'
logo: 'solo/images/logo.svg'
favicon: 'solo/images/favicon.ico'
markdown_extensions:
- markdown_include.include

View File

@ -1,12 +1,13 @@
/*
* app.h
*
* Created on: Jun 26, 2018
* Author: conor
*/
// Copyright 2019 SoloKeys Developers
//
// Licensed under the Apache License, Version 2.0, <LICENSE-APACHE or
// http://apache.org/licenses/LICENSE-2.0> or the MIT license <LICENSE-MIT or
// http://opensource.org/licenses/MIT>, at your option. This file may not be
// copied, modified, or distributed except according to those terms.
#ifndef SRC_APP_H_
#define SRC_APP_H_
#include <stdbool.h>
#define USING_DEV_BOARD
@ -15,10 +16,28 @@
#define DEBUG_LEVEL 1
#define ENABLE_U2F
#define ENABLE_U2F_EXTENSIONS
//#define BRIDGE_TO_WALLET
void printing_init();
extern bool use_udp;
// 0xRRGGBB
#define LED_INIT_VALUE 0x000800
#define LED_WINK_VALUE 0x000008
#define LED_MAX_SCALER 30
#define LED_MIN_SCALER 1
// # of ms between each change in LED
#define HEARTBEAT_PERIOD 100
// Each LED channel will be multiplied by a integer between LED_MAX_SCALER
// and LED_MIN_SCALER to cause the slow pulse. E.g.
// #define LED_INIT_VALUE 0x301000
// #define LED_MAX_SCALER 30
// #define LED_MIN_SCALER 1
// #define HEARTBEAT_PERIOD 8
// Will pulse from 0x301000 to 0x903000 to 0x301000 ...
// Which will take ~8 * (30)*2 ms
#endif /* SRC_APP_H_ */

View File

@ -1,3 +1,9 @@
// Copyright 2019 SoloKeys Developers
//
// Licensed under the Apache License, Version 2.0, <LICENSE-APACHE or
// http://apache.org/licenses/LICENSE-2.0> or the MIT license <LICENSE-MIT or
// http://opensource.org/licenses/MIT>, at your option. This file may not be
// copied, modified, or distributed except according to those terms.
#include <sys/time.h>
#include <stdint.h>
#include <stdio.h>
@ -9,18 +15,48 @@
#include <string.h>
#include <unistd.h>
#include <signal.h>
#include <fcntl.h>
#include "device.h"
#include "cbor.h"
#include "util.h"
#include "log.h"
#include "ctaphid.h"
#define RK_NUM 50
bool use_udp = true;
static bool _up_disabled = false;
struct ResidentKeyStore {
CTAP_residentKey rks[RK_NUM];
} RK_STORE;
void authenticator_initialize();
uint32_t __device_status = 0;
void device_set_status(uint32_t status)
{
if (status != CTAPHID_STATUS_IDLE && __device_status != status)
{
ctaphid_update_status(status);
}
__device_status = status;
}
void device_reboot()
{
printf1(TAG_RED, "REBOOT command recieved!\r\n");
exit(100);
}
int udp_server()
{
int fd;
static bool run_already = false;
static int fd = -1;
if (run_already && fd >= 0) return fd;
run_already = true;
if ( (fd = socket(AF_INET, SOCK_DGRAM, 0)) < 0 ) {
perror( "socket failed" );
return 1;
@ -72,6 +108,7 @@ int udp_recv(int fd, uint8_t * buf, int size)
perror( "recvfrom failed" );
exit(1);
}
printf1(TAG_DUMP, ">>"); dump_hex1(TAG_DUMP, buf, length);
return length;
}
@ -88,15 +125,11 @@ void udp_send(int fd, uint8_t * buf, int size)
perror( "sendto failed" );
exit(1);
}
}
void udp_close(int fd)
{
close(fd);
printf1(TAG_DUMP, "<<"); dump_hex1(TAG_DUMP, buf, size);
}
uint32_t millis()
{
struct timeval te;
@ -106,35 +139,79 @@ uint32_t millis()
}
static int serverfd = 0;
static int fd = 0;
void usbhid_init()
{
// just bridge to UDP for now for pure software testing
serverfd = udp_server();
if (use_udp)
{
fd = udp_server();
}
else
{
fd = open("/dev/hidg0", O_RDWR);
if (fd < 0)
{
perror("hidg open");
exit(1);
}
}
}
// Receive 64 byte USB HID message, don't block, return size of packet, return 0 if nothing
int usbhid_recv(uint8_t * msg)
{
int l = udp_recv(serverfd, msg, HID_MESSAGE_SIZE);
/*if (l && l != HID_MESSAGE_SIZE)*/
/*{*/
/*printf("Error, recv'd message of wrong size %d", l);*/
/*exit(1);*/
/*}*/
int l = 0;
if (use_udp)
{
l = udp_recv(fd, msg, HID_MESSAGE_SIZE);
}
else
{
l = read(fd, msg, HID_MESSAGE_SIZE); /* Flawfinder: ignore */
if (l < 0)
{
perror("hidg read");
exit(1);
}
}
uint8_t magic_cmd[] = "\xac\x10\x52\xca\x95\xe5\x69\xde\x69\xe0\x2e\xbf"
"\xf3\x33\x48\x5f\x13\xf9\xb2\xda\x34\xc5\xa8\xa3"
"\x40\x52\x66\x97\xa9\xab\x2e\x0b\x39\x4d\x8d\x04"
"\x97\x3c\x13\x40\x05\xbe\x1a\x01\x40\xbf\xf6\x04"
"\x5b\xb2\x6e\xb7\x7a\x73\xea\xa4\x78\x13\xf6\xb4"
"\x9a\x72\x50\xdc";
if ( memcmp(magic_cmd, msg, 64) == 0 )
{
printf1(TAG_RED, "MAGIC REBOOT command recieved!\r\n");
memset(msg,0,64);
exit(100);
return 0;
}
return l;
}
// Send 64 byte USB HID message
void usbhid_send(uint8_t * msg)
{
udp_send(serverfd, msg, HID_MESSAGE_SIZE);
if (use_udp)
{
udp_send(fd, msg, HID_MESSAGE_SIZE);
}
else
{
if (write(fd, msg, HID_MESSAGE_SIZE) < 0)
{
perror("hidg write");
exit(1);
}
}
}
void usbhid_close()
{
udp_close(serverfd);
close(fd);
}
void int_handler(int i)
@ -144,13 +221,54 @@ void int_handler(int i)
exit(0);
}
void device_init()
void usage(const char * cmd)
{
fprintf(stderr, "Usage: %s [-b udp|hidg]\n", cmd);
fprintf(stderr, " -b backing implementation: udp(default) or hidg\n");
exit(1);
}
void device_init(int argc, char *argv[])
{
int opt;
while ((opt = getopt(argc, argv, "b:")) != -1)
{
switch (opt)
{
case 'b':
if (strcmp("udp", optarg) == 0)
{
use_udp = true;
}
else if (strcmp("hidg", optarg) == 0)
{
use_udp = false;
}
else
{
usage(argv[0]);
}
break;
default:
usage(argv[0]);
break;
}
}
signal(SIGINT, int_handler);
printf1(TAG_GREEN, "Using %s backing\n", use_udp ? "UDP" : "hidg");
usbhid_init();
authenticator_initialize();
ctaphid_init();
ctap_init( 1 );
}
@ -158,7 +276,15 @@ void main_loop_delay()
{
struct timespec ts;
ts.tv_sec = 0;
ts.tv_nsec = 1000*1000*25;
ts.tv_nsec = 1000*1000*100;
nanosleep(&ts,NULL);
}
void delay(uint32_t ms)
{
struct timespec ts;
ts.tv_sec = 0;
ts.tv_nsec = 1000*1000*ms;
nanosleep(&ts,NULL);
}
@ -175,8 +301,12 @@ void ctaphid_write_block(uint8_t * data)
}
int ctap_user_presence_test()
int ctap_user_presence_test(uint32_t d)
{
if (_up_disabled)
{
return 2;
}
return 1;
}
@ -186,20 +316,11 @@ int ctap_user_verification(uint8_t arg)
}
uint32_t ctap_atomic_count(int sel)
uint32_t ctap_atomic_count(uint32_t amount)
{
static uint32_t counter1 = 25;
/*return 713;*/
if (sel == 0)
{
printf1(TAG_RED,"counter1: %d\n", counter1);
return counter1++;
}
else
{
printf2(TAG_ERR,"counter2 not imple\n");
exit(1);
}
counter1 += (amount + 1);
return counter1;
}
int ctap_generate_rng(uint8_t * dst, size_t num)
@ -211,15 +332,12 @@ int ctap_generate_rng(uint8_t * dst, size_t num)
perror("fopen");
exit(1);
}
ret = fread(dst, 1, num, urand);
fclose(urand);
if (ret != num)
if (fread(dst, 1, num, urand) != num)
{
perror("fwrite");
exit(1);
perror("fread");
}
/*memset(dst,0xaa,num);*/
fclose(urand);
return 1;
}
@ -227,6 +345,7 @@ int ctap_generate_rng(uint8_t * dst, size_t num)
const char * state_file = "authenticator_state.bin";
const char * backup_file = "authenticator_state2.bin";
const char * rk_file = "resident_keys.bin";
void authenticator_read_state(AuthenticatorState * state)
{
@ -346,6 +465,24 @@ int authenticator_is_backup_initialized()
/*}*/
static void sync_rk()
{
FILE * f = fopen(rk_file, "wb+");
if (f== NULL)
{
perror("fopen");
exit(1);
}
int ret = fwrite(&RK_STORE, 1, sizeof(RK_STORE), f);
fclose(f);
if (ret != sizeof(RK_STORE))
{
perror("fwrite");
exit(1);
}
}
void authenticator_initialize()
{
uint8_t header[16];
@ -369,6 +506,22 @@ void authenticator_initialize()
perror("fwrite");
exit(1);
}
// resident_keys
f = fopen(rk_file, "rb");
if (f== NULL)
{
perror("fopen");
exit(1);
}
ret = fread(&RK_STORE, 1, sizeof(RK_STORE), f);
fclose(f);
if(ret != sizeof(RK_STORE))
{
perror("fwrite");
exit(1);
}
}
else
{
@ -407,10 +560,84 @@ void authenticator_initialize()
exit(1);
}
// resident_keys
memset(&RK_STORE,0xff,sizeof(RK_STORE));
sync_rk();
}
}
void manage_device()
void device_manage()
{
}
void ctap_reset_rk()
{
memset(&RK_STORE,0xff,sizeof(RK_STORE));
sync_rk();
}
uint32_t ctap_rk_size()
{
return RK_NUM;
}
void ctap_store_rk(int index, CTAP_residentKey * rk)
{
if (index < RK_NUM)
{
memmove(RK_STORE.rks + index, rk, sizeof(CTAP_residentKey));
sync_rk();
}
else
{
printf1(TAG_ERR,"Out of bounds for store_rk\r\n");
}
}
void ctap_load_rk(int index, CTAP_residentKey * rk)
{
memmove(rk, RK_STORE.rks + index, sizeof(CTAP_residentKey));
}
void ctap_overwrite_rk(int index, CTAP_residentKey * rk)
{
if (index < RK_NUM)
{
memmove(RK_STORE.rks + index, rk, sizeof(CTAP_residentKey));
sync_rk();
}
else
{
printf1(TAG_ERR,"Out of bounds for store_rk\r\n");
}
}
void device_wink()
{
printf("*WINK*\n");
}
int device_is_nfc()
{
return 0;
}
void device_disable_up(bool disable)
{
_up_disabled = disable;
}
void device_set_clock_rate(DEVICE_CLOCK_RATE param)
{
}

Submodule python-fido2 deleted from 329434fdd4

File diff suppressed because one or more lines are too long

View File

@ -1,49 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<projectDescription>
<name>EFM32</name>
<comment></comment>
<projects>
</projects>
<buildSpec>
<buildCommand>
<name>org.eclipse.cdt.managedbuilder.core.genmakebuilder</name>
<triggers>clean,full,incremental,</triggers>
<arguments>
</arguments>
</buildCommand>
<buildCommand>
<name>org.eclipse.cdt.managedbuilder.core.ScannerConfigBuilder</name>
<triggers>full,incremental,</triggers>
<arguments>
</arguments>
</buildCommand>
</buildSpec>
<natures>
<nature>org.eclipse.cdt.core.cnature</nature>
<nature>com.silabs.ss.framework.ide.project.sls.core.SLSProjectNature</nature>
<nature>org.eclipse.cdt.managedbuilder.core.managedBuildNature</nature>
<nature>org.eclipse.cdt.managedbuilder.core.ScannerConfigNature</nature>
</natures>
<linkedResources>
<link>
<name>crypto</name>
<type>2</type>
<locationURI>$%7BPARENT-2-PROJECT_LOC%7D/crypto</locationURI>
</link>
<link>
<name>fido2</name>
<type>2</type>
<locationURI>$%7BPARENT-2-PROJECT_LOC%7D/fido2</locationURI>
</link>
<link>
<name>CMSIS/EFM32JG1B/startup_gcc_efm32jg1b.s</name>
<type>1</type>
<locationURI>STUDIO_SDK_LOC/platform/Device/SiliconLabs/EFM32JG1B/Source/GCC/startup_efm32jg1b.S</locationURI>
</link>
<link>
<name>CMSIS/EFM32JG1B/system_efm32jg1b.c</name>
<type>1</type>
<locationURI>STUDIO_SDK_LOC/platform/Device/SiliconLabs/EFM32JG1B/Source/system_efm32jg1b.c</locationURI>
</link>
</linkedResources>
</projectDescription>

View File

@ -1,2 +0,0 @@
copiedFilesOriginState={}
eclipse.preferences.version=1

View File

@ -1,70 +0,0 @@
eclipse.preferences.version=1
org.eclipse.cdt.codan.checkers.errnoreturn=Warning
org.eclipse.cdt.codan.checkers.errnoreturn.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},implicit\=>false}
org.eclipse.cdt.codan.checkers.errreturnvalue=Error
org.eclipse.cdt.codan.checkers.errreturnvalue.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true}}
org.eclipse.cdt.codan.checkers.nocommentinside=-Error
org.eclipse.cdt.codan.checkers.nocommentinside.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true}}
org.eclipse.cdt.codan.checkers.nolinecomment=-Error
org.eclipse.cdt.codan.checkers.nolinecomment.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true}}
org.eclipse.cdt.codan.checkers.noreturn=Error
org.eclipse.cdt.codan.checkers.noreturn.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},implicit\=>false}
org.eclipse.cdt.codan.internal.checkers.AbstractClassCreation=Error
org.eclipse.cdt.codan.internal.checkers.AbstractClassCreation.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true}}
org.eclipse.cdt.codan.internal.checkers.AmbiguousProblem=Error
org.eclipse.cdt.codan.internal.checkers.AmbiguousProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true}}
org.eclipse.cdt.codan.internal.checkers.AssignmentInConditionProblem=Warning
org.eclipse.cdt.codan.internal.checkers.AssignmentInConditionProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true}}
org.eclipse.cdt.codan.internal.checkers.AssignmentToItselfProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true}}
org.eclipse.cdt.codan.internal.checkers.CaseBreakProblem=Warning
org.eclipse.cdt.codan.internal.checkers.CaseBreakProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},no_break_comment\=>"no break",last_case_param\=>false,empty_case_param\=>false}
org.eclipse.cdt.codan.internal.checkers.CatchByReference=Warning
org.eclipse.cdt.codan.internal.checkers.CatchByReference.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},unknown\=>false,exceptions\=>()}
org.eclipse.cdt.codan.internal.checkers.CircularReferenceProblem=Error
org.eclipse.cdt.codan.internal.checkers.CircularReferenceProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true}}
org.eclipse.cdt.codan.internal.checkers.ClassMembersInitialization=Warning
org.eclipse.cdt.codan.internal.checkers.ClassMembersInitialization.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},skip\=>true}
org.eclipse.cdt.codan.internal.checkers.FieldResolutionProblem=Error
org.eclipse.cdt.codan.internal.checkers.FieldResolutionProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true}}
org.eclipse.cdt.codan.internal.checkers.FunctionResolutionProblem=Error
org.eclipse.cdt.codan.internal.checkers.FunctionResolutionProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true}}
org.eclipse.cdt.codan.internal.checkers.InvalidArguments=Error
org.eclipse.cdt.codan.internal.checkers.InvalidArguments.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true}}
org.eclipse.cdt.codan.internal.checkers.InvalidTemplateArgumentsProblem=Error
org.eclipse.cdt.codan.internal.checkers.InvalidTemplateArgumentsProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true}}
org.eclipse.cdt.codan.internal.checkers.LabelStatementNotFoundProblem=Error
org.eclipse.cdt.codan.internal.checkers.LabelStatementNotFoundProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true}}
org.eclipse.cdt.codan.internal.checkers.MemberDeclarationNotFoundProblem=Error
org.eclipse.cdt.codan.internal.checkers.MemberDeclarationNotFoundProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true}}
org.eclipse.cdt.codan.internal.checkers.MethodResolutionProblem=Error
org.eclipse.cdt.codan.internal.checkers.MethodResolutionProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true}}
org.eclipse.cdt.codan.internal.checkers.NamingConventionFunctionChecker=-Info
org.eclipse.cdt.codan.internal.checkers.NamingConventionFunctionChecker.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},pattern\=>"^[a-z]",macro\=>true,exceptions\=>()}
org.eclipse.cdt.codan.internal.checkers.NonVirtualDestructorProblem=Warning
org.eclipse.cdt.codan.internal.checkers.NonVirtualDestructorProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true}}
org.eclipse.cdt.codan.internal.checkers.OverloadProblem=Error
org.eclipse.cdt.codan.internal.checkers.OverloadProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true}}
org.eclipse.cdt.codan.internal.checkers.RedeclarationProblem=Error
org.eclipse.cdt.codan.internal.checkers.RedeclarationProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true}}
org.eclipse.cdt.codan.internal.checkers.RedefinitionProblem=Error
org.eclipse.cdt.codan.internal.checkers.RedefinitionProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true}}
org.eclipse.cdt.codan.internal.checkers.ReturnStyleProblem=-Warning
org.eclipse.cdt.codan.internal.checkers.ReturnStyleProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true}}
org.eclipse.cdt.codan.internal.checkers.ScanfFormatStringSecurityProblem=-Warning
org.eclipse.cdt.codan.internal.checkers.ScanfFormatStringSecurityProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true}}
org.eclipse.cdt.codan.internal.checkers.StatementHasNoEffectProblem=Warning
org.eclipse.cdt.codan.internal.checkers.StatementHasNoEffectProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},macro\=>true,exceptions\=>()}
org.eclipse.cdt.codan.internal.checkers.SuggestedParenthesisProblem=Warning
org.eclipse.cdt.codan.internal.checkers.SuggestedParenthesisProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},paramNot\=>false}
org.eclipse.cdt.codan.internal.checkers.SuspiciousSemicolonProblem=Warning
org.eclipse.cdt.codan.internal.checkers.SuspiciousSemicolonProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},else\=>false,afterelse\=>false}
org.eclipse.cdt.codan.internal.checkers.TypeResolutionProblem=Error
org.eclipse.cdt.codan.internal.checkers.TypeResolutionProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true}}
org.eclipse.cdt.codan.internal.checkers.UnusedFunctionDeclarationProblem=Warning
org.eclipse.cdt.codan.internal.checkers.UnusedFunctionDeclarationProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},macro\=>true}
org.eclipse.cdt.codan.internal.checkers.UnusedStaticFunctionProblem=Warning
org.eclipse.cdt.codan.internal.checkers.UnusedStaticFunctionProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},macro\=>true}
org.eclipse.cdt.codan.internal.checkers.UnusedVariableDeclarationProblem=Warning
org.eclipse.cdt.codan.internal.checkers.UnusedVariableDeclarationProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},macro\=>true,exceptions\=>("@(\#)","$Id")}
org.eclipse.cdt.codan.internal.checkers.VariableResolutionProblem=Error
org.eclipse.cdt.codan.internal.checkers.VariableResolutionProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true}}

View File

@ -1,317 +0,0 @@
/* @file startup_efm32pg1b.S
* @brief startup file for Silicon Labs EFM32PG1B devices.
* For use with GCC for ARM Embedded Processors
* @version 5.2.2
* Date: 12 June 2014
*
*/
/* Copyright (c) 2011 - 2014 ARM LIMITED
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
- Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
- Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
- Neither the name of ARM nor the names of its contributors may be used
to endorse or promote products derived from this software without
specific prior written permission.
*
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ARE DISCLAIMED. IN NO EVENT SHALL COPYRIGHT HOLDERS AND CONTRIBUTORS BE
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.
---------------------------------------------------------------------------*/
.syntax unified
.arch armv7-m
.section .stack
.align 3
#ifdef __STACK_SIZE
.equ Stack_Size, __STACK_SIZE
#else
.equ Stack_Size, 0x00000400
#endif
.globl __StackTop
.globl __StackLimit
__StackLimit:
.space Stack_Size
.size __StackLimit, . - __StackLimit
__StackTop:
.size __StackTop, . - __StackTop
.section .heap
.align 3
#ifdef __HEAP_SIZE
.equ Heap_Size, __HEAP_SIZE
#else
.equ Heap_Size, 0x00000C00
#endif
.globl __HeapBase
.globl __HeapLimit
__HeapBase:
.if Heap_Size
.space Heap_Size
.endif
.size __HeapBase, . - __HeapBase
__HeapLimit:
.size __HeapLimit, . - __HeapLimit
.section .vectors
.align 2
.globl __Vectors
__Vectors:
.long __StackTop /* Top of Stack */
.long Reset_Handler /* Reset Handler */
.long NMI_Handler /* NMI Handler */
.long HardFault_Handler /* Hard Fault Handler */
.long MemManage_Handler /* MPU Fault Handler */
.long BusFault_Handler /* Bus Fault Handler */
.long UsageFault_Handler /* Usage Fault Handler */
.long Default_Handler /* Reserved */
.long Default_Handler /* Reserved */
.long Default_Handler /* Reserved */
.long Default_Handler /* Reserved */
.long SVC_Handler /* SVCall Handler */
.long DebugMon_Handler /* Debug Monitor Handler */
.long Default_Handler /* Reserved */
.long PendSV_Handler /* PendSV Handler */
.long SysTick_Handler /* SysTick Handler */
/* External interrupts */
.long EMU_IRQHandler /* 0 - EMU */
.long Default_Handler /* 1 - Reserved */
.long WDOG0_IRQHandler /* 2 - WDOG0 */
.long Default_Handler /* 3 - Reserved */
.long Default_Handler /* 4 - Reserved */
.long Default_Handler /* 5 - Reserved */
.long Default_Handler /* 6 - Reserved */
.long Default_Handler /* 7 - Reserved */
.long LDMA_IRQHandler /* 8 - LDMA */
.long GPIO_EVEN_IRQHandler /* 9 - GPIO_EVEN */
.long TIMER0_IRQHandler /* 10 - TIMER0 */
.long USART0_RX_IRQHandler /* 11 - USART0_RX */
.long USART0_TX_IRQHandler /* 12 - USART0_TX */
.long ACMP0_IRQHandler /* 13 - ACMP0 */
.long ADC0_IRQHandler /* 14 - ADC0 */
.long IDAC0_IRQHandler /* 15 - IDAC0 */
.long I2C0_IRQHandler /* 16 - I2C0 */
.long GPIO_ODD_IRQHandler /* 17 - GPIO_ODD */
.long TIMER1_IRQHandler /* 18 - TIMER1 */
.long USART1_RX_IRQHandler /* 19 - USART1_RX */
.long USART1_TX_IRQHandler /* 20 - USART1_TX */
.long LEUART0_IRQHandler /* 21 - LEUART0 */
.long PCNT0_IRQHandler /* 22 - PCNT0 */
.long CMU_IRQHandler /* 23 - CMU */
.long MSC_IRQHandler /* 24 - MSC */
.long CRYPTO_IRQHandler /* 25 - CRYPTO */
.long LETIMER0_IRQHandler /* 26 - LETIMER0 */
.long Default_Handler /* 27 - Reserved */
.long Default_Handler /* 28 - Reserved */
.long RTCC_IRQHandler /* 29 - RTCC */
.long Default_Handler /* 30 - Reserved */
.long CRYOTIMER_IRQHandler /* 31 - CRYOTIMER */
.long Default_Handler /* 32 - Reserved */
.long FPUEH_IRQHandler /* 33 - FPUEH */
.size __Vectors, . - __Vectors
.text
.thumb
.thumb_func
.align 2
.globl Reset_Handler
.type Reset_Handler, %function
Reset_Handler:
#ifndef __NO_SYSTEM_INIT
ldr r0, =SystemInit
blx r0
#endif
/* Firstly it copies data from read only memory to RAM. There are two schemes
* to copy. One can copy more than one sections. Another can only copy
* one section. The former scheme needs more instructions and read-only
* data to implement than the latter.
* Macro __STARTUP_COPY_MULTIPLE is used to choose between two schemes. */
#ifdef __STARTUP_COPY_MULTIPLE
/* Multiple sections scheme.
*
* Between symbol address __copy_table_start__ and __copy_table_end__,
* there are array of triplets, each of which specify:
* offset 0: LMA of start of a section to copy from
* offset 4: VMA of start of a section to copy to
* offset 8: size of the section to copy. Must be multiply of 4
*
* All addresses must be aligned to 4 bytes boundary.
*/
ldr r4, =__copy_table_start__
ldr r5, =__copy_table_end__
.L_loop0:
cmp r4, r5
bge .L_loop0_done
ldr r1, [r4]
ldr r2, [r4, #4]
ldr r3, [r4, #8]
.L_loop0_0:
subs r3, #4
ittt ge
ldrge r0, [r1, r3]
strge r0, [r2, r3]
bge .L_loop0_0
adds r4, #12
b .L_loop0
.L_loop0_done:
#else
/* Single section scheme.
*
* The ranges of copy from/to are specified by following symbols
* __etext: LMA of start of the section to copy from. Usually end of text
* __data_start__: VMA of start of the section to copy to
* __data_end__: VMA of end of the section to copy to
*
* All addresses must be aligned to 4 bytes boundary.
*/
ldr r1, =__etext
ldr r2, =__data_start__
ldr r3, =__data_end__
.L_loop1:
cmp r2, r3
ittt lt
ldrlt r0, [r1], #4
strlt r0, [r2], #4
blt .L_loop1
#endif /*__STARTUP_COPY_MULTIPLE */
/* This part of work usually is done in C library startup code. Otherwise,
* define this macro to enable it in this startup.
*
* There are two schemes too. One can clear multiple BSS sections. Another
* can only clear one section. The former is more size expensive than the
* latter.
*
* Define macro __STARTUP_CLEAR_BSS_MULTIPLE to choose the former.
* Otherwise efine macro __STARTUP_CLEAR_BSS to choose the later.
*/
#ifdef __STARTUP_CLEAR_BSS_MULTIPLE
/* Multiple sections scheme.
*
* Between symbol address __zero_table_start__ and __zero_table_end__,
* there are array of tuples specifying:
* offset 0: Start of a BSS section
* offset 4: Size of this BSS section. Must be multiply of 4
*/
ldr r3, =__zero_table_start__
ldr r4, =__zero_table_end__
.L_loop2:
cmp r3, r4
bge .L_loop2_done
ldr r1, [r3]
ldr r2, [r3, #4]
movs r0, 0
.L_loop2_0:
subs r2, #4
itt ge
strge r0, [r1, r2]
bge .L_loop2_0
adds r3, #8
b .L_loop2
.L_loop2_done:
#elif defined (__STARTUP_CLEAR_BSS)
/* Single BSS section scheme.
*
* The BSS section is specified by following symbols
* __bss_start__: start of the BSS section.
* __bss_end__: end of the BSS section.
*
* Both addresses must be aligned to 4 bytes boundary.
*/
ldr r1, =__bss_start__
ldr r2, =__bss_end__
movs r0, 0
.L_loop3:
cmp r1, r2
itt lt
strlt r0, [r1], #4
blt .L_loop3
#endif /* __STARTUP_CLEAR_BSS_MULTIPLE || __STARTUP_CLEAR_BSS */
#ifndef __START
#define __START _start
#endif
bl __START
.pool
.size Reset_Handler, . - Reset_Handler
.align 1
.thumb_func
.weak Default_Handler
.type Default_Handler, %function
Default_Handler:
b .
.size Default_Handler, . - Default_Handler
/* Macro to define default handlers. Default handler
* will be weak symbol and just dead loops. They can be
* overwritten by other handlers */
.macro def_irq_handler handler_name
.weak \handler_name
.set \handler_name, Default_Handler
.endm
def_irq_handler NMI_Handler
def_irq_handler HardFault_Handler
def_irq_handler MemManage_Handler
def_irq_handler BusFault_Handler
def_irq_handler UsageFault_Handler
def_irq_handler SVC_Handler
def_irq_handler DebugMon_Handler
def_irq_handler PendSV_Handler
def_irq_handler SysTick_Handler
def_irq_handler EMU_IRQHandler
def_irq_handler WDOG0_IRQHandler
def_irq_handler LDMA_IRQHandler
def_irq_handler GPIO_EVEN_IRQHandler
def_irq_handler TIMER0_IRQHandler
def_irq_handler USART0_RX_IRQHandler
def_irq_handler USART0_TX_IRQHandler
def_irq_handler ACMP0_IRQHandler
def_irq_handler ADC0_IRQHandler
def_irq_handler IDAC0_IRQHandler
def_irq_handler I2C0_IRQHandler
def_irq_handler GPIO_ODD_IRQHandler
def_irq_handler TIMER1_IRQHandler
def_irq_handler USART1_RX_IRQHandler
def_irq_handler USART1_TX_IRQHandler
def_irq_handler LEUART0_IRQHandler
def_irq_handler PCNT0_IRQHandler
def_irq_handler CMU_IRQHandler
def_irq_handler MSC_IRQHandler
def_irq_handler CRYPTO_IRQHandler
def_irq_handler LETIMER0_IRQHandler
def_irq_handler RTCC_IRQHandler
def_irq_handler CRYOTIMER_IRQHandler
def_irq_handler FPUEH_IRQHandler
.end

View File

@ -1,389 +0,0 @@
/***************************************************************************//**
* @file system_efm32pg1b.c
* @brief CMSIS Cortex-M3/M4 System Layer for EFM32 devices.
* @version 5.2.2
******************************************************************************
* # License
* <b>Copyright 2017 Silicon Laboratories, Inc. http://www.silabs.com</b>
******************************************************************************
*
* Permission is granted to anyone to use this software for any purpose,
* including commercial applications, and to alter it and redistribute it
* freely, subject to the following restrictions:
*
* 1. The origin of this software must not be misrepresented; you must not
* claim that you wrote the original software.@n
* 2. Altered source versions must be plainly marked as such, and must not be
* misrepresented as being the original software.@n
* 3. This notice may not be removed or altered from any source distribution.
*
* DISCLAIMER OF WARRANTY/LIMITATION OF REMEDIES: Silicon Laboratories, Inc.
* has no obligation to support this Software. Silicon Laboratories, Inc. is
* providing the Software "AS IS", with no express or implied warranties of any
* kind, including, but not limited to, any implied warranties of
* merchantability or fitness for any particular purpose or warranties against
* infringement of any proprietary rights of a third party.
*
* Silicon Laboratories, Inc. will not be liable for any consequential,
* incidental, or special damages, or any other relief, or for any claim by
* any third party, arising from your use of this Software.
*
*****************************************************************************/
#include <stdint.h>
#include "em_device.h"
/*******************************************************************************
****************************** DEFINES ************************************
******************************************************************************/
/** LFRCO frequency, tuned to below frequency during manufacturing. */
#define EFM32_LFRCO_FREQ (32768UL)
/** ULFRCO frequency */
#define EFM32_ULFRCO_FREQ (1000UL)
/*******************************************************************************
************************** LOCAL VARIABLES ********************************
******************************************************************************/
/* System oscillator frequencies. These frequencies are normally constant */
/* for a target, but they are made configurable in order to allow run-time */
/* handling of different boards. The crystal oscillator clocks can be set */
/* compile time to a non-default value by defining respective EFM_nFXO_FREQ */
/* values according to board design. By defining the EFM_nFXO_FREQ to 0, */
/* one indicates that the oscillator is not present, in order to save some */
/* SW footprint. */
#ifndef EFM32_HFRCO_MAX_FREQ
/** Maximum HFRCO frequency */
#define EFM32_HFRCO_MAX_FREQ (38000000UL)
#endif
#ifndef EFM32_HFXO_FREQ
/** HFXO frequency */
#define EFM32_HFXO_FREQ (40000000UL)
#endif
#ifndef EFM32_HFRCO_STARTUP_FREQ
/** HFRCO startup frequency */
#define EFM32_HFRCO_STARTUP_FREQ (19000000UL)
#endif
/* Do not define variable if HF crystal oscillator not present */
#if (EFM32_HFXO_FREQ > 0UL)
/** @cond DO_NOT_INCLUDE_WITH_DOXYGEN */
/** System HFXO clock. */
static uint32_t SystemHFXOClock = EFM32_HFXO_FREQ;
/** @endcond (DO_NOT_INCLUDE_WITH_DOXYGEN) */
#endif
#ifndef EFM32_LFXO_FREQ
/** LFXO frequency */
#define EFM32_LFXO_FREQ (EFM32_LFRCO_FREQ)
#endif
/* Do not define variable if LF crystal oscillator not present */
#if (EFM32_LFXO_FREQ > 0UL)
/** @cond DO_NOT_INCLUDE_WITH_DOXYGEN */
/** System LFXO clock. */
static uint32_t SystemLFXOClock = 32768UL;
/** @endcond (DO_NOT_INCLUDE_WITH_DOXYGEN) */
#endif
/*******************************************************************************
************************** GLOBAL VARIABLES *******************************
******************************************************************************/
/**
* @brief
* System System Clock Frequency (Core Clock).
*
* @details
* Required CMSIS global variable that must be kept up-to-date.
*/
uint32_t SystemCoreClock = EFM32_HFRCO_STARTUP_FREQ;
/**
* @brief
* System HFRCO frequency
*
* @note
* This is an EFM32 proprietary variable, not part of the CMSIS definition.
*
* @details
* Frequency of the system HFRCO oscillator
*/
uint32_t SystemHfrcoFreq = EFM32_HFRCO_STARTUP_FREQ;
/*******************************************************************************
************************** GLOBAL FUNCTIONS *******************************
******************************************************************************/
/***************************************************************************//**
* @brief
* Get the current core clock frequency.
*
* @details
* Calculate and get the current core clock frequency based on the current
* configuration. Assuming that the SystemCoreClock global variable is
* maintained, the core clock frequency is stored in that variable as well.
* This function will however calculate the core clock based on actual HW
* configuration. It will also update the SystemCoreClock global variable.
*
* @note
* This is an EFM32 proprietary function, not part of the CMSIS definition.
*
* @return
* The current core clock frequency in Hz.
******************************************************************************/
uint32_t SystemCoreClockGet(void)
{
uint32_t ret;
uint32_t presc;
ret = SystemHFClockGet();
presc = (CMU->HFCOREPRESC & _CMU_HFCOREPRESC_PRESC_MASK) >>
_CMU_HFCOREPRESC_PRESC_SHIFT;
ret /= (presc + 1);
/* Keep CMSIS system clock variable up-to-date */
SystemCoreClock = ret;
return ret;
}
/***************************************************************************//**
* @brief
* Get the maximum core clock frequency.
*
* @note
* This is an EFM32 proprietary function, not part of the CMSIS definition.
*
* @return
* The maximum core clock frequency in Hz.
******************************************************************************/
uint32_t SystemMaxCoreClockGet(void)
{
return (EFM32_HFRCO_MAX_FREQ > EFM32_HFXO_FREQ ? \
EFM32_HFRCO_MAX_FREQ : EFM32_HFXO_FREQ);
}
/***************************************************************************//**
* @brief
* Get the current HFCLK frequency.
*
* @note
* This is an EFM32 proprietary function, not part of the CMSIS definition.
*
* @return
* The current HFCLK frequency in Hz.
******************************************************************************/
uint32_t SystemHFClockGet(void)
{
uint32_t ret;
switch (CMU->HFCLKSTATUS & _CMU_HFCLKSTATUS_SELECTED_MASK)
{
case CMU_HFCLKSTATUS_SELECTED_LFXO:
#if (EFM32_LFXO_FREQ > 0)
ret = SystemLFXOClock;
#else
/* We should not get here, since core should not be clocked. May */
/* be caused by a misconfiguration though. */
ret = 0;
#endif
break;
case CMU_HFCLKSTATUS_SELECTED_LFRCO:
ret = EFM32_LFRCO_FREQ;
break;
case CMU_HFCLKSTATUS_SELECTED_HFXO:
#if (EFM32_HFXO_FREQ > 0)
ret = SystemHFXOClock;
#else
/* We should not get here, since core should not be clocked. May */
/* be caused by a misconfiguration though. */
ret = 0;
#endif
break;
default: /* CMU_HFCLKSTATUS_SELECTED_HFRCO */
ret = SystemHfrcoFreq;
break;
}
return ret / (1U + ((CMU->HFPRESC & _CMU_HFPRESC_PRESC_MASK)
>> _CMU_HFPRESC_PRESC_SHIFT));
}
/**************************************************************************//**
* @brief
* Get high frequency crystal oscillator clock frequency for target system.
*
* @note
* This is an EFM32 proprietary function, not part of the CMSIS definition.
*
* @return
* HFXO frequency in Hz.
*****************************************************************************/
uint32_t SystemHFXOClockGet(void)
{
/* External crystal oscillator present? */
#if (EFM32_HFXO_FREQ > 0)
return SystemHFXOClock;
#else
return 0;
#endif
}
/**************************************************************************//**
* @brief
* Set high frequency crystal oscillator clock frequency for target system.
*
* @note
* This function is mainly provided for being able to handle target systems
* with different HF crystal oscillator frequencies run-time. If used, it
* should probably only be used once during system startup.
*
* @note
* This is an EFM32 proprietary function, not part of the CMSIS definition.
*
* @param[in] freq
* HFXO frequency in Hz used for target.
*****************************************************************************/
void SystemHFXOClockSet(uint32_t freq)
{
/* External crystal oscillator present? */
#if (EFM32_HFXO_FREQ > 0)
SystemHFXOClock = freq;
/* Update core clock frequency if HFXO is used to clock core */
if ((CMU->HFCLKSTATUS & _CMU_HFCLKSTATUS_SELECTED_MASK) == CMU_HFCLKSTATUS_SELECTED_HFXO)
{
/* The function will update the global variable */
SystemCoreClockGet();
}
#else
(void)freq; /* Unused parameter */
#endif
}
/**************************************************************************//**
* @brief
* Initialize the system.
*
* @details
* Do required generic HW system init.
*
* @note
* This function is invoked during system init, before the main() routine
* and any data has been initialized. For this reason, it cannot do any
* initialization of variables etc.
*****************************************************************************/
void SystemInit(void)
{
#if (__FPU_PRESENT == 1) && (__FPU_USED == 1)
/* Set floating point coprosessor access mode. */
SCB->CPACR |= ((3UL << 10*2) | /* set CP10 Full Access */
(3UL << 11*2) ); /* set CP11 Full Access */
#endif
}
/**************************************************************************//**
* @brief
* Get low frequency RC oscillator clock frequency for target system.
*
* @note
* This is an EFM32 proprietary function, not part of the CMSIS definition.
*
* @return
* LFRCO frequency in Hz.
*****************************************************************************/
uint32_t SystemLFRCOClockGet(void)
{
/* Currently we assume that this frequency is properly tuned during */
/* manufacturing and is not changed after reset. If future requirements */
/* for re-tuning by user, we can add support for that. */
return EFM32_LFRCO_FREQ;
}
/**************************************************************************//**
* @brief
* Get ultra low frequency RC oscillator clock frequency for target system.
*
* @note
* This is an EFM32 proprietary function, not part of the CMSIS definition.
*
* @return
* ULFRCO frequency in Hz.
*****************************************************************************/
uint32_t SystemULFRCOClockGet(void)
{
/* The ULFRCO frequency is not tuned, and can be very inaccurate */
return EFM32_ULFRCO_FREQ;
}
/**************************************************************************//**
* @brief
* Get low frequency crystal oscillator clock frequency for target system.
*
* @note
* This is an EFM32 proprietary function, not part of the CMSIS definition.
*
* @return
* LFXO frequency in Hz.
*****************************************************************************/
uint32_t SystemLFXOClockGet(void)
{
/* External crystal oscillator present? */
#if (EFM32_LFXO_FREQ > 0)
return SystemLFXOClock;
#else
return 0;
#endif
}
/**************************************************************************//**
* @brief
* Set low frequency crystal oscillator clock frequency for target system.
*
* @note
* This function is mainly provided for being able to handle target systems
* with different HF crystal oscillator frequencies run-time. If used, it
* should probably only be used once during system startup.
*
* @note
* This is an EFM32 proprietary function, not part of the CMSIS definition.
*
* @param[in] freq
* LFXO frequency in Hz used for target.
*****************************************************************************/
void SystemLFXOClockSet(uint32_t freq)
{
/* External crystal oscillator present? */
#if (EFM32_LFXO_FREQ > 0)
SystemLFXOClock = freq;
/* Update core clock frequency if LFXO is used to clock core */
if ((CMU->HFCLKSTATUS & _CMU_HFCLKSTATUS_SELECTED_MASK) == CMU_HFCLKSTATUS_SELECTED_LFXO)
{
/* The function will update the global variable */
SystemCoreClockGet();
}
#else
(void)freq; /* Unused parameter */
#endif
}

View File

@ -1,116 +0,0 @@
<?xml version="1.0" encoding="ASCII"?>
<device:XMLDevice xmi:version="2.0" xmlns:xmi="http://www.omg.org/XMI" xmlns:device="http://www.silabs.com/ss/hwconfig/document/device.ecore" name="EFM32PG1B200F256GM48" partId="mcu.arm.efm32.pg1.efm32pg1b200f256gm48" contextId="%DEFAULT%">
<mode name="DefaultMode">
<property object="ADC0" propertyId="ABPeripheral.included" value="true"/>
<property object="CMU" propertyId="ABPeripheral.included" value="true"/>
<property object="CMU" propertyId="clocksettings.hfrcosettings.hfrcofrequency" value="38 MHz"/>
<property object="CMU" propertyId="clocksettings.lfclocksettings.ulfrcorequired" value="Yes"/>
<property object="CRYOTIMER" propertyId="ABPeripheral.included" value="true"/>
<property object="CRYOTIMER" propertyId="cryotimer.clocking.clocksourceforcryotimer" value="ULFRCO"/>
<property object="CRYOTIMER" propertyId="cryotimer.clocking.eventafterevery" value="1 cycle"/>
<property object="CRYPTO" propertyId="ABPeripheral.included" value="true"/>
<property object="DefaultMode" propertyId="mode.diagramLocation" value="100, 100"/>
<property object="EMU" propertyId="ABPeripheral.included" value="true"/>
<property object="GPIO" propertyId="ABPeripheral.included" value="true"/>
<property object="PA0" propertyId="ports.settings.pinmode" value="Push-pull"/>
<property object="PA1" propertyId="ports.settings.dout" value="1"/>
<property object="PA1" propertyId="ports.settings.filter" value="Enabled"/>
<property object="PA1" propertyId="ports.settings.pinmode" value="Input pull"/>
<property object="PA1" propertyId="ports.settings.pulldirection" value="Pullup"/>
<property object="PA1" propertyId="ports.settings.pullup" value="Enabled"/>
<property object="PA3" propertyId="ports.settings.pinmode" value="Push-pull"/>
<property object="PA4" propertyId="ports.settings.dout" value="1"/>
<property object="PA4" propertyId="ports.settings.filter" value="Enabled"/>
<property object="PA4" propertyId="ports.settings.pinmode" value="Wired-and pullup filter"/>
<property object="PA4" propertyId="ports.settings.pulldirection" value="Pullup"/>
<property object="PA4" propertyId="ports.settings.pullup" value="Enabled"/>
<property object="PA5" propertyId="ports.settings.dout" value="1"/>
<property object="PA5" propertyId="ports.settings.filter" value="Enabled"/>
<property object="PA5" propertyId="ports.settings.pinmode" value="Push-pull"/>
<property object="PA5" propertyId="ports.settings.pulldirection" value="Pullup"/>
<property object="PA5" propertyId="ports.settings.pullup" value="Enabled"/>
<property object="PB13" propertyId="ports.settings.dout" value="1"/>
<property object="PB13" propertyId="ports.settings.filter" value="Enabled"/>
<property object="PB13" propertyId="ports.settings.pinmode" value="Push-pull"/>
<property object="PB13" propertyId="ports.settings.pulldirection" value="Pullup"/>
<property object="PB13" propertyId="ports.settings.pullup" value="Enabled"/>
<property object="PC10" propertyId="ports.settings.dout" value="1"/>
<property object="PC10" propertyId="ports.settings.filter" value="Enabled"/>
<property object="PC10" propertyId="ports.settings.pinmode" value="Push-pull"/>
<property object="PC10" propertyId="ports.settings.pulldirection" value="Pullup"/>
<property object="PC10" propertyId="ports.settings.pullup" value="Enabled"/>
<property object="PC6" propertyId="ports.settings.dout" value="1"/>
<property object="PC6" propertyId="ports.settings.filter" value="Enabled"/>
<property object="PC6" propertyId="ports.settings.pinmode" value="Push-pull"/>
<property object="PC6" propertyId="ports.settings.pulldirection" value="Pullup"/>
<property object="PC6" propertyId="ports.settings.pullup" value="Enabled"/>
<property object="PC7" propertyId="ports.settings.dout" value="1"/>
<property object="PC7" propertyId="ports.settings.filter" value="Enabled"/>
<property object="PC7" propertyId="ports.settings.pinmode" value="Input pull"/>
<property object="PC7" propertyId="ports.settings.pulldirection" value="Pullup"/>
<property object="PC7" propertyId="ports.settings.pullup" value="Enabled"/>
<property object="PC8" propertyId="ports.settings.dout" value="1"/>
<property object="PC8" propertyId="ports.settings.filter" value="Enabled"/>
<property object="PC8" propertyId="ports.settings.pinmode" value="Push-pull"/>
<property object="PC8" propertyId="ports.settings.pulldirection" value="Pullup"/>
<property object="PC8" propertyId="ports.settings.pullup" value="Enabled"/>
<property object="PC9" propertyId="ports.settings.dout" value="1"/>
<property object="PC9" propertyId="ports.settings.filter" value="Enabled"/>
<property object="PC9" propertyId="ports.settings.pinmode" value="Input pull"/>
<property object="PC9" propertyId="ports.settings.pulldirection" value="Pullup"/>
<property object="PC9" propertyId="ports.settings.pullup" value="Enabled"/>
<property object="PD10" propertyId="ports.settings.dout" value="1"/>
<property object="PD10" propertyId="ports.settings.filter" value="Enabled"/>
<property object="PD10" propertyId="ports.settings.pinmode" value="Push-pull"/>
<property object="PD10" propertyId="ports.settings.pulldirection" value="Pullup"/>
<property object="PD10" propertyId="ports.settings.pullup" value="Enabled"/>
<property object="PD15" propertyId="ports.settings.dout" value="1"/>
<property object="PD15" propertyId="ports.settings.filter" value="Enabled"/>
<property object="PD15" propertyId="ports.settings.pinmode" value="Push-pull"/>
<property object="PD15" propertyId="ports.settings.pulldirection" value="Pullup"/>
<property object="PD15" propertyId="ports.settings.pullup" value="Enabled"/>
<property object="PF2" propertyId="ports.settings.dout" value="1"/>
<property object="PF2" propertyId="ports.settings.filter" value="Enabled"/>
<property object="PF2" propertyId="ports.settings.pinmode" value="Push-pull"/>
<property object="PF2" propertyId="ports.settings.pulldirection" value="Pullup"/>
<property object="PF2" propertyId="ports.settings.pullup" value="Enabled"/>
<property object="PF3" propertyId="ports.settings.dout" value="1"/>
<property object="PF3" propertyId="ports.settings.filter" value="Enabled"/>
<property object="PF3" propertyId="ports.settings.pinmode" value="Wired-and pullup filter"/>
<property object="PF3" propertyId="ports.settings.pulldirection" value="Pullup"/>
<property object="PF3" propertyId="ports.settings.pullup" value="Enabled"/>
<property object="PF4" propertyId="ports.settings.pinmode" value="Push-pull"/>
<property object="PF5" propertyId="ports.settings.pinmode" value="Push-pull"/>
<property object="PF6" propertyId="ports.settings.dout" value="1"/>
<property object="PF6" propertyId="ports.settings.filter" value="Enabled"/>
<property object="PF6" propertyId="ports.settings.pinmode" value="Input pull"/>
<property object="PF6" propertyId="ports.settings.pulldirection" value="Pullup"/>
<property object="PF6" propertyId="ports.settings.pullup" value="Enabled"/>
<property object="PORTIO" propertyId="portio.i2c0.location.i2c0_sclloc" value="3"/>
<property object="PORTIO" propertyId="portio.i2c0.location.i2c0_sdaloc" value="27"/>
<property object="PORTIO" propertyId="portio.usart0.enable.cts" value="Enabled"/>
<property object="PORTIO" propertyId="portio.usart0.enable.rts" value="Enabled"/>
<property object="PORTIO" propertyId="portio.usart0.enable.rx" value="Enabled"/>
<property object="PORTIO" propertyId="portio.usart0.enable.tx" value="Enabled"/>
<property object="PORTIO" propertyId="portio.usart0.location.usart0_ctsloc" value="30"/>
<property object="PORTIO" propertyId="portio.usart0.location.usart0_rtsloc" value="30"/>
<property object="PORTIO" propertyId="portio.usart1.enable.clk" value="Enabled"/>
<property object="PORTIO" propertyId="portio.usart1.enable.rx" value="Enabled"/>
<property object="PORTIO" propertyId="portio.usart1.enable.tx" value="Enabled"/>
<property object="PORTIO" propertyId="portio.usart1.location.usart1_clkloc" value="11"/>
<property object="PORTIO" propertyId="portio.usart1.location.usart1_rxloc" value="11"/>
<property object="PORTIO" propertyId="portio.usart1.location.usart1_txloc" value="11"/>
<property object="TIMER0" propertyId="timer.clocksettings.clockselection" value="TIM0_CC1 input"/>
<property object="USART0" propertyId="ABPeripheral.included" value="true"/>
<property object="USART0" propertyId="usart.outputsettings.clockselect" value="Disabled"/>
<property object="USART1" propertyId="ABPeripheral.included" value="true"/>
<property object="USART1" propertyId="usart.mode.usartmode" value="Synchronous Mode (SPI / I2S)"/>
<property object="USART1" propertyId="usart.outputsettings.clockselect" value="Disabled"/>
<property object="USART1" propertyId="usart.synchronoussettings.baudrate" value="130000"/>
<property object="USART1" propertyId="usart.synchronoussettings.clockpolarityphasemode" value="Clock idle low, sample on falling edge"/>
</mode>
<modeTransition>
<property object="RESET &#x2192; DefaultMode" propertyId="modeTransition.source" value="RESET"/>
<property object="RESET &#x2192; DefaultMode" propertyId="modeTransition.target" value="DefaultMode"/>
</modeTransition>
</device:XMLDevice>

View File

@ -1,107 +0,0 @@
<?xml version="1.0" encoding="ASCII"?>
<device:XMLDevice xmi:version="2.0" xmlns:xmi="http://www.omg.org/XMI" xmlns:device="http://www.silabs.com/ss/hwconfig/document/device.ecore" name="EFM32JG1B200F128GM32" partId="mcu.arm.efm32.jg1.efm32jg1b200f128gm32" contextId="%DEFAULT%">
<mode name="DefaultMode">
<property object="ADC0" propertyId="ABPeripheral.included" value="true"/>
<property object="CMU" propertyId="ABPeripheral.included" value="true"/>
<property object="CMU" propertyId="clocksettings.hfrcosettings.hfrcofrequency" value="38 MHz"/>
<property object="CMU" propertyId="clocksettings.lfclocksettings.ulfrcorequired" value="Yes"/>
<property object="CRYOTIMER" propertyId="ABPeripheral.included" value="true"/>
<property object="CRYOTIMER" propertyId="cryotimer.clocking.clocksourceforcryotimer" value="ULFRCO"/>
<property object="CRYOTIMER" propertyId="cryotimer.clocking.eventafterevery" value="1 cycle"/>
<property object="CRYPTO" propertyId="ABPeripheral.included" value="true"/>
<property object="DefaultMode" propertyId="mode.diagramLocation" value="100, 100"/>
<property object="EMU" propertyId="ABPeripheral.included" value="true"/>
<property object="EMU" propertyId="emu.powerconfiguration.externalpowercircuitwiring" value="Not wired for DCDC"/>
<property object="GPIO" propertyId="ABPeripheral.included" value="true"/>
<property object="PA0" propertyId="ports.settings.pinmode" value="Input"/>
<property object="PA1" propertyId="ports.settings.pinmode" value="Input"/>
<property object="PB11" propertyId="ports.settings.dout" value="1"/>
<property object="PB11" propertyId="ports.settings.filter" value="Enabled"/>
<property object="PB11" propertyId="ports.settings.pinmode" value="Push-pull"/>
<property object="PB11" propertyId="ports.settings.pulldirection" value="Pullup"/>
<property object="PB11" propertyId="ports.settings.pullup" value="Enabled"/>
<property object="PB12" propertyId="ports.settings.dout" value="1"/>
<property object="PB12" propertyId="ports.settings.filter" value="Enabled"/>
<property object="PB12" propertyId="ports.settings.pinmode" value="Input pull"/>
<property object="PB12" propertyId="ports.settings.pulldirection" value="Pullup"/>
<property object="PB12" propertyId="ports.settings.pullup" value="Enabled"/>
<property object="PB13" propertyId="ports.settings.dout" value="1"/>
<property object="PB13" propertyId="ports.settings.filter" value="Enabled"/>
<property object="PB13" propertyId="ports.settings.pinmode" value="Push-pull"/>
<property object="PB13" propertyId="ports.settings.pulldirection" value="Pullup"/>
<property object="PB13" propertyId="ports.settings.pullup" value="Enabled"/>
<property object="PB15" propertyId="ports.settings.dout" value="1"/>
<property object="PB15" propertyId="ports.settings.filter" value="Enabled"/>
<property object="PB15" propertyId="ports.settings.pinmode" value="Push-pull"/>
<property object="PB15" propertyId="ports.settings.pulldirection" value="Pullup"/>
<property object="PB15" propertyId="ports.settings.pullup" value="Enabled"/>
<property object="PD10" propertyId="ports.settings.dout" value="1"/>
<property object="PD10" propertyId="ports.settings.filter" value="Enabled"/>
<property object="PD10" propertyId="ports.settings.pinmode" value="Push-pull"/>
<property object="PD10" propertyId="ports.settings.pulldirection" value="Pullup"/>
<property object="PD10" propertyId="ports.settings.pullup" value="Enabled"/>
<property object="PD11" propertyId="ports.settings.dout" value="1"/>
<property object="PD11" propertyId="ports.settings.filter" value="Enabled"/>
<property object="PD11" propertyId="ports.settings.pinmode" value="Input pull"/>
<property object="PD11" propertyId="ports.settings.pulldirection" value="Pullup"/>
<property object="PD11" propertyId="ports.settings.pullup" value="Enabled"/>
<property object="PD12" propertyId="ports.settings.dout" value="1"/>
<property object="PD12" propertyId="ports.settings.filter" value="Enabled"/>
<property object="PD12" propertyId="ports.settings.pinmode" value="Push-pull"/>
<property object="PD12" propertyId="ports.settings.pulldirection" value="Pullup"/>
<property object="PD12" propertyId="ports.settings.pullup" value="Enabled"/>
<property object="PD13" propertyId="ports.settings.dout" value="1"/>
<property object="PD13" propertyId="ports.settings.filter" value="Enabled"/>
<property object="PD13" propertyId="ports.settings.pinmode" value="Input pull"/>
<property object="PD13" propertyId="ports.settings.pulldirection" value="Pullup"/>
<property object="PD13" propertyId="ports.settings.pullup" value="Enabled"/>
<property object="PD14" propertyId="ports.settings.dout" value="1"/>
<property object="PD14" propertyId="ports.settings.filter" value="Enabled"/>
<property object="PD14" propertyId="ports.settings.pinmode" value="Push-pull"/>
<property object="PD14" propertyId="ports.settings.pulldirection" value="Pullup"/>
<property object="PD14" propertyId="ports.settings.pullup" value="Enabled"/>
<property object="PD15" propertyId="ports.settings.dout" value="1"/>
<property object="PD15" propertyId="ports.settings.filter" value="Enabled"/>
<property object="PD15" propertyId="ports.settings.pinmode" value="Push-pull"/>
<property object="PD15" propertyId="ports.settings.pulldirection" value="Pullup"/>
<property object="PD15" propertyId="ports.settings.pullup" value="Enabled"/>
<property object="PD9" propertyId="ports.settings.dout" value="1"/>
<property object="PD9" propertyId="ports.settings.filter" value="Enabled"/>
<property object="PD9" propertyId="ports.settings.pinmode" value="Push-pull"/>
<property object="PD9" propertyId="ports.settings.pulldirection" value="Pullup"/>
<property object="PD9" propertyId="ports.settings.pullup" value="Enabled"/>
<property object="PORTIO" propertyId="portio.timer0.enable.cc0" value="Enabled"/>
<property object="PORTIO" propertyId="portio.timer0.enable.cc1" value="Enabled"/>
<property object="PORTIO" propertyId="portio.timer0.enable.cc2" value="Enabled"/>
<property object="PORTIO" propertyId="portio.timer0.location.timer0_cc0loc" value="18"/>
<property object="PORTIO" propertyId="portio.timer0.location.timer0_cc1loc" value="16"/>
<property object="PORTIO" propertyId="portio.timer0.location.timer0_cc2loc" value="20"/>
<property object="PORTIO" propertyId="portio.usart0.enable.rx" value="Enabled"/>
<property object="PORTIO" propertyId="portio.usart0.enable.tx" value="Enabled"/>
<property object="PORTIO" propertyId="portio.usart0.location.usart0_txloc" value="20"/>
<property object="PORTIO" propertyId="portio.usart1.enable.clk" value="Enabled"/>
<property object="PORTIO" propertyId="portio.usart1.enable.rx" value="Enabled"/>
<property object="PORTIO" propertyId="portio.usart1.enable.tx" value="Enabled"/>
<property object="PORTIO" propertyId="portio.usart1.location.usart1_rxloc" value="6"/>
<property object="PORTIO" propertyId="portio.usart1.location.usart1_txloc" value="8"/>
<property object="TIMER0" propertyId="ABPeripheral.included" value="true"/>
<property object="TIMER0" propertyId="timer.capturecomparech0.ccmode" value="PWM"/>
<property object="TIMER0" propertyId="timer.capturecomparech0.countermatchoutputaction" value="Toggle on event"/>
<property object="TIMER0" propertyId="timer.capturecomparech1.ccmode" value="PWM"/>
<property object="TIMER0" propertyId="timer.capturecomparech1.countermatchoutputaction" value="Toggle on event"/>
<property object="TIMER0" propertyId="timer.capturecomparech2.ccmode" value="PWM"/>
<property object="TIMER0" propertyId="timer.capturecomparech2.countermatchoutputaction" value="Toggle on event"/>
<property object="TIMER0" propertyId="timer.clocksettings.hfperprescaler" value="Divide by 512"/>
<property object="USART0" propertyId="ABPeripheral.included" value="true"/>
<property object="USART0" propertyId="usart.outputsettings.clockselect" value="Disabled"/>
<property object="USART1" propertyId="ABPeripheral.included" value="true"/>
<property object="USART1" propertyId="usart.asynchronoussettings.baudrate" value="130000"/>
<property object="USART1" propertyId="usart.mode.usartmode" value="Synchronous Mode (SPI / I2S)"/>
<property object="USART1" propertyId="usart.outputsettings.clockselect" value="Disabled"/>
<property object="USART1" propertyId="usart.synchronoussettings.baudrate" value="130000"/>
</mode>
<modeTransition>
<property object="RESET &#x2192; DefaultMode" propertyId="modeTransition.source" value="RESET"/>
<property object="RESET &#x2192; DefaultMode" propertyId="modeTransition.target" value="DefaultMode"/>
</modeTransition>
</device:XMLDevice>

View File

@ -1,23 +0,0 @@
CC=arm-none-eabi-gcc
all:
cd 'GNU ARM v7.2.1 - Debug' && make all
#arm-none-eabi-gcc -g -gdwarf-2 -mcpu=cortex-m4 -mthumb -std=c99 '-DDEBUG=1' '-DEFM32PG1B200F256GM48=1' -IC:/Users/conor/Desktop/u2f-one/crypto/sha256 -IC:/Users/conor/Desktop/u2f-one/crypto/micro-ecc -IC:/Users/conor/Desktop/u2f-one/crypto/tiny-AES-c -I"C:\Users\conor\Desktop\u2f-one\efm32\inc" -IC:/Users/conor/Desktop/u2f-one/fido2 -IC:/Users/conor/Desktop/u2f-one/tinycbor/src -I"C:/SiliconLabs/SimplicityStudio/v4/developer/sdks/gecko_sdk_suite/v1.1//platform/CMSIS/Include" -I"C:/SiliconLabs/SimplicityStudio/v4/developer/sdks/gecko_sdk_suite/v1.1//hardware/kit/common/drivers" -I"C:/SiliconLabs/SimplicityStudio/v4/developer/sdks/gecko_sdk_suite/v1.1//hardware/kit/SLSTK3401A_EFM32PG/config" -I"C:/SiliconLabs/SimplicityStudio/v4/developer/sdks/gecko_sdk_suite/v1.1//platform/Device/SiliconLabs/EFM32PG1B/Include" -I"C:/SiliconLabs/SimplicityStudio/v4/developer/sdks/gecko_sdk_suite/v1.1//platform/emlib/inc" -I"C:/SiliconLabs/SimplicityStudio/v4/developer/sdks/gecko_sdk_suite/v1.1//hardware/kit/common/bsp" -O0 -Wall -c -fmessage-length=0 -mno-sched-prolog -fno-builtin -ffunction-sections -fdata-sections -mfpu=fpv4-sp-d16 -mfloat-abi=softfp -MMD -MP -MF"src/device.d" -MT"src/device.o" -o "src/device.o" "../src/device.c"
#arm-none-eabi-gcc -g -gdwarf-2 -mcpu=cortex-m4 -mthumb -T "EFM32.ld" -Xlinker --gc-sections -Xlinker -Map="EFM32.map" -mfpu=fpv4-sp-d16 -mfloat-abi=softfp --specs=nano.specs -o EFM32.axf "./CMSIS/EFM32PG1B/startup_gcc_efm32pg1b.o" "./CMSIS/EFM32PG1B/system_efm32pg1b.o" "./crypto/micro-ecc/uECC.o" "./crypto/sha256/sha256.o" "./crypto/tiny-AES-c/aes.o" "./emlib/em_assert.o" "./emlib/em_cmu.o" "./emlib/em_emu.o" "./emlib/em_gpio.o" "./emlib/em_system.o" "./emlib/em_usart.o" "./fido2/crypto.o" "./fido2/ctap.o" "./fido2/ctap_parse.o" "./fido2/ctaphid.o" "./fido2/log.o" "./fido2/main.o" "./fido2/stubs.o" "./fido2/test_power.o" "./fido2/u2f.o" "./fido2/util.o" "./src/InitDevice.o" "./src/device.o" "./src/main.o" "./src/printing.o" "./src/retargetio.o" -Wl,--start-group -lgcc -lc -lnosys -Wl,--end-group
cbor:
cd ../tinycbor/ && make clean
cd ../tinycbor/ && make CC="$(CC)" \
LDFLAGS="-lgcc -lc -lnosys --specs=nosys.specs -mcpu=cortex-m4 -mfloat-abi=softfp -mfpu=fpv4-sp-d16 -mthumb " \
CFLAGS="-g -gdwarf-2 -mcpu=cortex-m4 -mthumb -std=c99 -DEFM32PG1B200F256GM48=1 -O3 -Wall -c -fmessage-length=0 -mno-sched-prolog -fno-builtin -ffunction-sections -fdata-sections -mfpu=fpv4-sp-d16 -mfloat-abi=softfp -MMD -MP "
clean:
cd 'GNU ARM v7.2.1 - Debug' && make clean

File diff suppressed because it is too large Load Diff

View File

@ -1,81 +0,0 @@
/***************************************************************************//**
* @file em_assert.c
* @brief Assert API
* @version 5.2.2
*******************************************************************************
* # License
* <b>Copyright 2016 Silicon Laboratories, Inc. http://www.silabs.com</b>
*******************************************************************************
*
* Permission is granted to anyone to use this software for any purpose,
* including commercial applications, and to alter it and redistribute it
* freely, subject to the following restrictions:
*
* 1. The origin of this software must not be misrepresented; you must not
* claim that you wrote the original software.
* 2. Altered source versions must be plainly marked as such, and must not be
* misrepresented as being the original software.
* 3. This notice may not be removed or altered from any source distribution.
*
* DISCLAIMER OF WARRANTY/LIMITATION OF REMEDIES: Silicon Labs has no
* obligation to support this Software. Silicon Labs is providing the
* Software "AS IS", with no express or implied warranties of any kind,
* including, but not limited to, any implied warranties of merchantability
* or fitness for any particular purpose or warranties against infringement
* of any proprietary rights of a third party.
*
* Silicon Labs will not be liable for any consequential, incidental, or
* special damages, or any other relief, or for any claim by any third party,
* arising from your use of this Software.
*
******************************************************************************/
#include "em_assert.h"
#include <stdbool.h>
/***************************************************************************//**
* @addtogroup emlib
* @{
******************************************************************************/
/***************************************************************************//**
* @addtogroup ASSERT
* @{
******************************************************************************/
#if defined(DEBUG_EFM)
/***************************************************************************//**
* @brief
* EFM internal assert handling.
*
* This function is invoked through EFM_ASSERT() macro usage only, it should
* not be used explicitly.
*
* This implementation simply enters an indefinite loop, allowing
* the use of a debugger to determine cause of failure. By defining
* DEBUG_EFM_USER to the preprocessor for all files, a user defined version
* of this function must be defined and will be invoked instead, possibly
* providing output of assertion location.
*
* @note
* This function is not used unless @ref DEBUG_EFM is defined
* during preprocessing of EFM_ASSERT() usage.
*
* @param[in] file
* Name of source file where assertion failed.
*
* @param[in] line
* Line number in source file where assertion failed.
******************************************************************************/
void assertEFM(const char *file, int line)
{
(void)file; /* Unused parameter */
(void)line; /* Unused parameter */
while (true) {
}
}
#endif /* DEBUG_EFM */
/** @} (end addtogroup ASSERT) */
/** @} (end addtogroup emlib) */

File diff suppressed because it is too large Load Diff

View File

@ -1,61 +0,0 @@
/***************************************************************************//**
* @file em_cryotimer.c
* @brief Ultra Low Energy Timer/Counter (CRYOTIMER) peripheral API
* @version 5.2.2
*******************************************************************************
* # License
* <b>Copyright 2016 Silicon Laboratories, Inc. http://www.silabs.com</b>
*******************************************************************************
*
* Permission is granted to anyone to use this software for any purpose,
* including commercial applications, and to alter it and redistribute it
* freely, subject to the following restrictions:
*
* 1. The origin of this software must not be misrepresented; you must not
* claim that you wrote the original software.@n
* 2. Altered source versions must be plainly marked as such, and must not be
* misrepresented as being the original software.@n
* 3. This notice may not be removed or altered from any source distribution.
*
* DISCLAIMER OF WARRANTY/LIMITATION OF REMEDIES: Silicon Labs has no
* obligation to support this Software. Silicon Labs is providing the
* Software "AS IS", with no express or implied warranties of any kind,
* including, but not limited to, any implied warranties of merchantability
* or fitness for any particular purpose or warranties against infringement
* of any proprietary rights of a third party.
*
* Silicon Labs will not be liable for any consequential, incidental, or
* special damages, or any other relief, or for any claim by any third party,
* arising from your use of this Software.
*
******************************************************************************/
#include "em_cryotimer.h"
#include "em_bus.h"
#if defined(CRYOTIMER_PRESENT) && (CRYOTIMER_COUNT == 1)
/***************************************************************************//**
* @brief
* Initialize the CRYOTIMER.
*
* @details
* Use this function to initialize the CRYOTIMER.
* Select prescaler setting and select low frequency oscillator.
* Refer to the configuration structure @ref CRYOTIMER_Init_TypeDef for more
* details.
*
* @param[in] init
* Pointer to initialization structure.
******************************************************************************/
void CRYOTIMER_Init(const CRYOTIMER_Init_TypeDef *init)
{
CRYOTIMER->PERIODSEL = (uint32_t)init->period & _CRYOTIMER_PERIODSEL_MASK;
CRYOTIMER->CTRL = ((uint32_t)init->enable << _CRYOTIMER_CTRL_EN_SHIFT)
| ((uint32_t)init->debugRun << _CRYOTIMER_CTRL_DEBUGRUN_SHIFT)
| ((uint32_t)init->osc << _CRYOTIMER_CTRL_OSCSEL_SHIFT)
| ((uint32_t)init->presc << _CRYOTIMER_CTRL_PRESC_SHIFT);
CRYOTIMER_EM4WakeupEnable(init->em4Wakeup);
}
#endif /* defined(CRYOTIMER_PRESENT) && (CRYOTIMER_COUNT > 0) */

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -1,367 +0,0 @@
/***************************************************************************//**
* @file em_gpio.c
* @brief General Purpose IO (GPIO) peripheral API
* devices.
* @version 5.2.2
*******************************************************************************
* # License
* <b>Copyright 2016 Silicon Laboratories, Inc. http://www.silabs.com</b>
*******************************************************************************
*
* Permission is granted to anyone to use this software for any purpose,
* including commercial applications, and to alter it and redistribute it
* freely, subject to the following restrictions:
*
* 1. The origin of this software must not be misrepresented; you must not
* claim that you wrote the original software.
* 2. Altered source versions must be plainly marked as such, and must not be
* misrepresented as being the original software.
* 3. This notice may not be removed or altered from any source distribution.
*
* DISCLAIMER OF WARRANTY/LIMITATION OF REMEDIES: Silicon Labs has no
* obligation to support this Software. Silicon Labs is providing the
* Software "AS IS", with no express or implied warranties of any kind,
* including, but not limited to, any implied warranties of merchantability
* or fitness for any particular purpose or warranties against infringement
* of any proprietary rights of a third party.
*
* Silicon Labs will not be liable for any consequential, incidental, or
* special damages, or any other relief, or for any claim by any third party,
* arising from your use of this Software.
*
******************************************************************************/
#include "em_gpio.h"
#if defined(GPIO_COUNT) && (GPIO_COUNT > 0)
/***************************************************************************//**
* @addtogroup emlib
* @{
******************************************************************************/
/***************************************************************************//**
* @addtogroup GPIO
* @brief General Purpose Input/Output (GPIO) API
* @details
* This module contains functions to control the GPIO peripheral of Silicon
* Labs 32-bit MCUs and SoCs. The GPIO peripheral is used for pin configuration
* and direct pin manipulation and sensing as well as routing for peripheral
* pin connections.
* @{
******************************************************************************/
/*******************************************************************************
******************************* DEFINES ***********************************
******************************************************************************/
/** @cond DO_NOT_INCLUDE_WITH_DOXYGEN */
/** Validation of pin typically usable in assert statements. */
#define GPIO_DRIVEMODE_VALID(mode) ((mode) <= 3)
#define GPIO_STRENGHT_VALID(strenght) (!((strenght) \
& ~(_GPIO_P_CTRL_DRIVESTRENGTH_MASK \
| _GPIO_P_CTRL_DRIVESTRENGTHALT_MASK)))
/** @endcond */
/*******************************************************************************
************************** GLOBAL FUNCTIONS *******************************
******************************************************************************/
/***************************************************************************//**
* @brief
* Sets the pin location of the debug pins (Serial Wire interface).
*
* @note
* Changing the pins used for debugging uncontrolled, may result in a lockout.
*
* @param[in] location
* The debug pin location to use (0-3).
******************************************************************************/
void GPIO_DbgLocationSet(unsigned int location)
{
#if defined (_GPIO_ROUTE_SWLOCATION_MASK)
EFM_ASSERT(location < AFCHANLOC_MAX);
GPIO->ROUTE = (GPIO->ROUTE & ~_GPIO_ROUTE_SWLOCATION_MASK)
| (location << _GPIO_ROUTE_SWLOCATION_SHIFT);
#else
(void)location;
#endif
}
#if defined (_GPIO_P_CTRL_DRIVEMODE_MASK)
/***************************************************************************//**
* @brief
* Sets the drive mode for a GPIO port.
*
* @param[in] port
* The GPIO port to access.
*
* @param[in] mode
* Drive mode to use for port.
******************************************************************************/
void GPIO_DriveModeSet(GPIO_Port_TypeDef port, GPIO_DriveMode_TypeDef mode)
{
EFM_ASSERT(GPIO_PORT_VALID(port) && GPIO_DRIVEMODE_VALID(mode));
GPIO->P[port].CTRL = (GPIO->P[port].CTRL & ~(_GPIO_P_CTRL_DRIVEMODE_MASK))
| (mode << _GPIO_P_CTRL_DRIVEMODE_SHIFT);
}
#endif
#if defined (_GPIO_P_CTRL_DRIVESTRENGTH_MASK)
/***************************************************************************//**
* @brief
* Sets the drive strength for a GPIO port.
*
* @param[in] port
* The GPIO port to access.
*
* @param[in] strength
* Drive strength to use for port.
******************************************************************************/
void GPIO_DriveStrengthSet(GPIO_Port_TypeDef port,
GPIO_DriveStrength_TypeDef strength)
{
EFM_ASSERT(GPIO_PORT_VALID(port) && GPIO_STRENGHT_VALID(strength));
BUS_RegMaskedWrite(&GPIO->P[port].CTRL,
_GPIO_P_CTRL_DRIVESTRENGTH_MASK | _GPIO_P_CTRL_DRIVESTRENGTHALT_MASK,
strength);
}
#endif
/***************************************************************************//**
* @brief
* Configure GPIO external pin interrupt.
*
* @details
* If reconfiguring a GPIO interrupt that is already enabled, it is generally
* recommended to disable it first, see GPIO_Disable().
*
* The actual GPIO interrupt handler must be in place before enabling the
* interrupt.
*
* Notice that any pending interrupt for the selected interrupt is cleared
* by this function.
*
* @note
* On series 0 devices the pin number parameter is not used. The
* pin number used on these devices is hardwired to the interrupt with the
* same number. @n
* On series 1 devices, pin number can be selected freely within a group.
* Interrupt numbers are divided into 4 groups (intNo / 4) and valid pin
* number within the interrupt groups are:
* 0: pins 0-3
* 1: pins 4-7
* 2: pins 8-11
* 3: pins 12-15
*
* @param[in] port
* The port to associate with @p pin.
*
* @param[in] pin
* The pin number on the port.
*
* @param[in] intNo
* The interrupt number to trigger.
*
* @param[in] risingEdge
* Set to true if interrupts shall be enabled on rising edge, otherwise false.
*
* @param[in] fallingEdge
* Set to true if interrupts shall be enabled on falling edge, otherwise false.
*
* @param[in] enable
* Set to true if interrupt shall be enabled after configuration completed,
* false to leave disabled. See GPIO_IntDisable() and GPIO_IntEnable().
******************************************************************************/
void GPIO_ExtIntConfig(GPIO_Port_TypeDef port,
unsigned int pin,
unsigned int intNo,
bool risingEdge,
bool fallingEdge,
bool enable)
{
uint32_t tmp = 0;
#if !defined(_GPIO_EXTIPINSELL_MASK)
(void)pin;
#endif
EFM_ASSERT(GPIO_PORT_PIN_VALID(port, pin));
#if defined(_GPIO_EXTIPINSELL_MASK)
EFM_ASSERT(GPIO_INTNO_PIN_VALID(intNo, pin));
#endif
/* There are two registers controlling the interrupt configuration:
* The EXTIPSELL register controls pins 0-7 and EXTIPSELH controls
* pins 8-15. */
if (intNo < 8) {
BUS_RegMaskedWrite(&GPIO->EXTIPSELL,
_GPIO_EXTIPSELL_EXTIPSEL0_MASK
<< (_GPIO_EXTIPSELL_EXTIPSEL1_SHIFT * intNo),
port << (_GPIO_EXTIPSELL_EXTIPSEL1_SHIFT * intNo));
} else {
tmp = intNo - 8;
BUS_RegMaskedWrite(&GPIO->EXTIPSELH,
_GPIO_EXTIPSELH_EXTIPSEL8_MASK
<< (_GPIO_EXTIPSELH_EXTIPSEL9_SHIFT * tmp),
port << (_GPIO_EXTIPSELH_EXTIPSEL9_SHIFT * tmp));
}
#if defined(_GPIO_EXTIPINSELL_MASK)
/* There are two registers controlling the interrupt/pin number mapping:
* The EXTIPINSELL register controls interrupt 0-7 and EXTIPINSELH controls
* interrupt 8-15. */
if (intNo < 8) {
BUS_RegMaskedWrite(&GPIO->EXTIPINSELL,
_GPIO_EXTIPINSELL_EXTIPINSEL0_MASK
<< (_GPIO_EXTIPINSELL_EXTIPINSEL1_SHIFT * intNo),
((pin % 4) & _GPIO_EXTIPINSELL_EXTIPINSEL0_MASK)
<< (_GPIO_EXTIPINSELL_EXTIPINSEL1_SHIFT * intNo));
} else {
BUS_RegMaskedWrite(&GPIO->EXTIPINSELH,
_GPIO_EXTIPINSELH_EXTIPINSEL8_MASK
<< (_GPIO_EXTIPINSELH_EXTIPINSEL9_SHIFT * tmp),
((pin % 4) & _GPIO_EXTIPINSELH_EXTIPINSEL8_MASK)
<< (_GPIO_EXTIPSELH_EXTIPSEL9_SHIFT * tmp));
}
#endif
/* Enable/disable rising edge */
BUS_RegBitWrite(&(GPIO->EXTIRISE), intNo, risingEdge);
/* Enable/disable falling edge */
BUS_RegBitWrite(&(GPIO->EXTIFALL), intNo, fallingEdge);
/* Clear any pending interrupt */
GPIO->IFC = 1 << intNo;
/* Finally enable/disable interrupt */
BUS_RegBitWrite(&(GPIO->IEN), intNo, enable);
}
/***************************************************************************//**
* @brief
* Set the mode for a GPIO pin.
*
* @param[in] port
* The GPIO port to access.
*
* @param[in] pin
* The pin number in the port.
*
* @param[in] mode
* The desired pin mode.
*
* @param[in] out
* Value to set for pin in DOUT register. The DOUT setting is important for
* even some input mode configurations, determining pull-up/down direction.
******************************************************************************/
void GPIO_PinModeSet(GPIO_Port_TypeDef port,
unsigned int pin,
GPIO_Mode_TypeDef mode,
unsigned int out)
{
EFM_ASSERT(GPIO_PORT_PIN_VALID(port, pin));
/* If disabling pin, do not modify DOUT in order to reduce chance for */
/* glitch/spike (may not be sufficient precaution in all use cases) */
if (mode != gpioModeDisabled) {
if (out) {
GPIO_PinOutSet(port, pin);
} else {
GPIO_PinOutClear(port, pin);
}
}
/* There are two registers controlling the pins for each port. The MODEL
* register controls pins 0-7 and MODEH controls pins 8-15. */
if (pin < 8) {
GPIO->P[port].MODEL = (GPIO->P[port].MODEL & ~(0xFu << (pin * 4)))
| (mode << (pin * 4));
} else {
GPIO->P[port].MODEH = (GPIO->P[port].MODEH & ~(0xFu << ((pin - 8) * 4)))
| (mode << ((pin - 8) * 4));
}
if (mode == gpioModeDisabled) {
if (out) {
GPIO_PinOutSet(port, pin);
} else {
GPIO_PinOutClear(port, pin);
}
}
}
/***************************************************************************//**
* @brief
* Get the mode for a GPIO pin.
*
* @param[in] port
* The GPIO port to access.
*
* @param[in] pin
* The pin number in the port.
*
* @return
* The pin mode.
******************************************************************************/
GPIO_Mode_TypeDef GPIO_PinModeGet(GPIO_Port_TypeDef port,
unsigned int pin)
{
EFM_ASSERT(GPIO_PORT_PIN_VALID(port, pin));
if (pin < 8) {
return (GPIO_Mode_TypeDef) ((GPIO->P[port].MODEL >> (pin * 4)) & 0xF);
} else {
return (GPIO_Mode_TypeDef) ((GPIO->P[port].MODEH >> ((pin - 8) * 4)) & 0xF);
}
}
#if defined(_GPIO_EM4WUEN_MASK)
/**************************************************************************//**
* @brief
* Enable GPIO pin wake-up from EM4. When the function exits,
* EM4 mode can be safely entered.
*
* @note
* It is assumed that the GPIO pin modes are set correctly.
* Valid modes are @ref gpioModeInput and @ref gpioModeInputPull.
*
* @param[in] pinmask
* Bitmask containing the bitwise logic OR of which GPIO pin(s) to enable.
* Refer to Reference Manuals for pinmask to GPIO port/pin mapping.
* @param[in] polaritymask
* Bitmask containing the bitwise logic OR of GPIO pin(s) wake-up polarity.
* Refer to Reference Manuals for pinmask to GPIO port/pin mapping.
*****************************************************************************/
void GPIO_EM4EnablePinWakeup(uint32_t pinmask, uint32_t polaritymask)
{
EFM_ASSERT((pinmask & ~_GPIO_EM4WUEN_MASK) == 0);
#if defined(_GPIO_EM4WUPOL_MASK)
EFM_ASSERT((polaritymask & ~_GPIO_EM4WUPOL_MASK) == 0);
GPIO->EM4WUPOL &= ~pinmask; /* Set wakeup polarity */
GPIO->EM4WUPOL |= pinmask & polaritymask;
#elif defined(_GPIO_EXTILEVEL_MASK)
EFM_ASSERT((polaritymask & ~_GPIO_EXTILEVEL_MASK) == 0);
GPIO->EXTILEVEL &= ~pinmask;
GPIO->EXTILEVEL |= pinmask & polaritymask;
#endif
GPIO->EM4WUEN |= pinmask; /* Enable wakeup */
GPIO_EM4SetPinRetention(true); /* Enable pin retention */
#if defined(_GPIO_CMD_EM4WUCLR_MASK)
GPIO->CMD = GPIO_CMD_EM4WUCLR; /* Clear wake-up logic */
#elif defined(_GPIO_IFC_EM4WU_MASK)
GPIO_IntClear(pinmask);
#endif
}
#endif
/** @} (end addtogroup GPIO) */
/** @} (end addtogroup emlib) */
#endif /* defined(GPIO_COUNT) && (GPIO_COUNT > 0) */

View File

@ -1,811 +0,0 @@
/***************************************************************************//**
* @file em_i2c.c
* @brief Inter-integrated Circuit (I2C) Peripheral API
* @version 5.2.2
*******************************************************************************
* # License
* <b>Copyright 2016 Silicon Laboratories, Inc. http://www.silabs.com</b>
*******************************************************************************
*
* Permission is granted to anyone to use this software for any purpose,
* including commercial applications, and to alter it and redistribute it
* freely, subject to the following restrictions:
*
* 1. The origin of this software must not be misrepresented; you must not
* claim that you wrote the original software.
* 2. Altered source versions must be plainly marked as such, and must not be
* misrepresented as being the original software.
* 3. This notice may not be removed or altered from any source distribution.
*
* DISCLAIMER OF WARRANTY/LIMITATION OF REMEDIES: Silicon Labs has no
* obligation to support this Software. Silicon Labs is providing the
* Software "AS IS", with no express or implied warranties of any kind,
* including, but not limited to, any implied warranties of merchantability
* or fitness for any particular purpose or warranties against infringement
* of any proprietary rights of a third party.
*
* Silicon Labs will not be liable for any consequential, incidental, or
* special damages, or any other relief, or for any claim by any third party,
* arising from your use of this Software.
*
******************************************************************************/
#include "em_i2c.h"
#if defined(I2C_COUNT) && (I2C_COUNT > 0)
#include "em_cmu.h"
#include "em_bus.h"
#include "em_assert.h"
#include <limits.h>
/***************************************************************************//**
* @addtogroup emlib
* @{
******************************************************************************/
/***************************************************************************//**
* @addtogroup I2C
* @brief Inter-integrated Circuit (I2C) Peripheral API
* @details
* This module contains functions to control the I2C peripheral of Silicon
* Labs 32-bit MCUs and SoCs. The I2C interface allows communication on I2C
* buses with the lowest energy consumption possible.
* @{
******************************************************************************/
/*******************************************************************************
******************************* DEFINES ***********************************
******************************************************************************/
/** @cond DO_NOT_INCLUDE_WITH_DOXYGEN */
/** Validation of I2C register block pointer reference for assert statements. */
#if (I2C_COUNT == 1)
#define I2C_REF_VALID(ref) ((ref) == I2C0)
#elif (I2C_COUNT == 2)
#define I2C_REF_VALID(ref) ((ref == I2C0) || (ref == I2C1))
#elif (I2C_COUNT == 3)
#define I2C_REF_VALID(ref) ((ref == I2C0) || (ref == I2C1) || (ref == I2C2))
#endif
/** Error flags indicating I2C transfer has failed somehow. */
/* Notice that I2C_IF_TXOF (transmit overflow) is not really possible with */
/* this SW supporting master mode. Likewise for I2C_IF_RXUF (receive underflow) */
/* RXUF is only likely to occur with this SW if using a debugger peeking into */
/* RXDATA register. Thus, we ignore those types of fault. */
#define I2C_IF_ERRORS (I2C_IF_BUSERR | I2C_IF_ARBLOST)
/* Max I2C transmission rate constant */
#if defined(_SILICON_LABS_32B_SERIES_0)
#define I2C_CR_MAX 4
#elif defined(_SILICON_LABS_32B_SERIES_1)
#define I2C_CR_MAX 8
#else
#warning "Max I2C transmission rate constant is not defined"
#endif
/** @endcond */
/*******************************************************************************
******************************** ENUMS ************************************
******************************************************************************/
/** @cond DO_NOT_INCLUDE_WITH_DOXYGEN */
/** Master mode transfer states. */
typedef enum {
i2cStateStartAddrSend, /**< Send start + (first part of) address. */
i2cStateAddrWFAckNack, /**< Wait for ACK/NACK on (first part of) address. */
i2cStateAddrWF2ndAckNack, /**< Wait for ACK/NACK on second part of 10 bit address. */
i2cStateRStartAddrSend, /**< Send repeated start + (first part of) address. */
i2cStateRAddrWFAckNack, /**< Wait for ACK/NACK on address sent after repeated start. */
i2cStateDataSend, /**< Send data. */
i2cStateDataWFAckNack, /**< Wait for ACK/NACK on data sent. */
i2cStateWFData, /**< Wait for data. */
i2cStateWFStopSent, /**< Wait for STOP to have been transmitted. */
i2cStateDone /**< Transfer completed successfully. */
} I2C_TransferState_TypeDef;
/** @endcond */
/*******************************************************************************
******************************* STRUCTS ***********************************
******************************************************************************/
/** @cond DO_NOT_INCLUDE_WITH_DOXYGEN */
/** Structure used to store state information on an ongoing master mode transfer. */
typedef struct {
/** Current state. */
I2C_TransferState_TypeDef state;
/** Result return code. */
I2C_TransferReturn_TypeDef result;
/** Offset in current sequence buffer. */
uint16_t offset;
/* Index to current sequence buffer in use. */
uint8_t bufIndx;
/** Reference to I2C transfer sequence definition provided by user. */
I2C_TransferSeq_TypeDef *seq;
} I2C_Transfer_TypeDef;
/** @endcond */
/*******************************************************************************
***************************** LOCAL DATA *******^**************************
******************************************************************************/
/** @cond DO_NOT_INCLUDE_WITH_DOXYGEN */
/**
* Lookup table for Nlow + Nhigh setting defined by CLHR. Set undefined
* index (0x3) to reflect default setting just in case.
*/
static const uint8_t i2cNSum[] = { 4 + 4, 6 + 3, 11 + 6, 4 + 4 };
/** Transfer state info for ongoing master mode transfer */
static I2C_Transfer_TypeDef i2cTransfer[I2C_COUNT];
/** @endcond */
/*******************************************************************************
************************** GLOBAL FUNCTIONS *******************************
******************************************************************************/
/***************************************************************************//**
* @brief
* Get current configured I2C bus frequency.
*
* @details
* This frequency is only of relevance when acting as master.
*
* @param[in] i2c
* Pointer to I2C peripheral register block.
*
* @return
* Current I2C frequency in Hz.
******************************************************************************/
uint32_t I2C_BusFreqGet(I2C_TypeDef *i2c)
{
uint32_t freqHfper;
uint32_t n;
/* Max frequency is given by freqScl = freqHfper/((Nlow + Nhigh)(DIV + 1) + I2C_CR_MAX)
* More details can be found in the reference manual,
* I2C Clock Generation chapter. */
freqHfper = CMU_ClockFreqGet(cmuClock_HFPER);
/* n = Nlow + Nhigh */
n = (uint32_t)(i2cNSum[(i2c->CTRL & _I2C_CTRL_CLHR_MASK) >> _I2C_CTRL_CLHR_SHIFT]);
return (freqHfper / ((n * (i2c->CLKDIV + 1)) + I2C_CR_MAX));
}
/***************************************************************************//**
* @brief
* Set I2C bus frequency.
*
* @details
* The bus frequency is only of relevance when acting as a master. The bus
* frequency should not be set higher than the max frequency accepted by the
* slowest device on the bus.
*
* Notice that due to asymmetric requirements on low and high I2C clock
* cycles by the I2C specification, the actual max frequency allowed in order
* to comply with the specification may be somewhat lower than expected.
*
* Please refer to the reference manual, details on I2C clock generation,
* for max allowed theoretical frequencies for different modes.
*
* @param[in] i2c
* Pointer to I2C peripheral register block.
*
* @param[in] freqRef
* I2C reference clock frequency in Hz that will be used. If set to 0,
* then HFPER clock is used. Setting it to a higher than actual configured
* value only has the consequence of reducing the real I2C frequency.
*
* @param[in] freqScl
* Bus frequency to set (actual bus speed may be lower due to integer
* prescaling). Safe (according to I2C specification) max frequencies for
* standard, fast and fast+ modes are available using I2C_FREQ_ defines.
* (Using I2C_FREQ_ defines requires corresponding setting of @p type.)
* Slowest slave device on bus must always be considered.
*
* @param[in] i2cMode
* Clock low to high ratio type to use. If not using i2cClockHLRStandard,
* make sure all devices on the bus support the specified mode. Using a
* non-standard ratio is useful to achieve higher bus clock in fast and
* fast+ modes.
******************************************************************************/
void I2C_BusFreqSet(I2C_TypeDef *i2c,
uint32_t freqRef,
uint32_t freqScl,
I2C_ClockHLR_TypeDef i2cMode)
{
uint32_t n, minFreq;
int32_t div;
/* Avoid divide by 0 */
EFM_ASSERT(freqScl);
if (!freqScl) {
return;
}
/* Set the CLHR (clock low to high ratio). */
i2c->CTRL &= ~_I2C_CTRL_CLHR_MASK;
BUS_RegMaskedWrite(&i2c->CTRL,
_I2C_CTRL_CLHR_MASK,
i2cMode << _I2C_CTRL_CLHR_SHIFT);
if (!freqRef) {
freqRef = CMU_ClockFreqGet(cmuClock_HFPER);
}
/* Check minumum HF peripheral clock */
minFreq = UINT_MAX;
if (i2c->CTRL & I2C_CTRL_SLAVE) {
switch (i2cMode) {
case i2cClockHLRStandard:
#if defined(_SILICON_LABS_32B_SERIES_0)
minFreq = 4200000; break;
#elif defined(_SILICON_LABS_32B_SERIES_1)
minFreq = 2000000; break;
#endif
case i2cClockHLRAsymetric:
#if defined(_SILICON_LABS_32B_SERIES_0)
minFreq = 11000000; break;
#elif defined(_SILICON_LABS_32B_SERIES_1)
minFreq = 5000000; break;
#endif
case i2cClockHLRFast:
#if defined(_SILICON_LABS_32B_SERIES_0)
minFreq = 24400000; break;
#elif defined(_SILICON_LABS_32B_SERIES_1)
minFreq = 14000000; break;
#endif
}
} else {
/* For master mode, platform 1 and 2 share the same
min frequencies */
switch (i2cMode) {
case i2cClockHLRStandard:
minFreq = 2000000; break;
case i2cClockHLRAsymetric:
minFreq = 9000000; break;
case i2cClockHLRFast:
minFreq = 20000000; break;
}
}
/* Frequency most be larger-than */
EFM_ASSERT(freqRef > minFreq);
/* SCL frequency is given by
* freqScl = freqRef/((Nlow + Nhigh) * (DIV + 1) + I2C_CR_MAX)
*
* Thus
* DIV = ((freqRef - (I2C_CR_MAX * freqScl))/((Nlow + Nhigh) * freqScl)) - 1
*
* More details can be found in the reference manual,
* I2C Clock Generation chapter. */
/* n = Nlow + Nhigh */
n = (uint32_t)(i2cNSum[i2cMode]);
div = ((freqRef - (I2C_CR_MAX * freqScl)) / (n * freqScl)) - 1;
EFM_ASSERT(div >= 0);
EFM_ASSERT((uint32_t)div <= _I2C_CLKDIV_DIV_MASK);
/* Clock divisor must be at least 1 in slave mode according to reference */
/* manual (in which case there is normally no need to set bus frequency). */
if ((i2c->CTRL & I2C_CTRL_SLAVE) && !div) {
div = 1;
}
i2c->CLKDIV = (uint32_t)div;
}
/***************************************************************************//**
* @brief
* Enable/disable I2C.
*
* @note
* After enabling the I2C (from being disabled), the I2C is in BUSY state.
*
* @param[in] i2c
* Pointer to I2C peripheral register block.
*
* @param[in] enable
* true to enable counting, false to disable.
******************************************************************************/
void I2C_Enable(I2C_TypeDef *i2c, bool enable)
{
EFM_ASSERT(I2C_REF_VALID(i2c));
BUS_RegBitWrite(&(i2c->CTRL), _I2C_CTRL_EN_SHIFT, enable);
}
/***************************************************************************//**
* @brief
* Initialize I2C.
*
* @param[in] i2c
* Pointer to I2C peripheral register block.
*
* @param[in] init
* Pointer to I2C initialization structure.
******************************************************************************/
void I2C_Init(I2C_TypeDef *i2c, const I2C_Init_TypeDef *init)
{
EFM_ASSERT(I2C_REF_VALID(i2c));
i2c->IEN = 0;
i2c->IFC = _I2C_IFC_MASK;
/* Set SLAVE select mode */
BUS_RegBitWrite(&(i2c->CTRL), _I2C_CTRL_SLAVE_SHIFT, init->master ? 0 : 1);
I2C_BusFreqSet(i2c, init->refFreq, init->freq, init->clhr);
BUS_RegBitWrite(&(i2c->CTRL), _I2C_CTRL_EN_SHIFT, init->enable);
}
/***************************************************************************//**
* @brief
* Reset I2C to same state as after a HW reset.
*
* @note
* The ROUTE register is NOT reset by this function, in order to allow for
* centralized setup of this feature.
*
* @param[in] i2c
* Pointer to I2C peripheral register block.
******************************************************************************/
void I2C_Reset(I2C_TypeDef *i2c)
{
i2c->CTRL = _I2C_CTRL_RESETVALUE;
i2c->CLKDIV = _I2C_CLKDIV_RESETVALUE;
i2c->SADDR = _I2C_SADDR_RESETVALUE;
i2c->SADDRMASK = _I2C_SADDRMASK_RESETVALUE;
i2c->IEN = _I2C_IEN_RESETVALUE;
i2c->IFC = _I2C_IFC_MASK;
/* Do not reset route register, setting should be done independently */
}
/***************************************************************************//**
* @brief
* Continue an initiated I2C transfer (single master mode only).
*
* @details
* This function is used repeatedly after a I2C_TransferInit() in order to
* complete a transfer. It may be used in polled mode as the below example
* shows:
* @verbatim
* I2C_TransferReturn_TypeDef ret;
*
* // Do a polled transfer
* ret = I2C_TransferInit(I2C0, seq);
* while (ret == i2cTransferInProgress)
* {
* ret = I2C_Transfer(I2C0);
* }
* @endverbatim
* It may also be used in interrupt driven mode, where this function is invoked
* from the interrupt handler. Notice that if used in interrupt mode, NVIC
* interrupts must be configured and enabled for the I2C bus used. I2C
* peripheral specific interrupts are managed by this SW.
*
* @note
* Only single master mode is supported.
*
* @param[in] i2c
* Pointer to I2C peripheral register block.
*
* @return
* Returns status for ongoing transfer.
* @li #i2cTransferInProgress - indicates that transfer not finished.
* @li #i2cTransferDone - transfer completed successfully.
* @li otherwise some sort of error has occurred.
*
******************************************************************************/
I2C_TransferReturn_TypeDef I2C_Transfer(I2C_TypeDef *i2c)
{
uint32_t tmp;
uint32_t pending;
I2C_Transfer_TypeDef *transfer;
I2C_TransferSeq_TypeDef *seq;
EFM_ASSERT(I2C_REF_VALID(i2c));
/* Support up to 2 I2C buses */
if (i2c == I2C0) {
transfer = i2cTransfer;
}
#if (I2C_COUNT > 1)
else if (i2c == I2C1) {
transfer = i2cTransfer + 1;
}
#endif
#if (I2C_COUNT > 2)
else if (i2c == I2C2) {
transfer = i2cTransfer + 2;
}
#endif
else {
return i2cTransferUsageFault;
}
seq = transfer->seq;
for (;; ) {
pending = i2c->IF;
/* If some sort of fault, abort transfer. */
if (pending & I2C_IF_ERRORS) {
if (pending & I2C_IF_ARBLOST) {
/* If arbitration fault, it indicates either a slave device */
/* not responding as expected, or other master which is not */
/* supported by this SW. */
transfer->result = i2cTransferArbLost;
} else if (pending & I2C_IF_BUSERR) {
/* A bus error indicates a misplaced start or stop, which should */
/* not occur in master mode controlled by this SW. */
transfer->result = i2cTransferBusErr;
}
/* If error situation occurred, it is difficult to know */
/* exact cause and how to resolve. It will be up to a wrapper */
/* to determine how to handle a fault/recovery if possible. */
transfer->state = i2cStateDone;
goto done;
}
switch (transfer->state) {
/***************************************************/
/* Send first start+address (first byte if 10 bit) */
/***************************************************/
case i2cStateStartAddrSend:
if (seq->flags & I2C_FLAG_10BIT_ADDR) {
tmp = (((uint32_t)(seq->addr) >> 8) & 0x06) | 0xf0;
/* In 10 bit address mode, the address following the first */
/* start always indicate write. */
} else {
tmp = (uint32_t)(seq->addr) & 0xfe;
if (seq->flags & I2C_FLAG_READ) {
/* Indicate read request */
tmp |= 1;
}
}
transfer->state = i2cStateAddrWFAckNack;
i2c->TXDATA = tmp;/* Data not transmitted until START sent */
i2c->CMD = I2C_CMD_START;
goto done;
/*******************************************************/
/* Wait for ACK/NACK on address (first byte if 10 bit) */
/*******************************************************/
case i2cStateAddrWFAckNack:
if (pending & I2C_IF_NACK) {
i2c->IFC = I2C_IFC_NACK;
transfer->result = i2cTransferNack;
transfer->state = i2cStateWFStopSent;
i2c->CMD = I2C_CMD_STOP;
} else if (pending & I2C_IF_ACK) {
i2c->IFC = I2C_IFC_ACK;
/* If 10 bit address, send 2nd byte of address. */
if (seq->flags & I2C_FLAG_10BIT_ADDR) {
transfer->state = i2cStateAddrWF2ndAckNack;
i2c->TXDATA = (uint32_t)(seq->addr) & 0xff;
} else {
/* Determine whether receiving or sending data */
if (seq->flags & I2C_FLAG_READ) {
transfer->state = i2cStateWFData;
if (seq->buf[transfer->bufIndx].len == 1) {
i2c->CMD = I2C_CMD_NACK;
}
} else {
transfer->state = i2cStateDataSend;
continue;
}
}
}
goto done;
/******************************************************/
/* Wait for ACK/NACK on second byte of 10 bit address */
/******************************************************/
case i2cStateAddrWF2ndAckNack:
if (pending & I2C_IF_NACK) {
i2c->IFC = I2C_IFC_NACK;
transfer->result = i2cTransferNack;
transfer->state = i2cStateWFStopSent;
i2c->CMD = I2C_CMD_STOP;
} else if (pending & I2C_IF_ACK) {
i2c->IFC = I2C_IFC_ACK;
/* If using plain read sequence with 10 bit address, switch to send */
/* repeated start. */
if (seq->flags & I2C_FLAG_READ) {
transfer->state = i2cStateRStartAddrSend;
}
/* Otherwise expected to write 0 or more bytes */
else {
transfer->state = i2cStateDataSend;
}
continue;
}
goto done;
/*******************************/
/* Send repeated start+address */
/*******************************/
case i2cStateRStartAddrSend:
if (seq->flags & I2C_FLAG_10BIT_ADDR) {
tmp = ((seq->addr >> 8) & 0x06) | 0xf0;
} else {
tmp = seq->addr & 0xfe;
}
/* If this is a write+read combined sequence, then read is about to start */
if (seq->flags & I2C_FLAG_WRITE_READ) {
/* Indicate read request */
tmp |= 1;
}
transfer->state = i2cStateRAddrWFAckNack;
/* We have to write START cmd first since repeated start, otherwise */
/* data would be sent first. */
i2c->CMD = I2C_CMD_START;
i2c->TXDATA = tmp;
goto done;
/**********************************************************************/
/* Wait for ACK/NACK on repeated start+address (first byte if 10 bit) */
/**********************************************************************/
case i2cStateRAddrWFAckNack:
if (pending & I2C_IF_NACK) {
i2c->IFC = I2C_IFC_NACK;
transfer->result = i2cTransferNack;
transfer->state = i2cStateWFStopSent;
i2c->CMD = I2C_CMD_STOP;
} else if (pending & I2C_IF_ACK) {
i2c->IFC = I2C_IFC_ACK;
/* Determine whether receiving or sending data */
if (seq->flags & I2C_FLAG_WRITE_READ) {
transfer->state = i2cStateWFData;
} else {
transfer->state = i2cStateDataSend;
continue;
}
}
goto done;
/*****************************/
/* Send a data byte to slave */
/*****************************/
case i2cStateDataSend:
/* Reached end of data buffer? */
if (transfer->offset >= seq->buf[transfer->bufIndx].len) {
/* Move to next message part */
transfer->offset = 0;
transfer->bufIndx++;
/* Send repeated start when switching to read mode on 2nd buffer */
if (seq->flags & I2C_FLAG_WRITE_READ) {
transfer->state = i2cStateRStartAddrSend;
continue;
}
/* Only writing from one buffer, or finished both buffers */
if ((seq->flags & I2C_FLAG_WRITE) || (transfer->bufIndx > 1)) {
transfer->state = i2cStateWFStopSent;
i2c->CMD = I2C_CMD_STOP;
goto done;
}
/* Reprocess in case next buffer is empty */
continue;
}
/* Send byte */
i2c->TXDATA = (uint32_t)(seq->buf[transfer->bufIndx].data[transfer->offset++]);
transfer->state = i2cStateDataWFAckNack;
goto done;
/*********************************************************/
/* Wait for ACK/NACK from slave after sending data to it */
/*********************************************************/
case i2cStateDataWFAckNack:
if (pending & I2C_IF_NACK) {
i2c->IFC = I2C_IFC_NACK;
transfer->result = i2cTransferNack;
transfer->state = i2cStateWFStopSent;
i2c->CMD = I2C_CMD_STOP;
} else if (pending & I2C_IF_ACK) {
i2c->IFC = I2C_IFC_ACK;
transfer->state = i2cStateDataSend;
continue;
}
goto done;
/****************************/
/* Wait for data from slave */
/****************************/
case i2cStateWFData:
if (pending & I2C_IF_RXDATAV) {
uint8_t data;
unsigned int rxLen = seq->buf[transfer->bufIndx].len;
/* Must read out data in order to not block further progress */
data = (uint8_t)(i2c->RXDATA);
/* Make sure not storing beyond end of buffer just in case */
if (transfer->offset < rxLen) {
seq->buf[transfer->bufIndx].data[transfer->offset++] = data;
}
/* If we have read all requested data, then the sequence should end */
if (transfer->offset >= rxLen) {
/* If there is only one byte to receive we need to transmit the
NACK now, before the stop. */
if (1 == rxLen) {
i2c->CMD = I2C_CMD_NACK;
}
transfer->state = i2cStateWFStopSent;
i2c->CMD = I2C_CMD_STOP;
} else {
/* Send ACK and wait for next byte */
i2c->CMD = I2C_CMD_ACK;
if ( (1 < rxLen) && (transfer->offset == (rxLen - 1)) ) {
/* If there is more than one byte to receive and this is the next
to last byte we need to transmit the NACK now, before receiving
the last byte. */
i2c->CMD = I2C_CMD_NACK;
}
}
}
goto done;
/***********************************/
/* Wait for STOP to have been sent */
/***********************************/
case i2cStateWFStopSent:
if (pending & I2C_IF_MSTOP) {
i2c->IFC = I2C_IFC_MSTOP;
transfer->state = i2cStateDone;
}
goto done;
/******************************/
/* Unexpected state, SW fault */
/******************************/
default:
transfer->result = i2cTransferSwFault;
transfer->state = i2cStateDone;
goto done;
}
}
done:
if (transfer->state == i2cStateDone) {
/* Disable interrupt sources when done */
i2c->IEN = 0;
/* Update result unless some fault already occurred */
if (transfer->result == i2cTransferInProgress) {
transfer->result = i2cTransferDone;
}
}
/* Until transfer is done keep returning i2cTransferInProgress */
else {
return i2cTransferInProgress;
}
return transfer->result;
}
/***************************************************************************//**
* @brief
* Prepare and start an I2C transfer (single master mode only).
*
* @details
* This function must be invoked in order to start an I2C transfer
* sequence. In order to actually complete the transfer, I2C_Transfer() must
* be used either in polled mode or by adding a small driver wrapper utilizing
* interrupts.
*
* @note
* Only single master mode is supported.
*
* @param[in] i2c
* Pointer to I2C peripheral register block.
*
* @param[in] seq
* Pointer to sequence structure defining the I2C transfer to take place. The
* referenced structure must exist until the transfer has fully completed.
*
* @return
* Returns status for ongoing transfer:
* @li #i2cTransferInProgress - indicates that transfer not finished.
* @li otherwise some sort of error has occurred.
******************************************************************************/
I2C_TransferReturn_TypeDef I2C_TransferInit(I2C_TypeDef *i2c,
I2C_TransferSeq_TypeDef *seq)
{
I2C_Transfer_TypeDef *transfer;
EFM_ASSERT(I2C_REF_VALID(i2c));
EFM_ASSERT(seq);
/* Support up to 2 I2C buses */
if (i2c == I2C0) {
transfer = i2cTransfer;
}
#if (I2C_COUNT > 1)
else if (i2c == I2C1) {
transfer = i2cTransfer + 1;
}
#endif
#if (I2C_COUNT > 2)
else if (i2c == I2C2) {
transfer = i2cTransfer + 2;
}
#endif
else {
return i2cTransferUsageFault;
}
/* Check if in busy state. Since this SW assumes single master, we can */
/* just issue an abort. The BUSY state is normal after a reset. */
if (i2c->STATE & I2C_STATE_BUSY) {
i2c->CMD = I2C_CMD_ABORT;
}
/* Make sure user is not trying to read 0 bytes, it is not */
/* possible according to I2C spec, since slave will always start */
/* sending first byte ACK on address. The read operation can */
/* only be stopped by NACKing a received byte, ie minimum 1 byte. */
if (((seq->flags & I2C_FLAG_READ) && !(seq->buf[0].len))
|| ((seq->flags & I2C_FLAG_WRITE_READ) && !(seq->buf[1].len))
) {
return i2cTransferUsageFault;
}
/* Prepare for a transfer */
transfer->state = i2cStateStartAddrSend;
transfer->result = i2cTransferInProgress;
transfer->offset = 0;
transfer->bufIndx = 0;
transfer->seq = seq;
/* Ensure buffers are empty */
i2c->CMD = I2C_CMD_CLEARPC | I2C_CMD_CLEARTX;
if (i2c->IF & I2C_IF_RXDATAV) {
(void)i2c->RXDATA;
}
/* Clear all pending interrupts prior to starting transfer. */
i2c->IFC = _I2C_IFC_MASK;
/* Enable those interrupts we are interested in throughout transfer. */
/* Notice that the I2C interrupt must also be enabled in the NVIC, but */
/* that is left for an additional driver wrapper. */
i2c->IEN |= I2C_IF_NACK | I2C_IF_ACK | I2C_IF_MSTOP
| I2C_IF_RXDATAV | I2C_IF_ERRORS;
/* Start transfer */
return I2C_Transfer(i2c);
}
/** @} (end addtogroup I2C) */
/** @} (end addtogroup emlib) */
#endif /* defined(I2C_COUNT) && (I2C_COUNT > 0) */

Some files were not shown because too many files have changed in this diff Show More