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

Revision 3444, 15.3 KB (checked in by ludovic.rousseau, 8 months ago)

use "pkcs15.h" instead of <opensc/pkcs15.h> (and similar)

Thanks to Douglas E. Engert for the patch
http://www.opensc-project.org/pipermail/opensc-devel/2008-March/010959.html

Line 
1/*
2 * partial PKCS15 emulation for PIV-II cards
3 * only minimal use of the authentication cert and key
4 *
5 * Copyright (C) 2005,2006,2007 Douglas E. Engert <deengert@anl.gov>
6 *               2004, Nils Larsch <larsch@trustcenter.de>
7 * Copyright (C) 2006, Identity Alliance,
8 *               Thomas Harning <thomas.harning@identityalliance.com>
9 * Copyright (C) 2007, EMC, Russell Larner <rlarner@rsa.com>
10 *
11 * This library is free software; you can redistribute it and/or
12 * modify it under the terms of the GNU Lesser General Public
13 * License as published by the Free Software Foundation; either
14 * version 2.1 of the License, or (at your option) any later version.
15 *
16 * This library is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
19 * Lesser General Public License for more details.
20 *
21 * You should have received a copy of the GNU Lesser General Public
22 * License along with this library; if not, write to the Free Software
23 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
24 */
25
26#include "internal.h"
27#include <stdlib.h>
28#include <string.h>
29#include <stdio.h>
30#include <ctype.h>
31#include "pkcs15.h"
32#include "cardctl.h"
33
34#define MANU_ID         "piv_II "
35
36int sc_pkcs15emu_piv_init_ex(sc_pkcs15_card_t *, sc_pkcs15emu_opt_t *);
37
38
39typedef struct objdata_st {
40        const char *id;
41        const char *label;
42        const char *aoid;
43        const char *auth_id;
44        const char *path;
45        int         obj_flags;
46} objdata;
47
48typedef struct cdata_st {
49        const char *id;
50        const char *label;
51        int         authority;
52        const char *path;
53        int         obj_flags;
54        int         found;
55} cdata;
56
57typedef struct pdata_st {
58        const char *id;
59        const char *label;
60        const char *path;
61        int         ref;
62        int         type;
63        unsigned int maxlen;
64        unsigned int minlen;
65        unsigned int storedlen;
66        int         flags;     
67        int         tries_left;
68        const char  pad_char;
69        int         obj_flags;
70} pindata;
71
72typedef struct pubdata_st {
73        const char *id;
74        const char *label;
75        unsigned int modulus_len;
76        int         usage;
77        const char *path;
78        int         ref;
79        const char *auth_id;
80        int         obj_flags;
81        int         found;
82} pubdata;
83
84typedef struct prdata_st {
85        const char *id;
86        const char *label;
87        unsigned int modulus_len;
88        int         usage;
89        const char *path;
90        int         ref;
91        const char *auth_id;
92        int         obj_flags;
93} prdata;
94
95
96static int piv_detect_card(sc_pkcs15_card_t *p15card)
97{
98        sc_card_t *card = p15card->card;
99
100        SC_FUNC_CALLED(card->ctx, 1);
101        if (card->type < SC_CARD_TYPE_PIV_II_GENERIC
102                || card->type >= SC_CARD_TYPE_PIV_II_GENERIC+1000)
103                return SC_ERROR_INVALID_CARD;
104        return SC_SUCCESS;
105}
106
107static int sc_pkcs15emu_piv_init(sc_pkcs15_card_t *p15card)
108{
109
110        /* The cert objects will return all the data */
111const objdata objects[] = {
112        {"1", "Card Capability Container",
113                        "2.16.840.1.101.3.7.1.219.0", NULL, "DB00", 0},
114        {"2", "Card Holder Unique Identifier",
115                        "2.16.840.1.101.3.7.2.48.0", NULL, "3000", 0},
116        {"3", "Unsigned Card Holder Unique Identifier",
117                        "2.16.840.1.101.3.7.2.48.2", NULL, "3002", 0},
118        {"4", "X.509 Certificate for PIV Authentication",
119                        "2.16.840.1.101.3.7.2.1.1", NULL, "0101", 0},
120        {"5", "Card Holder Fingerprints",
121                        "2.16.840.1.101.3.7.2.96.16", "1", "6010", SC_PKCS15_CO_FLAG_PRIVATE},
122        {"6", "Printed Information",
123                        "2.16.840.1.101.3.7.2.48.1", "1", "3001", SC_PKCS15_CO_FLAG_PRIVATE},
124        {"7", "Card Holder Facial Image",
125                        "2.16.840.1.101.3.7.2.96.48", "1", "6030", SC_PKCS15_CO_FLAG_PRIVATE},
126        {"8", "X.509 Certificate for Digital Signature",
127                        "2.16.840.1.101.3.7.2.1.0",  NULL, "0100", 0},
128        {"9", "X.509 Certificate for Key Management",
129                        "2.16.840.1.101.3.7.2.1.2", NULL, "0102", 0},
130        {"10","X.509 Certificate for Card Authentication",
131                        "2.16.840.1.101.3.7.2.5.0", NULL, "0500", 0},
132        {"11", "Security Object",
133                        "2.16.840.1.101.3.7.2.144.0", NULL, "9000", 0},
134        {NULL, NULL, NULL, NULL, NULL, 0}
135};
136        /*
137         * NIST 800-73-1 is proposing to lift the restriction on
138         * requering pin protected certs. Thus the default will be to
139         * not require this. But there are a number of test cards
140         * that do enforce it. Code later on will allow SC_PKCS15_CO_FLAG_PRIVATE
141         * to be set.
142         */
143        /* certs will be pulled out from the cert objects */
144        cdata certs[] = {
145                {"1", "Certificate for PIV Authentication", 0, "0101cece", 0, 0},
146
147                {"2", "Certificate for Digital Signature", 0, "0100cece", 0, 0},
148                {"3", "Certificate for Key Management", 0, "0102cece", 0, 0},
149                {"4", "Certificate for Card Authentication", 0, "0500cece", 0, 0},
150                {NULL, NULL, 0, NULL, 0, 0}
151        };
152
153        const pindata pins[] = {
154                { "1", "PIV Card Holder pin", "", 0x80,
155                  SC_PKCS15_PIN_TYPE_ASCII_NUMERIC,
156                  8, 4, 8,
157                  SC_PKCS15_PIN_FLAG_NEEDS_PADDING |
158                  SC_PKCS15_PIN_FLAG_LOCAL,
159                  -1, 0xFF,
160                  SC_PKCS15_CO_FLAG_PRIVATE },
161                { "2", "PIV PUK", "", 0x81,
162                  SC_PKCS15_PIN_TYPE_ASCII_NUMERIC,
163                  8, 4, 8,
164                  SC_PKCS15_PIN_FLAG_NEEDS_PADDING |
165                  SC_PKCS15_PIN_FLAG_LOCAL | SC_PKCS15_PIN_FLAG_SO_PIN |
166                  SC_PKCS15_PIN_FLAG_UNBLOCKING_PIN,
167                  -1, 0xFF,
168                  SC_PKCS15_CO_FLAG_PRIVATE },
169                /* there are some more key, but dont need for now */
170                /* The admin 9b might fall in here */
171                { NULL, NULL, NULL, 0, 0, 0, 0, 0, 0, 0, 0, 0}
172        };
173
174
175        /*
176         * The size of the key or the algid is not really known
177         * but can be derived from the certificates.
178         * the cert, pubkey and privkey are a set.
179         * Key usages bits taken from pkcs15v1_1 Table 2
180         */
181        pubdata pubkeys[] = {
182
183                { "1", "PIV AUTH pubkey", 0000,
184                                SC_PKCS15_PRKEY_USAGE_ENCRYPT |
185                                SC_PKCS15_PRKEY_USAGE_WRAP |
186                                SC_PKCS15_PRKEY_USAGE_VERIFY |
187                                SC_PKCS15_PRKEY_USAGE_VERIFYRECOVER,
188                        "9A06", 0x9A, "1", 0, 0},
189                { "2", "SIGN pubkey", 0000,
190                                SC_PKCS15_PRKEY_USAGE_ENCRYPT |
191                                SC_PKCS15_PRKEY_USAGE_VERIFY |
192                                SC_PKCS15_PRKEY_USAGE_VERIFYRECOVER |
193                                SC_PKCS15_PRKEY_USAGE_NONREPUDIATION,
194                        "9C06", 0x9C, "1", 0, 0},
195                { "3", "KEY MAN pubkey", 0000,
196                                SC_PKCS15_PRKEY_USAGE_WRAP,
197                        "9D06", 0x9D, "1", 0, 0},
198                { "4", "CARD AUTH pubkey", 0000,
199                                SC_PKCS15_PRKEY_USAGE_VERIFY |
200                                SC_PKCS15_PRKEY_USAGE_VERIFYRECOVER,
201                        "9E06", 0x9E, "0", 0, 0},  /* no pin, and avail in contactless */
202                { NULL, NULL, 0, 0, NULL, 0, NULL, 0, 0}
203               
204        };
205
206        prdata prkeys[] = {
207                { "1", "PIV AUTH key", 0000,
208                                SC_PKCS15_PRKEY_USAGE_DECRYPT |
209                                SC_PKCS15_PRKEY_USAGE_UNWRAP |
210                                SC_PKCS15_PRKEY_USAGE_SIGN |
211                                SC_PKCS15_PRKEY_USAGE_SIGNRECOVER,
212                        "", 0x9A, "1", 0},
213                { "2", "SIGN key", 0000,
214                                SC_PKCS15_PRKEY_USAGE_DECRYPT |
215                                SC_PKCS15_PRKEY_USAGE_SIGN |
216                                SC_PKCS15_PRKEY_USAGE_SIGNRECOVER |
217                                SC_PKCS15_PRKEY_USAGE_NONREPUDIATION,
218                        "", 0x9C, "1", 0},
219                { "3", "KEY MAN key", 0000,
220                                SC_PKCS15_PRKEY_USAGE_UNWRAP,
221                        "", 0x9D, "1", 0},
222                { "4", "CARD AUTH key", 0000,
223                                SC_PKCS15_PRKEY_USAGE_SIGN |
224                                SC_PKCS15_PRKEY_USAGE_SIGNRECOVER,
225                        "", 0x9E, NULL, 0}, /* no PIN needed, works with wireless */
226                { NULL, NULL, 0, 0, NULL, 0, NULL, 0}
227        };
228
229        int    r, i;
230        sc_card_t *card = p15card->card;
231        int exposed_cert[4] = {1, 0, 0, 0};
232        sc_serial_number_t serial;
233        char buf[SC_MAX_SERIALNR * 2 + 1];
234
235        SC_FUNC_CALLED(card->ctx, 1);
236
237        /* could read this off card if needed */
238
239        /* CSP does not like a - in the name */
240        p15card->label = strdup("PIV_II");
241        p15card->manufacturer_id = strdup(MANU_ID);
242
243        /*
244         * get serial number
245         * We will use the FASC-N from the CHUID
246         * Note we are not verifying CHUID, belongs to this card
247         * but need serial number for Mac tokend
248         */
249
250        r = sc_card_ctl(card, SC_CARDCTL_GET_SERIALNR, &serial);
251        if (r < 0) {
252                sc_debug(card->ctx,"sc_card_ctl rc=%d",r);
253                p15card->serial_number = strdup("00000000");
254        } else {
255                sc_bin_to_hex(serial.value, serial.len, buf, sizeof(buf), 0);
256                p15card->serial_number = strdup(buf);
257        }
258
259        sc_debug(card->ctx, "PIV-II adding objects...");
260
261        /* set other objects */
262        for (i = 0; objects[i].label; i++) {
263                struct sc_pkcs15_data_info obj_info;
264                struct sc_pkcs15_object    obj_obj;
265
266                memset(&obj_info, 0, sizeof(obj_info));
267                memset(&obj_obj, 0, sizeof(obj_obj));
268                sc_pkcs15_format_id(objects[i].id, &obj_info.id);
269                sc_format_path(objects[i].path, &obj_info.path);
270                strncpy(obj_info.app_label, objects[i].label, SC_PKCS15_MAX_LABEL_SIZE - 1);
271                r = sc_format_oid(&obj_info.app_oid, objects[i].aoid);
272                if (r != SC_SUCCESS)
273                        return r;
274
275                if (objects[i].auth_id)
276                        sc_pkcs15_format_id(objects[i].auth_id, &obj_obj.auth_id);
277
278                strncpy(obj_obj.label, objects[i].label, SC_PKCS15_MAX_LABEL_SIZE - 1);
279                obj_obj.flags = objects[i].obj_flags;
280               
281                r = sc_pkcs15emu_object_add(p15card, SC_PKCS15_TYPE_DATA_OBJECT,
282                        &obj_obj, &obj_info);
283                if (r < 0)
284                        SC_FUNC_RETURN(card->ctx, 1, r);
285        }
286
287        /*
288         * certs, pubkeys and priv keys are related and we assume
289         * they are in order
290         * We need to read the cert, get modulus and keylen
291         * We use those for the pubkey, and priv key objects.
292         * If no cert, then see if pubkey (i.e. we are initilizing,
293         * and the pubkey is in a file,) then add pubkey and privkey
294         * If no cert and no pubkey, skip adding them.
295 
296         */
297        /* set certs */
298        sc_debug(card->ctx, "PIV-II adding certs...");
299        for (i = 0; certs[i].label; i++) {
300                struct sc_pkcs15_cert_info cert_info;
301                struct sc_pkcs15_object    cert_obj;
302                sc_pkcs15_der_t   cert_der;
303                sc_pkcs15_cert_t *cert_out;
304               
305                if ((card->flags & 0x20) &&  (exposed_cert[i] == 0))
306                        continue;
307
308                memset(&cert_info, 0, sizeof(cert_info));
309                memset(&cert_obj,  0, sizeof(cert_obj));
310       
311                sc_pkcs15_format_id(certs[i].id, &cert_info.id);
312                cert_info.authority = certs[i].authority;
313                sc_format_path(certs[i].path, &cert_info.path);
314
315                strncpy(cert_obj.label, certs[i].label, SC_PKCS15_MAX_LABEL_SIZE - 1);
316                cert_obj.flags = certs[i].obj_flags;
317
318                /* see if we have a cert */
319
320                r = sc_pkcs15_read_file(p15card, &cert_info.path, &cert_der.value, &cert_der.len,NULL);
321
322                if (r) {
323                        sc_debug(card->ctx, "No cert found,i=%d", i);
324                        continue;
325                }
326
327                certs[i].found = 1;
328                /* cache it using the PKCS15 emulation objects */
329                /* as it does not change */
330                if (cert_der.value) {
331                        cert_info.value.value = cert_der.value;
332                        cert_info.value.len = cert_der.len;
333                        cert_info.path.len = 0; /* use in mem cert from now on */
334                }
335                /* following will find the cached cert in cert_info */
336                r =  sc_pkcs15_read_certificate(p15card, &cert_info, &cert_out);
337                if (r < 0) {
338                        sc_error(card->ctx, "Failed to read/parse the certificate r=%d",r);
339                        continue;
340                }
341                /* TODO support DSA keys */
342                if (cert_out->key.algorithm == SC_ALGORITHM_RSA) {
343                        /* save modulus_len in pub and priv */
344                        pubkeys[i].modulus_len = cert_out->key.u.rsa.modulus.len * 8;
345                        prkeys[i].modulus_len = cert_out->key.u.rsa.modulus.len * 8;
346                }
347                sc_pkcs15_free_certificate(cert_out);
348
349                r = sc_pkcs15emu_add_x509_cert(p15card, &cert_obj, &cert_info);
350                if (r < 0) {
351                        sc_error(card->ctx, " Failed to add cert obj r=%d",r);
352                        continue;
353                }
354        }
355
356        /* set pins */
357        sc_debug(card->ctx, "PIV-II adding pins...");
358        for (i = 0; pins[i].label; i++) {
359                struct sc_pkcs15_pin_info pin_info;
360                struct sc_pkcs15_object   pin_obj;
361
362                memset(&pin_info, 0, sizeof(pin_info));
363                memset(&pin_obj,  0, sizeof(pin_obj));
364
365                sc_pkcs15_format_id(pins[i].id, &pin_info.auth_id);
366                pin_info.reference     = pins[i].ref;
367                pin_info.flags         = pins[i].flags;
368                pin_info.type          = pins[i].type;
369                pin_info.min_length    = pins[i].minlen;
370                pin_info.stored_length = pins[i].storedlen;
371                pin_info.max_length    = pins[i].maxlen;
372                pin_info.pad_char      = pins[i].pad_char;
373                sc_format_path(pins[i].path, &pin_info.path);
374                pin_info.tries_left    = -1;
375
376                strncpy(pin_obj.label, pins[i].label, SC_PKCS15_MAX_LABEL_SIZE - 1);
377                pin_obj.flags = pins[i].obj_flags;
378
379                r = sc_pkcs15emu_add_pin_obj(p15card, &pin_obj, &pin_info);
380                if (r < 0)
381                        SC_FUNC_RETURN(card->ctx, 1, r);
382        }
383
384
385
386        /* set public keys */
387        /* We may only need this during initialzation when genkey
388         * gets the pubkey, but it can not be read from the card
389         * at a later time. The piv-tool can stach in file
390         */ 
391        sc_debug(card->ctx, "PIV-II adding pub keys...");
392        for (i = 0; pubkeys[i].label; i++) {
393                struct sc_pkcs15_pubkey_info pubkey_info;
394                struct sc_pkcs15_object     pubkey_obj;
395                struct sc_pkcs15_pubkey *p15_key;
396
397                if ((card->flags & 0x20) &&  (exposed_cert[i] == 0))
398                        continue;
399
400                memset(&pubkey_info, 0, sizeof(pubkey_info));
401                memset(&pubkey_obj,  0, sizeof(pubkey_obj));
402
403
404                sc_pkcs15_format_id(pubkeys[i].id, &pubkey_info.id);
405                pubkey_info.usage         = pubkeys[i].usage;
406                pubkey_info.native        = 1;
407                pubkey_info.key_reference = pubkeys[i].ref;
408
409                sc_format_path(pubkeys[i].path, &pubkey_info.path);
410
411                strncpy(pubkey_obj.label, pubkeys[i].label, SC_PKCS15_MAX_LABEL_SIZE - 1);
412
413                pubkey_obj.flags = pubkeys[i].obj_flags;
414               
415
416                if (pubkeys[i].auth_id)
417                        sc_pkcs15_format_id(pubkeys[i].auth_id, &pubkey_obj.auth_id);
418
419                if (certs[i].found == 0) { /*  no cert found */
420                        sc_debug(card->ctx,"No cert for this pub key i=%d",i);
421                        /* TODO DSA */
422                        pubkey_obj.type = SC_PKCS15_TYPE_PUBKEY_RSA;
423                        pubkey_obj.data = &pubkey_info;
424                        r = sc_pkcs15_read_pubkey(p15card, &pubkey_obj, &p15_key);
425                                pubkey_obj.data = NULL;
426                                sc_debug(card->ctx," READING PUB KEY r=%d",r);
427                        if (r < 0 ) {
428                                continue;
429                        }
430                        /* Only get here if no cert, and the card-piv.c found
431                         * there is a pub key file. This only happens when trying
432                         * initializing a card and have set env to point at file 
433                         */
434                        if (p15_key->algorithm == SC_ALGORITHM_RSA) {
435                        /* save modulus_len in pub and priv */
436                        pubkeys[i].modulus_len = p15_key->u.rsa.modulus.len * 8;
437                        prkeys[i].modulus_len = p15_key->u.rsa.modulus.len * 8;
438                        pubkeys[i].found = 1;
439                        }
440
441                }
442                pubkey_info.modulus_length = pubkeys[i].modulus_len;
443                strncpy(pubkey_obj.label, pubkeys[i].label, SC_PKCS15_MAX_LABEL_SIZE - 1);
444
445                /* TODO DSA keys */
446                r = sc_pkcs15emu_add_rsa_pubkey(p15card, &pubkey_obj, &pubkey_info);
447                if (r < 0)
448                        SC_FUNC_RETURN(card->ctx, 1, r); /* should not fail */
449
450                pubkeys[i].found = 1;
451        }
452
453
454        /* set private keys */
455        sc_debug(card->ctx, "PIV-II adding private keys...");
456        for (i = 0; prkeys[i].label; i++) {
457                struct sc_pkcs15_prkey_info prkey_info;
458                struct sc_pkcs15_object     prkey_obj;
459
460                if ((card->flags & 0x20) &&  (exposed_cert[i] == 0))
461                        continue;
462
463                memset(&prkey_info, 0, sizeof(prkey_info));
464                memset(&prkey_obj,  0, sizeof(prkey_obj));
465
466                if (certs[i].found == 0 && pubkeys[i].found == 0)
467                        continue; /* i.e. no cert or pubkey */
468               
469                sc_pkcs15_format_id(prkeys[i].id, &prkey_info.id);
470                prkey_info.usage         = prkeys[i].usage;
471                prkey_info.native        = 1;
472                prkey_info.key_reference = prkeys[i].ref;
473                prkey_info.modulus_length= prkeys[i].modulus_len;
474                /* The cert or pubkey should have filled modulus_len */
475                /* TODO DSA keys */
476                sc_format_path(prkeys[i].path, &prkey_info.path);
477
478                strncpy(prkey_obj.label, prkeys[i].label, SC_PKCS15_MAX_LABEL_SIZE - 1);
479
480                prkey_obj.flags = prkeys[i].obj_flags;
481
482                if (prkeys[i].auth_id)
483                        sc_pkcs15_format_id(prkeys[i].auth_id, &prkey_obj.auth_id);
484
485                r = sc_pkcs15emu_add_rsa_prkey(p15card, &prkey_obj, &prkey_info);
486                if (r < 0)
487                        SC_FUNC_RETURN(card->ctx, 1, r);
488        }
489
490        SC_FUNC_RETURN(card->ctx, 1, SC_SUCCESS);
491}
492
493int sc_pkcs15emu_piv_init_ex(sc_pkcs15_card_t *p15card,
494                                  sc_pkcs15emu_opt_t *opts)
495{
496        sc_card_t   *card = p15card->card;
497        sc_context_t    *ctx = card->ctx;
498
499        SC_FUNC_CALLED(ctx, 1);
500
501        if (opts && opts->flags & SC_PKCS15EMU_FLAGS_NO_CHECK)
502                return sc_pkcs15emu_piv_init(p15card);
503        else {
504                int r = piv_detect_card(p15card);
505                if (r)
506                        return SC_ERROR_WRONG_CARD;
507                return sc_pkcs15emu_piv_init(p15card);
508        }
509}
Note: See TracBrowser for help on using the browser.