Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
Support SHA256/SHA512 for OATH
Signed-off-by: David Woodhouse <David.Woodhouse@intel.com>
  • Loading branch information
David Woodhouse authored and David Woodhouse committed Jan 30, 2015
1 parent cc2ea5d commit 929d35e
Show file tree
Hide file tree
Showing 8 changed files with 95 additions and 13 deletions.
20 changes: 18 additions & 2 deletions gnutls.c
Expand Up @@ -2597,10 +2597,26 @@ int hotp_hmac(struct openconnect_info *vpninfo, const void *challenge)
int ret;
int hpos;
unsigned char hash[64]; /* Enough for a SHA256 */
gnutls_mac_algorithm_t alg;

switch(vpninfo->oath_hmac_alg) {
case OATH_ALG_HMAC_SHA1:
alg = GNUTLS_MAC_SHA1;
break;
case OATH_ALG_HMAC_SHA256:
alg = GNUTLS_MAC_SHA256;
break;
case OATH_ALG_HMAC_SHA512:
alg = GNUTLS_MAC_SHA512;
break;
default:
vpn_progress(vpninfo, PRG_ERR,
_("Unsupported OATH HMAC algorithm\n"));
return -EINVAL;
}

hpos = 19;
ret = gnutls_hmac_fast(GNUTLS_MAC_SHA1,
vpninfo->oath_secret,
ret = gnutls_hmac_fast(alg, vpninfo->oath_secret,
vpninfo->oath_secret_len,
challenge, 8, hash);
if (ret) {
Expand Down
30 changes: 29 additions & 1 deletion oath.c
Expand Up @@ -226,7 +226,22 @@ int set_totp_mode(struct openconnect_info *vpninfo, const char *token_str)
ret = pskc_decode(vpninfo, token_str, toklen, OC_TOKEN_MODE_TOTP);
if (ret)
return -EINVAL;
} else if (strncasecmp(token_str, "base32:", strlen("base32:")) == 0) {
vpninfo->token_mode = OC_TOKEN_MODE_TOTP;
return 0;
}
if (!strncasecmp(token_str, "sha1:", 5)) {
token_str += 5;
vpninfo->oath_hmac_alg = OATH_ALG_HMAC_SHA1;
} else if (!strncasecmp(token_str, "sha256:", 7)) {
token_str += 7;
vpninfo->oath_hmac_alg = OATH_ALG_HMAC_SHA256;
} else if (!strncasecmp(token_str, "sha512:", 7)) {
token_str += 7;
vpninfo->oath_hmac_alg = OATH_ALG_HMAC_SHA256;
} else
vpninfo->oath_hmac_alg = OATH_ALG_HMAC_SHA1;

if (strncasecmp(token_str, "base32:", strlen("base32:")) == 0) {
ret = decode_base32(vpninfo, token_str + strlen("base32:"),
toklen - strlen("base32:"));
if (ret)
Expand Down Expand Up @@ -263,6 +278,19 @@ int set_hotp_mode(struct openconnect_info *vpninfo, const char *token_str)
vpninfo->token_mode = OC_TOKEN_MODE_HOTP;
return 0;
}

if (!strncasecmp(token_str, "sha1:", 5)) {
token_str += 5;
vpninfo->oath_hmac_alg = OATH_ALG_HMAC_SHA1;
} else if (!strncasecmp(token_str, "sha256:", 7)) {
token_str += 7;
vpninfo->oath_hmac_alg = OATH_ALG_HMAC_SHA256;
} else if (!strncasecmp(token_str, "sha512:", 7)) {
token_str += 7;
vpninfo->oath_hmac_alg = OATH_ALG_HMAC_SHA256;
} else
vpninfo->oath_hmac_alg = OATH_ALG_HMAC_SHA1;

p = strrchr(token_str, ',');
if (p) {
long counter;
Expand Down
5 changes: 5 additions & 0 deletions openconnect-internal.h
Expand Up @@ -406,6 +406,11 @@ struct openconnect_info {
#endif
char *oath_secret;
size_t oath_secret_len;
enum {
OATH_ALG_HMAC_SHA1 = 0,
OATH_ALG_HMAC_SHA256,
OATH_ALG_HMAC_SHA512,
} oath_hmac_alg;
enum {
HOTP_SECRET_BASE32 = 1,
HOTP_SECRET_RAW,
Expand Down
18 changes: 17 additions & 1 deletion openssl.c
Expand Up @@ -1672,8 +1672,24 @@ int hotp_hmac(struct openconnect_info *vpninfo, const void *challenge)
{
unsigned char hash[64]; /* Enough for a SHA256 */
unsigned int hashlen = sizeof(hash);
const EVP_MD *alg;

if (!HMAC(EVP_sha1(), vpninfo->oath_secret, vpninfo->oath_secret_len,
switch(vpninfo->oath_hmac_alg) {
case OATH_ALG_HMAC_SHA1:
alg = EVP_sha1();
break;
case OATH_ALG_HMAC_SHA256:
alg = EVP_sha256();
break;
case OATH_ALG_HMAC_SHA512:
alg = EVP_sha512();
break;
default:
vpn_progress(vpninfo, PRG_ERR,
_("Unsupported OATH HMAC algorithm\n"));
return -EINVAL;
}
if (!HMAC(alg, vpninfo->oath_secret, vpninfo->oath_secret_len,
challenge, 8, hash, &hashlen)) {
vpninfo->progress(vpninfo, PRG_ERR,
_("Failed to calculate OATH HMAC\n"));
Expand Down
2 changes: 1 addition & 1 deletion www/building.xml
Expand Up @@ -33,7 +33,7 @@ And <em>optionally</em> also:
<li><b><tt><a href="http://code.google.com/p/libproxy/">libproxy</a></tt></b></li>
<li><b><tt><a href="http://trousers.sourceforge.net/">trousers</a></tt></b> <i>(for TPM support if using GnuTLS)</i></li>
<li><b><tt><a href="http://stoken.sourceforge.net/">libstoken</a></tt></b> <i>(for SecurID software token support)</i></li>
<li><b><tt><a href="http://www.nongnu.org/oath-toolkit/">liboath</a></tt></b> <i>(for software HOTP/TOTP support)</i></li>
<li><b><tt><a href="http://www.nongnu.org/oath-toolkit/">libpskc</a></tt></b> <i>(for RFC6030 PSKC file storage of HOTP/TOTP keys)</i></li>
<li><b><tt><a href="https://pcsclite.alioth.debian.org/pcsclite.html">libpcsclite</a></tt></b> <i>(for Yubikey hardware HOTP/HOTP support)</i></li>
</ul>
<p>OpenConnect supports the use of HTTP and SOCKS proxies to connect to the
Expand Down
2 changes: 2 additions & 0 deletions www/changelog.xml
Expand Up @@ -15,6 +15,8 @@
<ul>
<li><b>OpenConnect HEAD</b>
<ul>
<li>Add SHA256/SHA512 support for OATH.</li>
<li>Remove liboath dependency.</li>
<li>Preliminary support for Juniper SSL VPN.</li>
</ul><br/>
</li>
Expand Down
2 changes: 1 addition & 1 deletion www/features.xml
Expand Up @@ -16,7 +16,7 @@
<li>Authentication via HTTP forms.</li>
<li>Authentication using SSL certificates &#8212; from local file, <a href="http://en.wikipedia.org/wiki/Trusted_Platform_Module">Trusted Platform Module</a> and PKCS#11 smartcards.</li>
<li>Authentication using SecurID software tokens <i>(when built with libstoken)</i></li>
<li>Authentication using OATH TOTP or HOTP software tokens <i>(when built with liboath)</i></li>
<li>Authentication using OATH TOTP or HOTP software tokens.</li>
<li>Authentication using Yubikey OATH tokens <i>(when built with libpcsclite)</i></li>
<li><i>UserGroup</i> support for selecting between multiple configurations on a single VPN server.</li>
<li>Data transport over TCP <i>(HTTPS)</i> or UDP <i>(DTLS)</i>.</li>
Expand Down
29 changes: 22 additions & 7 deletions www/token.xml
Expand Up @@ -15,10 +15,8 @@ generating one-time passwords:</p>
<ul>
<li><a href="http://en.wikipedia.org/wiki/SecurID">RSA SecurID</a> tokens using
<a href="http://stoken.sourceforge.net/">libstoken</a></li>
<li>OATH TOTP <i>(<a href="http://tools.ietf.org/html/rfc6238">RFC6238</a>)</i> tokens using
<a href="http://www.nongnu.org/oath-toolkit/">liboath</a></li>
<li>OATH HOTP <i>(<a href="http://tools.ietf.org/html/rfc4226">RFC4226</a>)</i> tokens using
<a href="http://www.nongnu.org/oath-toolkit/">liboath</a></li>
<li>OATH TOTP <i>(<a href="http://tools.ietf.org/html/rfc6238">RFC6238</a>)</i> tokens</li>
<li>OATH HOTP <i>(<a href="http://tools.ietf.org/html/rfc4226">RFC4226</a>)</i> tokens</li>
</ul>
<p>OATH HOTP/TOTP tokens are also supported in hardware by:</p>
<ul><li><a href="https://developers.yubico.com/ykneo-oath/">ykneo-oath</a> applet on
Expand Down Expand Up @@ -113,15 +111,21 @@ of a referenced file, or entered into the NetworkManager configuration dialog.
They may be specified in one of the following forms:</p>

<ul>
<li><b>SecretSecret!</b><br/>
<li><b>SecretSecret!</b></li>
<li><b>sha256:SecretSecret!</b></li>
<li><b>sha512:SecretSecret!</b><br/>
For secrets which are actually UTF-8 strings instead of entirely randomly generated
data, they may be specified directly in this form.</li>
<li><b>0x53656372657453656372657421</b><br/>
<li><b>0x53656372657453656372657421</b></li>
<li><b>sha256:0x53656372657453656372657421</b></li>
<li><b>sha512:0x53656372657453656372657421</b><br/>
This is the hexadecimal form which <i>(without the leading <tt>0x</tt>)</i> is
accepted by default by the
<tt><a href="http://www.nongnu.org/oath-toolkit/oathtool.1.html">oathtool</a></tt>
program.</li>
<li><b>base32:KNSWG4TFORJWKY3SMV2CC===</b><br/>
<li><b>base32:KNSWG4TFORJWKY3SMV2CC===</b></li>
<li><b>sha256:base32:KNSWG4TFORJWKY3SMV2CC===</b></li>
<li><b>sha512:base32:KNSWG4TFORJWKY3SMV2CC===</b><br/>
This is the base32 form which is accepted by the
<tt><a href="http://www.nongnu.org/oath-toolkit/oathtool.1.html">oathtool</a></tt>
program with its <tt>-b</tt> option..</li>
Expand All @@ -130,6 +134,15 @@ They may be specified in one of the following forms:</p>
These should be generally be imported from a file: '<tt>--token-secret @<i>FILE.PSKC</i></tt>'</li>
</ul>

<p>The default HMAC algorithm for TOTP tokens is SHA-1. SHA-256 and
SHA-512 are also supported; to use them prefix "<tt>sha256:</tt>" or
"<tt>sha512:</tt>" when explicitly providing a key on the command line.
Algorithms other than SHA-1 are not yet supported with PSKC files until
the relevant standards have been updated to indicate how they shall be
indicated in the PSKC file. See <a href="http://www.rfc-editor.org/errata_search.php?rfc=6238&amp;eid=4249">this erratum</a> to RFC6238 for current status.</p>



<h2>HOTP (HMAC-Based One-Time Password)</h2>

<p>HOTP tokens are very similar to TOTP tokens except that they are event-based, and
Expand Down Expand Up @@ -165,6 +178,8 @@ configuration. So if you configure a VPN connection with a HOTP token secret of
and authenticate once, you should be able to go back into the configuration and see
that the token secret has been updated to <tt>"0x1234,2"</tt>.</p>

<p>HOTP tokens also support SHA-256 and SHA-512 in precisely the same
fashion as TOTP tokens, as described above.</p>
<h2>Yubikey HOTP/TOTP</h2>

<p>The <a href="https://developers.yubico.com/ykneo-oath/">ykneo-oath</a> applet
Expand Down

0 comments on commit 929d35e

Please sign in to comment.