Browse Source

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>
Daniel Golle 10 years ago
parent
commit
54a8a2a6b9
19 changed files with 1868 additions and 0 deletions
  1. 224
    0
      utils/opensc/Makefile
  2. 267
    0
      utils/opensc/patches/0001-OpenPGP-Detect-and-support-Gnuk-Token.patch
  3. 50
    0
      utils/opensc/patches/0002-OpenPGP-Add-Gnuk-in-pkcs15-emulation-layer.patch
  4. 30
    0
      utils/opensc/patches/0003-OpenPGP-Include-private-DO-to-filesystem-at-driver-i.patch
  5. 82
    0
      utils/opensc/patches/0004-PKCS15-OpenPGP-Declare-DATA-objects.patch
  6. 173
    0
      utils/opensc/patches/0005-OpenPGP-Support-erasing-reset-card.patch
  7. 210
    0
      utils/opensc/patches/0006-openpgp-tool-Support-deleting-key-in-Gnuk.patch
  8. 27
    0
      utils/opensc/patches/0007-OpenPGP-Correct-building-Extended-Header-List-when-i.patch
  9. 58
    0
      utils/opensc/patches/0008-OpenPGP-Read-some-empty-DOs-from-Gnuk.patch
  10. 53
    0
      utils/opensc/patches/0009-PKCS15-OpenPGP-Do-not-show-empty-DO-in-pkcs15-emu_in.patch
  11. 91
    0
      utils/opensc/patches/0010-PKCS15-OpenPGP-Allow-to-store-data-to-pkcs15-data-ob.patch
  12. 87
    0
      utils/opensc/patches/0011-OpenPGP-Provide-enough-buffer-to-read-pubkey-from-Gn.patch
  13. 220
    0
      utils/opensc/patches/0012-OpenPGP-Support-write-certificate-for-Gnuk.patch
  14. 31
    0
      utils/opensc/patches/0013-pkcs15-openpgp-Change-to-sc_put_data-instead-of-sc_u.patch
  15. 53
    0
      utils/opensc/patches/0014-OpenPGP-Overcome-the-restriction-of-even-data-length.patch
  16. 92
    0
      utils/opensc/patches/0015-OpenPGP-Delete-key-as-file-for-Gnuk.patch
  17. 47
    0
      utils/opensc/patches/0016-OpenPGP-Correct-parameter-checking.patch
  18. 39
    0
      utils/opensc/patches/0017-OpenPGP-Make-code-neater.patch
  19. 34
    0
      utils/opensc/patches/0018-Move-declaration-to-top-of-block.patch

+ 224
- 0
utils/opensc/Makefile View File

@@ -0,0 +1,224 @@
1
+#
2
+# Copyright (C) 2011-2014 OpenWrt.org
3
+#
4
+# This is free software, licensed under the GNU General Public License v2.
5
+# See /LICENSE for more information.
6
+#
7
+
8
+include $(TOPDIR)/rules.mk
9
+
10
+PKG_NAME:=opensc
11
+PKG_VERSION:=20140317
12
+PKG_RELEASE:=1
13
+PKG_MAINTAINER:=Daniel Golle <daniel@makrotopia.org>
14
+
15
+PKG_RELEASE=$(PKG_SOURCE_VERSION)
16
+
17
+PKG_SOURCE_PROTO:=git
18
+PKG_SOURCE_URL:=https://github.com/OpenSC/OpenSC.git
19
+PKG_SOURCE_SUBDIR:=$(PKG_NAME)-$(PKG_VERSION)
20
+PKG_SOURCE_VERSION:=de6d61405b271e22244376e4817e16b49018e1ce
21
+PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz
22
+PKG_BUILD_DEPENDS:=+libpcsclite
23
+PKG_FIXUP:=libtool
24
+
25
+PKG_INSTALL:=1
26
+
27
+include $(INCLUDE_DIR)/package.mk
28
+
29
+define Package/libopensc
30
+  SECTION:=libs
31
+  CATEGORY:=Libraries
32
+  TITLE:=OpenSC libraries for smart cards
33
+  URL:=https://www.opensc-project.org/opensc/wiki/
34
+  DEPENDS:=+libopenssl +libpthread
35
+  MENU:=1
36
+endef
37
+
38
+define Package/libopensc/description
39
+  OpenSC provides a set of libraries and utilities to work with smart cards.
40
+  Its main focus is on cards that support cryptographic operations, and
41
+  facilitate their use in security applications such as authentication,
42
+  mail encryption and digital signatures.
43
+endef
44
+
45
+define Package/libopensc-pkcs11
46
+  SECTION:=libs
47
+  CATEGORY:=Libraries
48
+  TITLE:=OpenSC - PKCS11 provider
49
+  URL:=https://www.opensc-project.org/opensc/wiki/
50
+  DEPENDS:=libopensc
51
+endef
52
+
53
+define Package/libopensc-pkcs11/description
54
+  OpenSC PKCS#11 provider
55
+endef
56
+
57
+define Package/libpkcs11-spy
58
+  SECTION:=libs
59
+  CATEGORY:=Libraries
60
+  TITLE:=PKCS11 spying wrapper
61
+  URL:=https://www.opensc-project.org/opensc/wiki/
62
+endef
63
+
64
+define Package/libpkcs11-spy/dscription
65
+  PKCS#11 spying wrapper
66
+endef
67
+
68
+define Package/opensc-utils
69
+  SECTION:=utils
70
+  CATEGORY:=Utilities
71
+  TITLE:=OpenSC - tools for smart cards
72
+  URL:=https://www.opensc-project.org/opensc/wiki/
73
+  DEPENDS:=+libopensc
74
+  MENU:=1
75
+endef
76
+
77
+define Package/opensc-utils/description
78
+  OpenSC utilities
79
+endef
80
+
81
+define ToolGen
82
+define Package/opensc-utils-$(subst _,-,$(firstword $(subst :, ,$(1))))
83
+  TITLE:=$(firstword $(subst :, ,$(1))) utility from opensc
84
+  URL:=https://www.opensc-project.org/opensc/wiki/
85
+  SECTION:=utils
86
+  CATEGORY:=Utilities
87
+  DEPENDS:=opensc-utils $(wordlist 2,$(words $(subst :, ,$(1))),$(subst :, ,$(1)))
88
+endef
89
+endef
90
+
91
+define ProfileGen
92
+define Package/libopensc-profile-$(subst _,-,$(firstword $(subst :, ,$(1))))
93
+  TITLE:=$(firstword $(subst :, ,$(1))) card profile for opensc
94
+  URL:=https://www.opensc-project.org/opensc/wiki/
95
+  SECTION:=lib
96
+  CATEGORY:=Libraries
97
+  DEPENDS:=libopensc
98
+endef
99
+endef
100
+
101
+TOOLS:= \
102
+	cardos-tool \
103
+	cryptoflex-tool \
104
+	dnie-tool \
105
+	eidenv \
106
+	iasecc-tool \
107
+	netkey-tool \
108
+	openpgp-tool \
109
+	opensc-tool \
110
+	opensc-explorer:+libncurses:+libreadline \
111
+	piv-tool \
112
+	pkcs11-tool \
113
+	pkcs15-crypt \
114
+	pkcs15-init \
115
+	pkcs15-tool \
116
+	sc-hsm-tool \
117
+	westcos-tool
118
+
119
+PROFILES:= \
120
+	asepcos \
121
+	authentic \
122
+	cardos \
123
+	cyberflex \
124
+	entersafe \
125
+	epass2003 \
126
+	flex \
127
+	gpk \
128
+	ias_adele_admin1 \
129
+	ias_adele_admin2 \
130
+	ias_adele_common \
131
+	iasecc_admin_eid \
132
+	iasecc_generic_oberthur \
133
+	iasecc_generic_pki \
134
+	iasecc \
135
+	incrypto34 \
136
+	jcop \
137
+	miocos \
138
+	muscle \
139
+	myeid \
140
+	oberthur \
141
+	openpgp \
142
+	pkcs15 \
143
+	rutoken_ecp \
144
+	rutoken \
145
+	sc-hsm \
146
+	setcos \
147
+	starcos \
148
+	westcos
149
+
150
+$(foreach file,$(TOOLS),$(eval $(call ToolGen,$(file))))
151
+$(foreach file,$(PROFILES),$(eval $(call ProfileGen,$(file))))
152
+
153
+define Build/InstallDev
154
+	$(INSTALL_DIR) $(1)/usr/lib
155
+	$(CP) $(PKG_INSTALL_DIR)/usr/lib/libopensc.{a,so}* $(1)/usr/lib/
156
+	$(CP) $(PKG_INSTALL_DIR)/usr/lib/libsmm-local.{a,so}* $(1)/usr/lib/
157
+	$(CP) $(PKG_INSTALL_DIR)/usr/lib/opensc-pkcs11.so $(1)/usr/lib/
158
+	$(CP) $(PKG_INSTALL_DIR)/usr/lib/pkcs11-spy.so $(1)/usr/lib/
159
+	$(INSTALL_DIR) $(1)/usr/lib/pkcs11
160
+	$(LN) ../pkcs11-spy.so $(1)/usr/lib/pkcs11/
161
+	$(LN) ../opensc-pkcs11.so $(1)/usr/lib/pkcs11/
162
+	$(INSTALL_DIR) $(1)/usr/share/opensc
163
+	$(CP) $(PKG_INSTALL_DIR)/usr/share/opensc/* $(1)/usr/share/opensc/
164
+endef
165
+
166
+define Package/libopensc/install
167
+	$(INSTALL_DIR) $(1)/usr/lib
168
+	$(CP) $(PKG_INSTALL_DIR)/usr/lib/libopensc.so* $(1)/usr/lib/
169
+	$(CP) $(PKG_INSTALL_DIR)/usr/lib/libsmm-local.so* $(1)/usr/lib/
170
+	$(INSTALL_DIR) $(1)/etc
171
+	$(CP) $(PKG_INSTALL_DIR)/etc/opensc.conf $(1)/etc/
172
+endef
173
+
174
+define Package/libopensc-pkcs11/install
175
+	$(INSTALL_DIR) $(1)/usr/lib
176
+	$(CP) $(PKG_INSTALL_DIR)/usr/lib/opensc-pkcs11.so $(1)/usr/lib/
177
+	$(INSTALL_DIR) $(1)/usr/lib/pkcs11
178
+	$(LN) ../opensc-pkcs11.so $(1)/usr/lib/pkcs11/
179
+endef
180
+
181
+define Package/libpkcs11-spy/install
182
+	$(INSTALL_DIR) $(1)/usr/lib
183
+	$(CP) $(PKG_INSTALL_DIR)/usr/lib/pkcs11-spy.so $(1)/usr/lib/
184
+	$(INSTALL_DIR) $(1)/usr/lib/pkcs11
185
+	$(LN) ../pkcs11-spy.so $(1)/usr/lib/pkcs11/
186
+endef
187
+
188
+define Package/opensc-card-profiles
189
+	$(INSTALL_DIR) $(1)/usr/share/opensc
190
+	$(CP) $(PKG_INSTALL_DIR)/usr/share/opensc/* $(1)/usr/share/opensc/
191
+endef
192
+
193
+define Package/opensc-utils/install
194
+	true
195
+endef
196
+
197
+define ToolInstall
198
+define Package/opensc-utils-$(subst _,-,$(firstword $(subst :, ,$(1))))/install
199
+	$(INSTALL_DIR) $$(1)/usr/bin
200
+	$(INSTALL_BIN) \
201
+		$(PKG_INSTALL_DIR)/usr/bin/$(firstword $(subst :, ,$(1))) \
202
+		$$(1)/usr/bin/
203
+endef
204
+endef
205
+
206
+define ProfileInstall
207
+define Package/libopensc-profile-$(subst _,-,$(firstword $(subst :, ,$(1))))/install
208
+	$(INSTALL_DIR) $$(1)/usr/share/opensc
209
+	$(INSTALL_BIN) \
210
+		$(PKG_INSTALL_DIR)/usr/share/opensc/$(firstword $(subst :, ,$(1))).profile \
211
+		$$(1)/usr/share/opensc
212
+endef
213
+endef
214
+
215
+$(foreach file,$(TOOLS),$(eval $(call ToolInstall,$(file))))
216
+$(foreach file,$(PROFILES),$(eval $(call ProfileInstall,$(file))))
217
+
218
+$(eval $(call BuildPackage,libopensc))
219
+$(eval $(call BuildPackage,libopensc-pkcs11))
220
+$(eval $(call BuildPackage,libpkcs11-spy))
221
+
222
+$(eval $(call BuildPackage,opensc-utils))
223
+$(foreach file,$(TOOLS),$(eval $(call BuildPackage,opensc-utils-$(subst _,-,$(firstword $(subst :, ,$(file)))))))
224
+$(foreach file,$(PROFILES),$(eval $(call BuildPackage,libopensc-profile-$(subst _,-,$(firstword $(subst :, ,$(file)))))))

+ 267
- 0
utils/opensc/patches/0001-OpenPGP-Detect-and-support-Gnuk-Token.patch View File

@@ -0,0 +1,267 @@
1
+From c706491fc9b08d4cc6d7b254cf936d6b8d8691bc Mon Sep 17 00:00:00 2001
2
+From: =?UTF-8?q?Nguy=E1=BB=85n=20H=E1=BB=93ng=20Qu=C3=A2n?=
3
+ <ng.hong.quan@gmail.com>
4
+Date: Wed, 20 Feb 2013 11:54:30 +0700
5
+Subject: [PATCH 01/18] OpenPGP: Detect and support Gnuk Token.
6
+
7
+http://www.fsij.org/gnuk/
8
+---
9
+ src/libopensc/card-openpgp.c | 61 ++++++++++++++++++++++++++++++++++----------
10
+ src/libopensc/cards.h        |  1 +
11
+ src/tools/openpgp-tool.c     |  9 +++++--
12
+ 3 files changed, 56 insertions(+), 15 deletions(-)
13
+
14
+diff --git a/src/libopensc/card-openpgp.c b/src/libopensc/card-openpgp.c
15
+index 743e79c..716052b 100644
16
+--- a/src/libopensc/card-openpgp.c
17
++++ b/src/libopensc/card-openpgp.c
18
+@@ -43,6 +43,7 @@
19
+ static struct sc_atr_table pgp_atrs[] = {
20
+ 	{ "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 },
21
+ 	{ "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 },
22
++	{ "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 },
23
+ 	{ NULL, NULL, NULL, 0, 0, NULL }
24
+ };
25
+ 
26
+@@ -307,6 +308,8 @@ pgp_init(sc_card_t *card)
27
+ 	int		r;
28
+ 	struct blob 	*child = NULL;
29
+ 
30
++	LOG_FUNC_CALLED(card->ctx);
31
++
32
+ 	priv = calloc (1, sizeof *priv);
33
+ 	if (!priv)
34
+ 		return SC_ERROR_OUT_OF_MEMORY;
35
+@@ -315,11 +318,11 @@ pgp_init(sc_card_t *card)
36
+ 	card->cla = 0x00;
37
+ 
38
+ 	/* set pointer to correct list of card objects */
39
+-	priv->pgp_objects = (card->type == SC_CARD_TYPE_OPENPGP_V2)
40
++	priv->pgp_objects = (card->type == SC_CARD_TYPE_OPENPGP_V2 || card->type == SC_CARD_TYPE_OPENPGP_GNUK)
41
+ 				? pgp2_objects : pgp1_objects;
42
+ 
43
+ 	/* set detailed card version */
44
+-	priv->bcd_version = (card->type == SC_CARD_TYPE_OPENPGP_V2)
45
++	priv->bcd_version = (card->type == SC_CARD_TYPE_OPENPGP_V2 || card->type == SC_CARD_TYPE_OPENPGP_GNUK)
46
+ 				? OPENPGP_CARD_2_0 : OPENPGP_CARD_1_1;
47
+ 
48
+ 	/* select application "OpenPGP" */
49
+@@ -428,7 +431,8 @@ pgp_get_card_features(sc_card_t *card)
50
+ 		if ((pgp_get_blob(card, blob73, 0x00c0, &blob) >= 0) &&
51
+ 		    (blob->data != NULL) && (blob->len > 0)) {
52
+ 			/* in v2.0 bit 0x04 in first byte means "algorithm attributes changeable */
53
+-			if ((blob->data[0] & 0x04) && (card->type == SC_CARD_TYPE_OPENPGP_V2))
54
++			if ((blob->data[0] & 0x04) &&
55
++			    (card->type == SC_CARD_TYPE_OPENPGP_V2 || card->type == SC_CARD_TYPE_OPENPGP_GNUK))
56
+ 				priv->ext_caps |= EXT_CAP_ALG_ATTR_CHANGEABLE;
57
+ 			/* bit 0x08 in first byte means "support for private use DOs" */
58
+ 			if (blob->data[0] & 0x08)
59
+@@ -445,7 +449,8 @@ pgp_get_card_features(sc_card_t *card)
60
+ 				priv->ext_caps |= EXT_CAP_GET_CHALLENGE;
61
+ 			}
62
+ 			/* in v2.0 bit 0x80 in first byte means "support Secure Messaging" */
63
+-			if ((blob->data[0] & 0x80) && (card->type == SC_CARD_TYPE_OPENPGP_V2))
64
++			if ((blob->data[0] & 0x80) &&
65
++			    (card->type == SC_CARD_TYPE_OPENPGP_V2 || card->type == SC_CARD_TYPE_OPENPGP_GNUK))
66
+ 				priv->ext_caps |= EXT_CAP_SM;
67
+ 
68
+ 			if ((priv->bcd_version >= OPENPGP_CARD_2_0) && (blob->len >= 10)) {
69
+@@ -1055,12 +1060,18 @@ static int
70
+ pgp_get_pubkey(sc_card_t *card, unsigned int tag, u8 *buf, size_t buf_len)
71
+ {
72
+ 	sc_apdu_t	apdu;
73
++	u8 apdu_case = SC_APDU_CASE_4;
74
+ 	u8		idbuf[2];
75
+ 	int		r;
76
+ 
77
+ 	sc_log(card->ctx, "called, tag=%04x\n", tag);
78
+ 
79
+-	sc_format_apdu(card, &apdu, SC_APDU_CASE_4, 0x47, 0x81, 0);
80
++	/* With Gnuk token, force to use short APDU */
81
++	if (card->type == SC_CARD_TYPE_OPENPGP_GNUK) {
82
++		apdu_case = SC_APDU_CASE_4_SHORT;
83
++	}
84
++
85
++	sc_format_apdu(card, &apdu, apdu_case, 0x47, 0x81, 0);
86
+ 	apdu.lc = 2;
87
+ 	apdu.data = ushort2bebytes(idbuf, tag);
88
+ 	apdu.datalen = 2;
89
+@@ -1152,6 +1163,7 @@ pgp_put_data(sc_card_t *card, unsigned int tag, const u8 *buf, size_t buf_len)
90
+ 	u8 ins = 0xDA;
91
+ 	u8 p1 = tag >> 8;
92
+ 	u8 p2 = tag & 0xFF;
93
++	u8 apdu_case = SC_APDU_CASE_3;
94
+ 	int r;
95
+ 
96
+ 	LOG_FUNC_CALLED(card->ctx);
97
+@@ -1193,13 +1205,17 @@ pgp_put_data(sc_card_t *card, unsigned int tag, const u8 *buf, size_t buf_len)
98
+ 
99
+ 	/* Build APDU */
100
+ 	if (buf != NULL && buf_len > 0) {
101
+-		sc_format_apdu(card, &apdu, SC_APDU_CASE_3, ins, p1, p2);
102
++		/* Force short APDU for Gnuk */
103
++		if (card->type == SC_CARD_TYPE_OPENPGP_GNUK) {
104
++			apdu_case = SC_APDU_CASE_3_SHORT;
105
++		}
106
++		sc_format_apdu(card, &apdu, apdu_case, ins, p1, p2);
107
+ 
108
+ 		/* if card/reader does not support extended APDUs, but chaining, then set it */
109
+ 		if (((card->caps & SC_CARD_CAP_APDU_EXT) == 0) && (priv->ext_caps & EXT_CAP_CHAINING))
110
+ 			apdu.flags |= SC_APDU_FLAGS_CHAINING;
111
+ 
112
+-		apdu.data = buf;
113
++		apdu.data = (u8 *)buf;
114
+ 		apdu.datalen = buf_len;
115
+ 		apdu.lc = buf_len;
116
+ 	}
117
+@@ -1326,6 +1342,7 @@ pgp_compute_signature(sc_card_t *card, const u8 *data,
118
+ 	struct pgp_priv_data	*priv = DRVDATA(card);
119
+ 	sc_security_env_t	*env = &priv->sec_env;
120
+ 	sc_apdu_t		apdu;
121
++	u8 apdu_case = SC_APDU_CASE_4;
122
+ 	int			r;
123
+ 
124
+ 	LOG_FUNC_CALLED(card->ctx);
125
+@@ -1334,14 +1351,19 @@ pgp_compute_signature(sc_card_t *card, const u8 *data,
126
+ 		LOG_TEST_RET(card->ctx, SC_ERROR_INVALID_ARGUMENTS,
127
+ 				"invalid operation");
128
+ 
129
++	/* Force short APDU for Gnuk Token */
130
++	if (card->type == SC_CARD_TYPE_OPENPGP_GNUK) {
131
++		apdu_case = SC_APDU_CASE_4_SHORT;
132
++	}
133
++
134
+ 	switch (env->key_ref[0]) {
135
+ 	case 0x00: /* signature key */
136
+ 		/* PSO SIGNATURE */
137
+-		sc_format_apdu(card, &apdu, SC_APDU_CASE_4, 0x2A, 0x9E, 0x9A);
138
++		sc_format_apdu(card, &apdu, apdu_case, 0x2A, 0x9E, 0x9A);
139
+ 		break;
140
+ 	case 0x02: /* authentication key */
141
+ 		/* INTERNAL AUTHENTICATE */
142
+-		sc_format_apdu(card, &apdu, SC_APDU_CASE_4, 0x88, 0, 0);
143
++		sc_format_apdu(card, &apdu, apdu_case, 0x88, 0, 0);
144
+ 		break;
145
+ 	case 0x01:
146
+ 	default:
147
+@@ -1350,7 +1372,7 @@ pgp_compute_signature(sc_card_t *card, const u8 *data,
148
+ 	}
149
+ 
150
+ 	apdu.lc = data_len;
151
+-	apdu.data = data;
152
++	apdu.data = (u8 *)data;
153
+ 	apdu.datalen = data_len;
154
+ 	apdu.le = ((outlen >= 256) && !(card->caps & SC_CARD_CAP_APDU_EXT)) ? 256 : outlen;
155
+ 	apdu.resp    = out;
156
+@@ -1374,6 +1396,7 @@ pgp_decipher(sc_card_t *card, const u8 *in, size_t inlen,
157
+ 	struct pgp_priv_data	*priv = DRVDATA(card);
158
+ 	sc_security_env_t	*env = &priv->sec_env;
159
+ 	sc_apdu_t	apdu;
160
++	u8 apdu_case = SC_APDU_CASE_4;
161
+ 	u8		*temp = NULL;
162
+ 	int		r;
163
+ 
164
+@@ -1398,7 +1421,7 @@ pgp_decipher(sc_card_t *card, const u8 *in, size_t inlen,
165
+ 	case 0x01: /* Decryption key */
166
+ 	case 0x02: /* authentication key */
167
+ 		/* PSO DECIPHER */
168
+-		sc_format_apdu(card, &apdu, SC_APDU_CASE_4, 0x2A, 0x80, 0x86);
169
++		sc_format_apdu(card, &apdu, apdu_case, 0x2A, 0x80, 0x86);
170
+ 		break;
171
+ 	case 0x00: /* signature key */
172
+ 	default:
173
+@@ -1407,8 +1430,13 @@ pgp_decipher(sc_card_t *card, const u8 *in, size_t inlen,
174
+ 				"invalid key reference");
175
+ 	}
176
+ 
177
++	/* Gnuk only supports short APDU, so we need to use command chaining */
178
++	if (card->type == SC_CARD_TYPE_OPENPGP_GNUK) {
179
++		apdu.flags |= SC_APDU_FLAGS_CHAINING;
180
++	}
181
++
182
+ 	apdu.lc = inlen;
183
+-	apdu.data = in;
184
++	apdu.data = (u8 *)in;
185
+ 	apdu.datalen = inlen;
186
+ 	apdu.le = ((outlen >= 256) && !(card->caps & SC_CARD_CAP_APDU_EXT)) ? 256 : outlen;
187
+ 	apdu.resp = out;
188
+@@ -1794,6 +1822,11 @@ static int pgp_gen_key(sc_card_t *card, sc_cardctl_openpgp_keygen_info_t *key_in
189
+ 		LOG_FUNC_RETURN(card->ctx, SC_ERROR_INVALID_ARGUMENTS);
190
+ 	}
191
+ 
192
++	if (card->type == SC_CARD_TYPE_OPENPGP_GNUK && key_info->modulus_len != 2048) {
193
++		sc_log(card->ctx, "Gnuk does not support other key length than 2048.");
194
++		LOG_FUNC_RETURN(card->ctx, SC_ERROR_INVALID_ARGUMENTS);
195
++	}
196
++
197
+ 	/* Set attributes for new-generated key */
198
+ 	r = pgp_update_new_algo_attr(card, key_info);
199
+ 	LOG_TEST_RET(card->ctx, r, "Cannot set attributes for new-generated key");
200
+@@ -1801,7 +1834,9 @@ static int pgp_gen_key(sc_card_t *card, sc_cardctl_openpgp_keygen_info_t *key_in
201
+ 	/* Test whether we will need extended APDU. 1900 is an
202
+ 	 * arbitrary modulus length which for sure fits into a short APDU.
203
+ 	 * This idea is borrowed from GnuPG code.  */
204
+-	if (card->caps & SC_CARD_CAP_APDU_EXT && key_info->modulus_len > 1900) {
205
++	if (card->caps & SC_CARD_CAP_APDU_EXT
206
++	    && key_info->modulus_len > 1900
207
++	    && card->type != SC_CARD_TYPE_OPENPGP_GNUK) {
208
+ 		/* We won't store to apdu variable yet, because it will be reset in
209
+ 		 * sc_format_apdu() */
210
+ 		apdu_le = card->max_recv_size;
211
+diff --git a/src/libopensc/cards.h b/src/libopensc/cards.h
212
+index 0fbf9ca..01b08fd 100644
213
+--- a/src/libopensc/cards.h
214
++++ b/src/libopensc/cards.h
215
+@@ -104,6 +104,7 @@ enum {
216
+ 	SC_CARD_TYPE_OPENPGP_BASE = 9000,
217
+ 	SC_CARD_TYPE_OPENPGP_V1,
218
+ 	SC_CARD_TYPE_OPENPGP_V2,
219
++	SC_CARD_TYPE_OPENPGP_GNUK,
220
+ 
221
+ 	/* jcop driver */
222
+ 	SC_CARD_TYPE_JCOP_BASE = 10000,
223
+diff --git a/src/tools/openpgp-tool.c b/src/tools/openpgp-tool.c
224
+index 7058aaa..8b5e327 100644
225
+--- a/src/tools/openpgp-tool.c
226
++++ b/src/tools/openpgp-tool.c
227
+@@ -32,6 +32,7 @@
228
+ #include "libopensc/asn1.h"
229
+ #include "libopensc/cards.h"
230
+ #include "libopensc/cardctl.h"
231
++#include "libopensc/log.h"
232
+ #include "util.h"
233
+ 
234
+ #define	OPT_RAW		256
235
+@@ -216,7 +217,7 @@ static void display_data(const struct ef_name_map *mapping, char *value)
236
+ 			} else {
237
+ 				const char *label = mapping->name;
238
+ 
239
+-				printf("%s:%*s%s\n", label, 10-strlen(label), "", value);
240
++				printf("%s:%*s%s\n", label, 10 - (int)strlen(label), "", value);
241
+ 			}
242
+ 		}
243
+ 	}
244
+@@ -390,6 +391,8 @@ int do_genkey(sc_card_t *card, u8 key_id, unsigned int key_len)
245
+ 	sc_path_t path;
246
+ 	sc_file_t *file;
247
+ 
248
++	LOG_FUNC_CALLED(card->ctx);
249
++
250
+ 	if (key_id < 1 || key_id > 3) {
251
+ 		printf("Unknown key ID %d.\n", key_id);
252
+ 		return 1;
253
+@@ -481,8 +484,10 @@ int main(int argc, char **argv)
254
+ 
255
+ 	/* check card type */
256
+ 	if ((card->type != SC_CARD_TYPE_OPENPGP_V1) &&
257
+-	    (card->type != SC_CARD_TYPE_OPENPGP_V2)) {
258
++	    (card->type != SC_CARD_TYPE_OPENPGP_V2) &&
259
++	    (card->type != SC_CARD_TYPE_OPENPGP_GNUK)) {
260
+ 		util_error("not an OpenPGP card");
261
++		sc_log(card->ctx, "Card type %X", card->type);
262
+ 		exit_status = EXIT_FAILURE;
263
+ 		goto out;
264
+ 	}
265
+-- 
266
+1.9.3
267
+

+ 50
- 0
utils/opensc/patches/0002-OpenPGP-Add-Gnuk-in-pkcs15-emulation-layer.patch View File

@@ -0,0 +1,50 @@
1
+From ecc6460d17147b37def27a9b776e1fc5a61408d0 Mon Sep 17 00:00:00 2001
2
+From: =?UTF-8?q?Nguy=E1=BB=85n=20H=E1=BB=93ng=20Qu=C3=A2n?=
3
+ <ng.hong.quan@gmail.com>
4
+Date: Fri, 12 Apr 2013 17:24:00 +0700
5
+Subject: [PATCH 02/18] OpenPGP: Add Gnuk in pkcs15 emulation layer.
6
+
7
+---
8
+ src/libopensc/pkcs15-openpgp.c | 6 ++++--
9
+ src/libopensc/pkcs15-syn.c     | 1 +
10
+ 2 files changed, 5 insertions(+), 2 deletions(-)
11
+
12
+diff --git a/src/libopensc/pkcs15-openpgp.c b/src/libopensc/pkcs15-openpgp.c
13
+index d9dc074..5a8a1ca 100644
14
+--- a/src/libopensc/pkcs15-openpgp.c
15
++++ b/src/libopensc/pkcs15-openpgp.c
16
+@@ -155,7 +155,8 @@ sc_pkcs15emu_openpgp_init(sc_pkcs15_card_t *p15card)
17
+ 	u8		c4data[10];
18
+ 	u8		c5data[70];
19
+ 	int		r, i;
20
+-	const pgp_pin_cfg_t *pin_cfg = (card->type == SC_CARD_TYPE_OPENPGP_V2) ? pin_cfg_v2 : pin_cfg_v1;
21
++	const pgp_pin_cfg_t *pin_cfg = (card->type == SC_CARD_TYPE_OPENPGP_V2 || card->type == SC_CARD_TYPE_OPENPGP_GNUK)
22
++	                               ? pin_cfg_v2 : pin_cfg_v1;
23
+ 	sc_path_t path;
24
+ 	sc_file_t *file;
25
+ 
26
+@@ -367,7 +368,8 @@ failed:	sc_debug(card->ctx, SC_LOG_DEBUG_NORMAL, "Failed to initialize OpenPGP e
27
+ 
28
+ static int openpgp_detect_card(sc_pkcs15_card_t *p15card)
29
+ {
30
+-	if (p15card->card->type == SC_CARD_TYPE_OPENPGP_V1 || p15card->card->type == SC_CARD_TYPE_OPENPGP_V2)
31
++	if (p15card->card->type == SC_CARD_TYPE_OPENPGP_V1 || p15card->card->type == SC_CARD_TYPE_OPENPGP_V2
32
++	    || p15card->card->type == SC_CARD_TYPE_OPENPGP_GNUK)
33
+ 		return SC_SUCCESS;
34
+ 	else
35
+ 		return SC_ERROR_WRONG_CARD;
36
+diff --git a/src/libopensc/pkcs15-syn.c b/src/libopensc/pkcs15-syn.c
37
+index e2f6004..a9f8c0b 100644
38
+--- a/src/libopensc/pkcs15-syn.c
39
++++ b/src/libopensc/pkcs15-syn.c
40
+@@ -112,6 +112,7 @@ int sc_pkcs15_is_emulation_only(sc_card_t *card)
41
+ 		case SC_CARD_TYPE_GEMSAFEV1_PTEID:
42
+ 		case SC_CARD_TYPE_OPENPGP_V1:
43
+ 		case SC_CARD_TYPE_OPENPGP_V2:
44
++		case SC_CARD_TYPE_OPENPGP_GNUK:
45
+ 		case SC_CARD_TYPE_SC_HSM:
46
+ 			return 1;
47
+ 		default:
48
+-- 
49
+1.9.3
50
+

+ 30
- 0
utils/opensc/patches/0003-OpenPGP-Include-private-DO-to-filesystem-at-driver-i.patch View File

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

+ 82
- 0
utils/opensc/patches/0004-PKCS15-OpenPGP-Declare-DATA-objects.patch View File

@@ -0,0 +1,82 @@
1
+From fbf8e392db4456de97796259a62ccb972fe24df8 Mon Sep 17 00:00:00 2001
2
+From: =?UTF-8?q?Nguy=E1=BB=85n=20H=E1=BB=93ng=20Qu=C3=A2n?=
3
+ <ng.hong.quan@gmail.com>
4
+Date: Tue, 26 Feb 2013 17:37:16 +0700
5
+Subject: [PATCH 04/18] PKCS15-OpenPGP: Declare DATA objects.
6
+
7
+Begin to support read/write DATA object for PKCS-OpenPGP binding.
8
+This object is used by TrueCrypt.
9
+---
10
+ src/libopensc/pkcs15-openpgp.c | 35 +++++++++++++++++++++++++++++++++++
11
+ 1 file changed, 35 insertions(+)
12
+
13
+diff --git a/src/libopensc/pkcs15-openpgp.c b/src/libopensc/pkcs15-openpgp.c
14
+index 5a8a1ca..9f239ef 100644
15
+--- a/src/libopensc/pkcs15-openpgp.c
16
++++ b/src/libopensc/pkcs15-openpgp.c
17
+@@ -36,6 +36,7 @@ typedef USHORT ushort;
18
+ #endif
19
+ 
20
+ int sc_pkcs15emu_openpgp_init_ex(sc_pkcs15_card_t *, sc_pkcs15emu_opt_t *);
21
++static int sc_pkcs15emu_openpgp_add_data(sc_pkcs15_card_t *);
22
+ 
23
+ 
24
+ #define	PGP_USER_PIN_FLAGS	(SC_PKCS15_PIN_FLAG_CASE_SENSITIVE \
25
+@@ -45,6 +46,8 @@ int sc_pkcs15emu_openpgp_init_ex(sc_pkcs15_card_t *, sc_pkcs15emu_opt_t *);
26
+ 				| SC_PKCS15_PIN_FLAG_UNBLOCK_DISABLED \
27
+ 				| SC_PKCS15_PIN_FLAG_SO_PIN)
28
+ 
29
++#define PGP_NUM_PRIVDO       4
30
++
31
+ typedef struct _pgp_pin_cfg {
32
+ 	const char	*label;
33
+ 	int		reference;
34
+@@ -359,6 +362,9 @@ sc_pkcs15emu_openpgp_init(sc_pkcs15_card_t *p15card)
35
+ 			goto failed;
36
+ 	}
37
+ 
38
++	/* PKCS#15 DATA object from OpenPGP private DOs */
39
++	r = sc_pkcs15emu_openpgp_add_data(p15card);
40
++
41
+ 	return 0;
42
+ 
43
+ failed:	sc_debug(card->ctx, SC_LOG_DEBUG_NORMAL, "Failed to initialize OpenPGP emulation: %s\n",
44
+@@ -366,6 +372,35 @@ failed:	sc_debug(card->ctx, SC_LOG_DEBUG_NORMAL, "Failed to initialize OpenPGP e
45
+ 	return r;
46
+ }
47
+ 
48
++static int
49
++sc_pkcs15emu_openpgp_add_data(sc_pkcs15_card_t *p15card)
50
++{
51
++	sc_context_t *ctx = p15card->card->ctx;
52
++	int i, r;
53
++
54
++	LOG_FUNC_CALLED(ctx);
55
++	/* There is 4 private DO from 0101 to 0104 */
56
++	for (i = 1; i <= PGP_NUM_PRIVDO; i++) {
57
++		sc_pkcs15_data_info_t dat_info;
58
++		sc_pkcs15_object_t dat_obj;
59
++		char name[8];
60
++		char path[9];
61
++		memset(&dat_info, 0, sizeof(dat_info));
62
++		memset(&dat_obj, 0, sizeof(dat_obj));
63
++
64
++		sprintf(name, "PrivDO%d", i);
65
++		sprintf(path, "3F00010%d", i);
66
++
67
++		sc_format_path(path, &dat_info.path);
68
++		strlcpy(dat_obj.label, name, sizeof(dat_obj.label));
69
++		strlcpy(dat_info.app_label, name, sizeof(dat_info.app_label));
70
++
71
++		sc_log(ctx, "Add %s data object", name);
72
++		r = sc_pkcs15emu_add_data_object(p15card, &dat_obj, &dat_info);
73
++	}
74
++	LOG_FUNC_RETURN(ctx, r);
75
++}
76
++
77
+ static int openpgp_detect_card(sc_pkcs15_card_t *p15card)
78
+ {
79
+ 	if (p15card->card->type == SC_CARD_TYPE_OPENPGP_V1 || p15card->card->type == SC_CARD_TYPE_OPENPGP_V2
80
+-- 
81
+1.9.3
82
+

+ 173
- 0
utils/opensc/patches/0005-OpenPGP-Support-erasing-reset-card.patch View File

@@ -0,0 +1,173 @@
1
+From 4cdc5f3102f5ad93d263eea2f8206bb5e9fffc6c Mon Sep 17 00:00:00 2001
2
+From: =?UTF-8?q?Nguy=E1=BB=85n=20H=E1=BB=93ng=20Qu=C3=A2n?=
3
+ <ng.hong.quan@gmail.com>
4
+Date: Mon, 4 Mar 2013 11:28:08 +0700
5
+Subject: [PATCH 05/18] OpenPGP: Support erasing (reset) card.
6
+
7
+Command: openpgp-tool --erase
8
+---
9
+ src/libopensc/card-openpgp.c | 64 ++++++++++++++++++++++++++++++++++++++++++++
10
+ src/tools/openpgp-tool.c     | 23 +++++++++++++++-
11
+ 2 files changed, 86 insertions(+), 1 deletion(-)
12
+
13
+diff --git a/src/libopensc/card-openpgp.c b/src/libopensc/card-openpgp.c
14
+index ead07ae..42a9684 100644
15
+--- a/src/libopensc/card-openpgp.c
16
++++ b/src/libopensc/card-openpgp.c
17
+@@ -2197,6 +2197,66 @@ out:
18
+ 
19
+ #endif /* ENABLE_OPENSSL */
20
+ 
21
++/**
22
++ * Erase card
23
++ **/
24
++static int pgp_erase_card(sc_card_t *card)
25
++{
26
++	sc_context_t *ctx = card->ctx;
27
++	u8 *apdustring[10] = {
28
++		"00:20:00:81:08:40:40:40:40:40:40:40:40",
29
++		"00:20:00:81:08:40:40:40:40:40:40:40:40",
30
++		"00:20:00:81:08:40:40:40:40:40:40:40:40",
31
++		"00:20:00:81:08:40:40:40:40:40:40:40:40",
32
++		"00:20:00:83:08:40:40:40:40:40:40:40:40",
33
++		"00:20:00:83:08:40:40:40:40:40:40:40:40",
34
++		"00:20:00:83:08:40:40:40:40:40:40:40:40",
35
++		"00:20:00:83:08:40:40:40:40:40:40:40:40",
36
++		"00:e6:00:00",
37
++		"00:44:00:00"
38
++	};
39
++	u8 buf[SC_MAX_APDU_BUFFER_SIZE];
40
++	u8 rbuf[SC_MAX_APDU_BUFFER_SIZE];
41
++	sc_apdu_t apdu;
42
++	size_t len0;
43
++	int commandsnum = 10;
44
++	int i, r;
45
++
46
++	LOG_FUNC_CALLED(ctx);
47
++
48
++	/* Check card version */
49
++	if (card->type != SC_CARD_TYPE_OPENPGP_V2) {
50
++		sc_log(ctx, "Card is not OpenPGP v2");
51
++		LOG_FUNC_RETURN(ctx, SC_ERROR_NO_CARD_SUPPORT);
52
++	}
53
++	sc_log(ctx, "Card is OpenPGP v2. Erase card.");
54
++
55
++	/* Iterate over 10 commands above */
56
++	for (i = 0; i < commandsnum; i++) {
57
++		/* Convert the string to binary array */
58
++		len0 = sizeof(buf);
59
++		sc_hex_to_bin(apdustring[i], buf, &len0);
60
++		printf("Sending: ");
61
++		for (r = 0; r < len0; r++)
62
++			printf("%02X ", buf[r]);
63
++		printf("\n");
64
++
65
++		/* Build APDU from binary array */
66
++		r = sc_bytes2apdu(card->ctx, buf, len0, &apdu);
67
++		if (r) {
68
++			sc_log(ctx, "Failed to build APDU");
69
++			LOG_FUNC_RETURN(ctx, SC_ERROR_INTERNAL);
70
++		}
71
++		apdu.resp = rbuf;
72
++		apdu.resplen = sizeof(rbuf);
73
++
74
++		/* Send APDU to card */
75
++		r = sc_transmit_apdu(card, &apdu);
76
++		LOG_TEST_RET(ctx, r, "Transmiting APDU failed");
77
++	}
78
++	LOG_FUNC_RETURN(ctx, r);
79
++}
80
++
81
+ /* ABI: card ctl: perform special card-specific operations */
82
+ static int pgp_card_ctl(sc_card_t *card, unsigned long cmd, void *ptr)
83
+ {
84
+@@ -2221,6 +2281,10 @@ static int pgp_card_ctl(sc_card_t *card, unsigned long cmd, void *ptr)
85
+ 		LOG_FUNC_RETURN(card->ctx, r);
86
+ 		break;
87
+ #endif /* ENABLE_OPENSSL */
88
++	case SC_CARDCTL_ERASE_CARD:
89
++		r = pgp_erase_card(card);
90
++		LOG_FUNC_RETURN(card->ctx, r);
91
++		break;
92
+ 	}
93
+ 
94
+ 	LOG_FUNC_RETURN(card->ctx, SC_ERROR_NOT_SUPPORTED);
95
+diff --git a/src/tools/openpgp-tool.c b/src/tools/openpgp-tool.c
96
+index 8b5e327..0d360a3 100644
97
+--- a/src/tools/openpgp-tool.c
98
++++ b/src/tools/openpgp-tool.c
99
+@@ -76,6 +76,7 @@ static int opt_verify = 0;
100
+ static char *verifytype = NULL;
101
+ static int opt_pin = 0;
102
+ static char *pin = NULL;
103
++static int opt_erase = 0;
104
+ 
105
+ static const char *app_name = "openpgp-tool";
106
+ 
107
+@@ -92,6 +93,7 @@ static const struct option options[] = {
108
+ 	{ "help",      no_argument,       NULL, 'h'        },
109
+ 	{ "verbose",   no_argument,       NULL, 'v'        },
110
+ 	{ "version",   no_argument,       NULL, 'V'        },
111
++	{ "erase",     no_argument,       NULL, 'E'        },
112
+ 	{ "verify",    required_argument, NULL, OPT_VERIFY },
113
+ 	{ "pin",       required_argument, NULL, OPT_PIN },
114
+ 	{ NULL, 0, NULL, 0 }
115
+@@ -110,6 +112,7 @@ static const char *option_help[] = {
116
+ /* h */	"Print this help message",
117
+ /* v */	"Verbose operation. Use several times to enable debug output.",
118
+ /* V */	"Show version number",
119
++/* E */	"Erase (reset) the card",
120
+ 	"Verify PIN (CHV1, CHV2, CHV3...)",
121
+ 	"PIN string"
122
+ };
123
+@@ -228,7 +231,7 @@ static int decode_options(int argc, char **argv)
124
+ {
125
+ 	int c;
126
+ 
127
+-	while ((c = getopt_long(argc, argv,"r:x:CUG:L:hwvV", options, (int *) 0)) != EOF) {
128
++	while ((c = getopt_long(argc, argv,"r:x:CUG:L:hwvVE", options, (int *) 0)) != EOF) {
129
+ 		switch (c) {
130
+ 		case 'r':
131
+ 			opt_reader = optarg;
132
+@@ -288,6 +291,9 @@ static int decode_options(int argc, char **argv)
133
+ 			show_version();
134
+ 			exit(EXIT_SUCCESS);
135
+ 			break;
136
++		case 'E':
137
++			opt_erase++;
138
++			break;
139
+ 		default:
140
+ 			util_print_usage_and_die(app_name, options, option_help, NULL);
141
+ 		}
142
+@@ -446,6 +452,18 @@ int do_verify(sc_card_t *card, u8 *type, u8* pin)
143
+ 	return r;
144
+ }
145
+ 
146
++int do_erase(sc_card_t *card)
147
++{
148
++	int r;
149
++	/* Check card version */
150
++	if (card->type != SC_CARD_TYPE_OPENPGP_V2) {
151
++		printf("Do not erase card which is not OpenPGP v2\n");
152
++	}
153
++	printf("Erase card\n");
154
++	r = sc_card_ctl(card, SC_CARDCTL_ERASE_CARD, NULL);
155
++	return r;
156
++}
157
++
158
+ int main(int argc, char **argv)
159
+ {
160
+ 	sc_context_t *ctx = NULL;
161
+@@ -521,6 +539,9 @@ int main(int argc, char **argv)
162
+ 		exit(EXIT_FAILURE);
163
+ 	}
164
+ 
165
++	if (opt_erase)
166
++		exit_status != do_erase(card);
167
++
168
+ out:
169
+ 	sc_unlock(card);
170
+ 	sc_disconnect_card(card);
171
+-- 
172
+1.9.3
173
+

+ 210
- 0
utils/opensc/patches/0006-openpgp-tool-Support-deleting-key-in-Gnuk.patch View File

@@ -0,0 +1,210 @@
1
+From bbbedd3b358f80a7f98df2b22cf541cb007dd62e Mon Sep 17 00:00:00 2001
2
+From: =?UTF-8?q?Nguy=E1=BB=85n=20H=E1=BB=93ng=20Qu=C3=A2n?=
3
+ <ng.hong.quan@gmail.com>
4
+Date: Mon, 4 Mar 2013 18:13:03 +0700
5
+Subject: [PATCH 06/18] openpgp-tool: Support deleting key in Gnuk.
6
+
7
+---
8
+ src/tools/openpgp-tool.c | 144 ++++++++++++++++++++++++++++++++++++++++++++++-
9
+ 1 file changed, 143 insertions(+), 1 deletion(-)
10
+
11
+diff --git a/src/tools/openpgp-tool.c b/src/tools/openpgp-tool.c
12
+index 0d360a3..239c86b 100644
13
+--- a/src/tools/openpgp-tool.c
14
++++ b/src/tools/openpgp-tool.c
15
+@@ -39,6 +39,7 @@
16
+ #define	OPT_PRETTY	257
17
+ #define	OPT_VERIFY	258
18
+ #define	OPT_PIN	    259
19
++#define	OPT_DELKEY  260
20
+ 
21
+ /* define structures */
22
+ struct ef_name_map {
23
+@@ -77,6 +78,7 @@ static char *verifytype = NULL;
24
+ static int opt_pin = 0;
25
+ static char *pin = NULL;
26
+ static int opt_erase = 0;
27
++static int opt_delkey = 0;
28
+ 
29
+ static const char *app_name = "openpgp-tool";
30
+ 
31
+@@ -96,6 +98,7 @@ static const struct option options[] = {
32
+ 	{ "erase",     no_argument,       NULL, 'E'        },
33
+ 	{ "verify",    required_argument, NULL, OPT_VERIFY },
34
+ 	{ "pin",       required_argument, NULL, OPT_PIN },
35
++	{ "del-key",   required_argument, NULL, OPT_DELKEY },
36
+ 	{ NULL, 0, NULL, 0 }
37
+ };
38
+ 
39
+@@ -114,7 +117,8 @@ static const char *option_help[] = {
40
+ /* V */	"Show version number",
41
+ /* E */	"Erase (reset) the card",
42
+ 	"Verify PIN (CHV1, CHV2, CHV3...)",
43
+-	"PIN string"
44
++	"PIN string",
45
++	"Delete key (1, 2, 3 or all)"
46
+ };
47
+ 
48
+ static const struct ef_name_map openpgp_data[] = {
49
+@@ -294,6 +298,14 @@ static int decode_options(int argc, char **argv)
50
+ 		case 'E':
51
+ 			opt_erase++;
52
+ 			break;
53
++		case OPT_DELKEY:
54
++			opt_delkey++;
55
++			if (strcmp(optarg, "all") != 0)   /* Arg string is not 'all' */
56
++				key_id = optarg[0] - '0';
57
++			else                              /* Arg string is 'all' */
58
++				key_id = 'a';
59
++			actions++;
60
++			break;
61
+ 		default:
62
+ 			util_print_usage_and_die(app_name, options, option_help, NULL);
63
+ 		}
64
+@@ -452,6 +464,133 @@ int do_verify(sc_card_t *card, u8 *type, u8* pin)
65
+ 	return r;
66
+ }
67
+ 
68
++/**
69
++ * Delete key, for Gnuk.
70
++ **/
71
++int delete_key_gnuk(sc_card_t *card, u8 key_id)
72
++{
73
++	sc_context_t *ctx = card->ctx;
74
++	int r = SC_SUCCESS;
75
++	u8 *data = NULL;
76
++
77
++	/* Delete fingerprint */
78
++	sc_log(ctx, "Delete fingerprints");
79
++	r |= sc_put_data(card, 0xC6 + key_id, NULL, 0);
80
++	/* Delete creation time */
81
++	sc_log(ctx, "Delete creation time");
82
++	r |= sc_put_data(card, 0xCD + key_id, NULL, 0);
83
++
84
++	/* Rewrite Extended Header List */
85
++	sc_log(ctx, "Rewrite Extended Header List");
86
++
87
++	if (key_id == 1)
88
++		data = "\x4D\x02\xB6";
89
++	else if (key_id == 2)
90
++		data = "\x4D\x02\xB8";
91
++	else if (key_id == 3)
92
++		data = "\x4D\x02\xA4";
93
++	else
94
++		return SC_ERROR_INVALID_ARGUMENTS;
95
++
96
++	r |= sc_put_data(card, 0x4D, data, strlen(data) + 1);
97
++	return r;
98
++}
99
++
100
++/**
101
++ * Delete key, for OpenPGP card.
102
++ * This function is not complete and is reserved for future version (> 2) of OpenPGP card.
103
++ **/
104
++int delete_key_openpgp(sc_card_t *card, u8 key_id)
105
++{
106
++	sc_context_t *ctx = card->ctx;
107
++	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";
108
++	char *del_creationtime = "00:DA:00:CD:04:00:00:00:00";
109
++	/* We need to replace the 4th byte later */
110
++	char *apdustring = NULL;
111
++	u8 buf[SC_MAX_APDU_BUFFER_SIZE];
112
++	u8 rbuf[SC_MAX_APDU_BUFFER_SIZE];
113
++	sc_apdu_t apdu;
114
++	size_t len0;
115
++	int i;
116
++	int r = SC_SUCCESS;
117
++
118
++	for (i = 0; i < 2; i++) {
119
++		if (i == 0)    /* Reset fingerprint */
120
++			apdustring = del_fingerprint;
121
++		else           /* Reset creation time */
122
++			apdustring = del_creationtime;
123
++		/* Convert the string to binary array */
124
++		len0 = sizeof(buf);
125
++		sc_hex_to_bin(apdustring, buf, &len0);
126
++
127
++		/* Replace DO tag, subject to key ID */
128
++		buf[3] = buf[3] + key_id;
129
++
130
++		/* Build APDU from binary array */
131
++		r = sc_bytes2apdu(card->ctx, buf, len0, &apdu);
132
++		if (r) {
133
++			sc_log(ctx, "Failed to build APDU");
134
++			LOG_FUNC_RETURN(ctx, SC_ERROR_INTERNAL);
135
++		}
136
++		apdu.resp = rbuf;
137
++		apdu.resplen = sizeof(rbuf);
138
++
139
++		/* Send APDU to card */
140
++		r = sc_transmit_apdu(card, &apdu);
141
++		LOG_TEST_RET(ctx, r, "Transmiting APDU failed");
142
++	}
143
++	/* TODO: Rewrite Extended Header List.
144
++	 * Not support by OpenGPG v2 yet */
145
++	LOG_FUNC_RETURN(ctx, r);
146
++}
147
++
148
++int delete_key(sc_card_t *card, u8 key_id)
149
++{
150
++	sc_context_t *ctx = card->ctx;
151
++	int r;
152
++
153
++	LOG_FUNC_CALLED(ctx);
154
++	/* Check key ID */
155
++	if (key_id < 1 || key_id > 3) {
156
++		sc_log(ctx, "Invalid key ID %d", key_id);
157
++		LOG_FUNC_RETURN(ctx, SC_ERROR_INVALID_ARGUMENTS);
158
++	}
159
++
160
++	if (card->type == SC_CARD_TYPE_OPENPGP_GNUK)
161
++		r = delete_key_gnuk(card, key_id);
162
++	else
163
++		r = delete_key_openpgp(card, key_id);
164
++
165
++	LOG_FUNC_RETURN(ctx, r);
166
++}
167
++
168
++int do_delete_key(sc_card_t *card, u8 key_id)
169
++{
170
++	sc_context_t *ctx = card->ctx;
171
++	int r = SC_SUCCESS;
172
++
173
++	/* Currently, only Gnuk supports deleting keys */
174
++	if (card->type != SC_CARD_TYPE_OPENPGP_GNUK) {
175
++		printf("Only Gnuk supports deleting keys. General OpenPGP doesn't.");
176
++		return SC_ERROR_NOT_SUPPORTED;
177
++	}
178
++
179
++	if (key_id < 1 || (key_id > 3 && key_id != 'a')) {
180
++		printf("Error: Invalid key id %d", key_id);
181
++		return SC_ERROR_INVALID_ARGUMENTS;
182
++	}
183
++	if (key_id == 1 || key_id == 'a') {
184
++		r |= delete_key(card, 1);
185
++	}
186
++	if (key_id == 2 || key_id == 'a') {
187
++		r |= delete_key(card, 2);
188
++	}
189
++	if (key_id == 3 || key_id == 'a') {
190
++		r |= delete_key(card, 3);
191
++	}
192
++	return r;
193
++}
194
++
195
+ int do_erase(sc_card_t *card)
196
+ {
197
+ 	int r;
198
+@@ -539,6 +678,9 @@ int main(int argc, char **argv)
199
+ 		exit(EXIT_FAILURE);
200
+ 	}
201
+ 
202
++	if (opt_delkey)
203
++		exit_status != do_delete_key(card, key_id);
204
++
205
+ 	if (opt_erase)
206
+ 		exit_status != do_erase(card);
207
+ 
208
+-- 
209
+1.9.3
210
+

+ 27
- 0
utils/opensc/patches/0007-OpenPGP-Correct-building-Extended-Header-List-when-i.patch View File

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

+ 58
- 0
utils/opensc/patches/0008-OpenPGP-Read-some-empty-DOs-from-Gnuk.patch View File

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

+ 53
- 0
utils/opensc/patches/0009-PKCS15-OpenPGP-Do-not-show-empty-DO-in-pkcs15-emu_in.patch View File

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

+ 91
- 0
utils/opensc/patches/0010-PKCS15-OpenPGP-Allow-to-store-data-to-pkcs15-data-ob.patch View File

@@ -0,0 +1,91 @@
1
+From 88ded8fc5802c073caa71b649cee5a3116699b2a Mon Sep 17 00:00:00 2001
2
+From: =?UTF-8?q?Nguy=E1=BB=85n=20H=E1=BB=93ng=20Qu=C3=A2n?=
3
+ <ng.hong.quan@gmail.com>
4
+Date: Wed, 27 Mar 2013 11:39:33 +0700
5
+Subject: [PATCH 10/18] PKCS15-OpenPGP: Allow to store data to pkcs15 data
6
+ object.
7
+
8
+Only one DO is supported now.
9
+---
10
+ src/libopensc/pkcs15-openpgp.c  |  2 +-
11
+ src/pkcs15init/pkcs15-openpgp.c | 38 +++++++++++++++++++++++++++++++++++++-
12
+ 2 files changed, 38 insertions(+), 2 deletions(-)
13
+
14
+diff --git a/src/libopensc/pkcs15-openpgp.c b/src/libopensc/pkcs15-openpgp.c
15
+index 850dd74..b701041 100644
16
+--- a/src/libopensc/pkcs15-openpgp.c
17
++++ b/src/libopensc/pkcs15-openpgp.c
18
+@@ -397,7 +397,7 @@ sc_pkcs15emu_openpgp_add_data(sc_pkcs15_card_t *p15card)
19
+ 		 */
20
+ 		r = read_file(p15card->card, path, content, sizeof(content));
21
+ 		if (r <= 0 ) {
22
+-			sc_log(ctx, "Cannot read DO 010%d or there is no data in it", i);
23
++			sc_log(ctx, "No data get from DO 010%d", i);
24
+ 			/* Skip */
25
+ 			continue;
26
+ 		}
27
+diff --git a/src/pkcs15init/pkcs15-openpgp.c b/src/pkcs15init/pkcs15-openpgp.c
28
+index f3a4962..1455580 100755
29
+--- a/src/pkcs15init/pkcs15-openpgp.c
30
++++ b/src/pkcs15init/pkcs15-openpgp.c
31
+@@ -236,13 +236,16 @@ static int openpgp_emu_update_tokeninfo(sc_profile_t *profile, sc_pkcs15_card_t
32
+ }
33
+ 
34
+ static int openpgp_store_data(struct sc_pkcs15_card *p15card, struct sc_profile *profile,
35
+-                              struct sc_pkcs15_object *obj,	struct sc_pkcs15_der *content,
36
++                              struct sc_pkcs15_object *obj, struct sc_pkcs15_der *content,
37
+                               struct sc_path *path)
38
+ {
39
+ 	sc_card_t *card = p15card->card;
40
++	sc_context_t *ctx = card->ctx;
41
+ 	sc_file_t *file;
42
+ 	sc_pkcs15_cert_info_t *cinfo;
43
+ 	sc_pkcs15_id_t *cid;
44
++	sc_pkcs15_data_info_t *dinfo;
45
++	u8 buf[254];
46
+ 	int r;
47
+ 
48
+ 	LOG_FUNC_CALLED(card->ctx);
49
+@@ -282,6 +285,39 @@ static int openpgp_store_data(struct sc_pkcs15_card *p15card, struct sc_profile
50
+ 			                     content->len, 0);
51
+ 		break;
52
+ 
53
++	case SC_PKCS15_TYPE_DATA_OBJECT:
54
++		dinfo = (sc_pkcs15_data_info_t *) obj->data;
55
++		/* dinfo->app_label contains filename */
56
++		sc_log(ctx, "===== App label %s", dinfo->app_label);
57
++		/* Currently, we only support DO 0101. The reason is that when initializing this
58
++		 * pkcs15 emulation, PIN authentication is not applied and we can expose only this DO,
59
++		 * which is "read always".
60
++		 * If we support other DOs, they will not be exposed, and not helpful to user.
61
++		 * I haven't found a way to refresh the list of exposed DOs after verifying PIN yet.
62
++		 * http://sourceforge.net/mailarchive/message.php?msg_id=30646373
63
++		 **/
64
++		sc_log(ctx, "About to write to DO 0101");
65
++		sc_format_path("0101", path);
66
++		r = sc_select_file(card, path, &file);
67
++		LOG_TEST_RET(card->ctx, r, "Cannot select private DO");
68
++		r = sc_read_binary(card, 0, buf, sizeof(buf), 0);
69
++		if (r < 0) {
70
++			sc_log(ctx, "Cannot read DO 0101");
71
++			break;
72
++		}
73
++		if (r > 0) {
74
++			sc_log(ctx, "DO 0101 is full.");
75
++			r = SC_ERROR_TOO_MANY_OBJECTS;
76
++			break;
77
++		}
78
++		r = sc_pkcs15init_authenticate(profile, p15card, file, SC_AC_OP_UPDATE);
79
++		if (r >= 0 && content->len) {
80
++			r = sc_update_binary(p15card->card, 0,
81
++			                     (const unsigned char *) content->value,
82
++			                     content->len, 0);
83
++		}
84
++		break;
85
++
86
+ 	default:
87
+ 		r = SC_ERROR_NOT_IMPLEMENTED;
88
+ 	}
89
+-- 
90
+1.9.3
91
+

+ 87
- 0
utils/opensc/patches/0011-OpenPGP-Provide-enough-buffer-to-read-pubkey-from-Gn.patch View File

@@ -0,0 +1,87 @@
1
+From 7231ee09bb628f0401939778decce818ef6e3665 Mon Sep 17 00:00:00 2001
2
+From: =?UTF-8?q?Nguy=E1=BB=85n=20H=E1=BB=93ng=20Qu=C3=A2n?=
3
+ <ng.hong.quan@gmail.com>
4
+Date: Fri, 5 Apr 2013 17:18:50 +0700
5
+Subject: [PATCH 11/18] OpenPGP: Provide enough buffer to read pubkey from
6
+ Gnuk.
7
+
8
+---
9
+ src/libopensc/card-openpgp.c | 28 +++++++++++++++++++++++-----
10
+ 1 file changed, 23 insertions(+), 5 deletions(-)
11
+
12
+diff --git a/src/libopensc/card-openpgp.c b/src/libopensc/card-openpgp.c
13
+index 9b08bbb..8a1a270 100644
14
+--- a/src/libopensc/card-openpgp.c
15
++++ b/src/libopensc/card-openpgp.c
16
+@@ -263,7 +263,12 @@ static struct do_info		pgp2_objects[] = {	/* OpenPGP card spec 2.0 */
17
+ 
18
+ /* The DO holding X.509 certificate is constructed but does not contain child DO.
19
+  * We should notice this when building fake file system later. */
20
+-#define DO_CERT		0x7f21
21
++#define DO_CERT                  0x7f21
22
++/* Maximum length for response buffer when reading pubkey. This value is calculated with
23
++ * 4096-bit key length */
24
++#define MAXLEN_RESP_PUBKEY       527
25
++/* Gnuk only support 1 key length (2048 bit) */
26
++#define MAXLEN_RESP_PUBKEY_GNUK  271
27
+ 
28
+ #define DRVDATA(card)        ((struct pgp_priv_data *) ((card)->drv_data))
29
+ struct pgp_priv_data {
30
+@@ -729,6 +734,14 @@ pgp_read_blob(sc_card_t *card, struct blob *blob)
31
+ 		u8 	buffer[2048];
32
+ 		size_t	buf_len = (card->caps & SC_CARD_CAP_APDU_EXT)
33
+ 				  ? sizeof(buffer) : 256;
34
++
35
++		/* Buffer length for Gnuk pubkey */
36
++		if (card->type == SC_CARD_TYPE_OPENPGP_GNUK &&
37
++		    (blob->id == 0xa400 || blob->id == 0xb600 || blob->id == 0xb800
38
++		     || blob->id == 0xa401 || blob->id == 0xb601 || blob->id == 0xb801)) {
39
++			buf_len = MAXLEN_RESP_PUBKEY_GNUK;
40
++		}
41
++
42
+ 		int	r = blob->info->get_fn(card, blob->id, buffer, buf_len);
43
+ 
44
+ 		if (r < 0) {	/* an error occurred */
45
+@@ -1830,6 +1843,7 @@ static int pgp_gen_key(sc_card_t *card, sc_cardctl_openpgp_keygen_info_t *key_in
46
+ 	u8 apdu_case;
47
+ 	u8 *apdu_data;
48
+ 	size_t apdu_le;
49
++	size_t resplen = 0;
50
+ 	int r = SC_SUCCESS;
51
+ 
52
+ 	LOG_FUNC_CALLED(card->ctx);
53
+@@ -1868,23 +1882,27 @@ static int pgp_gen_key(sc_card_t *card, sc_cardctl_openpgp_keygen_info_t *key_in
54
+ 		apdu_case = SC_APDU_CASE_4_EXT;
55
+ 	}
56
+ 	else {
57
+-		apdu_le = 256;
58
+ 		apdu_case = SC_APDU_CASE_4_SHORT;
59
++		apdu_le = 256;
60
++		resplen = MAXLEN_RESP_PUBKEY;
61
++	}
62
++	if (card->type == SC_CARD_TYPE_OPENPGP_GNUK) {
63
++		resplen = MAXLEN_RESP_PUBKEY_GNUK;
64
+ 	}
65
+ 
66
+ 	/* Prepare APDU */
67
+-	sc_format_apdu(card, &apdu, apdu_case, 0x47, 0x80,  0);
68
++	sc_format_apdu(card, &apdu, apdu_case, 0x47, 0x80, 0);
69
+ 	apdu.data = apdu_data;
70
+ 	apdu.datalen = 2;  /* Data = B600 */
71
+ 	apdu.lc = 2;
72
+ 	apdu.le = apdu_le;
73
+ 
74
+ 	/* Buffer to receive response */
75
+-	apdu.resp = calloc(apdu.le, 1);
76
++	apdu.resplen = (resplen > 0) ? resplen : apdu_le;
77
++	apdu.resp = calloc(apdu.resplen, 1);
78
+ 	if (apdu.resp == NULL) {
79
+ 		LOG_FUNC_RETURN(card->ctx, SC_ERROR_NOT_ENOUGH_MEMORY);
80
+ 	}
81
+-	apdu.resplen = apdu.le;
82
+ 
83
+ 	/* Send */
84
+ 	sc_log(card->ctx, "Waiting for the card to generate key...");
85
+-- 
86
+1.9.3
87
+

+ 220
- 0
utils/opensc/patches/0012-OpenPGP-Support-write-certificate-for-Gnuk.patch View File

@@ -0,0 +1,220 @@
1
+From d8f63eb6fcc1441c12a44850da2fa22a6fe81634 Mon Sep 17 00:00:00 2001
2
+From: =?UTF-8?q?Nguy=E1=BB=85n=20H=E1=BB=93ng=20Qu=C3=A2n?=
3
+ <ng.hong.quan@gmail.com>
4
+Date: Thu, 11 Apr 2013 11:47:51 +0700
5
+Subject: [PATCH 12/18] OpenPGP: Support write certificate for Gnuk.
6
+
7
+---
8
+ src/libopensc/card-openpgp.c | 158 +++++++++++++++++++++++++++++++++----------
9
+ 1 file changed, 123 insertions(+), 35 deletions(-)
10
+
11
+diff --git a/src/libopensc/card-openpgp.c b/src/libopensc/card-openpgp.c
12
+index 8a1a270..d9db948 100644
13
+--- a/src/libopensc/card-openpgp.c
14
++++ b/src/libopensc/card-openpgp.c
15
+@@ -725,6 +725,8 @@ pgp_iterate_blobs(struct blob *blob, int level, void (*func)())
16
+ static int
17
+ pgp_read_blob(sc_card_t *card, struct blob *blob)
18
+ {
19
++	struct pgp_priv_data *priv = DRVDATA (card);
20
++
21
+ 	if (blob->data != NULL)
22
+ 		return SC_SUCCESS;
23
+ 	if (blob->info == NULL)
24
+@@ -735,6 +737,11 @@ pgp_read_blob(sc_card_t *card, struct blob *blob)
25
+ 		size_t	buf_len = (card->caps & SC_CARD_CAP_APDU_EXT)
26
+ 				  ? sizeof(buffer) : 256;
27
+ 
28
++		/* Buffer length for certificate */
29
++		if (blob->id == DO_CERT && priv->max_cert_size > 0) {
30
++			buf_len = MIN(priv->max_cert_size, sizeof(buffer));
31
++		}
32
++
33
+ 		/* Buffer length for Gnuk pubkey */
34
+ 		if (card->type == SC_CARD_TYPE_OPENPGP_GNUK &&
35
+ 		    (blob->id == 0xa400 || blob->id == 0xb600 || blob->id == 0xb800
36
+@@ -1190,49 +1197,75 @@ pgp_get_data(sc_card_t *card, unsigned int tag, u8 *buf, size_t buf_len)
37
+ 	LOG_FUNC_RETURN(card->ctx, apdu.resplen);
38
+ }
39
+ 
40
+-/* ABI: PUT DATA */
41
+-static int
42
+-pgp_put_data(sc_card_t *card, unsigned int tag, const u8 *buf, size_t buf_len)
43
++
44
++/* Internal: Write certificate for Gnuk */
45
++static int gnuk_write_certificate(sc_card_t *card, const u8 *buf, size_t length)
46
+ {
47
++	sc_context_t *ctx = card->ctx;
48
++	size_t i = 0;
49
+ 	sc_apdu_t apdu;
50
++	u8 *part;
51
++	size_t plen;
52
++	int r = SC_SUCCESS;
53
++
54
++	LOG_FUNC_CALLED(ctx);
55
++
56
++	/* If null data is passed, delete certificate */
57
++	if (buf == NULL || length == 0) {
58
++		sc_format_apdu(card, &apdu, SC_APDU_CASE_1, 0xD6, 0x85, 0);
59
++		r = sc_transmit_apdu(card, &apdu);
60
++		LOG_TEST_RET(card->ctx, r, "APDU transmit failed");
61
++		/* Check response */
62
++		r = sc_check_sw(card, apdu.sw1, apdu.sw2);
63
++		LOG_FUNC_RETURN(card->ctx, length);
64
++	}
65
++
66
++	/* Ref: gnuk_put_binary_libusb.py and gnuk_token.py in Gnuk source tree */
67
++	/* Split data to segments of 256 bytes. Send each segment via command chaining,
68
++	 * with particular P1 byte for each segment */
69
++	while (i*256 < length) {
70
++		part = (u8 *)buf + i*256;
71
++		plen = MIN(length - i*256, 256);
72
++
73
++		sc_log(card->ctx, "Write part %d from offset 0x%X, len %d", i+1, part, plen);
74
++
75
++		if (i == 0) {
76
++			sc_format_apdu(card, &apdu, SC_APDU_CASE_3_SHORT, 0xD6, 0x85, 0);
77
++		}
78
++		else {
79
++			sc_format_apdu(card, &apdu, SC_APDU_CASE_3_SHORT, 0xD6, i, 0);
80
++		}
81
++		apdu.flags |= SC_APDU_FLAGS_CHAINING;
82
++		apdu.data = part;
83
++		apdu.datalen = apdu.lc = plen;
84
++
85
++		r = sc_transmit_apdu(card, &apdu);
86
++		LOG_TEST_RET(card->ctx, r, "APDU transmit failed");
87
++		/* Check response */
88
++		r = sc_check_sw(card, apdu.sw1, apdu.sw2);
89
++		LOG_TEST_RET(card->ctx, r, "UPDATE BINARY returned error");
90
++
91
++		/* To next part */
92
++		i++;
93
++	}
94
++	LOG_FUNC_RETURN(card->ctx, length);
95
++}
96
++
97
++
98
++/* Internal: Use PUT DATA command to write */
99
++static int
100
++pgp_put_data_plain(sc_card_t *card, unsigned int tag, const u8 *buf, size_t buf_len)
101
++{
102
+ 	struct pgp_priv_data *priv = DRVDATA(card);
103
+-	struct blob *affected_blob = NULL;
104
+-	struct do_info *dinfo = NULL;
105
++	sc_context_t *ctx = card->ctx;
106
++	sc_apdu_t apdu;
107
+ 	u8 ins = 0xDA;
108
+ 	u8 p1 = tag >> 8;
109
+ 	u8 p2 = tag & 0xFF;
110
+ 	u8 apdu_case = SC_APDU_CASE_3;
111
+ 	int r;
112
+ 
113
+-	LOG_FUNC_CALLED(card->ctx);
114
+-
115
+-	/* Check if the tag is writable */
116
+-	affected_blob = pgp_find_blob(card, tag);
117
+-
118
+-	/* Non-readable DOs have no represented blob, we have to check from pgp_get_info_by_tag */
119
+-	if (affected_blob == NULL)
120
+-		dinfo = pgp_get_info_by_tag(card, tag);
121
+-	else
122
+-		dinfo = affected_blob->info;
123
+-
124
+-	if (dinfo == NULL) {
125
+-		sc_log(card->ctx, "The DO %04X does not exist.", tag);
126
+-		LOG_FUNC_RETURN(card->ctx, SC_ERROR_INVALID_ARGUMENTS);
127
+-	}
128
+-	else if ((dinfo->access & WRITE_MASK) == WRITE_NEVER) {
129
+-		sc_log(card->ctx, "DO %04X is not writable.", tag);
130
+-		LOG_FUNC_RETURN(card->ctx, SC_ERROR_NOT_ALLOWED);
131
+-	}
132
+-
133
+-	/* Check data size.
134
+-	 * We won't check other DOs than 7F21 (certificate), because their capacity
135
+-	 * is hard-codded and may change in various version of the card. If we check here,
136
+-	 * the driver may be sticked to a limit version number of card.
137
+-	 * 7F21 size is soft-coded, so we can check it. */
138
+-	if (tag == DO_CERT && buf_len > priv->max_cert_size) {
139
+-		sc_log(card->ctx, "Data size %ld exceeds DO size limit %ld.", buf_len, priv->max_cert_size);
140
+-		LOG_FUNC_RETURN(card->ctx, SC_ERROR_WRONG_LENGTH);
141
+-	}
142
++	LOG_FUNC_CALLED(ctx);
143
+ 
144
+ 	/* Extended Header list (004D DO) needs a variant of PUT DATA command */
145
+ 	if (tag == 0x004D) {
146
+@@ -1258,15 +1291,70 @@ pgp_put_data(sc_card_t *card, unsigned int tag, const u8 *buf, size_t buf_len)
147
+ 		apdu.lc = buf_len;
148
+ 	}
149
+ 	else {
150
++		/* This case is to empty DO */
151
+ 		sc_format_apdu(card, &apdu, SC_APDU_CASE_1, ins, p1, p2);
152
+ 	}
153
+ 
154
+ 	/* Send APDU to card */
155
+ 	r = sc_transmit_apdu(card, &apdu);
156
+-	LOG_TEST_RET(card->ctx, r, "APDU transmit failed");
157
++	LOG_TEST_RET(ctx, r, "APDU transmit failed");
158
+ 	/* Check response */
159
+ 	r = sc_check_sw(card, apdu.sw1, apdu.sw2);
160
+ 
161
++	if (r < 0)
162
++		LOG_FUNC_RETURN(ctx, r);
163
++
164
++	LOG_FUNC_RETURN(ctx, buf_len);
165
++}
166
++
167
++/* ABI: PUT DATA */
168
++static int
169
++pgp_put_data(sc_card_t *card, unsigned int tag, const u8 *buf, size_t buf_len)
170
++{
171
++	struct pgp_priv_data *priv = DRVDATA(card);
172
++	struct blob *affected_blob = NULL;
173
++	struct do_info *dinfo = NULL;
174
++	int r;
175
++
176
++	LOG_FUNC_CALLED(card->ctx);
177
++
178
++	/* Check if the tag is writable */
179
++	if (priv->current->id != tag)
180
++		affected_blob = pgp_find_blob(card, tag);
181
++
182
++	/* Non-readable DOs have no represented blob, we have to check from pgp_get_info_by_tag */
183
++	if (affected_blob == NULL)
184
++		dinfo = pgp_get_info_by_tag(card, tag);
185
++	else
186
++		dinfo = affected_blob->info;
187
++
188
++	if (dinfo == NULL) {
189
++		sc_log(card->ctx, "The DO %04X does not exist.", tag);
190
++		LOG_FUNC_RETURN(card->ctx, SC_ERROR_INVALID_ARGUMENTS);
191
++	}
192
++	else if ((dinfo->access & WRITE_MASK) == WRITE_NEVER) {
193
++		sc_log(card->ctx, "DO %04X is not writable.", tag);
194
++		LOG_FUNC_RETURN(card->ctx, SC_ERROR_NOT_ALLOWED);
195
++	}
196
++
197
++	/* Check data size.
198
++	 * We won't check other DOs than 7F21 (certificate), because their capacity
199
++	 * is hard-codded and may change in various version of the card. If we check here,
200
++	 * the driver may be sticked to a limit version number of card.
201
++	 * 7F21 size is soft-coded, so we can check it. */
202
++	if (tag == DO_CERT && buf_len > priv->max_cert_size) {
203
++		sc_log(card->ctx, "Data size %ld exceeds DO size limit %ld.", buf_len, priv->max_cert_size);
204
++		LOG_FUNC_RETURN(card->ctx, SC_ERROR_WRONG_LENGTH);
205
++	}
206
++
207
++	if (tag == DO_CERT && card->type == SC_CARD_TYPE_OPENPGP_GNUK) {
208
++		/* Gnuk need a special way to write certificate. */
209
++		r = gnuk_write_certificate(card, buf, buf_len);
210
++	}
211
++	else {
212
++		r = pgp_put_data_plain(card, tag, buf, buf_len);
213
++	}
214
++
215
+ 	/* Instruct more in case of error */
216
+ 	if (r == SC_ERROR_SECURITY_STATUS_NOT_SATISFIED) {
217
+ 		sc_debug(card->ctx, SC_LOG_DEBUG_VERBOSE, "Please verify PIN first.");
218
+-- 
219
+1.9.3
220
+

+ 31
- 0
utils/opensc/patches/0013-pkcs15-openpgp-Change-to-sc_put_data-instead-of-sc_u.patch View File

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

+ 53
- 0
utils/opensc/patches/0014-OpenPGP-Overcome-the-restriction-of-even-data-length.patch View File

@@ -0,0 +1,53 @@
1
+From df8a78e3c8c9d9d591c0d3fa31db7e010eb2c8c2 Mon Sep 17 00:00:00 2001
2
+From: =?UTF-8?q?Nguy=E1=BB=85n=20H=E1=BB=93ng=20Qu=C3=A2n?=
3
+ <ng.hong.quan@gmail.com>
4
+Date: Thu, 11 Apr 2013 16:18:31 +0700
5
+Subject: [PATCH 14/18] OpenPGP: Overcome the restriction of even data length
6
+ of Gnuk.
7
+
8
+When write certificate with odd length to Gnuk, we add zero padding to make it even.
9
+---
10
+ src/libopensc/card-openpgp.c | 20 ++++++++++++++++++--
11
+ 1 file changed, 18 insertions(+), 2 deletions(-)
12
+
13
+diff --git a/src/libopensc/card-openpgp.c b/src/libopensc/card-openpgp.c
14
+index d9db948..a666163 100644
15
+--- a/src/libopensc/card-openpgp.c
16
++++ b/src/libopensc/card-openpgp.c
17
+@@ -1206,6 +1206,10 @@ static int gnuk_write_certificate(sc_card_t *card, const u8 *buf, size_t length)
18
+ 	sc_apdu_t apdu;
19
+ 	u8 *part;
20
+ 	size_t plen;
21
++	/* Two round_ variables below are to build APDU data
22
++	 * with even length for Gnuk */
23
++	u8 roundbuf[256];
24
++	size_t roundlen = 0;
25
+ 	int r = SC_SUCCESS;
26
+ 
27
+ 	LOG_FUNC_CALLED(ctx);
28
+@@ -1236,8 +1240,20 @@ static int gnuk_write_certificate(sc_card_t *card, const u8 *buf, size_t length)
29
+ 			sc_format_apdu(card, &apdu, SC_APDU_CASE_3_SHORT, 0xD6, i, 0);
30
+ 		}
31
+ 		apdu.flags |= SC_APDU_FLAGS_CHAINING;
32
+-		apdu.data = part;
33
+-		apdu.datalen = apdu.lc = plen;
34
++
35
++		/* If the last part has odd length, we add zero padding to make it even.
36
++		 * Gnuk does not allow data with odd length */
37
++		if (plen < 256 && (plen % 2) != 0) {
38
++			roundlen = plen + 1;
39
++			memset(roundbuf, 0, roundlen);
40
++			memcpy(roundbuf, part, plen);
41
++			apdu.data = roundbuf;
42
++			apdu.datalen = apdu.lc = roundlen;
43
++		}
44
++		else {
45
++			apdu.data = part;
46
++			apdu.datalen = apdu.lc = plen;
47
++		}
48
+ 
49
+ 		r = sc_transmit_apdu(card, &apdu);
50
+ 		LOG_TEST_RET(card->ctx, r, "APDU transmit failed");
51
+-- 
52
+1.9.3
53
+

+ 92
- 0
utils/opensc/patches/0015-OpenPGP-Delete-key-as-file-for-Gnuk.patch View File

@@ -0,0 +1,92 @@
1
+From 693b3ac5a53e89a0cdeab0f728d24a6e16864f5c Mon Sep 17 00:00:00 2001
2
+From: =?UTF-8?q?Nguy=E1=BB=85n=20H=E1=BB=93ng=20Qu=C3=A2n?=
3
+ <ng.hong.quan@gmail.com>
4
+Date: Fri, 12 Apr 2013 15:33:31 +0700
5
+Subject: [PATCH 15/18] OpenPGP: Delete key as file, for Gnuk.
6
+
7
+---
8
+ src/libopensc/card-openpgp.c | 51 +++++++++++++++++++++++++++++++++++++++++++-
9
+ 1 file changed, 50 insertions(+), 1 deletion(-)
10
+
11
+diff --git a/src/libopensc/card-openpgp.c b/src/libopensc/card-openpgp.c
12
+index a666163..19d3b04 100644
13
+--- a/src/libopensc/card-openpgp.c
14
++++ b/src/libopensc/card-openpgp.c
15
+@@ -2437,6 +2437,44 @@ static int pgp_card_ctl(sc_card_t *card, unsigned long cmd, void *ptr)
16
+ 	LOG_FUNC_RETURN(card->ctx, SC_ERROR_NOT_SUPPORTED);
17
+ }
18
+ 
19
++
20
++/* Internal: Delete key */
21
++static int
22
++gnuk_delete_key(sc_card_t *card, u8 key_id)
23
++{
24
++	sc_context_t *ctx = card->ctx;
25
++	int r = SC_SUCCESS;
26
++	u8 *data = NULL;
27
++
28
++	LOG_FUNC_CALLED(ctx);
29
++
30
++	/* Delete fingerprint */
31
++	sc_log(ctx, "Delete fingerprints");
32
++	r = pgp_put_data(card, 0xC6 + key_id, NULL, 0);
33
++	LOG_TEST_RET(ctx, r, "Failed to delete fingerprints");
34
++	/* Delete creation time */
35
++	sc_log(ctx, "Delete creation time");
36
++	r = pgp_put_data(card, 0xCD + key_id, NULL, 0);
37
++	LOG_TEST_RET(ctx, r, "Failed to delete creation time");
38
++
39
++	/* Rewrite Extended Header List */
40
++	sc_log(ctx, "Rewrite Extended Header List");
41
++
42
++	if (key_id == 1)
43
++		data = "\x4D\x02\xB6";
44
++	else if (key_id == 2)
45
++		data = "\x4D\x02\xB8";
46
++	else if (key_id == 3)
47
++		data = "\x4D\x02\xA4";
48
++	else
49
++		LOG_FUNC_RETURN(ctx, SC_ERROR_INVALID_ARGUMENTS);
50
++
51
++	r = pgp_put_data(card, 0x4D, data, strlen(data) + 1);
52
++
53
++	LOG_FUNC_RETURN(ctx, r);
54
++}
55
++
56
++
57
+ /* ABI: DELETE FILE */
58
+ static int
59
+ pgp_delete_file(sc_card_t *card, const sc_path_t *path)
60
+@@ -2444,6 +2482,7 @@ pgp_delete_file(sc_card_t *card, const sc_path_t *path)
61
+ 	struct pgp_priv_data *priv = DRVDATA(card);
62
+ 	struct blob *blob;
63
+ 	sc_file_t *file;
64
++	u8 key_id;
65
+ 	int r;
66
+ 
67
+ 	LOG_FUNC_CALLED(card->ctx);
68
+@@ -2459,10 +2498,20 @@ pgp_delete_file(sc_card_t *card, const sc_path_t *path)
69
+ 	if (blob == priv->mf)
70
+ 		LOG_FUNC_RETURN(card->ctx, SC_ERROR_NOT_SUPPORTED);
71
+ 
72
+-	if (file->id == 0xB601 || file->id == 0xB801 || file->id == 0xA401) {
73
++	if (card->type != SC_CARD_TYPE_OPENPGP_GNUK &&
74
++	    (file->id == 0xB601 || file->id == 0xB801 || file->id == 0xA401)) {
75
+ 		/* These tags are just symbolic. We don't really delete it. */
76
+ 		r = SC_SUCCESS;
77
+ 	}
78
++	else if (card->type == SC_CARD_TYPE_OPENPGP_GNUK && file->id == 0xB601) {
79
++		r = gnuk_delete_key(card, 1);
80
++	}
81
++	else if (card->type == SC_CARD_TYPE_OPENPGP_GNUK && file->id == 0xB801) {
82
++		r = gnuk_delete_key(card, 2);
83
++	}
84
++	else if (card->type == SC_CARD_TYPE_OPENPGP_GNUK && file->id == 0xA401) {
85
++		r = gnuk_delete_key(card, 3);
86
++	}
87
+ 	else {
88
+ 		/* call pgp_put_data() with zero-sized NULL-buffer to zap the DO contents */
89
+ 		r = pgp_put_data(card, file->id, NULL, 0);
90
+-- 
91
+1.9.3
92
+

+ 47
- 0
utils/opensc/patches/0016-OpenPGP-Correct-parameter-checking.patch View File

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

+ 39
- 0
utils/opensc/patches/0017-OpenPGP-Make-code-neater.patch View File

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

+ 34
- 0
utils/opensc/patches/0018-Move-declaration-to-top-of-block.patch View File

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