summaryrefslogtreecommitdiff
path: root/ssh-pkcs11.c
diff options
context:
space:
mode:
Diffstat (limited to 'ssh-pkcs11.c')
-rw-r--r--ssh-pkcs11.c121
1 files changed, 95 insertions, 26 deletions
diff --git a/ssh-pkcs11.c b/ssh-pkcs11.c
index 036ee8115..384ac1edb 100644
--- a/ssh-pkcs11.c
+++ b/ssh-pkcs11.c
@@ -1,4 +1,4 @@
1/* $OpenBSD: ssh-pkcs11.c,v 1.39 2019/01/21 02:05:38 djm Exp $ */ 1/* $OpenBSD: ssh-pkcs11.c,v 1.40 2019/01/22 12:00:50 djm Exp $ */
2/* 2/*
3 * Copyright (c) 2010 Markus Friedl. All rights reserved. 3 * Copyright (c) 2010 Markus Friedl. All rights reserved.
4 * Copyright (c) 2014 Pedro Martelletto. All rights reserved. 4 * Copyright (c) 2014 Pedro Martelletto. All rights reserved.
@@ -240,6 +240,85 @@ pkcs11_find(struct pkcs11_provider *p, CK_ULONG slotidx, CK_ATTRIBUTE *attr,
240} 240}
241 241
242static int 242static int
243pkcs11_login(struct pkcs11_key *k11, CK_USER_TYPE type)
244{
245 struct pkcs11_slotinfo *si;
246 CK_FUNCTION_LIST *f;
247 char *pin = NULL, prompt[1024];
248 CK_RV rv;
249
250 if (!k11->provider || !k11->provider->valid) {
251 error("no pkcs11 (valid) provider found");
252 return (-1);
253 }
254
255 f = k11->provider->function_list;
256 si = &k11->provider->slotinfo[k11->slotidx];
257
258 if (!pkcs11_interactive) {
259 error("need pin entry%s",
260 (si->token.flags & CKF_PROTECTED_AUTHENTICATION_PATH) ?
261 " on reader keypad" : "");
262 return (-1);
263 }
264 if (si->token.flags & CKF_PROTECTED_AUTHENTICATION_PATH)
265 verbose("Deferring PIN entry to reader keypad.");
266 else {
267 snprintf(prompt, sizeof(prompt), "Enter PIN for '%s': ",
268 si->token.label);
269 if ((pin = read_passphrase(prompt, RP_ALLOW_EOF)) == NULL) {
270 debug("%s: no pin specified", __func__);
271 return (-1); /* bail out */
272 }
273 }
274 rv = f->C_Login(si->session, type, (u_char *)pin,
275 (pin != NULL) ? strlen(pin) : 0);
276 if (pin != NULL)
277 freezero(pin, strlen(pin));
278 if (rv != CKR_OK && rv != CKR_USER_ALREADY_LOGGED_IN) {
279 error("C_Login failed: %lu", rv);
280 return (-1);
281 }
282 si->logged_in = 1;
283 return (0);
284}
285
286static int
287pkcs11_check_obj_bool_attrib(struct pkcs11_key *k11, CK_OBJECT_HANDLE obj,
288 CK_ATTRIBUTE_TYPE type, int *val)
289{
290 struct pkcs11_slotinfo *si;
291 CK_FUNCTION_LIST *f;
292 CK_BBOOL flag = 0;
293 CK_ATTRIBUTE attr;
294 CK_RV rv;
295
296 *val = 0;
297
298 if (!k11->provider || !k11->provider->valid) {
299 error("no pkcs11 (valid) provider found");
300 return (-1);
301 }
302
303 f = k11->provider->function_list;
304 si = &k11->provider->slotinfo[k11->slotidx];
305
306 attr.type = type;
307 attr.pValue = &flag;
308 attr.ulValueLen = sizeof(flag);
309
310 rv = f->C_GetAttributeValue(si->session, obj, &attr, 1);
311 if (rv != CKR_OK) {
312 error("C_GetAttributeValue failed: %lu", rv);
313 return (-1);
314 }
315 *val = flag != 0;
316 debug("%s: provider %p slot %lu object %lu: attrib %lu = %d",
317 __func__, k11->provider, k11->slotidx, obj, type, *val);
318 return (0);
319}
320
321static int
243pkcs11_get_key(struct pkcs11_key *k11, CK_MECHANISM_TYPE mech_type) 322pkcs11_get_key(struct pkcs11_key *k11, CK_MECHANISM_TYPE mech_type)
244{ 323{
245 struct pkcs11_slotinfo *si; 324 struct pkcs11_slotinfo *si;
@@ -250,7 +329,8 @@ pkcs11_get_key(struct pkcs11_key *k11, CK_MECHANISM_TYPE mech_type)
250 CK_BBOOL true_val; 329 CK_BBOOL true_val;
251 CK_MECHANISM mech; 330 CK_MECHANISM mech;
252 CK_ATTRIBUTE key_filter[3]; 331 CK_ATTRIBUTE key_filter[3];
253 char *pin = NULL, prompt[1024]; 332 int always_auth = 0;
333 int did_login = 0;
254 334
255 if (!k11->provider || !k11->provider->valid) { 335 if (!k11->provider || !k11->provider->valid) {
256 error("no pkcs11 (valid) provider found"); 336 error("no pkcs11 (valid) provider found");
@@ -261,32 +341,11 @@ pkcs11_get_key(struct pkcs11_key *k11, CK_MECHANISM_TYPE mech_type)
261 si = &k11->provider->slotinfo[k11->slotidx]; 341 si = &k11->provider->slotinfo[k11->slotidx];
262 342
263 if ((si->token.flags & CKF_LOGIN_REQUIRED) && !si->logged_in) { 343 if ((si->token.flags & CKF_LOGIN_REQUIRED) && !si->logged_in) {
264 if (!pkcs11_interactive) { 344 if (pkcs11_login(k11, CKU_USER) < 0) {
265 error("need pin entry%s", (si->token.flags & 345 error("login failed");
266 CKF_PROTECTED_AUTHENTICATION_PATH) ?
267 " on reader keypad" : "");
268 return (-1);
269 }
270 if (si->token.flags & CKF_PROTECTED_AUTHENTICATION_PATH)
271 verbose("Deferring PIN entry to reader keypad.");
272 else {
273 snprintf(prompt, sizeof(prompt),
274 "Enter PIN for '%s': ", si->token.label);
275 pin = read_passphrase(prompt, RP_ALLOW_EOF);
276 if (pin == NULL)
277 return (-1); /* bail out */
278 }
279 rv = f->C_Login(si->session, CKU_USER, (u_char *)pin,
280 (pin != NULL) ? strlen(pin) : 0);
281 if (pin != NULL) {
282 explicit_bzero(pin, strlen(pin));
283 free(pin);
284 }
285 if (rv != CKR_OK && rv != CKR_USER_ALREADY_LOGGED_IN) {
286 error("C_Login failed: %lu", rv);
287 return (-1); 346 return (-1);
288 } 347 }
289 si->logged_in = 1; 348 did_login = 1;
290 } 349 }
291 350
292 memset(&key_filter, 0, sizeof(key_filter)); 351 memset(&key_filter, 0, sizeof(key_filter));
@@ -321,6 +380,16 @@ pkcs11_get_key(struct pkcs11_key *k11, CK_MECHANISM_TYPE mech_type)
321 return (-1); 380 return (-1);
322 } 381 }
323 382
383 pkcs11_check_obj_bool_attrib(k11, obj, CKA_ALWAYS_AUTHENTICATE,
384 &always_auth); /* ignore errors here */
385 if (always_auth && !did_login) {
386 debug("%s: always-auth key", __func__);
387 if (pkcs11_login(k11, CKU_CONTEXT_SPECIFIC) < 0) {
388 error("login failed for always-auth key");
389 return (-1);
390 }
391 }
392
324 return (0); 393 return (0);
325} 394}
326 395