Compare commits
57 Commits
key-backup
...
move_certs
Author | SHA1 | Date | |
---|---|---|---|
0873fa5f34 | |||
bb08f6e0d3 | |||
9fa2c97dc3 | |||
49ca42991c | |||
ef683bdc99 | |||
69478b4b6e | |||
9d5942ad10 | |||
446f1e0176 | |||
de2c1eff1b | |||
48147a39df | |||
6c48d75e44 | |||
fca1e9d405 | |||
0fbc28fbc1 | |||
2a02d0de33 | |||
00b09e0d40 | |||
26db2b3f6b | |||
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": [
|
||||
"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,
|
||||
|
@ -1,9 +1,3 @@
|
||||
**NEW!** We launched a new tiny security key called Somu, it's live on Crowd Supply and you can [pre-order it now](https://solokeys.com/somu)!
|
||||
|
||||
[<img src="https://miro.medium.com/max/1400/1*PnzCPLqq_5nt1gjgSEY2LQ.png" width="600">](https://solokeys.com/somu)
|
||||
|
||||
Somu is the micro version of Solo. We were inspired to make a secure Tomu, so we took its tiny form factor, we added the secure microcontroller and firmware of Solo, et voilà! Here we have Somu.
|
||||
|
||||
[](https://update.solokeys.com/)
|
||||
[](https://keybase.io/team/solokeys.public)
|
||||
[](https://travis-ci.com/solokeys/solo)
|
||||
@ -136,6 +130,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://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>
|
||||
|
||||
@ -169,7 +164,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)
|
||||
|
99
docs/solo/application-ideas.md
Normal file
99
docs/solo/application-ideas.md
Normal file
@ -0,0 +1,99 @@
|
||||
# Using Solo for passwordless or second factor login on Linux
|
||||
|
||||
## Setup on Ubuntu 18.04
|
||||
Before you can use Solo for passwordless or second factor login in your Linux system you have to install some packages.
|
||||
|
||||
This was tested under **Linux Mint 19.2**.
|
||||
|
||||
First you have to install PAM modules for u2f.
|
||||
|
||||
```
|
||||
sudo apt install libpam-u2f pamu2fcfg
|
||||
```
|
||||
|
||||
## Setting up key
|
||||
To use Solo as passwordless or second factor login, you have to setup your system with your Solo.
|
||||
First create a new folder named **Yubico** in your **.config** folder in your **home** directory
|
||||
|
||||
```
|
||||
mkdir ~/.config/Yubico
|
||||
```
|
||||
|
||||
Then create a new key for PAM U2F module. If it is your first key you want to register use following command:
|
||||
```
|
||||
pamu2fcfg > ~/.config/Yubico/u2f_keys
|
||||
```
|
||||
If you want to register an additional key use this command instead:
|
||||
```
|
||||
pamu2fcfg >> ~/.config/Yubico/u2f_keys
|
||||
```
|
||||
Now press the button on your Solo.
|
||||
|
||||
|
||||
If you can't generate your key (error message), you may add Yubico Team from PPA and install latest libpam-u2f and pamu2fcfg and try again.
|
||||
```
|
||||
sudo add-apt-repository ppa:yubico/stable
|
||||
sudo apt-get update
|
||||
sudo apt-get upgrade
|
||||
```
|
||||
|
||||
|
||||
## Login into Linux
|
||||
### Passwordless
|
||||
To login passwordless into your Linux system, you have to edit the file **lightdm** (or **gdm** or which display manager you prefered).
|
||||
In case of lightdm:
|
||||
|
||||
```
|
||||
sudo vim /etc/pam.d/lightdm
|
||||
```
|
||||
Now search following entry:
|
||||
```
|
||||
@include common-auth
|
||||
```
|
||||
and add
|
||||
```
|
||||
auth sufficient pam_u2f.so
|
||||
```
|
||||
**before** @include common-auth.
|
||||
|
||||
Save the file and test it.<br>
|
||||
Insert Solo in your USB port and logout.
|
||||
Now you should be able to login into Linux without password, only with pressing your button on Solo and press enter.
|
||||
|
||||
Why **sufficient**? The difference between the keyword sufficient and required is, if you don't have your Solo available, you can also login, because the system falls back to password mode.
|
||||
|
||||
|
||||
The login mechanism can be also used for additional features like:
|
||||
|
||||
: - Login after screen timeout - edit /etc/pam.d/mate-screensaver (or kde-screensaver, ...)
|
||||
- Passwordless sudo - edit /etc/pam.d/sudo
|
||||
|
||||
Check out your folder **/etc/pam.d/** and do some experiments.
|
||||
|
||||
**But remember:** <br>
|
||||
The login passwordless won't make your system more secure, but maybe more comfortable. If somebody have access to your Solo, this person will be also able to login into your system.
|
||||
|
||||
|
||||
### Solo as second factor
|
||||
To use Solo as second factor, for login into your Linux system, is nearly the same.
|
||||
|
||||
```
|
||||
sudo vim /etc/pam.d/lightdm
|
||||
```
|
||||
Now search following entry:
|
||||
```
|
||||
@include common-auth
|
||||
```
|
||||
and add
|
||||
```
|
||||
auth required pam_u2f.so
|
||||
```
|
||||
**after** @include common-auth.
|
||||
|
||||
Save the file and test it. <br>
|
||||
In case your Solo is not present, your password will be incrorrect. If Solo is plugged into your USB port, it will signal pressing the button and you will be able to login into Linux.
|
||||
|
||||
Why **required**? If you choose the option **sufficent** your Solo is optional. You could also login without second factor if your Solo is not connected.
|
||||
|
||||
**But remember:**<br>
|
||||
If you loose your Solo you won't be able to login into your system.
|
@ -47,7 +47,7 @@ typedef enum
|
||||
#endif
|
||||
|
||||
|
||||
const uint8_t attestation_cert_der[];
|
||||
const uint8_t * attestation_cert_der;
|
||||
const uint16_t attestation_cert_der_size;
|
||||
const uint8_t attestation_key[];
|
||||
const uint16_t attestation_key_size;
|
||||
@ -338,7 +338,7 @@ void crypto_aes256_encrypt(uint8_t * buf, int length)
|
||||
}
|
||||
|
||||
|
||||
const uint8_t attestation_cert_der[] =
|
||||
const uint8_t _attestation_cert_der[] =
|
||||
"\x30\x82\x01\xfb\x30\x82\x01\xa1\xa0\x03\x02\x01\x02\x02\x01\x00\x30\x0a\x06\x08"
|
||||
"\x2a\x86\x48\xce\x3d\x04\x03\x02\x30\x2c\x31\x0b\x30\x09\x06\x03\x55\x04\x06\x13"
|
||||
"\x02\x55\x53\x31\x0b\x30\x09\x06\x03\x55\x04\x08\x0c\x02\x4d\x44\x31\x10\x30\x0e"
|
||||
@ -365,9 +365,11 @@ const uint8_t attestation_cert_der[] =
|
||||
"\x7e\x74\x64\x1b\xa3\x7b\xf7\xe6\xd3\xaf\x79\x28\xdb\xdc\xa5\x88\x02\x21\x00\xcd"
|
||||
"\x06\xf1\xe3\xab\x16\x21\x8e\xd8\xc0\x14\xaf\x09\x4f\x5b\x73\xef\x5e\x9e\x4b\xe7"
|
||||
"\x35\xeb\xdd\x9b\x6d\x8f\x7d\xf3\xc4\x3a\xd7";
|
||||
const uint8_t * attestation_cert_der = (const uint8_t *)_attestation_cert_der;
|
||||
|
||||
|
||||
const uint16_t attestation_cert_der_size = sizeof(attestation_cert_der)-1;
|
||||
uint16_t attestation_cert_der_get_size(){
|
||||
return sizeof(_attestation_cert_der)-1;
|
||||
}
|
||||
|
||||
|
||||
const uint8_t attestation_key[] = "\xcd\x67\xaa\x31\x0d\x09\x1e\xd1\x6e\x7e\x98\x92\xaa\x07\x0e\x19\x94\xfc\xd7\x14\xae\x7c\x40\x8f\xb9\x46\xb7\x2e\x5f\xe7\x5d\x30";
|
||||
|
@ -54,10 +54,7 @@ void crypto_reset_master_secret();
|
||||
void crypto_load_master_secret(uint8_t * key);
|
||||
|
||||
|
||||
extern const uint8_t attestation_cert_der[];
|
||||
extern const uint16_t attestation_cert_der_size;
|
||||
|
||||
extern const uint8_t attestation_key[];
|
||||
extern const uint16_t attestation_key_size;
|
||||
extern const uint8_t * attestation_cert_der;
|
||||
uint16_t attestation_cert_der_get_size();
|
||||
|
||||
#endif
|
||||
|
10
fido2/ctap.c
10
fido2/ctap.c
@ -661,7 +661,7 @@ uint8_t ctap_add_attest_statement(CborEncoder * map, uint8_t * sigder, int len)
|
||||
ret = cbor_encoder_create_array(&stmtmap, &x5carr, 1);
|
||||
check_ret(ret);
|
||||
{
|
||||
ret = cbor_encode_byte_string(&x5carr, attestation_cert_der, attestation_cert_der_size);
|
||||
ret = cbor_encode_byte_string(&x5carr, attestation_cert_der, attestation_cert_der_get_size());
|
||||
check_ret(ret);
|
||||
ret = cbor_encoder_close_container(&stmtmap, &x5carr);
|
||||
check_ret(ret);
|
||||
@ -698,7 +698,7 @@ int ctap_authenticate_credential(struct rpId * rp, CTAP_credentialDescriptor * d
|
||||
crypto_sha256_init();
|
||||
crypto_sha256_update(rp->id, rp->size);
|
||||
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;
|
||||
case PUB_KEY_CRED_CUSTOM:
|
||||
return is_extension_request(getAssertionState.customCredId, getAssertionState.customCredIdSize);
|
||||
@ -1775,8 +1775,14 @@ void ctap_load_external_keys(uint8_t * keybytes){
|
||||
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);
|
||||
|
@ -696,7 +696,7 @@ uint8_t ctaphid_custom_command(int len, CTAP_RESPONSE * ctap_resp, CTAPHID_WRITE
|
||||
{
|
||||
ctap_response_init(ctap_resp);
|
||||
|
||||
#if !defined(IS_BOOTLOADER) && (defined(SOLO_HACKER) || defined(SOLO_EXPERIMENTAL))
|
||||
#if !defined(IS_BOOTLOADER) && (defined(SOLO_EXPERIMENTAL))
|
||||
uint32_t param;
|
||||
#endif
|
||||
#if defined(IS_BOOTLOADER)
|
||||
@ -716,17 +716,13 @@ uint8_t ctaphid_custom_command(int len, CTAP_RESPONSE * ctap_resp, CTAPHID_WRITE
|
||||
ctaphid_write(wb, NULL, 0);
|
||||
return 1;
|
||||
#endif
|
||||
#if defined(SOLO_HACKER)
|
||||
#if defined(SOLO)
|
||||
case CTAPHID_ENTERBOOT:
|
||||
printf1(TAG_HID,"CTAPHID_ENTERBOOT\n");
|
||||
boot_solo_bootloader();
|
||||
wb->bcnt = 0;
|
||||
ctaphid_write(wb, NULL, 0);
|
||||
return 1;
|
||||
case CTAPHID_ENTERSTBOOT:
|
||||
printf1(TAG_HID,"CTAPHID_ENTERBOOT\n");
|
||||
boot_st_bootloader();
|
||||
return 1;
|
||||
#endif
|
||||
|
||||
#if !defined(IS_BOOTLOADER)
|
||||
@ -745,16 +741,21 @@ uint8_t ctaphid_custom_command(int len, CTAP_RESPONSE * ctap_resp, CTAPHID_WRITE
|
||||
|
||||
case CTAPHID_GETVERSION:
|
||||
printf1(TAG_HID,"CTAPHID_GETVERSION\n");
|
||||
wb->bcnt = 3;
|
||||
wb->bcnt = 4;
|
||||
ctap_buffer[0] = SOLO_VERSION_MAJ;
|
||||
ctap_buffer[1] = SOLO_VERSION_MIN;
|
||||
ctap_buffer[2] = SOLO_VERSION_PATCH;
|
||||
ctaphid_write(wb, ctap_buffer, 3);
|
||||
#if defined(SOLO)
|
||||
ctap_buffer[3] = solo_is_locked();
|
||||
#else
|
||||
ctap_buffer[3] = 0;
|
||||
#endif
|
||||
ctaphid_write(wb, ctap_buffer, 4);
|
||||
ctaphid_write(wb, NULL, 0);
|
||||
return 1;
|
||||
break;
|
||||
|
||||
#if !defined(IS_BOOTLOADER) && (defined(SOLO_HACKER) || defined(SOLO_EXPERIMENTAL))
|
||||
#if !defined(IS_BOOTLOADER) && (defined(SOLO_EXPERIMENTAL))
|
||||
case CTAPHID_LOADKEY:
|
||||
/**
|
||||
* Load external key. Useful for enabling backups.
|
||||
|
54
fido2/u2f.c
54
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);
|
||||
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;
|
||||
|
||||
@ -160,9 +161,9 @@ static void dump_signature_der(uint8_t * sig)
|
||||
len = ctap_encode_der_sig(sig, sigder);
|
||||
u2f_response_writeback(sigder, len);
|
||||
}
|
||||
static int8_t u2f_load_key(struct u2f_key_handle * kh, uint8_t * appid)
|
||||
static int8_t u2f_load_key(struct u2f_key_handle * kh, uint8_t khl, uint8_t * appid)
|
||||
{
|
||||
crypto_ecc256_load_key((uint8_t*)kh, U2F_KEY_HANDLE_SIZE, NULL, 0);
|
||||
crypto_ecc256_load_key((uint8_t*)kh, khl, NULL, 0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -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.
|
||||
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];
|
||||
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;
|
||||
}
|
||||
else
|
||||
printf1(TAG_U2F, "FIDO2 key handle detected.\n");
|
||||
CredentialId * cred = (CredentialId *) kh;
|
||||
// FIDO2 credential.
|
||||
|
||||
if (memcmp(cred->rpIdHash, appid, 32) != 0)
|
||||
{
|
||||
printf1(TAG_U2F, "APPID does not match rpIdHash.\n");
|
||||
return 0;
|
||||
}
|
||||
make_auth_tag(appid, cred->nonce, cred->count, tag);
|
||||
|
||||
if (memcmp(cred->tag, tag, CREDENTIAL_TAG_SIZE) == 0){
|
||||
return 1;
|
||||
}
|
||||
|
||||
}else if (key_handle_len == U2F_KEY_HANDLE_SIZE)
|
||||
{
|
||||
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;
|
||||
u2f_make_auth_tag(kh, appid, tag);
|
||||
if (memcmp(kh->tag, tag, U2F_KEY_HANDLE_TAG_SIZE) == 0)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
printf1(TAG_U2F, "key handle + appid not authentic\n");
|
||||
printf1(TAG_U2F, "calc tag: \n"); dump_hex1(TAG_U2F,tag, U2F_KEY_HANDLE_TAG_SIZE);
|
||||
printf1(TAG_U2F, "inp tag: \n"); dump_hex1(TAG_U2F,kh->tag, U2F_KEY_HANDLE_TAG_SIZE);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
@ -216,7 +237,7 @@ static int16_t u2f_authenticate(struct u2f_authenticate_request * req, uint8_t c
|
||||
if (control == U2F_AUTHENTICATE_CHECK)
|
||||
{
|
||||
printf1(TAG_U2F, "CHECK-ONLY\r\n");
|
||||
if (u2f_authenticate_credential(&req->kh, req->app))
|
||||
if (u2f_authenticate_credential(&req->kh, req->khl, req->app))
|
||||
{
|
||||
return U2F_SW_CONDITIONS_NOT_SATISFIED;
|
||||
}
|
||||
@ -227,9 +248,8 @@ static int16_t u2f_authenticate(struct u2f_authenticate_request * req, uint8_t c
|
||||
}
|
||||
if (
|
||||
(control != U2F_AUTHENTICATE_SIGN && control != U2F_AUTHENTICATE_SIGN_NO_USER) ||
|
||||
req->khl != U2F_KEY_HANDLE_SIZE ||
|
||||
(!u2f_authenticate_credential(&req->kh, req->app)) || // Order of checks is important
|
||||
u2f_load_key(&req->kh, req->app) != 0
|
||||
(!u2f_authenticate_credential(&req->kh, req->khl, req->app)) || // Order of checks is important
|
||||
u2f_load_key(&req->kh, req->khl, req->app) != 0
|
||||
|
||||
)
|
||||
{
|
||||
@ -286,7 +306,7 @@ static int16_t u2f_register(struct u2f_register_request * req)
|
||||
uint8_t * sig = (uint8_t*)req;
|
||||
|
||||
|
||||
const uint16_t attest_size = attestation_cert_der_size;
|
||||
const uint16_t attest_size = attestation_cert_der_get_size();
|
||||
|
||||
if ( ! ctap_user_presence_test(750))
|
||||
{
|
||||
|
@ -103,7 +103,7 @@ void u2f_request(struct u2f_request_apdu* req, CTAP_RESPONSE * resp);
|
||||
// @len data length
|
||||
void u2f_request_nfc(uint8_t * header, uint8_t * data, int datalen, CTAP_RESPONSE * resp);
|
||||
|
||||
int8_t u2f_authenticate_credential(struct u2f_key_handle * kh, uint8_t * 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);
|
||||
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)
|
||||
#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
|
||||
|
@ -15,6 +15,7 @@ nav:
|
||||
- Bootloader mode: solo/bootloader-mode.md
|
||||
- Customization: solo/customization.md
|
||||
- Solo Extras: solo/solo-extras.md
|
||||
- Application Ideas: solo/application-ideas.md
|
||||
- Running on Nucleo32 board: solo/nucleo32-board.md
|
||||
- Signed update process: solo/signed-updates.md
|
||||
- Code documentation: solo/code-overview.md
|
||||
|
@ -108,6 +108,7 @@ int udp_recv(int fd, uint8_t * buf, int size)
|
||||
perror( "recvfrom failed" );
|
||||
exit(1);
|
||||
}
|
||||
printf1(TAG_DUMP, ">>"); dump_hex1(TAG_DUMP, buf, length);
|
||||
return length;
|
||||
}
|
||||
|
||||
@ -124,6 +125,8 @@ void udp_send(int fd, uint8_t * buf, int size)
|
||||
perror( "sendto failed" );
|
||||
exit(1);
|
||||
}
|
||||
|
||||
printf1(TAG_DUMP, "<<"); dump_hex1(TAG_DUMP, buf, size);
|
||||
}
|
||||
|
||||
|
||||
@ -316,7 +319,7 @@ int ctap_user_verification(uint8_t arg)
|
||||
uint32_t ctap_atomic_count(uint32_t amount)
|
||||
{
|
||||
static uint32_t counter1 = 25;
|
||||
counter1 += amount;
|
||||
counter1 += (amount + 1);
|
||||
return counter1;
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
}
|
@ -64,4 +64,9 @@ int is_authorized_to_boot();
|
||||
int is_bootloader_disabled();
|
||||
void bootloader_heartbeat();
|
||||
|
||||
// Return 1 if Solo is secure/locked.
|
||||
int solo_is_locked();
|
||||
|
||||
|
||||
|
||||
#endif
|
||||
|
@ -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,7 @@ 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
|
||||
@ -70,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
|
||||
|
@ -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);
|
||||
|
@ -9,6 +9,8 @@
|
||||
#include <stdint.h>
|
||||
#include "version.h"
|
||||
|
||||
#define SOLO
|
||||
|
||||
#define DEBUG_UART USART1
|
||||
|
||||
#ifndef DEBUG_LEVEL
|
||||
@ -46,6 +48,9 @@
|
||||
void printing_init();
|
||||
void hw_init(int lf);
|
||||
|
||||
// Return 1 if Solo is secure/locked.
|
||||
int solo_is_locked();
|
||||
|
||||
//#define TEST
|
||||
//#define TEST_POWER
|
||||
|
||||
|
@ -6,10 +6,10 @@
|
||||
// copied, modified, or distributed except according to those terms.
|
||||
#include <stdint.h>
|
||||
#include "crypto.h"
|
||||
#include "memory_layout.h"
|
||||
|
||||
#ifdef USE_SOLOKEYS_CERT
|
||||
|
||||
const uint8_t attestation_cert_der[] =
|
||||
const uint8_t attestation_solo_cert_der[] =
|
||||
"\x30\x82\x02\xe1\x30\x82\x02\x88\xa0\x03\x02\x01\x02\x02\x01\x01\x30\x0a\x06\x08"
|
||||
"\x2a\x86\x48\xce\x3d\x04\x03\x02\x30\x81\x80\x31\x0b\x30\x09\x06\x03\x55\x04\x06"
|
||||
"\x13\x02\x55\x53\x31\x11\x30\x0f\x06\x03\x55\x04\x08\x0c\x08\x4d\x61\x72\x79\x6c"
|
||||
@ -49,11 +49,8 @@ const uint8_t attestation_cert_der[] =
|
||||
"\xf8\x84\xc3\x78\x35\x93\x63\x81\x2e\xbe\xa6\x12\x32\x6e\x29\x90\xc8\x91\x4b\x71"
|
||||
"\x52"
|
||||
;
|
||||
#else
|
||||
|
||||
// For testing/development only
|
||||
|
||||
const uint8_t attestation_cert_der[] =
|
||||
const uint8_t attestation_hacker_cert_der[] =
|
||||
"\x30\x82\x02\xe9\x30\x82\x02\x8e\xa0\x03\x02\x01\x02\x02\x01\x01\x30\x0a\x06\x08"
|
||||
"\x2a\x86\x48\xce\x3d\x04\x03\x02\x30\x81\x82\x31\x0b\x30\x09\x06\x03\x55\x04\x06"
|
||||
"\x13\x02\x55\x53\x31\x11\x30\x0f\x06\x03\x55\x04\x08\x0c\x08\x4d\x61\x72\x79\x6c"
|
||||
@ -94,8 +91,16 @@ const uint8_t attestation_cert_der[] =
|
||||
"\xf3\x87\x61\x82\xd8\xcd\x48\xfc\x57"
|
||||
;
|
||||
|
||||
#endif
|
||||
|
||||
const uint16_t attestation_cert_der_size = sizeof(attestation_cert_der)-1;
|
||||
const uint16_t attestation_solo_cert_der_size = sizeof(attestation_solo_cert_der)-1;
|
||||
const uint16_t attestation_hacker_cert_der_size = sizeof(attestation_hacker_cert_der)-1;
|
||||
|
||||
// const uint16_t attestation_key_size = 32;
|
||||
const uint8_t * attestation_cert_der = ((flash_attestation_page *)ATTESTATION_PAGE_ADDR)->attestation_cert;
|
||||
|
||||
#include "log.h"
|
||||
uint16_t attestation_cert_der_get_size(){
|
||||
uint16_t sz = (uint16_t)((flash_attestation_page *)ATTESTATION_PAGE_ADDR)->attestation_cert_size;
|
||||
return sz;
|
||||
}
|
||||
|
||||
const uint16_t attestation_key_size = 32;
|
||||
|
@ -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,18 +185,19 @@ 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);
|
||||
_signing_key = _key;
|
||||
// static uint8_t _key [32];
|
||||
flash_attestation_page * page =(flash_attestation_page *)ATTESTATION_PAGE_ADDR;
|
||||
// memmove(_key, (uint8_t *)ATTESTATION_KEY_ADDR, 32);
|
||||
_signing_key = page->attestation_key;
|
||||
_key_len = 32;
|
||||
}
|
||||
|
||||
|
@ -34,7 +34,9 @@
|
||||
#define LOW_FREQUENCY 1
|
||||
#define HIGH_FREQUENCY 0
|
||||
|
||||
void wait_for_usb_tether();
|
||||
#define SOLO_FLAG_LOCKED 0x2
|
||||
|
||||
void wait_for_usb_tether(void);
|
||||
|
||||
|
||||
uint32_t __90_ms = 0;
|
||||
@ -48,12 +50,12 @@ static bool isLowFreq = 0;
|
||||
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)
|
||||
{
|
||||
int is_pressed = (tsc_read_button(0) || tsc_read_button(1));
|
||||
#ifndef IS_BOOTLOADER
|
||||
@ -69,7 +71,7 @@ static int is_touch_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;
|
||||
uint8_t current_touch = 0;
|
||||
@ -92,12 +94,13 @@ static void edge_detect_touch_button()
|
||||
|
||||
}
|
||||
|
||||
void device_disable_up(bool disable) {
|
||||
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;
|
||||
@ -142,7 +145,7 @@ void USB_IRQHandler(void)
|
||||
HAL_PCD_IRQHandler(&hpcd);
|
||||
}
|
||||
|
||||
uint32_t millis()
|
||||
uint32_t millis(void)
|
||||
{
|
||||
return (((uint32_t)TIM6->CNT) + (__90_ms * 90));
|
||||
}
|
||||
@ -160,7 +163,7 @@ 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();
|
||||
}
|
||||
@ -171,12 +174,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())
|
||||
{
|
||||
@ -189,6 +193,97 @@ void device_init_button()
|
||||
}
|
||||
}
|
||||
|
||||
int solo_is_locked(){
|
||||
uint64_t device_settings = ((flash_attestation_page *)ATTESTATION_PAGE_ADDR)->device_settings;
|
||||
return (device_settings & SOLO_FLAG_LOCKED) != 0;
|
||||
}
|
||||
|
||||
/** device_migrate
|
||||
* Depending on version of device, migrates:
|
||||
* * Moves attestation certificate to data segment.
|
||||
* * Creates locked variable and stores in data segment.
|
||||
*
|
||||
* Once in place, this allows all devices to accept same firmware,
|
||||
* rather than using "hacker" and "secure" builds.
|
||||
*/
|
||||
static void device_migrate(){
|
||||
extern const uint16_t attestation_solo_cert_der_size;
|
||||
extern const uint16_t attestation_hacker_cert_der_size;
|
||||
|
||||
extern uint8_t attestation_solo_cert_der[];
|
||||
extern uint8_t attestation_hacker_cert_der[];
|
||||
|
||||
uint64_t device_settings = ((flash_attestation_page *)ATTESTATION_PAGE_ADDR)->device_settings;
|
||||
uint32_t configure_tag = (uint32_t)(device_settings >> 32);
|
||||
|
||||
if (configure_tag != ATTESTATION_CONFIGURED_TAG)
|
||||
{
|
||||
printf1(TAG_RED,"Migrating certificate and lock information to data segment.\r\n");
|
||||
|
||||
device_settings = ATTESTATION_CONFIGURED_TAG;
|
||||
device_settings <<= 32;
|
||||
|
||||
// Read current device lock level.
|
||||
uint32_t optr = FLASH->OPTR;
|
||||
if ((optr & 0xff) != 0xAA){
|
||||
device_settings |= SOLO_FLAG_LOCKED;
|
||||
}
|
||||
|
||||
uint8_t tmp_attestation_key[32];
|
||||
|
||||
memmove(tmp_attestation_key,
|
||||
((flash_attestation_page *)ATTESTATION_PAGE_ADDR)->attestation_key,
|
||||
32);
|
||||
|
||||
flash_erase_page(ATTESTATION_PAGE);
|
||||
flash_write(
|
||||
(uint32_t)((flash_attestation_page *)ATTESTATION_PAGE_ADDR)->attestation_key,
|
||||
tmp_attestation_key,
|
||||
32
|
||||
);
|
||||
|
||||
// Check if this is Solo Hacker attestation (not confidential)
|
||||
// then write solo or hacker attestation cert to flash page.
|
||||
uint8_t solo_hacker_attestation_key[32] = "\x1b\x26\x26\xec\xc8\xf6\x9b\x0f\x69\xe3\x4f"
|
||||
"\xb2\x36\xd7\x64\x66\xba\x12\xac\x16\xc3\xab"
|
||||
"\x57\x50\xba\x06\x4e\x8b\x90\xe0\x24\x48";
|
||||
|
||||
if (memcmp(solo_hacker_attestation_key,
|
||||
tmp_attestation_key,
|
||||
32) == 0)
|
||||
{
|
||||
printf1(TAG_GREEN,"Updating solo hacker cert\r\n");
|
||||
flash_write_dword(
|
||||
(uint32_t)&((flash_attestation_page *)ATTESTATION_PAGE_ADDR)->attestation_cert_size,
|
||||
(uint64_t)attestation_hacker_cert_der_size
|
||||
);
|
||||
flash_write(
|
||||
(uint32_t)((flash_attestation_page *)ATTESTATION_PAGE_ADDR)->attestation_cert,
|
||||
attestation_hacker_cert_der,
|
||||
attestation_hacker_cert_der_size
|
||||
);
|
||||
}
|
||||
else
|
||||
{
|
||||
printf1(TAG_GREEN,"Updating solo secure cert\r\n");
|
||||
flash_write_dword(
|
||||
(uint32_t)&((flash_attestation_page *)ATTESTATION_PAGE_ADDR)->attestation_cert_size,
|
||||
(uint64_t)attestation_solo_cert_der_size
|
||||
);
|
||||
flash_write(
|
||||
(uint32_t)((flash_attestation_page *)ATTESTATION_PAGE_ADDR)->attestation_cert,
|
||||
attestation_solo_cert_der,
|
||||
attestation_solo_cert_der_size
|
||||
);
|
||||
}
|
||||
|
||||
// Save / done.
|
||||
flash_write_dword(
|
||||
(uint32_t) & ((flash_attestation_page *)ATTESTATION_PAGE_ADDR)->device_settings,
|
||||
(uint64_t)device_settings);
|
||||
}
|
||||
}
|
||||
|
||||
void device_init(int argc, char *argv[])
|
||||
{
|
||||
|
||||
@ -217,6 +312,8 @@ void device_init(int argc, char *argv[])
|
||||
ctaphid_init();
|
||||
ctap_init();
|
||||
|
||||
device_migrate();
|
||||
|
||||
#if BOOT_TO_DFU
|
||||
flash_option_bytes_init(1);
|
||||
#else
|
||||
@ -226,12 +323,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) )
|
||||
;
|
||||
@ -242,7 +339,7 @@ void wait_for_usb_tether()
|
||||
;
|
||||
}
|
||||
|
||||
void usbhid_init()
|
||||
void usbhid_init(void)
|
||||
{
|
||||
if (!isLowFreq)
|
||||
{
|
||||
@ -292,12 +389,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 +404,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;
|
||||
@ -382,7 +480,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);
|
||||
@ -407,6 +505,7 @@ void authenticator_write_state(AuthenticatorState * a, int backup)
|
||||
}
|
||||
}
|
||||
|
||||
#if !defined(IS_BOOTLOADER)
|
||||
uint32_t ctap_atomic_count(uint32_t amount)
|
||||
{
|
||||
int offset = 0;
|
||||
@ -498,10 +597,10 @@ uint32_t ctap_atomic_count(uint32_t amount)
|
||||
|
||||
return lastc;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
void device_manage()
|
||||
void device_manage(void)
|
||||
{
|
||||
#if NON_BLOCK_PRINTING
|
||||
int i = 10;
|
||||
@ -527,7 +626,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));
|
||||
@ -563,6 +662,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;
|
||||
@ -656,7 +756,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");
|
||||
@ -666,7 +766,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));
|
||||
}
|
||||
@ -728,7 +828,7 @@ void ctap_overwrite_rk(int index,CTAP_residentKey * rk)
|
||||
}
|
||||
}
|
||||
|
||||
void boot_st_bootloader()
|
||||
void boot_st_bootloader(void)
|
||||
{
|
||||
__disable_irq();
|
||||
|
||||
@ -740,7 +840,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)
|
||||
{
|
||||
@ -31,16 +31,10 @@ static void flash_unlock()
|
||||
// Locks flash and turns off DFU
|
||||
void flash_option_bytes_init(int boot_from_dfu)
|
||||
{
|
||||
#ifndef FLASH_ROP
|
||||
#define FLASH_ROP 0
|
||||
#endif
|
||||
#if FLASH_ROP == 0
|
||||
uint32_t val = 0xfffff8aa;
|
||||
#elif FLASH_ROP == 2
|
||||
uint32_t val = 0xfffff8cc;
|
||||
#else
|
||||
uint32_t val = 0xfffff8b9;
|
||||
#endif
|
||||
if (solo_is_locked()){
|
||||
val = 0xfffff8cc;
|
||||
}
|
||||
|
||||
if (boot_from_dfu)
|
||||
{
|
||||
|
@ -699,7 +699,7 @@ 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);
|
||||
|
@ -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)
|
||||
|
@ -17,8 +17,11 @@
|
||||
#define COUNTER1_PAGE (PAGES - 3)
|
||||
|
||||
// State of FIDO2 application
|
||||
#define STATE2_PAGE (PAGES - 2)
|
||||
#define STATE1_PAGE (PAGES - 1)
|
||||
#define STATE2_PAGE (PAGES - 2)
|
||||
#define STATE1_PAGE (PAGES - 1)
|
||||
|
||||
#define STATE1_PAGE_ADDR (0x08000000 + ((STATE1_PAGE)*PAGE_SIZE))
|
||||
#define STATE2_PAGE_ADDR (0x08000000 + ((STATE2_PAGE)*PAGE_SIZE))
|
||||
|
||||
// Storage of FIDO2 resident keys
|
||||
#define RK_NUM_PAGES 10
|
||||
@ -32,15 +35,51 @@
|
||||
#define APPLICATION_START_ADDR (0x08000000 + ((APPLICATION_START_PAGE)*PAGE_SIZE))
|
||||
|
||||
// where attestation key is located
|
||||
#define ATTESTATION_KEY_PAGE (PAGES - 15)
|
||||
#define ATTESTATION_KEY_ADDR (0x08000000 + ATTESTATION_KEY_PAGE*PAGE_SIZE)
|
||||
#define ATTESTATION_PAGE (PAGES - 15)
|
||||
#define ATTESTATION_PAGE_ADDR (0x08000000 + ATTESTATION_PAGE*PAGE_SIZE)
|
||||
|
||||
// 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");
|
||||
|
||||
#define ATTESTATION_CONFIGURED_TAG 0xaa551e78
|
||||
|
||||
struct flash_attestation_page{
|
||||
uint8_t attestation_key[32];
|
||||
// DWORD padded.
|
||||
uint64_t device_settings;
|
||||
uint64_t attestation_cert_size;
|
||||
uint8_t attestation_cert[2048 - 32 - 8 - 8];
|
||||
} __attribute__((packed));
|
||||
|
||||
typedef struct flash_attestation_page flash_attestation_page;
|
||||
|
||||
static_assert(sizeof(flash_attestation_page) == 2048, "Data structure doesn't match flash size");
|
||||
|
||||
|
||||
#endif
|
||||
|
@ -359,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;
|
||||
@ -374,7 +374,7 @@ bool WTX_on(int WTX_time)
|
||||
return true;
|
||||
}
|
||||
|
||||
bool WTX_off()
|
||||
bool WTX_off(void)
|
||||
{
|
||||
WTX_timer = 0;
|
||||
|
||||
@ -398,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())
|
||||
@ -856,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));
|
||||
@ -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];
|
||||
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
|
||||
{
|
||||
@ -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