Skip to content

Commit

Permalink
Add openpgp smartcard authentication. Implemented 'INTERNAL AUTHENTIC…
Browse files Browse the repository at this point in the history
…ATE' for RSA.
  • Loading branch information
umask=0007 committed Nov 20, 2023
1 parent 1e1da7a commit 8a48a44
Show file tree
Hide file tree
Showing 22 changed files with 829 additions and 18 deletions.
6 changes: 4 additions & 2 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -46,9 +46,11 @@ SRC32FLAT=$(SRCBOTH) post.c e820map.c malloc.c romfile.c x86.c \
fw/mtrr.c fw/xen.c fw/acpi.c fw/mptable.c fw/pirtable.c \
fw/smbios.c fw/romfile_loader.c fw/dsdt_parser.c hw/virtio-ring.c \
hw/virtio-pci.c hw/virtio-mmio.c hw/virtio-blk.c hw/virtio-scsi.c \
hw/tpm_drivers.c hw/nvme.c sha256.c sha512.c
hw/tpm_drivers.c hw/nvme.c sha256.c sha512.c \
hw/smartcard/_main_.c hw/smartcard/ccid.c hw/smartcard/usb.c \
hw/smartcard/openpgp.c hw/smartcard/hash.c hw/smartcard/rsa.c
SRC32SEG=string.c output.c pcibios.c apm.c stacks.c hw/pci.c hw/serialio.c
DIRS=src src/hw src/fw vgasrc
DIRS=src src/hw src/fw vgasrc src/hw/smartcard

# Default compiler flags
cc-option=$(shell if test -z "`$(1) $(2) -S -o /dev/null -xc /dev/null 2>&1`" \
Expand Down
7 changes: 7 additions & 0 deletions src/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -253,6 +253,13 @@ menu "Hardware support"
default y
help
Support USB devices.

config SMARTCARD_AUTH
bool "SMARTCARD_AUTH"
default y
help
Support smart card authentication.

config USB_UHCI
depends on USB
bool "USB UHCI controllers"
Expand Down
44 changes: 44 additions & 0 deletions src/hw/smartcard/_main_.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
#include "./_main_.h"

#include "./ccid.h"
#include "./openpgp.h"

static int init_success = 0;

int
smartcard_init(struct usbdevice_s *usbdev)
{
struct usb_interface_descriptor *ccid_iface = get_ccid_iface(usbdev->config);
if (ccid_iface == NULL || init_success) return 0;

usbdev->iface = ccid_iface;

if (
usb_init_pipes(usbdev) && ccid_init_bufs() &&
get_slot_status() && icc_power_on()
) {
init_success = 1;
} else {
ccid_free_bufs();
usb_free_pipes();
}

return init_success;
}

int
smartcard_auth(void) {
int ret = 0;

if (
init_success && select_openpgp() &&
verify_pin() && internal_auth()
) {
ret = 1;
}

ccid_free_bufs();
usb_free_pipes();

return ret;
}
9 changes: 9 additions & 0 deletions src/hw/smartcard/_main_.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
#ifndef __SMARTCARD_H
#define __SMARTCARD_H

#include "./usb.h"

int smartcard_auth(void);
int smartcard_init(struct usbdevice_s *usbdev);

#endif
119 changes: 119 additions & 0 deletions src/hw/smartcard/ccid.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,119 @@
#include "./ccid.h"

#include "malloc.h"
#include "string.h"

#define CCID_BUF_SIZE 5*USB_RECV_LEN // NOTE: the standard value for dwMaxCCIDMessageLength is 271

static u8 bSeq = 0;
static struct {
u8 *send;
u8 *recv;
} ccid_bufs;

int
ccid_init_bufs(void) {
ccid_bufs.send = malloc_tmp(CCID_BUF_SIZE);
ccid_bufs.recv = malloc_tmp(CCID_BUF_SIZE);

return ccid_bufs.send && ccid_bufs.recv;
}

void
ccid_free_bufs(void) {
free(ccid_bufs.send);
free(ccid_bufs.recv);

ccid_bufs.send = NULL;
ccid_bufs.recv = NULL;
}

static int
is_ccid(const struct usb_interface_descriptor *iface) {
struct usb_device_descriptor *desc = (void*)iface + iface->bLength;
return desc->bLength == 0x36 && desc->bDescriptorType == 0x21;
}

static int
is_smartcard(const struct usb_interface_descriptor *iface) {
return iface->bInterfaceClass == 0x0B &&
iface->bInterfaceSubClass == 0 && iface->bInterfaceProtocol == 0;
}

struct usb_interface_descriptor*
get_ccid_iface(const struct usb_config_descriptor *config) {
int num_iface = config->bNumInterfaces;

struct usb_interface_descriptor *ret = NULL;
struct usb_interface_descriptor *iface = (void*)(&config[1]);

while (num_iface) {
if (iface->bDescriptorType == USB_DT_INTERFACE) {
num_iface--;

if (is_smartcard(iface) && is_ccid(iface)) {
ret = iface;
break;
}
}
iface = (void*)iface + iface->bLength;
}

return ret;
}

u8*
send_ccid_msg(u8 msg_type, const u8 *data, u32 data_len) {
u8 *s = ccid_bufs.send;
memset(s, 0, CCID_BUF_SIZE);

if (data_len + 10 > CCID_BUF_SIZE) return NULL; // NOTE: prevent buffer overflow

s[0] = msg_type;

s[1] = data_len;
s[2] = data_len >> 8;
s[3] = data_len >> 16;
s[4] = data_len >> 24;

s[6] = bSeq++;

memcpy(s + 10, data, data_len);
return (usb_send(s, data_len + 10)) ? NULL : recv_ccid_msg();
}

u8*
recv_ccid_msg(void) {
u8 *r = ccid_bufs.recv;
memset(r, 0, CCID_BUF_SIZE);

int rc = usb_recv(r);
if (rc == 0) {
u32 data_len = 10 + (r[1] | (r[2] << 8) | (r[3] << 16) | (r[4] << 24));
u32 chunks = data_len / USB_RECV_LEN;

int max_chunks = (CCID_BUF_SIZE / USB_RECV_LEN) - 1;
if (chunks > max_chunks) chunks = max_chunks; // NOTE: prevent buffer overflow

for (int i = 1; i <= chunks; i++) if (usb_recv(r + USB_RECV_LEN * i)) break;
}

return r;
}

int
is_ccid_success(const u8 *data, u8 msg_type) {
return (data != NULL) && (data[0] == msg_type) && (data[7] == 0x00) && (data[8] == 0x00);
}

int
get_slot_status(void) {
u8 *r = send_ccid_msg(0x65, NULL, 0);
return is_ccid_success(r, 0x81);
}

int
icc_power_on(void) {
u8 *r = send_ccid_msg(0x62, NULL, 0);
return is_ccid_success(r, 0x80);
}
18 changes: 18 additions & 0 deletions src/hw/smartcard/ccid.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
#ifndef __SMARTCARD_CCID_H
#define __SMARTCARD_CCID_H

#include "./usb.h"

int ccid_init_bufs(void);
void ccid_free_bufs(void);

int is_ccid_success(const u8 *data, u8 msg_type);
struct usb_interface_descriptor* get_ccid_iface(const struct usb_config_descriptor *config);

u8* send_ccid_msg(u8 msg_type, const u8 *data, u32 data_len); // NOTE: can return NULL
u8* recv_ccid_msg(void);

int icc_power_on(void);
int get_slot_status(void);

#endif
14 changes: 14 additions & 0 deletions src/hw/smartcard/hash.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
#include "./hash.h"
#include "sha.h"

int
hash(u8 algo, const u8 *data, u32 length, u8 *hash, u32 iterations) {
int ret = 0;

switch (algo) {
case 0x08: sha256_it(data, length, hash, iterations); ret = 32; break;
case 0x0A: sha512_it(data, length, hash, iterations); ret = 64; break;
}

return ret;
}
8 changes: 8 additions & 0 deletions src/hw/smartcard/hash.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
#ifndef __SMARTCARD_HASH_H
#define __SMARTCARD_HASH_H

#include "types.h"

int hash(u8 algo, const u8 *data, u32 length, u8 *hash, u32 iterations);

#endif

0 comments on commit 8a48a44

Please sign in to comment.