add OpenSC package

OpenSC is a smart card middleware.
Patches for support of the GnuK USB token have been added.

Signed-off-by: Daniel Golle <daniel@makrotopia.org>
This commit is contained in:
Daniel Golle 2014-06-16 14:16:59 +02:00
parent 264e3a4365
commit 54a8a2a6b9
19 changed files with 1868 additions and 0 deletions

224
utils/opensc/Makefile Normal file
View File

@ -0,0 +1,224 @@
#
# Copyright (C) 2011-2014 OpenWrt.org
#
# This is free software, licensed under the GNU General Public License v2.
# See /LICENSE for more information.
#
include $(TOPDIR)/rules.mk
PKG_NAME:=opensc
PKG_VERSION:=20140317
PKG_RELEASE:=1
PKG_MAINTAINER:=Daniel Golle <daniel@makrotopia.org>
PKG_RELEASE=$(PKG_SOURCE_VERSION)
PKG_SOURCE_PROTO:=git
PKG_SOURCE_URL:=https://github.com/OpenSC/OpenSC.git
PKG_SOURCE_SUBDIR:=$(PKG_NAME)-$(PKG_VERSION)
PKG_SOURCE_VERSION:=de6d61405b271e22244376e4817e16b49018e1ce
PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz
PKG_BUILD_DEPENDS:=+libpcsclite
PKG_FIXUP:=libtool
PKG_INSTALL:=1
include $(INCLUDE_DIR)/package.mk
define Package/libopensc
SECTION:=libs
CATEGORY:=Libraries
TITLE:=OpenSC libraries for smart cards
URL:=https://www.opensc-project.org/opensc/wiki/
DEPENDS:=+libopenssl +libpthread
MENU:=1
endef
define Package/libopensc/description
OpenSC provides a set of libraries and utilities to work with smart cards.
Its main focus is on cards that support cryptographic operations, and
facilitate their use in security applications such as authentication,
mail encryption and digital signatures.
endef
define Package/libopensc-pkcs11
SECTION:=libs
CATEGORY:=Libraries
TITLE:=OpenSC - PKCS11 provider
URL:=https://www.opensc-project.org/opensc/wiki/
DEPENDS:=libopensc
endef
define Package/libopensc-pkcs11/description
OpenSC PKCS#11 provider
endef
define Package/libpkcs11-spy
SECTION:=libs
CATEGORY:=Libraries
TITLE:=PKCS11 spying wrapper
URL:=https://www.opensc-project.org/opensc/wiki/
endef
define Package/libpkcs11-spy/dscription
PKCS#11 spying wrapper
endef
define Package/opensc-utils
SECTION:=utils
CATEGORY:=Utilities
TITLE:=OpenSC - tools for smart cards
URL:=https://www.opensc-project.org/opensc/wiki/
DEPENDS:=+libopensc
MENU:=1
endef
define Package/opensc-utils/description
OpenSC utilities
endef
define ToolGen
define Package/opensc-utils-$(subst _,-,$(firstword $(subst :, ,$(1))))
TITLE:=$(firstword $(subst :, ,$(1))) utility from opensc
URL:=https://www.opensc-project.org/opensc/wiki/
SECTION:=utils
CATEGORY:=Utilities
DEPENDS:=opensc-utils $(wordlist 2,$(words $(subst :, ,$(1))),$(subst :, ,$(1)))
endef
endef
define ProfileGen
define Package/libopensc-profile-$(subst _,-,$(firstword $(subst :, ,$(1))))
TITLE:=$(firstword $(subst :, ,$(1))) card profile for opensc
URL:=https://www.opensc-project.org/opensc/wiki/
SECTION:=lib
CATEGORY:=Libraries
DEPENDS:=libopensc
endef
endef
TOOLS:= \
cardos-tool \
cryptoflex-tool \
dnie-tool \
eidenv \
iasecc-tool \
netkey-tool \
openpgp-tool \
opensc-tool \
opensc-explorer:+libncurses:+libreadline \
piv-tool \
pkcs11-tool \
pkcs15-crypt \
pkcs15-init \
pkcs15-tool \
sc-hsm-tool \
westcos-tool
PROFILES:= \
asepcos \
authentic \
cardos \
cyberflex \
entersafe \
epass2003 \
flex \
gpk \
ias_adele_admin1 \
ias_adele_admin2 \
ias_adele_common \
iasecc_admin_eid \
iasecc_generic_oberthur \
iasecc_generic_pki \
iasecc \
incrypto34 \
jcop \
miocos \
muscle \
myeid \
oberthur \
openpgp \
pkcs15 \
rutoken_ecp \
rutoken \
sc-hsm \
setcos \
starcos \
westcos
$(foreach file,$(TOOLS),$(eval $(call ToolGen,$(file))))
$(foreach file,$(PROFILES),$(eval $(call ProfileGen,$(file))))
define Build/InstallDev
$(INSTALL_DIR) $(1)/usr/lib
$(CP) $(PKG_INSTALL_DIR)/usr/lib/libopensc.{a,so}* $(1)/usr/lib/
$(CP) $(PKG_INSTALL_DIR)/usr/lib/libsmm-local.{a,so}* $(1)/usr/lib/
$(CP) $(PKG_INSTALL_DIR)/usr/lib/opensc-pkcs11.so $(1)/usr/lib/
$(CP) $(PKG_INSTALL_DIR)/usr/lib/pkcs11-spy.so $(1)/usr/lib/
$(INSTALL_DIR) $(1)/usr/lib/pkcs11
$(LN) ../pkcs11-spy.so $(1)/usr/lib/pkcs11/
$(LN) ../opensc-pkcs11.so $(1)/usr/lib/pkcs11/
$(INSTALL_DIR) $(1)/usr/share/opensc
$(CP) $(PKG_INSTALL_DIR)/usr/share/opensc/* $(1)/usr/share/opensc/
endef
define Package/libopensc/install
$(INSTALL_DIR) $(1)/usr/lib
$(CP) $(PKG_INSTALL_DIR)/usr/lib/libopensc.so* $(1)/usr/lib/
$(CP) $(PKG_INSTALL_DIR)/usr/lib/libsmm-local.so* $(1)/usr/lib/
$(INSTALL_DIR) $(1)/etc
$(CP) $(PKG_INSTALL_DIR)/etc/opensc.conf $(1)/etc/
endef
define Package/libopensc-pkcs11/install
$(INSTALL_DIR) $(1)/usr/lib
$(CP) $(PKG_INSTALL_DIR)/usr/lib/opensc-pkcs11.so $(1)/usr/lib/
$(INSTALL_DIR) $(1)/usr/lib/pkcs11
$(LN) ../opensc-pkcs11.so $(1)/usr/lib/pkcs11/
endef
define Package/libpkcs11-spy/install
$(INSTALL_DIR) $(1)/usr/lib
$(CP) $(PKG_INSTALL_DIR)/usr/lib/pkcs11-spy.so $(1)/usr/lib/
$(INSTALL_DIR) $(1)/usr/lib/pkcs11
$(LN) ../pkcs11-spy.so $(1)/usr/lib/pkcs11/
endef
define Package/opensc-card-profiles
$(INSTALL_DIR) $(1)/usr/share/opensc
$(CP) $(PKG_INSTALL_DIR)/usr/share/opensc/* $(1)/usr/share/opensc/
endef
define Package/opensc-utils/install
true
endef
define ToolInstall
define Package/opensc-utils-$(subst _,-,$(firstword $(subst :, ,$(1))))/install
$(INSTALL_DIR) $$(1)/usr/bin
$(INSTALL_BIN) \
$(PKG_INSTALL_DIR)/usr/bin/$(firstword $(subst :, ,$(1))) \
$$(1)/usr/bin/
endef
endef
define ProfileInstall
define Package/libopensc-profile-$(subst _,-,$(firstword $(subst :, ,$(1))))/install
$(INSTALL_DIR) $$(1)/usr/share/opensc
$(INSTALL_BIN) \
$(PKG_INSTALL_DIR)/usr/share/opensc/$(firstword $(subst :, ,$(1))).profile \
$$(1)/usr/share/opensc
endef
endef
$(foreach file,$(TOOLS),$(eval $(call ToolInstall,$(file))))
$(foreach file,$(PROFILES),$(eval $(call ProfileInstall,$(file))))
$(eval $(call BuildPackage,libopensc))
$(eval $(call BuildPackage,libopensc-pkcs11))
$(eval $(call BuildPackage,libpkcs11-spy))
$(eval $(call BuildPackage,opensc-utils))
$(foreach file,$(TOOLS),$(eval $(call BuildPackage,opensc-utils-$(subst _,-,$(firstword $(subst :, ,$(file)))))))
$(foreach file,$(PROFILES),$(eval $(call BuildPackage,libopensc-profile-$(subst _,-,$(firstword $(subst :, ,$(file)))))))

View File

@ -0,0 +1,267 @@
From c706491fc9b08d4cc6d7b254cf936d6b8d8691bc Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Nguy=E1=BB=85n=20H=E1=BB=93ng=20Qu=C3=A2n?=
<ng.hong.quan@gmail.com>
Date: Wed, 20 Feb 2013 11:54:30 +0700
Subject: [PATCH 01/18] OpenPGP: Detect and support Gnuk Token.
http://www.fsij.org/gnuk/
---
src/libopensc/card-openpgp.c | 61 ++++++++++++++++++++++++++++++++++----------
src/libopensc/cards.h | 1 +
src/tools/openpgp-tool.c | 9 +++++--
3 files changed, 56 insertions(+), 15 deletions(-)
diff --git a/src/libopensc/card-openpgp.c b/src/libopensc/card-openpgp.c
index 743e79c..716052b 100644
--- a/src/libopensc/card-openpgp.c
+++ b/src/libopensc/card-openpgp.c
@@ -43,6 +43,7 @@
static 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, "OpenPGP card v1.0/1.1", 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, "CryptoStick v1.2 (OpenPGP v2.0)", SC_CARD_TYPE_OPENPGP_V2, 0, NULL },
+ { "3b:da:11:ff:81:b1:fe:55:1f:03:00:31:84:73:80:01:80:00:90:00:e4", NULL, "Gnuk v1.0.x (OpenPGP v2.0)", SC_CARD_TYPE_OPENPGP_GNUK, 0, NULL },
{ NULL, NULL, NULL, 0, 0, NULL }
};
@@ -307,6 +308,8 @@ pgp_init(sc_card_t *card)
int r;
struct blob *child = NULL;
+ LOG_FUNC_CALLED(card->ctx);
+
priv = calloc (1, sizeof *priv);
if (!priv)
return SC_ERROR_OUT_OF_MEMORY;
@@ -315,11 +318,11 @@ pgp_init(sc_card_t *card)
card->cla = 0x00;
/* set pointer to correct list of card objects */
- priv->pgp_objects = (card->type == SC_CARD_TYPE_OPENPGP_V2)
+ priv->pgp_objects = (card->type == SC_CARD_TYPE_OPENPGP_V2 || card->type == SC_CARD_TYPE_OPENPGP_GNUK)
? pgp2_objects : pgp1_objects;
/* set detailed card version */
- priv->bcd_version = (card->type == SC_CARD_TYPE_OPENPGP_V2)
+ priv->bcd_version = (card->type == SC_CARD_TYPE_OPENPGP_V2 || card->type == SC_CARD_TYPE_OPENPGP_GNUK)
? OPENPGP_CARD_2_0 : OPENPGP_CARD_1_1;
/* select application "OpenPGP" */
@@ -428,7 +431,8 @@ pgp_get_card_features(sc_card_t *card)
if ((pgp_get_blob(card, blob73, 0x00c0, &blob) >= 0) &&
(blob->data != NULL) && (blob->len > 0)) {
/* in v2.0 bit 0x04 in first byte means "algorithm attributes changeable */
- if ((blob->data[0] & 0x04) && (card->type == SC_CARD_TYPE_OPENPGP_V2))
+ if ((blob->data[0] & 0x04) &&
+ (card->type == SC_CARD_TYPE_OPENPGP_V2 || card->type == SC_CARD_TYPE_OPENPGP_GNUK))
priv->ext_caps |= EXT_CAP_ALG_ATTR_CHANGEABLE;
/* bit 0x08 in first byte means "support for private use DOs" */
if (blob->data[0] & 0x08)
@@ -445,7 +449,8 @@ pgp_get_card_features(sc_card_t *card)
priv->ext_caps |= EXT_CAP_GET_CHALLENGE;
}
/* in v2.0 bit 0x80 in first byte means "support Secure Messaging" */
- if ((blob->data[0] & 0x80) && (card->type == SC_CARD_TYPE_OPENPGP_V2))
+ if ((blob->data[0] & 0x80) &&
+ (card->type == SC_CARD_TYPE_OPENPGP_V2 || card->type == SC_CARD_TYPE_OPENPGP_GNUK))
priv->ext_caps |= EXT_CAP_SM;
if ((priv->bcd_version >= OPENPGP_CARD_2_0) && (blob->len >= 10)) {
@@ -1055,12 +1060,18 @@ static int
pgp_get_pubkey(sc_card_t *card, unsigned int tag, u8 *buf, size_t buf_len)
{
sc_apdu_t apdu;
+ u8 apdu_case = SC_APDU_CASE_4;
u8 idbuf[2];
int r;
sc_log(card->ctx, "called, tag=%04x\n", tag);
- sc_format_apdu(card, &apdu, SC_APDU_CASE_4, 0x47, 0x81, 0);
+ /* With Gnuk token, force to use short APDU */
+ if (card->type == SC_CARD_TYPE_OPENPGP_GNUK) {
+ apdu_case = SC_APDU_CASE_4_SHORT;
+ }
+
+ sc_format_apdu(card, &apdu, apdu_case, 0x47, 0x81, 0);
apdu.lc = 2;
apdu.data = ushort2bebytes(idbuf, tag);
apdu.datalen = 2;
@@ -1152,6 +1163,7 @@ pgp_put_data(sc_card_t *card, unsigned int tag, const u8 *buf, size_t buf_len)
u8 ins = 0xDA;
u8 p1 = tag >> 8;
u8 p2 = tag & 0xFF;
+ u8 apdu_case = SC_APDU_CASE_3;
int r;
LOG_FUNC_CALLED(card->ctx);
@@ -1193,13 +1205,17 @@ pgp_put_data(sc_card_t *card, unsigned int tag, const u8 *buf, size_t buf_len)
/* Build APDU */
if (buf != NULL && buf_len > 0) {
- sc_format_apdu(card, &apdu, SC_APDU_CASE_3, ins, p1, p2);
+ /* Force short APDU for Gnuk */
+ if (card->type == SC_CARD_TYPE_OPENPGP_GNUK) {
+ apdu_case = SC_APDU_CASE_3_SHORT;
+ }
+ sc_format_apdu(card, &apdu, apdu_case, ins, p1, p2);
/* if card/reader does not support extended APDUs, but chaining, then set it */
if (((card->caps & SC_CARD_CAP_APDU_EXT) == 0) && (priv->ext_caps & EXT_CAP_CHAINING))
apdu.flags |= SC_APDU_FLAGS_CHAINING;
- apdu.data = buf;
+ apdu.data = (u8 *)buf;
apdu.datalen = buf_len;
apdu.lc = buf_len;
}
@@ -1326,6 +1342,7 @@ pgp_compute_signature(sc_card_t *card, const u8 *data,
struct pgp_priv_data *priv = DRVDATA(card);
sc_security_env_t *env = &priv->sec_env;
sc_apdu_t apdu;
+ u8 apdu_case = SC_APDU_CASE_4;
int r;
LOG_FUNC_CALLED(card->ctx);
@@ -1334,14 +1351,19 @@ pgp_compute_signature(sc_card_t *card, const u8 *data,
LOG_TEST_RET(card->ctx, SC_ERROR_INVALID_ARGUMENTS,
"invalid operation");
+ /* Force short APDU for Gnuk Token */
+ if (card->type == SC_CARD_TYPE_OPENPGP_GNUK) {
+ apdu_case = SC_APDU_CASE_4_SHORT;
+ }
+
switch (env->key_ref[0]) {
case 0x00: /* signature key */
/* PSO SIGNATURE */
- sc_format_apdu(card, &apdu, SC_APDU_CASE_4, 0x2A, 0x9E, 0x9A);
+ sc_format_apdu(card, &apdu, apdu_case, 0x2A, 0x9E, 0x9A);
break;
case 0x02: /* authentication key */
/* INTERNAL AUTHENTICATE */
- sc_format_apdu(card, &apdu, SC_APDU_CASE_4, 0x88, 0, 0);
+ sc_format_apdu(card, &apdu, apdu_case, 0x88, 0, 0);
break;
case 0x01:
default:
@@ -1350,7 +1372,7 @@ pgp_compute_signature(sc_card_t *card, const u8 *data,
}
apdu.lc = data_len;
- apdu.data = data;
+ apdu.data = (u8 *)data;
apdu.datalen = data_len;
apdu.le = ((outlen >= 256) && !(card->caps & SC_CARD_CAP_APDU_EXT)) ? 256 : outlen;
apdu.resp = out;
@@ -1374,6 +1396,7 @@ pgp_decipher(sc_card_t *card, const u8 *in, size_t inlen,
struct pgp_priv_data *priv = DRVDATA(card);
sc_security_env_t *env = &priv->sec_env;
sc_apdu_t apdu;
+ u8 apdu_case = SC_APDU_CASE_4;
u8 *temp = NULL;
int r;
@@ -1398,7 +1421,7 @@ pgp_decipher(sc_card_t *card, const u8 *in, size_t inlen,
case 0x01: /* Decryption key */
case 0x02: /* authentication key */
/* PSO DECIPHER */
- sc_format_apdu(card, &apdu, SC_APDU_CASE_4, 0x2A, 0x80, 0x86);
+ sc_format_apdu(card, &apdu, apdu_case, 0x2A, 0x80, 0x86);
break;
case 0x00: /* signature key */
default:
@@ -1407,8 +1430,13 @@ pgp_decipher(sc_card_t *card, const u8 *in, size_t inlen,
"invalid key reference");
}
+ /* Gnuk only supports short APDU, so we need to use command chaining */
+ if (card->type == SC_CARD_TYPE_OPENPGP_GNUK) {
+ apdu.flags |= SC_APDU_FLAGS_CHAINING;
+ }
+
apdu.lc = inlen;
- apdu.data = in;
+ apdu.data = (u8 *)in;
apdu.datalen = inlen;
apdu.le = ((outlen >= 256) && !(card->caps & SC_CARD_CAP_APDU_EXT)) ? 256 : outlen;
apdu.resp = out;
@@ -1794,6 +1822,11 @@ static int pgp_gen_key(sc_card_t *card, sc_cardctl_openpgp_keygen_info_t *key_in
LOG_FUNC_RETURN(card->ctx, SC_ERROR_INVALID_ARGUMENTS);
}
+ if (card->type == SC_CARD_TYPE_OPENPGP_GNUK && key_info->modulus_len != 2048) {
+ sc_log(card->ctx, "Gnuk does not support other key length than 2048.");
+ LOG_FUNC_RETURN(card->ctx, SC_ERROR_INVALID_ARGUMENTS);
+ }
+
/* Set attributes for new-generated key */
r = pgp_update_new_algo_attr(card, key_info);
LOG_TEST_RET(card->ctx, r, "Cannot set attributes for new-generated key");
@@ -1801,7 +1834,9 @@ static int pgp_gen_key(sc_card_t *card, sc_cardctl_openpgp_keygen_info_t *key_in
/* Test whether we will need extended APDU. 1900 is an
* arbitrary modulus length which for sure fits into a short APDU.
* This idea is borrowed from GnuPG code. */
- if (card->caps & SC_CARD_CAP_APDU_EXT && key_info->modulus_len > 1900) {
+ if (card->caps & SC_CARD_CAP_APDU_EXT
+ && key_info->modulus_len > 1900
+ && card->type != SC_CARD_TYPE_OPENPGP_GNUK) {
/* We won't store to apdu variable yet, because it will be reset in
* sc_format_apdu() */
apdu_le = card->max_recv_size;
diff --git a/src/libopensc/cards.h b/src/libopensc/cards.h
index 0fbf9ca..01b08fd 100644
--- a/src/libopensc/cards.h
+++ b/src/libopensc/cards.h
@@ -104,6 +104,7 @@ enum {
SC_CARD_TYPE_OPENPGP_BASE = 9000,
SC_CARD_TYPE_OPENPGP_V1,
SC_CARD_TYPE_OPENPGP_V2,
+ SC_CARD_TYPE_OPENPGP_GNUK,
/* jcop driver */
SC_CARD_TYPE_JCOP_BASE = 10000,
diff --git a/src/tools/openpgp-tool.c b/src/tools/openpgp-tool.c
index 7058aaa..8b5e327 100644
--- a/src/tools/openpgp-tool.c
+++ b/src/tools/openpgp-tool.c
@@ -32,6 +32,7 @@
#include "libopensc/asn1.h"
#include "libopensc/cards.h"
#include "libopensc/cardctl.h"
+#include "libopensc/log.h"
#include "util.h"
#define OPT_RAW 256
@@ -216,7 +217,7 @@ static void display_data(const struct ef_name_map *mapping, char *value)
} else {
const char *label = mapping->name;
- printf("%s:%*s%s\n", label, 10-strlen(label), "", value);
+ printf("%s:%*s%s\n", label, 10 - (int)strlen(label), "", value);
}
}
}
@@ -390,6 +391,8 @@ int do_genkey(sc_card_t *card, u8 key_id, unsigned int key_len)
sc_path_t path;
sc_file_t *file;
+ LOG_FUNC_CALLED(card->ctx);
+
if (key_id < 1 || key_id > 3) {
printf("Unknown key ID %d.\n", key_id);
return 1;
@@ -481,8 +484,10 @@ int main(int argc, char **argv)
/* check card type */
if ((card->type != SC_CARD_TYPE_OPENPGP_V1) &&
- (card->type != SC_CARD_TYPE_OPENPGP_V2)) {
+ (card->type != SC_CARD_TYPE_OPENPGP_V2) &&
+ (card->type != SC_CARD_TYPE_OPENPGP_GNUK)) {
util_error("not an OpenPGP card");
+ sc_log(card->ctx, "Card type %X", card->type);
exit_status = EXIT_FAILURE;
goto out;
}
--
1.9.3

View File

@ -0,0 +1,50 @@
From ecc6460d17147b37def27a9b776e1fc5a61408d0 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Nguy=E1=BB=85n=20H=E1=BB=93ng=20Qu=C3=A2n?=
<ng.hong.quan@gmail.com>
Date: Fri, 12 Apr 2013 17:24:00 +0700
Subject: [PATCH 02/18] OpenPGP: Add Gnuk in pkcs15 emulation layer.
---
src/libopensc/pkcs15-openpgp.c | 6 ++++--
src/libopensc/pkcs15-syn.c | 1 +
2 files changed, 5 insertions(+), 2 deletions(-)
diff --git a/src/libopensc/pkcs15-openpgp.c b/src/libopensc/pkcs15-openpgp.c
index d9dc074..5a8a1ca 100644
--- a/src/libopensc/pkcs15-openpgp.c
+++ b/src/libopensc/pkcs15-openpgp.c
@@ -155,7 +155,8 @@ sc_pkcs15emu_openpgp_init(sc_pkcs15_card_t *p15card)
u8 c4data[10];
u8 c5data[70];
int r, i;
- const pgp_pin_cfg_t *pin_cfg = (card->type == SC_CARD_TYPE_OPENPGP_V2) ? pin_cfg_v2 : pin_cfg_v1;
+ const pgp_pin_cfg_t *pin_cfg = (card->type == SC_CARD_TYPE_OPENPGP_V2 || card->type == SC_CARD_TYPE_OPENPGP_GNUK)
+ ? pin_cfg_v2 : pin_cfg_v1;
sc_path_t path;
sc_file_t *file;
@@ -367,7 +368,8 @@ failed: sc_debug(card->ctx, SC_LOG_DEBUG_NORMAL, "Failed to initialize OpenPGP e
static int openpgp_detect_card(sc_pkcs15_card_t *p15card)
{
- if (p15card->card->type == SC_CARD_TYPE_OPENPGP_V1 || p15card->card->type == SC_CARD_TYPE_OPENPGP_V2)
+ if (p15card->card->type == SC_CARD_TYPE_OPENPGP_V1 || p15card->card->type == SC_CARD_TYPE_OPENPGP_V2
+ || p15card->card->type == SC_CARD_TYPE_OPENPGP_GNUK)
return SC_SUCCESS;
else
return SC_ERROR_WRONG_CARD;
diff --git a/src/libopensc/pkcs15-syn.c b/src/libopensc/pkcs15-syn.c
index e2f6004..a9f8c0b 100644
--- a/src/libopensc/pkcs15-syn.c
+++ b/src/libopensc/pkcs15-syn.c
@@ -112,6 +112,7 @@ int sc_pkcs15_is_emulation_only(sc_card_t *card)
case SC_CARD_TYPE_GEMSAFEV1_PTEID:
case SC_CARD_TYPE_OPENPGP_V1:
case SC_CARD_TYPE_OPENPGP_V2:
+ case SC_CARD_TYPE_OPENPGP_GNUK:
case SC_CARD_TYPE_SC_HSM:
return 1;
default:
--
1.9.3

View File

@ -0,0 +1,30 @@
From 5f751ba5628f9d85e9d8dca9939a93f49d2525d0 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Nguy=E1=BB=85n=20H=E1=BB=93ng=20Qu=C3=A2n?=
<ng.hong.quan@gmail.com>
Date: Fri, 22 Mar 2013 17:37:16 +0700
Subject: [PATCH 03/18] OpenPGP: Include private DO to filesystem at driver
initialization.
In old implementation, the DOs which their access is restricted by
PIN (like DOs 0101 -> 0104) were excluded from the fake filesystem,
leading to that we cannot read their data later, even if we verified PIN.
---
src/libopensc/card-openpgp.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/libopensc/card-openpgp.c b/src/libopensc/card-openpgp.c
index 716052b..ead07ae 100644
--- a/src/libopensc/card-openpgp.c
+++ b/src/libopensc/card-openpgp.c
@@ -357,7 +357,7 @@ pgp_init(sc_card_t *card)
/* Populate MF - add matching blobs listed in the pgp_objects table. */
for (info = priv->pgp_objects; (info != NULL) && (info->id > 0); info++) {
- if (((info->access & READ_MASK) == READ_ALWAYS) &&
+ if (((info->access & READ_MASK) != READ_NEVER) &&
(info->get_fn != NULL)) {
child = pgp_new_blob(card, priv->mf, info->id, sc_file_new());
--
1.9.3

View File

@ -0,0 +1,82 @@
From fbf8e392db4456de97796259a62ccb972fe24df8 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Nguy=E1=BB=85n=20H=E1=BB=93ng=20Qu=C3=A2n?=
<ng.hong.quan@gmail.com>
Date: Tue, 26 Feb 2013 17:37:16 +0700
Subject: [PATCH 04/18] PKCS15-OpenPGP: Declare DATA objects.
Begin to support read/write DATA object for PKCS-OpenPGP binding.
This object is used by TrueCrypt.
---
src/libopensc/pkcs15-openpgp.c | 35 +++++++++++++++++++++++++++++++++++
1 file changed, 35 insertions(+)
diff --git a/src/libopensc/pkcs15-openpgp.c b/src/libopensc/pkcs15-openpgp.c
index 5a8a1ca..9f239ef 100644
--- a/src/libopensc/pkcs15-openpgp.c
+++ b/src/libopensc/pkcs15-openpgp.c
@@ -36,6 +36,7 @@ typedef USHORT ushort;
#endif
int sc_pkcs15emu_openpgp_init_ex(sc_pkcs15_card_t *, sc_pkcs15emu_opt_t *);
+static int sc_pkcs15emu_openpgp_add_data(sc_pkcs15_card_t *);
#define PGP_USER_PIN_FLAGS (SC_PKCS15_PIN_FLAG_CASE_SENSITIVE \
@@ -45,6 +46,8 @@ int sc_pkcs15emu_openpgp_init_ex(sc_pkcs15_card_t *, sc_pkcs15emu_opt_t *);
| SC_PKCS15_PIN_FLAG_UNBLOCK_DISABLED \
| SC_PKCS15_PIN_FLAG_SO_PIN)
+#define PGP_NUM_PRIVDO 4
+
typedef struct _pgp_pin_cfg {
const char *label;
int reference;
@@ -359,6 +362,9 @@ sc_pkcs15emu_openpgp_init(sc_pkcs15_card_t *p15card)
goto failed;
}
+ /* PKCS#15 DATA object from OpenPGP private DOs */
+ r = sc_pkcs15emu_openpgp_add_data(p15card);
+
return 0;
failed: sc_debug(card->ctx, SC_LOG_DEBUG_NORMAL, "Failed to initialize OpenPGP emulation: %s\n",
@@ -366,6 +372,35 @@ failed: sc_debug(card->ctx, SC_LOG_DEBUG_NORMAL, "Failed to initialize OpenPGP e
return r;
}
+static int
+sc_pkcs15emu_openpgp_add_data(sc_pkcs15_card_t *p15card)
+{
+ sc_context_t *ctx = p15card->card->ctx;
+ int i, r;
+
+ LOG_FUNC_CALLED(ctx);
+ /* There is 4 private DO from 0101 to 0104 */
+ for (i = 1; i <= PGP_NUM_PRIVDO; i++) {
+ sc_pkcs15_data_info_t dat_info;
+ sc_pkcs15_object_t dat_obj;
+ char name[8];
+ char path[9];
+ memset(&dat_info, 0, sizeof(dat_info));
+ memset(&dat_obj, 0, sizeof(dat_obj));
+
+ sprintf(name, "PrivDO%d", i);
+ sprintf(path, "3F00010%d", i);
+
+ sc_format_path(path, &dat_info.path);
+ strlcpy(dat_obj.label, name, sizeof(dat_obj.label));
+ strlcpy(dat_info.app_label, name, sizeof(dat_info.app_label));
+
+ sc_log(ctx, "Add %s data object", name);
+ r = sc_pkcs15emu_add_data_object(p15card, &dat_obj, &dat_info);
+ }
+ LOG_FUNC_RETURN(ctx, r);
+}
+
static int openpgp_detect_card(sc_pkcs15_card_t *p15card)
{
if (p15card->card->type == SC_CARD_TYPE_OPENPGP_V1 || p15card->card->type == SC_CARD_TYPE_OPENPGP_V2
--
1.9.3

View File

@ -0,0 +1,173 @@
From 4cdc5f3102f5ad93d263eea2f8206bb5e9fffc6c Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Nguy=E1=BB=85n=20H=E1=BB=93ng=20Qu=C3=A2n?=
<ng.hong.quan@gmail.com>
Date: Mon, 4 Mar 2013 11:28:08 +0700
Subject: [PATCH 05/18] OpenPGP: Support erasing (reset) card.
Command: openpgp-tool --erase
---
src/libopensc/card-openpgp.c | 64 ++++++++++++++++++++++++++++++++++++++++++++
src/tools/openpgp-tool.c | 23 +++++++++++++++-
2 files changed, 86 insertions(+), 1 deletion(-)
diff --git a/src/libopensc/card-openpgp.c b/src/libopensc/card-openpgp.c
index ead07ae..42a9684 100644
--- a/src/libopensc/card-openpgp.c
+++ b/src/libopensc/card-openpgp.c
@@ -2197,6 +2197,66 @@ out:
#endif /* ENABLE_OPENSSL */
+/**
+ * Erase card
+ **/
+static int pgp_erase_card(sc_card_t *card)
+{
+ sc_context_t *ctx = card->ctx;
+ u8 *apdustring[10] = {
+ "00:20:00:81:08:40:40:40:40:40:40:40:40",
+ "00:20:00:81:08:40:40:40:40:40:40:40:40",
+ "00:20:00:81:08:40:40:40:40:40:40:40:40",
+ "00:20:00:81:08:40:40:40:40:40:40:40:40",
+ "00:20:00:83:08:40:40:40:40:40:40:40:40",
+ "00:20:00:83:08:40:40:40:40:40:40:40:40",
+ "00:20:00:83:08:40:40:40:40:40:40:40:40",
+ "00:20:00:83:08:40:40:40:40:40:40:40:40",
+ "00:e6:00:00",
+ "00:44:00:00"
+ };
+ u8 buf[SC_MAX_APDU_BUFFER_SIZE];
+ u8 rbuf[SC_MAX_APDU_BUFFER_SIZE];
+ sc_apdu_t apdu;
+ size_t len0;
+ int commandsnum = 10;
+ int i, r;
+
+ LOG_FUNC_CALLED(ctx);
+
+ /* Check card version */
+ if (card->type != SC_CARD_TYPE_OPENPGP_V2) {
+ sc_log(ctx, "Card is not OpenPGP v2");
+ LOG_FUNC_RETURN(ctx, SC_ERROR_NO_CARD_SUPPORT);
+ }
+ sc_log(ctx, "Card is OpenPGP v2. Erase card.");
+
+ /* Iterate over 10 commands above */
+ for (i = 0; i < commandsnum; i++) {
+ /* Convert the string to binary array */
+ len0 = sizeof(buf);
+ sc_hex_to_bin(apdustring[i], buf, &len0);
+ printf("Sending: ");
+ for (r = 0; r < len0; r++)
+ printf("%02X ", buf[r]);
+ printf("\n");
+
+ /* Build APDU from binary array */
+ r = sc_bytes2apdu(card->ctx, buf, len0, &apdu);
+ if (r) {
+ sc_log(ctx, "Failed to build APDU");
+ LOG_FUNC_RETURN(ctx, SC_ERROR_INTERNAL);
+ }
+ apdu.resp = rbuf;
+ apdu.resplen = sizeof(rbuf);
+
+ /* Send APDU to card */
+ r = sc_transmit_apdu(card, &apdu);
+ LOG_TEST_RET(ctx, r, "Transmiting APDU failed");
+ }
+ LOG_FUNC_RETURN(ctx, r);
+}
+
/* ABI: card ctl: perform special card-specific operations */
static int pgp_card_ctl(sc_card_t *card, unsigned long cmd, void *ptr)
{
@@ -2221,6 +2281,10 @@ static int pgp_card_ctl(sc_card_t *card, unsigned long cmd, void *ptr)
LOG_FUNC_RETURN(card->ctx, r);
break;
#endif /* ENABLE_OPENSSL */
+ case SC_CARDCTL_ERASE_CARD:
+ r = pgp_erase_card(card);
+ LOG_FUNC_RETURN(card->ctx, r);
+ break;
}
LOG_FUNC_RETURN(card->ctx, SC_ERROR_NOT_SUPPORTED);
diff --git a/src/tools/openpgp-tool.c b/src/tools/openpgp-tool.c
index 8b5e327..0d360a3 100644
--- a/src/tools/openpgp-tool.c
+++ b/src/tools/openpgp-tool.c
@@ -76,6 +76,7 @@ static int opt_verify = 0;
static char *verifytype = NULL;
static int opt_pin = 0;
static char *pin = NULL;
+static int opt_erase = 0;
static const char *app_name = "openpgp-tool";
@@ -92,6 +93,7 @@ static const struct option options[] = {
{ "help", no_argument, NULL, 'h' },
{ "verbose", no_argument, NULL, 'v' },
{ "version", no_argument, NULL, 'V' },
+ { "erase", no_argument, NULL, 'E' },
{ "verify", required_argument, NULL, OPT_VERIFY },
{ "pin", required_argument, NULL, OPT_PIN },
{ NULL, 0, NULL, 0 }
@@ -110,6 +112,7 @@ static const char *option_help[] = {
/* h */ "Print this help message",
/* v */ "Verbose operation. Use several times to enable debug output.",
/* V */ "Show version number",
+/* E */ "Erase (reset) the card",
"Verify PIN (CHV1, CHV2, CHV3...)",
"PIN string"
};
@@ -228,7 +231,7 @@ static int decode_options(int argc, char **argv)
{
int c;
- while ((c = getopt_long(argc, argv,"r:x:CUG:L:hwvV", options, (int *) 0)) != EOF) {
+ while ((c = getopt_long(argc, argv,"r:x:CUG:L:hwvVE", options, (int *) 0)) != EOF) {
switch (c) {
case 'r':
opt_reader = optarg;
@@ -288,6 +291,9 @@ static int decode_options(int argc, char **argv)
show_version();
exit(EXIT_SUCCESS);
break;
+ case 'E':
+ opt_erase++;
+ break;
default:
util_print_usage_and_die(app_name, options, option_help, NULL);
}
@@ -446,6 +452,18 @@ int do_verify(sc_card_t *card, u8 *type, u8* pin)
return r;
}
+int do_erase(sc_card_t *card)
+{
+ int r;
+ /* Check card version */
+ if (card->type != SC_CARD_TYPE_OPENPGP_V2) {
+ printf("Do not erase card which is not OpenPGP v2\n");
+ }
+ printf("Erase card\n");
+ r = sc_card_ctl(card, SC_CARDCTL_ERASE_CARD, NULL);
+ return r;
+}
+
int main(int argc, char **argv)
{
sc_context_t *ctx = NULL;
@@ -521,6 +539,9 @@ int main(int argc, char **argv)
exit(EXIT_FAILURE);
}
+ if (opt_erase)
+ exit_status != do_erase(card);
+
out:
sc_unlock(card);
sc_disconnect_card(card);
--
1.9.3

View File

@ -0,0 +1,210 @@
From bbbedd3b358f80a7f98df2b22cf541cb007dd62e Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Nguy=E1=BB=85n=20H=E1=BB=93ng=20Qu=C3=A2n?=
<ng.hong.quan@gmail.com>
Date: Mon, 4 Mar 2013 18:13:03 +0700
Subject: [PATCH 06/18] openpgp-tool: Support deleting key in Gnuk.
---
src/tools/openpgp-tool.c | 144 ++++++++++++++++++++++++++++++++++++++++++++++-
1 file changed, 143 insertions(+), 1 deletion(-)
diff --git a/src/tools/openpgp-tool.c b/src/tools/openpgp-tool.c
index 0d360a3..239c86b 100644
--- a/src/tools/openpgp-tool.c
+++ b/src/tools/openpgp-tool.c
@@ -39,6 +39,7 @@
#define OPT_PRETTY 257
#define OPT_VERIFY 258
#define OPT_PIN 259
+#define OPT_DELKEY 260
/* define structures */
struct ef_name_map {
@@ -77,6 +78,7 @@ static char *verifytype = NULL;
static int opt_pin = 0;
static char *pin = NULL;
static int opt_erase = 0;
+static int opt_delkey = 0;
static const char *app_name = "openpgp-tool";
@@ -96,6 +98,7 @@ static const struct option options[] = {
{ "erase", no_argument, NULL, 'E' },
{ "verify", required_argument, NULL, OPT_VERIFY },
{ "pin", required_argument, NULL, OPT_PIN },
+ { "del-key", required_argument, NULL, OPT_DELKEY },
{ NULL, 0, NULL, 0 }
};
@@ -114,7 +117,8 @@ static const char *option_help[] = {
/* V */ "Show version number",
/* E */ "Erase (reset) the card",
"Verify PIN (CHV1, CHV2, CHV3...)",
- "PIN string"
+ "PIN string",
+ "Delete key (1, 2, 3 or all)"
};
static const struct ef_name_map openpgp_data[] = {
@@ -294,6 +298,14 @@ static int decode_options(int argc, char **argv)
case 'E':
opt_erase++;
break;
+ case OPT_DELKEY:
+ opt_delkey++;
+ if (strcmp(optarg, "all") != 0) /* Arg string is not 'all' */
+ key_id = optarg[0] - '0';
+ else /* Arg string is 'all' */
+ key_id = 'a';
+ actions++;
+ break;
default:
util_print_usage_and_die(app_name, options, option_help, NULL);
}
@@ -452,6 +464,133 @@ int do_verify(sc_card_t *card, u8 *type, u8* pin)
return r;
}
+/**
+ * Delete key, for Gnuk.
+ **/
+int delete_key_gnuk(sc_card_t *card, u8 key_id)
+{
+ sc_context_t *ctx = card->ctx;
+ int r = SC_SUCCESS;
+ u8 *data = NULL;
+
+ /* Delete fingerprint */
+ sc_log(ctx, "Delete fingerprints");
+ r |= sc_put_data(card, 0xC6 + key_id, NULL, 0);
+ /* Delete creation time */
+ sc_log(ctx, "Delete creation time");
+ r |= sc_put_data(card, 0xCD + key_id, NULL, 0);
+
+ /* Rewrite Extended Header List */
+ sc_log(ctx, "Rewrite Extended Header List");
+
+ if (key_id == 1)
+ data = "\x4D\x02\xB6";
+ else if (key_id == 2)
+ data = "\x4D\x02\xB8";
+ else if (key_id == 3)
+ data = "\x4D\x02\xA4";
+ else
+ return SC_ERROR_INVALID_ARGUMENTS;
+
+ r |= sc_put_data(card, 0x4D, data, strlen(data) + 1);
+ return r;
+}
+
+/**
+ * Delete key, for OpenPGP card.
+ * This function is not complete and is reserved for future version (> 2) of OpenPGP card.
+ **/
+int delete_key_openpgp(sc_card_t *card, u8 key_id)
+{
+ sc_context_t *ctx = card->ctx;
+ char *del_fingerprint = "00:DA:00:C6:14:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00";
+ char *del_creationtime = "00:DA:00:CD:04:00:00:00:00";
+ /* We need to replace the 4th byte later */
+ char *apdustring = NULL;
+ u8 buf[SC_MAX_APDU_BUFFER_SIZE];
+ u8 rbuf[SC_MAX_APDU_BUFFER_SIZE];
+ sc_apdu_t apdu;
+ size_t len0;
+ int i;
+ int r = SC_SUCCESS;
+
+ for (i = 0; i < 2; i++) {
+ if (i == 0) /* Reset fingerprint */
+ apdustring = del_fingerprint;
+ else /* Reset creation time */
+ apdustring = del_creationtime;
+ /* Convert the string to binary array */
+ len0 = sizeof(buf);
+ sc_hex_to_bin(apdustring, buf, &len0);
+
+ /* Replace DO tag, subject to key ID */
+ buf[3] = buf[3] + key_id;
+
+ /* Build APDU from binary array */
+ r = sc_bytes2apdu(card->ctx, buf, len0, &apdu);
+ if (r) {
+ sc_log(ctx, "Failed to build APDU");
+ LOG_FUNC_RETURN(ctx, SC_ERROR_INTERNAL);
+ }
+ apdu.resp = rbuf;
+ apdu.resplen = sizeof(rbuf);
+
+ /* Send APDU to card */
+ r = sc_transmit_apdu(card, &apdu);
+ LOG_TEST_RET(ctx, r, "Transmiting APDU failed");
+ }
+ /* TODO: Rewrite Extended Header List.
+ * Not support by OpenGPG v2 yet */
+ LOG_FUNC_RETURN(ctx, r);
+}
+
+int delete_key(sc_card_t *card, u8 key_id)
+{
+ sc_context_t *ctx = card->ctx;
+ int r;
+
+ LOG_FUNC_CALLED(ctx);
+ /* Check key ID */
+ if (key_id < 1 || key_id > 3) {
+ sc_log(ctx, "Invalid key ID %d", key_id);
+ LOG_FUNC_RETURN(ctx, SC_ERROR_INVALID_ARGUMENTS);
+ }
+
+ if (card->type == SC_CARD_TYPE_OPENPGP_GNUK)
+ r = delete_key_gnuk(card, key_id);
+ else
+ r = delete_key_openpgp(card, key_id);
+
+ LOG_FUNC_RETURN(ctx, r);
+}
+
+int do_delete_key(sc_card_t *card, u8 key_id)
+{
+ sc_context_t *ctx = card->ctx;
+ int r = SC_SUCCESS;
+
+ /* Currently, only Gnuk supports deleting keys */
+ if (card->type != SC_CARD_TYPE_OPENPGP_GNUK) {
+ printf("Only Gnuk supports deleting keys. General OpenPGP doesn't.");
+ return SC_ERROR_NOT_SUPPORTED;
+ }
+
+ if (key_id < 1 || (key_id > 3 && key_id != 'a')) {
+ printf("Error: Invalid key id %d", key_id);
+ return SC_ERROR_INVALID_ARGUMENTS;
+ }
+ if (key_id == 1 || key_id == 'a') {
+ r |= delete_key(card, 1);
+ }
+ if (key_id == 2 || key_id == 'a') {
+ r |= delete_key(card, 2);
+ }
+ if (key_id == 3 || key_id == 'a') {
+ r |= delete_key(card, 3);
+ }
+ return r;
+}
+
int do_erase(sc_card_t *card)
{
int r;
@@ -539,6 +678,9 @@ int main(int argc, char **argv)
exit(EXIT_FAILURE);
}
+ if (opt_delkey)
+ exit_status != do_delete_key(card, key_id);
+
if (opt_erase)
exit_status != do_erase(card);
--
1.9.3

View File

@ -0,0 +1,27 @@
From b6bc7a497e1fe20104f923de1092a35d137ba553 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Nguy=E1=BB=85n=20H=E1=BB=93ng=20Qu=C3=A2n?=
<ng.hong.quan@gmail.com>
Date: Mon, 4 Mar 2013 18:14:51 +0700
Subject: [PATCH 07/18] OpenPGP: Correct building Extended Header List when
importing keys.
---
src/libopensc/card-openpgp.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/libopensc/card-openpgp.c b/src/libopensc/card-openpgp.c
index 42a9684..47c1938 100644
--- a/src/libopensc/card-openpgp.c
+++ b/src/libopensc/card-openpgp.c
@@ -1978,7 +1978,7 @@ pgp_build_extended_header_list(sc_card_t *card, sc_cardctl_openpgp_keystore_info
u8 *p = NULL;
u8 *components[] = {key_info->e, key_info->p, key_info->q, key_info->n};
size_t componentlens[] = {key_info->e_len, key_info->p_len, key_info->q_len, key_info->n_len};
- unsigned int componenttags[] = {0x91, 0x92, 0x93, 0x95};
+ unsigned int componenttags[] = {0x91, 0x92, 0x93, 0x97};
char *componentnames[] = {
"public exponent",
"prime p",
--
1.9.3

View File

@ -0,0 +1,58 @@
From d1b8d3588336abac4876c1d537d8e8e5e578bc02 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Nguy=E1=BB=85n=20H=E1=BB=93ng=20Qu=C3=A2n?=
<ng.hong.quan@gmail.com>
Date: Mon, 25 Mar 2013 11:58:38 +0700
Subject: [PATCH 08/18] OpenPGP: Read some empty DOs from Gnuk.
In Gnuk, some empty DOs are returned as not exist, instead of existing with empty value.
So, we will consider them exist in driver.
---
src/libopensc/card-openpgp.c | 25 +++++++++++++++++++++++++
1 file changed, 25 insertions(+)
diff --git a/src/libopensc/card-openpgp.c b/src/libopensc/card-openpgp.c
index 47c1938..9b08bbb 100644
--- a/src/libopensc/card-openpgp.c
+++ b/src/libopensc/card-openpgp.c
@@ -813,6 +813,23 @@ pgp_get_blob(sc_card_t *card, struct blob *blob, unsigned int id,
}
}
+ /* This part is for "NOT FOUND" cases */
+
+ /* Special case:
+ * Gnuk does not have default value for children of DO 65 (DOs 5B, 5F2D, 5F35)
+ * So, if these blob was not found, we create it. */
+ if (blob->id == 0x65 && (id == 0x5B || id == 0x5F2D || id == 0x5F35)) {
+ sc_log(card->ctx, "Create blob %X under %X", id, blob->id);
+ child = pgp_new_blob(card, blob, id, sc_file_new());
+ if (child) {
+ pgp_set_blob(child, NULL, 0);
+ *ret = child;
+ return SC_SUCCESS;
+ }
+ else
+ sc_log(card->ctx, "Not enough memory to create blob for DO %X");
+ }
+
return SC_ERROR_FILE_NOT_FOUND;
}
@@ -1147,6 +1164,14 @@ pgp_get_data(sc_card_t *card, unsigned int tag, u8 *buf, size_t buf_len)
LOG_TEST_RET(card->ctx, r, "APDU transmit failed");
r = sc_check_sw(card, apdu.sw1, apdu.sw2);
+
+ /* For Gnuk card, if there is no certificate, it returns error instead of empty data.
+ * So, for this case, we ignore error and consider success */
+ if (r == SC_ERROR_DATA_OBJECT_NOT_FOUND && card->type == SC_CARD_TYPE_OPENPGP_GNUK
+ && (tag == DO_CERT || tag == 0x0101 || tag == 0x0102 || tag == 0x0103 || tag == 0x0104)) {
+ r = SC_SUCCESS;
+ apdu.resplen = 0;
+ }
LOG_TEST_RET(card->ctx, r, "Card returned error");
LOG_FUNC_RETURN(card->ctx, apdu.resplen);
--
1.9.3

View File

@ -0,0 +1,53 @@
From 6a4457cde65ef44f05b0689415ae7165b06fb8bf Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Nguy=E1=BB=85n=20H=E1=BB=93ng=20Qu=C3=A2n?=
<ng.hong.quan@gmail.com>
Date: Wed, 27 Mar 2013 11:38:42 +0700
Subject: [PATCH 09/18] PKCS15-OpenPGP: Do not show empty DO in pkcs15
emu_init.
---
src/libopensc/pkcs15-openpgp.c | 18 ++++++++++++++++++
1 file changed, 18 insertions(+)
diff --git a/src/libopensc/pkcs15-openpgp.c b/src/libopensc/pkcs15-openpgp.c
index 9f239ef..850dd74 100644
--- a/src/libopensc/pkcs15-openpgp.c
+++ b/src/libopensc/pkcs15-openpgp.c
@@ -385,16 +385,34 @@ sc_pkcs15emu_openpgp_add_data(sc_pkcs15_card_t *p15card)
sc_pkcs15_object_t dat_obj;
char name[8];
char path[9];
+ u8 content[254];
memset(&dat_info, 0, sizeof(dat_info));
memset(&dat_obj, 0, sizeof(dat_obj));
sprintf(name, "PrivDO%d", i);
sprintf(path, "3F00010%d", i);
+ /* Check if the DO can be read.
+ * We won't expose pkcs15 DATA object if DO is empty.
+ */
+ r = read_file(p15card->card, path, content, sizeof(content));
+ if (r <= 0 ) {
+ sc_log(ctx, "Cannot read DO 010%d or there is no data in it", i);
+ /* Skip */
+ continue;
+ }
sc_format_path(path, &dat_info.path);
strlcpy(dat_obj.label, name, sizeof(dat_obj.label));
strlcpy(dat_info.app_label, name, sizeof(dat_info.app_label));
+ /* Add DATA object to slot protected by PIN2 (PW1 with Ref 0x82) */
+ dat_obj.flags = SC_PKCS15_CO_FLAG_PRIVATE | SC_PKCS15_CO_FLAG_MODIFIABLE;
+ dat_obj.auth_id.len = 1;
+ if (i == 1 || i == 3)
+ dat_obj.auth_id.value[0] = 2;
+ else
+ dat_obj.auth_id.value[0] = 3;
+
sc_log(ctx, "Add %s data object", name);
r = sc_pkcs15emu_add_data_object(p15card, &dat_obj, &dat_info);
}
--
1.9.3

View File

@ -0,0 +1,91 @@
From 88ded8fc5802c073caa71b649cee5a3116699b2a Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Nguy=E1=BB=85n=20H=E1=BB=93ng=20Qu=C3=A2n?=
<ng.hong.quan@gmail.com>
Date: Wed, 27 Mar 2013 11:39:33 +0700
Subject: [PATCH 10/18] PKCS15-OpenPGP: Allow to store data to pkcs15 data
object.
Only one DO is supported now.
---
src/libopensc/pkcs15-openpgp.c | 2 +-
src/pkcs15init/pkcs15-openpgp.c | 38 +++++++++++++++++++++++++++++++++++++-
2 files changed, 38 insertions(+), 2 deletions(-)
diff --git a/src/libopensc/pkcs15-openpgp.c b/src/libopensc/pkcs15-openpgp.c
index 850dd74..b701041 100644
--- a/src/libopensc/pkcs15-openpgp.c
+++ b/src/libopensc/pkcs15-openpgp.c
@@ -397,7 +397,7 @@ sc_pkcs15emu_openpgp_add_data(sc_pkcs15_card_t *p15card)
*/
r = read_file(p15card->card, path, content, sizeof(content));
if (r <= 0 ) {
- sc_log(ctx, "Cannot read DO 010%d or there is no data in it", i);
+ sc_log(ctx, "No data get from DO 010%d", i);
/* Skip */
continue;
}
diff --git a/src/pkcs15init/pkcs15-openpgp.c b/src/pkcs15init/pkcs15-openpgp.c
index f3a4962..1455580 100755
--- a/src/pkcs15init/pkcs15-openpgp.c
+++ b/src/pkcs15init/pkcs15-openpgp.c
@@ -236,13 +236,16 @@ static int openpgp_emu_update_tokeninfo(sc_profile_t *profile, sc_pkcs15_card_t
}
static int openpgp_store_data(struct sc_pkcs15_card *p15card, struct sc_profile *profile,
- struct sc_pkcs15_object *obj, struct sc_pkcs15_der *content,
+ struct sc_pkcs15_object *obj, struct sc_pkcs15_der *content,
struct sc_path *path)
{
sc_card_t *card = p15card->card;
+ sc_context_t *ctx = card->ctx;
sc_file_t *file;
sc_pkcs15_cert_info_t *cinfo;
sc_pkcs15_id_t *cid;
+ sc_pkcs15_data_info_t *dinfo;
+ u8 buf[254];
int r;
LOG_FUNC_CALLED(card->ctx);
@@ -282,6 +285,39 @@ static int openpgp_store_data(struct sc_pkcs15_card *p15card, struct sc_profile
content->len, 0);
break;
+ case SC_PKCS15_TYPE_DATA_OBJECT:
+ dinfo = (sc_pkcs15_data_info_t *) obj->data;
+ /* dinfo->app_label contains filename */
+ sc_log(ctx, "===== App label %s", dinfo->app_label);
+ /* Currently, we only support DO 0101. The reason is that when initializing this
+ * pkcs15 emulation, PIN authentication is not applied and we can expose only this DO,
+ * which is "read always".
+ * If we support other DOs, they will not be exposed, and not helpful to user.
+ * I haven't found a way to refresh the list of exposed DOs after verifying PIN yet.
+ * http://sourceforge.net/mailarchive/message.php?msg_id=30646373
+ **/
+ sc_log(ctx, "About to write to DO 0101");
+ sc_format_path("0101", path);
+ r = sc_select_file(card, path, &file);
+ LOG_TEST_RET(card->ctx, r, "Cannot select private DO");
+ r = sc_read_binary(card, 0, buf, sizeof(buf), 0);
+ if (r < 0) {
+ sc_log(ctx, "Cannot read DO 0101");
+ break;
+ }
+ if (r > 0) {
+ sc_log(ctx, "DO 0101 is full.");
+ r = SC_ERROR_TOO_MANY_OBJECTS;
+ break;
+ }
+ r = sc_pkcs15init_authenticate(profile, p15card, file, SC_AC_OP_UPDATE);
+ if (r >= 0 && content->len) {
+ r = sc_update_binary(p15card->card, 0,
+ (const unsigned char *) content->value,
+ content->len, 0);
+ }
+ break;
+
default:
r = SC_ERROR_NOT_IMPLEMENTED;
}
--
1.9.3

View File

@ -0,0 +1,87 @@
From 7231ee09bb628f0401939778decce818ef6e3665 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Nguy=E1=BB=85n=20H=E1=BB=93ng=20Qu=C3=A2n?=
<ng.hong.quan@gmail.com>
Date: Fri, 5 Apr 2013 17:18:50 +0700
Subject: [PATCH 11/18] OpenPGP: Provide enough buffer to read pubkey from
Gnuk.
---
src/libopensc/card-openpgp.c | 28 +++++++++++++++++++++++-----
1 file changed, 23 insertions(+), 5 deletions(-)
diff --git a/src/libopensc/card-openpgp.c b/src/libopensc/card-openpgp.c
index 9b08bbb..8a1a270 100644
--- a/src/libopensc/card-openpgp.c
+++ b/src/libopensc/card-openpgp.c
@@ -263,7 +263,12 @@ static struct do_info pgp2_objects[] = { /* OpenPGP card spec 2.0 */
/* The DO holding X.509 certificate is constructed but does not contain child DO.
* We should notice this when building fake file system later. */
-#define DO_CERT 0x7f21
+#define DO_CERT 0x7f21
+/* Maximum length for response buffer when reading pubkey. This value is calculated with
+ * 4096-bit key length */
+#define MAXLEN_RESP_PUBKEY 527
+/* Gnuk only support 1 key length (2048 bit) */
+#define MAXLEN_RESP_PUBKEY_GNUK 271
#define DRVDATA(card) ((struct pgp_priv_data *) ((card)->drv_data))
struct pgp_priv_data {
@@ -729,6 +734,14 @@ pgp_read_blob(sc_card_t *card, struct blob *blob)
u8 buffer[2048];
size_t buf_len = (card->caps & SC_CARD_CAP_APDU_EXT)
? sizeof(buffer) : 256;
+
+ /* Buffer length for Gnuk pubkey */
+ if (card->type == SC_CARD_TYPE_OPENPGP_GNUK &&
+ (blob->id == 0xa400 || blob->id == 0xb600 || blob->id == 0xb800
+ || blob->id == 0xa401 || blob->id == 0xb601 || blob->id == 0xb801)) {
+ buf_len = MAXLEN_RESP_PUBKEY_GNUK;
+ }
+
int r = blob->info->get_fn(card, blob->id, buffer, buf_len);
if (r < 0) { /* an error occurred */
@@ -1830,6 +1843,7 @@ static int pgp_gen_key(sc_card_t *card, sc_cardctl_openpgp_keygen_info_t *key_in
u8 apdu_case;
u8 *apdu_data;
size_t apdu_le;
+ size_t resplen = 0;
int r = SC_SUCCESS;
LOG_FUNC_CALLED(card->ctx);
@@ -1868,23 +1882,27 @@ static int pgp_gen_key(sc_card_t *card, sc_cardctl_openpgp_keygen_info_t *key_in
apdu_case = SC_APDU_CASE_4_EXT;
}
else {
- apdu_le = 256;
apdu_case = SC_APDU_CASE_4_SHORT;
+ apdu_le = 256;
+ resplen = MAXLEN_RESP_PUBKEY;
+ }
+ if (card->type == SC_CARD_TYPE_OPENPGP_GNUK) {
+ resplen = MAXLEN_RESP_PUBKEY_GNUK;
}
/* Prepare APDU */
- sc_format_apdu(card, &apdu, apdu_case, 0x47, 0x80, 0);
+ sc_format_apdu(card, &apdu, apdu_case, 0x47, 0x80, 0);
apdu.data = apdu_data;
apdu.datalen = 2; /* Data = B600 */
apdu.lc = 2;
apdu.le = apdu_le;
/* Buffer to receive response */
- apdu.resp = calloc(apdu.le, 1);
+ apdu.resplen = (resplen > 0) ? resplen : apdu_le;
+ apdu.resp = calloc(apdu.resplen, 1);
if (apdu.resp == NULL) {
LOG_FUNC_RETURN(card->ctx, SC_ERROR_NOT_ENOUGH_MEMORY);
}
- apdu.resplen = apdu.le;
/* Send */
sc_log(card->ctx, "Waiting for the card to generate key...");
--
1.9.3

View File

@ -0,0 +1,220 @@
From d8f63eb6fcc1441c12a44850da2fa22a6fe81634 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Nguy=E1=BB=85n=20H=E1=BB=93ng=20Qu=C3=A2n?=
<ng.hong.quan@gmail.com>
Date: Thu, 11 Apr 2013 11:47:51 +0700
Subject: [PATCH 12/18] OpenPGP: Support write certificate for Gnuk.
---
src/libopensc/card-openpgp.c | 158 +++++++++++++++++++++++++++++++++----------
1 file changed, 123 insertions(+), 35 deletions(-)
diff --git a/src/libopensc/card-openpgp.c b/src/libopensc/card-openpgp.c
index 8a1a270..d9db948 100644
--- a/src/libopensc/card-openpgp.c
+++ b/src/libopensc/card-openpgp.c
@@ -725,6 +725,8 @@ pgp_iterate_blobs(struct blob *blob, int level, void (*func)())
static int
pgp_read_blob(sc_card_t *card, struct blob *blob)
{
+ struct pgp_priv_data *priv = DRVDATA (card);
+
if (blob->data != NULL)
return SC_SUCCESS;
if (blob->info == NULL)
@@ -735,6 +737,11 @@ pgp_read_blob(sc_card_t *card, struct blob *blob)
size_t buf_len = (card->caps & SC_CARD_CAP_APDU_EXT)
? sizeof(buffer) : 256;
+ /* Buffer length for certificate */
+ if (blob->id == DO_CERT && priv->max_cert_size > 0) {
+ buf_len = MIN(priv->max_cert_size, sizeof(buffer));
+ }
+
/* Buffer length for Gnuk pubkey */
if (card->type == SC_CARD_TYPE_OPENPGP_GNUK &&
(blob->id == 0xa400 || blob->id == 0xb600 || blob->id == 0xb800
@@ -1190,49 +1197,75 @@ pgp_get_data(sc_card_t *card, unsigned int tag, u8 *buf, size_t buf_len)
LOG_FUNC_RETURN(card->ctx, apdu.resplen);
}
-/* ABI: PUT DATA */
-static int
-pgp_put_data(sc_card_t *card, unsigned int tag, const u8 *buf, size_t buf_len)
+
+/* Internal: Write certificate for Gnuk */
+static int gnuk_write_certificate(sc_card_t *card, const u8 *buf, size_t length)
{
+ sc_context_t *ctx = card->ctx;
+ size_t i = 0;
sc_apdu_t apdu;
+ u8 *part;
+ size_t plen;
+ int r = SC_SUCCESS;
+
+ LOG_FUNC_CALLED(ctx);
+
+ /* If null data is passed, delete certificate */
+ if (buf == NULL || length == 0) {
+ sc_format_apdu(card, &apdu, SC_APDU_CASE_1, 0xD6, 0x85, 0);
+ r = sc_transmit_apdu(card, &apdu);
+ LOG_TEST_RET(card->ctx, r, "APDU transmit failed");
+ /* Check response */
+ r = sc_check_sw(card, apdu.sw1, apdu.sw2);
+ LOG_FUNC_RETURN(card->ctx, length);
+ }
+
+ /* Ref: gnuk_put_binary_libusb.py and gnuk_token.py in Gnuk source tree */
+ /* Split data to segments of 256 bytes. Send each segment via command chaining,
+ * with particular P1 byte for each segment */
+ while (i*256 < length) {
+ part = (u8 *)buf + i*256;
+ plen = MIN(length - i*256, 256);
+
+ sc_log(card->ctx, "Write part %d from offset 0x%X, len %d", i+1, part, plen);
+
+ if (i == 0) {
+ sc_format_apdu(card, &apdu, SC_APDU_CASE_3_SHORT, 0xD6, 0x85, 0);
+ }
+ else {
+ sc_format_apdu(card, &apdu, SC_APDU_CASE_3_SHORT, 0xD6, i, 0);
+ }
+ apdu.flags |= SC_APDU_FLAGS_CHAINING;
+ apdu.data = part;
+ apdu.datalen = apdu.lc = plen;
+
+ r = sc_transmit_apdu(card, &apdu);
+ LOG_TEST_RET(card->ctx, r, "APDU transmit failed");
+ /* Check response */
+ r = sc_check_sw(card, apdu.sw1, apdu.sw2);
+ LOG_TEST_RET(card->ctx, r, "UPDATE BINARY returned error");
+
+ /* To next part */
+ i++;
+ }
+ LOG_FUNC_RETURN(card->ctx, length);
+}
+
+
+/* Internal: Use PUT DATA command to write */
+static int
+pgp_put_data_plain(sc_card_t *card, unsigned int tag, const u8 *buf, size_t buf_len)
+{
struct pgp_priv_data *priv = DRVDATA(card);
- struct blob *affected_blob = NULL;
- struct do_info *dinfo = NULL;
+ sc_context_t *ctx = card->ctx;
+ sc_apdu_t apdu;
u8 ins = 0xDA;
u8 p1 = tag >> 8;
u8 p2 = tag & 0xFF;
u8 apdu_case = SC_APDU_CASE_3;
int r;
- LOG_FUNC_CALLED(card->ctx);
-
- /* Check if the tag is writable */
- affected_blob = pgp_find_blob(card, tag);
-
- /* Non-readable DOs have no represented blob, we have to check from pgp_get_info_by_tag */
- if (affected_blob == NULL)
- dinfo = pgp_get_info_by_tag(card, tag);
- else
- dinfo = affected_blob->info;
-
- if (dinfo == NULL) {
- sc_log(card->ctx, "The DO %04X does not exist.", tag);
- LOG_FUNC_RETURN(card->ctx, SC_ERROR_INVALID_ARGUMENTS);
- }
- else if ((dinfo->access & WRITE_MASK) == WRITE_NEVER) {
- sc_log(card->ctx, "DO %04X is not writable.", tag);
- LOG_FUNC_RETURN(card->ctx, SC_ERROR_NOT_ALLOWED);
- }
-
- /* Check data size.
- * We won't check other DOs than 7F21 (certificate), because their capacity
- * is hard-codded and may change in various version of the card. If we check here,
- * the driver may be sticked to a limit version number of card.
- * 7F21 size is soft-coded, so we can check it. */
- if (tag == DO_CERT && buf_len > priv->max_cert_size) {
- sc_log(card->ctx, "Data size %ld exceeds DO size limit %ld.", buf_len, priv->max_cert_size);
- LOG_FUNC_RETURN(card->ctx, SC_ERROR_WRONG_LENGTH);
- }
+ LOG_FUNC_CALLED(ctx);
/* Extended Header list (004D DO) needs a variant of PUT DATA command */
if (tag == 0x004D) {
@@ -1258,15 +1291,70 @@ pgp_put_data(sc_card_t *card, unsigned int tag, const u8 *buf, size_t buf_len)
apdu.lc = buf_len;
}
else {
+ /* This case is to empty DO */
sc_format_apdu(card, &apdu, SC_APDU_CASE_1, ins, p1, p2);
}
/* Send APDU to card */
r = sc_transmit_apdu(card, &apdu);
- LOG_TEST_RET(card->ctx, r, "APDU transmit failed");
+ LOG_TEST_RET(ctx, r, "APDU transmit failed");
/* Check response */
r = sc_check_sw(card, apdu.sw1, apdu.sw2);
+ if (r < 0)
+ LOG_FUNC_RETURN(ctx, r);
+
+ LOG_FUNC_RETURN(ctx, buf_len);
+}
+
+/* ABI: PUT DATA */
+static int
+pgp_put_data(sc_card_t *card, unsigned int tag, const u8 *buf, size_t buf_len)
+{
+ struct pgp_priv_data *priv = DRVDATA(card);
+ struct blob *affected_blob = NULL;
+ struct do_info *dinfo = NULL;
+ int r;
+
+ LOG_FUNC_CALLED(card->ctx);
+
+ /* Check if the tag is writable */
+ if (priv->current->id != tag)
+ affected_blob = pgp_find_blob(card, tag);
+
+ /* Non-readable DOs have no represented blob, we have to check from pgp_get_info_by_tag */
+ if (affected_blob == NULL)
+ dinfo = pgp_get_info_by_tag(card, tag);
+ else
+ dinfo = affected_blob->info;
+
+ if (dinfo == NULL) {
+ sc_log(card->ctx, "The DO %04X does not exist.", tag);
+ LOG_FUNC_RETURN(card->ctx, SC_ERROR_INVALID_ARGUMENTS);
+ }
+ else if ((dinfo->access & WRITE_MASK) == WRITE_NEVER) {
+ sc_log(card->ctx, "DO %04X is not writable.", tag);
+ LOG_FUNC_RETURN(card->ctx, SC_ERROR_NOT_ALLOWED);
+ }
+
+ /* Check data size.
+ * We won't check other DOs than 7F21 (certificate), because their capacity
+ * is hard-codded and may change in various version of the card. If we check here,
+ * the driver may be sticked to a limit version number of card.
+ * 7F21 size is soft-coded, so we can check it. */
+ if (tag == DO_CERT && buf_len > priv->max_cert_size) {
+ sc_log(card->ctx, "Data size %ld exceeds DO size limit %ld.", buf_len, priv->max_cert_size);
+ LOG_FUNC_RETURN(card->ctx, SC_ERROR_WRONG_LENGTH);
+ }
+
+ if (tag == DO_CERT && card->type == SC_CARD_TYPE_OPENPGP_GNUK) {
+ /* Gnuk need a special way to write certificate. */
+ r = gnuk_write_certificate(card, buf, buf_len);
+ }
+ else {
+ r = pgp_put_data_plain(card, tag, buf, buf_len);
+ }
+
/* Instruct more in case of error */
if (r == SC_ERROR_SECURITY_STATUS_NOT_SATISFIED) {
sc_debug(card->ctx, SC_LOG_DEBUG_VERBOSE, "Please verify PIN first.");
--
1.9.3

View File

@ -0,0 +1,31 @@
From e5c94d3f1f7e6a96a98815d6e51190498c357fb6 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Nguy=E1=BB=85n=20H=E1=BB=93ng=20Qu=C3=A2n?=
<ng.hong.quan@gmail.com>
Date: Wed, 10 Apr 2013 18:35:58 +0700
Subject: [PATCH 13/18] pkcs15-openpgp: Change to sc_put_data instead of
sc_update_binary when writing certificate.
---
src/pkcs15init/pkcs15-openpgp.c | 5 ++---
1 file changed, 2 insertions(+), 3 deletions(-)
diff --git a/src/pkcs15init/pkcs15-openpgp.c b/src/pkcs15init/pkcs15-openpgp.c
index 1455580..be1291e 100755
--- a/src/pkcs15init/pkcs15-openpgp.c
+++ b/src/pkcs15init/pkcs15-openpgp.c
@@ -279,10 +279,9 @@ static int openpgp_store_data(struct sc_pkcs15_card *p15card, struct sc_profile
r = sc_select_file(card, path, &file);
LOG_TEST_RET(card->ctx, r, "Cannot select cert file");
r = sc_pkcs15init_authenticate(profile, p15card, file, SC_AC_OP_UPDATE);
+ sc_log(card->ctx, "Data to write is %d long", content->len);
if (r >= 0 && content->len)
- r = sc_update_binary(p15card->card, 0,
- (const unsigned char *) content->value,
- content->len, 0);
+ r = sc_put_data(p15card->card, 0x7F21, (const unsigned char *) content->value, content->len);
break;
case SC_PKCS15_TYPE_DATA_OBJECT:
--
1.9.3

View File

@ -0,0 +1,53 @@
From df8a78e3c8c9d9d591c0d3fa31db7e010eb2c8c2 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Nguy=E1=BB=85n=20H=E1=BB=93ng=20Qu=C3=A2n?=
<ng.hong.quan@gmail.com>
Date: Thu, 11 Apr 2013 16:18:31 +0700
Subject: [PATCH 14/18] OpenPGP: Overcome the restriction of even data length
of Gnuk.
When write certificate with odd length to Gnuk, we add zero padding to make it even.
---
src/libopensc/card-openpgp.c | 20 ++++++++++++++++++--
1 file changed, 18 insertions(+), 2 deletions(-)
diff --git a/src/libopensc/card-openpgp.c b/src/libopensc/card-openpgp.c
index d9db948..a666163 100644
--- a/src/libopensc/card-openpgp.c
+++ b/src/libopensc/card-openpgp.c
@@ -1206,6 +1206,10 @@ static int gnuk_write_certificate(sc_card_t *card, const u8 *buf, size_t length)
sc_apdu_t apdu;
u8 *part;
size_t plen;
+ /* Two round_ variables below are to build APDU data
+ * with even length for Gnuk */
+ u8 roundbuf[256];
+ size_t roundlen = 0;
int r = SC_SUCCESS;
LOG_FUNC_CALLED(ctx);
@@ -1236,8 +1240,20 @@ static int gnuk_write_certificate(sc_card_t *card, const u8 *buf, size_t length)
sc_format_apdu(card, &apdu, SC_APDU_CASE_3_SHORT, 0xD6, i, 0);
}
apdu.flags |= SC_APDU_FLAGS_CHAINING;
- apdu.data = part;
- apdu.datalen = apdu.lc = plen;
+
+ /* If the last part has odd length, we add zero padding to make it even.
+ * Gnuk does not allow data with odd length */
+ if (plen < 256 && (plen % 2) != 0) {
+ roundlen = plen + 1;
+ memset(roundbuf, 0, roundlen);
+ memcpy(roundbuf, part, plen);
+ apdu.data = roundbuf;
+ apdu.datalen = apdu.lc = roundlen;
+ }
+ else {
+ apdu.data = part;
+ apdu.datalen = apdu.lc = plen;
+ }
r = sc_transmit_apdu(card, &apdu);
LOG_TEST_RET(card->ctx, r, "APDU transmit failed");
--
1.9.3

View File

@ -0,0 +1,92 @@
From 693b3ac5a53e89a0cdeab0f728d24a6e16864f5c Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Nguy=E1=BB=85n=20H=E1=BB=93ng=20Qu=C3=A2n?=
<ng.hong.quan@gmail.com>
Date: Fri, 12 Apr 2013 15:33:31 +0700
Subject: [PATCH 15/18] OpenPGP: Delete key as file, for Gnuk.
---
src/libopensc/card-openpgp.c | 51 +++++++++++++++++++++++++++++++++++++++++++-
1 file changed, 50 insertions(+), 1 deletion(-)
diff --git a/src/libopensc/card-openpgp.c b/src/libopensc/card-openpgp.c
index a666163..19d3b04 100644
--- a/src/libopensc/card-openpgp.c
+++ b/src/libopensc/card-openpgp.c
@@ -2437,6 +2437,44 @@ static int pgp_card_ctl(sc_card_t *card, unsigned long cmd, void *ptr)
LOG_FUNC_RETURN(card->ctx, SC_ERROR_NOT_SUPPORTED);
}
+
+/* Internal: Delete key */
+static int
+gnuk_delete_key(sc_card_t *card, u8 key_id)
+{
+ sc_context_t *ctx = card->ctx;
+ int r = SC_SUCCESS;
+ u8 *data = NULL;
+
+ LOG_FUNC_CALLED(ctx);
+
+ /* Delete fingerprint */
+ sc_log(ctx, "Delete fingerprints");
+ r = pgp_put_data(card, 0xC6 + key_id, NULL, 0);
+ LOG_TEST_RET(ctx, r, "Failed to delete fingerprints");
+ /* Delete creation time */
+ sc_log(ctx, "Delete creation time");
+ r = pgp_put_data(card, 0xCD + key_id, NULL, 0);
+ LOG_TEST_RET(ctx, r, "Failed to delete creation time");
+
+ /* Rewrite Extended Header List */
+ sc_log(ctx, "Rewrite Extended Header List");
+
+ if (key_id == 1)
+ data = "\x4D\x02\xB6";
+ else if (key_id == 2)
+ data = "\x4D\x02\xB8";
+ else if (key_id == 3)
+ data = "\x4D\x02\xA4";
+ else
+ LOG_FUNC_RETURN(ctx, SC_ERROR_INVALID_ARGUMENTS);
+
+ r = pgp_put_data(card, 0x4D, data, strlen(data) + 1);
+
+ LOG_FUNC_RETURN(ctx, r);
+}
+
+
/* ABI: DELETE FILE */
static int
pgp_delete_file(sc_card_t *card, const sc_path_t *path)
@@ -2444,6 +2482,7 @@ pgp_delete_file(sc_card_t *card, const sc_path_t *path)
struct pgp_priv_data *priv = DRVDATA(card);
struct blob *blob;
sc_file_t *file;
+ u8 key_id;
int r;
LOG_FUNC_CALLED(card->ctx);
@@ -2459,10 +2498,20 @@ pgp_delete_file(sc_card_t *card, const sc_path_t *path)
if (blob == priv->mf)
LOG_FUNC_RETURN(card->ctx, SC_ERROR_NOT_SUPPORTED);
- if (file->id == 0xB601 || file->id == 0xB801 || file->id == 0xA401) {
+ if (card->type != SC_CARD_TYPE_OPENPGP_GNUK &&
+ (file->id == 0xB601 || file->id == 0xB801 || file->id == 0xA401)) {
/* These tags are just symbolic. We don't really delete it. */
r = SC_SUCCESS;
}
+ else if (card->type == SC_CARD_TYPE_OPENPGP_GNUK && file->id == 0xB601) {
+ r = gnuk_delete_key(card, 1);
+ }
+ else if (card->type == SC_CARD_TYPE_OPENPGP_GNUK && file->id == 0xB801) {
+ r = gnuk_delete_key(card, 2);
+ }
+ else if (card->type == SC_CARD_TYPE_OPENPGP_GNUK && file->id == 0xA401) {
+ r = gnuk_delete_key(card, 3);
+ }
else {
/* call pgp_put_data() with zero-sized NULL-buffer to zap the DO contents */
r = pgp_put_data(card, file->id, NULL, 0);
--
1.9.3

View File

@ -0,0 +1,47 @@
From f96f7536a8c2efd0ba41fd94fe3334e5fa556854 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Nguy=E1=BB=85n=20H=E1=BB=93ng=20Qu=C3=A2n?=
<ng.hong.quan@gmail.com>
Date: Tue, 16 Apr 2013 10:19:34 +0700
Subject: [PATCH 16/18] OpenPGP: Correct parameter checking.
---
src/libopensc/card-openpgp.c | 9 +++++++--
1 file changed, 7 insertions(+), 2 deletions(-)
diff --git a/src/libopensc/card-openpgp.c b/src/libopensc/card-openpgp.c
index 19d3b04..196c094 100644
--- a/src/libopensc/card-openpgp.c
+++ b/src/libopensc/card-openpgp.c
@@ -1221,6 +1221,8 @@ static int gnuk_write_certificate(sc_card_t *card, const u8 *buf, size_t length)
LOG_TEST_RET(card->ctx, r, "APDU transmit failed");
/* Check response */
r = sc_check_sw(card, apdu.sw1, apdu.sw2);
+ if (r < 0)
+ LOG_FUNC_RETURN(card->ctx, r);
LOG_FUNC_RETURN(card->ctx, length);
}
@@ -2448,6 +2450,11 @@ gnuk_delete_key(sc_card_t *card, u8 key_id)
LOG_FUNC_CALLED(ctx);
+ if (key_id < 1 || key_id > 3) {
+ sc_log(ctx, "Key ID %d is invalid. Should be 1, 2 or 3.", key_id);
+ LOG_FUNC_RETURN(ctx, SC_ERROR_INVALID_ARGUMENTS);
+ }
+
/* Delete fingerprint */
sc_log(ctx, "Delete fingerprints");
r = pgp_put_data(card, 0xC6 + key_id, NULL, 0);
@@ -2466,8 +2473,6 @@ gnuk_delete_key(sc_card_t *card, u8 key_id)
data = "\x4D\x02\xB8";
else if (key_id == 3)
data = "\x4D\x02\xA4";
- else
- LOG_FUNC_RETURN(ctx, SC_ERROR_INVALID_ARGUMENTS);
r = pgp_put_data(card, 0x4D, data, strlen(data) + 1);
--
1.9.3

View File

@ -0,0 +1,39 @@
From 8a69525a60391b46db4994033527d219d2adaa4e Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Nguy=E1=BB=85n=20H=E1=BB=93ng=20Qu=C3=A2n?=
<ng.hong.quan@gmail.com>
Date: Tue, 16 Apr 2013 16:02:17 +0700
Subject: [PATCH 17/18] OpenPGP: Make code neater
---
src/libopensc/card-openpgp.c | 8 ++------
1 file changed, 2 insertions(+), 6 deletions(-)
diff --git a/src/libopensc/card-openpgp.c b/src/libopensc/card-openpgp.c
index 196c094..c4ef3b6 100644
--- a/src/libopensc/card-openpgp.c
+++ b/src/libopensc/card-openpgp.c
@@ -1220,10 +1220,7 @@ static int gnuk_write_certificate(sc_card_t *card, const u8 *buf, size_t length)
r = sc_transmit_apdu(card, &apdu);
LOG_TEST_RET(card->ctx, r, "APDU transmit failed");
/* Check response */
- r = sc_check_sw(card, apdu.sw1, apdu.sw2);
- if (r < 0)
- LOG_FUNC_RETURN(card->ctx, r);
- LOG_FUNC_RETURN(card->ctx, length);
+ LOG_TEST_RET(card->ctx, sc_check_sw(card, apdu.sw1, apdu.sw2), "Certificate writing failed");
}
/* Ref: gnuk_put_binary_libusb.py and gnuk_token.py in Gnuk source tree */
@@ -1260,8 +1257,7 @@ static int gnuk_write_certificate(sc_card_t *card, const u8 *buf, size_t length)
r = sc_transmit_apdu(card, &apdu);
LOG_TEST_RET(card->ctx, r, "APDU transmit failed");
/* Check response */
- r = sc_check_sw(card, apdu.sw1, apdu.sw2);
- LOG_TEST_RET(card->ctx, r, "UPDATE BINARY returned error");
+ LOG_TEST_RET(card->ctx, sc_check_sw(card, apdu.sw1, apdu.sw2), "UPDATE BINARY returned error");
/* To next part */
i++;
--
1.9.3

View File

@ -0,0 +1,34 @@
From a099f951d085d3abfefeead14a4af06913cb67d2 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Nguy=E1=BB=85n=20H=E1=BB=93ng=20Qu=C3=A2n?=
<ng.hong.quan@gmail.com>
Date: Wed, 8 May 2013 16:51:21 +0700
Subject: [PATCH 18/18] Move declaration to top of block.
---
src/libopensc/card-openpgp.c | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/src/libopensc/card-openpgp.c b/src/libopensc/card-openpgp.c
index c4ef3b6..7f2006e 100644
--- a/src/libopensc/card-openpgp.c
+++ b/src/libopensc/card-openpgp.c
@@ -736,6 +736,7 @@ pgp_read_blob(sc_card_t *card, struct blob *blob)
u8 buffer[2048];
size_t buf_len = (card->caps & SC_CARD_CAP_APDU_EXT)
? sizeof(buffer) : 256;
+ int r = SC_SUCCESS;
/* Buffer length for certificate */
if (blob->id == DO_CERT && priv->max_cert_size > 0) {
@@ -749,7 +750,7 @@ pgp_read_blob(sc_card_t *card, struct blob *blob)
buf_len = MAXLEN_RESP_PUBKEY_GNUK;
}
- int r = blob->info->get_fn(card, blob->id, buffer, buf_len);
+ r = blob->info->get_fn(card, blob->id, buffer, buf_len);
if (r < 0) { /* an error occurred */
blob->status = r;
--
1.9.3