GeezerVison is showing github.com — tls: report negotiated TLS groups · nodejs/node@4e0236d
File treeExpand file treeCollapse file tree Open diff view settings Expand file treeCollapse file tree Open diff view settings Collapse file Copy file name to clipboardExpand all lines: deps/ncrypto/ncrypto.cc +11Lines changed: 11 additions & 0 deletions | Original file line number | Diff line number | Diff line change |
|---|
@@ -3079,6 +3079,17 @@ EVPKeyPointer SSLPointer::getPeerTempKey() const { | 3079 | 3079 | return EVPKeyPointer(raw_key); | 3080 | 3080 | } | 3081 | 3081 |
| | 3082 | +std::optional<std::string_view> SSLPointer::getNegotiatedGroup() const { | | 3083 | +#if OPENSSL_VERSION_PREREQ(3, 5) | | 3084 | + if (!ssl_) return std::nullopt; | | 3085 | + const char* group = SSL_get0_group_name(get()); | | 3086 | + if (group == nullptr) return std::nullopt; | | 3087 | + return group; | | 3088 | +#else | | 3089 | + return std::nullopt; | | 3090 | +#endif | | 3091 | +} | | 3092 | + | 3082 | 3093 | std::optional<std::string_view> SSLPointer::getCipherName() const { | 3083 | 3094 | auto cipher = getCipher(); | 3084 | 3095 | if (cipher == nullptr) return std::nullopt; | |
Collapse file Copy file name to clipboardExpand all lines: deps/ncrypto/ncrypto.h +1Lines changed: 1 addition & 0 deletions | Original file line number | Diff line number | Diff line change |
|---|
@@ -1197,6 +1197,7 @@ class SSLPointer final { | 1197 | 1197 | std::optional<const std::string_view> getServerName() const; | 1198 | 1198 | X509View getCertificate() const; | 1199 | 1199 | EVPKeyPointer getPeerTempKey() const; | | 1200 | + std::optional<std::string_view> getNegotiatedGroup() const; | 1200 | 1201 | const SSL_CIPHER* getCipher() const; | 1201 | 1202 | bool isServer() const; | 1202 | 1203 |
| |
Collapse file Copy file name to clipboardExpand all lines: doc/api/tls.md +29-16Lines changed: 29 additions & 16 deletions - Display the source diff
- Display the rich diff
| Original file line number | Diff line number | Diff line change |
|---|
@@ -131,7 +131,8 @@ the character "E" appended to the traditional abbreviations): | 131 | 131 |
| 132 | 132 | Perfect forward secrecy using ECDHE is enabled by default. The `ecdhCurve` | 133 | 133 | option can be used when creating a TLS server to customize the list of supported | 134 | | -ECDH curves to use. See [`tls.createServer()`][] for more info. | | 134 | +ECDH curves for TLSv1.2 and below, and the list of supported TLS groups for | | 135 | +TLSv1.3. See [`tls.createServer()`][] for more info. | 135 | 136 |
| 136 | 137 | DHE is disabled by default but can be enabled alongside ECDHE by setting the | 137 | 138 | `dhparam` option to `'auto'`. Custom DHE parameters are also supported but | @@ -1196,12 +1197,19 @@ added: v5.0.0 | 1196 | 1197 |
| 1197 | 1198 | * Returns: {Object} | 1198 | 1199 |
| 1199 | | -Returns an object representing the type, name, and size of parameter of | 1200 | | -an ephemeral key exchange in [perfect forward secrecy][] on a client | 1201 | | -connection. It returns an empty object when the key exchange is not | 1202 | | -ephemeral. As this is only supported on a client socket; `null` is returned | 1203 | | -if called on a server socket. The supported types are `'DH'` and `'ECDH'`. The | 1204 | | -`name` property is available only when type is `'ECDH'`. | | 1200 | +Returns an object describing ephemeral key agreement in [perfect forward | | 1201 | +secrecy][] on a client connection. It returns an empty object when the key | | 1202 | +agreement is not ephemeral. As this is only supported on a client socket; | | 1203 | +`null` is returned if called on a server socket. The supported types are `'DH'`, | | 1204 | +`'ECDH'`, and `'TLSGroup'`. For `'DH'` and `'ECDH'`, the object describes peer | | 1205 | +temporary key parameters. For `'TLSGroup'`, the object identifies the negotiated | | 1206 | +TLS Supported Group used for key agreement when a peer temporary key object is | | 1207 | +not available. | | 1208 | + | | 1209 | +The `name` property is available only when type is `'ECDH'` or `'TLSGroup'`. The | | 1210 | +`size` property is not available when type is `'TLSGroup'`. For `'TLSGroup'`, | | 1211 | +`name` is the negotiated TLS Supported Group name. Standardized TLS group names | | 1212 | +and code points are listed in the [IANA TLS Supported Groups registry][]. | 1205 | 1213 |
| 1206 | 1214 | For example: `{ type: 'ECDH', name: 'prime256v1', size: 256 }`. | 1207 | 1215 |
| @@ -2015,12 +2023,16 @@ changes: | 2015 | 2023 | required for non-ECDHE [perfect forward secrecy][]. If omitted or invalid, | 2016 | 2024 | the parameters are silently discarded and DHE ciphers will not be available. | 2017 | 2025 | [ECDHE][]-based [perfect forward secrecy][] will still be available. | 2018 | | - * `ecdhCurve` {string} A string describing a named curve or a colon separated | 2019 | | - list of curve NIDs or names, for example `P-521:P-384:P-256`, to use for | 2020 | | - ECDH key agreement. Set to `auto` to select the | 2021 | | - curve automatically. Use [`crypto.getCurves()`][] to obtain a list of | 2022 | | - available curve names. On recent releases, `openssl ecparam -list_curves` | 2023 | | - will also display the name and description of each available elliptic curve. | | 2026 | + * `ecdhCurve` {string} A string describing a named curve, TLS group, or | | 2027 | + colon-separated list of named curves or TLS groups to use for key agreement, | | 2028 | + for example `P-521:P-384:P-256`, `X25519`, or `X25519MLKEM768`. The | | 2029 | + historical name of this option refers to ECDH key agreement in TLSv1.2 and | | 2030 | + below. In TLSv1.3, this option configures the TLS Supported Groups and | | 2031 | + key share groups offered or accepted by the TLS stack. Set to `auto` to | | 2032 | + select the group automatically. Use [`crypto.getCurves()`][] to obtain a | | 2033 | + list of available elliptic curve names. For TLS group names, use | | 2034 | + `openssl list -tls-groups` or consult the [IANA TLS Supported Groups | | 2035 | + registry][]. | 2024 | 2036 | **Default:** [`tls.DEFAULT_ECDH_CURVE`][]. | 2025 | 2037 | * `honorCipherOrder` {boolean} Attempt to use the server's cipher suite | 2026 | 2038 | preferences instead of the client's. When `true`, causes | @@ -2435,9 +2447,9 @@ changes: | 2435 | 2447 | description: Default value changed to `'auto'`. | 2436 | 2448 | --> | 2437 | 2449 |
| 2438 | | -The default curve name to use for ECDH key agreement in a tls server. The | 2439 | | -default value is `'auto'`. See [`tls.createSecureContext()`][] for further | 2440 | | -information. | | 2450 | +The default named curve or TLS group list to use for key agreement in a TLS | | 2451 | +server. The default value is `'auto'`. See [`tls.createSecureContext()`][] for | | 2452 | +further information. | 2441 | 2453 |
| 2442 | 2454 | ## `tls.DEFAULT_MAX_VERSION` | 2443 | 2455 |
| @@ -2485,6 +2497,7 @@ added: v0.11.3 | 2485 | 2497 | [Chrome's 'modern cryptography' setting]: https://www.chromium.org/Home/chromium-security/education/tls#TOC-Cipher-Suites | 2486 | 2498 | [DHE]: https://en.wikipedia.org/wiki/Diffie%E2%80%93Hellman_key_exchange | 2487 | 2499 | [ECDHE]: https://en.wikipedia.org/wiki/Elliptic_curve_Diffie%E2%80%93Hellman | | 2500 | +[IANA TLS Supported Groups registry]: https://www.iana.org/assignments/tls-parameters/tls-parameters.xhtml#tls-parameters-8 | 2488 | 2501 | [Modifying the default TLS cipher suite]: #modifying-the-default-tls-cipher-suite | 2489 | 2502 | [Mozilla's publicly trusted list of CAs]: https://hg.mozilla.org/mozilla-central/raw-file/tip/security/nss/lib/ckfw/builtins/certdata.txt | 2490 | 2503 | [OCSP request]: https://en.wikipedia.org/wiki/OCSP_stapling | |
Collapse file Copy file name to clipboardExpand all lines: src/crypto/crypto_common.cc +10-1Lines changed: 10 additions & 1 deletion | Original file line number | Diff line number | Diff line change |
|---|
@@ -215,13 +215,15 @@ MaybeLocal<Object> GetEphemeralKey(Environment* env, const SSLPointer& ssl) { | 215 | 215 | Undefined(env->isolate()), // name | 216 | 216 | Undefined(env->isolate()), // size | 217 | 217 | }; | 218 | | - EVPKeyPointer key = ssl.getPeerTempKey(); | | 218 | + | | 219 | + bool found = false; | 219 | 220 | if (EVPKeyPointer key = ssl.getPeerTempKey()) { | 220 | 221 | int kid = key.id(); | 221 | 222 | switch (kid) { | 222 | 223 | case EVP_PKEY_DH: { | 223 | 224 | values[0] = env->dh_string(); | 224 | 225 | values[2] = Integer::New(env->isolate(), key.bits()); | | 226 | + found = true; | 225 | 227 | break; | 226 | 228 | } | 227 | 229 | case EVP_PKEY_EC: | @@ -237,10 +239,17 @@ MaybeLocal<Object> GetEphemeralKey(Environment* env, const SSLPointer& ssl) { | 237 | 239 | values[0] = env->ecdh_string(); | 238 | 240 | values[1] = OneByteString(env->isolate(), curve_name); | 239 | 241 | values[2] = Integer::New(env->isolate(), key.bits()); | | 242 | + found = true; | 240 | 243 | break; | 241 | 244 | } | 242 | 245 | } | 243 | 246 | } | | 247 | + if (!found) { | | 248 | + if (auto name = ssl.getNegotiatedGroup()) { | | 249 | + values[0] = env->tls_group_string(); | | 250 | + values[1] = OneByteString(env->isolate(), name.value()); | | 251 | + } | | 252 | + } | 244 | 253 |
| 245 | 254 | return scope.EscapeMaybe(NewDictionaryInstance(env->context(), tmpl, values)); | 246 | 255 | } | |
Collapse file Copy file name to clipboardExpand all lines: src/env_properties.h +1Lines changed: 1 addition & 0 deletions | Original file line number | Diff line number | Diff line change |
|---|
| 363 | 363 | V(target_string, "target") \ | 364 | 364 | V(thread_id_string, "threadId") \ | 365 | 365 | V(thread_name_string, "threadName") \ | | 366 | + V(tls_group_string, "TLSGroup") \ | 366 | 367 | V(ticketkeycallback_string, "onticketkeycallback") \ | 367 | 368 | V(timeout_string, "timeout") \ | 368 | 369 | V(time_to_first_byte_string, "timeToFirstByte") \ | |
Collapse file Copy file name to clipboardExpand all lines: test/parallel/test-tls-client-getephemeralkeyinfo.js +54-3Lines changed: 54 additions & 3 deletions | Original file line number | Diff line number | Diff line change |
|---|
@@ -18,9 +18,6 @@ const tls = require('tls'); | 18 | 18 | const key = fixtures.readKey('agent2-key.pem'); | 19 | 19 | const cert = fixtures.readKey('agent2-cert.pem'); | 20 | 20 |
| 21 | | -// TODO(@sam-github) test works with TLS1.3, rework test to add | 22 | | -// 'ECDH' with 'TLS_AES_128_GCM_SHA256', | 23 | | - | 24 | 21 | function loadDHParam(n) { | 25 | 22 | return fixtures.readKey(`dh${n}.pem`); | 26 | 23 | } | @@ -89,3 +86,57 @@ test(256, 'ECDH', 'prime256v1', 'ECDHE-RSA-AES256-GCM-SHA384'); | 89 | 86 | test(521, 'ECDH', 'secp521r1', 'ECDHE-RSA-AES256-GCM-SHA384'); | 90 | 87 | test(253, 'ECDH', 'X25519', 'ECDHE-RSA-AES256-GCM-SHA384'); | 91 | 88 | test(448, 'ECDH', 'X448', 'ECDHE-RSA-AES256-GCM-SHA384'); | | 89 | + | | 90 | +function testTLS13Group(size, type, name) { | | 91 | + const options = { | | 92 | + key, | | 93 | + cert, | | 94 | + ecdhCurve: name, | | 95 | + minVersion: 'TLSv1.3', | | 96 | + maxVersion: 'TLSv1.3', | | 97 | + }; | | 98 | + | | 99 | + const server = tls.createServer(options, common.mustCall((conn) => { | | 100 | + assert.strictEqual(conn.getEphemeralKeyInfo(), null); | | 101 | + conn.end(); | | 102 | + })); | | 103 | + | | 104 | + server.on('close', common.mustSucceed()); | | 105 | + | | 106 | + server.listen(0, common.mustCall(() => { | | 107 | + const client = tls.connect({ | | 108 | + port: server.address().port, | | 109 | + rejectUnauthorized: false, | | 110 | + ecdhCurve: name, | | 111 | + minVersion: 'TLSv1.3', | | 112 | + maxVersion: 'TLSv1.3', | | 113 | + }, common.mustCall(() => { | | 114 | + const ekeyinfo = client.getEphemeralKeyInfo(); | | 115 | + assert.strictEqual(ekeyinfo.type, type); | | 116 | + assert.strictEqual(ekeyinfo.size, size); | | 117 | + assert.strictEqual(ekeyinfo.name, name); | | 118 | + server.close(); | | 119 | + })); | | 120 | + client.on('secureConnect', common.mustCall()); | | 121 | + })); | | 122 | +} | | 123 | + | | 124 | +testTLS13Group(253, 'ECDH', 'X25519'); | | 125 | + | | 126 | +if (hasOpenSSL(3, 5)) { | | 127 | + const tls13Groups = [ | | 128 | + 'MLKEM512', | | 129 | + 'MLKEM768', | | 130 | + 'MLKEM1024', | | 131 | + 'SecP256r1MLKEM768', | | 132 | + 'X25519MLKEM768', | | 133 | + 'SecP384r1MLKEM1024', | | 134 | + ]; | | 135 | + | | 136 | + if (hasOpenSSL(4, 0)) { | | 137 | + tls13Groups.push('curveSM2'); | | 138 | + tls13Groups.push('curveSM2MLKEM768'); | | 139 | + } | | 140 | + | | 141 | + tls13Groups.forEach((name) => testTLS13Group(undefined, 'TLSGroup', name)); | | 142 | +} |
|