Skip to content

Commit

Permalink
Add minimal CAC1 driver for legacy cards.
Browse files Browse the repository at this point in the history
It is using the same pkcs15 backend as the CAC2 cards as well as some of
the CAC2 driver methods.

The separation is made mostly for easier card matching or disabling.
  • Loading branch information
Jakuje committed Oct 23, 2018
1 parent 5095e29 commit 90fbc57
Show file tree
Hide file tree
Showing 8 changed files with 783 additions and 141 deletions.
3 changes: 2 additions & 1 deletion src/libopensc/Makefile.am
Expand Up @@ -40,7 +40,8 @@ libopensc_la_SOURCES_BASE = \
card-mcrd.c card-starcos.c card-openpgp.c card-jcop.c \
card-oberthur.c card-belpic.c card-atrust-acos.c \
card-entersafe.c card-epass2003.c card-coolkey.c card-incrypto34.c \
card-piv.c card-cac.c card-muscle.c card-acos5.c \
card-piv.c card-cac-common.c card-cac.c card-cac1.c \
card-muscle.c card-acos5.c \
card-asepcos.c card-akis.c card-gemsafeV1.c card-rutoken.c \
card-rtecp.c card-westcos.c card-myeid.c \
card-itacns.c card-authentic.c \
Expand Down
3 changes: 2 additions & 1 deletion src/libopensc/Makefile.mak
Expand Up @@ -19,7 +19,8 @@ OBJECTS = \
card-mcrd.obj card-starcos.obj card-openpgp.obj card-jcop.obj \
card-oberthur.obj card-belpic.obj card-atrust-acos.obj \
card-entersafe.obj card-epass2003.obj card-coolkey.obj \
card-incrypto34.obj card-cac.obj card-piv.obj card-muscle.obj \
card-incrypto34.obj card-cac.obj card-cac1.obj card-cac-common.obj \
card-piv.obj card-muscle.obj \
card-acos5.obj \
card-asepcos.obj card-akis.obj card-gemsafeV1.obj card-rutoken.obj \
card-rtecp.obj card-westcos.obj card-myeid.obj \
Expand Down
116 changes: 116 additions & 0 deletions src/libopensc/card-cac-common.c
@@ -0,0 +1,116 @@
/*
* card-cac-common.c: Code shared among CAC1 and CAC2 drivers
*
* Copyright (C) 2018, Red Hat, Inc.
*
* Author: Jakub Jelen <jjelen@redhat.com>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/

#if HAVE_CONFIG_H
#include "config.h"
#endif

#include <ctype.h>
#include <string.h>
#include <stdlib.h>

#ifdef _WIN32
#include <io.h>
#else
#include <unistd.h>
#endif

#include "internal.h"
#include "iso7816.h"
#include "card-cac-common.h"

/* default certificate labels for the CAC card */
const char *cac_labels[MAX_CAC_SLOTS] = {
"CAC ID Certificate",
"CAC Email Signature Certificate",
"CAC Email Encryption Certificate",
"CAC Cert 4",
"CAC Cert 5",
"CAC Cert 6",
"CAC Cert 7",
"CAC Cert 8",
"CAC Cert 9",
"CAC Cert 10",
"CAC Cert 11",
"CAC Cert 12",
"CAC Cert 13",
"CAC Cert 14",
"CAC Cert 15",
"CAC Cert 16"
};

const char *get_cac_label(int index)
{
if (index < 0 || index >= MAX_CAC_SLOTS)
return NULL;

return cac_labels[index];
}

static int cac_list_compare_path(const void *a, const void *b)
{
if (a == NULL || b == NULL)
return 1;
return memcmp( &((cac_object_t *) a)->path,
&((cac_object_t *) b)->path, sizeof(sc_path_t));
}

/* For SimCList autocopy, we need to know the size of the data elements */
static size_t cac_list_meter(const void *el) {
return sizeof(cac_object_t);
}

cac_private_data_t *cac_new_private_data(void)
{
cac_private_data_t *priv;
priv = calloc(1, sizeof(cac_private_data_t));
if (!priv)
return NULL;
list_init(&priv->pki_list);
list_attributes_comparator(&priv->pki_list, cac_list_compare_path);
list_attributes_copy(&priv->pki_list, cac_list_meter, 1);
list_init(&priv->general_list);
list_attributes_comparator(&priv->general_list, cac_list_compare_path);
list_attributes_copy(&priv->general_list, cac_list_meter, 1);
/* set other fields as appropriate */

return priv;
}

void cac_free_private_data(cac_private_data_t *priv)
{
free(priv->cac_id);
free(priv->cache_buf);
free(priv->aca_path);
list_destroy(&priv->pki_list);
list_destroy(&priv->general_list);
free(priv);
return;
}

int cac_add_object_to_list(list_t *list, const cac_object_t *object)
{
if (list_append(list, object) < 0)
return SC_ERROR_UNKNOWN;
return SC_SUCCESS;
}

89 changes: 89 additions & 0 deletions src/libopensc/card-cac-common.h
@@ -0,0 +1,89 @@
/*
* card-cac-common.h: Code shared among CAC1 and CAC2 drivers
*
* Copyright (C) 2018, Red Hat, Inc.
*
* Author: Jakub Jelen <jjelen@redhat.com>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/

#ifndef HAVE_CARD_CAC_COMMON_H
#define HAVE_CARD_CAC_COMMON_H

#define CAC_MAX_SIZE 4096 /* arbitrary, just needs to be 'large enough' */

typedef struct cac_cuid {
u8 gsc_rid[5];
u8 manufacturer_id;
u8 card_type;
u8 card_id;
} cac_cuid_t;

/* data structures to store meta data about CAC objects */
typedef struct cac_object {
const char *name;
int fd;
sc_path_t path;
} cac_object_t;

/*
* CAC private data per card state
*/
typedef struct cac_private_data {
int object_type; /* select set this so we know how to read the file */
int cert_next; /* index number for the next certificate found in the list */
u8 *cache_buf; /* cached version of the currently selected file */
size_t cache_buf_len; /* length of the cached selected file */
int cached; /* is the cached selected file valid */
cac_cuid_t cuid; /* card unique ID from the CCC */
u8 *cac_id; /* card serial number */
size_t cac_id_len; /* card serial number len */
list_t pki_list; /* list of pki containers */
cac_object_t *pki_current; /* current pki object _ctl function */
list_t general_list; /* list of general containers */
cac_object_t *general_current; /* current object for _ctl function */
sc_path_t *aca_path; /* ACA path to be selected before pin verification */
} cac_private_data_t;

#define CAC_DATA(card) ((cac_private_data_t*)card->drv_data)

/*
* Set up the normal CAC paths
*/
#define CAC_1_RID "\xA0\x00\x00\x00\x79"
#define CAC_TO_AID(x) x, sizeof(x)-1


#define MAX_CAC_SLOTS 16 /* Maximum number of slots is 16 now */

/* template for a CAC pki object */
static const cac_object_t cac_cac_pki_obj = {
"CAC Certificate", 0x0, { { 0 }, 0, 0, 0, SC_PATH_TYPE_DF_NAME,
{ CAC_TO_AID(CAC_1_RID "\x01\x00") } }
};

/* template for emulated cuid */
static const cac_cuid_t cac_cac_cuid = {
{ 0xa0, 0x00, 0x00, 0x00, 0x79 },
2, 2, 0
};

cac_private_data_t *cac_new_private_data(void);
void cac_free_private_data(cac_private_data_t *priv);
int cac_add_object_to_list(list_t *list, const cac_object_t *object);
const char *get_cac_label(int index);

#endif /* HAVE_CARD_CAC_COMMON_H */

0 comments on commit 90fbc57

Please sign in to comment.