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

Revision 3502, 21.9 KB (checked in by ludovic.rousseau, 7 months ago)

convert C++ in C comment

Line 
1/*
2 * card-muscle.c: Support for MuscleCard Applet from musclecard.com
3 *
4 * Copyright (C) 2006, Identity Alliance, Thomas Harning <support@identityalliance.com>
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 "muscle.h"
24#include "muscle-filesystem.h"
25#include <opensc/types.h>
26#include <opensc.h>
27
28#include <stdlib.h>
29#include <string.h>
30
31static struct sc_card_operations muscle_ops;
32static struct sc_card_driver muscle_drv = {
33        "Muscle Card Driver",
34        "muscle",
35        &muscle_ops,
36        NULL, 0, NULL
37};
38
39#define MUSCLE_DATA(card) ( (muscle_private_t*)card->drv_data )
40#define MUSCLE_FS(card) ( ((muscle_private_t*)card->drv_data)->fs )
41typedef struct muscle_private {
42        sc_security_env_t env;
43        unsigned short verifiedPins;
44        mscfs_t *fs;
45        int rsa_key_ref;
46       
47} muscle_private_t;
48
49static int muscle_finish(sc_card_t *card)
50{
51        muscle_private_t *priv = MUSCLE_DATA(card);
52        mscfs_free(priv->fs);
53        free(priv);
54        return 0;
55}
56
57
58static u8 muscleAppletId[] = { 0xA0, 0x00,0x00,0x00, 0x01, 0x01 };
59
60static int muscle_match_card(sc_card_t *card)
61{
62        /* Use SELECT APPLET, since its a more deterministic way of detection */
63        int i;
64        /* Since we send an APDU, the card's logout function may be called...
65         * however it's not always properly nulled out... */
66        card->ops->logout = NULL;
67
68        sc_ctx_suppress_errors_on(card->ctx);
69        i = msc_select_applet(card, muscleAppletId, 5);
70        sc_ctx_suppress_errors_off(card->ctx);
71        /* Mark the card for muscle_init */
72        card->drv_data = (void*)0xFFFFFFFF;
73        return i;
74}
75
76/* Since Musclecard has a different ACL system then PKCS15
77 * objects need to have their READ/UPDATE/DELETE permissions mapped for files
78 * and directory ACLS need to be set
79 * For keys.. they have different ACLS, but are accessed in different locations, so it shouldn't be an issue here
80 */
81static unsigned short muscle_parse_singleAcl(const sc_acl_entry_t* acl)
82{
83        unsigned short acl_entry = 0;
84        while(acl) {
85                int key = acl->key_ref;
86                int method = acl->method;
87                switch(method) {
88                case SC_AC_NEVER:
89                        return 0xFFFF;
90                /* Ignore... other items overwrite these */
91                case SC_AC_NONE:
92                case SC_AC_UNKNOWN:
93                        break;
94                case SC_AC_CHV:
95                        acl_entry |= (1 << key); /* Assuming key 0 == SO */
96                        break;
97                case SC_AC_AUT:
98                case SC_AC_TERM:
99                case SC_AC_PRO:
100                default:
101                        /* Ignored */
102                        break;
103                }
104                acl = acl->next;
105        }
106        return acl_entry;
107}
108
109static void muscle_parse_acls(const sc_file_t* file, unsigned short* read_perm, unsigned short* write_perm, unsigned short* delete_perm)
110{
111        assert(read_perm && write_perm && delete_perm);
112        *read_perm =  muscle_parse_singleAcl(sc_file_get_acl_entry(file, SC_AC_OP_READ));
113        *write_perm =  muscle_parse_singleAcl(sc_file_get_acl_entry(file, SC_AC_OP_UPDATE));
114        *delete_perm =  muscle_parse_singleAcl(sc_file_get_acl_entry(file, SC_AC_OP_DELETE));
115}
116
117static int muscle_create_directory(sc_card_t *card, sc_file_t *file)
118{
119        mscfs_t *fs = MUSCLE_FS(card);
120        msc_id objectId;
121        u8* oid = objectId.id;
122        unsigned id = file->id;
123        unsigned short read_perm = 0, write_perm = 0, delete_perm = 0;
124        int objectSize;
125        int r;
126        if(id == 0) /* No null name files */
127                return SC_ERROR_INVALID_ARGUMENTS;
128       
129        /* No nesting directories */
130        if(fs->currentPath[0] != 0x3F || fs->currentPath[1] != 0x00)
131                return SC_ERROR_NOT_SUPPORTED;
132        oid[0] = ((id & 0xFF00) >> 8) & 0xFF;
133        oid[1] = id & 0xFF;
134        oid[2] = oid[3] = 0;
135       
136        objectSize = file->size;
137       
138        muscle_parse_acls(file, &read_perm, &write_perm, &delete_perm);
139        r = msc_create_object(card, objectId, objectSize, read_perm, write_perm, delete_perm);
140        mscfs_clear_cache(fs);
141        if(r >= 0) return 0;
142        return r;
143}
144
145
146static int muscle_create_file(sc_card_t *card, sc_file_t *file)
147{
148        mscfs_t *fs = MUSCLE_FS(card);
149        int objectSize = file->size;
150        unsigned short read_perm = 0, write_perm = 0, delete_perm = 0;
151        msc_id objectId;
152        int r;
153        if(file->type == SC_FILE_TYPE_DF)
154                return muscle_create_directory(card, file);
155        if(file->type != SC_FILE_TYPE_WORKING_EF)
156                return SC_ERROR_NOT_SUPPORTED;
157        if(file->id == 0) /* No null name files */
158                return SC_ERROR_INVALID_ARGUMENTS;
159       
160        muscle_parse_acls(file, &read_perm, &write_perm, &delete_perm);
161       
162        mscfs_lookup_local(fs, file->id, &objectId);
163        r = msc_create_object(card, objectId, objectSize, read_perm, write_perm, delete_perm);
164        mscfs_clear_cache(fs);
165        if(r >= 0) return 0;
166        return r;
167}
168
169static int muscle_read_binary(sc_card_t *card, unsigned int idx, u8* buf, size_t count, unsigned long flags)
170{
171        mscfs_t *fs = MUSCLE_FS(card);
172        int r;
173        msc_id objectId;
174        u8* oid = objectId.id;
175        mscfs_file_t *file;
176       
177        r = mscfs_check_selection(fs, -1);
178        if(r < 0) SC_FUNC_RETURN(card->ctx, 0, r);
179        file = &fs->cache.array[fs->currentFileIndex];
180        objectId = file->objectId;
181        /* memcpy(objectId.id, file->objectId.id, 4); */
182        if(!file->ef) {
183                oid[0] = oid[2];
184                oid[1] = oid[3];
185                oid[2] = oid[3] = 0;
186        }
187        r = msc_read_object(card, objectId, idx, buf, count);
188        SC_FUNC_RETURN(card->ctx, 0, r);
189}
190
191static int muscle_update_binary(sc_card_t *card, unsigned int idx, const u8* buf, size_t count, unsigned long flags)
192{
193        mscfs_t *fs = MUSCLE_FS(card);
194        int r;
195        mscfs_file_t *file;
196        msc_id objectId;
197        u8* oid = objectId.id;
198
199        r = mscfs_check_selection(fs, -1);
200        if(r < 0) SC_FUNC_RETURN(card->ctx, 0, r);
201        file = &fs->cache.array[fs->currentFileIndex];
202       
203        objectId = file->objectId;
204        /* memcpy(objectId.id, file->objectId.id, 4); */
205        if(!file->ef) {
206                oid[0] = oid[2];
207                oid[1] = oid[3];
208                oid[2] = oid[3] = 0;
209        }
210        if(file->size < idx + count) {
211                int newFileSize = idx + count;
212                u8* buffer = malloc(newFileSize);
213                if(buffer == NULL) SC_FUNC_RETURN(card->ctx, 0, SC_ERROR_OUT_OF_MEMORY);
214               
215                r = msc_read_object(card, objectId, 0, buffer, file->size);
216                /* TODO: RETREIVE ACLS */
217                if(r < 0) goto update_bin_free_buffer;
218                r = msc_delete_object(card, objectId, 0);
219                if(r < 0) goto update_bin_free_buffer;
220                r = msc_create_object(card, objectId, newFileSize, 0,0,0);
221                if(r < 0) goto update_bin_free_buffer;
222                memcpy(buffer + idx, buf, count);
223                r = msc_update_object(card, objectId, 0, buffer, newFileSize);
224                if(r < 0) goto update_bin_free_buffer;
225                file->size = newFileSize;
226update_bin_free_buffer:
227                free(buffer);
228                SC_FUNC_RETURN(card->ctx, 0, r);
229        } else {
230                r = msc_update_object(card, objectId, idx, buf, count);
231        }
232        /* mscfs_clear_cache(fs); */
233        return r;
234}
235
236/* TODO: Evaluate correctness */
237static int muscle_delete_mscfs_file(sc_card_t *card, mscfs_file_t *file_data)
238{
239        mscfs_t *fs = MUSCLE_FS(card);
240        msc_id id = file_data->objectId;
241        u8* oid = id.id;
242        int r;
243
244        if(!file_data->ef) {
245                int x;
246                mscfs_file_t *childFile;
247                /* Delete children */
248                mscfs_check_cache(fs);
249               
250                if (card->ctx->debug >= 2) {
251                        sc_debug(card->ctx, "DELETING Children of: %02X%02X%02X%02X\n",
252                                        oid[0],oid[1],oid[2],oid[3]);
253                }
254                for(x = 0; x < fs->cache.size; x++) {
255                        msc_id objectId;
256                        childFile = &fs->cache.array[x];
257                        objectId = childFile->objectId;
258                       
259                        if(0 == memcmp(oid + 2, objectId.id, 2)) {
260                                if (card->ctx->debug >= 2) {
261                                        sc_debug(card->ctx, "DELETING: %02X%02X%02X%02X\n",
262                                                objectId.id[0],objectId.id[1],objectId.id[2],objectId.id[3]);
263                                }
264                                r = muscle_delete_mscfs_file(card, childFile);
265                                if(r < 0) SC_FUNC_RETURN(card->ctx, 2,r);
266                        }
267                }
268                oid[0] = oid[2];
269                oid[1] = oid[3];
270                oid[2] = oid[3] = 0;
271                /* ??? objectId = objectId >> 16; */
272        }
273        if((0 == memcmp(oid, "\x3F\x00\x00\x00", 4))
274                || (0 == memcmp(oid, "\x3F\x00\x3F\x00", 4))) {
275                sc_ctx_suppress_errors_on(card->ctx);
276        }
277        r = msc_delete_object(card, id, 1);
278        /* Check if its the root... this file generally is virtual
279         * So don't return an error if it fails */
280        if((0 == memcmp(oid, "\x3F\x00\x00\x00", 4))
281                || (0 == memcmp(oid, "\x3F\x00\x3F\x00", 4)))
282                sc_ctx_suppress_errors_off(card->ctx);
283                return 0;
284
285        if(r < 0) {
286                printf("ID: %02X%02X%02X%02X\n",
287                                        oid[0],oid[1],oid[2],oid[3]);
288                SC_FUNC_RETURN(card->ctx, 2,r);
289        }
290        return 0;
291}
292
293static int muscle_delete_file(sc_card_t *card, const sc_path_t *path_in)
294{
295        mscfs_t *fs = MUSCLE_FS(card);
296        mscfs_file_t *file_data = NULL;
297        int r = 0;
298
299        r = mscfs_loadFileInfo(fs, path_in->value, path_in->len, &file_data, NULL);
300        if(r < 0) SC_FUNC_RETURN(card->ctx, 2,r);
301        r = muscle_delete_mscfs_file(card, file_data);
302        mscfs_clear_cache(fs);
303        if(r < 0) SC_FUNC_RETURN(card->ctx, 2,r);
304        return 0;
305}
306
307static void muscle_load_single_acl(sc_file_t* file, int operation, unsigned short acl)
308{
309        int key;
310        /* Everybody by default.... */
311        sc_file_add_acl_entry(file, operation, SC_AC_NONE, 0);
312        if(acl == 0xFFFF) {
313                sc_file_add_acl_entry(file, operation, SC_AC_NEVER, 0);
314                return;
315        }
316        for(key = 0; key < 16; key++) {
317                if(acl >> key & 1) {
318                        sc_file_add_acl_entry(file, operation, SC_AC_CHV, key);
319                }
320        }
321}
322static void muscle_load_file_acls(sc_file_t* file, mscfs_file_t *file_data)
323{
324        muscle_load_single_acl(file, SC_AC_OP_READ, file_data->read);
325        muscle_load_single_acl(file, SC_AC_OP_WRITE, file_data->write);
326        muscle_load_single_acl(file, SC_AC_OP_UPDATE, file_data->write);
327        muscle_load_single_acl(file, SC_AC_OP_DELETE, file_data->delete);
328}
329static void muscle_load_dir_acls(sc_file_t* file, mscfs_file_t *file_data)
330{
331        muscle_load_single_acl(file, SC_AC_OP_SELECT, 0);
332        muscle_load_single_acl(file, SC_AC_OP_LIST_FILES, 0);
333        muscle_load_single_acl(file, SC_AC_OP_LOCK, 0xFFFF);
334        muscle_load_single_acl(file, SC_AC_OP_DELETE, file_data->delete);
335        muscle_load_single_acl(file, SC_AC_OP_CREATE, file_data->write);
336}
337
338/* Required type = -1 for don't care, 1 for EF, 0 for DF */
339static int select_item(sc_card_t *card, const sc_path_t *path_in, sc_file_t ** file_out, int requiredType)
340{
341        mscfs_t *fs = MUSCLE_FS(card);
342        mscfs_file_t *file_data = NULL;
343        const u8 *path = path_in->value;
344        int pathlen = path_in->len;
345        int r = 0;
346        int objectIndex;
347        u8* oid;
348       
349        mscfs_check_cache(fs);
350        r = mscfs_loadFileInfo(fs, path_in->value, path_in->len, &file_data, &objectIndex);
351        if(r < 0) SC_FUNC_RETURN(card->ctx, 2,r);
352       
353        /* Check if its the right type */
354        if(requiredType >= 0 && requiredType != file_data->ef) {
355                SC_FUNC_RETURN(card->ctx, 0, SC_ERROR_INVALID_ARGUMENTS);
356        }
357        oid = file_data->objectId.id;
358        /* Is it a file or directory */
359        if(file_data->ef) {
360                fs->currentPath[0] = oid[0];
361                fs->currentPath[1] = oid[1];
362                fs->currentFile[0] = oid[2];
363                fs->currentFile[1] = oid[3];
364        } else {
365                fs->currentPath[0] = oid[pathlen - 2];
366                fs->currentPath[1] = oid[pathlen - 1];
367                fs->currentFile[0] = 0;
368                fs->currentFile[1] = 0;
369        }
370       
371        fs->currentFileIndex = objectIndex;
372        if(file_out) {
373                sc_file_t *file;
374                file = sc_file_new();
375                file->path = *path_in;
376                file->size = file_data->size;
377                file->id = (oid[2] << 8) | oid[3];
378                memcpy(file->name, path, pathlen);
379                file->namelen = pathlen;
380                if(!file_data->ef) {
381                        file->type = SC_FILE_TYPE_DF;
382                } else {
383                        file->type = SC_FILE_TYPE_WORKING_EF;
384                        file->ef_structure = SC_FILE_EF_TRANSPARENT;
385                }
386               
387                /* Setup ACLS */
388                if(file_data->ef) {
389                        muscle_load_file_acls(file, file_data);
390                } else {
391                        muscle_load_dir_acls(file, file_data);
392                        /* Setup directory acls... */
393                }
394               
395                file->magic = SC_FILE_MAGIC;
396                *file_out = file;
397        }
398        return 0;
399}
400
401static int muscle_select_file(sc_card_t *card, const sc_path_t *path_in,
402                             sc_file_t **file_out)
403{
404        int r;
405       
406        assert(card != NULL && path_in != NULL);
407       
408        switch (path_in->type) {
409        case SC_PATH_TYPE_FILE_ID:
410                r = select_item(card, path_in, file_out, 1);
411                break;
412        case SC_PATH_TYPE_DF_NAME:
413                r = select_item(card, path_in, file_out, 0);
414                break;
415        case SC_PATH_TYPE_PATH:
416                r = select_item(card, path_in, file_out, -1);
417                break;
418        default:
419                SC_FUNC_RETURN(card->ctx, 2, SC_ERROR_INVALID_ARGUMENTS);
420        }
421        if(r > 0) r = 0;
422        SC_FUNC_RETURN(card->ctx, 2,r);
423}
424
425static int _listFile(mscfs_file_t *file, int reset, void *udata)
426{
427        int next = reset ? 0x00 : 0x01;
428        return msc_list_objects( (sc_card_t*)udata, next, file);
429}
430
431static int muscle_init(sc_card_t *card)
432{
433        int r = 0;
434        muscle_private_t *priv;
435       
436        /* drv_data is set to (void*)0xFFFFFFFF in muscle_detect,
437         * If drv_data doesn't equal that, then we need to detect... */
438        if(card->drv_data != (void*)0xFFFFFFFF) {
439                card->drv_data = NULL;
440                if(!muscle_match_card(card))
441                        return SC_ERROR_INVALID_CARD;
442        }
443
444        r = sc_get_default_driver()->ops->init(card);
445        if(r) return r;
446
447        card->name = "Muscle Card";
448        card->drv_data = malloc(sizeof(muscle_private_t));
449        if(!card->drv_data) {
450                SC_FUNC_RETURN(card->ctx, 0, SC_ERROR_OUT_OF_MEMORY);
451        }
452        memset(card->drv_data, 0, sizeof(muscle_private_t));
453        priv = MUSCLE_DATA(card);
454        priv->verifiedPins = 0;
455        priv->fs = mscfs_new();
456        if(!priv->fs) {
457                free(card->drv_data);
458                SC_FUNC_RETURN(card->ctx, 0, SC_ERROR_OUT_OF_MEMORY);
459        }
460        priv->fs->udata = card;
461        priv->fs->listFile = _listFile;
462
463        card->cla = 0xB0;
464       
465        card->flags |= SC_CARD_FLAG_ONBOARD_KEY_GEN;
466        card->flags |= SC_CARD_FLAG_RNG;
467        card->caps |= SC_CARD_CAP_RNG;
468                /* FIXME: Card type detection */
469        if (1) {
470                unsigned long flags;
471               
472                flags = SC_ALGORITHM_RSA_RAW;
473                flags |= SC_ALGORITHM_RSA_HASH_NONE;
474                flags |= SC_ALGORITHM_ONBOARD_KEY_GEN;
475
476                _sc_card_add_rsa_alg(card, 512, flags, 0);
477                _sc_card_add_rsa_alg(card, 768, flags, 0);
478                _sc_card_add_rsa_alg(card, 1024, flags, 0);
479                _sc_card_add_rsa_alg(card, 2048, flags, 0);
480        }
481        card->max_recv_size = 1024 * 64;
482        card->max_send_size = 1024 * 64;
483        return 0;
484}
485
486static int muscle_list_files(sc_card_t *card, u8 *buf, size_t bufLen)
487{
488        muscle_private_t* priv = MUSCLE_DATA(card);
489        mscfs_t *fs = priv->fs;
490        int x;
491        int count = 0;
492
493        mscfs_check_cache(priv->fs);
494       
495        for(x = 0; x < fs->cache.size; x++) {
496                u8* oid= fs->cache.array[x].objectId.id;
497                if (card->ctx->debug >= 2) {
498                        sc_debug(card->ctx, "FILE: %02X%02X%02X%02X\n",
499                                oid[0],oid[1],oid[2],oid[3]);
500                }
501                if(0 == memcmp(fs->currentPath, oid, 2)) {
502                        buf[0] = oid[2];
503                        buf[1] = oid[3];
504                        if(buf[0] == 0x00 && buf[1] == 0x00) continue; /* No directories/null names outside of root */
505                        buf += 2;
506                        count+=2;
507                }
508        }
509        return count;
510}
511
512static int (*iso_pin_cmd)(struct sc_card *, struct sc_pin_cmd_data *,
513                                int *tries_left);
514
515static int muscle_pin_cmd(sc_card_t *card, struct sc_pin_cmd_data *cmd,
516                                int *tries_left)
517{
518        muscle_private_t* priv = MUSCLE_DATA(card);
519        const int bufferLength = MSC_MAX_PIN_COMMAND_LENGTH;
520        u8 buffer[MSC_MAX_PIN_COMMAND_LENGTH];
521        switch(cmd->cmd) {
522        case SC_PIN_CMD_VERIFY:
523                switch(cmd->pin_type) {
524                case SC_AC_CHV: {
525                        sc_apdu_t apdu;
526                        int r;
527                        msc_verify_pin_apdu(card, &apdu, buffer, bufferLength, cmd->pin_reference, cmd->pin1.data, cmd->pin1.len);
528                        cmd->apdu = &apdu;
529                        cmd->pin1.offset = 5;
530                        r = iso_pin_cmd(card, cmd, tries_left);
531                        if(r >= 0)
532                                priv->verifiedPins |= (1 << cmd->pin_reference);
533                        return r;
534                }
535                case SC_AC_TERM:
536                case SC_AC_PRO:
537                case SC_AC_AUT:
538                case SC_AC_NONE:
539                default:
540                        sc_error(card->ctx, "Unsupported authentication method\n");
541                        return SC_ERROR_NOT_SUPPORTED;
542                }
543        case SC_PIN_CMD_CHANGE:
544                switch(cmd->pin_type) {
545                case SC_AC_CHV: {
546                        sc_apdu_t apdu;
547                        msc_change_pin_apdu(card, &apdu, buffer, bufferLength, cmd->pin_reference, cmd->pin1.data, cmd->pin1.len, cmd->pin2.data, cmd->pin2.len);
548                        cmd->apdu = &apdu;
549                        return iso_pin_cmd(card, cmd, tries_left);
550                }
551                case SC_AC_TERM:
552                case SC_AC_PRO:
553                case SC_AC_AUT:
554                case SC_AC_NONE:
555                default:
556                        sc_error(card->ctx, "Unsupported authentication method\n");
557                        return SC_ERROR_NOT_SUPPORTED;
558                }
559        case SC_PIN_CMD_UNBLOCK:
560        switch(cmd->pin_type) {
561                case SC_AC_CHV: {
562                        sc_apdu_t apdu;
563                        msc_unblock_pin_apdu(card, &apdu, buffer, bufferLength, cmd->pin_reference, cmd->pin1.data, cmd->pin1.len);
564                        cmd->apdu = &apdu;
565                        return iso_pin_cmd(card, cmd, tries_left);
566                }
567                case SC_AC_TERM:
568                case SC_AC_PRO:
569                case SC_AC_AUT:
570                case SC_AC_NONE:
571                default:
572                        sc_error(card->ctx, "Unsupported authentication method\n");
573                        return SC_ERROR_NOT_SUPPORTED;
574                }
575        default:
576                sc_error(card->ctx, "Unsupported command\n");
577                return SC_ERROR_NOT_SUPPORTED;
578
579        }
580       
581}
582
583static int muscle_card_extract_key(sc_card_t *card, sc_cardctl_muscle_key_info_t *info)
584{
585        /* CURRENTLY DONT SUPPOT EXTRACTING PRIVATE KEYS... */
586        switch(info->keyType) {
587        case 1: /* RSA */
588                return msc_extract_rsa_public_key(card,
589                        info->keyLocation,
590                        &info->modLength,
591                        &info->modValue,
592                        &info->expLength,
593                        &info->expValue);
594        default:
595                return SC_ERROR_NOT_SUPPORTED;
596        }
597}
598
599static int muscle_card_import_key(sc_card_t *card, sc_cardctl_muscle_key_info_t *info)
600{
601        /* CURRENTLY DONT SUPPOT EXTRACTING PRIVATE KEYS... */
602        switch(info->keyType) {
603        case 0x02: /* RSA_PRIVATE */
604        case 0x03: /* RSA_PRIVATE_CRT */
605                return msc_import_key(card,
606                        info->keyLocation,
607                        info);
608        default:
609                return SC_ERROR_NOT_SUPPORTED;
610        }
611}
612
613static int muscle_card_generate_key(sc_card_t *card, sc_cardctl_muscle_gen_key_info_t *info)
614{
615        return msc_generate_keypair(card,
616                info->privateKeyLocation,
617                info->publicKeyLocation,
618                info->keyType,
619                info->keySize,
620                0);
621}
622
623static int muscle_card_verified_pins(sc_card_t *card, sc_cardctl_muscle_verified_pins_info_t *info)
624{
625        muscle_private_t* priv = MUSCLE_DATA(card);
626        info->verifiedPins = priv->verifiedPins;
627        return 0;
628}
629static int muscle_card_ctl(sc_card_t *card, unsigned long request, void *data)
630{
631        switch(request) {
632        case SC_CARDCTL_MUSCLE_GENERATE_KEY:
633                return muscle_card_generate_key(card, (sc_cardctl_muscle_gen_key_info_t*) data);
634        case SC_CARDCTL_MUSCLE_EXTRACT_KEY:
635                return muscle_card_extract_key(card, (sc_cardctl_muscle_key_info_t*) data);
636        case SC_CARDCTL_MUSCLE_IMPORT_KEY:
637                return muscle_card_import_key(card, (sc_cardctl_muscle_key_info_t*) data);
638        case SC_CARDCTL_MUSCLE_VERIFIED_PINS:
639                return muscle_card_verified_pins(card, (sc_cardctl_muscle_verified_pins_info_t*) data);
640        default:
641                return SC_ERROR_NOT_SUPPORTED; /* Unsupported.. whatever it is */
642        }
643}
644
645static int muscle_set_security_env(sc_card_t *card,
646                                 const sc_security_env_t *env,
647                                 int se_num)   
648{
649        muscle_private_t* priv = MUSCLE_DATA(card);
650
651        if (env->operation != SC_SEC_OPERATION_SIGN &&
652            env->operation != SC_SEC_OPERATION_DECIPHER) {
653                sc_error(card->ctx, "Invalid crypto operation supplied.\n");
654                return SC_ERROR_NOT_SUPPORTED;
655        }
656        if (env->algorithm != SC_ALGORITHM_RSA) {
657                sc_error(card->ctx, "Invalid crypto algorithm supplied.\n");
658                return SC_ERROR_NOT_SUPPORTED;
659        }
660        /* ADJUST FOR PKCS1 padding support for decryption only */
661        if ((env->algorithm_flags & SC_ALGORITHM_RSA_PADS) ||
662            (env->algorithm_flags & SC_ALGORITHM_RSA_HASHES)) {
663                sc_error(card->ctx, "Card supports only raw RSA.\n");
664                return SC_ERROR_NOT_SUPPORTED;
665        }
666        if (env->flags & SC_SEC_ENV_KEY_REF_PRESENT) {
667                if (env->key_ref_len != 1 ||
668                    (env->key_ref[0] > 0x0F)) {
669                        sc_error(card->ctx, "Invalid key reference supplied.\n");
670                        return SC_ERROR_NOT_SUPPORTED;
671                }
672                priv->rsa_key_ref = env->key_ref[0];
673        }
674        if (env->flags & SC_SEC_ENV_ALG_REF_PRESENT) {
675                sc_error(card->ctx, "Algorithm reference not supported.\n");
676                return SC_ERROR_NOT_SUPPORTED;
677        }
678        /* if (env->flags & SC_SEC_ENV_FILE_REF_PRESENT)
679                if (memcmp(env->file_ref.value, "\x00\x12", 2) != 0) {
680                        sc_error(card->ctx, "File reference is not 0012.\n");
681                        return SC_ERROR_NOT_SUPPORTED;
682                } */
683        priv->env = *env;
684        return 0;
685}
686
687static int muscle_restore_security_env(sc_card_t *card, int se_num)
688{
689        muscle_private_t* priv = MUSCLE_DATA(card);
690        memset(&priv->env, 0, sizeof(priv->env));
691        return 0;
692}
693
694
695static int muscle_decipher(sc_card_t * card,
696                         const u8 * crgram, size_t crgram_len, u8 * out,
697                         size_t out_len)
698{
699        muscle_private_t* priv = MUSCLE_DATA(card);
700       
701        u8 key_id;
702        int r;
703
704        /* saniti check */
705        if (priv->env.operation != SC_SEC_OPERATION_DECIPHER)
706                return SC_ERROR_INVALID_ARGUMENTS;
707       
708        key_id = priv->rsa_key_ref * 2; /* Private key */
709
710        if (out_len < crgram_len) {
711                sc_error(card->ctx, "Output buffer too small");
712                return SC_ERROR_BUFFER_TOO_SMALL;
713        }
714       
715        r = msc_compute_crypt(card,
716                key_id,
717                0x00, /* RSA NO PADDING */
718                0x04, /* decrypt */
719                crgram,
720                out,
721                crgram_len,
722                out_len);
723        SC_TEST_RET(card->ctx, r, "Card signature failed");
724        return r;
725}
726
727static int muscle_compute_signature(sc_card_t *card, const u8 *data,
728                size_t data_len, u8 * out, size_t outlen)
729{
730        muscle_private_t* priv = MUSCLE_DATA(card);
731        u8 key_id;
732        int r;
733       
734        key_id = priv->rsa_key_ref * 2; /* Private key */
735       
736        if (outlen < data_len) {
737                sc_error(card->ctx, "Output buffer too small");
738                return SC_ERROR_BUFFER_TOO_SMALL;
739        }
740       
741        r = msc_compute_crypt(card,
742                key_id,
743                0x00, /* RSA NO PADDING */
744                0x04, /* -- decrypt raw... will do what we need since signing isn't yet supported */
745                data,
746                out,
747                data_len,
748                outlen);
749        SC_TEST_RET(card->ctx, r, "Card signature failed");
750        return r;
751}
752
753static int muscle_get_challenge(sc_card_t *card, u8 *rnd, size_t len)
754{
755        return msc_get_challenge(card, len, 0, NULL, rnd);
756}
757
758
759static struct sc_card_driver * sc_get_driver(void)
760{
761        struct sc_card_driver *iso_drv = sc_get_iso7816_driver();
762
763        muscle_ops = *iso_drv->ops;
764        iso_pin_cmd = iso_drv->ops->pin_cmd;
765        muscle_ops.check_sw = iso_drv->ops->check_sw;
766        muscle_ops.pin_cmd = muscle_pin_cmd;
767        muscle_ops.get_response = iso_drv->ops->get_response;
768        muscle_ops.match_card = muscle_match_card;
769        muscle_ops.init = muscle_init;
770        muscle_ops.finish = muscle_finish;
771       
772        muscle_ops.get_challenge = muscle_get_challenge;
773       
774        muscle_ops.set_security_env = muscle_set_security_env;
775        muscle_ops.restore_security_env = muscle_restore_security_env;
776        muscle_ops.compute_signature = muscle_compute_signature;
777        muscle_ops.decipher = muscle_decipher;
778        muscle_ops.card_ctl = muscle_card_ctl;
779        muscle_ops.read_binary = muscle_read_binary;
780        muscle_ops.update_binary = muscle_update_binary;
781        muscle_ops.create_file = muscle_create_file;
782        muscle_ops.select_file = muscle_select_file;
783        muscle_ops.delete_file = muscle_delete_file;
784        muscle_ops.list_files = muscle_list_files;
785
786        return &muscle_drv;
787}
788
789#if 1
790struct sc_card_driver * sc_get_muscle_driver(void)
791{
792        return sc_get_driver();
793}
794#endif
Note: See TracBrowser for help on using the browser.