Compare commits
98 Commits
cap_button
...
redue_boot
Author | SHA1 | Date | |
---|---|---|---|
0f8ddbf982 | |||
b2b9b5e0f9 | |||
9158453830 | |||
08658eb11e | |||
49d79fa5da | |||
69a7191860 | |||
a2fd507f45 | |||
a58658e35d | |||
bb2929b28f | |||
8e0eda8ed4 | |||
0ebe0ff502 | |||
7bcb7ea840 | |||
811a57f7ab | |||
5168afa16e | |||
208d26be89 | |||
45293fe998 | |||
a1a42fec5c | |||
8c256298ae | |||
01b928c0ec | |||
018a4d394c | |||
7a75fba6d3 | |||
c61f15a090 | |||
f072561899 | |||
6652feb4a2 | |||
fc7ea68d4a | |||
cb116efcc9 | |||
80b9df3e04 | |||
194ef5edcf | |||
006117bb6b | |||
75c75fa897 | |||
2969d09ffa | |||
b871e10d08 | |||
18d39a7047 | |||
a9bbdee35b | |||
321bbe3691 | |||
1ce191343f | |||
9041e5903c | |||
689d471688 | |||
8b9e44c3ed | |||
83dd92d9ba | |||
a5e1dc2a0c | |||
a053bbc669 | |||
3621f2ed4f | |||
3c7bf5a264 | |||
8bf1921263 | |||
e3ff136196 | |||
74181406fe | |||
987b04523d | |||
8023347c8e | |||
9dae7b2e7c | |||
cb13fb65de | |||
7fddd58704 | |||
3a1ea275cc | |||
22293f82f2 | |||
40c3c13b07 | |||
7042b0b656 | |||
ea803aab95 | |||
1100b159a9 | |||
9ddba5dfc3 | |||
35e52f4968 | |||
efddd2f3a8 | |||
17ceb7b9e8 | |||
188a34d1da | |||
9248c6462c | |||
118e129152 | |||
beb5a5892c | |||
d618081dd0 | |||
e4e0a3a84e | |||
3ba9b671fc | |||
69c34f9ca9 | |||
3b4c154fd1 | |||
ccd9a04146 | |||
bde4c09c21 | |||
5d3914bc5e | |||
abe306a649 | |||
41ceb78f6c | |||
8e192f2363 | |||
affc256ca2 | |||
32f920e372 | |||
a5aff478dd | |||
a5877f518f | |||
5a0cc0d02c | |||
b452e3dfe4 | |||
7f82233d17 | |||
8e3753e711 | |||
816ca21f08 | |||
6c60a37e8a | |||
ee351421cb | |||
bac576f3a0 | |||
6e637299e5 | |||
43b3e93854 | |||
5a448d636c | |||
7be0553377 | |||
a51417bf61 | |||
ba581db49c | |||
3a5cd786dc | |||
4fad28ea47 | |||
0ff9870612 |
@ -178,6 +178,25 @@
|
||||
"business",
|
||||
"ideas"
|
||||
]
|
||||
},
|
||||
{
|
||||
"login": "oplik0",
|
||||
"name": "Jakub",
|
||||
"avatar_url": "https://avatars2.githubusercontent.com/u/25460763?v=4",
|
||||
"profile": "https://github.com/oplik0",
|
||||
"contributions": [
|
||||
"bug"
|
||||
]
|
||||
},
|
||||
{
|
||||
"login": "jolo1581",
|
||||
"name": "Jan A.",
|
||||
"avatar_url": "https://avatars1.githubusercontent.com/u/53423977?v=4",
|
||||
"profile": "https://github.com/jolo1581",
|
||||
"contributions": [
|
||||
"code",
|
||||
"doc"
|
||||
]
|
||||
}
|
||||
],
|
||||
"contributorsPerLine": 7,
|
||||
|
2
Makefile
2
Makefile
@ -39,7 +39,7 @@ INCLUDES += -I./crypto/cifra/src
|
||||
|
||||
CFLAGS += $(INCLUDES)
|
||||
# for crypto/tiny-AES-c
|
||||
CFLAGS += -DAES256=1 -DAPP_CONFIG=\"app.h\"
|
||||
CFLAGS += -DAES256=1 -DAPP_CONFIG=\"app.h\" -DSOLO_EXPERIMENTAL=1
|
||||
|
||||
name = main
|
||||
|
||||
|
@ -135,6 +135,8 @@ Thanks goes to these wonderful people ([emoji key](https://allcontributors.org/d
|
||||
<td align="center"><a href="https://github.com/m3hm00d"><img src="https://avatars1.githubusercontent.com/u/42179593?v=4" width="100px;" alt="f.m3hm00d"/><br /><sub><b>f.m3hm00d</b></sub></a><br /><a href="https://github.com/solokeys/solo/commits?author=m3hm00d" title="Documentation">📖</a></td>
|
||||
<td align="center"><a href="http://blogs.gnome.org/hughsie/"><img src="https://avatars0.githubusercontent.com/u/151380?v=4" width="100px;" alt="Richard Hughes"/><br /><sub><b>Richard Hughes</b></sub></a><br /><a href="#ideas-hughsie" title="Ideas, Planning, & Feedback">🤔</a> <a href="https://github.com/solokeys/solo/commits?author=hughsie" title="Code">💻</a> <a href="#infra-hughsie" title="Infrastructure (Hosting, Build-Tools, etc)">🚇</a> <a href="#tool-hughsie" title="Tools">🔧</a></td>
|
||||
<td align="center"><a href="http://www.schulz.dk"><img src="https://avatars1.githubusercontent.com/u/1150049?v=4" width="100px;" alt="Kim Schulz"/><br /><sub><b>Kim Schulz</b></sub></a><br /><a href="#business-kimusan" title="Business development">💼</a> <a href="#ideas-kimusan" title="Ideas, Planning, & Feedback">🤔</a></td>
|
||||
<td align="center"><a href="https://github.com/oplik0"><img src="https://avatars2.githubusercontent.com/u/25460763?v=4" width="100px;" alt="Jakub"/><br /><sub><b>Jakub</b></sub></a><br /><a href="https://github.com/solokeys/solo/issues?q=author%3Aoplik0" title="Bug reports">🐛</a></td>
|
||||
<td align="center"><a href="https://github.com/jolo1581"><img src="https://avatars1.githubusercontent.com/u/53423977?v=4" width="100px;" alt="Jan A."/><br /><sub><b>Jan A.</b></sub></a><br /><a href="https://github.com/solokeys/solo/commits?author=jolo1581" title="Code">💻</a> <a href="https://github.com/solokeys/solo/commits?author=jolo1581" title="Documentation">📖</a></td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
@ -168,7 +170,7 @@ You can buy Solo, Solo Tap, and Solo for Hackers at [solokeys.com](https://solok
|
||||
<br/>
|
||||
|
||||
[](https://github.com/solokeys/solo/blob/master/LICENSE)
|
||||
[](#contributors)
|
||||
[](#contributors)
|
||||
[](https://travis-ci.com/solokeys/solo)
|
||||
[](https://discourse.solokeys.com)
|
||||
[](https://keybase.io/team/solokeys.public)
|
||||
|
@ -1 +1 @@
|
||||
2.4.3
|
||||
2.5.3
|
||||
|
@ -115,7 +115,7 @@ If the checks succeed, you are ready to program the device attestation key and c
|
||||
### Programming an attestation key and certificate
|
||||
|
||||
Convert the DER format of the device attestation certificate to "C" bytes using our utility script. You may first need to
|
||||
first install prerequisite python modules (pip install -r tools/requirements.txt).
|
||||
first install prerequisite python modules (`pip install -r tools/requirements.txt`).
|
||||
|
||||
```
|
||||
python tools/gencert/cbytes.py device_cert.der
|
||||
@ -123,7 +123,7 @@ python tools/gencert/cbytes.py device_cert.der
|
||||
|
||||
Copy the byte string portion into the [`attestation.c` source file of Solo](https://github.com/solokeys/solo/blob/master/targets/stm32l432/src/attestation.c). Overwrite the development or "default" certificate that is already there.
|
||||
|
||||
Now [build the Solo firmware](/solo/building), either a secure or hacker build. You will need to produce a bootloader.hex file and a solo.hex file.
|
||||
Now [build the Solo firmware](/solo/building), either a secure or hacker build. You will need to produce a `bootloader.hex` file and a `solo.hex` file.
|
||||
|
||||
Print your attestation key in a hex string format.
|
||||
|
||||
@ -131,11 +131,11 @@ Print your attestation key in a hex string format.
|
||||
python tools/print_x_y.py device_key.pem
|
||||
```
|
||||
|
||||
Merge the bootloader.hex, solo.hex, and attestion key into one firmware file.
|
||||
Merge the `bootloader.hex`, `solo.hex`, and attestion key into one firmware file.
|
||||
|
||||
```
|
||||
solo mergehex --attestation-key <attestation-key-hex-string> bootloader.hex solo.hex all.hex
|
||||
```
|
||||
|
||||
Now you have a newly create `all.hex` file with a custom attestation key. You can [program this all.hex file
|
||||
with Solo in DFU mode](/solo/programming#procedure).
|
||||
Now you have a newly create `all.hex` file with a custom attestation key. You can [program this `all.hex` file
|
||||
with Solo in DFU mode](/solo/programming#procedure).
|
||||
|
@ -85,14 +85,13 @@ brew install arm-none-eabi-gcc
|
||||
### Install flashing software
|
||||
|
||||
ST provides a CLI flashing tool - `STM32_Programmer_CLI`. It can be downloaded directly from the vendor's site:
|
||||
1\. Go to [download site URL](https://www.st.com/content/st_com/en/products/development-tools/software-development-tools/stm32-software-development-tools/stm32-programmers/stm32cubeprog.html),
|
||||
go to bottom page and from STM32CubeProg row select Download button.
|
||||
2\. Unzip contents of the archive.
|
||||
3\. Run \*Linux setup
|
||||
4\. In installation directory go to ./bin - there the ./STM32_Programmer_CLI is located
|
||||
5\. Add symlink to the STM32 CLI binary to .local/bin. Make sure the latter it is in $PATH.
|
||||
1. Go to [download site URL](https://www.st.com/content/st_com/en/products/development-tools/software-development-tools/stm32-software-development-tools/stm32-programmers/stm32cubeprog.html), go to bottom page and from STM32CubeProg row select Download button.
|
||||
2. Unzip contents of the archive.
|
||||
3. Run \*Linux setup
|
||||
4. In installation directory go to `./bin` - there the `./STM32_Programmer_CLI` is located
|
||||
5. Add symlink to the STM32 CLI binary to `.local/bin`. Make sure the latter it is in `$PATH`.
|
||||
|
||||
If you're on OsX and installed the STM32CubeProg, you need to add the following to your path:
|
||||
If you're on MacOS X and installed the STM32CubeProg, you need to add the following to your path:
|
||||
|
||||
```bash
|
||||
# ~/.bash_profile
|
||||
|
@ -3,16 +3,16 @@
|
||||
## Random number generation
|
||||
|
||||
Solo contains a True Random Number Generator (TRNG). A TRNG is a hardware based mechanism
|
||||
that leverages natural phenomenon to generate random numbers, which is can be better than a traditional
|
||||
that leverages natural phenomenon to generate random numbers, which can be better than a traditional
|
||||
RNG that has state and updates deterministically using cryptographic methods.
|
||||
|
||||
You can easily access the TRNG stream on Solo using our python tool [solo-python](https://github.com/solokeys/solo-python).
|
||||
You can easily access the TRNG stream on Solo using our python tool [`solo-python`](https://github.com/solokeys/solo-python).
|
||||
|
||||
```
|
||||
solo key rng raw > random.bin
|
||||
```
|
||||
|
||||
Or you can seed the state of the RNG on your kernel (/dev/random).
|
||||
Or you can seed the state of the RNG on your kernel (`/dev/random`).
|
||||
|
||||
```
|
||||
solo key rng feedkernel
|
||||
|
@ -18,7 +18,7 @@ Further progress is tracked in: <https://github.com/solokeys/solo/issues/144>.
|
||||
If you still need to setup a rule, a simple way to do it is:
|
||||
|
||||
```
|
||||
git clone git@github.com:solokeys/solo.git
|
||||
git clone https://github.com/solokeys/solo.git
|
||||
cd solo/udev
|
||||
make setup
|
||||
```
|
||||
|
18
fido2/apdu.c
18
fido2/apdu.c
@ -9,7 +9,7 @@
|
||||
|
||||
#include "apdu.h"
|
||||
|
||||
int apdu_decode(uint8_t *data, size_t len, APDU_STRUCT *apdu)
|
||||
uint16_t apdu_decode(uint8_t *data, size_t len, APDU_STRUCT *apdu)
|
||||
{
|
||||
EXT_APDU_HEADER *hapdu = (EXT_APDU_HEADER *)data;
|
||||
|
||||
@ -62,6 +62,11 @@ int apdu_decode(uint8_t *data, size_t len, APDU_STRUCT *apdu)
|
||||
if (len >= 7 && b0 == 0)
|
||||
{
|
||||
uint16_t extlen = (hapdu->lc[1] << 8) + hapdu->lc[2];
|
||||
|
||||
if (len - 7 < extlen)
|
||||
{
|
||||
return SW_WRONG_LENGTH;
|
||||
}
|
||||
|
||||
// case 2E (Le) - extended
|
||||
if (len == 7)
|
||||
@ -103,9 +108,18 @@ int apdu_decode(uint8_t *data, size_t len, APDU_STRUCT *apdu)
|
||||
apdu->le = 0x10000;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if ((len > 5) && (len - 5 < hapdu->lc[0]))
|
||||
{
|
||||
return SW_WRONG_LENGTH;
|
||||
}
|
||||
}
|
||||
|
||||
if (!apdu->case_type)
|
||||
return 1;
|
||||
{
|
||||
return SW_COND_USE_NOT_SATISFIED;
|
||||
}
|
||||
|
||||
if (apdu->lc)
|
||||
{
|
||||
|
@ -36,7 +36,7 @@ typedef struct
|
||||
uint8_t case_type;
|
||||
} __attribute__((packed)) APDU_STRUCT;
|
||||
|
||||
extern int apdu_decode(uint8_t *data, size_t len, APDU_STRUCT *apdu);
|
||||
extern uint16_t apdu_decode(uint8_t *data, size_t len, APDU_STRUCT *apdu);
|
||||
|
||||
#define APDU_FIDO_U2F_REGISTER 0x01
|
||||
#define APDU_FIDO_U2F_AUTHENTICATE 0x02
|
||||
|
144
fido2/ctap.c
144
fido2/ctap.c
@ -25,11 +25,11 @@
|
||||
#include "extensions.h"
|
||||
|
||||
#include "device.h"
|
||||
#include "data_migration.h"
|
||||
|
||||
uint8_t PIN_TOKEN[PIN_TOKEN_SIZE];
|
||||
uint8_t KEY_AGREEMENT_PUB[64];
|
||||
static uint8_t KEY_AGREEMENT_PRIV[32];
|
||||
static uint8_t PIN_CODE_HASH[32];
|
||||
static int8_t PIN_BOOT_ATTEMPTS_LEFT = PIN_BOOT_ATTEMPTS;
|
||||
|
||||
AuthenticatorState STATE;
|
||||
@ -438,7 +438,11 @@ static int ctap2_user_presence_test()
|
||||
{
|
||||
device_set_status(CTAPHID_STATUS_UPNEEDED);
|
||||
int ret = ctap_user_presence_test(CTAP2_UP_DELAY_MS);
|
||||
if ( ret > 0 )
|
||||
if ( ret > 1 )
|
||||
{
|
||||
return CTAP2_ERR_PROCESSING;
|
||||
}
|
||||
else if ( ret > 0 )
|
||||
{
|
||||
return CTAP1_ERR_SUCCESS;
|
||||
}
|
||||
@ -482,11 +486,19 @@ static int ctap_make_auth_data(struct rpId * rp, CborEncoder * map, uint8_t * au
|
||||
int but;
|
||||
|
||||
but = ctap2_user_presence_test(CTAP2_UP_DELAY_MS);
|
||||
check_retr(but);
|
||||
if (CTAP2_ERR_PROCESSING == but)
|
||||
{
|
||||
authData->head.flags = (0 << 0); // User presence disabled
|
||||
}
|
||||
else
|
||||
{
|
||||
check_retr(but);
|
||||
authData->head.flags = (1 << 0); // User presence
|
||||
}
|
||||
|
||||
|
||||
device_set_status(CTAPHID_STATUS_PROCESSING);
|
||||
|
||||
authData->head.flags = (but << 0);
|
||||
authData->head.flags |= (ctap_is_pin_set() << 2);
|
||||
|
||||
|
||||
@ -670,7 +682,16 @@ int ctap_authenticate_credential(struct rpId * rp, CTAP_credentialDescriptor * d
|
||||
switch(desc->type)
|
||||
{
|
||||
case PUB_KEY_CRED_PUB_KEY:
|
||||
make_auth_tag(desc->credential.id.rpIdHash, desc->credential.id.nonce, desc->credential.id.count, tag);
|
||||
crypto_sha256_init();
|
||||
crypto_sha256_update(rp->id, rp->size);
|
||||
crypto_sha256_final(rpIdHash);
|
||||
|
||||
printf1(TAG_RED,"rpId: %s\r\n", rp->id); dump_hex1(TAG_RED,rp->id, rp->size);
|
||||
if (memcmp(desc->credential.id.rpIdHash, rpIdHash, 32) != 0)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
make_auth_tag(rpIdHash, desc->credential.id.nonce, desc->credential.id.count, tag);
|
||||
return (memcmp(desc->credential.id.tag, tag, CREDENTIAL_TAG_SIZE) == 0);
|
||||
break;
|
||||
case PUB_KEY_CRED_CTAP1:
|
||||
@ -734,7 +755,7 @@ uint8_t ctap_make_credential(CborEncoder * encoder, uint8_t * request, int lengt
|
||||
}
|
||||
}
|
||||
|
||||
if (MC.up)
|
||||
if (MC.up == 1 || MC.up == 0)
|
||||
{
|
||||
return CTAP2_ERR_INVALID_OPTION;
|
||||
}
|
||||
@ -1227,8 +1248,9 @@ uint8_t ctap_get_assertion(CborEncoder * encoder, uint8_t * request, int length)
|
||||
else
|
||||
#endif
|
||||
{
|
||||
|
||||
device_disable_up(GA.up == 0);
|
||||
ret = ctap_make_auth_data(&GA.rp, &map, auth_data_buf, &auth_data_buf_sz, NULL);
|
||||
device_disable_up(false);
|
||||
check_retr(ret);
|
||||
|
||||
((CTAP_authDataHeader *)auth_data_buf)->flags &= ~(1 << 2);
|
||||
@ -1286,11 +1308,13 @@ uint8_t ctap_update_pin_if_verified(uint8_t * pinEnc, int len, uint8_t * platfor
|
||||
uint8_t hmac[32];
|
||||
int ret;
|
||||
|
||||
// Validate incoming data packet len
|
||||
if (len < 64)
|
||||
{
|
||||
return CTAP1_ERR_OTHER;
|
||||
}
|
||||
|
||||
// Validate device's state
|
||||
if (ctap_is_pin_set()) // Check first, prevent SCA
|
||||
{
|
||||
if (ctap_device_locked())
|
||||
@ -1303,6 +1327,7 @@ uint8_t ctap_update_pin_if_verified(uint8_t * pinEnc, int len, uint8_t * platfor
|
||||
}
|
||||
}
|
||||
|
||||
// calculate shared_secret
|
||||
crypto_ecc256_shared_secret(platform_pubkey, KEY_AGREEMENT_PRIV, shared_secret);
|
||||
|
||||
crypto_sha256_init();
|
||||
@ -1325,6 +1350,7 @@ uint8_t ctap_update_pin_if_verified(uint8_t * pinEnc, int len, uint8_t * platfor
|
||||
return CTAP2_ERR_PIN_AUTH_INVALID;
|
||||
}
|
||||
|
||||
// decrypt new PIN with shared secret
|
||||
crypto_aes256_init(shared_secret, NULL);
|
||||
|
||||
while((len & 0xf) != 0) // round up to nearest AES block size multiple
|
||||
@ -1334,7 +1360,7 @@ uint8_t ctap_update_pin_if_verified(uint8_t * pinEnc, int len, uint8_t * platfor
|
||||
|
||||
crypto_aes256_decrypt(pinEnc, len);
|
||||
|
||||
|
||||
// validate new PIN (length)
|
||||
|
||||
ret = trailing_zeros(pinEnc, NEW_PIN_ENC_MIN_SIZE - 1);
|
||||
ret = NEW_PIN_ENC_MIN_SIZE - ret;
|
||||
@ -1350,6 +1376,8 @@ uint8_t ctap_update_pin_if_verified(uint8_t * pinEnc, int len, uint8_t * platfor
|
||||
dump_hex1(TAG_CP, pinEnc, ret);
|
||||
}
|
||||
|
||||
// validate device's state, decrypt and compare pinHashEnc (user provided current PIN hash) with stored PIN_CODE_HASH
|
||||
|
||||
if (ctap_is_pin_set())
|
||||
{
|
||||
if (ctap_device_locked())
|
||||
@ -1362,7 +1390,14 @@ uint8_t ctap_update_pin_if_verified(uint8_t * pinEnc, int len, uint8_t * platfor
|
||||
}
|
||||
crypto_aes256_reset_iv(NULL);
|
||||
crypto_aes256_decrypt(pinHashEnc, 16);
|
||||
if (memcmp(pinHashEnc, PIN_CODE_HASH, 16) != 0)
|
||||
|
||||
uint8_t pinHashEncSalted[32];
|
||||
crypto_sha256_init();
|
||||
crypto_sha256_update(pinHashEnc, 16);
|
||||
crypto_sha256_update(STATE.PIN_SALT, sizeof(STATE.PIN_SALT));
|
||||
crypto_sha256_final(pinHashEncSalted);
|
||||
|
||||
if (memcmp(pinHashEncSalted, STATE.PIN_CODE_HASH, 16) != 0)
|
||||
{
|
||||
ctap_reset_key_agreement();
|
||||
ctap_decrement_pin_attempts();
|
||||
@ -1378,6 +1413,7 @@ uint8_t ctap_update_pin_if_verified(uint8_t * pinEnc, int len, uint8_t * platfor
|
||||
}
|
||||
}
|
||||
|
||||
// set new PIN (update and store PIN_CODE_HASH)
|
||||
ctap_update_pin(pinEnc, ret);
|
||||
|
||||
return 0;
|
||||
@ -1397,12 +1433,16 @@ uint8_t ctap_add_pin_if_verified(uint8_t * pinTokenEnc, uint8_t * platform_pubke
|
||||
|
||||
crypto_aes256_decrypt(pinHashEnc, 16);
|
||||
|
||||
|
||||
if (memcmp(pinHashEnc, PIN_CODE_HASH, 16) != 0)
|
||||
uint8_t pinHashEncSalted[32];
|
||||
crypto_sha256_init();
|
||||
crypto_sha256_update(pinHashEnc, 16);
|
||||
crypto_sha256_update(STATE.PIN_SALT, sizeof(STATE.PIN_SALT));
|
||||
crypto_sha256_final(pinHashEncSalted);
|
||||
if (memcmp(pinHashEncSalted, STATE.PIN_CODE_HASH, 16) != 0)
|
||||
{
|
||||
printf2(TAG_ERR,"Pin does not match!\n");
|
||||
printf2(TAG_ERR,"platform-pin-hash: "); dump_hex1(TAG_ERR, pinHashEnc, 16);
|
||||
printf2(TAG_ERR,"authentic-pin-hash: "); dump_hex1(TAG_ERR, PIN_CODE_HASH, 16);
|
||||
printf2(TAG_ERR,"authentic-pin-hash: "); dump_hex1(TAG_ERR, STATE.PIN_CODE_HASH, 16);
|
||||
printf2(TAG_ERR,"shared-secret: "); dump_hex1(TAG_ERR, shared_secret, 32);
|
||||
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);
|
||||
@ -1710,12 +1750,39 @@ static void ctap_state_init()
|
||||
STATE.remaining_tries = PIN_LOCKOUT_ATTEMPTS;
|
||||
STATE.is_pin_set = 0;
|
||||
STATE.rk_stored = 0;
|
||||
STATE.data_version = STATE_VERSION;
|
||||
|
||||
ctap_reset_rk();
|
||||
|
||||
if (ctap_generate_rng(STATE.PIN_SALT, sizeof(STATE.PIN_SALT)) != 1) {
|
||||
printf2(TAG_ERR, "Error, rng failed\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
printf1(TAG_STOR, "Generated PIN SALT: ");
|
||||
dump_hex1(TAG_STOR, STATE.PIN_SALT, sizeof STATE.PIN_SALT);
|
||||
}
|
||||
|
||||
/** Overwrite master secret from external source.
|
||||
* @param keybytes an array of KEY_SPACE_BYTES length.
|
||||
*
|
||||
* This function should only be called from a privilege mode.
|
||||
*/
|
||||
void ctap_load_external_keys(uint8_t * keybytes){
|
||||
memmove(STATE.key_space, keybytes, KEY_SPACE_BYTES);
|
||||
authenticator_write_state(&STATE, 0);
|
||||
authenticator_write_state(&STATE, 1);
|
||||
crypto_load_master_secret(STATE.key_space);
|
||||
}
|
||||
|
||||
#include "version.h"
|
||||
void ctap_init()
|
||||
{
|
||||
printf1(TAG_ERR,"Current firmware version address: %p\r\n", &firmware_version);
|
||||
printf1(TAG_ERR,"Current firmware version: %d.%d.%d.%d (%02x.%02x.%02x.%02x)\r\n",
|
||||
firmware_version.major, firmware_version.minor, firmware_version.patch, firmware_version.reserved,
|
||||
firmware_version.major, firmware_version.minor, firmware_version.patch, firmware_version.reserved
|
||||
);
|
||||
crypto_ecc256_init();
|
||||
|
||||
authenticator_read_state(&STATE);
|
||||
@ -1744,14 +1811,12 @@ void ctap_init()
|
||||
}
|
||||
}
|
||||
|
||||
do_migration_if_required(&STATE);
|
||||
|
||||
crypto_load_master_secret(STATE.key_space);
|
||||
|
||||
if (ctap_is_pin_set())
|
||||
{
|
||||
printf1(TAG_STOR,"pin code: \"%s\"\n", STATE.pin_code);
|
||||
crypto_sha256_init();
|
||||
crypto_sha256_update(STATE.pin_code, STATE.pin_code_length);
|
||||
crypto_sha256_final(PIN_CODE_HASH);
|
||||
printf1(TAG_STOR, "attempts_left: %d\n", STATE.remaining_tries);
|
||||
}
|
||||
else
|
||||
@ -1783,34 +1848,38 @@ uint8_t ctap_is_pin_set()
|
||||
return STATE.is_pin_set == 1;
|
||||
}
|
||||
|
||||
uint8_t ctap_pin_matches(uint8_t * pin, int len)
|
||||
{
|
||||
return memcmp(pin, STATE.pin_code, len) == 0;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Set new PIN, by updating PIN hash. Save state.
|
||||
* Globals: STATE
|
||||
* @param pin new PIN (raw)
|
||||
* @param len pin array length
|
||||
*/
|
||||
void ctap_update_pin(uint8_t * pin, int len)
|
||||
{
|
||||
if (len > NEW_PIN_ENC_MIN_SIZE || len < 4)
|
||||
if (len >= NEW_PIN_ENC_MIN_SIZE || len < 4)
|
||||
{
|
||||
printf2(TAG_ERR, "Update pin fail length\n");
|
||||
exit(1);
|
||||
}
|
||||
memset(STATE.pin_code, 0, NEW_PIN_ENC_MIN_SIZE);
|
||||
memmove(STATE.pin_code, pin, len);
|
||||
STATE.pin_code_length = len;
|
||||
STATE.pin_code[NEW_PIN_ENC_MIN_SIZE - 1] = 0;
|
||||
|
||||
crypto_sha256_init();
|
||||
crypto_sha256_update(STATE.pin_code, len);
|
||||
crypto_sha256_final(PIN_CODE_HASH);
|
||||
crypto_sha256_update(pin, len);
|
||||
uint8_t intermediateHash[32];
|
||||
crypto_sha256_final(intermediateHash);
|
||||
|
||||
crypto_sha256_init();
|
||||
crypto_sha256_update(intermediateHash, 16);
|
||||
memset(intermediateHash, 0, sizeof(intermediateHash));
|
||||
crypto_sha256_update(STATE.PIN_SALT, sizeof(STATE.PIN_SALT));
|
||||
crypto_sha256_final(STATE.PIN_CODE_HASH);
|
||||
|
||||
STATE.is_pin_set = 1;
|
||||
|
||||
authenticator_write_state(&STATE, 1);
|
||||
authenticator_write_state(&STATE, 0);
|
||||
|
||||
printf1(TAG_CTAP, "New pin set: %s\n", STATE.pin_code);
|
||||
printf1(TAG_CTAP, "New pin set: %s [%d]\n", pin, len);
|
||||
dump_hex1(TAG_ERR, STATE.PIN_CODE_HASH, sizeof(STATE.PIN_CODE_HASH));
|
||||
}
|
||||
|
||||
uint8_t ctap_decrement_pin_attempts()
|
||||
@ -1827,9 +1896,7 @@ uint8_t ctap_decrement_pin_attempts()
|
||||
|
||||
if (ctap_device_locked())
|
||||
{
|
||||
memset(PIN_TOKEN,0,sizeof(PIN_TOKEN));
|
||||
memset(PIN_CODE_HASH,0,sizeof(PIN_CODE_HASH));
|
||||
printf1(TAG_CP, "Device locked!\n");
|
||||
lock_device_permanently();
|
||||
}
|
||||
}
|
||||
else
|
||||
@ -1985,8 +2052,17 @@ void ctap_reset()
|
||||
}
|
||||
|
||||
ctap_reset_state();
|
||||
memset(PIN_CODE_HASH,0,sizeof(PIN_CODE_HASH));
|
||||
ctap_reset_key_agreement();
|
||||
|
||||
crypto_load_master_secret(STATE.key_space);
|
||||
}
|
||||
|
||||
void lock_device_permanently() {
|
||||
memset(PIN_TOKEN, 0, sizeof(PIN_TOKEN));
|
||||
memset(STATE.PIN_CODE_HASH, 0, sizeof(STATE.PIN_CODE_HASH));
|
||||
|
||||
printf1(TAG_CP, "Device locked!\n");
|
||||
|
||||
authenticator_write_state(&STATE, 0);
|
||||
authenticator_write_state(&STATE, 1);
|
||||
}
|
||||
|
@ -359,5 +359,8 @@ uint16_t ctap_key_len(uint8_t index);
|
||||
extern uint8_t PIN_TOKEN[PIN_TOKEN_SIZE];
|
||||
extern uint8_t KEY_AGREEMENT_PUB[64];
|
||||
|
||||
void lock_device_permanently();
|
||||
|
||||
void ctap_load_external_keys(uint8_t * keybytes);
|
||||
|
||||
#endif
|
||||
|
@ -715,6 +715,7 @@ uint8_t ctap_parse_make_credential(CTAP_makeCredential * MC, CborEncoder * encod
|
||||
CborValue it,map;
|
||||
|
||||
memset(MC, 0, sizeof(CTAP_makeCredential));
|
||||
MC->up = 0xff;
|
||||
ret = cbor_parser_init(request, length, CborValidateCanonicalFormat, &parser, &it);
|
||||
check_retr(ret);
|
||||
|
||||
@ -1010,6 +1011,7 @@ uint8_t ctap_parse_get_assertion(CTAP_getAssertion * GA, uint8_t * request, int
|
||||
|
||||
memset(GA, 0, sizeof(CTAP_getAssertion));
|
||||
GA->creds = getAssertionState.creds; // Save stack memory
|
||||
GA->up = 0xff;
|
||||
|
||||
ret = cbor_parser_init(request, length, CborValidateCanonicalFormat, &parser, &it);
|
||||
check_ret(ret);
|
||||
|
341
fido2/ctaphid.c
341
fido2/ctaphid.c
@ -16,6 +16,7 @@
|
||||
#include "util.h"
|
||||
#include "log.h"
|
||||
#include "extensions.h"
|
||||
#include "version.h"
|
||||
|
||||
// move custom SHA512 command out,
|
||||
// and the following headers too
|
||||
@ -538,11 +539,14 @@ extern void _check_ret(CborError ret, int line, const char * filename);
|
||||
#define check_hardcore(r) _check_ret(r,__LINE__, __FILE__);\
|
||||
if ((r) != CborNoError) exit(1);
|
||||
|
||||
|
||||
uint8_t ctaphid_custom_command(int len, CTAP_RESPONSE * ctap_resp, CTAPHID_WRITE_BUFFER * wb);
|
||||
|
||||
uint8_t ctaphid_handle_packet(uint8_t * pkt_raw)
|
||||
{
|
||||
uint8_t cmd;
|
||||
uint8_t cmd = 0;
|
||||
uint32_t cid;
|
||||
int len;
|
||||
int len = 0;
|
||||
#ifndef DISABLE_CTAPHID_CBOR
|
||||
int status;
|
||||
#endif
|
||||
@ -552,6 +556,10 @@ uint8_t ctaphid_handle_packet(uint8_t * pkt_raw)
|
||||
CTAP_RESPONSE ctap_resp;
|
||||
|
||||
int bufstatus = ctaphid_buffer_packet(pkt_raw, &cmd, &cid, &len);
|
||||
ctaphid_write_buffer_init(&wb);
|
||||
|
||||
wb.cid = cid;
|
||||
wb.cmd = cmd;
|
||||
|
||||
if (bufstatus == HID_IGNORE)
|
||||
{
|
||||
@ -587,9 +595,6 @@ uint8_t ctaphid_handle_packet(uint8_t * pkt_raw)
|
||||
case CTAPHID_PING:
|
||||
printf1(TAG_HID,"CTAPHID_PING\n");
|
||||
|
||||
ctaphid_write_buffer_init(&wb);
|
||||
wb.cid = cid;
|
||||
wb.cmd = CTAPHID_PING;
|
||||
wb.bcnt = len;
|
||||
timestamp();
|
||||
ctaphid_write(&wb, ctap_buffer, len);
|
||||
@ -602,13 +607,9 @@ uint8_t ctaphid_handle_packet(uint8_t * pkt_raw)
|
||||
case CTAPHID_WINK:
|
||||
printf1(TAG_HID,"CTAPHID_WINK\n");
|
||||
|
||||
ctaphid_write_buffer_init(&wb);
|
||||
|
||||
device_wink();
|
||||
|
||||
wb.cid = cid;
|
||||
wb.cmd = CTAPHID_WINK;
|
||||
|
||||
ctaphid_write(&wb,NULL,0);
|
||||
|
||||
break;
|
||||
@ -633,9 +634,6 @@ uint8_t ctaphid_handle_packet(uint8_t * pkt_raw)
|
||||
ctap_response_init(&ctap_resp);
|
||||
status = ctap_request(ctap_buffer, len, &ctap_resp);
|
||||
|
||||
ctaphid_write_buffer_init(&wb);
|
||||
wb.cid = cid;
|
||||
wb.cmd = CTAPHID_CBOR;
|
||||
wb.bcnt = (ctap_resp.length+1);
|
||||
|
||||
|
||||
@ -666,9 +664,6 @@ uint8_t ctaphid_handle_packet(uint8_t * pkt_raw)
|
||||
ctap_response_init(&ctap_resp);
|
||||
u2f_request((struct u2f_request_apdu*)ctap_buffer, &ctap_resp);
|
||||
|
||||
ctaphid_write_buffer_init(&wb);
|
||||
wb.cid = cid;
|
||||
wb.cmd = CTAPHID_MSG;
|
||||
wb.bcnt = (ctap_resp.length);
|
||||
|
||||
ctaphid_write(&wb, ctap_resp.data, ctap_resp.length);
|
||||
@ -679,209 +674,14 @@ 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);
|
||||
break;
|
||||
if (ctaphid_custom_command(len, &ctap_resp, &wb) != 0){
|
||||
is_busy = 0;
|
||||
}else{
|
||||
printf2(TAG_ERR, "error, unimplemented HID cmd: %02x\r\n", buffer_cmd());
|
||||
ctaphid_send_error(cid, CTAP1_ERR_INVALID_COMMAND);
|
||||
}
|
||||
}
|
||||
cid_del(cid);
|
||||
buffer_reset();
|
||||
@ -891,3 +691,112 @@ uint8_t ctaphid_handle_packet(uint8_t * pkt_raw)
|
||||
else return 0;
|
||||
|
||||
}
|
||||
|
||||
uint8_t ctaphid_custom_command(int len, CTAP_RESPONSE * ctap_resp, CTAPHID_WRITE_BUFFER * wb)
|
||||
{
|
||||
ctap_response_init(ctap_resp);
|
||||
|
||||
#if !defined(IS_BOOTLOADER) && (defined(SOLO_HACKER) || defined(SOLO_EXPERIMENTAL))
|
||||
uint32_t param;
|
||||
#endif
|
||||
#if defined(IS_BOOTLOADER)
|
||||
uint8_t is_busy;
|
||||
#endif
|
||||
|
||||
switch(wb->cmd)
|
||||
{
|
||||
#if defined(IS_BOOTLOADER)
|
||||
case CTAPHID_BOOT:
|
||||
printf1(TAG_HID,"CTAPHID_BOOT\n");
|
||||
u2f_set_writeback_buffer(ctap_resp);
|
||||
is_busy = bootloader_bridge(len, ctap_buffer);
|
||||
|
||||
ctaphid_write(wb, &is_busy, 1);
|
||||
ctaphid_write(wb, ctap_resp->data, ctap_resp->length);
|
||||
ctaphid_write(wb, NULL, 0);
|
||||
return 1;
|
||||
#endif
|
||||
#if defined(SOLO_HACKER)
|
||||
case CTAPHID_ENTERBOOT:
|
||||
printf1(TAG_HID,"CTAPHID_ENTERBOOT\n");
|
||||
boot_solo_bootloader();
|
||||
wb->bcnt = 0;
|
||||
ctaphid_write(wb, NULL, 0);
|
||||
return 1;
|
||||
case CTAPHID_ENTERSTBOOT:
|
||||
printf1(TAG_HID,"CTAPHID_ENTERBOOT\n");
|
||||
boot_st_bootloader();
|
||||
return 1;
|
||||
#endif
|
||||
|
||||
#if !defined(IS_BOOTLOADER)
|
||||
case CTAPHID_GETRNG:
|
||||
printf1(TAG_HID,"CTAPHID_GETRNG\n");
|
||||
wb->bcnt = ctap_buffer[0];
|
||||
if (!wb->bcnt)
|
||||
wb->bcnt = 57;
|
||||
memset(ctap_buffer,0,wb->bcnt);
|
||||
ctap_generate_rng(ctap_buffer, wb->bcnt);
|
||||
ctaphid_write(wb, ctap_buffer, wb->bcnt);
|
||||
ctaphid_write(wb, NULL, 0);
|
||||
return 1;
|
||||
break;
|
||||
#endif
|
||||
|
||||
case CTAPHID_GETVERSION:
|
||||
printf1(TAG_HID,"CTAPHID_GETVERSION\n");
|
||||
wb->bcnt = 3;
|
||||
ctap_buffer[0] = SOLO_VERSION_MAJ;
|
||||
ctap_buffer[1] = SOLO_VERSION_MIN;
|
||||
ctap_buffer[2] = SOLO_VERSION_PATCH;
|
||||
ctaphid_write(wb, ctap_buffer, 3);
|
||||
ctaphid_write(wb, NULL, 0);
|
||||
return 1;
|
||||
break;
|
||||
|
||||
#if !defined(IS_BOOTLOADER) && (defined(SOLO_HACKER) || defined(SOLO_EXPERIMENTAL))
|
||||
case CTAPHID_LOADKEY:
|
||||
/**
|
||||
* Load external key. Useful for enabling backups.
|
||||
* bytes: 4 96
|
||||
* payload: | counter_increase (BE) | master_key |
|
||||
*
|
||||
* Counter should be increased by a large amount, e.g. (0x10000000)
|
||||
* to outdo any previously lost/broken keys.
|
||||
*/
|
||||
printf1(TAG_HID,"CTAPHID_LOADKEY\n");
|
||||
if (len != 100)
|
||||
{
|
||||
printf2(TAG_ERR,"Error, invalid length.\n");
|
||||
ctaphid_send_error(wb->cid, CTAP1_ERR_INVALID_LENGTH);
|
||||
return 1;
|
||||
}
|
||||
|
||||
// Ask for THREE button presses
|
||||
if (ctap_user_presence_test(8000) > 0)
|
||||
if (ctap_user_presence_test(8000) > 0)
|
||||
if (ctap_user_presence_test(8000) > 0)
|
||||
{
|
||||
ctap_load_external_keys(ctap_buffer + 4);
|
||||
param = ctap_buffer[3];
|
||||
param |= ctap_buffer[2] << 8;
|
||||
param |= ctap_buffer[1] << 16;
|
||||
param |= ctap_buffer[0] << 24;
|
||||
ctap_atomic_count(param);
|
||||
|
||||
wb->bcnt = 0;
|
||||
|
||||
ctaphid_write(wb, NULL, 0);
|
||||
return 1;
|
||||
}
|
||||
|
||||
printf2(TAG_ERR, "Error, invalid length.\n");
|
||||
ctaphid_send_error(wb->cid, CTAP2_ERR_OPERATION_DENIED);
|
||||
return 1;
|
||||
#endif
|
||||
|
||||
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
@ -28,6 +28,8 @@
|
||||
#define CTAPHID_ENTERBOOT (TYPE_INIT | 0x51)
|
||||
#define CTAPHID_ENTERSTBOOT (TYPE_INIT | 0x52)
|
||||
#define CTAPHID_GETRNG (TYPE_INIT | 0x60)
|
||||
#define CTAPHID_GETVERSION (TYPE_INIT | 0x61)
|
||||
#define CTAPHID_LOADKEY (TYPE_INIT | 0x62)
|
||||
// reserved for debug, not implemented except for HACKER and DEBUG_LEVEl > 0
|
||||
#define CTAPHID_PROBE (TYPE_INIT | 0x70)
|
||||
|
||||
|
91
fido2/data_migration.c
Normal file
91
fido2/data_migration.c
Normal file
@ -0,0 +1,91 @@
|
||||
// Copyright 2019 SoloKeys Developers
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0, <LICENSE-APACHE or
|
||||
// http://apache.org/licenses/LICENSE-2.0> or the MIT license <LICENSE-MIT or
|
||||
// http://opensource.org/licenses/MIT>, at your option. This file may not be
|
||||
// copied, modified, or distributed except according to those terms.
|
||||
|
||||
#include "data_migration.h"
|
||||
#include "log.h"
|
||||
#include "device.h"
|
||||
#include "crypto.h"
|
||||
|
||||
// TODO move from macro to function/assert for better readability?
|
||||
#define check(x) assert(state_prev_0xff->x == state_tmp_ptr->x);
|
||||
#define check_buf(x) assert(memcmp(state_prev_0xff->x, state_tmp_ptr->x, sizeof(state_tmp_ptr->x)) == 0);
|
||||
|
||||
bool migrate_from_FF_to_01(AuthenticatorState_0xFF* state_prev_0xff, AuthenticatorState_0x01* state_tmp_ptr){
|
||||
// Calculate PIN hash, and replace PIN raw storage with it; add version to structure
|
||||
// other ingredients do not change
|
||||
if (state_tmp_ptr->data_version != 0xFF)
|
||||
return false;
|
||||
|
||||
static_assert(sizeof(AuthenticatorState_0xFF) <= sizeof(AuthenticatorState_0x01), "New state structure is smaller, than current one, which is not handled");
|
||||
|
||||
if (ctap_generate_rng(state_tmp_ptr->PIN_SALT, sizeof(state_tmp_ptr->PIN_SALT)) != 1) {
|
||||
printf2(TAG_ERR, "Error, rng failed\n");
|
||||
return false;
|
||||
}
|
||||
if (state_prev_0xff->is_pin_set){
|
||||
crypto_sha256_init();
|
||||
crypto_sha256_update(state_prev_0xff->pin_code, state_prev_0xff->pin_code_length);
|
||||
uint8_t intermediateHash[32];
|
||||
crypto_sha256_final(intermediateHash);
|
||||
|
||||
crypto_sha256_init();
|
||||
crypto_sha256_update(intermediateHash, 16);
|
||||
memset(intermediateHash, 0, sizeof(intermediateHash));
|
||||
crypto_sha256_update(state_tmp_ptr->PIN_SALT, sizeof(state_tmp_ptr->PIN_SALT));
|
||||
crypto_sha256_final(state_tmp_ptr->PIN_CODE_HASH);
|
||||
}
|
||||
|
||||
assert(state_tmp_ptr->_reserved == state_prev_0xff->pin_code_length);
|
||||
state_tmp_ptr->_reserved = 0xFF;
|
||||
state_tmp_ptr->data_version = 1;
|
||||
|
||||
check(is_initialized);
|
||||
check(is_pin_set);
|
||||
check(remaining_tries);
|
||||
check(rk_stored);
|
||||
check_buf(key_lens);
|
||||
check_buf(key_space);
|
||||
assert(state_tmp_ptr->data_version != 0xFF);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void save_migrated_state(AuthenticatorState *state_tmp_ptr) {
|
||||
memmove(&STATE, state_tmp_ptr, sizeof(AuthenticatorState));
|
||||
authenticator_write_state(state_tmp_ptr, 0);
|
||||
authenticator_write_state(state_tmp_ptr, 1);
|
||||
}
|
||||
|
||||
void do_migration_if_required(AuthenticatorState* state_current){
|
||||
// Currently handles only state structures with the same size, or bigger
|
||||
// FIXME rework to raw buffers with fixed size to allow state structure size decrease
|
||||
if(!state_current->is_initialized)
|
||||
return;
|
||||
|
||||
AuthenticatorState state_tmp;
|
||||
AuthenticatorState state_previous;
|
||||
authenticator_read_state(&state_previous);
|
||||
authenticator_read_state(&state_tmp);
|
||||
if(state_current->data_version == 0xFF){
|
||||
printf2(TAG_ERR, "Running migration\n");
|
||||
bool success = migrate_from_FF_to_01((AuthenticatorState_0xFF *) &state_previous, &state_tmp);
|
||||
if (!success){
|
||||
printf2(TAG_ERR, "Failed migration from 0xFF to 1\n");
|
||||
// FIXME discuss migration failure behavior
|
||||
goto return_cleanup;
|
||||
}
|
||||
dump_hex1(TAG_ERR, (void*)&state_tmp, sizeof(state_tmp));
|
||||
dump_hex1(TAG_ERR, (void*)&state_previous, sizeof(state_previous));
|
||||
save_migrated_state(&state_tmp);
|
||||
}
|
||||
|
||||
assert(state_current->data_version == STATE_VERSION);
|
||||
|
||||
return_cleanup:
|
||||
memset(&state_tmp, 0, sizeof(AuthenticatorState));
|
||||
memset(&state_previous, 0, sizeof(AuthenticatorState));
|
||||
}
|
15
fido2/data_migration.h
Normal file
15
fido2/data_migration.h
Normal file
@ -0,0 +1,15 @@
|
||||
// Copyright 2019 SoloKeys Developers
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0, <LICENSE-APACHE or
|
||||
// http://apache.org/licenses/LICENSE-2.0> or the MIT license <LICENSE-MIT or
|
||||
// http://opensource.org/licenses/MIT>, at your option. This file may not be
|
||||
// copied, modified, or distributed except according to those terms.
|
||||
|
||||
#ifndef FIDO2_PR_DATA_MIGRATION_H
|
||||
#define FIDO2_PR_DATA_MIGRATION_H
|
||||
|
||||
#include "storage.h"
|
||||
|
||||
void do_migration_if_required(AuthenticatorState* state_current);
|
||||
|
||||
#endif //FIDO2_PR_DATA_MIGRATION_H
|
@ -53,7 +53,7 @@ void device_set_status(uint32_t status);
|
||||
int device_is_button_pressed();
|
||||
|
||||
// Test for user presence
|
||||
// Return 1 for user is present, 0 user not present, -1 if cancel is requested.
|
||||
// Return 2 for disabled, 1 for user is present, 0 user not present, -1 if cancel is requested.
|
||||
int ctap_user_presence_test(uint32_t delay);
|
||||
|
||||
// Generate @num bytes of random numbers to @dest
|
||||
@ -61,8 +61,8 @@ int ctap_user_presence_test(uint32_t delay);
|
||||
int ctap_generate_rng(uint8_t * dst, size_t num);
|
||||
|
||||
// Increment atomic counter and return it.
|
||||
// Must support two counters, @sel selects counter0 or counter1.
|
||||
uint32_t ctap_atomic_count(int sel);
|
||||
// @param amount the amount to increase the counter by.
|
||||
uint32_t ctap_atomic_count(uint32_t amount);
|
||||
|
||||
// Verify the user
|
||||
// return 1 if user is verified, 0 if not
|
||||
@ -106,7 +106,7 @@ void device_set_clock_rate(DEVICE_CLOCK_RATE param);
|
||||
#define NFC_IS_AVAILABLE 2
|
||||
int device_is_nfc();
|
||||
|
||||
void request_from_nfc(bool request_active);
|
||||
void device_disable_up(bool request_active);
|
||||
|
||||
void device_init_button();
|
||||
|
||||
|
@ -95,7 +95,7 @@ int8_t wallet_pin(uint8_t subcmd, uint8_t * pinAuth, uint8_t * arg1, uint8_t * a
|
||||
if (ret != 0)
|
||||
return ret;
|
||||
|
||||
printf1(TAG_WALLET,"Success. Pin = %s\n", STATE.pin_code);
|
||||
// printf1(TAG_WALLET,"Success. Pin = %s\n", STATE.pin_code);
|
||||
|
||||
break;
|
||||
case CP_cmdChangePin:
|
||||
|
@ -50,6 +50,7 @@ struct logtag tagtable[] = {
|
||||
{TAG_EXT,"[1;37mEXT[0m"},
|
||||
{TAG_NFC,"[1;38mNFC[0m"},
|
||||
{TAG_NFC_APDU, "NAPDU"},
|
||||
{TAG_CCID, "CCID"},
|
||||
};
|
||||
|
||||
|
||||
|
@ -44,6 +44,7 @@ typedef enum
|
||||
TAG_EXT = (1 << 18),
|
||||
TAG_NFC = (1 << 19),
|
||||
TAG_NFC_APDU = (1 << 20),
|
||||
TAG_CCID = (1 << 21),
|
||||
|
||||
TAG_NO_TAG = (1UL << 30),
|
||||
TAG_FILENO = (1UL << 31)
|
||||
|
@ -46,6 +46,7 @@ int main(int argc, char *argv[])
|
||||
TAG_GREEN|
|
||||
TAG_RED|
|
||||
TAG_EXT|
|
||||
TAG_CCID|
|
||||
TAG_ERR
|
||||
);
|
||||
|
||||
|
@ -11,6 +11,9 @@
|
||||
|
||||
#define KEY_SPACE_BYTES 128
|
||||
#define MAX_KEYS (1)
|
||||
#define PIN_SALT_LEN (32)
|
||||
#define STATE_VERSION (1)
|
||||
|
||||
|
||||
#define BACKUP_MARKER 0x5A
|
||||
#define INITIALIZED_MARKER 0xA5
|
||||
@ -19,20 +22,40 @@
|
||||
#define ERR_KEY_SPACE_TAKEN (-2)
|
||||
#define ERR_KEY_SPACE_EMPTY (-2)
|
||||
|
||||
typedef struct
|
||||
{
|
||||
// Pin information
|
||||
uint8_t is_initialized;
|
||||
uint8_t is_pin_set;
|
||||
uint8_t pin_code[NEW_PIN_ENC_MIN_SIZE];
|
||||
int pin_code_length;
|
||||
int8_t remaining_tries;
|
||||
|
||||
uint16_t rk_stored;
|
||||
|
||||
uint16_t key_lens[MAX_KEYS];
|
||||
uint8_t key_space[KEY_SPACE_BYTES];
|
||||
} AuthenticatorState_0xFF;
|
||||
|
||||
|
||||
typedef struct
|
||||
{
|
||||
// Pin information
|
||||
uint8_t is_initialized;
|
||||
uint8_t is_pin_set;
|
||||
uint8_t pin_code[NEW_PIN_ENC_MIN_SIZE];
|
||||
int pin_code_length;
|
||||
uint8_t PIN_CODE_HASH[32];
|
||||
uint8_t PIN_SALT[PIN_SALT_LEN];
|
||||
int _reserved;
|
||||
int8_t remaining_tries;
|
||||
|
||||
uint16_t rk_stored;
|
||||
|
||||
uint16_t key_lens[MAX_KEYS];
|
||||
uint8_t key_space[KEY_SPACE_BYTES];
|
||||
} AuthenticatorState;
|
||||
uint8_t data_version;
|
||||
} AuthenticatorState_0x01;
|
||||
|
||||
typedef AuthenticatorState_0x01 AuthenticatorState;
|
||||
|
||||
|
||||
typedef struct
|
||||
|
@ -118,9 +118,9 @@ void u2f_request_nfc(uint8_t * header, uint8_t * data, int datalen, CTAP_RESPONS
|
||||
if (!header)
|
||||
return;
|
||||
|
||||
request_from_nfc(true); // disable presence test
|
||||
device_disable_up(true); // disable presence test
|
||||
u2f_request_ex((APDU_HEADER *)header, data, datalen, resp);
|
||||
request_from_nfc(false); // enable presence test
|
||||
device_disable_up(false); // enable presence test
|
||||
}
|
||||
|
||||
void u2f_request(struct u2f_request_apdu* req, CTAP_RESPONSE * resp)
|
||||
|
13
fido2/version.c
Normal file
13
fido2/version.c
Normal file
@ -0,0 +1,13 @@
|
||||
#include "version.h"
|
||||
|
||||
|
||||
const version_t firmware_version __attribute__ ((section (".flag"))) __attribute__ ((__used__)) = {
|
||||
.major = SOLO_VERSION_MAJ,
|
||||
.minor = SOLO_VERSION_MIN,
|
||||
.patch = SOLO_VERSION_PATCH,
|
||||
.reserved = 0
|
||||
};
|
||||
|
||||
// from tinycbor, for a quick static_assert
|
||||
#include <compilersupport_p.h>
|
||||
cbor_static_assert(sizeof(version_t) == 4);
|
@ -17,5 +17,23 @@
|
||||
#define SOLO_VERSION __STR(SOLO_VERSION_MAJ) "." __STR(SOLO_VERSION_MIN) "." __STR(SOLO_VERSION_PATCH)
|
||||
#endif
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
typedef struct {
|
||||
union{
|
||||
uint32_t raw;
|
||||
struct {
|
||||
uint8_t major;
|
||||
uint8_t minor;
|
||||
uint8_t patch;
|
||||
uint8_t reserved;
|
||||
};
|
||||
};
|
||||
} version_t;
|
||||
|
||||
bool is_newer(const version_t* const newer, const version_t* const older);
|
||||
const version_t firmware_version ;
|
||||
|
||||
|
||||
#endif
|
||||
|
25
pc/device.c
25
pc/device.c
@ -26,6 +26,7 @@
|
||||
#define RK_NUM 50
|
||||
|
||||
bool use_udp = true;
|
||||
static bool _up_disabled = false;
|
||||
|
||||
struct ResidentKeyStore {
|
||||
CTAP_residentKey rks[RK_NUM];
|
||||
@ -299,6 +300,10 @@ void ctaphid_write_block(uint8_t * data)
|
||||
|
||||
int ctap_user_presence_test(uint32_t d)
|
||||
{
|
||||
if (_up_disabled)
|
||||
{
|
||||
return 2;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
@ -308,20 +313,11 @@ int ctap_user_verification(uint8_t arg)
|
||||
}
|
||||
|
||||
|
||||
uint32_t ctap_atomic_count(int sel)
|
||||
uint32_t ctap_atomic_count(uint32_t amount)
|
||||
{
|
||||
static uint32_t counter1 = 25;
|
||||
/*return 713;*/
|
||||
if (sel == 0)
|
||||
{
|
||||
printf1(TAG_RED,"counter1: %d\n", counter1);
|
||||
return counter1++;
|
||||
}
|
||||
else
|
||||
{
|
||||
printf2(TAG_ERR,"counter2 not imple\n");
|
||||
exit(1);
|
||||
}
|
||||
counter1 += amount;
|
||||
return counter1;
|
||||
}
|
||||
|
||||
int ctap_generate_rng(uint8_t * dst, size_t num)
|
||||
@ -633,6 +629,11 @@ int device_is_nfc()
|
||||
return 0;
|
||||
}
|
||||
|
||||
void device_disable_up(bool disable)
|
||||
{
|
||||
_up_disabled = disable;
|
||||
}
|
||||
|
||||
void device_set_clock_rate(DEVICE_CLOCK_RATE param)
|
||||
{
|
||||
|
||||
|
@ -90,8 +90,7 @@ flash_dfu: solo.hex bootloader.hex
|
||||
# STM32_Programmer_CLI -c port=usb1 -halt -e all --readunprotect
|
||||
STM32_Programmer_CLI -c port=usb1 -halt -rdu -d all.hex
|
||||
|
||||
flashboot: solo.hex bootloader.hex
|
||||
$(VENV) $(merge_hex) solo.hex bootloader.hex all.hex
|
||||
flashboot: bootloader.hex
|
||||
STM32_Programmer_CLI -c port=SWD -halt -e all --readunprotect
|
||||
STM32_Programmer_CLI -c port=SWD -halt -d bootloader.hex -rst
|
||||
|
||||
|
@ -19,6 +19,12 @@
|
||||
#include "ctap_errors.h"
|
||||
#include "log.h"
|
||||
|
||||
volatile version_t current_firmware_version __attribute__ ((section (".flag2"))) __attribute__ ((__used__)) = {
|
||||
.major = SOLO_VERSION_MAJ,
|
||||
.minor = SOLO_VERSION_MIN,
|
||||
.patch = SOLO_VERSION_PATCH,
|
||||
.reserved = 0
|
||||
};
|
||||
|
||||
extern uint8_t REBOOT_FLAG;
|
||||
|
||||
@ -56,8 +62,6 @@ static void erase_application()
|
||||
}
|
||||
}
|
||||
|
||||
#define LAST_ADDR (APPLICATION_END_ADDR-2048 + 8)
|
||||
#define LAST_PAGE (APPLICATION_END_PAGE-1)
|
||||
static void disable_bootloader()
|
||||
{
|
||||
// Clear last 4 bytes of the last application page-1, which is 108th
|
||||
@ -102,6 +106,38 @@ int is_bootloader_disabled()
|
||||
uint32_t * auth = (uint32_t *)(AUTH_WORD_ADDR+4);
|
||||
return *auth == 0;
|
||||
}
|
||||
uint8_t * last_written_app_address;
|
||||
|
||||
#include "version.h"
|
||||
bool is_firmware_version_newer_or_equal()
|
||||
{
|
||||
|
||||
printf1(TAG_BOOT,"Current firmware version: %u.%u.%u.%u (%02x.%02x.%02x.%02x)\r\n",
|
||||
current_firmware_version.major, current_firmware_version.minor, current_firmware_version.patch, current_firmware_version.reserved,
|
||||
current_firmware_version.major, current_firmware_version.minor, current_firmware_version.patch, current_firmware_version.reserved
|
||||
);
|
||||
volatile version_t * new_version = ((volatile version_t *) last_written_app_address);
|
||||
printf1(TAG_BOOT,"Uploaded firmware version: %u.%u.%u.%u (%02x.%02x.%02x.%02x)\r\n",
|
||||
new_version->major, new_version->minor, new_version->patch, new_version->reserved,
|
||||
new_version->major, new_version->minor, new_version->patch, new_version->reserved
|
||||
);
|
||||
|
||||
const bool allowed = is_newer((const version_t *)new_version, (const version_t *)¤t_firmware_version) || current_firmware_version.raw == 0xFFFFFFFF;
|
||||
if (allowed){
|
||||
printf1(TAG_BOOT, "Update allowed, setting new firmware version as current.\r\n");
|
||||
// current_firmware_version.raw = new_version.raw;
|
||||
uint8_t page[PAGE_SIZE];
|
||||
memmove(page, (uint8_t*)BOOT_VERSION_ADDR, PAGE_SIZE);
|
||||
memmove(page, (version_t *)new_version, 4);
|
||||
printf1(TAG_BOOT, "Writing\r\n");
|
||||
flash_erase_page(BOOT_VERSION_PAGE);
|
||||
flash_write(BOOT_VERSION_ADDR, page, PAGE_SIZE);
|
||||
printf1(TAG_BOOT, "Finish\r\n");
|
||||
} else {
|
||||
printf1(TAG_BOOT, "Firmware older - update not allowed.\r\n");
|
||||
}
|
||||
return allowed;
|
||||
}
|
||||
|
||||
/**
|
||||
* Execute bootloader commands
|
||||
@ -125,10 +161,7 @@ int bootloader_bridge(int klen, uint8_t * keyh)
|
||||
return CTAP1_ERR_INVALID_LENGTH;
|
||||
}
|
||||
#ifndef SOLO_HACKER
|
||||
uint8_t * pubkey = (uint8_t*)"\xd2\xa4\x2f\x8f\xb2\x31\x1c\xc1\xf7\x0c\x7e\x64\x32\xfb\xbb\xb4\xa3\xdd\x32\x20"
|
||||
"\x0f\x1b\x88\x9c\xda\x62\xc2\x83\x25\x93\xdd\xb8\x75\x9d\xf9\x86\xee\x03\x6c\xce"
|
||||
"\x34\x47\x71\x36\xb3\xb2\xad\x6d\x12\xb7\xbe\x49\x3e\x20\xa4\x61\xac\xc7\x71\xc7"
|
||||
"\x1f\xa8\x14\xf2";
|
||||
extern uint8_t *pubkey_boot;
|
||||
|
||||
const struct uECC_Curve_t * curve = NULL;
|
||||
#endif
|
||||
@ -165,12 +198,11 @@ int bootloader_bridge(int klen, uint8_t * keyh)
|
||||
}
|
||||
// Do the actual write
|
||||
flash_write((uint32_t)ptr,req->payload, len);
|
||||
|
||||
|
||||
last_written_app_address = (uint8_t *)ptr + len - 8 + 4;
|
||||
break;
|
||||
case BootDone:
|
||||
// Writing to flash finished. Request code validation.
|
||||
printf1(TAG_BOOT, "BootDone: ");
|
||||
printf1(TAG_BOOT, "BootDone: \r\n");
|
||||
#ifndef SOLO_HACKER
|
||||
if (len != 64)
|
||||
{
|
||||
@ -185,17 +217,23 @@ int bootloader_bridge(int klen, uint8_t * keyh)
|
||||
crypto_sha256_final(hash);
|
||||
curve = uECC_secp256r1();
|
||||
// Verify incoming signature made over the SHA256 hash
|
||||
if (! uECC_verify(pubkey,
|
||||
hash,
|
||||
32,
|
||||
req->payload,
|
||||
curve))
|
||||
if (
|
||||
!uECC_verify(pubkey_boot, hash, 32, req->payload, curve)
|
||||
)
|
||||
{
|
||||
printf1(TAG_BOOT, "Signature invalid\r\n");
|
||||
return CTAP2_ERR_OPERATION_DENIED;
|
||||
}
|
||||
if (!is_firmware_version_newer_or_equal()){
|
||||
printf1(TAG_BOOT, "Firmware older - update not allowed.\r\n");
|
||||
printf1(TAG_BOOT, "Rebooting...\r\n");
|
||||
REBOOT_FLAG = 1;
|
||||
return CTAP2_ERR_OPERATION_DENIED;
|
||||
}
|
||||
#endif
|
||||
// Set the application validated, and mark for reboot.
|
||||
authorize_application();
|
||||
|
||||
REBOOT_FLAG = 1;
|
||||
break;
|
||||
case BootCheck:
|
||||
@ -218,6 +256,7 @@ int bootloader_bridge(int klen, uint8_t * keyh)
|
||||
break;
|
||||
case BootReboot:
|
||||
printf1(TAG_BOOT, "BootReboot.\r\n");
|
||||
printf1(TAG_BOOT, "Application authorized: %d.\r\n", is_authorized_to_boot());
|
||||
REBOOT_FLAG = 1;
|
||||
break;
|
||||
case BootDisable:
|
||||
@ -277,3 +316,10 @@ void bootloader_heartbeat()
|
||||
|
||||
led_rgb(((val * g)<<8) | ((val*r) << 16) | (val*b));
|
||||
}
|
||||
|
||||
uint32_t ctap_atomic_count(uint32_t amount)
|
||||
{
|
||||
static uint32_t count = 1000;
|
||||
count += (amount + 1);
|
||||
return count;
|
||||
}
|
@ -138,6 +138,14 @@ int main()
|
||||
|
||||
printf1(TAG_GEN,"recv'ing hid msg \n");
|
||||
|
||||
extern volatile version_t current_firmware_version;
|
||||
printf1(TAG_BOOT,"Current firmware version address: %p\r\n", ¤t_firmware_version);
|
||||
printf1(TAG_BOOT,"Current firmware version: %d.%d.%d.%d (%02x.%02x.%02x.%02x)\r\n",
|
||||
current_firmware_version.major, current_firmware_version.minor, current_firmware_version.patch, current_firmware_version.reserved,
|
||||
current_firmware_version.major, current_firmware_version.minor, current_firmware_version.patch, current_firmware_version.reserved
|
||||
);
|
||||
dump_hex1(TAG_BOOT, (uint8_t*)(¤t_firmware_version) - 16, 32);
|
||||
|
||||
|
||||
while(1)
|
||||
{
|
||||
|
6
targets/stm32l432/bootloader/pubkey_bootloader.c
Normal file
6
targets/stm32l432/bootloader/pubkey_bootloader.c
Normal file
@ -0,0 +1,6 @@
|
||||
#include "stdint.h"
|
||||
|
||||
uint8_t * pubkey_boot = (uint8_t*)"\xd2\xa4\x2f\x8f\xb2\x31\x1c\xc1\xf7\x0c\x7e\x64\x32\xfb\xbb\xb4\xa3\xdd\x32\x20"
|
||||
"\x0f\x1b\x88\x9c\xda\x62\xc2\x83\x25\x93\xdd\xb8\x75\x9d\xf9\x86\xee\x03\x6c\xce"
|
||||
"\x34\x47\x71\x36\xb3\xb2\xad\x6d\x12\xb7\xbe\x49\x3e\x20\xa4\x61\xac\xc7\x71\xc7"
|
||||
"\x1f\xa8\x14\xf2";
|
8
targets/stm32l432/bootloader/version_check.c
Normal file
8
targets/stm32l432/bootloader/version_check.c
Normal file
@ -0,0 +1,8 @@
|
||||
#include "version.h"
|
||||
|
||||
// FIXME test version check function
|
||||
bool is_newer(const version_t* const newer, const version_t* const older){
|
||||
return (newer->major > older->major) ||
|
||||
(newer->major == older->major && newer->minor > older->minor) ||
|
||||
(newer->major == older->major && newer->minor == older->minor && newer->patch >= older->patch);
|
||||
}
|
@ -10,6 +10,8 @@ SRC += $(DRIVER_LIBS) $(USB_LIB)
|
||||
SRC += ../../fido2/apdu.c ../../fido2/util.c ../../fido2/u2f.c ../../fido2/test_power.c
|
||||
SRC += ../../fido2/stubs.c ../../fido2/log.c ../../fido2/ctaphid.c ../../fido2/ctap.c
|
||||
SRC += ../../fido2/ctap_parse.c ../../fido2/main.c
|
||||
SRC += ../../fido2/version.c
|
||||
SRC += ../../fido2/data_migration.c
|
||||
SRC += ../../fido2/extensions/extensions.c ../../fido2/extensions/solo.c
|
||||
SRC += ../../fido2/extensions/wallet.c
|
||||
|
||||
@ -69,6 +71,7 @@ all: $(TARGET).elf
|
||||
|
||||
%.elf: $(OBJ)
|
||||
$(CC) $^ $(HW) $(LDFLAGS) -o $@
|
||||
@echo "Built version: $(VERSION_FLAGS)"
|
||||
|
||||
%.hex: %.elf
|
||||
$(SZ) $^
|
||||
|
@ -2,6 +2,7 @@ include build/common.mk
|
||||
|
||||
# ST related
|
||||
SRC = bootloader/main.c bootloader/bootloader.c
|
||||
SRC += bootloader/pubkey_bootloader.c bootloader/version_check.c
|
||||
SRC += src/init.c src/redirect.c src/flash.c src/rng.c src/led.c src/device.c
|
||||
SRC += src/fifo.c src/crypto.c src/attestation.c src/sense.c
|
||||
SRC += src/startup_stm32l432xx.s src/system_stm32l4xx.c
|
||||
@ -65,6 +66,7 @@ all: $(TARGET).elf
|
||||
|
||||
%.elf: $(OBJ)
|
||||
$(CC) $^ $(HW) $(LDFLAGS) -o $@
|
||||
arm-none-eabi-size $@
|
||||
|
||||
%.hex: %.elf
|
||||
$(CP) -O ihex $^ $(TARGET).hex
|
||||
|
@ -10,7 +10,8 @@ DRIVER_LIBS := lib/stm32l4xx_hal_pcd.c lib/stm32l4xx_hal_pcd_ex.c lib/stm32l4xx_
|
||||
|
||||
USB_LIB := lib/usbd/usbd_cdc.c lib/usbd/usbd_cdc_if.c lib/usbd/usbd_composite.c \
|
||||
lib/usbd/usbd_conf.c lib/usbd/usbd_core.c lib/usbd/usbd_ioreq.c \
|
||||
lib/usbd/usbd_ctlreq.c lib/usbd/usbd_desc.c lib/usbd/usbd_hid.c
|
||||
lib/usbd/usbd_ctlreq.c lib/usbd/usbd_desc.c lib/usbd/usbd_hid.c \
|
||||
lib/usbd/usbd_ccid.c
|
||||
|
||||
VERSION:=$(shell git describe --abbrev=0 )
|
||||
VERSION_FULL:=$(shell git describe)
|
||||
|
319
targets/stm32l432/lib/usbd/usbd_ccid.c
Normal file
319
targets/stm32l432/lib/usbd/usbd_ccid.c
Normal file
@ -0,0 +1,319 @@
|
||||
#include <stdint.h>
|
||||
#include "usbd_ccid.h"
|
||||
#include "usbd_ctlreq.h"
|
||||
#include "usbd_conf.h"
|
||||
#include "usbd_core.h"
|
||||
|
||||
#include "log.h"
|
||||
|
||||
static uint8_t USBD_CCID_Init (USBD_HandleTypeDef *pdev,
|
||||
uint8_t cfgidx);
|
||||
|
||||
static uint8_t USBD_CCID_DeInit (USBD_HandleTypeDef *pdev,
|
||||
uint8_t cfgidx);
|
||||
|
||||
static uint8_t USBD_CCID_Setup (USBD_HandleTypeDef *pdev,
|
||||
USBD_SetupReqTypedef *req);
|
||||
|
||||
static uint8_t USBD_CCID_DataIn (USBD_HandleTypeDef *pdev,
|
||||
uint8_t epnum);
|
||||
|
||||
static uint8_t USBD_CCID_DataOut (USBD_HandleTypeDef *pdev,
|
||||
uint8_t epnum);
|
||||
|
||||
static uint8_t USBD_CCID_EP0_RxReady (USBD_HandleTypeDef *pdev);
|
||||
|
||||
|
||||
USBD_ClassTypeDef USBD_CCID =
|
||||
{
|
||||
USBD_CCID_Init,
|
||||
USBD_CCID_DeInit,
|
||||
USBD_CCID_Setup,
|
||||
NULL, /* EP0_TxSent, */
|
||||
USBD_CCID_EP0_RxReady,
|
||||
USBD_CCID_DataIn,
|
||||
USBD_CCID_DataOut,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
};
|
||||
|
||||
static uint8_t ccidmsg_buf[CCID_DATA_PACKET_SIZE];
|
||||
|
||||
static uint8_t USBD_CCID_Init (USBD_HandleTypeDef *pdev, uint8_t cfgidx)
|
||||
{
|
||||
uint8_t ret = 0U;
|
||||
USBD_CCID_HandleTypeDef *hcdc;
|
||||
|
||||
//Y
|
||||
USBD_LL_OpenEP(pdev, CCID_IN_EP, USBD_EP_TYPE_BULK,
|
||||
CCID_DATA_PACKET_SIZE);
|
||||
|
||||
USBD_LL_OpenEP(pdev, CCID_OUT_EP, USBD_EP_TYPE_BULK,
|
||||
CCID_DATA_PACKET_SIZE);
|
||||
|
||||
pdev->ep_in[CCID_IN_EP & 0xFU].is_used = 1U;
|
||||
pdev->ep_out[CCID_OUT_EP & 0xFU].is_used = 1U;
|
||||
|
||||
|
||||
USBD_LL_OpenEP(pdev, CCID_CMD_EP, USBD_EP_TYPE_INTR, CCID_DATA_PACKET_SIZE);
|
||||
pdev->ep_in[CCID_CMD_EP & 0xFU].is_used = 1U;
|
||||
|
||||
// dump_pma_header("ccid.c");
|
||||
|
||||
static USBD_CCID_HandleTypeDef mem;
|
||||
pdev->pClassData = &mem;
|
||||
|
||||
hcdc = (USBD_CCID_HandleTypeDef*) pdev->pClassData;
|
||||
|
||||
// init transfer states
|
||||
hcdc->TxState = 0U;
|
||||
hcdc->RxState = 0U;
|
||||
|
||||
USBD_LL_PrepareReceive(&Solo_USBD_Device, CCID_OUT_EP, ccidmsg_buf,
|
||||
CCID_DATA_PACKET_SIZE);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static uint8_t USBD_CCID_DeInit (USBD_HandleTypeDef *pdev, uint8_t cfgidx)
|
||||
{
|
||||
uint8_t ret = 0U;
|
||||
//N
|
||||
|
||||
USBD_LL_CloseEP(pdev, CCID_IN_EP);
|
||||
pdev->ep_in[CCID_IN_EP & 0xFU].is_used = 0U;
|
||||
|
||||
USBD_LL_CloseEP(pdev, CCID_OUT_EP);
|
||||
pdev->ep_out[CCID_OUT_EP & 0xFU].is_used = 0U;
|
||||
|
||||
USBD_LL_CloseEP(pdev, CCID_CMD_EP);
|
||||
pdev->ep_in[CCID_CMD_EP & 0xFU].is_used = 0U;
|
||||
|
||||
/* DeInit physical Interface components */
|
||||
if(pdev->pClassData != NULL)
|
||||
{
|
||||
pdev->pClassData = NULL;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief USBD_CDC_Setup
|
||||
* Handle the CDC specific requests
|
||||
* @param pdev: instance
|
||||
* @param req: usb requests
|
||||
* @retval status
|
||||
*/
|
||||
static uint8_t USBD_CCID_Setup (USBD_HandleTypeDef *pdev,
|
||||
USBD_SetupReqTypedef *req)
|
||||
{
|
||||
USBD_CCID_HandleTypeDef *hcdc = (USBD_CCID_HandleTypeDef*) pdev->pClassData;
|
||||
uint8_t ifalt = 0U;
|
||||
uint16_t status_info = 0U;
|
||||
uint8_t ret = USBD_OK;
|
||||
//N
|
||||
|
||||
switch (req->bmRequest & USB_REQ_TYPE_MASK)
|
||||
{
|
||||
case USB_REQ_TYPE_CLASS :
|
||||
if (req->wLength)
|
||||
{
|
||||
if (req->bmRequest & 0x80U)
|
||||
{
|
||||
USBD_CtlSendData (pdev, (uint8_t *)(void *)hcdc->data, req->wLength);
|
||||
}
|
||||
else
|
||||
{
|
||||
hcdc->CmdOpCode = req->bRequest;
|
||||
hcdc->CmdLength = (uint8_t)req->wLength;
|
||||
|
||||
USBD_CtlPrepareRx (pdev, (uint8_t *)(void *)hcdc->data, req->wLength);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
}
|
||||
break;
|
||||
|
||||
case USB_REQ_TYPE_STANDARD:
|
||||
switch (req->bRequest)
|
||||
{
|
||||
case USB_REQ_GET_STATUS:
|
||||
if (pdev->dev_state == USBD_STATE_CONFIGURED)
|
||||
{
|
||||
USBD_CtlSendData (pdev, (uint8_t *)(void *)&status_info, 2U);
|
||||
}
|
||||
else
|
||||
{
|
||||
USBD_CtlError (pdev, req);
|
||||
ret = USBD_FAIL;
|
||||
}
|
||||
break;
|
||||
|
||||
case USB_REQ_GET_INTERFACE:
|
||||
if (pdev->dev_state == USBD_STATE_CONFIGURED)
|
||||
{
|
||||
USBD_CtlSendData (pdev, &ifalt, 1U);
|
||||
}
|
||||
else
|
||||
{
|
||||
USBD_CtlError (pdev, req);
|
||||
ret = USBD_FAIL;
|
||||
}
|
||||
break;
|
||||
|
||||
case USB_REQ_SET_INTERFACE:
|
||||
if (pdev->dev_state != USBD_STATE_CONFIGURED)
|
||||
{
|
||||
USBD_CtlError (pdev, req);
|
||||
ret = USBD_FAIL;
|
||||
}
|
||||
break;
|
||||
case USB_REQ_GET_DESCRIPTOR:
|
||||
break;
|
||||
default:
|
||||
USBD_CtlError (pdev, req);
|
||||
ret = USBD_FAIL;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
USBD_CtlError (pdev, req);
|
||||
ret = USBD_FAIL;
|
||||
break;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief USBD_CDC_DataIn
|
||||
* Data sent on non-control IN endpoint
|
||||
* @param pdev: device instance
|
||||
* @param epnum: endpoint number
|
||||
* @retval status
|
||||
*/
|
||||
static uint8_t USBD_CCID_DataOut (USBD_HandleTypeDef *pdev, uint8_t epnum)
|
||||
{
|
||||
return USBD_OK;
|
||||
}
|
||||
static uint8_t USBD_CCID_DataIn (USBD_HandleTypeDef *pdev, uint8_t epnum)
|
||||
{
|
||||
USBD_CCID_HandleTypeDef *hcdc = (USBD_CCID_HandleTypeDef*)pdev->pClassData;
|
||||
|
||||
hcdc->TxState = 0U;
|
||||
return USBD_OK;
|
||||
}
|
||||
|
||||
uint8_t USBD_CCID_TransmitPacket(uint8_t * msg, int len)
|
||||
{
|
||||
/* Update the packet total length */
|
||||
Solo_USBD_Device.ep_in[CCID_IN_EP & 0xFU].total_length = len;
|
||||
|
||||
while (PCD_GET_EP_TX_STATUS(USB, CCID_IN_EP & 0x0f) == USB_EP_TX_VALID)
|
||||
;
|
||||
/* Transmit next packet */
|
||||
USBD_LL_Transmit(&Solo_USBD_Device, CCID_IN_EP, msg,
|
||||
len);
|
||||
|
||||
printf1(TAG_CCID,"<< ");
|
||||
dump_hex1(TAG_CCID, msg, len);
|
||||
|
||||
return USBD_OK;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void ccid_send_status(CCID_HEADER * c, uint8_t status)
|
||||
{
|
||||
uint8_t msg[CCID_HEADER_SIZE];
|
||||
memset(msg,0,sizeof(msg));
|
||||
|
||||
msg[0] = CCID_SLOT_STATUS_RES;
|
||||
msg[6] = c->seq;
|
||||
msg[7] = status;
|
||||
|
||||
USBD_CCID_TransmitPacket(msg, sizeof(msg));
|
||||
|
||||
}
|
||||
|
||||
void ccid_send_data_block(CCID_HEADER * c, uint8_t status)
|
||||
{
|
||||
uint8_t msg[CCID_HEADER_SIZE];
|
||||
memset(msg,0,sizeof(msg));
|
||||
|
||||
msg[0] = CCID_DATA_BLOCK_RES;
|
||||
msg[6] = c->seq;
|
||||
msg[7] = status;
|
||||
|
||||
USBD_CCID_TransmitPacket(msg, sizeof(msg));
|
||||
|
||||
}
|
||||
|
||||
void handle_ccid(uint8_t * msg, int len)
|
||||
{
|
||||
CCID_HEADER * h = (CCID_HEADER *) msg;
|
||||
switch(h->type)
|
||||
{
|
||||
case CCID_SLOT_STATUS:
|
||||
ccid_send_status(h, CCID_STATUS_ON);
|
||||
break;
|
||||
case CCID_POWER_ON:
|
||||
ccid_send_data_block(h, CCID_STATUS_ON);
|
||||
break;
|
||||
case CCID_POWER_OFF:
|
||||
ccid_send_status(h, CCID_STATUS_OFF);
|
||||
break;
|
||||
default:
|
||||
ccid_send_status(h, CCID_STATUS_ON);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief USBD_CDC_DataOut
|
||||
* Data received on non-control Out endpoint
|
||||
* @param pdev: device instance
|
||||
* @param epnum: endpoint number
|
||||
* @retval status
|
||||
*/
|
||||
uint8_t usb_ccid_recieve_callback(USBD_HandleTypeDef *pdev, uint8_t epnum)
|
||||
{
|
||||
|
||||
USBD_CCID_HandleTypeDef *hcdc = (USBD_CCID_HandleTypeDef*) pdev->pClassData;
|
||||
|
||||
/* Get the received data length */
|
||||
hcdc->RxLength = USBD_LL_GetRxDataSize (pdev, epnum);
|
||||
|
||||
printf1(TAG_CCID, ">> ");
|
||||
dump_hex1(TAG_CCID, ccidmsg_buf, hcdc->RxLength);
|
||||
|
||||
handle_ccid(ccidmsg_buf, hcdc->RxLength);
|
||||
|
||||
USBD_LL_PrepareReceive(&Solo_USBD_Device, CCID_OUT_EP, ccidmsg_buf,
|
||||
CCID_DATA_PACKET_SIZE);
|
||||
|
||||
return USBD_OK;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief USBD_CDC_EP0_RxReady
|
||||
* Handle EP0 Rx Ready event
|
||||
* @param pdev: device instance
|
||||
* @retval status
|
||||
*/
|
||||
static uint8_t USBD_CCID_EP0_RxReady (USBD_HandleTypeDef *pdev)
|
||||
{
|
||||
return USBD_OK;
|
||||
}
|
58
targets/stm32l432/lib/usbd/usbd_ccid.h
Normal file
58
targets/stm32l432/lib/usbd/usbd_ccid.h
Normal file
@ -0,0 +1,58 @@
|
||||
#ifndef _USBD_H_
|
||||
#define _USBD_H_
|
||||
|
||||
#include "usbd_ioreq.h"
|
||||
|
||||
#define CCID_HEADER_SIZE 10
|
||||
typedef struct
|
||||
{
|
||||
uint8_t type;
|
||||
uint32_t len;
|
||||
uint8_t slot;
|
||||
uint8_t seq;
|
||||
uint8_t rsvd;
|
||||
uint16_t param;
|
||||
} __attribute__((packed)) CCID_HEADER;
|
||||
|
||||
#define CCID_IN_EP 0x86U /* EP1 for data IN */
|
||||
#define CCID_OUT_EP 0x04U /* EP1 for data OUT */
|
||||
#define CCID_CMD_EP 0x85U /* EP2 for CDC commands */
|
||||
|
||||
#define CCID_DATA_PACKET_SIZE 64
|
||||
|
||||
#define CCID_SET_PARAMS 0x61
|
||||
#define CCID_POWER_ON 0x62
|
||||
#define CCID_POWER_OFF 0x63
|
||||
#define CCID_SLOT_STATUS 0x65
|
||||
#define CCID_SECURE 0x69
|
||||
#define CCID_GET_PARAMS 0x6C
|
||||
#define CCID_RESET_PARAMS 0x6D
|
||||
#define CCID_XFR_BLOCK 0x6F
|
||||
|
||||
#define CCID_STATUS_ON 0x00
|
||||
#define CCID_STATUS_OFF 0x02
|
||||
|
||||
#define CCID_DATA_BLOCK_RES 0x80
|
||||
#define CCID_SLOT_STATUS_RES 0x81
|
||||
#define CCID_PARAMS_RES 0x82
|
||||
|
||||
extern USBD_ClassTypeDef USBD_CCID;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
uint32_t data[CCID_DATA_PACKET_SIZE / 4U];
|
||||
uint8_t CmdOpCode;
|
||||
uint8_t CmdLength;
|
||||
uint8_t *RxBuffer;
|
||||
uint8_t *TxBuffer;
|
||||
uint32_t RxLength;
|
||||
uint32_t TxLength;
|
||||
|
||||
__IO uint32_t TxState;
|
||||
__IO uint32_t RxState;
|
||||
}
|
||||
USBD_CCID_HandleTypeDef;
|
||||
|
||||
uint8_t usb_ccid_recieve_callback(USBD_HandleTypeDef *pdev, uint8_t epnum);
|
||||
|
||||
#endif
|
@ -195,302 +195,9 @@ USBD_ClassTypeDef USBD_CDC =
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
// USBD_CDC_GetHSCfgDesc,
|
||||
// USBD_CDC_GetFSCfgDesc,
|
||||
// USBD_CDC_GetOtherSpeedCfgDesc,
|
||||
// USBD_CDC_GetDeviceQualifierDescriptor,
|
||||
};
|
||||
|
||||
/* USB CDC device Configuration Descriptor */
|
||||
__ALIGN_BEGIN uint8_t USBD_CDC_CfgHSDesc[USB_CDC_CONFIG_DESC_SIZ] __ALIGN_END =
|
||||
{
|
||||
/*Configuration Descriptor*/
|
||||
0x09, /* bLength: Configuration Descriptor size */
|
||||
USB_DESC_TYPE_CONFIGURATION, /* bDescriptorType: Configuration */
|
||||
USB_CDC_CONFIG_DESC_SIZ, /* wTotalLength:no of returned bytes */
|
||||
0x00,
|
||||
0x02, /* bNumInterfaces: 2 interface */
|
||||
0x01, /* bConfigurationValue: Configuration value */
|
||||
0x00, /* iConfiguration: Index of string descriptor describing the configuration */
|
||||
0xC0, /* bmAttributes: self powered */
|
||||
0x32, /* MaxPower 0 mA */
|
||||
|
||||
/*---------------------------------------------------------------------------*/
|
||||
|
||||
/*Interface Descriptor */
|
||||
0x09, /* bLength: Interface Descriptor size */
|
||||
USB_DESC_TYPE_INTERFACE, /* bDescriptorType: Interface */
|
||||
/* Interface descriptor type */
|
||||
0x00, /* bInterfaceNumber: Number of Interface */
|
||||
0x00, /* bAlternateSetting: Alternate setting */
|
||||
0x01, /* bNumEndpoints: One endpoints used */
|
||||
0x02, /* bInterfaceClass: Communication Interface Class */
|
||||
0x02, /* bInterfaceSubClass: Abstract Control Model */
|
||||
0x01, /* bInterfaceProtocol: Common AT commands */
|
||||
0x00, /* iInterface: */
|
||||
|
||||
/*Header Functional Descriptor*/
|
||||
0x05, /* bLength: Endpoint Descriptor size */
|
||||
0x24, /* bDescriptorType: CS_INTERFACE */
|
||||
0x00, /* bDescriptorSubtype: Header Func Desc */
|
||||
0x10, /* bcdCDC: spec release number */
|
||||
0x01,
|
||||
|
||||
/*Call Management Functional Descriptor*/
|
||||
0x05, /* bFunctionLength */
|
||||
0x24, /* bDescriptorType: CS_INTERFACE */
|
||||
0x01, /* bDescriptorSubtype: Call Management Func Desc */
|
||||
0x00, /* bmCapabilities: D0+D1 */
|
||||
0x01, /* bDataInterface: 1 */
|
||||
|
||||
/*ACM Functional Descriptor*/
|
||||
0x04, /* bFunctionLength */
|
||||
0x24, /* bDescriptorType: CS_INTERFACE */
|
||||
0x02, /* bDescriptorSubtype: Abstract Control Management desc */
|
||||
0x02, /* bmCapabilities */
|
||||
|
||||
/*Union Functional Descriptor*/
|
||||
0x05, /* bFunctionLength */
|
||||
0x24, /* bDescriptorType: CS_INTERFACE */
|
||||
0x06, /* bDescriptorSubtype: Union func desc */
|
||||
0x00, /* bMasterInterface: Communication class interface */
|
||||
0x01, /* bSlaveInterface0: Data Class Interface */
|
||||
|
||||
/*Endpoint 2 Descriptor*/
|
||||
0x07, /* bLength: Endpoint Descriptor size */
|
||||
USB_DESC_TYPE_ENDPOINT, /* bDescriptorType: Endpoint */
|
||||
CDC_CMD_EP, /* bEndpointAddress */
|
||||
0x03, /* bmAttributes: Interrupt */
|
||||
LOBYTE(CDC_CMD_PACKET_SIZE), /* wMaxPacketSize: */
|
||||
HIBYTE(CDC_CMD_PACKET_SIZE),
|
||||
CDC_HS_BINTERVAL, /* bInterval: */
|
||||
/*---------------------------------------------------------------------------*/
|
||||
|
||||
/*Data class interface descriptor*/
|
||||
0x09, /* bLength: Endpoint Descriptor size */
|
||||
USB_DESC_TYPE_INTERFACE, /* bDescriptorType: */
|
||||
0x01, /* bInterfaceNumber: Number of Interface */
|
||||
0x00, /* bAlternateSetting: Alternate setting */
|
||||
0x02, /* bNumEndpoints: Two endpoints used */
|
||||
0x0A, /* bInterfaceClass: CDC */
|
||||
0x00, /* bInterfaceSubClass: */
|
||||
0x00, /* bInterfaceProtocol: */
|
||||
0x00, /* iInterface: */
|
||||
|
||||
/*Endpoint OUT Descriptor*/
|
||||
0x07, /* bLength: Endpoint Descriptor size */
|
||||
USB_DESC_TYPE_ENDPOINT, /* bDescriptorType: Endpoint */
|
||||
CDC_OUT_EP, /* bEndpointAddress */
|
||||
0x02, /* bmAttributes: Bulk */
|
||||
LOBYTE(CDC_DATA_HS_MAX_PACKET_SIZE), /* wMaxPacketSize: */
|
||||
HIBYTE(CDC_DATA_HS_MAX_PACKET_SIZE),
|
||||
0x00, /* bInterval: ignore for Bulk transfer */
|
||||
|
||||
/*Endpoint IN Descriptor*/
|
||||
0x07, /* bLength: Endpoint Descriptor size */
|
||||
USB_DESC_TYPE_ENDPOINT, /* bDescriptorType: Endpoint */
|
||||
CDC_IN_EP, /* bEndpointAddress */
|
||||
0x02, /* bmAttributes: Bulk */
|
||||
LOBYTE(CDC_DATA_HS_MAX_PACKET_SIZE), /* wMaxPacketSize: */
|
||||
HIBYTE(CDC_DATA_HS_MAX_PACKET_SIZE),
|
||||
0x00 /* bInterval: ignore for Bulk transfer */
|
||||
} ;
|
||||
|
||||
|
||||
/* USB CDC device Configuration Descriptor */
|
||||
__ALIGN_BEGIN uint8_t USBD_CDC_CfgFSDesc[USB_CDC_CONFIG_DESC_SIZ] __ALIGN_END =
|
||||
{
|
||||
/*Configuration Descriptor*/
|
||||
0x09, /* bLength: Configuration Descriptor size */
|
||||
USB_DESC_TYPE_CONFIGURATION, /* bDescriptorType: Configuration */
|
||||
USB_CDC_CONFIG_DESC_SIZ, /* wTotalLength:no of returned bytes */
|
||||
0x00,
|
||||
0x02, /* bNumInterfaces: 2 interface */
|
||||
0x01, /* bConfigurationValue: Configuration value */
|
||||
0x00, /* iConfiguration: Index of string descriptor describing the configuration */
|
||||
0xC0, /* bmAttributes: self powered */
|
||||
0x32, /* MaxPower 0 mA */
|
||||
|
||||
/*---------------------------------------------------------------------------*/
|
||||
|
||||
/*Interface Descriptor */
|
||||
0x09, /* bLength: Interface Descriptor size */
|
||||
USB_DESC_TYPE_INTERFACE, /* bDescriptorType: Interface */
|
||||
/* Interface descriptor type */
|
||||
0x00, /* bInterfaceNumber: Number of Interface */
|
||||
0x00, /* bAlternateSetting: Alternate setting */
|
||||
0x01, /* bNumEndpoints: One endpoints used */
|
||||
0x02, /* bInterfaceClass: Communication Interface Class */
|
||||
0x02, /* bInterfaceSubClass: Abstract Control Model */
|
||||
0x01, /* bInterfaceProtocol: Common AT commands */
|
||||
0x00, /* iInterface: */
|
||||
|
||||
/*Header Functional Descriptor*/
|
||||
0x05, /* bLength: Endpoint Descriptor size */
|
||||
0x24, /* bDescriptorType: CS_INTERFACE */
|
||||
0x00, /* bDescriptorSubtype: Header Func Desc */
|
||||
0x10, /* bcdCDC: spec release number */
|
||||
0x01,
|
||||
|
||||
/*Call Management Functional Descriptor*/
|
||||
0x05, /* bFunctionLength */
|
||||
0x24, /* bDescriptorType: CS_INTERFACE */
|
||||
0x01, /* bDescriptorSubtype: Call Management Func Desc */
|
||||
0x00, /* bmCapabilities: D0+D1 */
|
||||
0x01, /* bDataInterface: 1 */
|
||||
|
||||
/*ACM Functional Descriptor*/
|
||||
0x04, /* bFunctionLength */
|
||||
0x24, /* bDescriptorType: CS_INTERFACE */
|
||||
0x02, /* bDescriptorSubtype: Abstract Control Management desc */
|
||||
0x02, /* bmCapabilities */
|
||||
|
||||
/*Union Functional Descriptor*/
|
||||
0x05, /* bFunctionLength */
|
||||
0x24, /* bDescriptorType: CS_INTERFACE */
|
||||
0x06, /* bDescriptorSubtype: Union func desc */
|
||||
0x00, /* bMasterInterface: Communication class interface */
|
||||
0x01, /* bSlaveInterface0: Data Class Interface */
|
||||
|
||||
/*Endpoint 2 Descriptor*/
|
||||
0x07, /* bLength: Endpoint Descriptor size */
|
||||
USB_DESC_TYPE_ENDPOINT, /* bDescriptorType: Endpoint */
|
||||
CDC_CMD_EP, /* bEndpointAddress */
|
||||
0x03, /* bmAttributes: Interrupt */
|
||||
LOBYTE(CDC_CMD_PACKET_SIZE), /* wMaxPacketSize: */
|
||||
HIBYTE(CDC_CMD_PACKET_SIZE),
|
||||
CDC_FS_BINTERVAL, /* bInterval: */
|
||||
/*---------------------------------------------------------------------------*/
|
||||
|
||||
/*Data class interface descriptor*/
|
||||
0x09, /* bLength: Endpoint Descriptor size */
|
||||
USB_DESC_TYPE_INTERFACE, /* bDescriptorType: */
|
||||
0x01, /* bInterfaceNumber: Number of Interface */
|
||||
0x00, /* bAlternateSetting: Alternate setting */
|
||||
0x02, /* bNumEndpoints: Two endpoints used */
|
||||
0x0A, /* bInterfaceClass: CDC */
|
||||
0x00, /* bInterfaceSubClass: */
|
||||
0x00, /* bInterfaceProtocol: */
|
||||
0x00, /* iInterface: */
|
||||
|
||||
/*Endpoint OUT Descriptor*/
|
||||
0x07, /* bLength: Endpoint Descriptor size */
|
||||
USB_DESC_TYPE_ENDPOINT, /* bDescriptorType: Endpoint */
|
||||
CDC_OUT_EP, /* bEndpointAddress */
|
||||
0x02, /* bmAttributes: Bulk */
|
||||
LOBYTE(CDC_DATA_FS_MAX_PACKET_SIZE), /* wMaxPacketSize: */
|
||||
HIBYTE(CDC_DATA_FS_MAX_PACKET_SIZE),
|
||||
0x00, /* bInterval: ignore for Bulk transfer */
|
||||
|
||||
/*Endpoint IN Descriptor*/
|
||||
0x07, /* bLength: Endpoint Descriptor size */
|
||||
USB_DESC_TYPE_ENDPOINT, /* bDescriptorType: Endpoint */
|
||||
CDC_IN_EP, /* bEndpointAddress */
|
||||
0x02, /* bmAttributes: Bulk */
|
||||
LOBYTE(CDC_DATA_FS_MAX_PACKET_SIZE), /* wMaxPacketSize: */
|
||||
HIBYTE(CDC_DATA_FS_MAX_PACKET_SIZE),
|
||||
0x00 /* bInterval: ignore for Bulk transfer */
|
||||
} ;
|
||||
|
||||
__ALIGN_BEGIN uint8_t USBD_CDC_OtherSpeedCfgDesc[USB_CDC_CONFIG_DESC_SIZ] __ALIGN_END =
|
||||
{
|
||||
0x09, /* bLength: Configuation Descriptor size */
|
||||
USB_DESC_TYPE_OTHER_SPEED_CONFIGURATION,
|
||||
USB_CDC_CONFIG_DESC_SIZ,
|
||||
0x00,
|
||||
0x02, /* bNumInterfaces: 2 interfaces */
|
||||
0x01, /* bConfigurationValue: */
|
||||
0x04, /* iConfiguration: */
|
||||
0xC0, /* bmAttributes: */
|
||||
0x32, /* MaxPower 100 mA */
|
||||
|
||||
/*Interface Descriptor */
|
||||
0x09, /* bLength: Interface Descriptor size */
|
||||
USB_DESC_TYPE_INTERFACE, /* bDescriptorType: Interface */
|
||||
/* Interface descriptor type */
|
||||
0x00, /* bInterfaceNumber: Number of Interface */
|
||||
0x00, /* bAlternateSetting: Alternate setting */
|
||||
0x01, /* bNumEndpoints: One endpoints used */
|
||||
0x02, /* bInterfaceClass: Communication Interface Class */
|
||||
0x02, /* bInterfaceSubClass: Abstract Control Model */
|
||||
0x01, /* bInterfaceProtocol: Common AT commands */
|
||||
0x00, /* iInterface: */
|
||||
|
||||
/*Header Functional Descriptor*/
|
||||
0x05, /* bLength: Endpoint Descriptor size */
|
||||
0x24, /* bDescriptorType: CS_INTERFACE */
|
||||
0x00, /* bDescriptorSubtype: Header Func Desc */
|
||||
0x10, /* bcdCDC: spec release number */
|
||||
0x01,
|
||||
|
||||
/*Call Management Functional Descriptor*/
|
||||
0x05, /* bFunctionLength */
|
||||
0x24, /* bDescriptorType: CS_INTERFACE */
|
||||
0x01, /* bDescriptorSubtype: Call Management Func Desc */
|
||||
0x00, /* bmCapabilities: D0+D1 */
|
||||
0x01, /* bDataInterface: 1 */
|
||||
|
||||
/*ACM Functional Descriptor*/
|
||||
0x04, /* bFunctionLength */
|
||||
0x24, /* bDescriptorType: CS_INTERFACE */
|
||||
0x02, /* bDescriptorSubtype: Abstract Control Management desc */
|
||||
0x02, /* bmCapabilities */
|
||||
|
||||
/*Union Functional Descriptor*/
|
||||
0x05, /* bFunctionLength */
|
||||
0x24, /* bDescriptorType: CS_INTERFACE */
|
||||
0x06, /* bDescriptorSubtype: Union func desc */
|
||||
0x00, /* bMasterInterface: Communication class interface */
|
||||
0x01, /* bSlaveInterface0: Data Class Interface */
|
||||
|
||||
/*Endpoint 2 Descriptor*/
|
||||
0x07, /* bLength: Endpoint Descriptor size */
|
||||
USB_DESC_TYPE_ENDPOINT , /* bDescriptorType: Endpoint */
|
||||
CDC_CMD_EP, /* bEndpointAddress */
|
||||
0x03, /* bmAttributes: Interrupt */
|
||||
LOBYTE(CDC_CMD_PACKET_SIZE), /* wMaxPacketSize: */
|
||||
HIBYTE(CDC_CMD_PACKET_SIZE),
|
||||
CDC_FS_BINTERVAL, /* bInterval: */
|
||||
|
||||
/*---------------------------------------------------------------------------*/
|
||||
|
||||
/*Data class interface descriptor*/
|
||||
0x09, /* bLength: Endpoint Descriptor size */
|
||||
USB_DESC_TYPE_INTERFACE, /* bDescriptorType: */
|
||||
0x01, /* bInterfaceNumber: Number of Interface */
|
||||
0x00, /* bAlternateSetting: Alternate setting */
|
||||
0x02, /* bNumEndpoints: Two endpoints used */
|
||||
0x0A, /* bInterfaceClass: CDC */
|
||||
0x00, /* bInterfaceSubClass: */
|
||||
0x00, /* bInterfaceProtocol: */
|
||||
0x00, /* iInterface: */
|
||||
|
||||
/*Endpoint OUT Descriptor*/
|
||||
0x07, /* bLength: Endpoint Descriptor size */
|
||||
USB_DESC_TYPE_ENDPOINT, /* bDescriptorType: Endpoint */
|
||||
CDC_OUT_EP, /* bEndpointAddress */
|
||||
0x02, /* bmAttributes: Bulk */
|
||||
0x40, /* wMaxPacketSize: */
|
||||
0x00,
|
||||
0x00, /* bInterval: ignore for Bulk transfer */
|
||||
|
||||
/*Endpoint IN Descriptor*/
|
||||
0x07, /* bLength: Endpoint Descriptor size */
|
||||
USB_DESC_TYPE_ENDPOINT, /* bDescriptorType: Endpoint */
|
||||
CDC_IN_EP, /* bEndpointAddress */
|
||||
0x02, /* bmAttributes: Bulk */
|
||||
0x40, /* wMaxPacketSize: */
|
||||
0x00,
|
||||
0x00 /* bInterval */
|
||||
};
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/** @defgroup USBD_CDC_Private_Functions
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief USBD_CDC_Init
|
||||
@ -782,45 +489,7 @@ static uint8_t USBD_CDC_EP0_RxReady (USBD_HandleTypeDef *pdev)
|
||||
return USBD_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief USBD_CDC_GetFSCfgDesc
|
||||
* Return configuration descriptor
|
||||
* @param speed : current device speed
|
||||
* @param length : pointer data length
|
||||
* @retval pointer to descriptor buffer
|
||||
*/
|
||||
/*static uint8_t *USBD_CDC_GetFSCfgDesc (uint16_t *length)
|
||||
{
|
||||
*length = sizeof (USBD_CDC_CfgFSDesc);
|
||||
return USBD_CDC_CfgFSDesc;
|
||||
}
|
||||
*/
|
||||
/**
|
||||
* @brief USBD_CDC_GetHSCfgDesc
|
||||
* Return configuration descriptor
|
||||
* @param speed : current device speed
|
||||
* @param length : pointer data length
|
||||
* @retval pointer to descriptor buffer
|
||||
*/
|
||||
/*static uint8_t *USBD_CDC_GetHSCfgDesc (uint16_t *length)
|
||||
{
|
||||
*length = sizeof (USBD_CDC_CfgHSDesc);
|
||||
return USBD_CDC_CfgHSDesc;
|
||||
}
|
||||
*/
|
||||
/**
|
||||
* @brief USBD_CDC_GetCfgDesc
|
||||
* Return configuration descriptor
|
||||
* @param speed : current device speed
|
||||
* @param length : pointer data length
|
||||
* @retval pointer to descriptor buffer
|
||||
*/
|
||||
/*static uint8_t *USBD_CDC_GetOtherSpeedCfgDesc (uint16_t *length)
|
||||
{
|
||||
*length = sizeof (USBD_CDC_OtherSpeedCfgDesc);
|
||||
return USBD_CDC_OtherSpeedCfgDesc;
|
||||
}
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief DeviceQualifierDescriptor
|
||||
* return Device Qualifier descriptor
|
||||
@ -939,22 +608,10 @@ uint8_t USBD_CDC_ReceivePacket(USBD_HandleTypeDef *pdev)
|
||||
/* Suspend or Resume USB Out process */
|
||||
if(pdev->pClassData != NULL)
|
||||
{
|
||||
if(pdev->dev_speed == USBD_SPEED_HIGH )
|
||||
{
|
||||
/* Prepare Out endpoint to receive next packet */
|
||||
USBD_LL_PrepareReceive(pdev,
|
||||
CDC_OUT_EP,
|
||||
hcdc->RxBuffer,
|
||||
CDC_DATA_HS_OUT_PACKET_SIZE);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Prepare Out endpoint to receive next packet */
|
||||
USBD_LL_PrepareReceive(pdev,
|
||||
CDC_OUT_EP,
|
||||
hcdc->RxBuffer,
|
||||
CDC_DATA_FS_OUT_PACKET_SIZE);
|
||||
}
|
||||
return USBD_OK;
|
||||
}
|
||||
else
|
||||
|
@ -2,7 +2,9 @@
|
||||
#include "usbd_desc.h"
|
||||
#include "usbd_hid.h"
|
||||
#include "usbd_cdc.h"
|
||||
#include "usbd_ccid.h"
|
||||
#include "usbd_ctlreq.h"
|
||||
#include "app.h"
|
||||
|
||||
static uint8_t USBD_Composite_Init (USBD_HandleTypeDef *pdev, uint8_t cfgidx);
|
||||
|
||||
@ -26,18 +28,33 @@ static uint8_t *USBD_Composite_GetOtherSpeedCfgDesc (uint16_t *length);
|
||||
|
||||
static uint8_t *USBD_Composite_GetDeviceQualifierDescriptor (uint16_t *length);
|
||||
|
||||
#define NUM_CLASSES 2
|
||||
#define NUM_INTERFACES 3
|
||||
|
||||
#if NUM_INTERFACES>1
|
||||
#define COMPOSITE_CDC_HID_DESCRIPTOR_SIZE (90 + 8+9 + 4)
|
||||
#ifdef ENABLE_CCID
|
||||
#define CCID_SIZE 84
|
||||
#define CCID_NUM_INTERFACE 1
|
||||
#else
|
||||
#define COMPOSITE_CDC_HID_DESCRIPTOR_SIZE (41)
|
||||
#define CCID_NUM_INTERFACE 0
|
||||
#define CCID_SIZE 0
|
||||
#endif
|
||||
|
||||
#if DEBUG_LEVEL > 0
|
||||
#define CDC_SIZE (49 + 8 + 9 + 4)
|
||||
#define CDC_NUM_INTERFACE 2
|
||||
#else
|
||||
#define CDC_SIZE 0
|
||||
#define CDC_NUM_INTERFACE 0
|
||||
#endif
|
||||
|
||||
#define HID_SIZE 41
|
||||
|
||||
#define COMPOSITE_CDC_HID_DESCRIPTOR_SIZE (HID_SIZE + CDC_SIZE + CCID_SIZE)
|
||||
#define NUM_INTERFACES (1 + CDC_NUM_INTERFACE + CCID_NUM_INTERFACE)
|
||||
#define NUM_CLASSES 3
|
||||
|
||||
|
||||
#define HID_INTF_NUM 0
|
||||
#define CDC_MASTER_INTF_NUM 1
|
||||
#define CDC_SLAVE_INTF_NUM 2
|
||||
#define CDC_SLAVE_INTF_NUM 2
|
||||
#define CCID_INTF_NUM 3
|
||||
__ALIGN_BEGIN uint8_t COMPOSITE_CDC_HID_DESCRIPTOR[COMPOSITE_CDC_HID_DESCRIPTOR_SIZE] __ALIGN_END =
|
||||
{
|
||||
/*Configuration Descriptor*/
|
||||
@ -94,7 +111,7 @@ __ALIGN_BEGIN uint8_t COMPOSITE_CDC_HID_DESCRIPTOR[COMPOSITE_CDC_HID_DESCRIPTOR_
|
||||
0x00,
|
||||
HID_BINTERVAL, /*bInterval: Polling Interval */
|
||||
|
||||
#if NUM_INTERFACES > 1
|
||||
#if DEBUG_LEVEL > 0
|
||||
|
||||
/* */
|
||||
/* CDC */
|
||||
@ -191,6 +208,83 @@ __ALIGN_BEGIN uint8_t COMPOSITE_CDC_HID_DESCRIPTOR[COMPOSITE_CDC_HID_DESCRIPTOR_
|
||||
0x09,
|
||||
0x04,
|
||||
#endif
|
||||
|
||||
#ifdef ENABLE_CCID
|
||||
|
||||
/* CCID Interface Descriptor */
|
||||
9, /* bLength: Interface Descriptor size */
|
||||
USB_DESC_TYPE_INTERFACE, /* bDescriptorType: Interface */
|
||||
CCID_INTF_NUM, /* bInterfaceNumber: CCID Interface */
|
||||
0, /* Alternate setting for this interface */
|
||||
3, /* bNumEndpoints: Bulk-IN, Bulk-OUT, Intr-IN */
|
||||
0x0B, /* CCID class */
|
||||
0x00, /* CCID subclass */
|
||||
0x00, /* CCID protocol */
|
||||
0, /* string index for interface */
|
||||
|
||||
/* ICC Descriptor */
|
||||
54, /* bLength: */
|
||||
0x21, /* bDescriptorType: USBDESCR_ICC */
|
||||
0x10, 0x01, /* bcdCCID: revision 1.1 (of CCID) */
|
||||
0, /* bMaxSlotIndex: */
|
||||
1, /* bVoltageSupport: 5V-only */
|
||||
0x02, 0, 0, 0, /* dwProtocols: T=1 */
|
||||
0xa0, 0x0f, 0, 0, /* dwDefaultClock: 4000 */
|
||||
0xa0, 0x0f, 0, 0, /* dwMaximumClock: 4000 */
|
||||
0, /* bNumClockSupported: 0x00 */
|
||||
0x80, 0x25, 0, 0, /* dwDataRate: 9600 */
|
||||
0x80, 0x25, 0, 0, /* dwMaxDataRate: 9600 */
|
||||
0, /* bNumDataRateSupported: 0x00 */
|
||||
0xfe, 0, 0, 0, /* dwMaxIFSD: 254 */
|
||||
0, 0, 0, 0, /* dwSynchProtocols: 0 */
|
||||
0, 0, 0, 0, /* dwMechanical: 0 */
|
||||
0x7a, 0x04, 0x02, 0x00, /* dwFeatures:
|
||||
* Short and extended APDU level: 0x40000 ----
|
||||
* Short APDU level : 0x20000 *
|
||||
* (ICCD?) : 0x00800 ----
|
||||
* Automatic IFSD : 0x00400 *
|
||||
* NAD value other than 0x00 : 0x00200
|
||||
* Can set ICC in clock stop : 0x00100
|
||||
* Automatic PPS CUR : 0x00080
|
||||
* Automatic PPS PROP : 0x00040 *
|
||||
* Auto baud rate change : 0x00020 *
|
||||
* Auto clock change : 0x00010 *
|
||||
* Auto voltage selection : 0x00008 *
|
||||
* Auto activaction of ICC : 0x00004
|
||||
* Automatic conf. based on ATR : 0x00002 *
|
||||
*/
|
||||
0x0f, 0x01, 0, 0, /* dwMaxCCIDMessageLength: 271 */
|
||||
0xff, /* bClassGetResponse: 0xff */
|
||||
0x00, /* bClassEnvelope: 0 */
|
||||
0, 0, /* wLCDLayout: 0 */
|
||||
0, /* bPinSupport: No PIN pad */
|
||||
|
||||
1, /* bMaxCCIDBusySlots: 1 */
|
||||
/*Endpoint IN1 Descriptor*/
|
||||
7, /* bLength: Endpoint Descriptor size */
|
||||
USB_DESC_TYPE_ENDPOINT, /* bDescriptorType: Endpoint */
|
||||
CCID_IN_EP, /* bEndpointAddress: (IN1) */
|
||||
0x02, /* bmAttributes: Bulk */
|
||||
CCID_DATA_PACKET_SIZE, 0x00, /* wMaxPacketSize: */
|
||||
0x00, /* bInterval */
|
||||
/*Endpoint OUT1 Descriptor*/
|
||||
7, /* bLength: Endpoint Descriptor size */
|
||||
USB_DESC_TYPE_ENDPOINT, /* bDescriptorType: Endpoint */
|
||||
CCID_OUT_EP, /* bEndpointAddress: (OUT1) */
|
||||
0x02, /* bmAttributes: Bulk */
|
||||
CCID_DATA_PACKET_SIZE, 0x00, /* wMaxPacketSize: */
|
||||
0x00, /* bInterval */
|
||||
/*Endpoint IN2 Descriptor*/
|
||||
7, /* bLength: Endpoint Descriptor size */
|
||||
USB_DESC_TYPE_ENDPOINT, /* bDescriptorType: Endpoint */
|
||||
CCID_CMD_EP, /* bEndpointAddress: (IN2) */
|
||||
0x03, /* bmAttributes: Interrupt */
|
||||
CCID_DATA_PACKET_SIZE, 0x00, /* wMaxPacketSize: 4 */
|
||||
0xFF, /* bInterval (255ms) */
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
};
|
||||
|
||||
USBD_ClassTypeDef USBD_Composite =
|
||||
@ -211,15 +305,21 @@ USBD_ClassTypeDef USBD_Composite =
|
||||
USBD_Composite_GetDeviceQualifierDescriptor,
|
||||
};
|
||||
|
||||
static USBD_ClassTypeDef *USBD_Classes[MAX_CLASSES];
|
||||
static USBD_ClassTypeDef * USBD_Classes[MAX_CLASSES];
|
||||
|
||||
int in_endpoint_to_class[MAX_ENDPOINTS];
|
||||
|
||||
int out_endpoint_to_class[MAX_ENDPOINTS];
|
||||
|
||||
void USBD_Composite_Set_Classes(USBD_ClassTypeDef *hid_class, USBD_ClassTypeDef *cdc_class) {
|
||||
void USBD_Composite_Set_Classes(USBD_ClassTypeDef *hid_class, USBD_ClassTypeDef *ccid_class, USBD_ClassTypeDef *cdc_class) {
|
||||
memset(USBD_Classes, 0 , sizeof(USBD_Classes));
|
||||
USBD_Classes[0] = hid_class;
|
||||
USBD_Classes[1] = cdc_class;
|
||||
#ifdef ENABLE_CCID
|
||||
USBD_Classes[1] = ccid_class;
|
||||
#endif
|
||||
#if DEBUG_LEVEL > 0
|
||||
USBD_Classes[2] = cdc_class;
|
||||
#endif
|
||||
}
|
||||
|
||||
static USBD_ClassTypeDef * getClass(uint8_t index)
|
||||
@ -228,9 +328,15 @@ static USBD_ClassTypeDef * getClass(uint8_t index)
|
||||
{
|
||||
case HID_INTF_NUM:
|
||||
return USBD_Classes[0];
|
||||
#ifdef ENABLE_CCID
|
||||
case CCID_INTF_NUM:
|
||||
return USBD_Classes[1];
|
||||
#endif
|
||||
#if DEBUG_LEVEL > 0
|
||||
case CDC_MASTER_INTF_NUM:
|
||||
case CDC_SLAVE_INTF_NUM:
|
||||
return USBD_Classes[1];
|
||||
return USBD_Classes[2];
|
||||
#endif
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
@ -238,18 +344,18 @@ static USBD_ClassTypeDef * getClass(uint8_t index)
|
||||
static uint8_t USBD_Composite_Init (USBD_HandleTypeDef *pdev, uint8_t cfgidx) {
|
||||
int i;
|
||||
for(i = 0; i < NUM_CLASSES; i++) {
|
||||
if (USBD_Classes[i]->Init(pdev, cfgidx) != USBD_OK) {
|
||||
if (USBD_Classes[i] != NULL && USBD_Classes[i]->Init(pdev, cfgidx) != USBD_OK) {
|
||||
return USBD_FAIL;
|
||||
}
|
||||
}
|
||||
|
||||
//N
|
||||
return USBD_OK;
|
||||
}
|
||||
|
||||
static uint8_t USBD_Composite_DeInit (USBD_HandleTypeDef *pdev, uint8_t cfgidx) {
|
||||
int i;
|
||||
for(i = 0; i < NUM_CLASSES; i++) {
|
||||
if (USBD_Classes[i]->DeInit(pdev, cfgidx) != USBD_OK) {
|
||||
if (USBD_Classes[i] != NULL && USBD_Classes[i]->DeInit(pdev, cfgidx) != USBD_OK) {
|
||||
return USBD_FAIL;
|
||||
}
|
||||
}
|
||||
@ -275,7 +381,7 @@ static uint8_t USBD_Composite_Setup (USBD_HandleTypeDef *pdev, USBD_SetupReqType
|
||||
|
||||
case USB_REQ_GET_DESCRIPTOR :
|
||||
for(i = 0; i < NUM_CLASSES; i++) {
|
||||
if (USBD_Classes[i]->Setup(pdev, req) != USBD_OK) {
|
||||
if (USBD_Classes[i] != NULL && USBD_Classes[i]->Setup(pdev, req) != USBD_OK) {
|
||||
return USBD_FAIL;
|
||||
}
|
||||
}
|
||||
@ -298,6 +404,8 @@ static uint8_t USBD_Composite_DataIn (USBD_HandleTypeDef *pdev, uint8_t epnum) {
|
||||
|
||||
i = in_endpoint_to_class[epnum];
|
||||
|
||||
if (USBD_Classes[i] == NULL) return USBD_FAIL;
|
||||
|
||||
return USBD_Classes[i]->DataIn(pdev, epnum);
|
||||
}
|
||||
|
||||
@ -306,6 +414,8 @@ static uint8_t USBD_Composite_DataOut (USBD_HandleTypeDef *pdev, uint8_t epnum)
|
||||
|
||||
i = out_endpoint_to_class[epnum];
|
||||
|
||||
if (USBD_Classes[i] == NULL) return USBD_FAIL;
|
||||
|
||||
return USBD_Classes[i]->DataOut(pdev, epnum);
|
||||
|
||||
}
|
||||
@ -313,7 +423,7 @@ static uint8_t USBD_Composite_DataOut (USBD_HandleTypeDef *pdev, uint8_t epnum)
|
||||
static uint8_t USBD_Composite_EP0_RxReady (USBD_HandleTypeDef *pdev) {
|
||||
int i;
|
||||
for(i = 0; i < NUM_CLASSES; i++) {
|
||||
if (USBD_Classes[i]->EP0_RxReady != NULL) {
|
||||
if (USBD_Classes[i] != NULL && USBD_Classes[i]->EP0_RxReady != NULL) {
|
||||
if (USBD_Classes[i]->EP0_RxReady(pdev) != USBD_OK) {
|
||||
return USBD_FAIL;
|
||||
}
|
||||
@ -323,16 +433,19 @@ static uint8_t USBD_Composite_EP0_RxReady (USBD_HandleTypeDef *pdev) {
|
||||
}
|
||||
|
||||
static uint8_t *USBD_Composite_GetFSCfgDesc (uint16_t *length) {
|
||||
//Y
|
||||
*length = COMPOSITE_CDC_HID_DESCRIPTOR_SIZE;
|
||||
return COMPOSITE_CDC_HID_DESCRIPTOR;
|
||||
}
|
||||
|
||||
static uint8_t *USBD_Composite_GetHSCfgDesc (uint16_t *length) {
|
||||
//N
|
||||
*length = COMPOSITE_CDC_HID_DESCRIPTOR_SIZE;
|
||||
return COMPOSITE_CDC_HID_DESCRIPTOR;
|
||||
}
|
||||
|
||||
static uint8_t *USBD_Composite_GetOtherSpeedCfgDesc (uint16_t *length) {
|
||||
|
||||
*length = COMPOSITE_CDC_HID_DESCRIPTOR_SIZE;
|
||||
return COMPOSITE_CDC_HID_DESCRIPTOR;
|
||||
}
|
||||
@ -353,6 +466,7 @@ __ALIGN_BEGIN static uint8_t USBD_Composite_DeviceQualifierDesc[USB_LEN_DEV_QUAL
|
||||
};
|
||||
|
||||
uint8_t *USBD_Composite_GetDeviceQualifierDescriptor (uint16_t *length) {
|
||||
*length = sizeof (USBD_Composite_DeviceQualifierDesc);
|
||||
return USBD_Composite_DeviceQualifierDesc;
|
||||
//N
|
||||
*length = sizeof (USBD_Composite_DeviceQualifierDesc);
|
||||
return USBD_Composite_DeviceQualifierDesc;
|
||||
}
|
||||
|
@ -17,7 +17,7 @@ extern int in_endpoint_to_class[MAX_ENDPOINTS];
|
||||
|
||||
extern int out_endpoint_to_class[MAX_ENDPOINTS];
|
||||
|
||||
void USBD_Composite_Set_Classes(USBD_ClassTypeDef *class0, USBD_ClassTypeDef *class1);
|
||||
void USBD_Composite_Set_Classes(USBD_ClassTypeDef *class0, USBD_ClassTypeDef *class1, USBD_ClassTypeDef *class2);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
@ -50,6 +50,9 @@
|
||||
#include "stm32l4xx_hal.h"
|
||||
#include "usbd_core.h"
|
||||
#include "usbd_hid.h"
|
||||
#include "usbd_cdc.h"
|
||||
#include "usbd_ccid.h"
|
||||
#include "log.h"
|
||||
|
||||
void SystemClock_Config(void);
|
||||
|
||||
@ -117,9 +120,14 @@ void HAL_PCD_DataOutStageCallback(PCD_HandleTypeDef *hpcd, uint8_t epnum)
|
||||
USBD_LL_DataOutStage((USBD_HandleTypeDef*)hpcd->pData, epnum, hpcd->OUT_ep[epnum].xfer_buff);
|
||||
switch(epnum)
|
||||
{
|
||||
case HID_ENDPOINT:
|
||||
case HID_EPOUT_ADDR:
|
||||
usb_hid_recieve_callback(epnum);
|
||||
break;
|
||||
#ifdef ENABLE_CCID
|
||||
case CCID_OUT_EP:
|
||||
usb_ccid_recieve_callback((USBD_HandleTypeDef*)hpcd->pData, epnum);
|
||||
break;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
@ -218,7 +226,6 @@ void HAL_PCD_DisconnectCallback(PCD_HandleTypeDef *hpcd)
|
||||
{
|
||||
USBD_LL_DevDisconnected((USBD_HandleTypeDef*)hpcd->pData);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Initializes the low level portion of the device driver.
|
||||
* @param pdev: Device handle
|
||||
@ -252,14 +259,20 @@ USBD_StatusTypeDef USBD_LL_Init(USBD_HandleTypeDef *pdev)
|
||||
HAL_PCDEx_PMAConfig((PCD_HandleTypeDef*)pdev->pData , 0x80 , PCD_SNG_BUF, 0x58);
|
||||
|
||||
// HID
|
||||
HAL_PCDEx_PMAConfig((PCD_HandleTypeDef*)pdev->pData , 0x01 , PCD_SNG_BUF, 0x98);
|
||||
HAL_PCDEx_PMAConfig((PCD_HandleTypeDef*)pdev->pData , 0x81 , PCD_SNG_BUF, 0xd8);
|
||||
HAL_PCDEx_PMAConfig((PCD_HandleTypeDef*)pdev->pData , HID_EPOUT_ADDR , PCD_SNG_BUF, 0x98);
|
||||
HAL_PCDEx_PMAConfig((PCD_HandleTypeDef*)pdev->pData , HID_EPIN_ADDR , PCD_SNG_BUF, 0xd8);
|
||||
|
||||
// CCID
|
||||
HAL_PCDEx_PMAConfig((PCD_HandleTypeDef*)pdev->pData , CCID_OUT_EP , PCD_SNG_BUF, 0xd8 + 64); // data OUT
|
||||
HAL_PCDEx_PMAConfig((PCD_HandleTypeDef*)pdev->pData , CCID_IN_EP , PCD_SNG_BUF, 0xd8 + 64*2); // data IN
|
||||
HAL_PCDEx_PMAConfig((PCD_HandleTypeDef*)pdev->pData , CCID_CMD_EP , PCD_SNG_BUF, 0xd8 + 64*3); // commands
|
||||
|
||||
// CDC / uart
|
||||
HAL_PCDEx_PMAConfig((PCD_HandleTypeDef*)pdev->pData , 0x02 , PCD_SNG_BUF, 0xd8 + 64); // data OUT
|
||||
HAL_PCDEx_PMAConfig((PCD_HandleTypeDef*)pdev->pData , 0x82 , PCD_SNG_BUF, 0xd8 + 64*2); // data IN
|
||||
HAL_PCDEx_PMAConfig((PCD_HandleTypeDef*)pdev->pData , 0x83 , PCD_SNG_BUF, 0xd8 + 64*3); // commands
|
||||
HAL_PCDEx_PMAConfig((PCD_HandleTypeDef*)pdev->pData , CDC_CMD_EP , PCD_SNG_BUF, 0xd8 + 64*4); // commands
|
||||
HAL_PCDEx_PMAConfig((PCD_HandleTypeDef*)pdev->pData , CDC_OUT_EP , PCD_SNG_BUF, 0xd8 + 64*5); // data OUT
|
||||
HAL_PCDEx_PMAConfig((PCD_HandleTypeDef*)pdev->pData , CDC_IN_EP , PCD_SNG_BUF, 0xd8 + 64*6); // data IN
|
||||
|
||||
// dump_pma_header("usbd_conf");
|
||||
|
||||
return USBD_OK;
|
||||
}
|
||||
@ -310,6 +323,7 @@ USBD_StatusTypeDef USBD_LL_OpenEP(USBD_HandleTypeDef *pdev,
|
||||
uint8_t ep_type,
|
||||
uint16_t ep_mps)
|
||||
{
|
||||
// printf1(TAG_RED,"LL_Open. ep: %x, %x\r\n", ep_addr, ep_type);
|
||||
HAL_PCD_EP_Open((PCD_HandleTypeDef*) pdev->pData,
|
||||
ep_addr,
|
||||
ep_mps,
|
||||
|
@ -12,9 +12,17 @@ _estack = 0x2000c000;
|
||||
|
||||
_MIN_STACK_SIZE = 0x400;
|
||||
|
||||
/*
|
||||
flash_cfg is for storing bootloader data, like last used firmware version.
|
||||
bootloader_configuration should be equal to (APPLICATION_END_PAGE) page address, from targets/stm32l432/src/memory_layout.h:30; and equal to flash_cfg origin
|
||||
*/
|
||||
|
||||
bootloader_configuration = 0x08000000 + 216*1024+8;
|
||||
|
||||
MEMORY
|
||||
{
|
||||
flash (rx) : ORIGIN = 0x08000000, LENGTH = 20K
|
||||
flash_cfg (rx) : ORIGIN = 0x08000000 + 216*1024+8, LENGTH = 2K-8
|
||||
ram (xrw) : ORIGIN = 0x20000000, LENGTH = 48K
|
||||
sram2 (rw) : ORIGIN = 0x10000000, LENGTH = 16K
|
||||
}
|
||||
@ -39,6 +47,11 @@ SECTIONS
|
||||
_etext = .;
|
||||
} >flash
|
||||
|
||||
.flag2 bootloader_configuration :
|
||||
{
|
||||
KEEP(*(.flag2)) ;
|
||||
} > flash_cfg
|
||||
|
||||
_sidata = LOADADDR(.data);
|
||||
|
||||
.data :
|
||||
|
@ -12,9 +12,17 @@ _estack = 0x2000c000;
|
||||
|
||||
_MIN_STACK_SIZE = 0x400;
|
||||
|
||||
/*
|
||||
flash_cfg is for storing bootloader data, like last used firmware version.
|
||||
bootloader_configuration should be equal to (APPLICATION_END_PAGE) page address, from targets/stm32l432/src/memory_layout.h:30; and equal to flash_cfg origin
|
||||
*/
|
||||
|
||||
bootloader_configuration = 0x08000000 + 216*1024+8;
|
||||
|
||||
MEMORY
|
||||
{
|
||||
flash (rx) : ORIGIN = 0x08000000, LENGTH = 32K
|
||||
flash_cfg (rx) : ORIGIN = 0x08000000 + 216*1024+8, LENGTH = 2K-8
|
||||
ram (xrw) : ORIGIN = 0x20000000, LENGTH = 48K
|
||||
sram2 (rw) : ORIGIN = 0x10000000, LENGTH = 16K
|
||||
}
|
||||
@ -39,6 +47,11 @@ SECTIONS
|
||||
_etext = .;
|
||||
} >flash
|
||||
|
||||
.flag2 bootloader_configuration :
|
||||
{
|
||||
KEEP(*(.flag2)) ;
|
||||
} > flash_cfg
|
||||
|
||||
_sidata = LOADADDR(.data);
|
||||
|
||||
.data :
|
||||
|
@ -13,14 +13,21 @@ _estack = 0x2000c000;
|
||||
_MIN_STACK_SIZE = 0x400;
|
||||
|
||||
/*
|
||||
Memory layout of device:
|
||||
20 KB 198KB-8 38 KB
|
||||
| bootloader | application | secrets/data |
|
||||
len | 20 KB/10p| 196KB-8-8/98p | 2kB/1p | 38 KB/19p |
|
||||
pos | 0->20 KB | 20->216KB-8-8 | 216kB -> 218 kB | 218->256 KB |
|
||||
posp | 0-10 | 10-113 | 113-114 | 113-128 |
|
||||
desc | bootloader | application | bootloader data | secrets/data |
|
||||
|
||||
Last 8 bytes in application space are occupied by bootloader flags - app
|
||||
authorization and bootloader activation flag.
|
||||
*/
|
||||
|
||||
/* Current firmware version number is concatenated to the firmware code - see .flag marker */
|
||||
/* flash length is (APPLICATION_END_PAGE-20*1024), where 20K is bootloader */
|
||||
|
||||
MEMORY
|
||||
{
|
||||
flash (rx) : ORIGIN = 0x08005000, LENGTH = 198K - 8
|
||||
flash (rx) : ORIGIN = 0x08000000 + 20K, LENGTH = 216K - 20K - 8
|
||||
ram (xrw) : ORIGIN = 0x20000000, LENGTH = 48K
|
||||
sram2 (rw) : ORIGIN = 0x10000000, LENGTH = 16K
|
||||
}
|
||||
@ -56,6 +63,12 @@ SECTIONS
|
||||
_edata = .;
|
||||
} >ram AT> flash
|
||||
|
||||
.flag :
|
||||
{
|
||||
. = ALIGN(8);
|
||||
KEEP(*(.flag)) ;
|
||||
} > flash
|
||||
|
||||
.bss :
|
||||
{
|
||||
. = ALIGN(4);
|
||||
|
@ -12,9 +12,22 @@ _estack = 0x2000c000;
|
||||
|
||||
_MIN_STACK_SIZE = 0x400;
|
||||
|
||||
/*
|
||||
len | 32 KB/16p| 184KB-8-8/92p | 2kB/1p | 38 KB/19p |
|
||||
pos | 0->32 KB | 32->216KB-8-8 | 216kB -> 218 kB | 218->256 KB |
|
||||
posp | 0-16 | 16-113 | 113-114 | 113-128 |
|
||||
desc | bootloader | application | bootloader data | secrets/data |
|
||||
|
||||
Last 8 bytes in application space are occupied by bootloader flags - app
|
||||
authorization and bootloader activation flag.
|
||||
*/
|
||||
|
||||
/* Current firmware version number is concatenated to the firmware code - see .flag marker */
|
||||
/* flash length is (APPLICATION_END_PAGE-20*1024), where 20K is bootloader */
|
||||
|
||||
MEMORY
|
||||
{
|
||||
flash (rx) : ORIGIN = 0x08008000, LENGTH = 186K - 8
|
||||
flash (rx) : ORIGIN = 0x08000000 + 20K + 12K, LENGTH = 216K - 20K - 12K - 8
|
||||
ram (xrw) : ORIGIN = 0x20000000, LENGTH = 48K
|
||||
sram2 (rw) : ORIGIN = 0x10000000, LENGTH = 16K
|
||||
}
|
||||
@ -50,6 +63,12 @@ SECTIONS
|
||||
_edata = .;
|
||||
} >ram AT> flash
|
||||
|
||||
.flag :
|
||||
{
|
||||
. = ALIGN(8);
|
||||
KEEP(*(.flag)) ;
|
||||
} > flash
|
||||
|
||||
.bss :
|
||||
{
|
||||
. = ALIGN(4);
|
||||
|
@ -8,21 +8,25 @@
|
||||
#include "device.h"
|
||||
#include "nfc.h"
|
||||
|
||||
static void flush_rx()
|
||||
static void flush_rx(void)
|
||||
{
|
||||
while(LL_SPI_IsActiveFlag_RXNE(SPI1) != 0)
|
||||
{
|
||||
LL_SPI_ReceiveData8(SPI1);
|
||||
}
|
||||
}
|
||||
static void wait_for_tx()
|
||||
|
||||
|
||||
static void wait_for_tx(void)
|
||||
{
|
||||
// while (LL_SPI_IsActiveFlag_BSY(SPI1) == 1)
|
||||
// ;
|
||||
while(LL_SPI_GetTxFIFOLevel(SPI1) != LL_SPI_TX_FIFO_EMPTY)
|
||||
;
|
||||
}
|
||||
static void wait_for_rx()
|
||||
|
||||
|
||||
static void wait_for_rx(void)
|
||||
{
|
||||
while(LL_SPI_IsActiveFlag_RXNE(SPI1) == 0)
|
||||
;
|
||||
@ -270,7 +274,7 @@ void ams_print_int1(uint8_t int0)
|
||||
#endif
|
||||
}
|
||||
|
||||
int ams_init()
|
||||
int ams_init(void)
|
||||
{
|
||||
LL_GPIO_SetPinMode(SOLO_AMS_CS_PORT,SOLO_AMS_CS_PIN,LL_GPIO_MODE_OUTPUT);
|
||||
LL_GPIO_SetOutputPin(SOLO_AMS_CS_PORT,SOLO_AMS_CS_PIN);
|
||||
@ -292,7 +296,7 @@ int ams_init()
|
||||
return 0;
|
||||
}
|
||||
|
||||
void ams_configure()
|
||||
void ams_configure(void)
|
||||
{
|
||||
// Should not be used during passive operation.
|
||||
uint8_t block[4];
|
||||
|
@ -39,8 +39,8 @@ typedef union
|
||||
#define SELECT() LL_GPIO_ResetOutputPin(SOLO_AMS_CS_PORT,SOLO_AMS_CS_PIN)
|
||||
#define UNSELECT() LL_GPIO_SetOutputPin(SOLO_AMS_CS_PORT,SOLO_AMS_CS_PIN)
|
||||
|
||||
int ams_init();
|
||||
void ams_configure();
|
||||
int ams_init(void);
|
||||
void ams_configure(void);
|
||||
|
||||
void ams_read_buffer(uint8_t * data, int len);
|
||||
void ams_write_buffer(uint8_t * data, int len);
|
||||
|
@ -12,9 +12,13 @@
|
||||
#define DEBUG_UART USART1
|
||||
|
||||
#ifndef DEBUG_LEVEL
|
||||
// Enable the CDC ACM USB interface & debug logs (DEBUG_LEVEL > 0)
|
||||
#define DEBUG_LEVEL 0
|
||||
#endif
|
||||
|
||||
// Enable the CCID USB interface
|
||||
// #define ENABLE_CCID
|
||||
|
||||
#define NON_BLOCK_PRINTING 0
|
||||
|
||||
|
||||
|
@ -61,12 +61,13 @@ static uint8_t master_secret[64];
|
||||
static uint8_t transport_secret[32];
|
||||
|
||||
|
||||
void crypto_sha256_init()
|
||||
void crypto_sha256_init(void)
|
||||
{
|
||||
sha256_init(&sha256_ctx);
|
||||
}
|
||||
|
||||
void crypto_sha512_init() {
|
||||
void crypto_sha512_init(void)
|
||||
{
|
||||
cf_sha512_init(&sha512_ctx);
|
||||
}
|
||||
|
||||
@ -79,7 +80,7 @@ void crypto_load_master_secret(uint8_t * key)
|
||||
memmove(transport_secret, key+64, 32);
|
||||
}
|
||||
|
||||
void crypto_reset_master_secret()
|
||||
void crypto_reset_master_secret(void)
|
||||
{
|
||||
memset(master_secret, 0, 64);
|
||||
memset(transport_secret, 0, 32);
|
||||
@ -107,7 +108,8 @@ void crypto_sha256_final(uint8_t * hash)
|
||||
sha256_final(&sha256_ctx, hash);
|
||||
}
|
||||
|
||||
void crypto_sha512_final(uint8_t * hash) {
|
||||
void crypto_sha512_final(uint8_t * hash)
|
||||
{
|
||||
// NB: there is also cf_sha512_digest
|
||||
cf_sha512_digest_final(&sha512_ctx, hash);
|
||||
}
|
||||
@ -183,14 +185,14 @@ void crypto_sha256_hmac_final(uint8_t * key, uint32_t klen, uint8_t * hmac)
|
||||
}
|
||||
|
||||
|
||||
void crypto_ecc256_init()
|
||||
void crypto_ecc256_init(void)
|
||||
{
|
||||
uECC_set_rng((uECC_RNG_Function)ctap_generate_rng);
|
||||
_es256_curve = uECC_secp256r1();
|
||||
}
|
||||
|
||||
|
||||
void crypto_ecc256_load_attestation_key()
|
||||
void crypto_ecc256_load_attestation_key(void)
|
||||
{
|
||||
static uint8_t _key [32];
|
||||
memmove(_key, (uint8_t*)ATTESTATION_KEY_ADDR, 32);
|
||||
|
@ -34,7 +34,7 @@
|
||||
#define LOW_FREQUENCY 1
|
||||
#define HIGH_FREQUENCY 0
|
||||
|
||||
void wait_for_usb_tether();
|
||||
void wait_for_usb_tether(void);
|
||||
|
||||
|
||||
uint32_t __90_ms = 0;
|
||||
@ -45,28 +45,37 @@ uint32_t __last_update = 0;
|
||||
extern PCD_HandleTypeDef hpcd;
|
||||
static int _NFC_status = 0;
|
||||
static bool isLowFreq = 0;
|
||||
static bool _RequestComeFromNFC = false;
|
||||
static bool _up_disabled = false;
|
||||
|
||||
// #define IS_BUTTON_PRESSED() (0 == (LL_GPIO_ReadInputPort(SOLO_BUTTON_PORT) & SOLO_BUTTON_PIN))
|
||||
static int is_physical_button_pressed()
|
||||
static int is_physical_button_pressed(void)
|
||||
{
|
||||
return (0 == (LL_GPIO_ReadInputPort(SOLO_BUTTON_PORT) & SOLO_BUTTON_PIN));
|
||||
}
|
||||
|
||||
static int is_touch_button_pressed()
|
||||
static int is_touch_button_pressed(void)
|
||||
{
|
||||
return tsc_read_button(0) || tsc_read_button(1);
|
||||
int is_pressed = (tsc_read_button(0) || tsc_read_button(1));
|
||||
#ifndef IS_BOOTLOADER
|
||||
if (is_pressed)
|
||||
{
|
||||
// delay for debounce, and longer than polling timer period.
|
||||
delay(95);
|
||||
return (tsc_read_button(0) || tsc_read_button(1));
|
||||
}
|
||||
#endif
|
||||
return is_pressed;
|
||||
}
|
||||
|
||||
int (*IS_BUTTON_PRESSED)() = is_physical_button_pressed;
|
||||
|
||||
static void edge_detect_touch_button()
|
||||
static void edge_detect_touch_button(void)
|
||||
{
|
||||
static uint8_t last_touch = 0;
|
||||
uint8_t current_touch = 0;
|
||||
if (is_touch_button_pressed == IS_BUTTON_PRESSED)
|
||||
{
|
||||
current_touch = IS_BUTTON_PRESSED();
|
||||
current_touch = (tsc_read_button(0) || tsc_read_button(1));
|
||||
|
||||
// 1 sample per 25 ms
|
||||
if ((millis() - __last_button_bounce_time) > 25)
|
||||
@ -83,12 +92,13 @@ static void edge_detect_touch_button()
|
||||
|
||||
}
|
||||
|
||||
void request_from_nfc(bool request_active) {
|
||||
_RequestComeFromNFC = request_active;
|
||||
void device_disable_up(bool disable)
|
||||
{
|
||||
_up_disabled = disable;
|
||||
}
|
||||
|
||||
// Timer6 overflow handler. happens every ~90ms.
|
||||
void TIM6_DAC_IRQHandler()
|
||||
void TIM6_DAC_IRQHandler(void)
|
||||
{
|
||||
// timer is only 16 bits, so roll it over here
|
||||
TIM6->SR = 0;
|
||||
@ -133,7 +143,7 @@ void USB_IRQHandler(void)
|
||||
HAL_PCD_IRQHandler(&hpcd);
|
||||
}
|
||||
|
||||
uint32_t millis()
|
||||
uint32_t millis(void)
|
||||
{
|
||||
return (((uint32_t)TIM6->CNT) + (__90_ms * 90));
|
||||
}
|
||||
@ -151,9 +161,8 @@ void device_set_status(uint32_t status)
|
||||
__device_status = status;
|
||||
}
|
||||
|
||||
int device_is_button_pressed()
|
||||
int device_is_button_pressed(void)
|
||||
{
|
||||
|
||||
return IS_BUTTON_PRESSED();
|
||||
}
|
||||
|
||||
@ -163,12 +172,13 @@ void delay(uint32_t ms)
|
||||
while ((millis() - time) < ms)
|
||||
;
|
||||
}
|
||||
void device_reboot()
|
||||
|
||||
void device_reboot(void)
|
||||
{
|
||||
NVIC_SystemReset();
|
||||
}
|
||||
|
||||
void device_init_button()
|
||||
void device_init_button(void)
|
||||
{
|
||||
if (tsc_sensor_exists())
|
||||
{
|
||||
@ -218,12 +228,12 @@ void device_init(int argc, char *argv[])
|
||||
|
||||
}
|
||||
|
||||
int device_is_nfc()
|
||||
int device_is_nfc(void)
|
||||
{
|
||||
return _NFC_status;
|
||||
}
|
||||
|
||||
void wait_for_usb_tether()
|
||||
void wait_for_usb_tether(void)
|
||||
{
|
||||
while (USBD_OK != CDC_Transmit_FS((uint8_t*)"tethered\r\n", 10) )
|
||||
;
|
||||
@ -234,7 +244,7 @@ void wait_for_usb_tether()
|
||||
;
|
||||
}
|
||||
|
||||
void usbhid_init()
|
||||
void usbhid_init(void)
|
||||
{
|
||||
if (!isLowFreq)
|
||||
{
|
||||
@ -284,12 +294,12 @@ void ctaphid_write_block(uint8_t * data)
|
||||
}
|
||||
|
||||
|
||||
void usbhid_close()
|
||||
void usbhid_close(void)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void main_loop_delay()
|
||||
void main_loop_delay(void)
|
||||
{
|
||||
|
||||
}
|
||||
@ -299,13 +309,14 @@ static uint32_t winkt1 = 0;
|
||||
#ifdef LED_WINK_VALUE
|
||||
static uint32_t winkt2 = 0;
|
||||
#endif
|
||||
void device_wink()
|
||||
|
||||
void device_wink(void)
|
||||
{
|
||||
wink_time = 10;
|
||||
winkt1 = 0;
|
||||
}
|
||||
|
||||
void heartbeat()
|
||||
void heartbeat(void)
|
||||
{
|
||||
static int state = 0;
|
||||
static uint32_t val = (LED_MAX_SCALER - LED_MIN_SCALER)/2;
|
||||
@ -374,7 +385,7 @@ void authenticator_read_backup_state(AuthenticatorState * a)
|
||||
}
|
||||
|
||||
// Return 1 yes backup is init'd, else 0
|
||||
int authenticator_is_backup_initialized()
|
||||
int authenticator_is_backup_initialized(void)
|
||||
{
|
||||
uint8_t header[16];
|
||||
uint32_t * ptr = (uint32_t *)flash_addr(STATE2_PAGE);
|
||||
@ -399,7 +410,8 @@ void authenticator_write_state(AuthenticatorState * a, int backup)
|
||||
}
|
||||
}
|
||||
|
||||
uint32_t ctap_atomic_count(int sel)
|
||||
#if !defined(IS_BOOTLOADER)
|
||||
uint32_t ctap_atomic_count(uint32_t amount)
|
||||
{
|
||||
int offset = 0;
|
||||
uint32_t * ptr = (uint32_t *)flash_addr(COUNTER1_PAGE);
|
||||
@ -414,10 +426,12 @@ uint32_t ctap_atomic_count(int sel)
|
||||
|
||||
uint32_t lastc = 0;
|
||||
|
||||
if (sel != 0)
|
||||
if (amount == 0)
|
||||
{
|
||||
printf2(TAG_ERR,"counter2 not imple\n");
|
||||
exit(1);
|
||||
// Use a random count [1-16].
|
||||
uint8_t rng[1];
|
||||
ctap_generate_rng(rng, 1);
|
||||
amount = (rng[0] & 0x0f) + 1;
|
||||
}
|
||||
|
||||
for (offset = 0; offset < PAGE_SIZE/4; offset += 2) // wear-level the flash
|
||||
@ -450,7 +464,7 @@ uint32_t ctap_atomic_count(int sel)
|
||||
return lastc;
|
||||
}
|
||||
|
||||
lastc++;
|
||||
lastc += amount;
|
||||
|
||||
if (lastc/256 > erases)
|
||||
{
|
||||
@ -488,10 +502,10 @@ uint32_t ctap_atomic_count(int sel)
|
||||
|
||||
return lastc;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
void device_manage()
|
||||
void device_manage(void)
|
||||
{
|
||||
#if NON_BLOCK_PRINTING
|
||||
int i = 10;
|
||||
@ -517,7 +531,7 @@ void device_manage()
|
||||
#endif
|
||||
}
|
||||
|
||||
static int handle_packets()
|
||||
static int handle_packets(void)
|
||||
{
|
||||
static uint8_t hidmsg[HID_PACKET_SIZE];
|
||||
memset(hidmsg,0, sizeof(hidmsg));
|
||||
@ -553,6 +567,7 @@ static int wait_for_button_activate(uint32_t wait)
|
||||
} while (!IS_BUTTON_PRESSED());
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int wait_for_button_release(uint32_t wait)
|
||||
{
|
||||
int ret;
|
||||
@ -574,11 +589,17 @@ static int wait_for_button_release(uint32_t wait)
|
||||
int ctap_user_presence_test(uint32_t up_delay)
|
||||
{
|
||||
int ret;
|
||||
if (device_is_nfc() == NFC_IS_ACTIVE || _RequestComeFromNFC)
|
||||
|
||||
if (device_is_nfc() == NFC_IS_ACTIVE)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (_up_disabled)
|
||||
{
|
||||
return 2;
|
||||
}
|
||||
|
||||
#if SKIP_BUTTON_CHECK_WITH_DELAY
|
||||
int i=500;
|
||||
while(i--)
|
||||
@ -640,7 +661,7 @@ int ctap_user_verification(uint8_t arg)
|
||||
return 1;
|
||||
}
|
||||
|
||||
void ctap_reset_rk()
|
||||
void ctap_reset_rk(void)
|
||||
{
|
||||
int i;
|
||||
printf1(TAG_GREEN, "resetting RK \r\n");
|
||||
@ -650,7 +671,7 @@ void ctap_reset_rk()
|
||||
}
|
||||
}
|
||||
|
||||
uint32_t ctap_rk_size()
|
||||
uint32_t ctap_rk_size(void)
|
||||
{
|
||||
return RK_NUM_PAGES * (PAGE_SIZE / sizeof(CTAP_residentKey));
|
||||
}
|
||||
@ -712,7 +733,7 @@ void ctap_overwrite_rk(int index,CTAP_residentKey * rk)
|
||||
}
|
||||
}
|
||||
|
||||
void boot_st_bootloader()
|
||||
void boot_st_bootloader(void)
|
||||
{
|
||||
__disable_irq();
|
||||
|
||||
@ -724,7 +745,7 @@ void boot_st_bootloader()
|
||||
;
|
||||
}
|
||||
|
||||
void boot_solo_bootloader()
|
||||
void boot_solo_bootloader(void)
|
||||
{
|
||||
LL_IWDG_Enable(IWDG);
|
||||
|
||||
|
@ -14,12 +14,12 @@
|
||||
#include "log.h"
|
||||
#include "device.h"
|
||||
|
||||
static void flash_lock()
|
||||
static void flash_lock(void)
|
||||
{
|
||||
FLASH->CR |= (1U<<31);
|
||||
}
|
||||
|
||||
static void flash_unlock()
|
||||
static void flash_unlock(void)
|
||||
{
|
||||
if (FLASH->CR & FLASH_CR_LOCK)
|
||||
{
|
||||
|
@ -28,6 +28,7 @@
|
||||
#include "usbd_desc.h"
|
||||
#include "usbd_hid.h"
|
||||
#include "usbd_cdc.h"
|
||||
#include "usbd_ccid.h"
|
||||
#include "usbd_composite.h"
|
||||
#include "usbd_cdc_if.h"
|
||||
#include "device.h"
|
||||
@ -698,33 +699,33 @@ void SystemClock_Config_LF20(void)
|
||||
SET_BIT(RCC->APB1ENR1, RCC_APB1ENR1_PWREN);
|
||||
}
|
||||
|
||||
void init_usb()
|
||||
void init_usb(void)
|
||||
{
|
||||
// enable USB power
|
||||
SET_BIT(PWR->CR2, PWR_CR2_USV);
|
||||
|
||||
// Enable USB Clock
|
||||
SET_BIT(RCC->APB1ENR1, RCC_APB1ENR1_USBFSEN);
|
||||
|
||||
#if DEBUG_LEVEL > 0
|
||||
USBD_Composite_Set_Classes(&USBD_HID, &USBD_CDC);
|
||||
#ifndef IS_BOOTLOADER
|
||||
USBD_Composite_Set_Classes(&USBD_HID, &USBD_CCID, &USBD_CDC);
|
||||
in_endpoint_to_class[HID_EPIN_ADDR & 0x7F] = 0;
|
||||
out_endpoint_to_class[HID_EPOUT_ADDR & 0x7F] = 0;
|
||||
|
||||
in_endpoint_to_class[CDC_IN_EP & 0x7F] = 1;
|
||||
out_endpoint_to_class[CDC_OUT_EP & 0x7F] = 1;
|
||||
in_endpoint_to_class[CCID_IN_EP & 0x7F] = 1;
|
||||
out_endpoint_to_class[CCID_OUT_EP & 0x7F] = 1;
|
||||
|
||||
in_endpoint_to_class[CDC_IN_EP & 0x7F] = 2;
|
||||
out_endpoint_to_class[CDC_OUT_EP & 0x7F] = 2;
|
||||
|
||||
USBD_Init(&Solo_USBD_Device, &Solo_Desc, 0);
|
||||
USBD_RegisterClass(&Solo_USBD_Device, &USBD_Composite);
|
||||
// USBD_RegisterClass(&Solo_USBD_Device, &USBD_HID);
|
||||
//
|
||||
// USBD_RegisterClass(&Solo_USBD_Device, &USBD_CDC);
|
||||
#if DEBUG_LEVEL > 0
|
||||
USBD_CDC_RegisterInterface(&Solo_USBD_Device, &USBD_Interface_fops_FS);
|
||||
#endif
|
||||
#else
|
||||
USBD_Init(&Solo_USBD_Device, &Solo_Desc, 0);
|
||||
USBD_RegisterClass(&Solo_USBD_Device, &USBD_HID);
|
||||
#endif
|
||||
|
||||
USBD_Start(&Solo_USBD_Device);
|
||||
}
|
||||
|
||||
|
@ -22,7 +22,7 @@
|
||||
#ifndef _INIT_H_
|
||||
#define _INIT_H_
|
||||
|
||||
void init_usb();
|
||||
void init_usb(void);
|
||||
void init_gpio(void);
|
||||
void init_debug_uart(void);
|
||||
void init_pwm(void);
|
||||
|
@ -57,10 +57,11 @@ void TIM6_DAC_IRQHandler()
|
||||
__90_ms += 1;
|
||||
}
|
||||
|
||||
uint32_t millis()
|
||||
uint32_t millis(void)
|
||||
{
|
||||
return (((uint32_t)TIM6->CNT) + (__90_ms * 90));
|
||||
}
|
||||
|
||||
void _Error_Handler(char *file, int line)
|
||||
{
|
||||
while(1)
|
||||
|
@ -37,10 +37,33 @@
|
||||
|
||||
// End of application code. Leave some extra room for future data storage.
|
||||
// NOT included in application
|
||||
#define APPLICATION_END_PAGE ((PAGES - 19))
|
||||
#define APPLICATION_END_PAGE ((PAGES - 20))
|
||||
#define APPLICATION_END_ADDR ((0x08000000 + ((APPLICATION_END_PAGE)*PAGE_SIZE))-8)
|
||||
|
||||
// Bootloader state.
|
||||
#define AUTH_WORD_ADDR (APPLICATION_END_ADDR)
|
||||
|
||||
#define LAST_ADDR (APPLICATION_END_ADDR-2048 + 8)
|
||||
#define BOOT_VERSION_PAGE (APPLICATION_END_PAGE)
|
||||
#define BOOT_VERSION_ADDR (0x08000000 + BOOT_VERSION_PAGE*FLASH_PAGE_SIZE + 8)
|
||||
#define LAST_PAGE (APPLICATION_END_PAGE-1)
|
||||
|
||||
|
||||
struct flash_memory_st{
|
||||
uint8_t bootloader[APPLICATION_START_PAGE*2*1024];
|
||||
uint8_t application[(APPLICATION_END_PAGE-APPLICATION_START_PAGE)*2*1024-8];
|
||||
uint8_t auth_word[4];
|
||||
uint8_t bootloader_disabled[4];
|
||||
// place for more user data
|
||||
uint8_t _reserved_application_end_mark[8];
|
||||
uint8_t bootloader_data[2*1024-8];
|
||||
uint8_t user_data[38*1024];
|
||||
} __attribute__((packed));
|
||||
|
||||
typedef struct flash_memory_st flash_memory_st;
|
||||
|
||||
#include <assert.h>
|
||||
static_assert(sizeof(flash_memory_st) == 256*1024, "Data structure doesn't match flash size");
|
||||
|
||||
|
||||
#endif
|
||||
|
@ -18,6 +18,18 @@
|
||||
static uint8_t chain_buffer[2048] = {0};
|
||||
static size_t chain_buffer_len = 0;
|
||||
static bool chain_buffer_tx = false;
|
||||
static uint8_t current_cid = 0;
|
||||
|
||||
// forward declarations
|
||||
void rblock_acknowledge(uint8_t req0, bool ack);
|
||||
|
||||
uint8_t p14443_have_cid(uint8_t pcb) {
|
||||
// CID
|
||||
if (pcb & 0x08)
|
||||
return true;
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
uint8_t p14443_block_offset(uint8_t pcb) {
|
||||
uint8_t offset = 1;
|
||||
@ -191,7 +203,7 @@ bool nfc_write_response_ex(uint8_t req0, uint8_t * data, uint8_t len, uint16_t r
|
||||
return false;
|
||||
|
||||
res[0] = NFC_CMD_IBLOCK | (req0 & 0x0f);
|
||||
res[1] = 0;
|
||||
res[1] = current_cid;
|
||||
res[2] = 0;
|
||||
|
||||
uint8_t block_offset = p14443_block_offset(req0);
|
||||
@ -228,6 +240,8 @@ void nfc_write_response_chaining_plain(uint8_t req0, uint8_t * data, int len)
|
||||
{
|
||||
uint8_t res[32] = {0};
|
||||
res[0] = iBlock;
|
||||
res[1] = current_cid;
|
||||
res[2] = 0;
|
||||
if (len && data)
|
||||
memcpy(&res[block_offset], data, len);
|
||||
nfc_write_frame(res, len + block_offset);
|
||||
@ -237,7 +251,7 @@ void nfc_write_response_chaining_plain(uint8_t req0, uint8_t * data, int len)
|
||||
// transmit I block
|
||||
int vlen = MIN(32 - block_offset, len - sendlen);
|
||||
res[0] = iBlock;
|
||||
res[1] = 0;
|
||||
res[1] = current_cid;
|
||||
res[2] = 0;
|
||||
memcpy(&res[block_offset], &data[sendlen], vlen);
|
||||
|
||||
@ -268,6 +282,20 @@ void nfc_write_response_chaining_plain(uint8_t req0, uint8_t * data, int len)
|
||||
printf1(TAG_NFC, "R block RX timeout %d/%d.\r\n",sendlen,len);
|
||||
break;
|
||||
}
|
||||
|
||||
if (!IS_RBLOCK(recbuf[0]))
|
||||
{
|
||||
printf1(TAG_NFC, "R block RX error. Not a R block(0x%02x) %d/%d.\r\n", recbuf[0], sendlen, len);
|
||||
break;
|
||||
}
|
||||
|
||||
// NAK check
|
||||
if (recbuf[0] & NFC_CMD_RBLOCK_ACK)
|
||||
{
|
||||
rblock_acknowledge(recbuf[0], true);
|
||||
printf1(TAG_NFC, "R block RX error. NAK received. %d/%d.\r\n", recbuf[0], sendlen, len);
|
||||
break;
|
||||
}
|
||||
|
||||
uint8_t rblock_offset = p14443_block_offset(recbuf[0]);
|
||||
if (reclen != rblock_offset)
|
||||
@ -331,7 +359,7 @@ static uint32_t WTX_timer;
|
||||
|
||||
bool WTX_process(int read_timeout);
|
||||
|
||||
void WTX_clear()
|
||||
void WTX_clear(void)
|
||||
{
|
||||
WTX_sent = false;
|
||||
WTX_fail = false;
|
||||
@ -346,7 +374,7 @@ bool WTX_on(int WTX_time)
|
||||
return true;
|
||||
}
|
||||
|
||||
bool WTX_off()
|
||||
bool WTX_off(void)
|
||||
{
|
||||
WTX_timer = 0;
|
||||
|
||||
@ -370,7 +398,7 @@ bool WTX_off()
|
||||
return true;
|
||||
}
|
||||
|
||||
void WTX_timer_exec()
|
||||
void WTX_timer_exec(void)
|
||||
{
|
||||
// condition: (timer on) or (not expired[300ms])
|
||||
if ((WTX_timer == 0) || WTX_timer + 300 > millis())
|
||||
@ -466,7 +494,9 @@ void rblock_acknowledge(uint8_t req0, bool ack)
|
||||
NFC_STATE.block_num = !NFC_STATE.block_num;
|
||||
|
||||
buf[0] = NFC_CMD_RBLOCK | (req0 & 0x0f);
|
||||
if (ack)
|
||||
buf[1] = current_cid;
|
||||
// iso14443-4:2001 page 16. ACK, if bit is set to 0, NAK, if bit is set to 1
|
||||
if (!ack)
|
||||
buf[0] |= NFC_CMD_RBLOCK_ACK;
|
||||
|
||||
nfc_write_frame(buf, block_offset);
|
||||
@ -701,10 +731,10 @@ void apdu_process(uint8_t buf0, uint8_t *apduptr, APDU_STRUCT *apdu)
|
||||
printf1(TAG_NFC, "FIDO2 CTAP message. %d\r\n", timestamp());
|
||||
|
||||
// WTX_on(WTX_TIME_DEFAULT);
|
||||
request_from_nfc(true);
|
||||
device_disable_up(true);
|
||||
ctap_response_init(&ctap_resp);
|
||||
status = ctap_request(apdu->data, apdu->lc, &ctap_resp);
|
||||
request_from_nfc(false);
|
||||
device_disable_up(false);
|
||||
// if (!WTX_off())
|
||||
// return;
|
||||
|
||||
@ -784,9 +814,10 @@ void nfc_process_iblock(uint8_t * buf, int len)
|
||||
}
|
||||
|
||||
APDU_STRUCT apdu;
|
||||
if (apdu_decode(buf + block_offset, len - block_offset, &apdu)) {
|
||||
uint16_t ret = apdu_decode(buf + block_offset, len - block_offset, &apdu);
|
||||
if (ret != 0) {
|
||||
printf1(TAG_NFC,"apdu decode error\r\n");
|
||||
nfc_write_response(buf[0], SW_COND_USE_NOT_SATISFIED);
|
||||
nfc_write_response(buf[0], ret);
|
||||
return;
|
||||
}
|
||||
printf1(TAG_NFC,"apdu ok. %scase=%02x cla=%02x ins=%02x p1=%02x p2=%02x lc=%d le=%d\r\n",
|
||||
@ -802,7 +833,6 @@ void nfc_process_iblock(uint8_t * buf, int len)
|
||||
|
||||
memmove(&chain_buffer[chain_buffer_len], apdu.data, apdu.lc);
|
||||
chain_buffer_len += apdu.lc;
|
||||
delay(1);
|
||||
nfc_write_response(buf[0], SW_SUCCESS);
|
||||
printf1(TAG_NFC, "APDU chaining ok. %d/%d\r\n", apdu.lc, chain_buffer_len);
|
||||
return;
|
||||
@ -810,7 +840,6 @@ void nfc_process_iblock(uint8_t * buf, int len)
|
||||
|
||||
// if we have ISO 7816 APDU chain - move there all the data
|
||||
if (!chain_buffer_tx && chain_buffer_len > 0) {
|
||||
delay(1);
|
||||
memmove(&apdu.data[chain_buffer_len], apdu.data, apdu.lc);
|
||||
memmove(apdu.data, chain_buffer, chain_buffer_len);
|
||||
apdu.lc += chain_buffer_len; // here apdu struct does not match with memory!
|
||||
@ -827,7 +856,7 @@ void nfc_process_iblock(uint8_t * buf, int len)
|
||||
static uint8_t ibuf[1024];
|
||||
static int ibuflen = 0;
|
||||
|
||||
void clear_ibuf()
|
||||
void clear_ibuf(void)
|
||||
{
|
||||
ibuflen = 0;
|
||||
memset(ibuf, 0, sizeof(ibuf));
|
||||
@ -853,6 +882,8 @@ void nfc_process_block(uint8_t * buf, unsigned int len)
|
||||
else if (IS_IBLOCK(buf[0]))
|
||||
{
|
||||
uint8_t block_offset = p14443_block_offset(buf[0]);
|
||||
if (p14443_have_cid(buf[0]))
|
||||
current_cid = buf[1];
|
||||
if (buf[0] & 0x10)
|
||||
{
|
||||
printf1(TAG_NFC_APDU, "NFC_CMD_IBLOCK chaining blen=%d len=%d offs=%d\r\n", ibuflen, len, block_offset);
|
||||
@ -903,7 +934,9 @@ void nfc_process_block(uint8_t * buf, unsigned int len)
|
||||
}
|
||||
else if (IS_RBLOCK(buf[0]))
|
||||
{
|
||||
rblock_acknowledge(buf[0], false);
|
||||
if (p14443_have_cid(buf[0]))
|
||||
current_cid = buf[1];
|
||||
rblock_acknowledge(buf[0], true);
|
||||
printf1(TAG_NFC, "NFC_CMD_RBLOCK\r\n");
|
||||
}
|
||||
else if (IS_SBLOCK(buf[0]))
|
||||
@ -912,7 +945,10 @@ void nfc_process_block(uint8_t * buf, unsigned int len)
|
||||
if ((buf[0] & NFC_SBLOCK_DESELECT) == 0)
|
||||
{
|
||||
printf1(TAG_NFC, "NFC_CMD_SBLOCK, DESELECTED\r\n");
|
||||
nfc_write_frame(buf, 1);
|
||||
uint8_t block_offset = p14443_block_offset(buf[0]);
|
||||
if (p14443_have_cid(buf[0]))
|
||||
current_cid = buf[1];
|
||||
nfc_write_frame(buf, block_offset);
|
||||
ams_wait_for_tx(2);
|
||||
ams_write_command(AMS_CMD_SLEEP);
|
||||
nfc_state_init();
|
||||
@ -933,7 +969,7 @@ void nfc_process_block(uint8_t * buf, unsigned int len)
|
||||
}
|
||||
}
|
||||
|
||||
int nfc_loop()
|
||||
int nfc_loop(void)
|
||||
{
|
||||
uint8_t buf[32];
|
||||
AMS_DEVICE ams;
|
||||
|
@ -6,9 +6,9 @@
|
||||
#include "apdu.h"
|
||||
|
||||
// Return number of bytes read if any.
|
||||
int nfc_loop();
|
||||
int nfc_loop(void);
|
||||
|
||||
int nfc_init();
|
||||
int nfc_init(void);
|
||||
|
||||
typedef struct
|
||||
{
|
||||
@ -34,9 +34,9 @@ typedef struct
|
||||
#define IS_PPSS_CMD(x) (((x) & 0xf0) == NFC_CMD_PPSS)
|
||||
#define NFC_CMD_IBLOCK 0x00
|
||||
#define IS_IBLOCK(x) ( (((x) & 0xc0) == NFC_CMD_IBLOCK) && (((x) & 0x02) == 0x02) )
|
||||
#define NFC_CMD_RBLOCK 0x80
|
||||
#define NFC_CMD_RBLOCK_ACK 0x20
|
||||
#define IS_RBLOCK(x) ( (((x) & 0xc0) == NFC_CMD_RBLOCK) && (((x) & 0x02) == 0x02) )
|
||||
#define NFC_CMD_RBLOCK 0xa0
|
||||
#define NFC_CMD_RBLOCK_ACK 0x10
|
||||
#define IS_RBLOCK(x) ( (((x) & 0xe0) == NFC_CMD_RBLOCK) && (((x) & 0x02) == 0x02) )
|
||||
#define NFC_CMD_SBLOCK 0xc0
|
||||
#define IS_SBLOCK(x) ( (((x) & 0xc0) == NFC_CMD_SBLOCK) && (((x) & 0x02) == 0x02) )
|
||||
|
||||
@ -61,6 +61,6 @@ typedef enum
|
||||
APP_FIDO,
|
||||
} APPLETS;
|
||||
|
||||
void WTX_timer_exec();
|
||||
void WTX_timer_exec(void);
|
||||
|
||||
#endif
|
||||
|
@ -8,7 +8,7 @@
|
||||
#define ELECTRODE_0 TSC_GROUP2_IO1
|
||||
#define ELECTRODE_1 TSC_GROUP2_IO2
|
||||
|
||||
void tsc_init()
|
||||
void tsc_init(void)
|
||||
{
|
||||
LL_GPIO_InitTypeDef GPIO_InitStruct;
|
||||
// Enable TSC clock
|
||||
@ -74,7 +74,7 @@ void tsc_set_electrode(uint32_t channel_ids)
|
||||
TSC->IOCCR = (channel_ids);
|
||||
}
|
||||
|
||||
void tsc_start_acq()
|
||||
void tsc_start_acq(void)
|
||||
{
|
||||
TSC->CR &= ~(TSC_CR_START);
|
||||
|
||||
@ -86,7 +86,7 @@ void tsc_start_acq()
|
||||
TSC->CR |= TSC_CR_START;
|
||||
}
|
||||
|
||||
void tsc_wait_on_acq()
|
||||
void tsc_wait_on_acq(void)
|
||||
{
|
||||
while ( ! (TSC->ISR & TSC_FLAG_EOA) )
|
||||
;
|
||||
@ -117,7 +117,7 @@ uint32_t tsc_read_button(uint32_t index)
|
||||
return tsc_read(1) < 45;
|
||||
}
|
||||
|
||||
int tsc_sensor_exists()
|
||||
int tsc_sensor_exists(void)
|
||||
{
|
||||
static uint8_t does = 0;
|
||||
if (does) return 1;
|
||||
|
@ -3,9 +3,9 @@
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
void tsc_init();
|
||||
void tsc_init(void);
|
||||
|
||||
int tsc_sensor_exists();
|
||||
int tsc_sensor_exists(void);
|
||||
|
||||
// Read button0 or button1
|
||||
// Returns 1 if pressed, 0 if not.
|
||||
|
Reference in New Issue
Block a user