commit
7e0465370f
|
@ -12,7 +12,8 @@ noinst_HEADERS = cards.h ctbcs.h internal.h muscle.h muscle-filesystem.h \
|
|||
errors.h types.h compression.h itacns.h iso7816.h \
|
||||
authentic.h iasecc.h iasecc-sdo.h sm.h card-sc-hsm.h \
|
||||
pace.h cwa14890.h cwa-dnie.h card-gids.h aux-data.h \
|
||||
jpki.h sc-ossl-compat.h card-npa.h ccid-types.h reader-tr03119.h \
|
||||
jpki.h sc-ossl-compat.h card-npa.h card-openpgp.h \
|
||||
ccid-types.h reader-tr03119.h \
|
||||
card-cac-common.h
|
||||
|
||||
AM_CPPFLAGS = -D'OPENSC_CONF_PATH="$(sysconfdir)/opensc.conf"' \
|
||||
|
|
|
@ -52,11 +52,15 @@
|
|||
#include <openssl/sha.h>
|
||||
#endif /* ENABLE_OPENSSL */
|
||||
|
||||
#include "card-openpgp.h"
|
||||
|
||||
|
||||
static const char default_cardname[] = "OpenPGP card";
|
||||
static const char default_cardname_v1[] = "OpenPGP card v1.x";
|
||||
static const char default_cardname_v2[] = "OpenPGP card v2.x";
|
||||
static const char default_cardname_v3[] = "OpenPGP card v3.x";
|
||||
|
||||
|
||||
static const struct sc_atr_table pgp_atrs[] = {
|
||||
{ "3b:fa:13:00:ff:81:31:80:45:00:31:c1:73:c0:01:00:00:90:00:b1", NULL, default_cardname_v1, SC_CARD_TYPE_OPENPGP_V1, 0, NULL },
|
||||
{ "3b:da:18:ff:81:b1:fe:75:1f:03:00:31:c5:73:c0:01:40:00:90:00:0c", NULL, default_cardname_v2, SC_CARD_TYPE_OPENPGP_V2, 0, NULL },
|
||||
|
@ -72,6 +76,7 @@ static const struct sc_atr_table pgp_atrs[] = {
|
|||
{ NULL, NULL, NULL, 0, 0, NULL }
|
||||
};
|
||||
|
||||
|
||||
static struct sc_card_operations *iso_ops;
|
||||
static struct sc_card_operations pgp_ops;
|
||||
static struct sc_card_driver pgp_drv = {
|
||||
|
@ -81,84 +86,8 @@ static struct sc_card_driver pgp_drv = {
|
|||
NULL, 0, NULL
|
||||
};
|
||||
|
||||
/*
|
||||
* The OpenPGP card doesn't have a file system, instead everything
|
||||
* is stored in data objects that are accessed through GET/PUT.
|
||||
*
|
||||
* However, much inside OpenSC's pkcs15 implementation is based on
|
||||
* the assumption that we have a file system. So we fake one here.
|
||||
*
|
||||
* Selecting the MF causes us to select the OpenPGP AID.
|
||||
*
|
||||
* Everything else is mapped to "file" IDs.
|
||||
*/
|
||||
|
||||
enum _type { /* DO type */
|
||||
SIMPLE = SC_FILE_TYPE_WORKING_EF,
|
||||
CONSTRUCTED = SC_FILE_TYPE_DF
|
||||
};
|
||||
|
||||
enum _version { /* 2-byte BCD-alike encoded version number */
|
||||
OPENPGP_CARD_1_0 = 0x0100,
|
||||
OPENPGP_CARD_1_1 = 0x0101,
|
||||
OPENPGP_CARD_2_0 = 0x0200,
|
||||
OPENPGP_CARD_2_1 = 0x0201,
|
||||
OPENPGP_CARD_2_2 = 0x0202,
|
||||
OPENPGP_CARD_3_0 = 0x0300,
|
||||
OPENPGP_CARD_3_1 = 0x0301,
|
||||
OPENPGP_CARD_3_2 = 0x0302,
|
||||
OPENPGP_CARD_3_3 = 0x0303,
|
||||
OPENPGP_CARD_3_4 = 0x0304,
|
||||
};
|
||||
|
||||
enum _access { /* access flags for the respective DO/file */
|
||||
READ_NEVER = 0x0010,
|
||||
READ_PIN1 = 0x0011,
|
||||
READ_PIN2 = 0x0012,
|
||||
READ_PIN3 = 0x0014,
|
||||
READ_ALWAYS = 0x0018,
|
||||
READ_MASK = 0x00FF,
|
||||
WRITE_NEVER = 0x1000,
|
||||
WRITE_PIN1 = 0x1100,
|
||||
WRITE_PIN2 = 0x1200,
|
||||
WRITE_PIN3 = 0x1400,
|
||||
WRITE_ALWAYS = 0x1800,
|
||||
WRITE_MASK = 0x1F00
|
||||
};
|
||||
|
||||
enum _ext_caps { /* extended capabilities/features: bit flags */
|
||||
EXT_CAP_ALG_ATTR_CHANGEABLE = 0x0004,
|
||||
EXT_CAP_PRIVATE_DO = 0x0008,
|
||||
EXT_CAP_C4_CHANGEABLE = 0x0010,
|
||||
EXT_CAP_KEY_IMPORT = 0x0020,
|
||||
EXT_CAP_GET_CHALLENGE = 0x0040,
|
||||
EXT_CAP_SM = 0x0080,
|
||||
EXT_CAP_LCS = 0x0100,
|
||||
EXT_CAP_CHAINING = 0x1000,
|
||||
EXT_CAP_APDU_EXT = 0x2000,
|
||||
EXT_CAP_MSE = 0x4000
|
||||
};
|
||||
|
||||
enum _card_state {
|
||||
CARD_STATE_UNKNOWN = 0x00,
|
||||
CARD_STATE_INITIALIZATION = 0x03,
|
||||
CARD_STATE_ACTIVATED = 0x05
|
||||
};
|
||||
|
||||
enum _sm_algo {
|
||||
SM_ALGO_NONE = 0, /* SM not supported */
|
||||
SM_ALGO_AES128 = 1,
|
||||
SM_ALGO_AES256 = 2,
|
||||
SM_ALGO_SCP11b = 3,
|
||||
SM_ALGO_3DES = 256, /* 2.x: coded as 0 in DO C0 */
|
||||
SM_ALGO_UNKNOWN = 257 /* 3.x: coded as 0 in DO C0 */
|
||||
};
|
||||
|
||||
static struct pgp_supported_ec_curves {
|
||||
struct sc_object_id oid;
|
||||
size_t size;
|
||||
struct sc_object_id oid_binary;
|
||||
} ec_curves[] = {
|
||||
static pgp_ec_curves_t ec_curves[] = {
|
||||
{{{1, 2, 840, 10045, 3, 1, 7, -1}}, 256,
|
||||
{{0x2a, 0x86, 0x48, 0xce, 0x3d, 0x03, 0x01, 0x07, -1}}}, /* ansiX9p256r1 */
|
||||
{{{1, 3, 132, 0, 34, -1}}, 384,
|
||||
|
@ -174,11 +103,7 @@ static struct pgp_supported_ec_curves {
|
|||
{{{-1}}, 0, {{0x0}}} /* This entry must not be touched. */
|
||||
};
|
||||
|
||||
static struct pgp_supported_ec_curves_gnuk {
|
||||
struct sc_object_id oid;
|
||||
size_t size;
|
||||
struct sc_object_id oid_binary;
|
||||
} ec_curves_gnuk[] = {
|
||||
static pgp_ec_curves_t ec_curves_gnuk[] = {
|
||||
{{{1, 2, 840, 10045, 3, 1, 7, -1}}, 256,
|
||||
{{0x2a, 0x86, 0x48, 0xce, 0x3d, 0x03, 0x01, 0x07, -1}}}, /* ansiX9p256r1 */
|
||||
{{{1, 3, 132, 0, 10, -1}}, 256,
|
||||
|
@ -190,33 +115,18 @@ static struct pgp_supported_ec_curves_gnuk {
|
|||
{{{-1}}, 0, {{0x0}}} /* This entry must not be touched. */
|
||||
};
|
||||
|
||||
typedef struct pgp_blob {
|
||||
struct pgp_blob * next; /* pointer to next sibling */
|
||||
struct pgp_blob * parent; /* pointer to parent */
|
||||
struct do_info *info;
|
||||
|
||||
sc_file_t * file;
|
||||
unsigned int id;
|
||||
int status;
|
||||
|
||||
unsigned char * data;
|
||||
unsigned int len;
|
||||
struct pgp_blob * files; /* pointer to 1st child */
|
||||
} pgp_blob_t;
|
||||
|
||||
struct do_info {
|
||||
unsigned int id; /* ID of the DO in question */
|
||||
|
||||
enum _type type; /* constructed DO or not */
|
||||
enum _access access; /* R/W access levels for the DO */
|
||||
|
||||
/* function to get the DO from the card:
|
||||
* only != NULL is DO if readable and not only a part of a constructed DO */
|
||||
int (*get_fn)(sc_card_t *, unsigned int, u8 *, size_t);
|
||||
/* function to write the DO to the card:
|
||||
* only != NULL if DO is writeable under some conditions */
|
||||
int (*put_fn)(sc_card_t *, unsigned int, const u8 *, size_t);
|
||||
};
|
||||
/*
|
||||
* The OpenPGP card doesn't have a file system, instead everything
|
||||
* is stored in data objects that are accessed through GET/PUT.
|
||||
*
|
||||
* However, much inside OpenSC's pkcs15 implementation is based on
|
||||
* the assumption that we have a file system. So we fake one here.
|
||||
*
|
||||
* Selecting the MF causes us to select the OpenPGP AID.
|
||||
*
|
||||
* Everything else is mapped to "file" IDs.
|
||||
*/
|
||||
|
||||
static int pgp_get_card_features(sc_card_t *card);
|
||||
static int pgp_finish(sc_card_t *card);
|
||||
|
@ -224,50 +134,13 @@ static void pgp_iterate_blobs(pgp_blob_t *, int, void (*func)());
|
|||
|
||||
static int pgp_get_blob(sc_card_t *card, pgp_blob_t *blob,
|
||||
unsigned int id, pgp_blob_t **ret);
|
||||
static pgp_blob_t * pgp_new_blob(sc_card_t *, pgp_blob_t *, unsigned int, sc_file_t *);
|
||||
static pgp_blob_t *pgp_new_blob(sc_card_t *, pgp_blob_t *, unsigned int, sc_file_t *);
|
||||
static void pgp_free_blob(pgp_blob_t *);
|
||||
static int pgp_get_pubkey(sc_card_t *, unsigned int,
|
||||
u8 *, size_t);
|
||||
static int pgp_get_pubkey_pem(sc_card_t *, unsigned int,
|
||||
u8 *, size_t);
|
||||
|
||||
/* The DO holding X.509 certificate is constructed but does not contain a child DO.
|
||||
* We should notice this when building fake file system later. */
|
||||
#define DO_CERT 0x7f21
|
||||
/* Control Reference Template of private keys. Ref: Section 4.3.3.7 of OpenPGP card v2 spec.
|
||||
* Here we treat them as DOs just for convenience */
|
||||
#define DO_SIGN 0xb600
|
||||
#define DO_ENCR 0xb800
|
||||
#define DO_AUTH 0xa400
|
||||
/* These DOs do not exist. They are defined and used just for ease of implementation */
|
||||
#define DO_SIGN_SYM 0xb601
|
||||
#define DO_ENCR_SYM 0xb801
|
||||
#define DO_AUTH_SYM 0xa401
|
||||
/* Private DOs */
|
||||
#define DO_PRIV1 0x0101
|
||||
#define DO_PRIV2 0x0102
|
||||
#define DO_PRIV3 0x0103
|
||||
#define DO_PRIV4 0x0104
|
||||
/* Cardholder information DOs */
|
||||
#define DO_CARDHOLDER 0x65
|
||||
#define DO_NAME 0x5b
|
||||
#define DO_LANG_PREF 0x5f2d
|
||||
#define DO_SEX 0x5f35
|
||||
static int pgp_get_pubkey(sc_card_t *, unsigned int, u8 *, size_t);
|
||||
static int pgp_get_pubkey_pem(sc_card_t *, unsigned int, u8 *, size_t);
|
||||
|
||||
|
||||
/* Maximum length for response buffer when reading pubkey.
|
||||
* This value is calculated with 4096-bit key length */
|
||||
#define MAXLEN_RESP_PUBKEY 527
|
||||
/* Gnuk only supports 1 key length (2048 bit) */
|
||||
#define MAXLEN_RESP_PUBKEY_GNUK 271
|
||||
|
||||
/* Maximal size of a DO:
|
||||
* v2.0+: max. certificate size it at bytes 5-6 of Extended Capabilities DO 00C0
|
||||
* v3.0+: max. special DO size is at bytes 7-8 of Extended Capabilities DO 00C0
|
||||
* Theoretically we should have the 64k, but we currently limit to 8k. */
|
||||
#define MAX_OPENPGP_DO_SIZE 8192
|
||||
|
||||
static struct do_info pgp1x_objects[] = { /* OpenPGP card spec 1.1 */
|
||||
static pgp_do_info_t pgp1x_objects[] = { /* OpenPGP card spec 1.1 */
|
||||
{ 0x004f, SIMPLE, READ_ALWAYS | WRITE_NEVER, NULL, NULL },
|
||||
{ 0x005b, SIMPLE, READ_ALWAYS | WRITE_PIN3, NULL, sc_put_data },
|
||||
{ 0x005e, SIMPLE, READ_ALWAYS | WRITE_PIN3, sc_get_data, sc_put_data },
|
||||
|
@ -316,7 +189,7 @@ static struct do_info pgp1x_objects[] = { /* OpenPGP card spec 1.1 */
|
|||
{ 0, 0, 0, NULL, NULL },
|
||||
};
|
||||
|
||||
static struct do_info pgp34_objects[] = { /**** OpenPGP card spec 3.4 ****/
|
||||
static pgp_do_info_t pgp34_objects[] = { /**** OpenPGP card spec 3.4 ****/
|
||||
{ 0x00d9, SIMPLE, READ_ALWAYS | WRITE_PIN3, NULL, sc_put_data },
|
||||
{ 0x00da, SIMPLE, READ_ALWAYS | WRITE_PIN3, NULL, sc_put_data },
|
||||
{ 0x00db, SIMPLE, READ_ALWAYS | WRITE_PIN3, NULL, sc_put_data },
|
||||
|
@ -400,31 +273,10 @@ static struct do_info pgp34_objects[] = { /**** OpenPGP card spec 3.4 ****/
|
|||
{ 0, 0, 0, NULL, NULL },
|
||||
};
|
||||
|
||||
static struct do_info *pgp33_objects = pgp34_objects + 9;
|
||||
static struct do_info *pgp30_objects = pgp34_objects + 10;
|
||||
static struct do_info *pgp21_objects = pgp34_objects + 15;
|
||||
static struct do_info *pgp20_objects = pgp34_objects + 16;
|
||||
|
||||
|
||||
#define DRVDATA(card) ((struct pgp_priv_data *) ((card)->drv_data))
|
||||
|
||||
struct pgp_priv_data {
|
||||
pgp_blob_t *mf;
|
||||
pgp_blob_t *current; /* currently selected file */
|
||||
|
||||
enum _version bcd_version;
|
||||
struct do_info *pgp_objects;
|
||||
|
||||
enum _card_state state; /* card state */
|
||||
enum _ext_caps ext_caps; /* extended capabilities */
|
||||
|
||||
enum _sm_algo sm_algo; /* Secure Messaging algorithm */
|
||||
|
||||
size_t max_challenge_size;
|
||||
size_t max_cert_size;
|
||||
|
||||
sc_security_env_t sec_env;
|
||||
};
|
||||
static pgp_do_info_t *pgp33_objects = pgp34_objects + 9;
|
||||
static pgp_do_info_t *pgp30_objects = pgp34_objects + 10;
|
||||
static pgp_do_info_t *pgp21_objects = pgp34_objects + 15;
|
||||
static pgp_do_info_t *pgp20_objects = pgp34_objects + 16;
|
||||
|
||||
|
||||
/**
|
||||
|
@ -445,8 +297,6 @@ get_full_pgp_aid(sc_card_t *card, sc_file_t *file)
|
|||
}
|
||||
|
||||
|
||||
#define BCD2UCHAR(x) (((((x) & 0xF0) >> 4) * 10) + ((x) & 0x0F))
|
||||
|
||||
/**
|
||||
* ABI: check if card's ATR matches one of driver's
|
||||
* or if the OpenPGP application is present on the card.
|
||||
|
@ -515,7 +365,7 @@ pgp_init(sc_card_t *card)
|
|||
struct pgp_priv_data *priv;
|
||||
sc_path_t path;
|
||||
sc_file_t *file = NULL;
|
||||
struct do_info *info;
|
||||
pgp_do_info_t *info;
|
||||
int r, i;
|
||||
|
||||
LOG_FUNC_CALLED(card->ctx);
|
||||
|
@ -838,6 +688,9 @@ pgp_get_card_features(sc_card_t *card)
|
|||
card->caps |= SC_CARD_CAP_ISO7816_PIN_INFO;
|
||||
}
|
||||
|
||||
/* v1.1 & v2.x: special DOs are limited to 254 bytes */
|
||||
priv->max_specialDO_size = 254;
|
||||
|
||||
if ((pgp_get_blob(card, priv->mf, 0x006e, &blob6e) >= 0) &&
|
||||
(pgp_get_blob(card, blob6e, 0x0073, &blob73) >= 0)) {
|
||||
|
||||
|
@ -888,6 +741,9 @@ pgp_get_card_features(sc_card_t *card)
|
|||
priv->sm_algo = blob->data[1];
|
||||
if ((priv->sm_algo == SM_ALGO_NONE) && (priv->ext_caps & EXT_CAP_SM))
|
||||
priv->sm_algo = SM_ALGO_UNKNOWN;
|
||||
|
||||
/* v3.0+: max. size of special DOs is at bytes 7-8 */
|
||||
priv->max_specialDO_size = bebytes2ushort(blob->data + 6);
|
||||
}
|
||||
if (priv->bcd_version >= OPENPGP_CARD_3_3 && (blob->len >= 10)) {
|
||||
/* v3.3+: MSE for key numbers 2(DEC) and 3(AUT) supported */
|
||||
|
@ -1019,7 +875,7 @@ pgp_set_blob(pgp_blob_t *blob, const u8 *data, size_t len)
|
|||
* The Access Control is derived from the DO access permission.
|
||||
**/
|
||||
static void
|
||||
pgp_attach_acl(sc_card_t *card, sc_file_t *file, struct do_info *info)
|
||||
pgp_attach_acl(sc_card_t *card, sc_file_t *file, pgp_do_info_t *info)
|
||||
{
|
||||
unsigned int method = SC_AC_NONE;
|
||||
unsigned long key_ref = SC_AC_KEY_REF_NONE;
|
||||
|
@ -1096,7 +952,7 @@ pgp_new_blob(sc_card_t *card, pgp_blob_t *parent, unsigned int file_id,
|
|||
|
||||
if ((blob = calloc(1, sizeof(pgp_blob_t))) != NULL) {
|
||||
struct pgp_priv_data *priv = DRVDATA(card);
|
||||
struct do_info *info;
|
||||
pgp_do_info_t *info;
|
||||
|
||||
blob->file = file;
|
||||
|
||||
|
@ -1406,11 +1262,11 @@ pgp_find_blob(sc_card_t *card, unsigned int tag)
|
|||
/**
|
||||
* Internal: get info for a specific tag.
|
||||
*/
|
||||
static struct do_info *
|
||||
static pgp_do_info_t *
|
||||
pgp_get_info_by_tag(sc_card_t *card, unsigned int tag)
|
||||
{
|
||||
struct pgp_priv_data *priv = DRVDATA(card);
|
||||
struct do_info *info;
|
||||
pgp_do_info_t *info;
|
||||
|
||||
for (info = priv->pgp_objects; (info != NULL) && (info->id > 0); info++)
|
||||
if (tag == info->id)
|
||||
|
@ -1876,7 +1732,7 @@ pgp_put_data(sc_card_t *card, unsigned int tag, const u8 *buf, size_t buf_len)
|
|||
{
|
||||
struct pgp_priv_data *priv = DRVDATA(card);
|
||||
pgp_blob_t *affected_blob = NULL;
|
||||
struct do_info *dinfo = NULL;
|
||||
pgp_do_info_t *dinfo = NULL;
|
||||
int r;
|
||||
|
||||
LOG_FUNC_CALLED(card->ctx);
|
||||
|
|
|
@ -0,0 +1,193 @@
|
|||
/*
|
||||
* card-openpgp.h: Support for OpenPGP card
|
||||
*
|
||||
* Copyright (C) 2020 Peter Marschall <peter@adpm.de>
|
||||
*
|
||||
* 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 _CARD_OPENPGP_H
|
||||
#define _CARD_OPENPGP_H
|
||||
|
||||
/*
|
||||
* The OpenPGP card doesn't have a file system, instead everything
|
||||
* is stored in data objects that are accessed through GET/PUT.
|
||||
*
|
||||
* However, much inside OpenSC's pkcs15 implementation is based on
|
||||
* the assumption that we have a file system. So we fake one here.
|
||||
*
|
||||
* Selecting the MF causes us to select the OpenPGP AID.
|
||||
*
|
||||
* Everything else is mapped to "file" IDs.
|
||||
*/
|
||||
|
||||
typedef enum _pgp_do_type { /* DO type */
|
||||
SIMPLE = SC_FILE_TYPE_WORKING_EF,
|
||||
CONSTRUCTED = SC_FILE_TYPE_DF
|
||||
} pgp_do_type_t;
|
||||
|
||||
typedef enum _pgp_version { /* 2-byte BCD-alike encoded version number */
|
||||
OPENPGP_CARD_1_0 = 0x0100,
|
||||
OPENPGP_CARD_1_1 = 0x0101,
|
||||
OPENPGP_CARD_2_0 = 0x0200,
|
||||
OPENPGP_CARD_2_1 = 0x0201,
|
||||
OPENPGP_CARD_2_2 = 0x0202,
|
||||
OPENPGP_CARD_3_0 = 0x0300,
|
||||
OPENPGP_CARD_3_1 = 0x0301,
|
||||
OPENPGP_CARD_3_2 = 0x0302,
|
||||
OPENPGP_CARD_3_3 = 0x0303,
|
||||
OPENPGP_CARD_3_4 = 0x0304,
|
||||
} pgp_version_t;
|
||||
|
||||
typedef enum _pgp_access { /* access flags for the respective DO/file */
|
||||
READ_NEVER = 0x0010,
|
||||
READ_PIN1 = 0x0011,
|
||||
READ_PIN2 = 0x0012,
|
||||
READ_PIN3 = 0x0014,
|
||||
READ_ALWAYS = 0x0018,
|
||||
READ_MASK = 0x00FF,
|
||||
WRITE_NEVER = 0x1000,
|
||||
WRITE_PIN1 = 0x1100,
|
||||
WRITE_PIN2 = 0x1200,
|
||||
WRITE_PIN3 = 0x1400,
|
||||
WRITE_ALWAYS = 0x1800,
|
||||
WRITE_MASK = 0x1F00
|
||||
} pgp_access_t;
|
||||
|
||||
typedef enum _pgp_ext_caps { /* extended capabilities/features: bit flags */
|
||||
EXT_CAP_ALG_ATTR_CHANGEABLE = 0x0004,
|
||||
EXT_CAP_PRIVATE_DO = 0x0008,
|
||||
EXT_CAP_C4_CHANGEABLE = 0x0010,
|
||||
EXT_CAP_KEY_IMPORT = 0x0020,
|
||||
EXT_CAP_GET_CHALLENGE = 0x0040,
|
||||
EXT_CAP_SM = 0x0080,
|
||||
EXT_CAP_LCS = 0x0100,
|
||||
EXT_CAP_CHAINING = 0x1000,
|
||||
EXT_CAP_APDU_EXT = 0x2000,
|
||||
EXT_CAP_MSE = 0x4000
|
||||
} pgp_ext_caps_t;
|
||||
|
||||
typedef enum _pgp_card_state {
|
||||
CARD_STATE_UNKNOWN = 0x00,
|
||||
CARD_STATE_INITIALIZATION = 0x03,
|
||||
CARD_STATE_ACTIVATED = 0x05
|
||||
} pgp_card_state_t;
|
||||
|
||||
typedef enum _pgp_sm_algo {
|
||||
SM_ALGO_NONE = 0, /* SM not supported */
|
||||
SM_ALGO_AES128 = 1,
|
||||
SM_ALGO_AES256 = 2,
|
||||
SM_ALGO_SCP11b = 3,
|
||||
SM_ALGO_3DES = 256, /* 2.x: coded as 0 in DO C0 */
|
||||
SM_ALGO_UNKNOWN = 257 /* 3.x: coded as 0 in DO C0 */
|
||||
} pgp_sm_algo_t;
|
||||
|
||||
typedef struct _pgp_do_info {
|
||||
unsigned int id; /* ID of the DO in question */
|
||||
|
||||
pgp_do_type_t type; /* constructed DO or not */
|
||||
pgp_access_t access; /* R/W access levels for the DO */
|
||||
|
||||
/* function to get the DO from the card:
|
||||
* only != NULL is DO if readable and not only a part of a constructed DO */
|
||||
int (*get_fn)(sc_card_t *, unsigned int, u8 *, size_t);
|
||||
/* function to write the DO to the card:
|
||||
* only != NULL if DO is writeable under some conditions */
|
||||
int (*put_fn)(sc_card_t *, unsigned int, const u8 *, size_t);
|
||||
} pgp_do_info_t;
|
||||
|
||||
typedef struct pgp_blob {
|
||||
struct pgp_blob *next; /* pointer to next sibling */
|
||||
struct pgp_blob *parent; /* pointer to parent */
|
||||
pgp_do_info_t *info;
|
||||
|
||||
sc_file_t *file;
|
||||
unsigned int id;
|
||||
int status;
|
||||
|
||||
unsigned char *data;
|
||||
unsigned int len;
|
||||
struct pgp_blob *files; /* pointer to 1st child */
|
||||
} pgp_blob_t;
|
||||
|
||||
|
||||
/* The DO holding X.509 certificate is constructed but does not contain a child DO.
|
||||
* We should notice this when building fake file system later. */
|
||||
#define DO_CERT 0x7f21
|
||||
/* Control Reference Template of private keys. Ref: Section 4.3.3.7 of OpenPGP card v2 spec.
|
||||
* Here we treat them as DOs just for convenience */
|
||||
#define DO_SIGN 0xb600
|
||||
#define DO_ENCR 0xb800
|
||||
#define DO_AUTH 0xa400
|
||||
/* These DOs do not exist. They are defined and used just for ease of implementation */
|
||||
#define DO_SIGN_SYM 0xb601
|
||||
#define DO_ENCR_SYM 0xb801
|
||||
#define DO_AUTH_SYM 0xa401
|
||||
/* Private DOs */
|
||||
#define DO_PRIV1 0x0101
|
||||
#define DO_PRIV2 0x0102
|
||||
#define DO_PRIV3 0x0103
|
||||
#define DO_PRIV4 0x0104
|
||||
/* Cardholder information DOs */
|
||||
#define DO_CARDHOLDER 0x65
|
||||
#define DO_NAME 0x5b
|
||||
#define DO_LANG_PREF 0x5f2d
|
||||
#define DO_SEX 0x5f35
|
||||
|
||||
|
||||
/* Maximum length for response buffer when reading pubkey.
|
||||
* This value is calculated with 4096-bit key length */
|
||||
#define MAXLEN_RESP_PUBKEY 527
|
||||
/* Gnuk only supports 1 key length (2048 bit) */
|
||||
#define MAXLEN_RESP_PUBKEY_GNUK 271
|
||||
|
||||
/* Maximal size of a DO:
|
||||
* v2.0+: max. certificate size it at bytes 5-6 of Extended Capabilities DO 00C0
|
||||
* v3.0+: max. special DO size is at bytes 7-8 of Extended Capabilities DO 00C0
|
||||
* Theoretically we should have the 64k, but we currently limit to 8k. */
|
||||
#define MAX_OPENPGP_DO_SIZE 8192
|
||||
|
||||
|
||||
typedef struct _pgp_ec_curves {
|
||||
struct sc_object_id oid;
|
||||
size_t size;
|
||||
struct sc_object_id oid_binary;
|
||||
} pgp_ec_curves_t;
|
||||
|
||||
|
||||
#define DRVDATA(card) ((struct pgp_priv_data *) ((card)->drv_data))
|
||||
|
||||
struct pgp_priv_data {
|
||||
pgp_blob_t *mf;
|
||||
pgp_blob_t *current; /* currently selected file */
|
||||
|
||||
pgp_version_t bcd_version;
|
||||
pgp_do_info_t *pgp_objects;
|
||||
|
||||
pgp_card_state_t state; /* card state */
|
||||
pgp_ext_caps_t ext_caps; /* extended capabilities */
|
||||
|
||||
pgp_sm_algo_t sm_algo; /* Secure Messaging algorithm */
|
||||
|
||||
size_t max_challenge_size;
|
||||
size_t max_cert_size;
|
||||
size_t max_specialDO_size;
|
||||
|
||||
sc_security_env_t sec_env;
|
||||
};
|
||||
|
||||
#define BCD2UCHAR(x) (((((x) & 0xF0) >> 4) * 10) + ((x) & 0x0F))
|
||||
|
||||
#endif
|
|
@ -1,7 +1,7 @@
|
|||
/*
|
||||
* openpgp-tool.c: OpenPGP card utility
|
||||
*
|
||||
* Copyright (C) 2012 Peter Marschall <peter@adpm.de>
|
||||
* Copyright (C) 2012-2020 Peter Marschall <peter@adpm.de>
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
|
@ -47,6 +47,7 @@
|
|||
#include "libopensc/errors.h"
|
||||
#include "util.h"
|
||||
#include "libopensc/log.h"
|
||||
#include "libopensc/card-openpgp.h"
|
||||
|
||||
#define OPT_RAW 256
|
||||
#define OPT_PRETTY 257
|
||||
|
@ -194,7 +195,7 @@ static void show_version(void)
|
|||
fprintf(stderr,
|
||||
"openpgp-tool - OpenPGP card utility version " PACKAGE_VERSION "\n"
|
||||
"\n"
|
||||
"Copyright (c) 2012-18 Peter Marschall <peter@adpm.de>\n"
|
||||
"Copyright (c) 2012-2020 Peter Marschall <peter@adpm.de>\n"
|
||||
"Licensed under LGPL v2\n");
|
||||
}
|
||||
|
||||
|
@ -611,19 +612,25 @@ static int do_info(sc_card_t *card, const struct ef_name_map *map)
|
|||
|
||||
static int do_dump_do(sc_card_t *card, unsigned int tag)
|
||||
{
|
||||
struct pgp_priv_data *priv = DRVDATA(card);
|
||||
int r;
|
||||
size_t length;
|
||||
unsigned char buffer[254]; // Private DO are specified up to 254 bytes
|
||||
|
||||
memset(buffer, '\0', sizeof(buffer));
|
||||
unsigned char *buffer;
|
||||
|
||||
if (tag < 0x101 || tag > 0x104) {
|
||||
util_error("illegal DO identifier %04X", tag);
|
||||
return SC_ERROR_INVALID_ARGUMENTS;
|
||||
}
|
||||
|
||||
r = sc_get_data(card, tag, buffer, sizeof(buffer));
|
||||
buffer = calloc(priv->max_specialDO_size, sizeof(unsigned char));
|
||||
if (buffer == NULL) {
|
||||
util_error("error allocating memory for DO %04X", tag);
|
||||
return SC_ERROR_OUT_OF_MEMORY;
|
||||
}
|
||||
|
||||
r = sc_get_data(card, tag, buffer, priv->max_specialDO_size);
|
||||
if (r < 0) {
|
||||
free(buffer);
|
||||
util_error("failed to get data object DO %04X: %s", tag, sc_strerror(r));
|
||||
if (SC_ERROR_SECURITY_STATUS_NOT_SATISFIED == r) {
|
||||
util_error("make sure the 'verify' and 'pin' parameters are correct");
|
||||
|
@ -655,12 +662,15 @@ static int do_dump_do(sc_card_t *card, unsigned int tag)
|
|||
clearerr(stdout);
|
||||
close(tmp);
|
||||
|
||||
if (length != (size_t) r) /* fail on write errors */
|
||||
if (length != (size_t) r) { /* fail on write errors */
|
||||
free(buffer);
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
} else {
|
||||
util_hex_dump_asc(stdout, buffer, length, -1);
|
||||
}
|
||||
|
||||
free(buffer);
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
|
||||
|
@ -878,6 +888,14 @@ int main(int argc, char **argv)
|
|||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
/* force OpenPGP card driver */
|
||||
r = sc_set_card_driver(ctx, "openpgp");
|
||||
if (r) {
|
||||
sc_release_context(ctx);
|
||||
util_fatal("OpenPGP card driver not found!\n");
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
r = util_connect_card(ctx, &card, opt_reader, opt_wait, verbose);
|
||||
if (r) {
|
||||
sc_release_context(ctx);
|
||||
|
|
Loading…
Reference in New Issue