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>
36 #include <opensc/opensc.h>
37 #include <opensc/pkcs15.h>
45 #if OPENSSL_VERSION_NUMBER < 0x00907000L && defined(CRYPTO_LOCK_ENGINE)
47 #define RSA_get_default_method RSA_get_default_openssl_method
52 #include <openssl/engine.h>
53 #define sc_get_rsa sc_get_engine
55 #define sc_get_rsa sc_get_rsa_method
58 static int sc_reader_id
;
59 static sc_context_t
*ctx
= NULL
;
60 static sc_card_t
*card
= NULL
;
61 static sc_pkcs15_card_t
*p15card
= NULL
;
63 static char *sc_pin
= NULL
;
67 struct sc_pkcs15_id cert_id
;
75 sc_pkcs15_unbind(p15card
);
79 sc_disconnect_card(card
, 0);
83 sc_release_context(ctx
);
93 r
= sc_establish_context(&ctx
, "openssh");
96 if (sc_reader_id
>= ctx
->reader_count
) {
97 r
= SC_ERROR_NO_READERS_FOUND
;
98 error("Illegal reader number %d (max %d)", sc_reader_id
,
99 ctx
->reader_count
-1);
102 r
= sc_connect_card(ctx
->reader
[sc_reader_id
], 0, &card
);
105 r
= sc_pkcs15_bind(card
, &p15card
);
114 /* private key operations */
117 sc_prkey_op_init(RSA
*rsa
, struct sc_pkcs15_object
**key_obj_out
,
121 struct sc_priv_data
*priv
;
122 struct sc_pkcs15_object
*key_obj
;
123 struct sc_pkcs15_prkey_info
*key
;
124 struct sc_pkcs15_object
*pin_obj
;
125 struct sc_pkcs15_pin_info
*pin
;
127 priv
= (struct sc_priv_data
*) RSA_get_app_data(rsa
);
130 if (p15card
== NULL
) {
134 error("SmartCard init failed: %s", sc_strerror(r
));
138 r
= sc_pkcs15_find_prkey_by_id_usage(p15card
, &priv
->cert_id
,
141 error("Unable to find private key from SmartCard: %s",
146 r
= sc_pkcs15_find_pin_by_auth_id(p15card
, &key_obj
->auth_id
,
148 if (r
== SC_ERROR_OBJECT_NOT_FOUND
) {
149 /* no pin required */
152 error("Unable to lock smartcard: %s", sc_strerror(r
));
155 *key_obj_out
= key_obj
;
158 error("Unable to find PIN object from SmartCard: %s",
165 error("Unable to lock smartcard: %s", sc_strerror(r
));
168 if (sc_pin
!= NULL
) {
169 r
= sc_pkcs15_verify_pin(p15card
, pin
, sc_pin
,
173 error("PIN code verification failed: %s",
178 *key_obj_out
= key_obj
;
185 #define SC_USAGE_DECRYPT SC_PKCS15_PRKEY_USAGE_DECRYPT | \
186 SC_PKCS15_PRKEY_USAGE_UNWRAP
189 sc_private_decrypt(int flen
, u_char
*from
, u_char
*to
, RSA
*rsa
,
192 struct sc_pkcs15_object
*key_obj
;
195 if (padding
!= RSA_PKCS1_PADDING
)
197 r
= sc_prkey_op_init(rsa
, &key_obj
, SC_USAGE_DECRYPT
);
200 r
= sc_pkcs15_decipher(p15card
, key_obj
, SC_ALGORITHM_RSA_PAD_PKCS1
,
201 from
, flen
, to
, flen
);
204 error("sc_pkcs15_decipher() failed: %s", sc_strerror(r
));
213 #define SC_USAGE_SIGN SC_PKCS15_PRKEY_USAGE_SIGN | \
214 SC_PKCS15_PRKEY_USAGE_SIGNRECOVER
217 sc_sign(int type
, u_char
*m
, unsigned int m_len
,
218 unsigned char *sigret
, unsigned int *siglen
, RSA
*rsa
)
220 struct sc_pkcs15_object
*key_obj
;
222 unsigned long flags
= 0;
224 /* XXX: sc_prkey_op_init will search for a pkcs15 private
225 * key object with the sign or signrecover usage flag set.
226 * If the signing key has only the non-repudiation flag set
227 * the key will be rejected as using a non-repudiation key
228 * for authentication is not recommended. Note: This does not
229 * prevent the use of a non-repudiation key for authentication
230 * if the sign or signrecover flag is set as well.
232 r
= sc_prkey_op_init(rsa
, &key_obj
, SC_USAGE_SIGN
);
235 /* FIXME: length of sigret correct? */
236 /* FIXME: check 'type' and modify flags accordingly */
237 flags
= SC_ALGORITHM_RSA_PAD_PKCS1
| SC_ALGORITHM_RSA_HASH_SHA1
;
238 r
= sc_pkcs15_compute_signature(p15card
, key_obj
, flags
,
239 m
, m_len
, sigret
, RSA_size(rsa
));
242 error("sc_pkcs15_compute_signature() failed: %s",
254 sc_private_encrypt(int flen
, u_char
*from
, u_char
*to
, RSA
*rsa
,
257 error("Private key encryption not supported");
263 static int (*orig_finish
)(RSA
*rsa
) = NULL
;
268 struct sc_priv_data
*priv
;
270 priv
= RSA_get_app_data(rsa
);
272 if (priv
->ref_count
== 0) {
281 /* engine for overloading private key operations */
284 sc_get_rsa_method(void)
286 static RSA_METHOD smart_rsa
;
287 const RSA_METHOD
*def
= RSA_get_default_method();
289 /* use the OpenSSL version */
290 memcpy(&smart_rsa
, def
, sizeof(smart_rsa
));
292 smart_rsa
.name
= "opensc";
295 smart_rsa
.rsa_priv_enc
= sc_private_encrypt
;
296 smart_rsa
.rsa_priv_dec
= sc_private_decrypt
;
297 smart_rsa
.rsa_sign
= sc_sign
;
300 orig_finish
= def
->finish
;
301 smart_rsa
.finish
= sc_finish
;
310 static ENGINE
*smart_engine
= NULL
;
312 if ((smart_engine
= ENGINE_new()) == NULL
)
313 fatal("ENGINE_new failed");
315 ENGINE_set_id(smart_engine
, "opensc");
316 ENGINE_set_name(smart_engine
, "OpenSC");
318 ENGINE_set_RSA(smart_engine
, sc_get_rsa_method());
319 ENGINE_set_DSA(smart_engine
, DSA_get_default_openssl_method());
320 ENGINE_set_DH(smart_engine
, DH_get_default_openssl_method());
321 ENGINE_set_RAND(smart_engine
, RAND_SSLeay());
322 ENGINE_set_BN_mod_exp(smart_engine
, BN_mod_exp
);
329 convert_rsa_to_rsa1(Key
* in
, Key
* out
)
331 struct sc_priv_data
*priv
;
333 out
->rsa
->flags
= in
->rsa
->flags
;
334 out
->flags
= in
->flags
;
335 RSA_set_method(out
->rsa
, RSA_get_method(in
->rsa
));
336 BN_copy(out
->rsa
->n
, in
->rsa
->n
);
337 BN_copy(out
->rsa
->e
, in
->rsa
->e
);
338 priv
= RSA_get_app_data(in
->rsa
);
340 RSA_set_app_data(out
->rsa
, priv
);
345 sc_read_pubkey(Key
* k
, const struct sc_pkcs15_object
*cert_obj
)
348 sc_pkcs15_cert_t
*cert
= NULL
;
349 struct sc_priv_data
*priv
= NULL
;
350 sc_pkcs15_cert_info_t
*cinfo
= cert_obj
->data
;
353 EVP_PKEY
*pubkey
= NULL
;
357 debug("sc_read_pubkey() with cert id %02X", cinfo
->id
.value
[0]);
358 r
= sc_pkcs15_read_certificate(p15card
, cinfo
, &cert
);
360 logit("Certificate read failed: %s", sc_strerror(r
));
369 if (!d2i_X509(&x509
, &p
, cert
->data_len
)) {
370 logit("Unable to parse X.509 certificate");
374 sc_pkcs15_free_certificate(cert
);
376 pubkey
= X509_get_pubkey(x509
);
379 if (pubkey
->type
!= EVP_PKEY_RSA
) {
380 logit("Public key is of unknown type");
384 k
->rsa
= EVP_PKEY_get1_RSA(pubkey
);
385 EVP_PKEY_free(pubkey
);
387 k
->rsa
->flags
|= RSA_FLAG_SIGN_VER
;
388 RSA_set_method(k
->rsa
, sc_get_rsa_method());
389 priv
= xmalloc(sizeof(struct sc_priv_data
));
390 priv
->cert_id
= cinfo
->id
;
392 RSA_set_app_data(k
->rsa
, priv
);
394 k
->flags
= KEY_FLAG_EXT
;
395 tmp
= key_fingerprint(k
, SSH_FP_MD5
, SSH_FP_HEX
);
396 debug("fingerprint %d %s", key_size(k
), tmp
);
402 sc_pkcs15_free_certificate(cert
);
404 EVP_PKEY_free(pubkey
);
411 sc_get_keys(const char *id
, const char *pin
)
414 int i
, r
, real_count
= 0, key_count
;
415 sc_pkcs15_id_t cert_id
;
416 sc_pkcs15_object_t
*certs
[32];
417 char *buf
= xstrdup(id
), *p
;
419 debug("sc_get_keys called: id = %s", id
);
423 sc_pin
= (pin
== NULL
) ? NULL
: xstrdup(pin
);
426 if ((p
= strchr(buf
, ':')) != NULL
) {
429 sc_pkcs15_hex_string_to_id(p
, &cert_id
);
431 r
= sscanf(buf
, "%d", &sc_reader_id
);
435 if (p15card
== NULL
) {
439 error("Smartcard init failed: %s", sc_strerror(r
));
444 r
= sc_pkcs15_find_cert_by_id(p15card
, &cert_id
, &certs
[0]);
449 r
= sc_pkcs15_get_objects(p15card
, SC_PKCS15_TYPE_CERT_X509
,
452 logit("No certificates found on smartcard");
456 error("Certificate enumeration failed: %s",
462 if (key_count
> 1024)
463 fatal("Too many keys (%u), expected <= 1024", key_count
);
464 keys
= xcalloc(key_count
* 2 + 1, sizeof(Key
*));
465 for (i
= 0; i
< key_count
; i
++) {
466 sc_pkcs15_object_t
*tmp_obj
= NULL
;
467 cert_id
= ((sc_pkcs15_cert_info_t
*)(certs
[i
]->data
))->id
;
468 if (sc_pkcs15_find_prkey_by_id(p15card
, &cert_id
, &tmp_obj
))
469 /* skip the public key (certificate) if no
470 * corresponding private key is present */
472 k
= key_new(KEY_RSA
);
475 r
= sc_read_pubkey(k
, certs
[i
]);
477 error("sc_read_pubkey failed: %s", sc_strerror(r
));
481 keys
[real_count
] = k
;
483 k
= key_new(KEY_RSA1
);
486 convert_rsa_to_rsa1(keys
[real_count
-1], k
);
487 keys
[real_count
] = k
;
490 keys
[real_count
] = NULL
;
499 sc_put_key(Key
*prv
, const char *id
)
501 error("key uploading not yet supported");
506 sc_get_key_label(Key
*key
)
509 const struct sc_priv_data
*priv
;
510 struct sc_pkcs15_object
*key_obj
;
512 priv
= (const struct sc_priv_data
*) RSA_get_app_data(key
->rsa
);
513 if (priv
== NULL
|| p15card
== NULL
) {
514 logit("SmartCard key not loaded");
515 /* internal error => return default label */
516 return xstrdup("smartcard key");
518 r
= sc_pkcs15_find_prkey_by_id(p15card
, &priv
->cert_id
, &key_obj
);
520 logit("Unable to find private key from SmartCard: %s",
522 return xstrdup("smartcard key");
524 if (key_obj
== NULL
|| key_obj
->label
== NULL
)
525 /* the optional PKCS#15 label does not exists
526 * => return the default label */
527 return xstrdup("smartcard key");
528 return xstrdup(key_obj
->label
);
531 #endif /* SMARTCARD */