Compare commits

...

16 Commits

Author SHA1 Message Date
0873fa5f34 fix solo locked flag for bootloader 2019-10-27 10:17:13 -04:00
bb08f6e0d3 fix build 2019-10-27 10:06:39 -04:00
9fa2c97dc3 store all info in same page, dont use authenticator state 2019-10-27 09:27:56 -04:00
49ca42991c add locked variable to GETVERSION hid command 2019-10-27 09:03:17 -04:00
ef683bdc99 remove logs 2019-10-27 08:59:10 -04:00
69478b4b6e remove hacker macros 2019-10-27 08:58:34 -04:00
9d5942ad10 lock flash based on state setting 2019-10-27 08:58:12 -04:00
446f1e0176 migrate certs 2019-10-27 08:40:06 -04:00
de2c1eff1b pull certificate from flash page 2019-10-27 07:51:02 -04:00
48147a39df Remove Somu campaign from readme 2019-10-24 12:53:03 +02:00
6c48d75e44 Merge pull request #324 from jolo1581/document_application_ideas
Document application ideas
2019-10-23 13:01:49 +02:00
fca1e9d405 Added new document for Application Ideas.
Added manual how to setup Linux to use Solo for passwordless login or as
second factor by pressing button after password login. Added chapter
"Application Ideas" below chapter "Solo Extras" in official
documentation.
2019-10-18 11:44:03 +02:00
0fbc28fbc1 fix pc build 2019-10-08 16:10:29 -04:00
2a02d0de33 small errors 2019-10-08 16:10:29 -04:00
00b09e0d40 add u2f length arg 2019-10-08 16:10:29 -04:00
26db2b3f6b check FIDO2 credential IDs in U2F 2019-10-08 16:10:29 -04:00
17 changed files with 309 additions and 71 deletions

View File

@ -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.
[![latest release](https://img.shields.io/github/release/solokeys/solo.svg)](https://update.solokeys.com/)
[![Keybase Chat](https://img.shields.io/badge/chat-on%20keybase-brightgreen.svg)](https://keybase.io/team/solokeys.public)
[![Build Status](https://travis-ci.com/solokeys/solo.svg?style=flat-square&branch=master)](https://travis-ci.com/solokeys/solo)

View File

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

View File

@ -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";

View File

@ -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

View File

@ -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);

View File

@ -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.

View File

@ -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))
{

View File

@ -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();

View File

@ -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

View File

@ -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;
}

View File

@ -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

View File

@ -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

View File

@ -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;

View File

@ -194,9 +194,10 @@ void crypto_ecc256_init(void)
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;
}

View File

@ -34,6 +34,8 @@
#define LOW_FREQUENCY 1
#define HIGH_FREQUENCY 0
#define SOLO_FLAG_LOCKED 0x2
void wait_for_usb_tether(void);
@ -191,6 +193,97 @@ void device_init_button(void)
}
}
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[])
{
@ -219,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

View File

@ -31,16 +31,10 @@ static void flash_unlock(void)
// 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)
{

View File

@ -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,8 +35,8 @@
#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
@ -48,7 +51,6 @@
#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];
@ -65,5 +67,19 @@ 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