diff options
Diffstat (limited to 'crypto/openssh/ssh-pkcs11.c')
-rw-r--r-- | crypto/openssh/ssh-pkcs11.c | 85 |
1 files changed, 54 insertions, 31 deletions
diff --git a/crypto/openssh/ssh-pkcs11.c b/crypto/openssh/ssh-pkcs11.c index c49cbf4..92614a5 100644 --- a/crypto/openssh/ssh-pkcs11.c +++ b/crypto/openssh/ssh-pkcs11.c @@ -1,4 +1,4 @@ -/* $OpenBSD: ssh-pkcs11.c,v 1.11 2013/11/13 13:48:20 markus Exp $ */ +/* $OpenBSD: ssh-pkcs11.c,v 1.21 2015/07/18 08:02:17 djm Exp $ */ /* * Copyright (c) 2010 Markus Friedl. All rights reserved. * @@ -38,7 +38,7 @@ #include "log.h" #include "misc.h" -#include "key.h" +#include "sshkey.h" #include "ssh-pkcs11.h" #include "xmalloc.h" @@ -237,7 +237,7 @@ pkcs11_rsa_private_encrypt(int flen, const u_char *from, u_char *to, RSA *rsa, {CKA_ID, NULL, 0}, {CKA_SIGN, NULL, sizeof(true_val) } }; - char *pin, prompt[1024]; + char *pin = NULL, prompt[1024]; int rval = -1; key_filter[0].pValue = &private_key_class; @@ -255,21 +255,30 @@ pkcs11_rsa_private_encrypt(int flen, const u_char *from, u_char *to, RSA *rsa, si = &k11->provider->slotinfo[k11->slotidx]; if ((si->token.flags & CKF_LOGIN_REQUIRED) && !si->logged_in) { if (!pkcs11_interactive) { - error("need pin"); + error("need pin entry%s", (si->token.flags & + CKF_PROTECTED_AUTHENTICATION_PATH) ? + " on reader keypad" : ""); return (-1); } - snprintf(prompt, sizeof(prompt), "Enter PIN for '%s': ", - si->token.label); - pin = read_passphrase(prompt, RP_ALLOW_EOF); - if (pin == NULL) - return (-1); /* bail out */ - if ((rv = f->C_Login(si->session, CKU_USER, - (u_char *)pin, strlen(pin))) != CKR_OK) { + if (si->token.flags & CKF_PROTECTED_AUTHENTICATION_PATH) + verbose("Deferring PIN entry to reader keypad."); + else { + snprintf(prompt, sizeof(prompt), + "Enter PIN for '%s': ", si->token.label); + pin = read_passphrase(prompt, RP_ALLOW_EOF); + if (pin == NULL) + return (-1); /* bail out */ + } + rv = f->C_Login(si->session, CKU_USER, (u_char *)pin, + (pin != NULL) ? strlen(pin) : 0); + if (pin != NULL) { + explicit_bzero(pin, strlen(pin)); free(pin); + } + if (rv != CKR_OK && rv != CKR_USER_ALREADY_LOGGED_IN) { error("C_Login failed: %lu", rv); return (-1); } - free(pin); si->logged_in = 1; } key_filter[1].pValue = k11->keyid; @@ -366,8 +375,9 @@ pkcs11_open_session(struct pkcs11_provider *p, CK_ULONG slotidx, char *pin) return (-1); } if (login_required && pin) { - if ((rv = f->C_Login(session, CKU_USER, - (u_char *)pin, strlen(pin))) != CKR_OK) { + rv = f->C_Login(session, CKU_USER, + (u_char *)pin, strlen(pin)); + if (rv != CKR_OK && rv != CKR_USER_ALREADY_LOGGED_IN) { error("C_Login failed: %lu", rv); if ((rv = f->C_CloseSession(session)) != CKR_OK) error("C_CloseSession failed: %lu", rv); @@ -385,12 +395,12 @@ pkcs11_open_session(struct pkcs11_provider *p, CK_ULONG slotidx, char *pin) * keysp points to an (possibly empty) array with *nkeys keys. */ static int pkcs11_fetch_keys_filter(struct pkcs11_provider *, CK_ULONG, - CK_ATTRIBUTE [], CK_ATTRIBUTE [3], Key ***, int *) + CK_ATTRIBUTE [], CK_ATTRIBUTE [3], struct sshkey ***, int *) __attribute__((__bounded__(__minbytes__,4, 3 * sizeof(CK_ATTRIBUTE)))); static int pkcs11_fetch_keys(struct pkcs11_provider *p, CK_ULONG slotidx, - Key ***keysp, int *nkeys) + struct sshkey ***keysp, int *nkeys) { CK_OBJECT_CLASS pubkey_class = CKO_PUBLIC_KEY; CK_OBJECT_CLASS cert_class = CKO_CERTIFICATE; @@ -422,12 +432,12 @@ pkcs11_fetch_keys(struct pkcs11_provider *p, CK_ULONG slotidx, } static int -pkcs11_key_included(Key ***keysp, int *nkeys, Key *key) +pkcs11_key_included(struct sshkey ***keysp, int *nkeys, struct sshkey *key) { int i; for (i = 0; i < *nkeys; i++) - if (key_equal(key, (*keysp)[i])) + if (sshkey_equal(key, (*keysp)[i])) return (1); return (0); } @@ -435,9 +445,9 @@ pkcs11_key_included(Key ***keysp, int *nkeys, Key *key) static int pkcs11_fetch_keys_filter(struct pkcs11_provider *p, CK_ULONG slotidx, CK_ATTRIBUTE filter[], CK_ATTRIBUTE attribs[3], - Key ***keysp, int *nkeys) + struct sshkey ***keysp, int *nkeys) { - Key *key; + struct sshkey *key; RSA *rsa; X509 *x509; EVP_PKEY *evp; @@ -471,15 +481,23 @@ pkcs11_fetch_keys_filter(struct pkcs11_provider *p, CK_ULONG slotidx, error("C_GetAttributeValue failed: %lu", rv); continue; } - /* check that none of the attributes are zero length */ - if (attribs[0].ulValueLen == 0 || - attribs[1].ulValueLen == 0 || + /* + * Allow CKA_ID (always first attribute) to be empty, but + * ensure that none of the others are zero length. + * XXX assumes CKA_ID is always first. + */ + if (attribs[1].ulValueLen == 0 || attribs[2].ulValueLen == 0) { continue; } /* allocate buffers for attributes */ - for (i = 0; i < 3; i++) - attribs[i].pValue = xmalloc(attribs[i].ulValueLen); + for (i = 0; i < 3; i++) { + if (attribs[i].ulValueLen > 0) { + attribs[i].pValue = xmalloc( + attribs[i].ulValueLen); + } + } + /* * retrieve ID, modulus and public exponent of RSA key, * or ID, subject and value for certificates. @@ -517,16 +535,16 @@ pkcs11_fetch_keys_filter(struct pkcs11_provider *p, CK_ULONG slotidx, } if (rsa && rsa->n && rsa->e && pkcs11_rsa_wrap(p, slotidx, &attribs[0], rsa) == 0) { - key = key_new(KEY_UNSPEC); + key = sshkey_new(KEY_UNSPEC); key->rsa = rsa; key->type = KEY_RSA; - key->flags |= KEY_FLAG_EXT; + key->flags |= SSHKEY_FLAG_EXT; if (pkcs11_key_included(keysp, nkeys, key)) { - key_free(key); + sshkey_free(key); } else { /* expand key array and add key */ - *keysp = xrealloc(*keysp, *nkeys + 1, - sizeof(Key *)); + *keysp = xreallocarray(*keysp, *nkeys + 1, + sizeof(struct sshkey *)); (*keysp)[*nkeys] = key; *nkeys = *nkeys + 1; debug("have %d keys", *nkeys); @@ -544,7 +562,7 @@ pkcs11_fetch_keys_filter(struct pkcs11_provider *p, CK_ULONG slotidx, /* register a new provider, fails if provider already exists */ int -pkcs11_add_provider(char *provider_id, char *pin, Key ***keyp) +pkcs11_add_provider(char *provider_id, char *pin, struct sshkey ***keyp) { int nkeys, need_finalize = 0; struct pkcs11_provider *p = NULL; @@ -621,6 +639,11 @@ pkcs11_add_provider(char *provider_id, char *pin, Key ***keyp) error("C_GetTokenInfo failed: %lu", rv); continue; } + if ((token->flags & CKF_TOKEN_INITIALIZED) == 0) { + debug2("%s: ignoring uninitialised token in slot %lu", + __func__, (unsigned long)i); + continue; + } rmspace(token->label, sizeof(token->label)); rmspace(token->manufacturerID, sizeof(token->manufacturerID)); rmspace(token->model, sizeof(token->model)); |