Compare commits
52 Commits
Author | SHA1 | Date | |
---|---|---|---|
ec52ca2605 | |||
5d2acf19f1 | |||
6196481b7f | |||
f002d08071 | |||
e53b83257d | |||
05e149fb17 | |||
530e175ad1 | |||
6cd3873b37 | |||
241f58657b | |||
3b42289cce | |||
b3712b57fc | |||
37769bb735 | |||
d677f8c346 | |||
98bcf647c4 | |||
682a443f4e | |||
a28a05673f | |||
3a70ee0ec6 | |||
872a320abc | |||
3cbf7ec451 | |||
748c552eea | |||
98f996fcfe | |||
97eb6bba8a | |||
fdc5a68fcd | |||
1c1005a0e8 | |||
4831410111 | |||
05bc8bee55 | |||
7112633779 | |||
79b43a90fd | |||
ec7a6fd740 | |||
f2d6698066 | |||
3c9315e34c | |||
8ed7157bfe | |||
28a1b1cc06 | |||
5738bcc7a3 | |||
4fb166631d | |||
1b862d3b0c | |||
094420b32b | |||
349cbc39f2 | |||
e294cb3458 | |||
da31f984dd | |||
9d3e8c06fc | |||
b378bbf61d | |||
04b89a9739 | |||
0d28a7bcf6 | |||
aeafd09007 | |||
8b6148ac90 | |||
15a4fdfa66 | |||
e713daba26 | |||
b78f2cd2e7 | |||
601c98000a | |||
ab1c9417b1 | |||
f6d96013e1 |
@ -61,9 +61,11 @@ git checkout ${VERSION_TO_BUILD}
|
|||||||
git submodule update --init --recursive
|
git submodule update --init --recursive
|
||||||
```
|
```
|
||||||
|
|
||||||
## Installing the toolchain
|
## Installing the toolchain and applying updates
|
||||||
|
|
||||||
In order to compile ARM code, you need the ARM compiler and other things like bundling bootloader and firmware require the `solo-python` python package. Check our [documentation](https://docs.solokeys.io/solo/) for details
|
In order to compile ARM code, you need the ARM compiler and other things like bundling bootloader and firmware require the [solo-python](https://github.com/solokeys/solo-python) python package. Check our [documentation](https://docs.solokeys.io/solo/) for details.
|
||||||
|
|
||||||
|
You can update your solokey after running `pip3 install solo-python` with `solo key update` for the latest version. To apply a custom image use `solo program bootloader <file>(.json|.hex)`.
|
||||||
|
|
||||||
## Installing the toolkit and compiling in Docker
|
## Installing the toolkit and compiling in Docker
|
||||||
Alternatively, you can use Docker to create a container with the toolchain.
|
Alternatively, you can use Docker to create a container with the toolchain.
|
||||||
|
@ -1 +1 @@
|
|||||||
3.0.1
|
3.2.0
|
||||||
|
@ -104,9 +104,24 @@ solo mergehex bootloader.hex solo.hex bundle.hex
|
|||||||
|
|
||||||
`bundle.hex` is our complete firmware build. Note it is in this step that you can
|
`bundle.hex` is our complete firmware build. Note it is in this step that you can
|
||||||
include a custom attestation certificate or lock the device from debugging/DFU.
|
include a custom attestation certificate or lock the device from debugging/DFU.
|
||||||
By default the "hacker" attestation certifcate and key is used.
|
By default the "hacker" attestation certifcate and key is used. Use the `--lock` flag
|
||||||
|
to make this permanent.
|
||||||
|
|
||||||
```
|
```
|
||||||
|
solo mergehex \
|
||||||
|
--attestation-key "0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF" \
|
||||||
|
--attestation-cert attestation.der \
|
||||||
|
solo.hex \
|
||||||
|
bootloader.hex \
|
||||||
|
bundle.hex
|
||||||
|
```
|
||||||
|
|
||||||
|
**Warning**: If you use `--lock`, this will permanently lock the device to this new bootloader. You
|
||||||
|
won't be able to program the bootloader again or be able to connect a hardware debugger.
|
||||||
|
The new bootloader may be able to accept (signed) updates still, depending on how you configured it.
|
||||||
|
|
||||||
|
```
|
||||||
|
# Permanent!
|
||||||
solo mergehex \
|
solo mergehex \
|
||||||
--attestation-key "0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF" \
|
--attestation-key "0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF" \
|
||||||
--attestation-cert attestation.der \
|
--attestation-cert attestation.der \
|
||||||
@ -118,9 +133,5 @@ solo mergehex \
|
|||||||
|
|
||||||
See [here for more information on custom attestation](/solo/customization/).
|
See [here for more information on custom attestation](/solo/customization/).
|
||||||
|
|
||||||
If you use `--lock`, this will permanently lock the device to this new bootloader. You
|
|
||||||
won't be able to program the bootloader again or be able to connect a hardware debugger.
|
|
||||||
The new bootloader may be able to accept (signed) updates still, depending on how you configured it.
|
|
||||||
|
|
||||||
To learn more about normal updates or a "full" update, you should [read more on Solo's boot stages](/solo/bootloader-mode).
|
To learn more about normal updates or a "full" update, you should [read more on Solo's boot stages](/solo/bootloader-mode).
|
||||||
|
|
||||||
|
@ -45,7 +45,7 @@ email=example@example.com
|
|||||||
openssl ecparam -genkey -name "$curve" -out root_key.pem -rand seed.bin
|
openssl ecparam -genkey -name "$curve" -out root_key.pem -rand seed.bin
|
||||||
|
|
||||||
# generate a "signing request"
|
# generate a "signing request"
|
||||||
openssl req -new -key root_key.pem -out root_key.pem.csr -subj "/C=$country/ST=$state/O=$organization/OU=$unit/CN=example.com/emailAddress=$email"
|
openssl req -new -key root_key.pem -out root_key.pem.csr -subj "/C=$country/ST=$state/O=$organization/OU=$unit/CN=$CN/emailAddress=$email"
|
||||||
|
|
||||||
# self sign the request
|
# self sign the request
|
||||||
openssl x509 -trustout -req -days 18250 -in root_key.pem.csr -signkey root_key.pem -out root_cert.pem -sha256
|
openssl x509 -trustout -req -days 18250 -in root_key.pem.csr -signkey root_key.pem -out root_cert.pem -sha256
|
||||||
@ -74,7 +74,7 @@ Note you must use a prime256v1 curve for this step, and you must leave the unit/
|
|||||||
country=US
|
country=US
|
||||||
state=Maine
|
state=Maine
|
||||||
organization=OpenSourceSecurity
|
organization=OpenSourceSecurity
|
||||||
unit="Authenticator Attestation"
|
unit="Authenticator Attestation" # MUST KEEP THIS AS "Authenticator Attestation" for FIDO2.
|
||||||
CN=example.com
|
CN=example.com
|
||||||
email=example@example.com
|
email=example@example.com
|
||||||
|
|
||||||
@ -82,7 +82,7 @@ email=example@example.com
|
|||||||
openssl ecparam -genkey -name "$curve" -out device_key.pem -rand seed.bin
|
openssl ecparam -genkey -name "$curve" -out device_key.pem -rand seed.bin
|
||||||
|
|
||||||
# generate a "signing request"
|
# generate a "signing request"
|
||||||
openssl req -new -key device_key.pem -out device_key.pem.csr -subj "/C=$country/ST=$state/O=$organization/OU=$unit/CN=example.com/emailAddress=$email"
|
openssl req -new -key device_key.pem -out device_key.pem.csr -subj "/C=$country/ST=$state/O=$organization/OU=$unit/CN=$CN/emailAddress=$email"
|
||||||
|
|
||||||
# sign the request
|
# sign the request
|
||||||
openssl x509 -req -days 18250 -in device_key.pem.csr -extfile v3.ext -CA root_cert.pem -CAkey root_key.pem -set_serial 01 -out device_cert.pem -sha256
|
openssl x509 -req -days 18250 -in device_key.pem.csr -extfile v3.ext -CA root_cert.pem -CAkey root_key.pem -set_serial 01 -out device_cert.pem -sha256
|
||||||
@ -119,7 +119,7 @@ First, [Build your solo application and bootloader](/solo/building).
|
|||||||
Print your attestation key in a hex string format. Using our utility script:
|
Print your attestation key in a hex string format. Using our utility script:
|
||||||
|
|
||||||
```
|
```
|
||||||
python tools/print_x_y.py device_key.pem
|
python3 tools/gencert/print_x_y.py device_key.pem
|
||||||
```
|
```
|
||||||
|
|
||||||
Merge the `bootloader.hex`, `solo.hex`, attestion key, and certificate into one firmware file.
|
Merge the `bootloader.hex`, `solo.hex`, attestion key, and certificate into one firmware file.
|
||||||
@ -134,6 +134,8 @@ solo mergehex \
|
|||||||
bundle.hex
|
bundle.hex
|
||||||
```
|
```
|
||||||
|
|
||||||
|
**Warning**: Using the `--lock` flag prevents the DFU from being accessed on the device again. It's recommended to try first without the `--lock` flag to make sure it works.
|
||||||
|
|
||||||
Now you have a newly created `bundle.hex` file with a custom attestation key and cert. You can [program this `bundle.hex` file
|
Now you have a newly created `bundle.hex` file with a custom attestation key and cert. You can [program this `bundle.hex` file
|
||||||
with Solo in DFU mode](/solo/programming#procedure).
|
with Solo in DFU mode](/solo/programming#procedure).
|
||||||
|
|
||||||
|
871
fido2/ctap.c
871
fido2/ctap.c
File diff suppressed because it is too large
Load Diff
67
fido2/ctap.h
67
fido2/ctap.h
@ -16,7 +16,9 @@
|
|||||||
#define CTAP_CLIENT_PIN 0x06
|
#define CTAP_CLIENT_PIN 0x06
|
||||||
#define CTAP_RESET 0x07
|
#define CTAP_RESET 0x07
|
||||||
#define GET_NEXT_ASSERTION 0x08
|
#define GET_NEXT_ASSERTION 0x08
|
||||||
|
#define CTAP_CBOR_CRED_MGMT 0x0A
|
||||||
#define CTAP_VENDOR_FIRST 0x40
|
#define CTAP_VENDOR_FIRST 0x40
|
||||||
|
#define CTAP_CBOR_CRED_MGMT_PRE 0x41
|
||||||
#define CTAP_VENDOR_LAST 0xBF
|
#define CTAP_VENDOR_LAST 0xBF
|
||||||
|
|
||||||
#define MC_clientDataHash 0x01
|
#define MC_clientDataHash 0x01
|
||||||
@ -37,6 +39,19 @@
|
|||||||
#define GA_pinAuth 0x06
|
#define GA_pinAuth 0x06
|
||||||
#define GA_pinProtocol 0x07
|
#define GA_pinProtocol 0x07
|
||||||
|
|
||||||
|
#define CM_cmd 0x01
|
||||||
|
#define CM_cmdMetadata 0x01
|
||||||
|
#define CM_cmdRPBegin 0x02
|
||||||
|
#define CM_cmdRPNext 0x03
|
||||||
|
#define CM_cmdRKBegin 0x04
|
||||||
|
#define CM_cmdRKNext 0x05
|
||||||
|
#define CM_cmdRKDelete 0x06
|
||||||
|
#define CM_subCommandParams 0x02
|
||||||
|
#define CM_subCommandRpId 0x01
|
||||||
|
#define CM_subCommandCred 0x02
|
||||||
|
#define CM_pinProtocol 0x03
|
||||||
|
#define CM_pinAuth 0x04
|
||||||
|
|
||||||
#define CP_pinProtocol 0x01
|
#define CP_pinProtocol 0x01
|
||||||
#define CP_subCommand 0x02
|
#define CP_subCommand 0x02
|
||||||
#define CP_cmdGetRetries 0x01
|
#define CP_cmdGetRetries 0x01
|
||||||
@ -58,6 +73,11 @@
|
|||||||
#define EXT_HMAC_SECRET_REQUESTED 0x01
|
#define EXT_HMAC_SECRET_REQUESTED 0x01
|
||||||
#define EXT_HMAC_SECRET_PARSED 0x02
|
#define EXT_HMAC_SECRET_PARSED 0x02
|
||||||
|
|
||||||
|
#define EXT_CRED_PROTECT_INVALID 0x00
|
||||||
|
#define EXT_CRED_PROTECT_OPTIONAL 0x01
|
||||||
|
#define EXT_CRED_PROTECT_OPTIONAL_WITH_CREDID 0x02
|
||||||
|
#define EXT_CRED_PROTECT_REQUIRED 0x03
|
||||||
|
|
||||||
#define RESP_versions 0x1
|
#define RESP_versions 0x1
|
||||||
#define RESP_extensions 0x2
|
#define RESP_extensions 0x2
|
||||||
#define RESP_aaguid 0x3
|
#define RESP_aaguid 0x3
|
||||||
@ -141,16 +161,29 @@ typedef struct
|
|||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
uint8_t tag[CREDENTIAL_TAG_SIZE];
|
uint8_t tag[CREDENTIAL_TAG_SIZE];
|
||||||
uint8_t nonce[CREDENTIAL_NONCE_SIZE];
|
union {
|
||||||
|
uint8_t nonce[CREDENTIAL_NONCE_SIZE];
|
||||||
|
struct {
|
||||||
|
uint8_t _pad[CREDENTIAL_NONCE_SIZE - 4];
|
||||||
|
uint32_t value;
|
||||||
|
}__attribute__((packed)) metadata;
|
||||||
|
}__attribute__((packed)) entropy;
|
||||||
uint8_t rpIdHash[32];
|
uint8_t rpIdHash[32];
|
||||||
uint32_t count;
|
uint32_t count;
|
||||||
}__attribute__((packed)) CredentialId;
|
}__attribute__((packed)) CredentialId;
|
||||||
|
|
||||||
struct Credential {
|
struct __attribute__((packed)) Credential {
|
||||||
CredentialId id;
|
CredentialId id;
|
||||||
CTAP_userEntity user;
|
CTAP_userEntity user;
|
||||||
};
|
};
|
||||||
typedef struct Credential CTAP_residentKey;
|
typedef struct {
|
||||||
|
CredentialId id;
|
||||||
|
CTAP_userEntity user;
|
||||||
|
|
||||||
|
// Maximum amount of "extra" space in resident key.
|
||||||
|
uint8_t rpId[48];
|
||||||
|
uint8_t rpIdSize;
|
||||||
|
} __attribute__((packed)) CTAP_residentKey;
|
||||||
|
|
||||||
typedef struct
|
typedef struct
|
||||||
{
|
{
|
||||||
@ -217,6 +250,7 @@ typedef struct
|
|||||||
{
|
{
|
||||||
uint8_t hmac_secret_present;
|
uint8_t hmac_secret_present;
|
||||||
CTAP_hmac_secret hmac_secret;
|
CTAP_hmac_secret hmac_secret;
|
||||||
|
uint32_t cred_protect;
|
||||||
} CTAP_extensions;
|
} CTAP_extensions;
|
||||||
|
|
||||||
typedef struct
|
typedef struct
|
||||||
@ -285,6 +319,26 @@ typedef struct
|
|||||||
|
|
||||||
} CTAP_getAssertion;
|
} CTAP_getAssertion;
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
int cmd;
|
||||||
|
struct {
|
||||||
|
uint8_t rpIdHash[32];
|
||||||
|
CTAP_credentialDescriptor credentialDescriptor;
|
||||||
|
} subCommandParams;
|
||||||
|
|
||||||
|
struct {
|
||||||
|
uint8_t cmd;
|
||||||
|
uint8_t subCommandParamsCborCopy[sizeof(CTAP_credentialDescriptor) + 16];
|
||||||
|
} hashed;
|
||||||
|
uint32_t subCommandParamsCborSize;
|
||||||
|
|
||||||
|
uint8_t pinAuth[16];
|
||||||
|
uint8_t pinAuthPresent;
|
||||||
|
int pinProtocol;
|
||||||
|
} CTAP_credMgmt;
|
||||||
|
|
||||||
|
|
||||||
typedef struct
|
typedef struct
|
||||||
{
|
{
|
||||||
int pinProtocol;
|
int pinProtocol;
|
||||||
@ -303,7 +357,12 @@ typedef struct
|
|||||||
|
|
||||||
|
|
||||||
struct _getAssertionState {
|
struct _getAssertionState {
|
||||||
CTAP_authDataHeader authData;
|
// Room for both authData struct and extensions
|
||||||
|
struct {
|
||||||
|
CTAP_authDataHeader authData;
|
||||||
|
uint8_t extensions[80];
|
||||||
|
} __attribute__((packed)) buf;
|
||||||
|
CTAP_extensions extensions;
|
||||||
uint8_t clientDataHash[CLIENT_DATA_HASH_SIZE];
|
uint8_t clientDataHash[CLIENT_DATA_HASH_SIZE];
|
||||||
CTAP_credentialDescriptor creds[ALLOW_LIST_MAX_SIZE];
|
CTAP_credentialDescriptor creds[ALLOW_LIST_MAX_SIZE];
|
||||||
uint8_t lastcmd;
|
uint8_t lastcmd;
|
||||||
|
@ -666,8 +666,8 @@ uint8_t ctap_parse_extensions(CborValue * val, CTAP_extensions * ext)
|
|||||||
if (ret == CborErrorOutOfMemory)
|
if (ret == CborErrorOutOfMemory)
|
||||||
{
|
{
|
||||||
printf2(TAG_ERR,"Error, rp map key is too large. Ignoring.\n");
|
printf2(TAG_ERR,"Error, rp map key is too large. Ignoring.\n");
|
||||||
cbor_value_advance(&map);
|
check_ret( cbor_value_advance(&map) );
|
||||||
cbor_value_advance(&map);
|
check_ret( cbor_value_advance(&map) );
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
check_ret(ret);
|
check_ret(ret);
|
||||||
@ -698,6 +698,14 @@ uint8_t ctap_parse_extensions(CborValue * val, CTAP_extensions * ext)
|
|||||||
printf1(TAG_RED, "warning: hmac_secret request ignored for being wrong type\r\n");
|
printf1(TAG_RED, "warning: hmac_secret request ignored for being wrong type\r\n");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
else if (strncmp(key, "credProtect",11) == 0) {
|
||||||
|
if (cbor_value_get_type(&map) == CborIntegerType) {
|
||||||
|
ret = cbor_value_get_int(&map, (int*)&ext->cred_protect);
|
||||||
|
check_ret(ret);
|
||||||
|
} else {
|
||||||
|
printf1(TAG_RED, "warning: credProtect request ignored for being wrong type\r\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
ret = cbor_value_advance(&map);
|
ret = cbor_value_advance(&map);
|
||||||
check_ret(ret);
|
check_ret(ret);
|
||||||
@ -871,7 +879,7 @@ uint8_t ctap_parse_make_credential(CTAP_makeCredential * MC, CborEncoder * encod
|
|||||||
{
|
{
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
cbor_value_advance(&map);
|
ret = cbor_value_advance(&map);
|
||||||
check_ret(ret);
|
check_ret(ret);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -999,6 +1007,163 @@ uint8_t parse_allow_list(CTAP_getAssertion * GA, CborValue * it)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static uint8_t parse_cred_mgmt_subcommandparams(CborValue * val, CTAP_credMgmt * CM)
|
||||||
|
{
|
||||||
|
size_t map_length;
|
||||||
|
int key;
|
||||||
|
int ret;
|
||||||
|
unsigned int i;
|
||||||
|
CborValue map;
|
||||||
|
size_t sz = 32;
|
||||||
|
|
||||||
|
if (cbor_value_get_type(val) != CborMapType)
|
||||||
|
{
|
||||||
|
printf2(TAG_ERR,"error, wrong type\n");
|
||||||
|
return CTAP2_ERR_INVALID_CBOR_TYPE;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
ret = cbor_value_enter_container(val,&map);
|
||||||
|
check_ret(ret);
|
||||||
|
|
||||||
|
const uint8_t * start_byte = cbor_value_get_next_byte(&map) - 1;
|
||||||
|
|
||||||
|
ret = cbor_value_get_map_length(val, &map_length);
|
||||||
|
check_ret(ret);
|
||||||
|
|
||||||
|
for (i = 0; i < map_length; i++)
|
||||||
|
{
|
||||||
|
if (cbor_value_get_type(&map) != CborIntegerType)
|
||||||
|
{
|
||||||
|
printf2(TAG_ERR,"Error, expecting integer type for map key, got %s\n", cbor_value_get_type_string(&map));
|
||||||
|
return CTAP2_ERR_INVALID_CBOR_TYPE;
|
||||||
|
}
|
||||||
|
ret = cbor_value_get_int(&map, &key);
|
||||||
|
check_ret(ret);
|
||||||
|
ret = cbor_value_advance(&map);
|
||||||
|
check_ret(ret);
|
||||||
|
switch(key)
|
||||||
|
{
|
||||||
|
case CM_subCommandRpId:
|
||||||
|
ret = cbor_value_copy_byte_string(&map, CM->subCommandParams.rpIdHash, &sz, NULL);
|
||||||
|
if (ret == CborErrorOutOfMemory)
|
||||||
|
{
|
||||||
|
printf2(TAG_ERR,"Error, map key is too large\n");
|
||||||
|
return CTAP2_ERR_LIMIT_EXCEEDED;
|
||||||
|
}
|
||||||
|
check_ret(ret);
|
||||||
|
break;
|
||||||
|
case CM_subCommandCred:
|
||||||
|
ret = parse_credential_descriptor(&map, &CM->subCommandParams.credentialDescriptor);
|
||||||
|
check_ret(ret);;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
ret = cbor_value_advance(&map);
|
||||||
|
check_ret(ret);
|
||||||
|
}
|
||||||
|
|
||||||
|
const uint8_t * end_byte = cbor_value_get_next_byte(&map);
|
||||||
|
|
||||||
|
uint32_t length = (uint32_t)end_byte - (uint32_t)start_byte;
|
||||||
|
if (length > sizeof(CM->hashed.subCommandParamsCborCopy))
|
||||||
|
{
|
||||||
|
return CTAP2_ERR_LIMIT_EXCEEDED;
|
||||||
|
}
|
||||||
|
// Copy the details that were hashed so they can be verified later.
|
||||||
|
memmove(CM->hashed.subCommandParamsCborCopy, start_byte, length);
|
||||||
|
CM->subCommandParamsCborSize = length;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t ctap_parse_cred_mgmt(CTAP_credMgmt * CM, uint8_t * request, int length)
|
||||||
|
{
|
||||||
|
int ret;
|
||||||
|
unsigned int i;
|
||||||
|
int key;
|
||||||
|
size_t map_length;
|
||||||
|
CborParser parser;
|
||||||
|
CborValue it,map;
|
||||||
|
|
||||||
|
memset(CM, 0, sizeof(CTAP_credMgmt));
|
||||||
|
ret = cbor_parser_init(request, length, CborValidateCanonicalFormat, &parser, &it);
|
||||||
|
check_ret(ret);
|
||||||
|
|
||||||
|
CborType type = cbor_value_get_type(&it);
|
||||||
|
if (type != CborMapType)
|
||||||
|
{
|
||||||
|
printf2(TAG_ERR,"Error, expecting cbor map\n");
|
||||||
|
return CTAP2_ERR_INVALID_CBOR_TYPE;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
ret = cbor_value_enter_container(&it,&map);
|
||||||
|
check_ret(ret);
|
||||||
|
|
||||||
|
ret = cbor_value_get_map_length(&it, &map_length);
|
||||||
|
check_ret(ret);
|
||||||
|
|
||||||
|
printf1(TAG_PARSE, "CM map has %d elements\n", map_length);
|
||||||
|
|
||||||
|
for (i = 0; i < map_length; i++)
|
||||||
|
{
|
||||||
|
type = cbor_value_get_type(&map);
|
||||||
|
if (type != CborIntegerType)
|
||||||
|
{
|
||||||
|
printf2(TAG_ERR,"Error, expecting int for map key\n");
|
||||||
|
return CTAP2_ERR_INVALID_CBOR_TYPE;
|
||||||
|
}
|
||||||
|
ret = cbor_value_get_int_checked(&map, &key);
|
||||||
|
check_ret(ret);
|
||||||
|
|
||||||
|
ret = cbor_value_advance(&map);
|
||||||
|
check_ret(ret);
|
||||||
|
|
||||||
|
switch(key)
|
||||||
|
{
|
||||||
|
case CM_cmd:
|
||||||
|
printf1(TAG_PARSE, "CM_cmd\n");
|
||||||
|
if (cbor_value_get_type(&map) == CborIntegerType)
|
||||||
|
{
|
||||||
|
ret = cbor_value_get_int_checked(&map, &CM->cmd);
|
||||||
|
check_ret(ret);
|
||||||
|
CM->hashed.cmd = CM->cmd;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return CTAP2_ERR_INVALID_CBOR_TYPE;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case CM_subCommandParams:
|
||||||
|
printf1(TAG_PARSE, "CM_subCommandParams\n");
|
||||||
|
ret = parse_cred_mgmt_subcommandparams(&map, CM);
|
||||||
|
check_ret(ret);
|
||||||
|
break;
|
||||||
|
case CM_pinProtocol:
|
||||||
|
printf1(TAG_PARSE, "CM_pinProtocol\n");
|
||||||
|
if (cbor_value_get_type(&map) == CborIntegerType)
|
||||||
|
{
|
||||||
|
ret = cbor_value_get_int_checked(&map, &CM->pinProtocol);
|
||||||
|
check_ret(ret);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return CTAP2_ERR_INVALID_CBOR_TYPE;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case CM_pinAuth:
|
||||||
|
printf1(TAG_PARSE, "CM_pinAuth\n");
|
||||||
|
ret = parse_fixed_byte_string(&map, CM->pinAuth, 16);
|
||||||
|
check_retr(ret);
|
||||||
|
CM->pinAuthPresent = 1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
ret = cbor_value_advance(&map);
|
||||||
|
check_ret(ret);
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
uint8_t ctap_parse_get_assertion(CTAP_getAssertion * GA, uint8_t * request, int length)
|
uint8_t ctap_parse_get_assertion(CTAP_getAssertion * GA, uint8_t * request, int length)
|
||||||
{
|
{
|
||||||
@ -1132,7 +1297,7 @@ uint8_t ctap_parse_get_assertion(CTAP_getAssertion * GA, uint8_t * request, int
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
cbor_value_advance(&map);
|
ret = cbor_value_advance(&map);
|
||||||
check_ret(ret);
|
check_ret(ret);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1353,11 +1518,21 @@ uint8_t ctap_parse_client_pin(CTAP_clientPin * CP, uint8_t * request, int length
|
|||||||
break;
|
break;
|
||||||
case CP_getKeyAgreement:
|
case CP_getKeyAgreement:
|
||||||
printf1(TAG_CP,"CP_getKeyAgreement\n");
|
printf1(TAG_CP,"CP_getKeyAgreement\n");
|
||||||
|
if (cbor_value_get_type(&map) != CborBooleanType)
|
||||||
|
{
|
||||||
|
printf2(TAG_ERR,"Error, expecting cbor boolean\n");
|
||||||
|
return CTAP2_ERR_INVALID_CBOR_TYPE;
|
||||||
|
}
|
||||||
ret = cbor_value_get_boolean(&map, &CP->getKeyAgreement);
|
ret = cbor_value_get_boolean(&map, &CP->getKeyAgreement);
|
||||||
check_ret(ret);
|
check_ret(ret);
|
||||||
break;
|
break;
|
||||||
case CP_getRetries:
|
case CP_getRetries:
|
||||||
printf1(TAG_CP,"CP_getRetries\n");
|
printf1(TAG_CP,"CP_getRetries\n");
|
||||||
|
if (cbor_value_get_type(&map) != CborBooleanType)
|
||||||
|
{
|
||||||
|
printf2(TAG_ERR,"Error, expecting cbor boolean\n");
|
||||||
|
return CTAP2_ERR_INVALID_CBOR_TYPE;
|
||||||
|
}
|
||||||
ret = cbor_value_get_boolean(&map, &CP->getRetries);
|
ret = cbor_value_get_boolean(&map, &CP->getRetries);
|
||||||
check_ret(ret);
|
check_ret(ret);
|
||||||
break;
|
break;
|
||||||
|
@ -35,6 +35,7 @@ uint8_t parse_cose_key(CborValue * it, COSE_key * cose);
|
|||||||
|
|
||||||
uint8_t ctap_parse_make_credential(CTAP_makeCredential * MC, CborEncoder * encoder, uint8_t * request, int length);
|
uint8_t ctap_parse_make_credential(CTAP_makeCredential * MC, CborEncoder * encoder, uint8_t * request, int length);
|
||||||
uint8_t ctap_parse_get_assertion(CTAP_getAssertion * GA, uint8_t * request, int length);
|
uint8_t ctap_parse_get_assertion(CTAP_getAssertion * GA, uint8_t * request, int length);
|
||||||
|
uint8_t ctap_parse_cred_mgmt(CTAP_credMgmt * CM, uint8_t * request, int length);
|
||||||
uint8_t ctap_parse_client_pin(CTAP_clientPin * CP, uint8_t * request, int length);
|
uint8_t ctap_parse_client_pin(CTAP_clientPin * CP, uint8_t * request, int length);
|
||||||
uint8_t parse_credential_descriptor(CborValue * arr, CTAP_credentialDescriptor * cred);
|
uint8_t parse_credential_descriptor(CborValue * arr, CTAP_credentialDescriptor * cred);
|
||||||
|
|
||||||
|
@ -542,6 +542,9 @@ extern void _check_ret(CborError ret, int line, const char * filename);
|
|||||||
|
|
||||||
uint8_t ctaphid_custom_command(int len, CTAP_RESPONSE * ctap_resp, CTAPHID_WRITE_BUFFER * wb);
|
uint8_t ctaphid_custom_command(int len, CTAP_RESPONSE * ctap_resp, CTAPHID_WRITE_BUFFER * wb);
|
||||||
|
|
||||||
|
|
||||||
|
extern void solo_lock_if_not_already();
|
||||||
|
|
||||||
uint8_t ctaphid_handle_packet(uint8_t * pkt_raw)
|
uint8_t ctaphid_handle_packet(uint8_t * pkt_raw)
|
||||||
{
|
{
|
||||||
uint8_t cmd = 0;
|
uint8_t cmd = 0;
|
||||||
@ -731,6 +734,11 @@ uint8_t ctaphid_custom_command(int len, CTAP_RESPONSE * ctap_resp, CTAPHID_WRITE
|
|||||||
ctaphid_write(wb, NULL, 0);
|
ctaphid_write(wb, NULL, 0);
|
||||||
return 1;
|
return 1;
|
||||||
#endif
|
#endif
|
||||||
|
#if defined(SOLO)
|
||||||
|
case CTAPHID_REBOOT:
|
||||||
|
device_reboot();
|
||||||
|
return 1;
|
||||||
|
#endif
|
||||||
|
|
||||||
#if !defined(IS_BOOTLOADER)
|
#if !defined(IS_BOOTLOADER)
|
||||||
case CTAPHID_GETRNG:
|
case CTAPHID_GETRNG:
|
||||||
@ -762,34 +770,51 @@ uint8_t ctaphid_custom_command(int len, CTAP_RESPONSE * ctap_resp, CTAPHID_WRITE
|
|||||||
return 1;
|
return 1;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
// Remove on next release
|
||||||
|
#if !defined(IS_BOOTLOADER) && defined(SOLO)
|
||||||
|
case 0x99:
|
||||||
|
solo_lock_if_not_already();
|
||||||
|
wb->bcnt = 0;
|
||||||
|
ctaphid_write(wb, NULL, 0);
|
||||||
|
return 1;
|
||||||
|
break;
|
||||||
|
#endif
|
||||||
|
|
||||||
#if !defined(IS_BOOTLOADER) && (defined(SOLO_EXPERIMENTAL))
|
#if !defined(IS_BOOTLOADER) && (defined(SOLO_EXPERIMENTAL))
|
||||||
case CTAPHID_LOADKEY:
|
case CTAPHID_LOADKEY:
|
||||||
/**
|
/**
|
||||||
* Load external key. Useful for enabling backups.
|
* Load external key. Useful for enabling backups.
|
||||||
* bytes: 4 96
|
* bytes: 4 4 96
|
||||||
* payload: | counter_increase (BE) | master_key |
|
* payload: version [maj rev patch RFU]| counter_replacement (BE) | master_key |
|
||||||
*
|
*
|
||||||
* Counter should be increased by a large amount, e.g. (0x10000000)
|
* Counter should be increased by a large amount, e.g. (0x10000000)
|
||||||
* to outdo any previously lost/broken keys.
|
* to outdo any previously lost/broken keys.
|
||||||
*/
|
*/
|
||||||
printf1(TAG_HID,"CTAPHID_LOADKEY\n");
|
printf1(TAG_HID,"CTAPHID_LOADKEY\n");
|
||||||
if (len != 100)
|
if (len != 104)
|
||||||
{
|
{
|
||||||
printf2(TAG_ERR,"Error, invalid length.\n");
|
printf2(TAG_ERR,"Error, invalid length.\n");
|
||||||
ctaphid_send_error(wb->cid, CTAP1_ERR_INVALID_LENGTH);
|
ctaphid_send_error(wb->cid, CTAP1_ERR_INVALID_LENGTH);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
param = ctap_buffer[0] << 16;
|
||||||
|
param |= ctap_buffer[1] << 8;
|
||||||
|
param |= ctap_buffer[2] << 0;
|
||||||
|
if (param != 0){
|
||||||
|
ctaphid_send_error(wb->cid, CTAP2_ERR_UNSUPPORTED_OPTION);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
// Ask for THREE button presses
|
// 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)
|
if (ctap_user_presence_test(2000) > 0)
|
||||||
if (ctap_user_presence_test(8000) > 0)
|
if (ctap_user_presence_test(2000) > 0)
|
||||||
{
|
{
|
||||||
ctap_load_external_keys(ctap_buffer + 4);
|
ctap_load_external_keys(ctap_buffer + 8);
|
||||||
param = ctap_buffer[3];
|
param = ctap_buffer[7];
|
||||||
param |= ctap_buffer[2] << 8;
|
param |= ctap_buffer[6] << 8;
|
||||||
param |= ctap_buffer[1] << 16;
|
param |= ctap_buffer[5] << 16;
|
||||||
param |= ctap_buffer[0] << 24;
|
param |= ctap_buffer[4] << 24;
|
||||||
ctap_atomic_count(param);
|
ctap_atomic_count(param);
|
||||||
|
|
||||||
wb->bcnt = 0;
|
wb->bcnt = 0;
|
||||||
|
@ -27,6 +27,7 @@
|
|||||||
#define CTAPHID_BOOT (TYPE_INIT | 0x50)
|
#define CTAPHID_BOOT (TYPE_INIT | 0x50)
|
||||||
#define CTAPHID_ENTERBOOT (TYPE_INIT | 0x51)
|
#define CTAPHID_ENTERBOOT (TYPE_INIT | 0x51)
|
||||||
#define CTAPHID_ENTERSTBOOT (TYPE_INIT | 0x52)
|
#define CTAPHID_ENTERSTBOOT (TYPE_INIT | 0x52)
|
||||||
|
#define CTAPHID_REBOOT (TYPE_INIT | 0x53)
|
||||||
#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)
|
#define CTAPHID_LOADKEY (TYPE_INIT | 0x62)
|
||||||
|
@ -185,6 +185,22 @@ __attribute__((weak)) void ctap_store_rk(int index, CTAP_residentKey * rk)
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
__attribute__((weak)) void ctap_delete_rk(int index)
|
||||||
|
{
|
||||||
|
CTAP_residentKey rk;
|
||||||
|
memset(&rk, 0xff, sizeof(CTAP_residentKey));
|
||||||
|
|
||||||
|
if (index < RK_NUM)
|
||||||
|
{
|
||||||
|
memmove(RK_STORE.rks + index, &rk, sizeof(CTAP_residentKey));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
printf1(TAG_ERR,"Out of bounds for delete_rk\r\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
__attribute__((weak)) void ctap_load_rk(int index, CTAP_residentKey * rk)
|
__attribute__((weak)) void ctap_load_rk(int index, CTAP_residentKey * rk)
|
||||||
{
|
{
|
||||||
memmove(rk, RK_STORE.rks + index, sizeof(CTAP_residentKey));
|
memmove(rk, RK_STORE.rks + index, sizeof(CTAP_residentKey));
|
||||||
|
@ -140,6 +140,13 @@ uint32_t ctap_rk_size();
|
|||||||
*/
|
*/
|
||||||
void ctap_store_rk(int index,CTAP_residentKey * rk);
|
void ctap_store_rk(int index,CTAP_residentKey * rk);
|
||||||
|
|
||||||
|
/** Delete a resident key from an index.
|
||||||
|
* @param index to delete resident key from. Has no effect if no RK exists at index.
|
||||||
|
*
|
||||||
|
* *Optional*, if not implemented, operates on non-persistant RK's.
|
||||||
|
*/
|
||||||
|
void ctap_delete_rk(int index);
|
||||||
|
|
||||||
/** Read a resident key from an index into memory
|
/** Read a resident key from an index into memory
|
||||||
* @param index to read resident key from.
|
* @param index to read resident key from.
|
||||||
* @param rk pointer to resident key structure to write into with RK.
|
* @param rk pointer to resident key structure to write into with RK.
|
||||||
|
@ -51,6 +51,7 @@ struct logtag tagtable[] = {
|
|||||||
{TAG_NFC,"[1;38mNFC[0m"},
|
{TAG_NFC,"[1;38mNFC[0m"},
|
||||||
{TAG_NFC_APDU, "NAPDU"},
|
{TAG_NFC_APDU, "NAPDU"},
|
||||||
{TAG_CCID, "CCID"},
|
{TAG_CCID, "CCID"},
|
||||||
|
{TAG_CM, "CRED_MGMT"},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
@ -48,6 +48,7 @@ typedef enum
|
|||||||
TAG_NFC = (1 << 19),
|
TAG_NFC = (1 << 19),
|
||||||
TAG_NFC_APDU = (1 << 20),
|
TAG_NFC_APDU = (1 << 20),
|
||||||
TAG_CCID = (1 << 21),
|
TAG_CCID = (1 << 21),
|
||||||
|
TAG_CM = (1 << 22),
|
||||||
|
|
||||||
TAG_NO_TAG = (1UL << 30),
|
TAG_NO_TAG = (1UL << 30),
|
||||||
TAG_FILENO = (1UL << 31)
|
TAG_FILENO = (1UL << 31)
|
||||||
|
@ -204,7 +204,7 @@ int8_t u2f_authenticate_credential(struct u2f_key_handle * kh, uint8_t key_handl
|
|||||||
printf1(TAG_U2F, "APPID does not match rpIdHash.\n");
|
printf1(TAG_U2F, "APPID does not match rpIdHash.\n");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
make_auth_tag(appid, cred->nonce, cred->count, tag);
|
make_auth_tag(appid, (uint8_t*)&cred->entropy, cred->count, tag);
|
||||||
|
|
||||||
if (memcmp(cred->tag, tag, CREDENTIAL_TAG_SIZE) == 0){
|
if (memcmp(cred->tag, tag, CREDENTIAL_TAG_SIZE) == 0){
|
||||||
return 1;
|
return 1;
|
||||||
|
@ -1,12 +1,17 @@
|
|||||||
#include "version.h"
|
#include "version.h"
|
||||||
|
#include "app.h"
|
||||||
|
|
||||||
|
const version_t firmware_version
|
||||||
|
#ifdef SOLO
|
||||||
|
__attribute__ ((section (".flag"))) __attribute__ ((__used__))
|
||||||
|
#endif
|
||||||
|
= {
|
||||||
|
.major = SOLO_VERSION_MAJ,
|
||||||
|
.minor = SOLO_VERSION_MIN,
|
||||||
|
.patch = SOLO_VERSION_PATCH,
|
||||||
|
.reserved = 0
|
||||||
|
};
|
||||||
|
|
||||||
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
|
// from tinycbor, for a quick static_assert
|
||||||
#include <compilersupport_p.h>
|
#include <compilersupport_p.h>
|
||||||
|
@ -449,6 +449,12 @@ void ctap_store_rk(int index, CTAP_residentKey * rk)
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ctap_delete_rk(int index)
|
||||||
|
{
|
||||||
|
CTAP_residentKey rk;
|
||||||
|
memset(&rk, 0xff, sizeof(CTAP_residentKey));
|
||||||
|
memmove(RK_STORE.rks + index, &rk, sizeof(CTAP_residentKey));
|
||||||
|
}
|
||||||
|
|
||||||
void ctap_load_rk(int index, CTAP_residentKey * rk)
|
void ctap_load_rk(int index, CTAP_residentKey * rk)
|
||||||
{
|
{
|
||||||
|
@ -50,7 +50,7 @@ typedef struct {
|
|||||||
uint8_t payload[255 - 10];
|
uint8_t payload[255 - 10];
|
||||||
} __attribute__((packed)) BootloaderReq;
|
} __attribute__((packed)) BootloaderReq;
|
||||||
|
|
||||||
uint8_t * last_written_app_address;
|
uint8_t * last_written_app_address = 0;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Erase all application pages. **APPLICATION_END_PAGE excluded**.
|
* Erase all application pages. **APPLICATION_END_PAGE excluded**.
|
||||||
@ -58,7 +58,7 @@ uint8_t * last_written_app_address;
|
|||||||
static void erase_application()
|
static void erase_application()
|
||||||
{
|
{
|
||||||
int page;
|
int page;
|
||||||
last_written_app_address = (uint8_t*) APPLICATION_START_ADDR;
|
last_written_app_address = (uint8_t*) 0;
|
||||||
for(page = APPLICATION_START_PAGE; page < APPLICATION_END_PAGE; page++)
|
for(page = APPLICATION_START_PAGE; page < APPLICATION_END_PAGE; page++)
|
||||||
{
|
{
|
||||||
flash_erase_page(page);
|
flash_erase_page(page);
|
||||||
@ -114,6 +114,10 @@ int is_bootloader_disabled()
|
|||||||
bool is_firmware_version_newer_or_equal()
|
bool is_firmware_version_newer_or_equal()
|
||||||
{
|
{
|
||||||
|
|
||||||
|
if (last_written_app_address == 0) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
printf1(TAG_BOOT,"Current firmware version: %u.%u.%u.%u (%02x.%02x.%02x.%02x)\r\n",
|
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,
|
||||||
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
|
||||||
|
@ -84,4 +84,5 @@ cbor:
|
|||||||
cd ../../tinycbor/ && make clean
|
cd ../../tinycbor/ && make clean
|
||||||
cd ../../tinycbor/ && make CC="$(CC)" AR=$(AR) \
|
cd ../../tinycbor/ && make CC="$(CC)" AR=$(AR) \
|
||||||
LDFLAGS="$(LDFLAGS_LIB)" \
|
LDFLAGS="$(LDFLAGS_LIB)" \
|
||||||
CFLAGS="$(CFLAGS) -Os"
|
CFLAGS="$(CFLAGS) -Os -DCBOR_PARSER_MAX_RECURSIONS=3"
|
||||||
|
|
||||||
|
@ -61,7 +61,7 @@ SECTIONS
|
|||||||
*(.data*)
|
*(.data*)
|
||||||
. = ALIGN(8);
|
. = ALIGN(8);
|
||||||
_edata = .;
|
_edata = .;
|
||||||
} >ram AT> flash
|
} >sram2 AT> flash
|
||||||
|
|
||||||
.flag :
|
.flag :
|
||||||
{
|
{
|
||||||
|
@ -199,6 +199,20 @@ int solo_is_locked(){
|
|||||||
return tag == ATTESTATION_CONFIGURED_TAG && (device_settings & SOLO_FLAG_LOCKED) != 0;
|
return tag == ATTESTATION_CONFIGURED_TAG && (device_settings & SOLO_FLAG_LOCKED) != 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Locks solo flash from debugging. Locks on next reboot.
|
||||||
|
// This should be removed in next Solo release.
|
||||||
|
void solo_lock_if_not_already() {
|
||||||
|
uint8_t buf[2048];
|
||||||
|
|
||||||
|
memmove(buf, (uint8_t*)ATTESTATION_PAGE_ADDR, 2048);
|
||||||
|
|
||||||
|
((flash_attestation_page *)buf)->device_settings |= SOLO_FLAG_LOCKED;
|
||||||
|
|
||||||
|
flash_erase_page(ATTESTATION_PAGE);
|
||||||
|
|
||||||
|
flash_write(ATTESTATION_PAGE_ADDR, buf, 2048);
|
||||||
|
}
|
||||||
|
|
||||||
/** device_migrate
|
/** device_migrate
|
||||||
* Depending on version of device, migrates:
|
* Depending on version of device, migrates:
|
||||||
* * Moves attestation certificate to data segment.
|
* * Moves attestation certificate to data segment.
|
||||||
@ -563,7 +577,11 @@ uint32_t ctap_atomic_count(uint32_t amount)
|
|||||||
return lastc;
|
return lastc;
|
||||||
}
|
}
|
||||||
|
|
||||||
lastc += amount;
|
if (amount > 256){
|
||||||
|
lastc = amount;
|
||||||
|
} else {
|
||||||
|
lastc += amount;
|
||||||
|
}
|
||||||
|
|
||||||
if (lastc/256 > erases)
|
if (lastc/256 > erases)
|
||||||
{
|
{
|
||||||
@ -772,33 +790,28 @@ uint32_t ctap_rk_size(void)
|
|||||||
|
|
||||||
void ctap_store_rk(int index,CTAP_residentKey * rk)
|
void ctap_store_rk(int index,CTAP_residentKey * rk)
|
||||||
{
|
{
|
||||||
int page_offset = (sizeof(CTAP_residentKey) * index) / PAGE_SIZE;
|
ctap_overwrite_rk(index, rk);
|
||||||
uint32_t addr = flash_addr(page_offset + RK_START_PAGE) + ((sizeof(CTAP_residentKey)*index) % PAGE_SIZE);
|
}
|
||||||
|
|
||||||
printf1(TAG_GREEN, "storing RK %d @ %04x\r\n", index,addr);
|
void ctap_delete_rk(int index)
|
||||||
|
{
|
||||||
if (page_offset < RK_NUM_PAGES)
|
CTAP_residentKey rk;
|
||||||
{
|
memset(&rk, 0xff, sizeof(CTAP_residentKey));
|
||||||
flash_write(addr, (uint8_t*)rk, sizeof(CTAP_residentKey));
|
ctap_overwrite_rk(index, &rk);
|
||||||
//dump_hex1(TAG_GREEN,rk,sizeof(CTAP_residentKey));
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
printf2(TAG_ERR,"Out of bounds reading index %d for rk\n", index);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void ctap_load_rk(int index,CTAP_residentKey * rk)
|
void ctap_load_rk(int index,CTAP_residentKey * rk)
|
||||||
{
|
{
|
||||||
int page_offset = (sizeof(CTAP_residentKey) * index) / PAGE_SIZE;
|
int byte_offset_into_page = (sizeof(CTAP_residentKey) * (index % (PAGE_SIZE/sizeof(CTAP_residentKey))));
|
||||||
uint32_t addr = flash_addr(page_offset + RK_START_PAGE) + ((sizeof(CTAP_residentKey)*index) % PAGE_SIZE);
|
int page_offset = (index)/(PAGE_SIZE/sizeof(CTAP_residentKey));
|
||||||
|
|
||||||
|
uint32_t addr = flash_addr(page_offset + RK_START_PAGE) + byte_offset_into_page;
|
||||||
|
|
||||||
printf1(TAG_GREEN, "reading RK %d @ %04x\r\n", index, addr);
|
printf1(TAG_GREEN, "reading RK %d @ %04x\r\n", index, addr);
|
||||||
if (page_offset < RK_NUM_PAGES)
|
if (page_offset < RK_NUM_PAGES)
|
||||||
{
|
{
|
||||||
uint32_t * ptr = (uint32_t *)addr;
|
uint32_t * ptr = (uint32_t *)addr;
|
||||||
memmove((uint8_t*)rk,ptr,sizeof(CTAP_residentKey));
|
memmove((uint8_t*)rk,ptr,sizeof(CTAP_residentKey));
|
||||||
//dump_hex1(TAG_GREEN,rk,sizeof(CTAP_residentKey));
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -809,22 +822,28 @@ void ctap_load_rk(int index,CTAP_residentKey * rk)
|
|||||||
void ctap_overwrite_rk(int index,CTAP_residentKey * rk)
|
void ctap_overwrite_rk(int index,CTAP_residentKey * rk)
|
||||||
{
|
{
|
||||||
uint8_t tmppage[PAGE_SIZE];
|
uint8_t tmppage[PAGE_SIZE];
|
||||||
int page_offset = (sizeof(CTAP_residentKey) * index) / PAGE_SIZE;
|
|
||||||
int page = page_offset + RK_START_PAGE;
|
|
||||||
|
|
||||||
printf1(TAG_GREEN, "overwriting RK %d\r\n", index);
|
int byte_offset_into_page = (sizeof(CTAP_residentKey) * (index % (PAGE_SIZE/sizeof(CTAP_residentKey))));
|
||||||
|
int page_offset = (index)/(PAGE_SIZE/sizeof(CTAP_residentKey));
|
||||||
|
|
||||||
|
printf1(TAG_GREEN, "overwriting RK %d @ page %d @ addr 0x%08x-0x%08x\r\n",
|
||||||
|
index, RK_START_PAGE + page_offset,
|
||||||
|
flash_addr(RK_START_PAGE + page_offset) + byte_offset_into_page,
|
||||||
|
flash_addr(RK_START_PAGE + page_offset) + byte_offset_into_page + sizeof(CTAP_residentKey)
|
||||||
|
);
|
||||||
if (page_offset < RK_NUM_PAGES)
|
if (page_offset < RK_NUM_PAGES)
|
||||||
{
|
{
|
||||||
memmove(tmppage, (uint8_t*)flash_addr(page), PAGE_SIZE);
|
memmove(tmppage, (uint8_t*)flash_addr(RK_START_PAGE + page_offset), PAGE_SIZE);
|
||||||
|
|
||||||
memmove(tmppage + (sizeof(CTAP_residentKey) * index) % PAGE_SIZE, rk, sizeof(CTAP_residentKey));
|
memmove(tmppage + byte_offset_into_page, rk, sizeof(CTAP_residentKey));
|
||||||
flash_erase_page(page);
|
flash_erase_page(RK_START_PAGE + page_offset);
|
||||||
flash_write(flash_addr(page), tmppage, PAGE_SIZE);
|
flash_write(flash_addr(RK_START_PAGE + page_offset), tmppage, PAGE_SIZE);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
printf2(TAG_ERR,"Out of bounds reading index %d for rk\n", index);
|
printf2(TAG_ERR,"Out of bounds reading index %d for rk\n", index);
|
||||||
}
|
}
|
||||||
|
printf1(TAG_GREEN, "4\r\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
void boot_st_bootloader(void)
|
void boot_st_bootloader(void)
|
||||||
|
@ -146,12 +146,14 @@ void device_set_clock_rate(DEVICE_CLOCK_RATE param)
|
|||||||
case DEVICE_LOW_POWER_IDLE:
|
case DEVICE_LOW_POWER_IDLE:
|
||||||
SET_CLOCK_RATE0();
|
SET_CLOCK_RATE0();
|
||||||
break;
|
break;
|
||||||
|
#if !defined(IS_BOOTLOADER)
|
||||||
case DEVICE_LOW_POWER_FAST:
|
case DEVICE_LOW_POWER_FAST:
|
||||||
SET_CLOCK_RATE1();
|
SET_CLOCK_RATE1();
|
||||||
break;
|
break;
|
||||||
case DEVICE_FAST:
|
case DEVICE_FAST:
|
||||||
SET_CLOCK_RATE2();
|
SET_CLOCK_RATE2();
|
||||||
break;
|
break;
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user