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
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
/**
* cwa14890.h: Defines, Typedefs and prototype functions for SM Messaging according CWA-14890 standard.
*
* Copyright (C) 2010 Juan Antonio Martinez <jonsito@terra.es>
*
* This work is derived from many sources at OpenSC Project site,
* (see references), and the information made public for Spanish
* Direccion General de la Policia y de la Guardia Civil
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#ifndef __CWA14890_H__
#define __CWA14890_H__
#if defined(ENABLE_OPENSSL) && defined(ENABLE_SM)
/* Flags for setting SM status */
#define CWA_SM_OFF 0x00 /** Disable SM channel */
#define CWA_SM_ON 0x01 /** Enable SM channel */
/* TAGS for encoded APDU's */
#define CWA_SM_PLAIN_TAG 0x81 /** Plain value (to be protected by CC) */
#define CWA_SM_CRYPTO_TAG 0x87 /** Padding-content + cryptogram */
#define CWA_SM_MAC_TAG 0x8E /** Cryptographic checksum (MAC) */
#define CWA_SM_LE_TAG 0x97 /** Le (to be protected by CC ) */
#define CWA_SM_STATUS_TAG 0x99 /** Processing status (SW1-SW2 mac protected ) */
/*************** data structures for CWA14890 SM handling **************/
#include "libopensc/types.h"
#include <openssl/x509.h>
#include <openssl/des.h>
/**
* Data and function pointers to provide information to create and handle
* Secure Channel.
*/
typedef struct cwa_provider_st {
/************ operations related with secure channel creation *********/
/* pre and post operations */
/**
* CWA-14890 SM stablisment pre-operations.
*
* This code is called before any operation required in
* standard cwa14890 SM stablisment process. It's usually
* used for acquiring/initialize data to be used in the
* process (i.e: retrieve card serial number), to make sure
* that no extra apdu is sent during the SM establishment procedure
*
* @param card pointer to card driver structure
* @param provider pointer to SM data provider for DNIe
* @return SC_SUCCESS if OK. else error code
*/
int (*cwa_create_pre_ops) (sc_card_t * card,
struct cwa_provider_st * provider);
/**
* CWA-14890 SM stablisment post-operations.
*
* This code is called after successful SM channel establishment
* procedure, and before returning from create_sm_channel() function
* May be use for store data, trace, logs and so
*
* @param card pointer to card driver structure
* @param provider pointer to SM data provider for DNIe
* @return SC_SUCCESS if OK. else error code
*/
int (*cwa_create_post_ops) (sc_card_t * card,
struct cwa_provider_st * provider);
/**
* Get ICC (card) intermediate CA Certificate.
*
* @param card Pointer to card driver structure
* @param cert where to store resulting certificate
* @return SC_SUCCESS if ok; else error code
*/
int (*cwa_get_icc_intermediate_ca_cert) (sc_card_t * card,
X509 ** cert);
/**
* Get ICC (card) certificate.
*
* @param card Pointer to card driver structure
* @param cert where to store resulting certificate
* @return SC_SUCCESS if ok; else error code
*/
int (*cwa_get_icc_cert) (sc_card_t * card, X509 ** cert);
/**
* Obtain RSA public key from RootCA.
*
* @param root_ca_key pointer to resulting returned key
* @return SC_SUCCESS if ok; else error code
*/
int (*cwa_get_root_ca_pubkey) (sc_card_t * card, EVP_PKEY ** key);
/**
* Get RSA IFD (Terminal) private key data.
*
* Notice that resulting data should be kept in memory as little
* as possible Erasing them once used
*
* @param card pointer to card driver structure
* @param ifd_privkey where to store IFD private key
* @return SC_SUCCESS if ok; else error code
*/
int (*cwa_get_ifd_privkey) (sc_card_t * card, EVP_PKEY ** key);
/* TODO:
* CVC handling routines should be grouped in just retrieve CVC
* certificate. The key reference, as stated by CWA should be
* extracted from CVC...
*
* But to do this, an special OpenSSL with PACE extensions is
* needed. In the meantime, let's use binary buffers to get
* CVC and key references, until an CV_CERT handling API
* become available in standard OpenSSL
*
*@see http://openpace.sourceforge.net
*/
/**
* Retrieve IFD (application) CVC intermediate CA certificate and length.
*
* Returns a byte array with the intermediate CA certificate
* (in CardVerifiable Certificate format) to be sent to the
* card in External Authentication process
*
* @param card Pointer to card driver Certificate
* @param cert Where to store resulting byte array
* @param length len of returned byte array
* @return SC_SUCCESS if ok; else error code
*/
int (*cwa_get_cvc_ca_cert) (sc_card_t * card, u8 ** cert,
size_t * length);
/**
* Retrieve IFD (application) CVC certificate and length.
*
* Returns a byte array with the application's certificate
* (in CardVerifiable Certificate format) to be sent to the
* card in External Authentication process
*
* @param card Pointer to card driver Certificate
* @param cert Where to store resulting byte array
* @param length len of returned byte array
* @return SC_SUCCESS if ok; else error code
*/
int (*cwa_get_cvc_ifd_cert) (sc_card_t * card, u8 ** cert,
size_t * length);
/**
* Retrieve public key reference for Root CA to validate CVC intermediate CA certs.
*
* This is required in the process of On card external authenticate
* @param card Pointer to card driver structure
* @param buf where to store resulting key reference
* @param len where to store buffer length
* @return SC_SUCCESS if ok; else error code
*/
int (*cwa_get_root_ca_pubkey_ref) (sc_card_t * card, u8 ** buf,
size_t * len);
/**
* Get public key reference for intermediate CA to validate IFD cert.
*
* This is required in the process of On card external authenticate
*
* @param card Pointer to card driver structure
* @param buf where to store resulting key reference
* @param len where to store buffer length
* @return SC_SUCCESS if ok; else error code
*/
int (*cwa_get_intermediate_ca_pubkey_ref) (sc_card_t * card, u8 ** buf,
size_t * len);
/**
* Retrieve public key reference for IFD certificate.
*
* This tells the card with in memory key reference is to be used
* when CVC cert is sent for external auth procedure
*
* @param card pointer to card driver structure
* @param buf where to store data to be sent
* @param len where to store data length
* @return SC_SUCCESS if ok; else error code
*/
int (*cwa_get_ifd_pubkey_ref) (sc_card_t * card, u8 ** buf,
size_t * len);
/**
* Retrieve key reference for ICC private key.
*
* @param card pointer to card driver structure
* @param buf where to store data
* @param len where to store data length
* @return SC_SUCCESS if ok; else error
*/
int (*cwa_get_icc_privkey_ref) (sc_card_t * card, u8 ** buf,
size_t * len);
/**
* Retrieve SN.IFD - Terminal Serial Number.
*
* Result SN is 8 bytes long left padded with zeroes if required.
* The result should stored in card->sm_ctx.info.session.cwa.ifd.sn
*
* @param card pointer to card structure
* @return SC_SUCCESS if ok; else error
*/
int (*cwa_get_sn_ifd) (sc_card_t * card);
/**
* Get SN.ICC - Card Serial Number.
*
* Result value is 8 bytes long left padded with zeroes if needed)
* The result should stored in card->sm_ctx.info.session.cwa.icc.sn
*
* @param card pointer to card structure
* @return SC_SUCCESS if ok; else error
*/
int (*cwa_get_sn_icc) (sc_card_t * card);
} cwa_provider_t;
/************************** external function prototypes ******************/
/**
* Create Secure channel.
*
* Based on Several documents:
* - "Understanding the DNIe"
* - "Manual de comandos del DNIe"
* - ISO7816-4 and CWA14890-{1,2}
*
* @param card card info structure
* @param provider pointer to cwa provider
* @param flag Requested SM final state (OFF,COLD,WARM)
* @return SC_SUCCESS if OK; else error code
*/
extern int cwa_create_secure_channel(sc_card_t * card,
cwa_provider_t * provider, int flag);
/**
* Decode an APDU response.
*
* Calling this functions means that It's has been verified
* That apdu response comes in TLV encoded format and needs decoding
* Based on section 9 of CWA-14890 and Sect 6 of iso7816-4 standards
* And DNIe's manual
*
* @param card card info structure
* @param provider cwa provider data to handle SM channel
* @param apdu apdu to be decoded
* @return SC_SUCCESS if ok; else error code
*/
extern int cwa_decode_response(sc_card_t * card,
cwa_provider_t * provider,
sc_apdu_t * apdu);
/**
* Encode an APDU.
*
* Calling this functions means that It's has been verified
* That source apdu needs encoding
* Based on section 9 of CWA-14890 and Sect 6 of iso7816-4 standards
* And DNIe's manual
*
* @param card card info structure
* @param provider cwa provider data to handle SM channel
* @param from apdu to be encoded
* @param to Where to store encoded apdu
* @return SC_SUCCESS if ok; else error code
*/
extern int cwa_encode_apdu(sc_card_t * card,
cwa_provider_t * provider,
sc_apdu_t * from, sc_apdu_t * to);
/**
* Gets a default cwa_provider structure.
*
* @param card Pointer to card driver information
* @return default cwa_provider data, or null on error
*/
extern cwa_provider_t *cwa_get_default_provider(sc_card_t * card);
#endif /* ENABLE_OPENSSL */
#endif