use -std=gnu99 in CFLAGS. This is known to be needed when doing
i386/i686 builds on RHEL5.
+Version 2.4.3
+=============
+- ``--verify-hash`` can now take an optional flag which changes the hashing
+ algorithm. It can be either SHA1 or SHA256. The default if not provided is
+ SHA1 to preserve backwards compatibility with existing configurations.
Version 2.4.1
=============
Not available with PolarSSL.
.\"*********************************************************
.TP
-.B \-\-verify\-hash hash
-Specify SHA1 fingerprint for level-1 cert. The level-1 cert is the
+.B \-\-verify\-hash hash [algo]
+Specify SHA1 or SHA256 fingerprint for level-1 cert. The level-1 cert is the
CA (or intermediate cert) that signs the leaf certificate, and is
one removed from the leaf certificate in the direction of the root.
When accepting a connection from a peer, the level-1 cert
fingerprint must match
.B hash
or certificate verification will fail. Hash is specified
-as XX:XX:... For example: AD:B0:95:D8:09:C8:36:45:12:A9:89:C8:90:09:CB:13:72:A6:AD:16
+as XX:XX:... For example:
+
+.nf
+.ft 3
+.in +4
+AD:B0:95:D8:09:C8:36:45:12:A9:89:C8:90:09:CB:13:72:A6:AD:16
+.in -4
+.ft
+.fi
+
+The
+.B algo
+flag can be either SHA1 or SHA256. If not provided, it defaults to SHA1.
.\"*********************************************************
.TP
.B \-\-pkcs11\-cert\-private [0|1]...
/* Maximum HMAC digest size (bytes) */
#define OPENVPN_MAX_HMAC_SIZE 64
+/** Types referencing specific message digest hashing algorithms */
+typedef enum {
+ MD_SHA1,
+ MD_SHA256
+} hash_algo_type ;
+
/** Struct used in cipher name translation table */
typedef struct {
const char *openvpn_name; /**< Cipher name used by OpenVPN */
memmove(to.remote_cert_ku, options->remote_cert_ku, sizeof(to.remote_cert_ku));
to.remote_cert_eku = options->remote_cert_eku;
to.verify_hash = options->verify_hash;
+ to.verify_hash_algo = options->verify_hash_algo;
#ifdef ENABLE_X509ALTUSERNAME
to.x509_username_field = (char *) options->x509_username_field;
#else
"--x509-username-field : Field in x509 certificate containing the username.\n"
" Default is CN in the Subject field.\n"
#endif
- "--verify-hash : Specify SHA1 fingerprint for level-1 cert.\n"
+ "--verify-hash hash [algo] : Specify fingerprint for level-1 certificate.\n"
+ " Valid algo flags are SHA1 and SHA256. \n"
#ifdef _WIN32
"--cryptoapicert select-string : Load the certificate and private key from the\n"
" Windows Certificate System Store.\n"
options->extra_certs_file_inline = p[2];
}
}
- else if (streq(p[0], "verify-hash") && p[1] && !p[2])
+ else if (streq(p[0], "verify-hash") && p[1] && !p[3])
{
VERIFY_PERMISSION(OPT_P_GENERAL);
- options->verify_hash = parse_hash_fingerprint(p[1], SHA_DIGEST_LENGTH, msglevel, &options->gc);
+
+ if (!p[2] || (p[2] && streq(p[2], "SHA1")))
+ {
+ options->verify_hash = parse_hash_fingerprint(p[1], SHA_DIGEST_LENGTH, msglevel, &options->gc);
+ options->verify_hash_algo = MD_SHA1;
+ }
+ else if (p[2] && streq(p[2], "SHA256"))
+ {
+ options->verify_hash = parse_hash_fingerprint(p[1], SHA256_DIGEST_LENGTH, msglevel, &options->gc);
+ options->verify_hash_algo = MD_SHA256;
+ }
+ else
+ {
+ msg(msglevel, "invalid or unsupported hashing algorithm: %s (only SHA1 and SHA256 are valid)", p[2]);
+ goto err;
+ }
}
#ifdef ENABLE_CRYPTOAPI
else if (streq(p[0], "cryptoapicert") && p[1] && !p[2])
#include "comp.h"
#include "pushlist.h"
#include "clinat.h"
+#ifdef ENABLE_CRYPTO
+#include "crypto_backend.h"
+#endif
+
/*
* Maximum number of parameters associated with an option,
unsigned remote_cert_ku[MAX_PARMS];
const char *remote_cert_eku;
uint8_t *verify_hash;
+ hash_algo_type verify_hash_algo;
unsigned int ssl_flags; /* set to SSLF_x flags from ssl.h */
#ifdef ENABLE_PKCS11
unsigned remote_cert_ku[MAX_PARMS];
const char *remote_cert_eku;
uint8_t *verify_hash;
+ hash_algo_type verify_hash_algo;
char *x509_username_field;
/* allow openvpn config info to be
/* verify level 1 cert, i.e. the CA that signed our leaf cert */
if (cert_depth == 1 && opt->verify_hash)
{
- struct buffer sha1_hash = x509_get_sha1_fingerprint(cert, &gc);
- if (memcmp(BPTR(&sha1_hash), opt->verify_hash, BLEN(&sha1_hash)))
+ struct buffer ca_hash = {0};
+
+ switch (opt->verify_hash_algo)
+ {
+ case MD_SHA1:
+ ca_hash = x509_get_sha1_fingerprint(cert, &gc);
+ break;
+
+ case MD_SHA256:
+ ca_hash = x509_get_sha256_fingerprint(cert, &gc);
+ break;
+
+ default:
+ /* This should normally not happen at all; the algorithm used
+ * is parsed by add_option() [options.c] and set to a predefined
+ * value in an enumerated type. So if this unlikely scenario
+ * happens, consider this a failure
+ */
+ msg(M_WARN, "Unexpected invalid algorithm used with "
+ "--verify-hash (%i)", opt->verify_hash_algo);
+ ret = FAILURE;
+ goto cleanup;
+ }
+
+ if (memcmp(BPTR(&ca_hash), opt->verify_hash, BLEN(&ca_hash)))
{
msg(D_TLS_ERRORS, "TLS Error: level-1 certificate hash verification failed");
goto cleanup;