Revision 111a38b0

b/Makefile
141 141
check-qfloat: check-qfloat.o qfloat.o $(CHECK_PROG_DEPS)
142 142
check-qjson: check-qjson.o qfloat.o qint.o qdict.o qstring.o qlist.o qbool.o qjson.o json-streamer.o json-lexer.o json-parser.o $(CHECK_PROG_DEPS)
143 143

  
144
QEMULIBS=libhw32 libhw64 libuser libdis libdis-user
145

  
144 146
clean:
145 147
# avoid old build problems by removing potentially incorrect old files
146 148
	rm -f config.mak op-i386.h opc-i386.h gen-op-i386.h op-arm.h opc-arm.h gen-op-arm.h
......
152 154
	rm -f trace-dtrace.dtrace trace-dtrace.dtrace-timestamp
153 155
	rm -f trace-dtrace.h trace-dtrace.h-timestamp
154 156
	$(MAKE) -C tests clean
155
	for d in $(ALL_SUBDIRS) libhw32 libhw64 libuser libdis libdis-user; do \
157
	for d in $(ALL_SUBDIRS) $(QEMULIBS) libcacard; do \
156 158
	if test -d $$d; then $(MAKE) -C $$d $@ || exit 1; fi; \
157 159
	rm -f $$d/qemu-options.def; \
158 160
        done
......
163 165
	rm -f roms/seabios/config.mak roms/vgabios/config.mak
164 166
	rm -f qemu-doc.info qemu-doc.aux qemu-doc.cp qemu-doc.dvi qemu-doc.fn qemu-doc.info qemu-doc.ky qemu-doc.log qemu-doc.pdf qemu-doc.pg qemu-doc.toc qemu-doc.tp qemu-doc.vr
165 167
	rm -f qemu-tech.info qemu-tech.aux qemu-tech.cp qemu-tech.dvi qemu-tech.fn qemu-tech.info qemu-tech.ky qemu-tech.log qemu-tech.pdf qemu-tech.pg qemu-tech.toc qemu-tech.tp qemu-tech.vr
166
	for d in $(TARGET_DIRS) libhw32 libhw64 libuser libdis libdis-user; do \
168
	for d in $(TARGET_DIRS) $(QEMULIBS); do \
167 169
	rm -rf $$d || exit 1 ; \
168 170
        done
169 171

  
b/Makefile.objs
352 352
endif
353 353
endif
354 354

  
355
######################################################################
356
# smartcard
357

  
358
libcacard-y = cac.o event.o vcard.o vreader.o vcard_emul_nss.o vcard_emul_type.o card_7816.o
359

  
355 360
vl.o: QEMU_CFLAGS+=$(GPROF_CFLAGS)
356 361

  
357 362
vl.o: QEMU_CFLAGS+=$(SDL_CFLAGS)
b/Makefile.target
358 358

  
359 359
endif # CONFIG_SOFTMMU
360 360

  
361
ifndef CONFIG_LINUX_USER
362
# libcacard needs qemu-thread support, and besides is only needed by devices
363
# so not requires with linux-user targets
364
obj-$(CONFIG_SMARTCARD_NSS) += $(addprefix ../libcacard/, $(libcacard-y))
365
endif # CONFIG_LINUX_USER
366

  
361 367
obj-y += $(addprefix ../, $(trace-obj-y))
362 368
obj-$(CONFIG_GDBSTUB_XML) += gdbstub-xml.o
363 369

  
b/configure
176 176
spice=""
177 177
rbd=""
178 178
smartcard=""
179
smartcard_nss=""
179 180

  
180 181
# parse CC options first
181 182
for opt do
......
729 730
  ;;
730 731
  --enable-smartcard) smartcard="yes"
731 732
  ;;
733
  --disable-smartcard-nss) smartcard_nss="no"
734
  ;;
735
  --enable-smartcard-nss) smartcard_nss="yes"
736
  ;;
732 737
  *) echo "ERROR: unknown option $opt"; show_help="yes"
733 738
  ;;
734 739
  esac
......
928 933
echo "  --enable-rbd             enable building the rados block device (rbd)"
929 934
echo "  --disable-smartcard      disable smartcard support"
930 935
echo "  --enable-smartcard       enable smartcard support"
936
echo "  --disable-smartcard-nss  disable smartcard nss support"
937
echo "  --enable-smartcard-nss   enable smartcard nss support"
931 938
echo ""
932 939
echo "NOTE: The object files are built at the place where configure is launched"
933 940
exit 1
......
2311 2318
  fi
2312 2319
fi
2313 2320

  
2321
# check for libcacard for smartcard support
2322
if test "$smartcard" != "no" ; then
2323
    smartcard="yes"
2324
    smartcard_cflags=""
2325
    # TODO - what's the minimal nss version we support?
2326
    if test "$smartcard_nss" != "no"; then
2327
        if $pkg_config --atleast-version=3.12.8 nss >/dev/null 2>&1 ; then
2328
            smartcard_nss="yes"
2329
            smartcard_cflags="-I\$(SRC_PATH)/libcacard"
2330
            libcacard_libs=$($pkg_config --libs nss 2>/dev/null)
2331
            libcacard_cflags=$($pkg_config --cflags nss 2>/dev/null)
2332
            QEMU_CFLAGS="$QEMU_CFLAGS $smartcard_cflags $libcacard_cflags"
2333
            LIBS="$libcacard_libs $LIBS"
2334
        else
2335
            if test "$smartcard_nss" = "yes"; then
2336
                feature_not_found "nss"
2337
            fi
2338
            smartcard_nss="no"
2339
        fi
2340
    fi
2341
fi
2342
if test "$smartcard" = "no" ; then
2343
    smartcard_nss="no"
2344
fi
2345

  
2314 2346
##########################################
2315 2347

  
2316 2348
##########################################
......
2549 2581
echo "spice support     $spice"
2550 2582
echo "rbd support       $rbd"
2551 2583
echo "xfsctl support    $xfs"
2584
echo "nss used          $smartcard_nss"
2552 2585

  
2553 2586
if test $sdl_too_old = "yes"; then
2554 2587
echo "-> Your SDL version is too old - please upgrade to have SDL support"
......
2835 2868
  echo "CONFIG_SMARTCARD=y" >> $config_host_mak
2836 2869
fi
2837 2870

  
2871
if test "$smartcard_nss" = "yes" ; then
2872
  echo "CONFIG_SMARTCARD_NSS=y" >> $config_host_mak
2873
fi
2874

  
2838 2875
# XXX: suppress that
2839 2876
if [ "$bsd" = "yes" ] ; then
2840 2877
  echo "CONFIG_BSD=y" >> $config_host_mak
......
3183 3220
if test "$target_darwin_user" = "yes" ; then
3184 3221
  echo "CONFIG_DARWIN_USER=y" >> $config_target_mak
3185 3222
fi
3223
if test "$smartcard_nss" = "yes" ; then
3224
  echo "subdir-$target: subdir-libcacard" >> $config_host_mak
3225
  echo "libcacard_libs=$libcacard_libs" >> $config_host_mak
3226
  echo "libcacard_cflags=$libcacard_cflags" >> $config_host_mak
3227
fi
3186 3228
list=""
3187 3229
if test ! -z "$gdb_xml_files" ; then
3188 3230
  for x in $gdb_xml_files; do
......
3396 3438
  echo "QEMU_CFLAGS+=-DTARGET_PHYS_ADDR_BITS=$hwlib" > $d/config.mak
3397 3439
done
3398 3440

  
3441
if [ "$source_path" != `pwd` ]; then
3442
    # out of tree build
3443
    mkdir -p libcacard
3444
    rm -f libcacard/Makefile
3445
    ln -s "$source_path/libcacard/Makefile" libcacard/Makefile
3446
fi
3447

  
3399 3448
d=libuser
3400 3449
mkdir -p $d
3401 3450
symlink $source_path/Makefile.user $d/Makefile
b/libcacard/Makefile
1
-include ../config-host.mak
2
-include $(SRC_PATH)/Makefile.objs
3
-include $(SRC_PATH)/rules.mak
4

  
5
$(call set-vpath, $(SRC_PATH):$(SRC_PATH)/libcacard)
6

  
7
ifeq ($(CONFIG_WIN32),y)
8
QEMU_THREAD=qemu-thread-win32.o
9
else
10
QEMU_THREAD=qemu-thread-posix.o
11
endif
12

  
13

  
14
QEMU_OBJS=$(addprefix ../, $(QEMU_THREAD) $(oslib-obj-y) $(trace-obj-y) qemu-malloc.o qemu-timer-common.o)
15

  
16
QEMU_CFLAGS+=-I../
17

  
18
clean:
19
	rm -f *.o */*.o *.d */*.d *.a */*.a *~ */*~
20

  
b/libcacard/cac.c
1
/*
2
 * implement the applets for the CAC card.
3
 *
4
 * This code is licensed under the GNU LGPL, version 2.1 or later.
5
 * See the COPYING.LIB file in the top-level directory.
6
 */
7

  
8
#include "qemu-common.h"
9

  
10
#include "cac.h"
11
#include "vcard.h"
12
#include "vcard_emul.h"
13
#include "card_7816.h"
14

  
15
#define CAC_GET_PROPERTIES  0x56
16
#define CAC_GET_ACR         0x4c
17
#define CAC_READ_BUFFER     0x52
18
#define CAC_UPDATE_BUFFER   0x58
19
#define CAC_SIGN_DECRYPT    0x42
20
#define CAC_GET_CERTIFICATE 0x36
21

  
22
/* private data for PKI applets */
23
typedef struct CACPKIAppletDataStruct {
24
    unsigned char *cert;
25
    int cert_len;
26
    unsigned char *cert_buffer;
27
    int cert_buffer_len;
28
    unsigned char *sign_buffer;
29
    int sign_buffer_len;
30
    VCardKey *key;
31
} CACPKIAppletData;
32

  
33
/*
34
 * CAC applet private data
35
 */
36
struct VCardAppletPrivateStruct {
37
    union {
38
        CACPKIAppletData pki_data;
39
        void *reserved;
40
    } u;
41
};
42

  
43
/*
44
 * handle all the APDU's that are common to all CAC applets
45
 */
46
static VCardStatus
47
cac_common_process_apdu(VCard *card, VCardAPDU *apdu, VCardResponse **response)
48
{
49
    int ef;
50

  
51
    switch (apdu->a_ins) {
52
    case VCARD7816_INS_SELECT_FILE:
53
        if (apdu->a_p1 != 0x02) {
54
            /* let the 7816 code handle applet switches */
55
            return VCARD_NEXT;
56
        }
57
        /* handle file id setting */
58
        if (apdu->a_Lc != 2) {
59
            *response = vcard_make_response(
60
                VCARD7816_STATUS_ERROR_DATA_INVALID);
61
            return VCARD_DONE;
62
        }
63
        /* CAC 1.0 only supports ef = 0 */
64
        ef = apdu->a_body[0] | (apdu->a_body[1] << 8);
65
        if (ef != 0) {
66
            *response = vcard_make_response(
67
                VCARD7816_STATUS_ERROR_FILE_NOT_FOUND);
68
            return VCARD_DONE;
69
        }
70
        *response = vcard_make_response(VCARD7816_STATUS_SUCCESS);
71
        return VCARD_DONE;
72
    case VCARD7816_INS_GET_RESPONSE:
73
    case VCARD7816_INS_VERIFY:
74
        /* let the 7816 code handle these */
75
        return VCARD_NEXT;
76
    case CAC_GET_PROPERTIES:
77
    case CAC_GET_ACR:
78
        /* skip these for now, this will probably be needed */
79
        *response = vcard_make_response(VCARD7816_STATUS_ERROR_P1_P2_INCORRECT);
80
        return VCARD_DONE;
81
    }
82
    *response = vcard_make_response(
83
        VCARD7816_STATUS_ERROR_COMMAND_NOT_SUPPORTED);
84
    return VCARD_DONE;
85
}
86

  
87
/*
88
 *  reset the inter call state between applet selects
89
 */
90
static VCardStatus
91
cac_applet_pki_reset(VCard *card, int channel)
92
{
93
    VCardAppletPrivate *applet_private = NULL;
94
    CACPKIAppletData *pki_applet = NULL;
95
    applet_private = vcard_get_current_applet_private(card, channel);
96
    assert(applet_private);
97
    pki_applet = &(applet_private->u.pki_data);
98

  
99
    pki_applet->cert_buffer = NULL;
100
    if (pki_applet->sign_buffer) {
101
        qemu_free(pki_applet->sign_buffer);
102
        pki_applet->sign_buffer = NULL;
103
    }
104
    pki_applet->cert_buffer_len = 0;
105
    pki_applet->sign_buffer_len = 0;
106
    return VCARD_DONE;
107
}
108

  
109
static VCardStatus
110
cac_applet_pki_process_apdu(VCard *card, VCardAPDU *apdu,
111
                            VCardResponse **response)
112
{
113
    CACPKIAppletData *pki_applet = NULL;
114
    VCardAppletPrivate *applet_private = NULL;
115
    int size, next;
116
    unsigned char *sign_buffer;
117
    vcard_7816_status_t status;
118

  
119
    applet_private = vcard_get_current_applet_private(card, apdu->a_channel);
120
    assert(applet_private);
121
    pki_applet = &(applet_private->u.pki_data);
122

  
123
    switch (apdu->a_ins) {
124
    case CAC_UPDATE_BUFFER:
125
        *response = vcard_make_response(
126
            VCARD7816_STATUS_ERROR_CONDITION_NOT_SATISFIED);
127
        return VCARD_DONE;
128
    case CAC_GET_CERTIFICATE:
129
        if ((apdu->a_p2 != 0) || (apdu->a_p1 != 0)) {
130
            *response = vcard_make_response(
131
                             VCARD7816_STATUS_ERROR_P1_P2_INCORRECT);
132
            break;
133
        }
134
        assert(pki_applet->cert != NULL);
135
        size = apdu->a_Le;
136
        if (pki_applet->cert_buffer == NULL) {
137
            pki_applet->cert_buffer = pki_applet->cert;
138
            pki_applet->cert_buffer_len = pki_applet->cert_len;
139
        }
140
        size = MIN(size, pki_applet->cert_buffer_len);
141
        next = MIN(255, pki_applet->cert_buffer_len - size);
142
        *response = vcard_response_new_bytes(
143
                        card, pki_applet->cert_buffer, size,
144
                        apdu->a_Le, next ?
145
                        VCARD7816_SW1_WARNING_CHANGE :
146
                        VCARD7816_SW1_SUCCESS,
147
                        next);
148
        pki_applet->cert_buffer += size;
149
        pki_applet->cert_buffer_len -= size;
150
        if ((*response == NULL) || (next == 0)) {
151
            pki_applet->cert_buffer = NULL;
152
        }
153
        if (*response == NULL) {
154
            *response = vcard_make_response(
155
                            VCARD7816_STATUS_EXC_ERROR_MEMORY_FAILURE);
156
        }
157
        return VCARD_DONE;
158
    case CAC_SIGN_DECRYPT:
159
        if (apdu->a_p2 != 0) {
160
            *response = vcard_make_response(
161
                             VCARD7816_STATUS_ERROR_P1_P2_INCORRECT);
162
            break;
163
        }
164
        size = apdu->a_Lc;
165

  
166
        sign_buffer = realloc(pki_applet->sign_buffer,
167
                      pki_applet->sign_buffer_len+size);
168
        if (sign_buffer == NULL) {
169
            qemu_free(pki_applet->sign_buffer);
170
            pki_applet->sign_buffer = NULL;
171
            pki_applet->sign_buffer_len = 0;
172
            *response = vcard_make_response(
173
                            VCARD7816_STATUS_EXC_ERROR_MEMORY_FAILURE);
174
            return VCARD_DONE;
175
        }
176
        memcpy(sign_buffer+pki_applet->sign_buffer_len, apdu->a_body, size);
177
        size += pki_applet->sign_buffer_len;
178
        switch (apdu->a_p1) {
179
        case  0x80:
180
            /* p1 == 0x80 means we haven't yet sent the whole buffer, wait for
181
             * the rest */
182
            pki_applet->sign_buffer = sign_buffer;
183
            pki_applet->sign_buffer_len = size;
184
            *response = vcard_make_response(VCARD7816_STATUS_SUCCESS);
185
            return VCARD_DONE;
186
        case 0x00:
187
            /* we now have the whole buffer, do the operation, result will be
188
             * in the sign_buffer */
189
            status = vcard_emul_rsa_op(card, pki_applet->key,
190
                                       sign_buffer, size);
191
            if (status != VCARD7816_STATUS_SUCCESS) {
192
                *response = vcard_make_response(status);
193
                break;
194
            }
195
            *response = vcard_response_new(card, sign_buffer, size, apdu->a_Le,
196
                                                     VCARD7816_STATUS_SUCCESS);
197
            if (*response == NULL) {
198
                *response = vcard_make_response(
199
                                VCARD7816_STATUS_EXC_ERROR_MEMORY_FAILURE);
200
            }
201
            break;
202
        default:
203
           *response = vcard_make_response(
204
                                VCARD7816_STATUS_ERROR_P1_P2_INCORRECT);
205
            break;
206
        }
207
        qemu_free(sign_buffer);
208
        pki_applet->sign_buffer = NULL;
209
        pki_applet->sign_buffer_len = 0;
210
        return VCARD_DONE;
211
    case CAC_READ_BUFFER:
212
        /* new CAC call, go ahead and use the old version for now */
213
        /* TODO: implement */
214
        *response = vcard_make_response(
215
                                VCARD7816_STATUS_ERROR_COMMAND_NOT_SUPPORTED);
216
        return VCARD_DONE;
217
    }
218
    return cac_common_process_apdu(card, apdu, response);
219
}
220

  
221

  
222
static VCardStatus
223
cac_applet_id_process_apdu(VCard *card, VCardAPDU *apdu,
224
                           VCardResponse **response)
225
{
226
    switch (apdu->a_ins) {
227
    case CAC_UPDATE_BUFFER:
228
        *response = vcard_make_response(
229
                        VCARD7816_STATUS_ERROR_CONDITION_NOT_SATISFIED);
230
        return VCARD_DONE;
231
    case CAC_READ_BUFFER:
232
        /* new CAC call, go ahead and use the old version for now */
233
        /* TODO: implement */
234
        *response = vcard_make_response(
235
                        VCARD7816_STATUS_ERROR_COMMAND_NOT_SUPPORTED);
236
        return VCARD_DONE;
237
    }
238
    return cac_common_process_apdu(card, apdu, response);
239
}
240

  
241

  
242
/*
243
 * TODO: if we ever want to support general CAC middleware, we will need to
244
 * implement the various containers.
245
 */
246
static VCardStatus
247
cac_applet_container_process_apdu(VCard *card, VCardAPDU *apdu,
248
                                  VCardResponse **response)
249
{
250
    switch (apdu->a_ins) {
251
    case CAC_READ_BUFFER:
252
    case CAC_UPDATE_BUFFER:
253
        *response = vcard_make_response(
254
                        VCARD7816_STATUS_ERROR_COMMAND_NOT_SUPPORTED);
255
        return VCARD_DONE;
256
    default:
257
        break;
258
    }
259
    return cac_common_process_apdu(card, apdu, response);
260
}
261

  
262
/*
263
 * utilities for creating and destroying the private applet data
264
 */
265
static void
266
cac_delete_pki_applet_private(VCardAppletPrivate *applet_private)
267
{
268
    CACPKIAppletData *pki_applet_data = NULL;
269
    if (pki_applet_data == NULL) {
270
        return;
271
    }
272
    pki_applet_data = &(applet_private->u.pki_data);
273
    if (pki_applet_data->cert != NULL) {
274
        qemu_free(pki_applet_data->cert);
275
    }
276
    if (pki_applet_data->sign_buffer != NULL) {
277
        qemu_free(pki_applet_data->sign_buffer);
278
    }
279
    if (pki_applet_data->key != NULL) {
280
        vcard_emul_delete_key(pki_applet_data->key);
281
    }
282
    qemu_free(applet_private);
283
}
284

  
285
static VCardAppletPrivate *
286
cac_new_pki_applet_private(const unsigned char *cert,
287
                           int cert_len, VCardKey *key)
288
{
289
    CACPKIAppletData *pki_applet_data = NULL;
290
    VCardAppletPrivate *applet_private = NULL;
291
    applet_private = (VCardAppletPrivate *)qemu_malloc(sizeof(VCardAppletPrivate));
292

  
293
    pki_applet_data = &(applet_private->u.pki_data);
294
    pki_applet_data->cert_buffer = NULL;
295
    pki_applet_data->cert_buffer_len = 0;
296
    pki_applet_data->sign_buffer = NULL;
297
    pki_applet_data->sign_buffer_len = 0;
298
    pki_applet_data->key = NULL;
299
    pki_applet_data->cert = (unsigned char *)qemu_malloc(cert_len+1);
300
    /*
301
     * if we want to support compression, then we simply change the 0 to a 1
302
     * and compress the cert data with libz
303
     */
304
    pki_applet_data->cert[0] = 0; /* not compressed */
305
    memcpy(&pki_applet_data->cert[1], cert, cert_len);
306
    pki_applet_data->cert_len = cert_len+1;
307

  
308
    pki_applet_data->key = key;
309
    return applet_private;
310
}
311

  
312

  
313
/*
314
 * create a new cac applet which links to a given cert
315
 */
316
static VCardApplet *
317
cac_new_pki_applet(int i, const unsigned char *cert,
318
                   int cert_len, VCardKey *key)
319
{
320
    VCardAppletPrivate *applet_private = NULL;
321
    VCardApplet *applet = NULL;
322
    unsigned char pki_aid[] = { 0xa0, 0x00, 0x00, 0x00, 0x79, 0x01, 0x00 };
323
    int pki_aid_len = sizeof(pki_aid);
324

  
325
    pki_aid[pki_aid_len-1] = i;
326

  
327
    applet_private = cac_new_pki_applet_private(cert, cert_len, key);
328
    if (applet_private == NULL) {
329
        goto failure;
330
    }
331
    applet = vcard_new_applet(cac_applet_pki_process_apdu, cac_applet_pki_reset,
332
                              pki_aid, pki_aid_len);
333
    if (applet == NULL) {
334
        goto failure;
335
    }
336
    vcard_set_applet_private(applet, applet_private,
337
                             cac_delete_pki_applet_private);
338
    applet_private = NULL;
339

  
340
    return applet;
341

  
342
failure:
343
    if (applet_private != NULL) {
344
        cac_delete_pki_applet_private(applet_private);
345
    }
346
    return NULL;
347
}
348

  
349

  
350
static unsigned char cac_default_container_aid[] = {
351
    0xa0, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00 };
352
static unsigned char cac_id_aid[] = {
353
    0xa0, 0x00, 0x00, 0x00, 0x79, 0x03, 0x00 };
354
/*
355
 * Initialize the cac card. This is the only public function in this file. All
356
 * the rest are connected through function pointers.
357
 */
358
VCardStatus
359
cac_card_init(VReader *reader, VCard *card,
360
              const char *params,
361
              unsigned char * const *cert,
362
              int cert_len[],
363
              VCardKey *key[] /* adopt the keys*/,
364
              int cert_count)
365
{
366
    int i;
367
    VCardApplet *applet;
368

  
369
    /* CAC Cards are VM Cards */
370
    vcard_set_type(card, VCARD_VM);
371

  
372
    /* create one PKI applet for each cert */
373
    for (i = 0; i < cert_count; i++) {
374
        applet = cac_new_pki_applet(i, cert[i], cert_len[i], key[i]);
375
        if (applet == NULL) {
376
            goto failure;
377
        }
378
        vcard_add_applet(card, applet);
379
    }
380

  
381
    /* create a default blank container applet */
382
    applet = vcard_new_applet(cac_applet_container_process_apdu,
383
                              NULL, cac_default_container_aid,
384
                              sizeof(cac_default_container_aid));
385
    if (applet == NULL) {
386
        goto failure;
387
    }
388
    vcard_add_applet(card, applet);
389

  
390
    /* create a default blank container applet */
391
    applet = vcard_new_applet(cac_applet_id_process_apdu,
392
                              NULL, cac_id_aid,
393
                              sizeof(cac_id_aid));
394
    if (applet == NULL) {
395
        goto failure;
396
    }
397
    vcard_add_applet(card, applet);
398
    return VCARD_DONE;
399

  
400
failure:
401
    return VCARD_FAIL;
402
}
403

  
b/libcacard/cac.h
1
/*
2
 * defines the entry point for the cac card. Only used by cac.c anc
3
 * vcard_emul_type.c
4
 *
5
 * This work is licensed under the terms of the GNU LGPL, version 2.1 or later.
6
 * See the COPYING.LIB file in the top-level directory.
7
 */
8
#ifndef CAC_H
9
#define CAC_H 1
10
#include "vcard.h"
11
#include "vreader.h"
12
/*
13
 * Initialize the cac card. This is the only public function in this file. All
14
 * the rest are connected through function pointers.
15
 */
16
VCardStatus cac_card_init(VReader *reader, VCard *card, const char *params,
17
              unsigned char * const *cert, int cert_len[],
18
              VCardKey *key[] /* adopt the keys*/,
19
              int cert_count);
20

  
21
/* not yet implemented */
22
VCardStatus cac_is_cac_card(VReader *reader);
23
#endif
b/libcacard/card_7816.c
1
/*
2
 * Implement the 7816 portion of the card spec
3
 *
4
 * This code is licensed under the GNU LGPL, version 2.1 or later.
5
 * See the COPYING.LIB file in the top-level directory.
6
 */
7

  
8
#include "qemu-common.h"
9

  
10
#include "vcard.h"
11
#include "vcard_emul.h"
12
#include "card_7816.h"
13

  
14
/*
15
 * set the status bytes based on the status word
16
 */
17
static void
18
vcard_response_set_status(VCardResponse *response, vcard_7816_status_t status)
19
{
20
    unsigned char sw1, sw2;
21
    response->b_status = status; /* make sure the status and swX representations
22
                                  * are consistent */
23
    sw1 = (status >> 8) & 0xff;
24
    sw2 = status & 0xff;
25
    response->b_sw1 = sw1;
26
    response->b_sw2 = sw2;
27
    response->b_data[response->b_len] = sw1;
28
    response->b_data[response->b_len+1] = sw2;
29
}
30

  
31
/*
32
 * set the status bytes in a response buffer
33
 */
34
static void
35
vcard_response_set_status_bytes(VCardResponse *response,
36
                               unsigned char sw1, unsigned char sw2)
37
{
38
    response->b_status = sw1 << 8 | sw2;
39
    response->b_sw1 = sw1;
40
    response->b_sw2 = sw2;
41
    response->b_data[response->b_len] = sw1;
42
    response->b_data[response->b_len+1] = sw2;
43
}
44

  
45
/*
46
 * allocate a VCardResponse structure, plus space for the data buffer, and
47
 * set up everything but the resonse bytes.
48
 */
49
VCardResponse *
50
vcard_response_new_data(unsigned char *buf, int len)
51
{
52
    VCardResponse *new_response;
53

  
54
    new_response = (VCardResponse *)qemu_malloc(sizeof(VCardResponse));
55
    new_response->b_data = qemu_malloc(len + 2);
56
    memcpy(new_response->b_data, buf, len);
57
    new_response->b_total_len = len+2;
58
    new_response->b_len = len;
59
    new_response->b_type = VCARD_MALLOC;
60
    return new_response;
61
}
62

  
63
static VCardResponse *
64
vcard_init_buffer_response(VCard *card, unsigned char *buf, int len)
65
{
66
    VCardResponse *response;
67
    VCardBufferResponse *buffer_response;
68

  
69
    buffer_response = vcard_get_buffer_response(card);
70
    if (buffer_response) {
71
        vcard_set_buffer_response(card, NULL);
72
        vcard_buffer_response_delete(buffer_response);
73
    }
74
    buffer_response = vcard_buffer_response_new(buf, len);
75
    if (buffer_response == NULL) {
76
        return NULL;
77
    }
78
    response = vcard_response_new_status_bytes(VCARD7816_SW1_RESPONSE_BYTES,
79
                                               len > 255 ? 0 : len);
80
    if (response == NULL) {
81
        return NULL;
82
    }
83
    vcard_set_buffer_response(card, buffer_response);
84
    return response;
85
}
86

  
87
/*
88
 * general buffer to hold results from APDU calls
89
 */
90
VCardResponse *
91
vcard_response_new(VCard *card, unsigned char *buf,
92
                   int len, int Le, vcard_7816_status_t status)
93
{
94
    VCardResponse *new_response;
95

  
96
    if (len > Le) {
97
        return vcard_init_buffer_response(card, buf, len);
98
    }
99
    new_response = vcard_response_new_data(buf, len);
100
    if (new_response == NULL) {
101
        return NULL;
102
    }
103
    vcard_response_set_status(new_response, status);
104
    return new_response;
105
}
106

  
107
/*
108
 * general buffer to hold results from APDU calls
109
 */
110
VCardResponse *
111
vcard_response_new_bytes(VCard *card, unsigned char *buf, int len, int Le,
112
                         unsigned char sw1, unsigned char sw2)
113
{
114
    VCardResponse *new_response;
115

  
116
    if (len > Le) {
117
        return vcard_init_buffer_response(card, buf, len);
118
    }
119
    new_response = vcard_response_new_data(buf, len);
120
    if (new_response == NULL) {
121
        return NULL;
122
    }
123
    vcard_response_set_status_bytes(new_response, sw1, sw2);
124
    return new_response;
125
}
126

  
127
/*
128
 * get a new Reponse buffer that only has a status.
129
 */
130
static VCardResponse *
131
vcard_response_new_status(vcard_7816_status_t status)
132
{
133
    VCardResponse *new_response;
134

  
135
    new_response = (VCardResponse *)qemu_malloc(sizeof(VCardResponse));
136
    new_response->b_data = &new_response->b_sw1;
137
    new_response->b_len = 0;
138
    new_response->b_total_len = 2;
139
    new_response->b_type = VCARD_MALLOC_STRUCT;
140
    vcard_response_set_status(new_response, status);
141
    return new_response;
142
}
143

  
144
/*
145
 * same as above, but specify the status as separate bytes
146
 */
147
VCardResponse *
148
vcard_response_new_status_bytes(unsigned char sw1, unsigned char sw2)
149
{
150
    VCardResponse *new_response;
151

  
152
    new_response = (VCardResponse *)qemu_malloc(sizeof(VCardResponse));
153
    new_response->b_data = &new_response->b_sw1;
154
    new_response->b_len = 0;
155
    new_response->b_total_len = 2;
156
    new_response->b_type = VCARD_MALLOC_STRUCT;
157
    vcard_response_set_status_bytes(new_response, sw1, sw2);
158
    return new_response;
159
}
160

  
161

  
162
/*
163
 * free the response buffer. The Buffer has a type to handle the buffer
164
 * allocated in other ways than through malloc.
165
 */
166
void
167
vcard_response_delete(VCardResponse *response)
168
{
169
    if (response == NULL) {
170
        return;
171
    }
172
    switch (response->b_type) {
173
    case VCARD_MALLOC:
174
        /* everything was malloc'ed */
175
        if (response->b_data) {
176
            qemu_free(response->b_data);
177
        }
178
        qemu_free(response);
179
        break;
180
    case VCARD_MALLOC_DATA:
181
        /* only the data buffer was malloc'ed */
182
        if (response->b_data) {
183
            qemu_free(response->b_data);
184
        }
185
        break;
186
    case VCARD_MALLOC_STRUCT:
187
        /* only the structure was malloc'ed */
188
        qemu_free(response);
189
        break;
190
    case VCARD_STATIC:
191
        break;
192
    }
193
}
194

  
195
/*
196
 * decode the class bit and set our generic type field, channel, and
197
 * secure messaging values.
198
 */
199
static vcard_7816_status_t
200
vcard_apdu_set_class(VCardAPDU *apdu) {
201
    apdu->a_channel = 0;
202
    apdu->a_secure_messaging = 0;
203
    apdu->a_type = apdu->a_cla & 0xf0;
204
    apdu->a_gen_type = VCARD_7816_ISO;
205

  
206
    /* parse the class  tables 8 & 9 of the 7816-4 Part 4 spec */
207
    switch (apdu->a_type) {
208
        /* we only support the basic types */
209
    case 0x00:
210
    case 0x80:
211
    case 0x90:
212
    case 0xa0:
213
        apdu->a_channel = apdu->a_cla & 3;
214
        apdu->a_secure_messaging = apdu->a_cla & 0xe;
215
        break;
216
    case 0xb0:
217
    case 0xc0:
218
        break;
219

  
220
    case 0x10:
221
    case 0x20:
222
    case 0x30:
223
    case 0x40:
224
    case 0x50:
225
    case 0x60:
226
    case 0x70:
227
        /* Reserved for future use */
228
        apdu->a_gen_type = VCARD_7816_RFU;
229
        break;
230
    case 0xd0:
231
    case 0xe0:
232
    case 0xf0:
233
    default:
234
        apdu->a_gen_type =
235
            (apdu->a_cla == 0xff) ? VCARD_7816_PTS : VCARD_7816_PROPIETARY;
236
        break;
237
    }
238
    return VCARD7816_STATUS_SUCCESS;
239
}
240

  
241
/*
242
 * set the Le and Lc fiels according to table 5 of the
243
 * 7816-4 part 4 spec
244
 */
245
static vcard_7816_status_t
246
vcard_apdu_set_length(VCardAPDU *apdu)
247
{
248
    int L, Le;
249

  
250
    /* process according to table 5 of the 7816-4 Part 4 spec.
251
     * variable names match the variables in the spec */
252
    L = apdu->a_len-4; /* fixed APDU header */
253
    apdu->a_Lc = 0;
254
    apdu->a_Le = 0;
255
    apdu->a_body = NULL;
256
    switch (L) {
257
    case 0:
258
        /* 1 minimal apdu */
259
        return VCARD7816_STATUS_SUCCESS;
260
    case 1:
261
        /* 2S only return values apdu */
262
        /*   zero maps to 256 here */
263
        apdu->a_Le = apdu->a_header->ah_Le ?
264
                         apdu->a_header->ah_Le : 256;
265
        return VCARD7816_STATUS_SUCCESS;
266
    default:
267
        /* if the ah_Le byte is zero and we have more than
268
         * 1 byte in the header, then we must be using extended Le and Lc.
269
         * process the extended now. */
270
        if (apdu->a_header->ah_Le == 0) {
271
            if (L < 3) {
272
                /* coding error, need at least 3 bytes */
273
                return VCARD7816_STATUS_ERROR_WRONG_LENGTH;
274
            }
275
            /* calculate the first extended value. Could be either Le or Lc */
276
            Le = (apdu->a_header->ah_body[0] << 8)
277
               || apdu->a_header->ah_body[1];
278
            if (L == 3) {
279
                /* 2E extended, return data only */
280
                /*   zero maps to 65536 */
281
                apdu->a_Le = Le ? Le : 65536;
282
                return VCARD7816_STATUS_SUCCESS;
283
            }
284
            if (Le == 0) {
285
                /* reserved for future use, probably for next time we need
286
                 * to extend the lengths */
287
                return VCARD7816_STATUS_ERROR_WRONG_LENGTH;
288
            }
289
            /* we know that the first extended value is Lc now */
290
            apdu->a_Lc = Le;
291
            apdu->a_body = &apdu->a_header->ah_body[2];
292
            if (L == Le+3) {
293
                /* 3E extended, only body parameters */
294
                return VCARD7816_STATUS_SUCCESS;
295
            }
296
            if (L == Le+5) {
297
                /* 4E extended, parameters and return data */
298
                Le = (apdu->a_data[apdu->a_len-2] << 8)
299
                   || apdu->a_data[apdu->a_len-1];
300
                apdu->a_Le = Le ? Le : 65536;
301
                return VCARD7816_STATUS_SUCCESS;
302
            }
303
            return VCARD7816_STATUS_ERROR_WRONG_LENGTH;
304
        }
305
        /* not extended */
306
        apdu->a_Lc = apdu->a_header->ah_Le;
307
        apdu->a_body = &apdu->a_header->ah_body[0];
308
        if (L ==  apdu->a_Lc + 1) {
309
            /* 3S only body parameters */
310
            return VCARD7816_STATUS_SUCCESS;
311
        }
312
        if (L ==  apdu->a_Lc + 2) {
313
            /* 4S parameters and return data */
314
            Le = apdu->a_data[apdu->a_len-1];
315
            apdu->a_Le = Le ?  Le : 256;
316
            return VCARD7816_STATUS_SUCCESS;
317
        }
318
        break;
319
    }
320
    return VCARD7816_STATUS_ERROR_WRONG_LENGTH;
321
}
322

  
323
/*
324
 * create a new APDU from a raw set of bytes. This will decode all the
325
 * above fields. users of VCARDAPDU's can then depend on the already decoded
326
 * values.
327
 */
328
VCardAPDU *
329
vcard_apdu_new(unsigned char *raw_apdu, int len, vcard_7816_status_t *status)
330
{
331
    VCardAPDU *new_apdu;
332

  
333
    *status = VCARD7816_STATUS_EXC_ERROR_MEMORY_FAILURE;
334
    if (len < 4) {
335
        *status = VCARD7816_STATUS_ERROR_WRONG_LENGTH;
336
        return NULL;
337
    }
338

  
339
    new_apdu = (VCardAPDU *)qemu_malloc(sizeof(VCardAPDU));
340
    new_apdu->a_data = qemu_malloc(len);
341
    memcpy(new_apdu->a_data, raw_apdu, len);
342
    new_apdu->a_len = len;
343
    *status = vcard_apdu_set_class(new_apdu);
344
    if (*status != VCARD7816_STATUS_SUCCESS) {
345
        qemu_free(new_apdu);
346
        return NULL;
347
    }
348
    *status = vcard_apdu_set_length(new_apdu);
349
    if (*status != VCARD7816_STATUS_SUCCESS) {
350
        qemu_free(new_apdu);
351
        new_apdu = NULL;
352
    }
353
    return new_apdu;
354
}
355

  
356
void
357
vcard_apdu_delete(VCardAPDU *apdu)
358
{
359
    if (apdu == NULL) {
360
        return;
361
    }
362
    if (apdu->a_data) {
363
        qemu_free(apdu->a_data);
364
    }
365
    qemu_free(apdu);
366
}
367

  
368

  
369
/*
370
 * declare response buffers for all the 7816 defined error codes
371
 */
372
VCARD_RESPONSE_NEW_STATIC_STATUS(VCARD7816_STATUS_SUCCESS)
373
VCARD_RESPONSE_NEW_STATIC_STATUS(VCARD7816_STATUS_WARNING)
374
VCARD_RESPONSE_NEW_STATIC_STATUS(VCARD7816_STATUS_WARNING_RET_CORUPT)
375
VCARD_RESPONSE_NEW_STATIC_STATUS(VCARD7816_STATUS_WARNING_BUF_END_BEFORE_LE)
376
VCARD_RESPONSE_NEW_STATIC_STATUS(VCARD7816_STATUS_WARNING_INVALID_FILE_SELECTED)
377
VCARD_RESPONSE_NEW_STATIC_STATUS(VCARD7816_STATUS_WARNING_FCI_FORMAT_INVALID)
378
VCARD_RESPONSE_NEW_STATIC_STATUS(VCARD7816_STATUS_WARNING_CHANGE)
379
VCARD_RESPONSE_NEW_STATIC_STATUS(VCARD7816_STATUS_WARNING_FILE_FILLED)
380
VCARD_RESPONSE_NEW_STATIC_STATUS(VCARD7816_STATUS_EXC_ERROR)
381
VCARD_RESPONSE_NEW_STATIC_STATUS(VCARD7816_STATUS_EXC_ERROR_CHANGE)
382
VCARD_RESPONSE_NEW_STATIC_STATUS(VCARD7816_STATUS_EXC_ERROR_MEMORY_FAILURE)
383
VCARD_RESPONSE_NEW_STATIC_STATUS(VCARD7816_STATUS_ERROR_WRONG_LENGTH)
384
VCARD_RESPONSE_NEW_STATIC_STATUS(VCARD7816_STATUS_ERROR_CLA_NOT_SUPPORTED)
385
VCARD_RESPONSE_NEW_STATIC_STATUS(VCARD7816_STATUS_ERROR_CHANNEL_NOT_SUPPORTED)
386
VCARD_RESPONSE_NEW_STATIC_STATUS(VCARD7816_STATUS_ERROR_SECURE_NOT_SUPPORTED)
387
VCARD_RESPONSE_NEW_STATIC_STATUS(VCARD7816_STATUS_ERROR_COMMAND_NOT_SUPPORTED)
388
VCARD_RESPONSE_NEW_STATIC_STATUS(
389
                    VCARD7816_STATUS_ERROR_COMMAND_INCOMPATIBLE_WITH_FILE)
390
VCARD_RESPONSE_NEW_STATIC_STATUS(VCARD7816_STATUS_ERROR_SECURITY_NOT_SATISFIED)
391
VCARD_RESPONSE_NEW_STATIC_STATUS(VCARD7816_STATUS_ERROR_AUTHENTICATION_BLOCKED)
392
VCARD_RESPONSE_NEW_STATIC_STATUS(VCARD7816_STATUS_ERROR_DATA_INVALID)
393
VCARD_RESPONSE_NEW_STATIC_STATUS(VCARD7816_STATUS_ERROR_CONDITION_NOT_SATISFIED)
394
VCARD_RESPONSE_NEW_STATIC_STATUS(VCARD7816_STATUS_ERROR_DATA_NO_EF)
395
VCARD_RESPONSE_NEW_STATIC_STATUS(VCARD7816_STATUS_ERROR_SM_OBJECT_MISSING)
396
VCARD_RESPONSE_NEW_STATIC_STATUS(VCARD7816_STATUS_ERROR_SM_OBJECT_INCORRECT)
397
VCARD_RESPONSE_NEW_STATIC_STATUS(VCARD7816_STATUS_ERROR_WRONG_PARAMETERS)
398
VCARD_RESPONSE_NEW_STATIC_STATUS(
399
                            VCARD7816_STATUS_ERROR_WRONG_PARAMETERS_IN_DATA)
400
VCARD_RESPONSE_NEW_STATIC_STATUS(VCARD7816_STATUS_ERROR_FUNCTION_NOT_SUPPORTED)
401
VCARD_RESPONSE_NEW_STATIC_STATUS(VCARD7816_STATUS_ERROR_FILE_NOT_FOUND)
402
VCARD_RESPONSE_NEW_STATIC_STATUS(VCARD7816_STATUS_ERROR_RECORD_NOT_FOUND)
403
VCARD_RESPONSE_NEW_STATIC_STATUS(VCARD7816_STATUS_ERROR_NO_SPACE_FOR_FILE)
404
VCARD_RESPONSE_NEW_STATIC_STATUS(VCARD7816_STATUS_ERROR_LC_TLV_INCONSISTENT)
405
VCARD_RESPONSE_NEW_STATIC_STATUS(VCARD7816_STATUS_ERROR_P1_P2_INCORRECT)
406
VCARD_RESPONSE_NEW_STATIC_STATUS(VCARD7816_STATUS_ERROR_LC_P1_P2_INCONSISTENT)
407
VCARD_RESPONSE_NEW_STATIC_STATUS(VCARD7816_STATUS_ERROR_DATA_NOT_FOUND)
408
VCARD_RESPONSE_NEW_STATIC_STATUS(VCARD7816_STATUS_ERROR_WRONG_PARAMETERS_2)
409
VCARD_RESPONSE_NEW_STATIC_STATUS(VCARD7816_STATUS_ERROR_INS_CODE_INVALID)
410
VCARD_RESPONSE_NEW_STATIC_STATUS(VCARD7816_STATUS_ERROR_CLA_INVALID)
411
VCARD_RESPONSE_NEW_STATIC_STATUS(VCARD7816_STATUS_ERROR_GENERAL)
412

  
413
/*
414
 * return a single response code. This function cannot fail. It will always
415
 * return a response.
416
 */
417
VCardResponse *
418
vcard_make_response(vcard_7816_status_t status)
419
{
420
    VCardResponse *response = NULL;
421

  
422
    switch (status) {
423
    /* known 7816 response codes */
424
    case VCARD7816_STATUS_SUCCESS:
425
        return VCARD_RESPONSE_GET_STATIC(
426
                    VCARD7816_STATUS_SUCCESS);
427
    case VCARD7816_STATUS_WARNING:
428
        return VCARD_RESPONSE_GET_STATIC(
429
                    VCARD7816_STATUS_WARNING);
430
    case VCARD7816_STATUS_WARNING_RET_CORUPT:
431
        return VCARD_RESPONSE_GET_STATIC(
432
                    VCARD7816_STATUS_WARNING_RET_CORUPT);
433
    case VCARD7816_STATUS_WARNING_BUF_END_BEFORE_LE:
434
        return VCARD_RESPONSE_GET_STATIC(
435
                    VCARD7816_STATUS_WARNING_BUF_END_BEFORE_LE);
436
    case VCARD7816_STATUS_WARNING_INVALID_FILE_SELECTED:
437
        return VCARD_RESPONSE_GET_STATIC(
438
                    VCARD7816_STATUS_WARNING_INVALID_FILE_SELECTED);
439
    case VCARD7816_STATUS_WARNING_FCI_FORMAT_INVALID:
440
        return VCARD_RESPONSE_GET_STATIC(
441
                    VCARD7816_STATUS_WARNING_FCI_FORMAT_INVALID);
442
    case VCARD7816_STATUS_WARNING_CHANGE:
443
        return VCARD_RESPONSE_GET_STATIC(
444
                    VCARD7816_STATUS_WARNING_CHANGE);
445
    case VCARD7816_STATUS_WARNING_FILE_FILLED:
446
        return VCARD_RESPONSE_GET_STATIC(
447
                    VCARD7816_STATUS_WARNING_FILE_FILLED);
448
    case VCARD7816_STATUS_EXC_ERROR:
449
        return VCARD_RESPONSE_GET_STATIC(
450
                    VCARD7816_STATUS_EXC_ERROR);
451
    case VCARD7816_STATUS_EXC_ERROR_CHANGE:
452
        return VCARD_RESPONSE_GET_STATIC(
453
                    VCARD7816_STATUS_EXC_ERROR_CHANGE);
454
    case VCARD7816_STATUS_EXC_ERROR_MEMORY_FAILURE:
455
        return VCARD_RESPONSE_GET_STATIC(
456
                    VCARD7816_STATUS_EXC_ERROR_MEMORY_FAILURE);
457
    case VCARD7816_STATUS_ERROR_WRONG_LENGTH:
458
        return VCARD_RESPONSE_GET_STATIC(
459
                    VCARD7816_STATUS_ERROR_WRONG_LENGTH);
460
    case VCARD7816_STATUS_ERROR_CLA_NOT_SUPPORTED:
461
        return VCARD_RESPONSE_GET_STATIC(
462
                    VCARD7816_STATUS_ERROR_CLA_NOT_SUPPORTED);
463
    case VCARD7816_STATUS_ERROR_CHANNEL_NOT_SUPPORTED:
464
        return VCARD_RESPONSE_GET_STATIC(
465
                    VCARD7816_STATUS_ERROR_CHANNEL_NOT_SUPPORTED);
466
    case VCARD7816_STATUS_ERROR_SECURE_NOT_SUPPORTED:
467
        return VCARD_RESPONSE_GET_STATIC(
468
                    VCARD7816_STATUS_ERROR_SECURE_NOT_SUPPORTED);
469
    case VCARD7816_STATUS_ERROR_COMMAND_NOT_SUPPORTED:
470
        return VCARD_RESPONSE_GET_STATIC(
471
                    VCARD7816_STATUS_ERROR_COMMAND_NOT_SUPPORTED);
472
    case VCARD7816_STATUS_ERROR_COMMAND_INCOMPATIBLE_WITH_FILE:
473
        return VCARD_RESPONSE_GET_STATIC(
474
                    VCARD7816_STATUS_ERROR_COMMAND_INCOMPATIBLE_WITH_FILE);
475
    case VCARD7816_STATUS_ERROR_SECURITY_NOT_SATISFIED:
476
        return VCARD_RESPONSE_GET_STATIC(
477
                    VCARD7816_STATUS_ERROR_SECURITY_NOT_SATISFIED);
478
    case VCARD7816_STATUS_ERROR_AUTHENTICATION_BLOCKED:
479
        return VCARD_RESPONSE_GET_STATIC(
480
                    VCARD7816_STATUS_ERROR_AUTHENTICATION_BLOCKED);
481
    case VCARD7816_STATUS_ERROR_DATA_INVALID:
482
        return VCARD_RESPONSE_GET_STATIC(
483
                    VCARD7816_STATUS_ERROR_DATA_INVALID);
484
    case VCARD7816_STATUS_ERROR_CONDITION_NOT_SATISFIED:
485
        return VCARD_RESPONSE_GET_STATIC(
486
                    VCARD7816_STATUS_ERROR_CONDITION_NOT_SATISFIED);
487
    case VCARD7816_STATUS_ERROR_DATA_NO_EF:
488
        return VCARD_RESPONSE_GET_STATIC(
489
                    VCARD7816_STATUS_ERROR_DATA_NO_EF);
490
    case VCARD7816_STATUS_ERROR_SM_OBJECT_MISSING:
491
        return VCARD_RESPONSE_GET_STATIC(
492
                    VCARD7816_STATUS_ERROR_SM_OBJECT_MISSING);
493
    case VCARD7816_STATUS_ERROR_SM_OBJECT_INCORRECT:
494
        return VCARD_RESPONSE_GET_STATIC(
495
                    VCARD7816_STATUS_ERROR_SM_OBJECT_INCORRECT);
496
    case VCARD7816_STATUS_ERROR_WRONG_PARAMETERS:
497
        return VCARD_RESPONSE_GET_STATIC(
498
                    VCARD7816_STATUS_ERROR_WRONG_PARAMETERS);
499
    case VCARD7816_STATUS_ERROR_WRONG_PARAMETERS_IN_DATA:
500
        return VCARD_RESPONSE_GET_STATIC(
501
                    VCARD7816_STATUS_ERROR_WRONG_PARAMETERS_IN_DATA);
502
    case VCARD7816_STATUS_ERROR_FUNCTION_NOT_SUPPORTED:
503
        return VCARD_RESPONSE_GET_STATIC(
504
                    VCARD7816_STATUS_ERROR_FUNCTION_NOT_SUPPORTED);
505
    case VCARD7816_STATUS_ERROR_FILE_NOT_FOUND:
506
        return VCARD_RESPONSE_GET_STATIC(
507
                    VCARD7816_STATUS_ERROR_FILE_NOT_FOUND);
508
    case VCARD7816_STATUS_ERROR_RECORD_NOT_FOUND:
509
        return VCARD_RESPONSE_GET_STATIC(
510
                    VCARD7816_STATUS_ERROR_RECORD_NOT_FOUND);
511
    case VCARD7816_STATUS_ERROR_NO_SPACE_FOR_FILE:
512
        return VCARD_RESPONSE_GET_STATIC(
513
                    VCARD7816_STATUS_ERROR_NO_SPACE_FOR_FILE);
514
    case VCARD7816_STATUS_ERROR_LC_TLV_INCONSISTENT:
515
        return VCARD_RESPONSE_GET_STATIC(
516
                    VCARD7816_STATUS_ERROR_LC_TLV_INCONSISTENT);
517
    case VCARD7816_STATUS_ERROR_P1_P2_INCORRECT:
518
        return VCARD_RESPONSE_GET_STATIC(
519
                    VCARD7816_STATUS_ERROR_P1_P2_INCORRECT);
520
    case VCARD7816_STATUS_ERROR_LC_P1_P2_INCONSISTENT:
521
        return VCARD_RESPONSE_GET_STATIC(
522
                    VCARD7816_STATUS_ERROR_LC_P1_P2_INCONSISTENT);
523
    case VCARD7816_STATUS_ERROR_DATA_NOT_FOUND:
524
        return VCARD_RESPONSE_GET_STATIC(
525
                    VCARD7816_STATUS_ERROR_DATA_NOT_FOUND);
526
    case VCARD7816_STATUS_ERROR_WRONG_PARAMETERS_2:
527
        return VCARD_RESPONSE_GET_STATIC(
528
                    VCARD7816_STATUS_ERROR_WRONG_PARAMETERS_2);
529
    case VCARD7816_STATUS_ERROR_INS_CODE_INVALID:
530
        return VCARD_RESPONSE_GET_STATIC(
531
                    VCARD7816_STATUS_ERROR_INS_CODE_INVALID);
532
    case VCARD7816_STATUS_ERROR_CLA_INVALID:
533
        return VCARD_RESPONSE_GET_STATIC(
534
                    VCARD7816_STATUS_ERROR_CLA_INVALID);
535
    case VCARD7816_STATUS_ERROR_GENERAL:
536
        return VCARD_RESPONSE_GET_STATIC(
537
                    VCARD7816_STATUS_ERROR_GENERAL);
538
    default:
539
        /* we don't know this status code, create a response buffer to
540
         * hold it */
541
        response = vcard_response_new_status(status);
542
        if (response == NULL) {
543
            /* couldn't allocate the buffer, return memmory error */
544
            return VCARD_RESPONSE_GET_STATIC(
545
                        VCARD7816_STATUS_EXC_ERROR_MEMORY_FAILURE);
546
        }
547
    }
548
    assert(response);
549
    return response;
550
}
551

  
552
/*
553
 * Add File card support here if you need it.
554
 */
555
static VCardStatus
556
vcard7816_file_system_process_apdu(VCard *card, VCardAPDU *apdu,
557
                                   VCardResponse **response)
558
{
559
    /* TODO: if we want to support a virtual file system card, we do it here.
560
     * It would probably be a pkcs #15 card type */
561
    *response = vcard_make_response(
562
                    VCARD7816_STATUS_ERROR_COMMAND_NOT_SUPPORTED);
563
    return VCARD_DONE;
564
}
565

  
566
/*
567
 * VM card (including java cards)
568
 */
569
static VCardStatus
570
vcard7816_vm_process_apdu(VCard *card, VCardAPDU *apdu,
571
                          VCardResponse **response)
572
{
573
    int bytes_to_copy, next_byte_count, count;
574
    VCardApplet *current_applet;
575
    VCardBufferResponse *buffer_response;
576
    vcard_7816_status_t status;
577

  
578
    /* parse the class first */
579
    if (apdu->a_gen_type !=  VCARD_7816_ISO) {
580
        *response = vcard_make_response(
581
                        VCARD7816_STATUS_ERROR_COMMAND_NOT_SUPPORTED);
582
        return VCARD_DONE;
583
    }
584

  
585
    /* use a switch so that if we need to support secure channel stuff later,
586
     * we know where to put it */
587
    switch (apdu->a_secure_messaging) {
588
    case 0x0: /* no SM */
589
        break;
590
    case 0x4: /* proprietary SM */
591
    case 0x8: /* header not authenticated */
592
    case 0xc: /* header authenticated */
593
    default:
594
        /* for now, don't try to support secure channel stuff in the
595
         * virtual card. */
596
        *response = vcard_make_response(
597
                        VCARD7816_STATUS_ERROR_SECURE_NOT_SUPPORTED);
598
        return VCARD_DONE;
599
    }
600

  
601
    /* now parse the instruction */
602
    switch (apdu->a_ins) {
603
    case  VCARD7816_INS_MANAGE_CHANNEL: /* secure channel op */
604
    case  VCARD7816_INS_EXTERNAL_AUTHENTICATE: /* secure channel op */
605
    case  VCARD7816_INS_GET_CHALLENGE: /* secure channel op */
606
    case  VCARD7816_INS_INTERNAL_AUTHENTICATE: /* secure channel op */
607
    case  VCARD7816_INS_ERASE_BINARY: /* applet control op */
608
    case  VCARD7816_INS_READ_BINARY: /* applet control op */
609
    case  VCARD7816_INS_WRITE_BINARY: /* applet control op */
610
    case  VCARD7816_INS_UPDATE_BINARY: /* applet control op */
611
    case  VCARD7816_INS_READ_RECORD: /* file op */
612
    case  VCARD7816_INS_WRITE_RECORD: /* file op */
613
    case  VCARD7816_INS_UPDATE_RECORD: /* file op */
614
    case  VCARD7816_INS_APPEND_RECORD: /* file op */
615
    case  VCARD7816_INS_ENVELOPE:
616
    case  VCARD7816_INS_PUT_DATA:
617
        *response = vcard_make_response(
618
                            VCARD7816_STATUS_ERROR_COMMAND_NOT_SUPPORTED);
619
        break;
620

  
621
    case  VCARD7816_INS_SELECT_FILE:
622
        if (apdu->a_p1 != 0x04) {
623
            *response = vcard_make_response(
624
                            VCARD7816_STATUS_ERROR_FUNCTION_NOT_SUPPORTED);
625
            break;
626
        }
627

  
628
        /* side effect, deselect the current applet if no applet has been found
629
         * */
630
        current_applet = vcard_find_applet(card, apdu->a_body, apdu->a_Lc);
631
        vcard_select_applet(card, apdu->a_channel, current_applet);
632
        if (current_applet) {
633
            unsigned char *aid;
634
            int aid_len;
635
            aid = vcard_applet_get_aid(current_applet, &aid_len);
636
            *response = vcard_response_new(card, aid, aid_len, apdu->a_Le,
637
                                          VCARD7816_STATUS_SUCCESS);
638
        } else {
639
            *response = vcard_make_response(
640
                             VCARD7816_STATUS_ERROR_FILE_NOT_FOUND);
641
        }
642
        break;
643

  
644
    case  VCARD7816_INS_VERIFY:
645
        if ((apdu->a_p1 != 0x00) || (apdu->a_p2 != 0x00)) {
646
            *response = vcard_make_response(
647
                            VCARD7816_STATUS_ERROR_WRONG_PARAMETERS);
648
        } else {
649
            if (apdu->a_Lc == 0) {
650
                /* handle pin count if possible */
651
                count = vcard_emul_get_login_count(card);
652
                if (count < 0) {
653
                    *response = vcard_make_response(
654
                                    VCARD7816_STATUS_ERROR_DATA_NOT_FOUND);
655
                } else {
656
                    if (count > 0xf) {
657
                        count = 0xf;
658
                    }
659
                    *response = vcard_response_new_status_bytes(
660
                                                VCARD7816_SW1_WARNING_CHANGE,
661
                                                                0xc0 | count);
662
                    if (*response == NULL) {
663
                        *response = vcard_make_response(
664
                                    VCARD7816_STATUS_EXC_ERROR_MEMORY_FAILURE);
665
                    }
666
                }
667
            } else {
668
                    status = vcard_emul_login(card, apdu->a_body, apdu->a_Lc);
669
                *response = vcard_make_response(status);
670
            }
671
        }
672
        break;
673

  
674
    case VCARD7816_INS_GET_RESPONSE:
675
        buffer_response = vcard_get_buffer_response(card);
676
        if (!buffer_response) {
677
            *response = vcard_make_response(
678
                            VCARD7816_STATUS_ERROR_DATA_NOT_FOUND);
679
            /* handle error */
680
            break;
681
        }
682
        bytes_to_copy = MIN(buffer_response->len, apdu->a_Le);
683
        next_byte_count = MIN(256, buffer_response->len - bytes_to_copy);
684
        *response = vcard_response_new_bytes(
685
                        card, buffer_response->current, bytes_to_copy,
686
                        apdu->a_Le,
687
                        next_byte_count ?
688
                        VCARD7816_SW1_RESPONSE_BYTES : VCARD7816_SW1_SUCCESS,
689
                        next_byte_count);
690
        buffer_response->current += bytes_to_copy;
691
        buffer_response->len -= bytes_to_copy;
692
        if (*response == NULL || (next_byte_count == 0)) {
693
            vcard_set_buffer_response(card, NULL);
694
            vcard_buffer_response_delete(buffer_response);
695
        }
696
        if (*response == NULL) {
697
            *response =
698
                vcard_make_response(VCARD7816_STATUS_EXC_ERROR_MEMORY_FAILURE);
699
        }
700
        break;
701

  
702
    case VCARD7816_INS_GET_DATA:
703
        *response =
704
            vcard_make_response(VCARD7816_STATUS_ERROR_COMMAND_NOT_SUPPORTED);
705
        break;
706

  
707
    default:
708
        *response =
709
            vcard_make_response(VCARD7816_STATUS_ERROR_COMMAND_NOT_SUPPORTED);
710
        break;
711
    }
712

  
713
    /* response should have been set somewhere */
714
    assert(*response != NULL);
715
    return VCARD_DONE;
716
}
717

  
718

  
719
/*
720
 * APDU processing starts here. This routes the card processing stuff to the
721
 * right location.
722
 */
723
VCardStatus
724
vcard_process_apdu(VCard *card, VCardAPDU *apdu, VCardResponse **response)
725
{
726
    VCardStatus status;
727
    VCardBufferResponse *buffer_response;
728

  
729
    /* first handle any PTS commands, which aren't really APDU's */
730
    if (apdu->a_type == VCARD_7816_PTS) {
731
        /* the PTS responses aren't really responses either */
732
        *response = vcard_response_new_data(apdu->a_data, apdu->a_len);
733
        /* PTS responses have no status bytes */
734
        (*response)->b_total_len = (*response)->b_len;
735
        return VCARD_DONE;
736
    }
737
    buffer_response = vcard_get_buffer_response(card);
738
    if (buffer_response && apdu->a_ins != VCARD7816_INS_GET_RESPONSE) {
739
        /* clear out buffer_response, return an error */
740
        vcard_set_buffer_response(card, NULL);
741
        vcard_buffer_response_delete(buffer_response);
742
        *response = vcard_make_response(VCARD7816_STATUS_EXC_ERROR);
743
        return VCARD_DONE;
744
    }
745

  
746
    status = vcard_process_applet_apdu(card, apdu, response);
747
    if (status != VCARD_NEXT) {
748
        return status;
749
    }
750
    switch (vcard_get_type(card)) {
751
    case VCARD_FILE_SYSTEM:
752
        return vcard7816_file_system_process_apdu(card, apdu, response);
753
    case VCARD_VM:
754
        return vcard7816_vm_process_apdu(card, apdu, response);
755
    case VCARD_DIRECT:
756
        /* if we are type direct, then the applet should handle everything */
757
        assert("VCARD_DIRECT: applet failure");
758
        break;
759
    }
760
    *response =
761
        vcard_make_response(VCARD7816_STATUS_ERROR_COMMAND_NOT_SUPPORTED);
762
    return VCARD_DONE;
763
}
b/libcacard/card_7816.h
1
/*
2
 * Implement the 7816 portion of the card spec
3
 *
4
 * This work is licensed under the terms of the GNU LGPL, version 2.1 or later.
5
 * See the COPYING.LIB file in the top-level directory.
6
 */
7
#ifndef CARD_7816_H
8
#define CARD_7816_H  1
9

  
10
#include "card_7816t.h"
11
#include "vcardt.h"
12

  
... This diff was truncated because it exceeds the maximum size that can be displayed.

Also available in: Unified diff