Skip to content

Commit

Permalink
Merge pull request #217 from merlokk/extapdu
Browse files Browse the repository at this point in the history
Extended length apdu, iso14443 chaining and select
  • Loading branch information
conorpp committed Jul 9, 2019
2 parents ddbe317 + 10bf424 commit df2f950
Show file tree
Hide file tree
Showing 14 changed files with 322 additions and 110 deletions.
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

0 comments on commit df2f950

Please sign in to comment.