Merge pull request #1914 from marschap/PGPtool-fixes

PGPtool fixes
This commit is contained in:
Frank Morgner 2020-02-01 22:27:58 +01:00 committed by GitHub
commit 7e0465370f
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 259 additions and 191 deletions

View File

@ -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"' \

View File

@ -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);

View File

@ -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

View File

@ -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);