| FazBrowse GitHub Viewer | Trending | | Home |
| Tools: [Download Repo ZIP] [Original HTTPS Page] |
1 parent 503f279 commit 6d92eba
5 files changed
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -809,6 +809,19 @@ See SSL_CIPHER_get_name() and SSL_CIPHER_get_version() in | |||
| 809 | 809 | http://www.openssl.org/docs/ssl/ssl.html#DEALING_WITH_CIPHERS for more | |
| 810 | 810 | information. | |
| 811 | 811 | ||
| 812 | + ### tlsSocket.getEphemeralKeyInfo() | ||
| 813 | + | ||
| 814 | + Returns an object representing a type, name and size of parameter of | ||
| 815 | + an ephemeral key exchange in [Perfect forward Secrecy][] on a client | ||
| 816 | + connection. It returns an empty object when the key exchange is not | ||
| 817 | + ephemeral. As it is only supported on a client socket, it returns null | ||
| 818 | + if this is called on a server socket. The supported types are 'DH' and | ||
| 819 | + 'ECDH'. The `name` property is only available in 'ECDH'. | ||
| 820 | + | ||
| 821 | + Example: | ||
| 822 | + | ||
| 823 | + { type: 'ECDH', name: 'prime256v1', size: 256 } | ||
| 824 | + | ||
| 812 | 825 | ### tlsSocket.renegotiate(options, callback) | |
| 813 | 826 | ||
| 814 | 827 | Initiate TLS renegotiation process. The `options` may contain the following | |
@@ -887,6 +900,7 @@ The numeric representation of the local port. | |||
| 887 | 900 | [net.Server.address()]: net.html#net_server_address | |
| 888 | 901 | ['secureConnect']: #tls_event_secureconnect | |
| 889 | 902 | [secureConnection]: #tls_event_secureconnection | |
| 903 | + [Perfect Forward Secrecy]: #tls_perfect_forward_secrecy | ||
| 890 | 904 | [Stream]: stream.html#stream_stream | |
| 891 | 905 | [SSL_METHODS]: http://www.openssl.org/docs/ssl/ssl.html#DEALING_WITH_PROTOCOL_METHODS | |
| 892 | 906 | [tls.Server]: #tls_class_tls_server | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -628,6 +628,13 @@ TLSSocket.prototype.getCipher = function(err) { | |||
| 628 | 628 | } | |
| 629 | 629 | }; | |
| 630 | 630 | ||
| 631 | + TLSSocket.prototype.getEphemeralKeyInfo = function() { | ||
| 632 | + if (this._handle) | ||
| 633 | + return this._handle.getEphemeralKeyInfo(); | ||
| 634 | + | ||
| 635 | + return null; | ||
| 636 | + }; | ||
| 637 | + | ||
| 631 | 638 | // TODO: support anonymous (nocert) and PSK | |
| 632 | 639 | ||
| 633 | 640 | ||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -1134,6 +1134,7 @@ void SSLWrap<Base>::AddMethods(Environment* env, Local<FunctionTemplate> t) { | |||
| 1134 | 1134 | env->SetProtoMethod(t, "newSessionDone", NewSessionDone); | |
| 1135 | 1135 | env->SetProtoMethod(t, "setOCSPResponse", SetOCSPResponse); | |
| 1136 | 1136 | env->SetProtoMethod(t, "requestOCSP", RequestOCSP); | |
| 1137 | + env->SetProtoMethod(t, "getEphemeralKeyInfo", GetEphemeralKeyInfo); | ||
| 1137 | 1138 | ||
| 1138 | 1139 | #ifdef SSL_set_max_send_fragment | |
| 1139 | 1140 | env->SetProtoMethod(t, "setMaxSendFragment", SetMaxSendFragment); | |
@@ -1744,6 +1745,50 @@ void SSLWrap<Base>::RequestOCSP( | |||
| 1744 | 1745 | } | |
| 1745 | 1746 | ||
| 1746 | 1747 | ||
| 1748 | + template <class Base> | ||
| 1749 | + void SSLWrap<Base>::GetEphemeralKeyInfo( | ||
| 1750 | + const v8::FunctionCallbackInfo<v8::Value>& args) { | ||
| 1751 | + Base* w = Unwrap<Base>(args.Holder()); | ||
| 1752 | + Environment* env = Environment::GetCurrent(args); | ||
| 1753 | + | ||
| 1754 | + CHECK_NE(w->ssl_, nullptr); | ||
| 1755 | + | ||
| 1756 | + // tmp key is available on only client | ||
| 1757 | + if (w->is_server()) | ||
| 1758 | + return args.GetReturnValue().SetNull(); | ||
| 1759 | + | ||
| 1760 | + Local<Object> info = Object::New(env->isolate()); | ||
| 1761 | + | ||
| 1762 | + EVP_PKEY* key; | ||
| 1763 | + | ||
| 1764 | + if (SSL_get_server_tmp_key(w->ssl_, &key)) { | ||
| 1765 | + switch (EVP_PKEY_id(key)) { | ||
| 1766 | + case EVP_PKEY_DH: | ||
| 1767 | + info->Set(env->type_string(), | ||
| 1768 | + FIXED_ONE_BYTE_STRING(env->isolate(), "DH")); | ||
| 1769 | + info->Set(env->size_string(), | ||
| 1770 | + Integer::New(env->isolate(), EVP_PKEY_bits(key))); | ||
| 1771 | + break; | ||
| 1772 | + case EVP_PKEY_EC: | ||
| 1773 | + { | ||
| 1774 | + EC_KEY* ec = EVP_PKEY_get1_EC_KEY(key); | ||
| 1775 | + int nid = EC_GROUP_get_curve_name(EC_KEY_get0_group(ec)); | ||
| 1776 | + EC_KEY_free(ec); | ||
| 1777 | + info->Set(env->type_string(), | ||
| 1778 | + FIXED_ONE_BYTE_STRING(env->isolate(), "ECDH")); | ||
| 1779 | + info->Set(env->name_string(), | ||
| 1780 | + OneByteString(args.GetIsolate(), OBJ_nid2sn(nid))); | ||
| 1781 | + info->Set(env->size_string(), | ||
| 1782 | + Integer::New(env->isolate(), EVP_PKEY_bits(key))); | ||
| 1783 | + } | ||
| 1784 | + } | ||
| 1785 | + EVP_PKEY_free(key); | ||
| 1786 | + } | ||
| 1787 | + | ||
| 1788 | + return args.GetReturnValue().Set(info); | ||
| 1789 | + } | ||
| 1790 | + | ||
| 1791 | + | ||
| 1747 | 1792 | #ifdef SSL_set_max_send_fragment | |
| 1748 | 1793 | template <class Base> | |
| 1749 | 1794 | void SSLWrap<Base>::SetMaxSendFragment( | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -236,6 +236,8 @@ class SSLWrap { | |||
| 236 | 236 | static void NewSessionDone(const v8::FunctionCallbackInfo<v8::Value>& args); | |
| 237 | 237 | static void SetOCSPResponse(const v8::FunctionCallbackInfo<v8::Value>& args); | |
| 238 | 238 | static void RequestOCSP(const v8::FunctionCallbackInfo<v8::Value>& args); | |
| 239 | + static void GetEphemeralKeyInfo( | ||
| 240 | + const v8::FunctionCallbackInfo<v8::Value>& args); | ||
| 239 | 241 | ||
| 240 | 242 | #ifdef SSL_set_max_send_fragment | |
| 241 | 243 | static void SetMaxSendFragment( | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -0,0 +1,98 @@ | |||
| 1 | + 'use strict'; | ||
| 2 | + var common = require('../common'); | ||
| 3 | + var assert = require('assert'); | ||
| 4 | + | ||
| 5 | + if (!common.hasCrypto) { | ||
| 6 | + console.log('1..0 # Skipped: missing crypto'); | ||
| 7 | + process.exit(); | ||
| 8 | + } | ||
| 9 | + var tls = require('tls'); | ||
| 10 | + | ||
| 11 | + var fs = require('fs'); | ||
| 12 | + var key = fs.readFileSync(common.fixturesDir + '/keys/agent2-key.pem'); | ||
| 13 | + var cert = fs.readFileSync(common.fixturesDir + '/keys/agent2-cert.pem'); | ||
| 14 | + | ||
| 15 | + var ntests = 0; | ||
| 16 | + var nsuccess = 0; | ||
| 17 | + | ||
| 18 | + function loadDHParam(n) { | ||
| 19 | + var path = common.fixturesDir; | ||
| 20 | + if (n !== 'error') path += '/keys'; | ||
| 21 | + return fs.readFileSync(path + '/dh' + n + '.pem'); | ||
| 22 | + } | ||
| 23 | + | ||
| 24 | + var cipherlist = { | ||
| 25 | + 'NOT_PFS': 'AES128-SHA256', | ||
| 26 | + 'DH': 'DHE-RSA-AES128-GCM-SHA256', | ||
| 27 | + 'ECDH': 'ECDHE-RSA-AES128-GCM-SHA256' | ||
| 28 | + }; | ||
| 29 | + | ||
| 30 | + function test(size, type, name, next) { | ||
| 31 | + var cipher = type ? cipherlist[type] : cipherlist['NOT_PFS']; | ||
| 32 | + | ||
| 33 | + if (name) tls.DEFAULT_ECDH_CURVE = name; | ||
| 34 | + | ||
| 35 | + var options = { | ||
| 36 | + key: key, | ||
| 37 | + cert: cert, | ||
| 38 | + ciphers: cipher | ||
| 39 | + }; | ||
| 40 | + | ||
| 41 | + if (type === 'DH') options.dhparam = loadDHParam(size); | ||
| 42 | + | ||
| 43 | + var server = tls.createServer(options, function(conn) { | ||
| 44 | + assert.strictEqual(conn.getEphemeralKeyInfo(), null); | ||
| 45 | + conn.end(); | ||
| 46 | + }); | ||
| 47 | + | ||
| 48 | + server.on('close', function(err) { | ||
| 49 | + assert(!err); | ||
| 50 | + if (next) next(); | ||
| 51 | + }); | ||
| 52 | + | ||
| 53 | + server.listen(common.PORT, '127.0.0.1', function() { | ||
| 54 | + var client = tls.connect({ | ||
| 55 | + port: common.PORT, | ||
| 56 | + rejectUnauthorized: false | ||
| 57 | + }, function() { | ||
| 58 | + var ekeyinfo = client.getEphemeralKeyInfo(); | ||
| 59 | + assert.strictEqual(ekeyinfo.type, type); | ||
| 60 | + assert.strictEqual(ekeyinfo.size, size); | ||
| 61 | + assert.strictEqual(ekeyinfo.name, name); | ||
| 62 | + nsuccess++; | ||
| 63 | + server.close(); | ||
| 64 | + }); | ||
| 65 | + }); | ||
| 66 | + } | ||
| 67 | + | ||
| 68 | + function testNOT_PFS() { | ||
| 69 | + test(undefined, undefined, undefined, testDHE1024); | ||
| 70 | + ntests++; | ||
| 71 | + } | ||
| 72 | + | ||
| 73 | + function testDHE1024() { | ||
| 74 | + test(1024, 'DH', undefined, testDHE2048); | ||
| 75 | + ntests++; | ||
| 76 | + } | ||
| 77 | + | ||
| 78 | + function testDHE2048() { | ||
| 79 | + test(2048, 'DH', undefined, testECDHE256); | ||
| 80 | + ntests++; | ||
| 81 | + } | ||
| 82 | + | ||
| 83 | + function testECDHE256() { | ||
| 84 | + test(256, 'ECDH', tls.DEFAULT_ECDH_CURVE, testECDHE512); | ||
| 85 | + ntests++; | ||
| 86 | + } | ||
| 87 | + | ||
| 88 | + function testECDHE512() { | ||
| 89 | + test(521, 'ECDH', 'secp521r1', null); | ||
| 90 | + ntests++; | ||
| 91 | + } | ||
| 92 | + | ||
| 93 | + testNOT_PFS(); | ||
| 94 | + | ||
| 95 | + process.on('exit', function() { | ||
| 96 | + assert.equal(ntests, nsuccess); | ||
| 97 | + assert.equal(ntests, 5); | ||
| 98 | + }); | ||
| Back | FazBrowse Home | New Git URL |
0 commit comments