Compare commits
45 Commits
key-backup
...
fido2_on_u
Author | SHA1 | Date | |
---|---|---|---|
9dfc3d49e8 | |||
3487895e2d | |||
6335f16874 | |||
82551c0b1c | |||
ff88660027 | |||
9ecfda02c5 | |||
9158453830 | |||
08658eb11e | |||
49d79fa5da | |||
69a7191860 | |||
a2fd507f45 | |||
a58658e35d | |||
bb2929b28f | |||
8e0eda8ed4 | |||
0ebe0ff502 | |||
7bcb7ea840 | |||
811a57f7ab | |||
5168afa16e | |||
a5e1dc2a0c | |||
a053bbc669 | |||
3621f2ed4f | |||
3c7bf5a264 | |||
e3ff136196 | |||
74181406fe | |||
987b04523d | |||
8023347c8e | |||
9dae7b2e7c | |||
cb13fb65de | |||
7fddd58704 | |||
3a1ea275cc | |||
22293f82f2 | |||
40c3c13b07 | |||
7042b0b656 | |||
ea803aab95 | |||
1100b159a9 | |||
9ddba5dfc3 | |||
35e52f4968 | |||
efddd2f3a8 | |||
17ceb7b9e8 | |||
188a34d1da | |||
9248c6462c | |||
118e129152 | |||
beb5a5892c | |||
d618081dd0 | |||
e4e0a3a84e |
@ -187,6 +187,16 @@
|
|||||||
"contributions": [
|
"contributions": [
|
||||||
"bug"
|
"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,
|
"contributorsPerLine": 7,
|
||||||
|
2
Makefile
2
Makefile
@ -39,7 +39,7 @@ INCLUDES += -I./crypto/cifra/src
|
|||||||
|
|
||||||
CFLAGS += $(INCLUDES)
|
CFLAGS += $(INCLUDES)
|
||||||
# for crypto/tiny-AES-c
|
# for crypto/tiny-AES-c
|
||||||
CFLAGS += -DAES256=1 -DAPP_CONFIG=\"app.h\"
|
CFLAGS += -DAES256=1 -DAPP_CONFIG=\"app.h\" -DSOLO_EXPERIMENTAL=1
|
||||||
|
|
||||||
name = main
|
name = main
|
||||||
|
|
||||||
|
@ -136,6 +136,7 @@ Thanks goes to these wonderful people ([emoji key](https://allcontributors.org/d
|
|||||||
<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://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="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/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>
|
</tr>
|
||||||
</table>
|
</table>
|
||||||
|
|
||||||
@ -169,7 +170,7 @@ You can buy Solo, Solo Tap, and Solo for Hackers at [solokeys.com](https://solok
|
|||||||
<br/>
|
<br/>
|
||||||
|
|
||||||
[](https://github.com/solokeys/solo/blob/master/LICENSE)
|
[](https://github.com/solokeys/solo/blob/master/LICENSE)
|
||||||
[](#contributors)
|
[](#contributors)
|
||||||
[](https://travis-ci.com/solokeys/solo)
|
[](https://travis-ci.com/solokeys/solo)
|
||||||
[](https://discourse.solokeys.com)
|
[](https://discourse.solokeys.com)
|
||||||
[](https://keybase.io/team/solokeys.public)
|
[](https://keybase.io/team/solokeys.public)
|
||||||
|
21
fido2/ctap.c
21
fido2/ctap.c
@ -698,7 +698,7 @@ int ctap_authenticate_credential(struct rpId * rp, CTAP_credentialDescriptor * d
|
|||||||
crypto_sha256_init();
|
crypto_sha256_init();
|
||||||
crypto_sha256_update(rp->id, rp->size);
|
crypto_sha256_update(rp->id, rp->size);
|
||||||
crypto_sha256_final(rpIdHash);
|
crypto_sha256_final(rpIdHash);
|
||||||
return u2f_authenticate_credential((struct u2f_key_handle *)&desc->credential.id, rpIdHash);
|
return u2f_authenticate_credential((struct u2f_key_handle *)&desc->credential.id, U2F_KEY_HANDLE_SIZE,rpIdHash);
|
||||||
break;
|
break;
|
||||||
case PUB_KEY_CRED_CUSTOM:
|
case PUB_KEY_CRED_CUSTOM:
|
||||||
return is_extension_request(getAssertionState.customCredId, getAssertionState.customCredIdSize);
|
return is_extension_request(getAssertionState.customCredId, getAssertionState.customCredIdSize);
|
||||||
@ -1761,11 +1761,28 @@ static void ctap_state_init()
|
|||||||
|
|
||||||
printf1(TAG_STOR, "Generated PIN SALT: ");
|
printf1(TAG_STOR, "Generated PIN SALT: ");
|
||||||
dump_hex1(TAG_STOR, STATE.PIN_SALT, sizeof STATE.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()
|
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();
|
crypto_ecc256_init();
|
||||||
|
|
||||||
authenticator_read_state(&STATE);
|
authenticator_read_state(&STATE);
|
||||||
|
@ -361,4 +361,6 @@ extern uint8_t KEY_AGREEMENT_PUB[64];
|
|||||||
|
|
||||||
void lock_device_permanently();
|
void lock_device_permanently();
|
||||||
|
|
||||||
|
void ctap_load_external_keys(uint8_t * keybytes);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
207
fido2/ctaphid.c
207
fido2/ctaphid.c
@ -539,11 +539,14 @@ extern void _check_ret(CborError ret, int line, const char * filename);
|
|||||||
#define check_hardcore(r) _check_ret(r,__LINE__, __FILE__);\
|
#define check_hardcore(r) _check_ret(r,__LINE__, __FILE__);\
|
||||||
if ((r) != CborNoError) exit(1);
|
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 ctaphid_handle_packet(uint8_t * pkt_raw)
|
||||||
{
|
{
|
||||||
uint8_t cmd;
|
uint8_t cmd = 0;
|
||||||
uint32_t cid;
|
uint32_t cid;
|
||||||
int len;
|
int len = 0;
|
||||||
#ifndef DISABLE_CTAPHID_CBOR
|
#ifndef DISABLE_CTAPHID_CBOR
|
||||||
int status;
|
int status;
|
||||||
#endif
|
#endif
|
||||||
@ -553,6 +556,10 @@ uint8_t ctaphid_handle_packet(uint8_t * pkt_raw)
|
|||||||
CTAP_RESPONSE ctap_resp;
|
CTAP_RESPONSE ctap_resp;
|
||||||
|
|
||||||
int bufstatus = ctaphid_buffer_packet(pkt_raw, &cmd, &cid, &len);
|
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)
|
if (bufstatus == HID_IGNORE)
|
||||||
{
|
{
|
||||||
@ -588,9 +595,6 @@ uint8_t ctaphid_handle_packet(uint8_t * pkt_raw)
|
|||||||
case CTAPHID_PING:
|
case CTAPHID_PING:
|
||||||
printf1(TAG_HID,"CTAPHID_PING\n");
|
printf1(TAG_HID,"CTAPHID_PING\n");
|
||||||
|
|
||||||
ctaphid_write_buffer_init(&wb);
|
|
||||||
wb.cid = cid;
|
|
||||||
wb.cmd = CTAPHID_PING;
|
|
||||||
wb.bcnt = len;
|
wb.bcnt = len;
|
||||||
timestamp();
|
timestamp();
|
||||||
ctaphid_write(&wb, ctap_buffer, len);
|
ctaphid_write(&wb, ctap_buffer, len);
|
||||||
@ -603,13 +607,9 @@ uint8_t ctaphid_handle_packet(uint8_t * pkt_raw)
|
|||||||
case CTAPHID_WINK:
|
case CTAPHID_WINK:
|
||||||
printf1(TAG_HID,"CTAPHID_WINK\n");
|
printf1(TAG_HID,"CTAPHID_WINK\n");
|
||||||
|
|
||||||
ctaphid_write_buffer_init(&wb);
|
|
||||||
|
|
||||||
device_wink();
|
device_wink();
|
||||||
|
|
||||||
wb.cid = cid;
|
|
||||||
wb.cmd = CTAPHID_WINK;
|
|
||||||
|
|
||||||
ctaphid_write(&wb,NULL,0);
|
ctaphid_write(&wb,NULL,0);
|
||||||
|
|
||||||
break;
|
break;
|
||||||
@ -634,9 +634,6 @@ uint8_t ctaphid_handle_packet(uint8_t * pkt_raw)
|
|||||||
ctap_response_init(&ctap_resp);
|
ctap_response_init(&ctap_resp);
|
||||||
status = ctap_request(ctap_buffer, len, &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);
|
wb.bcnt = (ctap_resp.length+1);
|
||||||
|
|
||||||
|
|
||||||
@ -667,9 +664,6 @@ uint8_t ctaphid_handle_packet(uint8_t * pkt_raw)
|
|||||||
ctap_response_init(&ctap_resp);
|
ctap_response_init(&ctap_resp);
|
||||||
u2f_request((struct u2f_request_apdu*)ctap_buffer, &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);
|
wb.bcnt = (ctap_resp.length);
|
||||||
|
|
||||||
ctaphid_write(&wb, ctap_resp.data, ctap_resp.length);
|
ctaphid_write(&wb, ctap_resp.data, ctap_resp.length);
|
||||||
@ -680,76 +674,14 @@ uint8_t ctaphid_handle_packet(uint8_t * pkt_raw)
|
|||||||
printf1(TAG_HID,"CTAPHID_CANCEL\n");
|
printf1(TAG_HID,"CTAPHID_CANCEL\n");
|
||||||
is_busy = 0;
|
is_busy = 0;
|
||||||
break;
|
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
|
|
||||||
|
|
||||||
case CTAPHID_GETVERSION:
|
|
||||||
printf1(TAG_HID,"CTAPHID_GETVERSION\n");
|
|
||||||
ctap_response_init(&ctap_resp);
|
|
||||||
ctaphid_write_buffer_init(&wb);
|
|
||||||
wb.cid = cid;
|
|
||||||
wb.cmd = CTAPHID_GETVERSION;
|
|
||||||
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);
|
|
||||||
is_busy = 0;
|
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
default:
|
||||||
printf2(TAG_ERR,"error, unimplemented HID cmd: %02x\r\n", buffer_cmd());
|
if (ctaphid_custom_command(len, &ctap_resp, &wb) != 0){
|
||||||
ctaphid_send_error(cid, CTAP1_ERR_INVALID_COMMAND);
|
is_busy = 0;
|
||||||
break;
|
}else{
|
||||||
|
printf2(TAG_ERR, "error, unimplemented HID cmd: %02x\r\n", buffer_cmd());
|
||||||
|
ctaphid_send_error(cid, CTAP1_ERR_INVALID_COMMAND);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
cid_del(cid);
|
cid_del(cid);
|
||||||
buffer_reset();
|
buffer_reset();
|
||||||
@ -759,3 +691,112 @@ uint8_t ctaphid_handle_packet(uint8_t * pkt_raw)
|
|||||||
else return 0;
|
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;
|
||||||
|
}
|
@ -29,6 +29,7 @@
|
|||||||
#define CTAPHID_ENTERSTBOOT (TYPE_INIT | 0x52)
|
#define CTAPHID_ENTERSTBOOT (TYPE_INIT | 0x52)
|
||||||
#define CTAPHID_GETRNG (TYPE_INIT | 0x60)
|
#define CTAPHID_GETRNG (TYPE_INIT | 0x60)
|
||||||
#define CTAPHID_GETVERSION (TYPE_INIT | 0x61)
|
#define CTAPHID_GETVERSION (TYPE_INIT | 0x61)
|
||||||
|
#define CTAPHID_LOADKEY (TYPE_INIT | 0x62)
|
||||||
// reserved for debug, not implemented except for HACKER and DEBUG_LEVEl > 0
|
// reserved for debug, not implemented except for HACKER and DEBUG_LEVEl > 0
|
||||||
#define CTAPHID_PROBE (TYPE_INIT | 0x70)
|
#define CTAPHID_PROBE (TYPE_INIT | 0x70)
|
||||||
|
|
||||||
|
@ -61,8 +61,8 @@ int ctap_user_presence_test(uint32_t delay);
|
|||||||
int ctap_generate_rng(uint8_t * dst, size_t num);
|
int ctap_generate_rng(uint8_t * dst, size_t num);
|
||||||
|
|
||||||
// Increment atomic counter and return it.
|
// Increment atomic counter and return it.
|
||||||
// Must support two counters, @sel selects counter0 or counter1.
|
// @param amount the amount to increase the counter by.
|
||||||
uint32_t ctap_atomic_count(int sel);
|
uint32_t ctap_atomic_count(uint32_t amount);
|
||||||
|
|
||||||
// Verify the user
|
// Verify the user
|
||||||
// return 1 if user is verified, 0 if not
|
// return 1 if user is verified, 0 if not
|
||||||
|
52
fido2/u2f.c
52
fido2/u2f.c
@ -26,6 +26,7 @@ static int16_t u2f_authenticate(struct u2f_authenticate_request * req, uint8_t c
|
|||||||
int8_t u2f_response_writeback(const uint8_t * buf, uint16_t len);
|
int8_t u2f_response_writeback(const uint8_t * buf, uint16_t len);
|
||||||
void u2f_reset_response();
|
void u2f_reset_response();
|
||||||
|
|
||||||
|
void make_auth_tag(uint8_t * rpIdHash, uint8_t * nonce, uint32_t count, uint8_t * tag);
|
||||||
|
|
||||||
static CTAP_RESPONSE * _u2f_resp = NULL;
|
static CTAP_RESPONSE * _u2f_resp = NULL;
|
||||||
|
|
||||||
@ -160,9 +161,9 @@ static void dump_signature_der(uint8_t * sig)
|
|||||||
len = ctap_encode_der_sig(sig, sigder);
|
len = ctap_encode_der_sig(sig, sigder);
|
||||||
u2f_response_writeback(sigder, len);
|
u2f_response_writeback(sigder, len);
|
||||||
}
|
}
|
||||||
static int8_t u2f_load_key(struct u2f_key_handle * kh, uint8_t * appid)
|
static int8_t u2f_load_key(struct u2f_key_handle * kh, uint8_t khl, uint8_t * appid)
|
||||||
{
|
{
|
||||||
crypto_ecc256_load_key((uint8_t*)kh, U2F_KEY_HANDLE_SIZE, NULL, 0);
|
crypto_ecc256_load_key((uint8_t*)kh, khl, NULL, 0);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -187,21 +188,41 @@ int8_t u2f_new_keypair(struct u2f_key_handle * kh, uint8_t * appid, uint8_t * pu
|
|||||||
|
|
||||||
|
|
||||||
// Return 1 if authenticate, 0 if not.
|
// Return 1 if authenticate, 0 if not.
|
||||||
int8_t u2f_authenticate_credential(struct u2f_key_handle * kh, uint8_t * appid)
|
int8_t u2f_authenticate_credential(struct u2f_key_handle * kh, uint8_t key_handle_len, uint8_t * appid)
|
||||||
{
|
{
|
||||||
|
printf1(TAG_U2F, "checked CRED SIZE %d. (FIDO2: %d)\n", key_handle_len, sizeof(CredentialId));
|
||||||
uint8_t tag[U2F_KEY_HANDLE_TAG_SIZE];
|
uint8_t tag[U2F_KEY_HANDLE_TAG_SIZE];
|
||||||
u2f_make_auth_tag(kh, appid, tag);
|
|
||||||
if (memcmp(kh->tag, tag, U2F_KEY_HANDLE_TAG_SIZE) == 0)
|
if (key_handle_len == sizeof(CredentialId))
|
||||||
{
|
{
|
||||||
return 1;
|
printf1(TAG_U2F, "FIDO2 key handle detected.\n");
|
||||||
}
|
CredentialId * cred = (CredentialId *) kh;
|
||||||
else
|
// FIDO2 credential.
|
||||||
|
|
||||||
|
if (memcmp(cred->rpIdHash, appid, 32) != 0)
|
||||||
|
{
|
||||||
|
printf1(TAG_U2F, "APPID does not match rpIdHash.\n");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
make_auth_tag(appid, cred->nonce, cred->count, tag);
|
||||||
|
|
||||||
|
if (memcmp(cred->tag, tag, CREDENTIAL_TAG_SIZE) == 0){
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
}else if (key_handle_len == U2F_KEY_HANDLE_SIZE)
|
||||||
{
|
{
|
||||||
printf1(TAG_U2F, "key handle + appid not authentic\n");
|
u2f_make_auth_tag(kh, appid, tag);
|
||||||
printf1(TAG_U2F, "calc tag: \n"); dump_hex1(TAG_U2F,tag, U2F_KEY_HANDLE_TAG_SIZE);
|
if (memcmp(kh->tag, tag, U2F_KEY_HANDLE_TAG_SIZE) == 0)
|
||||||
printf1(TAG_U2F, "inp tag: \n"); dump_hex1(TAG_U2F,kh->tag, U2F_KEY_HANDLE_TAG_SIZE);
|
{
|
||||||
return 0;
|
return 1;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
printf1(TAG_U2F, "key handle + appid not authentic\n");
|
||||||
|
printf1(TAG_U2F, "calc tag: \n"); dump_hex1(TAG_U2F,tag, U2F_KEY_HANDLE_TAG_SIZE);
|
||||||
|
printf1(TAG_U2F, "inp tag: \n"); dump_hex1(TAG_U2F,kh->tag, U2F_KEY_HANDLE_TAG_SIZE);
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -216,7 +237,7 @@ static int16_t u2f_authenticate(struct u2f_authenticate_request * req, uint8_t c
|
|||||||
if (control == U2F_AUTHENTICATE_CHECK)
|
if (control == U2F_AUTHENTICATE_CHECK)
|
||||||
{
|
{
|
||||||
printf1(TAG_U2F, "CHECK-ONLY\r\n");
|
printf1(TAG_U2F, "CHECK-ONLY\r\n");
|
||||||
if (u2f_authenticate_credential(&req->kh, req->app))
|
if (u2f_authenticate_credential(&req->kh, req->khl, req->app))
|
||||||
{
|
{
|
||||||
return U2F_SW_CONDITIONS_NOT_SATISFIED;
|
return U2F_SW_CONDITIONS_NOT_SATISFIED;
|
||||||
}
|
}
|
||||||
@ -227,9 +248,8 @@ static int16_t u2f_authenticate(struct u2f_authenticate_request * req, uint8_t c
|
|||||||
}
|
}
|
||||||
if (
|
if (
|
||||||
(control != U2F_AUTHENTICATE_SIGN && control != U2F_AUTHENTICATE_SIGN_NO_USER) ||
|
(control != U2F_AUTHENTICATE_SIGN && control != U2F_AUTHENTICATE_SIGN_NO_USER) ||
|
||||||
req->khl != U2F_KEY_HANDLE_SIZE ||
|
(!u2f_authenticate_credential(&req->kh, req->khl, req->app)) || // Order of checks is important
|
||||||
(!u2f_authenticate_credential(&req->kh, req->app)) || // Order of checks is important
|
u2f_load_key(&req->kh, req->khl, req->app) != 0
|
||||||
u2f_load_key(&req->kh, req->app) != 0
|
|
||||||
|
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
|
@ -103,7 +103,7 @@ void u2f_request(struct u2f_request_apdu* req, CTAP_RESPONSE * resp);
|
|||||||
// @len data length
|
// @len data length
|
||||||
void u2f_request_nfc(uint8_t * header, uint8_t * data, int datalen, CTAP_RESPONSE * resp);
|
void u2f_request_nfc(uint8_t * header, uint8_t * data, int datalen, CTAP_RESPONSE * resp);
|
||||||
|
|
||||||
int8_t u2f_authenticate_credential(struct u2f_key_handle * kh, uint8_t * appid);
|
int8_t u2f_authenticate_credential(struct u2f_key_handle * kh, uint8_t key_handle_len, uint8_t * appid);
|
||||||
|
|
||||||
int8_t u2f_response_writeback(const uint8_t * buf, uint16_t len);
|
int8_t u2f_response_writeback(const uint8_t * buf, uint16_t len);
|
||||||
void u2f_reset_response();
|
void u2f_reset_response();
|
||||||
|
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)
|
#define SOLO_VERSION __STR(SOLO_VERSION_MAJ) "." __STR(SOLO_VERSION_MIN) "." __STR(SOLO_VERSION_PATCH)
|
||||||
#endif
|
#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
|
#endif
|
||||||
|
18
pc/device.c
18
pc/device.c
@ -108,6 +108,7 @@ int udp_recv(int fd, uint8_t * buf, int size)
|
|||||||
perror( "recvfrom failed" );
|
perror( "recvfrom failed" );
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
|
printf1(TAG_DUMP, ">>"); dump_hex1(TAG_DUMP, buf, length);
|
||||||
return length;
|
return length;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -124,6 +125,8 @@ void udp_send(int fd, uint8_t * buf, int size)
|
|||||||
perror( "sendto failed" );
|
perror( "sendto failed" );
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
printf1(TAG_DUMP, "<<"); dump_hex1(TAG_DUMP, buf, size);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -313,20 +316,11 @@ int ctap_user_verification(uint8_t arg)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
uint32_t ctap_atomic_count(int sel)
|
uint32_t ctap_atomic_count(uint32_t amount)
|
||||||
{
|
{
|
||||||
static uint32_t counter1 = 25;
|
static uint32_t counter1 = 25;
|
||||||
/*return 713;*/
|
counter1 += (amount + 1);
|
||||||
if (sel == 0)
|
return counter1;
|
||||||
{
|
|
||||||
printf1(TAG_RED,"counter1: %d\n", counter1);
|
|
||||||
return counter1++;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
printf2(TAG_ERR,"counter2 not imple\n");
|
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int ctap_generate_rng(uint8_t * dst, size_t num)
|
int ctap_generate_rng(uint8_t * dst, size_t num)
|
||||||
|
@ -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 -e all --readunprotect
|
||||||
STM32_Programmer_CLI -c port=usb1 -halt -rdu -d all.hex
|
STM32_Programmer_CLI -c port=usb1 -halt -rdu -d all.hex
|
||||||
|
|
||||||
flashboot: solo.hex bootloader.hex
|
flashboot: bootloader.hex
|
||||||
$(VENV) $(merge_hex) solo.hex bootloader.hex all.hex
|
|
||||||
STM32_Programmer_CLI -c port=SWD -halt -e all --readunprotect
|
STM32_Programmer_CLI -c port=SWD -halt -e all --readunprotect
|
||||||
STM32_Programmer_CLI -c port=SWD -halt -d bootloader.hex -rst
|
STM32_Programmer_CLI -c port=SWD -halt -d bootloader.hex -rst
|
||||||
|
|
||||||
|
@ -19,6 +19,12 @@
|
|||||||
#include "ctap_errors.h"
|
#include "ctap_errors.h"
|
||||||
#include "log.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;
|
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()
|
static void disable_bootloader()
|
||||||
{
|
{
|
||||||
// Clear last 4 bytes of the last application page-1, which is 108th
|
// 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);
|
uint32_t * auth = (uint32_t *)(AUTH_WORD_ADDR+4);
|
||||||
return *auth == 0;
|
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
|
* Execute bootloader commands
|
||||||
@ -125,10 +161,7 @@ int bootloader_bridge(int klen, uint8_t * keyh)
|
|||||||
return CTAP1_ERR_INVALID_LENGTH;
|
return CTAP1_ERR_INVALID_LENGTH;
|
||||||
}
|
}
|
||||||
#ifndef SOLO_HACKER
|
#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"
|
extern uint8_t *pubkey_boot;
|
||||||
"\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";
|
|
||||||
|
|
||||||
const struct uECC_Curve_t * curve = NULL;
|
const struct uECC_Curve_t * curve = NULL;
|
||||||
#endif
|
#endif
|
||||||
@ -165,12 +198,11 @@ int bootloader_bridge(int klen, uint8_t * keyh)
|
|||||||
}
|
}
|
||||||
// Do the actual write
|
// Do the actual write
|
||||||
flash_write((uint32_t)ptr,req->payload, len);
|
flash_write((uint32_t)ptr,req->payload, len);
|
||||||
|
last_written_app_address = (uint8_t *)ptr + len - 8 + 4;
|
||||||
|
|
||||||
break;
|
break;
|
||||||
case BootDone:
|
case BootDone:
|
||||||
// Writing to flash finished. Request code validation.
|
// Writing to flash finished. Request code validation.
|
||||||
printf1(TAG_BOOT, "BootDone: ");
|
printf1(TAG_BOOT, "BootDone: \r\n");
|
||||||
#ifndef SOLO_HACKER
|
#ifndef SOLO_HACKER
|
||||||
if (len != 64)
|
if (len != 64)
|
||||||
{
|
{
|
||||||
@ -185,17 +217,23 @@ int bootloader_bridge(int klen, uint8_t * keyh)
|
|||||||
crypto_sha256_final(hash);
|
crypto_sha256_final(hash);
|
||||||
curve = uECC_secp256r1();
|
curve = uECC_secp256r1();
|
||||||
// Verify incoming signature made over the SHA256 hash
|
// Verify incoming signature made over the SHA256 hash
|
||||||
if (! uECC_verify(pubkey,
|
if (
|
||||||
hash,
|
!uECC_verify(pubkey_boot, hash, 32, req->payload, curve)
|
||||||
32,
|
)
|
||||||
req->payload,
|
|
||||||
curve))
|
|
||||||
{
|
{
|
||||||
|
printf1(TAG_BOOT, "Signature invalid\r\n");
|
||||||
return CTAP2_ERR_OPERATION_DENIED;
|
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
|
#endif
|
||||||
// Set the application validated, and mark for reboot.
|
// Set the application validated, and mark for reboot.
|
||||||
authorize_application();
|
authorize_application();
|
||||||
|
|
||||||
REBOOT_FLAG = 1;
|
REBOOT_FLAG = 1;
|
||||||
break;
|
break;
|
||||||
case BootCheck:
|
case BootCheck:
|
||||||
@ -218,6 +256,7 @@ int bootloader_bridge(int klen, uint8_t * keyh)
|
|||||||
break;
|
break;
|
||||||
case BootReboot:
|
case BootReboot:
|
||||||
printf1(TAG_BOOT, "BootReboot.\r\n");
|
printf1(TAG_BOOT, "BootReboot.\r\n");
|
||||||
|
printf1(TAG_BOOT, "Application authorized: %d.\r\n", is_authorized_to_boot());
|
||||||
REBOOT_FLAG = 1;
|
REBOOT_FLAG = 1;
|
||||||
break;
|
break;
|
||||||
case BootDisable:
|
case BootDisable:
|
||||||
@ -277,3 +316,10 @@ void bootloader_heartbeat()
|
|||||||
|
|
||||||
led_rgb(((val * g)<<8) | ((val*r) << 16) | (val*b));
|
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");
|
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)
|
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,7 @@ SRC += $(DRIVER_LIBS) $(USB_LIB)
|
|||||||
SRC += ../../fido2/apdu.c ../../fido2/util.c ../../fido2/u2f.c ../../fido2/test_power.c
|
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/stubs.c ../../fido2/log.c ../../fido2/ctaphid.c ../../fido2/ctap.c
|
||||||
SRC += ../../fido2/ctap_parse.c ../../fido2/main.c
|
SRC += ../../fido2/ctap_parse.c ../../fido2/main.c
|
||||||
|
SRC += ../../fido2/version.c
|
||||||
SRC += ../../fido2/data_migration.c
|
SRC += ../../fido2/data_migration.c
|
||||||
SRC += ../../fido2/extensions/extensions.c ../../fido2/extensions/solo.c
|
SRC += ../../fido2/extensions/extensions.c ../../fido2/extensions/solo.c
|
||||||
SRC += ../../fido2/extensions/wallet.c
|
SRC += ../../fido2/extensions/wallet.c
|
||||||
@ -70,6 +71,7 @@ all: $(TARGET).elf
|
|||||||
|
|
||||||
%.elf: $(OBJ)
|
%.elf: $(OBJ)
|
||||||
$(CC) $^ $(HW) $(LDFLAGS) -o $@
|
$(CC) $^ $(HW) $(LDFLAGS) -o $@
|
||||||
|
@echo "Built version: $(VERSION_FLAGS)"
|
||||||
|
|
||||||
%.hex: %.elf
|
%.hex: %.elf
|
||||||
$(SZ) $^
|
$(SZ) $^
|
||||||
|
@ -2,6 +2,7 @@ include build/common.mk
|
|||||||
|
|
||||||
# ST related
|
# ST related
|
||||||
SRC = bootloader/main.c bootloader/bootloader.c
|
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/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/fifo.c src/crypto.c src/attestation.c src/sense.c
|
||||||
SRC += src/startup_stm32l432xx.s src/system_stm32l4xx.c
|
SRC += src/startup_stm32l432xx.s src/system_stm32l4xx.c
|
||||||
@ -65,6 +66,7 @@ all: $(TARGET).elf
|
|||||||
|
|
||||||
%.elf: $(OBJ)
|
%.elf: $(OBJ)
|
||||||
$(CC) $^ $(HW) $(LDFLAGS) -o $@
|
$(CC) $^ $(HW) $(LDFLAGS) -o $@
|
||||||
|
arm-none-eabi-size $@
|
||||||
|
|
||||||
%.hex: %.elf
|
%.hex: %.elf
|
||||||
$(CP) -O ihex $^ $(TARGET).hex
|
$(CP) -O ihex $^ $(TARGET).hex
|
||||||
|
@ -12,9 +12,17 @@ _estack = 0x2000c000;
|
|||||||
|
|
||||||
_MIN_STACK_SIZE = 0x400;
|
_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
|
MEMORY
|
||||||
{
|
{
|
||||||
flash (rx) : ORIGIN = 0x08000000, LENGTH = 20K
|
flash (rx) : ORIGIN = 0x08000000, LENGTH = 20K
|
||||||
|
flash_cfg (rx) : ORIGIN = 0x08000000 + 216*1024+8, LENGTH = 2K-8
|
||||||
ram (xrw) : ORIGIN = 0x20000000, LENGTH = 48K
|
ram (xrw) : ORIGIN = 0x20000000, LENGTH = 48K
|
||||||
sram2 (rw) : ORIGIN = 0x10000000, LENGTH = 16K
|
sram2 (rw) : ORIGIN = 0x10000000, LENGTH = 16K
|
||||||
}
|
}
|
||||||
@ -39,6 +47,11 @@ SECTIONS
|
|||||||
_etext = .;
|
_etext = .;
|
||||||
} >flash
|
} >flash
|
||||||
|
|
||||||
|
.flag2 bootloader_configuration :
|
||||||
|
{
|
||||||
|
KEEP(*(.flag2)) ;
|
||||||
|
} > flash_cfg
|
||||||
|
|
||||||
_sidata = LOADADDR(.data);
|
_sidata = LOADADDR(.data);
|
||||||
|
|
||||||
.data :
|
.data :
|
||||||
|
@ -12,9 +12,17 @@ _estack = 0x2000c000;
|
|||||||
|
|
||||||
_MIN_STACK_SIZE = 0x400;
|
_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
|
MEMORY
|
||||||
{
|
{
|
||||||
flash (rx) : ORIGIN = 0x08000000, LENGTH = 32K
|
flash (rx) : ORIGIN = 0x08000000, LENGTH = 32K
|
||||||
|
flash_cfg (rx) : ORIGIN = 0x08000000 + 216*1024+8, LENGTH = 2K-8
|
||||||
ram (xrw) : ORIGIN = 0x20000000, LENGTH = 48K
|
ram (xrw) : ORIGIN = 0x20000000, LENGTH = 48K
|
||||||
sram2 (rw) : ORIGIN = 0x10000000, LENGTH = 16K
|
sram2 (rw) : ORIGIN = 0x10000000, LENGTH = 16K
|
||||||
}
|
}
|
||||||
@ -39,6 +47,11 @@ SECTIONS
|
|||||||
_etext = .;
|
_etext = .;
|
||||||
} >flash
|
} >flash
|
||||||
|
|
||||||
|
.flag2 bootloader_configuration :
|
||||||
|
{
|
||||||
|
KEEP(*(.flag2)) ;
|
||||||
|
} > flash_cfg
|
||||||
|
|
||||||
_sidata = LOADADDR(.data);
|
_sidata = LOADADDR(.data);
|
||||||
|
|
||||||
.data :
|
.data :
|
||||||
|
@ -13,14 +13,21 @@ _estack = 0x2000c000;
|
|||||||
_MIN_STACK_SIZE = 0x400;
|
_MIN_STACK_SIZE = 0x400;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Memory layout of device:
|
len | 20 KB/10p| 196KB-8-8/98p | 2kB/1p | 38 KB/19p |
|
||||||
20 KB 198KB-8 38 KB
|
pos | 0->20 KB | 20->216KB-8-8 | 216kB -> 218 kB | 218->256 KB |
|
||||||
| bootloader | application | secrets/data |
|
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
|
MEMORY
|
||||||
{
|
{
|
||||||
flash (rx) : ORIGIN = 0x08005000, LENGTH = 198K - 8
|
flash (rx) : ORIGIN = 0x08000000 + 20K, LENGTH = 216K - 20K - 8
|
||||||
ram (xrw) : ORIGIN = 0x20000000, LENGTH = 48K
|
ram (xrw) : ORIGIN = 0x20000000, LENGTH = 48K
|
||||||
sram2 (rw) : ORIGIN = 0x10000000, LENGTH = 16K
|
sram2 (rw) : ORIGIN = 0x10000000, LENGTH = 16K
|
||||||
}
|
}
|
||||||
@ -56,6 +63,12 @@ SECTIONS
|
|||||||
_edata = .;
|
_edata = .;
|
||||||
} >ram AT> flash
|
} >ram AT> flash
|
||||||
|
|
||||||
|
.flag :
|
||||||
|
{
|
||||||
|
. = ALIGN(8);
|
||||||
|
KEEP(*(.flag)) ;
|
||||||
|
} > flash
|
||||||
|
|
||||||
.bss :
|
.bss :
|
||||||
{
|
{
|
||||||
. = ALIGN(4);
|
. = ALIGN(4);
|
||||||
|
@ -12,9 +12,22 @@ _estack = 0x2000c000;
|
|||||||
|
|
||||||
_MIN_STACK_SIZE = 0x400;
|
_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
|
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
|
ram (xrw) : ORIGIN = 0x20000000, LENGTH = 48K
|
||||||
sram2 (rw) : ORIGIN = 0x10000000, LENGTH = 16K
|
sram2 (rw) : ORIGIN = 0x10000000, LENGTH = 16K
|
||||||
}
|
}
|
||||||
@ -50,6 +63,12 @@ SECTIONS
|
|||||||
_edata = .;
|
_edata = .;
|
||||||
} >ram AT> flash
|
} >ram AT> flash
|
||||||
|
|
||||||
|
.flag :
|
||||||
|
{
|
||||||
|
. = ALIGN(8);
|
||||||
|
KEEP(*(.flag)) ;
|
||||||
|
} > flash
|
||||||
|
|
||||||
.bss :
|
.bss :
|
||||||
{
|
{
|
||||||
. = ALIGN(4);
|
. = ALIGN(4);
|
||||||
|
@ -8,21 +8,25 @@
|
|||||||
#include "device.h"
|
#include "device.h"
|
||||||
#include "nfc.h"
|
#include "nfc.h"
|
||||||
|
|
||||||
static void flush_rx()
|
static void flush_rx(void)
|
||||||
{
|
{
|
||||||
while(LL_SPI_IsActiveFlag_RXNE(SPI1) != 0)
|
while(LL_SPI_IsActiveFlag_RXNE(SPI1) != 0)
|
||||||
{
|
{
|
||||||
LL_SPI_ReceiveData8(SPI1);
|
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_IsActiveFlag_BSY(SPI1) == 1)
|
||||||
// ;
|
// ;
|
||||||
while(LL_SPI_GetTxFIFOLevel(SPI1) != LL_SPI_TX_FIFO_EMPTY)
|
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)
|
while(LL_SPI_IsActiveFlag_RXNE(SPI1) == 0)
|
||||||
;
|
;
|
||||||
@ -270,7 +274,7 @@ void ams_print_int1(uint8_t int0)
|
|||||||
#endif
|
#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_SetPinMode(SOLO_AMS_CS_PORT,SOLO_AMS_CS_PIN,LL_GPIO_MODE_OUTPUT);
|
||||||
LL_GPIO_SetOutputPin(SOLO_AMS_CS_PORT,SOLO_AMS_CS_PIN);
|
LL_GPIO_SetOutputPin(SOLO_AMS_CS_PORT,SOLO_AMS_CS_PIN);
|
||||||
@ -292,7 +296,7 @@ int ams_init()
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ams_configure()
|
void ams_configure(void)
|
||||||
{
|
{
|
||||||
// Should not be used during passive operation.
|
// Should not be used during passive operation.
|
||||||
uint8_t block[4];
|
uint8_t block[4];
|
||||||
|
@ -39,8 +39,8 @@ typedef union
|
|||||||
#define SELECT() LL_GPIO_ResetOutputPin(SOLO_AMS_CS_PORT,SOLO_AMS_CS_PIN)
|
#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)
|
#define UNSELECT() LL_GPIO_SetOutputPin(SOLO_AMS_CS_PORT,SOLO_AMS_CS_PIN)
|
||||||
|
|
||||||
int ams_init();
|
int ams_init(void);
|
||||||
void ams_configure();
|
void ams_configure(void);
|
||||||
|
|
||||||
void ams_read_buffer(uint8_t * data, int len);
|
void ams_read_buffer(uint8_t * data, int len);
|
||||||
void ams_write_buffer(uint8_t * data, int len);
|
void ams_write_buffer(uint8_t * data, int len);
|
||||||
|
@ -61,12 +61,13 @@ static uint8_t master_secret[64];
|
|||||||
static uint8_t transport_secret[32];
|
static uint8_t transport_secret[32];
|
||||||
|
|
||||||
|
|
||||||
void crypto_sha256_init()
|
void crypto_sha256_init(void)
|
||||||
{
|
{
|
||||||
sha256_init(&sha256_ctx);
|
sha256_init(&sha256_ctx);
|
||||||
}
|
}
|
||||||
|
|
||||||
void crypto_sha512_init() {
|
void crypto_sha512_init(void)
|
||||||
|
{
|
||||||
cf_sha512_init(&sha512_ctx);
|
cf_sha512_init(&sha512_ctx);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -79,7 +80,7 @@ void crypto_load_master_secret(uint8_t * key)
|
|||||||
memmove(transport_secret, key+64, 32);
|
memmove(transport_secret, key+64, 32);
|
||||||
}
|
}
|
||||||
|
|
||||||
void crypto_reset_master_secret()
|
void crypto_reset_master_secret(void)
|
||||||
{
|
{
|
||||||
memset(master_secret, 0, 64);
|
memset(master_secret, 0, 64);
|
||||||
memset(transport_secret, 0, 32);
|
memset(transport_secret, 0, 32);
|
||||||
@ -107,7 +108,8 @@ void crypto_sha256_final(uint8_t * hash)
|
|||||||
sha256_final(&sha256_ctx, 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
|
// NB: there is also cf_sha512_digest
|
||||||
cf_sha512_digest_final(&sha512_ctx, hash);
|
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);
|
uECC_set_rng((uECC_RNG_Function)ctap_generate_rng);
|
||||||
_es256_curve = uECC_secp256r1();
|
_es256_curve = uECC_secp256r1();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void crypto_ecc256_load_attestation_key()
|
void crypto_ecc256_load_attestation_key(void)
|
||||||
{
|
{
|
||||||
static uint8_t _key [32];
|
static uint8_t _key [32];
|
||||||
memmove(_key, (uint8_t*)ATTESTATION_KEY_ADDR, 32);
|
memmove(_key, (uint8_t*)ATTESTATION_KEY_ADDR, 32);
|
||||||
|
@ -34,7 +34,7 @@
|
|||||||
#define LOW_FREQUENCY 1
|
#define LOW_FREQUENCY 1
|
||||||
#define HIGH_FREQUENCY 0
|
#define HIGH_FREQUENCY 0
|
||||||
|
|
||||||
void wait_for_usb_tether();
|
void wait_for_usb_tether(void);
|
||||||
|
|
||||||
|
|
||||||
uint32_t __90_ms = 0;
|
uint32_t __90_ms = 0;
|
||||||
@ -48,12 +48,12 @@ static bool isLowFreq = 0;
|
|||||||
static bool _up_disabled = false;
|
static bool _up_disabled = false;
|
||||||
|
|
||||||
// #define IS_BUTTON_PRESSED() (0 == (LL_GPIO_ReadInputPort(SOLO_BUTTON_PORT) & SOLO_BUTTON_PIN))
|
// #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));
|
return (0 == (LL_GPIO_ReadInputPort(SOLO_BUTTON_PORT) & SOLO_BUTTON_PIN));
|
||||||
}
|
}
|
||||||
|
|
||||||
static int is_touch_button_pressed()
|
static int is_touch_button_pressed(void)
|
||||||
{
|
{
|
||||||
int is_pressed = (tsc_read_button(0) || tsc_read_button(1));
|
int is_pressed = (tsc_read_button(0) || tsc_read_button(1));
|
||||||
#ifndef IS_BOOTLOADER
|
#ifndef IS_BOOTLOADER
|
||||||
@ -69,7 +69,7 @@ static int is_touch_button_pressed()
|
|||||||
|
|
||||||
int (*IS_BUTTON_PRESSED)() = is_physical_button_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;
|
static uint8_t last_touch = 0;
|
||||||
uint8_t current_touch = 0;
|
uint8_t current_touch = 0;
|
||||||
@ -92,12 +92,13 @@ static void edge_detect_touch_button()
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void device_disable_up(bool disable) {
|
void device_disable_up(bool disable)
|
||||||
|
{
|
||||||
_up_disabled = disable;
|
_up_disabled = disable;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Timer6 overflow handler. happens every ~90ms.
|
// 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
|
// timer is only 16 bits, so roll it over here
|
||||||
TIM6->SR = 0;
|
TIM6->SR = 0;
|
||||||
@ -142,7 +143,7 @@ void USB_IRQHandler(void)
|
|||||||
HAL_PCD_IRQHandler(&hpcd);
|
HAL_PCD_IRQHandler(&hpcd);
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t millis()
|
uint32_t millis(void)
|
||||||
{
|
{
|
||||||
return (((uint32_t)TIM6->CNT) + (__90_ms * 90));
|
return (((uint32_t)TIM6->CNT) + (__90_ms * 90));
|
||||||
}
|
}
|
||||||
@ -160,7 +161,7 @@ void device_set_status(uint32_t status)
|
|||||||
__device_status = status;
|
__device_status = status;
|
||||||
}
|
}
|
||||||
|
|
||||||
int device_is_button_pressed()
|
int device_is_button_pressed(void)
|
||||||
{
|
{
|
||||||
return IS_BUTTON_PRESSED();
|
return IS_BUTTON_PRESSED();
|
||||||
}
|
}
|
||||||
@ -171,12 +172,13 @@ void delay(uint32_t ms)
|
|||||||
while ((millis() - time) < ms)
|
while ((millis() - time) < ms)
|
||||||
;
|
;
|
||||||
}
|
}
|
||||||
void device_reboot()
|
|
||||||
|
void device_reboot(void)
|
||||||
{
|
{
|
||||||
NVIC_SystemReset();
|
NVIC_SystemReset();
|
||||||
}
|
}
|
||||||
|
|
||||||
void device_init_button()
|
void device_init_button(void)
|
||||||
{
|
{
|
||||||
if (tsc_sensor_exists())
|
if (tsc_sensor_exists())
|
||||||
{
|
{
|
||||||
@ -226,12 +228,12 @@ void device_init(int argc, char *argv[])
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int device_is_nfc()
|
int device_is_nfc(void)
|
||||||
{
|
{
|
||||||
return _NFC_status;
|
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) )
|
while (USBD_OK != CDC_Transmit_FS((uint8_t*)"tethered\r\n", 10) )
|
||||||
;
|
;
|
||||||
@ -242,7 +244,7 @@ void wait_for_usb_tether()
|
|||||||
;
|
;
|
||||||
}
|
}
|
||||||
|
|
||||||
void usbhid_init()
|
void usbhid_init(void)
|
||||||
{
|
{
|
||||||
if (!isLowFreq)
|
if (!isLowFreq)
|
||||||
{
|
{
|
||||||
@ -292,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)
|
||||||
{
|
{
|
||||||
|
|
||||||
}
|
}
|
||||||
@ -307,13 +309,14 @@ static uint32_t winkt1 = 0;
|
|||||||
#ifdef LED_WINK_VALUE
|
#ifdef LED_WINK_VALUE
|
||||||
static uint32_t winkt2 = 0;
|
static uint32_t winkt2 = 0;
|
||||||
#endif
|
#endif
|
||||||
void device_wink()
|
|
||||||
|
void device_wink(void)
|
||||||
{
|
{
|
||||||
wink_time = 10;
|
wink_time = 10;
|
||||||
winkt1 = 0;
|
winkt1 = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void heartbeat()
|
void heartbeat(void)
|
||||||
{
|
{
|
||||||
static int state = 0;
|
static int state = 0;
|
||||||
static uint32_t val = (LED_MAX_SCALER - LED_MIN_SCALER)/2;
|
static uint32_t val = (LED_MAX_SCALER - LED_MIN_SCALER)/2;
|
||||||
@ -382,7 +385,7 @@ void authenticator_read_backup_state(AuthenticatorState * a)
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Return 1 yes backup is init'd, else 0
|
// Return 1 yes backup is init'd, else 0
|
||||||
int authenticator_is_backup_initialized()
|
int authenticator_is_backup_initialized(void)
|
||||||
{
|
{
|
||||||
uint8_t header[16];
|
uint8_t header[16];
|
||||||
uint32_t * ptr = (uint32_t *)flash_addr(STATE2_PAGE);
|
uint32_t * ptr = (uint32_t *)flash_addr(STATE2_PAGE);
|
||||||
@ -407,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;
|
int offset = 0;
|
||||||
uint32_t * ptr = (uint32_t *)flash_addr(COUNTER1_PAGE);
|
uint32_t * ptr = (uint32_t *)flash_addr(COUNTER1_PAGE);
|
||||||
@ -422,10 +426,12 @@ uint32_t ctap_atomic_count(int sel)
|
|||||||
|
|
||||||
uint32_t lastc = 0;
|
uint32_t lastc = 0;
|
||||||
|
|
||||||
if (sel != 0)
|
if (amount == 0)
|
||||||
{
|
{
|
||||||
printf2(TAG_ERR,"counter2 not imple\n");
|
// Use a random count [1-16].
|
||||||
exit(1);
|
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
|
for (offset = 0; offset < PAGE_SIZE/4; offset += 2) // wear-level the flash
|
||||||
@ -458,7 +464,7 @@ uint32_t ctap_atomic_count(int sel)
|
|||||||
return lastc;
|
return lastc;
|
||||||
}
|
}
|
||||||
|
|
||||||
lastc++;
|
lastc += amount;
|
||||||
|
|
||||||
if (lastc/256 > erases)
|
if (lastc/256 > erases)
|
||||||
{
|
{
|
||||||
@ -496,10 +502,10 @@ uint32_t ctap_atomic_count(int sel)
|
|||||||
|
|
||||||
return lastc;
|
return lastc;
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
void device_manage(void)
|
||||||
void device_manage()
|
|
||||||
{
|
{
|
||||||
#if NON_BLOCK_PRINTING
|
#if NON_BLOCK_PRINTING
|
||||||
int i = 10;
|
int i = 10;
|
||||||
@ -525,7 +531,7 @@ void device_manage()
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
static int handle_packets()
|
static int handle_packets(void)
|
||||||
{
|
{
|
||||||
static uint8_t hidmsg[HID_PACKET_SIZE];
|
static uint8_t hidmsg[HID_PACKET_SIZE];
|
||||||
memset(hidmsg,0, sizeof(hidmsg));
|
memset(hidmsg,0, sizeof(hidmsg));
|
||||||
@ -561,6 +567,7 @@ static int wait_for_button_activate(uint32_t wait)
|
|||||||
} while (!IS_BUTTON_PRESSED());
|
} while (!IS_BUTTON_PRESSED());
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int wait_for_button_release(uint32_t wait)
|
static int wait_for_button_release(uint32_t wait)
|
||||||
{
|
{
|
||||||
int ret;
|
int ret;
|
||||||
@ -654,7 +661,7 @@ int ctap_user_verification(uint8_t arg)
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ctap_reset_rk()
|
void ctap_reset_rk(void)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
printf1(TAG_GREEN, "resetting RK \r\n");
|
printf1(TAG_GREEN, "resetting RK \r\n");
|
||||||
@ -664,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));
|
return RK_NUM_PAGES * (PAGE_SIZE / sizeof(CTAP_residentKey));
|
||||||
}
|
}
|
||||||
@ -726,7 +733,7 @@ void ctap_overwrite_rk(int index,CTAP_residentKey * rk)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void boot_st_bootloader()
|
void boot_st_bootloader(void)
|
||||||
{
|
{
|
||||||
__disable_irq();
|
__disable_irq();
|
||||||
|
|
||||||
@ -738,7 +745,7 @@ void boot_st_bootloader()
|
|||||||
;
|
;
|
||||||
}
|
}
|
||||||
|
|
||||||
void boot_solo_bootloader()
|
void boot_solo_bootloader(void)
|
||||||
{
|
{
|
||||||
LL_IWDG_Enable(IWDG);
|
LL_IWDG_Enable(IWDG);
|
||||||
|
|
||||||
|
@ -14,12 +14,12 @@
|
|||||||
#include "log.h"
|
#include "log.h"
|
||||||
#include "device.h"
|
#include "device.h"
|
||||||
|
|
||||||
static void flash_lock()
|
static void flash_lock(void)
|
||||||
{
|
{
|
||||||
FLASH->CR |= (1U<<31);
|
FLASH->CR |= (1U<<31);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void flash_unlock()
|
static void flash_unlock(void)
|
||||||
{
|
{
|
||||||
if (FLASH->CR & FLASH_CR_LOCK)
|
if (FLASH->CR & FLASH_CR_LOCK)
|
||||||
{
|
{
|
||||||
|
@ -699,7 +699,7 @@ void SystemClock_Config_LF20(void)
|
|||||||
SET_BIT(RCC->APB1ENR1, RCC_APB1ENR1_PWREN);
|
SET_BIT(RCC->APB1ENR1, RCC_APB1ENR1_PWREN);
|
||||||
}
|
}
|
||||||
|
|
||||||
void init_usb()
|
void init_usb(void)
|
||||||
{
|
{
|
||||||
// enable USB power
|
// enable USB power
|
||||||
SET_BIT(PWR->CR2, PWR_CR2_USV);
|
SET_BIT(PWR->CR2, PWR_CR2_USV);
|
||||||
|
@ -22,7 +22,7 @@
|
|||||||
#ifndef _INIT_H_
|
#ifndef _INIT_H_
|
||||||
#define _INIT_H_
|
#define _INIT_H_
|
||||||
|
|
||||||
void init_usb();
|
void init_usb(void);
|
||||||
void init_gpio(void);
|
void init_gpio(void);
|
||||||
void init_debug_uart(void);
|
void init_debug_uart(void);
|
||||||
void init_pwm(void);
|
void init_pwm(void);
|
||||||
|
@ -57,10 +57,11 @@ void TIM6_DAC_IRQHandler()
|
|||||||
__90_ms += 1;
|
__90_ms += 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t millis()
|
uint32_t millis(void)
|
||||||
{
|
{
|
||||||
return (((uint32_t)TIM6->CNT) + (__90_ms * 90));
|
return (((uint32_t)TIM6->CNT) + (__90_ms * 90));
|
||||||
}
|
}
|
||||||
|
|
||||||
void _Error_Handler(char *file, int line)
|
void _Error_Handler(char *file, int line)
|
||||||
{
|
{
|
||||||
while(1)
|
while(1)
|
||||||
|
@ -37,10 +37,33 @@
|
|||||||
|
|
||||||
// End of application code. Leave some extra room for future data storage.
|
// End of application code. Leave some extra room for future data storage.
|
||||||
// NOT included in application
|
// 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)
|
#define APPLICATION_END_ADDR ((0x08000000 + ((APPLICATION_END_PAGE)*PAGE_SIZE))-8)
|
||||||
|
|
||||||
// Bootloader state.
|
// Bootloader state.
|
||||||
#define AUTH_WORD_ADDR (APPLICATION_END_ADDR)
|
#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
|
#endif
|
||||||
|
@ -359,7 +359,7 @@ static uint32_t WTX_timer;
|
|||||||
|
|
||||||
bool WTX_process(int read_timeout);
|
bool WTX_process(int read_timeout);
|
||||||
|
|
||||||
void WTX_clear()
|
void WTX_clear(void)
|
||||||
{
|
{
|
||||||
WTX_sent = false;
|
WTX_sent = false;
|
||||||
WTX_fail = false;
|
WTX_fail = false;
|
||||||
@ -374,7 +374,7 @@ bool WTX_on(int WTX_time)
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool WTX_off()
|
bool WTX_off(void)
|
||||||
{
|
{
|
||||||
WTX_timer = 0;
|
WTX_timer = 0;
|
||||||
|
|
||||||
@ -398,7 +398,7 @@ bool WTX_off()
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void WTX_timer_exec()
|
void WTX_timer_exec(void)
|
||||||
{
|
{
|
||||||
// condition: (timer on) or (not expired[300ms])
|
// condition: (timer on) or (not expired[300ms])
|
||||||
if ((WTX_timer == 0) || WTX_timer + 300 > millis())
|
if ((WTX_timer == 0) || WTX_timer + 300 > millis())
|
||||||
@ -856,7 +856,7 @@ void nfc_process_iblock(uint8_t * buf, int len)
|
|||||||
static uint8_t ibuf[1024];
|
static uint8_t ibuf[1024];
|
||||||
static int ibuflen = 0;
|
static int ibuflen = 0;
|
||||||
|
|
||||||
void clear_ibuf()
|
void clear_ibuf(void)
|
||||||
{
|
{
|
||||||
ibuflen = 0;
|
ibuflen = 0;
|
||||||
memset(ibuf, 0, sizeof(ibuf));
|
memset(ibuf, 0, sizeof(ibuf));
|
||||||
@ -969,7 +969,7 @@ void nfc_process_block(uint8_t * buf, unsigned int len)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int nfc_loop()
|
int nfc_loop(void)
|
||||||
{
|
{
|
||||||
uint8_t buf[32];
|
uint8_t buf[32];
|
||||||
AMS_DEVICE ams;
|
AMS_DEVICE ams;
|
||||||
|
@ -6,9 +6,9 @@
|
|||||||
#include "apdu.h"
|
#include "apdu.h"
|
||||||
|
|
||||||
// Return number of bytes read if any.
|
// Return number of bytes read if any.
|
||||||
int nfc_loop();
|
int nfc_loop(void);
|
||||||
|
|
||||||
int nfc_init();
|
int nfc_init(void);
|
||||||
|
|
||||||
typedef struct
|
typedef struct
|
||||||
{
|
{
|
||||||
@ -61,6 +61,6 @@ typedef enum
|
|||||||
APP_FIDO,
|
APP_FIDO,
|
||||||
} APPLETS;
|
} APPLETS;
|
||||||
|
|
||||||
void WTX_timer_exec();
|
void WTX_timer_exec(void);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -8,7 +8,7 @@
|
|||||||
#define ELECTRODE_0 TSC_GROUP2_IO1
|
#define ELECTRODE_0 TSC_GROUP2_IO1
|
||||||
#define ELECTRODE_1 TSC_GROUP2_IO2
|
#define ELECTRODE_1 TSC_GROUP2_IO2
|
||||||
|
|
||||||
void tsc_init()
|
void tsc_init(void)
|
||||||
{
|
{
|
||||||
LL_GPIO_InitTypeDef GPIO_InitStruct;
|
LL_GPIO_InitTypeDef GPIO_InitStruct;
|
||||||
// Enable TSC clock
|
// Enable TSC clock
|
||||||
@ -74,7 +74,7 @@ void tsc_set_electrode(uint32_t channel_ids)
|
|||||||
TSC->IOCCR = (channel_ids);
|
TSC->IOCCR = (channel_ids);
|
||||||
}
|
}
|
||||||
|
|
||||||
void tsc_start_acq()
|
void tsc_start_acq(void)
|
||||||
{
|
{
|
||||||
TSC->CR &= ~(TSC_CR_START);
|
TSC->CR &= ~(TSC_CR_START);
|
||||||
|
|
||||||
@ -86,7 +86,7 @@ void tsc_start_acq()
|
|||||||
TSC->CR |= TSC_CR_START;
|
TSC->CR |= TSC_CR_START;
|
||||||
}
|
}
|
||||||
|
|
||||||
void tsc_wait_on_acq()
|
void tsc_wait_on_acq(void)
|
||||||
{
|
{
|
||||||
while ( ! (TSC->ISR & TSC_FLAG_EOA) )
|
while ( ! (TSC->ISR & TSC_FLAG_EOA) )
|
||||||
;
|
;
|
||||||
@ -117,7 +117,7 @@ uint32_t tsc_read_button(uint32_t index)
|
|||||||
return tsc_read(1) < 45;
|
return tsc_read(1) < 45;
|
||||||
}
|
}
|
||||||
|
|
||||||
int tsc_sensor_exists()
|
int tsc_sensor_exists(void)
|
||||||
{
|
{
|
||||||
static uint8_t does = 0;
|
static uint8_t does = 0;
|
||||||
if (does) return 1;
|
if (does) return 1;
|
||||||
|
@ -3,9 +3,9 @@
|
|||||||
|
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
|
||||||
void tsc_init();
|
void tsc_init(void);
|
||||||
|
|
||||||
int tsc_sensor_exists();
|
int tsc_sensor_exists(void);
|
||||||
|
|
||||||
// Read button0 or button1
|
// Read button0 or button1
|
||||||
// Returns 1 if pressed, 0 if not.
|
// Returns 1 if pressed, 0 if not.
|
||||||
|
Reference in New Issue
Block a user