source: trunk/third/openssh/scard-opensc.c @ 18759

Revision 18759, 10.0 KB checked in by zacheiss, 22 years ago (diff)
This commit was generated by cvs2svn to compensate for changes in r18758, which included commits to RCS files with non-trunk default branches.
Line 
1/*
2 * Copyright (c) 2002 Juha Yrjölä.  All rights reserved.
3 * Copyright (c) 2001 Markus Friedl.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 *    notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 *    notice, this list of conditions and the following disclaimer in the
12 *    documentation and/or other materials provided with the distribution.
13 *
14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
15 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
16 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
17 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
18 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
19 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
20 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
21 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
23 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24 */
25
26#include "includes.h"
27#if defined(SMARTCARD) && defined(USE_OPENSC)
28
29#include <openssl/evp.h>
30#include <openssl/x509.h>
31
32#include <opensc/opensc.h>
33#include <opensc/pkcs15.h>
34
35#include "key.h"
36#include "log.h"
37#include "xmalloc.h"
38#include "readpass.h"
39#include "scard.h"
40
41#if OPENSSL_VERSION_NUMBER < 0x00907000L && defined(CRYPTO_LOCK_ENGINE)
42#define USE_ENGINE
43#define RSA_get_default_method RSA_get_default_openssl_method
44#else
45#endif
46
47#ifdef USE_ENGINE
48#include <openssl/engine.h>
49#define sc_get_rsa sc_get_engine
50#else
51#define sc_get_rsa sc_get_rsa_method
52#endif
53
54static int sc_reader_id;
55static sc_context_t *ctx = NULL;
56static sc_card_t *card = NULL;
57static sc_pkcs15_card_t *p15card = NULL;
58
59static char *sc_pin = NULL;
60
61struct sc_priv_data
62{
63        struct sc_pkcs15_id cert_id;
64        int ref_count;
65};
66
67void
68sc_close(void)
69{
70        if (p15card) {
71                sc_pkcs15_unbind(p15card);
72                p15card = NULL;
73        }
74        if (card) {
75                sc_disconnect_card(card, 0);
76                card = NULL;
77        }
78        if (ctx) {
79                sc_release_context(ctx);
80                ctx = NULL;
81        }
82}
83
84static int
85sc_init(void)
86{
87        int r;
88
89        r = sc_establish_context(&ctx, "openssh");
90        if (r)
91                goto err;
92        r = sc_connect_card(ctx->reader[sc_reader_id], 0, &card);
93        if (r)
94                goto err;
95        r = sc_pkcs15_bind(card, &p15card);
96        if (r)
97                goto err;
98        return 0;
99err:
100        sc_close();
101        return r;
102}
103
104/* private key operations */
105
106static int
107sc_prkey_op_init(RSA *rsa, struct sc_pkcs15_object **key_obj_out)
108{
109        int r;
110        struct sc_priv_data *priv;
111        struct sc_pkcs15_object *key_obj;
112        struct sc_pkcs15_prkey_info *key;
113        struct sc_pkcs15_object *pin_obj;
114        struct sc_pkcs15_pin_info *pin;
115
116        priv = (struct sc_priv_data *) RSA_get_app_data(rsa);
117        if (priv == NULL)
118                return -1;
119        if (p15card == NULL) {
120                sc_close();
121                r = sc_init();
122                if (r) {
123                        error("SmartCard init failed: %s", sc_strerror(r));
124                        goto err;
125                }
126        }
127        r = sc_pkcs15_find_prkey_by_id(p15card, &priv->cert_id, &key_obj);
128        if (r) {
129                error("Unable to find private key from SmartCard: %s",
130                      sc_strerror(r));
131                goto err;
132        }
133        key = key_obj->data;
134        r = sc_pkcs15_find_pin_by_auth_id(p15card, &key_obj->auth_id,
135                                          &pin_obj);
136        if (r) {
137                error("Unable to find PIN object from SmartCard: %s",
138                      sc_strerror(r));
139                goto err;
140        }
141        pin = pin_obj->data;
142        r = sc_lock(card);
143        if (r) {
144                error("Unable to lock smartcard: %s", sc_strerror(r));
145                goto err;
146        }
147        if (sc_pin != NULL) {
148                r = sc_pkcs15_verify_pin(p15card, pin, sc_pin,
149                                         strlen(sc_pin));
150                if (r) {
151                        sc_unlock(card);
152                        error("PIN code verification failed: %s",
153                              sc_strerror(r));
154                        goto err;
155                }
156        }
157        *key_obj_out = key_obj;
158        return 0;
159err:
160        sc_close();
161        return -1;
162}
163
164static int
165sc_private_decrypt(int flen, u_char *from, u_char *to, RSA *rsa,
166    int padding)
167{
168        struct sc_pkcs15_object *key_obj;
169        int r;
170
171        if (padding != RSA_PKCS1_PADDING)
172                return -1;     
173        r = sc_prkey_op_init(rsa, &key_obj);
174        if (r)
175                return -1;
176        r = sc_pkcs15_decipher(p15card, key_obj, 0, from, flen, to, flen);
177        sc_unlock(card);
178        if (r < 0) {
179                error("sc_pkcs15_decipher() failed: %s", sc_strerror(r));
180                goto err;
181        }
182        return r;
183err:
184        sc_close();
185        return -1;
186}
187
188static int
189sc_sign(int type, u_char *m, unsigned int m_len,
190        unsigned char *sigret, unsigned int *siglen, RSA *rsa)
191{
192        struct sc_pkcs15_object *key_obj;
193        int r;
194        unsigned long flags = 0;
195
196        r = sc_prkey_op_init(rsa, &key_obj);
197        if (r)
198                return -1;
199        /* FIXME: length of sigret correct? */
200        /* FIXME: check 'type' and modify flags accordingly */
201        flags = SC_ALGORITHM_RSA_PAD_PKCS1 | SC_ALGORITHM_RSA_HASH_SHA1;
202        r = sc_pkcs15_compute_signature(p15card, key_obj, flags,
203                                        m, m_len, sigret, RSA_size(rsa));
204        sc_unlock(card);
205        if (r < 0) {
206                error("sc_pkcs15_compute_signature() failed: %s",
207                      sc_strerror(r));
208                goto err;
209        }
210        *siglen = r;
211        return 1;
212err:
213        sc_close();
214        return 0;
215}
216
217static int
218sc_private_encrypt(int flen, u_char *from, u_char *to, RSA *rsa,
219    int padding)
220{
221        error("Private key encryption not supported");
222        return -1;
223}
224
225/* called on free */
226
227static int (*orig_finish)(RSA *rsa) = NULL;
228
229static int
230sc_finish(RSA *rsa)
231{
232        struct sc_priv_data *priv;
233
234        priv = RSA_get_app_data(rsa);
235        priv->ref_count--;
236        if (priv->ref_count == 0) {
237                free(priv);
238                sc_close();
239        }
240        if (orig_finish)
241                orig_finish(rsa);
242        return 1;
243}
244
245/* engine for overloading private key operations */
246
247static RSA_METHOD *
248sc_get_rsa_method(void)
249{
250        static RSA_METHOD smart_rsa;
251        const RSA_METHOD *def = RSA_get_default_method();
252
253        /* use the OpenSSL version */
254        memcpy(&smart_rsa, def, sizeof(smart_rsa));
255
256        smart_rsa.name          = "opensc";
257
258        /* overload */
259        smart_rsa.rsa_priv_enc  = sc_private_encrypt;
260        smart_rsa.rsa_priv_dec  = sc_private_decrypt;
261        smart_rsa.rsa_sign      = sc_sign;
262
263        /* save original */
264        orig_finish             = def->finish;
265        smart_rsa.finish        = sc_finish;
266
267        return &smart_rsa;
268}
269
270#ifdef USE_ENGINE
271static ENGINE *
272sc_get_engine(void)
273{
274        static ENGINE *smart_engine = NULL;
275
276        if ((smart_engine = ENGINE_new()) == NULL)
277                fatal("ENGINE_new failed");
278
279        ENGINE_set_id(smart_engine, "opensc");
280        ENGINE_set_name(smart_engine, "OpenSC");
281
282        ENGINE_set_RSA(smart_engine, sc_get_rsa_method());
283        ENGINE_set_DSA(smart_engine, DSA_get_default_openssl_method());
284        ENGINE_set_DH(smart_engine, DH_get_default_openssl_method());
285        ENGINE_set_RAND(smart_engine, RAND_SSLeay());
286        ENGINE_set_BN_mod_exp(smart_engine, BN_mod_exp);
287
288        return smart_engine;
289}
290#endif
291
292static void
293convert_rsa_to_rsa1(Key * in, Key * out)
294{
295        struct sc_priv_data *priv;
296       
297        out->rsa->flags = in->rsa->flags;
298        out->flags = in->flags;
299        RSA_set_method(out->rsa, RSA_get_method(in->rsa));
300        BN_copy(out->rsa->n, in->rsa->n);
301        BN_copy(out->rsa->e, in->rsa->e);
302        priv = RSA_get_app_data(in->rsa);
303        priv->ref_count++;
304        RSA_set_app_data(out->rsa, priv);
305        return;
306}
307
308static int
309sc_read_pubkey(Key * k, const struct sc_pkcs15_object *cert_obj)
310{
311        int r;
312        sc_pkcs15_cert_t *cert = NULL;
313        struct sc_priv_data *priv = NULL;
314        sc_pkcs15_cert_info_t *cinfo = cert_obj->data;
315
316        X509 *x509 = NULL;
317        EVP_PKEY *pubkey = NULL;
318        u8 *p;
319        char *tmp;
320       
321        debug("sc_read_pubkey() with cert id %02X", cinfo->id.value[0]);
322        r = sc_pkcs15_read_certificate(p15card, cinfo, &cert);
323        if (r) {
324                log("Certificate read failed: %s", sc_strerror(r));
325                goto err;
326        }
327        x509 = X509_new();
328        if (x509 == NULL) {
329                r = -1;
330                goto err;
331        }
332        p = cert->data;
333        if (!d2i_X509(&x509, &p, cert->data_len)) {
334                log("Unable to parse X.509 certificate");
335                r = -1;
336                goto err;
337        }
338        sc_pkcs15_free_certificate(cert);
339        cert = NULL;
340        pubkey = X509_get_pubkey(x509);
341        X509_free(x509);
342        x509 = NULL;
343        if (pubkey->type != EVP_PKEY_RSA) {
344                log("Public key is of unknown type");
345                r = -1;
346                goto err;
347        }
348        k->rsa = EVP_PKEY_get1_RSA(pubkey);
349        EVP_PKEY_free(pubkey);
350
351        k->rsa->flags |= RSA_FLAG_SIGN_VER;
352        RSA_set_method(k->rsa, sc_get_rsa_method());
353        priv = xmalloc(sizeof(struct sc_priv_data));
354        priv->cert_id = cinfo->id;
355        priv->ref_count = 1;
356        RSA_set_app_data(k->rsa, priv);
357
358        k->flags = KEY_FLAG_EXT;
359        tmp = key_fingerprint(k, SSH_FP_MD5, SSH_FP_HEX);
360        debug("fingerprint %d %s", key_size(k), tmp);
361        xfree(tmp);
362       
363        return 0;
364err:
365        if (cert)
366                sc_pkcs15_free_certificate(cert);
367        if (pubkey)
368                EVP_PKEY_free(pubkey);
369        if (x509)
370                X509_free(x509);
371        return r;
372}
373
374Key **
375sc_get_keys(const char *id, const char *pin)
376{
377        Key *k, **keys;
378        int i, r, real_count = 0, key_count;
379        sc_pkcs15_id_t cert_id;
380        sc_pkcs15_object_t *certs[32];
381        char *buf = xstrdup(id), *p;
382
383        debug("sc_get_keys called: id = %s", id);
384
385        if (sc_pin != NULL)
386                xfree(sc_pin);
387        sc_pin = (pin == NULL) ? NULL : xstrdup(pin);
388
389        cert_id.len = 0;
390        if ((p = strchr(buf, ':')) != NULL) {
391                *p = 0;
392                p++;
393                sc_pkcs15_hex_string_to_id(p, &cert_id);
394        }
395        r = sscanf(buf, "%d", &sc_reader_id);
396        xfree(buf);
397        if (r != 1)
398                goto err;
399        if (p15card == NULL) {
400                sc_close();
401                r = sc_init();
402                if (r) {
403                        error("Smartcard init failed: %s", sc_strerror(r));
404                        goto err;
405                }
406        }
407        if (cert_id.len) {
408                r = sc_pkcs15_find_cert_by_id(p15card, &cert_id, &certs[0]);
409                if (r < 0)
410                        goto err;
411                key_count = 1;
412        } else {
413                r = sc_pkcs15_get_objects(p15card, SC_PKCS15_TYPE_CERT_X509,
414                                          certs, 32);
415                if (r == 0) {
416                        log("No certificates found on smartcard");
417                        r = -1;
418                        goto err;
419                } else if (r < 0) {
420                        error("Certificate enumeration failed: %s",
421                              sc_strerror(r));
422                        goto err;
423                }
424                key_count = r;
425        }
426        /* FIXME: only keep entries with a corresponding private key */
427        keys = xmalloc(sizeof(Key *) * (key_count*2+1));
428        for (i = 0; i < key_count; i++) {
429                k = key_new(KEY_RSA);
430                if (k == NULL)
431                        break;
432                r = sc_read_pubkey(k, certs[i]);
433                if (r) {
434                        error("sc_read_pubkey failed: %s", sc_strerror(r));
435                        key_free(k);
436                        continue;
437                }
438                keys[real_count] = k;
439                real_count++;
440                k = key_new(KEY_RSA1);
441                if (k == NULL)
442                        break;
443                convert_rsa_to_rsa1(keys[real_count-1], k);
444                keys[real_count] = k;
445                real_count++;
446        }
447        keys[real_count] = NULL;
448
449        return keys;
450err:
451        sc_close();
452        return NULL;
453}
454
455int
456sc_put_key(Key *prv, const char *id)
457{
458        error("key uploading not yet supported");
459        return -1;
460}
461
462#endif /* SMARTCARD */
Note: See TracBrowser for help on using the repository browser.