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
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
|
From 6d138f0199575516bfaad18cbbafcfa2ee61e58f 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/26] OpenPGP: Support erasing (reset) card.
Command: openpgp-tool --erase
---
src/libopensc/card-openpgp.c | 64 ++++++++++++++++++++++++++++++++++++++++++++
src/tools/openpgp-tool.c | 22 ++++++++++++++-
2 files changed, 85 insertions(+), 1 deletion(-)
Index: opensc-20150513/src/libopensc/card-openpgp.c
===================================================================
--- opensc-20150513.orig/src/libopensc/card-openpgp.c
+++ opensc-20150513/src/libopensc/card-openpgp.c
@@ -2206,6 +2206,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)
{
@@ -2232,6 +2292,10 @@ static int pgp_card_ctl(sc_card_t *card,
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);
Index: opensc-20150513/src/tools/openpgp-tool.c
===================================================================
--- opensc-20150513.orig/src/tools/openpgp-tool.c
+++ opensc-20150513/src/tools/openpgp-tool.c
@@ -78,6 +78,7 @@ static int opt_pin = 0;
static const char *pin = NULL;
static int opt_dump_do = 0;
static u8 do_dump_idx;
+static int opt_erase = 0;
static const char *app_name = "openpgp-tool";
@@ -94,6 +95,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 },
{ "do", required_argument, NULL, 'd' },
@@ -113,6 +115,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",
/* d */ "Dump private data object number <arg> (i.e. PRIVATE-DO-<arg>)"
@@ -232,7 +235,7 @@ static int decode_options(int argc, char
{
int c;
- while ((c = getopt_long(argc, argv,"r:x:CUG:L:hwvVd:", options, (int *) 0)) != EOF) {
+ while ((c = getopt_long(argc, argv,"r:x:CUG:L:hwvVd:E", options, (int *) 0)) != EOF) {
switch (c) {
case 'r':
opt_reader = optarg;
@@ -294,6 +297,8 @@ static int decode_options(int argc, char
do_dump_idx = optarg[0] - '0';
opt_dump_do++;
actions++;
+ case 'E':
+ opt_erase++;
break;
default:
util_print_usage_and_die(app_name, options, option_help, NULL);
@@ -452,6 +457,18 @@ int do_verify(sc_card_t *card, char *typ
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;
@@ -531,6 +548,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);
|