root/trunk/src/libopensc/card-gpk.c

Revision 3405, 47.4 KB (checked in by alonbl, 9 months ago)

Complete rewrite of OpenSC build system.

1. Build system now supports MinGW (Windows) compilation using msys and cross compilation.
2. Ability to explicitly disable and enable dependencies of the package.
3. openct, pcsc and nsplugins features are disabled by default.
4. Modified pcsc driver to use pcsc dynamically, no compile time dependency is required.
5. --enable-pcsc-lite configuration option renamed to --enable-pcsc.
6. Install opensc.conf file (as opensc.conf.new if opensc.conf exists).
7. Add--enable-doc configuration option, allow installing documentation into target.
8. Add --disable-man configuration option, allow msys mingw32 users to

build from svn without extra dependencies.

9. Add export files to each library in order to export only required symbols.

Windows native build may use these files instead of scanning objects' symbols.

10. Add opensc-tool --info to display some general information about the build.
11. Create compatibility library to be linked against library instread of recompiling the

same source files in different places.

12. Add different win32 version resource to each class of outputs.
13. Make xsl-stylesheets location selectable.
14. Some win32 fixups.
15. Some warning fixups.
16. Many other autoconf/automake cleanups.

Alon Bar-Lev

svn diff -r 3315:3399 https://www.opensc-project.org/svn/opensc/branches/alonbl/mingw

_M .
D configure.in
_M src
_M src/openssh
M src/openssh/Makefile.am
_M src/tools
M src/tools/rutoken-tool.c
M src/tools/opensc-tool.c
M src/tools/cardos-info.c
M src/tools/pkcs15-crypt.c
M src/tools/pkcs15-init.c
M src/tools/piv-tool.c
M src/tools/netkey-tool.c
M src/tools/eidenv.c
M src/tools/cryptoflex-tool.c
M src/tools/util.c
M src/tools/pkcs11-tool.c
M src/tools/pkcs15-tool.c
M src/tools/util.h
M src/tools/opensc-explorer.c
M src/tools/Makefile.am
_M src/pkcs11
M src/pkcs11/pkcs11-global.c
M src/pkcs11/framework-pkcs15.c
M src/pkcs11/mechanism.c
M src/pkcs11/pkcs11-display.c
M src/pkcs11/pkcs11-object.c
A src/pkcs11/opensc-pkcs11.exports
M src/pkcs11/sc-pkcs11.h
M src/pkcs11/pkcs11-spy.c
M src/pkcs11/openssl.c
M src/pkcs11/Makefile.am
A src/pkcs11/pkcs11-spy.exports
_M src/tests
_M src/tests/regression
M src/tests/regression/Makefile.am
M src/tests/sc-test.c
M src/tests/pintest.c
M src/tests/Makefile.am
_M src/include
_M src/include/opensc
M src/include/opensc/Makefile.am
A src/include/opensc/svnignore
M src/include/Makefile.am
_M src/signer
_M src/signer/npinclude
M src/signer/npinclude/Makefile.am
M src/signer/Makefile.am
A src/signer/signer.exports
_M src/common
A src/common/compat_dummy.c
D src/common/getopt.txt
D src/common/strlcpy.c
D src/common/LICENSE
A src/common/compat_getopt.txt
A src/common/compat_strlcpy.c
A src/common/LICENSE.compat_getopt
A src/common/compat_getopt.c
D src/common/strlcpy.h
D src/common/ChangeLog
D src/common/getpass.c
D src/common/my_getopt.c
A src/common/compat_strlcpy.h
A src/common/compat_getpass.c
A src/common/compat_getopt.h
A src/common/ChangeLog.compat_getopt
D src/common/README.strlcpy
D src/common/my_getopt.h
A src/common/compat_getpass.h
A src/common/README.compat_strlcpy
D src/common/strlcpy.3
A src/common/README.compat_getopt
D src/common/getopt.3
D src/common/README.my_getopt
A src/common/compat_strlcpy.3
A src/common/compat_getopt.3
M src/common/Makefile.am
M src/Makefile.am
_M src/pkcs15init
M src/pkcs15init/pkcs15-oberthur.c
M src/pkcs15init/profile.c
M src/pkcs15init/pkcs15-lib.c
M src/pkcs15init/pkcs15-rutoken.c
A src/pkcs15init/pkcs15init.exports
M src/pkcs15init/pkcs15-gpk.c
M src/pkcs15init/Makefile.am
_M src/scconf
M src/scconf/Makefile.am
M src/scconf/parse.c
A src/scconf/scconf.exports
_M src/libopensc
M src/libopensc/card-rutoken.c
M src/libopensc/compression.c
M src/libopensc/sc.c
M src/libopensc/card-piv.c
M src/libopensc/pkcs15-openpgp.c
M src/libopensc/pkcs15-postecert.c
M src/libopensc/pkcs15-tcos.c
M src/libopensc/opensc-config.in
M src/libopensc/reader-pcsc.c
A src/libopensc/internal-winscard.h
M src/libopensc/ctx.c
A src/libopensc/libopensc.exports
M src/libopensc/pkcs15-piv.c
M src/libopensc/pkcs15-infocamere.c
M src/libopensc/internal.h
M src/libopensc/pkcs15-actalis.c
M src/libopensc/pkcs15-starcert.c
M src/libopensc/card-oberthur.c
M src/libopensc/pkcs15-atrust-acos.c
M src/libopensc/p15card-helper.c
D src/libopensc/part10.h
M src/libopensc/ui.c
M src/libopensc/card-gpk.c
M src/libopensc/pkcs15-wrap.c
M src/libopensc/pkcs15-gemsafeGPK.c
M src/libopensc/log.c
M src/libopensc/pkcs15-esteid.c
M src/libopensc/pkcs15-prkey-rutoken.c
M src/libopensc/log.h
M src/libopensc/Makefile.am
M src/libopensc/reader-openct.c
_M aclocal
M aclocal/Makefile.am
_M win32
M win32/Makefile.am
A win32/versioninfo.rc.in
A win32/ltrc.inc
A configure.ac
_M doc
_M doc/tools
M doc/tools/pkcs15-profile.xml
D doc/changelog.sh
D doc/export-wiki.xsl
_M doc/api
_M doc/api/file
M doc/api/man.xsl
_M doc/api/asn1
_M doc/api/apps
_M doc/api/init
_M doc/api/types
_M doc/api/card
M doc/api/html.xsl
_M doc/api/misc
_M doc/api/util
M doc/Makefile.am
D doc/export-wiki.sh
AM doc/nonpersistent
A doc/nonpersistent/export-wiki.xsl
A doc/nonpersistent/Makefile.am
A doc/nonpersistent/export-wiki.sh
A doc/nonpersistent/svn2cl.xsl
D doc/generate-man.sh
D doc/svn2cl.xsl
M Makefile.am
A svnignore
_M etc
M etc/opensc.conf.in
M etc/Makefile.am
D man
_M solaris
M solaris/Makefile

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
Line 
1/*
2 * card-gpk: Driver for GPK 4000 cards
3 *
4 * Copyright (C) 2002  Olaf Kirch <okir@lst.de>
5 *
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
10 *
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14 * Lesser General Public License for more details.
15 *
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
19 */
20
21#include "internal.h"
22#include "cardctl.h"
23#include "pkcs15.h"
24#ifdef ENABLE_OPENSSL
25#include <stdlib.h>
26#include <string.h>
27#include <openssl/evp.h>
28#include <openssl/rand.h>
29
30#define GPK_SEL_MF              0x00
31#define GPK_SEL_DF              0x01
32#define GPK_SEL_EF              0x02
33#define GPK_SEL_AID             0x04
34#define GPK_FID_MF              0x3F00
35
36#define GPK_FTYPE_SC            0x21
37
38#define GPK_SIGN_RSA_MD5        0x11
39#define GPK_SIGN_RSA_SHA        0x12
40#define GPK_SIGN_RSA_SSL        0x18
41#define GPK_VERIFY_RSA_MD5      0x21
42#define GPK_VERIFY_RSA_SHA      0x22
43#define GPK_AUTH_RSA_MD5        0x31
44#define GPK_AUTH_RSA_SHA        0x32
45#define GPK_AUTH_RSA_SSL        0x38
46#define GPK_UNWRAP_RSA          0x77
47
48#define GPK_MAX_PINS            8
49#define GPK_HASH_CHUNK          62
50
51/*
52 * GPK4000 private data
53 */
54struct gpk_private_data {
55        /* The GPK usually do file offsets in multiples of
56         * 4 bytes. This can be customized however. We
57         * should really query for this during gpk_init */
58        unsigned int    offset_shift;
59        unsigned int    offset_mask;
60        unsigned int    locked : 1,
61                        sample_card : 1;
62
63        /* access control bits of file most recently selected */
64        unsigned short int ac[3];
65
66        /* is non-zero if we should use secure messaging */
67        unsigned        key_set   : 1;
68        unsigned int    key_reference;
69        u8              key[16];
70
71        /* crypto related data from set_security_env */
72        unsigned int    sec_algorithm;
73        unsigned int    sec_hash_len;
74        unsigned int    sec_mod_len;
75        unsigned int    sec_padding;
76};
77#define DRVDATA(card)   ((struct gpk_private_data *) ((card)->drv_data))
78
79static int      gpk_get_info(sc_card_t *, int, int, u8 *, size_t);
80
81/*
82 * ATRs of GPK4000 cards courtesy of libscez
83 */
84static struct sc_atr_table gpk_atrs[] = {
85        { "3B:27:00:80:65:A2:04:01:01:37", NULL, "GPK 4K", SC_CARD_TYPE_GPK_GPK4000_s, 0, NULL },
86        { "3B:27:00:80:65:A2:05:01:01:37", NULL, "GPK 4K", SC_CARD_TYPE_GPK_GPK4000_sp, 0, NULL },
87        { "3B:27:00:80:65:A2:0C:01:01:37", NULL, "GPK 4K", SC_CARD_TYPE_GPK_GPK4000_su256, 0, NULL },
88        { "3B:A7:00:40:14:80:65:A2:14:01:01:37", NULL, "GPK 4K", SC_CARD_TYPE_GPK_GPK4000_sdo, 0, NULL },
89        { "3B:A7:00:40:18:80:65:A2:08:01:01:52", NULL, "GPK 8K", SC_CARD_TYPE_GPK_GPK8000_8K, 0, NULL },
90        { "3B:A7:00:40:18:80:65:A2:09:01:01:52", NULL, "GPK 8K", SC_CARD_TYPE_GPK_GPK8000_16K, 0, NULL },
91        { "3B:A7:00:40:18:80:65:A2:09:01:02:52", NULL, "GPK 16K", SC_CARD_TYPE_GPK_GPK16000, 0, NULL },
92        { "3B:A7:00:40:18:80:65:A2:09:01:03:52", NULL, "GPK 16K", SC_CARD_TYPE_GPK_GPK16000, 0, NULL },
93        { NULL, NULL, NULL, 0, 0, NULL }
94};
95
96/*
97 * Driver and card ops structures
98 */
99static struct sc_card_operations        gpk_ops, *iso_ops;
100static struct sc_card_driver gpk_drv = {
101        "Gemplus GPK",
102        "gpk",
103        &gpk_ops,
104        NULL, 0, NULL
105};
106
107/*
108 * return 1 if this driver can handle the card
109 */
110static int
111gpk_match_card(sc_card_t *card)
112{
113        int i;
114
115        i = _sc_match_atr(card, gpk_atrs, &card->type);
116        if (i < 0) {
117                const u8 *hist_bytes = card->slot->atr_info.hist_bytes;
118
119                /* Gemplus GPK docs say we can use just the
120                 * FMN and PRN fields of the historical bytes
121                 * to recognize a GPK card
122                 *  See Table 43, pp. 188
123                 * We'll use the first 2 bytes as well
124                 */
125
126                if ((card->slot->atr_info.hist_bytes_len >= 7)
127                        && (hist_bytes[0] == 0x80)
128                        && (hist_bytes[1] == 0x65)
129                        && (hist_bytes[2] == 0xa2)) {   /* FMN */
130                        if (hist_bytes[3] == 0x08) {    /* PRN? */
131                                card->type = SC_CARD_TYPE_GPK_GPK8000;
132                                return 1;
133                        }
134                        if (hist_bytes[3] == 0x09) {    /* PRN? */
135                                card->type = SC_CARD_TYPE_GPK_GPK16000;
136                                return 1;
137                        }
138                }
139                return 0;
140        }
141        return 1;
142}
143
144/*
145 * Initialize the card struct
146 */
147static int
148gpk_init(sc_card_t *card)
149{
150        struct gpk_private_data *priv;
151        unsigned long   exponent, flags, kg;
152        unsigned char info[13];
153
154        card->drv_data = priv = (struct gpk_private_data *) calloc(1, sizeof(*priv));
155        if (card->drv_data == NULL)
156                return SC_ERROR_OUT_OF_MEMORY;
157
158        /* read/write/update binary expect offset to be the
159         * number of 32 bit words.
160         * offset_shift is the shift value.
161         * offset_mask is the corresponding mask. */
162        priv->offset_shift = 2;
163        priv->offset_mask = 3;
164        card->cla = 0x00;
165
166        /* Set up algorithm info. GPK 16000 will do any RSA
167         * exponent, earlier ones are restricted to 0x10001 */
168        flags = SC_ALGORITHM_RSA_HASH_MD5 | SC_ALGORITHM_RSA_HASH_SHA1
169                | SC_ALGORITHM_RSA_HASH_MD5_SHA1;
170        flags |= SC_ALGORITHM_RSA_PAD_PKCS1 | SC_ALGORITHM_RSA_PAD_ANSI
171                | SC_ALGORITHM_RSA_PAD_ISO9796;
172        exponent = (card->type < SC_CARD_TYPE_GPK_GPK16000) ? 0x10001 : 0;
173        kg = (card->type >= SC_CARD_TYPE_GPK_GPK8000) ? SC_ALGORITHM_ONBOARD_KEY_GEN : 0;
174        _sc_card_add_rsa_alg(card,  512, flags|kg, exponent);
175        _sc_card_add_rsa_alg(card,  768, flags, exponent);
176        _sc_card_add_rsa_alg(card, 1024, flags|kg, exponent);
177
178        /* Inspect the LOCK byte */
179        if (gpk_get_info(card, 0x02, 0xA4, info, sizeof(info)) >= 0) {
180                if (info[12] & 0x40) {
181                        priv->offset_shift = 0;
182                        priv->offset_mask = 0;
183                }
184                if (info[12] & 0x10) {
185                        /* DSA supported - add algo information.
186                         * It's highly unlikely we'll ever see this.
187                         */
188                }
189                if (info[12] & 0x08) {
190                        priv->locked = 1;
191                }
192                /* Sample cards use a transport key of "TEST KEYTEST KEY" */
193                if (!memcmp(info+5, "\x00\xff\x00", 3)) {
194                        priv->sample_card = 1;
195                }
196        }
197
198        /* State that we have an RNG */
199        card->caps |= SC_CARD_CAP_RNG;
200
201        /* Make sure max send/receive size is 4 byte aligned. */
202        card->max_send_size &= ~3;
203        if (card->max_recv_size >= 256)
204                card->max_recv_size = 252;
205        else
206                card->max_recv_size &= ~3;
207
208        return 0;
209}
210
211/*
212 * Card is being closed; discard any private data etc
213 */
214static int
215gpk_finish(sc_card_t *card)
216{
217        if (card->drv_data)
218                free(card->drv_data);
219        card->drv_data = NULL;
220        return 0;
221}
222
223/*
224 * Error code handling for the GPK4000.
225 * sc_check_sw doesn't seem to handle all of the
226 * status words the GPK is capable of returning
227 */
228#if 0
229static int
230gpk_check_sw(sc_card_t *card, u8 sw1, u8 sw2)
231{
232        unsigned short int      sw = (sw1 << 8) | sw2;
233
234        if ((sw & 0xFFF0) == 0x63C0) {
235                sc_error(card->ctx, "wrong PIN, %u tries left\n", sw&0xf);
236                return SC_ERROR_PIN_CODE_INCORRECT;
237        }
238
239        switch (sw) {
240        case 0x6400:
241                sc_error(card->ctx, "wrong crypto context\n");
242                return SC_ERROR_OBJECT_NOT_VALID; /* XXX ??? */
243
244        /* The following are handled by iso7816_check_sw
245         * but all return SC_ERROR_UNKNOWN_DATA_RECEIVED
246         * XXX: fix in the iso driver? */
247        case 0x6983:
248                sc_error(card->ctx, "PIN is blocked\n");
249                return SC_ERROR_PIN_CODE_INCORRECT;
250        case 0x6581:
251                sc_error(card->ctx, "out of space on card or file\n");
252                return SC_ERROR_OUT_OF_MEMORY;
253        case 0x6981:
254                return SC_ERROR_FILE_NOT_FOUND;
255        case 0x6A80:
256        case 0x6b00:
257                return SC_ERROR_INVALID_ARGUMENTS;
258        }
259
260        return iso7816_check_sw(card, sw1, sw2);
261}
262#endif
263
264/*
265 * Select a DF/EF
266 */
267static int
268match_path(sc_card_t *card, unsigned short int **pathptr, size_t *pathlen,
269                int need_info)
270{
271        unsigned short int      *curptr, *ptr;
272        size_t          curlen, len;
273        size_t          i;
274
275        curptr = (unsigned short int *) card->cache.current_path.value;
276        curlen = card->cache.current_path.len;
277        ptr    = *pathptr;
278        len    = *pathlen;
279
280        if (curlen < 1 || len < 1)
281                return 0;
282
283        /* Make sure path starts with MF.
284         * Note the cached path should always begin with MF. */
285        if (ptr[0] != GPK_FID_MF || curptr[0] != GPK_FID_MF)
286                return 0;
287
288        for (i = 1; i < len && i < curlen; i++) {
289                if (ptr[i] != curptr[i])
290                        break;
291        }
292
293        if (len < curlen) {
294                /* Caller asked us to select the DF, but the
295                 * current file is some EF within the DF we're
296                 * interested in. Say ACK */
297                if (len == 2)
298                        goto okay;
299                /* Anything else won't work */
300                return 0;
301        }
302
303        /* In the case of an exact match:
304         * If the caller needs info on the file to be selected,
305         * make sure we at least select the file itself.
306         * If the DF matches the current DF, just return the
307         * FID */
308        if (i == len && need_info) {
309                if (i > 1) {
310                        *pathptr = ptr + len - 1;
311                        *pathlen = len - 1;
312                        return 1;
313                }
314                /* bummer */
315                return 0;
316        }
317
318okay:
319        *pathptr = ptr + i;
320        *pathlen = len - i;
321        return 1;
322}
323
324static void
325ac_to_acl(unsigned int ac, sc_file_t *file, unsigned int op)
326{
327        unsigned int    npins, pin;
328
329        npins = (ac >> 14) & 3;
330        if (npins == 3) {
331                sc_file_add_acl_entry(file, op, SC_AC_NEVER,
332                                SC_AC_KEY_REF_NONE);
333                return;
334        }
335
336        sc_file_add_acl_entry(file, op, SC_AC_NONE, SC_AC_KEY_REF_NONE);
337        pin = ac & 0xFF;
338        if (npins >= 1)
339                sc_file_add_acl_entry(file, op, SC_AC_CHV, (pin >> 4) & 0xF);
340        if (npins == 2)
341                sc_file_add_acl_entry(file, op, SC_AC_CHV, pin & 0xF);
342
343        /* Check whether secure messaging key is specified */
344        if (ac & 0x3F00)
345                sc_file_add_acl_entry(file, op, SC_AC_PRO, (ac & 0x3F00) >> 8);
346}
347
348/*
349 * Convert ACLs requested by the application to access condition
350 * bits supported by the GPK. Since these do not map 1:1 there's
351 * some fuzz involved.
352 */
353static void
354acl_to_ac(sc_file_t *file, unsigned int op, u8 *ac)
355{
356        const sc_acl_entry_t *acl;
357        unsigned int    npins = 0;
358
359        ac[0] = ac[1] = 0;
360
361        if ((acl = sc_file_get_acl_entry(file, op)) == NULL)
362                return;
363
364        assert(acl->method != SC_AC_UNKNOWN);
365        switch (acl->method) {
366        case SC_AC_NEVER:
367                ac[0] = 0xC0;
368                return;
369        case SC_AC_NONE:
370                return;
371        }
372
373        while (acl) {
374                if (acl->method == SC_AC_CHV) {
375                        /* Support up to 2 PINS only */
376                        if (++npins >= 2)
377                                continue;
378                        ac[1] >>= 4;
379                        ac[1] |= acl->key_ref << 4;
380                        ac[0] += 0x40;
381                }
382                if (acl->method == SC_AC_PRO) {
383                        ac[0] |= acl->key_ref & 0x1f;
384                }
385                acl = acl->next;
386        }
387}
388
389static int
390gpk_parse_fci(sc_card_t *card,
391                const u8 *buf, size_t buflen,
392                sc_file_t *file)
393{
394        const u8        *end, *next;
395        unsigned int    tag, len;
396
397        end = buf + buflen;
398        for (; buf + 2 < end; buf = next) {
399                next = buf + 2 + buf[1];
400                if (next > end)
401                        break;
402                tag = *buf++;
403                len = *buf++;
404                if (tag == 0x84) {
405                        /* unknown purpose - usually the name, but
406                         * the content looks weird, such as
407                         * 84 0D A0 00 00 00 18 0F 00 00 01 63 00 01 04
408                         */
409                } else
410                if (tag == 0xC1 && len >= 2) {
411                        /* Seems to be the file id, followed by something
412                         * C1 04 02 00 00 00 */
413                        file->id = (buf[0] << 8) | buf[1];
414                } else
415                if (tag == 0xC2) {
416                        /* unknown purpose
417                         * C2 01 01
418                         */
419                }
420        }
421
422        return 0;
423}
424
425static int
426gpk_parse_fileinfo(sc_card_t *card,
427                const u8 *buf, size_t buflen,
428                sc_file_t *file)
429{
430        const u8        *sp, *end, *next;
431        int             i, rc;
432
433        memset(file, 0, sizeof(*file));
434        for (i = 0; i < SC_MAX_AC_OPS; i++)
435                sc_file_add_acl_entry(file, i, SC_AC_UNKNOWN, SC_AC_KEY_REF_NONE);
436
437        end = buf + buflen;
438        for (sp = buf; sp + 2 < end; sp = next) {
439                next = sp + 2 + sp[1];
440                if (next > end)
441                        break;
442                if (sp[0] == 0x84) {
443                        /* ignore if name is longer than what it should be */
444                        if (sp[1] > sizeof(file->name))
445                                continue;
446                        memset(file->name, 0, sizeof(file->name));
447                        memcpy(file->name, sp+2, sp[1]);
448                } else
449                if (sp[0] == 0x85) {
450                        unsigned int    ac[3], n;
451
452                        file->id = (sp[4] << 8) | sp[5];
453                        file->size = (sp[8] << 8) | sp[9];
454                        file->record_length = sp[7];
455
456                        /* Map ACLs. Note the third AC byte is
457                         * valid of EFs only */
458                        for (n = 0; n < 3; n++)
459                                ac[n] = (sp[10+2*n] << 8) | sp[11+2*n];
460
461                        /* Examine file type */
462                        switch (sp[6] & 7) {
463                        case 0x01: case 0x02: case 0x03: case 0x04:
464                        case 0x05: case 0x06: case 0x07:
465                                file->type = SC_FILE_TYPE_WORKING_EF;
466                                file->ef_structure = sp[6] & 7;
467                                ac_to_acl(ac[0], file, SC_AC_OP_UPDATE);
468                                ac_to_acl(ac[1], file, SC_AC_OP_WRITE);
469                                ac_to_acl(ac[2], file, SC_AC_OP_READ);
470                                break;
471                        case 0x00: /* 0x38 is DF */
472                                file->type = SC_FILE_TYPE_DF;
473                                /* Icky: the GPK uses different ACLs
474                                 * for creating data files and
475                                 * 'sensitive' i.e. key files */
476                                ac_to_acl(ac[0], file, SC_AC_OP_LOCK);
477                                ac_to_acl(ac[1], file, SC_AC_OP_CREATE);
478                                sc_file_add_acl_entry(file, SC_AC_OP_SELECT,
479                                        SC_AC_NONE, SC_AC_KEY_REF_NONE);
480                                sc_file_add_acl_entry(file, SC_AC_OP_DELETE,
481                                        SC_AC_NEVER, SC_AC_KEY_REF_NONE);
482                                sc_file_add_acl_entry(file, SC_AC_OP_REHABILITATE,
483                                        SC_AC_NEVER, SC_AC_KEY_REF_NONE);
484                                sc_file_add_acl_entry(file, SC_AC_OP_INVALIDATE,
485                                        SC_AC_NEVER, SC_AC_KEY_REF_NONE);
486                                sc_file_add_acl_entry(file, SC_AC_OP_LIST_FILES,
487                                        SC_AC_NEVER, SC_AC_KEY_REF_NONE);
488                                break;
489                        }
490                } else
491                if (sp[0] == 0x6f) {
492                        /* oops - this is a directory with an IADF.
493                         * This happens with the personalized GemSafe cards
494                         * for instance. */
495                        file->type = SC_FILE_TYPE_DF;
496                        rc = gpk_parse_fci(card, sp + 2, sp[1], file);
497                        if (rc < 0)
498                                return rc;
499                }
500        }
501
502        if (file->record_length)
503                file->record_count = file->size / file->record_length;
504        file->magic = SC_FILE_MAGIC;
505
506        return 0;
507}
508
509static int
510gpk_select(sc_card_t *card, int kind,
511                const u8 *buf, size_t buflen,
512                sc_file_t **file)
513{
514        struct gpk_private_data *priv = DRVDATA(card);
515        sc_apdu_t       apdu;
516        u8              resbuf[256];
517        int             r;
518
519        /* If we're about to select a DF, invalidate secure messaging keys */
520        if (kind == GPK_SEL_MF || kind == GPK_SEL_DF) {
521                memset(priv->key, 0, sizeof(priv->key));
522                priv->key_set = 0;
523        }
524
525        /* do the apdu thing */
526        memset(&apdu, 0, sizeof(apdu));
527        apdu.cla = 0x00;
528        apdu.cse = SC_APDU_CASE_3_SHORT;
529        apdu.ins = 0xA4;
530        apdu.p1 = kind;
531        apdu.p2 = 0;
532        apdu.data = buf;
533        apdu.datalen = buflen;
534        apdu.lc = apdu.datalen;
535
536        if (file) {
537                apdu.cse = SC_APDU_CASE_4_SHORT;
538                apdu.resp = resbuf;
539                apdu.resplen = sizeof(resbuf);
540                apdu.le = sizeof(resbuf);
541        }
542
543        r = sc_transmit_apdu(card, &apdu);
544        SC_TEST_RET(card->ctx, r, "APDU transmit failed");
545        r = sc_check_sw(card, apdu.sw1, apdu.sw2);
546        SC_TEST_RET(card->ctx, r, "Card returned error");
547
548        /* Nothing we can say about it... invalidate
549         * path cache */
550        if (kind == GPK_SEL_AID) {
551                card->cache.current_path.len = 0;
552        }
553
554        if (file == NULL)
555                return 0;
556        *file = sc_file_new();
557
558        r = gpk_parse_fileinfo(card, apdu.resp, apdu.resplen, *file);
559        if (r < 0) {
560                sc_file_free(*file);
561                *file = NULL;
562        }
563        return r;
564}
565
566static int
567gpk_select_id(sc_card_t *card, int kind, unsigned int fid,
568                sc_file_t **file)
569{
570        sc_path_t       *cp = &card->cache.current_path;
571        u8              fbuf[2];
572        int             r;
573
574        if (card->ctx->debug)
575                sc_debug(card->ctx, "gpk_select_id(0x%04X, kind=%u)\n", fid, kind);
576
577        fbuf[0] = fid >> 8;
578        fbuf[1] = fid & 0xff;
579
580        sc_ctx_suppress_errors_on(card->ctx);
581        r = gpk_select(card, kind, fbuf, 2, file);
582        sc_ctx_suppress_errors_off(card->ctx);
583
584        /* Fix up the path cache.
585         * NB we never cache the ID of an EF, just the DF path */
586        if (r == 0) {
587                unsigned short int      *path;
588
589                switch (kind) {
590                case GPK_SEL_MF:
591                        cp->len = 0;
592                        /* fallthru */
593                case GPK_SEL_DF:
594                        assert(cp->len + 1 <= SC_MAX_PATH_SIZE / 2);
595                        path = (unsigned short int *) cp->value;
596                        path[cp->len++] = fid;
597                }
598        } else {
599                cp->len = 0;
600        }
601        return r;
602}
603
604static int
605gpk_select_file(sc_card_t *card, const sc_path_t *path,
606                sc_file_t **file)
607{
608        unsigned short int      pathtmp[SC_MAX_PATH_SIZE/2];
609        unsigned short int      *pathptr;
610        size_t                  pathlen, n;
611        int                     locked = 0, r = 0, use_relative = 0, retry = 1;
612        u8                      leaf_type;
613
614        SC_FUNC_CALLED(card->ctx, 1);
615
616        /* Handle the AID case first */
617        if (path->type == SC_PATH_TYPE_DF_NAME) {
618                if (path->len > 16)
619                        return SC_ERROR_INVALID_ARGUMENTS;
620                r = gpk_select(card, GPK_SEL_AID,
621                                        path->value, path->len, file);
622                goto done;
623        }
624
625        /* Now we know we're dealing with 16bit FIDs, either as
626         * an absolute path name (SC_PATH_TYPE_PATH) or a relative
627         * FID (SC_PATH_TYPE_FILE_ID)
628         *
629         * The API should really tell us whether this is a DF or EF
630         * we're selecting. All we can do is read tea leaves...
631         */
632        leaf_type = GPK_SEL_EF;
633
634try_again:
635        if ((path->len & 1) || path->len > sizeof(pathtmp))
636                return SC_ERROR_INVALID_ARGUMENTS;
637        pathptr = pathtmp;
638        for (n = 0; n < path->len; n += 2)
639                pathptr[n>>1] = (path->value[n] << 8)|path->value[n+1];
640        pathlen = path->len >> 1;
641
642        /* See whether we can skip an initial portion of the
643         * (absolute) path */
644        if (path->type == SC_PATH_TYPE_PATH) {
645                /* Do not retry selecting if this cannot be a DF */
646                if ((pathptr[0] == GPK_FID_MF && pathlen > 2)
647                 || (pathptr[0] != GPK_FID_MF && pathlen > 1))
648                        retry = 0;
649                use_relative = match_path(card, &pathptr, &pathlen, file != 0);
650                if (pathlen == 0)
651                        goto done;
652        } else {
653                /* SC_PATH_TYPE_FILEID */
654                if (pathlen > 1)
655                        return SC_ERROR_INVALID_ARGUMENTS;
656                use_relative = 1;
657        }
658
659        if (pathlen == 1 && pathptr[0] == GPK_FID_MF) {
660                /* Select just the MF */
661                leaf_type = GPK_SEL_MF;
662        } else {
663                if (!locked++) {
664                        r = sc_lock(card);
665                        SC_TEST_RET(card->ctx, r, "sc_lock() failed");
666                }
667
668                /* Do we need to select the MF first? */
669                if (!use_relative) {
670                        r = gpk_select_id(card, GPK_SEL_MF, GPK_FID_MF, NULL);
671                        if (r)
672                                sc_unlock(card);
673                        SC_TEST_RET(card->ctx, r, "Unable to select MF");
674
675                        /* Consume the MF FID if it's there */
676                        if (pathptr[0] == GPK_FID_MF) {
677                                pathptr++;
678                                pathlen--;
679                        }
680                        if (pathlen == 0)
681                                goto done;
682                }
683
684                /* Next comes a DF, if at all.
685                 * This loop can deal with nesting levels > 1 even
686                 * though the GPK4000 doesn't support it. */
687                while (pathlen > 1) {
688                        r = gpk_select_id(card, GPK_SEL_DF, pathptr[0], NULL);
689                        if (r)
690                                sc_unlock(card);
691                        SC_TEST_RET(card->ctx, r, "Unable to select DF");
692                        pathptr++;
693                        pathlen--;
694                }
695        }
696
697        /* Remaining component will be a DF or EF. How do we find out?
698         * All we can do is try */
699        r = gpk_select_id(card, leaf_type, pathptr[0], file);
700        if (r) {
701                /* Did we guess EF, and were wrong? If so, invalidate
702                 * path cache and try again; this time aiming for a DF */
703                if (leaf_type == GPK_SEL_EF && retry) {
704                        card->cache.current_path.len = 0;
705                        leaf_type = GPK_SEL_DF;
706                        goto try_again;
707                }
708        }
709
710done:
711        if (locked)
712                sc_unlock(card);
713        return r;
714}
715
716/*
717 * GPK versions of {read,write,update}_binary functions.
718 * Required because by default the GPKs do word offsets
719 */
720static int
721gpk_read_binary(sc_card_t *card, unsigned int offset,
722                u8 *buf, size_t count, unsigned long flags)
723{
724        struct gpk_private_data *priv = DRVDATA(card);
725
726        if (offset & priv->offset_mask) {
727                sc_error(card->ctx, "Invalid file offset (not a multiple of %d)",
728                                priv->offset_mask + 1);
729                return SC_ERROR_INVALID_ARGUMENTS;
730        }
731        return iso_ops->read_binary(card, offset >> priv->offset_shift,
732                        buf, count, flags);
733}
734
735static int
736gpk_write_binary(sc_card_t *card, unsigned int offset,
737                const u8 *buf, size_t count, unsigned long flags)
738{
739        struct gpk_private_data *priv = DRVDATA(card);
740
741        if (offset & priv->offset_mask) {
742                sc_error(card->ctx, "Invalid file offset (not a multiple of %d)",
743                                priv->offset_mask + 1);
744                return SC_ERROR_INVALID_ARGUMENTS;
745        }
746        return iso_ops->write_binary(card, offset >> priv->offset_shift,
747                        buf, count, flags);
748}
749
750static int
751gpk_update_binary(sc_card_t *card, unsigned int offset,
752                const u8 *buf, size_t count, unsigned long flags)
753{
754        struct gpk_private_data *priv = DRVDATA(card);
755
756        if (offset & priv->offset_mask) {
757                sc_error(card->ctx, "Invalid file offset (not a multiple of %d)",
758                                priv->offset_mask + 1);
759                return SC_ERROR_INVALID_ARGUMENTS;
760        }
761        return iso_ops->update_binary(card, offset >> priv->offset_shift,
762                        buf, count, flags);
763}
764
765/*
766 * Secure messaging
767 */
768static int
769gpk_compute_crycks(sc_card_t *card, sc_apdu_t *apdu,
770                        u8 *crycks1)
771{
772        struct gpk_private_data *priv = DRVDATA(card);
773        u8              in[8], out[8], block[64];
774        unsigned int    len = 0, i;
775        int             r = SC_SUCCESS, outl;
776        EVP_CIPHER_CTX  ctx;
777
778        /* Fill block with 0x00 and then with the data. */
779        memset(block, 0x00, sizeof(block));
780        block[len++] = apdu->cla;
781        block[len++] = apdu->ins;
782        block[len++] = apdu->p1;
783        block[len++] = apdu->p2;
784        block[len++] = apdu->lc + 3;
785        if ((i = apdu->datalen) + len > sizeof(block))
786                i = sizeof(block) - len;
787        memcpy(block+len, apdu->data, i);
788        len += i;
789
790        /* Set IV */
791        memset(in, 0x00, 8);
792
793        EVP_CIPHER_CTX_init(&ctx);
794        EVP_EncryptInit_ex(&ctx, EVP_des_ede_cbc(), NULL, priv->key, in);
795        for (i = 0; i < len; i += 8) {
796                if (!EVP_EncryptUpdate(&ctx, out, &outl, &block[i], 8)) {
797                        r = SC_ERROR_INTERNAL;
798                        break;
799                }
800        }
801        if (!EVP_CIPHER_CTX_cleanup(&ctx))
802                r = SC_ERROR_INTERNAL;
803
804        memcpy((u8 *) (apdu->data + apdu->datalen), out + 5, 3);
805        apdu->datalen += 3;
806        apdu->lc += 3;
807        apdu->le += 3;
808        if (crycks1)
809                memcpy(crycks1, out, 3);
810        sc_mem_clear(in, sizeof(in));
811        sc_mem_clear(out, sizeof(out));
812        sc_mem_clear(block, sizeof(block));
813        return r;
814}
815
816/*
817 * Verify secure messaging response
818 */
819static int
820gpk_verify_crycks(sc_card_t *card, sc_apdu_t *apdu, u8 *crycks)
821{
822        if (apdu->resplen < 3
823         || memcmp(apdu->resp + apdu->resplen - 3, crycks, 3)) {
824                if (card->ctx->debug)
825                        sc_debug(card->ctx, "Invalid secure messaging reply\n");
826                return SC_ERROR_UNKNOWN_DATA_RECEIVED;
827        }
828        apdu->resplen -= 3;
829        return 0;
830}
831
832/*
833 * Create a file or directory.
834 * This is a bit tricky because we abuse the ef_structure
835 * field to transport file types that are non-standard
836 * (the GPK4000 has lots of bizarre file types).
837 */
838static int
839gpk_create_file(sc_card_t *card, sc_file_t *file)
840{
841        struct gpk_private_data *priv = DRVDATA(card);
842        sc_apdu_t       apdu;
843        u8              data[28+3], crycks[3], resp[3];
844        size_t          datalen, namelen;
845        int             r;
846
847        if (card->ctx->debug)
848                sc_debug(card->ctx, "gpk_create_file(0x%04X)\n", file->id);
849
850        /* Prepare APDU */
851        memset(&apdu, 0, sizeof(apdu));
852        apdu.cla = 0x80;        /* assume no secure messaging */
853        apdu.cse = SC_APDU_CASE_3_SHORT;
854        apdu.ins = 0xE0;
855        apdu.p2  = 0x00;
856
857        /* clear data */
858        memset(data, 0, sizeof(data));
859        datalen = 12;
860
861        /* FID */
862        data[0] = file->id >> 8;
863        data[1] = file->id & 0xFF;
864
865        /* encode ACLs */
866        if (file->type == SC_FILE_TYPE_DF) {
867                /* The GPK4000 has separate AC bits for
868                 * creating sensitive files and creating
869                 * data files. Since OpenSC has just the notion
870                 * of "file" we use the same ACL for both AC words
871                 */
872                apdu.p1 = 0x01; /* create DF */
873                data[2] = 0x38;
874                acl_to_ac(file, SC_AC_OP_CREATE, data + 6);
875                acl_to_ac(file, SC_AC_OP_CREATE, data + 8);
876                if ((namelen = file->namelen) != 0) {
877                        if (namelen > 16)
878                                return SC_ERROR_INVALID_ARGUMENTS;
879                        memcpy(data+datalen, file->name, namelen);
880                        data[5] = namelen;
881                        datalen += namelen;
882                }
883        } else {
884                apdu.p1 = 0x02; /* create EF */
885                data[2] = file->ef_structure;
886                data[3] = file->record_length;
887                data[4] = file->size >> 8;
888                data[5] = file->size & 0xff;
889                acl_to_ac(file, SC_AC_OP_UPDATE, data + 6);
890                acl_to_ac(file, SC_AC_OP_WRITE, data + 8);
891                acl_to_ac(file, SC_AC_OP_READ, data + 10);
892        }
893
894        apdu.data = data;
895        apdu.datalen = datalen;
896        apdu.lc = datalen;
897
898        if (priv->key_set) {
899                apdu.cla = 0x84;
900                apdu.cse = SC_APDU_CASE_4_SHORT;
901                r = gpk_compute_crycks(card, &apdu, crycks);
902                if (r)
903                        return r;
904      Â