Merge branch 'master' into error

pull/24/head
Conor Patrick 2018-11-04 17:15:04 -05:00 zatwierdzone przez GitHub
commit 215f53551e
Nie znaleziono w bazie danych klucza dla tego podpisu
ID klucza GPG: 4AEE18F83AFDEB23
48 zmienionych plików z 2001 dodań i 2467 usunięć

Wyświetl plik

@ -32,7 +32,7 @@ name = main
all: python-fido2 main
.PHONY: test
test:
test:
$(MAKE) -C . main
$(MAKE) -C . testgcm
./testgcm
@ -56,7 +56,7 @@ efm8prog:
efm32com:
cd './targets/efm32/GNU ARM v7.2.1 - Debug' && $(MAKE) all
efm32prog: efm32com
commander flash './targets/efm32/GNU ARM v7.2.1 - Debug/EFM32.hex' $(EFM32_DEBUGGER) -p "0x1E7FC:0x00000000:4"
commander flash './targets/efm32/GNU ARM v7.2.1 - Debug/EFM32.hex' $(EFM32_DEBUGGER) -p "0x1E7FC:0x00000000:4"
efm32read: efm32com
commander swo read $(EFM32_DEBUGGER)
efm32bootprog: efm32com
@ -65,10 +65,10 @@ efm32bootprog: efm32com
$(name): $(obj) $(LIBCBOR)
$(CC) $(LDFLAGS) -o $@ $(obj) $(LDFLAGS)
crypto/aes-gcm/aes_gcm.o:
crypto/aes-gcm/aes_gcm.o:
$(CC) -c crypto/aes-gcm/aes_gcm.c $(CFLAGS) -DTEST -o crypto/aes-gcm/aes_gcm.o
testgcm: $(obj) $(LIBCBOR) crypto/aes-gcm/aes_gcm.o
testgcm: $(obj) $(LIBCBOR) crypto/aes-gcm/aes_gcm.o
$(CC) -c fido2/main.c $(CFLAGS) -DTEST -o fido2/main.o
$(CC) $(LDFLAGS) -o $@ $^ $(LDFLAGS)
@ -87,11 +87,11 @@ venv:
echo " pip install virtualenv" ;\
fi
virtualenv venv
./venv/bin/pip install wheel
./venv/bin/pip install wheel
.PHONY: python-fido2
python-fido2: venv
cd python-fido2/ && ../venv/bin/python setup.py install
cd python-fido2/ && ../venv/bin/python setup.py install
venv/bin/mkdocs: venv
./venv/bin/pip install mkdocs mkdocs-material
@ -112,4 +112,3 @@ clean:
fi ;\
done
rm -rf venv

Wyświetl plik

@ -51,7 +51,7 @@ bulk order and provide open source security tokens for everyone that is interest
Clone solo and build it
```bash
git clone https://github.com/SoloKeysSec/solo
git clone --recurse-submodules https://github.com/SoloKeysSec/solo
cd solo/
make all

Wyświetl plik

@ -0,0 +1,40 @@
# Overview of firmware
This is a high level overview of the code. We aim to make the code self documenting
and easy to understand, especially when paired with a high level overview.
## FIDO2 codebase
* main.c - calls high level functions and implements event loop.
* ctaphid.c - implements [USBHID protocol](https://fidoalliance.org/specs/fido-v2.0-id-20180227/fido-client-to-authenticator-protocol-v2.0-id-20180227.html#usb) for FIDO.
* u2f.c - implements [U2F protocol](https://fidoalliance.org/specs/fido-u2f-v1.2-ps-20170411/fido-u2f-raw-message-formats-v1.2-ps-20170411.html).
* ctap.c - implements [CTAP2 protocol](https://fidoalliance.org/specs/fido-v2.0-id-20180227/fido-client-to-authenticator-protocol-v2.0-id-20180227.html).
* ctap_parse.c - implements parsing for CTAP protocol.
* this could use some work minimizing.
* log.c - embedded friendly debug logging.
* crypto.c - software implementation of the crypto needs of the application. Generally this will be copied and edited for different platforms. API defined in crypto.h should be the same.
* device.h - definitions of functions that are platform specific and should be implemented separately. See device.c in any of the implementations to see examples.
## Data flow
The main loop will poll the USB peripheral to see if any messages arrived,
and then pass each one to the USBHID layer.
Once a USBHID message is fully buffered, it will be acted on, unless there was a previous error.
This will get passed up to U2F or CTAP2 layer. The response is buffered and then written out to USB.
Depending on platform, there should be a minimum number of interrupts configured. USB will need interrupts,
and possibly timer interrupts for keeping track of time. ST implementation users a 16-bit timer to track time,
and interrupts to count overflows.
If the application is waiting on user input in CTAP2, then USBHID messages need to be continued to be polled,
to catch any [cancel command](https://fidoalliance.org/specs/fido-v2.0-id-20180227/fido-client-to-authenticator-protocol-v2.0-id-20180227.html#usb-hid-cancel).
Also, every 100ms or so, an update needs to be sent via USBHID if the CTAP2 application is still processing a getAssertion request,
a makeCredential request, or is waiting on user input. ST leverages same 16-bit timer interrupt for this.

Wyświetl plik

@ -2,6 +2,10 @@ Documentation of the `master` branch is deployed to Netlify automatically.
To host or develop locally:
- `make docsrv` and visit [localhost:8000](http://localhost:8000).
```
pip install mkdocs mkdocs-material
```
`make docsrv` and visit [localhost:8000](http://localhost:8000).
The file `runtime.txt` is necessary to tell Netlify to use Python3.

Wyświetl plik

@ -39,7 +39,11 @@ Try reading and writing to the device node you identified in the previous step.
* write: try `echo "hello, Solo" > /dev/hidraw0`. Again, if you don't get denied permission, you're OK.
## Which rule should I use, and how do I do it?
Simplest is probably to copy [Yubico's rule file](https://github.com/Yubico/libu2f-host/blob/master/70-u2f.rules) to `/etc/udev/rules.d/fido.rules` on your system. This contains rules for Yubico's keys, the U2F Zero, and many others. The relevant line for U2F Zero is:
Simplest is probably to copy [Yubico's rule file](https://github.com/Yubico/libu2f-host/blob/master/70-u2f.rules) to `/etc/udev/rules.d/fido.rules` on your system, for instance:
```
$ (cd /etc/udev/rules.d/ && sudo curl https://raw.githubusercontent.com/Yubico/libu2f-host/master/70-u2f.rules -O)
```
This contains rules for Yubico's keys, the U2F Zero, and many others. The relevant line for U2F Zero is:
```
KERNEL=="hidraw*", SUBSYSTEM=="hidraw", ATTRS{idVendor}=="10c4", ATTRS{idProduct}=="8acf", TAG+="uaccess"
```

Wyświetl plik

@ -53,11 +53,9 @@ static const uint8_t * _signing_key = NULL;
static int _key_len = 0;
// Secrets for testing only
static uint8_t master_secret[32] = "\x00\x11\x22\x33\x44\x55\x66\x77\x88\x99\xaa\xbb\xcc\xdd\xee\xff"
"\xff\xee\xdd\xcc\xbb\xaa\x99\x88\x77\x66\x55\x44\x33\x22\x11\x00";
static uint8_t master_secret[32];
static uint8_t transport_secret[32] = "\x10\x01\x22\x33\x44\x55\x66\x77\x87\x90\x0a\xbb\x3c\xd8\xee\xff"
"\xff\xee\x8d\x1c\x3b\xfa\x99\x88\x77\x86\x55\x44\xd3\xff\x33\x00";
static uint8_t transport_secret[32];
@ -71,6 +69,11 @@ void crypto_reset_master_secret()
ctap_generate_rng(master_secret, 32);
}
void crypto_load_master_secret(uint8_t * key)
{
memmove(master_secret, key, 32);
memmove(transport_secret, key+32, 32);
}
void crypto_sha256_update(uint8_t * data, size_t len)
{
@ -353,5 +356,3 @@ const uint16_t attestation_key_size = sizeof(attestation_key)-1;
#else
#error "No crypto implementation defined"
#endif

Wyświetl plik

@ -49,9 +49,8 @@ void generate_private_key(uint8_t * data, int len, uint8_t * data2, int len2, ui
void crypto_ecc256_make_key_pair(uint8_t * pubkey, uint8_t * privkey);
void crypto_ecc256_shared_secret(const uint8_t * pubkey, const uint8_t * privkey, uint8_t * shared_secret);
// Key must be 32 bytes
#define CRYPTO_TRANSPORT_KEY NULL
#define CRYPTO_MASTER_KEY NULL
#define CRYPTO_TRANSPORT_KEY ((uint8_t*)1)
#define CRYPTO_MASTER_KEY ((uint8_t*)0)
void crypto_aes256_init(uint8_t * key, uint8_t * nonce);
void crypto_aes256_reset_iv(uint8_t * nonce);
@ -61,11 +60,13 @@ void crypto_aes256_decrypt(uint8_t * buf, int lenth);
void crypto_aes256_encrypt(uint8_t * buf, int lenth);
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;
#endif

Wyświetl plik

@ -26,6 +26,7 @@
#include "cbor.h"
#include "ctap.h"
#include "ctaphid.h"
#include "ctap_parse.h"
#include "ctap_errors.h"
#include "cose_key.h"
@ -43,6 +44,7 @@ uint8_t PIN_TOKEN[PIN_TOKEN_SIZE];
uint8_t KEY_AGREEMENT_PUB[64];
static uint8_t KEY_AGREEMENT_PRIV[32];
static uint8_t PIN_CODE_HASH[32];
static int8_t PIN_BOOT_ATTEMPTS_LEFT = PIN_BOOT_ATTEMPTS;
AuthenticatorState STATE;
@ -264,15 +266,15 @@ static int ctap_generate_cose_key(CborEncoder * cose_key, uint8_t * hmac_input,
return 0;
}
void make_auth_tag(struct rpId * rp, CTAP_userEntity * user, uint32_t count, uint8_t * tag)
void make_auth_tag(uint8_t * nonce, CTAP_userEntity * user, uint32_t count, uint8_t * tag)
{
uint8_t hashbuf[32];
crypto_sha256_hmac_init(NULL, 0, hashbuf);
crypto_sha256_update(rp->id, rp->size);
crypto_sha256_hmac_init(CRYPTO_TRANSPORT_KEY, 0, hashbuf);
crypto_sha256_update(nonce, CREDENTIAL_NONCE_SIZE);
crypto_sha256_update(user->id, user->id_size);
crypto_sha256_update(user->name, strnlen((const char*)user->name, USER_NAME_LIMIT));
crypto_sha256_update((uint8_t*)&count, 4);
crypto_sha256_hmac_final(NULL,0,hashbuf);
crypto_sha256_hmac_final(CRYPTO_TRANSPORT_KEY,0,hashbuf);
memmove(tag, hashbuf, CREDENTIAL_TAG_SIZE);
}
@ -283,21 +285,19 @@ static uint32_t auth_data_update_count(CTAP_authDataHeader * authData)
if (count == 0) // count 0 will indicate invalid token
{
count = ctap_atomic_count( 0 );
}
uint8_t * byte = (uint8_t*) &authData->signCount;
*byte++ = count & 0xff;
count = count >> 8;
*byte++ = count & 0xff;
count = count >> 8;
*byte++ = count & 0xff;
count = count >> 8;
*byte++ = count & 0xff;
*byte++ = (count >> 0) & 0xff;
*byte++ = (count >> 8) & 0xff;
*byte++ = (count >> 16) & 0xff;
*byte++ = (count >> 24) & 0xff;
return count;
}
static int ctap_make_auth_data(struct rpId * rp, CborEncoder * map, uint8_t * auth_data_buf, int len, CTAP_userEntity * user, uint8_t credtype, int32_t algtype)
static int ctap_make_auth_data(struct rpId * rp, CborEncoder * map, uint8_t * auth_data_buf, int len, CTAP_userEntity * user, uint8_t credtype, int32_t algtype, int32_t * sz)
{
CborEncoder cose_key;
int auth_data_sz, ret;
@ -318,10 +318,24 @@ static int ctap_make_auth_data(struct rpId * rp, CborEncoder * map, uint8_t * au
count = auth_data_update_count(&authData->head);
authData->head.flags = (ctap_user_presence_test() << 0);
device_set_status(CTAPHID_STATUS_UPNEEDED);
int but = ctap_user_presence_test();
if (!but)
{
return CTAP2_ERR_OPERATION_DENIED;
}
else if (but < 0) // Cancel
{
return CTAP2_ERR_KEEPALIVE_CANCEL;
}
device_set_status(CTAPHID_STATUS_PROCESSING);
authData->head.flags = (but << 0);
authData->head.flags |= (ctap_user_verification(0) << 2);
if (credtype != 0)
{
// add attestedCredentialData
@ -338,19 +352,19 @@ static int ctap_make_auth_data(struct rpId * rp, CborEncoder * map, uint8_t * au
#else
memset((uint8_t*)&authData->attest.credential, 0, sizeof(struct Credential));
// Make a tag we can later check to make sure this is a token we made
make_auth_tag(rp, user, count, authData->attest.credential.tag);
ctap_generate_rng(authData->attest.credential.nonce, CREDENTIAL_NONCE_SIZE);
memmove(&authData->attest.credential.enc.user, user, sizeof(CTAP_userEntity)); //TODO encrypt this
memmove(&authData->attest.credential.enc.user, user, sizeof(CTAP_userEntity));
authData->attest.credential.enc.count = count;
// Make a tag we can later check to make sure this is a token we made
make_auth_tag(authData->attest.credential.nonce, user, count, authData->attest.credential.tag);
crypto_aes256_init(CRYPTO_TRANSPORT_KEY, NULL);
crypto_aes256_encrypt((uint8_t*)&authData->attest.credential.enc, CREDENTIAL_ENC_SIZE);
ctap_generate_cose_key(&cose_key, (uint8_t*)&authData->attest.credential, sizeof(struct Credential), credtype, algtype);
printf1(TAG_MC,"COSE_KEY: "); dump_hex1(TAG_MC, cose_key_buf, cbor_encoder_get_buffer_size(&cose_key, cose_key_buf));
auth_data_sz = sizeof(CTAP_authData) + cbor_encoder_get_buffer_size(&cose_key, cose_key_buf);
#endif
@ -367,7 +381,8 @@ static int ctap_make_auth_data(struct rpId * rp, CborEncoder * map, uint8_t * au
check_ret(ret);
}
return auth_data_sz;
if (sz) *sz = auth_data_sz;
return 0;
}
@ -419,7 +434,6 @@ int ctap_calculate_signature(uint8_t * data, int datalen, uint8_t * clientDataHa
crypto_sha256_update(clientDataHash, CLIENT_DATA_HASH_SIZE);
crypto_sha256_final(hashbuf);
printf1(TAG_GREEN, "sha256: "); dump_hex1(TAG_DUMP,hashbuf,32);
crypto_ecc256_sign(hashbuf, 32, sigbuf);
return ctap_encode_der_sig(sigbuf,sigder);
@ -471,13 +485,8 @@ uint8_t ctap_add_attest_statement(CborEncoder * map, uint8_t * sigder, int len)
int ctap_authenticate_credential(struct rpId * rp, CTAP_credentialDescriptor * desc)
{
uint8_t tag[16];
if (desc->type != PUB_KEY_CRED_PUB_KEY)
{
printf1(TAG_GA,"unsupported credential type: %d\n", desc->type);
return 0;
}
make_auth_tag(rp, &desc->credential.enc.user, desc->credential.enc.count, tag);
make_auth_tag(desc->credential.nonce, &desc->credential.enc.user, desc->credential.enc.count, tag);
return (memcmp(desc->credential.tag, tag, CREDENTIAL_TAG_SIZE) == 0);
}
@ -519,6 +528,12 @@ uint8_t ctap_make_credential(CborEncoder * encoder, uint8_t * request, int lengt
}
}
if (MC.up)
{
return CTAP2_ERR_INVALID_OPTION;
}
crypto_aes256_init(CRYPTO_TRANSPORT_KEY, NULL);
for (i = 0; i < MC.excludeListSize; i++)
{
ret = parse_credential_descriptor(&MC.excludeList, excl_cred);
@ -528,8 +543,11 @@ uint8_t ctap_make_credential(CborEncoder * encoder, uint8_t * request, int lengt
}
check_retr(ret);
crypto_aes256_reset_iv(NULL);
crypto_aes256_decrypt((uint8_t*)& excl_cred->credential.enc, CREDENTIAL_ENC_SIZE);
if (ctap_authenticate_credential(&MC.rp, excl_cred))
{
printf1(TAG_MC, "Cred %d failed!\r\n",i);
return CTAP2_ERR_CREDENTIAL_EXCLUDED;
}
@ -540,9 +558,11 @@ uint8_t ctap_make_credential(CborEncoder * encoder, uint8_t * request, int lengt
CborEncoder map;
ret = cbor_encoder_create_map(encoder, &map, 3);
check_ret(ret);
int32_t auth_data_sz;
int auth_data_sz = ctap_make_auth_data(&MC.rp, &map, auth_data_buf, sizeof(auth_data_buf),
&MC.user, MC.publicKeyCredentialType, MC.COSEAlgorithmIdentifier);
ret = ctap_make_auth_data(&MC.rp, &map, auth_data_buf, sizeof(auth_data_buf),
&MC.user, MC.publicKeyCredentialType, MC.COSEAlgorithmIdentifier, &auth_data_sz);
check_retr(ret);
crypto_ecc256_load_attestation_key();
int sigder_sz = ctap_calculate_signature(auth_data_buf, auth_data_sz, MC.clientDataHash, auth_data_buf, sigbuf, sigder);
@ -724,11 +744,6 @@ uint8_t ctap_end_get_assertion(CborEncoder * map, CTAP_credentialDescriptor * cr
crypto_ecc256_load_key((uint8_t*)&cred->credential, sizeof(struct Credential), NULL, 0);
/*printf1(TAG_GREEN,"auth_data_buf: "); dump_hex1(TAG_DUMP, auth_data_buf, sizeof(CTAP_authDataHeader));*/
/*printf1(TAG_GREEN,"clientdatahash: "); dump_hex1(TAG_DUMP, clientDataHash, 32);*/
/*printf1(TAG_GREEN,"credential: # %d\n", cred->credential.enc.count);*/
/*dump_hex1(TAG_DUMP, clientDataHash, 32);*/
int sigder_sz = ctap_calculate_signature(auth_data_buf, sizeof(CTAP_authDataHeader), clientDataHash, auth_data_buf, sigbuf, sigder);
{
@ -801,12 +816,16 @@ uint8_t ctap_get_assertion(CborEncoder * encoder, uint8_t * request, int length)
}
}
if (!GA.rp.size || !GA.clientDataHashPresent)
{
return CTAP2_ERR_MISSING_PARAMETER;
}
CborEncoder map;
ret = cbor_encoder_create_map(encoder, &map, 5);
check_ret(ret);
ctap_make_auth_data(&GA.rp, &map, auth_data_buf, sizeof(auth_data_buf), NULL, 0,0);
ret = ctap_make_auth_data(&GA.rp, &map, auth_data_buf, sizeof(auth_data_buf), NULL, 0,0,NULL);
check_retr(ret);
printf1(TAG_GA, "ALLOW_LIST has %d creds\n", GA.credLen);
/*for (int j = 0; j < GA.credLen; j++)*/
@ -834,13 +853,13 @@ uint8_t ctap_get_assertion(CborEncoder * encoder, uint8_t * request, int length)
else
{
printf2(TAG_ERR,"Error, no authentic credential\n");
return CTAP2_ERR_CREDENTIAL_NOT_VALID;
return CTAP2_ERR_NO_CREDENTIALS;
}
printf1(TAG_RED,"resulting order of creds:\n");
printf1(TAG_GA,"resulting order of creds:\n");
for (int j = 0; j < GA.credLen; j++)
{
printf1(TAG_RED,"CRED ID (# %d)\n", GA.creds[j].credential.enc.count);
printf1(TAG_GA,"CRED ID (# %d)\n", GA.creds[j].credential.enc.count);
}
{
@ -861,6 +880,18 @@ uint8_t ctap_get_assertion(CborEncoder * encoder, uint8_t * request, int length)
return 0;
}
// Return how many trailing zeros in a buffer
static int trailing_zeros(uint8_t * buf, int indx)
{
int c = 0;
while(0==buf[indx] && indx)
{
indx--;
c++;
}
return c;
}
uint8_t ctap_update_pin_if_verified(uint8_t * pinEnc, int len, uint8_t * platform_pubkey, uint8_t * pinAuth, uint8_t * pinHashEnc)
{
uint8_t shared_secret[32];
@ -876,7 +907,11 @@ uint8_t ctap_update_pin_if_verified(uint8_t * pinEnc, int len, uint8_t * platfor
{
if (ctap_device_locked())
{
return CTAP2_ERR_OPERATION_DENIED;
return CTAP2_ERR_PIN_BLOCKED;
}
if (ctap_device_boot_locked())
{
return CTAP2_ERR_PIN_AUTH_BLOCKED;
}
}
@ -911,25 +946,31 @@ uint8_t ctap_update_pin_if_verified(uint8_t * pinEnc, int len, uint8_t * platfor
crypto_aes256_decrypt(pinEnc, len);
printf1(TAG_CP,"new pin: %s\n", pinEnc);
ret = strnlen((const char *)pinEnc, NEW_PIN_ENC_MAX_SIZE);
if (ret == NEW_PIN_ENC_MAX_SIZE)
ret = trailing_zeros(pinEnc, NEW_PIN_ENC_MIN_SIZE - 1);
ret = NEW_PIN_ENC_MIN_SIZE - ret;
if (ret < NEW_PIN_MIN_SIZE || ret >= NEW_PIN_MAX_SIZE)
{
printf2(TAG_ERR,"No NULL terminator in new pin string\n");
return CTAP1_ERR_OTHER;
}
else if (ret < 4)
{
printf2(TAG_ERR,"new PIN is too short\n");
printf2(TAG_ERR,"new PIN is too short or too long [%d bytes]\n", ret);
return CTAP2_ERR_PIN_POLICY_VIOLATION;
}
else
{
printf1(TAG_CP,"new pin: %s [%d bytes]\n", pinEnc, ret);
dump_hex1(TAG_CP, pinEnc, ret);
}
if (ctap_is_pin_set())
{
if (ctap_device_locked())
{
return CTAP2_ERR_OPERATION_DENIED;
return CTAP2_ERR_PIN_BLOCKED;
}
if (ctap_device_boot_locked())
{
return CTAP2_ERR_PIN_AUTH_BLOCKED;
}
crypto_aes256_reset_iv(NULL);
crypto_aes256_decrypt(pinHashEnc, 16);
@ -937,6 +978,10 @@ uint8_t ctap_update_pin_if_verified(uint8_t * pinEnc, int len, uint8_t * platfor
{
crypto_ecc256_make_key_pair(KEY_AGREEMENT_PUB, KEY_AGREEMENT_PRIV);
ctap_decrement_pin_attempts();
if (ctap_device_boot_locked())
{
return CTAP2_ERR_PIN_AUTH_BLOCKED;
}
return CTAP2_ERR_PIN_INVALID;
}
else
@ -976,6 +1021,10 @@ uint8_t ctap_add_pin_if_verified(uint8_t * pinTokenEnc, uint8_t * platform_pubke
// Generate new keyAgreement pair
crypto_ecc256_make_key_pair(KEY_AGREEMENT_PUB, KEY_AGREEMENT_PRIV);
ctap_decrement_pin_attempts();
if (ctap_device_boot_locked())
{
return CTAP2_ERR_PIN_AUTH_BLOCKED;
}
return CTAP2_ERR_PIN_INVALID;
}
@ -995,6 +1044,20 @@ uint8_t ctap_client_pin(CborEncoder * encoder, uint8_t * request, int length)
uint8_t pinTokenEnc[PIN_TOKEN_SIZE];
int ret = ctap_parse_client_pin(&CP,request,length);
switch(CP.subCommand)
{
case CP_cmdSetPin:
case CP_cmdChangePin:
case CP_cmdGetPinToken:
if (ctap_device_locked())
{
return CTAP2_ERR_PIN_BLOCKED;
}
if (ctap_device_boot_locked())
{
return CTAP2_ERR_PIN_AUTH_BLOCKED;
}
}
if (ret != 0)
{
@ -1104,7 +1167,7 @@ uint8_t ctap_client_pin(CborEncoder * encoder, uint8_t * request, int length)
check_ret(ret);
}
if (num_map)
if (num_map || CP.getRetries)
{
ret = cbor_encoder_close_container(encoder, &map);
check_ret(ret);
@ -1141,10 +1204,14 @@ uint8_t ctap_request(uint8_t * pkt_raw, int length, CTAP_RESPONSE * resp)
{
case CTAP_MAKE_CREDENTIAL:
case CTAP_GET_ASSERTION:
case CTAP_CLIENT_PIN:
if (ctap_device_locked())
{
status = CTAP2_ERR_OPERATION_DENIED;
status = CTAP2_ERR_PIN_BLOCKED;
goto done;
}
if (ctap_device_boot_locked())
{
status = CTAP2_ERR_PIN_AUTH_BLOCKED;
goto done;
}
break;
@ -1153,6 +1220,7 @@ uint8_t ctap_request(uint8_t * pkt_raw, int length, CTAP_RESPONSE * resp)
switch(cmd)
{
case CTAP_MAKE_CREDENTIAL:
device_set_status(CTAPHID_STATUS_PROCESSING);
printf1(TAG_CTAP,"CTAP_MAKE_CREDENTIAL\n");
t1 = millis();
status = ctap_make_credential(&encoder, pkt_raw, length);
@ -1164,6 +1232,7 @@ uint8_t ctap_request(uint8_t * pkt_raw, int length, CTAP_RESPONSE * resp)
resp->length = cbor_encoder_get_buffer_size(&encoder, buf);
break;
case CTAP_GET_ASSERTION:
device_set_status(CTAPHID_STATUS_PROCESSING);
printf1(TAG_CTAP,"CTAP_GET_ASSERTION\n");
t1 = millis();
status = ctap_get_assertion(&encoder, pkt_raw, length);
@ -1190,6 +1259,7 @@ uint8_t ctap_request(uint8_t * pkt_raw, int length, CTAP_RESPONSE * resp)
case CTAP_CLIENT_PIN:
printf1(TAG_CTAP,"CTAP_CLIENT_PIN\n");
status = ctap_client_pin(&encoder, pkt_raw, length);
resp->length = cbor_encoder_get_buffer_size(&encoder, buf);
dump_hex1(TAG_DUMP, buf, cbor_encoder_get_buffer_size(&encoder, buf));
break;
@ -1228,6 +1298,7 @@ uint8_t ctap_request(uint8_t * pkt_raw, int length, CTAP_RESPONSE * resp)
}
done:
device_set_status(CTAPHID_STATUS_IDLE);
getAssertionState.lastcmd = cmd;
if (status != CTAP1_ERR_SUCCESS)
@ -1235,7 +1306,7 @@ done:
resp->length = 0;
}
printf1(TAG_CTAP,"cbor output structure: %d bytes\n", resp->length);
printf1(TAG_CTAP,"cbor output structure: %d bytes. Return 0x%02x\n", resp->length, status);
return status;
}
@ -1253,6 +1324,9 @@ static void ctap_state_init()
{
// Set to 0xff instead of 0x00 to be easier on flash
memset(&STATE, 0xff, sizeof(AuthenticatorState));
// Fresh RNG for key
ctap_generate_rng(STATE.key_space, KEY_SPACE_BYTES);
STATE.is_initialized = INITIALIZED_MARKER;
STATE.remaining_tries = PIN_LOCKOUT_ATTEMPTS;
STATE.is_pin_set = 0;
@ -1264,6 +1338,8 @@ void ctap_init()
authenticator_read_state(&STATE);
device_set_status(CTAPHID_STATUS_IDLE);
if (STATE.is_initialized == INITIALIZED_MARKER)
{
printf1(TAG_STOR,"Auth state is initialized\n");
@ -1286,11 +1362,13 @@ void ctap_init()
}
}
crypto_load_master_secret(STATE.key_space);
if (ctap_is_pin_set())
{
printf1(TAG_STOR,"pin code: \"%s\"\n", STATE.pin_code);
crypto_sha256_init();
crypto_sha256_update(STATE.pin_code, strnlen((char *)STATE.pin_code, NEW_PIN_ENC_MAX_SIZE));
crypto_sha256_update(STATE.pin_code, STATE.pin_code_length);
crypto_sha256_final(PIN_CODE_HASH);
printf1(TAG_STOR, "attempts_left: %d\n", STATE.remaining_tries);
}
@ -1303,7 +1381,6 @@ void ctap_init()
printf1(TAG_ERR, "DEVICE LOCKED!\n");
}
if (ctap_generate_rng(PIN_TOKEN, PIN_TOKEN_SIZE) != 1)
{
printf2(TAG_ERR,"Error, rng failed\n");
@ -1331,14 +1408,15 @@ uint8_t ctap_pin_matches(uint8_t * pin, int len)
void ctap_update_pin(uint8_t * pin, int len)
{
// TODO this should go in flash
if (len > NEW_PIN_ENC_MAX_SIZE-1 || len < 4)
if (len > NEW_PIN_ENC_MIN_SIZE || len < 4)
{
printf2(TAG_ERR, "Update pin fail length\n");
exit(1);
}
memset(STATE.pin_code, 0, NEW_PIN_ENC_MAX_SIZE);
memset(STATE.pin_code, 0, NEW_PIN_ENC_MIN_SIZE);
memmove(STATE.pin_code, pin, len);
STATE.pin_code_length = len;
STATE.pin_code[NEW_PIN_ENC_MIN_SIZE - 1] = 0;
crypto_sha256_init();
crypto_sha256_update(STATE.pin_code, len);
@ -1346,18 +1424,25 @@ void ctap_update_pin(uint8_t * pin, int len)
STATE.is_pin_set = 1;
authenticator_write_state(&STATE, 1);
authenticator_write_state(&STATE, 0);
printf1(TAG_CTAP, "New pin set: %s\n", STATE.pin_code);
}
uint8_t ctap_decrement_pin_attempts()
{
if (STATE.remaining_tries > 0)
if (PIN_BOOT_ATTEMPTS_LEFT > 0)
{
PIN_BOOT_ATTEMPTS_LEFT--;
}
if (! ctap_device_locked())
{
STATE.remaining_tries--;
ctap_flush_state(0);
printf1(TAG_CP, "ATTEMPTS left: %d\n", STATE.remaining_tries);
if (STATE.remaining_tries == 0)
if (ctap_device_locked())
{
memset(PIN_TOKEN,0,sizeof(PIN_TOKEN));
memset(PIN_CODE_HASH,0,sizeof(PIN_CODE_HASH));
@ -1374,7 +1459,12 @@ uint8_t ctap_decrement_pin_attempts()
int8_t ctap_device_locked()
{
return STATE.remaining_tries == 0;
return STATE.remaining_tries <= 0;
}
int8_t ctap_device_boot_locked()
{
return PIN_BOOT_ATTEMPTS_LEFT <= 0;
}
int8_t ctap_leftover_pin_attempts()
@ -1385,6 +1475,7 @@ int8_t ctap_leftover_pin_attempts()
void ctap_reset_pin_attempts()
{
STATE.remaining_tries = PIN_LOCKOUT_ATTEMPTS;
PIN_BOOT_ATTEMPTS_LEFT = PIN_BOOT_ATTEMPTS;
ctap_flush_state(0);
}
@ -1459,7 +1550,6 @@ int8_t ctap_store_key(uint8_t index, uint8_t * key, uint16_t len)
memmove(STATE.key_space + offset, key, len);
ctap_flush_state(0);
ctap_flush_state(1);
return 0;
@ -1511,6 +1601,5 @@ void ctap_reset()
memset(PIN_CODE_HASH,0,sizeof(PIN_CODE_HASH));
crypto_ecc256_make_key_pair(KEY_AGREEMENT_PUB, KEY_AGREEMENT_PRIV);
crypto_reset_master_secret(); // Not sure what the significance of this is??
crypto_reset_master_secret();
}

Wyświetl plik

@ -34,7 +34,8 @@
#define CTAP_VENDOR_FIRST 0x40
#define CTAP_VENDOR_LAST 0xBF
#define CTAP_AAGUID ((uint8_t*)"\x00\x11\x22\x33\x44\x55\x66\x77\x88\x99\xaa\xbb\xcc\xdd\xee\xff")
// AAGUID For Solo
#define CTAP_AAGUID ((uint8_t*)"\x88\x76\x63\x1b\xd4\xa0\x42\x7f\x57\x73\x0e\xc7\x1c\x9e\x02\x79")
#define MC_clientDataHash 0x01
#define MC_rp 0x02
@ -126,10 +127,14 @@
#define ALLOW_LIST_MAX_SIZE 20
#define NEW_PIN_ENC_MAX_SIZE 256 // includes NULL terminator
#define NEW_PIN_ENC_MIN_SIZE 64
#define NEW_PIN_MAX_SIZE 64
#define NEW_PIN_MIN_SIZE 4
#define CTAP_RESPONSE_BUFFER_SIZE 1024
#define CTAP_RESPONSE_BUFFER_SIZE 4096
#define PIN_LOCKOUT_ATTEMPTS 8
#define PIN_LOCKOUT_ATTEMPTS 8 // Number of attempts total
#define PIN_BOOT_ATTEMPTS 3 // number of attempts per boot
typedef struct
{
@ -198,6 +203,7 @@ typedef struct
uint8_t rk;
uint8_t uv;
uint8_t up;
uint8_t pinAuth[16];
uint8_t pinAuthPresent;
@ -215,6 +221,7 @@ typedef struct
{
uint32_t paramsParsed;
uint8_t clientDataHash[CLIENT_DATA_HASH_SIZE];
uint8_t clientDataHashPresent;
struct rpId rp;
@ -222,12 +229,14 @@ typedef struct
uint8_t rk;
uint8_t uv;
uint8_t up;
uint8_t pinAuth[16];
uint8_t pinAuthPresent;
int pinProtocol;
CTAP_credentialDescriptor creds[ALLOW_LIST_MAX_SIZE];
uint8_t allowListPresent;
} CTAP_getAssertion;
typedef struct
@ -281,6 +290,7 @@ uint8_t ctap_is_pin_set();
uint8_t ctap_pin_matches(uint8_t * pin, int len);
void ctap_reset();
int8_t ctap_device_locked();
int8_t ctap_device_boot_locked();
// Key storage API

Wyświetl plik

@ -92,7 +92,7 @@ const char * cbor_value_get_type_string(const CborValue *value)
uint8_t parse_user(CTAP_makeCredential * MC, CborValue * val)
{
size_t sz, map_length;
uint8_t key[8];
uint8_t key[24];
int ret;
int i;
CborValue map;
@ -126,6 +126,7 @@ uint8_t parse_user(CTAP_makeCredential * MC, CborValue * val)
printf2(TAG_ERR,"Error, rp map key is too large\n");
return CTAP2_ERR_LIMIT_EXCEEDED;
}
check_ret(ret);
key[sizeof(key) - 1] = 0;
@ -153,6 +154,11 @@ uint8_t parse_user(CTAP_makeCredential * MC, CborValue * val)
}
else if (strcmp((const char *)key, "name") == 0)
{
if (cbor_value_get_type(&map) != CborTextStringType)
{
printf2(TAG_ERR,"Error, expecting text string type for user.name value\n");
return CTAP2_ERR_INVALID_CBOR_TYPE;
}
sz = USER_NAME_LIMIT;
ret = cbor_value_copy_text_string(&map, (char *)MC->user.name, &sz, NULL);
if (ret != CborErrorOutOfMemory)
@ -161,6 +167,22 @@ uint8_t parse_user(CTAP_makeCredential * MC, CborValue * val)
}
MC->user.name[USER_NAME_LIMIT - 1] = 0;
}
else if (strcmp((const char *)key, "displayName") == 0)
{
if (cbor_value_get_type(&map) != CborTextStringType)
{
printf2(TAG_ERR,"Error, expecting text string type for user.displayName value\n");
return CTAP2_ERR_INVALID_CBOR_TYPE;
}
}
else if (strcmp((const char *)key, "icon") == 0)
{
if (cbor_value_get_type(&map) != CborTextStringType)
{
printf2(TAG_ERR,"Error, expecting text string type for user.icon value\n");
return CTAP2_ERR_INVALID_CBOR_TYPE;
}
}
else
{
printf1(TAG_PARSE,"ignoring key %s for user map\n", key);
@ -263,6 +285,19 @@ uint8_t parse_pub_key_cred_params(CTAP_makeCredential * MC, CborValue * val)
ret = cbor_value_get_array_length(val, &arr_length);
check_ret(ret);
for (i = 0; i < arr_length; i++)
{
if ((ret = parse_pub_key_cred_param(&arr, &cred_type, &alg_type)) != 0)
{
return ret;
}
ret = cbor_value_advance(&arr);
check_ret(ret);
}
ret = cbor_value_enter_container(val,&arr);
check_ret(ret);
for (i = 0; i < arr_length; i++)
{
if ((ret = parse_pub_key_cred_param(&arr, &cred_type, &alg_type)) == 0)
@ -275,11 +310,6 @@ uint8_t parse_pub_key_cred_params(CTAP_makeCredential * MC, CborValue * val)
return 0;
}
}
else
{
// Continue? fail?
return ret;
}
ret = cbor_value_advance(&arr);
check_ret(ret);
}
@ -309,10 +339,40 @@ uint8_t parse_fixed_byte_string(CborValue * map, uint8_t * dst, int len)
return 0;
}
uint8_t parse_verify_exclude_list(CborValue * val)
{
int i;
int ret;
CborValue arr;
size_t size;
CTAP_credentialDescriptor cred;
if (cbor_value_get_type(val) != CborArrayType)
{
printf2(TAG_ERR,"error, exclude list is not a map\n");
return CTAP2_ERR_INVALID_CBOR_TYPE;
}
ret = cbor_value_get_array_length(val, &size);
check_ret(ret);
ret = cbor_value_enter_container(val,&arr);
check_ret(ret);
for (i = 0; i < size; i++)
{
ret = parse_credential_descriptor(&arr, &cred);
check_ret(ret);
ret = cbor_value_advance(&arr);
check_ret(ret);
}
return 0;
}
uint8_t parse_rp_id(struct rpId * rp, CborValue * val)
{
size_t sz = DOMAIN_NAME_MAX_SIZE;
if (cbor_value_get_type(val) != CborTextStringType)
{
return CTAP2_ERR_INVALID_CBOR_TYPE;
}
int ret = cbor_value_copy_text_string(val, (char*)rp->id, &sz, NULL);
if (ret == CborErrorOutOfMemory)
{
@ -413,7 +473,7 @@ uint8_t parse_rp(struct rpId * rp, CborValue * val)
return 0;
}
uint8_t parse_options(CborValue * val, uint8_t * rk, uint8_t * uv)
uint8_t parse_options(CborValue * val, uint8_t * rk, uint8_t * uv, uint8_t * up)
{
size_t sz, map_length;
char key[8];
@ -463,21 +523,27 @@ uint8_t parse_options(CborValue * val, uint8_t * rk, uint8_t * uv)
return CTAP2_ERR_INVALID_CBOR_TYPE;
}
if (strcmp(key, "rk") == 0)
if (strncmp(key, "rk",2) == 0)
{
ret = cbor_value_get_boolean(&map, &b);
check_ret(ret);
*rk = b;
}
else if (strcmp(key, "uv") == 0)
else if (strncmp(key, "uv",2) == 0)
{
ret = cbor_value_get_boolean(&map, &b);
check_ret(ret);
*uv = b;
}
else if (strncmp(key, "up",2) == 0)
{
ret = cbor_value_get_boolean(&map, &b);
check_ret(ret);
*up = b;
}
else
{
printf1(TAG_PARSE,"ignoring key %s for option map\n", key);
printf2(TAG_PARSE,"ignoring option specified %s\n", key);
}
@ -576,27 +642,30 @@ uint8_t ctap_parse_make_credential(CTAP_makeCredential * MC, CborEncoder * encod
break;
case MC_excludeList:
printf1(TAG_MC,"CTAP_excludeList\n");
if( cbor_value_get_type(&map) == CborArrayType )
{
ret = cbor_value_enter_container(&map, &MC->excludeList);
check_ret(ret);
ret = parse_verify_exclude_list(&map);
check_ret(ret);
ret = cbor_value_enter_container(&map, &MC->excludeList);
check_ret(ret);
ret = cbor_value_get_array_length(&map, &MC->excludeListSize);
check_ret(ret);
ret = cbor_value_get_array_length(&map, &MC->excludeListSize);
check_ret(ret);
}
else
{
return CTAP2_ERR_INVALID_CBOR_TYPE;
}
printf1(TAG_MC,"CTAP_excludeList done\n");
break;
case MC_extensions:
printf1(TAG_MC,"CTAP_extensions\n");
type = cbor_value_get_type(&map);
if (type != CborMapType)
{
return CTAP2_ERR_INVALID_CBOR_TYPE;
}
break;
case MC_options:
printf1(TAG_MC,"CTAP_options\n");
ret = parse_options(&map, &MC->rk, &MC->uv);
ret = parse_options(&map, &MC->rk, &MC->uv, &MC->up);
check_retr(ret);
break;
case MC_pinAuth:
@ -661,8 +730,8 @@ uint8_t parse_credential_descriptor(CborValue * arr, CTAP_credentialDescriptor *
cbor_value_copy_byte_string(&val, (uint8_t*)&cred->credential, &buflen, NULL);
if (buflen != CREDENTIAL_ID_SIZE)
{
printf2(TAG_ERR,"Error, credential is incorrect length\n");
return CTAP2_ERR_CBOR_UNEXPECTED_TYPE; // maybe just skip it instead of fail?
printf2(TAG_ERR,"Ignoring credential is incorrect length\n");
//return CTAP2_ERR_CBOR_UNEXPECTED_TYPE; // maybe just skip it instead of fail?
}
ret = cbor_value_map_find_value(arr, "type", &val);
@ -677,13 +746,14 @@ uint8_t parse_credential_descriptor(CborValue * arr, CTAP_credentialDescriptor *
buflen = sizeof(type);
cbor_value_copy_text_string(&val, type, &buflen, NULL);
if (strcmp(type, "public-key") == 0)
if (strncmp(type, "public-key",11) == 0)
{
cred->type = PUB_KEY_CRED_PUB_KEY;
}
else
{
cred->type = PUB_KEY_CRED_UNKNOWN;
printf1(TAG_RED, "Unknown type: %s\r\n", type);
}
return 0;
@ -783,6 +853,7 @@ uint8_t ctap_parse_get_assertion(CTAP_getAssertion * GA, uint8_t * request, int
ret = parse_fixed_byte_string(&map, GA->clientDataHash, CLIENT_DATA_HASH_SIZE);
check_retr(ret);
GA->clientDataHashPresent = 1;
printf1(TAG_GA," "); dump_hex1(TAG_GA, GA->clientDataHash, 32);
break;
@ -796,10 +867,9 @@ uint8_t ctap_parse_get_assertion(CTAP_getAssertion * GA, uint8_t * request, int
case GA_allowList:
printf1(TAG_GA,"GA_allowList\n");
ret = parse_allow_list(GA, &map);
if (ret == 0)
{
check_ret(ret);
GA->allowListPresent = 1;
}
break;
case GA_extensions:
printf1(TAG_GA,"GA_extensions\n");
@ -807,7 +877,7 @@ uint8_t ctap_parse_get_assertion(CTAP_getAssertion * GA, uint8_t * request, int
case GA_options:
printf1(TAG_GA,"CTAP_options\n");
ret = parse_options(&map, &GA->rk, &GA->uv);
ret = parse_options(&map, &GA->rk, &GA->uv, &GA->up);
check_retr(ret);
break;
case GA_pinAuth:
@ -1033,10 +1103,11 @@ uint8_t ctap_parse_client_pin(CTAP_clientPin * CP, uint8_t * request, int length
{
ret = cbor_value_calculate_string_length(&map, &sz);
check_ret(ret);
if (sz > NEW_PIN_ENC_MAX_SIZE)
if (sz > NEW_PIN_ENC_MAX_SIZE || sz < NEW_PIN_ENC_MIN_SIZE)
{
return CTAP1_ERR_OTHER;
return CTAP2_ERR_PIN_POLICY_VIOLATION;
}
CP->newPinEncSize = sz;
sz = NEW_PIN_ENC_MAX_SIZE;
ret = cbor_value_copy_byte_string(&map, CP->newPinEnc, &sz, NULL);
@ -1078,5 +1149,3 @@ uint8_t ctap_parse_client_pin(CTAP_clientPin * CP, uint8_t * request, int length
return 0;
}

Wyświetl plik

@ -42,7 +42,7 @@ uint8_t parse_pub_key_cred_params(CTAP_makeCredential * MC, CborValue * val);
uint8_t parse_fixed_byte_string(CborValue * map, uint8_t * dst, int len);
uint8_t parse_rp_id(struct rpId * rp, CborValue * val);
uint8_t parse_rp(struct rpId * rp, CborValue * val);
uint8_t parse_options(CborValue * val, uint8_t * rk, uint8_t * uv);
uint8_t parse_options(CborValue * val, uint8_t * rk, uint8_t * uv, uint8_t * up);
uint8_t parse_allow_list(CTAP_getAssertion * GA, CborValue * it);
uint8_t parse_cose_key(CborValue * it, uint8_t * x, uint8_t * y, int * kty, int * crv);

Wyświetl plik

@ -43,6 +43,8 @@ typedef enum
EMPTY = 0,
BUFFERING,
BUFFERED,
HID_ERROR,
HID_IGNORE,
} CTAP_BUFFER_STATE;
@ -221,7 +223,6 @@ static int buffer_packet(CTAPHID_PACKET * pkt)
static void buffer_reset()
{
ctap_buffer_bcnt = 0;
ctap_buffer_offset = 0;
ctap_packet_seq = 0;
@ -341,7 +342,7 @@ static void send_init_response(uint32_t oldcid, uint32_t newcid, uint8_t * nonce
memmove(init_resp.nonce, nonce, 8);
init_resp.cid = newcid;
init_resp.protocol_version = 0;//?
init_resp.protocol_version = CTAPHID_PROTOCOL_VERSION;
init_resp.version_major = 0;//?
init_resp.version_minor = 0;//?
init_resp.build_version = 0;//?
@ -361,14 +362,32 @@ void ctaphid_check_timeouts()
{
printf1(TAG_HID, "TIMEOUT CID: %08x\n", CIDS[i].cid);
ctaphid_send_error(CIDS[i].cid, CTAP1_ERR_TIMEOUT);
memset(CIDS + i, 0, sizeof(struct CID));
CIDS[i].busy = 0;
if (CIDS[i].cid == buffer_cid())
{
buffer_reset();
}
// memset(CIDS + i, 0, sizeof(struct CID));
}
}
}
void ctaphid_update_status(int8_t status)
{
CTAPHID_WRITE_BUFFER wb;
printf1(TAG_HID, "Send device update %d!\n",status);
ctaphid_write_buffer_init(&wb);
void ctaphid_handle_packet(uint8_t * pkt_raw)
wb.cid = buffer_cid();
wb.cmd = CTAPHID_KEEPALIVE;
wb.bcnt = 1;
ctaphid_write(&wb, &status, 1);
ctaphid_write(&wb, NULL, 0);
}
static int ctaphid_buffer_packet(uint8_t * pkt_raw, uint8_t * cmd, uint32_t * cid, int * len)
{
CTAPHID_PACKET * pkt = (CTAPHID_PACKET *)(pkt_raw);
@ -378,29 +397,25 @@ void ctaphid_handle_packet(uint8_t * pkt_raw)
if (!is_cont_pkt(pkt)) printf1(TAG_HID, " length: %d\n", ctaphid_packet_len(pkt));
int ret;
uint8_t status;
uint32_t oldcid;
uint32_t newcid;
static CTAPHID_WRITE_BUFFER wb;
uint32_t active_cid;
uint32_t t1,t2;
CTAP_RESPONSE ctap_resp;
*cid = pkt->cid;
if (is_init_pkt(pkt))
{
if (ctaphid_packet_len(pkt) != 8)
{
printf2(TAG_ERR, "Error,invalid length field for init packet\n");
ctaphid_send_error(pkt->cid, CTAP1_ERR_INVALID_LENGTH);
return;
*cmd = CTAP1_ERR_INVALID_LENGTH;
return HID_ERROR;
}
if (pkt->cid == 0)
{
printf2(TAG_ERR,"Error, invalid cid 0\n");
ctaphid_send_error(pkt->cid, CTAP1_ERR_INVALID_CHANNEL);
return;
*cmd = CTAP1_ERR_INVALID_CHANNEL;
return HID_ERROR;
}
ctaphid_init();
@ -426,22 +441,30 @@ void ctaphid_handle_packet(uint8_t * pkt_raw)
if (ret == -1)
{
printf2(TAG_ERR, "Error, not enough memory for new CID. return BUSY.\n");
ctaphid_send_error(pkt->cid, CTAP1_ERR_CHANNEL_BUSY);
return;
*cmd = CTAP1_ERR_CHANNEL_BUSY;
return HID_ERROR;
}
send_init_response(oldcid, newcid, pkt->pkt.init.payload);
cid_del(newcid);
return;
return HID_IGNORE;
}
else
{
// Check if matches existing CID
if (pkt->cid == CTAPHID_BROADCAST_CID)
{
ctaphid_send_error(pkt->cid, CTAP1_ERR_INVALID_CHANNEL);
return;
*cmd = CTAP1_ERR_INVALID_CHANNEL;
return HID_ERROR;
}
if (! cid_exists(pkt->cid) && ! is_cont_pkt(pkt))
{
if (buffer_status() == EMPTY)
{
add_cid(pkt->cid);
}
}
if (cid_exists(pkt->cid))
{
if (buffer_status() == BUFFERING)
@ -450,14 +473,22 @@ void ctaphid_handle_packet(uint8_t * pkt_raw)
{
printf2(TAG_ERR,"INVALID_SEQ\n");
printf2(TAG_ERR,"Have %d/%d bytes\n", ctap_buffer_offset, ctap_buffer_bcnt);
ctaphid_send_error(pkt->cid, CTAP1_ERR_INVALID_SEQ);
return;
*cmd = CTAP1_ERR_INVALID_SEQ;
return HID_ERROR;
}
else if (pkt->cid != buffer_cid())
{
printf2(TAG_ERR,"BUSY with %08x\n", buffer_cid());
ctaphid_send_error(pkt->cid, CTAP1_ERR_CHANNEL_BUSY);
return;
if (! is_cont_pkt(pkt))
{
printf2(TAG_ERR,"BUSY with %08x\n", buffer_cid());
*cmd = CTAP1_ERR_CHANNEL_BUSY;
return HID_ERROR;
}
else
{
printf2(TAG_ERR,"ignoring random cont packet from %04x\n",pkt->cid);
return HID_IGNORE;
}
}
}
if (! is_cont_pkt(pkt))
@ -465,23 +496,24 @@ void ctaphid_handle_packet(uint8_t * pkt_raw)
if (ctaphid_packet_len(pkt) > CTAPHID_BUFFER_SIZE)
{
ctaphid_send_error(pkt->cid, CTAP1_ERR_INVALID_LENGTH);
return;
*cmd = CTAP1_ERR_INVALID_LENGTH;
return HID_ERROR;
}
}
else
{
if (buffer_status() == EMPTY || pkt->cid != buffer_cid())
{
printf2(TAG_ERR,"ignoring random cont packet\n");
return;
printf2(TAG_ERR,"ignoring random cont packet from %04x\n",pkt->cid);
return HID_IGNORE;
}
}
if (buffer_packet(pkt) == SEQUENCE_ERROR)
{
printf2(TAG_ERR,"Buffering sequence error\n");
ctaphid_send_error(pkt->cid, CTAP1_ERR_INVALID_SEQ);
return;
*cmd = CTAP1_ERR_INVALID_SEQ;
return HID_ERROR;
}
ret = cid_refresh(pkt->cid);
if (ret != 0)
@ -489,133 +521,177 @@ void ctaphid_handle_packet(uint8_t * pkt_raw)
printf2(TAG_ERR,"Error, refresh cid failed\n");
exit(1);
}
active_cid = pkt->cid;
}
else if (is_cont_pkt(pkt))
{
printf2(TAG_ERR,"ignoring unwarranted cont packet\n");
// Ignore
return;
return HID_IGNORE;
}
else
{
printf2(TAG_ERR,"BUSY\n");
ctaphid_send_error(pkt->cid, CTAP1_ERR_CHANNEL_BUSY);
return;
*cmd = CTAP1_ERR_CHANNEL_BUSY;
return HID_ERROR;
}
}
switch(buffer_status())
{
case BUFFERING:
printf1(TAG_HID,"BUFFERING\n");
active_cid_timestamp = millis();
break;
case EMPTY:
printf1(TAG_HID,"empty buffer!\n");
case BUFFERED:
switch(buffer_cmd())
{
case CTAPHID_INIT:
printf2(TAG_ERR,"CTAPHID_INIT, error this should already be handled\n");
exit(1);
break;
#ifndef DISABLE_CTAPHID_PING
case CTAPHID_PING:
printf1(TAG_HID,"CTAPHID_PING\n");
ctaphid_write_buffer_init(&wb);
wb.cid = active_cid;
wb.cmd = CTAPHID_PING;
wb.bcnt = buffer_len();
t1 = millis();
ctaphid_write(&wb, ctap_buffer, buffer_len());
ctaphid_write(&wb, NULL,0);
t2 = millis();
printf1(TAG_TIME,"PING writeback: %d ms\n",(uint32_t)(t2-t1));
break;
#endif
#ifndef DISABLE_CTAPHID_WINK
case CTAPHID_WINK:
printf1(TAG_HID,"CTAPHID_WINK\n");
ctaphid_write_buffer_init(&wb);
wb.cid = active_cid;
wb.cmd = CTAPHID_WINK;
ctaphid_write(&wb,NULL,0);
break;
#endif
#ifndef DISABLE_CTAPHID_CBOR
case CTAPHID_CBOR:
printf1(TAG_HID,"CTAPHID_CBOR\n");
if (buffer_len() == 0)
{
printf2(TAG_ERR,"Error,invalid 0 length field for cbor packet\n");
ctaphid_send_error(pkt->cid, CTAP1_ERR_INVALID_LENGTH);
return;
}
ctap_response_init(&ctap_resp);
status = ctap_request(ctap_buffer, buffer_len(), &ctap_resp);
ctaphid_write_buffer_init(&wb);
wb.cid = active_cid;
wb.cmd = CTAPHID_CBOR;
wb.bcnt = (ctap_resp.length+1);
t1 = millis();
ctaphid_write(&wb, &status, 1);
ctaphid_write(&wb, ctap_resp.data, ctap_resp.length);
ctaphid_write(&wb, NULL, 0);
t2 = millis();
printf1(TAG_TIME,"CBOR writeback: %d ms\n",(uint32_t)(t2-t1));
break;
#endif
case CTAPHID_MSG:
printf1(TAG_HID,"CTAPHID_MSG\n");
if (buffer_len() == 0)
{
printf2(TAG_ERR,"Error,invalid 0 length field for MSG/U2F packet\n");
ctaphid_send_error(pkt->cid, CTAP1_ERR_INVALID_LENGTH);
return;
}
ctap_response_init(&ctap_resp);
u2f_request((struct u2f_request_apdu*)ctap_buffer, &ctap_resp);
ctaphid_write_buffer_init(&wb);
wb.cid = active_cid;
wb.cmd = CTAPHID_MSG;
wb.bcnt = (ctap_resp.length);
ctaphid_write(&wb, ctap_resp.data, ctap_resp.length);
ctaphid_write(&wb, NULL, 0);
break;
default:
printf2(TAG_ERR,"error, unimplemented HID cmd: %02x\r\n", buffer_cmd());
ctaphid_send_error(pkt->cid, CTAP1_ERR_INVALID_COMMAND);
break;
}
cid_del(buffer_cid());
buffer_reset();
break;
default:
printf2(TAG_ERR,"invalid buffer state; abort\n");
exit(1);
break;
}
printf1(TAG_HID,"\n");
*len = buffer_len();
*cmd = buffer_cmd();
return buffer_status();
}
uint8_t ctaphid_handle_packet(uint8_t * pkt_raw)
{
uint8_t cmd;
uint32_t cid;
int len;
int status;
static uint8_t is_busy = 0;
static CTAPHID_WRITE_BUFFER wb;
CTAP_RESPONSE ctap_resp;
uint32_t t1,t2;
int bufstatus = ctaphid_buffer_packet(pkt_raw, &cmd, &cid, &len);
if (bufstatus == HID_IGNORE)
{
return 0;
}
if (bufstatus == HID_ERROR)
{
cid_del(cid);
if (cmd == CTAP1_ERR_INVALID_SEQ)
{
buffer_reset();
}
ctaphid_send_error(cid, cmd);
return 0;
}
if (bufstatus == BUFFERING)
{
active_cid_timestamp = millis();
return 0;
}
switch(cmd)
{
case CTAPHID_INIT:
printf2(TAG_ERR,"CTAPHID_INIT, error this should already be handled\n");
exit(1);
break;
#ifndef DISABLE_CTAPHID_PING
case CTAPHID_PING:
printf1(TAG_HID,"CTAPHID_PING\n");
ctaphid_write_buffer_init(&wb);
wb.cid = cid;
wb.cmd = CTAPHID_PING;
wb.bcnt = len;
t1 = millis();
ctaphid_write(&wb, ctap_buffer, len);
ctaphid_write(&wb, NULL,0);
t2 = millis();
printf1(TAG_TIME,"PING writeback: %d ms\n",(uint32_t)(t2-t1));
break;
#endif
#ifndef DISABLE_CTAPHID_WINK
case CTAPHID_WINK:
printf1(TAG_HID,"CTAPHID_WINK\n");
ctaphid_write_buffer_init(&wb);
wb.cid = cid;
wb.cmd = CTAPHID_WINK;
ctaphid_write(&wb,NULL,0);
break;
#endif
#ifndef DISABLE_CTAPHID_CBOR
case CTAPHID_CBOR:
printf1(TAG_HID,"CTAPHID_CBOR\n");
if (len == 0)
{
printf2(TAG_ERR,"Error,invalid 0 length field for cbor packet\n");
ctaphid_send_error(cid, CTAP1_ERR_INVALID_LENGTH);
return 0;
}
if (is_busy)
{
printf1(TAG_HID,"Channel busy for CBOR\n");
ctaphid_send_error(cid, CTAP1_ERR_CHANNEL_BUSY);
return 0;
}
is_busy = 1;
ctap_response_init(&ctap_resp);
status = ctap_request(ctap_buffer, len, &ctap_resp);
ctaphid_write_buffer_init(&wb);
wb.cid = cid;
wb.cmd = CTAPHID_CBOR;
wb.bcnt = (ctap_resp.length+1);
t1 = millis();
ctaphid_write(&wb, &status, 1);
ctaphid_write(&wb, ctap_resp.data, ctap_resp.length);
ctaphid_write(&wb, NULL, 0);
t2 = millis();
printf1(TAG_TIME,"CBOR writeback: %d ms\n",(uint32_t)(t2-t1));
is_busy = 0;
break;
#endif
case CTAPHID_MSG:
printf1(TAG_HID,"CTAPHID_MSG\n");
if (len == 0)
{
printf2(TAG_ERR,"Error,invalid 0 length field for MSG/U2F packet\n");
ctaphid_send_error(cid, CTAP1_ERR_INVALID_LENGTH);
return 0;
}
if (is_busy)
{
printf1(TAG_HID,"Channel busy for MSG\n");
ctaphid_send_error(cid, CTAP1_ERR_CHANNEL_BUSY);
return 0;
}
is_busy = 1;
ctap_response_init(&ctap_resp);
u2f_request((struct u2f_request_apdu*)ctap_buffer, &ctap_resp);
ctaphid_write_buffer_init(&wb);
wb.cid = cid;
wb.cmd = CTAPHID_MSG;
wb.bcnt = (ctap_resp.length);
ctaphid_write(&wb, ctap_resp.data, ctap_resp.length);
ctaphid_write(&wb, NULL, 0);
is_busy = 0;
break;
case CTAPHID_CANCEL:
printf1(TAG_HID,"CTAPHID_CANCEL\n");
is_busy = 0;
break;
default:
printf2(TAG_ERR,"error, unimplemented HID cmd: %02x\r\n", buffer_cmd());
ctaphid_send_error(cid, CTAP1_ERR_INVALID_COMMAND);
break;
}
cid_del(cid);
buffer_reset();
printf1(TAG_HID,"\n");
if (!is_busy) return cmd;
else return 0;
}

Wyświetl plik

@ -36,6 +36,7 @@
#define CTAPHID_CBOR (TYPE_INIT | 0x10)
#define CTAPHID_CANCEL (TYPE_INIT | 0x11)
#define CTAPHID_ERROR (TYPE_INIT | 0x3f)
#define CTAPHID_KEEPALIVE (TYPE_INIT | 0x3b)
#define ERR_INVALID_CMD 0x01
#define ERR_INVALID_PAR 0x02
@ -43,6 +44,11 @@
#define ERR_MSG_TIMEOUT 0x05
#define ERR_CHANNEL_BUSY 0x06
#define CTAPHID_PROTOCOL_VERSION 2
#define CTAPHID_STATUS_IDLE 0
#define CTAPHID_STATUS_PROCESSING 1
#define CTAPHID_STATUS_UPNEEDED 2
#define CTAPHID_INIT_PAYLOAD_SIZE (HID_MESSAGE_SIZE-7)
#define CTAPHID_CONT_PAYLOAD_SIZE (HID_MESSAGE_SIZE-5)
@ -91,10 +97,12 @@ typedef struct
void ctaphid_init();
void ctaphid_handle_packet(uint8_t * pkt_raw);
uint8_t ctaphid_handle_packet(uint8_t * pkt_raw);
void ctaphid_check_timeouts();
void ctaphid_update_status(int8_t status);
#define ctaphid_packet_len(pkt) ((uint16_t)((pkt)->pkt.init.bcnth << 8) | ((pkt)->pkt.init.bcntl))

Wyświetl plik

@ -28,6 +28,8 @@ void device_init();
uint32_t millis();
void delay(uint32_t ms);
// HID message size in bytes
#define HID_MESSAGE_SIZE 64
@ -53,9 +55,15 @@ int authenticator_is_backup_initialized();
void authenticator_write_state(AuthenticatorState *, int backup);
// Called each main loop. Doesn't need to do anything.
void device_manage();
// sets status that's uses for sending status updates ~100ms.
// A timer should be set up to call `ctaphid_update_status`
void device_set_status(int status);
// Test for user presence
// Return 1 for user is present, 0 user not present
// Return 1 for user is present, 0 user not present, -1 if cancel is requested.
extern int ctap_user_presence_test();
// Generate @num bytes of random numbers to @dest

Wyświetl plik

@ -36,29 +36,25 @@
int main(int argc, char * argv[])
{
int count = 0;
uint32_t t1 = 0;
uint32_t t2 = 0;
uint32_t accum = 0;
uint32_t dt = 0;
uint8_t hidmsg[64];
uint32_t t1 = 0;
set_logging_mask(
/*0*/
TAG_GEN|
/*TAG_MC |*/
/*TAG_GA |*/
TAG_WALLET |
// TAG_GEN|
// TAG_MC |
// TAG_GA |
// TAG_WALLET |
TAG_STOR |
/*TAG_CP |*/
TAG_CTAP|
// TAG_HID|
// TAG_CP |
// TAG_CTAP|
// TAG_HID|
/*TAG_U2F|*/
/*TAG_PARSE |*/
// TAG_TIME|
/*TAG_DUMP|*/
/*TAG_GREEN|*/
/*TAG_RED|*/
// TAG_PARSE |
// TAG_TIME|
// TAG_DUMP|
TAG_GREEN|
TAG_RED|
TAG_ERR
);
@ -85,30 +81,23 @@ int main(int argc, char * argv[])
t1 = millis();
}
device_manage();
if (usbhid_recv(hidmsg) > 0)
{
printf1(TAG_DUMP,"%d>> ",count++); dump_hex1(TAG_DUMP, hidmsg,sizeof(hidmsg));
t2 = millis();
ctaphid_handle_packet(hidmsg);
accum += millis() - t2;
printf1(TAG_TIME,"accum: %d\n", (uint32_t)accum);
printf1(TAG_TIME,"dt: %d\n", t2 - dt);
dt = t2;
memset(hidmsg, 0, sizeof(hidmsg));
}
else
{
/*main_loop_delay();*/
}
ctaphid_check_timeouts();
}
// Should never get here
usbhid_close();
printf("done\n");
printf1(TAG_GREEN, "done\n");
return 0;
}
#endif

Wyświetl plik

@ -39,8 +39,9 @@ typedef struct
// Pin information
uint8_t is_initialized;
uint8_t is_pin_set;
uint8_t pin_code[NEW_PIN_ENC_MAX_SIZE];
uint8_t remaining_tries;
uint8_t pin_code[NEW_PIN_ENC_MIN_SIZE];
int pin_code_length;
int8_t remaining_tries;
uint16_t key_lens[MAX_KEYS];
uint8_t key_space[KEY_SPACE_BYTES];

Wyświetl plik

@ -124,7 +124,7 @@ int main(int argc, char * argv[])
// Should never get here
usbhid_close();
printf("done\n");
printf1(TAG_GREEN, "done\n");
return 0;
}

Wyświetl plik

@ -11,6 +11,7 @@ nav:
- FIDO2 Implementation: fido2-impl.md
- Signed update process: signed-updates.md
- Building: building.md
- Code documentation: code-overview.md
- Contributing Code: contributing.md
- Contributing Docs: documenting.md
- What the udev?!: udev.md

Wyświetl plik

@ -410,7 +410,7 @@ void authenticator_initialize()
}
}
void manage_device()
{
}

Wyświetl plik

@ -1,16 +1,32 @@
CC=arm-none-eabi-gcc
CP=arm-none-eabi-objcopy
SZ=arm-none-eabi-size
AR=arm-none-eabi-ar
# ST related
SRC = src/main.c src/init.c src/redirect.c src/flash.c src/rng.c src/led.c src/device.c
SRC += src/fifo.c
SRC += ../../fido2/util.c
SRC += src/fifo.c src/crypto.c src/attestation.c
SRC += src/startup_stm32l432xx.s src/system_stm32l4xx.c
SRC += $(wildcard lib/*.c) $(wildcard lib/usbd/*.c)
# FIDO2 lib
SRC += ../../fido2/util.c ../../fido2/u2f.c ../../fido2/test_power.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
# Crypto libs
SRC += ../../crypto/sha256/sha256.c ../../crypto/micro-ecc/uECC.c ../../crypto/tiny-AES-c/aes.c
OBJ1=$(SRC:.c=.o)
OBJ=$(OBJ1:.s=.o)
INC=-Isrc/ -Isrc/cmsis/ -Ilib/ -Ilib/usbd/ -I../../fido2/
INC = -Isrc/ -Isrc/cmsis/ -Ilib/ -Ilib/usbd/ -I../../fido2/ -I../../fido2/extensions
INC += -I../../tinycbor/src -I../../crypto/sha256 -I../../crypto/micro-ecc
INC += -I../../crypto/tiny-AES-c
SEARCH=-L../../tinycbor/lib
LDSCRIPT=stm32l432xx.ld
CFLAGS= $(INC)
@ -23,8 +39,13 @@ HW=-mcpu=cortex-m4 -mfpu=fpv4-sp-d16 -mfloat-abi=hard -mthumb
# Solo
CHIP=STM32L442xx
CFLAGS=$(INC) -c -D$(CHIP) -DUSE_FULL_LL_DRIVER -Os -Wall -fdata-sections -ffunction-sections
LDFLAGS=$(HW) -specs=nano.specs -specs=nosys.specs -T$(LDSCRIPT) -Wl,-Map=$(TARGET).map,--cref -Wl,--gc-sections -u _printf_float
DEFINES = -D$(CHIP) -DAES256=1 -DUSE_FULL_LL_DRIVER
# DEFINES += -DTEST_SOLO_STM32 -DTEST -DTEST_FIFO=1
CFLAGS=$(INC) -c $(DEFINES) -Wall -fdata-sections -ffunction-sections $(HW)
LDFLAGS_LIB=$(HW) $(SEARCH) -specs=nano.specs -specs=nosys.specs -Wl,--gc-sections -u _printf_float -lnosys
LDFLAGS=$(HW) $(LDFLAGS_LIB) -T$(LDSCRIPT) -Wl,-Map=$(TARGET).map,--cref -ltinycbor
.PRECIOUS: %.o
@ -32,11 +53,13 @@ all: $(TARGET).elf
$(SZ) $^
%.o: %.c
$(CC) $^ $(HW) $(CFLAGS) -o $@
$(CC) $^ $(HW) -Os $(CFLAGS) -o $@
../../crypto/micro-ecc/uECC.o: ../../crypto/micro-ecc/uECC.c
$(CC) $^ $(HW) -O3 $(CFLAGS) -o $@
%.o: %.s
$(CC) $^ $(HW) $(CFLAGS) -o $@
$(CC) $^ $(HW) -Os $(CFLAGS) -o $@
%.elf: $(OBJ)
$(CC) $^ $(HW) $(LDFLAGS) -o $@
@ -48,16 +71,14 @@ clean:
rm -f *.o src/*.o src/*.elf *.elf *.hex $(OBJ)
flash: $(TARGET).hex
STM32_Programmer_CLI -c port=SWD -halt -d $(TARGET).hex -rst
sleep 0.5
python dfuse-tool/dfuse-tool.py --leave
STM32_Programmer_CLI -c port=SWD -halt -e all --readunprotect
STM32_Programmer_CLI -c port=SWD -halt -d $(TARGET).hex -rst
test:
STM32_Programmer_CLI -c port=SWD -halt -d ../../../cube_stm32l442/build/cube_stm32l442.hex -rst
sleep 0.5
python dfuse-tool/dfuse-tool.py --leave
detach:
STM32_Programmer_CLI -c port=usb1 -ob nBOOT0=1
test2:
STM32_Programmer_CLI -c port=SWD -halt -d ../../../stmusb2/build/stmusb2.hex -rst
sleep 0.5
python dfuse-tool/dfuse-tool.py --leave
cbor:
cd ../../tinycbor/ && make clean
cd ../../tinycbor/ && make CC="$(CC)" AR=$(AR) \
LDFLAGS="$(LDFLAGS_LIB)" \
CFLAGS="$(CFLAGS)"

Wyświetl plik

@ -1,707 +0,0 @@
/**
******************************************************************************
* @file usbd_hid.c
* @author MCD Application Team
* @brief This file provides the HID core functions.
*
* @verbatim
*
* ===================================================================
* HID Class Description
* ===================================================================
* This module manages the HID class V1.11 following the "Device Class Definition
* for Human Interface Devices (HID) Version 1.11 Jun 27, 2001".
* This driver implements the following aspects of the specification:
* - The Boot Interface Subclass
* - The Mouse protocol
* - Usage Page : Generic Desktop
* - Usage : Joystick
* - Collection : Application
*
* @note In HS mode and when the DMA is used, all variables and data structures
* dealing with the DMA during the transaction process should be 32-bit aligned.
*
*
* @endverbatim
*
******************************************************************************
* @attention
*
* <h2><center>&copy; Copyright (c) 2017 STMicroelectronics International N.V.
* All rights reserved.</center></h2>
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted, provided that the following conditions are met:
*
* 1. Redistribution of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* 3. Neither the name of STMicroelectronics nor the names of other
* contributors to this software may be used to endorse or promote products
* derived from this software without specific written permission.
* 4. This software, including modifications and/or derivative works of this
* software, must execute solely and exclusively on microcontroller or
* microprocessor devices manufactured by or for STMicroelectronics.
* 5. Redistribution and use of this software other than as permitted under
* this license is void and will automatically terminate your rights under
* this license.
*
* THIS SOFTWARE IS PROVIDED BY STMICROELECTRONICS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS, IMPLIED OR STATUTORY WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
* PARTICULAR PURPOSE AND NON-INFRINGEMENT OF THIRD PARTY INTELLECTUAL PROPERTY
* RIGHTS ARE DISCLAIMED TO THE FULLEST EXTENT PERMITTED BY LAW. IN NO EVENT
* SHALL STMICROELECTRONICS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
******************************************************************************
*/
/* BSPDependencies
- "stm32xxxxx_{eval}{discovery}{nucleo_144}.c"
- "stm32xxxxx_{eval}{discovery}_io.c"
EndBSPDependencies */
/* Includes ------------------------------------------------------------------*/
#include "usbd_hid.h"
#include "usbd_ctlreq.h"
/** @addtogroup STM32_USB_DEVICE_LIBRARY
* @{
*/
/** @defgroup USBD_HID
* @brief usbd core module
* @{
*/
/** @defgroup USBD_HID_Private_TypesDefinitions
* @{
*/
/**
* @}
*/
/** @defgroup USBD_HID_Private_Defines
* @{
*/
/**
* @}
*/
/** @defgroup USBD_HID_Private_Macros
* @{
*/
/**
* @}
*/
/** @defgroup USBD_HID_Private_FunctionPrototypes
* @{
*/
static uint8_t USBD_HID_Init (USBD_HandleTypeDef *pdev,
uint8_t cfgidx);
static uint8_t USBD_HID_DeInit (USBD_HandleTypeDef *pdev,
uint8_t cfgidx);
static uint8_t USBD_HID_Setup (USBD_HandleTypeDef *pdev,
USBD_SetupReqTypedef *req);
static uint8_t *USBD_HID_GetFSCfgDesc (uint16_t *length);
static uint8_t *USBD_HID_GetHSCfgDesc (uint16_t *length);
static uint8_t *USBD_HID_GetOtherSpeedCfgDesc (uint16_t *length);
static uint8_t *USBD_HID_GetDeviceQualifierDesc (uint16_t *length);
static uint8_t USBD_HID_DataIn (USBD_HandleTypeDef *pdev, uint8_t epnum);
/**
* @}
*/
/** @defgroup USBD_HID_Private_Variables
* @{
*/
USBD_ClassTypeDef USBD_HID =
{
USBD_HID_Init,
USBD_HID_DeInit,
USBD_HID_Setup,
NULL, /*EP0_TxSent*/
NULL, /*EP0_RxReady*/
USBD_HID_DataIn, /*DataIn*/
NULL, /*DataOut*/
NULL, /*SOF */
NULL,
NULL,
USBD_HID_GetHSCfgDesc,
USBD_HID_GetFSCfgDesc,
USBD_HID_GetOtherSpeedCfgDesc,
USBD_HID_GetDeviceQualifierDesc,
};
/* USB HID device FS Configuration Descriptor */
__ALIGN_BEGIN static uint8_t USBD_HID_CfgFSDesc[USB_HID_CONFIG_DESC_SIZ] __ALIGN_END =
{
0x09, /* bLength: Configuration Descriptor size */
USB_DESC_TYPE_CONFIGURATION, /* bDescriptorType: Configuration */
USB_HID_CONFIG_DESC_SIZ,
/* wTotalLength: Bytes returned */
0x00,
0x01, /*bNumInterfaces: 1 interface*/
0x01, /*bConfigurationValue: Configuration value*/
0x00, /*iConfiguration: Index of string descriptor describing
the configuration*/
0xE0, /*bmAttributes: bus powered and Support Remote Wake-up */
0x32, /*MaxPower 100 mA: this current is used for detecting Vbus*/
/************** Descriptor of Joystick Mouse interface ****************/
/* 09 */
0x09, /*bLength: Interface Descriptor size*/
USB_DESC_TYPE_INTERFACE,/*bDescriptorType: Interface descriptor type*/
0x00, /*bInterfaceNumber: Number of Interface*/
0x00, /*bAlternateSetting: Alternate setting*/
0x01, /*bNumEndpoints*/
0x03, /*bInterfaceClass: HID*/
0x01, /*bInterfaceSubClass : 1=BOOT, 0=no boot*/
0x02, /*nInterfaceProtocol : 0=none, 1=keyboard, 2=mouse*/
0, /*iInterface: Index of string descriptor*/
/******************** Descriptor of Joystick Mouse HID ********************/
/* 18 */
0x09, /*bLength: HID Descriptor size*/
HID_DESCRIPTOR_TYPE, /*bDescriptorType: HID*/
0x11, /*bcdHID: HID Class Spec release number*/
0x01,
0x00, /*bCountryCode: Hardware target country*/
0x01, /*bNumDescriptors: Number of HID class descriptors to follow*/
0x22, /*bDescriptorType*/
HID_MOUSE_REPORT_DESC_SIZE,/*wItemLength: Total length of Report descriptor*/
0x00,
/******************** Descriptor of Mouse endpoint ********************/
/* 27 */
0x07, /*bLength: Endpoint Descriptor size*/
USB_DESC_TYPE_ENDPOINT, /*bDescriptorType:*/
HID_EPIN_ADDR, /*bEndpointAddress: Endpoint Address (IN)*/
0x03, /*bmAttributes: Interrupt endpoint*/
HID_EPIN_SIZE, /*wMaxPacketSize: 4 Byte max */
0x00,
HID_FS_BINTERVAL, /*bInterval: Polling Interval */
/* 34 */
};
/* USB HID device HS Configuration Descriptor */
__ALIGN_BEGIN static uint8_t USBD_HID_CfgHSDesc[USB_HID_CONFIG_DESC_SIZ] __ALIGN_END =
{
0x09, /* bLength: Configuration Descriptor size */
USB_DESC_TYPE_CONFIGURATION, /* bDescriptorType: Configuration */
USB_HID_CONFIG_DESC_SIZ,
/* wTotalLength: Bytes returned */
0x00,
0x01, /*bNumInterfaces: 1 interface*/
0x01, /*bConfigurationValue: Configuration value*/
0x00, /*iConfiguration: Index of string descriptor describing
the configuration*/
0xE0, /*bmAttributes: bus powered and Support Remote Wake-up */
0x32, /*MaxPower 100 mA: this current is used for detecting Vbus*/
/************** Descriptor of Joystick Mouse interface ****************/
/* 09 */
0x09, /*bLength: Interface Descriptor size*/
USB_DESC_TYPE_INTERFACE,/*bDescriptorType: Interface descriptor type*/
0x00, /*bInterfaceNumber: Number of Interface*/
0x00, /*bAlternateSetting: Alternate setting*/
0x01, /*bNumEndpoints*/
0x03, /*bInterfaceClass: HID*/
0x01, /*bInterfaceSubClass : 1=BOOT, 0=no boot*/
0x02, /*nInterfaceProtocol : 0=none, 1=keyboard, 2=mouse*/
0, /*iInterface: Index of string descriptor*/
/******************** Descriptor of Joystick Mouse HID ********************/
/* 18 */
0x09, /*bLength: HID Descriptor size*/
HID_DESCRIPTOR_TYPE, /*bDescriptorType: HID*/
0x11, /*bcdHID: HID Class Spec release number*/
0x01,
0x00, /*bCountryCode: Hardware target country*/
0x01, /*bNumDescriptors: Number of HID class descriptors to follow*/
0x22, /*bDescriptorType*/
HID_MOUSE_REPORT_DESC_SIZE,/*wItemLength: Total length of Report descriptor*/
0x00,
/******************** Descriptor of Mouse endpoint ********************/
/* 27 */
0x07, /*bLength: Endpoint Descriptor size*/
USB_DESC_TYPE_ENDPOINT, /*bDescriptorType:*/
HID_EPIN_ADDR, /*bEndpointAddress: Endpoint Address (IN)*/
0x03, /*bmAttributes: Interrupt endpoint*/
HID_EPIN_SIZE, /*wMaxPacketSize: 4 Byte max */
0x00,
HID_HS_BINTERVAL, /*bInterval: Polling Interval */
/* 34 */
};
/* USB HID device Other Speed Configuration Descriptor */
__ALIGN_BEGIN static uint8_t USBD_HID_OtherSpeedCfgDesc[USB_HID_CONFIG_DESC_SIZ] __ALIGN_END =
{
0x09, /* bLength: Configuration Descriptor size */
USB_DESC_TYPE_CONFIGURATION, /* bDescriptorType: Configuration */
USB_HID_CONFIG_DESC_SIZ,
/* wTotalLength: Bytes returned */
0x00,
0x01, /*bNumInterfaces: 1 interface*/
0x01, /*bConfigurationValue: Configuration value*/
0x00, /*iConfiguration: Index of string descriptor describing
the configuration*/
0xE0, /*bmAttributes: bus powered and Support Remote Wake-up */
0x32, /*MaxPower 100 mA: this current is used for detecting Vbus*/
/************** Descriptor of Joystick Mouse interface ****************/
/* 09 */
0x09, /*bLength: Interface Descriptor size*/
USB_DESC_TYPE_INTERFACE,/*bDescriptorType: Interface descriptor type*/
0x00, /*bInterfaceNumber: Number of Interface*/
0x00, /*bAlternateSetting: Alternate setting*/
0x01, /*bNumEndpoints*/
0x03, /*bInterfaceClass: HID*/
0x01, /*bInterfaceSubClass : 1=BOOT, 0=no boot*/
0x02, /*nInterfaceProtocol : 0=none, 1=keyboard, 2=mouse*/
0, /*iInterface: Index of string descriptor*/
/******************** Descriptor of Joystick Mouse HID ********************/
/* 18 */
0x09, /*bLength: HID Descriptor size*/
HID_DESCRIPTOR_TYPE, /*bDescriptorType: HID*/
0x11, /*bcdHID: HID Class Spec release number*/
0x01,
0x00, /*bCountryCode: Hardware target country*/
0x01, /*bNumDescriptors: Number of HID class descriptors to follow*/
0x22, /*bDescriptorType*/
HID_MOUSE_REPORT_DESC_SIZE,/*wItemLength: Total length of Report descriptor*/
0x00,
/******************** Descriptor of Mouse endpoint ********************/
/* 27 */
0x07, /*bLength: Endpoint Descriptor size*/
USB_DESC_TYPE_ENDPOINT, /*bDescriptorType:*/
HID_EPIN_ADDR, /*bEndpointAddress: Endpoint Address (IN)*/
0x03, /*bmAttributes: Interrupt endpoint*/
HID_EPIN_SIZE, /*wMaxPacketSize: 4 Byte max */
0x00,
HID_FS_BINTERVAL, /*bInterval: Polling Interval */
/* 34 */
};
/* USB HID device Configuration Descriptor */
__ALIGN_BEGIN static uint8_t USBD_HID_Desc[USB_HID_DESC_SIZ] __ALIGN_END =
{
/* 18 */
0x09, /*bLength: HID Descriptor size*/
HID_DESCRIPTOR_TYPE, /*bDescriptorType: HID*/
0x11, /*bcdHID: HID Class Spec release number*/
0x01,
0x00, /*bCountryCode: Hardware target country*/
0x01, /*bNumDescriptors: Number of HID class descriptors to follow*/
0x22, /*bDescriptorType*/
HID_MOUSE_REPORT_DESC_SIZE,/*wItemLength: Total length of Report descriptor*/
0x00,
};
/* USB Standard Device Descriptor */
__ALIGN_BEGIN static uint8_t USBD_HID_DeviceQualifierDesc[USB_LEN_DEV_QUALIFIER_DESC] __ALIGN_END =
{
USB_LEN_DEV_QUALIFIER_DESC,
USB_DESC_TYPE_DEVICE_QUALIFIER,
0x00,
0x02,
0x00,
0x00,
0x00,
0x40,
0x01,
0x00,
};
__ALIGN_BEGIN static uint8_t HID_MOUSE_ReportDesc[HID_MOUSE_REPORT_DESC_SIZE] __ALIGN_END =
{
0x05, 0x01,
0x09, 0x02,
0xA1, 0x01,
0x09, 0x01,
0xA1, 0x00,
0x05, 0x09,
0x19, 0x01,
0x29, 0x03,
0x15, 0x00,
0x25, 0x01,
0x95, 0x03,
0x75, 0x01,
0x81, 0x02,
0x95, 0x01,
0x75, 0x05,
0x81, 0x01,
0x05, 0x01,
0x09, 0x30,
0x09, 0x31,
0x09, 0x38,
0x15, 0x81,
0x25, 0x7F,
0x75, 0x08,
0x95, 0x03,
0x81, 0x06,
0xC0, 0x09,
0x3c, 0x05,
0xff, 0x09,
0x01, 0x15,
0x00, 0x25,
0x01, 0x75,
0x01, 0x95,
0x02, 0xb1,
0x22, 0x75,
0x06, 0x95,
0x01, 0xb1,
0x01, 0xc0
};
/**
* @}
*/
/** @defgroup USBD_HID_Private_Functions
* @{
*/
/**
* @brief USBD_HID_Init
* Initialize the HID interface
* @param pdev: device instance
* @param cfgidx: Configuration index
* @retval status
*/
static uint8_t USBD_HID_Init (USBD_HandleTypeDef *pdev, uint8_t cfgidx)
{
/* Open EP IN */
USBD_LL_OpenEP(pdev, HID_EPIN_ADDR, USBD_EP_TYPE_INTR, HID_EPIN_SIZE);
pdev->ep_in[HID_EPIN_ADDR & 0xFU].is_used = 1U;
pdev->pClassData = USBD_malloc(sizeof (USBD_HID_HandleTypeDef));
if (pdev->pClassData == NULL)
{
return USBD_FAIL;
}
((USBD_HID_HandleTypeDef *)pdev->pClassData)->state = HID_IDLE;
return USBD_OK;
}
/**
* @brief USBD_HID_Init
* DeInitialize the HID layer
* @param pdev: device instance
* @param cfgidx: Configuration index
* @retval status
*/
static uint8_t USBD_HID_DeInit (USBD_HandleTypeDef *pdev,
uint8_t cfgidx)
{
/* Close HID EPs */
USBD_LL_CloseEP(pdev, HID_EPIN_ADDR);
pdev->ep_in[HID_EPIN_ADDR & 0xFU].is_used = 0U;
/* FRee allocated memory */
if(pdev->pClassData != NULL)
{
USBD_free(pdev->pClassData);
pdev->pClassData = NULL;
}
return USBD_OK;
}
/**
* @brief USBD_HID_Setup
* Handle the HID specific requests
* @param pdev: instance
* @param req: usb requests
* @retval status
*/
static uint8_t USBD_HID_Setup (USBD_HandleTypeDef *pdev,
USBD_SetupReqTypedef *req)
{
USBD_HID_HandleTypeDef *hhid = (USBD_HID_HandleTypeDef*) pdev->pClassData;
uint16_t len = 0U;
uint8_t *pbuf = NULL;
uint16_t status_info = 0U;
USBD_StatusTypeDef ret = USBD_OK;
switch (req->bmRequest & USB_REQ_TYPE_MASK)
{
case USB_REQ_TYPE_CLASS :
switch (req->bRequest)
{
case HID_REQ_SET_PROTOCOL:
hhid->Protocol = (uint8_t)(req->wValue);
break;
case HID_REQ_GET_PROTOCOL:
USBD_CtlSendData (pdev, (uint8_t *)(void *)&hhid->Protocol, 1U);
break;
case HID_REQ_SET_IDLE:
hhid->IdleState = (uint8_t)(req->wValue >> 8);
break;
case HID_REQ_GET_IDLE:
USBD_CtlSendData (pdev, (uint8_t *)(void *)&hhid->IdleState, 1U);
break;
default:
USBD_CtlError (pdev, req);
ret = USBD_FAIL;
break;
}
break;
case USB_REQ_TYPE_STANDARD:
switch (req->bRequest)
{
case USB_REQ_GET_STATUS:
if (pdev->dev_state == USBD_STATE_CONFIGURED)
{
USBD_CtlSendData (pdev, (uint8_t *)(void *)&status_info, 2U);
}
else
{
USBD_CtlError (pdev, req);
ret = USBD_FAIL;
}
break;
case USB_REQ_GET_DESCRIPTOR:
if(req->wValue >> 8 == HID_REPORT_DESC)
{
len = MIN(HID_MOUSE_REPORT_DESC_SIZE , req->wLength);
pbuf = HID_MOUSE_ReportDesc;
}
else if(req->wValue >> 8 == HID_DESCRIPTOR_TYPE)
{
pbuf = USBD_HID_Desc;
len = MIN(USB_HID_DESC_SIZ, req->wLength);
}
else
{
USBD_CtlError (pdev, req);
ret = USBD_FAIL;
break;
}
USBD_CtlSendData (pdev, pbuf, len);
break;
case USB_REQ_GET_INTERFACE :
if (pdev->dev_state == USBD_STATE_CONFIGURED)
{
USBD_CtlSendData (pdev, (uint8_t *)(void *)&hhid->AltSetting, 1U);
}
else
{
USBD_CtlError (pdev, req);
ret = USBD_FAIL;
}
break;
case USB_REQ_SET_INTERFACE :
if (pdev->dev_state == USBD_STATE_CONFIGURED)
{
hhid->AltSetting = (uint8_t)(req->wValue);
}
else
{
USBD_CtlError (pdev, req);
ret = USBD_FAIL;
}
break;
default:
USBD_CtlError (pdev, req);
ret = USBD_FAIL;
break;
}
break;
default:
USBD_CtlError (pdev, req);
ret = USBD_FAIL;
break;
}
return ret;
}
/**
* @brief USBD_HID_SendReport
* Send HID Report
* @param pdev: device instance
* @param buff: pointer to report
* @retval status
*/
uint8_t USBD_HID_SendReport (USBD_HandleTypeDef *pdev,
uint8_t *report,
uint16_t len)
{
USBD_HID_HandleTypeDef *hhid = (USBD_HID_HandleTypeDef*)pdev->pClassData;
if (pdev->dev_state == USBD_STATE_CONFIGURED )
{
if(hhid->state == HID_IDLE)
{
hhid->state = HID_BUSY;
USBD_LL_Transmit (pdev,
HID_EPIN_ADDR,
report,
len);
}
}
return USBD_OK;
}
/**
* @brief USBD_HID_GetPollingInterval
* return polling interval from endpoint descriptor
* @param pdev: device instance
* @retval polling interval
*/
uint32_t USBD_HID_GetPollingInterval (USBD_HandleTypeDef *pdev)
{
uint32_t polling_interval = 0U;
/* HIGH-speed endpoints */
if(pdev->dev_speed == USBD_SPEED_HIGH)
{
/* Sets the data transfer polling interval for high speed transfers.
Values between 1..16 are allowed. Values correspond to interval
of 2 ^ (bInterval-1). This option (8 ms, corresponds to HID_HS_BINTERVAL */
polling_interval = (((1U <<(HID_HS_BINTERVAL - 1U))) / 8U);
}
else /* LOW and FULL-speed endpoints */
{
/* Sets the data transfer polling interval for low and full
speed transfers */
polling_interval = HID_FS_BINTERVAL;
}
return ((uint32_t)(polling_interval));
}
/**
* @brief USBD_HID_GetCfgFSDesc
* return FS configuration descriptor
* @param speed : current device speed
* @param length : pointer data length
* @retval pointer to descriptor buffer
*/
static uint8_t *USBD_HID_GetFSCfgDesc (uint16_t *length)
{
*length = sizeof (USBD_HID_CfgFSDesc);
return USBD_HID_CfgFSDesc;
}
/**
* @brief USBD_HID_GetCfgHSDesc
* return HS configuration descriptor
* @param speed : current device speed
* @param length : pointer data length
* @retval pointer to descriptor buffer
*/
static uint8_t *USBD_HID_GetHSCfgDesc (uint16_t *length)
{
*length = sizeof (USBD_HID_CfgHSDesc);
return USBD_HID_CfgHSDesc;
}
/**
* @brief USBD_HID_GetOtherSpeedCfgDesc
* return other speed configuration descriptor
* @param speed : current device speed
* @param length : pointer data length
* @retval pointer to descriptor buffer
*/
static uint8_t *USBD_HID_GetOtherSpeedCfgDesc (uint16_t *length)
{
*length = sizeof (USBD_HID_OtherSpeedCfgDesc);
return USBD_HID_OtherSpeedCfgDesc;
}
/**
* @brief USBD_HID_DataIn
* handle data IN Stage
* @param pdev: device instance
* @param epnum: endpoint index
* @retval status
*/
static uint8_t USBD_HID_DataIn (USBD_HandleTypeDef *pdev,
uint8_t epnum)
{
/* Ensure that the FIFO is empty before a new transfer, this condition could
be caused by a new transfer before the end of the previous transfer */
((USBD_HID_HandleTypeDef *)pdev->pClassData)->state = HID_IDLE;
return USBD_OK;
}
/**
* @brief DeviceQualifierDescriptor
* return Device Qualifier descriptor
* @param length : pointer data length
* @retval pointer to descriptor buffer
*/
static uint8_t *USBD_HID_GetDeviceQualifierDesc (uint16_t *length)
{
*length = sizeof (USBD_HID_DeviceQualifierDesc);
return USBD_HID_DeviceQualifierDesc;
}
/**
* @}
*/
/**
* @}
*/
/**
* @}
*/
/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/

Wyświetl plik

@ -1,170 +0,0 @@
/**
******************************************************************************
* @file usbd_hid.h
* @author MCD Application Team
* @brief Header file for the usbd_hid_core.c file.
******************************************************************************
* @attention
*
* <h2><center>&copy; Copyright (c) 2017 STMicroelectronics International N.V.
* All rights reserved.</center></h2>
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted, provided that the following conditions are met:
*
* 1. Redistribution of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* 3. Neither the name of STMicroelectronics nor the names of other
* contributors to this software may be used to endorse or promote products
* derived from this software without specific written permission.
* 4. This software, including modifications and/or derivative works of this
* software, must execute solely and exclusively on microcontroller or
* microprocessor devices manufactured by or for STMicroelectronics.
* 5. Redistribution and use of this software other than as permitted under
* this license is void and will automatically terminate your rights under
* this license.
*
* THIS SOFTWARE IS PROVIDED BY STMICROELECTRONICS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS, IMPLIED OR STATUTORY WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
* PARTICULAR PURPOSE AND NON-INFRINGEMENT OF THIRD PARTY INTELLECTUAL PROPERTY
* RIGHTS ARE DISCLAIMED TO THE FULLEST EXTENT PERMITTED BY LAW. IN NO EVENT
* SHALL STMICROELECTRONICS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
******************************************************************************
*/
/* Define to prevent recursive inclusion -------------------------------------*/
#ifndef __USB_HID_H
#define __USB_HID_H
#ifdef __cplusplus
extern "C" {
#endif
/* Includes ------------------------------------------------------------------*/
#include "usbd_ioreq.h"
/** @addtogroup STM32_USB_DEVICE_LIBRARY
* @{
*/
/** @defgroup USBD_HID
* @brief This file is the Header file for usbd_hid.c
* @{
*/
/** @defgroup USBD_HID_Exported_Defines
* @{
*/
#define HID_EPIN_ADDR 0x81U
#define HID_EPIN_SIZE 0x04U
#define USB_HID_CONFIG_DESC_SIZ 34U
#define USB_HID_DESC_SIZ 9U
#define HID_MOUSE_REPORT_DESC_SIZE 74U
#define HID_DESCRIPTOR_TYPE 0x21U
#define HID_REPORT_DESC 0x22U
#ifndef HID_HS_BINTERVAL
#define HID_HS_BINTERVAL 0x07U
#endif /* HID_HS_BINTERVAL */
#ifndef HID_FS_BINTERVAL
#define HID_FS_BINTERVAL 0x0AU
#endif /* HID_FS_BINTERVAL */
#define HID_REQ_SET_PROTOCOL 0x0BU
#define HID_REQ_GET_PROTOCOL 0x03U
#define HID_REQ_SET_IDLE 0x0AU
#define HID_REQ_GET_IDLE 0x02U
#define HID_REQ_SET_REPORT 0x09U
#define HID_REQ_GET_REPORT 0x01U
/**
* @}
*/
/** @defgroup USBD_CORE_Exported_TypesDefinitions
* @{
*/
typedef enum
{
HID_IDLE = 0,
HID_BUSY,
}
HID_StateTypeDef;
typedef struct
{
uint32_t Protocol;
uint32_t IdleState;
uint32_t AltSetting;
HID_StateTypeDef state;
}
USBD_HID_HandleTypeDef;
/**
* @}
*/
/** @defgroup USBD_CORE_Exported_Macros
* @{
*/
/**
* @}
*/
/** @defgroup USBD_CORE_Exported_Variables
* @{
*/
extern USBD_ClassTypeDef USBD_HID;
#define USBD_HID_CLASS &USBD_HID
/**
* @}
*/
/** @defgroup USB_CORE_Exported_Functions
* @{
*/
uint8_t USBD_HID_SendReport (USBD_HandleTypeDef *pdev,
uint8_t *report,
uint16_t len);
uint32_t USBD_HID_GetPollingInterval (USBD_HandleTypeDef *pdev);
/**
* @}
*/
#ifdef __cplusplus
}
#endif
#endif /* __USB_HID_H */
/**
* @}
*/
/**
* @}
*/
/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/

Wyświetl plik

@ -64,23 +64,19 @@ PCD_HandleTypeDef hpcd;
*/
void HAL_PCD_MspInit(PCD_HandleTypeDef *hpcd)
{
SET_BIT(RCC->APB1ENR1, RCC_APB1ENR1_USBFSEN);
if(hpcd->Init.low_power_enable == 1)
{
/* Enable EXTI Line 17 for USB wakeup */
__HAL_USB_WAKEUP_EXTI_ENABLE_IT();
}
/*LL_APB1_GRP1_EnableClock(LL_APB1_GRP1_PERIPH_PWR);*/
// SET_BIT(RCC->APB1ENR1, RCC_APB1ENR1_USBFSEN);
//
// if(hpcd->Init.low_power_enable == 1)
// {
// /* Enable EXTI Line 17 for USB wakeup */
// __HAL_USB_WAKEUP_EXTI_ENABLE_IT();
// }
//
// /*[> Set USB FS Interrupt priority <]*/
// /*HAL_NVIC_SetPriority(USB_IRQn, 0x0F, 0);*/
// NVIC_SetPriority(USB_IRQn, NVIC_EncodePriority(NVIC_GetPriorityGrouping(), 0x0f, 0));
//
// /*[> Enable USB FS Interrupt <]*/
// NVIC_EnableIRQ(USB_IRQn);
/* Set USB FS Interrupt priority */
NVIC_SetPriority(USB_IRQn, NVIC_EncodePriority(NVIC_GetPriorityGrouping(), 0x0f, 0));
/* Enable USB FS Interrupt */
NVIC_EnableIRQ(USB_IRQn);
}
/**
@ -223,35 +219,38 @@ void HAL_PCD_DisconnectCallback(PCD_HandleTypeDef *hpcd)
USBD_LL_DevDisconnected((USBD_HandleTypeDef*)hpcd->pData);
}
/*******************************************************************************
LL Driver Interface (USB Device Library --> PCD)
*******************************************************************************/
/**
* @brief Initializes the Low Level portion of the Device driver.
* @brief Initializes the low level portion of the device driver.
* @param pdev: Device handle
* @retval USBD Status
* @retval USBD status
*/
extern void _Error_Handler(char *file, int line);
USBD_StatusTypeDef USBD_LL_Init(USBD_HandleTypeDef *pdev)
{
/* Set LL Driver parameters */
hpcd.Instance = USB;
hpcd.Init.dev_endpoints = 8;
hpcd.Init.ep0_mps = 0x40;
hpcd.Init.phy_itface = PCD_PHY_EMBEDDED;
hpcd.Init.speed = PCD_SPEED_FULL;
hpcd.Init.low_power_enable = 1;
/* Link The driver to the stack */
/* Enable USB power on Pwrctrl CR2 register. */
SET_BIT(PWR->CR2, PWR_CR2_USV);
/* Link the driver to the stack. */
hpcd.pData = pdev;
pdev->pData = &hpcd;
/* Initialize LL Driver */
HAL_PCD_Init(&hpcd);
HAL_PCDEx_PMAConfig(&hpcd , 0x00 , PCD_SNG_BUF, 0x18);
HAL_PCDEx_PMAConfig(&hpcd , 0x80 , PCD_SNG_BUF, 0x58);
HAL_PCDEx_PMAConfig(&hpcd , 0x81 , PCD_SNG_BUF, 0x100);
hpcd.Instance = USB;
hpcd.Init.dev_endpoints = 8;
hpcd.Init.speed = PCD_SPEED_FULL;
hpcd.Init.ep0_mps = DEP0CTL_MPS_64;
hpcd.Init.phy_itface = PCD_PHY_EMBEDDED;
hpcd.Init.Sof_enable = DISABLE;
hpcd.Init.low_power_enable = DISABLE;
hpcd.Init.lpm_enable = DISABLE;
hpcd.Init.battery_charging_enable = DISABLE;
if (HAL_PCD_Init(&hpcd) != HAL_OK)
{
_Error_Handler(__FILE__, __LINE__);
}
HAL_PCDEx_PMAConfig((PCD_HandleTypeDef*)pdev->pData , 0x00 , PCD_SNG_BUF, 0x18);
HAL_PCDEx_PMAConfig((PCD_HandleTypeDef*)pdev->pData , 0x80 , PCD_SNG_BUF, 0x58);
HAL_PCDEx_PMAConfig((PCD_HandleTypeDef*)pdev->pData , 0x01 , PCD_SNG_BUF, 0x98);
HAL_PCDEx_PMAConfig((PCD_HandleTypeDef*)pdev->pData , 0x81 , PCD_SNG_BUF, 0xd8);
return USBD_OK;
}

Wyświetl plik

@ -95,6 +95,9 @@ static uint8_t *USBD_HID_GetDeviceQualifierDesc (uint16_t *length);
static uint8_t USBD_HID_DataIn (USBD_HandleTypeDef *pdev, uint8_t epnum);
static uint8_t USBD_HID_DataOut (USBD_HandleTypeDef *pdev,
uint8_t epnum);
USBD_ClassTypeDef USBD_HID =
{
@ -104,7 +107,7 @@ USBD_ClassTypeDef USBD_HID =
NULL, /*EP0_TxSent*/
NULL, /*EP0_RxReady*/
USBD_HID_DataIn, /*DataIn*/
NULL, /*DataOut*/
USBD_HID_DataOut, /*DataOut*/
NULL, /*SOF */
NULL,
NULL,
@ -223,8 +226,7 @@ __ALIGN_BEGIN static uint8_t HID_MOUSE_ReportDesc[HID_FIDO_REPORT_DESC_SIZE] __
0x95, HID_PACKET_SIZE, // REPORT_COUNT (64)
0x91, 0x02, // OUTPUT (Data,Var,Abs)
0xc0,// END_COLLECTION
0xc0,// END_COLLECTION
};
@ -233,12 +235,46 @@ static uint8_t hidmsg_buf[64];
void usb_hid_recieve_callback(uint8_t ep)
{
fifo_hidmsg_add(hidmsg_buf);
memset(hidmsg_buf,0,64);
USBD_LL_PrepareReceive(&Solo_USBD_Device,
HID_ENDPOINT,
hidmsg_buf,
HID_PACKET_SIZE);
}
static void dump_pma()
{
register uint32_t _wRegBase = (uint32_t)USB;
_wRegBase += (uint32_t)(USB)->BTABLE + 0x400;
uint16_t * pma_ptr = (uint16_t *)_wRegBase;
uint16_t val;
uint32_t offset = (uint32_t)(USB)->BTABLE;
printf("btable: %02lx\r\n",offset);
for (int i = 0; i < 2; i++)
{
uint16_t addr_tx = pma_ptr[i * 4 + 0];
uint16_t cnt_tx = pma_ptr[i * 4 + 1];
uint16_t addr_rx = pma_ptr[i * 4 + 2];
uint16_t cnt_rx = pma_ptr[i * 4 + 3];
printf("EP%d addr_tx == %02x, count_tx == %02x\r\n", i, addr_tx,cnt_tx );
printf("EP%d addr_rx == %02x, count_rx == %02x\r\n", i, addr_rx,cnt_rx );
}
uint16_t ep1_tx = pma_ptr[1 * 4 + 0];
for (int i = 0; i < 32; i++)
{
val = pma_ptr[ep1_tx + i];
printf("%04x ",val);
}
printf("\r\n");
}
/**
* @brief USBD_HID_Init
* Initialize the HID interface
@ -252,17 +288,12 @@ static uint8_t USBD_HID_Init (USBD_HandleTypeDef *pdev, uint8_t cfgidx)
/* Open EP IN */
USBD_LL_OpenEP(pdev, HID_EPIN_ADDR, USBD_EP_TYPE_INTR, HID_EPIN_SIZE);
USBD_LL_OpenEP(pdev, HID_EPOUT_ADDR, USBD_EP_TYPE_INTR, HID_EPOUT_SIZE);
static uint8_t mem[4];
static uint8_t mem[sizeof (USBD_HID_HandleTypeDef)];
pdev->ep_in[HID_EPIN_ADDR & 0xFU].is_used = 1U;
pdev->ep_out[HID_EPOUT_ADDR & 0xFU].is_used = 1U;
pdev->pClassData = mem;
if (pdev->pClassData == NULL)
{
return USBD_FAIL;
}
((USBD_HID_HandleTypeDef *)pdev->pClassData)->state = HID_IDLE;
@ -411,60 +442,8 @@ static uint8_t USBD_HID_Setup (USBD_HandleTypeDef *pdev,
return ret;
}
/**
* @brief USBD_HID_SendReport
* Send HID Report
* @param pdev: device instance
* @param buff: pointer to report
* @retval status
*/
uint8_t USBD_HID_SendReport (USBD_HandleTypeDef *pdev,
uint8_t *report,
uint16_t len)
{
USBD_HID_HandleTypeDef *hhid = (USBD_HID_HandleTypeDef*)pdev->pClassData;
if (pdev->dev_state == USBD_STATE_CONFIGURED )
{
if(hhid->state == HID_IDLE)
{
hhid->state = HID_BUSY;
USBD_LL_Transmit (pdev,
HID_EPIN_ADDR,
report,
len);
}
}
return USBD_OK;
}
/**
* @brief USBD_HID_GetPollingInterval
* return polling interval from endpoint descriptor
* @param pdev: device instance
* @retval polling interval
*/
uint32_t USBD_HID_GetPollingInterval (USBD_HandleTypeDef *pdev)
{
uint32_t polling_interval = 0U;
/* HIGH-speed endpoints */
if(pdev->dev_speed == USBD_SPEED_HIGH)
{
/* Sets the data transfer polling interval for high speed transfers.
Values between 1..16 are allowed. Values correspond to interval
of 2 ^ (bInterval-1). This option (8 ms, corresponds to HID_HS_BINTERVAL */
polling_interval = (((1U <<(HID_BINTERVAL - 1U))) / 8U);
}
else /* LOW and FULL-speed endpoints */
{
/* Sets the data transfer polling interval for low and full
speed transfers */
polling_interval = HID_BINTERVAL;
}
return ((uint32_t)(polling_interval));
}
/**
* @brief USBD_HID_GetCfgFSDesc
@ -495,6 +474,14 @@ static uint8_t USBD_HID_DataIn (USBD_HandleTypeDef *pdev,
return USBD_OK;
}
static uint8_t USBD_HID_DataOut (USBD_HandleTypeDef *pdev,
uint8_t epnum)
{
/* Ensure that the FIFO is empty before a new transfer, this condition could
be caused by a new transfer before the end of the previous transfer */
((USBD_HID_HandleTypeDef *)pdev->pClassData)->state = HID_IDLE;
return USBD_OK;
}
/**
* @brief DeviceQualifierDescriptor

Wyświetl plik

@ -66,7 +66,7 @@
#define HID_DESCRIPTOR_TYPE 0x21U
#define HID_REPORT_DESC 0x22U
#define HID_BINTERVAL 10
#define HID_BINTERVAL 5
#define HID_REQ_SET_PROTOCOL 0x0BU
#define HID_REQ_GET_PROTOCOL 0x03U

Wyświetl plik

@ -1,816 +0,0 @@
/**
******************************************************************************
* @file usbd_hid.c
* @author MCD Application Team
* @brief This file provides the HID core functions.
*
* @verbatim
*
* ===================================================================
* HID Class Description
* ===================================================================
* This module manages the HID class V1.11 following the "Device Class Definition
* for Human Interface Devices (HID) Version 1.11 Jun 27, 2001".
* This driver implements the following aspects of the specification:
* - The Boot Interface Subclass
* - The Mouse protocol
* - Usage Page : Generic Desktop
* - Usage : Joystick
* - Collection : Application
*
* @note In HS mode and when the DMA is used, all variables and data structures
* dealing with the DMA during the transaction process should be 32-bit aligned.
*
*
* @endverbatim
*
******************************************************************************
* @attention
*
* <h2><center>&copy; Copyright (c) 2017 STMicroelectronics International N.V.
* All rights reserved.</center></h2>
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted, provided that the following conditions are met:
*
* 1. Redistribution of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* 3. Neither the name of STMicroelectronics nor the names of other
* contributors to this software may be used to endorse or promote products
* derived from this software without specific written permission.
* 4. This software, including modifications and/or derivative works of this
* software, must execute solely and exclusively on microcontroller or
* microprocessor devices manufactured by or for STMicroelectronics.
* 5. Redistribution and use of this software other than as permitted under
* this license is void and will automatically terminate your rights under
* this license.
*
* THIS SOFTWARE IS PROVIDED BY STMICROELECTRONICS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS, IMPLIED OR STATUTORY WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
* PARTICULAR PURPOSE AND NON-INFRINGEMENT OF THIRD PARTY INTELLECTUAL PROPERTY
* RIGHTS ARE DISCLAIMED TO THE FULLEST EXTENT PERMITTED BY LAW. IN NO EVENT
* SHALL STMICROELECTRONICS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
******************************************************************************
*/
/* BSPDependencies
- "stm32xxxxx_{eval}{discovery}{nucleo_144}.c"
- "stm32xxxxx_{eval}{discovery}_io.c"
EndBSPDependencies */
/* Includes ------------------------------------------------------------------*/
#include "usbd_hid.h"
#include "usbd_ctlreq.h"
/** @addtogroup STM32_USB_DEVICE_LIBRARY
* @{
*/
/** @defgroup USBD_HID
* @brief usbd core module
* @{
*/
/** @defgroup USBD_HID_Private_TypesDefinitions
* @{
*/
/**
* @}
*/
/** @defgroup USBD_HID_Private_Defines
* @{
*/
/**
* @}
*/
/** @defgroup USBD_HID_Private_Macros
* @{
*/
/**
* @}
*/
/** @defgroup USBD_HID_Private_FunctionPrototypes
* @{
*/
static uint8_t USBD_HID_Init (USBD_HandleTypeDef *pdev,
uint8_t cfgidx);
static uint8_t USBD_HID_DeInit (USBD_HandleTypeDef *pdev,
uint8_t cfgidx);
static uint8_t USBD_HID_Setup (USBD_HandleTypeDef *pdev,
USBD_SetupReqTypedef *req);
static uint8_t *USBD_HID_GetFSCfgDesc (uint16_t *length);
static uint8_t *USBD_HID_GetHSCfgDesc (uint16_t *length);
static uint8_t *USBD_HID_GetOtherSpeedCfgDesc (uint16_t *length);
static uint8_t *USBD_HID_GetDeviceQualifierDesc (uint16_t *length);
static uint8_t USBD_HID_DataIn (USBD_HandleTypeDef *pdev, uint8_t epnum);
static uint8_t USBD_HID_DataOut (USBD_HandleTypeDef *pdev, uint8_t epnum);
/**
* @}
*/
/** @defgroup USBD_HID_Private_Variables
* @{
*/
USBD_ClassTypeDef USBD_HID =
{
USBD_HID_Init,
USBD_HID_DeInit,
USBD_HID_Setup,
NULL, /*EP0_TxSent*/
NULL, /*EP0_RxReady*/
USBD_HID_DataIn, /*DataIn*/
USBD_HID_DataOut, /*DataOut*/
NULL, /*SOF */
NULL,
NULL,
USBD_HID_GetHSCfgDesc,
USBD_HID_GetFSCfgDesc,
USBD_HID_GetOtherSpeedCfgDesc,
USBD_HID_GetDeviceQualifierDesc,
};
#define USBD_HID_CfgHSDesc USBD_HID_OtherSpeedCfgDesc
#define USBD_HID_CfgFSDesc USBD_HID_OtherSpeedCfgDesc
/* USB HID device FS Configuration Descriptor */
/*__ALIGN_BEGIN static uint8_t USBD_HID_CfgFSDesc[USB_HID_CONFIG_DESC_SIZ] __ALIGN_END =*/
/*{*/
/*0x09, [> bLength: Configuration Descriptor size <]*/
/*USB_DESC_TYPE_CONFIGURATION, [> bDescriptorType: Configuration <]*/
/*USB_HID_CONFIG_DESC_SIZ,*/
/*[> wTotalLength: Bytes returned <]*/
/*0x00,*/
/*0x01, [>bNumInterfaces: 1 interface<]*/
/*0x01, [>bConfigurationValue: Configuration value<]*/
/*0x00, //iConfiguration: Index of string descriptor describing*/
/*//the configuration*/
/*0xE0, [>bmAttributes: bus powered and Support Remote Wake-up <]*/
/*0x32, [>MaxPower 100 mA: this current is used for detecting Vbus<]*/
/*[>************* Descriptor of Joystick Mouse interface ***************<]*/
/*[> 09 <]*/
/*0x09, [>bLength: Interface Descriptor size<]*/
/*USB_DESC_TYPE_INTERFACE,[>bDescriptorType: Interface descriptor type<]*/
/*0x00, [>bInterfaceNumber: Number of Interface<]*/
/*0x00, [>bAlternateSetting: Alternate setting<]*/
/*0x01, [>bNumEndpoints<]*/
/*0x03, [>bInterfaceClass: HID<]*/
/*0x01, [>bInterfaceSubClass : 1=BOOT, 0=no boot<]*/
/*0x02, [>nInterfaceProtocol : 0=none, 1=keyboard, 2=mouse<]*/
/*0, [>iInterface: Index of string descriptor<]*/
/*[>******************* Descriptor of Joystick Mouse HID *******************<]*/
/*[> 18 <]*/
/*0x09, [>bLength: HID Descriptor size<]*/
/*HID_DESCRIPTOR_TYPE, [>bDescriptorType: HID<]*/
/*0x11, [>bcdHID: HID Class Spec release number<]*/
/*0x01,*/
/*0x00, [>bCountryCode: Hardware target country<]*/
/*0x01, [>bNumDescriptors: Number of HID class descriptors to follow<]*/
/*0x22, [>bDescriptorType<]*/
/*HID_MOUSE_REPORT_DESC_SIZE,[>wItemLength: Total length of Report descriptor<]*/
/*0x00,*/
/*[>******************* Descriptor of Mouse endpoint *******************<]*/
/*[> 27 <]*/
/*0x07, [>bLength: Endpoint Descriptor size<]*/
/*USB_DESC_TYPE_ENDPOINT, [>bDescriptorType:<]*/
/*HID_EPIN_ADDR, [>bEndpointAddress: Endpoint Address (IN)<]*/
/*0x03, [>bmAttributes: Interrupt endpoint<]*/
/*HID_EPIN_SIZE, [>wMaxPacketSize: 4 Byte max <]*/
/*0x00,*/
/*HID_FS_BINTERVAL, [>bInterval: Polling Interval <]*/
/*[> 34 <]*/
/*};*/
/* USB HID device HS Configuration Descriptor */
/*__ALIGN_BEGIN static uint8_t USBD_HID_CfgHSDesc[USB_HID_CONFIG_DESC_SIZ] __ALIGN_END =*/
/*{*/
/*0x09, [> bLength: Configuration Descriptor size <]*/
/*USB_DESC_TYPE_CONFIGURATION, [> bDescriptorType: Configuration <]*/
/*USB_HID_CONFIG_DESC_SIZ,*/
/*[> wTotalLength: Bytes returned <]*/
/*0x00,*/
/*0x01, [>bNumInterfaces: 1 interface<]*/
/*0x01, [>bConfigurationValue: Configuration value<]*/
/*0x00, //iConfiguration: Index of string descriptor describing*/
/*the configuration**/
/*0xE0, [>bmAttributes: bus powered and Support Remote Wake-up <]*/
/*0x32, [>MaxPower 100 mA: this current is used for detecting Vbus<]*/
/*[>************* Descriptor of Joystick Mouse interface ***************<]*/
/*[> 09 <]*/
/*0x09, [>bLength: Interface Descriptor size<]*/
/*USB_DESC_TYPE_INTERFACE,[>bDescriptorType: Interface descriptor type<]*/
/*0x00, [>bInterfaceNumber: Number of Interface<]*/
/*0x00, [>bAlternateSetting: Alternate setting<]*/
/*0x01, [>bNumEndpoints<]*/
/*0x03, [>bInterfaceClass: HID<]*/
/*0x01, [>bInterfaceSubClass : 1=BOOT, 0=no boot<]*/
/*0x02, [>nInterfaceProtocol : 0=none, 1=keyboard, 2=mouse<]*/
/*0, [>iInterface: Index of string descriptor<]*/
/*[>******************* Descriptor of Joystick Mouse HID *******************<]*/
/*[> 18 <]*/
/*0x09, [>bLength: HID Descriptor size<]*/
/*HID_DESCRIPTOR_TYPE, [>bDescriptorType: HID<]*/
/*0x11, [>bcdHID: HID Class Spec release number<]*/
/*0x01,*/
/*0x00, [>bCountryCode: Hardware target country<]*/
/*0x01, [>bNumDescriptors: Number of HID class descriptors to follow<]*/
/*0x22, [>bDescriptorType<]*/
/*HID_MOUSE_REPORT_DESC_SIZE,[>wItemLength: Total length of Report descriptor<]*/
/*0x00,*/
/*[>******************* Descriptor of Mouse endpoint *******************<]*/
/*[> 27 <]*/
/*0x07, [>bLength: Endpoint Descriptor size<]*/
/*USB_DESC_TYPE_ENDPOINT, [>bDescriptorType:<]*/
/*HID_EPIN_ADDR, [>bEndpointAddress: Endpoint Address (IN)<]*/
/*0x03, [>bmAttributes: Interrupt endpoint<]*/
/*HID_EPIN_SIZE, [>wMaxPacketSize: 4 Byte max <]*/
/*0x00,*/
/*HID_HS_BINTERVAL, [>bInterval: Polling Interval <]*/
/*[> 34 <]*/
/*};*/
/* USB HID device Other Speed Configuration Descriptor */
/*__ALIGN_BEGIN static uint8_t USBD_HID_OtherSpeedCfgDesc[USB_HID_CONFIG_DESC_SIZ] __ALIGN_END =*/
/*{*/
/*0x09, [> bLength: Configuration Descriptor size <]*/
/*USB_DESC_TYPE_CONFIGURATION, [> bDescriptorType: Configuration <]*/
/*USB_HID_CONFIG_DESC_SIZ,*/
/*[> wTotalLength: Bytes returned <]*/
/*0x00,*/
/*0x01, [>bNumInterfaces: 1 interface<]*/
/*0x01, [>bConfigurationValue: Configuration value<]*/
/*0x00, //iConfiguration: Index of string descriptor describing*/
/*//the configuration*/
/*0xE0, [>bmAttributes: bus powered and Support Remote Wake-up <]*/
/*0x32, [>MaxPower 100 mA: this current is used for detecting Vbus<]*/
/*[>************* Descriptor of Joystick Mouse interface ***************<]*/
/*[> 09 <]*/
/*0x09, [>bLength: Interface Descriptor size<]*/
/*USB_DESC_TYPE_INTERFACE,[>bDescriptorType: Interface descriptor type<]*/
/*0x00, [>bInterfaceNumber: Number of Interface<]*/
/*0x00, [>bAlternateSetting: Alternate setting<]*/
/*0x01, [>bNumEndpoints<]*/
/*0x03, [>bInterfaceClass: HID<]*/
/*0x01, [>bInterfaceSubClass : 1=BOOT, 0=no boot<]*/
/*0x02, [>nInterfaceProtocol : 0=none, 1=keyboard, 2=mouse<]*/
/*0, [>iInterface: Index of string descriptor<]*/
/*[>******************* Descriptor of Joystick Mouse HID *******************<]*/
/*[> 18 <]*/
/*0x09, [>bLength: HID Descriptor size<]*/
/*HID_DESCRIPTOR_TYPE, [>bDescriptorType: HID<]*/
/*0x11, [>bcdHID: HID Class Spec release number<]*/
/*0x01,*/
/*0x00, [>bCountryCode: Hardware target country<]*/
/*0x01, [>bNumDescriptors: Number of HID class descriptors to follow<]*/
/*0x22, [>bDescriptorType<]*/
/*HID_MOUSE_REPORT_DESC_SIZE,[>wItemLength: Total length of Report descriptor<]*/
/*0x00,*/
/*[>******************* Descriptor of Mouse endpoint *******************<]*/
/*[> 27 <]*/
/*0x07, [>bLength: Endpoint Descriptor size<]*/
/*USB_DESC_TYPE_ENDPOINT, [>bDescriptorType:<]*/
/*HID_EPIN_ADDR, [>bEndpointAddress: Endpoint Address (IN)<]*/
/*0x03, [>bmAttributes: Interrupt endpoint<]*/
/*HID_EPIN_SIZE, [>wMaxPacketSize: 4 Byte max <]*/
/*0x00,*/
/*HID_FS_BINTERVAL, [>bInterval: Polling Interval <]*/
/*[> 34 <]*/
/*};*/
__ALIGN_BEGIN static uint8_t USBD_HID_OtherSpeedCfgDesc[] __ALIGN_END =
{
0x09, // bLength
USB_DESC_TYPE_CONFIGURATION, /* bDescriptorType: Configuration */
0x29,// wTotalLength(LSB)
0x00,// wTotalLength(MSB)
1,// bNumInterfaces
1,// bConfigurationValue
0,// iConfiguration
0xE0, /*bmAttributes: bus powered and Support Remote Wake-up */
0x32, /*MaxPower 100 mA: this current is used for detecting Vbus*/
//Interface 0 Descriptor
0x09, /*bLength: Interface Descriptor size*/
USB_DESC_TYPE_INTERFACE,/*bDescriptorType: Interface descriptor type*/
0,// bInterfaceNumber
0,// bAlternateSetting
2,// bNumEndpoints
3,// bInterfaceClass: HID (Human Interface Device)
0,// bInterfaceSubClass
0,// bInterfaceProtocol
0,// iInterface
//HID Descriptor
0x09, /*bLength: HID Descriptor size*/
HID_DESCRIPTOR_TYPE, /*bDescriptorType: HID*/
0x11,// bcdHID (LSB)
0x01,// bcdHID (MSB)
0,// bCountryCode
1,// bNumDescriptors
0x22, /*bDescriptorType, HID report type*/
( 34 ), // wDescriptorLength(LSB)
( 34 )>>8, // wDescriptorLength(MSB)
//Endpoint 2 IN Descriptor
7,// bLength
USB_DESC_TYPE_ENDPOINT, /*bDescriptorType:*/
HID_EPIN_ADDR,// bEndpointAddress input
0x03,// bAttrib interrupt type
HID_PACKET_SIZE,// wMaxPacketSize (LSB)
0x00,// wMaxPacketSize (MSB)
HID_FS_BINTERVAL,// bInterval
//Endpoint 3 OUT Descriptor
7,// bLength
USB_DESC_TYPE_ENDPOINT, /*bDescriptorType:*/
HID_EPOUT_ADDR,// bEndpointAddress output
0x03,// bAttrib, interrupt type
HID_PACKET_SIZE,// wMaxPacketSize (LSB)
0x00,// wMaxPacketSize (MSB)
HID_FS_BINTERVAL, /*bInterval: Polling Interval */
};
/* USB HID device Configuration Descriptor */
__ALIGN_BEGIN static uint8_t USBD_HID_Desc[USB_HID_DESC_SIZ] __ALIGN_END =
{
/* 18 */
0x09, /*bLength: HID Descriptor size*/
HID_DESCRIPTOR_TYPE, /*bDescriptorType: HID*/
0x11, /*bcdHID: HID Class Spec release number*/
0x01,
0x00, /*bCountryCode: Hardware target country*/
0x01, /*bNumDescriptors: Number of HID class descriptors to follow*/
0x22, /*bDescriptorType*/
HID_MOUSE_REPORT_DESC_SIZE,/*wItemLength: Total length of Report descriptor*/
0x00,
};
/* USB Standard Device Descriptor */
__ALIGN_BEGIN static uint8_t USBD_HID_DeviceQualifierDesc[USB_LEN_DEV_QUALIFIER_DESC] __ALIGN_END =
{
USB_LEN_DEV_QUALIFIER_DESC,
USB_DESC_TYPE_DEVICE_QUALIFIER,
0x00,
0x02,
0x00,
0x00,
0x00,
0x40,
0x01,
0x00,
};
/*__ALIGN_BEGIN static uint8_t HID_MOUSE_ReportDesc[HID_MOUSE_REPORT_DESC_SIZE] __ALIGN_END =*/
/*{*/
/*0x05, 0x01,*/
/*0x09, 0x02,*/
/*0xA1, 0x01,*/
/*0x09, 0x01,*/
/*0xA1, 0x00,*/
/*0x05, 0x09,*/
/*0x19, 0x01,*/
/*0x29, 0x03,*/
/*0x15, 0x00,*/
/*0x25, 0x01,*/
/*0x95, 0x03,*/
/*0x75, 0x01,*/
/*0x81, 0x02,*/
/*0x95, 0x01,*/
/*0x75, 0x05,*/
/*0x81, 0x01,*/
/*0x05, 0x01,*/
/*0x09, 0x30,*/
/*0x09, 0x31,*/
/*0x09, 0x38,*/
/*0x15, 0x81,*/
/*0x25, 0x7F,*/
/*0x75, 0x08,*/
/*0x95, 0x03,*/
/*0x81, 0x06,*/
/*0xC0, 0x09,*/
/*0x3c, 0x05,*/
/*0xff, 0x09,*/
/*0x01, 0x15,*/
/*0x00, 0x25,*/
/*0x01, 0x75,*/
/*0x01, 0x95,*/
/*0x02, 0xb1,*/
/*0x22, 0x75,*/
/*0x06, 0x95,*/
/*0x01, 0xb1,*/
/*0x01, 0xc0*/
/*};*/
/*__ALIGN_BEGIN static uint8_t HID_MOUSE_ReportDesc[HID_MOUSE_REPORT_DESC_SIZE] __ALIGN_END =*/
/*{*/
/*0x06, 0xd0, 0xf1,// USAGE_PAGE (FIDO Alliance)*/
/*0x09, 0x01,// USAGE (Keyboard)*/
/*0xa1, 0x01,// COLLECTION (Application)*/
/*0x09, 0x20, // USAGE (Input Report Data)*/
/*0x15, 0x00, // LOGICAL_MINIMUM (0)*/
/*0x26, 0xff, 0x00, // LOGICAL_MAXIMUM (255)*/
/*0x75, 0x08, // REPORT_SIZE (8)*/
/*0x95, HID_PACKET_SIZE, // REPORT_COUNT (64)*/
/*0x81, 0x02, // INPUT (Data,Var,Abs)*/
/*0x09, 0x21, // USAGE(Output Report Data)*/
/*0x15, 0x00, // LOGICAL_MINIMUM (0)*/
/*0x26, 0xff, 0x00, // LOGICAL_MAXIMUM (255)*/
/*0x75, 0x08, // REPORT_SIZE (8)*/
/*0x95, HID_PACKET_SIZE, // REPORT_COUNT (64)*/
/*0x91, 0x02, // OUTPUT (Data,Var,Abs)*/
/*0xc0,// END_COLLECTION*/
/*};*/
#define _DEBUG() printf("%d\r\n", __LINE__)
/**
* @}
*/
/** @defgroup USBD_HID_Private_Functions
* @{
*/
/**
* @brief USBD_HID_Init
* Initialize the HID interface
* @param pdev: device instance
* @param cfgidx: Configuration index
* @retval status
*/
static uint8_t USBD_HID_Init (USBD_HandleTypeDef *pdev, uint8_t cfgidx)
{
/* Open EP IN */
_DEBUG();
USBD_LL_OpenEP(pdev, HID_EPIN_ADDR, USBD_EP_TYPE_INTR, HID_EPIN_SIZE);
USBD_LL_OpenEP(pdev, HID_EPOUT_ADDR, USBD_EP_TYPE_INTR, HID_EPOUT_SIZE);
pdev->ep_in[HID_EPIN_ADDR & 0xFU].is_used = 1U;
pdev->pClassData = USBD_malloc(sizeof (USBD_HID_HandleTypeDef));
if (pdev->pClassData == NULL)
{
return USBD_FAIL;
}
((USBD_HID_HandleTypeDef *)pdev->pClassData)->state = HID_IDLE;
return USBD_OK;
}
/**
* @brief USBD_HID_Init
* DeInitialize the HID layer
* @param pdev: device instance
* @param cfgidx: Configuration index
* @retval status
*/
static uint8_t USBD_HID_DeInit (USBD_HandleTypeDef *pdev,
uint8_t cfgidx)
{
_DEBUG();
/* Close HID EPs */
USBD_LL_CloseEP(pdev, HID_EPIN_ADDR);
pdev->ep_in[HID_EPIN_ADDR & 0xFU].is_used = 0U;
/* FRee allocated memory */
if(pdev->pClassData != NULL)
{
USBD_free(pdev->pClassData);
pdev->pClassData = NULL;
}
return USBD_OK;
}
/**
* @brief USBD_HID_Setup
* Handle the HID specific requests
* @param pdev: instance
* @param req: usb requests
* @retval status
*/
static uint8_t USBD_HID_Setup (USBD_HandleTypeDef *pdev,
USBD_SetupReqTypedef *req)
{
USBD_HID_HandleTypeDef *hhid = (USBD_HID_HandleTypeDef*) pdev->pClassData;
uint16_t len = 0U;
uint8_t *pbuf = NULL;
uint16_t status_info = 0U;
USBD_StatusTypeDef ret = USBD_OK;
_DEBUG();
switch (req->bmRequest & USB_REQ_TYPE_MASK)
{
case USB_REQ_TYPE_CLASS :
switch (req->bRequest)
{
case HID_REQ_SET_PROTOCOL:
hhid->Protocol = (uint8_t)(req->wValue);
break;
case HID_REQ_GET_PROTOCOL:
USBD_CtlSendData (pdev, (uint8_t *)(void *)&hhid->Protocol, 1U);
break;
case HID_REQ_SET_IDLE:
hhid->IdleState = (uint8_t)(req->wValue >> 8);
break;
case HID_REQ_GET_IDLE:
USBD_CtlSendData (pdev, (uint8_t *)(void *)&hhid->IdleState, 1U);
break;
default:
USBD_CtlError (pdev, req);
ret = USBD_FAIL;
printf("HID setup error %d\r\n", __LINE__);
break;
}
break;
case USB_REQ_TYPE_STANDARD:
switch (req->bRequest)
{
case USB_REQ_GET_STATUS:
if (pdev->dev_state == USBD_STATE_CONFIGURED)
{
USBD_CtlSendData (pdev, (uint8_t *)(void *)&status_info, 2U);
}
else
{
USBD_CtlError (pdev, req);
ret = USBD_FAIL;
}
break;
case USB_REQ_GET_DESCRIPTOR:
if(req->wValue >> 8 == HID_REPORT_DESC)
{
len = MIN(HID_MOUSE_REPORT_DESC_SIZE , req->wLength);
pbuf = HID_MOUSE_ReportDesc;
}
else if(req->wValue >> 8 == HID_DESCRIPTOR_TYPE)
{
pbuf = USBD_HID_Desc;
len = MIN(USB_HID_DESC_SIZ, req->wLength);
}
else
{
USBD_CtlError (pdev, req);
ret = USBD_FAIL;
break;
}
USBD_CtlSendData (pdev, pbuf, len);
break;
case USB_REQ_GET_INTERFACE :
if (pdev->dev_state == USBD_STATE_CONFIGURED)
{
USBD_CtlSendData (pdev, (uint8_t *)(void *)&hhid->AltSetting, 1U);
}
else
{
USBD_CtlError (pdev, req);
ret = USBD_FAIL;
}
break;
case USB_REQ_SET_INTERFACE :
if (pdev->dev_state == USBD_STATE_CONFIGURED)
{
hhid->AltSetting = (uint8_t)(req->wValue);
}
else
{
USBD_CtlError (pdev, req);
ret = USBD_FAIL;
}
break;
default:
USBD_CtlError (pdev, req);
ret = USBD_FAIL;
printf("HID setup error %d\r\n", __LINE__);
break;
}
break;
default:
USBD_CtlError (pdev, req);
ret = USBD_FAIL;
printf("HID setup error %d\r\n", __LINE__);
break;
}
return ret;
}
/**
* @brief USBD_HID_SendReport
* Send HID Report
* @param pdev: device instance
* @param buff: pointer to report
* @retval status
*/
uint8_t USBD_HID_SendReport (USBD_HandleTypeDef *pdev,
uint8_t *report,
uint16_t len)
{
USBD_HID_HandleTypeDef *hhid = (USBD_HID_HandleTypeDef*)pdev->pClassData;
_DEBUG();
if (pdev->dev_state == USBD_STATE_CONFIGURED )
{
if(hhid->state == HID_IDLE)
{
hhid->state = HID_BUSY;
USBD_LL_Transmit (pdev,
HID_EPIN_ADDR,
report,
len);
}
}
return USBD_OK;
}
/**
* @brief USBD_HID_GetPollingInterval
* return polling interval from endpoint descriptor
* @param pdev: device instance
* @retval polling interval
*/
uint32_t USBD_HID_GetPollingInterval (USBD_HandleTypeDef *pdev)
{
uint32_t polling_interval = 0U;
_DEBUG();
/* HIGH-speed endpoints */
if(pdev->dev_speed == USBD_SPEED_HIGH)
{
/* Sets the data transfer polling interval for high speed transfers.
Values between 1..16 are allowed. Values correspond to interval
of 2 ^ (bInterval-1). This option (8 ms, corresponds to HID_HS_BINTERVAL */
polling_interval = (((1U <<(HID_HS_BINTERVAL - 1U))) / 8U);
}
else /* LOW and FULL-speed endpoints */
{
/* Sets the data transfer polling interval for low and full
speed transfers */
polling_interval = HID_FS_BINTERVAL;
}
return ((uint32_t)(polling_interval));
}
/**
* @brief USBD_HID_GetCfgFSDesc
* return FS configuration descriptor
* @param speed : current device speed
* @param length : pointer data length
* @retval pointer to descriptor buffer
*/
static uint8_t *USBD_HID_GetFSCfgDesc (uint16_t *length)
{
_DEBUG();
*length = sizeof (USBD_HID_CfgFSDesc);
return USBD_HID_CfgFSDesc;
}
/**
* @brief USBD_HID_GetCfgHSDesc
* return HS configuration descriptor
* @param speed : current device speed
* @param length : pointer data length
* @retval pointer to descriptor buffer
*/
static uint8_t *USBD_HID_GetHSCfgDesc (uint16_t *length)
{
_DEBUG();
*length = sizeof (USBD_HID_CfgHSDesc);
return USBD_HID_CfgHSDesc;
}
/**
* @brief USBD_HID_GetOtherSpeedCfgDesc
* return other speed configuration descriptor
* @param speed : current device speed
* @param length : pointer data length
* @retval pointer to descriptor buffer
*/
static uint8_t *USBD_HID_GetOtherSpeedCfgDesc (uint16_t *length)
{
_DEBUG();
*length = sizeof (USBD_HID_OtherSpeedCfgDesc);
return USBD_HID_OtherSpeedCfgDesc;
}
/**
* @brief USBD_HID_DataIn
* handle data IN Stage
* @param pdev: device instance
* @param epnum: endpoint index
* @retval status
*/
static uint8_t USBD_HID_DataIn (USBD_HandleTypeDef *pdev,
uint8_t epnum)
{
_DEBUG();
/* Ensure that the FIFO is empty before a new transfer, this condition could
be caused by a new transfer before the end of the previous transfer */
((USBD_HID_HandleTypeDef *)pdev->pClassData)->state = HID_IDLE;
return USBD_OK;
}
static uint8_t USBD_HID_DataOut (USBD_HandleTypeDef *pdev, uint8_t epnum)
{
_DEBUG();
/* Ensure that the FIFO is empty before a new transfer, this condition could
be caused by a new transfer before the end of the previous transfer */
((USBD_HID_HandleTypeDef *)pdev->pClassData)->state = HID_IDLE;
return USBD_OK;
}
/**
* @brief DeviceQualifierDescriptor
* return Device Qualifier descriptor
* @param length : pointer data length
* @retval pointer to descriptor buffer
*/
static uint8_t *USBD_HID_GetDeviceQualifierDesc (uint16_t *length)
{
_DEBUG();
*length = sizeof (USBD_HID_DeviceQualifierDesc);
return USBD_HID_DeviceQualifierDesc;
}
/**
* @}
*/
/**
* @}
*/
/**
* @}
*/
/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/

Wyświetl plik

@ -1,176 +0,0 @@
/**
******************************************************************************
* @file usbd_hid.h
* @author MCD Application Team
* @brief Header file for the usbd_hid_core.c file.
******************************************************************************
* @attention
*
* <h2><center>&copy; Copyright (c) 2017 STMicroelectronics International N.V.
* All rights reserved.</center></h2>
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted, provided that the following conditions are met:
*
* 1. Redistribution of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* 3. Neither the name of STMicroelectronics nor the names of other
* contributors to this software may be used to endorse or promote products
* derived from this software without specific written permission.
* 4. This software, including modifications and/or derivative works of this
* software, must execute solely and exclusively on microcontroller or
* microprocessor devices manufactured by or for STMicroelectronics.
* 5. Redistribution and use of this software other than as permitted under
* this license is void and will automatically terminate your rights under
* this license.
*
* THIS SOFTWARE IS PROVIDED BY STMICROELECTRONICS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS, IMPLIED OR STATUTORY WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
* PARTICULAR PURPOSE AND NON-INFRINGEMENT OF THIRD PARTY INTELLECTUAL PROPERTY
* RIGHTS ARE DISCLAIMED TO THE FULLEST EXTENT PERMITTED BY LAW. IN NO EVENT
* SHALL STMICROELECTRONICS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
******************************************************************************
*/
/* Define to prevent recursive inclusion -------------------------------------*/
#ifndef __USB_HID_H
#define __USB_HID_H
#ifdef __cplusplus
extern "C" {
#endif
/* Includes ------------------------------------------------------------------*/
#include "usbd_ioreq.h"
/** @addtogroup STM32_USB_DEVICE_LIBRARY
* @{
*/
/** @defgroup USBD_HID
* @brief This file is the Header file for usbd_hid.c
* @{
*/
/** @defgroup USBD_HID_Exported_Defines
* @{
*/
#define HID_PACKET_SIZE (64)
#define HID_EPIN_ADDR 0x81U
#define HID_EPIN_SIZE HID_PACKET_SIZE
#define HID_EPOUT_ADDR 0x01U
#define HID_EPOUT_SIZE HID_PACKET_SIZE
//#define USB_HID_CONFIG_DESC_SIZ 34U
#define USB_HID_DESC_SIZ 9U
#define HID_MOUSE_REPORT_DESC_SIZE 34U
#define HID_DESCRIPTOR_TYPE 0x21U
#define HID_REPORT_DESC 0x22U
#ifndef HID_HS_BINTERVAL
#define HID_HS_BINTERVAL 0x07U
#endif /* HID_HS_BINTERVAL */
#ifndef HID_FS_BINTERVAL
#define HID_FS_BINTERVAL 0x0AU
#endif /* HID_FS_BINTERVAL */
#define HID_REQ_SET_PROTOCOL 0x0BU
#define HID_REQ_GET_PROTOCOL 0x03U
#define HID_REQ_SET_IDLE 0x0AU
#define HID_REQ_GET_IDLE 0x02U
#define HID_REQ_SET_REPORT 0x09U
#define HID_REQ_GET_REPORT 0x01U
/**
* @}
*/
/** @defgroup USBD_CORE_Exported_TypesDefinitions
* @{
*/
typedef enum
{
HID_IDLE = 0,
HID_BUSY,
}
HID_StateTypeDef;
typedef struct
{
uint32_t Protocol;
uint32_t IdleState;
uint32_t AltSetting;
HID_StateTypeDef state;
}
USBD_HID_HandleTypeDef;
/**
* @}
*/
/** @defgroup USBD_CORE_Exported_Macros
* @{
*/
/**
* @}
*/
/** @defgroup USBD_CORE_Exported_Variables
* @{
*/
extern USBD_ClassTypeDef USBD_HID;
#define USBD_HID_CLASS &USBD_HID
/**
* @}
*/
/** @defgroup USB_CORE_Exported_Functions
* @{
*/
uint8_t USBD_HID_SendReport (USBD_HandleTypeDef *pdev,
uint8_t *report,
uint16_t len);
uint32_t USBD_HID_GetPollingInterval (USBD_HandleTypeDef *pdev);
/**
* @}
*/
#ifdef __cplusplus
}
#endif
#endif /* __USB_HID_H */
/**
* @}
*/
/**
* @}
*/
/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/

Wyświetl plik

@ -4,9 +4,33 @@
#define DEBUG_UART USART1
#define DEBUG_LEVEL 1
#define NON_BLOCK_PRINTING 0
//#define USING_DEV_BOARD
//#define ENABLE_U2F_EXTENSIONS
#define ENABLE_U2F
//#define DISABLE_CTAPHID_PING
//#define DISABLE_CTAPHID_WINK
//#define DISABLE_CTAPHID_CBOR
void printing_init();
void hw_init(void);
//#define TEST
//#define TEST_POWER
#define LED_INIT_VALUE 0x001000
// Button
#define SOLO_BUTTON_PORT GPIOA
#define SOLO_BUTTON_PIN LL_GPIO_PIN_0
#define SKIP_BUTTON_CHECK_WITH_DELAY 1
#define SKIP_BUTTON_CHECK_FAST 0
#endif

Wyświetl plik

@ -0,0 +1,39 @@
#include <stdint.h>
#include "crypto.h"
// For testing/development only
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"
"\x06\x03\x55\x04\x0a\x0c\x07\x54\x45\x53\x54\x20\x43\x41\x30\x20\x17\x0d\x31\x38"
"\x30\x35\x31\x30\x30\x33\x30\x36\x32\x30\x5a\x18\x0f\x32\x30\x36\x38\x30\x34\x32"
"\x37\x30\x33\x30\x36\x32\x30\x5a\x30\x7c\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\x0f\x30\x0d"
"\x06\x03\x55\x04\x07\x0c\x06\x4c\x61\x75\x72\x65\x6c\x31\x15\x30\x13\x06\x03\x55"
"\x04\x0a\x0c\x0c\x54\x45\x53\x54\x20\x43\x4f\x4d\x50\x41\x4e\x59\x31\x22\x30\x20"
"\x06\x03\x55\x04\x0b\x0c\x19\x41\x75\x74\x68\x65\x6e\x74\x69\x63\x61\x74\x6f\x72"
"\x20\x41\x74\x74\x65\x73\x74\x61\x74\x69\x6f\x6e\x31\x14\x30\x12\x06\x03\x55\x04"
"\x03\x0c\x0b\x63\x6f\x6e\x6f\x72\x70\x70\x2e\x63\x6f\x6d\x30\x59\x30\x13\x06\x07"
"\x2a\x86\x48\xce\x3d\x02\x01\x06\x08\x2a\x86\x48\xce\x3d\x03\x01\x07\x03\x42\x00"
"\x04\x45\xa9\x02\xc1\x2e\x9c\x0a\x33\xfa\x3e\x84\x50\x4a\xb8\x02\xdc\x4d\xb9\xaf"
"\x15\xb1\xb6\x3a\xea\x8d\x3f\x03\x03\x55\x65\x7d\x70\x3f\xb4\x02\xa4\x97\xf4\x83"
"\xb8\xa6\xf9\x3c\xd0\x18\xad\x92\x0c\xb7\x8a\x5a\x3e\x14\x48\x92\xef\x08\xf8\xca"
"\xea\xfb\x32\xab\x20\xa3\x62\x30\x60\x30\x46\x06\x03\x55\x1d\x23\x04\x3f\x30\x3d"
"\xa1\x30\xa4\x2e\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\x06\x03\x55\x04"
"\x0a\x0c\x07\x54\x45\x53\x54\x20\x43\x41\x82\x09\x00\xf7\xc9\xec\x89\xf2\x63\x94"
"\xd9\x30\x09\x06\x03\x55\x1d\x13\x04\x02\x30\x00\x30\x0b\x06\x03\x55\x1d\x0f\x04"
"\x04\x03\x02\x04\xf0\x30\x0a\x06\x08\x2a\x86\x48\xce\x3d\x04\x03\x02\x03\x48\x00"
"\x30\x45\x02\x20\x18\x38\xb0\x45\x03\x69\xaa\xa7\xb7\x38\x62\x01\xaf\x24\x97\x5e"
"\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 uint16_t attestation_cert_der_size = 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";
const uint16_t attestation_key_size = sizeof(attestation_key)-1;

Wyświetl plik

@ -0,0 +1,331 @@
/*
* Wrapper for crypto implementation on device
*
* */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "util.h"
#include "crypto.h"
#ifdef USE_SOFTWARE_IMPLEMENTATION
#include "sha256.h"
#include "uECC.h"
#include "aes.h"
#include "ctap.h"
#include "device.h"
#include "app.h"
#include "log.h"
typedef enum
{
MBEDTLS_ECP_DP_NONE = 0,
MBEDTLS_ECP_DP_SECP192R1, /*!< 192-bits NIST curve */
MBEDTLS_ECP_DP_SECP224R1, /*!< 224-bits NIST curve */
MBEDTLS_ECP_DP_SECP256R1, /*!< 256-bits NIST curve */
MBEDTLS_ECP_DP_SECP384R1, /*!< 384-bits NIST curve */
MBEDTLS_ECP_DP_SECP521R1, /*!< 521-bits NIST curve */
MBEDTLS_ECP_DP_BP256R1, /*!< 256-bits Brainpool curve */
MBEDTLS_ECP_DP_BP384R1, /*!< 384-bits Brainpool curve */
MBEDTLS_ECP_DP_BP512R1, /*!< 512-bits Brainpool curve */
MBEDTLS_ECP_DP_CURVE25519, /*!< Curve25519 */
MBEDTLS_ECP_DP_SECP192K1, /*!< 192-bits "Koblitz" curve */
MBEDTLS_ECP_DP_SECP224K1, /*!< 224-bits "Koblitz" curve */
MBEDTLS_ECP_DP_SECP256K1, /*!< 256-bits "Koblitz" curve */
} mbedtls_ecp_group_id;
static SHA256_CTX sha256_ctx;
static const struct uECC_Curve_t * _es256_curve = NULL;
static const uint8_t * _signing_key = NULL;
static int _key_len = 0;
// Secrets for testing only
static uint8_t master_secret[64];
static uint8_t transport_secret[32];
void crypto_sha256_init()
{
sha256_init(&sha256_ctx);
}
void crypto_load_master_secret(uint8_t * key)
{
#if KEY_SPACE_BYTES < 96
#error "need more key bytes"
#endif
memmove(master_secret, key, 64);
memmove(transport_secret, key+64, 32);
}
void crypto_reset_master_secret()
{
memset(master_secret, 0, 64);
memset(transport_secret, 0, 32);
ctap_generate_rng(master_secret, 64);
ctap_generate_rng(transport_secret, 32);
}
void crypto_sha256_update(uint8_t * data, size_t len)
{
sha256_update(&sha256_ctx, data, len);
}
void crypto_sha256_update_secret()
{
sha256_update(&sha256_ctx, master_secret, 32);
}
void crypto_sha256_final(uint8_t * hash)
{
sha256_final(&sha256_ctx, hash);
}
void crypto_sha256_hmac_init(uint8_t * key, uint32_t klen, uint8_t * hmac)
{
uint8_t buf[64];
int i;
memset(buf, 0, sizeof(buf));
if (key == CRYPTO_MASTER_KEY)
{
key = master_secret;
klen = sizeof(master_secret)/2;
}
else if (key == CRYPTO_TRANSPORT_KEY)
{
key = transport_secret;
klen = 32;
}
if(klen > 64)
{
printf2(TAG_ERR, "Error, key size must be <= 64\n");
exit(1);
}
memmove(buf, key, klen);
for (i = 0; i < sizeof(buf); i++)
{
buf[i] = buf[i] ^ 0x36;
}
crypto_sha256_init();
crypto_sha256_update(buf, 64);
}
void crypto_sha256_hmac_final(uint8_t * key, uint32_t klen, uint8_t * hmac)
{
uint8_t buf[64];
int i;
crypto_sha256_final(hmac);
memset(buf, 0, sizeof(buf));
if (key == CRYPTO_MASTER_KEY)
{
key = master_secret;
klen = sizeof(master_secret)/2;
}
if(klen > 64)
{
printf2(TAG_ERR, "Error, key size must be <= 64\n");
exit(1);
}
memmove(buf, key, klen);
for (i = 0; i < sizeof(buf); i++)
{
buf[i] = buf[i] ^ 0x5c;
}
crypto_sha256_init();
crypto_sha256_update(buf, 64);
crypto_sha256_update(hmac, 32);
crypto_sha256_final(hmac);
}
void crypto_ecc256_init()
{
uECC_set_rng((uECC_RNG_Function)ctap_generate_rng);
_es256_curve = uECC_secp256r1();
}
void crypto_ecc256_load_attestation_key()
{
_signing_key = attestation_key;
_key_len = 32;
}
void crypto_ecc256_sign(uint8_t * data, int len, uint8_t * sig)
{
if ( uECC_sign(_signing_key, data, len, sig, _es256_curve) == 0)
{
printf2(TAG_ERR, "error, uECC failed\n");
exit(1);
}
}
void crypto_ecc256_load_key(uint8_t * data, int len, uint8_t * data2, int len2)
{
static uint8_t privkey[32];
generate_private_key(data,len,data2,len2,privkey);
_signing_key = privkey;
_key_len = 32;
}
void crypto_ecdsa_sign(uint8_t * data, int len, uint8_t * sig, int MBEDTLS_ECP_ID)
{
const struct uECC_Curve_t * curve = NULL;
switch(MBEDTLS_ECP_ID)
{
case MBEDTLS_ECP_DP_SECP192R1:
curve = uECC_secp192r1();
if (_key_len != 24) goto fail;
break;
case MBEDTLS_ECP_DP_SECP224R1:
curve = uECC_secp224r1();
if (_key_len != 28) goto fail;
break;
case MBEDTLS_ECP_DP_SECP256R1:
curve = uECC_secp256r1();
if (_key_len != 32) goto fail;
break;
case MBEDTLS_ECP_DP_SECP256K1:
curve = uECC_secp256k1();
if (_key_len != 32) goto fail;
break;
default:
printf2(TAG_ERR, "error, invalid ECDSA alg specifier\n");
exit(1);
}
if ( uECC_sign(_signing_key, data, len, sig, curve) == 0)
{
printf2(TAG_ERR, "error, uECC failed\n");
exit(1);
}
return;
fail:
printf2(TAG_ERR, "error, invalid key length\n");
exit(1);
}
void generate_private_key(uint8_t * data, int len, uint8_t * data2, int len2, uint8_t * privkey)
{
crypto_sha256_hmac_init(CRYPTO_MASTER_KEY, 0, privkey);
crypto_sha256_update(data, len);
crypto_sha256_update(data2, len2);
crypto_sha256_update(master_secret, 32); // TODO AES
crypto_sha256_hmac_final(CRYPTO_MASTER_KEY, 0, privkey);
crypto_aes256_init(master_secret + 32, NULL);
crypto_aes256_encrypt(privkey, 32);
}
/*int uECC_compute_public_key(const uint8_t *private_key, uint8_t *public_key, uECC_Curve curve);*/
void crypto_ecc256_derive_public_key(uint8_t * data, int len, uint8_t * x, uint8_t * y)
{
uint8_t privkey[32];
uint8_t pubkey[64];
generate_private_key(data,len,NULL,0,privkey);
memset(pubkey,0,sizeof(pubkey));
uECC_compute_public_key(privkey, pubkey, _es256_curve);
memmove(x,pubkey,32);
memmove(y,pubkey+32,32);
}
void crypto_load_external_key(uint8_t * key, int len)
{
_signing_key = key;
_key_len = len;
}
void crypto_ecc256_make_key_pair(uint8_t * pubkey, uint8_t * privkey)
{
if (uECC_make_key(pubkey, privkey, _es256_curve) != 1)
{
printf2(TAG_ERR, "Error, uECC_make_key failed\n");
exit(1);
}
}
void crypto_ecc256_shared_secret(const uint8_t * pubkey, const uint8_t * privkey, uint8_t * shared_secret)
{
if (uECC_shared_secret(pubkey, privkey, shared_secret, _es256_curve) != 1)
{
printf2(TAG_ERR, "Error, uECC_shared_secret failed\n");
exit(1);
}
}
struct AES_ctx aes_ctx;
void crypto_aes256_init(uint8_t * key, uint8_t * nonce)
{
if (key == CRYPTO_TRANSPORT_KEY)
{
AES_init_ctx(&aes_ctx, transport_secret);
}
else
{
AES_init_ctx(&aes_ctx, key);
}
if (nonce == NULL)
{
memset(aes_ctx.Iv, 0, 16);
}
else
{
memmove(aes_ctx.Iv, nonce, 16);
}
}
// prevent round key recomputation
void crypto_aes256_reset_iv(uint8_t * nonce)
{
if (nonce == NULL)
{
memset(aes_ctx.Iv, 0, 16);
}
else
{
memmove(aes_ctx.Iv, nonce, 16);
}
}
void crypto_aes256_decrypt(uint8_t * buf, int length)
{
AES_CBC_decrypt_buffer(&aes_ctx, buf, length);
}
void crypto_aes256_encrypt(uint8_t * buf, int length)
{
AES_CBC_encrypt_buffer(&aes_ctx, buf, length);
}
#else
#error "No crypto implementation defined"
#endif

Wyświetl plik

@ -1,25 +1,415 @@
#include "device.h"
#include "usbd_def.h"
#include "stm32l4xx.h"
#include "stm32l4xx_ll_gpio.h"
#include "stm32l4xx_ll_tim.h"
#include "stm32l4xx_ll_usart.h"
#include "usbd_hid.h"
uint32_t __65_seconds = 0;
#include "app.h"
#include "flash.h"
#include "rng.h"
#include "led.h"
#include "device.h"
#include "util.h"
#include "fifo.h"
#include "log.h"
#include "ctaphid.h"
#define PAGE_SIZE 2048
#define PAGES 128
// Pages 119-127 are data
#define COUNTER2_PAGE (PAGES - 4)
#define COUNTER1_PAGE (PAGES - 3)
#define STATE2_PAGE (PAGES - 2)
#define STATE1_PAGE (PAGES - 1)
#define APPLICATION_START_PAGE (0)
#define APPLICATION_START_ADDR flash_addr(APPLICATION_START_PAGE)
#define APPLICATION_END_PAGE ((PAGES - 9)) // 119 is NOT included in application
#define APPLICATION_END_ADDR (flash_addr(APPLICATION_END_PAGE)-4) // NOT included in application
#define AUTH_WORD_ADDR (flash_addr(APPLICATION_END_PAGE)-4)
uint32_t __90_ms = CTAPHID_STATUS_IDLE;
uint32_t __device_status = 0;
uint32_t __last_update = 0;
extern PCD_HandleTypeDef hpcd;
#define IS_BUTTON_PRESSED() (0 == (LL_GPIO_ReadInputPort(SOLO_BUTTON_PORT) & SOLO_BUTTON_PIN))
// Timer6 overflow handler. happens every ~90ms.
void TIM6_DAC_IRQHandler()
{
// timer is only 16 bits, so roll it over here
TIM6->SR = 0;
__65_seconds += 1;
__90_ms += 1;
if ((millis() - __last_update) > 8)
{
if (__device_status != CTAPHID_STATUS_IDLE)
{
ctaphid_update_status(__device_status);
}
}
}
extern PCD_HandleTypeDef hpcd;
// Global USB interrupt handler
void USB_IRQHandler(void)
{
HAL_PCD_IRQHandler(&hpcd);
}
uint32_t millis()
{
return (((uint32_t)TIM6->CNT) + (__90_ms * 90));
}
void device_set_status(int status)
{
__disable_irq();
__last_update = millis();
__enable_irq();
if (status != CTAPHID_STATUS_IDLE && __device_status != status)
{
ctaphid_update_status(status);
}
__device_status = status;
}
void delay(uint32_t ms)
{
uint32_t time = millis();
while ((millis() - time) < ms)
;
}
void device_init()
{
hw_init();
LL_GPIO_SetPinMode(SOLO_BUTTON_PORT,SOLO_BUTTON_PIN,LL_GPIO_MODE_INPUT);
LL_GPIO_SetPinPull(SOLO_BUTTON_PORT,SOLO_BUTTON_PIN,LL_GPIO_PULL_UP);
flash_option_bytes_init(0);
printf1(TAG_GEN,"hello solo\r\n");
}
void usbhid_init()
{
printf1(TAG_GEN,"hello solo\r\n");
}
int usbhid_recv(uint8_t * msg)
{
if (fifo_hidmsg_size())
{
fifo_hidmsg_take(msg);
printf1(TAG_DUMP,">> ");
dump_hex1(TAG_DUMP,msg, HID_PACKET_SIZE);
return HID_PACKET_SIZE;
}
return 0;
}
void usbhid_send(uint8_t * msg)
{
printf1(TAG_DUMP,"<< ");
dump_hex1(TAG_DUMP, msg, HID_PACKET_SIZE);
while (PCD_GET_EP_TX_STATUS(USB, HID_EPIN_ADDR & 0x0f) == USB_EP_TX_VALID)
;
USBD_LL_Transmit(&Solo_USBD_Device, HID_EPIN_ADDR, msg, HID_PACKET_SIZE);
}
void ctaphid_write_block(uint8_t * data)
{
usbhid_send(data);
}
void usbhid_close()
{
}
void main_loop_delay()
{
}
void heartbeat()
{
static int state = 0;
static uint32_t val = (LED_INIT_VALUE >> 8) & 0xff;
int but = IS_BUTTON_PRESSED();
if (state)
{
val--;
}
else
{
val++;
}
if (val > 30 || val < 1)
{
state = !state;
}
if (but) led_rgb(val * 2);
else
led_rgb((val << 16) | (val*2 << 8));
}
void authenticator_read_state(AuthenticatorState * a)
{
uint32_t * ptr = (uint32_t *)flash_addr(STATE1_PAGE);
memmove(a,ptr,sizeof(AuthenticatorState));
}
void authenticator_read_backup_state(AuthenticatorState * a)
{
uint32_t * ptr = (uint32_t *)flash_addr(STATE2_PAGE);
memmove(a,ptr,sizeof(AuthenticatorState));
}
// Return 1 yes backup is init'd, else 0
int authenticator_is_backup_initialized()
{
uint8_t header[16];
uint32_t * ptr = (uint32_t *)flash_addr(STATE2_PAGE);
memmove(header,ptr,16);
AuthenticatorState * state = (AuthenticatorState*)header;
return state->is_initialized == INITIALIZED_MARKER;
}
void authenticator_write_state(AuthenticatorState * a, int backup)
{
if (! backup)
{
flash_erase_page(STATE1_PAGE);
flash_write(flash_addr(STATE1_PAGE), (uint8_t*)a, sizeof(AuthenticatorState));
}
else
{
flash_erase_page(STATE2_PAGE);
flash_write(flash_addr(STATE2_PAGE), (uint8_t*)a, sizeof(AuthenticatorState));
}
}
uint32_t ctap_atomic_count(int sel)
{
int offset = 0;
uint32_t * ptr = (uint32_t *)flash_addr(COUNTER1_PAGE);
uint32_t erases = *(uint32_t *)flash_addr(COUNTER2_PAGE);
static uint32_t sc = 0;
if (erases == 0xffffffff)
{
erases = 1;
flash_erase_page(COUNTER2_PAGE);
flash_write(flash_addr(COUNTER2_PAGE), (uint8_t*)&erases, 4);
}
uint32_t lastc = 0;
if (sel != 0)
{
printf2(TAG_ERR,"counter2 not imple\n");
exit(1);
}
for (offset = 0; offset < PAGE_SIZE/4; offset += 2) // wear-level the flash
{
if (ptr[offset] != 0xffffffff)
{
if (ptr[offset] < lastc)
{
printf2(TAG_ERR,"Error, count went down!\r\n");
}
lastc = ptr[offset];
}
else
{
break;
}
}
if (!lastc) // Happens on initialization as well.
{
printf2(TAG_ERR,"warning, power interrupted during previous count. Restoring. lastc==%lu, erases=%lu, offset=%d\r\n", lastc,erases,offset);
// there are 32 counts per page
lastc = erases * 256 + 1;
flash_erase_page(COUNTER1_PAGE);
flash_write(flash_addr(COUNTER1_PAGE), (uint8_t*)&lastc, 4);
erases++;
flash_erase_page(COUNTER2_PAGE);
flash_write(flash_addr(COUNTER2_PAGE), (uint8_t*)&erases, 4);
return lastc;
}
lastc++;
if (lastc/256 > erases)
{
printf2(TAG_ERR,"warning, power interrupted, erases mark, restoring. lastc==%lu, erases=%lu\r\n", lastc,erases);
erases = lastc/256;
flash_erase_page(COUNTER2_PAGE);
flash_write(flash_addr(COUNTER2_PAGE), (uint8_t*)&erases, 4);
}
if (offset == PAGE_SIZE/4)
{
if (lastc/256 > erases)
{
printf2(TAG_ERR,"warning, power interrupted, erases mark, restoring lastc==%lu, erases=%lu\r\n", lastc,erases);
}
erases = lastc/256 + 1;
flash_erase_page(COUNTER2_PAGE);
flash_write(flash_addr(COUNTER2_PAGE), (uint8_t*)&erases, 4);
flash_erase_page(COUNTER1_PAGE);
offset = 0;
}
flash_write(flash_addr(COUNTER1_PAGE) + offset * 4, (uint8_t*)&lastc, 4);
if (lastc == sc)
{
printf1(TAG_RED,"no count detected: lastc==%lu, erases=%lu, offset=%d\r\n", lastc,erases,offset);
while(1)
;
}
sc = lastc;
return lastc;
}
void device_manage()
{
#if NON_BLOCK_PRINTING
int i = 10;
uint8_t c;
while (i--)
{
if (fifo_debug_size())
{
fifo_debug_take(&c);
while (! LL_USART_IsActiveFlag_TXE(DEBUG_UART))
;
LL_USART_TransmitData8(DEBUG_UART,c);
}
else
{
break;
}
}
#endif
}
static int handle_packets()
{
static uint8_t hidmsg[HID_PACKET_SIZE];
memset(hidmsg,0, sizeof(hidmsg));
if (usbhid_recv(hidmsg) > 0)
{
if ( ctaphid_handle_packet(hidmsg) == CTAPHID_CANCEL)
{
printf1(TAG_GREEN, "CANCEL!\r\n");
return -1;
}
else
{
return 0;
}
}
return 0;
}
int ctap_user_presence_test()
{
int ret;
#if SKIP_BUTTON_CHECK_WITH_DELAY
int i=500;
while(i--)
{
delay(1);
ret = handle_packets();
if (ret) return ret;
}
goto done;
#elif SKIP_BUTTON_CHECK_FAST
delay(2);
ret = handle_packets();
if (ret) return ret;
goto done;
#endif
uint32_t t1 = millis();
led_rgb(0xff3520);
while (IS_BUTTON_PRESSED())
{
if (t1 + 5000 < millis())
{
printf1(TAG_GEN,"Button not pressed\n");
goto fail;
}
ret = handle_packets();
if (ret) return ret;
}
t1 = millis();
do
{
if (t1 + 5000 < millis())
{
goto fail;
}
delay(1);
ret = handle_packets();
if (ret) return ret;
}
while (! IS_BUTTON_PRESSED());
led_rgb(0x001040);
delay(50);
done:
return 1;
fail:
return 0;
}
int ctap_generate_rng(uint8_t * dst, size_t num)
{
rng_get_bytes(dst, num);
return 1;
}
int ctap_user_verification(uint8_t arg)
{
return 1;
}
void _Error_Handler(char *file, int line)
{
printf2(TAG_ERR,"Error: %s: %d\r\n", file, line);
while(1)
{
}
}

Wyświetl plik

@ -1,12 +0,0 @@
#ifndef _DEVICE_H_
#define _DEVICE_H_
#include <stdint.h>
#include "stm32l4xx_ll_tim.h"
void delay(uint32_t ms);
#define millis() (((uint32_t)TIM6->CNT) | (__65_seconds<<16))
extern uint32_t __65_seconds;
#endif

Wyświetl plik

@ -4,9 +4,9 @@
#include "fifo.h"
FIFO_CREATE(debug,4096,1)
FIFO_CREATE(hidmsg,100,100)
FIFO_CREATE(hidmsg,100,64)
#if TEST_FIFO
FIFO_CREATE(test,10,100)
@ -24,23 +24,25 @@ void fifo_test()
for (int i = 0; i < 10; i++)
{
printf("rhead: %d, whead: %d\r\n", fifo_test_rhead(), fifo_test_whead());
ret = fifo_test_add(data[i]);
printf("%d\r\n",i);
if (ret != 0)
{
printf("fifo_test_add fail\r\n");
goto end;
goto fail;
}
}
for (int i = 0; i < 10; i++)
{
printf("rhead: %d, whead: %d\r\n", fifo_test_rhead(), fifo_test_whead());
ret = fifo_test_take(verif[i]);
printf("%d\r\n",i );
if (ret != 0)
{
printf("fifo_test_take fail\r\n");
goto end;
goto fail;
}
if (memcmp(verif[i], data[i], 100) != 0)
@ -48,17 +50,18 @@ void fifo_test()
printf("fifo_test_take result fail\r\n");
dump_hex(data[i],100);
dump_hex(verif[i],100);
goto end;
goto fail;
}
}
for (int i = 0; i < 10; i++)
{
printf("rhead: %d, whead: %d\r\n", fifo_test_rhead(), fifo_test_whead());
ret = fifo_test_add(data[i]);
if (ret != 0)
{
printf("fifo_test_add 2 fail\r\n");
goto end;
goto fail;
}
}
@ -66,22 +69,25 @@ void fifo_test()
if (ret == 0)
{
printf("fifo_test_add should have failed\r\n");
goto end;
goto fail;
}
for (int i = 0; i < 10; i++)
{
printf("rhead: %d, whead: %d\r\n", fifo_test_rhead(), fifo_test_whead());
ret = fifo_test_take(verif[i]);
if (ret != 0)
{
printf("fifo_test_take fail\r\n");
goto end;
goto fail;
}
if (memcmp(verif[i], data[i], 100) != 0)
{
printf("fifo_test_take result fail\r\n");
goto end;
goto fail;
}
}
@ -89,12 +95,12 @@ void fifo_test()
if (ret == 0)
{
printf("fifo_test_take should have failed\r\n");
goto end;
goto fail;
}
printf("test pass!\r\n");
end:
return ;
fail:
while(1)
;
}

Wyświetl plik

@ -3,7 +3,9 @@
#include "app.h"
#ifndef TEST_FIFO
#define TEST_FIFO 0
#endif
#define FIFO_CREATE(NAME,LENGTH,BYTES)\
int __##NAME##_WRITE_PTR = 0;\
@ -13,7 +15,7 @@ static uint8_t __##NAME##_WRITE_BUF[BYTES * LENGTH];\
\
int fifo_##NAME##_add(uint8_t * c)\
{\
if (__##NAME##_WRITE_PTR != __##NAME##_READ_PTR || !__##NAME##_SIZE)\
if (__##NAME##_SIZE < LENGTH)\
{\
memmove(__##NAME##_WRITE_BUF + __##NAME##_WRITE_PTR * BYTES, c, BYTES);\
__##NAME##_WRITE_PTR ++;\
@ -28,7 +30,7 @@ int fifo_##NAME##_add(uint8_t * c)\
int fifo_##NAME##_take(uint8_t * c)\
{\
memmove(c, __##NAME##_WRITE_BUF + __##NAME##_READ_PTR * BYTES, BYTES);\
if (__##NAME##_READ_PTR != __##NAME##_WRITE_PTR || __##NAME##_SIZE)\
if ( __##NAME##_SIZE > 0)\
{\
__##NAME##_READ_PTR ++;\
if (__##NAME##_READ_PTR >= LENGTH)\
@ -43,15 +45,27 @@ uint32_t fifo_##NAME##_size()\
{\
return (__##NAME##_SIZE);\
}\
uint32_t fifo_##NAME##_rhead()\
{\
return (__##NAME##_READ_PTR);\
}\
uint32_t fifo_##NAME##_whead()\
{\
return (__##NAME##_WRITE_PTR);\
}\
#define FIFO_CREATE_H(NAME,LENGTH,BYTES)\
#define FIFO_CREATE_H(NAME)\
int fifo_##NAME##_add(uint8_t * c);\
int fifo_##NAME##_take(uint8_t * c);\
uint32_t fifo_##NAME##_size();\
uint32_t fifo_##NAME##_rhead();\
uint32_t fifo_##NAME##_whead();\
FIFO_CREATE_H(hidmsg,10,64)
FIFO_CREATE_H(hidmsg)
FIFO_CREATE_H(test,100,100)
FIFO_CREATE_H(debug)
FIFO_CREATE_H(test)
void fifo_test();

Wyświetl plik

@ -5,6 +5,8 @@
#include "app.h"
#include "flash.h"
#include "log.h"
#include "device.h"
static void flash_unlock()
{
@ -14,12 +16,59 @@ static void flash_unlock()
FLASH->KEYR = 0xCDEF89AB;
}
}
// Locks flash and turns off DFU
void flash_option_bytes_init(int boot_from_dfu)
{
#if DEBUG_LEVEL
uint32_t val = 0xfffff8aa;
#else
uint32_t val = 0xfffff8b9;
#endif
if (boot_from_dfu)
{
val &= ~(1<<27); // nBOOT0 = 0 (boot from system rom)
}
val &= ~(1<<26); // nSWBOOT0 = 0 (boot from nBoot0)
val &= ~(1<<25); // SRAM2_RST = 1 (erase sram on reset)
val &= ~(1<<24); // SRAM2_PE = 1 (parity check en)
if (FLASH->OPTR == val)
{
return;
}
__disable_irq();
while (FLASH->SR & (1<<16))
;
flash_unlock();
if (FLASH->CR & (1<<30))
{
FLASH->OPTKEYR = 0x08192A3B;
FLASH->OPTKEYR = 0x4C5D6E7F;
}
FLASH->OPTR =val;
FLASH->CR |= (1<<17);
while (FLASH->SR & (1<<16))
;
flash_lock();
__enable_irq();
}
void flash_erase_page(uint8_t page)
{
__disable_irq();
// Wait if flash is busy
while (FLASH->SR & (1<<16))
;
flash_unlock();
FLASH->SR = FLASH->SR;
// enable flash erase and select page
@ -33,7 +82,7 @@ void flash_erase_page(uint8_t page)
if(FLASH->SR & (1<<1))
{
printf("erase NOT successful %lx\r\n", FLASH->SR);
printf2(TAG_ERR,"erase NOT successful %lx\r\n", FLASH->SR);
}
FLASH->CR &= ~(0x7);
@ -58,7 +107,7 @@ void flash_write_dword(uint32_t addr, uint64_t data)
if(FLASH->SR & (1<<1))
{
printf("program NOT successful %lx\r\n", FLASH->SR);
printf2(TAG_ERR,"program NOT successful %lx\r\n", FLASH->SR);
}
FLASH->SR = (1<<0);
@ -70,9 +119,12 @@ void flash_write(uint32_t addr, uint8_t * data, size_t sz)
{
int i;
uint8_t buf[8];
while (FLASH->SR & (1<<16))
;
flash_unlock();
// dword align
addr &= ~(0x7);
addr &= ~(0x07);
for(i = 0; i < sz; i+=8)
{
@ -89,5 +141,5 @@ void flash_write(uint32_t addr, uint8_t * data, size_t sz)
void flash_lock()
{
FLASH->CR |= (1<<31);
FLASH->CR |= (1U<<31);
}

Wyświetl plik

@ -4,6 +4,7 @@
void flash_erase_page(uint8_t page);
void flash_write_dword(uint32_t addr, uint64_t data);
void flash_write(uint32_t addr, uint8_t * data, size_t sz);
void flash_option_bytes_init(int boot_from_dfu);
#define FLASH_PAGE_SIZE 2048

Wyświetl plik

@ -20,6 +20,7 @@
#include "usbd_core.h"
#include "usbd_desc.h"
#include "usbd_hid.h"
#include "device.h"
/* USER CODE BEGIN Includes */
@ -336,10 +337,10 @@ static void MX_TIM6_Init(void)
LL_APB1_GRP1_EnableClock(LL_APB1_GRP1_PERIPH_TIM6);
// 48 MHz sys clock --> 6 MHz timer clock
// 6 MHz / 6000 == 1000 Hz
// 48 MHz / 48000 == 1000 Hz
TIM_InitStruct.Prescaler = 48000;
TIM_InitStruct.CounterMode = LL_TIM_COUNTERMODE_UP;
TIM_InitStruct.Autoreload = 0xffff;
TIM_InitStruct.Autoreload = 90;
LL_TIM_Init(TIM6, &TIM_InitStruct);
LL_TIM_DisableARRPreload(TIM6);
@ -355,6 +356,35 @@ static void MX_TIM6_Init(void)
LL_TIM_EnableCounter(TIM6);
}
/* TIM7 init function */
// static void MX_TIM7_Init(void)
// {
//
// LL_TIM_InitTypeDef TIM_InitStruct;
//
// /* Peripheral clock enable */
// LL_APB1_GRP1_EnableClock(LL_APB1_GRP1_PERIPH_TIM7);
//
// // 48 MHz sys clock --> 6 MHz timer clock
// // 6 MHz / 6000 == 1000 Hz
// TIM_InitStruct.Prescaler = 48000;
// TIM_InitStruct.CounterMode = LL_TIM_COUNTERMODE_UP;
// TIM_InitStruct.Autoreload = 0xffff;
// LL_TIM_Init(TIM6, &TIM_InitStruct);
//
// LL_TIM_DisableARRPreload(TIM7);
//
// LL_TIM_SetTriggerOutput(TIM7, LL_TIM_TRGO_RESET);
//
// LL_TIM_DisableMasterSlaveMode(TIM7);
//
// // enable interrupt
// TIM7->DIER |= 1;
//
// // Start immediately
// LL_TIM_EnableCounter(TIM7);
// }
/* RNG init function */
static void MX_RNG_Init(void)
{

Wyświetl plik

@ -6,6 +6,7 @@
#include "led.h"
#include "device.h"
#include "log.h"
void led_rgb(uint32_t hex)
{
@ -46,9 +47,9 @@ void led_test_colors()
while(1)
{
printf("%d: %lu\r\n", j++, millis());
printf1(TAG_GREEN, "%d: %lu\r\n", j++, millis());
printf("white pulse\r\n");
printf1(TAG_GREEN,"white pulse\r\n");
time = millis();
while((millis() - time) < 5000)
{
@ -56,7 +57,7 @@ void led_test_colors()
led_rgb(i | (i << 8) | (i << 16));
}
printf("blue pulse\r\n");
printf1(TAG_GREEN,"blue pulse\r\n");
time = millis();
while((millis() - time) < 5000)
{
@ -64,7 +65,7 @@ void led_test_colors()
led_rgb(i);
}
printf("green pulse\r\n");
printf1(TAG_GREEN,"green pulse\r\n");
time = millis();
while((millis() - time) < 5000)
{
@ -72,7 +73,7 @@ void led_test_colors()
led_rgb(i<<8);
}
printf("red pulse\r\n");
printf1(TAG_GREEN,"red pulse\r\n");
time = millis();
while((millis() - time) < 5000)
{
@ -80,7 +81,7 @@ void led_test_colors()
led_rgb(i<<16);
}
printf("purple pulse\r\n");
printf1(TAG_GREEN,"purple pulse\r\n");
time = millis();
while((millis() - time) < 5000)
{
@ -88,7 +89,7 @@ void led_test_colors()
led_rgb((i<<16) | i);
}
printf("orange pulse\r\n");
printf1(TAG_GREEN,"orange pulse\r\n");
time = millis();
while((millis() - time) < 5000)
{
@ -96,7 +97,7 @@ void led_test_colors()
led_rgb((i<<16) | (i<<8));
}
printf("yellow pulse\r\n");
printf1(TAG_GREEN,"yellow pulse\r\n");
time = millis();
while((millis() - time) < 5000)
{
@ -105,5 +106,3 @@ void led_test_colors()
}
}
}

Wyświetl plik

@ -27,8 +27,126 @@
#include "device.h"
#include "util.h"
#include "fifo.h"
#include "log.h"
#ifdef TEST_SOLO_STM32
#define Error_Handler() _Error_Handler(__FILE__,__LINE__)
#define PAGE_SIZE 2048
#define PAGES 128
// Pages 119-127 are data
#define COUNTER2_PAGE (PAGES - 4)
#define COUNTER1_PAGE (PAGES - 3)
#define STATE2_PAGE (PAGES - 2)
#define STATE1_PAGE (PAGES - 1)
void test_atomic_counter()
{
// flash_erase_page(COUNTER1_PAGE);
// flash_erase_page(COUNTER2_PAGE);
int i;
uint32_t c0 = ctap_atomic_count(0);
for (i = 0; i < 128; i++)
{
uint32_t c1 = ctap_atomic_count(0);
if (c1 <= (c0 ))
{
printf("error, count failed %lu <= %lu\r\n",c1,c0);
while(1)
;
}
printf("%lu\r\n", c1);
c0 = c1;
}
printf("test faults\r\n");
printf("%lu\r\n", ctap_atomic_count(0));
printf("%lu\r\n", ctap_atomic_count(0));
printf("%lu\r\n", ctap_atomic_count(0));
printf("%lu\r\n", ctap_atomic_count(0));
printf("%lu\r\n", ctap_atomic_count(0));
flash_erase_page(COUNTER1_PAGE);
printf("%lu\r\n", ctap_atomic_count(0));
printf("%lu\r\n", ctap_atomic_count(0));
printf("%lu\r\n", ctap_atomic_count(0));
printf("%lu\r\n", ctap_atomic_count(0));
printf("%lu\r\n", ctap_atomic_count(0));
flash_erase_page(COUNTER1_PAGE);
printf("%lu\r\n", ctap_atomic_count(0));
printf("%lu\r\n", ctap_atomic_count(0));
printf("%lu\r\n", ctap_atomic_count(0));
printf("%lu\r\n", ctap_atomic_count(0));
printf("%lu\r\n", ctap_atomic_count(0));
flash_erase_page(COUNTER1_PAGE);
printf("%lu\r\n", ctap_atomic_count(0));
printf("%lu\r\n", ctap_atomic_count(0));
printf("%lu\r\n", ctap_atomic_count(0));
printf("%lu\r\n", ctap_atomic_count(0));
printf("%lu\r\n", ctap_atomic_count(0));
flash_erase_page(COUNTER1_PAGE);
printf("%lu\r\n", ctap_atomic_count(0));
printf("%lu\r\n", ctap_atomic_count(0));
printf("%lu\r\n", ctap_atomic_count(0));
printf("%lu\r\n", ctap_atomic_count(0));
printf("%lu\r\n", ctap_atomic_count(0));
flash_erase_page(COUNTER2_PAGE);
printf("%lu\r\n", ctap_atomic_count(0));
printf("%lu\r\n", ctap_atomic_count(0));
printf("%lu\r\n", ctap_atomic_count(0));
printf("%lu\r\n", ctap_atomic_count(0));
printf("%lu\r\n", ctap_atomic_count(0));
flash_erase_page(COUNTER2_PAGE);
printf("%lu\r\n", ctap_atomic_count(0));
printf("%lu\r\n", ctap_atomic_count(0));
printf("%lu\r\n", ctap_atomic_count(0));
printf("%lu\r\n", ctap_atomic_count(0));
printf("%lu\r\n", ctap_atomic_count(0));
flash_erase_page(COUNTER2_PAGE);
printf("%lu\r\n", ctap_atomic_count(0));
printf("%lu\r\n", ctap_atomic_count(0));
printf("%lu\r\n", ctap_atomic_count(0));
printf("%lu\r\n", ctap_atomic_count(0));
printf("%lu\r\n", ctap_atomic_count(0));
flash_erase_page(COUNTER2_PAGE);
printf("%lu\r\n", ctap_atomic_count(0));
printf("%lu\r\n", ctap_atomic_count(0));
printf("%lu\r\n", ctap_atomic_count(0));
printf("%lu\r\n", ctap_atomic_count(0));
printf("%lu\r\n", ctap_atomic_count(0));
flash_erase_page(COUNTER1_PAGE);
printf("%lu\r\n", ctap_atomic_count(0));
printf("%lu\r\n", ctap_atomic_count(0));
printf("%lu\r\n", ctap_atomic_count(0));
printf("%lu\r\n", ctap_atomic_count(0));
printf("%lu\r\n", ctap_atomic_count(0));
flash_erase_page(COUNTER1_PAGE);
printf("%lu\r\n", ctap_atomic_count(0));
printf("%lu\r\n", ctap_atomic_count(0));
printf("%lu\r\n", ctap_atomic_count(0));
printf("%lu\r\n", ctap_atomic_count(0));
printf("%lu\r\n", ctap_atomic_count(0));
flash_erase_page(COUNTER1_PAGE);
}
int main(void)
{
@ -40,7 +158,24 @@ int main(void)
uint8_t hidbuf[HID_PACKET_SIZE];
hw_init();
set_logging_mask(
/*0*/
// TAG_GEN|
TAG_MC |
TAG_GA |
// TAG_WALLET |
TAG_STOR |
TAG_CP |
TAG_CTAP|
// TAG_HID|
/*TAG_U2F|*/
TAG_PARSE |
//TAG_TIME|
// TAG_DUMP|
TAG_GREEN|
TAG_RED|
TAG_ERR
);
printf("hello solo\r\n");
// Test flash
@ -49,6 +184,24 @@ int main(void)
memmove(buf,(uint8_t*)flash_addr(60),sizeof(str));
printf("flash: \"%s\"\r\n", buf);
// test_atomic_counter();
// Note that 4 byte aligned addresses won't get written correctly.
flash_erase_page(60);
uint32_t count = 0;
flash_write(flash_addr(60) + 0,(uint8_t*)&count,4);
count += 1;
flash_write(flash_addr(60) + 4,(uint8_t*)&count,4);
count += 1;
flash_write(flash_addr(60) + 8,(uint8_t*)&count,4);
count += 1;
flash_write(flash_addr(60) + 12,(uint8_t*)&count,4);
count += 1;
flash_write(flash_addr(60) + 16,(uint8_t*)&count,4);
dump_hex((uint8_t *)flash_addr(60), 20);
// test timer
uint32_t t1 = millis();
delay(100);
@ -62,7 +215,7 @@ int main(void)
/*// Test PWM + weighting of RGB*/
/*led_test_colors();*/
fifo_test();
uint32_t t0 = millis();
@ -90,14 +243,9 @@ int main(void)
fifo_hidmsg_take(hidbuf);
dump_hex(hidbuf, HID_PACKET_SIZE);
}
while(1)
;
}
}
void _Error_Handler(char *file, int line)
{
printf("Error: %s: %d\r\n", file, line);
while(1)
{
}
}
#endif

Wyświetl plik

@ -1,40 +1,23 @@
#include "stm32l4xx_ll_usart.h"
#include "app.h"
#include "fifo.h"
int WRITE_PTR = 0;
int READ_PTR = 0;
#define BUF_SIZE 20000
static uint8_t WRITE_BUF[BUF_SIZE];
#if DEBUG_LEVEL>0
void add2buf(uint8_t c)
{
WRITE_BUF[WRITE_PTR++] = c;
if (WRITE_PTR >= BUF_SIZE)
WRITE_PTR = 0;
}
uint8_t takebuf()
{
uint8_t c;
c = WRITE_BUF[READ_PTR++];
if (READ_PTR >= BUF_SIZE)
READ_PTR = 0;
return c;
}
uint8_t bufavail()
{
return (READ_PTR < WRITE_PTR);
}
void _putchar(char c)
{
// add2buf(c);
#if NON_BLOCK_PRINTING
fifo_debug_add(&c);
#else
while (! LL_USART_IsActiveFlag_TXE(DEBUG_UART))
;
LL_USART_TransmitData8(DEBUG_UART,c);
#endif
}
int _write (int fd, const void *buf, long int len)
{
uint8_t * data = (uint8_t *) buf;
@ -43,4 +26,6 @@ int _write (int fd, const void *buf, long int len)
_putchar(*data++);
}
return 0;
}
#endif

Wyświetl plik

@ -5,6 +5,7 @@
#include "stm32l4xx_ll_rng.h"
#include "rng.h"
#include "log.h"
int __errno = 0;
@ -20,7 +21,7 @@ void rng_get_bytes(uint8_t * dst, size_t sz)
if (RNG->SR & 0x66)
{
printf("Error RNG: %02lx\r\n", RNG->SR);
printf2(TAG_ERR,"Error RNG: %02lx\r\n", RNG->SR);
exit(1);
}
@ -54,7 +55,7 @@ float shannon_entropy(float * p, size_t sz)
return entropy;
}
// Measure shannon entropy of RNG
// Measure shannon entropy of RNG
float rng_test(size_t n)
{
unsigned int i;

Wyświetl plik

@ -41,7 +41,7 @@ _Min_Stack_Size = 0x400; /* required amount of stack */
/* Specify the memory areas */
MEMORY
{
FLASH (rx) : ORIGIN = 0x08000000, LENGTH = 256K
FLASH (rx) : ORIGIN = 0x08000000, LENGTH = 238K /* Leave out 18 Kb for data */
RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 48K
SRAM2 (rw) : ORIGIN = 0x10000000, LENGTH = 16K
}
@ -83,8 +83,8 @@ SECTIONS
. = ALIGN(8);
} >FLASH
.ARM.extab :
{
.ARM.extab :
{
. = ALIGN(8);
*(.ARM.extab* .gnu.linkonce.armextab.*)
. = ALIGN(8);
@ -105,7 +105,7 @@ SECTIONS
PROVIDE_HIDDEN (__preinit_array_end = .);
. = ALIGN(8);
} >FLASH
.init_array :
{
. = ALIGN(8);
@ -129,7 +129,7 @@ SECTIONS
_sidata = LOADADDR(.data);
/* Initialized data sections goes into RAM, load LMA copy after code */
.data :
.data :
{
. = ALIGN(8);
_sdata = .; /* create a global symbol at data start */
@ -142,11 +142,11 @@ SECTIONS
_sisram2 = LOADADDR(.sram2);
/* CCM-RAM section
*
* IMPORTANT NOTE!
/* CCM-RAM section
*
* IMPORTANT NOTE!
* If initialized variables will be placed in this section,
* the startup code needs to be modified to copy the init-values.
* the startup code needs to be modified to copy the init-values.
*/
.sram2 :
{
@ -154,12 +154,12 @@ SECTIONS
_ssram2 = .; /* create a global symbol at sram2 start */
*(.sram2)
*(.sram2*)
. = ALIGN(8);
_esram2 = .; /* create a global symbol at sram2 end */
} >SRAM2 AT> FLASH
/* Uninitialized data section */
. = ALIGN(4);
.bss :
@ -187,7 +187,7 @@ SECTIONS
. = ALIGN(8);
} >RAM
/* Remove information from the standard libraries */
/DISCARD/ :
@ -199,5 +199,3 @@ SECTIONS
.ARM.attributes 0 : { *(.ARM.attributes) }
}

Wyświetl plik

@ -61,6 +61,7 @@ class Tester():
self.origin = 'https://examplo.org'
def find_device(self,):
print (list(CtapHidDevice.list_devices()))
dev = next(CtapHidDevice.list_devices(), None)
if not dev:
raise RuntimeError('No FIDO device found')
@ -118,34 +119,34 @@ class Tester():
def test_long_ping(self):
amt = 1000
while 1 :
pingdata = os.urandom(amt)
pingdata = os.urandom(amt)
try:
t1 = time.time() * 1000
r = self.send_data(CTAPHID.PING, pingdata)
t2 = time.time() * 1000
delt = t2 - t1
#if (delt < 140 ):
#raise RuntimeError('Fob is too fast (%d ms)' % delt)
if (delt > 555 * (amt/1000)):
raise RuntimeError('Fob is too slow (%d ms)' % delt)
if (r != pingdata):
raise ValueError('Ping data not echo\'d')
print('1000 byte ping time: %s ms' % delt)
except CtapError as e:
print('7609 byte Ping failed:', e)
raise RuntimeError('ping failed')
print('PASS: 7609 byte ping')
#sys.flush(sys.sto)
sys.stdout.flush()
def test_hid(self,check_timeouts = False):
if check_timeouts:
print('Test idle')
try:
t1 = time.time() * 1000
r = self.send_data(CTAPHID.PING, pingdata)
t2 = time.time() * 1000
delt = t2 - t1
#if (delt < 140 ):
#raise RuntimeError('Fob is too fast (%d ms)' % delt)
if (delt > 555 * (amt/1000)):
raise RuntimeError('Fob is too slow (%d ms)' % delt)
if (r != pingdata):
raise ValueError('Ping data not echo\'d')
print('1000 byte ping time: %s ms' % delt)
except CtapError as e:
print('7609 byte Ping failed:', e)
raise RuntimeError('ping failed')
print('PASS: 7609 byte ping')
#sys.flush(sys.sto)
sys.stdout.flush()
def test_hid(self,):
#print('Test idle')
#try:
#cmd,resp = self.recv_raw()
#except socket.timeout:
#print('Pass: Idle')
cmd,resp = self.recv_raw()
except socket.timeout:
print('Pass: Idle')
print('Test init')
r = self.send_data(CTAPHID.INIT, '\x11\x11\x11\x11\x11\x11\x11\x11')
@ -216,18 +217,19 @@ class Tester():
self.check_error(resp, CtapError.ERR.INVALID_LENGTH)
print('PASS: invalid length')
#r = self.send_data(CTAPHID.PING, '\x44'*200)
#print('Sending packets that skip a sequence number.')
#self.send_raw('\x81\x04\x90')
#self.send_raw('\x00')
#self.send_raw('\x01')
## skip 2
#self.send_raw('\x03')
#cmd,resp = self.recv_raw()
#self.check_error(resp, CtapError.ERR.INVALID_SEQ)
#cmd,resp = self.recv_raw()
#assert(cmd == 0xbf) # timeout
#print('PASS: invalid sequence')
r = self.send_data(CTAPHID.PING, '\x44'*200)
print('Sending packets that skip a sequence number.')
self.send_raw('\x81\x04\x90')
self.send_raw('\x00')
self.send_raw('\x01')
# skip 2
self.send_raw('\x03')
cmd,resp = self.recv_raw()
self.check_error(resp, CtapError.ERR.INVALID_SEQ)
if check_timeouts:
cmd,resp = self.recv_raw()
assert(cmd == 0xbf) # timeout
print('PASS: invalid sequence')
print('Resync and send ping')
try:
@ -262,13 +264,13 @@ class Tester():
cmd,r = self.recv_raw() # init response
assert(cmd == 0x86)
self.set_cid(oldcid)
#print('wait for timeout')
#cmd,r = self.recv_raw() # timeout response
#assert(cmd == 0xbf)
if check_timeouts:
#print('wait for timeout')
cmd,r = self.recv_raw() # timeout response
assert(cmd == 0xbf)
print('PASS: resync and timeout')
print('Test timeout')
self.send_data(CTAPHID.INIT, '\x11\x22\x33\x44\x55\x66\x77\x88')
t1 = time.time() * 1000
@ -294,14 +296,15 @@ class Tester():
assert(r[0] == CtapError.ERR.INVALID_SEQ)
print('PASS: Test not cont')
print('Check random cont ignored')
#self.send_data(CTAPHID.INIT, '\x11\x22\x33\x44\x55\x66\x77\x88')
#self.send_raw('\x01\x10\x00')
#try:
#cmd,r = self.recv_raw() # timeout response
#except socket.timeout:
#pass
print('PASS: random cont')
if check_timeouts:
print('Check random cont ignored')
self.send_data(CTAPHID.INIT, '\x11\x22\x33\x44\x55\x66\x77\x88')
self.send_raw('\x01\x10\x00')
try:
cmd,r = self.recv_raw() # timeout response
except socket.timeout:
pass
print('PASS: random cont')
print('Check busy')
t1 = time.time() * 1000
@ -336,11 +339,13 @@ class Tester():
self.send_raw('\x81\x00\x63')
self.send_raw('\x00')
cmd,r = self.recv_raw() # busy response
self.set_cid(cid1) # finish 1st channel ping
self.send_raw('\x00')
self.set_cid(cid2)
cmd,r = self.recv_raw() # busy response
assert(cmd == 0xbf)
assert(r[0] == CtapError.ERR.CHANNEL_BUSY)
@ -349,18 +354,19 @@ class Tester():
assert(cmd == 0x81)
assert(len(r) == 0x63)
#cmd,r = self.recv_raw() # timeout
#assert(cmd == 0xbf)
#assert(r[0] == CtapError.ERR.TIMEOUT)
if check_timeouts:
cmd,r = self.recv_raw() # timeout
assert(cmd == 0xbf)
assert(r[0] == CtapError.ERR.TIMEOUT)
print('PASS: busy interleaved')
print('Test idle, wait for timeout')
sys.stdout.flush()
try:
cmd,resp = self.recv_raw()
except socket.timeout:
print('Pass: Idle')
if check_timeouts:
print('Test idle, wait for timeout')
sys.stdout.flush()
try:
cmd,resp = self.recv_raw()
except socket.timeout:
print('Pass: Idle')
print('Test cid 0 is invalid')
self.set_cid('\x00\x00\x00\x00')
@ -381,13 +387,13 @@ class Tester():
def test_u2f(self,):
pass
def test_fido2_simple(self):
def test_fido2_simple(self, pin_token=None):
creds = []
exclude_list = []
rp = {'id': 'examplo.org', 'name': 'ExaRP'}
user = {'id': b'usee_od', 'name': 'AB User'}
challenge = 'Y2hhbGxlbmdl'
PIN = None
PIN = pin_token
fake_id1 = array.array('B',[randint(0,255) for i in range(0,150)]).tostring()
fake_id2 = array.array('B',[randint(0,255) for i in range(0,73)]).tostring()
@ -482,6 +488,7 @@ class Tester():
attest.verify(data.hash)
cred = attest.auth_data.credential_data
creds.append(cred)
print(cred)
print('PASS')
if PIN is not None:
@ -505,15 +512,19 @@ class Tester():
real_excl = [{'id': cred.credential_id, 'type': 'public-key'}]
try:
attest, data = self.client.make_credential(rp, user, challenge, pin = PIN, exclude_list = exclude_list + real_excl)
raise RuntimeError('Exclude list did not return expected error')
except CtapError as e:
assert(e.code == CtapError.ERR.CREDENTIAL_EXCLUDED)
except ClientError as e:
assert(e.cause.code == CtapError.ERR.CREDENTIAL_EXCLUDED)
print('PASS')
print('get assertion')
allow_list = [{'id':creds[0].credential_id, 'type': 'public-key'}]
assertions, client_data = self.client.get_assertion(rp['id'], challenge, allow_list, pin = PIN)
assertions[0].verify(client_data.hash, creds[0].public_key)
print('PASS')
for i, x in enumerate(creds):
print('get assertion %d' % i)
allow_list = [{'id':x.credential_id, 'type': 'public-key'}]
assertions, client_data = self.client.get_assertion(rp['id'], challenge, allow_list, pin = PIN)
assertions[0].verify(client_data.hash, x.public_key)
print('PASS')
if PIN is not None:
print('get assertion with wrong pin code')
@ -525,11 +536,16 @@ class Tester():
assert(e.cause.code == CtapError.ERR.PIN_INVALID)
print('PASS')
print('get multiple assertions')
allow_list = [{'id': x.credential_id, 'type': 'public-key'} for x in creds]
assertions, client_data = self.client.get_assertion(rp['id'], challenge, allow_list, pin = PIN)
for ass,cred in zip(assertions, creds):
i += 1
ass.verify(client_data.hash, cred.public_key)
print('%d verified' % i)
print('PASS')
print('Reset device')
@ -567,6 +583,20 @@ class Tester():
assert(e.code == CtapError.ERR.PIN_INVALID)
print('PASS')
print('MC using wrong pin')
try:
self.test_fido2_simple('abcd3');
except CtapError as e:
assert(e.code == CtapError.ERR.PIN_INVALID)
except ClientError as e:
assert(e.cause.code == CtapError.ERR.PIN_INVALID)
print('PASS')
print('Reboot device and hit enter')
input()
self.find_device()
self.test_fido2_simple(PIN);
print('Re-run make_credential and get_assertion tests with pin code')
test(self, PIN)
@ -577,7 +607,6 @@ class Tester():
print('Warning, reset failed: ', e)
print('PASS')
def test_find_brute_force():
i = 0
while 1:
@ -593,12 +622,9 @@ def test_find_brute_force():
if __name__ == '__main__':
t = Tester()
t.find_device()
#t.test_hid()
#t.test_long_ping()
# t.test_hid()
# t.test_long_ping()
t.test_fido2()
#test_find_brute_force()
# test_find_brute_force()
#t.test_fido2_simple()
t.test_fido2_brute_force()
#t.test_fido2_brute_force()

Wyświetl plik

@ -1,5 +1,6 @@
#!/usr/bin/env python
from __future__ import print_function
import base64
"""
cbytes.py
@ -39,4 +40,6 @@ print()
print('code uint8_t __attest[] = \n%s;' % c_str)
print('const uint16_t __attest_size = sizeof(__attest)-1;')
b = base64.b64encode(buf)
print('b64: ')
print(b)

Wyświetl plik

@ -0,0 +1,22 @@
#!/bin/bash
keyname=interkey.pem
certname=intercert.pem
smallcertname=intercert.der
curve=prime256v1
[[ "$#" != 2 ]] && echo "usage: $0 <signing-key> <root-ca>" && exit 1
# generate EC private key
openssl ecparam -genkey -name "$curve" -out "$keyname" -rand seed.txt
# generate a "signing request"
openssl req -new -key "$keyname" -out "$keyname".csr -subj "/C=US/ST=Maryland/O=Solo Keys/OU=Authenticator Attestation/CN=solokeys.com/emailAddress=hello@solokeys.com"
# sign the request
openssl x509 -req -days 18250 -in "$keyname".csr -extfile v3.ext -CA "$2" -CAkey "$1" -set_serial 01 -out "$certname" -sha256
# convert to smaller size format DER
openssl x509 -in $certname -outform der -out $smallcertname
openssl x509 -in $certname -text -noout

Wyświetl plik

@ -6,12 +6,13 @@ smallcertname=cert.der
curve=prime256v1
# generate EC private key
openssl ecparam -genkey -name "$curve" -out "$keyname"
openssl ecparam -genkey -name "$curve" -out "$keyname" -rand seed.txt
# generate a "signing request"
openssl req -new -key "$keyname" -out "$keyname".csr
openssl req -new -key "$keyname" -out "$keyname".csr -subj "/C=US/ST=Maryland/O=Solo Keys/OU=Root CA/CN=solokeys.com/emailAddress=hello@solokeys.com"
# self sign the request
openssl x509 -req -days 18250 -in "$keyname".csr -signkey "$keyname" -out "$certname"
openssl x509 -trustout -req -days 18250 -in "$keyname".csr -signkey "$keyname" -out "$certname" -sha256
# convert to smaller size format DER
openssl x509 -in $certname -outform der -out $smallcertname
openssl x509 -in $certname -text -noout

Wyświetl plik

@ -0,0 +1,16 @@
import sys
from ecdsa import SigningKey, NIST256p
sk = SigningKey.from_pem(open(sys.argv[1]).read())
print('Private key in various formats:')
print()
print([c for c in sk.to_string()])
print()
print(''.join(['%02x'%c for c in sk.to_string()]))
print()
print('"\\x' + '\\x'.join(['%02x'%c for c in sk.to_string()]) + '"')
print()

Wyświetl plik

@ -0,0 +1,22 @@
# verify that the root CA/keypair and intermediate CA/keypairs are set up correctly.
[[ "$#" != 4 ]] && echo "usage: $0 <inter-key> <inter-cert> <root-key> <root-cert>" && exit 1
ikey=$1
icert=$2
rkey=$3
rcert=$4
echo 'challenge $RANDOM' > chal.txt
# check that they are actual key pairs
openssl dgst -sha256 -sign "$ikey" -out sig.txt chal.txt
openssl dgst -sha256 -verify <(openssl x509 -in "$icert" -pubkey -noout) -signature sig.txt chal.txt
openssl dgst -sha256 -sign "$rkey" -out sig.txt chal.txt
openssl dgst -sha256 -verify <(openssl x509 -in "$rcert" -pubkey -noout) -signature sig.txt chal.txt
# Check they are a chain
openssl verify -verbose -CAfile "$rcert" "$icert"