Skip to content

Instantly share code, notes, and snippets.

@h-yamamo
Created February 19, 2016 14:35
Show Gist options
  • Save h-yamamo/b8d92f00b168e21bb661 to your computer and use it in GitHub Desktop.
Save h-yamamo/b8d92f00b168e21bb661 to your computer and use it in GitHub Desktop.
Fix downgrade hash algorithm to SHA1 via SNI for ubuntu trusty 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.1f-1ubuntu2.16 1.0.1f-1ubuntu2.16+alg
--- a/ssl/ssl_lib.c 2014-10-15 16:56:03.000000000 +0000
+++ b/ssl/ssl_lib.c 2016-02-19 21:58:14.000000000 +0900
@@ -2406,6 +2406,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;
@@ -2428,6 +2431,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.1f-1ubuntu2.16 1.0.1f-1ubuntu2.16+alg
--- a/ssl/t1_lib.c 2014-10-15 16:56:03.000000000 +0000
+++ b/ssl/t1_lib.c 2016-02-19 21:56:39.000000000 +0900
@@ -2482,6 +2482,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;
@@ -2497,12 +2501,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
@@ -2513,12 +2519,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);
@@ -2532,6 +2554,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

Fixed in openssl_1.0.1f-1ubuntu2.18, so no longer needed.

How to build package

apt-get -d source openssl
tar xf openssl_1.0.1f.orig.tar.gz
cd openssl-1.0.1f
tar xf ../openssl_1.0.1f-1ubuntu2.17.debian.tar.gz
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 2449

                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