Code style.

Signed-off-by: Pol Henarejos <pol.henarejos@cttc.es>
This commit is contained in:
Pol Henarejos
2023-09-17 19:11:39 +02:00
parent bafede2ae5
commit 332debea6d
9 changed files with 123 additions and 66 deletions

View File

@@ -129,10 +129,16 @@ int cbor_process(uint8_t last_cmd, const uint8_t *data, size_t len) {
return 1; return 1;
} }
CborError COSE_key_params(int crv, int alg, mbedtls_ecp_group *grp, mbedtls_ecp_point *Q, CborEncoder *mapEncoderParent, CborEncoder *mapEncoder) { CborError COSE_key_params(int crv,
int alg,
mbedtls_ecp_group *grp,
mbedtls_ecp_point *Q,
CborEncoder *mapEncoderParent,
CborEncoder *mapEncoder) {
CborError error = CborNoError; CborError error = CborNoError;
int kty = 1; int kty = 1;
if (crv == FIDO2_CURVE_P256 || crv == FIDO2_CURVE_P384 || crv == FIDO2_CURVE_P521 || crv == FIDO2_CURVE_P256K1) { if (crv == FIDO2_CURVE_P256 || crv == FIDO2_CURVE_P384 || crv == FIDO2_CURVE_P521 ||
crv == FIDO2_CURVE_P256K1) {
kty = 2; kty = 2;
} }
@@ -162,15 +168,17 @@ CborError COSE_key_params(int crv, int alg, mbedtls_ecp_group *grp, mbedtls_ecp_
} }
else { else {
size_t olen = 0; size_t olen = 0;
CBOR_CHECK(mbedtls_ecp_point_write_binary(grp, Q, MBEDTLS_ECP_PF_COMPRESSED, &olen, pkey, sizeof(pkey))); CBOR_CHECK(mbedtls_ecp_point_write_binary(grp, Q, MBEDTLS_ECP_PF_COMPRESSED, &olen, pkey,
sizeof(pkey)));
CBOR_CHECK(cbor_encode_byte_string(mapEncoder, pkey, olen)); CBOR_CHECK(cbor_encode_byte_string(mapEncoder, pkey, olen));
} }
CBOR_CHECK(cbor_encoder_close_container(mapEncoderParent, mapEncoder)); CBOR_CHECK(cbor_encoder_close_container(mapEncoderParent, mapEncoder));
err: err:
return error; return error;
} }
CborError COSE_key(mbedtls_ecp_keypair *key, CborEncoder *mapEncoderParent, CborEncoder *mapEncoder) { CborError COSE_key(mbedtls_ecp_keypair *key, CborEncoder *mapEncoderParent,
CborEncoder *mapEncoder) {
int crv = mbedtls_curve_to_fido(key->grp.id), alg = 0; int crv = mbedtls_curve_to_fido(key->grp.id), alg = 0;
if (key->grp.id == MBEDTLS_ECP_DP_SECP256R1) { if (key->grp.id == MBEDTLS_ECP_DP_SECP256R1) {
alg = FIDO2_ALG_ES256; alg = FIDO2_ALG_ES256;
@@ -189,9 +197,16 @@ CborError COSE_key(mbedtls_ecp_keypair *key, CborEncoder *mapEncoderParent, Cbor
} }
return COSE_key_params(crv, alg, &key->grp, &key->Q, mapEncoderParent, mapEncoder); return COSE_key_params(crv, alg, &key->grp, &key->Q, mapEncoderParent, mapEncoder);
} }
CborError COSE_key_shared(mbedtls_ecdh_context *key, CborEncoder *mapEncoderParent, CborEncoder *mapEncoder) { CborError COSE_key_shared(mbedtls_ecdh_context *key,
CborEncoder *mapEncoderParent,
CborEncoder *mapEncoder) {
int crv = mbedtls_curve_to_fido(key->ctx.mbed_ecdh.grp.id), alg = FIDO2_ALG_ECDH_ES_HKDF_256; int crv = mbedtls_curve_to_fido(key->ctx.mbed_ecdh.grp.id), alg = FIDO2_ALG_ECDH_ES_HKDF_256;
return COSE_key_params(crv, alg, &key->ctx.mbed_ecdh.grp, &key->ctx.mbed_ecdh.Q, mapEncoderParent, mapEncoder); return COSE_key_params(crv,
alg,
&key->ctx.mbed_ecdh.grp,
&key->ctx.mbed_ecdh.Q,
mapEncoderParent,
mapEncoder);
} }
CborError COSE_public_key(int alg, CborEncoder *mapEncoderParent, CborEncoder *mapEncoder) { CborError COSE_public_key(int alg, CborEncoder *mapEncoderParent, CborEncoder *mapEncoder) {
CborError error = CborNoError; CborError error = CborNoError;
@@ -201,10 +216,15 @@ CborError COSE_public_key(int alg, CborEncoder *mapEncoderParent, CborEncoder *m
CBOR_CHECK(cbor_encode_text_stringz(mapEncoder, "type")); CBOR_CHECK(cbor_encode_text_stringz(mapEncoder, "type"));
CBOR_CHECK(cbor_encode_text_stringz(mapEncoder, "public-key")); CBOR_CHECK(cbor_encode_text_stringz(mapEncoder, "public-key"));
CBOR_CHECK(cbor_encoder_close_container(mapEncoderParent, mapEncoder)); CBOR_CHECK(cbor_encoder_close_container(mapEncoderParent, mapEncoder));
err: err:
return error; return error;
} }
CborError COSE_read_key(CborValue *f, int64_t *kty, int64_t *alg, int64_t *crv, CborByteString *kax, CborByteString *kay) { CborError COSE_read_key(CborValue *f,
int64_t *kty,
int64_t *alg,
int64_t *crv,
CborByteString *kax,
CborByteString *kay) {
int64_t kkey = 0; int64_t kkey = 0;
CborError error = CborNoError; CborError error = CborNoError;
CBOR_PARSE_MAP_START(*f, 0) CBOR_PARSE_MAP_START(*f, 0)
@@ -230,6 +250,6 @@ CborError COSE_read_key(CborValue *f, int64_t *kty, int64_t *alg, int64_t *crv,
} }
} }
CBOR_PARSE_MAP_END(*f, 0); CBOR_PARSE_MAP_END(*f, 0);
err: err:
return error; return error;
} }

View File

@@ -336,7 +336,8 @@ int cbor_cred_mgmt(const uint8_t *data, size_t len) {
mbedtls_platform_zeroize(largeBlobKey, sizeof(largeBlobKey)); mbedtls_platform_zeroize(largeBlobKey, sizeof(largeBlobKey));
} }
CBOR_CHECK(cbor_encode_uint(&mapEncoder, 0x0C)); CBOR_CHECK(cbor_encode_uint(&mapEncoder, 0x0C));
CBOR_CHECK(cbor_encode_boolean(&mapEncoder, cred.extensions.thirdPartyPayment == ptrue)); CBOR_CHECK(cbor_encode_boolean(&mapEncoder,
cred.extensions.thirdPartyPayment == ptrue));
} }
else { else {
CBOR_CHECK(cbor_encode_uint(&mapEncoder, 0x0C)); CBOR_CHECK(cbor_encode_uint(&mapEncoder, 0x0C));

View File

@@ -65,7 +65,8 @@ int cbor_make_credential(const uint8_t *data, size_t len) {
CBOR_FIELD_GET_BYTES(clientDataHash, 1); CBOR_FIELD_GET_BYTES(clientDataHash, 1);
} }
else if (val_u == 0x02) { // rp else if (val_u == 0x02) { // rp
CBOR_PARSE_MAP_START(_f1, 2) { CBOR_PARSE_MAP_START(_f1, 2)
{
CBOR_FIELD_GET_KEY_TEXT(2); CBOR_FIELD_GET_KEY_TEXT(2);
CBOR_FIELD_KEY_TEXT_VAL_TEXT(2, "id", rp.id); CBOR_FIELD_KEY_TEXT_VAL_TEXT(2, "id", rp.id);
CBOR_FIELD_KEY_TEXT_VAL_TEXT(2, "name", rp.parent.name); CBOR_FIELD_KEY_TEXT_VAL_TEXT(2, "name", rp.parent.name);
@@ -73,7 +74,8 @@ int cbor_make_credential(const uint8_t *data, size_t len) {
CBOR_PARSE_MAP_END(_f1, 2); CBOR_PARSE_MAP_END(_f1, 2);
} }
else if (val_u == 0x03) { // user else if (val_u == 0x03) { // user
CBOR_PARSE_MAP_START(_f1, 2) { CBOR_PARSE_MAP_START(_f1, 2)
{
CBOR_FIELD_GET_KEY_TEXT(2); CBOR_FIELD_GET_KEY_TEXT(2);
CBOR_FIELD_KEY_TEXT_VAL_BYTES(2, "id", user.id); CBOR_FIELD_KEY_TEXT_VAL_BYTES(2, "id", user.id);
CBOR_FIELD_KEY_TEXT_VAL_TEXT(2, "name", user.parent.name); CBOR_FIELD_KEY_TEXT_VAL_TEXT(2, "name", user.parent.name);
@@ -83,9 +85,11 @@ int cbor_make_credential(const uint8_t *data, size_t len) {
CBOR_PARSE_MAP_END(_f1, 2); CBOR_PARSE_MAP_END(_f1, 2);
} }
else if (val_u == 0x04) { // pubKeyCredParams else if (val_u == 0x04) { // pubKeyCredParams
CBOR_PARSE_ARRAY_START(_f1, 2) { CBOR_PARSE_ARRAY_START(_f1, 2)
{
PublicKeyCredentialParameters *pk = &pubKeyCredParams[pubKeyCredParams_len]; PublicKeyCredentialParameters *pk = &pubKeyCredParams[pubKeyCredParams_len];
CBOR_PARSE_MAP_START(_f2, 3) { CBOR_PARSE_MAP_START(_f2, 3)
{
CBOR_FIELD_GET_KEY_TEXT(3); CBOR_FIELD_GET_KEY_TEXT(3);
CBOR_FIELD_KEY_TEXT_VAL_TEXT(3, "type", pk->type); CBOR_FIELD_KEY_TEXT_VAL_TEXT(3, "type", pk->type);
CBOR_FIELD_KEY_TEXT_VAL_INT(3, "alg", pk->alg); CBOR_FIELD_KEY_TEXT_VAL_INT(3, "alg", pk->alg);
@@ -96,14 +100,17 @@ int cbor_make_credential(const uint8_t *data, size_t len) {
CBOR_PARSE_ARRAY_END(_f1, 2); CBOR_PARSE_ARRAY_END(_f1, 2);
} }
else if (val_u == 0x05) { // excludeList else if (val_u == 0x05) { // excludeList
CBOR_PARSE_ARRAY_START(_f1, 2) { CBOR_PARSE_ARRAY_START(_f1, 2)
{
PublicKeyCredentialDescriptor *pc = &excludeList[excludeList_len]; PublicKeyCredentialDescriptor *pc = &excludeList[excludeList_len];
CBOR_PARSE_MAP_START(_f2, 3) { CBOR_PARSE_MAP_START(_f2, 3)
{
CBOR_FIELD_GET_KEY_TEXT(3); CBOR_FIELD_GET_KEY_TEXT(3);
CBOR_FIELD_KEY_TEXT_VAL_BYTES(3, "id", pc->id); CBOR_FIELD_KEY_TEXT_VAL_BYTES(3, "id", pc->id);
CBOR_FIELD_KEY_TEXT_VAL_TEXT(3, "type", pc->type); CBOR_FIELD_KEY_TEXT_VAL_TEXT(3, "type", pc->type);
if (strcmp(_fd3, "transports") == 0) { if (strcmp(_fd3, "transports") == 0) {
CBOR_PARSE_ARRAY_START(_f3, 4) { CBOR_PARSE_ARRAY_START(_f3, 4)
{
CBOR_FIELD_GET_TEXT(pc->transports[pc->transports_len], 4); CBOR_FIELD_GET_TEXT(pc->transports[pc->transports_len], 4);
pc->transports_len++; pc->transports_len++;
} }
@@ -117,7 +124,8 @@ int cbor_make_credential(const uint8_t *data, size_t len) {
} }
else if (val_u == 0x06) { // extensions else if (val_u == 0x06) { // extensions
extensions.present = true; extensions.present = true;
CBOR_PARSE_MAP_START(_f1, 2) { CBOR_PARSE_MAP_START(_f1, 2)
{
CBOR_FIELD_GET_KEY_TEXT(2); CBOR_FIELD_GET_KEY_TEXT(2);
CBOR_FIELD_KEY_TEXT_VAL_BOOL(2, "hmac-secret", extensions.hmac_secret); CBOR_FIELD_KEY_TEXT_VAL_BOOL(2, "hmac-secret", extensions.hmac_secret);
CBOR_FIELD_KEY_TEXT_VAL_UINT(2, "credProtect", extensions.credProtect); CBOR_FIELD_KEY_TEXT_VAL_UINT(2, "credProtect", extensions.credProtect);
@@ -131,7 +139,8 @@ int cbor_make_credential(const uint8_t *data, size_t len) {
} }
else if (val_u == 0x07) { // options else if (val_u == 0x07) { // options
options.present = true; options.present = true;
CBOR_PARSE_MAP_START(_f1, 2) { CBOR_PARSE_MAP_START(_f1, 2)
{
CBOR_FIELD_GET_KEY_TEXT(2); CBOR_FIELD_GET_KEY_TEXT(2);
CBOR_FIELD_KEY_TEXT_VAL_BOOL(2, "rk", options.rk); CBOR_FIELD_KEY_TEXT_VAL_BOOL(2, "rk", options.rk);
CBOR_FIELD_KEY_TEXT_VAL_BOOL(2, "up", options.up); CBOR_FIELD_KEY_TEXT_VAL_BOOL(2, "up", options.up);
@@ -468,7 +477,8 @@ int cbor_make_credential(const uint8_t *data, size_t len) {
CBOR_CHECK(cbor_encoder_create_map(&mapEncoder, &mapEncoder2, CBOR_CHECK(cbor_encoder_create_map(&mapEncoder, &mapEncoder2,
self_attestation == false || is_nitrokey ? 3 : 2)); self_attestation == false || is_nitrokey ? 3 : 2));
CBOR_CHECK(cbor_encode_text_stringz(&mapEncoder2, "alg")); CBOR_CHECK(cbor_encode_text_stringz(&mapEncoder2, "alg"));
CBOR_CHECK(cbor_encode_negative_int(&mapEncoder2, self_attestation || is_nitrokey ? -alg : -FIDO2_ALG_ES256)); CBOR_CHECK(cbor_encode_negative_int(&mapEncoder2,
self_attestation || is_nitrokey ? -alg : -FIDO2_ALG_ES256));
CBOR_CHECK(cbor_encode_text_stringz(&mapEncoder2, "sig")); CBOR_CHECK(cbor_encode_text_stringz(&mapEncoder2, "sig"));
CBOR_CHECK(cbor_encode_byte_string(&mapEncoder2, sig, olen)); CBOR_CHECK(cbor_encode_byte_string(&mapEncoder2, sig, olen));
if (self_attestation == false || is_nitrokey) { if (self_attestation == false || is_nitrokey) {

View File

@@ -205,7 +205,9 @@ int credential_load(const uint8_t *cred_id,
CBOR_FIELD_KEY_TEXT_VAL_UINT(2, "credProtect", cred->extensions.credProtect); CBOR_FIELD_KEY_TEXT_VAL_UINT(2, "credProtect", cred->extensions.credProtect);
CBOR_FIELD_KEY_TEXT_VAL_BYTES(2, "credBlob", cred->extensions.credBlob); CBOR_FIELD_KEY_TEXT_VAL_BYTES(2, "credBlob", cred->extensions.credBlob);
CBOR_FIELD_KEY_TEXT_VAL_BOOL(2, "largeBlobKey", cred->extensions.largeBlobKey); CBOR_FIELD_KEY_TEXT_VAL_BOOL(2, "largeBlobKey", cred->extensions.largeBlobKey);
CBOR_FIELD_KEY_TEXT_VAL_BOOL(2, "thirdPartyPayment", cred->extensions.thirdPartyPayment); CBOR_FIELD_KEY_TEXT_VAL_BOOL(2,
"thirdPartyPayment",
cred->extensions.thirdPartyPayment);
CBOR_ADVANCE(2); CBOR_ADVANCE(2);
} }
CBOR_PARSE_MAP_END(_f1, 2); CBOR_PARSE_MAP_END(_f1, 2);

View File

@@ -241,8 +241,15 @@ typedef struct CborCharString {
} } while (0) } } while (0)
extern CborError COSE_key(mbedtls_ecp_keypair *, CborEncoder *, CborEncoder *); extern CborError COSE_key(mbedtls_ecp_keypair *, CborEncoder *, CborEncoder *);
extern CborError COSE_key_shared(mbedtls_ecdh_context *key, CborEncoder *mapEncoderParent, CborEncoder *mapEncoder); extern CborError COSE_key_shared(mbedtls_ecdh_context *key,
CborEncoder *mapEncoderParent,
CborEncoder *mapEncoder);
extern CborError COSE_public_key(int alg, CborEncoder *mapEncoderParent, CborEncoder *mapEncoder); extern CborError COSE_public_key(int alg, CborEncoder *mapEncoderParent, CborEncoder *mapEncoder);
extern CborError COSE_read_key(CborValue *f, int64_t *kty, int64_t *alg, int64_t *crv, CborByteString *kax, CborByteString *kay); extern CborError COSE_read_key(CborValue *f,
int64_t *kty,
int64_t *alg,
int64_t *crv,
CborByteString *kax,
CborByteString *kay);
#endif //_CTAP2_CBOR_H_ #endif //_CTAP2_CBOR_H_

View File

@@ -46,7 +46,8 @@ file_t file_entries[] = {
{ .fid = EF_LARGEBLOB, .parent = 0, .name = NULL, { .fid = EF_LARGEBLOB, .parent = 0, .name = NULL,
.type = FILE_TYPE_INTERNAL_EF | FILE_DATA_FLASH, .data = NULL, .type = FILE_TYPE_INTERNAL_EF | FILE_DATA_FLASH, .data = NULL,
.ef_structure = FILE_EF_TRANSPARENT, .acl = { 0xff } }, // Large Blob .ef_structure = FILE_EF_TRANSPARENT, .acl = { 0xff } }, // Large Blob
{ .fid = EF_OTP_PIN, .parent = 0, .name = NULL, .type = FILE_TYPE_INTERNAL_EF | FILE_DATA_FLASH, { .fid = EF_OTP_PIN, .parent = 0, .name = NULL,
.type = FILE_TYPE_INTERNAL_EF | FILE_DATA_FLASH,
.data = NULL, .ef_structure = FILE_EF_TRANSPARENT, .acl = { 0xff } }, .data = NULL, .ef_structure = FILE_EF_TRANSPARENT, .acl = { 0xff } },
{ .fid = 0x0000, .parent = 0xff, .name = NULL, .type = FILE_TYPE_UNKNOWN, .data = NULL, { .fid = 0x0000, .parent = 0xff, .name = NULL, .type = FILE_TYPE_UNKNOWN, .data = NULL,
.ef_structure = 0, .acl = { 0 } } //end .ef_structure = 0, .acl = { 0 } } //end

View File

@@ -36,8 +36,8 @@ app_t *man_select(app_t *a, const uint8_t *aid, uint8_t aid_len) {
a->aid = man_aid; a->aid = man_aid;
a->process_apdu = man_process_apdu; a->process_apdu = man_process_apdu;
a->unload = man_unload; a->unload = man_unload;
sprintf((char *)res_APDU, "%d.%d.0", PICO_FIDO_VERSION_MAJOR, PICO_FIDO_VERSION_MINOR); sprintf((char *) res_APDU, "%d.%d.0", PICO_FIDO_VERSION_MAJOR, PICO_FIDO_VERSION_MINOR);
res_APDU_size = strlen((char *)res_APDU); res_APDU_size = strlen((char *) res_APDU);
apdu.ne = res_APDU_size; apdu.ne = res_APDU_size;
scan_all(); scan_all();
return a; return a;
@@ -65,7 +65,7 @@ bool cap_supported(uint16_t cap) {
if (tag_len == 2) { if (tag_len == 2) {
ecaps = (tag_data[0] << 8) | tag_data[1]; ecaps = (tag_data[0] << 8) | tag_data[1];
} }
return (ecaps & cap); return ecaps & cap;
} }
} }
} }

View File

@@ -585,7 +585,7 @@ int cmd_verify_hotp() {
return SW_DATA_INVALID(); return SW_DATA_INVALID();
} }
if (asn1_find_tag(file_get_data(ef), file_get_size(ef), TAG_IMF, &chal_len, if (asn1_find_tag(file_get_data(ef), file_get_size(ef), TAG_IMF, &chal_len,
&chal) == false) { &chal) == false) {
return SW_INCORRECT_PARAMS(); return SW_INCORRECT_PARAMS();
} }
if (asn1_find_tag(apdu.data, apdu.nc, TAG_RESPONSE, &code_len, &code) == true) { if (asn1_find_tag(apdu.data, apdu.nc, TAG_RESPONSE, &code_len, &code) == true) {
@@ -598,10 +598,10 @@ int cmd_verify_hotp() {
} }
uint32_t res_int = (res_APDU[2] << 24) | (res_APDU[3] << 16) | (res_APDU[4] << 8) | res_APDU[5]; uint32_t res_int = (res_APDU[2] << 24) | (res_APDU[3] << 16) | (res_APDU[4] << 8) | res_APDU[5];
if (res_APDU[1] == 6) { if (res_APDU[1] == 6) {
res_int %= (uint32_t)1e6; res_int %= (uint32_t) 1e6;
} }
else { else {
res_int %= (uint32_t)1e8; res_int %= (uint32_t) 1e8;
} }
if (res_int != code_int) { if (res_int != code_int) {
return SW_WRONG_DATA(); return SW_WRONG_DATA();

View File

@@ -51,7 +51,8 @@
#define ALLOW_UPDATE 0x20 // Allow update of existing configuration (selected flags + access code) #define ALLOW_UPDATE 0x20 // Allow update of existing configuration (selected flags + access code)
#define DORMANT 0x40 // Dormant config (woken up, flag removed, requires update flag) #define DORMANT 0x40 // Dormant config (woken up, flag removed, requires update flag)
#define LED_INV 0x80 // LED idle state is off rather than on #define LED_INV 0x80 // LED idle state is off rather than on
#define EXTFLAG_UPDATE_MASK (SERIAL_BTN_VISIBLE | SERIAL_USB_VISIBLE | SERIAL_API_VISIBLE | USE_NUMERIC_KEYPAD | FAST_TRIG | ALLOW_UPDATE | DORMANT | LED_INV) #define EXTFLAG_UPDATE_MASK (SERIAL_BTN_VISIBLE | SERIAL_USB_VISIBLE | SERIAL_API_VISIBLE | \
USE_NUMERIC_KEYPAD | FAST_TRIG | ALLOW_UPDATE | DORMANT | LED_INV)
/* TKT Flags */ /* TKT Flags */
#define TAB_FIRST 0x01 // Send TAB before first part #define TAB_FIRST 0x01 // Send TAB before first part
@@ -63,7 +64,8 @@
#define OATH_HOTP 0x40 // OATH HOTP mode #define OATH_HOTP 0x40 // OATH HOTP mode
#define CHAL_RESP 0x40 // Challenge-response enabled (both must be set) #define CHAL_RESP 0x40 // Challenge-response enabled (both must be set)
#define PROTECT_CFG2 0x80 // Block update of config 2 unless config 2 is configured and has this bit set #define PROTECT_CFG2 0x80 // Block update of config 2 unless config 2 is configured and has this bit set
#define TKTFLAG_UPDATE_MASK (TAB_FIRST | APPEND_TAB1 | APPEND_TAB2 | APPEND_DELAY1 | APPEND_DELAY2 | APPEND_CR) #define TKTFLAG_UPDATE_MASK (TAB_FIRST | APPEND_TAB1 | APPEND_TAB2 | APPEND_DELAY1 | APPEND_DELAY2 | \
APPEND_CR)
/* CFG Flags */ /* CFG Flags */
#define SEND_REF 0x01 // Send reference string (0..F) before data #define SEND_REF 0x01 // Send reference string (0..F) before data
@@ -135,7 +137,8 @@ app_t *otp_select(app_t *a, const uint8_t *aid, uint8_t aid_len) {
return NULL; return NULL;
} }
uint8_t modhex_tab[] = {'c', 'b', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'n', 'r', 't', 'u', 'v'}; uint8_t modhex_tab[] =
{ 'c', 'b', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'n', 'r', 't', 'u', 'v' };
int encode_modhex(const uint8_t *in, size_t len, uint8_t *out) { int encode_modhex(const uint8_t *in, size_t len, uint8_t *out) {
for (int l = 0; l < len; l++) { for (int l = 0; l < len; l++) {
*out++ = modhex_tab[in[l] >> 4]; *out++ = modhex_tab[in[l] >> 4];
@@ -151,8 +154,9 @@ void init_otp() {
for (int i = 0; i < 2; i++) { for (int i = 0; i < 2; i++) {
file_t *ef = search_dynamic_file(EF_OTP_SLOT1 + i); file_t *ef = search_dynamic_file(EF_OTP_SLOT1 + i);
uint8_t *data = file_get_data(ef); uint8_t *data = file_get_data(ef);
otp_config_t *otp_config = (otp_config_t *)data; otp_config_t *otp_config = (otp_config_t *) data;
if (file_has_data(ef) && !(otp_config->tkt_flags & OATH_HOTP) && !(otp_config->cfg_flags & SHORT_TICKET || otp_config->cfg_flags & STATIC_TICKET)) { if (file_has_data(ef) && !(otp_config->tkt_flags & OATH_HOTP) &&
!(otp_config->cfg_flags & SHORT_TICKET || otp_config->cfg_flags & STATIC_TICKET)) {
uint16_t counter = (data[otp_config_size] << 8) | data[otp_config_size + 1]; uint16_t counter = (data[otp_config_size] << 8) | data[otp_config_size + 1];
if (++counter <= 0x7fff) { if (++counter <= 0x7fff) {
uint8_t new_data[otp_config_size + 8]; uint8_t new_data[otp_config_size + 8];
@@ -173,7 +177,7 @@ extern int calculate_oath(uint8_t truncate,
const uint8_t *chal, const uint8_t *chal,
size_t chal_len); size_t chal_len);
#ifndef ENABLE_EMULATION #ifndef ENABLE_EMULATION
static uint8_t session_counter[2] = {0}; static uint8_t session_counter[2] = { 0 };
#endif #endif
int otp_button_pressed(uint8_t slot) { int otp_button_pressed(uint8_t slot) {
init_otp(); init_otp();
@@ -183,7 +187,7 @@ int otp_button_pressed(uint8_t slot) {
#ifndef ENABLE_EMULATION #ifndef ENABLE_EMULATION
file_t *ef = search_dynamic_file(slot == 1 ? EF_OTP_SLOT1 : EF_OTP_SLOT2); file_t *ef = search_dynamic_file(slot == 1 ? EF_OTP_SLOT1 : EF_OTP_SLOT2);
const uint8_t *data = file_get_data(ef); const uint8_t *data = file_get_data(ef);
otp_config_t *otp_config = (otp_config_t *)data; otp_config_t *otp_config = (otp_config_t *) data;
if (file_has_data(ef) == false) { if (file_has_data(ef) == false) {
return 1; return 1;
} }
@@ -196,10 +200,10 @@ int otp_button_pressed(uint8_t slot) {
memcpy(tmp_key + 2, otp_config->aes_key, KEY_SIZE); memcpy(tmp_key + 2, otp_config->aes_key, KEY_SIZE);
uint64_t imf = 0; uint64_t imf = 0;
const uint8_t *p = data + otp_config_size; const uint8_t *p = data + otp_config_size;
imf |= (uint64_t)*p++ << 56; imf |= (uint64_t) *p++ << 56;
imf |= (uint64_t)*p++ << 48; imf |= (uint64_t) *p++ << 48;
imf |= (uint64_t)*p++ << 40; imf |= (uint64_t) *p++ << 40;
imf |= (uint64_t)*p++ << 32; imf |= (uint64_t) *p++ << 32;
imf |= *p++ << 24; imf |= *p++ << 24;
imf |= *p++ << 16; imf |= *p++ << 16;
imf |= *p++ << 8; imf |= *p++ << 8;
@@ -207,24 +211,28 @@ int otp_button_pressed(uint8_t slot) {
if (imf == 0) { if (imf == 0) {
imf = ((otp_config->uid[4] << 8) | otp_config->uid[5]) << 4; imf = ((otp_config->uid[4] << 8) | otp_config->uid[5]) << 4;
} }
uint8_t chal[8] = {imf >> 56, imf >> 48, imf >> 40, imf >> 32, imf >> 24, imf >> 16, imf >> 8, imf & 0xff}; uint8_t chal[8] =
{ imf >> 56, imf >> 48, imf >> 40, imf >> 32, imf >> 24, imf >> 16, imf >> 8, imf & 0xff };
res_APDU_size = 0; res_APDU_size = 0;
int ret = calculate_oath(1, tmp_key, sizeof(tmp_key), chal, sizeof(chal)); int ret = calculate_oath(1, tmp_key, sizeof(tmp_key), chal, sizeof(chal));
if (ret == CCID_OK) { if (ret == CCID_OK) {
uint32_t base = otp_config->cfg_flags & OATH_HOTP8 ? 1e8 : 1e6; uint32_t base = otp_config->cfg_flags & OATH_HOTP8 ? 1e8 : 1e6;
uint32_t number = (res_APDU[2] << 24) | (res_APDU[3] << 16) | (res_APDU[4] << 8) | res_APDU[5]; uint32_t number =
(res_APDU[2] << 24) | (res_APDU[3] << 16) | (res_APDU[4] << 8) | res_APDU[5];
number %= base; number %= base;
char number_str[9]; char number_str[9];
if (otp_config->cfg_flags & OATH_HOTP8) { if (otp_config->cfg_flags & OATH_HOTP8) {
sprintf(number_str, "%08lu", (long unsigned int)number); sprintf(number_str, "%08lu", (long unsigned int) number);
add_keyboard_buffer((const uint8_t *)number_str, 8, true); add_keyboard_buffer((const uint8_t *) number_str, 8, true);
} }
else { else {
sprintf(number_str, "%06lu", (long unsigned int)number); sprintf(number_str, "%06lu", (long unsigned int) number);
add_keyboard_buffer((const uint8_t *)number_str, 6, true); add_keyboard_buffer((const uint8_t *) number_str, 6, true);
} }
imf++; imf++;
uint8_t new_chal[8] = {imf >> 56, imf >> 48, imf >> 40, imf >> 32, imf >> 24, imf >> 16, imf >> 8, imf & 0xff}; uint8_t new_chal[8] =
{ imf >> 56, imf >> 48, imf >> 40, imf >> 32, imf >> 24, imf >> 16, imf >> 8,
imf & 0xff };
uint8_t new_otp_config[otp_config_size + sizeof(new_chal)]; uint8_t new_otp_config[otp_config_size + sizeof(new_chal)];
memcpy(new_otp_config, otp_config, otp_config_size); memcpy(new_otp_config, otp_config, otp_config_size);
memcpy(new_otp_config + otp_config_size, new_chal, sizeof(new_chal)); memcpy(new_otp_config + otp_config_size, new_chal, sizeof(new_chal));
@@ -232,7 +240,7 @@ int otp_button_pressed(uint8_t slot) {
low_flash_available(); low_flash_available();
} }
if (otp_config->tkt_flags & APPEND_CR) { if (otp_config->tkt_flags & APPEND_CR) {
append_keyboard_buffer((const uint8_t *)"\r", 1); append_keyboard_buffer((const uint8_t *) "\r", 1);
} }
} }
else if (otp_config->cfg_flags & SHORT_TICKET || otp_config->cfg_flags & STATIC_TICKET) { else if (otp_config->cfg_flags & SHORT_TICKET || otp_config->cfg_flags & STATIC_TICKET) {
@@ -241,7 +249,7 @@ int otp_button_pressed(uint8_t slot) {
} }
add_keyboard_buffer(otp_config->fixed_data, otp_config->fixed_size, false); add_keyboard_buffer(otp_config->fixed_data, otp_config->fixed_size, false);
if (otp_config->tkt_flags & APPEND_CR) { if (otp_config->tkt_flags & APPEND_CR) {
append_keyboard_buffer((const uint8_t *)"\x28", 1); append_keyboard_buffer((const uint8_t *) "\x28", 1);
} }
} }
else { else {
@@ -276,9 +284,9 @@ int otp_button_pressed(uint8_t slot) {
mbedtls_aes_free(&ctx); mbedtls_aes_free(&ctx);
uint8_t otp_out[44]; uint8_t otp_out[44];
encode_modhex(otpk, sizeof(otpk), otp_out); encode_modhex(otpk, sizeof(otpk), otp_out);
add_keyboard_buffer((const uint8_t *)otp_out, sizeof(otp_out), true); add_keyboard_buffer((const uint8_t *) otp_out, sizeof(otp_out), true);
if (otp_config->tkt_flags & APPEND_CR) { if (otp_config->tkt_flags & APPEND_CR) {
append_keyboard_buffer((const uint8_t *)"\r", 1); append_keyboard_buffer((const uint8_t *) "\r", 1);
} }
if (++session_counter[slot - 1] == 0) { if (++session_counter[slot - 1] == 0) {
@@ -319,16 +327,16 @@ uint16_t otp_status() {
res_APDU[3] = 0; res_APDU[3] = 0;
res_APDU[4] = config_seq; res_APDU[4] = config_seq;
res_APDU[5] = (CONFIG2_TOUCH | CONFIG1_TOUCH) | res_APDU[5] = (CONFIG2_TOUCH | CONFIG1_TOUCH) |
(file_has_data(search_dynamic_file(EF_OTP_SLOT1)) ? CONFIG1_VALID : (file_has_data(search_dynamic_file(EF_OTP_SLOT1)) ? CONFIG1_VALID :
0x00) | 0x00) |
(file_has_data(search_dynamic_file(EF_OTP_SLOT2)) ? CONFIG2_VALID : (file_has_data(search_dynamic_file(EF_OTP_SLOT2)) ? CONFIG2_VALID :
0x00); 0x00);
res_APDU[6] = 0; res_APDU[6] = 0;
return SW_OK(); return SW_OK();
} }
bool check_crc(const otp_config_t *data) { bool check_crc(const otp_config_t *data) {
uint16_t crc = calculate_crc((const uint8_t *)data, otp_config_size); uint16_t crc = calculate_crc((const uint8_t *) data, otp_config_size);
return crc == 0xF0B8; return crc == 0xF0B8;
} }
@@ -338,7 +346,7 @@ int cmd_otp() {
return SW_INCORRECT_P1P2(); return SW_INCORRECT_P1P2();
} }
if (p1 == 0x01 || p1 == 0x03) { // Configure slot if (p1 == 0x01 || p1 == 0x03) { // Configure slot
otp_config_t *odata = (otp_config_t *)apdu.data; otp_config_t *odata = (otp_config_t *) apdu.data;
file_t *ef = file_new(p1 == 0x01 ? EF_OTP_SLOT1 : EF_OTP_SLOT2); file_t *ef = file_new(p1 == 0x01 ? EF_OTP_SLOT1 : EF_OTP_SLOT2);
if (file_has_data(ef)) { if (file_has_data(ef)) {
otp_config_t *otpc = (otp_config_t *) file_get_data(ef); otp_config_t *otpc = (otp_config_t *) file_get_data(ef);
@@ -367,7 +375,7 @@ int cmd_otp() {
return otp_status(); return otp_status();
} }
else if (p1 == 0x04 || p1 == 0x05) { else if (p1 == 0x04 || p1 == 0x05) {
otp_config_t *odata = (otp_config_t *)apdu.data; otp_config_t *odata = (otp_config_t *) apdu.data;
if (odata->rfu[0] != 0 || odata->rfu[1] != 0 || check_crc(odata) == false) { if (odata->rfu[0] != 0 || odata->rfu[1] != 0 || check_crc(odata) == false) {
return SW_WRONG_DATA(); return SW_WRONG_DATA();
} }
@@ -379,9 +387,12 @@ int cmd_otp() {
} }
memcpy(apdu.data, file_get_data(ef), FIXED_SIZE + UID_SIZE + KEY_SIZE); memcpy(apdu.data, file_get_data(ef), FIXED_SIZE + UID_SIZE + KEY_SIZE);
odata->fixed_size = otpc->fixed_size; odata->fixed_size = otpc->fixed_size;
odata->ext_flags = (otpc->ext_flags & ~EXTFLAG_UPDATE_MASK) | (odata->ext_flags & EXTFLAG_UPDATE_MASK); odata->ext_flags = (otpc->ext_flags & ~EXTFLAG_UPDATE_MASK) |
odata->tkt_flags = (otpc->tkt_flags & ~TKTFLAG_UPDATE_MASK) | (odata->tkt_flags & TKTFLAG_UPDATE_MASK); (odata->ext_flags & EXTFLAG_UPDATE_MASK);
odata->cfg_flags = (otpc->cfg_flags & ~CFGFLAG_UPDATE_MASK) | (odata->cfg_flags & CFGFLAG_UPDATE_MASK); odata->tkt_flags = (otpc->tkt_flags & ~TKTFLAG_UPDATE_MASK) |
(odata->tkt_flags & TKTFLAG_UPDATE_MASK);
odata->cfg_flags = (otpc->cfg_flags & ~CFGFLAG_UPDATE_MASK) |
(odata->cfg_flags & CFGFLAG_UPDATE_MASK);
flash_write_data_to_file(ef, apdu.data, otp_config_size); flash_write_data_to_file(ef, apdu.data, otp_config_size);
low_flash_available(); low_flash_available();
} }
@@ -421,13 +432,18 @@ int cmd_otp() {
else if (p1 == 0x30 || p1 == 0x38 || p1 == 0x20 || p1 == 0x28) { else if (p1 == 0x30 || p1 == 0x38 || p1 == 0x20 || p1 == 0x28) {
file_t *ef = search_dynamic_file(p1 == 0x30 || p1 == 0x20 ? EF_OTP_SLOT1 : EF_OTP_SLOT2); file_t *ef = search_dynamic_file(p1 == 0x30 || p1 == 0x20 ? EF_OTP_SLOT1 : EF_OTP_SLOT2);
if (file_has_data(ef)) { if (file_has_data(ef)) {
otp_config_t *otp_config = (otp_config_t *)file_get_data(ef); otp_config_t *otp_config = (otp_config_t *) file_get_data(ef);
if (!(otp_config->cfg_flags & CHAL_YUBICO && otp_config->tkt_flags & CHAL_RESP)) { if (!(otp_config->cfg_flags & CHAL_YUBICO && otp_config->tkt_flags & CHAL_RESP)) {
return SW_WRONG_DATA(); return SW_WRONG_DATA();
} }
int ret = 0; int ret = 0;
if (p1 == 0x30 || p1 == 0x38) { if (p1 == 0x30 || p1 == 0x38) {
mbedtls_md_hmac(mbedtls_md_info_from_type(MBEDTLS_MD_SHA1), otp_config->aes_key, KEY_SIZE, apdu.data, 8, res_APDU); mbedtls_md_hmac(mbedtls_md_info_from_type(MBEDTLS_MD_SHA1),
otp_config->aes_key,
KEY_SIZE,
apdu.data,
8,
res_APDU);
if (ret == 0) { if (ret == 0) {
res_APDU_size = 20; res_APDU_size = 20;
} }