root/trunk/src/libopensc/pkcs15-gemsafeV1.c

Revision 3557, 15.0 kB (checked in by aj, 3 months ago)

Douglas E. Engert:
The pkcs15-gemsafeV1.c code assumes that the key_ref is always 3. But that is
not always the case. In our case it is 4. The patch tries to determine the
key_ref by looking at what appears to be a table of allocated keys, and picking
the first allocated key.

In case this is not always true, the patch will also allow for the the
opensc.conf card flag = n to specify the key_ref as the low order 4 bits of the
flag.

Line 
1/*
2 * This library is free software; you can redistribute it and/or
3 * modify it under the terms of the GNU Lesser General Public
4 * License as published by the Free Software Foundation; either
5 * version 2.1 of the License, or (at your option) any later version.
6 *
7 * This library is distributed in the hope that it will be useful,
8 * but WITHOUT ANY WARRANTY; without even the implied warranty of
9 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
10 * Lesser General Public License for more details.
11 *
12 * You should have received a copy of the GNU Lesser General Public
13 * License along with this library; if not, write to the Free Software
14 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
15*/
16
17/* Initially written by David Mattes (david.mattes@boeing.com) */
18
19#include "internal.h"
20#include "pkcs15.h"
21#include <stdlib.h>
22#include <string.h>
23#include <stdio.h>
24
25#define MANU_ID                 "Gemplus"
26#define APPLET_NAME             "GemSAFE V1"
27#define DRIVER_SERIAL_NUMBER    "v0.9"
28
29int sc_pkcs15emu_gemsafeV1_init_ex(sc_pkcs15_card_t *, sc_pkcs15emu_opt_t *);
30
31static int
32sc_pkcs15emu_add_cert(sc_pkcs15_card_t *p15card,
33        int type, int authority,
34        const sc_path_t *path,
35        const sc_pkcs15_id_t *id,
36        const char *label, int obj_flags);
37
38static int
39sc_pkcs15emu_add_pin(sc_pkcs15_card_t *p15card,
40        const sc_pkcs15_id_t *id, const char *label,
41        const sc_path_t *path, int ref, int type,
42        unsigned int min_length,
43        unsigned int max_length,
44        int flags, int tries_left, const char pad_char, int obj_flags);
45
46static int
47sc_pkcs15emu_add_prkey(sc_pkcs15_card_t *p15card,
48        const sc_pkcs15_id_t *id,
49        const char *label,
50        int type, unsigned int modulus_length, int usage,
51        const sc_path_t *path, int ref,
52        const sc_pkcs15_id_t *auth_id, int obj_flags);
53
54typedef struct cdata_st {
55        const char *label;
56        int         authority;
57        const char *path;
58        const char *id;
59        int         obj_flags;
60} cdata;
61
62const cdata gemsafe_cert[] = {
63        {"DS certificate", 0, "3F0016000004","45", SC_PKCS15_CO_FLAG_MODIFIABLE},
64        {NULL, 0, NULL, 0, 0}
65};
66
67typedef struct pdata_st {
68        const char *id;
69        const char *label;
70        const char *path;
71        int         ref;
72        int         type;
73        unsigned int maxlen;
74        unsigned int minlen;
75        int         flags;
76        int         tries_left;
77        const char  pad_char;
78        int         obj_flags;
79} pindata;
80
81const pindata gemsafe_pin[] = {
82        { "01", "DS pin", NULL, 0x01, SC_PKCS15_PIN_TYPE_BCD,
83          16, 6, SC_PKCS15_PIN_FLAG_NEEDS_PADDING | SC_PKCS15_PIN_FLAG_LOCAL,
84          3, 0xFF,
85          SC_PKCS15_CO_FLAG_MODIFIABLE | SC_PKCS15_CO_FLAG_PRIVATE },
86        { NULL, NULL, NULL, 0, 0, 0, 0, 0, 0, 0, 0 }
87};
88
89typedef struct prdata_st {
90        const char *id;
91        const char *label;
92        unsigned int modulus_len;
93        int         usage;
94        const char *path;
95        int         ref;
96        const char *auth_id;
97        int         obj_flags;
98} prdata;
99
100#define USAGE_NONREP    SC_PKCS15_PRKEY_USAGE_NONREPUDIATION
101#define USAGE_KE        SC_PKCS15_PRKEY_USAGE_ENCRYPT | \
102                        SC_PKCS15_PRKEY_USAGE_DECRYPT | \
103                        SC_PKCS15_PRKEY_USAGE_WRAP    | \
104                        SC_PKCS15_PRKEY_USAGE_UNWRAP
105#define USAGE_AUT       SC_PKCS15_PRKEY_USAGE_ENCRYPT | \
106                        SC_PKCS15_PRKEY_USAGE_DECRYPT | \
107                        SC_PKCS15_PRKEY_USAGE_WRAP    | \
108                        SC_PKCS15_PRKEY_USAGE_UNWRAP  | \
109                        SC_PKCS15_PRKEY_USAGE_SIGN
110
111const prdata gemsafe_prkeys[] = {
112        { "45", "DS key", 1024, USAGE_AUT, NULL,
113          0x03, "01", SC_PKCS15_CO_FLAG_PRIVATE},
114        { NULL, NULL, 0, 0, NULL, 0, NULL, 0}
115};
116
117static int gemsafe_get_cert_len(sc_card_t *card, sc_path_t *path,
118        int *key_ref)
119{
120        const char *fn_name = "gemsafe_get_cert_len";
121        int r;
122        int ind;
123        u8  ibuf[248];
124        struct sc_file *file;
125        size_t objlen, certlen;
126        unsigned int block=0;
127        int found = 0;
128        unsigned int offset=0, index_local, i=0;
129
130        r = sc_select_file(card, path, &file);
131        if (r < 0)
132                return 0;
133
134        /* Apparently, the Applet max read "quanta" is 248 bytes */
135        /* Initial read */
136        r = sc_read_binary(card, offset, ibuf, 248, 0);
137        if (r < 0)
138                return 0;
139
140        /* Actual stored object size is encoded in first 2 bytes
141         * (allocated EF space is much greater!)
142         */
143        objlen = (((size_t) ibuf[0]) << 8) | ibuf[1];
144        sc_debug(card->ctx, "%s: Certificate object is of size: %d\n", fn_name, objlen);
145
146        if (objlen < 1 || objlen > 10240) {
147            sc_error(card->ctx, "%s: Invalid object size: %d\n", fn_name, objlen);
148            return 0;
149        }
150
151        /*
152         * We need to find the private key associated with the cert
153         * It looks like the first thing in the block is a table of
154         * which keys are allocated.
155         * We will look for the first allocated key, and save the
156         * key_ref. The table is small and is in the first 248 bytes.
157         * If for some reason this is not true, we can still override
158         * the key_ref in the opensc.conf with flag = n.
159         */
160        ind = 2; /* skip length */
161        while (ibuf[ind] == 0x01) {
162                if (ibuf[ind+1] == 0xFE) {
163                        *key_ref = ibuf[ind+4];
164                        sc_debug(card->ctx, "Using key_ref %d found at offset %d\n",
165                                        *key_ref, ind);
166                        break;
167                }
168                ind = ind + 8;
169        }
170
171        /* Using (block+1) in while loop avoids using final cert object data block */
172        while (!found && ( (block+1) * 248 < objlen) ) {
173            /* Check current buffer */
174            for (i = 0; i < 248; i++) {
175                if (ibuf[i] == 0x30 && ibuf[i+1] == 0x82) {
176                    found = 1;
177                    break;
178                }
179            }
180
181            /* Grab another buffer */
182            if (!found) {
183                block++;
184                offset = block*248;
185                r = sc_read_binary(card, offset, ibuf, 248, 0);
186                if (r < 0) {
187                    sc_error(card->ctx, "%s: Could not read cert object\n", fn_name);
188                    return 0;
189                }
190            }
191
192        }
193
194        index_local = block*248 + i;
195
196        /* DER Cert len is encoded this way */
197        certlen = ((((size_t) ibuf[i+2]) << 8) | ibuf[i+3]) + 4;
198        sc_debug(card->ctx, "%s: certlen: %04X\n", fn_name, certlen);
199
200        path->index = index_local;
201        path->count = certlen;
202
203        return 1;
204
205}
206
207static int gemsafe_detect_card( sc_pkcs15_card_t *p15card)
208{
209    sc_debug(p15card->card->ctx, "In gemsafe_detect_card\n");
210    return SC_SUCCESS;
211}
212
213static int sc_pkcs15emu_gemsafeV1_init( sc_pkcs15_card_t *p15card)
214{
215    const char *fn_name = "sc_pkcs15emu_gemsafe_init";
216
217    int    r, i;
218        int        key_ref = 0x03;
219    struct sc_path path;
220    struct sc_file *file = NULL;
221    struct sc_card *card = p15card->card;
222    struct sc_apdu apdu;
223    u8     rbuf[SC_MAX_APDU_BUFFER_SIZE];
224    char * endptr;
225    float version=0.0;
226
227    sc_debug(p15card->card->ctx, "%s: Setting pkcs15 parameters\n", fn_name);
228
229    if (p15card->label)
230        free(p15card->label);
231    p15card->label = malloc(strlen(APPLET_NAME) + 1);
232    if (!p15card->label)
233        return SC_ERROR_INTERNAL;
234    strcpy(p15card->label, APPLET_NAME);
235
236    if (p15card->serial_number)
237            free(p15card->serial_number);
238    p15card->serial_number = malloc(strlen(DRIVER_SERIAL_NUMBER) + 1);
239    if (!p15card->serial_number)
240            return SC_ERROR_INTERNAL;
241    strcpy(p15card->serial_number, DRIVER_SERIAL_NUMBER);
242
243    /* the GemSAFE applet version number */
244    sc_format_apdu(card, &apdu, SC_APDU_CASE_2_SHORT, 0xca, 0xdf, 0x03);
245    apdu.cla = 0x80;
246    apdu.resp = rbuf;
247    apdu.resplen = sizeof(rbuf);
248    /* Manual says Le=0x05, but should be 0x08 to return full version numer */
249    apdu.le = 0x08;
250    apdu.lc = 0;
251    apdu.datalen = 0;
252    r = sc_transmit_apdu(card, &apdu);
253    SC_TEST_RET(card->ctx, r, "APDU transmit failed");
254    if (apdu.sw1 != 0x90 || apdu.sw2 != 0x00)
255            return SC_ERROR_INTERNAL;
256    if (r != SC_SUCCESS)
257            return SC_ERROR_INTERNAL;
258    endptr = (char *)(apdu.resp + apdu.resplen);
259    version = strtod( (const char *)(apdu.resp + 4), &endptr);
260    sc_debug(p15card->card->ctx, "%s: version (float): %f, version (int): %d\n",
261            fn_name, version, (int)version);
262    p15card->version = (int)version;
263
264    /* the manufacturer ID, in this case GemPlus */
265    if (p15card->manufacturer_id)
266            free(p15card->manufacturer_id);
267    p15card->manufacturer_id = malloc(strlen(MANU_ID) + 1);
268    if (!p15card->manufacturer_id)
269            return SC_ERROR_INTERNAL;
270    strcpy(p15card->manufacturer_id, MANU_ID);
271
272    /* set certs */
273    sc_debug(p15card->card->ctx, "%s: Setting certificate\n", fn_name);
274    for (i = 0; gemsafe_cert[i].label; i++) {
275            struct sc_pkcs15_id  p15Id;
276
277            sc_format_path(gemsafe_cert[i].path, &path);
278            if (!gemsafe_get_cert_len(card, &path, &key_ref))
279                    /* skip errors */
280                    continue;
281            sc_pkcs15_format_id(gemsafe_cert[i].id, &p15Id);
282            sc_pkcs15emu_add_cert(p15card, SC_PKCS15_TYPE_CERT_X509,
283                            gemsafe_cert[i].authority, &path, &p15Id,
284                            gemsafe_cert[i].label, gemsafe_cert[i].obj_flags);
285    }
286    /* set gemsafe_pin */
287    sc_debug(p15card->card->ctx, "%s: Setting PIN\n", fn_name);
288    for (i = 0; gemsafe_pin[i].label; i++) {
289            struct sc_pkcs15_id  p15Id;
290
291            sc_pkcs15_format_id(gemsafe_pin[i].id, &p15Id);
292            sc_pkcs15emu_add_pin(p15card, &p15Id, gemsafe_pin[i].label,
293                            &path, gemsafe_pin[i].ref, gemsafe_pin[i].type,
294                            gemsafe_pin[i].minlen, gemsafe_pin[i].maxlen,
295                            gemsafe_pin[i].flags,
296                            gemsafe_pin[i].tries_left, gemsafe_pin[i].pad_char,
297                            gemsafe_pin[i].obj_flags);
298    }
299    /* set private keys */
300    sc_debug(p15card->card->ctx, "%s: Setting private key\n", fn_name);
301    for (i = 0; gemsafe_prkeys[i].label; i++) {
302            struct sc_pkcs15_id p15Id,
303                                authId, *pauthId;
304            sc_pkcs15_format_id(gemsafe_prkeys[i].id, &p15Id);
305            if (gemsafe_prkeys[i].auth_id) {
306                    sc_pkcs15_format_id(gemsafe_prkeys[i].auth_id, &authId);
307                    pauthId = &authId;
308            } else
309                    pauthId = NULL;
310                        /*
311                         * the key ref may be different for different sites
312                         * by adding flags=n where the low order 4 bits can be
313                         * the key ref we can force it.
314                         */
315                        if ( p15card->card->flags & 0x0F) {
316                                key_ref = p15card->card->flags & 0x0F;
317                                sc_debug(p15card->card->ctx,
318                                        "Overriding key_ref  with %d\n", key_ref);
319                        }
320            sc_pkcs15emu_add_prkey(p15card, &p15Id, gemsafe_prkeys[i].label,
321                            SC_PKCS15_TYPE_PRKEY_RSA,
322                            gemsafe_prkeys[i].modulus_len, gemsafe_prkeys[i].usage,
323                            &path, key_ref, pauthId,
324                            gemsafe_prkeys[i].obj_flags);
325    }
326
327    /* select the application DF */
328    sc_debug(p15card->card->ctx,"%s: Selecting application DF\n", fn_name);
329    sc_format_path("3F001600", &path);
330    r = sc_select_file(card, &path, &file);
331    if (r != SC_SUCCESS || !file)
332            return SC_ERROR_INTERNAL;
333    /* set the application DF */
334    if (p15card->file_app)
335            free(p15card->file_app);
336    p15card->file_app = file;
337
338    return SC_SUCCESS;
339
340}
341
342int sc_pkcs15emu_gemsafeV1_init_ex( sc_pkcs15_card_t *p15card,
343                        sc_pkcs15emu_opt_t *opts)
344{
345    if (opts && opts->flags & SC_PKCS15EMU_FLAGS_NO_CHECK)
346            return sc_pkcs15emu_gemsafeV1_init(p15card);
347    else {
348            int r = gemsafe_detect_card(p15card);
349            if (r)
350                    return SC_ERROR_WRONG_CARD;
351            return sc_pkcs15emu_gemsafeV1_init(p15card);
352    }
353}
354
355static sc_pkcs15_df_t *
356sc_pkcs15emu_get_df(sc_pkcs15_card_t *p15card, unsigned int type)
357{
358        sc_pkcs15_df_t  *df;
359        sc_file_t       *file;
360        int             created = 0;
361
362        while (1) {
363                for (df = p15card->df_list; df; df = df->next) {
364                        if (df->type == type) {
365                                if (created)
366                                        df->enumerated = 1;
367                                return df;
368                        }
369                }
370
371                assert(created == 0);
372
373                file = sc_file_new();
374                if (!file)
375                        return NULL;
376                sc_format_path("11001101", &file->path);
377                sc_pkcs15_add_df(p15card, type, &file->path, file);
378                sc_file_free(file);
379                created++;
380        }
381}
382
383static int
384sc_pkcs15emu_add_object(sc_pkcs15_card_t *p15card, int type,
385                const char *label, void *data,
386                const sc_pkcs15_id_t *auth_id, int obj_flags)
387{
388        sc_pkcs15_object_t *obj;
389        int             df_type;
390
391        obj = (sc_pkcs15_object_t *) calloc(1, sizeof(*obj));
392
393        obj->type  = type;
394        obj->data  = data;
395
396        if (label)
397                strncpy(obj->label, label, sizeof(obj->label)-1);
398
399        obj->flags = obj_flags;
400        if (auth_id)
401                obj->auth_id = *auth_id;
402
403        switch (type & SC_PKCS15_TYPE_CLASS_MASK) {
404        case SC_PKCS15_TYPE_AUTH:
405                df_type = SC_PKCS15_AODF;
406                break;
407        case SC_PKCS15_TYPE_PRKEY:
408                df_type = SC_PKCS15_PRKDF;
409                break;
410        case SC_PKCS15_TYPE_PUBKEY:
411                df_type = SC_PKCS15_PUKDF;
412                break;
413        case SC_PKCS15_TYPE_CERT:
414                df_type = SC_PKCS15_CDF;
415                break;
416        default:
417                sc_error(p15card->card->ctx,
418                        "Unknown PKCS15 object type %d\n", type);
419                return SC_ERROR_INVALID_ARGUMENTS;
420        }
421
422        obj->df = sc_pkcs15emu_get_df(p15card, df_type);
423        sc_pkcs15_add_object(p15card, obj);
424
425        return 0;
426}
427
428static int
429sc_pkcs15emu_add_pin(sc_pkcs15_card_t *p15card,
430                const sc_pkcs15_id_t *id, const char *label,
431                const sc_path_t *path, int ref, int type,
432                unsigned int min_length,
433                unsigned int max_length,
434                int flags, int tries_left, const char pad_char, int obj_flags)
435{
436        sc_pkcs15_pin_info_t *info;
437
438        info = (sc_pkcs15_pin_info_t *) calloc(1, sizeof(*info));
439        info->auth_id           = *id;
440        info->min_length        = min_length;
441        info->max_length        = max_length;
442        info->stored_length     = max_length;
443        info->type              = type;
444        info->reference         = ref;
445        info->flags             = flags;
446        info->tries_left        = tries_left;
447        info->magic             = SC_PKCS15_PIN_MAGIC;
448        info->pad_char          = pad_char;
449
450        if (path)
451                info->path = *path;
452
453        return sc_pkcs15emu_add_object(p15card,
454                                       SC_PKCS15_TYPE_AUTH_PIN,
455                                       label, info, NULL, obj_flags);
456}
457
458static int
459sc_pkcs15emu_add_cert(sc_pkcs15_card_t *p15card,
460                int type, int authority,
461                const sc_path_t *path,
462                const sc_pkcs15_id_t *id,
463                const char *label, int obj_flags)
464{
465        /* const char *label = "Certificate"; */
466        sc_pkcs15_cert_info_t *info;
467        info = (sc_pkcs15_cert_info_t *) calloc(1, sizeof(*info));
468        info->id                = *id;
469        info->authority         = authority;
470        if (path)
471                info->path = *path;
472
473        return sc_pkcs15emu_add_object(p15card, type, label, info, NULL, obj_flags);
474}
475
476static int
477sc_pkcs15emu_add_prkey(sc_pkcs15_card_t *p15card,
478                const sc_pkcs15_id_t *id,
479                const char *label,
480                int type, unsigned int modulus_length, int usage,
481                const sc_path_t *path, int ref,
482                const sc_pkcs15_id_t *auth_id, int obj_flags)
483{
484        sc_pkcs15_prkey_info_t *info;
485
486        info = (sc_pkcs15_prkey_info_t *) calloc(1, sizeof(*info));
487        info->id                = *id;
488        info->modulus_length    = modulus_length;
489        info->usage             = usage;
490        info->native            = 1;
491        info->access_flags      = SC_PKCS15_PRKEY_ACCESS_SENSITIVE
492                                | SC_PKCS15_PRKEY_ACCESS_ALWAYSSENSITIVE
493                                | SC_PKCS15_PRKEY_ACCESS_NEVEREXTRACTABLE
494                                | SC_PKCS15_PRKEY_ACCESS_LOCAL;
495        info->key_reference     = ref;
496
497        if (path)
498                info->path = *path;
499
500        return sc_pkcs15emu_add_object(p15card, type, label,
501                        info, auth_id, obj_flags);
502}
503
504#if 0
505static int
506sc_pkcs15emu_add_pubkey(sc_pkcs15_card_t *p15card,
507                const sc_pkcs15_id_t *id,
508                const char *label, int type,
509                unsigned int modulus_length, int usage,
510                const sc_path_t *path, int ref,
511                const sc_pkcs15_id_t *auth_id, int obj_flags)
512{
513        sc_pkcs15_pubkey_info_t *info;
514
515        info = (sc_pkcs15_pubkey_info_t *) calloc(1, sizeof(*info));
516        info->id                = *id;
517        info->modulus_length    = modulus_length;
518        info->usage             = usage;
519        info->access_flags      = SC_PKCS15_PRKEY_ACCESS_EXTRACTABLE;
520        info->key_reference     = ref;
521
522        if (path)
523                info->path = *path;
524
525        return sc_pkcs15emu_add_object(p15card, type, label, info, auth_id, obj_flags);
526}
527#endif
528
529/* SC_IMPLEMENT_DRIVER_VERSION("0.9.4") */
Note: See TracBrowser for help on using the browser.