2 * Copyright (c) 2002 Juha Yrjölä. All rights reserved.
3 * Copyright (c) 2001 Markus Friedl.
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
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.
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.
27 #if defined(SMARTCARD) && defined(USE_OPENSC)
29 #include <sys/types.h>
31 #include <openssl/evp.h>
32 #include <openssl/x509.h>
37 #include <opensc/opensc.h>
38 #include <opensc/pkcs15.h>
46 #if OPENSSL_VERSION_NUMBER < 0x00907000L && defined(CRYPTO_LOCK_ENGINE)
48 #define RSA_get_default_method RSA_get_default_openssl_method
53 #include <openssl/engine.h>
54 #define sc_get_rsa sc_get_engine
56 #define sc_get_rsa sc_get_rsa_method
59 static int sc_reader_id
;
60 static sc_context_t
*ctx
= NULL
;
61 static sc_card_t
*card
= NULL
;
62 static sc_pkcs15_card_t
*p15card
= NULL
;
64 static char *sc_pin
= NULL
;
68 struct sc_pkcs15_id cert_id
;
76 sc_pkcs15_unbind(p15card
);
80 sc_disconnect_card(card
, 0);
84 sc_release_context(ctx
);
94 r
= sc_establish_context(&ctx
, "openssh");
97 if (sc_reader_id
>= ctx
->reader_count
) {
98 r
= SC_ERROR_NO_READERS_FOUND
;
99 error("Illegal reader number %d (max %d)", sc_reader_id
,
100 ctx
->reader_count
-1);
103 r
= sc_connect_card(ctx
->reader
[sc_reader_id
], 0, &card
);
106 r
= sc_pkcs15_bind(card
, &p15card
);
115 /* private key operations */
118 sc_prkey_op_init(RSA
*rsa
, struct sc_pkcs15_object
**key_obj_out
,
122 struct sc_priv_data
*priv
;
123 struct sc_pkcs15_object
*key_obj
;
124 struct sc_pkcs15_prkey_info
*key
;
125 struct sc_pkcs15_object
*pin_obj
;
126 struct sc_pkcs15_pin_info
*pin
;
128 priv
= (struct sc_priv_data
*) RSA_get_app_data(rsa
);
131 if (p15card
== NULL
) {
135 error("SmartCard init failed: %s", sc_strerror(r
));
139 r
= sc_pkcs15_find_prkey_by_id_usage(p15card
, &priv
->cert_id
,
142 error("Unable to find private key from SmartCard: %s",
147 r
= sc_pkcs15_find_pin_by_auth_id(p15card
, &key_obj
->auth_id
,
149 if (r
== SC_ERROR_OBJECT_NOT_FOUND
) {
150 /* no pin required */
153 error("Unable to lock smartcard: %s", sc_strerror(r
));
156 *key_obj_out
= key_obj
;
159 error("Unable to find PIN object from SmartCard: %s",
166 error("Unable to lock smartcard: %s", sc_strerror(r
));
169 if (sc_pin
!= NULL
) {
170 r
= sc_pkcs15_verify_pin(p15card
, pin
, sc_pin
,
174 error("PIN code verification failed: %s",
179 *key_obj_out
= key_obj
;
186 #define SC_USAGE_DECRYPT SC_PKCS15_PRKEY_USAGE_DECRYPT | \
187 SC_PKCS15_PRKEY_USAGE_UNWRAP
190 sc_private_decrypt(int flen
, u_char
*from
, u_char
*to
, RSA
*rsa
,
193 struct sc_pkcs15_object
*key_obj
;
196 if (padding
!= RSA_PKCS1_PADDING
)
198 r
= sc_prkey_op_init(rsa
, &key_obj
, SC_USAGE_DECRYPT
);
201 r
= sc_pkcs15_decipher(p15card
, key_obj
, SC_ALGORITHM_RSA_PAD_PKCS1
,
202 from
, flen
, to
, flen
);
205 error("sc_pkcs15_decipher() failed: %s", sc_strerror(r
));
214 #define SC_USAGE_SIGN SC_PKCS15_PRKEY_USAGE_SIGN | \
215 SC_PKCS15_PRKEY_USAGE_SIGNRECOVER
218 sc_sign(int type
, u_char
*m
, unsigned int m_len
,
219 unsigned char *sigret
, unsigned int *siglen
, RSA
*rsa
)
221 struct sc_pkcs15_object
*key_obj
;
223 unsigned long flags
= 0;
225 /* XXX: sc_prkey_op_init will search for a pkcs15 private
226 * key object with the sign or signrecover usage flag set.
227 * If the signing key has only the non-repudiation flag set
228 * the key will be rejected as using a non-repudiation key
229 * for authentication is not recommended. Note: This does not
230 * prevent the use of a non-repudiation key for authentication
231 * if the sign or signrecover flag is set as well.
233 r
= sc_prkey_op_init(rsa
, &key_obj
, SC_USAGE_SIGN
);
236 /* FIXME: length of sigret correct? */
237 /* FIXME: check 'type' and modify flags accordingly */
238 flags
= SC_ALGORITHM_RSA_PAD_PKCS1
| SC_ALGORITHM_RSA_HASH_SHA1
;
239 r
= sc_pkcs15_compute_signature(p15card
, key_obj
, flags
,
240 m
, m_len
, sigret
, RSA_size(rsa
));
243 error("sc_pkcs15_compute_signature() failed: %s",
255 sc_private_encrypt(int flen
, u_char
*from
, u_char
*to
, RSA
*rsa
,
258 error("Private key encryption not supported");
264 static int (*orig_finish
)(RSA
*rsa
) = NULL
;
269 struct sc_priv_data
*priv
;
271 priv
= RSA_get_app_data(rsa
);
273 if (priv
->ref_count
== 0) {
282 /* engine for overloading private key operations */
285 sc_get_rsa_method(void)
287 static RSA_METHOD smart_rsa
;
288 const RSA_METHOD
*def
= RSA_get_default_method();
290 /* use the OpenSSL version */
291 memcpy(&smart_rsa
, def
, sizeof(smart_rsa
));
293 smart_rsa
.name
= "opensc";
296 smart_rsa
.rsa_priv_enc
= sc_private_encrypt
;
297 smart_rsa
.rsa_priv_dec
= sc_private_decrypt
;
298 smart_rsa
.rsa_sign
= sc_sign
;
301 orig_finish
= def
->finish
;
302 smart_rsa
.finish
= sc_finish
;
311 static ENGINE
*smart_engine
= NULL
;
313 if ((smart_engine
= ENGINE_new()) == NULL
)
314 fatal("ENGINE_new failed");
316 ENGINE_set_id(smart_engine
, "opensc");
317 ENGINE_set_name(smart_engine
, "OpenSC");
319 ENGINE_set_RSA(smart_engine
, sc_get_rsa_method());
320 ENGINE_set_DSA(smart_engine
, DSA_get_default_openssl_method());
321 ENGINE_set_DH(smart_engine
, DH_get_default_openssl_method());
322 ENGINE_set_RAND(smart_engine
, RAND_SSLeay());
323 ENGINE_set_BN_mod_exp(smart_engine
, BN_mod_exp
);
330 convert_rsa_to_rsa1(Key
* in
, Key
* out
)
332 struct sc_priv_data
*priv
;
334 out
->rsa
->flags
= in
->rsa
->flags
;
335 out
->flags
= in
->flags
;
336 RSA_set_method(out
->rsa
, RSA_get_method(in
->rsa
));
337 BN_copy(out
->rsa
->n
, in
->rsa
->n
);
338 BN_copy(out
->rsa
->e
, in
->rsa
->e
);
339 priv
= RSA_get_app_data(in
->rsa
);
341 RSA_set_app_data(out
->rsa
, priv
);
346 sc_read_pubkey(Key
* k
, const struct sc_pkcs15_object
*cert_obj
)
349 sc_pkcs15_cert_t
*cert
= NULL
;
350 struct sc_priv_data
*priv
= NULL
;
351 sc_pkcs15_cert_info_t
*cinfo
= cert_obj
->data
;
354 EVP_PKEY
*pubkey
= NULL
;
358 debug("sc_read_pubkey() with cert id %02X", cinfo
->id
.value
[0]);
359 r
= sc_pkcs15_read_certificate(p15card
, cinfo
, &cert
);
361 logit("Certificate read failed: %s", sc_strerror(r
));
370 if (!d2i_X509(&x509
, &p
, cert
->data_len
)) {
371 logit("Unable to parse X.509 certificate");
375 sc_pkcs15_free_certificate(cert
);
377 pubkey
= X509_get_pubkey(x509
);
380 if (pubkey
->type
!= EVP_PKEY_RSA
) {
381 logit("Public key is of unknown type");
385 k
->rsa
= EVP_PKEY_get1_RSA(pubkey
);
386 EVP_PKEY_free(pubkey
);
388 k
->rsa
->flags
|= RSA_FLAG_SIGN_VER
;
389 RSA_set_method(k
->rsa
, sc_get_rsa_method());
390 priv
= xmalloc(sizeof(struct sc_priv_data
));
391 priv
->cert_id
= cinfo
->id
;
393 RSA_set_app_data(k
->rsa
, priv
);
395 k
->flags
= KEY_FLAG_EXT
;
396 tmp
= key_fingerprint(k
, SSH_FP_MD5
, SSH_FP_HEX
);
397 debug("fingerprint %d %s", key_size(k
), tmp
);
403 sc_pkcs15_free_certificate(cert
);
405 EVP_PKEY_free(pubkey
);
412 sc_get_keys(const char *id
, const char *pin
)
415 int i
, r
, real_count
= 0, key_count
;
416 sc_pkcs15_id_t cert_id
;
417 sc_pkcs15_object_t
*certs
[32];
418 char *buf
= xstrdup(id
), *p
;
420 debug("sc_get_keys called: id = %s", id
);
424 sc_pin
= (pin
== NULL
) ? NULL
: xstrdup(pin
);
427 if ((p
= strchr(buf
, ':')) != NULL
) {
430 sc_pkcs15_hex_string_to_id(p
, &cert_id
);
432 r
= sscanf(buf
, "%d", &sc_reader_id
);
436 if (p15card
== NULL
) {
440 error("Smartcard init failed: %s", sc_strerror(r
));
445 r
= sc_pkcs15_find_cert_by_id(p15card
, &cert_id
, &certs
[0]);
450 r
= sc_pkcs15_get_objects(p15card
, SC_PKCS15_TYPE_CERT_X509
,
453 logit("No certificates found on smartcard");
457 error("Certificate enumeration failed: %s",
463 if (key_count
> 1024)
464 fatal("Too many keys (%u), expected <= 1024", key_count
);
465 keys
= xcalloc(key_count
* 2 + 1, sizeof(Key
*));
466 for (i
= 0; i
< key_count
; i
++) {
467 sc_pkcs15_object_t
*tmp_obj
= NULL
;
468 cert_id
= ((sc_pkcs15_cert_info_t
*)(certs
[i
]->data
))->id
;
469 if (sc_pkcs15_find_prkey_by_id(p15card
, &cert_id
, &tmp_obj
))
470 /* skip the public key (certificate) if no
471 * corresponding private key is present */
473 k
= key_new(KEY_RSA
);
476 r
= sc_read_pubkey(k
, certs
[i
]);
478 error("sc_read_pubkey failed: %s", sc_strerror(r
));
482 keys
[real_count
] = k
;
484 k
= key_new(KEY_RSA1
);
487 convert_rsa_to_rsa1(keys
[real_count
-1], k
);
488 keys
[real_count
] = k
;
491 keys
[real_count
] = NULL
;
500 sc_put_key(Key
*prv
, const char *id
)
502 error("key uploading not yet supported");
507 sc_get_key_label(Key
*key
)
510 const struct sc_priv_data
*priv
;
511 struct sc_pkcs15_object
*key_obj
;
513 priv
= (const struct sc_priv_data
*) RSA_get_app_data(key
->rsa
);
514 if (priv
== NULL
|| p15card
== NULL
) {
515 logit("SmartCard key not loaded");
516 /* internal error => return default label */
517 return xstrdup("smartcard key");
519 r
= sc_pkcs15_find_prkey_by_id(p15card
, &priv
->cert_id
, &key_obj
);
521 logit("Unable to find private key from SmartCard: %s",
523 return xstrdup("smartcard key");
525 if (key_obj
== NULL
|| key_obj
->label
== NULL
)
526 /* the optional PKCS#15 label does not exists
527 * => return the default label */
528 return xstrdup("smartcard key");
529 return xstrdup(key_obj
->label
);
532 #endif /* SMARTCARD */