Compare commits
454 Commits
fido2-cert
...
2.1.0
Author | SHA1 | Date | |
---|---|---|---|
89769ecc18 | |||
3b3f47bfcf | |||
6fa443b0bc | |||
893d4131b2 | |||
4e21c0bd8f | |||
251eb6bf64 | |||
08e236df69 | |||
d2091563ab | |||
54a6a82ca0 | |||
40b9dae38a | |||
98a209e330 | |||
d3b5fb68ee | |||
74a1f0e21b | |||
e21172fff8 | |||
9d3144e9b1 | |||
a2a774125f | |||
349ea5343a | |||
c851807376 | |||
84d1629aa3 | |||
8f6ae29163 | |||
a0d27c2c56 | |||
3a10427bd9 | |||
f3b591e570 | |||
175f59d206 | |||
f5ff6a11f0 | |||
d979420324 | |||
5076af1be4 | |||
0a7845459c | |||
c4262b0f5b | |||
53fb0059a7 | |||
a1a75e4ab5 | |||
d68011ef04 | |||
02e83073e0 | |||
3a48756f96 | |||
946e932b1e | |||
142d4002e5 | |||
dbe5283e1f | |||
2d233f164e | |||
b62e9906c7 | |||
e22e636475 | |||
074225d87a | |||
bb9b2ea9d4 | |||
e8d5bc5829 | |||
850381a633 | |||
ce3ad0e56f | |||
00d86379e5 | |||
6098810167 | |||
821880a8d6 | |||
44f96f5843 | |||
6ec9fb962a | |||
c9bfe001ee | |||
5e46fd96ac | |||
103cc3cfb0 | |||
9544330dc3 | |||
0964ff69b7 | |||
e4a2b9e1ca | |||
d29fa34da1 | |||
6ed2610a5c | |||
3b9d4e5023 | |||
2da083c18a | |||
50bfbc1eff | |||
86739df7a1 | |||
c7f0d050d7 | |||
b79670a447 | |||
169ba59ed4 | |||
f3003c58c9 | |||
084e518018 | |||
6674f0a8ff | |||
f704851419 | |||
0d5e1ee872 | |||
5cb81c753d | |||
b0b0564df9 | |||
195dc2a8ae | |||
4982b13f64 | |||
63a93f6ec2 | |||
7b8ec18e76 | |||
67faef0117 | |||
0b9f0af3c7 | |||
880d54a4f0 | |||
1507758ad1 | |||
e883c5aa6e | |||
afc85e0d2e | |||
a40dcf3f17 | |||
4b82e80d7a | |||
246dea8a44 | |||
7a98764a5b | |||
dc946f5b35 | |||
0232893611 | |||
5995f84822 | |||
1ff00895b1 | |||
83641b3789 | |||
9b356076c5 | |||
6c96521c7d | |||
35707c3797 | |||
e31e703afd | |||
3a8be9eef7 | |||
e2b30ec087 | |||
495e10f3a1 | |||
11ca6bd517 | |||
a265da09fb | |||
1b4d1be9ee | |||
32f2436380 | |||
7255c4f8db | |||
4e215db42a | |||
a1ad641076 | |||
daf56b0cc7 | |||
5859073cb8 | |||
ff5207ba77 | |||
324b4a89cc | |||
9f60caf9c1 | |||
0865f2a660 | |||
b1c72c9d94 | |||
5e70c11b54 | |||
46ada5a8b9 | |||
0eac67259d | |||
9399a5f195 | |||
47aa287480 | |||
865b698bed | |||
14974e0ebe | |||
1ed7833c9f | |||
e8d0ad5e7c | |||
e2ca7f52db | |||
c97b9f9b8f | |||
ecf994b647 | |||
347d0942b1 | |||
ff0d42c8d5 | |||
a6673b0917 | |||
0c296bba30 | |||
57930aaa13 | |||
1a6895ca25 | |||
54241ecd42 | |||
e537d00173 | |||
a195408a11 | |||
54b7f42056 | |||
6128e86da2 | |||
fed9f473aa | |||
f6ff3c1b87 | |||
afd3218358 | |||
ed6da0ba1e | |||
46d7be865d | |||
596c6c1077 | |||
6c3014575f | |||
190ecc8fd8 | |||
0d2e03a5a9 | |||
991530f88b | |||
de31924be3 | |||
6b97807f51 | |||
35022775cd | |||
6fecb3c035 | |||
3fed8cebdf | |||
c81bc9fb98 | |||
99f09790f1 | |||
6745c9a0cb | |||
0651316da5 | |||
f48becc6dc | |||
85c58e9d5b | |||
c9862977bf | |||
1a40299dcb | |||
8f9ff17bef | |||
9e9d26e604 | |||
b3d76d56e0 | |||
13424fdbcd | |||
2327247c29 | |||
85004370b7 | |||
8f6f8a34e1 | |||
f0f0aaaaa4 | |||
5fddde240f | |||
b212c71da6 | |||
1ea4a2776b | |||
41f1d5efed | |||
6e497ad04e | |||
34fb8c9c24 | |||
8386ae56d2 | |||
d38d3a8342 | |||
ce364e5e87 | |||
c482d6cc74 | |||
2cb96cb793 | |||
a32bea2697 | |||
7df402a20a | |||
650e0b26cc | |||
831976f3a2 | |||
e7e83820a9 | |||
8dd211d557 | |||
747d9a194d | |||
bfd8827073 | |||
ce92c7634e | |||
f97d9ab34f | |||
a2611fb013 | |||
3b320e0aeb | |||
f2d0e3d275 | |||
c1631c7172 | |||
259020ece0 | |||
589b17c596 | |||
ad4e526497 | |||
f005ea438c | |||
2615fd39ac | |||
eba9ce8475 | |||
a4f01c3f23 | |||
c2342834dd | |||
be212fd8b1 | |||
ee817ea8bb | |||
6c6f0a0068 | |||
5862a8a5ac | |||
a966ea3a58 | |||
eed418ea33 | |||
9a037279c8 | |||
727e1f2fd9 | |||
5afdef463e | |||
1dd835d698 | |||
400b37a96a | |||
23c140fd99 | |||
894f6f7ee1 | |||
b9e6d552f8 | |||
828a8fc0b5 | |||
45eaef2663 | |||
ed676151f1 | |||
45da2f0b32 | |||
6c23532f08 | |||
bc8984aac3 | |||
020fe21546 | |||
9957a83746 | |||
72bca0765a | |||
ba4f9ed7ae | |||
eb2d377ffb | |||
8303bb04d3 | |||
d23bf0a144 | |||
a6446e67bc | |||
529b879c08 | |||
2893cd7ce3 | |||
0634510b92 | |||
858545c0c8 | |||
120fb95541 | |||
665e84d183 | |||
13d9885da4 | |||
e230a9464e | |||
342af18b1f | |||
be9bd941c8 | |||
0f6be6740b | |||
9054736e0e | |||
c6d946136e | |||
32400c8d09 | |||
587c9aad14 | |||
c624a32ef6 | |||
3005a63938 | |||
f470e9a9cd | |||
e3971a5e0f | |||
2ed8667f18 | |||
765d532f82 | |||
ca05385513 | |||
5328610ff1 | |||
bc1bb3509f | |||
375db69e3a | |||
771fffe329 | |||
4611f05051 | |||
e657e26886 | |||
3ffcc47374 | |||
102f2f261b | |||
24d8abf820 | |||
449faea7d3 | |||
1b5e230d45 | |||
81a89ed6aa | |||
ca2074de36 | |||
ee98340a03 | |||
3d0d91fa5c | |||
38171dba06 | |||
4ba57ccc85 | |||
c3bddee814 | |||
b7bc50bc4f | |||
19627a959a | |||
429e4b2a77 | |||
6e5de7bd6b | |||
c6daa4acc9 | |||
ab01d0c73d | |||
0ef42b2df7 | |||
f6e2bfa683 | |||
5c8acdd666 | |||
e996d470f9 | |||
4c36a752cb | |||
e2e29492e6 | |||
5f637992b1 | |||
91d092a27a | |||
23cbfde312 | |||
cce25b2a1c | |||
f24058d2e8 | |||
4c941997b4 | |||
37f1790028 | |||
91066292ae | |||
1ffe85f083 | |||
2049020b92 | |||
7a6abdfd0c | |||
ff4cb32bc3 | |||
1857482617 | |||
2feef8b043 | |||
3eddfbf8a9 | |||
a662a9a619 | |||
1a656d60e4 | |||
e235402fb8 | |||
6ca9f1946b | |||
df671775ba | |||
3ba83f6407 | |||
ffa4225827 | |||
cde6bc107a | |||
15de8dc4a6 | |||
94fe58d020 | |||
e8634a2d61 | |||
67b0abde4b | |||
d713167ec4 | |||
45888c9a25 | |||
d02206ba09 | |||
ad9186c13b | |||
4e0dc15dfd | |||
a75d272f4a | |||
15c3383249 | |||
c556fcd8c3 | |||
b4bfe5e3b9 | |||
29d4d88259 | |||
7bd5f29a79 | |||
a72f5029dc | |||
81e58a92f2 | |||
c3b4806e85 | |||
dffc1833cb | |||
31538faab1 | |||
1866d366fb | |||
dcf7940b3d | |||
1874e11fba | |||
302ce75ce6 | |||
178c25710b | |||
62cd7cc728 | |||
20f8aac768 | |||
5806b25fd1 | |||
4110434e33 | |||
8c103be5c0 | |||
9ff52fcdb4 | |||
e7f01f4e55 | |||
04a85db303 | |||
61ad141830 | |||
f38b29256b | |||
121070822f | |||
96f65be9c2 | |||
78c40976c3 | |||
8eacfa6717 | |||
aa978abfc7 | |||
80f2b487f0 | |||
a0f8b27841 | |||
b7c0e4ea92 | |||
d89fe933f3 | |||
794c231b0d | |||
6ffba7d472 | |||
c330346c31 | |||
eda26e3c93 | |||
fa4da6e9d7 | |||
6d3313bd3f | |||
ea210320c6 | |||
bdc4c8f9df | |||
8c1d716632 | |||
ca27b26c6b | |||
600b2a61fe | |||
2f61c061b7 | |||
44077a4f2f | |||
ba4ca96253 | |||
a48a962653 | |||
4c6f0969c1 | |||
ccac725b7f | |||
41ed68eb44 | |||
3d9dd08208 | |||
83d59dfc54 | |||
ce11e4173f | |||
f15ba1d3dc | |||
c0a2b677f0 | |||
f8f895df4f | |||
de3d6fd5ba | |||
4072a51a5b | |||
5f3c50e690 | |||
6ca7076fe5 | |||
dd320d049f | |||
a8e1060eee | |||
8210e9ecd9 | |||
59503c775e | |||
2f9987a28a | |||
cbc422b817 | |||
c7f1aecd61 | |||
f2f71e2cbf | |||
a1d3205011 | |||
b01b37d86b | |||
e63462cd86 | |||
4136853e76 | |||
c58c8300ac | |||
89de3738c0 | |||
6a5449b8cb | |||
b2c78ca7c0 | |||
fa810ff54d | |||
de900dec2c | |||
9565ae4cda | |||
b8a27eadca | |||
a4d79d12dd | |||
8e8d74c5ad | |||
1f380b0264 | |||
58605fd278 | |||
d726465b67 | |||
4fe98ef560 | |||
ea7ab508bc | |||
f2a04ff1ff | |||
c8531d3870 | |||
ff2600a1fc | |||
a4f0744a6e | |||
71fbf37f69 | |||
a219b4f7d9 | |||
00ad1dd0ce | |||
2144816e0b | |||
80934f3e3b | |||
05d99120cd | |||
57879291cc | |||
fbddf051c8 | |||
ebd24e6181 | |||
bbc61d5743 | |||
ab06837628 | |||
2a8498210c | |||
db0642eeab | |||
a96ff8eb63 | |||
94140a0aa9 | |||
09778c7c51 | |||
5dd3355bd8 | |||
51cf2d5ec9 | |||
15a1fb1e5b | |||
e360fa0097 | |||
827a7da443 | |||
1a07b4a73a | |||
beedc24839 | |||
b9ebde22e5 | |||
cbf021c7a8 | |||
5ee91048e2 | |||
173b8833ce | |||
b475c8391a | |||
5a636d1ebe | |||
97b715881b | |||
b0cc9cf582 | |||
5a96e82f4d | |||
9b4b18e1a4 | |||
e107a9aa86 | |||
aece05b2e8 | |||
eb39e0f2c4 | |||
bfa2d2830d | |||
0c461bb5d8 | |||
9ff5dc6373 | |||
ac7950f4c4 | |||
93d4112bc3 | |||
5ba11b1c40 | |||
673470540d | |||
1a9548c0f0 | |||
50f565895f | |||
296d2e6c74 | |||
d402df42e2 | |||
eb4a29edc6 | |||
ff682d6b5e |
19
.editorconfig
Normal file
19
.editorconfig
Normal 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
|
4
.gitignore
vendored
4
.gitignore
vendored
@ -75,7 +75,11 @@ tools/python-fido2/*
|
||||
site/
|
||||
_site/
|
||||
venv/
|
||||
env2/
|
||||
env3/
|
||||
.project
|
||||
.tags*
|
||||
targets/*/docs/
|
||||
main
|
||||
|
||||
builds/*
|
||||
|
8
.gitmodules
vendored
8
.gitmodules
vendored
@ -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
|
||||
|
11
.travis.yml
11
.travis.yml
@ -1,4 +1,4 @@
|
||||
dist: trusty
|
||||
dist: xenial
|
||||
language: c
|
||||
compiler: gcc
|
||||
addons:
|
||||
@ -7,6 +7,13 @@ addons:
|
||||
- ubuntu-toolchain-r-test
|
||||
packages:
|
||||
- gcc-7
|
||||
- cppcheck
|
||||
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
|
||||
- sudo apt-get install -y python3-venv
|
||||
script:
|
||||
- export CC=gcc-7
|
||||
- make test
|
||||
- pyenv shell 3.6.7
|
||||
- make travis
|
||||
|
1
99-solo.rules
Symbolic link
1
99-solo.rules
Symbolic link
@ -0,0 +1 @@
|
||||
udev/70-solokeys-access.rules
|
1
ALPHA_VERSION
Normal file
1
ALPHA_VERSION
Normal file
@ -0,0 +1 @@
|
||||
2.0.0
|
27
CHANGELOG.md
Normal file
27
CHANGELOG.md
Normal file
@ -0,0 +1,27 @@
|
||||
# Changelog
|
||||
All notable changes to this project will be documented in this file.
|
||||
|
||||
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
|
||||
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
||||
|
||||
## [Unreleased]
|
||||
|
||||
## [1.1.0] - 2019-02-17
|
||||
### Added
|
||||
- Code cleanup
|
||||
- Buffer over-read bug fix
|
||||
- U2F counter endianness bug fix
|
||||
- More testing
|
||||
- Extension interface to U2F and FIDO2
|
||||
- Read firmware version
|
||||
- Read RNG bytes
|
||||
|
||||
## [1.1.1] - 2019-03-01
|
||||
|
||||
- This version fixes an incorrect error code returned in U2F.
|
||||
|
||||
## [2.0.0] - 2019-03-01
|
||||
|
||||
- Merge of NFC functionality branch
|
||||
- Bug fix with compiled USB name being too long causing buffer overrun
|
||||
- Change upper byte of counter from `0xff` to `0x7f` to fix issues with some websites.
|
33
Dockerfile
Normal file
33
Dockerfile
Normal file
@ -0,0 +1,33 @@
|
||||
FROM debian:stretch-slim
|
||||
MAINTAINER SoloKeys <hello@solokeys.com>
|
||||
|
||||
RUN apt-get update -qq
|
||||
RUN apt-get install -qq bzip2 git make wget >/dev/null
|
||||
|
||||
# 1. ARM GCC: for compilation
|
||||
RUN wget -q -O gcc.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
|
||||
# from website
|
||||
RUN echo "f55f90d483ddb3bcf4dae5882c2094cd gcc.tar.bz2" > gcc.md5
|
||||
RUN md5sum -c gcc.md5
|
||||
# self-generated
|
||||
RUN echo "fb31fbdfe08406ece43eef5df623c0b2deb8b53e405e2c878300f7a1f303ee52 gcc.tar.bz2" > gcc.sha256
|
||||
RUN sha256sum -c gcc.sha256
|
||||
RUN tar -C /opt -xf gcc.tar.bz2
|
||||
|
||||
# 2. Python3.7: for solo-python (merging etc.)
|
||||
RUN wget -q -O miniconda.sh https://repo.anaconda.com/miniconda/Miniconda3-4.5.12-Linux-x86_64.sh
|
||||
# from website
|
||||
RUN echo "866ae9dff53ad0874e1d1a60b1ad1ef8 miniconda.sh" > miniconda.md5
|
||||
RUN md5sum -c miniconda.md5
|
||||
# self-generated
|
||||
RUN echo "e5e5b4cd2a918e0e96b395534222773f7241dc59d776db1b9f7fedfcb489157a miniconda.sh" > miniconda.sha256
|
||||
RUN sha256sum -c miniconda.sha256
|
||||
|
||||
RUN bash ./miniconda.sh -b -p /opt/conda
|
||||
RUN ln -s /opt/conda/bin/python /usr/local/bin/python3
|
||||
RUN ln -s /opt/conda/bin/python /usr/local/bin/python
|
||||
RUN ln -s /opt/conda/bin/pip /usr/local/bin/pip3
|
||||
RUN ln -s /opt/conda/bin/pip /usr/local/bin/pip
|
||||
|
||||
# 3. Source code
|
||||
RUN git clone --recurse-submodules https://github.com/solokeys/solo /solo --config core.autocrlf=input
|
20
LICENSE
20
LICENSE
@ -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
201
LICENSE-APACHE
Normal 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
23
LICENSE-MIT
Normal 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.
|
132
Makefile
132
Makefile
@ -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:=$(shell git describe --abbrev=0 )
|
||||
VERSION_FULL:=$(shell git describe)
|
||||
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)
|
||||
|
||||
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\"
|
||||
|
||||
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,74 @@ tinycbor/Makefile crypto/tiny-AES-c/aes.c:
|
||||
.PHONY: cbor
|
||||
cbor: $(LIBCBOR)
|
||||
|
||||
$(LIBCBOR): tinycbor/Makefile
|
||||
$(LIBCBOR):
|
||||
cd tinycbor/ && $(MAKE) clean && $(MAKE) -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)"
|
||||
$(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
|
||||
DOCKER_IMAGE := "solokeys/solo-firmware:local"
|
||||
SOLO_VERSIONISH := "master"
|
||||
docker-build:
|
||||
docker build -t $(DOCKER_IMAGE) .
|
||||
docker run --rm -v "$(CURDIR)/builds:/builds" \
|
||||
-v "$(CURDIR)/in-docker-build.sh:/in-docker-build.sh" \
|
||||
$(DOCKER_IMAGE) "./in-docker-build.sh" $(SOLO_VERSIONISH)
|
||||
uncached-docker-build:
|
||||
docker build --no-cache -t $(DOCKER_IMAGE) .
|
||||
docker run --rm -v "$(CURDIR)/builds:/builds" \
|
||||
-v "$(CURDIR)/in-docker-build.sh:/in-docker-build.sh" \
|
||||
$(DOCKER_IMAGE) "./in-docker-build.sh" $(SOLO_VERSIONISH)
|
||||
|
||||
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
|
||||
|
||||
travis:
|
||||
$(MAKE) test VENV=". ../../venv/bin/activate;"
|
||||
$(MAKE) black
|
||||
|
185
README.md
185
README.md
@ -1,145 +1,130 @@
|
||||

|
||||
[](https://solokeys.com/kickstarter)
|
||||
[](https://travis-ci.com/SoloKeysSec/solo)
|
||||
[](https://discourse.solokeys.com)
|
||||
[](https://github.com/solokeys/solo/blob/master/LICENSE)
|
||||
[](https://travis-ci.com/solokeys/solo)
|
||||
[](https://discourse.solokeys.com)
|
||||
[](https://keybase.io/team/solokeys.public)
|
||||
[](https://app.fossa.io/projects/git%2Bgithub.com%2Fsolokeys%2Fsolo?ref=badge_shield)
|
||||
|
||||
[](https://github.com/solokeys/solo/releases)
|
||||
[](https://github.com/solokeys/solo/commits/master)
|
||||
[](https://github.com/solokeys/solo/commits/master)
|
||||
[](https://github.com/solokeys/solo/commits/master)
|
||||
[](https://github.com/solokeys/solo/graphs/contributors)
|
||||
|
||||
|
||||
# Solo
|
||||
|
||||
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 is an open source security key, and you can get one at [solokeys.com](https://solokeys.com).
|
||||
|
||||
> 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>.
|
||||
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.
|
||||
|
||||

|
||||

|
||||
<img src="https://solokeys.com/images/photos/hero-on-white-cropped.png" width="600">
|
||||
|
||||
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.
|
||||
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.
|
||||
|
||||
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.
|
||||
|
||||
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 only support Python3.
|
||||
|
||||
```bash
|
||||
git clone --recurse-submodules https://github.com/SoloKeysSec/solo
|
||||
cd solo/
|
||||
git clone --recurse-submodules https://github.com/solokeys/solo
|
||||
cd solo
|
||||
|
||||
git submodules init
|
||||
git submodules update
|
||||
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
|
||||
```
|
||||
|
||||
Alternatively, run `make docker-build` and use the firmware generated in `/tmp`.
|
||||
|
||||
If you forgot the `--recurse-submodules` when cloning, simply `git submodule update --init --recursive`.
|
||||
|
||||
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.
|
||||
|
||||
# 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.
|
||||
|
||||
```
|
||||
./venv/bin/python python-fido2/examples/credential.py
|
||||
In another shell, you can run client software, for example our tests:
|
||||
```bash
|
||||
python tools/ctap_test.py sim fido2
|
||||
```
|
||||
|
||||
Run the FIDO2 tests.
|
||||
You can find more details in our [documentation](https://docs.solokeys.io/solo/), including how to build on the the NUCLEO-L432KC development board.
|
||||
|
||||
```
|
||||
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.
|
||||
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.
|
||||
|
||||
Contributors are 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.
|
||||
|
||||
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 under the terms of either the Apache 2.0 license or MIT license.
|
||||
|
||||
|
||||
[](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).
|
||||
|
1
STABLE_VERSION
Normal file
1
STABLE_VERSION
Normal file
@ -0,0 +1 @@
|
||||
2.0.0
|
0
builds/.gitkeep
Normal file
0
builds/.gitkeep
Normal file
1
crypto/cifra
Submodule
1
crypto/cifra
Submodule
Submodule crypto/cifra added at d04dd31860
@ -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...
|
@ -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)
|
@ -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!
|
||||
|
@ -1 +0,0 @@
|
||||
../README.md
|
Binary file not shown.
183
docs/solo/building.md
Normal file
183
docs/solo/building.md
Normal file
@ -0,0 +1,183 @@
|
||||
To build, develop and debug the firmware for the STM32L432. This will work
|
||||
for Solo Hacker, the Nucleo development board, or you 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 manage 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`.
|
||||
|
||||
To program your build, you'll need one of the following programs.
|
||||
|
||||
- [openocd](http://openocd.org)
|
||||
- [stlink](https://github.com/texane/stlink)
|
||||
- [STM32CubeProg](https://www.st.com/en/development-tools/stm32cubeprog.html)
|
||||
|
||||
# Compilation
|
||||
|
||||
Enter the `stm32l4xx` target directory.
|
||||
|
||||
```
|
||||
cd targets/stm32l432
|
||||
```
|
||||
|
||||
Now build Solo.
|
||||
|
||||
```
|
||||
make build-hacker
|
||||
```
|
||||
|
||||
The `build-hacker` recipe does a few things. 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 build-hacker DEBUG=1
|
||||
```
|
||||
|
||||
If you use `DEBUG=2`, that means Solo will not boot until something starts reading
|
||||
it's debug messages. So it basically it 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 Solo release
|
||||
|
||||
If you want to build a release of Solo, we recommend trying a Hacker build first
|
||||
just to make sure that it's working. Otherwise it may not be as easy or possible to
|
||||
fix any mistakes.
|
||||
|
||||
If you're ready to program a full release, run this recipe to build.
|
||||
|
||||
```
|
||||
make build-release-locked
|
||||
```
|
||||
|
||||
Programming `all.hex` will cause the device to permanently lock itself.
|
||||
|
||||
|
||||
# Programming
|
||||
|
||||
It's recommended to test a debug/hacker build first to make sure Solo is working as expected.
|
||||
Then you can switch to a locked down build, which cannot be reprogrammed as easily (or not at all!).
|
||||
|
||||
We recommend using our `solo` tool to manage programming. It is cross platform. First you must
|
||||
install the prerequisites:
|
||||
|
||||
```
|
||||
pip3 install -r tools/requirements.txt
|
||||
```
|
||||
|
||||
If you're on Windows, you must also install [libusb](https://sourceforge.net/projects/libusb-win32/files/libusb-win32-releases/1.2.6.0/).
|
||||
|
||||
## Pre-programmed Solo Hacker
|
||||
|
||||
If your Solo device is already programmed (it flashes green when powered), we recommend
|
||||
programming it using the Solo bootloader.
|
||||
|
||||
```
|
||||
solo program aux enter-bootloader
|
||||
solo program bootloader solo.hex
|
||||
```
|
||||
|
||||
Make sure to program `solo.hex` and not `all.hex`. Nothing bad would happen, but you'd
|
||||
see errors.
|
||||
|
||||
If something bad happens, you can always boot the Solo bootloader by doing the following.
|
||||
|
||||
1. Unplug device.
|
||||
2. Hold down button.
|
||||
3. Plug in device while holding down button.
|
||||
4. Wait about 2 seconds for flashing yellow light. Release button.
|
||||
|
||||
If you hold the button for an additional 5 seconds, it will boot to the ST DFU (device firmware update).
|
||||
Don't use the ST DFU unless you know what you're doing.
|
||||
|
||||
## ST USB DFU
|
||||
|
||||
If your Solo has never been programmed, it will boot the ST USB DFU. The LED is turned
|
||||
off and it enumerates as "STM BOOTLOADER".
|
||||
|
||||
You can program it by running the following.
|
||||
|
||||
```
|
||||
solo program aux enter-bootloader
|
||||
solo program aux enter-dfu
|
||||
# powercycle key
|
||||
solo program dfu all.hex
|
||||
```
|
||||
|
||||
Make sure to program `all.hex`, as this contains both the bootloader and the Solo application.
|
||||
|
||||
If all goes well, you should see a slow-flashing green light.
|
||||
|
||||
## Solo Hacker vs Solo
|
||||
|
||||
A Solo hacker device doesn't need to be in bootloader mode to be programmed, it will automatically switch.
|
||||
|
||||
Solo (locked) needs the button to be held down when plugged in to boot to the bootloader.
|
||||
|
||||
A locked Solo will only accept signed updates.
|
||||
|
||||
## Signed updates
|
||||
|
||||
If this is not a device with a hacker build, you can only program signed updates.
|
||||
|
||||
```
|
||||
solo program bootloader /path/to/firmware.json
|
||||
```
|
||||
|
||||
If you've provisioned the Solo bootloader with your own secp256r1 public key, you can sign your
|
||||
firmware by running the following command.
|
||||
|
||||
```
|
||||
solo sign /path/to/signing-key.pem /path/to/solo.hex /output-path/to/firmware.json
|
||||
```
|
||||
|
||||
If your Solo isn't locked, you can always reprogram it using a debugger connected directly
|
||||
to the token.
|
||||
|
||||
# Permanently locking the device
|
||||
|
||||
If you plan to be using your Solo for real, you should lock it permanently. This prevents
|
||||
someone from connecting a debugger to your token and stealing credentials.
|
||||
|
||||
To do this, build the locked release firmware.
|
||||
```
|
||||
make build-release-locked
|
||||
```
|
||||
|
||||
Now when you program `all.hex`, the device will lock itself when it first boots. You can only update it
|
||||
with signed updates.
|
||||
|
||||
If you'd like to also permanently disable signed updates, plug in your programmed Solo and run the following:
|
||||
|
||||
```
|
||||
# WARNING: No more signed updates.
|
||||
solo program disable-bootloader
|
||||
```
|
15
docs/solo/contributing.md
Normal file
15
docs/solo/contributing.md
Normal 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)
|
@ -6,6 +6,6 @@ To host or develop locally:
|
||||
pip install mkdocs mkdocs-material
|
||||
```
|
||||
|
||||
`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.
|
@ -15,6 +15,8 @@ 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
|
||||
@ -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.
|
BIN
docs/solo/images/favicon.ico
Normal file
BIN
docs/solo/images/favicon.ico
Normal file
Binary file not shown.
After Width: | Height: | Size: 15 KiB |
Before Width: | Height: | Size: 3.9 KiB After Width: | Height: | Size: 3.9 KiB |
4
docs/solo/index.md
Normal file
4
docs/solo/index.md
Normal file
@ -0,0 +1,4 @@
|
||||
Welcome to the technical documentation for [solokeys/solo](https://github.com/solokeys/solo).
|
||||
|
||||
For now, you can read the repository `README.md`, more documentation to come!
|
||||
|
12
docs/solo/metadata-statements.md
Normal file
12
docs/solo/metadata-statements.md
Normal 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!}
|
||||
```
|
1
docs/solo/repo-readme.md
Symbolic link
1
docs/solo/repo-readme.md
Symbolic link
@ -0,0 +1 @@
|
||||
../../README.md
|
@ -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.
|
@ -1,18 +1,31 @@
|
||||
# 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. (Under Fedora, your key may work without such a rule.)
|
||||
|
||||
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, for instance the following rule should cover normal access (it has to be on one line):
|
||||
|
||||
```
|
||||
# U2F Zero
|
||||
KERNEL=="hidraw*", SUBSYSTEM=="hidraw", ATTRS{idVendor}=="10c4", ATTRS{idProduct}=="8acf", TAG+="uaccess"
|
||||
SUBSYSTEM=="hidraw", ATTRS{idVendor}=="0483", ATTRS{idProduct}=="a2ca", TAG+="uaccess", MODE="0660", GROUP="plugdev"
|
||||
```
|
||||
|
||||
Then run
|
||||
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
|
||||
```
|
||||
|
||||
A simple way to setup both the udev rule and the udevadm reload is:
|
||||
|
||||
```
|
||||
git clone git@github.com:solokeys/solo.git
|
||||
cd solo/udev
|
||||
make setup
|
||||
```
|
||||
|
||||
We are working on getting user access to Solo keys enabled automatically in common Linux distributions: <https://github.com/solokeys/solo/issues/144>.
|
||||
|
||||
|
||||
|
||||
# How do udev rules work and why are they needed
|
||||
|
||||
In Linux, `udev` (part of `systemd`, read `man 7 udev`) handles "hot-pluggable" devices, of which Solo and U2F Zero are examples. In particular, it creates nodes in the `/dev` filesystem (in Linux, everything is a file), which allow accessing the device.
|
||||
@ -30,13 +43,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 +60,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 +73,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
|
30
fido2/apdu.h
Normal file
30
fido2/apdu.h
Normal file
@ -0,0 +1,30 @@
|
||||
#ifndef _APDU_H_
|
||||
#define _APDU_H_
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
typedef struct
|
||||
{
|
||||
uint8_t cla;
|
||||
uint8_t ins;
|
||||
uint8_t p1;
|
||||
uint8_t p2;
|
||||
uint8_t lc;
|
||||
} __attribute__((packed)) APDU_HEADER;
|
||||
|
||||
#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_INS_SELECT 0xA4
|
||||
#define APDU_INS_READ_BINARY 0xB0
|
||||
|
||||
#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_INS_INVALID 0x6d00 // Instruction code not supported or invalid
|
||||
#define SW_INTERNAL_EXCEPTION 0x6f00
|
||||
|
||||
#endif //_APDU_H_
|
@ -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
|
||||
|
||||
|
@ -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
|
||||
@ -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);
|
||||
|
||||
}
|
||||
@ -257,7 +273,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 +282,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);
|
||||
}
|
||||
|
||||
|
@ -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,6 +19,10 @@ 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);
|
||||
|
452
fido2/ctap.c
452
fido2/ctap.c
@ -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>
|
||||
@ -34,12 +19,12 @@
|
||||
#include "util.h"
|
||||
#include "log.h"
|
||||
#include "device.h"
|
||||
#include "app.h"
|
||||
#include APP_CONFIG
|
||||
#include "wallet.h"
|
||||
#include "extensions.h"
|
||||
|
||||
#include "device.h"
|
||||
|
||||
#define PIN_TOKEN_SIZE 16
|
||||
uint8_t PIN_TOKEN[PIN_TOKEN_SIZE];
|
||||
uint8_t KEY_AGREEMENT_PUB[64];
|
||||
static uint8_t KEY_AGREEMENT_PRIV[32];
|
||||
@ -48,6 +33,8 @@ static int8_t PIN_BOOT_ATTEMPTS_LEFT = PIN_BOOT_ATTEMPTS;
|
||||
|
||||
AuthenticatorState STATE;
|
||||
|
||||
static void ctap_reset_key_agreement();
|
||||
|
||||
static struct {
|
||||
CTAP_authDataHeader authData;
|
||||
uint8_t clientDataHash[CLIENT_DATA_HASH_SIZE];
|
||||
@ -81,6 +68,8 @@ uint8_t verify_pin_auth(uint8_t * pinAuth, uint8_t * clientDataHash)
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
uint8_t ctap_get_info(CborEncoder * encoder)
|
||||
{
|
||||
int ret;
|
||||
@ -89,16 +78,14 @@ uint8_t ctap_get_info(CborEncoder * encoder)
|
||||
CborEncoder options;
|
||||
CborEncoder pins;
|
||||
|
||||
const int number_of_versions = 2;
|
||||
|
||||
ret = cbor_encoder_create_map(encoder, &map, 5);
|
||||
ret = cbor_encoder_create_map(encoder, &map, 6);
|
||||
check_ret(ret);
|
||||
{
|
||||
|
||||
ret = cbor_encode_uint(&map, RESP_versions); // versions key
|
||||
check_ret(ret);
|
||||
{
|
||||
ret = cbor_encoder_create_array(&map, &array, number_of_versions);
|
||||
ret = cbor_encoder_create_array(&map, &array, 2);
|
||||
check_ret(ret);
|
||||
{
|
||||
ret = cbor_encode_text_stringz(&array, "U2F_V2");
|
||||
@ -110,6 +97,19 @@ uint8_t ctap_get_info(CborEncoder * encoder)
|
||||
check_ret(ret);
|
||||
}
|
||||
|
||||
ret = cbor_encode_uint(&map, RESP_extensions);
|
||||
check_ret(ret);
|
||||
{
|
||||
ret = cbor_encoder_create_array(&map, &array, 1);
|
||||
check_ret(ret);
|
||||
{
|
||||
ret = cbor_encode_text_stringz(&array, "hmac-secret");
|
||||
check_ret(ret);
|
||||
}
|
||||
ret = cbor_encoder_close_container(&map, &array);
|
||||
check_ret(ret);
|
||||
}
|
||||
|
||||
ret = cbor_encode_uint(&map, RESP_aaguid);
|
||||
check_ret(ret);
|
||||
{
|
||||
@ -323,18 +323,123 @@ static int is_matching_rk(CTAP_residentKey * rk, CTAP_residentKey * rk2)
|
||||
(rk->user.id_size == rk2->user.id_size);
|
||||
}
|
||||
|
||||
static int ctap_make_extensions(CTAP_extensions * ext, uint8_t * ext_encoder_buf, unsigned int * ext_encoder_buf_size)
|
||||
{
|
||||
CborEncoder extensions;
|
||||
int ret;
|
||||
uint8_t output[64];
|
||||
uint8_t shared_secret[32];
|
||||
uint8_t hmac[32];
|
||||
uint8_t credRandom[32];
|
||||
|
||||
static int ctap_make_auth_data(struct rpId * rp, CborEncoder * map, uint8_t * auth_data_buf, int len, CTAP_userEntity * user, uint8_t credtype, int32_t algtype, int32_t * sz, int store)
|
||||
if (ext->hmac_secret_present == EXT_HMAC_SECRET_PARSED)
|
||||
{
|
||||
printf1(TAG_CTAP, "Processing hmac-secret..\r\n");
|
||||
|
||||
crypto_ecc256_shared_secret((uint8_t*) &ext->hmac_secret.keyAgreement.pubkey,
|
||||
KEY_AGREEMENT_PRIV,
|
||||
shared_secret);
|
||||
crypto_sha256_init();
|
||||
crypto_sha256_update(shared_secret, 32);
|
||||
crypto_sha256_final(shared_secret);
|
||||
|
||||
crypto_sha256_hmac_init(shared_secret, 32, hmac);
|
||||
crypto_sha256_update(ext->hmac_secret.saltEnc, ext->hmac_secret.saltLen);
|
||||
crypto_sha256_hmac_final(shared_secret, 32, hmac);
|
||||
|
||||
if (memcmp(ext->hmac_secret.saltAuth, hmac, 16) == 0)
|
||||
{
|
||||
printf1(TAG_CTAP, "saltAuth is valid\r\n");
|
||||
}
|
||||
else
|
||||
{
|
||||
printf1(TAG_CTAP, "saltAuth is invalid\r\n");
|
||||
return CTAP2_ERR_EXTENSION_FIRST;
|
||||
}
|
||||
|
||||
// Generate credRandom
|
||||
crypto_sha256_hmac_init(CRYPTO_TRANSPORT_KEY, 0, credRandom);
|
||||
crypto_sha256_update((uint8_t*)&ext->hmac_secret.credential->id, sizeof(CredentialId));
|
||||
crypto_sha256_hmac_final(CRYPTO_TRANSPORT_KEY, 0, credRandom);
|
||||
|
||||
// Decrypt saltEnc
|
||||
crypto_aes256_init(shared_secret, NULL);
|
||||
crypto_aes256_decrypt(ext->hmac_secret.saltEnc, ext->hmac_secret.saltLen);
|
||||
|
||||
// Generate outputs
|
||||
crypto_sha256_hmac_init(credRandom, 32, output);
|
||||
crypto_sha256_update(ext->hmac_secret.saltEnc, 32);
|
||||
crypto_sha256_hmac_final(credRandom, 32, output);
|
||||
|
||||
if (ext->hmac_secret.saltLen == 64)
|
||||
{
|
||||
crypto_sha256_hmac_init(credRandom, 32, output + 32);
|
||||
crypto_sha256_update(ext->hmac_secret.saltEnc + 32, 32);
|
||||
crypto_sha256_hmac_final(credRandom, 32, output + 32);
|
||||
}
|
||||
|
||||
// Encrypt for final output
|
||||
crypto_aes256_init(shared_secret, NULL);
|
||||
crypto_aes256_encrypt(output, ext->hmac_secret.saltLen);
|
||||
|
||||
// output
|
||||
printf1(TAG_GREEN, "have %d bytes for Extenstions encoder\r\n",*ext_encoder_buf_size);
|
||||
cbor_encoder_init(&extensions, ext_encoder_buf, *ext_encoder_buf_size, 0);
|
||||
{
|
||||
CborEncoder hmac_secret_map;
|
||||
ret = cbor_encoder_create_map(&extensions, &hmac_secret_map, 1);
|
||||
check_ret(ret);
|
||||
{
|
||||
ret = cbor_encode_text_stringz(&hmac_secret_map, "hmac-secret");
|
||||
check_ret(ret);
|
||||
|
||||
ret = cbor_encode_byte_string(&hmac_secret_map, output, ext->hmac_secret.saltLen);
|
||||
check_ret(ret);
|
||||
}
|
||||
ret = cbor_encoder_close_container(&extensions, &hmac_secret_map);
|
||||
check_ret(ret);
|
||||
}
|
||||
*ext_encoder_buf_size = cbor_encoder_get_buffer_size(&extensions, ext_encoder_buf);
|
||||
}
|
||||
else if (ext->hmac_secret_present == EXT_HMAC_SECRET_REQUESTED)
|
||||
{
|
||||
cbor_encoder_init(&extensions, ext_encoder_buf, *ext_encoder_buf_size, 0);
|
||||
{
|
||||
CborEncoder hmac_secret_map;
|
||||
ret = cbor_encoder_create_map(&extensions, &hmac_secret_map, 1);
|
||||
check_ret(ret);
|
||||
{
|
||||
ret = cbor_encode_text_stringz(&hmac_secret_map, "hmac-secret");
|
||||
check_ret(ret);
|
||||
|
||||
ret = cbor_encode_boolean(&hmac_secret_map, 1);
|
||||
check_ret(ret);
|
||||
}
|
||||
ret = cbor_encoder_close_container(&extensions, &hmac_secret_map);
|
||||
check_ret(ret);
|
||||
}
|
||||
*ext_encoder_buf_size = cbor_encoder_get_buffer_size(&extensions, ext_encoder_buf);
|
||||
}
|
||||
else
|
||||
{
|
||||
*ext_encoder_buf_size = 0;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static int ctap_make_auth_data(struct rpId * rp, CborEncoder * map, uint8_t * auth_data_buf, uint32_t * len, CTAP_credInfo * credInfo)
|
||||
{
|
||||
CborEncoder cose_key;
|
||||
int auth_data_sz, ret;
|
||||
|
||||
unsigned int auth_data_sz = sizeof(CTAP_authDataHeader);
|
||||
uint32_t count;
|
||||
CTAP_residentKey rk, rk2;
|
||||
CTAP_authData * authData = (CTAP_authData *)auth_data_buf;
|
||||
|
||||
uint8_t * cose_key_buf = auth_data_buf + sizeof(CTAP_authData);
|
||||
|
||||
if((sizeof(CTAP_authDataHeader)) > len)
|
||||
if((sizeof(CTAP_authDataHeader)) > *len)
|
||||
{
|
||||
printf1(TAG_ERR,"assertion fail, auth_data_buf must be at least %d bytes\n", sizeof(CTAP_authData) - sizeof(CTAP_attestHeader));
|
||||
exit(1);
|
||||
@ -350,7 +455,12 @@ static int ctap_make_auth_data(struct rpId * rp, CborEncoder * map, uint8_t * au
|
||||
count = auth_data_update_count(&authData->head);
|
||||
|
||||
device_set_status(CTAPHID_STATUS_UPNEEDED);
|
||||
int but = ctap_user_presence_test();
|
||||
// if NFC - not need to click a button
|
||||
int but = 1;
|
||||
if(!device_is_nfc())
|
||||
{
|
||||
but = ctap_user_presence_test();
|
||||
}
|
||||
|
||||
if (!but)
|
||||
{
|
||||
@ -366,13 +476,12 @@ static int ctap_make_auth_data(struct rpId * rp, CborEncoder * map, uint8_t * au
|
||||
authData->head.flags |= (ctap_is_pin_set() << 2);
|
||||
|
||||
|
||||
|
||||
if (credtype != 0)
|
||||
if (credInfo != NULL)
|
||||
{
|
||||
// add attestedCredentialData
|
||||
authData->head.flags |= (1 << 6);//include attestation data
|
||||
|
||||
cbor_encoder_init(&cose_key, cose_key_buf, len - sizeof(CTAP_authData), 0);
|
||||
cbor_encoder_init(&cose_key, cose_key_buf, *len - sizeof(CTAP_authData), 0);
|
||||
|
||||
memmove(authData->attest.aaguid, CTAP_AAGUID, 16);
|
||||
authData->attest.credLenL = sizeof(CredentialId) & 0x00FF;
|
||||
@ -390,13 +499,13 @@ static int ctap_make_auth_data(struct rpId * rp, CborEncoder * map, uint8_t * au
|
||||
make_auth_tag(authData->head.rpIdHash, authData->attest.id.nonce, count, authData->attest.id.tag);
|
||||
|
||||
// resident key
|
||||
if (store)
|
||||
if (credInfo->rk)
|
||||
{
|
||||
memmove(&rk.id, &authData->attest.id, sizeof(CredentialId));
|
||||
memmove(&rk.user, user, sizeof(CTAP_userEntity));
|
||||
memmove(&rk.user, &credInfo->user, sizeof(CTAP_userEntity));
|
||||
|
||||
int index = STATE.rk_stored;
|
||||
int i;
|
||||
unsigned int index = STATE.rk_stored;
|
||||
unsigned int i;
|
||||
for (i = 0; i < index; i++)
|
||||
{
|
||||
ctap_load_rk(i, &rk2);
|
||||
@ -417,63 +526,63 @@ static int ctap_make_auth_data(struct rpId * rp, CborEncoder * map, uint8_t * au
|
||||
}
|
||||
done_rk:
|
||||
|
||||
// DELETE
|
||||
//crypto_aes256_init(CRYPTO_TRANSPORT_KEY, NULL);
|
||||
//crypto_aes256_encrypt((uint8_t*)&authData->attest.credential.user, CREDENTIAL_ENC_SIZE);
|
||||
printf1(TAG_GREEN, "MADE credId: "); dump_hex1(TAG_GREEN, (uint8_t*) &authData->attest.id, sizeof(CredentialId));
|
||||
|
||||
ctap_generate_cose_key(&cose_key, (uint8_t*)&authData->attest.id, sizeof(CredentialId), credtype, algtype);
|
||||
ctap_generate_cose_key(&cose_key, (uint8_t*)&authData->attest.id, sizeof(CredentialId), credInfo->publicKeyCredentialType, credInfo->COSEAlgorithmIdentifier);
|
||||
|
||||
auth_data_sz = sizeof(CTAP_authData) + cbor_encoder_get_buffer_size(&cose_key, cose_key_buf);
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
auth_data_sz = sizeof(CTAP_authDataHeader);
|
||||
}
|
||||
|
||||
{
|
||||
ret = cbor_encode_int(map,RESP_authData);
|
||||
check_ret(ret);
|
||||
ret = cbor_encode_byte_string(map, auth_data_buf, auth_data_sz);
|
||||
check_ret(ret);
|
||||
}
|
||||
|
||||
if (sz) *sz = auth_data_sz;
|
||||
|
||||
|
||||
|
||||
*len = auth_data_sz;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int ctap_encode_der_sig(uint8_t * sigbuf, uint8_t * sigder)
|
||||
/**
|
||||
*
|
||||
* @param in_sigbuf IN location to deposit signature (must be 64 bytes)
|
||||
* @param out_sigder OUT location to deposit der signature (must be 72 bytes)
|
||||
* @return length of der signature
|
||||
* // FIXME add tests for maximum and minimum length of the input and output
|
||||
*/
|
||||
int ctap_encode_der_sig(const uint8_t * const in_sigbuf, uint8_t * const out_sigder)
|
||||
{
|
||||
// Need to caress into dumb der format ..
|
||||
int i;
|
||||
int8_t lead_s = 0; // leading zeros
|
||||
int8_t lead_r = 0;
|
||||
uint8_t i;
|
||||
uint8_t lead_s = 0; // leading zeros
|
||||
uint8_t lead_r = 0;
|
||||
for (i=0; i < 32; i++)
|
||||
if (sigbuf[i] == 0) lead_r++;
|
||||
if (in_sigbuf[i] == 0) lead_r++;
|
||||
else break;
|
||||
|
||||
for (i=0; i < 32; i++)
|
||||
if (sigbuf[i+32] == 0) lead_s++;
|
||||
if (in_sigbuf[i+32] == 0) lead_s++;
|
||||
else break;
|
||||
|
||||
int8_t pad_s = ((sigbuf[32 + lead_s] & 0x80) == 0x80);
|
||||
int8_t pad_r = ((sigbuf[0 + lead_r] & 0x80) == 0x80);
|
||||
int8_t pad_s = ((in_sigbuf[32 + lead_s] & 0x80) == 0x80);
|
||||
int8_t pad_r = ((in_sigbuf[0 + lead_r] & 0x80) == 0x80);
|
||||
|
||||
sigder[0] = 0x30;
|
||||
sigder[1] = 0x44 + pad_s + pad_r - lead_s - lead_r;
|
||||
memset(out_sigder, 0, 72);
|
||||
out_sigder[0] = 0x30;
|
||||
out_sigder[1] = 0x44 + pad_s + pad_r - lead_s - lead_r;
|
||||
|
||||
sigder[2] = 0x02;
|
||||
sigder[3 + pad_r] = 0;
|
||||
sigder[3] = 0x20 + pad_r - lead_r;
|
||||
memmove(sigder + 4 + pad_r, sigbuf + lead_r, 32);
|
||||
// R ingredient
|
||||
out_sigder[2] = 0x02;
|
||||
out_sigder[3 + pad_r] = 0;
|
||||
out_sigder[3] = 0x20 + pad_r - lead_r;
|
||||
memmove(out_sigder + 4 + pad_r, in_sigbuf + lead_r, 32u - lead_r);
|
||||
|
||||
// S ingredient
|
||||
out_sigder[4 + 32 + pad_r - lead_r] = 0x02;
|
||||
out_sigder[5 + 32 + pad_r + pad_s - lead_r] = 0;
|
||||
out_sigder[5 + 32 + pad_r - lead_r] = 0x20 + pad_s - lead_s;
|
||||
memmove(out_sigder + 6 + 32 + pad_r + pad_s - lead_r, in_sigbuf + 32u + lead_s, 32u - lead_s);
|
||||
|
||||
sigder[4 + 32 + pad_r - lead_r] = 0x02;
|
||||
sigder[5 + 32 + pad_r + pad_s - lead_r] = 0;
|
||||
sigder[5 + 32 + pad_r - lead_r] = 0x20 + pad_s - lead_s;
|
||||
memmove(sigder + 6 + 32 + pad_r + pad_s - lead_r, sigbuf + 32 + lead_s, 32);
|
||||
//
|
||||
return 0x46 + pad_s + pad_r - lead_r - lead_s;
|
||||
}
|
||||
|
||||
@ -481,8 +590,8 @@ int ctap_encode_der_sig(uint8_t * sigbuf, uint8_t * sigder)
|
||||
// @data data to hash before signature
|
||||
// @clientDataHash for signature
|
||||
// @tmp buffer for hash. (can be same as data if data >= 32 bytes)
|
||||
// @sigbuf location to deposit signature (must be 64 bytes)
|
||||
// @sigder location to deposit der signature (must be 72 bytes)
|
||||
// @sigbuf OUT location to deposit signature (must be 64 bytes)
|
||||
// @sigder OUT location to deposit der signature (must be 72 bytes)
|
||||
// @return length of der signature
|
||||
int ctap_calculate_signature(uint8_t * data, int datalen, uint8_t * clientDataHash, uint8_t * hashbuf, uint8_t * sigbuf, uint8_t * sigder)
|
||||
{
|
||||
@ -554,13 +663,15 @@ int ctap_authenticate_credential(struct rpId * rp, CTAP_credentialDescriptor * d
|
||||
uint8_t ctap_make_credential(CborEncoder * encoder, uint8_t * request, int length)
|
||||
{
|
||||
CTAP_makeCredential MC;
|
||||
int ret, i;
|
||||
uint8_t auth_data_buf[300];
|
||||
int ret;
|
||||
unsigned int i;
|
||||
uint8_t auth_data_buf[310];
|
||||
CTAP_credentialDescriptor * excl_cred = (CTAP_credentialDescriptor *) auth_data_buf;
|
||||
uint8_t * sigbuf = auth_data_buf + 32;
|
||||
uint8_t * sigder = auth_data_buf + 32 + 64;
|
||||
|
||||
ret = ctap_parse_make_credential(&MC,encoder,request,length);
|
||||
|
||||
if (ret != 0)
|
||||
{
|
||||
printf2(TAG_ERR,"error, parse_make_credential failed\n");
|
||||
@ -615,19 +726,38 @@ uint8_t ctap_make_credential(CborEncoder * encoder, uint8_t * request, int lengt
|
||||
check_ret(ret);
|
||||
}
|
||||
|
||||
|
||||
CborEncoder map;
|
||||
ret = cbor_encoder_create_map(encoder, &map, 3);
|
||||
check_ret(ret);
|
||||
int32_t auth_data_sz;
|
||||
|
||||
ret = ctap_make_auth_data(&MC.rp, &map, auth_data_buf, sizeof(auth_data_buf),
|
||||
&MC.user, MC.publicKeyCredentialType, MC.COSEAlgorithmIdentifier, &auth_data_sz, MC.rk);
|
||||
uint32_t auth_data_sz = sizeof(auth_data_buf);
|
||||
|
||||
ret = ctap_make_auth_data(&MC.rp, &map, auth_data_buf, &auth_data_sz,
|
||||
&MC.credInfo);
|
||||
check_retr(ret);
|
||||
|
||||
{
|
||||
unsigned int ext_encoder_buf_size = sizeof(auth_data_buf) - auth_data_sz;
|
||||
uint8_t * ext_encoder_buf = auth_data_buf + auth_data_sz;
|
||||
|
||||
ret = ctap_make_extensions(&MC.extensions, ext_encoder_buf, &ext_encoder_buf_size);
|
||||
check_retr(ret);
|
||||
if (ext_encoder_buf_size)
|
||||
{
|
||||
((CTAP_authData *)auth_data_buf)->head.flags |= (1 << 7);
|
||||
auth_data_sz += ext_encoder_buf_size;
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
ret = cbor_encode_int(&map,RESP_authData);
|
||||
check_ret(ret);
|
||||
ret = cbor_encode_byte_string(&map, auth_data_buf, auth_data_sz);
|
||||
check_ret(ret);
|
||||
}
|
||||
|
||||
crypto_ecc256_load_attestation_key();
|
||||
int sigder_sz = ctap_calculate_signature(auth_data_buf, auth_data_sz, MC.clientDataHash, auth_data_buf, sigbuf, sigder);
|
||||
|
||||
printf1(TAG_MC,"der sig [%d]: ", sigder_sz); dump_hex1(TAG_MC, sigder, sigder_sz);
|
||||
|
||||
ret = ctap_add_attest_statement(&map, sigder, sigder_sz);
|
||||
@ -780,7 +910,18 @@ int ctap_filter_invalid_credentials(CTAP_getAssertion * GA)
|
||||
if (! ctap_authenticate_credential(&GA->rp, &GA->creds[i]))
|
||||
{
|
||||
printf1(TAG_GA, "CRED #%d is invalid\n", GA->creds[i].credential.id.count);
|
||||
GA->creds[i].credential.id.count = 0; // invalidate
|
||||
#ifdef ENABLE_U2F_EXTENSIONS
|
||||
if (is_extension_request((uint8_t*)&GA->creds[i].credential.id, sizeof(CredentialId)))
|
||||
{
|
||||
printf1(TAG_EXT, "CRED #%d is extension\n", GA->creds[i].credential.id.count);
|
||||
count++;
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
GA->creds[i].credential.id.count = 0; // invalidate
|
||||
}
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -807,7 +948,7 @@ int ctap_filter_invalid_credentials(CTAP_getAssertion * GA)
|
||||
printf1(TAG_GA, "RK %d is a rpId match!\r\n", i);
|
||||
if (count == ALLOW_LIST_MAX_SIZE-1)
|
||||
{
|
||||
printf2(TAG_ERR, "not enough ram allocated for matching RK's (%d)\r\n", count);
|
||||
printf2(TAG_ERR, "not enough ram allocated for matching RK's (%d). Skipping.\r\n", count);
|
||||
break;
|
||||
}
|
||||
GA->creds[count].type = PUB_KEY_CRED_PUB_KEY;
|
||||
@ -836,6 +977,7 @@ static void save_credential_list(CTAP_authDataHeader * head, uint8_t * clientDat
|
||||
memmove(getAssertionState.clientDataHash, clientDataHash, CLIENT_DATA_HASH_SIZE);
|
||||
memmove(&getAssertionState.authData, head, sizeof(CTAP_authDataHeader));
|
||||
memmove(getAssertionState.creds, creds, sizeof(CTAP_credentialDescriptor) * (count));
|
||||
|
||||
}
|
||||
getAssertionState.count = count;
|
||||
printf1(TAG_GA,"saved %d credentials\n",count);
|
||||
@ -860,6 +1002,7 @@ uint8_t ctap_end_get_assertion(CborEncoder * map, CTAP_credentialDescriptor * cr
|
||||
int ret;
|
||||
uint8_t sigbuf[64];
|
||||
uint8_t sigder[72];
|
||||
int sigder_sz;
|
||||
|
||||
if (add_user)
|
||||
{
|
||||
@ -873,7 +1016,16 @@ uint8_t ctap_end_get_assertion(CborEncoder * map, CTAP_credentialDescriptor * cr
|
||||
|
||||
crypto_ecc256_load_key((uint8_t*)&cred->credential.id, sizeof(CredentialId), NULL, 0);
|
||||
|
||||
int sigder_sz = ctap_calculate_signature(auth_data_buf, sizeof(CTAP_authDataHeader), clientDataHash, auth_data_buf, sigbuf, sigder);
|
||||
#ifdef ENABLE_U2F_EXTENSIONS
|
||||
if ( extend_fido2(&cred->credential.id, sigder) )
|
||||
{
|
||||
sigder_sz = 72;
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
sigder_sz = ctap_calculate_signature(auth_data_buf, sizeof(CTAP_authDataHeader), clientDataHash, auth_data_buf, sigbuf, sigder);
|
||||
}
|
||||
|
||||
{
|
||||
ret = cbor_encode_int(map, RESP_signature);
|
||||
@ -890,7 +1042,6 @@ uint8_t ctap_get_next_assertion(CborEncoder * encoder)
|
||||
CborEncoder map;
|
||||
CTAP_authDataHeader authData;
|
||||
memmove(&authData, &getAssertionState.authData, sizeof(CTAP_authDataHeader));
|
||||
// CTAP_authDataHeader * authData = &getAssertionState.authData;
|
||||
|
||||
CTAP_credentialDescriptor * cred = pop_credential();
|
||||
|
||||
@ -913,6 +1064,7 @@ uint8_t ctap_get_next_assertion(CborEncoder * encoder)
|
||||
ret = cbor_encoder_create_map(encoder, &map, 3);
|
||||
}
|
||||
|
||||
|
||||
check_ret(ret);
|
||||
printf1(TAG_RED, "RPID hash: "); dump_hex1(TAG_RED, authData.rpIdHash, 32);
|
||||
|
||||
@ -923,6 +1075,7 @@ uint8_t ctap_get_next_assertion(CborEncoder * encoder)
|
||||
check_ret(ret);
|
||||
}
|
||||
|
||||
|
||||
// if only one account for this RP, null out the user details
|
||||
if (!getAssertionState.user_verified)
|
||||
{
|
||||
@ -943,7 +1096,7 @@ uint8_t ctap_get_next_assertion(CborEncoder * encoder)
|
||||
uint8_t ctap_get_assertion(CborEncoder * encoder, uint8_t * request, int length)
|
||||
{
|
||||
CTAP_getAssertion GA;
|
||||
uint8_t auth_data_buf[sizeof(CTAP_authDataHeader)];
|
||||
uint8_t auth_data_buf[sizeof(CTAP_authDataHeader) + 80];
|
||||
int ret = ctap_parse_get_assertion(&GA,request,length);
|
||||
|
||||
if (ret != 0)
|
||||
@ -952,19 +1105,15 @@ uint8_t ctap_get_assertion(CborEncoder * encoder, uint8_t * request, int length)
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (ctap_is_pin_set() && GA.pinAuthPresent == 0)
|
||||
if (GA.pinAuthPresent)
|
||||
{
|
||||
printf2(TAG_ERR,"pinAuth is required\n");
|
||||
return CTAP2_ERR_PIN_REQUIRED;
|
||||
ret = verify_pin_auth(GA.pinAuth, GA.clientDataHash);
|
||||
check_retr(ret);
|
||||
getAssertionState.user_verified = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (ctap_is_pin_set() || (GA.pinAuthPresent))
|
||||
{
|
||||
ret = verify_pin_auth(GA.pinAuth, GA.clientDataHash);
|
||||
check_retr(ret);
|
||||
getAssertionState.user_verified = 1;
|
||||
}
|
||||
getAssertionState.user_verified = 0;
|
||||
}
|
||||
|
||||
if (!GA.rp.size || !GA.clientDataHashPresent)
|
||||
@ -989,34 +1138,15 @@ uint8_t ctap_get_assertion(CborEncoder * encoder, uint8_t * request, int length)
|
||||
map_size += 1;
|
||||
}
|
||||
|
||||
if (GA.extensions.hmac_secret_present == EXT_HMAC_SECRET_PARSED)
|
||||
{
|
||||
printf1(TAG_GA, "hmac-secret is present\r\n");
|
||||
}
|
||||
|
||||
ret = cbor_encoder_create_map(encoder, &map, map_size);
|
||||
check_ret(ret);
|
||||
|
||||
ret = ctap_make_auth_data(&GA.rp, &map, auth_data_buf, sizeof(auth_data_buf), NULL, 0,0,NULL, 0);
|
||||
check_retr(ret);
|
||||
|
||||
/*for (int j = 0; j < GA.credLen; j++)*/
|
||||
/*{*/
|
||||
/*printf1(TAG_GA,"CRED ID (# %d): ", GA.creds[j].credential.enc.count);*/
|
||||
/*dump_hex1(TAG_GA, (uint8_t*)&GA.creds[j].credential, sizeof(struct Credential));*/
|
||||
/*if (ctap_authenticate_credential(&GA.rp, &GA.creds[j])) // warning encryption will break this*/
|
||||
/*{*/
|
||||
/*printf1(TAG_GA," Authenticated.\n");*/
|
||||
/*}*/
|
||||
/*else*/
|
||||
/*{*/
|
||||
/*printf1(TAG_GA," NOT authentic.\n");*/
|
||||
/*}*/
|
||||
/*}*/
|
||||
|
||||
// Decrypt here
|
||||
|
||||
//
|
||||
if (validCredCount > 0)
|
||||
{
|
||||
save_credential_list((CTAP_authDataHeader*)auth_data_buf, GA.clientDataHash, GA.creds, validCredCount-1); // skip last one
|
||||
}
|
||||
else
|
||||
if (validCredCount == 0)
|
||||
{
|
||||
printf2(TAG_ERR,"Error, no authentic credential\n");
|
||||
return CTAP2_ERR_NO_CREDENTIALS;
|
||||
@ -1030,7 +1160,8 @@ uint8_t ctap_get_assertion(CborEncoder * encoder, uint8_t * request, int length)
|
||||
}
|
||||
|
||||
printf1(TAG_GA,"resulting order of creds:\n");
|
||||
for (int j = 0; j < GA.credLen; j++)
|
||||
int j;
|
||||
for (j = 0; j < GA.credLen; j++)
|
||||
{
|
||||
printf1(TAG_GA,"CRED ID (# %d)\n", GA.creds[j].credential.id.count);
|
||||
}
|
||||
@ -1045,6 +1176,50 @@ uint8_t ctap_get_assertion(CborEncoder * encoder, uint8_t * request, int length)
|
||||
|
||||
CTAP_credentialDescriptor * cred = &GA.creds[validCredCount - 1];
|
||||
|
||||
GA.extensions.hmac_secret.credential = &cred->credential;
|
||||
|
||||
#ifdef ENABLE_U2F_EXTENSIONS
|
||||
if ( is_extension_request((uint8_t*)&GA.creds[validCredCount - 1].credential.id, sizeof(CredentialId)) )
|
||||
{
|
||||
ret = cbor_encode_int(&map,RESP_authData);
|
||||
check_ret(ret);
|
||||
memset(auth_data_buf,0,sizeof(CTAP_authDataHeader));
|
||||
ret = cbor_encode_byte_string(&map, auth_data_buf, sizeof(CTAP_authDataHeader));
|
||||
check_ret(ret);
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
uint32_t len = sizeof(auth_data_buf);
|
||||
ret = ctap_make_auth_data(&GA.rp, &map, auth_data_buf, &len, NULL);
|
||||
check_retr(ret);
|
||||
|
||||
((CTAP_authData *)auth_data_buf)->head.flags &= ~(1 << 2);
|
||||
((CTAP_authData *)auth_data_buf)->head.flags |= (getAssertionState.user_verified << 2);
|
||||
|
||||
{
|
||||
unsigned int ext_encoder_buf_size = sizeof(auth_data_buf) - len;
|
||||
uint8_t * ext_encoder_buf = auth_data_buf + len;
|
||||
|
||||
ret = ctap_make_extensions(&GA.extensions, ext_encoder_buf, &ext_encoder_buf_size);
|
||||
check_retr(ret);
|
||||
if (ext_encoder_buf_size)
|
||||
{
|
||||
((CTAP_authData *)auth_data_buf)->head.flags |= (1 << 7);
|
||||
len += ext_encoder_buf_size;
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
ret = cbor_encode_int(&map,RESP_authData);
|
||||
check_ret(ret);
|
||||
ret = cbor_encode_byte_string(&map, auth_data_buf, len);
|
||||
check_ret(ret);
|
||||
}
|
||||
}
|
||||
|
||||
save_credential_list((CTAP_authDataHeader*)auth_data_buf, GA.clientDataHash, GA.creds, validCredCount-1); // skip last one
|
||||
|
||||
ret = ctap_end_get_assertion(&map, cred, auth_data_buf, GA.clientDataHash, add_user_info);
|
||||
check_retr(ret);
|
||||
|
||||
@ -1150,7 +1325,7 @@ uint8_t ctap_update_pin_if_verified(uint8_t * pinEnc, int len, uint8_t * platfor
|
||||
crypto_aes256_decrypt(pinHashEnc, 16);
|
||||
if (memcmp(pinHashEnc, PIN_CODE_HASH, 16) != 0)
|
||||
{
|
||||
crypto_ecc256_make_key_pair(KEY_AGREEMENT_PUB, KEY_AGREEMENT_PRIV);
|
||||
ctap_reset_key_agreement();
|
||||
ctap_decrement_pin_attempts();
|
||||
if (ctap_device_boot_locked())
|
||||
{
|
||||
@ -1193,7 +1368,7 @@ uint8_t ctap_add_pin_if_verified(uint8_t * pinTokenEnc, uint8_t * platform_pubke
|
||||
printf2(TAG_ERR,"platform-pubkey: "); dump_hex1(TAG_ERR, platform_pubkey, 64);
|
||||
printf2(TAG_ERR,"device-pubkey: "); dump_hex1(TAG_ERR, KEY_AGREEMENT_PUB, 64);
|
||||
// Generate new keyAgreement pair
|
||||
crypto_ecc256_make_key_pair(KEY_AGREEMENT_PUB, KEY_AGREEMENT_PRIV);
|
||||
ctap_reset_key_agreement();
|
||||
ctap_decrement_pin_attempts();
|
||||
if (ctap_device_boot_locked())
|
||||
{
|
||||
@ -1218,6 +1393,7 @@ uint8_t ctap_client_pin(CborEncoder * encoder, uint8_t * request, int length)
|
||||
uint8_t pinTokenEnc[PIN_TOKEN_SIZE];
|
||||
int ret = ctap_parse_client_pin(&CP,request,length);
|
||||
|
||||
|
||||
switch(CP.subCommand)
|
||||
{
|
||||
case CP_cmdSetPin:
|
||||
@ -1362,19 +1538,15 @@ uint8_t ctap_request(uint8_t * pkt_raw, int length, CTAP_RESPONSE * resp)
|
||||
CborEncoder encoder;
|
||||
uint8_t status = 0;
|
||||
uint8_t cmd = *pkt_raw;
|
||||
uint64_t t1;
|
||||
uint64_t t2;
|
||||
pkt_raw++;
|
||||
length--;
|
||||
|
||||
uint8_t * buf = resp->data;
|
||||
printf1(TAG_GREEN, "lastcmd0 = 0x%02x\r\n", getAssertionState.lastcmd);
|
||||
|
||||
cbor_encoder_init(&encoder, buf, resp->data_size, 0);
|
||||
|
||||
printf1(TAG_CTAP,"cbor input structure: %d bytes\n", length);
|
||||
printf1(TAG_DUMP,"cbor req: "); dump_hex1(TAG_DUMP, pkt_raw, length);
|
||||
printf1(TAG_GREEN, "lastcmd1 = 0x%02x\r\n", getAssertionState.lastcmd);
|
||||
|
||||
switch(cmd)
|
||||
{
|
||||
@ -1398,10 +1570,9 @@ uint8_t ctap_request(uint8_t * pkt_raw, int length, CTAP_RESPONSE * resp)
|
||||
case CTAP_MAKE_CREDENTIAL:
|
||||
device_set_status(CTAPHID_STATUS_PROCESSING);
|
||||
printf1(TAG_CTAP,"CTAP_MAKE_CREDENTIAL\n");
|
||||
t1 = millis();
|
||||
timestamp();
|
||||
status = ctap_make_credential(&encoder, pkt_raw, length);
|
||||
t2 = millis();
|
||||
printf1(TAG_TIME,"make_credential time: %d ms\n", t2-t1);
|
||||
printf1(TAG_TIME,"make_credential time: %d ms\n", timestamp());
|
||||
|
||||
resp->length = cbor_encoder_get_buffer_size(&encoder, buf);
|
||||
dump_hex1(TAG_DUMP, buf, resp->length);
|
||||
@ -1410,10 +1581,9 @@ uint8_t ctap_request(uint8_t * pkt_raw, int length, CTAP_RESPONSE * resp)
|
||||
case CTAP_GET_ASSERTION:
|
||||
device_set_status(CTAPHID_STATUS_PROCESSING);
|
||||
printf1(TAG_CTAP,"CTAP_GET_ASSERTION\n");
|
||||
t1 = millis();
|
||||
timestamp();
|
||||
status = ctap_get_assertion(&encoder, pkt_raw, length);
|
||||
t2 = millis();
|
||||
printf1(TAG_TIME,"get_assertion time: %d ms\n", t2-t1);
|
||||
printf1(TAG_TIME,"get_assertion time: %d ms\n", timestamp());
|
||||
|
||||
resp->length = cbor_encoder_get_buffer_size(&encoder, buf);
|
||||
|
||||
@ -1465,7 +1635,7 @@ uint8_t ctap_request(uint8_t * pkt_raw, int length, CTAP_RESPONSE * resp)
|
||||
else
|
||||
{
|
||||
printf2(TAG_ERR, "unwanted GET_NEXT_ASSERTION. lastcmd == 0x%02x\n", getAssertionState.lastcmd);
|
||||
dump_hex1(TAG_GREEN, &getAssertionState, sizeof(getAssertionState));
|
||||
dump_hex1(TAG_GREEN, (uint8_t*)&getAssertionState, sizeof(getAssertionState));
|
||||
status = CTAP2_ERR_NOT_ALLOWED;
|
||||
}
|
||||
break;
|
||||
@ -1477,7 +1647,6 @@ uint8_t ctap_request(uint8_t * pkt_raw, int length, CTAP_RESPONSE * resp)
|
||||
done:
|
||||
device_set_status(CTAPHID_STATUS_IDLE);
|
||||
getAssertionState.lastcmd = cmd;
|
||||
printf1(TAG_GREEN, "lastcmd = 0x%02x\r\n", getAssertionState.lastcmd);
|
||||
|
||||
if (status != CTAP1_ERR_SUCCESS)
|
||||
{
|
||||
@ -1561,12 +1730,16 @@ void ctap_init()
|
||||
exit(1);
|
||||
}
|
||||
|
||||
crypto_ecc256_make_key_pair(KEY_AGREEMENT_PUB, KEY_AGREEMENT_PRIV);
|
||||
if (! device_is_nfc())
|
||||
{
|
||||
ctap_reset_key_agreement();
|
||||
}
|
||||
|
||||
#ifdef BRIDGE_TO_WALLET
|
||||
wallet_init();
|
||||
#endif
|
||||
|
||||
|
||||
}
|
||||
|
||||
uint8_t ctap_is_pin_set()
|
||||
@ -1757,7 +1930,10 @@ int8_t ctap_load_key(uint8_t index, uint8_t * key)
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static void ctap_reset_key_agreement()
|
||||
{
|
||||
crypto_ecc256_make_key_pair(KEY_AGREEMENT_PUB, KEY_AGREEMENT_PRIV);
|
||||
}
|
||||
|
||||
void ctap_reset()
|
||||
{
|
||||
@ -1774,7 +1950,7 @@ void ctap_reset()
|
||||
|
||||
ctap_reset_state();
|
||||
memset(PIN_CODE_HASH,0,sizeof(PIN_CODE_HASH));
|
||||
crypto_ecc256_make_key_pair(KEY_AGREEMENT_PUB, KEY_AGREEMENT_PRIV);
|
||||
ctap_reset_key_agreement();
|
||||
|
||||
crypto_reset_master_secret();
|
||||
}
|
||||
|
102
fido2/ctap.h
102
fido2/ctap.h
@ -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
|
||||
@ -157,9 +149,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 +192,62 @@ 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;
|
||||
int pinProtocol;
|
||||
CTAP_extensions extensions;
|
||||
|
||||
} CTAP_makeCredential;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
uint8_t type;
|
||||
struct Credential credential;
|
||||
} CTAP_credentialDescriptor;
|
||||
|
||||
|
||||
typedef struct
|
||||
{
|
||||
@ -245,22 +269,16 @@ typedef struct
|
||||
|
||||
CTAP_credentialDescriptor creds[ALLOW_LIST_MAX_SIZE];
|
||||
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;
|
||||
@ -279,7 +297,7 @@ 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();
|
||||
|
@ -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
|
||||
|
@ -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 "cbor.h"
|
||||
@ -94,7 +79,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 +128,14 @@ 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;
|
||||
printf1(TAG_GREEN,"parsed id_size: %d\r\n", MC->credInfo.user.id_size);
|
||||
check_ret(ret);
|
||||
}
|
||||
else if (strcmp((const char *)key, "name") == 0)
|
||||
@ -161,12 +146,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 +161,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 +176,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 +270,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 +305,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 +319,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 +344,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 +393,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 +481,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 +521,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,10 +556,158 @@ 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;
|
||||
@ -646,8 +779,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 +788,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,11 +813,13 @@ 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:
|
||||
@ -790,7 +925,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,7 +968,7 @@ 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;
|
||||
@ -900,6 +1036,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:
|
||||
@ -954,14 +1092,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 +1138,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 +1153,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 +1163,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 +1182,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 +1192,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 +1262,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;
|
||||
|
@ -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);
|
||||
|
266
fido2/ctaphid.c
266
fido2/ctaphid.c
@ -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,14 @@
|
||||
#include "time.h"
|
||||
#include "util.h"
|
||||
#include "log.h"
|
||||
#include "app.h"
|
||||
#include "extensions.h"
|
||||
|
||||
// move custom SHA512 command out,
|
||||
// and the following headers too
|
||||
#include "sha2.h"
|
||||
#include "crypto.h"
|
||||
|
||||
#include APP_CONFIG
|
||||
|
||||
typedef enum
|
||||
{
|
||||
@ -112,7 +104,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 +120,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 +133,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 +148,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 +386,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,19 +534,23 @@ 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_handle_packet(uint8_t * pkt_raw)
|
||||
{
|
||||
uint8_t cmd;
|
||||
uint32_t cid;
|
||||
int len;
|
||||
#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);
|
||||
|
||||
if (bufstatus == HID_IGNORE)
|
||||
@ -595,11 +591,11 @@ uint8_t ctaphid_handle_packet(uint8_t * pkt_raw)
|
||||
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
|
||||
@ -608,6 +604,8 @@ uint8_t ctaphid_handle_packet(uint8_t * pkt_raw)
|
||||
|
||||
ctaphid_write_buffer_init(&wb);
|
||||
|
||||
device_wink();
|
||||
|
||||
wb.cid = cid;
|
||||
wb.cmd = CTAPHID_WINK;
|
||||
|
||||
@ -641,12 +639,11 @@ uint8_t ctaphid_handle_packet(uint8_t * pkt_raw)
|
||||
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
|
||||
@ -682,6 +679,205 @@ uint8_t ctaphid_handle_packet(uint8_t * pkt_raw)
|
||||
printf1(TAG_HID,"CTAPHID_CANCEL\n");
|
||||
is_busy = 0;
|
||||
break;
|
||||
#if defined(IS_BOOTLOADER)
|
||||
case CTAPHID_BOOT:
|
||||
printf1(TAG_HID,"CTAPHID_BOOT\n");
|
||||
ctap_response_init(&ctap_resp);
|
||||
u2f_set_writeback_buffer(&ctap_resp);
|
||||
is_busy = bootloader_bridge(len, ctap_buffer);
|
||||
|
||||
ctaphid_write_buffer_init(&wb);
|
||||
wb.cid = cid;
|
||||
wb.cmd = CTAPHID_BOOT;
|
||||
wb.bcnt = (ctap_resp.length + 1);
|
||||
ctaphid_write(&wb, &is_busy, 1);
|
||||
ctaphid_write(&wb, ctap_resp.data, ctap_resp.length);
|
||||
ctaphid_write(&wb, NULL, 0);
|
||||
is_busy = 0;
|
||||
break;
|
||||
#endif
|
||||
#if defined(SOLO_HACKER)
|
||||
case CTAPHID_ENTERBOOT:
|
||||
printf1(TAG_HID,"CTAPHID_ENTERBOOT\n");
|
||||
boot_solo_bootloader();
|
||||
ctaphid_write_buffer_init(&wb);
|
||||
wb.cid = cid;
|
||||
wb.cmd = CTAPHID_ENTERBOOT;
|
||||
wb.bcnt = 0;
|
||||
ctaphid_write(&wb, NULL, 0);
|
||||
is_busy = 0;
|
||||
break;
|
||||
case CTAPHID_ENTERSTBOOT:
|
||||
printf1(TAG_HID,"CTAPHID_ENTERBOOT\n");
|
||||
boot_st_bootloader();
|
||||
break;
|
||||
#endif
|
||||
#if !defined(IS_BOOTLOADER)
|
||||
case CTAPHID_GETRNG:
|
||||
printf1(TAG_HID,"CTAPHID_GETRNG\n");
|
||||
ctap_response_init(&ctap_resp);
|
||||
ctaphid_write_buffer_init(&wb);
|
||||
wb.cid = cid;
|
||||
wb.cmd = CTAPHID_GETRNG;
|
||||
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);
|
||||
is_busy = 0;
|
||||
break;
|
||||
#endif
|
||||
#if defined(SOLO_HACKER) && (DEBUG_LEVEL > 0) && (!IS_BOOTLOADER == 1)
|
||||
case CTAPHID_PROBE:
|
||||
|
||||
/*
|
||||
* Expects CBOR-serialized data of the form
|
||||
* {"subcommand": "hash_type", "data": b"the_data"}
|
||||
* with hash_type in SHA256, SHA512
|
||||
*/
|
||||
|
||||
// some random logging
|
||||
printf1(TAG_HID,"CTAPHID_PROBE\n");
|
||||
// initialise CTAP response object
|
||||
ctap_response_init(&ctap_resp);
|
||||
// initialise write buffer
|
||||
ctaphid_write_buffer_init(&wb);
|
||||
wb.cid = cid;
|
||||
wb.cmd = CTAPHID_PROBE;
|
||||
|
||||
// prepare parsing (or halt)
|
||||
int ret;
|
||||
CborParser parser;
|
||||
CborValue it, map;
|
||||
ret = cbor_parser_init(
|
||||
ctap_buffer, (size_t) buffer_len(),
|
||||
// strictly speaking, CTAP is not RFC canonical...
|
||||
CborValidateCanonicalFormat,
|
||||
&parser, &it);
|
||||
check_hardcore(ret);
|
||||
|
||||
CborType type = cbor_value_get_type(&it);
|
||||
if (type != CborMapType) exit(1);
|
||||
|
||||
ret = cbor_value_enter_container(&it,&map);
|
||||
check_hardcore(ret);
|
||||
|
||||
size_t map_length = 0;
|
||||
ret = cbor_value_get_map_length(&it, &map_length);
|
||||
if (map_length != 2) exit(1);
|
||||
|
||||
// parse subcommand (or halt)
|
||||
CborValue val;
|
||||
ret = cbor_value_map_find_value(&it, "subcommand", &val);
|
||||
check_hardcore(ret);
|
||||
if (!cbor_value_is_text_string(&val))
|
||||
exit(1);
|
||||
|
||||
int sha_version = 0;
|
||||
bool found = false;
|
||||
if (!found) {
|
||||
ret = cbor_value_text_string_equals(
|
||||
&val, "SHA256", &found);
|
||||
check_hardcore(ret);
|
||||
if (found)
|
||||
sha_version = 256;
|
||||
}
|
||||
if (!found) {
|
||||
ret = cbor_value_text_string_equals(
|
||||
&val, "SHA512", &found);
|
||||
check_hardcore(ret);
|
||||
if (found)
|
||||
sha_version = 512;
|
||||
}
|
||||
if (sha_version == 0)
|
||||
exit(1);
|
||||
|
||||
// parse data (or halt)
|
||||
ret = cbor_value_map_find_value(&it, "data", &val);
|
||||
check_hardcore(ret);
|
||||
if (!cbor_value_is_byte_string(&val))
|
||||
exit(1);
|
||||
|
||||
size_t data_length = 0;
|
||||
ret = cbor_value_calculate_string_length(&val, &data_length);
|
||||
check_hardcore(ret);
|
||||
if (data_length > 6*1024)
|
||||
exit(1);
|
||||
|
||||
unsigned char data[6*1024];
|
||||
ret = cbor_value_copy_byte_string (
|
||||
&val, &data[0], &data_length, &val);
|
||||
check_hardcore(ret);
|
||||
|
||||
// execute subcommand
|
||||
if (sha_version == 256) {
|
||||
// calculate hash
|
||||
crypto_sha256_init();
|
||||
crypto_sha256_update(data, data_length);
|
||||
crypto_sha256_final(ctap_buffer);
|
||||
// write output
|
||||
wb.bcnt = CF_SHA256_HASHSZ; // 32 bytes
|
||||
ctaphid_write(&wb, &ctap_buffer, CF_SHA256_HASHSZ);
|
||||
}
|
||||
|
||||
if (sha_version == 512) {
|
||||
// calculate hash
|
||||
crypto_sha512_init();
|
||||
crypto_sha512_update(data, data_length);
|
||||
crypto_sha512_final(ctap_buffer);
|
||||
// write output
|
||||
wb.bcnt = CF_SHA512_HASHSZ; // 64 bytes
|
||||
ctaphid_write(&wb, &ctap_buffer, CF_SHA512_HASHSZ);
|
||||
}
|
||||
|
||||
// finalize
|
||||
ctaphid_write(&wb, NULL, 0);
|
||||
is_busy = 0;
|
||||
break;
|
||||
|
||||
/*
|
||||
case CTAPHID_SHA256:
|
||||
// some random logging
|
||||
printf1(TAG_HID,"CTAPHID_SHA256\n");
|
||||
// initialise CTAP response object
|
||||
ctap_response_init(&ctap_resp);
|
||||
// initialise write buffer
|
||||
ctaphid_write_buffer_init(&wb);
|
||||
wb.cid = cid;
|
||||
wb.cmd = CTAPHID_SHA256;
|
||||
wb.bcnt = CF_SHA256_HASHSZ; // 32 bytes
|
||||
// calculate hash
|
||||
crypto_sha256_init();
|
||||
crypto_sha256_update(ctap_buffer, buffer_len());
|
||||
crypto_sha256_final(ctap_buffer);
|
||||
// copy to output
|
||||
ctaphid_write(&wb, &ctap_buffer, CF_SHA256_HASHSZ);
|
||||
ctaphid_write(&wb, NULL, 0);
|
||||
is_busy = 0;
|
||||
break;
|
||||
case CTAPHID_SHA512:
|
||||
// some random logging
|
||||
printf1(TAG_HID,"CTAPHID_SHA512\n");
|
||||
// initialise CTAP response object
|
||||
ctap_response_init(&ctap_resp);
|
||||
// initialise write buffer
|
||||
ctaphid_write_buffer_init(&wb);
|
||||
wb.cid = cid;
|
||||
wb.cmd = CTAPHID_SHA512;
|
||||
wb.bcnt = CF_SHA512_HASHSZ; // 64 bytes
|
||||
// calculate hash
|
||||
crypto_sha512_init();
|
||||
crypto_sha512_update(ctap_buffer, buffer_len());
|
||||
crypto_sha512_final(ctap_buffer);
|
||||
// copy to output
|
||||
ctaphid_write(&wb, &ctap_buffer, CF_SHA512_HASHSZ);
|
||||
ctaphid_write(&wb, NULL, 0);
|
||||
is_busy = 0;
|
||||
break;
|
||||
*/
|
||||
#endif
|
||||
default:
|
||||
printf2(TAG_ERR,"error, unimplemented HID cmd: %02x\r\n", buffer_cmd());
|
||||
ctaphid_send_error(cid, CTAP1_ERR_INVALID_COMMAND);
|
||||
|
@ -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,14 @@
|
||||
#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)
|
||||
// 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
|
||||
|
@ -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 _DEVICE_H
|
||||
#define _DEVICE_H
|
||||
|
||||
@ -45,6 +30,7 @@ void main_loop_delay();
|
||||
|
||||
void heartbeat();
|
||||
|
||||
|
||||
void authenticator_read_state(AuthenticatorState * );
|
||||
|
||||
void authenticator_read_backup_state(AuthenticatorState * );
|
||||
@ -60,7 +46,10 @@ 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.
|
||||
@ -90,4 +79,29 @@ 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 1 if operating in NFC mode.
|
||||
// 0 otherwise.
|
||||
bool device_is_nfc();
|
||||
|
||||
|
||||
#endif
|
||||
|
@ -1,35 +1,100 @@
|
||||
/*
|
||||
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;
|
||||
}
|
||||
|
||||
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);
|
||||
#elif defined(WALLET_EXTENSION)
|
||||
ret = bridge_u2f_to_wallet(_chal, _appid, 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)))
|
||||
{
|
||||
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 +102,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 +110,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;
|
||||
|
@ -1,28 +1,20 @@
|
||||
/*
|
||||
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 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);
|
||||
|
||||
#endif /* EXTENSIONS_H_ */
|
||||
|
73
fido2/extensions/solo.c
Normal file
73
fido2/extensions/solo.c
Normal file
@ -0,0 +1,73 @@
|
||||
/*
|
||||
* 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;
|
||||
|
||||
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;
|
||||
|
||||
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
27
fido2/extensions/solo.h
Normal 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
|
@ -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"
|
||||
@ -52,26 +37,6 @@ typedef enum
|
||||
#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)
|
||||
{
|
||||
@ -200,8 +165,7 @@ int16_t bridge_u2f_to_wallet(uint8_t * _chal, uint8_t * _appid, uint8_t klen, ui
|
||||
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 +186,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++)
|
||||
{
|
||||
@ -348,8 +297,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();
|
||||
@ -466,24 +413,8 @@ int16_t bridge_u2f_to_wallet(uint8_t * _chal, uint8_t * _appid, uint8_t klen, ui
|
||||
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;
|
||||
}
|
||||
|
@ -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,21 @@ 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;
|
||||
|
||||
|
||||
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_wallet_device(uint8_t * req, int len);
|
||||
int is_extension_request(uint8_t * req, int len);
|
||||
|
||||
void wallet_init();
|
||||
|
||||
|
52
fido2/log.c
52
fido2/log.c
@ -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,10 @@ struct logtag tagtable[] = {
|
||||
{TAG_TIME,"[1;33mTIME[0m"},
|
||||
{TAG_WALLET,"[1;34mWALLET[0m"},
|
||||
{TAG_STOR,"[1;35mSTOR[0m"},
|
||||
{TAG_BOOT,"[1;36mBOOT[0m"},
|
||||
{TAG_EXT,"[1;37mEXT[0m"},
|
||||
{TAG_NFC,"[1;38mNFC[0m"},
|
||||
{TAG_NFC_APDU, "NAPDU"},
|
||||
};
|
||||
|
||||
|
||||
@ -65,7 +60,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 +70,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 +102,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
|
||||
|
85
fido2/log.h
85
fido2/log.h
@ -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,56 @@
|
||||
|
||||
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_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
|
||||
|
||||
|
78
fido2/main.c
78
fido2/main.c
@ -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 <stdint.h>
|
||||
@ -30,53 +15,49 @@
|
||||
#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()
|
||||
{
|
||||
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_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();
|
||||
|
||||
memset(hidmsg,0,sizeof(hidmsg));
|
||||
|
||||
printf1(TAG_GEN,"recv'ing hid msg \n");
|
||||
// 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 +73,7 @@ int main(int argc, char * argv[])
|
||||
{
|
||||
}
|
||||
ctaphid_check_timeouts();
|
||||
|
||||
}
|
||||
|
||||
// Should never get here
|
||||
|
@ -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
|
||||
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
||||
/*
|
||||
|
143
fido2/u2f.c
143
fido2/u2f.c
@ -1,49 +1,40 @@
|
||||
/*
|
||||
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 "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();
|
||||
|
||||
|
||||
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 +43,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 +58,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");
|
||||
@ -119,6 +110,22 @@ end:
|
||||
printf1(TAG_U2F,"u2f resp: "); dump_hex1(TAG_U2F, _u2f_resp->data, _u2f_resp->length);
|
||||
}
|
||||
|
||||
void u2f_request_nfc(uint8_t * req, int len, CTAP_RESPONSE * resp)
|
||||
{
|
||||
if (len < 5 || !req)
|
||||
return;
|
||||
|
||||
uint32_t alen = req[4];
|
||||
|
||||
u2f_request_ex((APDU_HEADER *)req, &req[5], alen, resp);
|
||||
}
|
||||
|
||||
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 +144,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];
|
||||
@ -161,7 +173,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);
|
||||
@ -201,6 +213,7 @@ static int16_t u2f_authenticate(struct u2f_authenticate_request * req, uint8_t c
|
||||
|
||||
if (control == U2F_AUTHENTICATE_CHECK)
|
||||
{
|
||||
printf1(TAG_U2F, "CHECK-ONLY\r\n");
|
||||
if (u2f_appid_eq(&req->kh, req->app) == 0)
|
||||
{
|
||||
return U2F_SW_CONDITIONS_NOT_SATISFIED;
|
||||
@ -211,39 +224,51 @@ static int16_t u2f_authenticate(struct u2f_authenticate_request * req, uint8_t c
|
||||
}
|
||||
}
|
||||
if (
|
||||
control != U2F_AUTHENTICATE_SIGN ||
|
||||
req->khl != U2F_KEY_HANDLE_SIZE ||
|
||||
(control != U2F_AUTHENTICATE_SIGN && control != U2F_AUTHENTICATE_SIGN_NO_USER) ||
|
||||
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
|
||||
|
||||
)
|
||||
{
|
||||
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(!device_is_nfc() && up)
|
||||
{
|
||||
if (ctap_user_presence_test() == 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;
|
||||
@ -261,10 +286,13 @@ static int16_t u2f_register(struct u2f_register_request * req)
|
||||
|
||||
const uint16_t attest_size = attestation_cert_der_size;
|
||||
|
||||
if ( ! ctap_user_presence_test())
|
||||
{
|
||||
return U2F_SW_CONDITIONS_NOT_SATISFIED;
|
||||
}
|
||||
if(!device_is_nfc())
|
||||
{
|
||||
if ( ! ctap_user_presence_test())
|
||||
{
|
||||
return U2F_SW_CONDITIONS_NOT_SATISFIED;
|
||||
}
|
||||
}
|
||||
|
||||
if ( u2f_new_keypair(&key_handle, req->app, pubkey) == -1)
|
||||
{
|
||||
@ -284,8 +312,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);
|
||||
|
||||
@ -305,6 +331,7 @@ static int16_t u2f_register(struct u2f_register_request * req)
|
||||
|
||||
return U2F_SW_NO_ERROR;
|
||||
}
|
||||
#endif
|
||||
|
||||
int16_t u2f_version()
|
||||
{
|
||||
|
39
fido2/u2f.h
39
fido2/u2f.h
@ -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,18 @@ 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 * req, int len, CTAP_RESPONSE * resp);
|
||||
|
||||
|
||||
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();
|
||||
|
||||
|
29
fido2/util.c
29
fido2/util.c
@ -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");
|
||||
}
|
||||
|
||||
|
||||
|
27
fido2/util.h
27
fido2/util.h
@ -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
|
||||
|
||||
|
21
fido2/version.h
Normal file
21
fido2/version.h
Normal file
@ -0,0 +1,21 @@
|
||||
#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
|
||||
|
||||
|
||||
#endif
|
51
in-docker-build.sh
Executable file
51
in-docker-build.sh
Executable file
@ -0,0 +1,51 @@
|
||||
#!/bin/bash -xe
|
||||
|
||||
version=${1:-master}
|
||||
|
||||
export PREFIX=/opt/gcc-arm-none-eabi-8-2018-q4-major/bin/
|
||||
|
||||
cd /solo/targets/stm32l432
|
||||
git fetch --tags
|
||||
git checkout ${version}
|
||||
git submodule update --init --recursive
|
||||
version=$(git describe)
|
||||
|
||||
make cbor
|
||||
|
||||
out_dir="/builds"
|
||||
|
||||
function build() {
|
||||
part=${1}
|
||||
variant=${2}
|
||||
output=${3:-${part}}
|
||||
what="${part}-${variant}"
|
||||
|
||||
make full-clean
|
||||
|
||||
make ${what}
|
||||
|
||||
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
|
||||
build bootloader verifying
|
||||
build firmware hacker solo
|
||||
build firmware hacker-debug-1 solo
|
||||
build firmware hacker-debug-2 solo
|
||||
build firmware secure solo
|
||||
|
||||
pip install -U pip
|
||||
pip install -U solo-python
|
||||
cd ${out_dir}
|
||||
bundle="bundle-hacker-${version}"
|
||||
/opt/conda/bin/solo mergehex bootloader-nonverifying-${version}.hex firmware-hacker-${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-hacker-debug-1-${version}.hex ${bundle}.hex
|
||||
bundle="bundle-hacker-debug-2-${version}"
|
||||
/opt/conda/bin/solo mergehex bootloader-nonverifying-${version}.hex firmware-hacker-debug-2-${version}.hex ${bundle}.hex
|
39
metadata/Solo-FIDO2-CTAP2-Authenticator.json
Normal file
39
metadata/Solo-FIDO2-CTAP2-Authenticator.json
Normal file
File diff suppressed because one or more lines are too long
37
metadata/Solo-FIDO2-U2F-Authenticator.json
Normal file
37
metadata/Solo-FIDO2-U2F-Authenticator.json
Normal file
File diff suppressed because one or more lines are too long
34
mkdocs.yml
34
mkdocs.yml
@ -1,21 +1,27 @@
|
||||
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 © 2018 SoloKeys'
|
||||
site_url: 'https://docs.solokeys.io/solo/'
|
||||
repo_url: 'https://github.com/solokeys/solo'
|
||||
repo_name: 'solokeys/solo'
|
||||
copyright: 'Copyright © 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
|
||||
- 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
|
||||
|
30
pc/app.h
30
pc/app.h
@ -1,9 +1,9 @@
|
||||
/*
|
||||
* 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_
|
||||
@ -15,10 +15,26 @@
|
||||
#define DEBUG_LEVEL 1
|
||||
|
||||
#define ENABLE_U2F
|
||||
|
||||
#define ENABLE_U2F_EXTENSIONS
|
||||
//#define BRIDGE_TO_WALLET
|
||||
|
||||
void printing_init();
|
||||
|
||||
// 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_ */
|
||||
|
169
pc/device.c
169
pc/device.c
@ -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>
|
||||
@ -14,13 +20,35 @@
|
||||
#include "cbor.h"
|
||||
#include "util.h"
|
||||
#include "log.h"
|
||||
#include "ctaphid.h"
|
||||
|
||||
#define RK_NUM 50
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
|
||||
|
||||
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;
|
||||
@ -118,11 +146,20 @@ void usbhid_init()
|
||||
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);*/
|
||||
/*}*/
|
||||
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;
|
||||
}
|
||||
|
||||
@ -151,6 +188,10 @@ void device_init()
|
||||
usbhid_init();
|
||||
|
||||
authenticator_initialize();
|
||||
|
||||
ctaphid_init();
|
||||
|
||||
ctap_init( 1 );
|
||||
}
|
||||
|
||||
|
||||
@ -158,7 +199,7 @@ 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);
|
||||
}
|
||||
|
||||
@ -211,15 +252,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 +265,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 +385,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 +426,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 +480,74 @@ 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");
|
||||
}
|
||||
|
||||
bool device_is_nfc()
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
Submodule python-fido2 deleted from 329434fdd4
File diff suppressed because one or more lines are too long
@ -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>
|
@ -1,2 +0,0 @@
|
||||
copiedFilesOriginState={}
|
||||
eclipse.preferences.version=1
|
@ -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}}
|
@ -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
|
@ -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
|
||||
}
|
@ -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 → DefaultMode" propertyId="modeTransition.source" value="RESET"/>
|
||||
<property object="RESET → DefaultMode" propertyId="modeTransition.target" value="DefaultMode"/>
|
||||
</modeTransition>
|
||||
</device:XMLDevice>
|
@ -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 → DefaultMode" propertyId="modeTransition.source" value="RESET"/>
|
||||
<property object="RESET → DefaultMode" propertyId="modeTransition.target" value="DefaultMode"/>
|
||||
</modeTransition>
|
||||
</device:XMLDevice>
|
@ -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
@ -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
@ -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
@ -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) */
|
@ -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) */
|
@ -1,355 +0,0 @@
|
||||
/***************************************************************************//**
|
||||
* @file em_ldma.c
|
||||
* @brief Direct memory access (LDMA) module 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_ldma.h"
|
||||
|
||||
#if defined(LDMA_PRESENT) && (LDMA_COUNT == 1)
|
||||
|
||||
#include <stddef.h>
|
||||
#include "em_assert.h"
|
||||
#include "em_bus.h"
|
||||
#include "em_cmu.h"
|
||||
#include "em_core.h"
|
||||
|
||||
/***************************************************************************//**
|
||||
* @addtogroup emlib
|
||||
* @{
|
||||
******************************************************************************/
|
||||
|
||||
/***************************************************************************//**
|
||||
* @addtogroup LDMA
|
||||
* @{
|
||||
******************************************************************************/
|
||||
|
||||
#if defined(LDMA_IRQ_HANDLER_TEMPLATE)
|
||||
/***************************************************************************//**
|
||||
* @brief
|
||||
* Template for an LDMA IRQ handler.
|
||||
******************************************************************************/
|
||||
void LDMA_IRQHandler(void)
|
||||
{
|
||||
uint32_t ch;
|
||||
/* Get all pending and enabled interrupts. */
|
||||
uint32_t pending = LDMA_IntGetEnabled();
|
||||
|
||||
/* Loop here on an LDMA error to enable debugging. */
|
||||
while (pending & LDMA_IF_ERROR) {
|
||||
}
|
||||
|
||||
/* Iterate over all LDMA channels. */
|
||||
for (ch = 0; ch < DMA_CHAN_COUNT; ch++) {
|
||||
uint32_t mask = 0x1 << ch;
|
||||
if (pending & mask) {
|
||||
/* Clear interrupt flag. */
|
||||
LDMA->IFC = mask;
|
||||
|
||||
/* Do more stuff here, execute callbacks etc. */
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
/***************************************************************************//**
|
||||
* @brief
|
||||
* De-initialize the LDMA controller.
|
||||
*
|
||||
* LDMA interrupts are disabled and the LDMA clock is stopped.
|
||||
******************************************************************************/
|
||||
void LDMA_DeInit(void)
|
||||
{
|
||||
NVIC_DisableIRQ(LDMA_IRQn);
|
||||
LDMA->IEN = 0;
|
||||
LDMA->CHEN = 0;
|
||||
CMU_ClockEnable(cmuClock_LDMA, false);
|
||||
}
|
||||
|
||||
/***************************************************************************//**
|
||||
* @brief
|
||||
* Enable or disable a LDMA channel request.
|
||||
*
|
||||
* @details
|
||||
* Use this function to enable or disable a LDMA channel request. This will
|
||||
* prevent the LDMA from proceeding after its current transaction if disabled.
|
||||
*
|
||||
* @param[in] channel
|
||||
* LDMA channel to enable or disable requests on.
|
||||
*
|
||||
* @param[in] enable
|
||||
* If 'true' request will be enabled. If 'false' request will be disabled.
|
||||
******************************************************************************/
|
||||
void LDMA_EnableChannelRequest(int ch, bool enable)
|
||||
{
|
||||
EFM_ASSERT(ch < DMA_CHAN_COUNT);
|
||||
|
||||
BUS_RegBitWrite(&LDMA->REQDIS, ch, !enable);
|
||||
}
|
||||
|
||||
/***************************************************************************//**
|
||||
* @brief
|
||||
* Initialize the LDMA controller.
|
||||
*
|
||||
* @details
|
||||
* This function will disable all the LDMA channels and enable the LDMA bus
|
||||
* clock in the CMU. This function will also enable the LDMA IRQ in the NVIC
|
||||
* and set the LDMA IRQ priority to a user configurable priority. The LDMA
|
||||
* interrupt priority is configured using the @ref LDMA_Init_t structure.
|
||||
*
|
||||
* @note
|
||||
* Since this function enables the LDMA IRQ you should always add a custom
|
||||
* LDMA_IRQHandler to the application in order to handle any interrupts
|
||||
* from LDMA.
|
||||
*
|
||||
* @param[in] init
|
||||
* Pointer to initialization structure used to configure the LDMA.
|
||||
******************************************************************************/
|
||||
void LDMA_Init(const LDMA_Init_t *init)
|
||||
{
|
||||
EFM_ASSERT(init != NULL);
|
||||
EFM_ASSERT(!((init->ldmaInitCtrlNumFixed << _LDMA_CTRL_NUMFIXED_SHIFT)
|
||||
& ~_LDMA_CTRL_NUMFIXED_MASK));
|
||||
EFM_ASSERT(!((init->ldmaInitCtrlSyncPrsClrEn << _LDMA_CTRL_SYNCPRSCLREN_SHIFT)
|
||||
& ~_LDMA_CTRL_SYNCPRSCLREN_MASK));
|
||||
EFM_ASSERT(!((init->ldmaInitCtrlSyncPrsSetEn << _LDMA_CTRL_SYNCPRSSETEN_SHIFT)
|
||||
& ~_LDMA_CTRL_SYNCPRSSETEN_MASK));
|
||||
EFM_ASSERT(init->ldmaInitIrqPriority < (1 << __NVIC_PRIO_BITS));
|
||||
|
||||
CMU_ClockEnable(cmuClock_LDMA, true);
|
||||
|
||||
LDMA->CTRL = (init->ldmaInitCtrlNumFixed << _LDMA_CTRL_NUMFIXED_SHIFT)
|
||||
| (init->ldmaInitCtrlSyncPrsClrEn << _LDMA_CTRL_SYNCPRSCLREN_SHIFT)
|
||||
| (init->ldmaInitCtrlSyncPrsSetEn << _LDMA_CTRL_SYNCPRSSETEN_SHIFT);
|
||||
|
||||
LDMA->CHEN = 0;
|
||||
LDMA->DBGHALT = 0;
|
||||
LDMA->REQDIS = 0;
|
||||
|
||||
/* Enable LDMA error interrupt. */
|
||||
LDMA->IEN = LDMA_IEN_ERROR;
|
||||
LDMA->IFC = 0xFFFFFFFF;
|
||||
|
||||
NVIC_ClearPendingIRQ(LDMA_IRQn);
|
||||
|
||||
/* Range is 0..7, 0 is highest priority. */
|
||||
NVIC_SetPriority(LDMA_IRQn, init->ldmaInitIrqPriority);
|
||||
|
||||
NVIC_EnableIRQ(LDMA_IRQn);
|
||||
}
|
||||
|
||||
/***************************************************************************//**
|
||||
* @brief
|
||||
* Start a DMA transfer.
|
||||
*
|
||||
* @param[in] ch
|
||||
* DMA channel.
|
||||
*
|
||||
* @param[in] transfer
|
||||
* Initialization structure used to configure the transfer.
|
||||
*
|
||||
* @param[in] descriptor
|
||||
* Transfer descriptor, can be an array of descriptors linked together.
|
||||
******************************************************************************/
|
||||
void LDMA_StartTransfer(int ch,
|
||||
const LDMA_TransferCfg_t *transfer,
|
||||
const LDMA_Descriptor_t *descriptor)
|
||||
{
|
||||
uint32_t tmp;
|
||||
CORE_DECLARE_IRQ_STATE;
|
||||
uint32_t chMask = 1 << ch;
|
||||
|
||||
EFM_ASSERT(ch < DMA_CHAN_COUNT);
|
||||
EFM_ASSERT(transfer != NULL);
|
||||
EFM_ASSERT(!(transfer->ldmaReqSel & ~_LDMA_CH_REQSEL_MASK));
|
||||
|
||||
EFM_ASSERT(!((transfer->ldmaCtrlSyncPrsClrOff << _LDMA_CTRL_SYNCPRSCLREN_SHIFT)
|
||||
& ~_LDMA_CTRL_SYNCPRSCLREN_MASK));
|
||||
EFM_ASSERT(!((transfer->ldmaCtrlSyncPrsClrOn << _LDMA_CTRL_SYNCPRSCLREN_SHIFT)
|
||||
& ~_LDMA_CTRL_SYNCPRSCLREN_MASK));
|
||||
EFM_ASSERT(!((transfer->ldmaCtrlSyncPrsSetOff << _LDMA_CTRL_SYNCPRSSETEN_SHIFT)
|
||||
& ~_LDMA_CTRL_SYNCPRSSETEN_MASK));
|
||||
EFM_ASSERT(!((transfer->ldmaCtrlSyncPrsSetOn << _LDMA_CTRL_SYNCPRSSETEN_SHIFT)
|
||||
& ~_LDMA_CTRL_SYNCPRSSETEN_MASK));
|
||||
|
||||
EFM_ASSERT(!((transfer->ldmaCfgArbSlots << _LDMA_CH_CFG_ARBSLOTS_SHIFT)
|
||||
& ~_LDMA_CH_CFG_ARBSLOTS_MASK));
|
||||
EFM_ASSERT(!((transfer->ldmaCfgSrcIncSign << _LDMA_CH_CFG_SRCINCSIGN_SHIFT)
|
||||
& ~_LDMA_CH_CFG_SRCINCSIGN_MASK) );
|
||||
EFM_ASSERT(!((transfer->ldmaCfgDstIncSign << _LDMA_CH_CFG_DSTINCSIGN_SHIFT)
|
||||
& ~_LDMA_CH_CFG_DSTINCSIGN_MASK));
|
||||
EFM_ASSERT(!((transfer->ldmaLoopCnt << _LDMA_CH_LOOP_LOOPCNT_SHIFT)
|
||||
& ~_LDMA_CH_LOOP_LOOPCNT_MASK));
|
||||
|
||||
LDMA->CH[ch].REQSEL = transfer->ldmaReqSel;
|
||||
LDMA->CH[ch].LOOP = (transfer->ldmaLoopCnt << _LDMA_CH_LOOP_LOOPCNT_SHIFT);
|
||||
LDMA->CH[ch].CFG = (transfer->ldmaCfgArbSlots << _LDMA_CH_CFG_ARBSLOTS_SHIFT)
|
||||
| (transfer->ldmaCfgSrcIncSign << _LDMA_CH_CFG_SRCINCSIGN_SHIFT)
|
||||
| (transfer->ldmaCfgDstIncSign << _LDMA_CH_CFG_DSTINCSIGN_SHIFT);
|
||||
|
||||
/* Set descriptor address. */
|
||||
LDMA->CH[ch].LINK = (uint32_t)descriptor & _LDMA_CH_LINK_LINKADDR_MASK;
|
||||
|
||||
/* Clear pending channel interrupt. */
|
||||
LDMA->IFC = chMask;
|
||||
|
||||
/* Critical region. */
|
||||
CORE_ENTER_ATOMIC();
|
||||
|
||||
/* Enable channel interrupt. */
|
||||
LDMA->IEN |= chMask;
|
||||
|
||||
if (transfer->ldmaReqDis) {
|
||||
LDMA->REQDIS |= chMask;
|
||||
}
|
||||
|
||||
if (transfer->ldmaDbgHalt) {
|
||||
LDMA->DBGHALT |= chMask;
|
||||
}
|
||||
|
||||
tmp = LDMA->CTRL;
|
||||
|
||||
if (transfer->ldmaCtrlSyncPrsClrOff) {
|
||||
tmp &= ~_LDMA_CTRL_SYNCPRSCLREN_MASK
|
||||
| (~transfer->ldmaCtrlSyncPrsClrOff << _LDMA_CTRL_SYNCPRSCLREN_SHIFT);
|
||||
}
|
||||
|
||||
if (transfer->ldmaCtrlSyncPrsClrOn) {
|
||||
tmp |= transfer->ldmaCtrlSyncPrsClrOn << _LDMA_CTRL_SYNCPRSCLREN_SHIFT;
|
||||
}
|
||||
|
||||
if (transfer->ldmaCtrlSyncPrsSetOff) {
|
||||
tmp &= ~_LDMA_CTRL_SYNCPRSSETEN_MASK
|
||||
| (~transfer->ldmaCtrlSyncPrsSetOff << _LDMA_CTRL_SYNCPRSSETEN_SHIFT);
|
||||
}
|
||||
|
||||
if (transfer->ldmaCtrlSyncPrsSetOn) {
|
||||
tmp |= transfer->ldmaCtrlSyncPrsSetOn << _LDMA_CTRL_SYNCPRSSETEN_SHIFT;
|
||||
}
|
||||
|
||||
LDMA->CTRL = tmp;
|
||||
|
||||
BUS_RegMaskedClear(&LDMA->CHDONE, chMask); /* Clear the done flag. */
|
||||
LDMA->LINKLOAD = chMask; /* Start transfer by loading descriptor. */
|
||||
|
||||
/* Critical region end. */
|
||||
CORE_EXIT_ATOMIC();
|
||||
}
|
||||
|
||||
/***************************************************************************//**
|
||||
* @brief
|
||||
* Stop a DMA transfer.
|
||||
*
|
||||
* @note
|
||||
* The DMA will complete the current AHB burst transfer before stopping.
|
||||
*
|
||||
* @param[in] ch
|
||||
* DMA channel to stop.
|
||||
******************************************************************************/
|
||||
void LDMA_StopTransfer(int ch)
|
||||
{
|
||||
uint32_t chMask = 1 << ch;
|
||||
|
||||
EFM_ASSERT(ch < DMA_CHAN_COUNT);
|
||||
|
||||
CORE_ATOMIC_SECTION(
|
||||
LDMA->IEN &= ~chMask;
|
||||
BUS_RegMaskedClear(&LDMA->CHEN, chMask);
|
||||
)
|
||||
}
|
||||
|
||||
/***************************************************************************//**
|
||||
* @brief
|
||||
* Check if a DMA transfer has completed.
|
||||
*
|
||||
* @param[in] ch
|
||||
* DMA channel to check.
|
||||
*
|
||||
* @return
|
||||
* True if transfer has completed, false if not.
|
||||
******************************************************************************/
|
||||
bool LDMA_TransferDone(int ch)
|
||||
{
|
||||
bool retVal = false;
|
||||
uint32_t chMask = 1 << ch;
|
||||
|
||||
EFM_ASSERT(ch < DMA_CHAN_COUNT);
|
||||
|
||||
CORE_ATOMIC_SECTION(
|
||||
if (((LDMA->CHEN & chMask) == 0)
|
||||
&& ((LDMA->CHDONE & chMask) == chMask)) {
|
||||
retVal = true;
|
||||
}
|
||||
)
|
||||
return retVal;
|
||||
}
|
||||
|
||||
/***************************************************************************//**
|
||||
* @brief
|
||||
* Get number of items remaining in a transfer.
|
||||
*
|
||||
* @note
|
||||
* This function is does not take into account that a DMA transfers with
|
||||
* a chain of linked transfers might be ongoing. It will only check the
|
||||
* count for the current transfer.
|
||||
*
|
||||
* @param[in] ch
|
||||
* The channel number of the transfer to check.
|
||||
*
|
||||
* @return
|
||||
* Number of items remaining in the transfer.
|
||||
******************************************************************************/
|
||||
uint32_t LDMA_TransferRemainingCount(int ch)
|
||||
{
|
||||
uint32_t remaining, done, iflag;
|
||||
uint32_t chMask = 1 << ch;
|
||||
|
||||
EFM_ASSERT(ch < DMA_CHAN_COUNT);
|
||||
|
||||
CORE_ATOMIC_SECTION(
|
||||
iflag = LDMA->IF;
|
||||
done = LDMA->CHDONE;
|
||||
remaining = LDMA->CH[ch].CTRL;
|
||||
)
|
||||
|
||||
iflag &= chMask;
|
||||
done &= chMask;
|
||||
remaining = (remaining & _LDMA_CH_CTRL_XFERCNT_MASK)
|
||||
>> _LDMA_CH_CTRL_XFERCNT_SHIFT;
|
||||
|
||||
if (done || ((remaining == 0) && iflag)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return remaining + 1;
|
||||
}
|
||||
|
||||
/** @} (end addtogroup LDMA) */
|
||||
/** @} (end addtogroup emlib) */
|
||||
#endif /* defined( LDMA_PRESENT ) && ( LDMA_COUNT == 1 ) */
|
File diff suppressed because it is too large
Load Diff
@ -1,114 +0,0 @@
|
||||
/***************************************************************************//**
|
||||
* @file em_system.c
|
||||
* @brief System 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_system.h"
|
||||
#include "em_assert.h"
|
||||
#include <stddef.h>
|
||||
|
||||
/***************************************************************************//**
|
||||
* @addtogroup emlib
|
||||
* @{
|
||||
******************************************************************************/
|
||||
|
||||
/***************************************************************************//**
|
||||
* @addtogroup SYSTEM
|
||||
* @{
|
||||
******************************************************************************/
|
||||
|
||||
/*******************************************************************************
|
||||
************************** GLOBAL FUNCTIONS *******************************
|
||||
******************************************************************************/
|
||||
|
||||
/***************************************************************************//**
|
||||
* @brief
|
||||
* Get chip major/minor revision.
|
||||
*
|
||||
* @param[out] rev
|
||||
* Location to place chip revision info.
|
||||
******************************************************************************/
|
||||
void SYSTEM_ChipRevisionGet(SYSTEM_ChipRevision_TypeDef *rev)
|
||||
{
|
||||
uint8_t tmp;
|
||||
|
||||
EFM_ASSERT(rev);
|
||||
|
||||
/* CHIP FAMILY bit [5:2] */
|
||||
tmp = (((ROMTABLE->PID1 & _ROMTABLE_PID1_FAMILYMSB_MASK) >> _ROMTABLE_PID1_FAMILYMSB_SHIFT) << 2);
|
||||
/* CHIP FAMILY bit [1:0] */
|
||||
tmp |= ((ROMTABLE->PID0 & _ROMTABLE_PID0_FAMILYLSB_MASK) >> _ROMTABLE_PID0_FAMILYLSB_SHIFT);
|
||||
rev->family = tmp;
|
||||
|
||||
/* CHIP MAJOR bit [3:0] */
|
||||
rev->major = (ROMTABLE->PID0 & _ROMTABLE_PID0_REVMAJOR_MASK) >> _ROMTABLE_PID0_REVMAJOR_SHIFT;
|
||||
|
||||
/* CHIP MINOR bit [7:4] */
|
||||
tmp = (((ROMTABLE->PID2 & _ROMTABLE_PID2_REVMINORMSB_MASK) >> _ROMTABLE_PID2_REVMINORMSB_SHIFT) << 4);
|
||||
/* CHIP MINOR bit [3:0] */
|
||||
tmp |= ((ROMTABLE->PID3 & _ROMTABLE_PID3_REVMINORLSB_MASK) >> _ROMTABLE_PID3_REVMINORLSB_SHIFT);
|
||||
rev->minor = tmp;
|
||||
}
|
||||
|
||||
/***************************************************************************//**
|
||||
* @brief
|
||||
* Get factory calibration value for a given peripheral register.
|
||||
*
|
||||
* @param[in] regAddress
|
||||
* Peripheral calibration register address to get calibration value for. If
|
||||
* a calibration value is found then this register is updated with the
|
||||
* calibration value.
|
||||
*
|
||||
* @return
|
||||
* True if a calibration value exists, false otherwise.
|
||||
******************************************************************************/
|
||||
bool SYSTEM_GetCalibrationValue(volatile uint32_t *regAddress)
|
||||
{
|
||||
SYSTEM_CalAddrVal_TypeDef * p, * end;
|
||||
|
||||
p = (SYSTEM_CalAddrVal_TypeDef *)(DEVINFO_BASE & 0xFFFFF000);
|
||||
end = (SYSTEM_CalAddrVal_TypeDef *)DEVINFO_BASE;
|
||||
|
||||
for (; p < end; p++) {
|
||||
if (p->address == 0xFFFFFFFF) {
|
||||
/* Found table terminator */
|
||||
return false;
|
||||
}
|
||||
if (p->address == (uint32_t)regAddress) {
|
||||
*regAddress = p->calValue;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
/* Nothing found for regAddress */
|
||||
return false;
|
||||
}
|
||||
|
||||
/** @} (end addtogroup SYSTEM) */
|
||||
/** @} (end addtogroup emlib) */
|
@ -1,253 +0,0 @@
|
||||
/***************************************************************************//**
|
||||
* @file em_timer.c
|
||||
* @brief Timer/counter (TIMER) 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_timer.h"
|
||||
#if defined(TIMER_COUNT) && (TIMER_COUNT > 0)
|
||||
|
||||
#include "em_assert.h"
|
||||
|
||||
/***************************************************************************//**
|
||||
* @addtogroup emlib
|
||||
* @{
|
||||
******************************************************************************/
|
||||
|
||||
/***************************************************************************//**
|
||||
* @addtogroup TIMER
|
||||
* @brief Timer/Counter (TIMER) Peripheral API
|
||||
* @details
|
||||
* The timer module consists of three main parts:
|
||||
* @li General timer config and enable control.
|
||||
* @li Compare/capture control.
|
||||
* @li Dead time insertion control (may not be available for all timers).
|
||||
* @{
|
||||
******************************************************************************/
|
||||
|
||||
/*******************************************************************************
|
||||
************************** GLOBAL FUNCTIONS *******************************
|
||||
******************************************************************************/
|
||||
|
||||
/***************************************************************************//**
|
||||
* @brief
|
||||
* Initialize TIMER.
|
||||
*
|
||||
* @details
|
||||
* Notice that counter top must be configured separately with for instance
|
||||
* TIMER_TopSet(). In addition, compare/capture and dead-time insertion
|
||||
* init must be initialized separately if used. That should probably
|
||||
* be done prior to the use of this function if configuring the TIMER to
|
||||
* start when initialization is completed.
|
||||
*
|
||||
* @param[in] timer
|
||||
* Pointer to TIMER peripheral register block.
|
||||
*
|
||||
* @param[in] init
|
||||
* Pointer to TIMER initialization structure.
|
||||
******************************************************************************/
|
||||
void TIMER_Init(TIMER_TypeDef *timer, const TIMER_Init_TypeDef *init)
|
||||
{
|
||||
EFM_ASSERT(TIMER_REF_VALID(timer));
|
||||
|
||||
/* Stop timer if specified to be disabled (dosn't hurt if already stopped) */
|
||||
if (!(init->enable)) {
|
||||
timer->CMD = TIMER_CMD_STOP;
|
||||
}
|
||||
|
||||
/* Reset counter */
|
||||
timer->CNT = _TIMER_CNT_RESETVALUE;
|
||||
|
||||
timer->CTRL = ((uint32_t)(init->prescale) << _TIMER_CTRL_PRESC_SHIFT)
|
||||
| ((uint32_t)(init->clkSel) << _TIMER_CTRL_CLKSEL_SHIFT)
|
||||
| ((uint32_t)(init->fallAction) << _TIMER_CTRL_FALLA_SHIFT)
|
||||
| ((uint32_t)(init->riseAction) << _TIMER_CTRL_RISEA_SHIFT)
|
||||
| ((uint32_t)(init->mode) << _TIMER_CTRL_MODE_SHIFT)
|
||||
| (init->debugRun ? TIMER_CTRL_DEBUGRUN : 0)
|
||||
| (init->dmaClrAct ? TIMER_CTRL_DMACLRACT : 0)
|
||||
| (init->quadModeX4 ? TIMER_CTRL_QDM_X4 : 0)
|
||||
| (init->oneShot ? TIMER_CTRL_OSMEN : 0)
|
||||
|
||||
#if defined(TIMER_CTRL_X2CNT) && defined(TIMER_CTRL_ATI)
|
||||
| (init->count2x ? TIMER_CTRL_X2CNT : 0)
|
||||
| (init->ati ? TIMER_CTRL_ATI : 0)
|
||||
#endif
|
||||
| (init->sync ? TIMER_CTRL_SYNC : 0);
|
||||
|
||||
/* Start timer if specified to be enabled (dosn't hurt if already started) */
|
||||
if (init->enable) {
|
||||
timer->CMD = TIMER_CMD_START;
|
||||
}
|
||||
}
|
||||
|
||||
/***************************************************************************//**
|
||||
* @brief
|
||||
* Initialize TIMER compare/capture channel.
|
||||
*
|
||||
* @details
|
||||
* Notice that if operating channel in compare mode, the CCV and CCVB register
|
||||
* must be set separately as required.
|
||||
*
|
||||
* @param[in] timer
|
||||
* Pointer to TIMER peripheral register block.
|
||||
*
|
||||
* @param[in] ch
|
||||
* Compare/capture channel to init for.
|
||||
*
|
||||
* @param[in] init
|
||||
* Pointer to TIMER initialization structure.
|
||||
******************************************************************************/
|
||||
void TIMER_InitCC(TIMER_TypeDef *timer,
|
||||
unsigned int ch,
|
||||
const TIMER_InitCC_TypeDef *init)
|
||||
{
|
||||
EFM_ASSERT(TIMER_REF_VALID(timer));
|
||||
EFM_ASSERT(TIMER_CH_VALID(ch));
|
||||
|
||||
timer->CC[ch].CTRL =
|
||||
((uint32_t)(init->eventCtrl) << _TIMER_CC_CTRL_ICEVCTRL_SHIFT)
|
||||
| ((uint32_t)(init->edge) << _TIMER_CC_CTRL_ICEDGE_SHIFT)
|
||||
| ((uint32_t)(init->prsSel) << _TIMER_CC_CTRL_PRSSEL_SHIFT)
|
||||
| ((uint32_t)(init->cufoa) << _TIMER_CC_CTRL_CUFOA_SHIFT)
|
||||
| ((uint32_t)(init->cofoa) << _TIMER_CC_CTRL_COFOA_SHIFT)
|
||||
| ((uint32_t)(init->cmoa) << _TIMER_CC_CTRL_CMOA_SHIFT)
|
||||
| ((uint32_t)(init->mode) << _TIMER_CC_CTRL_MODE_SHIFT)
|
||||
| (init->filter ? TIMER_CC_CTRL_FILT_ENABLE : 0)
|
||||
| (init->prsInput ? TIMER_CC_CTRL_INSEL_PRS : 0)
|
||||
| (init->coist ? TIMER_CC_CTRL_COIST : 0)
|
||||
| (init->outInvert ? TIMER_CC_CTRL_OUTINV : 0);
|
||||
}
|
||||
|
||||
#if defined(_TIMER_DTCTRL_MASK)
|
||||
/***************************************************************************//**
|
||||
* @brief
|
||||
* Initialize the TIMER DTI unit.
|
||||
*
|
||||
* @param[in] timer
|
||||
* Pointer to TIMER peripheral register block.
|
||||
*
|
||||
* @param[in] init
|
||||
* Pointer to TIMER DTI initialization structure.
|
||||
******************************************************************************/
|
||||
void TIMER_InitDTI(TIMER_TypeDef *timer, const TIMER_InitDTI_TypeDef *init)
|
||||
{
|
||||
EFM_ASSERT(TIMER0 == timer);
|
||||
|
||||
/* Make sure the DTI unit is disabled while initializing. */
|
||||
TIMER_EnableDTI(timer, false);
|
||||
|
||||
/* Setup the DTCTRL register.
|
||||
The enable bit will be set at the end of the function if specified. */
|
||||
timer->DTCTRL =
|
||||
(init->autoRestart ? TIMER_DTCTRL_DTDAS : 0)
|
||||
| (init->activeLowOut ? TIMER_DTCTRL_DTIPOL : 0)
|
||||
| (init->invertComplementaryOut ? TIMER_DTCTRL_DTCINV : 0)
|
||||
| (init->enablePrsSource ? TIMER_DTCTRL_DTPRSEN : 0)
|
||||
| ((uint32_t)(init->prsSel) << _TIMER_DTCTRL_DTPRSSEL_SHIFT);
|
||||
|
||||
/* Setup the DTTIME register. */
|
||||
timer->DTTIME =
|
||||
((uint32_t)(init->prescale) << _TIMER_DTTIME_DTPRESC_SHIFT)
|
||||
| ((uint32_t)(init->riseTime) << _TIMER_DTTIME_DTRISET_SHIFT)
|
||||
| ((uint32_t)(init->fallTime) << _TIMER_DTTIME_DTFALLT_SHIFT);
|
||||
|
||||
/* Setup the DTFC register. */
|
||||
timer->DTFC =
|
||||
(init->enableFaultSourceCoreLockup ? TIMER_DTFC_DTLOCKUPFEN : 0)
|
||||
| (init->enableFaultSourceDebugger ? TIMER_DTFC_DTDBGFEN : 0)
|
||||
| (init->enableFaultSourcePrsSel0 ? TIMER_DTFC_DTPRS0FEN : 0)
|
||||
| (init->enableFaultSourcePrsSel1 ? TIMER_DTFC_DTPRS1FEN : 0)
|
||||
| ((uint32_t)(init->faultAction) << _TIMER_DTFC_DTFA_SHIFT)
|
||||
| ((uint32_t)(init->faultSourcePrsSel0) << _TIMER_DTFC_DTPRS0FSEL_SHIFT)
|
||||
| ((uint32_t)(init->faultSourcePrsSel1) << _TIMER_DTFC_DTPRS1FSEL_SHIFT);
|
||||
|
||||
/* Setup the DTOGEN register. */
|
||||
timer->DTOGEN = init->outputsEnableMask;
|
||||
|
||||
/* Clear any previous DTI faults. */
|
||||
TIMER_ClearDTIFault(timer, TIMER_GetDTIFault(timer));
|
||||
|
||||
/* Enable/disable before returning. */
|
||||
TIMER_EnableDTI(timer, init->enable);
|
||||
}
|
||||
#endif
|
||||
|
||||
/***************************************************************************//**
|
||||
* @brief
|
||||
* Reset TIMER 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] timer
|
||||
* Pointer to TIMER peripheral register block.
|
||||
******************************************************************************/
|
||||
void TIMER_Reset(TIMER_TypeDef *timer)
|
||||
{
|
||||
int i;
|
||||
|
||||
EFM_ASSERT(TIMER_REF_VALID(timer));
|
||||
|
||||
/* Make sure disabled first, before resetting other registers */
|
||||
timer->CMD = TIMER_CMD_STOP;
|
||||
|
||||
timer->CTRL = _TIMER_CTRL_RESETVALUE;
|
||||
timer->IEN = _TIMER_IEN_RESETVALUE;
|
||||
timer->IFC = _TIMER_IFC_MASK;
|
||||
timer->TOPB = _TIMER_TOPB_RESETVALUE;
|
||||
/* Write TOP after TOPB to invalidate TOPB (clear TIMER_STATUS_TOPBV) */
|
||||
timer->TOP = _TIMER_TOP_RESETVALUE;
|
||||
timer->CNT = _TIMER_CNT_RESETVALUE;
|
||||
/* Do not reset route register, setting should be done independently */
|
||||
/* (Note: ROUTE register may be locked by DTLOCK register.) */
|
||||
|
||||
for (i = 0; TIMER_CH_VALID(i); i++) {
|
||||
timer->CC[i].CTRL = _TIMER_CC_CTRL_RESETVALUE;
|
||||
timer->CC[i].CCV = _TIMER_CC_CCV_RESETVALUE;
|
||||
timer->CC[i].CCVB = _TIMER_CC_CCVB_RESETVALUE;
|
||||
}
|
||||
|
||||
/* Reset dead time insertion module, no effect on timers without DTI */
|
||||
|
||||
#if defined(TIMER_DTLOCK_LOCKKEY_UNLOCK)
|
||||
/* Unlock DTI registers first in case locked */
|
||||
timer->DTLOCK = TIMER_DTLOCK_LOCKKEY_UNLOCK;
|
||||
|
||||
timer->DTCTRL = _TIMER_DTCTRL_RESETVALUE;
|
||||
timer->DTTIME = _TIMER_DTTIME_RESETVALUE;
|
||||
timer->DTFC = _TIMER_DTFC_RESETVALUE;
|
||||
timer->DTOGEN = _TIMER_DTOGEN_RESETVALUE;
|
||||
timer->DTFAULTC = _TIMER_DTFAULTC_MASK;
|
||||
#endif
|
||||
}
|
||||
|
||||
/** @} (end addtogroup TIMER) */
|
||||
/** @} (end addtogroup emlib) */
|
||||
#endif /* defined(TIMER_COUNT) && (TIMER_COUNT > 0) */
|
File diff suppressed because it is too large
Load Diff
@ -1,48 +0,0 @@
|
||||
//=========================================================
|
||||
// inc/InitDevice.h: generated by Hardware Configurator
|
||||
//
|
||||
// This file will be regenerated when saving a document.
|
||||
// leave the sections inside the "$[...]" comment tags alone
|
||||
// or they will be overwritten!
|
||||
//=========================================================
|
||||
#ifndef __INIT_DEVICE_H__
|
||||
#define __INIT_DEVICE_H__
|
||||
|
||||
// USER CONSTANTS
|
||||
// USER PROTOTYPES
|
||||
|
||||
// $[Mode Transition Prototypes]
|
||||
extern void enter_DefaultMode_from_RESET(void);
|
||||
// [Mode Transition Prototypes]$
|
||||
|
||||
// $[Config(Per-Module Mode)Transition Prototypes]
|
||||
extern void EMU_enter_DefaultMode_from_RESET(void);
|
||||
extern void LFXO_enter_DefaultMode_from_RESET(void);
|
||||
extern void CMU_enter_DefaultMode_from_RESET(void);
|
||||
extern void ADC0_enter_DefaultMode_from_RESET(void);
|
||||
extern void ACMP0_enter_DefaultMode_from_RESET(void);
|
||||
extern void ACMP1_enter_DefaultMode_from_RESET(void);
|
||||
extern void IDAC0_enter_DefaultMode_from_RESET(void);
|
||||
extern void RTCC_enter_DefaultMode_from_RESET(void);
|
||||
extern void USART0_enter_DefaultMode_from_RESET(void);
|
||||
extern void USART1_enter_DefaultMode_from_RESET(void);
|
||||
extern void LEUART0_enter_DefaultMode_from_RESET(void);
|
||||
extern void WDOG0_enter_DefaultMode_from_RESET(void);
|
||||
extern void I2C0_enter_DefaultMode_from_RESET(void);
|
||||
extern void GPCRC_enter_DefaultMode_from_RESET(void);
|
||||
extern void LDMA_enter_DefaultMode_from_RESET(void);
|
||||
extern void TIMER0_enter_DefaultMode_from_RESET(void);
|
||||
extern void TIMER1_enter_DefaultMode_from_RESET(void);
|
||||
extern void LETIMER0_enter_DefaultMode_from_RESET(void);
|
||||
extern void CRYOTIMER_enter_DefaultMode_from_RESET(void);
|
||||
extern void PCNT0_enter_DefaultMode_from_RESET(void);
|
||||
extern void PRS_enter_DefaultMode_from_RESET(void);
|
||||
extern void PORTIO_enter_DefaultMode_from_RESET(void);
|
||||
// [Config(Per-Module Mode)Transition Prototypes]$
|
||||
|
||||
// $[User-defined pin name abstraction]
|
||||
|
||||
// [User-defined pin name abstraction]$
|
||||
|
||||
#endif
|
||||
|
@ -1,35 +0,0 @@
|
||||
/*
|
||||
* app.h
|
||||
*
|
||||
* Created on: Jun 26, 2018
|
||||
* Author: conor
|
||||
*/
|
||||
|
||||
#ifndef SRC_APP_H_
|
||||
#define SRC_APP_H_
|
||||
|
||||
#define DEBUG_LEVEL 1
|
||||
|
||||
//#define PRINTING_USE_VCOM
|
||||
|
||||
//#define USING_DEV_BOARD
|
||||
|
||||
//#define ENABLE_U2F_EXTENSIONS
|
||||
|
||||
#define ENABLE_U2F
|
||||
|
||||
//#define DISABLE_CTAPHID_PING
|
||||
//#define DISABLE_CTAPHID_WINK
|
||||
//#define DISABLE_CTAPHID_CBOR
|
||||
|
||||
void printing_init();
|
||||
|
||||
//#define TEST
|
||||
//#define TEST_POWER
|
||||
|
||||
// GPIO assignments
|
||||
#define NFC_DEV_SS gpioPortF,2
|
||||
|
||||
#define LED_INIT_VALUE 0x001000
|
||||
|
||||
#endif /* SRC_APP_H_ */
|
@ -1,278 +0,0 @@
|
||||
/*
|
||||
* Configuration for enabling CRYPTO hardware acceleration in all mbedtls
|
||||
* modules when running on SiliconLabs devices.
|
||||
*
|
||||
* Copyright (C) 2016, Silicon Labs, http://www.silabs.com
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @defgroup sl_crypto_config Silicon Labs CRYPTO Hardware Acceleration Configuration
|
||||
* @addtogroup sl_crypto_config
|
||||
*
|
||||
* @brief
|
||||
* mbed TLS configuration for Silicon Labs CRYPTO hardware acceleration
|
||||
*
|
||||
* @details
|
||||
* mbed TLS configuration is composed of settings in this Silicon Labs specific CRYPTO hardware acceleration file located in mbedtls/configs and the mbed TLS configuration file in mbedtls/include/mbedtls/config.h.
|
||||
* This configuration can be used as a starting point to evaluate hardware acceleration available on Silicon Labs devices.
|
||||
*
|
||||
* @{
|
||||
*/
|
||||
|
||||
#ifndef MBEDTLS_CONFIG_SL_CRYPTO_ALL_ACCELERATION_H
|
||||
#define MBEDTLS_CONFIG_SL_CRYPTO_ALL_ACCELERATION_H
|
||||
|
||||
#include "em_device.h"
|
||||
|
||||
#if !defined(NO_CRYPTO_ACCELERATION)
|
||||
/**
|
||||
* @name SECTION: Silicon Labs Acceleration settings
|
||||
*
|
||||
* This section sets Silicon Labs Acceleration settings.
|
||||
* @{
|
||||
|
||||
*/
|
||||
|
||||
/**
|
||||
* \def MBEDTLS_AES_ALT
|
||||
*
|
||||
* Enable hardware acceleration for the AES block cipher
|
||||
*
|
||||
* Module: sl_crypto/src/crypto_aes.c for devices with CRYPTO
|
||||
* sl_crypto/src/aes_aes.c for devices with AES
|
||||
*
|
||||
* See MBEDTLS_AES_C for more information.
|
||||
*/
|
||||
#define MBEDTLS_AES_ALT
|
||||
#define MBEDTLS_ECP_ALT
|
||||
/**
|
||||
* \def MBEDTLS_ECP_INTERNAL_ALT
|
||||
* \def ECP_SHORTWEIERSTRASS
|
||||
* \def MBEDTLS_ECP_ADD_MIXED_ALT
|
||||
* \def MBEDTLS_ECP_DOUBLE_JAC_ALT
|
||||
* \def MBEDTLS_ECP_NORMALIZE_JAC_MANY_ALT
|
||||
* \def MBEDTLS_ECP_NORMALIZE_JAC_ALT
|
||||
*
|
||||
* Enable hardware acceleration for the elliptic curve over GF(p) library.
|
||||
*
|
||||
* Module: sl_crypto/src/crypto_ecp.c
|
||||
* Caller: library/ecp.c
|
||||
*
|
||||
* Requires: MBEDTLS_BIGNUM_C, MBEDTLS_ECP_C and at least one
|
||||
* MBEDTLS_ECP_DP_XXX_ENABLED and (CRYPTO_COUNT > 0)
|
||||
*/
|
||||
#if defined(CRYPTO_COUNT) && (CRYPTO_COUNT > 0)
|
||||
#define MBEDTLS_ECP_INTERNAL_ALT
|
||||
#define ECP_SHORTWEIERSTRASS
|
||||
#define MBEDTLS_ECP_ADD_MIXED_ALT
|
||||
#define MBEDTLS_ECP_DOUBLE_JAC_ALT
|
||||
#define MBEDTLS_ECP_NORMALIZE_JAC_MANY_ALT
|
||||
#define MBEDTLS_ECP_NORMALIZE_JAC_ALT
|
||||
#define MBEDTLS_ECP_RANDOMIZE_JAC_ALT
|
||||
#endif
|
||||
|
||||
/**
|
||||
* \def MBEDTLS_SHA1_ALT
|
||||
*
|
||||
* Enable hardware acceleration for the SHA1 cryptographic hash algorithm.
|
||||
*
|
||||
* Module: sl_crypto/src/crypto_sha.c
|
||||
* Caller: library/mbedtls_md.c
|
||||
* library/ssl_cli.c
|
||||
* library/ssl_srv.c
|
||||
* library/ssl_tls.c
|
||||
* library/x509write_crt.c
|
||||
*
|
||||
* Requires: MBEDTLS_SHA1_C and (CRYPTO_COUNT > 0)
|
||||
* See MBEDTLS_SHA1_C for more information.
|
||||
*/
|
||||
#if defined(CRYPTO_COUNT) && (CRYPTO_COUNT > 0)
|
||||
#define MBEDTLS_SHA1_ALT
|
||||
#endif
|
||||
|
||||
/**
|
||||
* \def MBEDTLS_SHA256_ALT
|
||||
*
|
||||
* Enable hardware acceleration for the SHA-224 and SHA-256 cryptographic
|
||||
* hash algorithms.
|
||||
*
|
||||
* Module: sl_crypto/src/crypto_sha.c
|
||||
* Caller: library/entropy.c
|
||||
* library/mbedtls_md.c
|
||||
* library/ssl_cli.c
|
||||
* library/ssl_srv.c
|
||||
* library/ssl_tls.c
|
||||
*
|
||||
* Requires: MBEDTLS_SHA256_C and (CRYPTO_COUNT > 0)
|
||||
* See MBEDTLS_SHA256_C for more information.
|
||||
*/
|
||||
#if defined(CRYPTO_COUNT) && (CRYPTO_COUNT > 0)
|
||||
#define MBEDTLS_SHA256_ALT
|
||||
#endif
|
||||
|
||||
#endif /* #if !defined(NO_CRYPTO_ACCELERATION) */
|
||||
|
||||
/**
|
||||
* \def MBEDTLS_TRNG_C
|
||||
*
|
||||
* Enable software support for the True Random Number Generator (TRNG)
|
||||
* incorporated from Series 1 Configuration 2 devices (EFR32MG12, etc.)
|
||||
* from Silicon Labs.
|
||||
*
|
||||
* TRNG is not supported by software for EFR32XG13 (SDID_89) and
|
||||
* EFR32XG14 (SDID_95).
|
||||
*
|
||||
* Requires TRNG_PRESENT &&
|
||||
* !(_SILICON_LABS_GECKO_INTERNAL_SDID_89 ||
|
||||
* _SILICON_LABS_GECKO_INTERNAL_SDID_95)
|
||||
*/
|
||||
#if defined(TRNG_PRESENT) && \
|
||||
!(defined(_SILICON_LABS_GECKO_INTERNAL_SDID_89) || \
|
||||
defined(_SILICON_LABS_GECKO_INTERNAL_SDID_95))
|
||||
#define MBEDTLS_TRNG_C
|
||||
#endif
|
||||
|
||||
/**
|
||||
* \def MBEDTLS_ENTROPY_ADC_C
|
||||
*
|
||||
* Enable software support for the retrieving entropy data from the ADC
|
||||
* incorporated on devices from Silicon Labs.
|
||||
*
|
||||
* Requires ADC_PRESENT && _ADC_SINGLECTRLX_VREFSEL_VENTROPY
|
||||
*/
|
||||
#if defined(ADC_PRESENT) && defined(_ADC_SINGLECTRLX_VREFSEL_VENTROPY)
|
||||
#define MBEDTLS_ENTROPY_ADC_C
|
||||
#endif
|
||||
|
||||
/**
|
||||
* \def MBEDTLS_ENTROPY_ADC_INSTANCE
|
||||
*
|
||||
* Specify which ADC instance shall be used as entropy source.
|
||||
*
|
||||
* Requires MBEDTLS_ENTROPY_ADC_C
|
||||
*/
|
||||
#if defined(MBEDTLS_ENTROPY_ADC_C)
|
||||
#define MBEDTLS_ENTROPY_ADC_INSTANCE (0)
|
||||
#endif
|
||||
|
||||
/**
|
||||
* \def MBEDTLS_ENTROPY_RAIL_C
|
||||
*
|
||||
* Enable software support for the retrieving entropy data from the RAIL
|
||||
* incorporated on devices from Silicon Labs.
|
||||
*
|
||||
* Requires _EFR_DEVICE
|
||||
*/
|
||||
#if defined(_EFR_DEVICE)
|
||||
#define MBEDTLS_ENTROPY_RAIL_C
|
||||
#endif
|
||||
|
||||
/**
|
||||
* \def MBEDTLS_ENTROPY_HARDWARE_ALT_RAIL
|
||||
*
|
||||
* Use the radio (RAIL) as default hardware entropy source.
|
||||
*
|
||||
* Requires MBEDTLS_ENTROPY_RAIL_C && _EFR_DEVICE && !MBEDTLS_TRNG_C
|
||||
*/
|
||||
#if defined(MBEDTLS_ENTROPY_RAIL_C) && \
|
||||
defined(_EFR_DEVICE) && !defined(MBEDTLS_TRNG_C)
|
||||
#define MBEDTLS_ENTROPY_HARDWARE_ALT_RAIL
|
||||
#endif
|
||||
|
||||
/**
|
||||
* \def MBEDTLS_ENTROPY_HARDWARE_ALT
|
||||
*
|
||||
* Integrate the provided default entropy source into the mbed
|
||||
* TLS entropy infrastructure.
|
||||
*
|
||||
* Requires MBEDTLS_TRNG_C || MBEDTLS_ENTROPY_HARDWARE_ALT_RAIL
|
||||
*/
|
||||
#if defined(MBEDTLS_TRNG_C) || defined(MBEDTLS_ENTROPY_HARDWARE_ALT_RAIL)
|
||||
#define MBEDTLS_ENTROPY_HARDWARE_ALT
|
||||
#endif
|
||||
|
||||
/* Default ECC configuration for Silicon Labs devices: */
|
||||
|
||||
/* ECC curves supported by CRYPTO hardware module: */
|
||||
#define MBEDTLS_ECP_DP_SECP192R1_ENABLED
|
||||
#define MBEDTLS_ECP_DP_SECP224R1_ENABLED
|
||||
#define MBEDTLS_ECP_DP_SECP256R1_ENABLED
|
||||
|
||||
/* Save RAM by adjusting to our exact needs */
|
||||
#define MBEDTLS_ECP_MAX_BITS 256
|
||||
#ifndef MBEDTLS_MPI_MAX_SIZE
|
||||
#define MBEDTLS_MPI_MAX_SIZE 32 // 384 bits is 48 bytes
|
||||
#endif
|
||||
|
||||
/*
|
||||
Set MBEDTLS_ECP_WINDOW_SIZE to configure
|
||||
ECC point multiplication window size, see ecp.h:
|
||||
2 = Save RAM at the expense of speed
|
||||
3 = Improve speed at the expense of RAM
|
||||
4 = Optimize speed at the expense of RAM
|
||||
*/
|
||||
#define MBEDTLS_ECP_WINDOW_SIZE 3
|
||||
#define MBEDTLS_ECP_FIXED_POINT_OPTIM 0
|
||||
|
||||
/* Significant speed benefit at the expense of some ROM */
|
||||
#define MBEDTLS_ECP_NIST_OPTIM
|
||||
|
||||
/* Include the default mbed TLS config file */
|
||||
#include "mbedtls/config.h"
|
||||
|
||||
#undef MBEDTLS_TIMING_C
|
||||
#undef MBEDTLS_FS_IO
|
||||
#undef MBEDTLS_SHA512_C
|
||||
#undef MBEDTLS_ENTROPY_SHA512_ACCUMULATOR
|
||||
|
||||
#undef MBEDTLS_NET_C
|
||||
|
||||
#define MBEDTLS_ECP_NORMALIZE_JAC_ALT
|
||||
#define MBEDTLS_ECP_DEVICE_ALT
|
||||
#define MBEDTLS_MPI_MODULAR_DIVISION_ALT
|
||||
|
||||
#define MBEDTLS_ECP_INTERNAL_ALT
|
||||
#define ECP_SHORTWEIERSTRASS
|
||||
#define MBEDTLS_ECP_ADD_MIXED_ALT
|
||||
#define MBEDTLS_ECP_DOUBLE_JAC_ALT
|
||||
#define MBEDTLS_ECP_NORMALIZE_JAC_MANY_ALT
|
||||
#define MBEDTLS_ECP_NORMALIZE_JAC_ALT
|
||||
#define MBEDTLS_ECP_RANDOMIZE_JAC_ALT
|
||||
#define MBEDTLS_ECP_DEVICE_ADD_MIXED_ALT
|
||||
|
||||
//#define MBEDTLS_ENTROPY_ALT
|
||||
|
||||
//#define MBEDTLS_MPI_MUL_MPI_ALT // doesnt seem to be implemented
|
||||
//#define MBEDTLS_MPI_MUL_INT_ALT // makes no difference or slightly slower
|
||||
|
||||
#define MBEDTLS_NO_PLATFORM_ENTROPY
|
||||
/* Hardware entropy source is not yet supported. Uncomment this macro to
|
||||
provide your own implementation of an entropy collector. */
|
||||
//#define MBEDTLS_ENTROPY_HARDWARE_ALT
|
||||
|
||||
/* Exclude and/or change default config here. E.g.: */
|
||||
//#undef MBEDTLS_ECP_DP_SECP384R1_ENABLED
|
||||
//#undef MBEDTLS_ECP_DP_SECP521R1_ENABLED
|
||||
//#undef MBEDTLS_ECP_DP_BP384R1_ENABLED
|
||||
//#undef MBEDTLS_ECP_DP_BP512R1_ENABLED
|
||||
//#undef MBEDTLS_SHA512_C
|
||||
|
||||
#include "mbedtls/check_config.h"
|
||||
|
||||
/** @} (end section sl_crypto_config) */
|
||||
/** @} (end addtogroup sl_crypto_config) */
|
||||
|
||||
#endif /* MBEDTLS_CONFIG_SL_CRYPTO_ALL_ACCELERATION_H */
|
@ -1,13 +0,0 @@
|
||||
/*
|
||||
* nfc.h
|
||||
*
|
||||
* Created on: Jul 22, 2018
|
||||
* Author: conor
|
||||
*/
|
||||
|
||||
#ifndef INC_NFC_H_
|
||||
#define INC_NFC_H_
|
||||
|
||||
void nfc_test();
|
||||
|
||||
#endif /* INC_NFC_H_ */
|
@ -1,752 +0,0 @@
|
||||
//=========================================================
|
||||
// src/InitDevice.c: generated by Hardware Configurator
|
||||
//
|
||||
// This file will be regenerated when saving a document.
|
||||
// leave the sections inside the "$[...]" comment tags alone
|
||||
// or they will be overwritten!
|
||||
//=========================================================
|
||||
|
||||
// USER INCLUDES
|
||||
#include "InitDevice.h"
|
||||
|
||||
// USER PROTOTYPES
|
||||
// USER FUNCTIONS
|
||||
|
||||
// $[Library includes]
|
||||
#include "em_system.h"
|
||||
#include "em_emu.h"
|
||||
#include "em_cmu.h"
|
||||
#include "em_device.h"
|
||||
#include "em_chip.h"
|
||||
#include "em_assert.h"
|
||||
#include "em_adc.h"
|
||||
#include "em_cryotimer.h"
|
||||
#include "em_crypto.h"
|
||||
#include "em_gpio.h"
|
||||
#include "em_timer.h"
|
||||
#include "em_usart.h"
|
||||
// [Library includes]$
|
||||
|
||||
//==============================================================================
|
||||
// enter_DefaultMode_from_RESET
|
||||
//==============================================================================
|
||||
extern void enter_DefaultMode_from_RESET(void) {
|
||||
// $[Config Calls]
|
||||
CHIP_Init();
|
||||
|
||||
EMU_enter_DefaultMode_from_RESET();
|
||||
CMU_enter_DefaultMode_from_RESET();
|
||||
ADC0_enter_DefaultMode_from_RESET();
|
||||
USART0_enter_DefaultMode_from_RESET();
|
||||
USART1_enter_DefaultMode_from_RESET();
|
||||
TIMER0_enter_DefaultMode_from_RESET();
|
||||
CRYOTIMER_enter_DefaultMode_from_RESET();
|
||||
PORTIO_enter_DefaultMode_from_RESET();
|
||||
// [Config Calls]$
|
||||
|
||||
}
|
||||
|
||||
//================================================================================
|
||||
// EMU_enter_DefaultMode_from_RESET
|
||||
//================================================================================
|
||||
extern void EMU_enter_DefaultMode_from_RESET(void) {
|
||||
|
||||
// $[EMU Initialization]
|
||||
/* External power circuit not wired for DCDC; shut down regulator */
|
||||
EMU_DCDCPowerOff();
|
||||
/* Initialize EM2/EM3 mode */
|
||||
EMU_EM23Init_TypeDef em23Init = EMU_EM23INIT_DEFAULT;
|
||||
|
||||
em23Init.em23VregFullEn = 0;
|
||||
|
||||
EMU_EM23Init(&em23Init);
|
||||
/* Initialize EM4H/S mode */
|
||||
EMU_EM4Init_TypeDef em4Init = EMU_EM4INIT_DEFAULT;
|
||||
|
||||
em4Init.retainLfrco = 0;
|
||||
em4Init.retainLfxo = 0;
|
||||
em4Init.retainUlfrco = 0;
|
||||
em4Init.em4State = emuEM4Shutoff;
|
||||
em4Init.pinRetentionMode = emuPinRetentionDisable;
|
||||
|
||||
EMU_EM4Init(&em4Init);
|
||||
// [EMU Initialization]$
|
||||
|
||||
}
|
||||
|
||||
//================================================================================
|
||||
// LFXO_enter_DefaultMode_from_RESET
|
||||
//================================================================================
|
||||
extern void LFXO_enter_DefaultMode_from_RESET(void) {
|
||||
|
||||
}
|
||||
|
||||
//================================================================================
|
||||
// CMU_enter_DefaultMode_from_RESET
|
||||
//================================================================================
|
||||
extern void CMU_enter_DefaultMode_from_RESET(void) {
|
||||
|
||||
// $[High Frequency Clock Setup]
|
||||
/* Initializing HFXO */
|
||||
CMU_HFXOInit_TypeDef hfxoInit = CMU_HFXOINIT_DEFAULT;
|
||||
|
||||
CMU_HFXOInit(&hfxoInit);
|
||||
|
||||
/* Setting system HFRCO frequency */
|
||||
CMU_HFRCOFreqSet (cmuHFRCOFreq_38M0Hz);
|
||||
|
||||
/* Using HFRCO as high frequency clock, HFCLK */
|
||||
CMU_ClockSelectSet(cmuClock_HF, cmuSelect_HFRCO);
|
||||
// [High Frequency Clock Setup]$
|
||||
|
||||
// $[LE clocks enable]
|
||||
/* Enable ULFRCO oscillator, and wait for it to be stable */
|
||||
CMU_OscillatorEnable(cmuOsc_ULFRCO, true, true);
|
||||
|
||||
// [LE clocks enable]$
|
||||
|
||||
// $[LFACLK Setup]
|
||||
/* LFACLK is disabled */
|
||||
// [LFACLK Setup]$
|
||||
// $[LFBCLK Setup]
|
||||
/* LFBCLK is disabled */
|
||||
// [LFBCLK Setup]$
|
||||
// $[LFECLK Setup]
|
||||
/* LFECLK is disabled */
|
||||
// [LFECLK Setup]$
|
||||
// $[Peripheral Clock enables]
|
||||
/* Enable clock for HF peripherals */
|
||||
CMU_ClockEnable(cmuClock_HFPER, true);
|
||||
|
||||
/* Enable clock for ADC0 */
|
||||
CMU_ClockEnable(cmuClock_ADC0, true);
|
||||
|
||||
/* Enable clock for CRYOTIMER */
|
||||
CMU_ClockEnable(cmuClock_CRYOTIMER, true);
|
||||
|
||||
/* Enable clock for TIMER0 */
|
||||
CMU_ClockEnable(cmuClock_TIMER0, true);
|
||||
|
||||
/* Enable clock for USART0 */
|
||||
CMU_ClockEnable(cmuClock_USART0, true);
|
||||
|
||||
/* Enable clock for USART1 */
|
||||
CMU_ClockEnable(cmuClock_USART1, true);
|
||||
|
||||
/* Enable clock for GPIO by default */
|
||||
CMU_ClockEnable(cmuClock_GPIO, true);
|
||||
|
||||
// [Peripheral Clock enables]$
|
||||
|
||||
// $[Clock output]
|
||||
/* Disable CLKOUT0 output */
|
||||
CMU->CTRL = (CMU->CTRL & ~_CMU_CTRL_CLKOUTSEL0_MASK)
|
||||
| CMU_CTRL_CLKOUTSEL0_DISABLED;
|
||||
/* Disable CLKOUT1 output */
|
||||
CMU->CTRL = (CMU->CTRL & ~_CMU_CTRL_CLKOUTSEL1_MASK)
|
||||
| CMU_CTRL_CLKOUTSEL1_DISABLED;
|
||||
|
||||
// [Clock output]$
|
||||
|
||||
// $[CMU_IO]
|
||||
/* Disable CLKOUT0 pin */
|
||||
CMU->ROUTEPEN &= ~CMU_ROUTEPEN_CLKOUT0PEN;
|
||||
|
||||
/* Disable CLKOUT1 pin */
|
||||
CMU->ROUTEPEN &= ~CMU_ROUTEPEN_CLKOUT1PEN;
|
||||
|
||||
// [CMU_IO]$
|
||||
|
||||
}
|
||||
|
||||
//================================================================================
|
||||
// ADC0_enter_DefaultMode_from_RESET
|
||||
//================================================================================
|
||||
extern void ADC0_enter_DefaultMode_from_RESET(void) {
|
||||
|
||||
// $[ADC0_Init]
|
||||
ADC_Init_TypeDef ADC0_init = ADC_INIT_DEFAULT;
|
||||
|
||||
ADC0_init.ovsRateSel = adcOvsRateSel2;
|
||||
ADC0_init.warmUpMode = adcWarmupNormal;
|
||||
ADC0_init.timebase = ADC_TimebaseCalc(0);
|
||||
ADC0_init.prescale = ADC_PrescaleCalc(7000000, 0);
|
||||
ADC0_init.tailgate = 0;
|
||||
ADC0_init.em2ClockConfig = adcEm2Disabled;
|
||||
|
||||
ADC_Init(ADC0, &ADC0_init);
|
||||
// [ADC0_Init]$
|
||||
|
||||
// $[ADC0_InputConfiguration]
|
||||
// [ADC0_InputConfiguration]$
|
||||
|
||||
}
|
||||
|
||||
//================================================================================
|
||||
// ACMP0_enter_DefaultMode_from_RESET
|
||||
//================================================================================
|
||||
extern void ACMP0_enter_DefaultMode_from_RESET(void) {
|
||||
|
||||
// $[ACMP0_Init]
|
||||
// [ACMP0_Init]$
|
||||
|
||||
// $[ACMP0_IO]
|
||||
// [ACMP0_IO]$
|
||||
|
||||
}
|
||||
|
||||
//================================================================================
|
||||
// ACMP1_enter_DefaultMode_from_RESET
|
||||
//================================================================================
|
||||
extern void ACMP1_enter_DefaultMode_from_RESET(void) {
|
||||
|
||||
// $[ACMP1_Init]
|
||||
// [ACMP1_Init]$
|
||||
|
||||
// $[ACMP1_IO]
|
||||
// [ACMP1_IO]$
|
||||
|
||||
}
|
||||
|
||||
//================================================================================
|
||||
// IDAC0_enter_DefaultMode_from_RESET
|
||||
//================================================================================
|
||||
extern void IDAC0_enter_DefaultMode_from_RESET(void) {
|
||||
|
||||
}
|
||||
|
||||
//================================================================================
|
||||
// RTCC_enter_DefaultMode_from_RESET
|
||||
//================================================================================
|
||||
extern void RTCC_enter_DefaultMode_from_RESET(void) {
|
||||
|
||||
// $[Compare/Capture Channel 0 init]
|
||||
// [Compare/Capture Channel 0 init]$
|
||||
|
||||
// $[Compare/Capture Channel 1 init]
|
||||
// [Compare/Capture Channel 1 init]$
|
||||
|
||||
// $[Compare/Capture Channel 2 init]
|
||||
// [Compare/Capture Channel 2 init]$
|
||||
|
||||
// $[RTCC init]
|
||||
// [RTCC init]$
|
||||
|
||||
}
|
||||
|
||||
//================================================================================
|
||||
// USART0_enter_DefaultMode_from_RESET
|
||||
//================================================================================
|
||||
extern void USART0_enter_DefaultMode_from_RESET(void) {
|
||||
|
||||
// $[USART_InitAsync]
|
||||
USART_InitAsync_TypeDef initasync = USART_INITASYNC_DEFAULT;
|
||||
|
||||
initasync.enable = usartDisable;
|
||||
initasync.baudrate = 115200;
|
||||
initasync.databits = usartDatabits8;
|
||||
initasync.parity = usartNoParity;
|
||||
initasync.stopbits = usartStopbits1;
|
||||
initasync.oversampling = usartOVS16;
|
||||
#if defined( USART_INPUT_RXPRS ) && defined( USART_CTRL_MVDIS )
|
||||
initasync.mvdis = 0;
|
||||
initasync.prsRxEnable = 0;
|
||||
initasync.prsRxCh = 0;
|
||||
#endif
|
||||
|
||||
USART_InitAsync(USART0, &initasync);
|
||||
// [USART_InitAsync]$
|
||||
|
||||
// $[USART_InitSync]
|
||||
// [USART_InitSync]$
|
||||
|
||||
// $[USART_InitPrsTrigger]
|
||||
USART_PrsTriggerInit_TypeDef initprs = USART_INITPRSTRIGGER_DEFAULT;
|
||||
|
||||
initprs.rxTriggerEnable = 0;
|
||||
initprs.txTriggerEnable = 0;
|
||||
initprs.prsTriggerChannel = usartPrsTriggerCh0;
|
||||
|
||||
USART_InitPrsTrigger(USART0, &initprs);
|
||||
// [USART_InitPrsTrigger]$
|
||||
|
||||
// $[USART_InitIO]
|
||||
/* Disable CLK pin */
|
||||
USART0->ROUTELOC0 = (USART0->ROUTELOC0 & (~_USART_ROUTELOC0_CLKLOC_MASK))
|
||||
| USART_ROUTELOC0_CLKLOC_LOC4;
|
||||
USART0->ROUTEPEN = USART0->ROUTEPEN & (~USART_ROUTEPEN_CLKPEN);
|
||||
|
||||
/* Disable CS pin */
|
||||
USART0->ROUTELOC0 = (USART0->ROUTELOC0 & (~_USART_ROUTELOC0_CSLOC_MASK))
|
||||
| USART_ROUTELOC0_CSLOC_LOC3;
|
||||
USART0->ROUTEPEN = USART0->ROUTEPEN & (~USART_ROUTEPEN_CSPEN);
|
||||
|
||||
/* Disable CTS pin */
|
||||
USART0->ROUTELOC1 = (USART0->ROUTELOC1 & (~_USART_ROUTELOC1_CTSLOC_MASK))
|
||||
| USART_ROUTELOC1_CTSLOC_LOC2;
|
||||
USART0->ROUTEPEN = USART0->ROUTEPEN & (~USART_ROUTEPEN_CTSPEN);
|
||||
|
||||
/* Disable RTS pin */
|
||||
USART0->ROUTELOC1 = (USART0->ROUTELOC1 & (~_USART_ROUTELOC1_RTSLOC_MASK))
|
||||
| USART_ROUTELOC1_RTSLOC_LOC1;
|
||||
USART0->ROUTEPEN = USART0->ROUTEPEN & (~USART_ROUTEPEN_RTSPEN);
|
||||
|
||||
/* Set up RX pin */
|
||||
USART0->ROUTELOC0 = (USART0->ROUTELOC0 & (~_USART_ROUTELOC0_RXLOC_MASK))
|
||||
| USART_ROUTELOC0_RXLOC_LOC0;
|
||||
USART0->ROUTEPEN = USART0->ROUTEPEN | USART_ROUTEPEN_RXPEN;
|
||||
|
||||
/* Set up TX pin */
|
||||
USART0->ROUTELOC0 = (USART0->ROUTELOC0 & (~_USART_ROUTELOC0_TXLOC_MASK))
|
||||
| USART_ROUTELOC0_TXLOC_LOC20;
|
||||
USART0->ROUTEPEN = USART0->ROUTEPEN | USART_ROUTEPEN_TXPEN;
|
||||
|
||||
// [USART_InitIO]$
|
||||
|
||||
// $[USART_Misc]
|
||||
/* Disable CTS */
|
||||
USART0->CTRLX = USART0->CTRLX & (~USART_CTRLX_CTSEN);
|
||||
/* Set CTS active low */
|
||||
USART0->CTRLX = USART0->CTRLX & (~USART_CTRLX_CTSINV);
|
||||
/* Set RTS active low */
|
||||
USART0->CTRLX = USART0->CTRLX & (~USART_CTRLX_RTSINV);
|
||||
/* Set CS active low */
|
||||
USART0->CTRL = USART0->CTRL & (~USART_CTRL_CSINV);
|
||||
/* Set TX active high */
|
||||
USART0->CTRL = USART0->CTRL & (~USART_CTRL_TXINV);
|
||||
/* Set RX active high */
|
||||
USART0->CTRL = USART0->CTRL & (~USART_CTRL_RXINV);
|
||||
// [USART_Misc]$
|
||||
|
||||
// $[USART_Enable]
|
||||
|
||||
/* Enable USART if opted by user */
|
||||
USART_Enable(USART0, usartEnable);
|
||||
// [USART_Enable]$
|
||||
|
||||
}
|
||||
|
||||
//================================================================================
|
||||
// USART1_enter_DefaultMode_from_RESET
|
||||
//================================================================================
|
||||
extern void USART1_enter_DefaultMode_from_RESET(void) {
|
||||
|
||||
// $[USART_InitAsync]
|
||||
// [USART_InitAsync]$
|
||||
|
||||
// $[USART_InitSync]
|
||||
USART_InitSync_TypeDef initsync = USART_INITSYNC_DEFAULT;
|
||||
|
||||
initsync.enable = usartDisable;
|
||||
initsync.baudrate = 130000;
|
||||
initsync.databits = usartDatabits8;
|
||||
initsync.master = 1;
|
||||
initsync.msbf = 1;
|
||||
initsync.clockMode = usartClockMode0;
|
||||
#if defined( USART_INPUT_RXPRS ) && defined( USART_TRIGCTRL_AUTOTXTEN )
|
||||
initsync.prsRxEnable = 0;
|
||||
initsync.prsRxCh = 0;
|
||||
initsync.autoTx = 0;
|
||||
#endif
|
||||
|
||||
USART_InitSync(USART1, &initsync);
|
||||
// [USART_InitSync]$
|
||||
|
||||
// $[USART_InitPrsTrigger]
|
||||
USART_PrsTriggerInit_TypeDef initprs = USART_INITPRSTRIGGER_DEFAULT;
|
||||
|
||||
initprs.rxTriggerEnable = 0;
|
||||
initprs.txTriggerEnable = 0;
|
||||
initprs.prsTriggerChannel = usartPrsTriggerCh0;
|
||||
|
||||
USART_InitPrsTrigger(USART1, &initprs);
|
||||
// [USART_InitPrsTrigger]$
|
||||
|
||||
// $[USART_InitIO]
|
||||
/* Set up CLK pin */
|
||||
USART1->ROUTELOC0 = (USART1->ROUTELOC0 & (~_USART_ROUTELOC0_CLKLOC_MASK))
|
||||
| USART_ROUTELOC0_CLKLOC_LOC4;
|
||||
USART1->ROUTEPEN = USART1->ROUTEPEN | USART_ROUTEPEN_CLKPEN;
|
||||
|
||||
/* Disable CS pin */
|
||||
USART1->ROUTELOC0 = (USART1->ROUTELOC0 & (~_USART_ROUTELOC0_CSLOC_MASK))
|
||||
| USART_ROUTELOC0_CSLOC_LOC3;
|
||||
USART1->ROUTEPEN = USART1->ROUTEPEN & (~USART_ROUTEPEN_CSPEN);
|
||||
|
||||
/* Disable CTS pin */
|
||||
USART1->ROUTELOC1 = (USART1->ROUTELOC1 & (~_USART_ROUTELOC1_CTSLOC_MASK))
|
||||
| USART_ROUTELOC1_CTSLOC_LOC2;
|
||||
USART1->ROUTEPEN = USART1->ROUTEPEN & (~USART_ROUTEPEN_CTSPEN);
|
||||
|
||||
/* Disable RTS pin */
|
||||
USART1->ROUTELOC1 = (USART1->ROUTELOC1 & (~_USART_ROUTELOC1_RTSLOC_MASK))
|
||||
| USART_ROUTELOC1_RTSLOC_LOC1;
|
||||
USART1->ROUTEPEN = USART1->ROUTEPEN & (~USART_ROUTEPEN_RTSPEN);
|
||||
|
||||
/* Set up RX pin */
|
||||
USART1->ROUTELOC0 = (USART1->ROUTELOC0 & (~_USART_ROUTELOC0_RXLOC_MASK))
|
||||
| USART_ROUTELOC0_RXLOC_LOC6;
|
||||
USART1->ROUTEPEN = USART1->ROUTEPEN | USART_ROUTEPEN_RXPEN;
|
||||
|
||||
/* Set up TX pin */
|
||||
USART1->ROUTELOC0 = (USART1->ROUTELOC0 & (~_USART_ROUTELOC0_TXLOC_MASK))
|
||||
| USART_ROUTELOC0_TXLOC_LOC8;
|
||||
USART1->ROUTEPEN = USART1->ROUTEPEN | USART_ROUTEPEN_TXPEN;
|
||||
|
||||
// [USART_InitIO]$
|
||||
|
||||
// $[USART_Misc]
|
||||
/* Disable CTS */
|
||||
USART1->CTRLX = USART1->CTRLX & (~USART_CTRLX_CTSEN);
|
||||
/* Set CTS active low */
|
||||
USART1->CTRLX = USART1->CTRLX & (~USART_CTRLX_CTSINV);
|
||||
/* Set RTS active low */
|
||||
USART1->CTRLX = USART1->CTRLX & (~USART_CTRLX_RTSINV);
|
||||
/* Set CS active low */
|
||||
USART1->CTRL = USART1->CTRL & (~USART_CTRL_CSINV);
|
||||
/* Set TX active high */
|
||||
USART1->CTRL = USART1->CTRL & (~USART_CTRL_TXINV);
|
||||
/* Set RX active high */
|
||||
USART1->CTRL = USART1->CTRL & (~USART_CTRL_RXINV);
|
||||
// [USART_Misc]$
|
||||
|
||||
// $[USART_Enable]
|
||||
|
||||
/* Enable USART if opted by user */
|
||||
USART_Enable(USART1, usartEnable);
|
||||
// [USART_Enable]$
|
||||
|
||||
}
|
||||
|
||||
//================================================================================
|
||||
// LEUART0_enter_DefaultMode_from_RESET
|
||||
//================================================================================
|
||||
extern void LEUART0_enter_DefaultMode_from_RESET(void) {
|
||||
|
||||
// $[LEUART0 initialization]
|
||||
// [LEUART0 initialization]$
|
||||
|
||||
}
|
||||
|
||||
//================================================================================
|
||||
// WDOG0_enter_DefaultMode_from_RESET
|
||||
//================================================================================
|
||||
extern void WDOG0_enter_DefaultMode_from_RESET(void) {
|
||||
|
||||
// $[WDOG Initialization]
|
||||
// [WDOG Initialization]$
|
||||
|
||||
}
|
||||
|
||||
//================================================================================
|
||||
// I2C0_enter_DefaultMode_from_RESET
|
||||
//================================================================================
|
||||
extern void I2C0_enter_DefaultMode_from_RESET(void) {
|
||||
|
||||
// $[I2C0 I/O setup]
|
||||
// [I2C0 I/O setup]$
|
||||
|
||||
// $[I2C0 initialization]
|
||||
// [I2C0 initialization]$
|
||||
|
||||
}
|
||||
|
||||
//================================================================================
|
||||
// GPCRC_enter_DefaultMode_from_RESET
|
||||
//================================================================================
|
||||
extern void GPCRC_enter_DefaultMode_from_RESET(void) {
|
||||
|
||||
}
|
||||
|
||||
//================================================================================
|
||||
// LDMA_enter_DefaultMode_from_RESET
|
||||
//================================================================================
|
||||
extern void LDMA_enter_DefaultMode_from_RESET(void) {
|
||||
|
||||
}
|
||||
|
||||
//================================================================================
|
||||
// TIMER0_enter_DefaultMode_from_RESET
|
||||
//================================================================================
|
||||
extern void TIMER0_enter_DefaultMode_from_RESET(void) {
|
||||
|
||||
// $[TIMER0 I/O setup]
|
||||
/* Set up CC0 */
|
||||
TIMER0->ROUTELOC0 = (TIMER0->ROUTELOC0 & (~_TIMER_ROUTELOC0_CC0LOC_MASK))
|
||||
| TIMER_ROUTELOC0_CC0LOC_LOC18;
|
||||
TIMER0->ROUTEPEN = TIMER0->ROUTEPEN | TIMER_ROUTEPEN_CC0PEN;
|
||||
/* Set up CC1 */
|
||||
TIMER0->ROUTELOC0 = (TIMER0->ROUTELOC0 & (~_TIMER_ROUTELOC0_CC1LOC_MASK))
|
||||
| TIMER_ROUTELOC0_CC1LOC_LOC16;
|
||||
TIMER0->ROUTEPEN = TIMER0->ROUTEPEN | TIMER_ROUTEPEN_CC1PEN;
|
||||
/* Set up CC2 */
|
||||
TIMER0->ROUTELOC0 = (TIMER0->ROUTELOC0 & (~_TIMER_ROUTELOC0_CC2LOC_MASK))
|
||||
| TIMER_ROUTELOC0_CC2LOC_LOC20;
|
||||
TIMER0->ROUTEPEN = TIMER0->ROUTEPEN | TIMER_ROUTEPEN_CC2PEN;
|
||||
/* Set up CDTI0 */
|
||||
TIMER0->ROUTELOC2 = (TIMER0->ROUTELOC2 & (~_TIMER_ROUTELOC2_CDTI0LOC_MASK))
|
||||
| TIMER_ROUTELOC2_CDTI0LOC_LOC3;
|
||||
TIMER0->ROUTEPEN = TIMER0->ROUTEPEN & (~TIMER_ROUTEPEN_CDTI0PEN);
|
||||
/* Set up CDTI1 */
|
||||
TIMER0->ROUTELOC2 = (TIMER0->ROUTELOC2 & (~_TIMER_ROUTELOC2_CDTI1LOC_MASK))
|
||||
| TIMER_ROUTELOC2_CDTI1LOC_LOC2;
|
||||
TIMER0->ROUTEPEN = TIMER0->ROUTEPEN & (~TIMER_ROUTEPEN_CDTI1PEN);
|
||||
/* Set up CDTI2 */
|
||||
TIMER0->ROUTELOC2 = (TIMER0->ROUTELOC2 & (~_TIMER_ROUTELOC2_CDTI2LOC_MASK))
|
||||
| TIMER_ROUTELOC2_CDTI2LOC_LOC1;
|
||||
TIMER0->ROUTEPEN = TIMER0->ROUTEPEN & (~TIMER_ROUTEPEN_CDTI2PEN);
|
||||
// [TIMER0 I/O setup]$
|
||||
|
||||
// $[TIMER0 initialization]
|
||||
TIMER_Init_TypeDef init = TIMER_INIT_DEFAULT;
|
||||
|
||||
init.enable = 1;
|
||||
init.debugRun = 0;
|
||||
init.dmaClrAct = 0;
|
||||
init.sync = 0;
|
||||
init.clkSel = timerClkSelHFPerClk;
|
||||
init.prescale = timerPrescale512;
|
||||
init.fallAction = timerInputActionNone;
|
||||
init.riseAction = timerInputActionNone;
|
||||
init.mode = timerModeUp;
|
||||
init.quadModeX4 = 0;
|
||||
init.oneShot = 0;
|
||||
init.count2x = 0;
|
||||
init.ati = 0;
|
||||
TIMER_Init(TIMER0, &init);
|
||||
// [TIMER0 initialization]$
|
||||
|
||||
// $[TIMER0 CC0 init]
|
||||
TIMER_InitCC_TypeDef initCC0 = TIMER_INITCC_DEFAULT;
|
||||
|
||||
initCC0.prsInput = false;
|
||||
initCC0.prsSel = timerPRSSELCh0;
|
||||
initCC0.edge = timerEdgeRising;
|
||||
initCC0.mode = timerCCModePWM;
|
||||
initCC0.eventCtrl = timerEventEveryEdge;
|
||||
initCC0.filter = 0;
|
||||
initCC0.cofoa = timerOutputActionNone;
|
||||
initCC0.cufoa = timerOutputActionNone;
|
||||
initCC0.cmoa = timerOutputActionToggle;
|
||||
initCC0.coist = 0;
|
||||
initCC0.outInvert = 0;
|
||||
TIMER_InitCC(TIMER0, 0, &initCC0);
|
||||
// [TIMER0 CC0 init]$
|
||||
|
||||
// $[TIMER0 CC1 init]
|
||||
TIMER_InitCC_TypeDef initCC1 = TIMER_INITCC_DEFAULT;
|
||||
|
||||
initCC1.prsInput = false;
|
||||
initCC1.prsSel = timerPRSSELCh0;
|
||||
initCC1.edge = timerEdgeRising;
|
||||
initCC1.mode = timerCCModePWM;
|
||||
initCC1.eventCtrl = timerEventEveryEdge;
|
||||
initCC1.filter = 0;
|
||||
initCC1.cofoa = timerOutputActionNone;
|
||||
initCC1.cufoa = timerOutputActionNone;
|
||||
initCC1.cmoa = timerOutputActionToggle;
|
||||
initCC1.coist = 0;
|
||||
initCC1.outInvert = 0;
|
||||
TIMER_InitCC(TIMER0, 1, &initCC1);
|
||||
// [TIMER0 CC1 init]$
|
||||
|
||||
// $[TIMER0 CC2 init]
|
||||
TIMER_InitCC_TypeDef initCC2 = TIMER_INITCC_DEFAULT;
|
||||
|
||||
initCC2.prsInput = false;
|
||||
initCC2.prsSel = timerPRSSELCh0;
|
||||
initCC2.edge = timerEdgeRising;
|
||||
initCC2.mode = timerCCModePWM;
|
||||
initCC2.eventCtrl = timerEventEveryEdge;
|
||||
initCC2.filter = 0;
|
||||
initCC2.cofoa = timerOutputActionNone;
|
||||
initCC2.cufoa = timerOutputActionNone;
|
||||
initCC2.cmoa = timerOutputActionToggle;
|
||||
initCC2.coist = 0;
|
||||
initCC2.outInvert = 0;
|
||||
TIMER_InitCC(TIMER0, 2, &initCC2);
|
||||
// [TIMER0 CC2 init]$
|
||||
|
||||
// $[TIMER0 DTI init]
|
||||
TIMER_InitDTI_TypeDef initDTI = TIMER_INITDTI_DEFAULT;
|
||||
|
||||
initDTI.enable = 0;
|
||||
initDTI.activeLowOut = 0;
|
||||
initDTI.invertComplementaryOut = 0;
|
||||
initDTI.autoRestart = 0;
|
||||
initDTI.enablePrsSource = 0;
|
||||
initDTI.prsSel = timerPRSSELCh0;
|
||||
initDTI.prescale = timerPrescale1;
|
||||
initDTI.riseTime = 1;
|
||||
initDTI.fallTime = 1;
|
||||
initDTI.enableFaultSourceCoreLockup = 1;
|
||||
initDTI.enableFaultSourceDebugger = 1;
|
||||
initDTI.faultSourcePrsSel0 = 0;
|
||||
initDTI.faultSourcePrsSel0 = timerPRSSELCh0;
|
||||
initDTI.faultSourcePrsSel1 = 0;
|
||||
initDTI.faultSourcePrsSel1 = timerPRSSELCh0;
|
||||
initDTI.faultAction = timerDtiFaultActionInactive;
|
||||
initDTI.outputsEnableMask = 0 | TIMER_DTOGEN_DTOGCC0EN
|
||||
| TIMER_DTOGEN_DTOGCC1EN | TIMER_DTOGEN_DTOGCC2EN;
|
||||
TIMER_InitDTI(TIMER0, &initDTI);
|
||||
// [TIMER0 DTI init]$
|
||||
|
||||
}
|
||||
|
||||
//================================================================================
|
||||
// TIMER1_enter_DefaultMode_from_RESET
|
||||
//================================================================================
|
||||
extern void TIMER1_enter_DefaultMode_from_RESET(void) {
|
||||
|
||||
// $[TIMER1 I/O setup]
|
||||
// [TIMER1 I/O setup]$
|
||||
|
||||
// $[TIMER1 initialization]
|
||||
// [TIMER1 initialization]$
|
||||
|
||||
// $[TIMER1 CC0 init]
|
||||
// [TIMER1 CC0 init]$
|
||||
|
||||
// $[TIMER1 CC1 init]
|
||||
// [TIMER1 CC1 init]$
|
||||
|
||||
// $[TIMER1 CC2 init]
|
||||
// [TIMER1 CC2 init]$
|
||||
|
||||
// $[TIMER1 CC3 init]
|
||||
// [TIMER1 CC3 init]$
|
||||
|
||||
}
|
||||
|
||||
//================================================================================
|
||||
// LETIMER0_enter_DefaultMode_from_RESET
|
||||
//================================================================================
|
||||
extern void LETIMER0_enter_DefaultMode_from_RESET(void) {
|
||||
|
||||
// $[LETIMER0 Compare Values]
|
||||
// [LETIMER0 Compare Values]$
|
||||
|
||||
// $[LETIMER0 Repeat Values]
|
||||
// [LETIMER0 Repeat Values]$
|
||||
|
||||
// $[LETIMER0 Initialization]
|
||||
// [LETIMER0 Initialization]$
|
||||
|
||||
// $[LETIMER0 PRS Input Triggers]
|
||||
// [LETIMER0 PRS Input Triggers]$
|
||||
|
||||
// $[LETIMER0 I/O setup]
|
||||
// [LETIMER0 I/O setup]$
|
||||
|
||||
}
|
||||
|
||||
//================================================================================
|
||||
// CRYOTIMER_enter_DefaultMode_from_RESET
|
||||
//================================================================================
|
||||
extern void CRYOTIMER_enter_DefaultMode_from_RESET(void) {
|
||||
|
||||
// $[CRYOTIMER_Init]
|
||||
CRYOTIMER_Init_TypeDef cryoInit = CRYOTIMER_INIT_DEFAULT;
|
||||
|
||||
/* General settings */
|
||||
cryoInit.enable = 1;
|
||||
cryoInit.debugRun = 0;
|
||||
cryoInit.em4Wakeup = 0;
|
||||
|
||||
/* Clocking settings */
|
||||
/* With a frequency of 1000Hz on ULFRCO, this will result in a 1.00 ms timeout */
|
||||
cryoInit.osc = cryotimerOscULFRCO;
|
||||
cryoInit.presc = cryotimerPresc_1;
|
||||
cryoInit.period = cryotimerPeriod_1;
|
||||
CRYOTIMER_Init(&cryoInit);
|
||||
// [CRYOTIMER_Init]$
|
||||
|
||||
}
|
||||
|
||||
//================================================================================
|
||||
// PCNT0_enter_DefaultMode_from_RESET
|
||||
//================================================================================
|
||||
extern void PCNT0_enter_DefaultMode_from_RESET(void) {
|
||||
|
||||
// $[PCNT0 I/O setup]
|
||||
// [PCNT0 I/O setup]$
|
||||
|
||||
// $[PCNT0 initialization]
|
||||
// [PCNT0 initialization]$
|
||||
|
||||
}
|
||||
|
||||
//================================================================================
|
||||
// PRS_enter_DefaultMode_from_RESET
|
||||
//================================================================================
|
||||
extern void PRS_enter_DefaultMode_from_RESET(void) {
|
||||
|
||||
// $[PRS initialization]
|
||||
// [PRS initialization]$
|
||||
|
||||
}
|
||||
|
||||
//================================================================================
|
||||
// PORTIO_enter_DefaultMode_from_RESET
|
||||
//================================================================================
|
||||
extern void PORTIO_enter_DefaultMode_from_RESET(void) {
|
||||
|
||||
// $[Port A Configuration]
|
||||
|
||||
/* Pin PA0 is configured to Input enabled */
|
||||
GPIO_PinModeSet(gpioPortA, 0, gpioModeInput, 0);
|
||||
|
||||
/* Pin PA1 is configured to Input enabled */
|
||||
GPIO_PinModeSet(gpioPortA, 1, gpioModeInput, 0);
|
||||
// [Port A Configuration]$
|
||||
|
||||
// $[Port B Configuration]
|
||||
|
||||
/* Pin PB11 is configured to Push-pull */
|
||||
GPIO_PinModeSet(gpioPortB, 11, gpioModePushPull, 1);
|
||||
|
||||
/* Pin PB12 is configured to Input enabled with pull-up */
|
||||
GPIO_PinModeSet(gpioPortB, 12, gpioModeInputPull, 1);
|
||||
|
||||
/* Pin PB13 is configured to Push-pull */
|
||||
GPIO_PinModeSet(gpioPortB, 13, gpioModePushPull, 1);
|
||||
|
||||
/* Pin PB15 is configured to Push-pull */
|
||||
GPIO_PinModeSet(gpioPortB, 15, gpioModePushPull, 1);
|
||||
// [Port B Configuration]$
|
||||
|
||||
// $[Port C Configuration]
|
||||
// [Port C Configuration]$
|
||||
|
||||
// $[Port D Configuration]
|
||||
|
||||
/* Pin PD9 is configured to Push-pull */
|
||||
GPIO_PinModeSet(gpioPortD, 9, gpioModePushPull, 1);
|
||||
|
||||
/* Pin PD10 is configured to Push-pull */
|
||||
GPIO_PinModeSet(gpioPortD, 10, gpioModePushPull, 1);
|
||||
|
||||
/* Pin PD11 is configured to Input enabled with pull-up */
|
||||
GPIO_PinModeSet(gpioPortD, 11, gpioModeInputPull, 1);
|
||||
|
||||
/* Pin PD12 is configured to Push-pull */
|
||||
GPIO_PinModeSet(gpioPortD, 12, gpioModePushPull, 1);
|
||||
|
||||
/* Pin PD13 is configured to Input enabled with pull-up */
|
||||
GPIO_PinModeSet(gpioPortD, 13, gpioModeInputPull, 1);
|
||||
|
||||
/* Pin PD14 is configured to Push-pull */
|
||||
GPIO_PinModeSet(gpioPortD, 14, gpioModePushPull, 1);
|
||||
|
||||
/* Pin PD15 is configured to Push-pull */
|
||||
GPIO_PinModeSet(gpioPortD, 15, gpioModePushPull, 1);
|
||||
// [Port D Configuration]$
|
||||
|
||||
// $[Port E Configuration]
|
||||
// [Port E Configuration]$
|
||||
|
||||
// $[Port F Configuration]
|
||||
// [Port F Configuration]$
|
||||
|
||||
}
|
||||
|
@ -1,668 +0,0 @@
|
||||
/*
|
||||
* Wrapper for crypto implementation on device
|
||||
*
|
||||
* */
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "em_adc.h"
|
||||
|
||||
#include "util.h"
|
||||
#include "crypto.h"
|
||||
#include "device.h"
|
||||
|
||||
|
||||
#include "sha256.h"
|
||||
#include "uECC.h"
|
||||
#include "aes.h"
|
||||
#include "ctap.h"
|
||||
#include "log.h"
|
||||
|
||||
#include MBEDTLS_CONFIG_FILE
|
||||
#include "sha256_alt.h"
|
||||
#include "mbedtls/ctr_drbg.h"
|
||||
#include "mbedtls/ecdsa.h"
|
||||
|
||||
const uint8_t attestation_cert_der[];
|
||||
const uint16_t attestation_cert_der_size;
|
||||
const uint8_t attestation_key[];
|
||||
const uint16_t attestation_key_size;
|
||||
|
||||
|
||||
static mbedtls_sha256_context embed_sha256_ctx;
|
||||
static mbedtls_ctr_drbg_context ctr_drbg;
|
||||
|
||||
static const struct uECC_Curve_t * _es256_curve = NULL;
|
||||
static const uint8_t * _signing_key = NULL;
|
||||
static int _key_len = 0;
|
||||
|
||||
// Secrets for testing only
|
||||
static uint8_t master_secret[32] = "\x00\x11\x22\x33\x44\x55\x66\x77\x88\x99\xaa\xbb\xcc\xdd\xee\xff"
|
||||
"\xff\xee\xdd\xcc\xbb\xaa\x99\x88\x77\x66\x55\x44\x33\x22\x11\x00";
|
||||
|
||||
static uint8_t transport_secret[32] = "\x10\x01\x22\x33\x44\x55\x66\x77\x87\x90\x0a\xbb\x3c\xd8\xee\xff"
|
||||
"\xff\xee\x8d\x1c\x3b\xfa\x99\x88\x77\x86\x55\x44\xd3\xff\x33\x00";
|
||||
|
||||
|
||||
|
||||
void crypto_sha256_init()
|
||||
{
|
||||
mbedtls_sha256_init( &embed_sha256_ctx );
|
||||
mbedtls_sha256_starts(&embed_sha256_ctx,0);
|
||||
// sha256_init(&sha256_ctx);
|
||||
}
|
||||
|
||||
void crypto_reset_master_secret()
|
||||
{
|
||||
ctap_generate_rng(master_secret, 32);
|
||||
}
|
||||
|
||||
|
||||
void crypto_sha256_update(uint8_t * data, size_t len)
|
||||
{
|
||||
mbedtls_sha256_update(&embed_sha256_ctx,data,len);
|
||||
// sha256_update(&sha256_ctx, data, len);
|
||||
}
|
||||
|
||||
void crypto_sha256_update_secret()
|
||||
{
|
||||
mbedtls_sha256_update(&embed_sha256_ctx,master_secret,32);
|
||||
// sha256_update(&sha256_ctx, master_secret, 32);
|
||||
}
|
||||
|
||||
void crypto_sha256_final(uint8_t * hash)
|
||||
{
|
||||
mbedtls_sha256_finish( &embed_sha256_ctx, hash );
|
||||
// sha256_final(&sha256_ctx, hash);
|
||||
}
|
||||
|
||||
void crypto_sha256_hmac_init(uint8_t * key, uint32_t klen, uint8_t * hmac)
|
||||
{
|
||||
uint8_t buf[64];
|
||||
int i;
|
||||
memset(buf, 0, sizeof(buf));
|
||||
|
||||
if (key == CRYPTO_MASTER_KEY)
|
||||
{
|
||||
key = master_secret;
|
||||
klen = sizeof(master_secret);
|
||||
}
|
||||
|
||||
if(klen > 64)
|
||||
{
|
||||
printf2(TAG_ERR,"Error, key size must be <= 64\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
memmove(buf, key, klen);
|
||||
|
||||
for (i = 0; i < sizeof(buf); i++)
|
||||
{
|
||||
buf[i] = buf[i] ^ 0x36;
|
||||
}
|
||||
|
||||
crypto_sha256_init();
|
||||
crypto_sha256_update(buf, 64);
|
||||
}
|
||||
|
||||
void crypto_sha256_hmac_final(uint8_t * key, uint32_t klen, uint8_t * hmac)
|
||||
{
|
||||
uint8_t buf[64];
|
||||
int i;
|
||||
crypto_sha256_final(hmac);
|
||||
memset(buf, 0, sizeof(buf));
|
||||
if (key == CRYPTO_MASTER_KEY)
|
||||
{
|
||||
key = master_secret;
|
||||
klen = sizeof(master_secret);
|
||||
}
|
||||
|
||||
|
||||
if(klen > 64)
|
||||
{
|
||||
printf2(TAG_ERR,"Error, key size must be <= 64\n");
|
||||
exit(1);
|
||||
}
|
||||
memmove(buf, key, klen);
|
||||
|
||||
for (i = 0; i < sizeof(buf); i++)
|
||||
{
|
||||
buf[i] = buf[i] ^ 0x5c;
|
||||
}
|
||||
|
||||
crypto_sha256_init();
|
||||
crypto_sha256_update(buf, 64);
|
||||
crypto_sha256_update(hmac, 32);
|
||||
crypto_sha256_final(hmac);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
uint8_t adc_rng(void)
|
||||
{
|
||||
int i;
|
||||
uint8_t random = 0;
|
||||
|
||||
/* Random number generation */
|
||||
for (i=0; i<3; i++)
|
||||
{
|
||||
ADC_Start(ADC0, adcStartSingle);
|
||||
while ((ADC0->IF & ADC_IF_SINGLE) == 0);
|
||||
random |= ((ADC_DataSingleGet(ADC0) & 0x07) << (i * 3));
|
||||
}
|
||||
|
||||
return random;
|
||||
}
|
||||
|
||||
// Generate @num bytes of random numbers to @dest
|
||||
// return 1 if success, error otherwise
|
||||
int ctap_generate_rng(uint8_t * dst, size_t num)
|
||||
{
|
||||
return mbedtls_ctr_drbg_random(&ctr_drbg,dst,num) == 0;
|
||||
}
|
||||
|
||||
int adc_entropy_func( void *data, unsigned char *output, size_t len )
|
||||
{
|
||||
while(len--)
|
||||
*output++ = adc_rng();
|
||||
return 0;
|
||||
}
|
||||
|
||||
void crypto_ecc256_init()
|
||||
{
|
||||
uECC_set_rng((uECC_RNG_Function)ctap_generate_rng);
|
||||
_es256_curve = uECC_secp256r1();
|
||||
mbedtls_ctr_drbg_init(&ctr_drbg);
|
||||
|
||||
if ( mbedtls_ctr_drbg_seed(&ctr_drbg, adc_entropy_func, NULL,
|
||||
master_secret,32 ) != 0 ) {
|
||||
printf2(TAG_ERR, "mbedtls_ctr_drbg_seed failed\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
void crypto_load_external_key(uint8_t * key, int len)
|
||||
{
|
||||
_signing_key = key;
|
||||
_key_len = len;
|
||||
}
|
||||
void crypto_ecc256_load_attestation_key()
|
||||
{
|
||||
_signing_key = attestation_key;
|
||||
_key_len = 32;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* \brief Import a point from unsigned binary data
|
||||
*
|
||||
* \param grp Group to which the point should belong
|
||||
* \param P Point to import
|
||||
* \param buf Input buffer
|
||||
* \param ilen Actual length of input
|
||||
*
|
||||
* \return 0 if successful,
|
||||
* MBEDTLS_ERR_ECP_BAD_INPUT_DATA if input is invalid,
|
||||
* MBEDTLS_ERR_MPI_ALLOC_FAILED if memory allocation failed,
|
||||
* MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE if the point format
|
||||
* is not implemented.
|
||||
*
|
||||
* \note This function does NOT check that the point actually
|
||||
* belongs to the given group, see mbedtls_ecp_check_pubkey() for
|
||||
* that.
|
||||
*/
|
||||
//int mbedtls_ecp_point_read_binary( const mbedtls_ecp_group *grp, mbedtls_ecp_point *P,
|
||||
// const unsigned char *buf, size_t ilen );
|
||||
|
||||
/**
|
||||
* \brief Import X from unsigned binary data, big endian
|
||||
*
|
||||
* \param X Destination MPI
|
||||
* \param buf Input buffer
|
||||
* \param buflen Input buffer size
|
||||
*
|
||||
* \return 0 if successful,
|
||||
* MBEDTLS_ERR_MPI_ALLOC_FAILED if memory allocation failed
|
||||
*/
|
||||
//int mbedtls_mpi_read_binary( mbedtls_mpi *X, const unsigned char *buf, size_t buflen );
|
||||
|
||||
/*
|
||||
* Set context from an mbedtls_ecp_keypair
|
||||
*/
|
||||
//int mbedtls_ecdsa_from_keypair( mbedtls_ecdsa_context *ctx, const mbedtls_ecp_keypair *key );
|
||||
|
||||
|
||||
|
||||
void crypto_ecc256_sign(uint8_t * data, int len, uint8_t * sig)
|
||||
{
|
||||
mbedtls_ecp_group grp; /*!< Elliptic curve and base point */
|
||||
mbedtls_mpi d; /*!< our secret value */
|
||||
//#define CRYPTO_ENABLE CMU->HFBUSCLKEN0 |= CMU_HFBUSCLKEN0_CRYPTO; \
|
||||
// CRYPTO->IFC = _CRYPTO_IFC_MASK; \
|
||||
// CRYPTO->CMD = CRYPTO_CMD_SEQSTOP; \
|
||||
// CRYPTO->CTRL = CRYPTO_CTRL_DMA0RSEL_DDATA0; \
|
||||
// CRYPTO->SEQCTRL = 0; \
|
||||
// CRYPTO->SEQCTRLB = 0
|
||||
//
|
||||
//#define CRYPTO_DISABLE \
|
||||
// CRYPTO->IEN = 0; \
|
||||
// CMU->HFBUSCLKEN0 &= ~CMU_HFBUSCLKEN0_CRYPTO;
|
||||
// CRYPTO_DISABLE;
|
||||
// CRYPTO_ENABLE;
|
||||
// mbedtls_ecp_group_init( &grp );
|
||||
// mbedtls_mpi_init( &d );
|
||||
// mbedtls_ecp_group_load(&grp, MBEDTLS_ECP_DP_SECP256R1);
|
||||
// mbedtls_mpi_read_binary(&d, _signing_key, 32);
|
||||
//
|
||||
// mbedtls_mpi r,s;
|
||||
// mbedtls_mpi_init(&r);
|
||||
// mbedtls_mpi_init(&s);
|
||||
//
|
||||
// printf("signing..\n");
|
||||
// dump_hex(data,len);
|
||||
// mbedtls_ecdsa_sign_det( &grp, &r, &s, &d,
|
||||
// data, 32, MBEDTLS_MD_SHA256 );// Issue: this will freeze on 13th iteration..
|
||||
// printf("signed\n");
|
||||
//
|
||||
// mbedtls_mpi_write_binary(&r,sig,32);
|
||||
// mbedtls_mpi_write_binary(&s,sig+32,32);
|
||||
|
||||
if ( uECC_sign(_signing_key, data, len, sig, _es256_curve) == 0)
|
||||
{
|
||||
printf2(TAG_ERR,"error, uECC failed\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#if 1
|
||||
void crypto_ecdsa_sign(uint8_t * data, int len, uint8_t * sig, int MBEDTLS_ECP_ID)
|
||||
{
|
||||
|
||||
const struct uECC_Curve_t * curve = NULL;
|
||||
|
||||
switch(MBEDTLS_ECP_ID)
|
||||
{
|
||||
case MBEDTLS_ECP_DP_SECP192R1:
|
||||
curve = uECC_secp192r1();
|
||||
if (_key_len != 24) goto fail;
|
||||
break;
|
||||
case MBEDTLS_ECP_DP_SECP224R1:
|
||||
curve = uECC_secp224r1();
|
||||
if (_key_len != 28) goto fail;
|
||||
break;
|
||||
case MBEDTLS_ECP_DP_SECP256R1:
|
||||
curve = uECC_secp256r1();
|
||||
if (_key_len != 32) goto fail;
|
||||
break;
|
||||
case MBEDTLS_ECP_DP_SECP256K1:
|
||||
curve = uECC_secp256k1();
|
||||
if (_key_len != 32) goto fail;
|
||||
break;
|
||||
default:
|
||||
printf2(TAG_ERR,"error, invalid ECDSA alg specifier\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if ( uECC_sign(_signing_key, data, len, sig, curve) == 0)
|
||||
{
|
||||
printf2(TAG_ERR,"error, uECC failed\n");
|
||||
exit(1);
|
||||
}
|
||||
return;
|
||||
|
||||
fail:
|
||||
printf2(TAG_ERR,"error, invalid key length: %d\n", _key_len);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
#else
|
||||
void crypto_ecdsa_sign(uint8_t * data, int len, uint8_t * sig, int MBEDTLS_ECP_ID)
|
||||
{
|
||||
mbedtls_ecp_group grp; /*!< Elliptic curve and base point */
|
||||
mbedtls_mpi d; /*!< our secret value */
|
||||
|
||||
mbedtls_ecp_group_init( &grp );
|
||||
mbedtls_mpi_init( &d );
|
||||
mbedtls_ecp_group_load(&grp, MBEDTLS_ECP_ID);
|
||||
mbedtls_mpi_read_binary(&d, _signing_key, 32);
|
||||
|
||||
mbedtls_mpi r,s;
|
||||
mbedtls_mpi_init(&r);
|
||||
mbedtls_mpi_init(&s);
|
||||
|
||||
printf("signing..\n");
|
||||
dump_hex(data,len);
|
||||
mbedtls_ecdsa_sign_det( &grp, &r, &s, &d,
|
||||
data, 32, MBEDTLS_MD_SHA256 );// Issue: this will freeze on 13th iteration..
|
||||
printf("signed\n");
|
||||
|
||||
mbedtls_mpi_write_binary(&r,sig,32);
|
||||
mbedtls_mpi_write_binary(&s,sig+32,32);
|
||||
}
|
||||
|
||||
|
||||
|
||||
#endif
|
||||
/*
|
||||
* Generate a keypair with configurable base point
|
||||
*/
|
||||
// mbedtls_ecp_gen_keypair( &ctx->grp, &ctx->d, &ctx->Q, f_rng, p_rng )
|
||||
// mbedtls_ecp_gen_keypair_base( grp, &grp->G, d, Q, f_rng, p_rng )
|
||||
/*
|
||||
* Curve types: internal for now, might be exposed later
|
||||
*/
|
||||
typedef enum
|
||||
{
|
||||
ECP_TYPE_NONE = 0,
|
||||
ECP_TYPE_SHORT_WEIERSTRASS, /* y^2 = x^3 + a x + b */
|
||||
ECP_TYPE_MONTGOMERY, /* y^2 = x^3 + a x^2 + x */
|
||||
} ecp_curve_type;
|
||||
/*
|
||||
* Get the type of a curve
|
||||
*/
|
||||
static inline ecp_curve_type ecp_get_type( const mbedtls_ecp_group *grp )
|
||||
{
|
||||
if( grp->G.X.p == NULL )
|
||||
return( ECP_TYPE_NONE );
|
||||
|
||||
if( grp->G.Y.p == NULL )
|
||||
return( ECP_TYPE_MONTGOMERY );
|
||||
else
|
||||
return( ECP_TYPE_SHORT_WEIERSTRASS );
|
||||
}
|
||||
static int mbedtls_ecp_gen_privkey( mbedtls_ecp_group *grp,
|
||||
const mbedtls_ecp_point *G,
|
||||
mbedtls_mpi *d, mbedtls_ecp_point *Q,
|
||||
int (*f_rng)(void *, unsigned char *, size_t),
|
||||
void *p_rng )
|
||||
{
|
||||
int ret;
|
||||
size_t n_size = ( grp->nbits + 7 ) / 8;
|
||||
|
||||
#if defined(ECP_MONTGOMERY)
|
||||
if( ecp_get_type( grp ) == ECP_TYPE_MONTGOMERY )
|
||||
{
|
||||
/* [M225] page 5 */
|
||||
size_t b;
|
||||
|
||||
MBEDTLS_MPI_CHK( mbedtls_mpi_fill_random( d, n_size, f_rng, p_rng ) );
|
||||
|
||||
/* Make sure the most significant bit is nbits */
|
||||
b = mbedtls_mpi_bitlen( d ) - 1; /* mbedtls_mpi_bitlen is one-based */
|
||||
if( b > grp->nbits )
|
||||
MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( d, b - grp->nbits ) );
|
||||
else
|
||||
MBEDTLS_MPI_CHK( mbedtls_mpi_set_bit( d, grp->nbits, 1 ) );
|
||||
|
||||
/* Make sure the last three bits are unset */
|
||||
MBEDTLS_MPI_CHK( mbedtls_mpi_set_bit( d, 0, 0 ) );
|
||||
MBEDTLS_MPI_CHK( mbedtls_mpi_set_bit( d, 1, 0 ) );
|
||||
MBEDTLS_MPI_CHK( mbedtls_mpi_set_bit( d, 2, 0 ) );
|
||||
}
|
||||
else
|
||||
#endif /* ECP_MONTGOMERY */
|
||||
#if defined(ECP_SHORTWEIERSTRASS)
|
||||
if( ecp_get_type( grp ) == ECP_TYPE_SHORT_WEIERSTRASS )
|
||||
{
|
||||
/* SEC1 3.2.1: Generate d such that 1 <= n < N */
|
||||
int count = 0;
|
||||
unsigned char rnd[MBEDTLS_ECP_MAX_BYTES];
|
||||
|
||||
/*
|
||||
* Match the procedure given in RFC 6979 (deterministic ECDSA):
|
||||
* - use the same byte ordering;
|
||||
* - keep the leftmost nbits bits of the generated octet string;
|
||||
* - try until result is in the desired range.
|
||||
* This also avoids any biais, which is especially important for ECDSA.
|
||||
*/
|
||||
do
|
||||
{
|
||||
MBEDTLS_MPI_CHK( f_rng( p_rng, rnd, n_size ) );
|
||||
MBEDTLS_MPI_CHK( mbedtls_mpi_read_binary( d, rnd, n_size ) );
|
||||
MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( d, 8 * n_size - grp->nbits ) );
|
||||
|
||||
/*
|
||||
* Each try has at worst a probability 1/2 of failing (the msb has
|
||||
* a probability 1/2 of being 0, and then the result will be < N),
|
||||
* so after 30 tries failure probability is a most 2**(-30).
|
||||
*
|
||||
* For most curves, 1 try is enough with overwhelming probability,
|
||||
* since N starts with a lot of 1s in binary, but some curves
|
||||
* such as secp224k1 are actually very close to the worst case.
|
||||
*/
|
||||
if( ++count > 30 )
|
||||
return( MBEDTLS_ERR_ECP_RANDOM_FAILED );
|
||||
}
|
||||
while( mbedtls_mpi_cmp_int( d, 1 ) < 0 ||
|
||||
mbedtls_mpi_cmp_mpi( d, &grp->N ) >= 0 );
|
||||
}
|
||||
else
|
||||
#endif /* ECP_SHORTWEIERSTRASS */
|
||||
return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA );
|
||||
|
||||
cleanup:
|
||||
if( ret != 0 )
|
||||
return( ret );
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int mbedtls_ecp_derive_pubkey( mbedtls_ecp_group *grp,
|
||||
const mbedtls_ecp_point *G,
|
||||
mbedtls_mpi *d, mbedtls_ecp_point *Q,
|
||||
int (*f_rng)(void *, unsigned char *, size_t),
|
||||
void *p_rng )
|
||||
{
|
||||
return( mbedtls_ecp_mul( grp, Q, d, G, f_rng, p_rng ) );
|
||||
}
|
||||
|
||||
|
||||
static int hmac_vector_func(uint8_t * hmac, uint8_t * dst, int len)
|
||||
{
|
||||
static int hmac_ptr = 0;
|
||||
if (hmac==NULL)
|
||||
{
|
||||
hmac_ptr = 0;
|
||||
return 0;
|
||||
}
|
||||
int i;
|
||||
while(len--)
|
||||
{
|
||||
*dst++ = hmac[hmac_ptr++ % 32];
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void generate_private_key(uint8_t * data, int len, uint8_t * data2, int len2, uint8_t * privkey)
|
||||
{
|
||||
crypto_sha256_hmac_init(CRYPTO_MASTER_KEY, 0, privkey);
|
||||
crypto_sha256_update(data, len);
|
||||
crypto_sha256_update(data2, len2);
|
||||
crypto_sha256_update(master_secret, 32);
|
||||
crypto_sha256_hmac_final(CRYPTO_MASTER_KEY, 0, privkey);
|
||||
|
||||
// mbedtls_ecp_group grp; /*!< Elliptic curve and base point */
|
||||
// mbedtls_mpi d; /*!< our secret value */
|
||||
// mbedtls_ecp_point Q;
|
||||
//
|
||||
// mbedtls_ecp_group_init( &grp );
|
||||
// mbedtls_mpi_init( &d );
|
||||
// mbedtls_ecp_point_init(&Q);
|
||||
//
|
||||
// mbedtls_ecp_group_load(&grp, MBEDTLS_ECP_DP_SECP256R1);
|
||||
//
|
||||
//// mbedtls_mpi_read_binary(&d, _signing_key, 32);
|
||||
// hmac_vector_func(NULL, NULL, 0);
|
||||
// mbedtls_ecp_gen_privkey(&grp, &grp.G, &d, &Q, hmac_vector_func, privkey);
|
||||
// mbedtls_mpi_write_binary(&d,privkey,32);
|
||||
}
|
||||
|
||||
|
||||
/*int uECC_compute_public_key(const uint8_t *private_key, uint8_t *public_key, uECC_Curve curve);*/
|
||||
void crypto_ecc256_derive_public_key(uint8_t * data, int len, uint8_t * x, uint8_t * y)
|
||||
{
|
||||
int ret;
|
||||
uint8_t privkey[32];
|
||||
uint8_t pubkey[64];
|
||||
|
||||
// generate_private_key(data,len,NULL,0,privkey);
|
||||
|
||||
crypto_sha256_hmac_init(CRYPTO_MASTER_KEY, 0, privkey);
|
||||
crypto_sha256_update(data, len);
|
||||
crypto_sha256_update(NULL, 0);
|
||||
crypto_sha256_update(master_secret, 32);
|
||||
crypto_sha256_hmac_final(CRYPTO_MASTER_KEY, 0, privkey);
|
||||
|
||||
// mbedtls_ecp_group grp; /*!< Elliptic curve and base point */
|
||||
// mbedtls_mpi d; /*!< our secret value */
|
||||
// mbedtls_ecp_point Q;
|
||||
//
|
||||
// mbedtls_ecp_group_init( &grp );
|
||||
// mbedtls_mpi_init( &d );
|
||||
// mbedtls_ecp_point_init(&Q);
|
||||
//
|
||||
// mbedtls_ecp_group_load(&grp, MBEDTLS_ECP_DP_SECP256R1);
|
||||
//
|
||||
//// mbedtls_mpi_read_binary(&d, _signing_key, 32);
|
||||
// hmac_vector_func(NULL, NULL, 0);
|
||||
// ret= mbedtls_ecp_gen_privkey(&grp, &grp.G, &d, &Q, hmac_vector_func, privkey);
|
||||
// if (ret != 0)
|
||||
// {
|
||||
// printf("error with priv key -0x04%x\n", -ret);
|
||||
// }
|
||||
//// mbedtls_mpi_write_binary(&d,privkey,32);
|
||||
//
|
||||
// memset(pubkey,0,sizeof(pubkey));
|
||||
//
|
||||
// ret = mbedtls_ecp_derive_pubkey( &grp, &grp.G,
|
||||
// &d, &Q, hmac_vector_func, privkey);
|
||||
//
|
||||
// if (ret != 0)
|
||||
// {
|
||||
// printf("error with public key\n");
|
||||
// }
|
||||
//
|
||||
// mbedtls_mpi_write_binary(&Q.X,x,32);
|
||||
// mbedtls_mpi_write_binary(&Q.Y,y,32);
|
||||
|
||||
uECC_compute_public_key(privkey, pubkey, _es256_curve);
|
||||
memmove(x,pubkey,32);
|
||||
memmove(y,pubkey+32,32);
|
||||
}
|
||||
|
||||
void crypto_ecc256_load_key(uint8_t * data, int len, uint8_t * data2, int len2)
|
||||
{
|
||||
static uint8_t privkey[32];
|
||||
generate_private_key(data,len,data2,len2,privkey);
|
||||
_signing_key = privkey;
|
||||
_key_len = 32;
|
||||
}
|
||||
|
||||
void crypto_ecc256_make_key_pair(uint8_t * pubkey, uint8_t * privkey)
|
||||
{
|
||||
if (uECC_make_key(pubkey, privkey, _es256_curve) != 1)
|
||||
{
|
||||
printf2(TAG_ERR,"Error, uECC_make_key failed\n");
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
void crypto_ecc256_shared_secret(const uint8_t * pubkey, const uint8_t * privkey, uint8_t * shared_secret)
|
||||
{
|
||||
if (uECC_shared_secret(pubkey, privkey, shared_secret, _es256_curve) != 1)
|
||||
{
|
||||
printf2(TAG_ERR,"Error, uECC_shared_secret failed\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
struct AES_ctx aes_ctx;
|
||||
void crypto_aes256_init(uint8_t * key, uint8_t * nonce)
|
||||
{
|
||||
if (key == CRYPTO_TRANSPORT_KEY)
|
||||
{
|
||||
AES_init_ctx(&aes_ctx, transport_secret);
|
||||
}
|
||||
else
|
||||
{
|
||||
AES_init_ctx(&aes_ctx, key);
|
||||
}
|
||||
if (nonce == NULL)
|
||||
{
|
||||
memset(aes_ctx.Iv, 0, 16);
|
||||
}
|
||||
else
|
||||
{
|
||||
memmove(aes_ctx.Iv, nonce, 16);
|
||||
}
|
||||
}
|
||||
|
||||
// prevent round key recomputation
|
||||
void crypto_aes256_reset_iv(uint8_t * nonce)
|
||||
{
|
||||
if (nonce == NULL)
|
||||
{
|
||||
memset(aes_ctx.Iv, 0, 16);
|
||||
}
|
||||
else
|
||||
{
|
||||
memmove(aes_ctx.Iv, nonce, 16);
|
||||
}
|
||||
}
|
||||
|
||||
void crypto_aes256_decrypt(uint8_t * buf, int length)
|
||||
{
|
||||
AES_CBC_decrypt_buffer(&aes_ctx, buf, length);
|
||||
}
|
||||
|
||||
void crypto_aes256_encrypt(uint8_t * buf, int length)
|
||||
{
|
||||
AES_CBC_encrypt_buffer(&aes_ctx, buf, length);
|
||||
}
|
||||
|
||||
|
||||
|
||||
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"
|
||||
"\x06\x03\x55\x04\x0a\x0c\x07\x54\x45\x53\x54\x20\x43\x41\x30\x20\x17\x0d\x31\x38"
|
||||
"\x30\x35\x31\x30\x30\x33\x30\x36\x32\x30\x5a\x18\x0f\x32\x30\x36\x38\x30\x34\x32"
|
||||
"\x37\x30\x33\x30\x36\x32\x30\x5a\x30\x7c\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\x0f\x30\x0d"
|
||||
"\x06\x03\x55\x04\x07\x0c\x06\x4c\x61\x75\x72\x65\x6c\x31\x15\x30\x13\x06\x03\x55"
|
||||
"\x04\x0a\x0c\x0c\x54\x45\x53\x54\x20\x43\x4f\x4d\x50\x41\x4e\x59\x31\x22\x30\x20"
|
||||
"\x06\x03\x55\x04\x0b\x0c\x19\x41\x75\x74\x68\x65\x6e\x74\x69\x63\x61\x74\x6f\x72"
|
||||
"\x20\x41\x74\x74\x65\x73\x74\x61\x74\x69\x6f\x6e\x31\x14\x30\x12\x06\x03\x55\x04"
|
||||
"\x03\x0c\x0b\x63\x6f\x6e\x6f\x72\x70\x70\x2e\x63\x6f\x6d\x30\x59\x30\x13\x06\x07"
|
||||
"\x2a\x86\x48\xce\x3d\x02\x01\x06\x08\x2a\x86\x48\xce\x3d\x03\x01\x07\x03\x42\x00"
|
||||
"\x04\x45\xa9\x02\xc1\x2e\x9c\x0a\x33\xfa\x3e\x84\x50\x4a\xb8\x02\xdc\x4d\xb9\xaf"
|
||||
"\x15\xb1\xb6\x3a\xea\x8d\x3f\x03\x03\x55\x65\x7d\x70\x3f\xb4\x02\xa4\x97\xf4\x83"
|
||||
"\xb8\xa6\xf9\x3c\xd0\x18\xad\x92\x0c\xb7\x8a\x5a\x3e\x14\x48\x92\xef\x08\xf8\xca"
|
||||
"\xea\xfb\x32\xab\x20\xa3\x62\x30\x60\x30\x46\x06\x03\x55\x1d\x23\x04\x3f\x30\x3d"
|
||||
"\xa1\x30\xa4\x2e\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\x06\x03\x55\x04"
|
||||
"\x0a\x0c\x07\x54\x45\x53\x54\x20\x43\x41\x82\x09\x00\xf7\xc9\xec\x89\xf2\x63\x94"
|
||||
"\xd9\x30\x09\x06\x03\x55\x1d\x13\x04\x02\x30\x00\x30\x0b\x06\x03\x55\x1d\x0f\x04"
|
||||
"\x04\x03\x02\x04\xf0\x30\x0a\x06\x08\x2a\x86\x48\xce\x3d\x04\x03\x02\x03\x48\x00"
|
||||
"\x30\x45\x02\x20\x18\x38\xb0\x45\x03\x69\xaa\xa7\xb7\x38\x62\x01\xaf\x24\x97\x5e"
|
||||
"\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 uint16_t attestation_cert_der_size = 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";
|
||||
const uint16_t attestation_key_size = sizeof(attestation_key)-1;
|
||||
|
||||
|
||||
|
@ -1,692 +0,0 @@
|
||||
/*
|
||||
* device.c
|
||||
*
|
||||
* Created on: Jun 27, 2018
|
||||
* Author: conor
|
||||
*/
|
||||
#include <time.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#include "em_chip.h"
|
||||
#include "em_gpio.h"
|
||||
#include "em_usart.h"
|
||||
#include "em_adc.h"
|
||||
#include "em_cmu.h"
|
||||
#include "em_msc.h"
|
||||
#include "em_i2c.h"
|
||||
#include "em_timer.h"
|
||||
|
||||
#include "InitDevice.h"
|
||||
#include "cbor.h"
|
||||
#include "log.h"
|
||||
#include "ctaphid.h"
|
||||
#include "util.h"
|
||||
#include "app.h"
|
||||
#include "uECC.h"
|
||||
#include "crypto.h"
|
||||
#include "nfc.h"
|
||||
|
||||
#ifdef USING_DEV_BOARD
|
||||
|
||||
#define MSG_AVAIL_PIN gpioPortC,9
|
||||
#define RDY_PIN gpioPortC,10
|
||||
#define RW_PIN gpioPortD,11
|
||||
#define RESET_PIN gpioPortB,13
|
||||
#define LED_RED_PIN gpioPortF,4
|
||||
#define LED_GREEN_PIN gpioPortF,5
|
||||
|
||||
#else
|
||||
|
||||
#define MSG_AVAIL_PIN gpioPortA,1
|
||||
#define RDY_PIN gpioPortA,0
|
||||
#define RW_PIN gpioPortD,15
|
||||
#define RESET_PIN gpioPortB,15
|
||||
#define LED_RED_PIN gpioPortD,10
|
||||
#define LED_GREEN_PIN gpioPortD,14
|
||||
#define LED_BLUE_PIN gpioPortD,9
|
||||
#define BUTTON_PIN gpioPortD,13
|
||||
|
||||
#define RED_CHANNEL 0
|
||||
#define GREEN_CHANNEL 2
|
||||
#define BLUE_CHANNEL 1
|
||||
|
||||
#endif
|
||||
|
||||
#define PAGE_SIZE 2048
|
||||
#define PAGES 64
|
||||
#define COUNTER_PAGE (PAGES - 3)
|
||||
#define STATE1_PAGE (PAGES - 2)
|
||||
#define STATE2_PAGE (PAGES - 1)
|
||||
|
||||
#define APPLICATION_START_ADDR 0x4000
|
||||
#define APPLICATION_START_PAGE (0x4000/PAGE_SIZE)
|
||||
|
||||
#define APPLICATION_END_ADDR (PAGE_SIZE*(PAGES - 3)-4) // NOT included in application
|
||||
#define APPLICATION_END_PAGE ((PAGES - 3)) // 125 is NOT included in application
|
||||
|
||||
#define AUTH_WORD_ADDR (PAGE_SIZE*(PAGES - 3)-4)
|
||||
|
||||
|
||||
|
||||
static void init_atomic_counter()
|
||||
{
|
||||
int offset = 0;
|
||||
uint32_t count;
|
||||
uint32_t one = 1;
|
||||
uint32_t * ptr = PAGE_SIZE * COUNTER_PAGE;
|
||||
|
||||
for (offset = 0; offset < PAGE_SIZE/4; offset += 1)
|
||||
{
|
||||
count = *(ptr+offset);
|
||||
if (count != 0xffffffff)
|
||||
{
|
||||
return;
|
||||
}
|
||||
}
|
||||
MSC_WriteWordFast(ptr,&one,4);
|
||||
}
|
||||
|
||||
|
||||
uint32_t ctap_atomic_count(int sel)
|
||||
{
|
||||
int offset = 0;
|
||||
uint32_t count;
|
||||
uint32_t zero = 0;
|
||||
uint32_t * ptr = PAGE_SIZE * COUNTER_PAGE;
|
||||
|
||||
if (sel != 0)
|
||||
{
|
||||
printf2(TAG_ERR,"counter2 not imple\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
for (offset = 0; offset < PAGE_SIZE/4; offset += 1) // wear-level the flash
|
||||
{
|
||||
count = *(ptr+offset);
|
||||
if (count != 0)
|
||||
{
|
||||
count++;
|
||||
offset++;
|
||||
if (offset == PAGE_SIZE/4)
|
||||
{
|
||||
offset = 0;
|
||||
MSC_ErasePage(ptr);
|
||||
/*printf("RESET page counter\n");*/
|
||||
}
|
||||
else
|
||||
{
|
||||
MSC_WriteWordFast(ptr+offset-1,&zero,4);
|
||||
}
|
||||
MSC_WriteWordFast(ptr+offset,&count,4);
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
static uint32_t _color;
|
||||
uint32_t get_RBG()
|
||||
{
|
||||
return _color;
|
||||
}
|
||||
|
||||
void RGB(uint32_t hex)
|
||||
{
|
||||
uint16_t r = 256 - ((hex & 0xff0000) >> 16);
|
||||
uint16_t g = 256 - ((hex & 0xff00) >> 8);
|
||||
uint16_t b = 256 - ((hex & 0xff) >> 0);
|
||||
|
||||
TIMER_CompareBufSet(TIMER0, GREEN_CHANNEL, g); // green
|
||||
TIMER_CompareBufSet(TIMER0, RED_CHANNEL, r); // red
|
||||
TIMER_CompareBufSet(TIMER0, BLUE_CHANNEL, b); // blue
|
||||
_color = hex;
|
||||
}
|
||||
|
||||
|
||||
#define IS_BUTTON_PRESSED() (GPIO_PinInGet(BUTTON_PIN) == 0)
|
||||
|
||||
// Verify the user
|
||||
// return 1 if user is verified, 0 if not
|
||||
int ctap_user_verification(uint8_t arg)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
// Test for user presence
|
||||
// Return 1 for user is present, 0 user not present
|
||||
int ctap_user_presence_test()
|
||||
{
|
||||
#ifdef SKIP_BUTTON_CHECK
|
||||
return 1;
|
||||
#endif
|
||||
|
||||
|
||||
uint32_t t1 = millis();
|
||||
RGB(0x304010);
|
||||
|
||||
#ifdef USE_BUTTON_DELAY
|
||||
delay(3000);
|
||||
RGB(0x001040);
|
||||
delay(50);
|
||||
return 1;
|
||||
#endif
|
||||
while (IS_BUTTON_PRESSED())
|
||||
{
|
||||
if (t1 + 5000 < millis())
|
||||
{
|
||||
printf1(TAG_GEN,"Button not pressed\n");
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
t1 = millis();
|
||||
|
||||
do
|
||||
{
|
||||
if (t1 + 5000 < millis())
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
if (! IS_BUTTON_PRESSED())
|
||||
continue;
|
||||
delay(1);
|
||||
}
|
||||
while (! IS_BUTTON_PRESSED());
|
||||
|
||||
RGB(0x001040);
|
||||
|
||||
delay(50);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
// Must be implemented by application
|
||||
// data is HID_MESSAGE_SIZE long in bytes
|
||||
#ifndef TEST_POWER
|
||||
void ctaphid_write_block(uint8_t * data)
|
||||
{
|
||||
printf1(TAG_DUMP,"<< "); dump_hex1(TAG_DUMP, data, HID_MESSAGE_SIZE);
|
||||
usbhid_send(data);
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef IS_BOOTLOADER // two different colors between bootloader and app
|
||||
void heartbeat()
|
||||
{
|
||||
static int state = 0;
|
||||
static uint32_t val = (LED_INIT_VALUE >> 8) & 0xff;
|
||||
int but = IS_BUTTON_PRESSED();
|
||||
|
||||
|
||||
if (state)
|
||||
{
|
||||
val--;
|
||||
}
|
||||
else
|
||||
{
|
||||
val++;
|
||||
}
|
||||
|
||||
if (val > 30 || val < 1)
|
||||
{
|
||||
state = !state;
|
||||
}
|
||||
|
||||
// if (but) RGB(val * 2);
|
||||
// else
|
||||
RGB((val << 16) | (val*2 << 8));
|
||||
|
||||
}
|
||||
#else
|
||||
void heartbeat()
|
||||
{
|
||||
static int state = 0;
|
||||
static uint32_t val = (LED_INIT_VALUE >> 8) & 0xff;
|
||||
int but = IS_BUTTON_PRESSED();
|
||||
|
||||
|
||||
|
||||
#if 0
|
||||
RGB(0x100000); // bright ass light
|
||||
return;
|
||||
#endif
|
||||
|
||||
if (state)
|
||||
{
|
||||
val--;
|
||||
}
|
||||
else
|
||||
{
|
||||
val++;
|
||||
}
|
||||
|
||||
if (val >120/3 || val < 1)
|
||||
{
|
||||
state = !state;
|
||||
}
|
||||
|
||||
if (but) RGB(val * 2);
|
||||
else RGB(val*3 | ((val*3) << 8) | (val << 16) );
|
||||
// else RGB((val*3) << 8);
|
||||
|
||||
}
|
||||
#endif
|
||||
uint32_t millis()
|
||||
{
|
||||
return CRYOTIMER->CNT;
|
||||
}
|
||||
|
||||
|
||||
void usbhid_init()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
static int msgs_to_recv = 0;
|
||||
|
||||
static void wait_for_efm8_ready()
|
||||
{
|
||||
// Wait for efm8 to be ready
|
||||
while (GPIO_PinInGet(RDY_PIN) == 0)
|
||||
;
|
||||
}
|
||||
|
||||
static void wait_for_efm8_busy()
|
||||
{
|
||||
// Wait for efm8 to be ready
|
||||
while (GPIO_PinInGet(RDY_PIN) != 0)
|
||||
;
|
||||
}
|
||||
|
||||
#ifndef TEST_POWER
|
||||
int usbhid_recv(uint8_t * msg)
|
||||
{
|
||||
int i;
|
||||
|
||||
if (GPIO_PinInGet(MSG_AVAIL_PIN) == 0)
|
||||
{
|
||||
GPIO_PinOutClear(RW_PIN); // Drive low to indicate READ
|
||||
wait_for_efm8_ready();
|
||||
|
||||
|
||||
for (i = 0; i < 64; i++)
|
||||
{
|
||||
msg[i] = USART_SpiTransfer(USART1, 'A');
|
||||
// delay(1);
|
||||
}
|
||||
|
||||
GPIO_PinOutSet(RW_PIN);
|
||||
|
||||
wait_for_efm8_busy();
|
||||
|
||||
|
||||
// // msgs_to_recv--;
|
||||
// printf(">> ");
|
||||
// dump_hex(msg,64);
|
||||
return 64;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
void usbhid_send(uint8_t * msg)
|
||||
{
|
||||
int i;
|
||||
// uint32_t t1 = millis();
|
||||
USART_SpiTransfer(USART1, *msg++); // Send 1 byte
|
||||
wait_for_efm8_ready();
|
||||
|
||||
for (i = 1; i < HID_MESSAGE_SIZE; i++)
|
||||
{
|
||||
USART_SpiTransfer(USART1, *msg++);
|
||||
}
|
||||
wait_for_efm8_busy();
|
||||
|
||||
delay(10);
|
||||
// uint32_t t2 = millis();
|
||||
// printf("wait time: %u\n", (uint32_t)(t2-t1));
|
||||
|
||||
}
|
||||
|
||||
void usbhid_close()
|
||||
{
|
||||
}
|
||||
|
||||
void main_loop_delay()
|
||||
{
|
||||
}
|
||||
|
||||
void delay(int ms)
|
||||
{
|
||||
int t1 = millis();
|
||||
while(millis() - t1 < ms)
|
||||
;
|
||||
}
|
||||
|
||||
void GPIO_ODD_IRQHandler()
|
||||
{
|
||||
uint32_t flag = GPIO->IF;
|
||||
GPIO->IFC = flag;
|
||||
if (flag & (1<<9))
|
||||
{
|
||||
// printf("pin 9 interrupt\r\n");
|
||||
msgs_to_recv++;
|
||||
}
|
||||
else
|
||||
{
|
||||
printf1(TAG_ERR,"wrong pin int %x\r\n",flag);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
void init_adc()
|
||||
{
|
||||
/* Enable ADC Clock */
|
||||
CMU_ClockEnable(cmuClock_ADC0, true);
|
||||
ADC_Init_TypeDef init = ADC_INIT_DEFAULT;
|
||||
ADC_InitSingle_TypeDef singleInit = ADC_INITSINGLE_DEFAULT;
|
||||
|
||||
/* Initialize the ADC with the required values */
|
||||
init.timebase = ADC_TimebaseCalc(0);
|
||||
init.prescale = ADC_PrescaleCalc(7000000, 0);
|
||||
ADC_Init(ADC0, &init);
|
||||
|
||||
/* Initialize for single conversion specific to RNG */
|
||||
singleInit.reference = adcRefVEntropy;
|
||||
singleInit.diff = true;
|
||||
singleInit.posSel = adcPosSelVSS;
|
||||
singleInit.negSel = adcNegSelVSS;
|
||||
ADC_InitSingle(ADC0, &singleInit);
|
||||
|
||||
/* Set VINATT to maximum value and clear FIFO */
|
||||
ADC0->SINGLECTRLX |= _ADC_SINGLECTRLX_VINATT_MASK;
|
||||
ADC0->SINGLEFIFOCLEAR = ADC_SINGLEFIFOCLEAR_SINGLEFIFOCLEAR;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void authenticator_read_state(AuthenticatorState * state)
|
||||
{
|
||||
uint32_t * ptr = PAGE_SIZE*STATE1_PAGE;
|
||||
memmove(state,ptr,sizeof(AuthenticatorState));
|
||||
}
|
||||
|
||||
void authenticator_read_backup_state(AuthenticatorState * state )
|
||||
{
|
||||
uint32_t * ptr = PAGE_SIZE*STATE2_PAGE;
|
||||
memmove(state,ptr,sizeof(AuthenticatorState));
|
||||
}
|
||||
|
||||
void authenticator_write_state(AuthenticatorState * state, int backup)
|
||||
{
|
||||
uint32_t * ptr;
|
||||
if (! backup)
|
||||
{
|
||||
ptr = PAGE_SIZE*STATE1_PAGE;
|
||||
MSC_ErasePage(ptr);
|
||||
// for (i = 0; i < sizeof(AuthenticatorState)/4; i++ )
|
||||
MSC_WriteWordFast(ptr,state,sizeof(AuthenticatorState) + (sizeof(AuthenticatorState)%4));
|
||||
}
|
||||
else
|
||||
{
|
||||
ptr = PAGE_SIZE*STATE2_PAGE;
|
||||
MSC_ErasePage(ptr);
|
||||
// for (i = 0; i < sizeof(AuthenticatorState)/4; i++ )
|
||||
MSC_WriteWordFast(ptr,state,sizeof(AuthenticatorState) + (sizeof(AuthenticatorState)%4));
|
||||
}
|
||||
}
|
||||
|
||||
// Return 1 yes backup is init'd, else 0
|
||||
int authenticator_is_backup_initialized()
|
||||
{
|
||||
uint8_t header[16];
|
||||
uint32_t * ptr = PAGE_SIZE*STATE2_PAGE;
|
||||
memmove(header,ptr,16);
|
||||
AuthenticatorState * state = (AuthenticatorState*)header;
|
||||
return state->is_initialized == INITIALIZED_MARKER;
|
||||
}
|
||||
|
||||
|
||||
uint8_t adc_rng(void);
|
||||
|
||||
void reset_efm8()
|
||||
{
|
||||
// Reset EFM8
|
||||
GPIO_PinOutClear(RESET_PIN);
|
||||
delay(2);
|
||||
GPIO_PinOutSet(RESET_PIN);
|
||||
}
|
||||
|
||||
void bootloader_init(void)
|
||||
{
|
||||
/* Chip errata */
|
||||
|
||||
// Reset EFM8
|
||||
GPIO_PinModeSet(RESET_PIN, gpioModePushPull, 1);
|
||||
|
||||
// status LEDS
|
||||
GPIO_PinModeSet(LED_RED_PIN,
|
||||
gpioModePushPull,
|
||||
1); // red
|
||||
|
||||
GPIO_PinModeSet(LED_GREEN_PIN,
|
||||
gpioModePushPull,
|
||||
1); // green
|
||||
GPIO_PinModeSet(LED_BLUE_PIN,
|
||||
gpioModePushPull,
|
||||
1); // blue
|
||||
|
||||
// EFM8 RDY/BUSY
|
||||
GPIO_PinModeSet(RDY_PIN, gpioModeInput, 0);
|
||||
|
||||
// EFM8 MSG Available
|
||||
GPIO_PinModeSet(MSG_AVAIL_PIN, gpioModeInput, 0);
|
||||
|
||||
// SPI R/w Indicator
|
||||
GPIO_PinModeSet(RW_PIN, gpioModePushPull, 1);
|
||||
|
||||
|
||||
printing_init();
|
||||
|
||||
|
||||
MSC_Init();
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
void device_init(void)
|
||||
{
|
||||
/* Chip errata */
|
||||
|
||||
CHIP_Init();
|
||||
enter_DefaultMode_from_RESET();
|
||||
|
||||
// status LEDS
|
||||
GPIO_PinModeSet(LED_RED_PIN,
|
||||
gpioModePushPull,
|
||||
1); // red
|
||||
|
||||
GPIO_PinModeSet(LED_GREEN_PIN,
|
||||
gpioModePushPull,
|
||||
1); // green
|
||||
GPIO_PinModeSet(LED_BLUE_PIN,
|
||||
gpioModePushPull,
|
||||
1); // blue
|
||||
|
||||
// EFM8 RDY/BUSY
|
||||
GPIO_PinModeSet(RDY_PIN, gpioModeInput, 0);
|
||||
|
||||
// EFM8 MSG Available
|
||||
GPIO_PinModeSet(MSG_AVAIL_PIN, gpioModeInput, 0);
|
||||
|
||||
// SPI R/w Indicator
|
||||
GPIO_PinModeSet(RW_PIN, gpioModePushPull, 1);
|
||||
|
||||
// Reset EFM8
|
||||
GPIO_PinModeSet(RESET_PIN, gpioModePushPull, 1);
|
||||
|
||||
TIMER_TopSet(TIMER0, 255);
|
||||
|
||||
RGB(LED_INIT_VALUE);
|
||||
|
||||
printing_init();
|
||||
|
||||
init_adc();
|
||||
|
||||
MSC_Init();
|
||||
|
||||
init_atomic_counter();
|
||||
if (sizeof(AuthenticatorState) > PAGE_SIZE)
|
||||
{
|
||||
printf2(TAG_ERR, "not enough room in page\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
CborEncoder test;
|
||||
uint8_t buf[64];
|
||||
cbor_encoder_init(&test, buf, 20, 0);
|
||||
|
||||
reset_efm8();
|
||||
|
||||
printf1(TAG_GEN,"Device init\r\n");
|
||||
int i=0;
|
||||
|
||||
for (i = 0; i < sizeof(buf); i++)
|
||||
{
|
||||
buf[i] = adc_rng();
|
||||
}
|
||||
|
||||
}
|
||||
#ifdef IS_BOOTLOADER
|
||||
typedef enum
|
||||
{
|
||||
BootWrite = 0x40,
|
||||
BootDone = 0x41,
|
||||
BootCheck = 0x42,
|
||||
BootErase = 0x43,
|
||||
} WalletOperation;
|
||||
|
||||
|
||||
typedef struct {
|
||||
uint8_t op;
|
||||
uint8_t addr[3];
|
||||
uint8_t tag[4];
|
||||
uint8_t len;
|
||||
uint8_t payload[255 - 9];
|
||||
} __attribute__((packed)) BootloaderReq;
|
||||
|
||||
//#define APPLICATION_START_ADDR 0x8000
|
||||
//#define APPLICATION_START_PAGE (0x8000/PAGE_SIZE)
|
||||
|
||||
//#define APPLICATION_END_ADDR (PAGE_SIZE*125-4) // NOT included in application
|
||||
|
||||
static void erase_application()
|
||||
{
|
||||
int page;
|
||||
uint32_t * ptrpage;
|
||||
for(page = APPLICATION_START_PAGE; page < APPLICATION_END_PAGE; page++)
|
||||
{
|
||||
ptrpage = page * PAGE_SIZE;
|
||||
MSC_ErasePage(ptrpage);
|
||||
}
|
||||
}
|
||||
|
||||
static void authorize_application()
|
||||
{
|
||||
uint32_t zero = 0;
|
||||
uint32_t * ptr;
|
||||
ptr = AUTH_WORD_ADDR;
|
||||
MSC_WriteWordFast(ptr,&zero, 4);
|
||||
}
|
||||
int bootloader_bridge(uint8_t klen, uint8_t * keyh)
|
||||
{
|
||||
static int has_erased = 0;
|
||||
BootloaderReq * req = (BootloaderReq * )keyh;
|
||||
uint8_t payload[256];
|
||||
uint8_t hash[32];
|
||||
uint8_t * pubkey = (uint8_t*)"\x57\xe6\x80\x39\x56\x46\x2f\x0c\x95\xac\x72\x71\xf0\xbc\xe8\x2d\x67\xd0\x59\x29\x2e\x15\x22\x89\x6a\xbd\x3f\x7f\x27\xf3\xc0\xc6\xe2\xd7\x7d\x8a\x9f\xcc\x53\xc5\x91\xb2\x0c\x9c\x3b\x4e\xa4\x87\x31\x67\xb4\xa9\x4b\x0e\x8d\x06\x67\xd8\xc5\xef\x2c\x50\x4a\x55";
|
||||
const struct uECC_Curve_t * curve = NULL;
|
||||
|
||||
/*printf("bootloader_bridge\n");*/
|
||||
if (req->len > 255-9)
|
||||
{
|
||||
return CTAP1_ERR_INVALID_LENGTH;
|
||||
}
|
||||
|
||||
memset(payload, 0xff, sizeof(payload));
|
||||
memmove(payload, req->payload, req->len);
|
||||
|
||||
uint32_t addr = (*((uint32_t*)req->addr)) & 0xffffff;
|
||||
|
||||
uint32_t * ptr = addr;
|
||||
|
||||
switch(req->op){
|
||||
case BootWrite:
|
||||
/*printf("BootWrite 0x%08x\n", addr);*/
|
||||
if (ptr < APPLICATION_START_ADDR || ptr >= APPLICATION_END_ADDR)
|
||||
{
|
||||
return CTAP2_ERR_NOT_ALLOWED;
|
||||
}
|
||||
|
||||
if (!has_erased)
|
||||
{
|
||||
erase_application();
|
||||
has_erased = 1;
|
||||
}
|
||||
if (is_authorized_to_boot())
|
||||
{
|
||||
printf2(TAG_ERR, "Error, boot check bypassed\n");
|
||||
exit(1);
|
||||
}
|
||||
MSC_WriteWordFast(ptr,payload, req->len + (req->len%4));
|
||||
break;
|
||||
case BootDone:
|
||||
// printf("BootDone\n");
|
||||
ptr = APPLICATION_START_ADDR;
|
||||
crypto_sha256_init();
|
||||
crypto_sha256_update(ptr, APPLICATION_END_ADDR-APPLICATION_START_ADDR);
|
||||
crypto_sha256_final(hash);
|
||||
// printf("hash: "); dump_hex(hash, 32);
|
||||
// printf("sig: "); dump_hex(payload, 64);
|
||||
curve = uECC_secp256r1();
|
||||
|
||||
if (! uECC_verify(pubkey,
|
||||
hash,
|
||||
32,
|
||||
payload,
|
||||
curve))
|
||||
{
|
||||
return CTAP2_ERR_OPERATION_DENIED;
|
||||
}
|
||||
authorize_application();
|
||||
REBOOT_FLAG = 1;
|
||||
break;
|
||||
case BootCheck:
|
||||
/*printf("BootCheck\n");*/
|
||||
return 0;
|
||||
break;
|
||||
case BootErase:
|
||||
/*printf("BootErase\n");*/
|
||||
erase_application();
|
||||
return 0;
|
||||
break;
|
||||
default:
|
||||
return CTAP1_ERR_INVALID_COMMAND;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int is_authorized_to_boot()
|
||||
{
|
||||
uint32_t * auth = AUTH_WORD_ADDR;
|
||||
return *auth == 0;
|
||||
}
|
||||
|
||||
#endif
|
@ -1,13 +0,0 @@
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "em_chip.h"
|
||||
#include "em_cmu.h"
|
||||
#include "em_emu.h"
|
||||
#include "em_core.h"
|
||||
#include "em_gpio.h"
|
||||
|
||||
#include "InitDevice.h"
|
||||
|
||||
#include "app.h"
|
||||
#include "cbor.h"
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user