From 761469ccfbb51c552c19696d7558552b1ef9beab Mon Sep 17 00:00:00 2001 From: Marcin Adamski Date: Mon, 4 Apr 2022 13:52:56 +0200 Subject: [PATCH] fix 971: Server always downgrades TLS to v1.0 --- lib/tls.js | 2 +- tests/unit/tls.js | 192 +++++++++++++++++++++++++++++++++------------- 2 files changed, 140 insertions(+), 54 deletions(-) diff --git a/lib/tls.js b/lib/tls.js index fadfd646f..126ef4d99 100644 --- a/lib/tls.js +++ b/lib/tls.js @@ -1087,7 +1087,7 @@ tls.handleClientHello = function(c, record, length) { } else { // use highest compatible minor version var version; - for(var i = 1; i < tls.SupportedVersions.length; ++i) { + for(var i = 0; i < tls.SupportedVersions.length; ++i) { version = tls.SupportedVersions[i]; if(version.minor <= msg.version.minor) { break; diff --git a/tests/unit/tls.js b/tests/unit/tls.js index 45b0712a4..bd9d5e58b 100644 --- a/tests/unit/tls.js +++ b/tests/unit/tls.js @@ -6,6 +6,61 @@ require('../../lib/util'); (function() { describe('tls', function() { + + function createCertificate(cn, data) { + var keys = forge.pki.rsa.generateKeyPair(512); + var cert = forge.pki.createCertificate(); + cert.publicKey = keys.publicKey; + cert.serialNumber = '01'; + cert.validity.notBefore = new Date(); + cert.validity.notAfter = new Date(); + cert.validity.notAfter.setFullYear( + cert.validity.notBefore.getFullYear() + 1); + var attrs = [{ + name: 'commonName', + value: cn + }, { + name: 'countryName', + value: 'US' + }, { + shortName: 'ST', + value: 'Virginia' + }, { + name: 'localityName', + value: 'Blacksburg' + }, { + name: 'organizationName', + value: 'Test' + }, { + shortName: 'OU', + value: 'Test' + }]; + cert.setSubject(attrs); + cert.setIssuer(attrs); + cert.setExtensions([{ + name: 'basicConstraints', + cA: true + }, { + name: 'keyUsage', + keyCertSign: true, + digitalSignature: true, + nonRepudiation: true, + keyEncipherment: true, + dataEncipherment: true + }, { + name: 'subjectAltName', + altNames: [{ + type: 6, // URI + value: 'https://myuri.com/webid#me' + }] + }]); + cert.sign(keys.privateKey); + data[cn] = { + cert: forge.pki.certificateToPem(cert), + privateKey: forge.pki.privateKeyToPem(keys.privateKey) + }; + } + it('should test TLS 1.0 PRF', function() { // Note: This test vector is originally from: // http://www.imc.org/ietf-tls/mail-archive/msg01589.html @@ -117,59 +172,90 @@ require('../../lib/util'); end.client.handshake(); - function createCertificate(cn, data) { - var keys = forge.pki.rsa.generateKeyPair(512); - var cert = forge.pki.createCertificate(); - cert.publicKey = keys.publicKey; - cert.serialNumber = '01'; - cert.validity.notBefore = new Date(); - cert.validity.notAfter = new Date(); - cert.validity.notAfter.setFullYear( - cert.validity.notBefore.getFullYear() + 1); - var attrs = [{ - name: 'commonName', - value: cn - }, { - name: 'countryName', - value: 'US' - }, { - shortName: 'ST', - value: 'Virginia' - }, { - name: 'localityName', - value: 'Blacksburg' - }, { - name: 'organizationName', - value: 'Test' - }, { - shortName: 'OU', - value: 'Test' - }]; - cert.setSubject(attrs); - cert.setIssuer(attrs); - cert.setExtensions([{ - name: 'basicConstraints', - cA: true - }, { - name: 'keyUsage', - keyCertSign: true, - digitalSignature: true, - nonRepudiation: true, - keyEncipherment: true, - dataEncipherment: true - }, { - name: 'subjectAltName', - altNames: [{ - type: 6, // URI - value: 'https://myuri.com/webid#me' - }] - }]); - cert.sign(keys.privateKey); - data[cn] = { - cert: forge.pki.certificateToPem(cert), - privateKey: forge.pki.privateKeyToPem(keys.privateKey) - }; - } + }); + + it('should use TLS v1.1 by default and not downgrade to 1.0 if client requested 1.1', function(done) { + /* This test covers a bug in which TLS server upon reception ClientHello with TLS v1.1 + downgraded TLS to 1.0 for no reason. + */ + var end = {}; + var data = {}; + + createCertificate('server', data); + createCertificate('client', data); + data.client.connection = {}; + data.server.connection = {}; + + end.client = forge.tls.createConnection({ + server: false, + caStore: [data.server.cert], + sessionCache: {}, + cipherSuites: [ + forge.tls.CipherSuites.TLS_RSA_WITH_AES_128_CBC_SHA, + forge.tls.CipherSuites.TLS_RSA_WITH_AES_256_CBC_SHA], + virtualHost: 'server', + verify: function(c, verified, depth, certs) { + return true; + }, + connected: function(c) { + data.client.version = c.version; + }, + getCertificate: function(c, hint) { + return data.client.cert; + }, + getPrivateKey: function(c, cert) { + return data.client.privateKey; + }, + tlsDataReady: function(c) { + end.server.process(c.tlsData.getBytes()); + }, + dataReady: function(c) { + }, + closed: function(c) { + }, + error: function(c, error) { + ASSERT.equal(error.message, undefined); + } + }); + + end.server = forge.tls.createConnection({ + server: true, + caStore: [data.client.cert], + sessionCache: {}, + cipherSuites: [ + forge.tls.CipherSuites.TLS_RSA_WITH_AES_128_CBC_SHA, + forge.tls.CipherSuites.TLS_RSA_WITH_AES_256_CBC_SHA], + connected: function(c) { + data.server.version = c.version; + c.close(); + }, + verifyClient: true, + verify: function(c, verified, depth, certs) { + return true; + }, + getCertificate: function(c, hint) { + return data.server.cert; + }, + getPrivateKey: function(c, cert) { + return data.server.privateKey; + }, + tlsDataReady: function(c) { + end.client.process(c.tlsData.getBytes()); + }, + dataReady: function(c) { + }, + closed: function(c) { + ASSERT.deepEqual(data.client.version, forge.tls.Versions.TLS_1_1); + ASSERT.deepEqual(data.server.version, forge.tls.Versions.TLS_1_1); + done(); + }, + error: function(c, error) { + ASSERT.equal(error.message, undefined); + } + }); + + end.client.handshake(); + }); }); })();