summaryrefslogtreecommitdiffstats
path: root/utils/opensc/patches/0011-OpenPGP-Provide-enough-buffer-to-read-pubkey-from-Gn.patch
blob: 8fc34642d0c14155d6d6a549fb16ef17a2d70ac5 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
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