Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
Avoid keeping the real Yubikey PIN around
Just keep the PBKDF2 hashed version around instead.

Signed-off-by: David Woodhouse <David.Woodhouse@intel.com>
  • Loading branch information
David Woodhouse authored and David Woodhouse committed Nov 14, 2014
1 parent a23f11a commit bac41df
Show file tree
Hide file tree
Showing 5 changed files with 46 additions and 26 deletions.
25 changes: 16 additions & 9 deletions gnutls.c
Expand Up @@ -2351,10 +2351,10 @@ static P11KitPin *pin_callback(const char *pin_source, P11KitUri *pin_uri,
#endif

#ifdef HAVE_LIBPCSCLITE
int openconnect_yubikey_challenge(const char *password, const void *ident, int id_len,
const void *challenge, int chall_len, void *result)
int openconnect_hash_yubikey_password(struct openconnect_info *vpninfo,
const char *password, const void *ident, int id_len)
{
unsigned char U[SHA1_SIZE], T[SHA1_SIZE];
unsigned char U[SHA1_SIZE];
gnutls_hmac_hd_t dgst;
int ret = -EIO;
int i, j;
Expand All @@ -2371,23 +2371,30 @@ int openconnect_yubikey_challenge(const char *password, const void *ident, int i
goto out;
gnutls_hmac_output(dgst, U);

memcpy(T, U, SHA1_SIZE);
memcpy(vpninfo->yubikey_pwhash, U, 16);

for (i = 1; i < 1000; i++) {
if (gnutls_hmac(dgst, U, SHA1_SIZE))
goto out;

gnutls_hmac_output(dgst, U);

for (j = 0; j < SHA1_SIZE; j++)
T[j] ^= U[j];
for (j = 0; j < 16; j++)
vpninfo->yubikey_pwhash[j] ^= U[j];
}

if (gnutls_hmac_fast(GNUTLS_MAC_SHA1, T, 16, challenge, chall_len, result))
goto out;

ret = 0;
out:
gnutls_hmac_deinit(dgst, NULL);
return ret;
}

int openconnect_yubikey_chalresp(struct openconnect_info *vpninfo,
const void *challenge, int chall_len, void *result)
{
if (gnutls_hmac_fast(GNUTLS_MAC_SHA1, vpninfo->yubikey_pwhash, 16, challenge, chall_len, result))
return -EIO;

return 0;
}
#endif
2 changes: 1 addition & 1 deletion library.c
Expand Up @@ -263,7 +263,7 @@ void openconnect_vpninfo_free(struct openconnect_info *vpninfo)
SCardDisconnect(vpninfo->pcsc_card, SCARD_LEAVE_CARD);
SCardReleaseContext(vpninfo->pcsc_ctx);
}
free(vpninfo->yubikey_password);
memset(vpninfo->yubikey_pwhash, 0, sizeof(vpninfo->yubikey_pwhash));
free(vpninfo->yubikey_objname);
#endif
/* These check strm->state so they are safe to call multiple times */
Expand Down
9 changes: 6 additions & 3 deletions openconnect-internal.h
Expand Up @@ -290,7 +290,8 @@ struct openconnect_info {
#ifdef HAVE_LIBPCSCLITE
SCARDHANDLE pcsc_ctx, pcsc_card;
char *yubikey_objname;
char *yubikey_password;
unsigned char yubikey_pwhash[16];
int yubikey_pw_set;
int yubikey_mode;
#endif
openconnect_lock_token_vfn lock_token;
Expand Down Expand Up @@ -646,8 +647,10 @@ int openconnect_md5(unsigned char *result, void *data, int len);
int openconnect_random(void *bytes, int len);
int openconnect_local_cert_md5(struct openconnect_info *vpninfo,
char *buf);
int openconnect_yubikey_challenge(const char *password, const void *ident, int id_len,
const void *challenge, int chall_len, void *result);
int openconnect_yubikey_chalresp(struct openconnect_info *vpninfo,
const void *challenge, int chall_len, void *result);
int openconnect_hash_yubikey_password(struct openconnect_info *vpninfo,
const char *password, const void *ident, int id_len);
#if defined(OPENCONNECT_OPENSSL)
#define openconnect_https_connected(_v) ((_v)->https_ssl)
#elif defined (OPENCONNECT_GNUTLS)
Expand Down
18 changes: 12 additions & 6 deletions openssl.c
Expand Up @@ -1615,16 +1615,22 @@ int openconnect_local_cert_md5(struct openconnect_info *vpninfo,
}

#ifdef HAVE_LIBPCSCLITE
int openconnect_yubikey_challenge(const char *password, const void *ident, int id_len,
int openconnect_hash_yubikey_password(struct openconnect_info *vpninfo,
const char *password, const void *ident, int id_len)
{
if (!PKCS5_PBKDF2_HMAC_SHA1(password, strlen(password), ident, id_len, 1000, 16,
vpninfo->yubikey_pwhash))
return -EIO;

return 0;
}

int openconnect_yubikey_chalresp(struct openconnect_info *vpninfo,
const void *challenge, int chall_len, void *result)
{
unsigned char T[20];
unsigned int mdlen = SHA1_SIZE;

if (!PKCS5_PBKDF2_HMAC_SHA1(password, strlen(password), ident, id_len, 1000, 16, T))
return -EIO;

if (!HMAC(EVP_sha1(), T, 16, challenge, chall_len, result, &mdlen))
if (!HMAC(EVP_sha1(), vpninfo->yubikey_pwhash, 16, challenge, chall_len, result, &mdlen))
return -EIO;

return 0;
Expand Down
18 changes: 11 additions & 7 deletions yubikey.c
Expand Up @@ -196,7 +196,7 @@ static int select_yubioath_applet(struct openconnect_info *vpninfo,
chall_len = tlvlen;

retry:
if (!vpninfo->yubikey_password) {
if (!vpninfo->yubikey_pw_set) {
struct oc_auth_form f;
struct oc_form_opt o;

Expand All @@ -217,11 +217,15 @@ static int select_yubioath_applet(struct openconnect_info *vpninfo,
if (!o._value)
return -EPERM;

vpninfo->yubikey_password = o._value;
ret = openconnect_hash_yubikey_password(vpninfo, o._value, applet_id, id_len);
if (ret)
return ret;

vpninfo->yubikey_pw_set = 1;
memset(o._value, 0, strlen(o._value));
free(o._value);
}
if (openconnect_yubikey_challenge(vpninfo->yubikey_password,
applet_id, id_len,
&challenge, chall_len,
if (openconnect_yubikey_chalresp(vpninfo, &challenge, chall_len,
chalresp + 7)) {
vpn_progress(vpninfo, PRG_ERR,
_("Failed to calculate Yubikey unlock response\n"));
Expand All @@ -243,8 +247,8 @@ static int select_yubioath_applet(struct openconnect_info *vpninfo,
ret = yubikey_cmd(vpninfo, pcsc_card, PRG_ERR, _("unlock command"),
chalresp, sizeof(chalresp), buf);
if (ret == -EINVAL) {
free(vpninfo->yubikey_password);
vpninfo->yubikey_password = NULL;
memset(vpninfo->yubikey_pwhash, 0, sizeof(vpninfo->yubikey_pwhash));
vpninfo->yubikey_pw_set = 0;
goto retry;
}
if (ret)
Expand Down

0 comments on commit bac41df

Please sign in to comment.