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

Revision 3512, 14.2 KB (checked in by alonbl, 7 months ago)

Better handle openct reader replug, revert last change in pkcs11-pin

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
Line 
1/*
2 * pkcs15-pin.c: PKCS #15 PIN functions
3 *
4 * Copyright (C) 2001, 2002  Juha YrjölÀ <juha.yrjola@iki.fi>
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 "pkcs15.h"
23#include "asn1.h"
24#include <assert.h>
25#include <string.h>
26#include <stdlib.h>
27#include <stdio.h>
28
29static const struct sc_asn1_entry c_asn1_com_ao_attr[] = {
30        { "authId",       SC_ASN1_PKCS15_ID, SC_ASN1_TAG_OCTET_STRING, 0, NULL, NULL },
31        { NULL, 0, 0, 0, NULL, NULL }
32};
33static const struct sc_asn1_entry c_asn1_pin_attr[] = {
34        { "pinFlags",     SC_ASN1_BIT_FIELD, SC_ASN1_TAG_BIT_STRING, 0, NULL, NULL },
35        { "pinType",      SC_ASN1_ENUMERATED, SC_ASN1_TAG_ENUMERATED, 0, NULL, NULL },
36        { "minLength",    SC_ASN1_INTEGER, SC_ASN1_TAG_INTEGER, 0, NULL, NULL },
37        { "storedLength", SC_ASN1_INTEGER, SC_ASN1_TAG_INTEGER, 0, NULL, NULL },
38        { "maxLength",    SC_ASN1_INTEGER, SC_ASN1_TAG_INTEGER, SC_ASN1_OPTIONAL, NULL, NULL },
39        { "pinReference", SC_ASN1_INTEGER, SC_ASN1_CTX | 0, SC_ASN1_OPTIONAL, NULL, NULL },
40        { "padChar",      SC_ASN1_OCTET_STRING, SC_ASN1_TAG_OCTET_STRING, SC_ASN1_OPTIONAL, NULL, NULL },
41        { "lastPinChange",SC_ASN1_GENERALIZEDTIME, SC_ASN1_TAG_GENERALIZEDTIME, SC_ASN1_OPTIONAL, NULL, NULL },
42        { "path",         SC_ASN1_PATH, SC_ASN1_TAG_SEQUENCE | SC_ASN1_CONS, SC_ASN1_OPTIONAL, NULL, NULL },
43        { NULL, 0, 0, 0, NULL, NULL }
44};
45static const struct sc_asn1_entry c_asn1_type_pin_attr[] = {
46        { "pinAttributes", SC_ASN1_STRUCT, SC_ASN1_TAG_SEQUENCE | SC_ASN1_CONS, 0, NULL, NULL },
47        { NULL, 0, 0, 0, NULL, NULL }
48};
49static const struct sc_asn1_entry c_asn1_pin[] = {
50        { "pin", SC_ASN1_PKCS15_OBJECT, SC_ASN1_TAG_SEQUENCE | SC_ASN1_CONS, 0, NULL, NULL },
51        { NULL, 0, 0, 0, NULL, NULL }
52};
53
54int sc_pkcs15_decode_aodf_entry(struct sc_pkcs15_card *p15card,
55                                struct sc_pkcs15_object *obj,
56                                const u8 ** buf, size_t *buflen)
57{
58        sc_context_t *ctx = p15card->card->ctx;
59        struct sc_pkcs15_pin_info info;
60        int r;
61        size_t flags_len = sizeof(info.flags);
62        size_t padchar_len = 1;
63        struct sc_asn1_entry asn1_com_ao_attr[2], asn1_pin_attr[10], asn1_type_pin_attr[2];
64        struct sc_asn1_entry asn1_pin[2];
65        struct sc_asn1_pkcs15_object pin_obj = { obj, asn1_com_ao_attr, NULL, asn1_type_pin_attr };
66       
67        sc_copy_asn1_entry(c_asn1_pin, asn1_pin);
68        sc_copy_asn1_entry(c_asn1_type_pin_attr, asn1_type_pin_attr);
69        sc_copy_asn1_entry(c_asn1_pin_attr, asn1_pin_attr);
70        sc_copy_asn1_entry(c_asn1_com_ao_attr, asn1_com_ao_attr);
71
72        sc_format_asn1_entry(asn1_pin + 0, &pin_obj, NULL, 0);
73
74        sc_format_asn1_entry(asn1_type_pin_attr + 0, asn1_pin_attr, NULL, 0);
75
76        sc_format_asn1_entry(asn1_pin_attr + 0, &info.flags, &flags_len, 0);
77        sc_format_asn1_entry(asn1_pin_attr + 1, &info.type, NULL, 0);
78        sc_format_asn1_entry(asn1_pin_attr + 2, &info.min_length, NULL, 0);
79        sc_format_asn1_entry(asn1_pin_attr + 3, &info.stored_length, NULL, 0);
80        sc_format_asn1_entry(asn1_pin_attr + 4, &info.max_length, NULL, 0);
81        sc_format_asn1_entry(asn1_pin_attr + 5, &info.reference, NULL, 0);
82        sc_format_asn1_entry(asn1_pin_attr + 6, &info.pad_char, &padchar_len, 0);
83        /* We don't support lastPinChange yet. */
84        sc_format_asn1_entry(asn1_pin_attr + 8, &info.path, NULL, 0);
85
86        sc_format_asn1_entry(asn1_com_ao_attr + 0, &info.auth_id, NULL, 0);
87
88        /* Fill in defaults */
89        memset(&info, 0, sizeof(info));
90        info.reference = 0;
91        info.tries_left = -1;
92
93        r = sc_asn1_decode(ctx, asn1_pin, *buf, *buflen, buf, buflen);
94        if (r == SC_ERROR_ASN1_END_OF_CONTENTS)
95                return r;
96        SC_TEST_RET(ctx, r, "ASN.1 decoding failed");
97        info.magic = SC_PKCS15_PIN_MAGIC;
98        obj->type = SC_PKCS15_TYPE_AUTH_PIN;
99        obj->data = malloc(sizeof(info));
100        if (obj->data == NULL)
101                SC_FUNC_RETURN(ctx, 0, SC_ERROR_OUT_OF_MEMORY);
102        if (info.max_length == 0) {
103                if (p15card->card->max_pin_len != 0)
104                        info.max_length = p15card->card->max_pin_len;
105                else if (info.stored_length != 0)
106                        info.max_length = info.type != SC_PKCS15_PIN_TYPE_BCD ?
107                                info.stored_length : 2 * info.stored_length;
108                else
109                        info.max_length = 8; /* shouldn't happen */
110        }
111        memcpy(obj->data, &info, sizeof(info));
112
113        return 0;
114}
115
116int sc_pkcs15_encode_aodf_entry(sc_context_t *ctx,
117                                 const struct sc_pkcs15_object *obj,
118                                 u8 **buf, size_t *buflen)
119{
120        struct sc_asn1_entry asn1_com_ao_attr[2], asn1_pin_attr[10], asn1_type_pin_attr[2];
121        struct sc_asn1_entry asn1_pin[2];
122        struct sc_pkcs15_pin_info *pin =
123                (struct sc_pkcs15_pin_info *) obj->data;
124        struct sc_asn1_pkcs15_object pin_obj = { (struct sc_pkcs15_object *) obj,
125                                                 asn1_com_ao_attr, NULL, asn1_type_pin_attr };
126        int r;
127        size_t flags_len;
128        size_t padchar_len = 1;
129
130        sc_copy_asn1_entry(c_asn1_pin, asn1_pin);
131        sc_copy_asn1_entry(c_asn1_type_pin_attr, asn1_type_pin_attr);
132        sc_copy_asn1_entry(c_asn1_pin_attr, asn1_pin_attr);
133        sc_copy_asn1_entry(c_asn1_com_ao_attr, asn1_com_ao_attr);
134
135        sc_format_asn1_entry(asn1_pin + 0, &pin_obj, NULL, 1);
136
137        sc_format_asn1_entry(asn1_type_pin_attr + 0, asn1_pin_attr, NULL, 1);
138
139        flags_len = sizeof(pin->flags);
140        sc_format_asn1_entry(asn1_pin_attr + 0, &pin->flags, &flags_len, 1);
141        sc_format_asn1_entry(asn1_pin_attr + 1, &pin->type, NULL, 1);
142        sc_format_asn1_entry(asn1_pin_attr + 2, &pin->min_length, NULL, 1);
143        sc_format_asn1_entry(asn1_pin_attr + 3, &pin->stored_length, NULL, 1);
144        if (pin->max_length > 0)
145                sc_format_asn1_entry(asn1_pin_attr + 4, &pin->max_length, NULL, 1);
146        if (pin->reference >= 0)
147                sc_format_asn1_entry(asn1_pin_attr + 5, &pin->reference, NULL, 1);
148        /* FIXME: check if pad_char present */
149        sc_format_asn1_entry(asn1_pin_attr + 6, &pin->pad_char, &padchar_len, 1);
150        sc_format_asn1_entry(asn1_pin_attr + 8, &pin->path, NULL, 1);
151
152        sc_format_asn1_entry(asn1_com_ao_attr + 0, &pin->auth_id, NULL, 1);
153
154        assert(pin->magic == SC_PKCS15_PIN_MAGIC);
155        r = sc_asn1_encode(ctx, asn1_pin, buf, buflen);
156
157        return r;
158}
159
160static int _validate_pin(struct sc_pkcs15_card *p15card,
161                         struct sc_pkcs15_pin_info *pin,
162                         size_t pinlen)
163{
164        size_t max_length;
165        assert(p15card != NULL);
166       
167        if (pin->magic != SC_PKCS15_PIN_MAGIC)
168                return SC_ERROR_OBJECT_NOT_VALID;
169               
170        /* prevent buffer overflow from hostile card */ 
171        if (pin->stored_length > SC_MAX_PIN_SIZE)
172                return SC_ERROR_BUFFER_TOO_SMALL;
173
174        /* if we use pinpad, no more checks are needed */
175        if (p15card->card->slot->capabilities & SC_SLOT_CAP_PIN_PAD)
176                return SC_SUCCESS;
177               
178        /* If pin is given, make sure it is within limits */
179        max_length = pin->max_length != 0 ? pin->max_length : SC_MAX_PIN_SIZE;
180        if (pinlen > max_length || pinlen < pin->min_length)
181                return SC_ERROR_INVALID_PIN_LENGTH;
182
183        return SC_SUCCESS;
184}
185
186/*
187 * Verify a PIN.
188 *
189 * If the code given to us has zero length, this means we
190 * should ask the card reader to obtain the PIN from the
191 * reader's PIN pad
192 */
193int sc_pkcs15_verify_pin(struct sc_pkcs15_card *p15card,
194                         struct sc_pkcs15_pin_info *pin,
195                         const u8 *pincode, size_t pinlen)
196{
197        int r;
198        sc_card_t *card;
199        struct sc_pin_cmd_data data;
200
201        if ((r = _validate_pin(p15card, pin, pinlen)) != SC_SUCCESS)
202                return r;
203
204        card = p15card->card;
205
206        r = sc_lock(card);
207        if (r == SC_ERROR_CARD_RESET || r == SC_ERROR_READER_REATTACHED) {
208                r = sc_lock(card);
209        }
210        SC_TEST_RET(card->ctx, r, "sc_lock() failed");
211        /* the path in the pin object is optional */
212        if (pin->path.len > 0) {
213                r = sc_select_file(card, &pin->path, NULL);
214                if (r)
215                        goto out;
216        }
217
218        /* Initialize arguments */
219        memset(&data, 0, sizeof(data));
220        data.cmd = SC_PIN_CMD_VERIFY;
221        data.pin_type = SC_AC_CHV;
222        data.pin_reference = pin->reference;
223        data.pin1.min_length = pin->min_length;
224        data.pin1.max_length = pin->max_length;
225        data.pin1.pad_length = pin->stored_length;
226        data.pin1.pad_char = pin->pad_char;
227        data.pin1.data = pincode;
228        data.pin1.len = pinlen;
229
230        if (pin->flags & SC_PKCS15_PIN_FLAG_NEEDS_PADDING)
231                data.flags |= SC_PIN_CMD_NEED_PADDING;
232
233        switch (pin->type) {
234        case SC_PKCS15_PIN_TYPE_BCD:
235                data.pin1.encoding = SC_PIN_ENCODING_BCD;
236                break;
237        case SC_PKCS15_PIN_TYPE_ASCII_NUMERIC:
238                data.pin1.encoding = SC_PIN_ENCODING_ASCII;
239                break;
240        default:
241                /* assume/hope the card driver knows how to encode the pin */
242                data.pin1.encoding = 0;
243        }
244
245        if(p15card->card->slot->capabilities & SC_SLOT_CAP_PIN_PAD) {
246                data.flags |= SC_PIN_CMD_USE_PINPAD;
247                if (pin->flags & SC_PKCS15_PIN_FLAG_SO_PIN)
248                        data.pin1.prompt = "Please enter SO PIN";
249                else
250                        data.pin1.prompt = "Please enter PIN";
251        }
252
253        r = sc_pin_cmd(card, &data, &pin->tries_left);
254out:
255        sc_unlock(card);
256        return r;
257}
258
259/*
260 * Change a PIN.
261 */
262int sc_pkcs15_change_pin(struct sc_pkcs15_card *p15card,
263                         struct sc_pkcs15_pin_info *pin,
264                         const u8 *oldpin, size_t oldpinlen,
265                         const u8 *newpin, size_t newpinlen)
266{
267        int r;
268        sc_card_t *card;
269        struct sc_pin_cmd_data data;
270       
271        /* make sure the pins are in valid range */
272        if ((r = _validate_pin(p15card, pin, oldpinlen)) != SC_SUCCESS)
273                return r;
274        if ((r = _validate_pin(p15card, pin, newpinlen)) != SC_SUCCESS)
275                return r;
276
277        card = p15card->card;
278        r = sc_lock(card);
279        SC_TEST_RET(card->ctx, r, "sc_lock() failed");
280        /* the path in the pin object is optional */
281        if (pin->path.len > 0) {
282                r = sc_select_file(card, &pin->path, NULL);
283                if (r)
284                        goto out;
285        }
286
287        /* set pin_cmd data */
288        memset(&data, 0, sizeof(data));
289        data.cmd             = SC_PIN_CMD_CHANGE;
290        data.pin_type        = SC_AC_CHV;
291        data.pin_reference   = pin->reference;
292        data.pin1.data       = oldpin;
293        data.pin1.len        = oldpinlen;
294        data.pin1.pad_char   = pin->pad_char;
295        data.pin1.min_length = pin->min_length;
296        data.pin1.max_length = pin->max_length;
297        data.pin1.pad_length = pin->stored_length;
298        data.pin2.data       = newpin;
299        data.pin2.len        = newpinlen;
300        data.pin2.pad_char   = pin->pad_char;
301        data.pin2.min_length = pin->min_length;
302        data.pin2.max_length = pin->max_length;
303        data.pin2.pad_length = pin->stored_length;
304
305        if (pin->flags & SC_PKCS15_PIN_FLAG_NEEDS_PADDING)
306                data.flags |= SC_PIN_CMD_NEED_PADDING;
307
308        switch (pin->type) {
309        case SC_PKCS15_PIN_TYPE_BCD:
310                data.pin1.encoding = SC_PIN_ENCODING_BCD;
311                data.pin2.encoding = SC_PIN_ENCODING_BCD;
312                break;
313        case SC_PKCS15_PIN_TYPE_ASCII_NUMERIC:
314                data.pin1.encoding = SC_PIN_ENCODING_ASCII;
315                data.pin2.encoding = SC_PIN_ENCODING_ASCII;
316                break;
317        }
318       
319        if(p15card->card->slot->capabilities & SC_SLOT_CAP_PIN_PAD) {
320                data.flags |= SC_PIN_CMD_USE_PINPAD;
321                if (pin->flags & SC_PKCS15_PIN_FLAG_SO_PIN) {
322                        data.pin1.prompt = "Please enter SO PIN";
323                        data.pin2.prompt = "Please enter new SO PIN";
324                } else {
325                        data.pin1.prompt = "Please enter PIN";
326                        data.pin2.prompt = "Please enter new PIN";
327                }
328        }
329
330        r = sc_pin_cmd(card, &data, &pin->tries_left);
331
332out:
333        sc_unlock(card);
334        return r;
335}
336
337/*
338 * Unblock a PIN.
339 */
340int sc_pkcs15_unblock_pin(struct sc_pkcs15_card *p15card,
341                         struct sc_pkcs15_pin_info *pin,
342                         const u8 *puk, size_t puklen,
343                         const u8 *newpin, size_t newpinlen)
344{
345        int r;
346        sc_card_t *card;
347        struct sc_pin_cmd_data data;
348        struct sc_pkcs15_object *pin_obj, *puk_obj;
349        struct sc_pkcs15_pin_info *puk_info = NULL;
350
351        /* make sure the pins are in valid range */
352        if ((r = _validate_pin(p15card, pin, newpinlen)) != SC_SUCCESS)
353                return r;
354
355        card = p15card->card;
356        /* get pin_info object of the puk (this is a little bit complicated
357         * as we don't have the id of the puk (at least now))
358         * note: for compatibility reasons we give no error if no puk object
359         * is found */
360        /* first step:  get the pkcs15 object of the pin */
361        r = sc_pkcs15_find_pin_by_auth_id(p15card, &pin->auth_id, &pin_obj);
362        if (r >= 0 && pin_obj) {
363                /* second step: try to get the pkcs15 object of the puk */
364                r = sc_pkcs15_find_pin_by_auth_id(p15card, &pin_obj->auth_id, &puk_obj);
365                if (r >= 0 && puk_obj) {
366                        /* third step:  get the pkcs15 info object of the puk */
367                        puk_info = (struct sc_pkcs15_pin_info *)puk_obj->data;
368                }
369        }
370        if (!puk_info) {
371                sc_debug(card->ctx, "Unable to get puk object, using pin object instead!\n");
372                puk_info = pin;
373        }
374       
375        /* make sure the puk is in valid range */
376        if ((r = _validate_pin(p15card, puk_info, puklen)) != SC_SUCCESS)
377                return r;
378
379        r = sc_lock(card);
380        SC_TEST_RET(card->ctx, r, "sc_lock() failed");
381        /* the path in the pin object is optional */
382        if (pin->path.len > 0) {
383                r = sc_select_file(card, &pin->path, NULL);
384                if (r)
385                        goto out;
386        }
387
388        /* set pin_cmd data */
389        memset(&data, 0, sizeof(data));
390        data.cmd             = SC_PIN_CMD_UNBLOCK;
391        data.pin_type        = SC_AC_CHV;
392        data.pin_reference   = pin->reference;
393        data.pin1.data       = puk;
394        data.pin1.len        = puklen;
395        data.pin1.pad_char   = pin->pad_char;
396        data.pin1.min_length = pin->min_length;
397        data.pin1.max_length = pin->max_length;
398        data.pin1.pad_length = pin->stored_length;
399        data.pin2.data       = newpin;
400        data.pin2.len        = newpinlen;
401        data.pin2.pad_char   = puk_info->pad_char;
402        data.pin2.min_length = puk_info->min_length;
403        data.pin2.max_length = puk_info->max_length;
404        data.pin2.pad_length = puk_info->stored_length;
405
406        if (pin->flags & SC_PKCS15_PIN_FLAG_NEEDS_PADDING)
407                data.flags |= SC_PIN_CMD_NEED_PADDING;
408
409        switch (pin->type) {
410        case SC_PKCS15_PIN_TYPE_BCD:
411                data.pin1.encoding = SC_PIN_ENCODING_BCD;
412                break;
413        case SC_PKCS15_PIN_TYPE_ASCII_NUMERIC:
414                data.pin1.encoding = SC_PIN_ENCODING_ASCII;
415                break;
416        }
417
418        switch (puk_info->type) {
419        case SC_PKCS15_PIN_TYPE_BCD:
420                data.pin2.encoding = SC_PIN_ENCODING_BCD;
421                break;
422        case SC_PKCS15_PIN_TYPE_ASCII_NUMERIC:
423                data.pin2.encoding = SC_PIN_ENCODING_ASCII;
424                break;
425        }
426       
427        if(p15card->card->slot->capabilities & SC_SLOT_CAP_PIN_PAD) {
428                data.flags |= SC_PIN_CMD_USE_PINPAD;
429                if (pin->flags & SC_PKCS15_PIN_FLAG_SO_PIN) {
430                        data.pin1.prompt = "Please enter PUK";
431                        data.pin2.prompt = "Please enter new SO PIN";
432                } else {
433                        data.pin1.prompt = "Please enter PUK";
434                        data.pin2.prompt = "Please enter new PIN";
435                }
436        }
437
438        r = sc_pin_cmd(card, &data, &pin->tries_left);
439
440out:
441        sc_unlock(card);
442        return r;
443}
444
445void sc_pkcs15_free_pin_info(sc_pkcs15_pin_info_t *pin)
446{
447        free(pin);
448}
Note: See TracBrowser for help on using the browser.