diff options
Diffstat (limited to 'scard-opensc.c')
-rw-r--r-- | scard-opensc.c | 85 |
1 files changed, 74 insertions, 11 deletions
diff --git a/scard-opensc.c b/scard-opensc.c index dd21de39a..2489fec45 100644 --- a/scard-opensc.c +++ b/scard-opensc.c | |||
@@ -89,6 +89,12 @@ sc_init(void) | |||
89 | r = sc_establish_context(&ctx, "openssh"); | 89 | r = sc_establish_context(&ctx, "openssh"); |
90 | if (r) | 90 | if (r) |
91 | goto err; | 91 | goto err; |
92 | if (sc_reader_id >= ctx->reader_count) { | ||
93 | r = SC_ERROR_NO_READERS_FOUND; | ||
94 | error("Illegal reader number %d (max %d)", sc_reader_id, | ||
95 | ctx->reader_count -1); | ||
96 | goto err; | ||
97 | } | ||
92 | r = sc_connect_card(ctx->reader[sc_reader_id], 0, &card); | 98 | r = sc_connect_card(ctx->reader[sc_reader_id], 0, &card); |
93 | if (r) | 99 | if (r) |
94 | goto err; | 100 | goto err; |
@@ -104,7 +110,8 @@ err: | |||
104 | /* private key operations */ | 110 | /* private key operations */ |
105 | 111 | ||
106 | static int | 112 | static int |
107 | sc_prkey_op_init(RSA *rsa, struct sc_pkcs15_object **key_obj_out) | 113 | sc_prkey_op_init(RSA *rsa, struct sc_pkcs15_object **key_obj_out, |
114 | unsigned int usage) | ||
108 | { | 115 | { |
109 | int r; | 116 | int r; |
110 | struct sc_priv_data *priv; | 117 | struct sc_priv_data *priv; |
@@ -124,7 +131,8 @@ sc_prkey_op_init(RSA *rsa, struct sc_pkcs15_object **key_obj_out) | |||
124 | goto err; | 131 | goto err; |
125 | } | 132 | } |
126 | } | 133 | } |
127 | r = sc_pkcs15_find_prkey_by_id(p15card, &priv->cert_id, &key_obj); | 134 | r = sc_pkcs15_find_prkey_by_id_usage(p15card, &priv->cert_id, |
135 | usage, &key_obj); | ||
128 | if (r) { | 136 | if (r) { |
129 | error("Unable to find private key from SmartCard: %s", | 137 | error("Unable to find private key from SmartCard: %s", |
130 | sc_strerror(r)); | 138 | sc_strerror(r)); |
@@ -133,7 +141,16 @@ sc_prkey_op_init(RSA *rsa, struct sc_pkcs15_object **key_obj_out) | |||
133 | key = key_obj->data; | 141 | key = key_obj->data; |
134 | r = sc_pkcs15_find_pin_by_auth_id(p15card, &key_obj->auth_id, | 142 | r = sc_pkcs15_find_pin_by_auth_id(p15card, &key_obj->auth_id, |
135 | &pin_obj); | 143 | &pin_obj); |
136 | if (r) { | 144 | if (r == SC_ERROR_OBJECT_NOT_FOUND) { |
145 | /* no pin required */ | ||
146 | r = sc_lock(card); | ||
147 | if (r) { | ||
148 | error("Unable to lock smartcard: %s", sc_strerror(r)); | ||
149 | goto err; | ||
150 | } | ||
151 | *key_obj_out = key_obj; | ||
152 | return 0; | ||
153 | } else if (r) { | ||
137 | error("Unable to find PIN object from SmartCard: %s", | 154 | error("Unable to find PIN object from SmartCard: %s", |
138 | sc_strerror(r)); | 155 | sc_strerror(r)); |
139 | goto err; | 156 | goto err; |
@@ -161,6 +178,9 @@ err: | |||
161 | return -1; | 178 | return -1; |
162 | } | 179 | } |
163 | 180 | ||
181 | #define SC_USAGE_DECRYPT SC_PKCS15_PRKEY_USAGE_DECRYPT | \ | ||
182 | SC_PKCS15_PRKEY_USAGE_UNWRAP | ||
183 | |||
164 | static int | 184 | static int |
165 | sc_private_decrypt(int flen, u_char *from, u_char *to, RSA *rsa, | 185 | sc_private_decrypt(int flen, u_char *from, u_char *to, RSA *rsa, |
166 | int padding) | 186 | int padding) |
@@ -170,10 +190,11 @@ sc_private_decrypt(int flen, u_char *from, u_char *to, RSA *rsa, | |||
170 | 190 | ||
171 | if (padding != RSA_PKCS1_PADDING) | 191 | if (padding != RSA_PKCS1_PADDING) |
172 | return -1; | 192 | return -1; |
173 | r = sc_prkey_op_init(rsa, &key_obj); | 193 | r = sc_prkey_op_init(rsa, &key_obj, SC_USAGE_DECRYPT); |
174 | if (r) | 194 | if (r) |
175 | return -1; | 195 | return -1; |
176 | r = sc_pkcs15_decipher(p15card, key_obj, 0, from, flen, to, flen); | 196 | r = sc_pkcs15_decipher(p15card, key_obj, SC_ALGORITHM_RSA_PAD_PKCS1, |
197 | from, flen, to, flen); | ||
177 | sc_unlock(card); | 198 | sc_unlock(card); |
178 | if (r < 0) { | 199 | if (r < 0) { |
179 | error("sc_pkcs15_decipher() failed: %s", sc_strerror(r)); | 200 | error("sc_pkcs15_decipher() failed: %s", sc_strerror(r)); |
@@ -185,6 +206,9 @@ err: | |||
185 | return -1; | 206 | return -1; |
186 | } | 207 | } |
187 | 208 | ||
209 | #define SC_USAGE_SIGN SC_PKCS15_PRKEY_USAGE_SIGN | \ | ||
210 | SC_PKCS15_PRKEY_USAGE_SIGNRECOVER | ||
211 | |||
188 | static int | 212 | static int |
189 | sc_sign(int type, u_char *m, unsigned int m_len, | 213 | sc_sign(int type, u_char *m, unsigned int m_len, |
190 | unsigned char *sigret, unsigned int *siglen, RSA *rsa) | 214 | unsigned char *sigret, unsigned int *siglen, RSA *rsa) |
@@ -193,7 +217,15 @@ sc_sign(int type, u_char *m, unsigned int m_len, | |||
193 | int r; | 217 | int r; |
194 | unsigned long flags = 0; | 218 | unsigned long flags = 0; |
195 | 219 | ||
196 | r = sc_prkey_op_init(rsa, &key_obj); | 220 | /* XXX: sc_prkey_op_init will search for a pkcs15 private |
221 | * key object with the sign or signrecover usage flag set. | ||
222 | * If the signing key has only the non-repudiation flag set | ||
223 | * the key will be rejected as using a non-repudiation key | ||
224 | * for authentication is not recommended. Note: This does not | ||
225 | * prevent the use of a non-repudiation key for authentication | ||
226 | * if the sign or signrecover flag is set as well. | ||
227 | */ | ||
228 | r = sc_prkey_op_init(rsa, &key_obj, SC_USAGE_SIGN); | ||
197 | if (r) | 229 | if (r) |
198 | return -1; | 230 | return -1; |
199 | /* FIXME: length of sigret correct? */ | 231 | /* FIXME: length of sigret correct? */ |
@@ -321,7 +353,7 @@ sc_read_pubkey(Key * k, const struct sc_pkcs15_object *cert_obj) | |||
321 | debug("sc_read_pubkey() with cert id %02X", cinfo->id.value[0]); | 353 | debug("sc_read_pubkey() with cert id %02X", cinfo->id.value[0]); |
322 | r = sc_pkcs15_read_certificate(p15card, cinfo, &cert); | 354 | r = sc_pkcs15_read_certificate(p15card, cinfo, &cert); |
323 | if (r) { | 355 | if (r) { |
324 | log("Certificate read failed: %s", sc_strerror(r)); | 356 | logit("Certificate read failed: %s", sc_strerror(r)); |
325 | goto err; | 357 | goto err; |
326 | } | 358 | } |
327 | x509 = X509_new(); | 359 | x509 = X509_new(); |
@@ -331,7 +363,7 @@ sc_read_pubkey(Key * k, const struct sc_pkcs15_object *cert_obj) | |||
331 | } | 363 | } |
332 | p = cert->data; | 364 | p = cert->data; |
333 | if (!d2i_X509(&x509, &p, cert->data_len)) { | 365 | if (!d2i_X509(&x509, &p, cert->data_len)) { |
334 | log("Unable to parse X.509 certificate"); | 366 | logit("Unable to parse X.509 certificate"); |
335 | r = -1; | 367 | r = -1; |
336 | goto err; | 368 | goto err; |
337 | } | 369 | } |
@@ -341,7 +373,7 @@ sc_read_pubkey(Key * k, const struct sc_pkcs15_object *cert_obj) | |||
341 | X509_free(x509); | 373 | X509_free(x509); |
342 | x509 = NULL; | 374 | x509 = NULL; |
343 | if (pubkey->type != EVP_PKEY_RSA) { | 375 | if (pubkey->type != EVP_PKEY_RSA) { |
344 | log("Public key is of unknown type"); | 376 | logit("Public key is of unknown type"); |
345 | r = -1; | 377 | r = -1; |
346 | goto err; | 378 | goto err; |
347 | } | 379 | } |
@@ -413,7 +445,7 @@ sc_get_keys(const char *id, const char *pin) | |||
413 | r = sc_pkcs15_get_objects(p15card, SC_PKCS15_TYPE_CERT_X509, | 445 | r = sc_pkcs15_get_objects(p15card, SC_PKCS15_TYPE_CERT_X509, |
414 | certs, 32); | 446 | certs, 32); |
415 | if (r == 0) { | 447 | if (r == 0) { |
416 | log("No certificates found on smartcard"); | 448 | logit("No certificates found on smartcard"); |
417 | r = -1; | 449 | r = -1; |
418 | goto err; | 450 | goto err; |
419 | } else if (r < 0) { | 451 | } else if (r < 0) { |
@@ -423,9 +455,14 @@ sc_get_keys(const char *id, const char *pin) | |||
423 | } | 455 | } |
424 | key_count = r; | 456 | key_count = r; |
425 | } | 457 | } |
426 | /* FIXME: only keep entries with a corresponding private key */ | ||
427 | keys = xmalloc(sizeof(Key *) * (key_count*2+1)); | 458 | keys = xmalloc(sizeof(Key *) * (key_count*2+1)); |
428 | for (i = 0; i < key_count; i++) { | 459 | for (i = 0; i < key_count; i++) { |
460 | sc_pkcs15_object_t *tmp_obj = NULL; | ||
461 | cert_id = ((sc_pkcs15_cert_info_t *)(certs[i]->data))->id; | ||
462 | if (sc_pkcs15_find_prkey_by_id(p15card, &cert_id, &tmp_obj)) | ||
463 | /* skip the public key (certificate) if no | ||
464 | * corresponding private key is present */ | ||
465 | continue; | ||
429 | k = key_new(KEY_RSA); | 466 | k = key_new(KEY_RSA); |
430 | if (k == NULL) | 467 | if (k == NULL) |
431 | break; | 468 | break; |
@@ -459,4 +496,30 @@ sc_put_key(Key *prv, const char *id) | |||
459 | return -1; | 496 | return -1; |
460 | } | 497 | } |
461 | 498 | ||
499 | char * | ||
500 | sc_get_key_label(Key *key) | ||
501 | { | ||
502 | int r; | ||
503 | const struct sc_priv_data *priv; | ||
504 | struct sc_pkcs15_object *key_obj; | ||
505 | |||
506 | priv = (const struct sc_priv_data *) RSA_get_app_data(key->rsa); | ||
507 | if (priv == NULL || p15card == NULL) { | ||
508 | logit("SmartCard key not loaded"); | ||
509 | /* internal error => return default label */ | ||
510 | return xstrdup("smartcard key"); | ||
511 | } | ||
512 | r = sc_pkcs15_find_prkey_by_id(p15card, &priv->cert_id, &key_obj); | ||
513 | if (r) { | ||
514 | logit("Unable to find private key from SmartCard: %s", | ||
515 | sc_strerror(r)); | ||
516 | return xstrdup("smartcard key"); | ||
517 | } | ||
518 | if (key_obj == NULL || key_obj->label == NULL) | ||
519 | /* the optional PKCS#15 label does not exists | ||
520 | * => return the default label */ | ||
521 | return xstrdup("smartcard key"); | ||
522 | return xstrdup(key_obj->label); | ||
523 | } | ||
524 | |||
462 | #endif /* SMARTCARD */ | 525 | #endif /* SMARTCARD */ |