Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Extended length apdu, iso14443 chaining and select #217

Merged
merged 25 commits into from
Jul 9, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -83,3 +83,5 @@ targets/*/docs/
main

builds/*
tools/testing/.idea/*
tools/testing/tests/__pycache__/*
122 changes: 122 additions & 0 deletions fido2/apdu.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,122 @@
// Copyright 2019 SoloKeys Developers
//
// Licensed under the Apache License, Version 2.0, <LICENSE-APACHE or
// http://apache.org/licenses/LICENSE-2.0> or the MIT license <LICENSE-MIT or
// http://opensource.org/licenses/MIT>, at your option. This file may not be
// copied, modified, or distributed except according to those terms.

// iso7816:2013. 5.3.2 Decoding conventions for command bodies

#include "apdu.h"

int apdu_decode(uint8_t *data, size_t len, APDU_STRUCT *apdu)
{
EXT_APDU_HEADER *hapdu = (EXT_APDU_HEADER *)data;

apdu->cla = hapdu->cla;
apdu->ins = hapdu->ins;
apdu->p1 = hapdu->p1;
apdu->p2 = hapdu->p2;

apdu->lc = 0;
apdu->data = NULL;
apdu->le = 0;
apdu->extended_apdu = false;
apdu->case_type = 0x00;

uint8_t b0 = hapdu->lc[0];

// case 1
if (len == 4)
{
apdu->case_type = 0x01;
}

// case 2S (Le)
if (len == 5)
{
apdu->case_type = 0x02;
apdu->le = b0;
if (!apdu->le)
apdu->le = 0x100;
}

// case 3S (Lc + data)
if (len == 5U + b0 && b0 != 0)
{
apdu->case_type = 0x03;
apdu->lc = b0;
}

// case 4S (Lc + data + Le)
if (len == 5U + b0 + 1U && b0 != 0)
{
apdu->case_type = 0x04;
apdu->lc = b0;
apdu->le = data[len - 1];
if (!apdu->le)
apdu->le = 0x100;
}

// extended length apdu
if (len >= 7 && b0 == 0)
{
uint16_t extlen = (hapdu->lc[1] << 8) + hapdu->lc[2];

// case 2E (Le) - extended
if (len == 7)
{
apdu->case_type = 0x12;
apdu->extended_apdu = true;
apdu->le = extlen;
if (!apdu->le)
apdu->le = 0x10000;
}

// case 3E (Lc + data) - extended
if (len == 7U + extlen)
{
apdu->case_type = 0x13;
apdu->extended_apdu = true;
apdu->lc = extlen;
}

// case 4E (Lc + data + Le) - extended 2-byte Le
if (len == 7U + extlen + 2U)
{
apdu->case_type = 0x14;
apdu->extended_apdu = true;
apdu->lc = extlen;
apdu->le = (data[len - 2] << 8) + data[len - 1];
if (!apdu->le)
apdu->le = 0x10000;
}

// case 4E (Lc + data + Le) - extended 3-byte Le
if (len == 7U + extlen + 3U && data[len - 3] == 0)
{
apdu->case_type = 0x24;
apdu->extended_apdu = true;
apdu->lc = extlen;
apdu->le = (data[len - 2] << 8) + data[len - 1];
if (!apdu->le)
apdu->le = 0x10000;
}
}

if (!apdu->case_type)
return 1;

if (apdu->lc)
{
if (apdu->extended_apdu)
{
apdu->data = data + 7;
} else {
apdu->data = data + 5;
}

}

return 0;
}
27 changes: 27 additions & 0 deletions fido2/apdu.h
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@
#define _APDU_H_

#include <stdint.h>
#include <stdbool.h>
#include <stddef.h>

typedef struct
{
Expand All @@ -12,6 +14,30 @@ typedef struct
uint8_t lc;
} __attribute__((packed)) APDU_HEADER;

typedef struct
{
uint8_t cla;
uint8_t ins;
uint8_t p1;
uint8_t p2;
uint8_t lc[3];
} __attribute__((packed)) EXT_APDU_HEADER;

typedef struct
{
uint8_t cla;
uint8_t ins;
uint8_t p1;
uint8_t p2;
uint16_t lc;
uint8_t *data;
uint32_t le;
bool extended_apdu;
uint8_t case_type;
} __attribute__((packed)) APDU_STRUCT;

extern int apdu_decode(uint8_t *data, size_t len, APDU_STRUCT *apdu);

#define APDU_FIDO_U2F_REGISTER 0x01
#define APDU_FIDO_U2F_AUTHENTICATE 0x02
#define APDU_FIDO_U2F_VERSION 0x03
Expand All @@ -25,6 +51,7 @@ typedef struct
#define SW_COND_USE_NOT_SATISFIED 0x6985
#define SW_FILE_NOT_FOUND 0x6a82
#define SW_INS_INVALID 0x6d00 // Instruction code not supported or invalid
#define SW_CLA_INVALID 0x6e00
#define SW_INTERNAL_EXCEPTION 0x6f00

#endif //_APDU_H_
2 changes: 2 additions & 0 deletions fido2/device.h
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,8 @@ void device_set_clock_rate(DEVICE_CLOCK_RATE param);
#define NFC_IS_AVAILABLE 2
int device_is_nfc();

void request_from_nfc(bool request_active);

void device_init_button();

#endif
10 changes: 5 additions & 5 deletions fido2/u2f.c
Original file line number Diff line number Diff line change
Expand Up @@ -113,14 +113,14 @@ void u2f_request_ex(APDU_HEADER *req, uint8_t *payload, uint32_t len, CTAP_RESPO
printf1(TAG_U2F,"u2f resp: "); dump_hex1(TAG_U2F, _u2f_resp->data, _u2f_resp->length);
}

void u2f_request_nfc(uint8_t * req, int len, CTAP_RESPONSE * resp)
void u2f_request_nfc(uint8_t * header, uint8_t * data, int datalen, CTAP_RESPONSE * resp)
{
if (len < 5 || !req)
if (!header)
return;

uint32_t alen = req[4];

u2f_request_ex((APDU_HEADER *)req, &req[5], alen, resp);
request_from_nfc(true); // disable presence test
u2f_request_ex((APDU_HEADER *)header, data, datalen, resp);
request_from_nfc(false); // enable presence test
}

void u2f_request(struct u2f_request_apdu* req, CTAP_RESPONSE * resp)
Expand Down
2 changes: 1 addition & 1 deletion fido2/u2f.h
Original file line number Diff line number Diff line change
Expand Up @@ -101,7 +101,7 @@ void u2f_request(struct u2f_request_apdu* req, CTAP_RESPONSE * resp);
// u2f_request send a U2F message to NFC protocol
// @req data with iso7816 apdu message
// @len data length
void u2f_request_nfc(uint8_t * req, int len, CTAP_RESPONSE * resp);
void u2f_request_nfc(uint8_t * header, uint8_t * data, int datalen, CTAP_RESPONSE * resp);

int8_t u2f_authenticate_credential(struct u2f_key_handle * kh, uint8_t * appid);

Expand Down
2 changes: 1 addition & 1 deletion targets/stm32l432/build/application.mk
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ SRC += src/startup_stm32l432xx.s src/system_stm32l4xx.c
SRC += $(DRIVER_LIBS) $(USB_LIB)

# FIDO2 lib
SRC += ../../fido2/util.c ../../fido2/u2f.c ../../fido2/test_power.c
SRC += ../../fido2/apdu.c ../../fido2/util.c ../../fido2/u2f.c ../../fido2/test_power.c
SRC += ../../fido2/stubs.c ../../fido2/log.c ../../fido2/ctaphid.c ../../fido2/ctap.c
SRC += ../../fido2/ctap_parse.c ../../fido2/main.c
SRC += ../../fido2/extensions/extensions.c ../../fido2/extensions/solo.c
Expand Down
2 changes: 1 addition & 1 deletion targets/stm32l432/src/app.h
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@
// #define DISABLE_CTAPHID_WINK
// #define DISABLE_CTAPHID_CBOR

#define ENABLE_SERIAL_PRINTING
// #define ENABLE_SERIAL_PRINTING

#if defined(SOLO_HACKER)
#define SOLO_PRODUCT_NAME "Solo Hacker " SOLO_VERSION
Expand Down
7 changes: 6 additions & 1 deletion targets/stm32l432/src/device.c
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ uint32_t __last_update = 0;
extern PCD_HandleTypeDef hpcd;
static int _NFC_status = 0;
static bool isLowFreq = 0;
static bool _RequestComeFromNFC = false;

// #define IS_BUTTON_PRESSED() (0 == (LL_GPIO_ReadInputPort(SOLO_BUTTON_PORT) & SOLO_BUTTON_PIN))
static int is_physical_button_pressed()
Expand All @@ -57,6 +58,10 @@ static int is_touch_button_pressed()

int (*IS_BUTTON_PRESSED)() = is_physical_button_pressed;

void request_from_nfc(bool request_active) {
_RequestComeFromNFC = request_active;
}

// Timer6 overflow handler. happens every ~90ms.
void TIM6_DAC_IRQHandler()
{
Expand Down Expand Up @@ -491,7 +496,7 @@ static int handle_packets()
int ctap_user_presence_test(uint32_t up_delay)
{
int ret;
if (device_is_nfc() == NFC_IS_ACTIVE)
if (device_is_nfc() == NFC_IS_ACTIVE || _RequestComeFromNFC)
{
return 1;
}
Expand Down
Loading