summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ssh-pkcs11.c34
1 files changed, 22 insertions, 12 deletions
diff --git a/ssh-pkcs11.c b/ssh-pkcs11.c
index 384ac1edb..f116e4051 100644
--- a/ssh-pkcs11.c
+++ b/ssh-pkcs11.c
@@ -1,4 +1,4 @@
1/* $OpenBSD: ssh-pkcs11.c,v 1.40 2019/01/22 12:00:50 djm Exp $ */ 1/* $OpenBSD: ssh-pkcs11.c,v 1.41 2019/01/22 12:03:58 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.
@@ -620,26 +620,36 @@ static int
620pkcs11_open_session(struct pkcs11_provider *p, CK_ULONG slotidx, char *pin, 620pkcs11_open_session(struct pkcs11_provider *p, CK_ULONG slotidx, char *pin,
621 CK_ULONG user) 621 CK_ULONG user)
622{ 622{
623 CK_RV rv; 623 struct pkcs11_slotinfo *si;
624 CK_FUNCTION_LIST *f; 624 CK_FUNCTION_LIST *f;
625 CK_RV rv;
625 CK_SESSION_HANDLE session; 626 CK_SESSION_HANDLE session;
626 int login_required, ret; 627 int login_required, have_pinpad, ret;
627 628
628 f = p->function_list; 629 f = p->function_list;
629 login_required = p->slotinfo[slotidx].token.flags & CKF_LOGIN_REQUIRED; 630 si = &p->slotinfo[slotidx];
630 if (pin && login_required && !strlen(pin)) { 631
632 have_pinpad = si->token.flags & CKF_PROTECTED_AUTHENTICATION_PATH;
633 login_required = si->token.flags & CKF_LOGIN_REQUIRED;
634
635 /* fail early before opening session */
636 if (login_required && !have_pinpad && pin != NULL && strlen(pin) == 0) {
631 error("pin required"); 637 error("pin required");
632 return (-SSH_PKCS11_ERR_PIN_REQUIRED); 638 return (-SSH_PKCS11_ERR_PIN_REQUIRED);
633 } 639 }
634 if ((rv = f->C_OpenSession(p->slotlist[slotidx], CKF_RW_SESSION| 640 if ((rv = f->C_OpenSession(p->slotlist[slotidx], CKF_RW_SESSION|
635 CKF_SERIAL_SESSION, NULL, NULL, &session)) 641 CKF_SERIAL_SESSION, NULL, NULL, &session)) != CKR_OK) {
636 != CKR_OK) {
637 error("C_OpenSession failed: %lu", rv); 642 error("C_OpenSession failed: %lu", rv);
638 return (-1); 643 return (-1);
639 } 644 }
640 if (login_required && pin) { 645 if (login_required) {
641 rv = f->C_Login(session, user, 646 if (have_pinpad && (pin == NULL || strlen(pin) == 0)) {
642 (u_char *)pin, strlen(pin)); 647 /* defer PIN entry to the reader keypad */
648 rv = f->C_Login(session, CKU_USER, NULL_PTR, 0);
649 } else {
650 rv = f->C_Login(session, CKU_USER,
651 (u_char *)pin, strlen(pin));
652 }
643 if (rv != CKR_OK && rv != CKR_USER_ALREADY_LOGGED_IN) { 653 if (rv != CKR_OK && rv != CKR_USER_ALREADY_LOGGED_IN) {
644 error("C_Login failed: %lu", rv); 654 error("C_Login failed: %lu", rv);
645 ret = (rv == CKR_PIN_LOCKED) ? 655 ret = (rv == CKR_PIN_LOCKED) ?
@@ -649,9 +659,9 @@ pkcs11_open_session(struct pkcs11_provider *p, CK_ULONG slotidx, char *pin,
649 error("C_CloseSession failed: %lu", rv); 659 error("C_CloseSession failed: %lu", rv);
650 return (ret); 660 return (ret);
651 } 661 }
652 p->slotinfo[slotidx].logged_in = 1; 662 si->logged_in = 1;
653 } 663 }
654 p->slotinfo[slotidx].session = session; 664 si->session = session;
655 return (0); 665 return (0);
656} 666}
657 667