Skip to content

Instantly share code, notes, and snippets.

@h-yamamo
Created February 19, 2016 14:37
Show Gist options
  • Save h-yamamo/1273d8b957473567bfe8 to your computer and use it in GitHub Desktop.
Save h-yamamo/1273d8b957473567bfe8 to your computer and use it in GitHub Desktop.
Fix downgrade hash algorithm to SHA1 via SNI for debian jessie openssl package
Improve TLS Extensions signature and hash algorithm
Reference:
Move signing digest out of CERT.
https://github.com/openssl/openssl/commit/d376e57d6826e56f4c922806e088a111c52f9e92
diff -ur openssl-1.0.1k-3+deb8u2 openssl-1.0.1k-3+deb8u2+alg
--- a/ssl/ssl_lib.c 2015-01-08 23:00:56.000000000 +0900
+++ b/ssl/ssl_lib.c 2016-02-19 21:58:14.000000000 +0900
@@ -2392,6 +2392,9 @@ EVP_PKEY *ssl_get_sign_pkey(SSL *s, const SSL_CIPHER *
unsigned long alg_a;
CERT *c;
int idx = -1;
+ int sha384 = !!(cipher->algorithm2 & SSL_HANDSHAKE_MAC_SHA384);
+ unsigned sigalgs = s->server >> 8;
+ s->server &= 0xf;
alg_a = cipher->algorithm_auth;
c=s->cert;
@@ -2414,6 +2417,30 @@
SSLerr(SSL_F_SSL_GET_SIGN_PKEY,ERR_R_INTERNAL_ERROR);
return(NULL);
}
+
+ if (s->version >= TLS1_2_VERSION && s->version < 0x800 &&
+ (idx <= SSL_PKEY_RSA_SIGN || idx == SSL_PKEY_ECC))
+ {
+ int bits = EVP_PKEY_bits(c->pkeys[idx].privatekey);
+
+ if (idx == SSL_PKEY_ECC)
+ {
+ sigalgs >>= 4;
+ if (bits > 256)
+ sha384 = 1;
+ }
+ else if (bits > 2048)
+ sha384 = 1;
+
+ if (sha384 && sigalgs & 0x2)
+ c->pkeys[idx].digest = EVP_sha384();
+ else if (sigalgs & 0x1)
+ c->pkeys[idx].digest = EVP_sha256();
+ else if (sigalgs & 0x2)
+ c->pkeys[idx].digest = EVP_sha384();
+ else if (sigalgs & 0x4)
+ c->pkeys[idx].digest = EVP_sha512();
+ }
if (pmd)
*pmd = c->pkeys[idx].digest;
return c->pkeys[idx].privatekey;
diff -ur openssl-1.0.1k-3+deb8u2 openssl-1.0.1k-3+deb8u2+alg
--- a/ssl/t1_lib.c 2015-01-08 23:00:56.000000000 +0900
+++ b/ssl/t1_lib.c 2016-02-19 21:56:39.000000000 +0900
@@ -2535,6 +2535,10 @@ int tls1_process_sigalgs(SSL *s, const unsigned char *
int i, idx;
const EVP_MD *md;
CERT *c = s->cert;
+ unsigned sigalgs = 0;
+
+ s->server &= 0xf;
+
/* Extension ignored for TLS versions below 1.2 */
if (TLS1_get_version(s) < TLS1_2_VERSION)
return 1;
@@ -2550,12 +2554,14 @@
for (i = 0; i < dsize; i += 2)
{
unsigned char hash_alg = data[i], sig_alg = data[i+1];
+ int shft = 0;
switch(sig_alg)
{
#ifndef OPENSSL_NO_RSA
case TLSEXT_signature_rsa:
idx = SSL_PKEY_RSA_SIGN;
+ shft = 8;
break;
#endif
#ifndef OPENSSL_NO_DSA
@@ -2566,12 +2572,28 @@
#ifndef OPENSSL_NO_ECDSA
case TLSEXT_signature_ecdsa:
idx = SSL_PKEY_ECC;
+ shft = 12;
break;
#endif
default:
continue;
}
+ switch(hash_alg)
+ {
+ case TLSEXT_hash_sha256:
+ sigalgs |= 0x1 << shft;
+ break;
+ case TLSEXT_hash_sha384:
+ sigalgs |= 0x2 << shft;
+ break;
+ case TLSEXT_hash_sha512:
+ sigalgs |= 0x4 << shft;
+ break;
+ default:
+ break;
+ }
+
if (c->pkeys[idx].digest == NULL)
{
md = tls12_get_hash(hash_alg);
@@ -2585,6 +2607,8 @@
}
+ if (s->server)
+ s->server |= sigalgs & 0xff00;
/* Set any remaining keys to default values. NOTE: if alg is not
* supported it stays as NULL.
@h-yamamo
Copy link
Author

h-yamamo commented Feb 19, 2016

( fixed in openssl_1.0.1t-1 or upper revision )

How to build package

apt-get -d source openssl
tar xf openssl_1.0.1k.orig.tar.gz
cd openssl-1.0.1k
tar xf ../openssl_1.0.1k-3+deb8u5.debian.tar.xz
cp (somewhere)/tlsext-signhashalgs.patch debian/patches/
echo tlsext-signhashalgs.patch >> debian/patches/series
vi debian/changelog  # add description about this patch
debuild -uc -us

Note: This patch does not consider xxx_DSS_xxx ciphersuites, because scarcely use them.

To mandate SHA-256 agaist SHA-1 attack:
TLS1.2のclientは通常ClientHelloで署名アルゴリズムにSHA-256を含みますが、
攻撃者がSHA-1のみを指定して攻撃を試みることが考えられます。
それに対応するためにSHA-256を必須にする方法が考えられます。
コードは以下のように2行追加になります。

ssl_lib.c: line 2435

                if (sha384 && sigalgs & 0x2)
                        c->pkeys[idx].digest = EVP_sha384();
                else if (sigalgs & 0x1)
                        c->pkeys[idx].digest = EVP_sha256();
                else if (sigalgs & 0x2)
                        c->pkeys[idx].digest = EVP_sha384();
                else if (sigalgs & 0x4)
                        c->pkeys[idx].digest = EVP_sha512();
                else
                        c->pkeys[idx].digest = EVP_sha256();

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment