add apdu_decode

This commit is contained in:
merlokk 2019-07-04 16:27:33 +03:00
parent 4dc6bcf771
commit a51c9192b1
2 changed files with 145 additions and 0 deletions

119
fido2/apdu.c Normal file
View File

@ -0,0 +1,119 @@
// 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 && b0 != 0)
{
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 = 0x13;
apdu->lc = (hapdu->lc[1] << 8) + hapdu->lc[2];
}
// 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->lc = extlen;
}
// case 4E (Lc + data + Le) - extended 2-byte Le
if (len == 7U + extlen + 2U)
{
apdu->case_type = 0x14;
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->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 + 5;
} else {
apdu->data = data + 7;
}
}
return 0;
}

View File

@ -2,6 +2,8 @@
#define _APDU_H_
#include <stdint.h>
#include <stdbool.h>
#include <stddef.h>
typedef struct
{
@ -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