smartcard: rebase file system on top of spaceship

This commit is contained in:
Shiz 2020-04-13 04:24:33 +02:00
parent 943ca8f953
commit dc42b5c512
6 changed files with 136 additions and 143 deletions

View File

@ -1,5 +1,6 @@
SRCS += \
util.c \
spaceship.c \
dongle.c
include $(ROOT)/src/transport/build.mk

View File

@ -1,3 +1,5 @@
#pragma once
enum nsl_smartcard_error
{
NSL_SMARTCARD_ERROR_NONE = 0,

View File

@ -1,7 +1,6 @@
#include <string.h>
#include <stdlib.h>
#include "fs.h"
#include "error.h"
#include "../util.h"
@ -9,14 +8,6 @@
#define NSL_SMARTCARD_DEV_PIN_DEFAULT "123456781234567812345678"
#define NSL_SMARTCARD_PIN_LEN_REPORT_CUTOFF 16
static inline void init_common(struct nsl_smartcard_file *file, nsl_smartcart_file_id_t id, enum nsl_smartcard_file_type type)
{
file->parent = NULL;
file->prev = file->next = NULL;
file->id = id;
file->type = type;
file->flags = NSL_SMARTCARD_FILE_FLAG_USED;
}
static inline int is_authorized(struct nsl_smartcard_file *file, enum nsl_smartcard_auth_level level)
{
@ -27,18 +18,6 @@ static inline int is_authorized(struct nsl_smartcard_file *file, enum nsl_smartc
}
int nsl_smartcard_file_init(struct nsl_smartcard_file *file, nsl_smartcart_file_id_t id, enum nsl_smartcard_file_type type)
{
init_common(file, id, type);
if (!nsl_smartcard_is_file(file)) {
return NSL_SMARTCARD_ERROR_WRONG_TYPE;
}
file->contents.file.data = NULL;
file->contents.file.len = 0;
return 0;
}
int nsl_smartcard_file_open(struct nsl_smartcard_file *file, struct nsl_smartcard_handle *handle)
{
if (!nsl_smartcard_is_file(file)) {
@ -47,13 +26,13 @@ int nsl_smartcard_file_open(struct nsl_smartcard_file *file, struct nsl_smartcar
switch (file->type) {
case NSL_SMARTCARD_FILE_EXECUTABLE:
if (!is_authorized(file->parent, NSL_SMARTCARD_AUTH_DEV)) {
if (!is_authorized(nsl_smartcard_file_parent(file), NSL_SMARTCARD_AUTH_DEV)) {
return NSL_SMARTCARD_ERROR_UNAUTHORIZED;
}
break;
case NSL_SMARTCARD_FILE_DATA:
case NSL_SMARTCARD_FILE_KEY:
if (!is_authorized(file->parent, NSL_SMARTCARD_AUTH_INTERNAL)) {
if (!is_authorized(nsl_smartcard_file_parent(file), NSL_SMARTCARD_AUTH_INTERNAL)) {
return NSL_SMARTCARD_ERROR_UNAUTHORIZED;
}
break;
@ -73,11 +52,7 @@ int nsl_smartcard_file_delete(struct nsl_smartcard_file *file)
return NSL_SMARTCARD_ERROR_WRONG_TYPE;
}
file->flags &= ~NSL_SMARTCARD_FILE_FLAG_USED;
if (file->flags & NSL_SMARTCARD_FILE_FLAG_ALLOCATED) {
free(file->contents.file.data);
}
file->contents.file.data = NULL;
file->contents.file.len = 0;
spaceship_free(&file->spaceship);
return 0;
}
@ -156,15 +131,93 @@ int nsl_smartcard_handle_close(struct nsl_smartcard_handle *handle)
}
int nsl_smartcard_dir_init(struct nsl_smartcard_file *file, nsl_smartcart_file_id_t id)
static inline void init_common(struct nsl_smartcard_file *file, nsl_smartcard_file_id_t id, enum nsl_smartcard_file_type type)
{
file->id = id;
file->type = type;
file->flags = NSL_SMARTCARD_FILE_FLAG_USED;
}
static void init_dir(struct nsl_smartcard_file *file, nsl_smartcard_file_id_t id)
{
init_common(file, id, NSL_SMARTCARD_FILE_DIR);
file->contents.dir.children = NULL;
file->contents.dir.auth = NSL_SMARTCARD_AUTH_NONE;
file->contents.dir.auth_attempts = 0;
memcpy(file->contents.dir.user_pin, NSL_SMARTCARD_USER_PIN_DEFAULT, sizeof(file->contents.dir.user_pin));
memcpy(file->contents.dir.dev_pin, NSL_SMARTCARD_DEV_PIN_DEFAULT, sizeof(file->contents.dir.user_pin));
}
static int init_file(struct nsl_smartcard_file *file, nsl_smartcard_file_id_t id, enum nsl_smartcard_file_type type)
{
init_common(file, id, type);
if (!nsl_smartcard_is_file(file)) {
return NSL_SMARTCARD_ERROR_WRONG_TYPE;
}
file->contents.file.data = NULL;
file->contents.file.len = 0;
return 0;
}
int nsl_smartcard_create_root(void *mem, size_t size, struct nsl_smartcard_file **out)
{
spaceship_init(mem, size);
struct nsl_smartcard_file *dir = spaceship_alloc(mem, size);
if (!dir) {
return NSL_SMARTCARD_ERROR_NO_MEMORY;
}
spaceship_init_sub(&dir->spaceship, sizeof(*dir));
init_dir(dir, NSL_SMARTCARD_ROOT_DIR_ID);
*out = dir;
return 0;
}
int nsl_smartcard_dir_create(struct nsl_smartcard_file *file, nsl_smartcard_file_id_t id, struct nsl_smartcard_file **out)
{
if (!nsl_smartcard_is_dir(file)) {
return NSL_SMARTCARD_ERROR_WRONG_TYPE;
}
if (!is_authorized(file, NSL_SMARTCARD_AUTH_DEV)) {
return NSL_SMARTCARD_ERROR_UNAUTHORIZED;
}
struct nsl_smartcard_file *dir = spaceship_alloc(&file->spaceship, 512);
if (!dir) {
return NSL_SMARTCARD_ERROR_NO_MEMORY;
}
spaceship_init_sub(&dir->spaceship, sizeof(*dir));
init_dir(dir, id);
if (out) {
*out = dir;
}
return 0;
}
int nsl_smartcard_dir_create_file(struct nsl_smartcard_file *file, nsl_smartcard_file_id_t id, enum nsl_smartcard_file_type type, struct nsl_smartcard_file **out)
{
if (!nsl_smartcard_is_dir(file)) {
return NSL_SMARTCARD_ERROR_WRONG_TYPE;
}
if (!is_authorized(file, NSL_SMARTCARD_AUTH_DEV)) {
return NSL_SMARTCARD_ERROR_UNAUTHORIZED;
}
struct nsl_smartcard_file *f = spaceship_alloc(&file->spaceship, sizeof(*f));
if (!f) {
return NSL_SMARTCARD_ERROR_NO_MEMORY;
}
int err = init_file(f, id, type);
if (err) {
spaceship_free(&f->spaceship);
return err;
}
if (out) {
*out = f;
}
return 0;
}
@ -180,7 +233,7 @@ int nsl_smartcard_dir_delete(struct nsl_smartcard_file *file)
}
file->flags &= ~NSL_SMARTCARD_FILE_FLAG_USED;
file->contents.dir.auth = NSL_SMARTCARD_AUTH_NONE;
spaceship_free(&file->spaceship);
return 0;
}
@ -276,40 +329,12 @@ int nsl_smartcard_dir_internal_end(struct nsl_smartcard_file *file)
}
int nsl_smartcard_dir_add(struct nsl_smartcard_file *file, struct nsl_smartcard_file *child)
int nsl_smartcard_dir_find(struct nsl_smartcard_file *file, nsl_smartcard_file_id_t id, struct nsl_smartcard_file **child)
{
if (!nsl_smartcard_is_dir(file)) {
return NSL_SMARTCARD_ERROR_WRONG_TYPE;
}
if (!is_authorized(file, NSL_SMARTCARD_AUTH_DEV)) {
return NSL_SMARTCARD_ERROR_UNAUTHORIZED;
}
if (child->id == NSL_SMARTCARD_ROOT_DIR_ID) {
return NSL_SMARTCARD_ERROR_WRONG_ID;
}
if (child->parent || child->prev || child->next) {
return NSL_SMARTCARD_ERROR_IN_USE;
}
if (file->id == child->id || (file->parent && file->parent->id == child->id)) {
return NSL_SMARTCARD_ERROR_WRONG_ID;
}
if (!nsl_smartcard_dir_find(file, child->id, NULL)) {
return NSL_SMARTCARD_ERROR_WRONG_ID;
}
child->parent = file;
child->prev = NULL;
child->next = file->contents.dir.children;
file->contents.dir.children->prev = child;
file->contents.dir.children = child;
return 0;
}
int nsl_smartcard_dir_find(struct nsl_smartcard_file *file, nsl_smartcart_file_id_t id, struct nsl_smartcard_file **child)
{
if (!nsl_smartcard_is_dir(file)) {
return NSL_SMARTCARD_ERROR_WRONG_TYPE;
}
for (struct nsl_smartcard_file *f = file->contents.dir.children; f; f = f->next) {
for (struct nsl_smartcard_file *f = nsl_smartcard_file_iter(file); f; f = nsl_smartcard_file_next(f)) {
if (f->id == id) {
if (child) {
*child = f;
@ -320,34 +345,6 @@ int nsl_smartcard_dir_find(struct nsl_smartcard_file *file, nsl_smartcart_file_i
return NSL_SMARTCARD_ERROR_NOT_FOUND;
}
int nsl_smartcard_dir_remove(struct nsl_smartcard_file *file, nsl_smartcart_file_id_t id)
{
if (!nsl_smartcard_is_dir(file)) {
return NSL_SMARTCARD_ERROR_WRONG_TYPE;
}
if (!is_authorized(file, NSL_SMARTCARD_AUTH_DEV)) {
return NSL_SMARTCARD_ERROR_UNAUTHORIZED;
}
struct nsl_smartcard_file *child;
if (!nsl_smartcard_dir_find(file, id, &child)) {
return NSL_SMARTCARD_ERROR_WRONG_ID;
}
if (child->prev) {
child->prev->next = child->next;
} else {
file->contents.dir.children = child->next;
}
if (child->next) {
child->next->prev = child->prev;
}
child->parent = NULL;
child->prev = child->next = NULL;
return 0;
}
int nsl_smartcard_dir_clear(struct nsl_smartcard_file *file)
{
if (!nsl_smartcard_is_dir(file)) {
@ -357,25 +354,13 @@ int nsl_smartcard_dir_clear(struct nsl_smartcard_file *file)
return NSL_SMARTCARD_ERROR_UNAUTHORIZED;
}
struct nsl_smartcard_file *child = file->contents.dir.children, *next;
while (child) {
next = child->next;
nsl_smartcard_dir_remove(file, child->id);
for (struct nsl_smartcard_file *child = nsl_smartcard_file_iter(file); child; child = nsl_smartcard_file_next(child)) {
if (nsl_smartcard_is_dir(child)) {
nsl_smartcard_dir_delete(child);
} else {
nsl_smartcard_file_delete(child);
}
child = next;
}
return 0;
}
int nsl_smartcard_dir_iter(struct nsl_smartcard_file *file, struct nsl_smartcard_file **child)
{
if (!nsl_smartcard_is_dir(file)) {
return NSL_SMARTCARD_ERROR_WRONG_TYPE;
}
*child = file->contents.dir.children;
return 0;
}

View File

@ -1,5 +1,7 @@
#include <stdint.h>
#include <stddef.h>
#include "../spaceship.h"
#include "error.h"
#define NSL_SMARTCARD_USER_PIN_LEN 8
@ -8,7 +10,7 @@
#define NSL_SMARTCARD_CUR_DIR_ID 0x3FFF
typedef uint16_t nsl_smartcart_file_id_t;
typedef uint16_t nsl_smartcard_file_id_t;
enum nsl_smartcard_auth_level
{
@ -44,7 +46,6 @@ struct nsl_smartcard_file_contents
struct nsl_smartcard_dir_contents
{
struct nsl_smartcard_file *children;
uint8_t user_pin[NSL_SMARTCARD_USER_PIN_LEN];
uint8_t dev_pin[NSL_SMARTCARD_DEV_PIN_LEN];
@ -54,13 +55,12 @@ struct nsl_smartcard_dir_contents
struct nsl_smartcard_file
{
struct nsl_smartcard_file *parent;
struct nsl_smartcard_file *prev, *next;
struct spaceship_chunk spaceship;
enum nsl_smartcard_file_type type;
int flags;
nsl_smartcart_file_id_t id;
nsl_smartcard_file_id_t id;
union {
struct nsl_smartcard_file_contents file;
struct nsl_smartcard_dir_contents dir;
@ -98,31 +98,47 @@ struct nsl_smartcard_handle
int valid;
};
int nsl_smartcard_file_init(struct nsl_smartcard_file *, nsl_smartcart_file_id_t id, enum nsl_smartcard_file_type type);
int nsl_smartcard_file_delete(struct nsl_smartcard_file *);
int nsl_smartcard_file_open(struct nsl_smartcard_file *, struct nsl_smartcard_handle *handle);
static inline int nsl_smartcard_handle_is_valid(struct nsl_smartcard_handle *handle)
{
return handle->valid;
}
int nsl_smartcard_handle_read(struct nsl_smartcard_handle *, uint8_t *data, size_t *len);
int nsl_smartcard_handle_write(struct nsl_smartcard_handle *, const uint8_t *data, size_t *len);
int nsl_smartcard_handle_seek(struct nsl_smartcard_handle *, size_t pos, enum nsl_smartcard_origin origin);
int nsl_smartcard_handle_tell(struct nsl_smartcard_handle *, size_t *pos);
int nsl_smartcard_handle_close(struct nsl_smartcard_handle *);
int nsl_smartcard_dir_init(struct nsl_smartcard_file *, nsl_smartcart_file_id_t id);
int nsl_smartcard_file_open(struct nsl_smartcard_file *, struct nsl_smartcard_handle *handle);
int nsl_smartcard_file_delete(struct nsl_smartcard_file *);
int nsl_smartcard_dir_create(struct nsl_smartcard_file *, nsl_smartcard_file_id_t id, struct nsl_smartcard_file **);
int nsl_smartcard_dir_create_file(struct nsl_smartcard_file *, nsl_smartcard_file_id_t id, enum nsl_smartcard_file_type type, struct nsl_smartcard_file **);
int nsl_smartcard_dir_delete(struct nsl_smartcard_file *);
int nsl_smartcard_dir_authorize(struct nsl_smartcard_file *, const uint8_t *pin, size_t len, enum nsl_smartcard_auth_level level);
int nsl_smartcard_dir_change_pin(struct nsl_smartcard_file *, const uint8_t *pin, size_t len, enum nsl_smartcard_auth_level level);
int nsl_smartcard_dir_internal_begin(struct nsl_smartcard_file *);
int nsl_smartcard_dir_internal_end(struct nsl_smartcard_file *);
int nsl_smartcard_dir_add(struct nsl_smartcard_file *, struct nsl_smartcard_file *child);
int nsl_smartcard_dir_find(struct nsl_smartcard_file *, nsl_smartcart_file_id_t id, struct nsl_smartcard_file **child);
int nsl_smartcard_dir_remove(struct nsl_smartcard_file *, nsl_smartcart_file_id_t id);
int nsl_smartcard_dir_find(struct nsl_smartcard_file *, nsl_smartcard_file_id_t id, struct nsl_smartcard_file **child);
int nsl_smartcard_dir_clear(struct nsl_smartcard_file *);
int nsl_smartcard_dir_iter(struct nsl_smartcard_file *, struct nsl_smartcard_file **child);
int nsl_smartcard_create_root(void *mem, size_t size, struct nsl_smartcard_file **);
static inline struct nsl_smartcard_file *nsl_smartcard_file_iter(struct nsl_smartcard_file *file)
{
return spaceship_get_first_child(&file->spaceship);
}
static inline struct nsl_smartcard_file *nsl_smartcard_file_next(struct nsl_smartcard_file *file)
{
return spaceship_get_next_sibling(&file->spaceship);
}
static inline struct nsl_smartcard_file *nsl_smartcard_file_parent(struct nsl_smartcard_file *file)
{
return spaceship_get_parent(&file->spaceship);
}

View File

@ -15,9 +15,13 @@ static void set_error(struct nsl_smartcard *smartcard, uint8_t sw1, uint8_t sw2)
int nsl_smartcard_init(struct nsl_smartcard *smartcard)
{
smartcard->rootdir = smartcard->curdir = NULL;
smartcard->curdir = NULL;
memset(smartcard->handles, 0, sizeof(smartcard->handles));
smartcard->last_handle = 0;
int err = nsl_smartcard_create_root(smartcard->file_system, sizeof(smartcard->file_system), &smartcard->rootdir);
if (err) {
return err;
}
memset(smartcard->standard_handlers, 0, sizeof(smartcard->standard_handlers));
memset(smartcard->proprietary_handlers, 0, sizeof(smartcard->proprietary_handlers));
@ -50,7 +54,7 @@ int nsl_smartcard_change_pin(struct nsl_smartcard *smartcard, const uint8_t *pin
}
int nsl_smartcard_mkdir(struct nsl_smartcard *smartcard, nsl_smartcart_file_id_t id)
int nsl_smartcard_mkdir(struct nsl_smartcard *smartcard, nsl_smartcard_file_id_t id)
{
if (!smartcard->curdir) {
return NSL_SMARTCARD_ERROR_NOT_FOUND;
@ -61,26 +65,10 @@ int nsl_smartcard_mkdir(struct nsl_smartcard *smartcard, nsl_smartcart_file_id_t
return NSL_SMARTCARD_ERROR_ALREADY_EXISTS;
}
struct nsl_smartcard_file *dir = malloc(sizeof(*dir));
if (!dir) {
return NSL_SMARTCARD_ERROR_NO_MEMORY;
}
int err = nsl_smartcard_dir_init(dir, id);
if (err) {
goto err;
}
err = nsl_smartcard_dir_add(parent, dir);
if (err) {
goto err;
}
return 0;
err:
free(dir);
return err;
return nsl_smartcard_dir_create(smartcard->curdir, id, NULL);
}
int nsl_smartcard_chdir(struct nsl_smartcard *smartcard, nsl_smartcart_file_id_t id)
int nsl_smartcard_chdir(struct nsl_smartcard *smartcard, nsl_smartcard_file_id_t id)
{
struct nsl_smartcard_file *dir;
if (id == NSL_SMARTCARD_CUR_DIR_ID) {
@ -101,7 +89,7 @@ int nsl_smartcard_chdir(struct nsl_smartcard *smartcard, nsl_smartcart_file_id_t
return 0;
}
int nsl_smartcard_exec(struct nsl_smartcard *smartcard, nsl_smartcart_file_id_t id, const uint8_t *inbuf, size_t inlen, uint8_t *outbuf, size_t outlen)
int nsl_smartcard_exec(struct nsl_smartcard *smartcard, nsl_smartcard_file_id_t id, const uint8_t *inbuf, size_t inlen, uint8_t *outbuf, size_t outlen)
{
if (!smartcard->curdir) {
return NSL_SMARTCARD_ERROR_NOT_FOUND;
@ -119,7 +107,7 @@ int nsl_smartcard_exec(struct nsl_smartcard *smartcard, nsl_smartcart_file_id_t
}
int nsl_smartcard_open(struct nsl_smartcard *smartcard, nsl_smartcart_file_id_t id, struct nsl_smartcard_handle **handle)
int nsl_smartcard_open(struct nsl_smartcard *smartcard, nsl_smartcard_file_id_t id, struct nsl_smartcard_handle **handle)
{
size_t nhandles = sizeof(smartcard->handles) / sizeof(*smartcard->handles);
size_t cur = smartcard->last_handle + 1;

View File

@ -22,6 +22,7 @@ struct nsl_smartcard {
nsl_smartcard_handler_t standard_handlers[0x100];
nsl_smartcard_handler_t proprietary_handlers[0x100];
uint8_t file_system[8192];
struct nsl_smartcard_handle handles[NSL_SMARTCARD_MAX_HANDLES];
uint8_t last_handle;
};
@ -31,9 +32,9 @@ int nsl_smartcard_reset(struct nsl_smartcard *smartcard);
int nsl_smartcard_authorize(struct nsl_smartcard *smartcard, const uint8_t *pin, size_t len, enum nsl_smartcard_auth_level level);
int nsl_smartcard_change_pin(struct nsl_smartcard *smartcard, const uint8_t *pin, size_t len, enum nsl_smartcard_auth_level level);
int nsl_smartcard_mkdir(struct nsl_smartcard *smartcard, nsl_smartcart_file_id_t id);
int nsl_smartcard_chdir(struct nsl_smartcard *smartcard, nsl_smartcart_file_id_t id);
int nsl_smartcard_exec(struct nsl_smartcard *smartcard, nsl_smartcart_file_id_t id, const uint8_t *inbuf, size_t inlen, uint8_t *outbuf, size_t outlen);
int nsl_smartcard_open(struct nsl_smartcard *smartcard, nsl_smartcart_file_id_t id, struct nsl_smartcard_handle **handle);
int nsl_smartcard_mkdir(struct nsl_smartcard *smartcard, nsl_smartcard_file_id_t id);
int nsl_smartcard_chdir(struct nsl_smartcard *smartcard, nsl_smartcard_file_id_t id);
int nsl_smartcard_exec(struct nsl_smartcard *smartcard, nsl_smartcard_file_id_t id, const uint8_t *inbuf, size_t inlen, uint8_t *outbuf, size_t outlen);
int nsl_smartcard_open(struct nsl_smartcard *smartcard, nsl_smartcard_file_id_t id, struct nsl_smartcard_handle **handle);
int nsl_smartcard_process(struct nsl_smartcard *smartcard, const uint8_t *inbuf, size_t inlen, uint8_t *outbuf, size_t outlen);