├── LICENSE ├── LICENSE-Go ├── README.en.md ├── README.md ├── alert.go ├── auth.go ├── cache.go ├── cipher_suites.go ├── common.go ├── common_string.go ├── conn.go ├── defaults.go ├── defaults_boring.go ├── defaults_fips140.go ├── ech.go ├── fips140tls └── fipstls.go ├── generate_cert.go ├── go.mod ├── go.sum ├── handshake_client.go ├── handshake_client_tls13.go ├── handshake_messages.go ├── handshake_server.go ├── handshake_server_tls13.go ├── hpke └── hpye.go ├── key_agreement.go ├── key_schedule.go ├── prf.go ├── quic.go ├── ticket.go ├── tls.go ├── tls12 └── tls12.go └── tls13 └── tls13.go /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2023 RPRX. All rights reserved. 2 | 3 | Mozilla Public License Version 2.0 4 | ================================== 5 | 6 | 1. Definitions 7 | -------------- 8 | 9 | 1.1. "Contributor" 10 | means each individual or legal entity that creates, contributes to 11 | the creation of, or owns Covered Software. 12 | 13 | 1.2. "Contributor Version" 14 | means the combination of the Contributions of others (if any) used 15 | by a Contributor and that particular Contributor's Contribution. 16 | 17 | 1.3. "Contribution" 18 | means Covered Software of a particular Contributor. 19 | 20 | 1.4. "Covered Software" 21 | means Source Code Form to which the initial Contributor has attached 22 | the notice in Exhibit A, the Executable Form of such Source Code 23 | Form, and Modifications of such Source Code Form, in each case 24 | including portions thereof. 25 | 26 | 1.5. "Incompatible With Secondary Licenses" 27 | means 28 | 29 | (a) that the initial Contributor has attached the notice described 30 | in Exhibit B to the Covered Software; or 31 | 32 | (b) that the Covered Software was made available under the terms of 33 | version 1.1 or earlier of the License, but not also under the 34 | terms of a Secondary License. 35 | 36 | 1.6. "Executable Form" 37 | means any form of the work other than Source Code Form. 38 | 39 | 1.7. "Larger Work" 40 | means a work that combines Covered Software with other material, in 41 | a separate file or files, that is not Covered Software. 42 | 43 | 1.8. "License" 44 | means this document. 45 | 46 | 1.9. "Licensable" 47 | means having the right to grant, to the maximum extent possible, 48 | whether at the time of the initial grant or subsequently, any and 49 | all of the rights conveyed by this License. 50 | 51 | 1.10. "Modifications" 52 | means any of the following: 53 | 54 | (a) any file in Source Code Form that results from an addition to, 55 | deletion from, or modification of the contents of Covered 56 | Software; or 57 | 58 | (b) any new file in Source Code Form that contains any Covered 59 | Software. 60 | 61 | 1.11. "Patent Claims" of a Contributor 62 | means any patent claim(s), including without limitation, method, 63 | process, and apparatus claims, in any patent Licensable by such 64 | Contributor that would be infringed, but for the grant of the 65 | License, by the making, using, selling, offering for sale, having 66 | made, import, or transfer of either its Contributions or its 67 | Contributor Version. 68 | 69 | 1.12. "Secondary License" 70 | means either the GNU General Public License, Version 2.0, the GNU 71 | Lesser General Public License, Version 2.1, the GNU Affero General 72 | Public License, Version 3.0, or any later versions of those 73 | licenses. 74 | 75 | 1.13. "Source Code Form" 76 | means the form of the work preferred for making modifications. 77 | 78 | 1.14. "You" (or "Your") 79 | means an individual or a legal entity exercising rights under this 80 | License. For legal entities, "You" includes any entity that 81 | controls, is controlled by, or is under common control with You. For 82 | purposes of this definition, "control" means (a) the power, direct 83 | or indirect, to cause the direction or management of such entity, 84 | whether by contract or otherwise, or (b) ownership of more than 85 | fifty percent (50%) of the outstanding shares or beneficial 86 | ownership of such entity. 87 | 88 | 2. License Grants and Conditions 89 | -------------------------------- 90 | 91 | 2.1. Grants 92 | 93 | Each Contributor hereby grants You a world-wide, royalty-free, 94 | non-exclusive license: 95 | 96 | (a) under intellectual property rights (other than patent or trademark) 97 | Licensable by such Contributor to use, reproduce, make available, 98 | modify, display, perform, distribute, and otherwise exploit its 99 | Contributions, either on an unmodified basis, with Modifications, or 100 | as part of a Larger Work; and 101 | 102 | (b) under Patent Claims of such Contributor to make, use, sell, offer 103 | for sale, have made, import, and otherwise transfer either its 104 | Contributions or its Contributor Version. 105 | 106 | 2.2. Effective Date 107 | 108 | The licenses granted in Section 2.1 with respect to any Contribution 109 | become effective for each Contribution on the date the Contributor first 110 | distributes such Contribution. 111 | 112 | 2.3. Limitations on Grant Scope 113 | 114 | The licenses granted in this Section 2 are the only rights granted under 115 | this License. No additional rights or licenses will be implied from the 116 | distribution or licensing of Covered Software under this License. 117 | Notwithstanding Section 2.1(b) above, no patent license is granted by a 118 | Contributor: 119 | 120 | (a) for any code that a Contributor has removed from Covered Software; 121 | or 122 | 123 | (b) for infringements caused by: (i) Your and any other third party's 124 | modifications of Covered Software, or (ii) the combination of its 125 | Contributions with other software (except as part of its Contributor 126 | Version); or 127 | 128 | (c) under Patent Claims infringed by Covered Software in the absence of 129 | its Contributions. 130 | 131 | This License does not grant any rights in the trademarks, service marks, 132 | or logos of any Contributor (except as may be necessary to comply with 133 | the notice requirements in Section 3.4). 134 | 135 | 2.4. Subsequent Licenses 136 | 137 | No Contributor makes additional grants as a result of Your choice to 138 | distribute the Covered Software under a subsequent version of this 139 | License (see Section 10.2) or under the terms of a Secondary License (if 140 | permitted under the terms of Section 3.3). 141 | 142 | 2.5. Representation 143 | 144 | Each Contributor represents that the Contributor believes its 145 | Contributions are its original creation(s) or it has sufficient rights 146 | to grant the rights to its Contributions conveyed by this License. 147 | 148 | 2.6. Fair Use 149 | 150 | This License is not intended to limit any rights You have under 151 | applicable copyright doctrines of fair use, fair dealing, or other 152 | equivalents. 153 | 154 | 2.7. Conditions 155 | 156 | Sections 3.1, 3.2, 3.3, and 3.4 are conditions of the licenses granted 157 | in Section 2.1. 158 | 159 | 3. Responsibilities 160 | ------------------- 161 | 162 | 3.1. Distribution of Source Form 163 | 164 | All distribution of Covered Software in Source Code Form, including any 165 | Modifications that You create or to which You contribute, must be under 166 | the terms of this License. You must inform recipients that the Source 167 | Code Form of the Covered Software is governed by the terms of this 168 | License, and how they can obtain a copy of this License. You may not 169 | attempt to alter or restrict the recipients' rights in the Source Code 170 | Form. 171 | 172 | 3.2. Distribution of Executable Form 173 | 174 | If You distribute Covered Software in Executable Form then: 175 | 176 | (a) such Covered Software must also be made available in Source Code 177 | Form, as described in Section 3.1, and You must inform recipients of 178 | the Executable Form how they can obtain a copy of such Source Code 179 | Form by reasonable means in a timely manner, at a charge no more 180 | than the cost of distribution to the recipient; and 181 | 182 | (b) You may distribute such Executable Form under the terms of this 183 | License, or sublicense it under different terms, provided that the 184 | license for the Executable Form does not attempt to limit or alter 185 | the recipients' rights in the Source Code Form under this License. 186 | 187 | 3.3. Distribution of a Larger Work 188 | 189 | You may create and distribute a Larger Work under terms of Your choice, 190 | provided that You also comply with the requirements of this License for 191 | the Covered Software. If the Larger Work is a combination of Covered 192 | Software with a work governed by one or more Secondary Licenses, and the 193 | Covered Software is not Incompatible With Secondary Licenses, this 194 | License permits You to additionally distribute such Covered Software 195 | under the terms of such Secondary License(s), so that the recipient of 196 | the Larger Work may, at their option, further distribute the Covered 197 | Software under the terms of either this License or such Secondary 198 | License(s). 199 | 200 | 3.4. Notices 201 | 202 | You may not remove or alter the substance of any license notices 203 | (including copyright notices, patent notices, disclaimers of warranty, 204 | or limitations of liability) contained within the Source Code Form of 205 | the Covered Software, except that You may alter any license notices to 206 | the extent required to remedy known factual inaccuracies. 207 | 208 | 3.5. Application of Additional Terms 209 | 210 | You may choose to offer, and to charge a fee for, warranty, support, 211 | indemnity or liability obligations to one or more recipients of Covered 212 | Software. However, You may do so only on Your own behalf, and not on 213 | behalf of any Contributor. You must make it absolutely clear that any 214 | such warranty, support, indemnity, or liability obligation is offered by 215 | You alone, and You hereby agree to indemnify every Contributor for any 216 | liability incurred by such Contributor as a result of warranty, support, 217 | indemnity or liability terms You offer. You may include additional 218 | disclaimers of warranty and limitations of liability specific to any 219 | jurisdiction. 220 | 221 | 4. Inability to Comply Due to Statute or Regulation 222 | --------------------------------------------------- 223 | 224 | If it is impossible for You to comply with any of the terms of this 225 | License with respect to some or all of the Covered Software due to 226 | statute, judicial order, or regulation then You must: (a) comply with 227 | the terms of this License to the maximum extent possible; and (b) 228 | describe the limitations and the code they affect. Such description must 229 | be placed in a text file included with all distributions of the Covered 230 | Software under this License. Except to the extent prohibited by statute 231 | or regulation, such description must be sufficiently detailed for a 232 | recipient of ordinary skill to be able to understand it. 233 | 234 | 5. Termination 235 | -------------- 236 | 237 | 5.1. The rights granted under this License will terminate automatically 238 | if You fail to comply with any of its terms. However, if You become 239 | compliant, then the rights granted under this License from a particular 240 | Contributor are reinstated (a) provisionally, unless and until such 241 | Contributor explicitly and finally terminates Your grants, and (b) on an 242 | ongoing basis, if such Contributor fails to notify You of the 243 | non-compliance by some reasonable means prior to 60 days after You have 244 | come back into compliance. Moreover, Your grants from a particular 245 | Contributor are reinstated on an ongoing basis if such Contributor 246 | notifies You of the non-compliance by some reasonable means, this is the 247 | first time You have received notice of non-compliance with this License 248 | from such Contributor, and You become compliant prior to 30 days after 249 | Your receipt of the notice. 250 | 251 | 5.2. If You initiate litigation against any entity by asserting a patent 252 | infringement claim (excluding declaratory judgment actions, 253 | counter-claims, and cross-claims) alleging that a Contributor Version 254 | directly or indirectly infringes any patent, then the rights granted to 255 | You by any and all Contributors for the Covered Software under Section 256 | 2.1 of this License shall terminate. 257 | 258 | 5.3. In the event of termination under Sections 5.1 or 5.2 above, all 259 | end user license agreements (excluding distributors and resellers) which 260 | have been validly granted by You or Your distributors under this License 261 | prior to termination shall survive termination. 262 | 263 | ************************************************************************ 264 | * * 265 | * 6. Disclaimer of Warranty * 266 | * ------------------------- * 267 | * * 268 | * Covered Software is provided under this License on an "as is" * 269 | * basis, without warranty of any kind, either expressed, implied, or * 270 | * statutory, including, without limitation, warranties that the * 271 | * Covered Software is free of defects, merchantable, fit for a * 272 | * particular purpose or non-infringing. The entire risk as to the * 273 | * quality and performance of the Covered Software is with You. * 274 | * Should any Covered Software prove defective in any respect, You * 275 | * (not any Contributor) assume the cost of any necessary servicing, * 276 | * repair, or correction. This disclaimer of warranty constitutes an * 277 | * essential part of this License. No use of any Covered Software is * 278 | * authorized under this License except under this disclaimer. * 279 | * * 280 | ************************************************************************ 281 | 282 | ************************************************************************ 283 | * * 284 | * 7. Limitation of Liability * 285 | * -------------------------- * 286 | * * 287 | * Under no circumstances and under no legal theory, whether tort * 288 | * (including negligence), contract, or otherwise, shall any * 289 | * Contributor, or anyone who distributes Covered Software as * 290 | * permitted above, be liable to You for any direct, indirect, * 291 | * special, incidental, or consequential damages of any character * 292 | * including, without limitation, damages for lost profits, loss of * 293 | * goodwill, work stoppage, computer failure or malfunction, or any * 294 | * and all other commercial damages or losses, even if such party * 295 | * shall have been informed of the possibility of such damages. This * 296 | * limitation of liability shall not apply to liability for death or * 297 | * personal injury resulting from such party's negligence to the * 298 | * extent applicable law prohibits such limitation. Some * 299 | * jurisdictions do not allow the exclusion or limitation of * 300 | * incidental or consequential damages, so this exclusion and * 301 | * limitation may not apply to You. * 302 | * * 303 | ************************************************************************ 304 | 305 | 8. Litigation 306 | ------------- 307 | 308 | Any litigation relating to this License may be brought only in the 309 | courts of a jurisdiction where the defendant maintains its principal 310 | place of business and such litigation shall be governed by laws of that 311 | jurisdiction, without reference to its conflict-of-law provisions. 312 | Nothing in this Section shall prevent a party's ability to bring 313 | cross-claims or counter-claims. 314 | 315 | 9. Miscellaneous 316 | ---------------- 317 | 318 | This License represents the complete agreement concerning the subject 319 | matter hereof. If any provision of this License is held to be 320 | unenforceable, such provision shall be reformed only to the extent 321 | necessary to make it enforceable. Any law or regulation which provides 322 | that the language of a contract shall be construed against the drafter 323 | shall not be used to construe this License against a Contributor. 324 | 325 | 10. Versions of the License 326 | --------------------------- 327 | 328 | 10.1. New Versions 329 | 330 | Mozilla Foundation is the license steward. Except as provided in Section 331 | 10.3, no one other than the license steward has the right to modify or 332 | publish new versions of this License. Each version will be given a 333 | distinguishing version number. 334 | 335 | 10.2. Effect of New Versions 336 | 337 | You may distribute the Covered Software under the terms of the version 338 | of the License under which You originally received the Covered Software, 339 | or under the terms of any subsequent version published by the license 340 | steward. 341 | 342 | 10.3. Modified Versions 343 | 344 | If you create software not governed by this License, and you want to 345 | create a new license for such software, you may create and use a 346 | modified version of this License if you rename the license and remove 347 | any references to the name of the license steward (except to note that 348 | such modified license differs from this License). 349 | 350 | 10.4. Distributing Source Code Form that is Incompatible With Secondary 351 | Licenses 352 | 353 | If You choose to distribute Source Code Form that is Incompatible With 354 | Secondary Licenses under the terms of this version of the License, the 355 | notice described in Exhibit B of this License must be attached. 356 | 357 | Exhibit A - Source Code Form License Notice 358 | ------------------------------------------- 359 | 360 | This Source Code Form is subject to the terms of the Mozilla Public 361 | License, v. 2.0. If a copy of the MPL was not distributed with this 362 | file, You can obtain one at http://mozilla.org/MPL/2.0/. 363 | 364 | If it is not possible or desirable to put the notice in a particular 365 | file, then You may include the notice in a location (such as a LICENSE 366 | file in a relevant directory) where a recipient would be likely to look 367 | for such a notice. 368 | 369 | You may add additional accurate notices of copyright ownership. 370 | 371 | Exhibit B - "Incompatible With Secondary Licenses" Notice 372 | --------------------------------------------------------- 373 | 374 | This Source Code Form is "Incompatible With Secondary Licenses", as 375 | defined by the Mozilla Public License, v. 2.0. 376 | -------------------------------------------------------------------------------- /LICENSE-Go: -------------------------------------------------------------------------------- 1 | Copyright (c) 2009 The Go Authors. All rights reserved. 2 | 3 | Redistribution and use in source and binary forms, with or without 4 | modification, are permitted provided that the following conditions are 5 | met: 6 | 7 | * Redistributions of source code must retain the above copyright 8 | notice, this list of conditions and the following disclaimer. 9 | * Redistributions in binary form must reproduce the above 10 | copyright notice, this list of conditions and the following disclaimer 11 | in the documentation and/or other materials provided with the 12 | distribution. 13 | * Neither the name of Google Inc. nor the names of its 14 | contributors may be used to endorse or promote products derived from 15 | this software without specific prior written permission. 16 | 17 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 18 | "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 19 | LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 20 | A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 21 | OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 22 | SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 23 | LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 24 | DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 25 | THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 26 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 27 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 28 | -------------------------------------------------------------------------------- /README.en.md: -------------------------------------------------------------------------------- 1 | # REALITY 2 | 3 | ### THE NEXT FUTURE 4 | 5 | Server side implementation of REALITY protocol, a fork of package tls in latest [Go](https://github.com/golang/go/commits/master/src/crypto/tls). 6 | For client side, please follow https://github.com/XTLS/Xray-core/blob/main/transport/internet/reality/reality.go. 7 | 8 | TODO List: TODO 9 | 10 | ## VLESS-XTLS-uTLS-REALITY example for [Xray-core](https://github.com/XTLS/Xray-core) 11 | 12 | [中文](README.md) | English 13 | 14 | ```json5 15 | { 16 | "inbounds": [ // Server Inbound Configuration 17 | { 18 | "listen": "0.0.0.0", 19 | "port": 443, 20 | "protocol": "vless", 21 | "settings": { 22 | "clients": [ 23 | { 24 | "id": "", // Required, execute ./xray uuid to generate, or a string of 1-30 characters 25 | "flow": "xtls-rprx-vision" // Optional, if any, client must enable XTLS 26 | } 27 | ], 28 | "decryption": "none" 29 | }, 30 | "streamSettings": { 31 | "network": "tcp", 32 | "security": "reality", 33 | "realitySettings": { 34 | "show": false, // Optional, if true, output debugging information 35 | "dest": "example.com:443", // Required, the format is the same as the dest of VLESS fallbacks 36 | "xver": 0, // Optional, the format is the same as xver of VLESS fallbacks 37 | "serverNames": [ // Required, the acceptable serverName list, does not support * wildcards for now 38 | "example.com", 39 | "www.example.com" 40 | ], 41 | "privateKey": "", // Required, execute ./xray x25519 to generate 42 | "minClientVer": "", // Optional, minimum client Xray version, format is x.y.z 43 | "maxClientVer": "", // Optional, the highest version of client Xray, the format is x.y.z 44 | "maxTimeDiff": 0, // Optional, the maximum time difference allowed, in milliseconds 45 | "shortIds": [ // Required, the acceptable shortId list, which can be used to distinguish different clients 46 | "", // If there is this item, the client shortId can be empty 47 | "0123456789abcdef" // 0 to f, the length is a multiple of 2, the maximum length is 16 48 | ] 49 | } 50 | } 51 | } 52 | ] 53 | } 54 | ``` 55 | 56 | REALITY is intented to replace the use of TLS, it can **eliminate the detectable TLS fingerprint on the server side**, while still maintain the forward secrecy, etc. **Guard against the certificate chain attack, thus its security exceeds conventional TLS** 57 | **REALITY can point to other people's websites**, no need to buy domain names, configure TLS server, more convenient to deploy a proxy service. It **achieves full real TLS that is undistingwishable with the specified SNI to the middleman** 58 | 59 | For general proxy purposes, the minimum standard of the target website: **Websites out of China's GFW, support TLSv1.3 and H2, the domain name is not used for redirection** (the main domain name may be used to redirect to www) 60 | Bonus points: target website IP reside closer to proxy IP (looks more reasonable, and lower latency), handshake messages after Server Hello are encrypted together (such as dl.google.com), OCSP Stapling 61 | Configuration bonus items: **Block the proxy traffic back to China, TCP/80, UDP/443 are also forwarded to target** (REALITY behaves like port forwarding to the observer, the target IP may be better if it is an uncommon choice among REALITY users) 62 | 63 | **REALITY can also be used with proxy protocols other than XTLS**, but this is not recommended due to their obvious and already targeted TLS in TLS characteristics 64 | The next main goal of REALITY is "**pre-built mode**", that is, to collect and build the characteristics of the target website in advance, and the next main goal of XTLS is **0-RTT** 65 | 66 | ```json5 67 | { 68 | "outbounds": [ // Client outbound configuration 69 | { 70 | "protocol": "vless", 71 | "settings": { 72 | "vnext": [ 73 | { 74 | "address": "", // The domain name or IP of the server 75 | "port": 443, 76 | "users": [ 77 | { 78 | "id": "", // consistent with the server 79 | "flow": "xtls-rprx-vision", // consistent with the server 80 | "encryption": "none" 81 | } 82 | ] 83 | } 84 | ] 85 | }, 86 | "streamSettings": { 87 | "network": "tcp", 88 | "security": "reality", 89 | "realitySettings": { 90 | "show": false, // Optional, if true, output debugging information 91 | "fingerprint": "chrome", // Required, use uTLS library to emulate client TLS fingerprint 92 | "serverName": "", // One of the server serverNames 93 | "publicKey": "", // The public key corresponding to the private key of the server 94 | "shortId": "", // One of the server shortIds 95 | "spiderX": "" // The initial path and parameters of the crawler, recommended to be different for each client 96 | } 97 | } 98 | } 99 | ] 100 | } 101 | ``` 102 | 103 | The REALITY client should receive the "**Temporary Trusted Certificate**" issued by "**Temporary Authentication Key**", but the real certificate of the target website will be received in the following three cases: 104 | 105 | 1. The REALITY server rejects the Client Hello of the client, and the traffic is redirected to the target website 106 | 2. The Client Hello of the client is redirected to the target website by the middleman 107 | 3. Man-in-the-middle attack, it may be the help of the target website, or it may be a certificate chain attack 108 | 109 | The REALITY client can perfectly distinguish temporary trusted certificates, real certificates, and invalid certificates, and decide the next action: 110 | 111 | 1. When the temporary trusted certificate is received, the proxy connection is available and everything is business as usual 112 | 2. When the real certificate is received, enter the crawler mode (spiderX) 113 | 3. When an invalid certificate is received, TLS alert will be sent and the connection will be disconnected 114 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # REALITY 2 | 3 | ### THE NEXT FUTURE 4 | 5 | Server side implementation of REALITY protocol, a fork of package tls in latest [Go](https://github.com/golang/go/commits/master/src/crypto/tls). 6 | For client side, please follow https://github.com/XTLS/Xray-core/blob/main/transport/internet/reality/reality.go. 7 | 8 | TODO List: TODO 9 | 10 | ## VLESS-XTLS-uTLS-REALITY example for [Xray-core](https://github.com/XTLS/Xray-core) 11 | 12 | 中文 | [English](README.en.md) 13 | 14 | ```json5 15 | { 16 | "inbounds": [ // 服务端入站配置 17 | { 18 | "listen": "0.0.0.0", 19 | "port": 443, 20 | "protocol": "vless", 21 | "settings": { 22 | "clients": [ 23 | { 24 | "id": "", // 必填,执行 ./xray uuid 生成,或 1-30 字节的字符串 25 | "flow": "xtls-rprx-vision" // 选填,若有,客户端必须启用 XTLS 26 | } 27 | ], 28 | "decryption": "none" 29 | }, 30 | "streamSettings": { 31 | "network": "tcp", 32 | "security": "reality", 33 | "realitySettings": { 34 | "show": false, // 选填,若为 true,输出调试信息 35 | "dest": "example.com:443", // 必填,格式同 VLESS fallbacks 的 dest 36 | "xver": 0, // 选填,格式同 VLESS fallbacks 的 xver 37 | "serverNames": [ // 必填,客户端可用的 serverName 列表,暂不支持 * 通配符 38 | "example.com", 39 | "www.example.com" 40 | ], 41 | "privateKey": "", // 必填,执行 ./xray x25519 生成 42 | "minClientVer": "", // 选填,客户端 Xray 最低版本,格式为 x.y.z 43 | "maxClientVer": "", // 选填,客户端 Xray 最高版本,格式为 x.y.z 44 | "maxTimeDiff": 0, // 选填,允许的最大时间差,单位为毫秒 45 | "shortIds": [ // 必填,客户端可用的 shortId 列表,可用于区分不同的客户端 46 | "", // 若有此项,客户端 shortId 可为空 47 | "0123456789abcdef" // 0 到 f,长度为 2 的倍数,长度上限为 16 48 | ] 49 | } 50 | } 51 | } 52 | ] 53 | } 54 | ``` 55 | 56 | 若用 REALITY 取代 TLS,**可消除服务端 TLS 指纹特征**,仍有前向保密性等,**且证书链攻击无效,安全性超越常规 TLS** 57 | **可以指向别人的网站**,无需自己买域名、配置 TLS 服务端,更方便,**实现向中间人呈现指定 SNI 的全程真实 TLS** 58 | 59 | 通常代理用途,目标网站最低标准:**国外网站,支持 TLSv1.3 与 H2,域名非跳转用**(主域名可能被用于跳转到 www) 60 | 加分项:IP 相近(更像,且延迟低),Server Hello 后的握手消息一起加密(如 dl.google.com),有 OCSP Stapling 61 | 配置加分项:**禁回国流量,TCP/80、UDP/443 也转发**(REALITY 对外表现即为端口转发,目标 IP 冷门或许更好) 62 | 63 | **REALITY 也可以搭配 XTLS 以外的代理协议使用**,但不建议这样做,因为它们存在明显且已被针对的 TLS in TLS 特征 64 | REALITY 的下一个主要目标是“**预先构建模式**”,即提前采集目标网站特征,XTLS 的下一个主要目标是 **0-RTT** 65 | 66 | ```json5 67 | { 68 | "outbounds": [ // 客户端出站配置 69 | { 70 | "protocol": "vless", 71 | "settings": { 72 | "vnext": [ 73 | { 74 | "address": "", // 服务端的域名或 IP 75 | "port": 443, 76 | "users": [ 77 | { 78 | "id": "", // 与服务端一致 79 | "flow": "xtls-rprx-vision", // 与服务端一致 80 | "encryption": "none" 81 | } 82 | ] 83 | } 84 | ] 85 | }, 86 | "streamSettings": { 87 | "network": "tcp", 88 | "security": "reality", 89 | "realitySettings": { 90 | "show": false, // 选填,若为 true,输出调试信息 91 | "fingerprint": "chrome", // 必填,使用 uTLS 库模拟客户端 TLS 指纹 92 | "serverName": "", // 服务端 serverNames 之一 93 | "publicKey": "", // 服务端私钥对应的公钥 94 | "shortId": "", // 服务端 shortIds 之一 95 | "spiderX": "" // 爬虫初始路径与参数,建议每个客户端不同 96 | } 97 | } 98 | } 99 | ] 100 | } 101 | ``` 102 | 103 | REALITY 客户端应当收到由“**临时认证密钥**”签发的“**临时可信证书**”,但以下三种情况会收到目标网站的真证书: 104 | 105 | 1. REALITY 服务端拒绝了客户端的 Client Hello,流量被导入目标网站 106 | 2. 客户端的 Client Hello 被中间人重定向至目标网站 107 | 3. 中间人攻击,可能是目标网站帮忙,也可能是证书链攻击 108 | 109 | REALITY 客户端可以完美区分临时可信证书、真证书、无效证书,并决定下一步动作: 110 | 111 | 1. 收到临时可信证书时,连接可用,一切如常 112 | 2. 收到真证书时,进入爬虫模式 113 | 3. 收到无效证书时,TLS alert,断开连接 114 | 115 | ## Stargazers over time 116 | 117 | [![Stargazers over time](https://starchart.cc/XTLS/REALITY.svg)](https://starchart.cc/XTLS/REALITY) 118 | -------------------------------------------------------------------------------- /alert.go: -------------------------------------------------------------------------------- 1 | // Copyright 2009 The Go Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE-Go file. 4 | 5 | package reality 6 | 7 | import "strconv" 8 | 9 | // An AlertError is a TLS alert. 10 | // 11 | // When using a QUIC transport, QUICConn methods will return an error 12 | // which wraps AlertError rather than sending a TLS alert. 13 | type AlertError uint8 14 | 15 | func (e AlertError) Error() string { 16 | return alert(e).String() 17 | } 18 | 19 | type alert uint8 20 | 21 | const ( 22 | // alert level 23 | alertLevelWarning = 1 24 | alertLevelError = 2 25 | ) 26 | 27 | const ( 28 | alertCloseNotify alert = 0 29 | alertUnexpectedMessage alert = 10 30 | alertBadRecordMAC alert = 20 31 | alertDecryptionFailed alert = 21 32 | alertRecordOverflow alert = 22 33 | alertDecompressionFailure alert = 30 34 | alertHandshakeFailure alert = 40 35 | alertBadCertificate alert = 42 36 | alertUnsupportedCertificate alert = 43 37 | alertCertificateRevoked alert = 44 38 | alertCertificateExpired alert = 45 39 | alertCertificateUnknown alert = 46 40 | alertIllegalParameter alert = 47 41 | alertUnknownCA alert = 48 42 | alertAccessDenied alert = 49 43 | alertDecodeError alert = 50 44 | alertDecryptError alert = 51 45 | alertExportRestriction alert = 60 46 | alertProtocolVersion alert = 70 47 | alertInsufficientSecurity alert = 71 48 | alertInternalError alert = 80 49 | alertInappropriateFallback alert = 86 50 | alertUserCanceled alert = 90 51 | alertNoRenegotiation alert = 100 52 | alertMissingExtension alert = 109 53 | alertUnsupportedExtension alert = 110 54 | alertCertificateUnobtainable alert = 111 55 | alertUnrecognizedName alert = 112 56 | alertBadCertificateStatusResponse alert = 113 57 | alertBadCertificateHashValue alert = 114 58 | alertUnknownPSKIdentity alert = 115 59 | alertCertificateRequired alert = 116 60 | alertNoApplicationProtocol alert = 120 61 | alertECHRequired alert = 121 62 | ) 63 | 64 | var alertText = map[alert]string{ 65 | alertCloseNotify: "close notify", 66 | alertUnexpectedMessage: "unexpected message", 67 | alertBadRecordMAC: "bad record MAC", 68 | alertDecryptionFailed: "decryption failed", 69 | alertRecordOverflow: "record overflow", 70 | alertDecompressionFailure: "decompression failure", 71 | alertHandshakeFailure: "handshake failure", 72 | alertBadCertificate: "bad certificate", 73 | alertUnsupportedCertificate: "unsupported certificate", 74 | alertCertificateRevoked: "revoked certificate", 75 | alertCertificateExpired: "expired certificate", 76 | alertCertificateUnknown: "unknown certificate", 77 | alertIllegalParameter: "illegal parameter", 78 | alertUnknownCA: "unknown certificate authority", 79 | alertAccessDenied: "access denied", 80 | alertDecodeError: "error decoding message", 81 | alertDecryptError: "error decrypting message", 82 | alertExportRestriction: "export restriction", 83 | alertProtocolVersion: "protocol version not supported", 84 | alertInsufficientSecurity: "insufficient security level", 85 | alertInternalError: "internal error", 86 | alertInappropriateFallback: "inappropriate fallback", 87 | alertUserCanceled: "user canceled", 88 | alertNoRenegotiation: "no renegotiation", 89 | alertMissingExtension: "missing extension", 90 | alertUnsupportedExtension: "unsupported extension", 91 | alertCertificateUnobtainable: "certificate unobtainable", 92 | alertUnrecognizedName: "unrecognized name", 93 | alertBadCertificateStatusResponse: "bad certificate status response", 94 | alertBadCertificateHashValue: "bad certificate hash value", 95 | alertUnknownPSKIdentity: "unknown PSK identity", 96 | alertCertificateRequired: "certificate required", 97 | alertNoApplicationProtocol: "no application protocol", 98 | alertECHRequired: "encrypted client hello required", 99 | } 100 | 101 | func (e alert) String() string { 102 | s, ok := alertText[e] 103 | if ok { 104 | return "tls: " + s 105 | } 106 | return "tls: alert(" + strconv.Itoa(int(e)) + ")" 107 | } 108 | 109 | func (e alert) Error() string { 110 | return e.String() 111 | } 112 | -------------------------------------------------------------------------------- /auth.go: -------------------------------------------------------------------------------- 1 | // Copyright 2017 The Go Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE-Go file. 4 | 5 | package reality 6 | 7 | import ( 8 | "bytes" 9 | "crypto" 10 | "crypto/ecdsa" 11 | "crypto/ed25519" 12 | "crypto/elliptic" 13 | "crypto/rsa" 14 | "errors" 15 | "fmt" 16 | "hash" 17 | "io" 18 | "slices" 19 | ) 20 | 21 | // verifyHandshakeSignature verifies a signature against pre-hashed 22 | // (if required) handshake contents. 23 | func verifyHandshakeSignature(sigType uint8, pubkey crypto.PublicKey, hashFunc crypto.Hash, signed, sig []byte) error { 24 | switch sigType { 25 | case signatureECDSA: 26 | pubKey, ok := pubkey.(*ecdsa.PublicKey) 27 | if !ok { 28 | return fmt.Errorf("expected an ECDSA public key, got %T", pubkey) 29 | } 30 | if !ecdsa.VerifyASN1(pubKey, signed, sig) { 31 | return errors.New("ECDSA verification failure") 32 | } 33 | case signatureEd25519: 34 | pubKey, ok := pubkey.(ed25519.PublicKey) 35 | if !ok { 36 | return fmt.Errorf("expected an Ed25519 public key, got %T", pubkey) 37 | } 38 | if !ed25519.Verify(pubKey, signed, sig) { 39 | return errors.New("Ed25519 verification failure") 40 | } 41 | case signaturePKCS1v15: 42 | pubKey, ok := pubkey.(*rsa.PublicKey) 43 | if !ok { 44 | return fmt.Errorf("expected an RSA public key, got %T", pubkey) 45 | } 46 | if err := rsa.VerifyPKCS1v15(pubKey, hashFunc, signed, sig); err != nil { 47 | return err 48 | } 49 | case signatureRSAPSS: 50 | pubKey, ok := pubkey.(*rsa.PublicKey) 51 | if !ok { 52 | return fmt.Errorf("expected an RSA public key, got %T", pubkey) 53 | } 54 | signOpts := &rsa.PSSOptions{SaltLength: rsa.PSSSaltLengthEqualsHash} 55 | if err := rsa.VerifyPSS(pubKey, hashFunc, signed, sig, signOpts); err != nil { 56 | return err 57 | } 58 | default: 59 | return errors.New("internal error: unknown signature type") 60 | } 61 | return nil 62 | } 63 | 64 | const ( 65 | serverSignatureContext = "TLS 1.3, server CertificateVerify\x00" 66 | clientSignatureContext = "TLS 1.3, client CertificateVerify\x00" 67 | ) 68 | 69 | var signaturePadding = []byte{ 70 | 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 71 | 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 72 | 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 73 | 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 74 | 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 75 | 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 76 | 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 77 | 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 78 | } 79 | 80 | // signedMessage returns the pre-hashed (if necessary) message to be signed by 81 | // certificate keys in TLS 1.3. See RFC 8446, Section 4.4.3. 82 | func signedMessage(sigHash crypto.Hash, context string, transcript hash.Hash) []byte { 83 | if sigHash == directSigning { 84 | b := &bytes.Buffer{} 85 | b.Write(signaturePadding) 86 | io.WriteString(b, context) 87 | b.Write(transcript.Sum(nil)) 88 | return b.Bytes() 89 | } 90 | h := sigHash.New() 91 | h.Write(signaturePadding) 92 | io.WriteString(h, context) 93 | h.Write(transcript.Sum(nil)) 94 | return h.Sum(nil) 95 | } 96 | 97 | // typeAndHashFromSignatureScheme returns the corresponding signature type and 98 | // crypto.Hash for a given TLS SignatureScheme. 99 | func typeAndHashFromSignatureScheme(signatureAlgorithm SignatureScheme) (sigType uint8, hash crypto.Hash, err error) { 100 | switch signatureAlgorithm { 101 | case PKCS1WithSHA1, PKCS1WithSHA256, PKCS1WithSHA384, PKCS1WithSHA512: 102 | sigType = signaturePKCS1v15 103 | case PSSWithSHA256, PSSWithSHA384, PSSWithSHA512: 104 | sigType = signatureRSAPSS 105 | case ECDSAWithSHA1, ECDSAWithP256AndSHA256, ECDSAWithP384AndSHA384, ECDSAWithP521AndSHA512: 106 | sigType = signatureECDSA 107 | case Ed25519: 108 | sigType = signatureEd25519 109 | default: 110 | return 0, 0, fmt.Errorf("unsupported signature algorithm: %v", signatureAlgorithm) 111 | } 112 | switch signatureAlgorithm { 113 | case PKCS1WithSHA1, ECDSAWithSHA1: 114 | hash = crypto.SHA1 115 | case PKCS1WithSHA256, PSSWithSHA256, ECDSAWithP256AndSHA256: 116 | hash = crypto.SHA256 117 | case PKCS1WithSHA384, PSSWithSHA384, ECDSAWithP384AndSHA384: 118 | hash = crypto.SHA384 119 | case PKCS1WithSHA512, PSSWithSHA512, ECDSAWithP521AndSHA512: 120 | hash = crypto.SHA512 121 | case Ed25519: 122 | hash = directSigning 123 | default: 124 | return 0, 0, fmt.Errorf("unsupported signature algorithm: %v", signatureAlgorithm) 125 | } 126 | return sigType, hash, nil 127 | } 128 | 129 | // legacyTypeAndHashFromPublicKey returns the fixed signature type and crypto.Hash for 130 | // a given public key used with TLS 1.0 and 1.1, before the introduction of 131 | // signature algorithm negotiation. 132 | func legacyTypeAndHashFromPublicKey(pub crypto.PublicKey) (sigType uint8, hash crypto.Hash, err error) { 133 | switch pub.(type) { 134 | case *rsa.PublicKey: 135 | return signaturePKCS1v15, crypto.MD5SHA1, nil 136 | case *ecdsa.PublicKey: 137 | return signatureECDSA, crypto.SHA1, nil 138 | case ed25519.PublicKey: 139 | // RFC 8422 specifies support for Ed25519 in TLS 1.0 and 1.1, 140 | // but it requires holding on to a handshake transcript to do a 141 | // full signature, and not even OpenSSL bothers with the 142 | // complexity, so we can't even test it properly. 143 | return 0, 0, fmt.Errorf("tls: Ed25519 public keys are not supported before TLS 1.2") 144 | default: 145 | return 0, 0, fmt.Errorf("tls: unsupported public key: %T", pub) 146 | } 147 | } 148 | 149 | var rsaSignatureSchemes = []struct { 150 | scheme SignatureScheme 151 | minModulusBytes int 152 | maxVersion uint16 153 | }{ 154 | // RSA-PSS is used with PSSSaltLengthEqualsHash, and requires 155 | // emLen >= hLen + sLen + 2 156 | {PSSWithSHA256, crypto.SHA256.Size()*2 + 2, VersionTLS13}, 157 | {PSSWithSHA384, crypto.SHA384.Size()*2 + 2, VersionTLS13}, 158 | {PSSWithSHA512, crypto.SHA512.Size()*2 + 2, VersionTLS13}, 159 | // PKCS #1 v1.5 uses prefixes from hashPrefixes in crypto/rsa, and requires 160 | // emLen >= len(prefix) + hLen + 11 161 | // TLS 1.3 dropped support for PKCS #1 v1.5 in favor of RSA-PSS. 162 | {PKCS1WithSHA256, 19 + crypto.SHA256.Size() + 11, VersionTLS12}, 163 | {PKCS1WithSHA384, 19 + crypto.SHA384.Size() + 11, VersionTLS12}, 164 | {PKCS1WithSHA512, 19 + crypto.SHA512.Size() + 11, VersionTLS12}, 165 | {PKCS1WithSHA1, 15 + crypto.SHA1.Size() + 11, VersionTLS12}, 166 | } 167 | 168 | // signatureSchemesForCertificate returns the list of supported SignatureSchemes 169 | // for a given certificate, based on the public key and the protocol version, 170 | // and optionally filtered by its explicit SupportedSignatureAlgorithms. 171 | func signatureSchemesForCertificate(version uint16, cert *Certificate) []SignatureScheme { 172 | priv, ok := cert.PrivateKey.(crypto.Signer) 173 | if !ok { 174 | return nil 175 | } 176 | 177 | var sigAlgs []SignatureScheme 178 | switch pub := priv.Public().(type) { 179 | case *ecdsa.PublicKey: 180 | if version != VersionTLS13 { 181 | // In TLS 1.2 and earlier, ECDSA algorithms are not 182 | // constrained to a single curve. 183 | sigAlgs = []SignatureScheme{ 184 | ECDSAWithP256AndSHA256, 185 | ECDSAWithP384AndSHA384, 186 | ECDSAWithP521AndSHA512, 187 | ECDSAWithSHA1, 188 | } 189 | break 190 | } 191 | switch pub.Curve { 192 | case elliptic.P256(): 193 | sigAlgs = []SignatureScheme{ECDSAWithP256AndSHA256} 194 | case elliptic.P384(): 195 | sigAlgs = []SignatureScheme{ECDSAWithP384AndSHA384} 196 | case elliptic.P521(): 197 | sigAlgs = []SignatureScheme{ECDSAWithP521AndSHA512} 198 | default: 199 | return nil 200 | } 201 | case *rsa.PublicKey: 202 | size := pub.Size() 203 | sigAlgs = make([]SignatureScheme, 0, len(rsaSignatureSchemes)) 204 | for _, candidate := range rsaSignatureSchemes { 205 | if size >= candidate.minModulusBytes && version <= candidate.maxVersion { 206 | sigAlgs = append(sigAlgs, candidate.scheme) 207 | } 208 | } 209 | case ed25519.PublicKey: 210 | sigAlgs = []SignatureScheme{Ed25519} 211 | default: 212 | return nil 213 | } 214 | 215 | if cert.SupportedSignatureAlgorithms != nil { 216 | sigAlgs = slices.DeleteFunc(sigAlgs, func(sigAlg SignatureScheme) bool { 217 | return !isSupportedSignatureAlgorithm(sigAlg, cert.SupportedSignatureAlgorithms) 218 | }) 219 | } 220 | 221 | // Filter out any unsupported signature algorithms, for example due to 222 | // FIPS 140-3 policy, tlssha1=0, or any downstream changes to defaults.go. 223 | supportedAlgs := supportedSignatureAlgorithms(version) 224 | sigAlgs = slices.DeleteFunc(sigAlgs, func(sigAlg SignatureScheme) bool { 225 | return !isSupportedSignatureAlgorithm(sigAlg, supportedAlgs) 226 | }) 227 | 228 | return sigAlgs 229 | } 230 | 231 | // selectSignatureScheme picks a SignatureScheme from the peer's preference list 232 | // that works with the selected certificate. It's only called for protocol 233 | // versions that support signature algorithms, so TLS 1.2 and 1.3. 234 | func selectSignatureScheme(vers uint16, c *Certificate, peerAlgs []SignatureScheme) (SignatureScheme, error) { 235 | supportedAlgs := signatureSchemesForCertificate(vers, c) 236 | if len(supportedAlgs) == 0 { 237 | return 0, unsupportedCertificateError(c) 238 | } 239 | if len(peerAlgs) == 0 && vers == VersionTLS12 { 240 | // For TLS 1.2, if the client didn't send signature_algorithms then we 241 | // can assume that it supports SHA1. See RFC 5246, Section 7.4.1.4.1. 242 | // RFC 9155 made signature_algorithms mandatory in TLS 1.2, and we gated 243 | // it behind the tlssha1 GODEBUG setting. 244 | // if tlssha1.Value() != "1" { 245 | return 0, errors.New("tls: missing signature_algorithms from TLS 1.2 peer") 246 | // } 247 | // peerAlgs = []SignatureScheme{PKCS1WithSHA1, ECDSAWithSHA1} 248 | } 249 | // Pick signature scheme in the peer's preference order, as our 250 | // preference order is not configurable. 251 | for _, preferredAlg := range peerAlgs { 252 | if isSupportedSignatureAlgorithm(preferredAlg, supportedAlgs) { 253 | return preferredAlg, nil 254 | } 255 | } 256 | return 0, errors.New("tls: peer doesn't support any of the certificate's signature algorithms") 257 | } 258 | 259 | // unsupportedCertificateError returns a helpful error for certificates with 260 | // an unsupported private key. 261 | func unsupportedCertificateError(cert *Certificate) error { 262 | switch cert.PrivateKey.(type) { 263 | case rsa.PrivateKey, ecdsa.PrivateKey: 264 | return fmt.Errorf("tls: unsupported certificate: private key is %T, expected *%T", 265 | cert.PrivateKey, cert.PrivateKey) 266 | case *ed25519.PrivateKey: 267 | return fmt.Errorf("tls: unsupported certificate: private key is *ed25519.PrivateKey, expected ed25519.PrivateKey") 268 | } 269 | 270 | signer, ok := cert.PrivateKey.(crypto.Signer) 271 | if !ok { 272 | return fmt.Errorf("tls: certificate private key (%T) does not implement crypto.Signer", 273 | cert.PrivateKey) 274 | } 275 | 276 | switch pub := signer.Public().(type) { 277 | case *ecdsa.PublicKey: 278 | switch pub.Curve { 279 | case elliptic.P256(): 280 | case elliptic.P384(): 281 | case elliptic.P521(): 282 | default: 283 | return fmt.Errorf("tls: unsupported certificate curve (%s)", pub.Curve.Params().Name) 284 | } 285 | case *rsa.PublicKey: 286 | return fmt.Errorf("tls: certificate RSA key size too small for supported signature algorithms") 287 | case ed25519.PublicKey: 288 | default: 289 | return fmt.Errorf("tls: unsupported certificate key (%T)", pub) 290 | } 291 | 292 | if cert.SupportedSignatureAlgorithms != nil { 293 | return fmt.Errorf("tls: peer doesn't support the certificate custom signature algorithms") 294 | } 295 | 296 | return fmt.Errorf("tls: internal error: unsupported key (%T)", cert.PrivateKey) 297 | } 298 | -------------------------------------------------------------------------------- /cache.go: -------------------------------------------------------------------------------- 1 | // Copyright 2022 The Go Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE-Go file. 4 | 5 | package reality 6 | 7 | import ( 8 | "crypto/x509" 9 | "runtime" 10 | "sync" 11 | "weak" 12 | ) 13 | 14 | // weakCertCache provides a cache of *x509.Certificates, allowing multiple 15 | // connections to reuse parsed certificates, instead of re-parsing the 16 | // certificate for every connection, which is an expensive operation. 17 | type weakCertCache struct{ sync.Map } 18 | 19 | func (wcc *weakCertCache) newCert(der []byte) (*x509.Certificate, error) { 20 | if entry, ok := wcc.Load(string(der)); ok { 21 | if v := entry.(weak.Pointer[x509.Certificate]).Value(); v != nil { 22 | return v, nil 23 | } 24 | } 25 | 26 | cert, err := x509.ParseCertificate(der) 27 | if err != nil { 28 | return nil, err 29 | } 30 | 31 | wp := weak.Make(cert) 32 | if entry, loaded := wcc.LoadOrStore(string(der), wp); !loaded { 33 | runtime.AddCleanup(cert, func(_ any) { wcc.CompareAndDelete(string(der), entry) }, any(string(der))) 34 | } else if v := entry.(weak.Pointer[x509.Certificate]).Value(); v != nil { 35 | return v, nil 36 | } else { 37 | if wcc.CompareAndSwap(string(der), entry, wp) { 38 | runtime.AddCleanup(cert, func(_ any) { wcc.CompareAndDelete(string(der), wp) }, any(string(der))) 39 | } 40 | } 41 | return cert, nil 42 | } 43 | 44 | var globalCertCache = new(weakCertCache) -------------------------------------------------------------------------------- /cipher_suites.go: -------------------------------------------------------------------------------- 1 | // Copyright 2010 The Go Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE-Go file. 4 | 5 | package reality 6 | 7 | import ( 8 | "crypto" 9 | "crypto/aes" 10 | "crypto/cipher" 11 | "crypto/des" 12 | "crypto/hmac" 13 | "crypto/rc4" 14 | "crypto/sha1" 15 | "crypto/sha256" 16 | "fmt" 17 | "hash" 18 | "runtime" 19 | _ "unsafe" // for linkname 20 | 21 | "golang.org/x/crypto/chacha20poly1305" 22 | "golang.org/x/sys/cpu" 23 | ) 24 | 25 | // CipherSuite is a TLS cipher suite. Note that most functions in this package 26 | // accept and expose cipher suite IDs instead of this type. 27 | type CipherSuite struct { 28 | ID uint16 29 | Name string 30 | 31 | // Supported versions is the list of TLS protocol versions that can 32 | // negotiate this cipher suite. 33 | SupportedVersions []uint16 34 | 35 | // Insecure is true if the cipher suite has known security issues 36 | // due to its primitives, design, or implementation. 37 | Insecure bool 38 | } 39 | 40 | var ( 41 | supportedUpToTLS12 = []uint16{VersionTLS10, VersionTLS11, VersionTLS12} 42 | supportedOnlyTLS12 = []uint16{VersionTLS12} 43 | supportedOnlyTLS13 = []uint16{VersionTLS13} 44 | ) 45 | 46 | // CipherSuites returns a list of cipher suites currently implemented by this 47 | // package, excluding those with security issues, which are returned by 48 | // [InsecureCipherSuites]. 49 | // 50 | // The list is sorted by ID. Note that the default cipher suites selected by 51 | // this package might depend on logic that can't be captured by a static list, 52 | // and might not match those returned by this function. 53 | func CipherSuites() []*CipherSuite { 54 | return []*CipherSuite{ 55 | {TLS_AES_128_GCM_SHA256, "TLS_AES_128_GCM_SHA256", supportedOnlyTLS13, false}, 56 | {TLS_AES_256_GCM_SHA384, "TLS_AES_256_GCM_SHA384", supportedOnlyTLS13, false}, 57 | {TLS_CHACHA20_POLY1305_SHA256, "TLS_CHACHA20_POLY1305_SHA256", supportedOnlyTLS13, false}, 58 | 59 | {TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA, "TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA", supportedUpToTLS12, false}, 60 | {TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA, "TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA", supportedUpToTLS12, false}, 61 | {TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA, "TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA", supportedUpToTLS12, false}, 62 | {TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA, "TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA", supportedUpToTLS12, false}, 63 | {TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256, "TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256", supportedOnlyTLS12, false}, 64 | {TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384, "TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384", supportedOnlyTLS12, false}, 65 | {TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256, "TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256", supportedOnlyTLS12, false}, 66 | {TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384, "TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384", supportedOnlyTLS12, false}, 67 | {TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256, "TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256", supportedOnlyTLS12, false}, 68 | {TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256, "TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256", supportedOnlyTLS12, false}, 69 | } 70 | } 71 | 72 | // InsecureCipherSuites returns a list of cipher suites currently implemented by 73 | // this package and which have security issues. 74 | // 75 | // Most applications should not use the cipher suites in this list, and should 76 | // only use those returned by [CipherSuites]. 77 | func InsecureCipherSuites() []*CipherSuite { 78 | // This list includes legacy RSA kex, RC4, CBC_SHA256, and 3DES cipher 79 | // suites. See cipherSuitesPreferenceOrder for details. 80 | return []*CipherSuite{ 81 | {TLS_RSA_WITH_RC4_128_SHA, "TLS_RSA_WITH_RC4_128_SHA", supportedUpToTLS12, true}, 82 | {TLS_RSA_WITH_3DES_EDE_CBC_SHA, "TLS_RSA_WITH_3DES_EDE_CBC_SHA", supportedUpToTLS12, true}, 83 | {TLS_RSA_WITH_AES_128_CBC_SHA, "TLS_RSA_WITH_AES_128_CBC_SHA", supportedUpToTLS12, true}, 84 | {TLS_RSA_WITH_AES_256_CBC_SHA, "TLS_RSA_WITH_AES_256_CBC_SHA", supportedUpToTLS12, true}, 85 | {TLS_RSA_WITH_AES_128_CBC_SHA256, "TLS_RSA_WITH_AES_128_CBC_SHA256", supportedOnlyTLS12, true}, 86 | {TLS_RSA_WITH_AES_128_GCM_SHA256, "TLS_RSA_WITH_AES_128_GCM_SHA256", supportedOnlyTLS12, true}, 87 | {TLS_RSA_WITH_AES_256_GCM_SHA384, "TLS_RSA_WITH_AES_256_GCM_SHA384", supportedOnlyTLS12, true}, 88 | {TLS_ECDHE_ECDSA_WITH_RC4_128_SHA, "TLS_ECDHE_ECDSA_WITH_RC4_128_SHA", supportedUpToTLS12, true}, 89 | {TLS_ECDHE_RSA_WITH_RC4_128_SHA, "TLS_ECDHE_RSA_WITH_RC4_128_SHA", supportedUpToTLS12, true}, 90 | {TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA, "TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA", supportedUpToTLS12, true}, 91 | {TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256, "TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256", supportedOnlyTLS12, true}, 92 | {TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256, "TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256", supportedOnlyTLS12, true}, 93 | } 94 | } 95 | 96 | // CipherSuiteName returns the standard name for the passed cipher suite ID 97 | // (e.g. "TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256"), or a fallback representation 98 | // of the ID value if the cipher suite is not implemented by this package. 99 | func CipherSuiteName(id uint16) string { 100 | for _, c := range CipherSuites() { 101 | if c.ID == id { 102 | return c.Name 103 | } 104 | } 105 | for _, c := range InsecureCipherSuites() { 106 | if c.ID == id { 107 | return c.Name 108 | } 109 | } 110 | return fmt.Sprintf("0x%04X", id) 111 | } 112 | 113 | const ( 114 | // suiteECDHE indicates that the cipher suite involves elliptic curve 115 | // Diffie-Hellman. This means that it should only be selected when the 116 | // client indicates that it supports ECC with a curve and point format 117 | // that we're happy with. 118 | suiteECDHE = 1 << iota 119 | // suiteECSign indicates that the cipher suite involves an ECDSA or 120 | // EdDSA signature and therefore may only be selected when the server's 121 | // certificate is ECDSA or EdDSA. If this is not set then the cipher suite 122 | // is RSA based. 123 | suiteECSign 124 | // suiteTLS12 indicates that the cipher suite should only be advertised 125 | // and accepted when using TLS 1.2. 126 | suiteTLS12 127 | // suiteSHA384 indicates that the cipher suite uses SHA384 as the 128 | // handshake hash. 129 | suiteSHA384 130 | ) 131 | 132 | // A cipherSuite is a TLS 1.0–1.2 cipher suite, and defines the key exchange 133 | // mechanism, as well as the cipher+MAC pair or the AEAD. 134 | type cipherSuite struct { 135 | id uint16 136 | // the lengths, in bytes, of the key material needed for each component. 137 | keyLen int 138 | macLen int 139 | ivLen int 140 | ka func(version uint16) keyAgreement 141 | // flags is a bitmask of the suite* values, above. 142 | flags int 143 | cipher func(key, iv []byte, isRead bool) any 144 | mac func(key []byte) hash.Hash 145 | aead func(key, fixedNonce []byte) aead 146 | } 147 | 148 | var cipherSuites = []*cipherSuite{ // TODO: replace with a map, since the order doesn't matter. 149 | {TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305, 32, 0, 12, ecdheRSAKA, suiteECDHE | suiteTLS12, nil, nil, aeadChaCha20Poly1305}, 150 | {TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305, 32, 0, 12, ecdheECDSAKA, suiteECDHE | suiteECSign | suiteTLS12, nil, nil, aeadChaCha20Poly1305}, 151 | {TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256, 16, 0, 4, ecdheRSAKA, suiteECDHE | suiteTLS12, nil, nil, aeadAESGCM}, 152 | {TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256, 16, 0, 4, ecdheECDSAKA, suiteECDHE | suiteECSign | suiteTLS12, nil, nil, aeadAESGCM}, 153 | {TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384, 32, 0, 4, ecdheRSAKA, suiteECDHE | suiteTLS12 | suiteSHA384, nil, nil, aeadAESGCM}, 154 | {TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384, 32, 0, 4, ecdheECDSAKA, suiteECDHE | suiteECSign | suiteTLS12 | suiteSHA384, nil, nil, aeadAESGCM}, 155 | {TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256, 16, 32, 16, ecdheRSAKA, suiteECDHE | suiteTLS12, cipherAES, macSHA256, nil}, 156 | {TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA, 16, 20, 16, ecdheRSAKA, suiteECDHE, cipherAES, macSHA1, nil}, 157 | {TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256, 16, 32, 16, ecdheECDSAKA, suiteECDHE | suiteECSign | suiteTLS12, cipherAES, macSHA256, nil}, 158 | {TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA, 16, 20, 16, ecdheECDSAKA, suiteECDHE | suiteECSign, cipherAES, macSHA1, nil}, 159 | {TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA, 32, 20, 16, ecdheRSAKA, suiteECDHE, cipherAES, macSHA1, nil}, 160 | {TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA, 32, 20, 16, ecdheECDSAKA, suiteECDHE | suiteECSign, cipherAES, macSHA1, nil}, 161 | {TLS_RSA_WITH_AES_128_GCM_SHA256, 16, 0, 4, rsaKA, suiteTLS12, nil, nil, aeadAESGCM}, 162 | {TLS_RSA_WITH_AES_256_GCM_SHA384, 32, 0, 4, rsaKA, suiteTLS12 | suiteSHA384, nil, nil, aeadAESGCM}, 163 | {TLS_RSA_WITH_AES_128_CBC_SHA256, 16, 32, 16, rsaKA, suiteTLS12, cipherAES, macSHA256, nil}, 164 | {TLS_RSA_WITH_AES_128_CBC_SHA, 16, 20, 16, rsaKA, 0, cipherAES, macSHA1, nil}, 165 | {TLS_RSA_WITH_AES_256_CBC_SHA, 32, 20, 16, rsaKA, 0, cipherAES, macSHA1, nil}, 166 | {TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA, 24, 20, 8, ecdheRSAKA, suiteECDHE, cipher3DES, macSHA1, nil}, 167 | {TLS_RSA_WITH_3DES_EDE_CBC_SHA, 24, 20, 8, rsaKA, 0, cipher3DES, macSHA1, nil}, 168 | {TLS_RSA_WITH_RC4_128_SHA, 16, 20, 0, rsaKA, 0, cipherRC4, macSHA1, nil}, 169 | {TLS_ECDHE_RSA_WITH_RC4_128_SHA, 16, 20, 0, ecdheRSAKA, suiteECDHE, cipherRC4, macSHA1, nil}, 170 | {TLS_ECDHE_ECDSA_WITH_RC4_128_SHA, 16, 20, 0, ecdheECDSAKA, suiteECDHE | suiteECSign, cipherRC4, macSHA1, nil}, 171 | } 172 | 173 | // selectCipherSuite returns the first TLS 1.0–1.2 cipher suite from ids which 174 | // is also in supportedIDs and passes the ok filter. 175 | func selectCipherSuite(ids, supportedIDs []uint16, ok func(*cipherSuite) bool) *cipherSuite { 176 | for _, id := range ids { 177 | candidate := cipherSuiteByID(id) 178 | if candidate == nil || !ok(candidate) { 179 | continue 180 | } 181 | 182 | for _, suppID := range supportedIDs { 183 | if id == suppID { 184 | return candidate 185 | } 186 | } 187 | } 188 | return nil 189 | } 190 | 191 | // A cipherSuiteTLS13 defines only the pair of the AEAD algorithm and hash 192 | // algorithm to be used with HKDF. See RFC 8446, Appendix B.4. 193 | type cipherSuiteTLS13 struct { 194 | id uint16 195 | keyLen int 196 | aead func(key, fixedNonce []byte) aead 197 | hash crypto.Hash 198 | } 199 | 200 | // cipherSuitesTLS13 should be an internal detail, 201 | // but widely used packages access it using linkname. 202 | // Notable members of the hall of shame include: 203 | // - github.com/quic-go/quic-go 204 | // - github.com/sagernet/quic-go 205 | // 206 | // Do not remove or change the type signature. 207 | // See go.dev/issue/67401. 208 | // 209 | //go:linkname cipherSuitesTLS13 210 | var cipherSuitesTLS13 = []*cipherSuiteTLS13{ // TODO: replace with a map. 211 | {TLS_AES_128_GCM_SHA256, 16, aeadAESGCMTLS13, crypto.SHA256}, 212 | {TLS_CHACHA20_POLY1305_SHA256, 32, aeadChaCha20Poly1305, crypto.SHA256}, 213 | {TLS_AES_256_GCM_SHA384, 32, aeadAESGCMTLS13, crypto.SHA384}, 214 | } 215 | 216 | // cipherSuitesPreferenceOrder is the order in which we'll select (on the 217 | // server) or advertise (on the client) TLS 1.0–1.2 cipher suites. 218 | // 219 | // Cipher suites are filtered but not reordered based on the application and 220 | // peer's preferences, meaning we'll never select a suite lower in this list if 221 | // any higher one is available. This makes it more defensible to keep weaker 222 | // cipher suites enabled, especially on the server side where we get the last 223 | // word, since there are no known downgrade attacks on cipher suites selection. 224 | // 225 | // The list is sorted by applying the following priority rules, stopping at the 226 | // first (most important) applicable one: 227 | // 228 | // - Anything else comes before RC4 229 | // 230 | // RC4 has practically exploitable biases. See https://www.rc4nomore.com. 231 | // 232 | // - Anything else comes before CBC_SHA256 233 | // 234 | // SHA-256 variants of the CBC ciphersuites don't implement any Lucky13 235 | // countermeasures. See https://www.isg.rhul.ac.uk/tls/Lucky13.html and 236 | // https://www.imperialviolet.org/2013/02/04/luckythirteen.html. 237 | // 238 | // - Anything else comes before 3DES 239 | // 240 | // 3DES has 64-bit blocks, which makes it fundamentally susceptible to 241 | // birthday attacks. See https://sweet32.info. 242 | // 243 | // - ECDHE comes before anything else 244 | // 245 | // Once we got the broken stuff out of the way, the most important 246 | // property a cipher suite can have is forward secrecy. We don't 247 | // implement FFDHE, so that means ECDHE. 248 | // 249 | // - AEADs come before CBC ciphers 250 | // 251 | // Even with Lucky13 countermeasures, MAC-then-Encrypt CBC cipher suites 252 | // are fundamentally fragile, and suffered from an endless sequence of 253 | // padding oracle attacks. See https://eprint.iacr.org/2015/1129, 254 | // https://www.imperialviolet.org/2014/12/08/poodleagain.html, and 255 | // https://blog.cloudflare.com/yet-another-padding-oracle-in-openssl-cbc-ciphersuites/. 256 | // 257 | // - AES comes before ChaCha20 258 | // 259 | // When AES hardware is available, AES-128-GCM and AES-256-GCM are faster 260 | // than ChaCha20Poly1305. 261 | // 262 | // When AES hardware is not available, AES-128-GCM is one or more of: much 263 | // slower, way more complex, and less safe (because not constant time) 264 | // than ChaCha20Poly1305. 265 | // 266 | // We use this list if we think both peers have AES hardware, and 267 | // cipherSuitesPreferenceOrderNoAES otherwise. 268 | // 269 | // - AES-128 comes before AES-256 270 | // 271 | // The only potential advantages of AES-256 are better multi-target 272 | // margins, and hypothetical post-quantum properties. Neither apply to 273 | // TLS, and AES-256 is slower due to its four extra rounds (which don't 274 | // contribute to the advantages above). 275 | // 276 | // - ECDSA comes before RSA 277 | // 278 | // The relative order of ECDSA and RSA cipher suites doesn't matter, 279 | // as they depend on the certificate. Pick one to get a stable order. 280 | var cipherSuitesPreferenceOrder = []uint16{ 281 | // AEADs w/ ECDHE 282 | TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256, TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256, 283 | TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384, TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384, 284 | TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305, TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305, 285 | 286 | // CBC w/ ECDHE 287 | TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA, TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA, 288 | TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA, TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA, 289 | 290 | // AEADs w/o ECDHE 291 | TLS_RSA_WITH_AES_128_GCM_SHA256, 292 | TLS_RSA_WITH_AES_256_GCM_SHA384, 293 | 294 | // CBC w/o ECDHE 295 | TLS_RSA_WITH_AES_128_CBC_SHA, 296 | TLS_RSA_WITH_AES_256_CBC_SHA, 297 | 298 | // 3DES 299 | TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA, 300 | TLS_RSA_WITH_3DES_EDE_CBC_SHA, 301 | 302 | // CBC_SHA256 303 | TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256, TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256, 304 | TLS_RSA_WITH_AES_128_CBC_SHA256, 305 | 306 | // RC4 307 | TLS_ECDHE_ECDSA_WITH_RC4_128_SHA, TLS_ECDHE_RSA_WITH_RC4_128_SHA, 308 | TLS_RSA_WITH_RC4_128_SHA, 309 | } 310 | 311 | var cipherSuitesPreferenceOrderNoAES = []uint16{ 312 | // ChaCha20Poly1305 313 | TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305, TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305, 314 | 315 | // AES-GCM w/ ECDHE 316 | TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256, TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256, 317 | TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384, TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384, 318 | 319 | // The rest of cipherSuitesPreferenceOrder. 320 | TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA, TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA, 321 | TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA, TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA, 322 | TLS_RSA_WITH_AES_128_GCM_SHA256, 323 | TLS_RSA_WITH_AES_256_GCM_SHA384, 324 | TLS_RSA_WITH_AES_128_CBC_SHA, 325 | TLS_RSA_WITH_AES_256_CBC_SHA, 326 | TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA, 327 | TLS_RSA_WITH_3DES_EDE_CBC_SHA, 328 | TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256, TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256, 329 | TLS_RSA_WITH_AES_128_CBC_SHA256, 330 | TLS_ECDHE_ECDSA_WITH_RC4_128_SHA, TLS_ECDHE_RSA_WITH_RC4_128_SHA, 331 | TLS_RSA_WITH_RC4_128_SHA, 332 | } 333 | 334 | // disabledCipherSuites are not used unless explicitly listed in Config.CipherSuites. 335 | var disabledCipherSuites = map[uint16]bool{ 336 | // CBC_SHA256 337 | TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256: true, 338 | TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256: true, 339 | TLS_RSA_WITH_AES_128_CBC_SHA256: true, 340 | 341 | // RC4 342 | TLS_ECDHE_ECDSA_WITH_RC4_128_SHA: true, 343 | TLS_ECDHE_RSA_WITH_RC4_128_SHA: true, 344 | TLS_RSA_WITH_RC4_128_SHA: true, 345 | } 346 | 347 | // rsaKexCiphers contains the ciphers which use RSA based key exchange, 348 | // which we also disable by default unless a GODEBUG is set. 349 | var rsaKexCiphers = map[uint16]bool{ 350 | TLS_RSA_WITH_RC4_128_SHA: true, 351 | TLS_RSA_WITH_3DES_EDE_CBC_SHA: true, 352 | TLS_RSA_WITH_AES_128_CBC_SHA: true, 353 | TLS_RSA_WITH_AES_256_CBC_SHA: true, 354 | TLS_RSA_WITH_AES_128_CBC_SHA256: true, 355 | TLS_RSA_WITH_AES_128_GCM_SHA256: true, 356 | TLS_RSA_WITH_AES_256_GCM_SHA384: true, 357 | } 358 | 359 | // tdesCiphers contains 3DES ciphers, 360 | // which we also disable by default unless a GODEBUG is set. 361 | var tdesCiphers = map[uint16]bool{ 362 | TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA: true, 363 | TLS_RSA_WITH_3DES_EDE_CBC_SHA: true, 364 | } 365 | 366 | var ( 367 | // Keep in sync with crypto/internal/fips/aes/gcm.supportsAESGCM. 368 | hasGCMAsmAMD64 = cpu.X86.HasAES && cpu.X86.HasPCLMULQDQ && cpu.X86.HasSSE41 && cpu.X86.HasSSSE3 369 | hasGCMAsmARM64 = cpu.ARM64.HasAES && cpu.ARM64.HasPMULL 370 | hasGCMAsmS390X = cpu.S390X.HasAES && cpu.S390X.HasAESCTR && cpu.S390X.HasGHASH 371 | hasGCMAsmPPC64 = runtime.GOARCH == "ppc64" || runtime.GOARCH == "ppc64le" 372 | 373 | hasAESGCMHardwareSupport = hasGCMAsmAMD64 || hasGCMAsmARM64 || hasGCMAsmS390X || hasGCMAsmPPC64 374 | ) 375 | 376 | var aesgcmCiphers = map[uint16]bool{ 377 | // TLS 1.2 378 | TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256: true, 379 | TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384: true, 380 | TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256: true, 381 | TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384: true, 382 | // TLS 1.3 383 | TLS_AES_128_GCM_SHA256: true, 384 | TLS_AES_256_GCM_SHA384: true, 385 | } 386 | 387 | // isAESGCMPreferred returns whether we have hardware support for AES-GCM, and the 388 | // first known cipher in the peer's preference list is an AES-GCM cipher, 389 | // implying the peer also has hardware support for it. 390 | func isAESGCMPreferred(ciphers []uint16) bool { 391 | if !hasAESGCMHardwareSupport { 392 | return false 393 | } 394 | for _, cID := range ciphers { 395 | if c := cipherSuiteByID(cID); c != nil { 396 | return aesgcmCiphers[cID] 397 | } 398 | if c := cipherSuiteTLS13ByID(cID); c != nil { 399 | return aesgcmCiphers[cID] 400 | } 401 | } 402 | return false 403 | } 404 | 405 | func cipherRC4(key, iv []byte, isRead bool) any { 406 | cipher, _ := rc4.NewCipher(key) 407 | return cipher 408 | } 409 | 410 | func cipher3DES(key, iv []byte, isRead bool) any { 411 | block, _ := des.NewTripleDESCipher(key) 412 | if isRead { 413 | return cipher.NewCBCDecrypter(block, iv) 414 | } 415 | return cipher.NewCBCEncrypter(block, iv) 416 | } 417 | 418 | func cipherAES(key, iv []byte, isRead bool) any { 419 | block, _ := aes.NewCipher(key) 420 | if isRead { 421 | return cipher.NewCBCDecrypter(block, iv) 422 | } 423 | return cipher.NewCBCEncrypter(block, iv) 424 | } 425 | 426 | // macSHA1 returns a SHA-1 based constant time MAC. 427 | func macSHA1(key []byte) hash.Hash { 428 | return hmac.New(sha1.New, key) 429 | } 430 | 431 | // macSHA256 returns a SHA-256 based MAC. This is only supported in TLS 1.2 and 432 | // is currently only used in disabled-by-default cipher suites. 433 | func macSHA256(key []byte) hash.Hash { 434 | return hmac.New(sha256.New, key) 435 | } 436 | 437 | type aead interface { 438 | cipher.AEAD 439 | 440 | // explicitNonceLen returns the number of bytes of explicit nonce 441 | // included in each record. This is eight for older AEADs and 442 | // zero for modern ones. 443 | explicitNonceLen() int 444 | } 445 | 446 | const ( 447 | aeadNonceLength = 12 448 | noncePrefixLength = 4 449 | ) 450 | 451 | // prefixNonceAEAD wraps an AEAD and prefixes a fixed portion of the nonce to 452 | // each call. 453 | type prefixNonceAEAD struct { 454 | // nonce contains the fixed part of the nonce in the first four bytes. 455 | nonce [aeadNonceLength]byte 456 | aead cipher.AEAD 457 | } 458 | 459 | func (f *prefixNonceAEAD) NonceSize() int { return aeadNonceLength - noncePrefixLength } 460 | func (f *prefixNonceAEAD) Overhead() int { return f.aead.Overhead() } 461 | func (f *prefixNonceAEAD) explicitNonceLen() int { return f.NonceSize() } 462 | 463 | func (f *prefixNonceAEAD) Seal(out, nonce, plaintext, additionalData []byte) []byte { 464 | copy(f.nonce[4:], nonce) 465 | return f.aead.Seal(out, f.nonce[:], plaintext, additionalData) 466 | } 467 | 468 | func (f *prefixNonceAEAD) Open(out, nonce, ciphertext, additionalData []byte) ([]byte, error) { 469 | copy(f.nonce[4:], nonce) 470 | return f.aead.Open(out, f.nonce[:], ciphertext, additionalData) 471 | } 472 | 473 | // xorNonceAEAD wraps an AEAD by XORing in a fixed pattern to the nonce 474 | // before each call. 475 | type xorNonceAEAD struct { 476 | nonceMask [aeadNonceLength]byte 477 | aead cipher.AEAD 478 | } 479 | 480 | func (f *xorNonceAEAD) NonceSize() int { return 8 } // 64-bit sequence number 481 | func (f *xorNonceAEAD) Overhead() int { return f.aead.Overhead() } 482 | func (f *xorNonceAEAD) explicitNonceLen() int { return 0 } 483 | 484 | func (f *xorNonceAEAD) Seal(out, nonce, plaintext, additionalData []byte) []byte { 485 | for i, b := range nonce { 486 | f.nonceMask[4+i] ^= b 487 | } 488 | result := f.aead.Seal(out, f.nonceMask[:], plaintext, additionalData) 489 | for i, b := range nonce { 490 | f.nonceMask[4+i] ^= b 491 | } 492 | 493 | return result 494 | } 495 | 496 | func (f *xorNonceAEAD) Open(out, nonce, ciphertext, additionalData []byte) ([]byte, error) { 497 | for i, b := range nonce { 498 | f.nonceMask[4+i] ^= b 499 | } 500 | result, err := f.aead.Open(out, f.nonceMask[:], ciphertext, additionalData) 501 | for i, b := range nonce { 502 | f.nonceMask[4+i] ^= b 503 | } 504 | 505 | return result, err 506 | } 507 | 508 | func aeadAESGCM(key, noncePrefix []byte) aead { 509 | if len(noncePrefix) != noncePrefixLength { 510 | panic("tls: internal error: wrong nonce length") 511 | } 512 | aes, err := aes.NewCipher(key) 513 | if err != nil { 514 | panic(err) 515 | } 516 | //aead, err := gcm.NewGCMForTLS12(aes) 517 | aead, err := cipher.NewGCM(aes) 518 | if err != nil { 519 | panic(err) 520 | } 521 | 522 | ret := &prefixNonceAEAD{aead: aead} 523 | copy(ret.nonce[:], noncePrefix) 524 | return ret 525 | } 526 | 527 | // aeadAESGCMTLS13 should be an internal detail, 528 | // but widely used packages access it using linkname. 529 | // Notable members of the hall of shame include: 530 | // - github.com/xtls/xray-core 531 | // - github.com/v2fly/v2ray-core 532 | // 533 | // Do not remove or change the type signature. 534 | // See go.dev/issue/67401. 535 | // 536 | //go:linkname aeadAESGCMTLS13 537 | func aeadAESGCMTLS13(key, nonceMask []byte) aead { 538 | if len(nonceMask) != aeadNonceLength { 539 | panic("tls: internal error: wrong nonce length") 540 | } 541 | aes, err := aes.NewCipher(key) 542 | if err != nil { 543 | panic(err) 544 | } 545 | //aead, err := gcm.NewGCMForTLS13(aes) 546 | aead, err := cipher.NewGCM(aes) 547 | if err != nil { 548 | panic(err) 549 | } 550 | 551 | ret := &xorNonceAEAD{aead: aead} 552 | copy(ret.nonceMask[:], nonceMask) 553 | return ret 554 | } 555 | 556 | func aeadChaCha20Poly1305(key, nonceMask []byte) aead { 557 | if len(nonceMask) != aeadNonceLength { 558 | panic("tls: internal error: wrong nonce length") 559 | } 560 | aead, err := chacha20poly1305.New(key) 561 | if err != nil { 562 | panic(err) 563 | } 564 | 565 | ret := &xorNonceAEAD{aead: aead} 566 | copy(ret.nonceMask[:], nonceMask) 567 | return ret 568 | } 569 | 570 | type constantTimeHash interface { 571 | hash.Hash 572 | ConstantTimeSum(b []byte) []byte 573 | } 574 | 575 | // cthWrapper wraps any hash.Hash that implements ConstantTimeSum, and replaces 576 | // with that all calls to Sum. It's used to obtain a ConstantTimeSum-based HMAC. 577 | type cthWrapper struct { 578 | h constantTimeHash 579 | } 580 | 581 | func (c *cthWrapper) Size() int { return c.h.Size() } 582 | func (c *cthWrapper) BlockSize() int { return c.h.BlockSize() } 583 | func (c *cthWrapper) Reset() { c.h.Reset() } 584 | func (c *cthWrapper) Write(p []byte) (int, error) { return c.h.Write(p) } 585 | func (c *cthWrapper) Sum(b []byte) []byte { return c.h.ConstantTimeSum(b) } 586 | 587 | func newConstantTimeHash(h func() hash.Hash) func() hash.Hash { 588 | return func() hash.Hash { 589 | return &cthWrapper{h().(constantTimeHash)} 590 | } 591 | } 592 | 593 | // tls10MAC implements the TLS 1.0 MAC function. RFC 2246, Section 6.2.3. 594 | func tls10MAC(h hash.Hash, out, seq, header, data, extra []byte) []byte { 595 | h.Reset() 596 | h.Write(seq) 597 | h.Write(header) 598 | h.Write(data) 599 | res := h.Sum(out) 600 | if extra != nil { 601 | h.Write(extra) 602 | } 603 | return res 604 | } 605 | 606 | func rsaKA(version uint16) keyAgreement { 607 | return rsaKeyAgreement{} 608 | } 609 | 610 | func ecdheECDSAKA(version uint16) keyAgreement { 611 | return &ecdheKeyAgreement{ 612 | isRSA: false, 613 | version: version, 614 | } 615 | } 616 | 617 | func ecdheRSAKA(version uint16) keyAgreement { 618 | return &ecdheKeyAgreement{ 619 | isRSA: true, 620 | version: version, 621 | } 622 | } 623 | 624 | // mutualCipherSuite returns a cipherSuite given a list of supported 625 | // ciphersuites and the id requested by the peer. 626 | func mutualCipherSuite(have []uint16, want uint16) *cipherSuite { 627 | for _, id := range have { 628 | if id == want { 629 | return cipherSuiteByID(id) 630 | } 631 | } 632 | return nil 633 | } 634 | 635 | func cipherSuiteByID(id uint16) *cipherSuite { 636 | for _, cipherSuite := range cipherSuites { 637 | if cipherSuite.id == id { 638 | return cipherSuite 639 | } 640 | } 641 | return nil 642 | } 643 | 644 | func mutualCipherSuiteTLS13(have []uint16, want uint16) *cipherSuiteTLS13 { 645 | for _, id := range have { 646 | if id == want { 647 | return cipherSuiteTLS13ByID(id) 648 | } 649 | } 650 | return nil 651 | } 652 | 653 | func cipherSuiteTLS13ByID(id uint16) *cipherSuiteTLS13 { 654 | for _, cipherSuite := range cipherSuitesTLS13 { 655 | if cipherSuite.id == id { 656 | return cipherSuite 657 | } 658 | } 659 | return nil 660 | } 661 | 662 | // A list of cipher suite IDs that are, or have been, implemented by this 663 | // package. 664 | // 665 | // See https://www.iana.org/assignments/tls-parameters/tls-parameters.xml 666 | const ( 667 | // TLS 1.0 - 1.2 cipher suites. 668 | TLS_RSA_WITH_RC4_128_SHA uint16 = 0x0005 669 | TLS_RSA_WITH_3DES_EDE_CBC_SHA uint16 = 0x000a 670 | TLS_RSA_WITH_AES_128_CBC_SHA uint16 = 0x002f 671 | TLS_RSA_WITH_AES_256_CBC_SHA uint16 = 0x0035 672 | TLS_RSA_WITH_AES_128_CBC_SHA256 uint16 = 0x003c 673 | TLS_RSA_WITH_AES_128_GCM_SHA256 uint16 = 0x009c 674 | TLS_RSA_WITH_AES_256_GCM_SHA384 uint16 = 0x009d 675 | TLS_ECDHE_ECDSA_WITH_RC4_128_SHA uint16 = 0xc007 676 | TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA uint16 = 0xc009 677 | TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA uint16 = 0xc00a 678 | TLS_ECDHE_RSA_WITH_RC4_128_SHA uint16 = 0xc011 679 | TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA uint16 = 0xc012 680 | TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA uint16 = 0xc013 681 | TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA uint16 = 0xc014 682 | TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256 uint16 = 0xc023 683 | TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256 uint16 = 0xc027 684 | TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 uint16 = 0xc02f 685 | TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256 uint16 = 0xc02b 686 | TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 uint16 = 0xc030 687 | TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384 uint16 = 0xc02c 688 | TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256 uint16 = 0xcca8 689 | TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256 uint16 = 0xcca9 690 | 691 | // TLS 1.3 cipher suites. 692 | TLS_AES_128_GCM_SHA256 uint16 = 0x1301 693 | TLS_AES_256_GCM_SHA384 uint16 = 0x1302 694 | TLS_CHACHA20_POLY1305_SHA256 uint16 = 0x1303 695 | 696 | // TLS_FALLBACK_SCSV isn't a standard cipher suite but an indicator 697 | // that the client is doing version fallback. See RFC 7507. 698 | TLS_FALLBACK_SCSV uint16 = 0x5600 699 | 700 | // Legacy names for the corresponding cipher suites with the correct _SHA256 701 | // suffix, retained for backward compatibility. 702 | TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305 = TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256 703 | TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305 = TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256 704 | ) 705 | -------------------------------------------------------------------------------- /common_string.go: -------------------------------------------------------------------------------- 1 | // Code generated by "stringer -linecomment -type=SignatureScheme,CurveID,ClientAuthType -output=common_string.go"; DO NOT EDIT. 2 | 3 | package reality 4 | 5 | import "strconv" 6 | 7 | func _() { 8 | // An "invalid array index" compiler error signifies that the constant values have changed. 9 | // Re-run the stringer command to generate them again. 10 | var x [1]struct{} 11 | _ = x[PKCS1WithSHA256-1025] 12 | _ = x[PKCS1WithSHA384-1281] 13 | _ = x[PKCS1WithSHA512-1537] 14 | _ = x[PSSWithSHA256-2052] 15 | _ = x[PSSWithSHA384-2053] 16 | _ = x[PSSWithSHA512-2054] 17 | _ = x[ECDSAWithP256AndSHA256-1027] 18 | _ = x[ECDSAWithP384AndSHA384-1283] 19 | _ = x[ECDSAWithP521AndSHA512-1539] 20 | _ = x[Ed25519-2055] 21 | _ = x[PKCS1WithSHA1-513] 22 | _ = x[ECDSAWithSHA1-515] 23 | } 24 | 25 | const ( 26 | _SignatureScheme_name_0 = "PKCS1WithSHA1" 27 | _SignatureScheme_name_1 = "ECDSAWithSHA1" 28 | _SignatureScheme_name_2 = "PKCS1WithSHA256" 29 | _SignatureScheme_name_3 = "ECDSAWithP256AndSHA256" 30 | _SignatureScheme_name_4 = "PKCS1WithSHA384" 31 | _SignatureScheme_name_5 = "ECDSAWithP384AndSHA384" 32 | _SignatureScheme_name_6 = "PKCS1WithSHA512" 33 | _SignatureScheme_name_7 = "ECDSAWithP521AndSHA512" 34 | _SignatureScheme_name_8 = "PSSWithSHA256PSSWithSHA384PSSWithSHA512Ed25519" 35 | ) 36 | 37 | var ( 38 | _SignatureScheme_index_8 = [...]uint8{0, 13, 26, 39, 46} 39 | ) 40 | 41 | func (i SignatureScheme) String() string { 42 | switch { 43 | case i == 513: 44 | return _SignatureScheme_name_0 45 | case i == 515: 46 | return _SignatureScheme_name_1 47 | case i == 1025: 48 | return _SignatureScheme_name_2 49 | case i == 1027: 50 | return _SignatureScheme_name_3 51 | case i == 1281: 52 | return _SignatureScheme_name_4 53 | case i == 1283: 54 | return _SignatureScheme_name_5 55 | case i == 1537: 56 | return _SignatureScheme_name_6 57 | case i == 1539: 58 | return _SignatureScheme_name_7 59 | case 2052 <= i && i <= 2055: 60 | i -= 2052 61 | return _SignatureScheme_name_8[_SignatureScheme_index_8[i]:_SignatureScheme_index_8[i+1]] 62 | default: 63 | return "SignatureScheme(" + strconv.FormatInt(int64(i), 10) + ")" 64 | } 65 | } 66 | func _() { 67 | // An "invalid array index" compiler error signifies that the constant values have changed. 68 | // Re-run the stringer command to generate them again. 69 | var x [1]struct{} 70 | _ = x[CurveP256-23] 71 | _ = x[CurveP384-24] 72 | _ = x[CurveP521-25] 73 | _ = x[X25519-29] 74 | _ = x[X25519MLKEM768-4588] 75 | } 76 | 77 | const ( 78 | _CurveID_name_0 = "CurveP256CurveP384CurveP521" 79 | _CurveID_name_1 = "X25519" 80 | _CurveID_name_2 = "X25519MLKEM768" 81 | ) 82 | 83 | var ( 84 | _CurveID_index_0 = [...]uint8{0, 9, 18, 27} 85 | ) 86 | 87 | func (i CurveID) String() string { 88 | switch { 89 | case 23 <= i && i <= 25: 90 | i -= 23 91 | return _CurveID_name_0[_CurveID_index_0[i]:_CurveID_index_0[i+1]] 92 | case i == 29: 93 | return _CurveID_name_1 94 | case i == 4588: 95 | return _CurveID_name_2 96 | default: 97 | return "CurveID(" + strconv.FormatInt(int64(i), 10) + ")" 98 | } 99 | } 100 | func _() { 101 | // An "invalid array index" compiler error signifies that the constant values have changed. 102 | // Re-run the stringer command to generate them again. 103 | var x [1]struct{} 104 | _ = x[NoClientCert-0] 105 | _ = x[RequestClientCert-1] 106 | _ = x[RequireAnyClientCert-2] 107 | _ = x[VerifyClientCertIfGiven-3] 108 | _ = x[RequireAndVerifyClientCert-4] 109 | } 110 | 111 | const _ClientAuthType_name = "NoClientCertRequestClientCertRequireAnyClientCertVerifyClientCertIfGivenRequireAndVerifyClientCert" 112 | 113 | var _ClientAuthType_index = [...]uint8{0, 12, 29, 49, 72, 98} 114 | 115 | func (i ClientAuthType) String() string { 116 | if i < 0 || i >= ClientAuthType(len(_ClientAuthType_index)-1) { 117 | return "ClientAuthType(" + strconv.FormatInt(int64(i), 10) + ")" 118 | } 119 | return _ClientAuthType_name[_ClientAuthType_index[i]:_ClientAuthType_index[i+1]] 120 | } 121 | -------------------------------------------------------------------------------- /defaults.go: -------------------------------------------------------------------------------- 1 | // Copyright 2024 The Go Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package reality 6 | 7 | import ( 8 | "slices" 9 | _ "unsafe" // for linkname 10 | ) 11 | 12 | // Defaults are collected in this file to allow distributions to more easily patch 13 | // them to apply local policies. 14 | 15 | //var tlsmlkem = godebug.New("tlsmlkem") 16 | 17 | // defaultCurvePreferences is the default set of supported key exchanges, as 18 | // well as the preference order. 19 | func defaultCurvePreferences() []CurveID { 20 | if false { 21 | return []CurveID{X25519, CurveP256, CurveP384, CurveP521} 22 | } 23 | return []CurveID{X25519MLKEM768, X25519, CurveP256, CurveP384, CurveP521} 24 | } 25 | 26 | //var tlssha1 = godebug.New("tlssha1") 27 | 28 | // defaultSupportedSignatureAlgorithms returns the signature and hash algorithms that 29 | // the code advertises and supports in a TLS 1.2+ ClientHello and in a TLS 1.2+ 30 | // CertificateRequest. The two fields are merged to match with TLS 1.3. 31 | // Note that in TLS 1.2, the ECDSA algorithms are not constrained to P-256, etc. 32 | func defaultSupportedSignatureAlgorithms() []SignatureScheme { 33 | return []SignatureScheme{ 34 | PSSWithSHA256, 35 | ECDSAWithP256AndSHA256, 36 | Ed25519, 37 | PSSWithSHA384, 38 | PSSWithSHA512, 39 | PKCS1WithSHA256, 40 | PKCS1WithSHA384, 41 | PKCS1WithSHA512, 42 | ECDSAWithP384AndSHA384, 43 | ECDSAWithP521AndSHA512, 44 | } 45 | } 46 | 47 | // defaultSupportedSignatureAlgorithmsCert returns the signature algorithms that 48 | // the code advertises as supported for signatures in certificates. 49 | // 50 | // We include all algorithms, including SHA-1 and PKCS#1 v1.5, because it's more 51 | // likely that something on our side will be willing to accept a *-with-SHA1 52 | // certificate (e.g. with a custom VerifyConnection or by a direct match with 53 | // the CertPool), than that the peer would have a better certificate but is just 54 | // choosing not to send it. crypto/x509 will refuse to verify important SHA-1 55 | // signatures anyway. 56 | func defaultSupportedSignatureAlgorithmsCert() []SignatureScheme { 57 | return []SignatureScheme{ 58 | PSSWithSHA256, 59 | ECDSAWithP256AndSHA256, 60 | Ed25519, 61 | PSSWithSHA384, 62 | PSSWithSHA512, 63 | PKCS1WithSHA256, 64 | PKCS1WithSHA384, 65 | PKCS1WithSHA512, 66 | ECDSAWithP384AndSHA384, 67 | ECDSAWithP521AndSHA512, 68 | PKCS1WithSHA1, 69 | ECDSAWithSHA1, 70 | } 71 | } 72 | 73 | //var tlsrsakex = godebug.New("tlsrsakex") 74 | //var tls3des = godebug.New("tls3des") 75 | 76 | func supportedCipherSuites(aesGCMPreferred bool) []uint16 { 77 | if aesGCMPreferred { 78 | return slices.Clone(cipherSuitesPreferenceOrder) 79 | } else { 80 | return slices.Clone(cipherSuitesPreferenceOrderNoAES) 81 | } 82 | } 83 | 84 | func defaultCipherSuites(aesGCMPreferred bool) []uint16 { 85 | cipherSuites := supportedCipherSuites(aesGCMPreferred) 86 | return slices.DeleteFunc(cipherSuites, func(c uint16) bool { 87 | return disabledCipherSuites[c] || 88 | rsaKexCiphers[c] || 89 | tdesCiphers[c] 90 | }) 91 | } 92 | 93 | // defaultCipherSuitesTLS13 is also the preference order, since there are no 94 | // disabled by default TLS 1.3 cipher suites. The same AES vs ChaCha20 logic as 95 | // cipherSuitesPreferenceOrder applies. 96 | // 97 | // defaultCipherSuitesTLS13 should be an internal detail, 98 | // but widely used packages access it using linkname. 99 | // Notable members of the hall of shame include: 100 | // - github.com/quic-go/quic-go 101 | // - github.com/sagernet/quic-go 102 | // 103 | // Do not remove or change the type signature. 104 | // See go.dev/issue/67401. 105 | // 106 | //go:linkname defaultCipherSuitesTLS13 107 | var defaultCipherSuitesTLS13 = []uint16{ 108 | TLS_AES_128_GCM_SHA256, 109 | TLS_AES_256_GCM_SHA384, 110 | TLS_CHACHA20_POLY1305_SHA256, 111 | } 112 | 113 | // defaultCipherSuitesTLS13NoAES should be an internal detail, 114 | // but widely used packages access it using linkname. 115 | // Notable members of the hall of shame include: 116 | // - github.com/quic-go/quic-go 117 | // - github.com/sagernet/quic-go 118 | // 119 | // Do not remove or change the type signature. 120 | // See go.dev/issue/67401. 121 | // 122 | //go:linkname defaultCipherSuitesTLS13NoAES 123 | var defaultCipherSuitesTLS13NoAES = []uint16{ 124 | TLS_CHACHA20_POLY1305_SHA256, 125 | TLS_AES_128_GCM_SHA256, 126 | TLS_AES_256_GCM_SHA384, 127 | } -------------------------------------------------------------------------------- /defaults_boring.go: -------------------------------------------------------------------------------- 1 | // Copyright 2025 The Go Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | //go:build boringcrypto 6 | 7 | package reality 8 | 9 | import ( 10 | "crypto/ecdsa" 11 | "crypto/elliptic" 12 | "crypto/rsa" 13 | "crypto/x509" 14 | ) 15 | 16 | // These Go+BoringCrypto policies mostly match BoringSSL's 17 | // ssl_compliance_policy_fips_202205, which is based on NIST SP 800-52r2. 18 | // https://cs.opensource.google/boringssl/boringssl/+/master:ssl/ssl_lib.cc;l=3289;drc=ea7a88fa 19 | // 20 | // P-521 is allowed per https://go.dev/issue/71757. 21 | // 22 | // They are applied when crypto/tls/fipsonly is imported with GOEXPERIMENT=boringcrypto. 23 | 24 | var ( 25 | allowedSupportedVersionsFIPS = []uint16{ 26 | VersionTLS12, 27 | VersionTLS13, 28 | } 29 | allowedCurvePreferencesFIPS = []CurveID{ 30 | CurveP256, 31 | CurveP384, 32 | CurveP521, 33 | } 34 | allowedSignatureAlgorithmsFIPS = []SignatureScheme{ 35 | PSSWithSHA256, 36 | PSSWithSHA384, 37 | PSSWithSHA512, 38 | PKCS1WithSHA256, 39 | ECDSAWithP256AndSHA256, 40 | PKCS1WithSHA384, 41 | ECDSAWithP384AndSHA384, 42 | PKCS1WithSHA512, 43 | ECDSAWithP521AndSHA512, 44 | } 45 | allowedCipherSuitesFIPS = []uint16{ 46 | TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256, 47 | TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384, 48 | TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256, 49 | TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384, 50 | } 51 | allowedCipherSuitesTLS13FIPS = []uint16{ 52 | TLS_AES_128_GCM_SHA256, 53 | TLS_AES_256_GCM_SHA384, 54 | } 55 | ) 56 | 57 | func isCertificateAllowedFIPS(c *x509.Certificate) bool { 58 | // The key must be RSA 2048, RSA 3072, RSA 4096, 59 | // or ECDSA P-256, P-384, P-521. 60 | switch k := c.PublicKey.(type) { 61 | case *rsa.PublicKey: 62 | size := k.N.BitLen() 63 | return size == 2048 || size == 3072 || size == 4096 64 | case *ecdsa.PublicKey: 65 | return k.Curve == elliptic.P256() || k.Curve == elliptic.P384() || k.Curve == elliptic.P521() 66 | } 67 | 68 | return false 69 | } -------------------------------------------------------------------------------- /defaults_fips140.go: -------------------------------------------------------------------------------- 1 | // Copyright 2025 The Go Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | //go:build !boringcrypto 6 | 7 | package reality 8 | 9 | import ( 10 | "crypto/ecdsa" 11 | "crypto/ed25519" 12 | "crypto/elliptic" 13 | "crypto/rsa" 14 | "crypto/x509" 15 | ) 16 | 17 | // These FIPS 140-3 policies allow anything approved by SP 800-140C 18 | // and SP 800-140D, and tested as part of the Go Cryptographic Module. 19 | // 20 | // Notably, not SHA-1, 3DES, RC4, ChaCha20Poly1305, RSA PKCS #1 v1.5 key 21 | // transport, or TLS 1.0—1.1 (because we don't test its KDF). 22 | // 23 | // These are not default lists, but filters to apply to the default or 24 | // configured lists. Missing items are treated as if they were not implemented. 25 | // 26 | // They are applied when the fips140 GODEBUG is "on" or "only". 27 | 28 | var ( 29 | allowedSupportedVersionsFIPS = []uint16{ 30 | VersionTLS12, 31 | VersionTLS13, 32 | } 33 | allowedCurvePreferencesFIPS = []CurveID{ 34 | X25519MLKEM768, 35 | CurveP256, 36 | CurveP384, 37 | CurveP521, 38 | } 39 | allowedSignatureAlgorithmsFIPS = []SignatureScheme{ 40 | PSSWithSHA256, 41 | ECDSAWithP256AndSHA256, 42 | Ed25519, 43 | PSSWithSHA384, 44 | PSSWithSHA512, 45 | PKCS1WithSHA256, 46 | PKCS1WithSHA384, 47 | PKCS1WithSHA512, 48 | ECDSAWithP384AndSHA384, 49 | ECDSAWithP521AndSHA512, 50 | } 51 | allowedCipherSuitesFIPS = []uint16{ 52 | TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256, 53 | TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384, 54 | TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256, 55 | TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384, 56 | TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256, 57 | TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256, 58 | } 59 | allowedCipherSuitesTLS13FIPS = []uint16{ 60 | TLS_AES_128_GCM_SHA256, 61 | TLS_AES_256_GCM_SHA384, 62 | } 63 | ) 64 | 65 | func isCertificateAllowedFIPS(c *x509.Certificate) bool { 66 | switch k := c.PublicKey.(type) { 67 | case *rsa.PublicKey: 68 | return k.N.BitLen() >= 2048 69 | case *ecdsa.PublicKey: 70 | return k.Curve == elliptic.P256() || k.Curve == elliptic.P384() || k.Curve == elliptic.P521() 71 | case ed25519.PublicKey: 72 | return true 73 | default: 74 | return false 75 | } 76 | } -------------------------------------------------------------------------------- /ech.go: -------------------------------------------------------------------------------- 1 | // Copyright 2024 The Go Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package reality 6 | 7 | import ( 8 | "bytes" 9 | "errors" 10 | "fmt" 11 | "slices" 12 | "strings" 13 | 14 | "golang.org/x/crypto/cryptobyte" 15 | 16 | "github.com/xtls/reality/hpke" 17 | ) 18 | 19 | // sortedSupportedAEADs is just a sorted version of hpke.SupportedAEADS. 20 | // We need this so that when we insert them into ECHConfigs the ordering 21 | // is stable. 22 | var sortedSupportedAEADs []uint16 23 | 24 | func init() { 25 | for aeadID := range hpke.SupportedAEADs { 26 | sortedSupportedAEADs = append(sortedSupportedAEADs, aeadID) 27 | } 28 | slices.Sort(sortedSupportedAEADs) 29 | } 30 | 31 | type EchCipher struct { 32 | KDFID uint16 33 | AEADID uint16 34 | } 35 | 36 | type echExtension struct { 37 | Type uint16 38 | Data []byte 39 | } 40 | 41 | type EchConfig struct { 42 | raw []byte 43 | 44 | Version uint16 45 | Length uint16 46 | 47 | ConfigID uint8 48 | KemID uint16 49 | PublicKey []byte 50 | SymmetricCipherSuite []EchCipher 51 | 52 | MaxNameLength uint8 53 | PublicName []byte 54 | Extensions []echExtension 55 | } 56 | 57 | var errMalformedECHConfigList = errors.New("tls: malformed ECHConfigList") 58 | 59 | type echConfigErr struct { 60 | field string 61 | } 62 | 63 | func (e *echConfigErr) Error() string { 64 | if e.field == "" { 65 | return "tls: malformed ECHConfig" 66 | } 67 | return fmt.Sprintf("tls: malformed ECHConfig, invalid %s field", e.field) 68 | } 69 | 70 | func parseECHConfig(enc []byte) (skip bool, ec EchConfig, err error) { 71 | s := cryptobyte.String(enc) 72 | ec.raw = []byte(enc) 73 | if !s.ReadUint16(&ec.Version) { 74 | return false, EchConfig{}, &echConfigErr{"version"} 75 | } 76 | if !s.ReadUint16(&ec.Length) { 77 | return false, EchConfig{}, &echConfigErr{"length"} 78 | } 79 | if len(ec.raw) < int(ec.Length)+4 { 80 | return false, EchConfig{}, &echConfigErr{"length"} 81 | } 82 | ec.raw = ec.raw[:ec.Length+4] 83 | if ec.Version != extensionEncryptedClientHello { 84 | s.Skip(int(ec.Length)) 85 | return true, EchConfig{}, nil 86 | } 87 | if !s.ReadUint8(&ec.ConfigID) { 88 | return false, EchConfig{}, &echConfigErr{"config_id"} 89 | } 90 | if !s.ReadUint16(&ec.KemID) { 91 | return false, EchConfig{}, &echConfigErr{"kem_id"} 92 | } 93 | if !readUint16LengthPrefixed(&s, &ec.PublicKey) { 94 | return false, EchConfig{}, &echConfigErr{"public_key"} 95 | } 96 | var cipherSuites cryptobyte.String 97 | if !s.ReadUint16LengthPrefixed(&cipherSuites) { 98 | return false, EchConfig{}, &echConfigErr{"cipher_suites"} 99 | } 100 | for !cipherSuites.Empty() { 101 | var c EchCipher 102 | if !cipherSuites.ReadUint16(&c.KDFID) { 103 | return false, EchConfig{}, &echConfigErr{"cipher_suites kdf_id"} 104 | } 105 | if !cipherSuites.ReadUint16(&c.AEADID) { 106 | return false, EchConfig{}, &echConfigErr{"cipher_suites aead_id"} 107 | } 108 | ec.SymmetricCipherSuite = append(ec.SymmetricCipherSuite, c) 109 | } 110 | if !s.ReadUint8(&ec.MaxNameLength) { 111 | return false, EchConfig{}, &echConfigErr{"maximum_name_length"} 112 | } 113 | var publicName cryptobyte.String 114 | if !s.ReadUint8LengthPrefixed(&publicName) { 115 | return false, EchConfig{}, &echConfigErr{"public_name"} 116 | } 117 | ec.PublicName = publicName 118 | var extensions cryptobyte.String 119 | if !s.ReadUint16LengthPrefixed(&extensions) { 120 | return false, EchConfig{}, &echConfigErr{"extensions"} 121 | } 122 | for !extensions.Empty() { 123 | var e echExtension 124 | if !extensions.ReadUint16(&e.Type) { 125 | return false, EchConfig{}, &echConfigErr{"extensions type"} 126 | } 127 | if !extensions.ReadUint16LengthPrefixed((*cryptobyte.String)(&e.Data)) { 128 | return false, EchConfig{}, &echConfigErr{"extensions data"} 129 | } 130 | ec.Extensions = append(ec.Extensions, e) 131 | } 132 | 133 | return false, ec, nil 134 | } 135 | 136 | // parseECHConfigList parses a draft-ietf-tls-esni-18 ECHConfigList, returning a 137 | // slice of parsed ECHConfigs, in the same order they were parsed, or an error 138 | // if the list is malformed. 139 | func parseECHConfigList(data []byte) ([]EchConfig, error) { 140 | s := cryptobyte.String(data) 141 | var length uint16 142 | if !s.ReadUint16(&length) { 143 | return nil, errMalformedECHConfigList 144 | } 145 | if length != uint16(len(data)-2) { 146 | return nil, errMalformedECHConfigList 147 | } 148 | var configs []EchConfig 149 | for len(s) > 0 { 150 | if len(s) < 4 { 151 | return nil, errors.New("tls: malformed ECHConfig") 152 | } 153 | configLen := uint16(s[2])<<8 | uint16(s[3]) 154 | skip, ec, err := parseECHConfig(s) 155 | if err != nil { 156 | return nil, err 157 | } 158 | s = s[configLen+4:] 159 | if !skip { 160 | configs = append(configs, ec) 161 | } 162 | } 163 | return configs, nil 164 | } 165 | 166 | func pickECHConfig(list []EchConfig) *EchConfig { 167 | for _, ec := range list { 168 | if _, ok := hpke.SupportedKEMs[ec.KemID]; !ok { 169 | continue 170 | } 171 | var validSCS bool 172 | for _, cs := range ec.SymmetricCipherSuite { 173 | if _, ok := hpke.SupportedAEADs[cs.AEADID]; !ok { 174 | continue 175 | } 176 | if _, ok := hpke.SupportedKDFs[cs.KDFID]; !ok { 177 | continue 178 | } 179 | validSCS = true 180 | break 181 | } 182 | if !validSCS { 183 | continue 184 | } 185 | if !validDNSName(string(ec.PublicName)) { 186 | continue 187 | } 188 | var unsupportedExt bool 189 | for _, ext := range ec.Extensions { 190 | // If high order bit is set to 1 the extension is mandatory. 191 | // Since we don't support any extensions, if we see a mandatory 192 | // bit, we skip the config. 193 | if ext.Type&uint16(1<<15) != 0 { 194 | unsupportedExt = true 195 | } 196 | } 197 | if unsupportedExt { 198 | continue 199 | } 200 | return &ec 201 | } 202 | return nil 203 | } 204 | 205 | func pickECHCipherSuite(suites []EchCipher) (EchCipher, error) { 206 | for _, s := range suites { 207 | // NOTE: all of the supported AEADs and KDFs are fine, rather than 208 | // imposing some sort of preference here, we just pick the first valid 209 | // suite. 210 | if _, ok := hpke.SupportedAEADs[s.AEADID]; !ok { 211 | continue 212 | } 213 | if _, ok := hpke.SupportedKDFs[s.KDFID]; !ok { 214 | continue 215 | } 216 | return s, nil 217 | } 218 | return EchCipher{}, errors.New("tls: no supported symmetric ciphersuites for ECH") 219 | } 220 | 221 | func encodeInnerClientHello(inner *clientHelloMsg, maxNameLength int) ([]byte, error) { 222 | h, err := inner.marshalMsg(true) 223 | if err != nil { 224 | return nil, err 225 | } 226 | h = h[4:] // strip four byte prefix 227 | 228 | var paddingLen int 229 | if inner.serverName != "" { 230 | paddingLen = max(0, maxNameLength-len(inner.serverName)) 231 | } else { 232 | paddingLen = maxNameLength + 9 233 | } 234 | paddingLen = 31 - ((len(h) + paddingLen - 1) % 32) 235 | 236 | return append(h, make([]byte, paddingLen)...), nil 237 | } 238 | 239 | func skipUint8LengthPrefixed(s *cryptobyte.String) bool { 240 | var skip uint8 241 | if !s.ReadUint8(&skip) { 242 | return false 243 | } 244 | return s.Skip(int(skip)) 245 | } 246 | 247 | func skipUint16LengthPrefixed(s *cryptobyte.String) bool { 248 | var skip uint16 249 | if !s.ReadUint16(&skip) { 250 | return false 251 | } 252 | return s.Skip(int(skip)) 253 | } 254 | 255 | type rawExtension struct { 256 | extType uint16 257 | data []byte 258 | } 259 | 260 | func extractRawExtensions(hello *clientHelloMsg) ([]rawExtension, error) { 261 | s := cryptobyte.String(hello.original) 262 | if !s.Skip(4+2+32) || // header, version, random 263 | !skipUint8LengthPrefixed(&s) || // session ID 264 | !skipUint16LengthPrefixed(&s) || // cipher suites 265 | !skipUint8LengthPrefixed(&s) { // compression methods 266 | return nil, errors.New("tls: malformed outer client hello") 267 | } 268 | var rawExtensions []rawExtension 269 | var extensions cryptobyte.String 270 | if !s.ReadUint16LengthPrefixed(&extensions) { 271 | return nil, errors.New("tls: malformed outer client hello") 272 | } 273 | 274 | for !extensions.Empty() { 275 | var extension uint16 276 | var extData cryptobyte.String 277 | if !extensions.ReadUint16(&extension) || 278 | !extensions.ReadUint16LengthPrefixed(&extData) { 279 | return nil, errors.New("tls: invalid inner client hello") 280 | } 281 | rawExtensions = append(rawExtensions, rawExtension{extension, extData}) 282 | } 283 | return rawExtensions, nil 284 | } 285 | 286 | func decodeInnerClientHello(outer *clientHelloMsg, encoded []byte) (*clientHelloMsg, error) { 287 | // Reconstructing the inner client hello from its encoded form is somewhat 288 | // complicated. It is missing its header (message type and length), session 289 | // ID, and the extensions may be compressed. Since we need to put the 290 | // extensions back in the same order as they were in the raw outer hello, 291 | // and since we don't store the raw extensions, or the order we parsed them 292 | // in, we need to reparse the raw extensions from the outer hello in order 293 | // to properly insert them into the inner hello. This _should_ result in raw 294 | // bytes which match the hello as it was generated by the client. 295 | innerReader := cryptobyte.String(encoded) 296 | var versionAndRandom, sessionID, cipherSuites, compressionMethods []byte 297 | var extensions cryptobyte.String 298 | if !innerReader.ReadBytes(&versionAndRandom, 2+32) || 299 | !readUint8LengthPrefixed(&innerReader, &sessionID) || 300 | len(sessionID) != 0 || 301 | !readUint16LengthPrefixed(&innerReader, &cipherSuites) || 302 | !readUint8LengthPrefixed(&innerReader, &compressionMethods) || 303 | !innerReader.ReadUint16LengthPrefixed(&extensions) { 304 | return nil, errors.New("tls: invalid inner client hello") 305 | } 306 | 307 | // The specification says we must verify that the trailing padding is all 308 | // zeros. This is kind of weird for TLS messages, where we generally just 309 | // throw away any trailing garbage. 310 | for _, p := range innerReader { 311 | if p != 0 { 312 | return nil, errors.New("tls: invalid inner client hello") 313 | } 314 | } 315 | 316 | rawOuterExts, err := extractRawExtensions(outer) 317 | if err != nil { 318 | return nil, err 319 | } 320 | 321 | recon := cryptobyte.NewBuilder(nil) 322 | recon.AddUint8(typeClientHello) 323 | recon.AddUint24LengthPrefixed(func(recon *cryptobyte.Builder) { 324 | recon.AddBytes(versionAndRandom) 325 | recon.AddUint8LengthPrefixed(func(recon *cryptobyte.Builder) { 326 | recon.AddBytes(outer.sessionId) 327 | }) 328 | recon.AddUint16LengthPrefixed(func(recon *cryptobyte.Builder) { 329 | recon.AddBytes(cipherSuites) 330 | }) 331 | recon.AddUint8LengthPrefixed(func(recon *cryptobyte.Builder) { 332 | recon.AddBytes(compressionMethods) 333 | }) 334 | recon.AddUint16LengthPrefixed(func(recon *cryptobyte.Builder) { 335 | for !extensions.Empty() { 336 | var extension uint16 337 | var extData cryptobyte.String 338 | if !extensions.ReadUint16(&extension) || 339 | !extensions.ReadUint16LengthPrefixed(&extData) { 340 | recon.SetError(errors.New("tls: invalid inner client hello")) 341 | return 342 | } 343 | if extension == extensionECHOuterExtensions { 344 | if !extData.ReadUint8LengthPrefixed(&extData) { 345 | recon.SetError(errors.New("tls: invalid inner client hello")) 346 | return 347 | } 348 | var i int 349 | for !extData.Empty() { 350 | var extType uint16 351 | if !extData.ReadUint16(&extType) { 352 | recon.SetError(errors.New("tls: invalid inner client hello")) 353 | return 354 | } 355 | if extType == extensionEncryptedClientHello { 356 | recon.SetError(errors.New("tls: invalid outer extensions")) 357 | return 358 | } 359 | for ; i <= len(rawOuterExts); i++ { 360 | if i == len(rawOuterExts) { 361 | recon.SetError(errors.New("tls: invalid outer extensions")) 362 | return 363 | } 364 | if rawOuterExts[i].extType == extType { 365 | break 366 | } 367 | } 368 | recon.AddUint16(rawOuterExts[i].extType) 369 | recon.AddUint16LengthPrefixed(func(recon *cryptobyte.Builder) { 370 | recon.AddBytes(rawOuterExts[i].data) 371 | }) 372 | } 373 | } else { 374 | recon.AddUint16(extension) 375 | recon.AddUint16LengthPrefixed(func(recon *cryptobyte.Builder) { 376 | recon.AddBytes(extData) 377 | }) 378 | } 379 | } 380 | }) 381 | }) 382 | 383 | reconBytes, err := recon.Bytes() 384 | if err != nil { 385 | return nil, err 386 | } 387 | inner := &clientHelloMsg{} 388 | if !inner.unmarshal(reconBytes) { 389 | return nil, errors.New("tls: invalid reconstructed inner client hello") 390 | } 391 | 392 | if !bytes.Equal(inner.encryptedClientHello, []byte{uint8(innerECHExt)}) { 393 | return nil, errInvalidECHExt 394 | } 395 | 396 | hasTLS13 := false 397 | for _, v := range inner.supportedVersions { 398 | // Skip GREASE values (values of the form 0x?A0A). 399 | // GREASE (Generate Random Extensions And Sustain Extensibility) is a mechanism used by 400 | // browsers like Chrome to ensure TLS implementations correctly ignore unknown values. 401 | // GREASE values follow a specific pattern: 0x?A0A, where ? can be any hex digit. 402 | // These values should be ignored when processing supported TLS versions. 403 | if v&0x0F0F == 0x0A0A && v&0xff == v>>8 { 404 | continue 405 | } 406 | 407 | // Ensure at least TLS 1.3 is offered. 408 | if v == VersionTLS13 { 409 | hasTLS13 = true 410 | } else if v < VersionTLS13 { 411 | // Reject if any non-GREASE value is below TLS 1.3, as ECH requires TLS 1.3+. 412 | return nil, errors.New("tls: client sent encrypted_client_hello extension with unsupported versions") 413 | } 414 | } 415 | 416 | if !hasTLS13 { 417 | return nil, errors.New("tls: client sent encrypted_client_hello extension but did not offer TLS 1.3") 418 | } 419 | 420 | return inner, nil 421 | } 422 | 423 | func decryptECHPayload(context *hpke.Recipient, hello, payload []byte) ([]byte, error) { 424 | outerAAD := bytes.Replace(hello[4:], payload, make([]byte, len(payload)), 1) 425 | return context.Open(outerAAD, payload) 426 | } 427 | 428 | func generateOuterECHExt(id uint8, kdfID, aeadID uint16, encodedKey []byte, payload []byte) ([]byte, error) { 429 | var b cryptobyte.Builder 430 | b.AddUint8(0) // outer 431 | b.AddUint16(kdfID) 432 | b.AddUint16(aeadID) 433 | b.AddUint8(id) 434 | b.AddUint16LengthPrefixed(func(b *cryptobyte.Builder) { b.AddBytes(encodedKey) }) 435 | b.AddUint16LengthPrefixed(func(b *cryptobyte.Builder) { b.AddBytes(payload) }) 436 | return b.Bytes() 437 | } 438 | 439 | func computeAndUpdateOuterECHExtension(outer, inner *clientHelloMsg, ech *echClientContext, useKey bool) error { 440 | var encapKey []byte 441 | if useKey { 442 | encapKey = ech.encapsulatedKey 443 | } 444 | encodedInner, err := encodeInnerClientHello(inner, int(ech.config.MaxNameLength)) 445 | if err != nil { 446 | return err 447 | } 448 | // NOTE: the tag lengths for all of the supported AEADs are the same (16 449 | // bytes), so we have hardcoded it here. If we add support for another AEAD 450 | // with a different tag length, we will need to change this. 451 | encryptedLen := len(encodedInner) + 16 // AEAD tag length 452 | outer.encryptedClientHello, err = generateOuterECHExt(ech.config.ConfigID, ech.kdfID, ech.aeadID, encapKey, make([]byte, encryptedLen)) 453 | if err != nil { 454 | return err 455 | } 456 | serializedOuter, err := outer.marshal() 457 | if err != nil { 458 | return err 459 | } 460 | serializedOuter = serializedOuter[4:] // strip the four byte prefix 461 | encryptedInner, err := ech.hpkeContext.Seal(serializedOuter, encodedInner) 462 | if err != nil { 463 | return err 464 | } 465 | outer.encryptedClientHello, err = generateOuterECHExt(ech.config.ConfigID, ech.kdfID, ech.aeadID, encapKey, encryptedInner) 466 | if err != nil { 467 | return err 468 | } 469 | return nil 470 | } 471 | 472 | // validDNSName is a rather rudimentary check for the validity of a DNS name. 473 | // This is used to check if the public_name in a ECHConfig is valid when we are 474 | // picking a config. This can be somewhat lax because even if we pick a 475 | // valid-looking name, the DNS layer will later reject it anyway. 476 | func validDNSName(name string) bool { 477 | if len(name) > 253 { 478 | return false 479 | } 480 | labels := strings.Split(name, ".") 481 | if len(labels) <= 1 { 482 | return false 483 | } 484 | for _, l := range labels { 485 | labelLen := len(l) 486 | if labelLen == 0 { 487 | return false 488 | } 489 | for i, r := range l { 490 | if r == '-' && (i == 0 || i == labelLen-1) { 491 | return false 492 | } 493 | if (r < '0' || r > '9') && (r < 'a' || r > 'z') && (r < 'A' || r > 'Z') && r != '-' { 494 | return false 495 | } 496 | } 497 | } 498 | return true 499 | } 500 | 501 | // ECHRejectionError is the error type returned when ECH is rejected by a remote 502 | // server. If the server offered a ECHConfigList to use for retries, the 503 | // RetryConfigList field will contain this list. 504 | // 505 | // The client may treat an ECHRejectionError with an empty set of RetryConfigs 506 | // as a secure signal from the server. 507 | type ECHRejectionError struct { 508 | RetryConfigList []byte 509 | } 510 | 511 | func (e *ECHRejectionError) Error() string { 512 | return "tls: server rejected ECH" 513 | } 514 | 515 | var errMalformedECHExt = errors.New("tls: malformed encrypted_client_hello extension") 516 | var errInvalidECHExt = errors.New("tls: client sent invalid encrypted_client_hello extension") 517 | 518 | type echExtType uint8 519 | 520 | const ( 521 | innerECHExt echExtType = 1 522 | outerECHExt echExtType = 0 523 | ) 524 | 525 | func parseECHExt(ext []byte) (echType echExtType, cs EchCipher, configID uint8, encap []byte, payload []byte, err error) { 526 | data := make([]byte, len(ext)) 527 | copy(data, ext) 528 | s := cryptobyte.String(data) 529 | var echInt uint8 530 | if !s.ReadUint8(&echInt) { 531 | err = errMalformedECHExt 532 | return 533 | } 534 | echType = echExtType(echInt) 535 | if echType == innerECHExt { 536 | if !s.Empty() { 537 | err = errMalformedECHExt 538 | return 539 | } 540 | return echType, cs, 0, nil, nil, nil 541 | } 542 | if echType != outerECHExt { 543 | err = errInvalidECHExt 544 | return 545 | } 546 | if !s.ReadUint16(&cs.KDFID) { 547 | err = errMalformedECHExt 548 | return 549 | } 550 | if !s.ReadUint16(&cs.AEADID) { 551 | err = errMalformedECHExt 552 | return 553 | } 554 | if !s.ReadUint8(&configID) { 555 | err = errMalformedECHExt 556 | return 557 | } 558 | if !readUint16LengthPrefixed(&s, &encap) { 559 | err = errMalformedECHExt 560 | return 561 | } 562 | if !readUint16LengthPrefixed(&s, &payload) { 563 | err = errMalformedECHExt 564 | return 565 | } 566 | 567 | // NOTE: clone encap and payload so that mutating them does not mutate the 568 | // raw extension bytes. 569 | return echType, cs, configID, bytes.Clone(encap), bytes.Clone(payload), nil 570 | } 571 | 572 | func marshalEncryptedClientHelloConfigList(configs []EncryptedClientHelloKey) ([]byte, error) { 573 | builder := cryptobyte.NewBuilder(nil) 574 | builder.AddUint16LengthPrefixed(func(builder *cryptobyte.Builder) { 575 | for _, c := range configs { 576 | builder.AddBytes(c.Config) 577 | } 578 | }) 579 | return builder.Bytes() 580 | } 581 | 582 | func (c *Conn) processECHClientHello(outer *clientHelloMsg, echKeys []EncryptedClientHelloKey) (*clientHelloMsg, *echServerContext, error) { 583 | echType, echCiphersuite, configID, encap, payload, err := parseECHExt(outer.encryptedClientHello) 584 | if err != nil { 585 | if errors.Is(err, errInvalidECHExt) { 586 | c.sendAlert(alertIllegalParameter) 587 | } else { 588 | c.sendAlert(alertDecodeError) 589 | } 590 | 591 | return nil, nil, errInvalidECHExt 592 | } 593 | 594 | if echType == innerECHExt { 595 | return outer, &echServerContext{inner: true}, nil 596 | } 597 | 598 | if len(echKeys) == 0 { 599 | return outer, nil, nil 600 | } 601 | 602 | for _, echKey := range echKeys { 603 | skip, config, err := parseECHConfig(echKey.Config) 604 | if err != nil || skip { 605 | c.sendAlert(alertInternalError) 606 | return nil, nil, fmt.Errorf("tls: invalid EncryptedClientHelloKeys Config: %s", err) 607 | } 608 | if skip { 609 | continue 610 | } 611 | echPriv, err := hpke.ParseHPKEPrivateKey(config.KemID, echKey.PrivateKey) 612 | if err != nil { 613 | c.sendAlert(alertInternalError) 614 | return nil, nil, fmt.Errorf("tls: invalid EncryptedClientHelloKeys PrivateKey: %s", err) 615 | } 616 | info := append([]byte("tls ech\x00"), echKey.Config...) 617 | hpkeContext, err := hpke.SetupRecipient(hpke.DHKEM_X25519_HKDF_SHA256, echCiphersuite.KDFID, echCiphersuite.AEADID, echPriv, info, encap) 618 | if err != nil { 619 | // attempt next trial decryption 620 | continue 621 | } 622 | 623 | encodedInner, err := decryptECHPayload(hpkeContext, outer.original, payload) 624 | if err != nil { 625 | // attempt next trial decryption 626 | continue 627 | } 628 | 629 | // NOTE: we do not enforce that the sent server_name matches the ECH 630 | // configs PublicName, since this is not particularly important, and 631 | // the client already had to know what it was in order to properly 632 | // encrypt the payload. This is only a MAY in the spec, so we're not 633 | // doing anything revolutionary. 634 | 635 | echInner, err := decodeInnerClientHello(outer, encodedInner) 636 | if err != nil { 637 | c.sendAlert(alertIllegalParameter) 638 | return nil, nil, errInvalidECHExt 639 | } 640 | 641 | c.echAccepted = true 642 | 643 | return echInner, &echServerContext{ 644 | hpkeContext: hpkeContext, 645 | configID: configID, 646 | ciphersuite: echCiphersuite, 647 | }, nil 648 | } 649 | 650 | return outer, nil, nil 651 | } 652 | 653 | func buildRetryConfigList(keys []EncryptedClientHelloKey) ([]byte, error) { 654 | var atLeastOneRetryConfig bool 655 | var retryBuilder cryptobyte.Builder 656 | retryBuilder.AddUint16LengthPrefixed(func(b *cryptobyte.Builder) { 657 | for _, c := range keys { 658 | if !c.SendAsRetry { 659 | continue 660 | } 661 | atLeastOneRetryConfig = true 662 | b.AddBytes(c.Config) 663 | } 664 | }) 665 | if !atLeastOneRetryConfig { 666 | return nil, nil 667 | } 668 | return retryBuilder.Bytes() 669 | } 670 | -------------------------------------------------------------------------------- /fips140tls/fipstls.go: -------------------------------------------------------------------------------- 1 | // Copyright 2024 The Go Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | // Package fips140tls controls whether crypto/tls requires FIPS-approved settings. 6 | package fips140tls 7 | 8 | import ( 9 | "crypto/fips140" 10 | "sync/atomic" 11 | ) 12 | 13 | var required atomic.Bool 14 | 15 | func init() { 16 | if fips140.Enabled() { 17 | Force() 18 | } 19 | } 20 | 21 | // Force forces crypto/tls to restrict TLS configurations to FIPS-approved settings. 22 | // By design, this call is impossible to undo (except in tests). 23 | func Force() { 24 | required.Store(true) 25 | } 26 | 27 | // Required reports whether FIPS-approved settings are required. 28 | // 29 | // Required is true if FIPS 140-3 mode is enabled with GODEBUG=fips140=on, or if 30 | // the crypto/tls/fipsonly package is imported by a Go+BoringCrypto build. 31 | func Required() bool { 32 | return required.Load() 33 | } 34 | 35 | func TestingOnlyAbandon() { 36 | required.Store(false) 37 | } -------------------------------------------------------------------------------- /generate_cert.go: -------------------------------------------------------------------------------- 1 | // Copyright 2009 The Go Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE-Go file. 4 | 5 | //go:build ignore 6 | 7 | // Generate a self-signed X.509 certificate for a TLS server. Outputs to 8 | // 'cert.pem' and 'key.pem' and will overwrite existing files. 9 | 10 | package main 11 | 12 | import ( 13 | "crypto/ecdsa" 14 | "crypto/ed25519" 15 | "crypto/elliptic" 16 | "crypto/rand" 17 | "crypto/rsa" 18 | "crypto/x509" 19 | "crypto/x509/pkix" 20 | "encoding/pem" 21 | "flag" 22 | "log" 23 | "math/big" 24 | "net" 25 | "os" 26 | "strings" 27 | "time" 28 | ) 29 | 30 | var ( 31 | host = flag.String("host", "", "Comma-separated hostnames and IPs to generate a certificate for") 32 | validFrom = flag.String("start-date", "", "Creation date formatted as Jan 1 15:04:05 2011") 33 | validFor = flag.Duration("duration", 365*24*time.Hour, "Duration that certificate is valid for") 34 | isCA = flag.Bool("ca", false, "whether this cert should be its own Certificate Authority") 35 | rsaBits = flag.Int("rsa-bits", 2048, "Size of RSA key to generate. Ignored if --ecdsa-curve is set") 36 | ecdsaCurve = flag.String("ecdsa-curve", "", "ECDSA curve to use to generate a key. Valid values are P224, P256 (recommended), P384, P521") 37 | ed25519Key = flag.Bool("ed25519", false, "Generate an Ed25519 key") 38 | ) 39 | 40 | func publicKey(priv any) any { 41 | switch k := priv.(type) { 42 | case *rsa.PrivateKey: 43 | return &k.PublicKey 44 | case *ecdsa.PrivateKey: 45 | return &k.PublicKey 46 | case ed25519.PrivateKey: 47 | return k.Public().(ed25519.PublicKey) 48 | default: 49 | return nil 50 | } 51 | } 52 | 53 | func main() { 54 | flag.Parse() 55 | 56 | if len(*host) == 0 { 57 | log.Fatalf("Missing required --host parameter") 58 | } 59 | 60 | var priv any 61 | var err error 62 | switch *ecdsaCurve { 63 | case "": 64 | if *ed25519Key { 65 | _, priv, err = ed25519.GenerateKey(rand.Reader) 66 | } else { 67 | priv, err = rsa.GenerateKey(rand.Reader, *rsaBits) 68 | } 69 | case "P224": 70 | priv, err = ecdsa.GenerateKey(elliptic.P224(), rand.Reader) 71 | case "P256": 72 | priv, err = ecdsa.GenerateKey(elliptic.P256(), rand.Reader) 73 | case "P384": 74 | priv, err = ecdsa.GenerateKey(elliptic.P384(), rand.Reader) 75 | case "P521": 76 | priv, err = ecdsa.GenerateKey(elliptic.P521(), rand.Reader) 77 | default: 78 | log.Fatalf("Unrecognized elliptic curve: %q", *ecdsaCurve) 79 | } 80 | if err != nil { 81 | log.Fatalf("Failed to generate private key: %v", err) 82 | } 83 | 84 | // ECDSA, ED25519 and RSA subject keys should have the DigitalSignature 85 | // KeyUsage bits set in the x509.Certificate template 86 | keyUsage := x509.KeyUsageDigitalSignature 87 | // Only RSA subject keys should have the KeyEncipherment KeyUsage bits set. In 88 | // the context of TLS this KeyUsage is particular to RSA key exchange and 89 | // authentication. 90 | if _, isRSA := priv.(*rsa.PrivateKey); isRSA { 91 | keyUsage |= x509.KeyUsageKeyEncipherment 92 | } 93 | 94 | var notBefore time.Time 95 | if len(*validFrom) == 0 { 96 | notBefore = time.Now() 97 | } else { 98 | notBefore, err = time.Parse("Jan 2 15:04:05 2006", *validFrom) 99 | if err != nil { 100 | log.Fatalf("Failed to parse creation date: %v", err) 101 | } 102 | } 103 | 104 | notAfter := notBefore.Add(*validFor) 105 | 106 | serialNumberLimit := new(big.Int).Lsh(big.NewInt(1), 128) 107 | serialNumber, err := rand.Int(rand.Reader, serialNumberLimit) 108 | if err != nil { 109 | log.Fatalf("Failed to generate serial number: %v", err) 110 | } 111 | 112 | template := x509.Certificate{ 113 | SerialNumber: serialNumber, 114 | Subject: pkix.Name{ 115 | Organization: []string{"Acme Co"}, 116 | }, 117 | NotBefore: notBefore, 118 | NotAfter: notAfter, 119 | 120 | KeyUsage: keyUsage, 121 | ExtKeyUsage: []x509.ExtKeyUsage{x509.ExtKeyUsageServerAuth}, 122 | BasicConstraintsValid: true, 123 | } 124 | 125 | hosts := strings.Split(*host, ",") 126 | for _, h := range hosts { 127 | if ip := net.ParseIP(h); ip != nil { 128 | template.IPAddresses = append(template.IPAddresses, ip) 129 | } else { 130 | template.DNSNames = append(template.DNSNames, h) 131 | } 132 | } 133 | 134 | if *isCA { 135 | template.IsCA = true 136 | template.KeyUsage |= x509.KeyUsageCertSign 137 | } 138 | 139 | derBytes, err := x509.CreateCertificate(rand.Reader, &template, &template, publicKey(priv), priv) 140 | if err != nil { 141 | log.Fatalf("Failed to create certificate: %v", err) 142 | } 143 | 144 | certOut, err := os.Create("cert.pem") 145 | if err != nil { 146 | log.Fatalf("Failed to open cert.pem for writing: %v", err) 147 | } 148 | if err := pem.Encode(certOut, &pem.Block{Type: "CERTIFICATE", Bytes: derBytes}); err != nil { 149 | log.Fatalf("Failed to write data to cert.pem: %v", err) 150 | } 151 | if err := certOut.Close(); err != nil { 152 | log.Fatalf("Error closing cert.pem: %v", err) 153 | } 154 | log.Print("wrote cert.pem\n") 155 | 156 | keyOut, err := os.OpenFile("key.pem", os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0600) 157 | if err != nil { 158 | log.Fatalf("Failed to open key.pem for writing: %v", err) 159 | } 160 | privBytes, err := x509.MarshalPKCS8PrivateKey(priv) 161 | if err != nil { 162 | log.Fatalf("Unable to marshal private key: %v", err) 163 | } 164 | if err := pem.Encode(keyOut, &pem.Block{Type: "PRIVATE KEY", Bytes: privBytes}); err != nil { 165 | log.Fatalf("Failed to write data to key.pem: %v", err) 166 | } 167 | if err := keyOut.Close(); err != nil { 168 | log.Fatalf("Error closing key.pem: %v", err) 169 | } 170 | log.Print("wrote key.pem\n") 171 | } 172 | -------------------------------------------------------------------------------- /go.mod: -------------------------------------------------------------------------------- 1 | module github.com/xtls/reality 2 | 3 | go 1.24 4 | 5 | require ( 6 | github.com/pires/go-proxyproto v0.8.1 7 | golang.org/x/crypto v0.38.0 8 | golang.org/x/sys v0.33.0 9 | ) 10 | -------------------------------------------------------------------------------- /go.sum: -------------------------------------------------------------------------------- 1 | github.com/pires/go-proxyproto v0.8.1 h1:9KEixbdJfhrbtjpz/ZwCdWDD2Xem0NZ38qMYaASJgp0= 2 | github.com/pires/go-proxyproto v0.8.1/go.mod h1:ZKAAyp3cgy5Y5Mo4n9AlScrkCZwUy0g3Jf+slqQVcuU= 3 | golang.org/x/crypto v0.38.0 h1:jt+WWG8IZlBnVbomuhg2Mdq0+BBQaHbtqHEFEigjUV8= 4 | golang.org/x/crypto v0.38.0/go.mod h1:MvrbAqul58NNYPKnOra203SB9vpuZW0e+RRZV+Ggqjw= 5 | golang.org/x/sys v0.33.0 h1:q3i8TbbEz+JRD9ywIRlyRAQbM0qF7hu24q3teo2hbuw= 6 | golang.org/x/sys v0.33.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k= 7 | -------------------------------------------------------------------------------- /hpke/hpye.go: -------------------------------------------------------------------------------- 1 | // Copyright 2024 The Go Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package hpke 6 | 7 | import ( 8 | "crypto" 9 | "crypto/aes" 10 | "crypto/cipher" 11 | "crypto/ecdh" 12 | "crypto/hkdf" 13 | "crypto/rand" 14 | "encoding/binary" 15 | "errors" 16 | "math/bits" 17 | 18 | "golang.org/x/crypto/chacha20poly1305" 19 | ) 20 | 21 | // testingOnlyGenerateKey is only used during testing, to provide 22 | // a fixed test key to use when checking the RFC 9180 vectors. 23 | var testingOnlyGenerateKey func() (*ecdh.PrivateKey, error) 24 | 25 | type hkdfKDF struct { 26 | hash crypto.Hash 27 | } 28 | 29 | func (kdf *hkdfKDF) LabeledExtract(sid []byte, salt []byte, label string, inputKey []byte) ([]byte, error) { 30 | labeledIKM := make([]byte, 0, 7+len(sid)+len(label)+len(inputKey)) 31 | labeledIKM = append(labeledIKM, []byte("HPKE-v1")...) 32 | labeledIKM = append(labeledIKM, sid...) 33 | labeledIKM = append(labeledIKM, label...) 34 | labeledIKM = append(labeledIKM, inputKey...) 35 | return hkdf.Extract(kdf.hash.New, labeledIKM, salt) 36 | } 37 | 38 | func (kdf *hkdfKDF) LabeledExpand(suiteID []byte, randomKey []byte, label string, info []byte, length uint16) ([]byte, error) { 39 | labeledInfo := make([]byte, 0, 2+7+len(suiteID)+len(label)+len(info)) 40 | labeledInfo = binary.BigEndian.AppendUint16(labeledInfo, length) 41 | labeledInfo = append(labeledInfo, []byte("HPKE-v1")...) 42 | labeledInfo = append(labeledInfo, suiteID...) 43 | labeledInfo = append(labeledInfo, label...) 44 | labeledInfo = append(labeledInfo, info...) 45 | return hkdf.Expand(kdf.hash.New, randomKey, string(labeledInfo), int(length)) 46 | } 47 | 48 | // dhKEM implements the KEM specified in RFC 9180, Section 4.1. 49 | type dhKEM struct { 50 | dh ecdh.Curve 51 | kdf hkdfKDF 52 | 53 | suiteID []byte 54 | nSecret uint16 55 | } 56 | 57 | type KemID uint16 58 | 59 | const DHKEM_X25519_HKDF_SHA256 = 0x0020 60 | 61 | var SupportedKEMs = map[uint16]struct { 62 | curve ecdh.Curve 63 | hash crypto.Hash 64 | nSecret uint16 65 | }{ 66 | // RFC 9180 Section 7.1 67 | DHKEM_X25519_HKDF_SHA256: {ecdh.X25519(), crypto.SHA256, 32}, 68 | } 69 | 70 | func newDHKem(kemID uint16) (*dhKEM, error) { 71 | suite, ok := SupportedKEMs[kemID] 72 | if !ok { 73 | return nil, errors.New("unsupported suite ID") 74 | } 75 | return &dhKEM{ 76 | dh: suite.curve, 77 | kdf: hkdfKDF{suite.hash}, 78 | suiteID: binary.BigEndian.AppendUint16([]byte("KEM"), kemID), 79 | nSecret: suite.nSecret, 80 | }, nil 81 | } 82 | 83 | func (dh *dhKEM) ExtractAndExpand(dhKey, kemContext []byte) ([]byte, error) { 84 | eaePRK, err := dh.kdf.LabeledExtract(dh.suiteID[:], nil, "eae_prk", dhKey) 85 | if err != nil { 86 | return nil, err 87 | } 88 | return dh.kdf.LabeledExpand(dh.suiteID[:], eaePRK, "shared_secret", kemContext, dh.nSecret) 89 | } 90 | 91 | func (dh *dhKEM) Encap(pubRecipient *ecdh.PublicKey) (sharedSecret []byte, encapPub []byte, err error) { 92 | var privEph *ecdh.PrivateKey 93 | if testingOnlyGenerateKey != nil { 94 | privEph, err = testingOnlyGenerateKey() 95 | } else { 96 | privEph, err = dh.dh.GenerateKey(rand.Reader) 97 | } 98 | if err != nil { 99 | return nil, nil, err 100 | } 101 | dhVal, err := privEph.ECDH(pubRecipient) 102 | if err != nil { 103 | return nil, nil, err 104 | } 105 | encPubEph := privEph.PublicKey().Bytes() 106 | 107 | encPubRecip := pubRecipient.Bytes() 108 | kemContext := append(encPubEph, encPubRecip...) 109 | sharedSecret, err = dh.ExtractAndExpand(dhVal, kemContext) 110 | if err != nil { 111 | return nil, nil, err 112 | } 113 | return sharedSecret, encPubEph, nil 114 | } 115 | 116 | func (dh *dhKEM) Decap(encPubEph []byte, secRecipient *ecdh.PrivateKey) ([]byte, error) { 117 | pubEph, err := dh.dh.NewPublicKey(encPubEph) 118 | if err != nil { 119 | return nil, err 120 | } 121 | dhVal, err := secRecipient.ECDH(pubEph) 122 | if err != nil { 123 | return nil, err 124 | } 125 | kemContext := append(encPubEph, secRecipient.PublicKey().Bytes()...) 126 | return dh.ExtractAndExpand(dhVal, kemContext) 127 | } 128 | 129 | type context struct { 130 | aead cipher.AEAD 131 | 132 | sharedSecret []byte 133 | 134 | suiteID []byte 135 | 136 | key []byte 137 | baseNonce []byte 138 | exporterSecret []byte 139 | 140 | seqNum uint128 141 | } 142 | 143 | type Sender struct { 144 | *context 145 | } 146 | 147 | type Recipient struct { 148 | *context 149 | } 150 | 151 | var aesGCMNew = func(key []byte) (cipher.AEAD, error) { 152 | block, err := aes.NewCipher(key) 153 | if err != nil { 154 | return nil, err 155 | } 156 | return cipher.NewGCM(block) 157 | } 158 | 159 | type AEADID uint16 160 | 161 | const ( 162 | AEAD_AES_128_GCM = 0x0001 163 | AEAD_AES_256_GCM = 0x0002 164 | AEAD_ChaCha20Poly1305 = 0x0003 165 | ) 166 | 167 | var SupportedAEADs = map[uint16]struct { 168 | keySize int 169 | nonceSize int 170 | aead func([]byte) (cipher.AEAD, error) 171 | }{ 172 | // RFC 9180, Section 7.3 173 | AEAD_AES_128_GCM: {keySize: 16, nonceSize: 12, aead: aesGCMNew}, 174 | AEAD_AES_256_GCM: {keySize: 32, nonceSize: 12, aead: aesGCMNew}, 175 | AEAD_ChaCha20Poly1305: {keySize: chacha20poly1305.KeySize, nonceSize: chacha20poly1305.NonceSize, aead: chacha20poly1305.New}, 176 | } 177 | 178 | type KDFID uint16 179 | 180 | const KDF_HKDF_SHA256 = 0x0001 181 | 182 | var SupportedKDFs = map[uint16]func() *hkdfKDF{ 183 | // RFC 9180, Section 7.2 184 | KDF_HKDF_SHA256: func() *hkdfKDF { return &hkdfKDF{crypto.SHA256} }, 185 | } 186 | 187 | func newContext(sharedSecret []byte, kemID, kdfID, aeadID uint16, info []byte) (*context, error) { 188 | sid := suiteID(kemID, kdfID, aeadID) 189 | 190 | kdfInit, ok := SupportedKDFs[kdfID] 191 | if !ok { 192 | return nil, errors.New("unsupported KDF id") 193 | } 194 | kdf := kdfInit() 195 | 196 | aeadInfo, ok := SupportedAEADs[aeadID] 197 | if !ok { 198 | return nil, errors.New("unsupported AEAD id") 199 | } 200 | 201 | pskIDHash, err := kdf.LabeledExtract(sid, nil, "psk_id_hash", nil) 202 | if err != nil { 203 | return nil, err 204 | } 205 | infoHash, err := kdf.LabeledExtract(sid, nil, "info_hash", info) 206 | if err != nil { 207 | return nil, err 208 | } 209 | ksContext := append([]byte{0}, pskIDHash...) 210 | ksContext = append(ksContext, infoHash...) 211 | 212 | secret, err := kdf.LabeledExtract(sid, sharedSecret, "secret", nil) 213 | if err != nil { 214 | return nil, err 215 | } 216 | key, err := kdf.LabeledExpand(sid, secret, "key", ksContext, uint16(aeadInfo.keySize) /* Nk - key size for AEAD */) 217 | if err != nil { 218 | return nil, err 219 | } 220 | baseNonce, err := kdf.LabeledExpand(sid, secret, "base_nonce", ksContext, uint16(aeadInfo.nonceSize) /* Nn - nonce size for AEAD */) 221 | if err != nil { 222 | return nil, err 223 | } 224 | exporterSecret, err := kdf.LabeledExpand(sid, secret, "exp", ksContext, uint16(kdf.hash.Size()) /* Nh - hash output size of the kdf*/) 225 | if err != nil { 226 | return nil, err 227 | } 228 | 229 | aead, err := aeadInfo.aead(key) 230 | if err != nil { 231 | return nil, err 232 | } 233 | 234 | return &context{ 235 | aead: aead, 236 | sharedSecret: sharedSecret, 237 | suiteID: sid, 238 | key: key, 239 | baseNonce: baseNonce, 240 | exporterSecret: exporterSecret, 241 | }, nil 242 | } 243 | 244 | func SetupSender(kemID, kdfID, aeadID uint16, pub *ecdh.PublicKey, info []byte) ([]byte, *Sender, error) { 245 | kem, err := newDHKem(kemID) 246 | if err != nil { 247 | return nil, nil, err 248 | } 249 | sharedSecret, encapsulatedKey, err := kem.Encap(pub) 250 | if err != nil { 251 | return nil, nil, err 252 | } 253 | 254 | context, err := newContext(sharedSecret, kemID, kdfID, aeadID, info) 255 | if err != nil { 256 | return nil, nil, err 257 | } 258 | 259 | return encapsulatedKey, &Sender{context}, nil 260 | } 261 | 262 | func SetupRecipient(kemID, kdfID, aeadID uint16, priv *ecdh.PrivateKey, info, encPubEph []byte) (*Recipient, error) { 263 | kem, err := newDHKem(kemID) 264 | if err != nil { 265 | return nil, err 266 | } 267 | sharedSecret, err := kem.Decap(encPubEph, priv) 268 | if err != nil { 269 | return nil, err 270 | } 271 | 272 | context, err := newContext(sharedSecret, kemID, kdfID, aeadID, info) 273 | if err != nil { 274 | return nil, err 275 | } 276 | 277 | return &Recipient{context}, nil 278 | } 279 | 280 | func (ctx *context) nextNonce() []byte { 281 | nonce := ctx.seqNum.bytes()[16-ctx.aead.NonceSize():] 282 | for i := range ctx.baseNonce { 283 | nonce[i] ^= ctx.baseNonce[i] 284 | } 285 | return nonce 286 | } 287 | 288 | func (ctx *context) incrementNonce() { 289 | // Message limit is, according to the RFC, 2^95+1, which 290 | // is somewhat confusing, but we do as we're told. 291 | if ctx.seqNum.bitLen() >= (ctx.aead.NonceSize()*8)-1 { 292 | panic("message limit reached") 293 | } 294 | ctx.seqNum = ctx.seqNum.addOne() 295 | } 296 | 297 | func (s *Sender) Seal(aad, plaintext []byte) ([]byte, error) { 298 | ciphertext := s.aead.Seal(nil, s.nextNonce(), plaintext, aad) 299 | s.incrementNonce() 300 | return ciphertext, nil 301 | } 302 | 303 | func (r *Recipient) Open(aad, ciphertext []byte) ([]byte, error) { 304 | plaintext, err := r.aead.Open(nil, r.nextNonce(), ciphertext, aad) 305 | if err != nil { 306 | return nil, err 307 | } 308 | r.incrementNonce() 309 | return plaintext, nil 310 | } 311 | 312 | func suiteID(kemID, kdfID, aeadID uint16) []byte { 313 | suiteID := make([]byte, 0, 4+2+2+2) 314 | suiteID = append(suiteID, []byte("HPKE")...) 315 | suiteID = binary.BigEndian.AppendUint16(suiteID, kemID) 316 | suiteID = binary.BigEndian.AppendUint16(suiteID, kdfID) 317 | suiteID = binary.BigEndian.AppendUint16(suiteID, aeadID) 318 | return suiteID 319 | } 320 | 321 | func ParseHPKEPublicKey(kemID uint16, bytes []byte) (*ecdh.PublicKey, error) { 322 | kemInfo, ok := SupportedKEMs[kemID] 323 | if !ok { 324 | return nil, errors.New("unsupported KEM id") 325 | } 326 | return kemInfo.curve.NewPublicKey(bytes) 327 | } 328 | 329 | func ParseHPKEPrivateKey(kemID uint16, bytes []byte) (*ecdh.PrivateKey, error) { 330 | kemInfo, ok := SupportedKEMs[kemID] 331 | if !ok { 332 | return nil, errors.New("unsupported KEM id") 333 | } 334 | return kemInfo.curve.NewPrivateKey(bytes) 335 | } 336 | 337 | type uint128 struct { 338 | hi, lo uint64 339 | } 340 | 341 | func (u uint128) addOne() uint128 { 342 | lo, carry := bits.Add64(u.lo, 1, 0) 343 | return uint128{u.hi + carry, lo} 344 | } 345 | 346 | func (u uint128) bitLen() int { 347 | return bits.Len64(u.hi) + bits.Len64(u.lo) 348 | } 349 | 350 | func (u uint128) bytes() []byte { 351 | b := make([]byte, 16) 352 | binary.BigEndian.PutUint64(b[0:], u.hi) 353 | binary.BigEndian.PutUint64(b[8:], u.lo) 354 | return b 355 | } -------------------------------------------------------------------------------- /key_agreement.go: -------------------------------------------------------------------------------- 1 | // Copyright 2010 The Go Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE-Go file. 4 | 5 | package reality 6 | 7 | import ( 8 | "crypto" 9 | "crypto/ecdh" 10 | "crypto/md5" 11 | "crypto/rsa" 12 | "crypto/sha1" 13 | "crypto/x509" 14 | "errors" 15 | "fmt" 16 | "io" 17 | "slices" 18 | ) 19 | 20 | // A keyAgreement implements the client and server side of a TLS 1.0–1.2 key 21 | // agreement protocol by generating and processing key exchange messages. 22 | type keyAgreement interface { 23 | // On the server side, the first two methods are called in order. 24 | 25 | // In the case that the key agreement protocol doesn't use a 26 | // ServerKeyExchange message, generateServerKeyExchange can return nil, 27 | // nil. 28 | generateServerKeyExchange(*Config, *Certificate, *clientHelloMsg, *serverHelloMsg) (*serverKeyExchangeMsg, error) 29 | processClientKeyExchange(*Config, *Certificate, *clientKeyExchangeMsg, uint16) ([]byte, error) 30 | 31 | // On the client side, the next two methods are called in order. 32 | 33 | // This method may not be called if the server doesn't send a 34 | // ServerKeyExchange message. 35 | processServerKeyExchange(*Config, *clientHelloMsg, *serverHelloMsg, *x509.Certificate, *serverKeyExchangeMsg) error 36 | generateClientKeyExchange(*Config, *clientHelloMsg, *x509.Certificate) ([]byte, *clientKeyExchangeMsg, error) 37 | } 38 | 39 | var errClientKeyExchange = errors.New("tls: invalid ClientKeyExchange message") 40 | var errServerKeyExchange = errors.New("tls: invalid ServerKeyExchange message") 41 | 42 | // rsaKeyAgreement implements the standard TLS key agreement where the client 43 | // encrypts the pre-master secret to the server's public key. 44 | type rsaKeyAgreement struct{} 45 | 46 | func (ka rsaKeyAgreement) generateServerKeyExchange(config *Config, cert *Certificate, clientHello *clientHelloMsg, hello *serverHelloMsg) (*serverKeyExchangeMsg, error) { 47 | return nil, nil 48 | } 49 | 50 | func (ka rsaKeyAgreement) processClientKeyExchange(config *Config, cert *Certificate, ckx *clientKeyExchangeMsg, version uint16) ([]byte, error) { 51 | if len(ckx.ciphertext) < 2 { 52 | return nil, errClientKeyExchange 53 | } 54 | ciphertextLen := int(ckx.ciphertext[0])<<8 | int(ckx.ciphertext[1]) 55 | if ciphertextLen != len(ckx.ciphertext)-2 { 56 | return nil, errClientKeyExchange 57 | } 58 | ciphertext := ckx.ciphertext[2:] 59 | 60 | priv, ok := cert.PrivateKey.(crypto.Decrypter) 61 | if !ok { 62 | return nil, errors.New("tls: certificate private key does not implement crypto.Decrypter") 63 | } 64 | // Perform constant time RSA PKCS #1 v1.5 decryption 65 | preMasterSecret, err := priv.Decrypt(config.rand(), ciphertext, &rsa.PKCS1v15DecryptOptions{SessionKeyLen: 48}) 66 | if err != nil { 67 | return nil, err 68 | } 69 | // We don't check the version number in the premaster secret. For one, 70 | // by checking it, we would leak information about the validity of the 71 | // encrypted pre-master secret. Secondly, it provides only a small 72 | // benefit against a downgrade attack and some implementations send the 73 | // wrong version anyway. See the discussion at the end of section 74 | // 7.4.7.1 of RFC 4346. 75 | return preMasterSecret, nil 76 | } 77 | 78 | func (ka rsaKeyAgreement) processServerKeyExchange(config *Config, clientHello *clientHelloMsg, serverHello *serverHelloMsg, cert *x509.Certificate, skx *serverKeyExchangeMsg) error { 79 | return errors.New("tls: unexpected ServerKeyExchange") 80 | } 81 | 82 | func (ka rsaKeyAgreement) generateClientKeyExchange(config *Config, clientHello *clientHelloMsg, cert *x509.Certificate) ([]byte, *clientKeyExchangeMsg, error) { 83 | preMasterSecret := make([]byte, 48) 84 | preMasterSecret[0] = byte(clientHello.vers >> 8) 85 | preMasterSecret[1] = byte(clientHello.vers) 86 | _, err := io.ReadFull(config.rand(), preMasterSecret[2:]) 87 | if err != nil { 88 | return nil, nil, err 89 | } 90 | 91 | rsaKey, ok := cert.PublicKey.(*rsa.PublicKey) 92 | if !ok { 93 | return nil, nil, errors.New("tls: server certificate contains incorrect key type for selected ciphersuite") 94 | } 95 | encrypted, err := rsa.EncryptPKCS1v15(config.rand(), rsaKey, preMasterSecret) 96 | if err != nil { 97 | return nil, nil, err 98 | } 99 | ckx := new(clientKeyExchangeMsg) 100 | ckx.ciphertext = make([]byte, len(encrypted)+2) 101 | ckx.ciphertext[0] = byte(len(encrypted) >> 8) 102 | ckx.ciphertext[1] = byte(len(encrypted)) 103 | copy(ckx.ciphertext[2:], encrypted) 104 | return preMasterSecret, ckx, nil 105 | } 106 | 107 | // sha1Hash calculates a SHA1 hash over the given byte slices. 108 | func sha1Hash(slices [][]byte) []byte { 109 | hsha1 := sha1.New() 110 | for _, slice := range slices { 111 | hsha1.Write(slice) 112 | } 113 | return hsha1.Sum(nil) 114 | } 115 | 116 | // md5SHA1Hash implements TLS 1.0's hybrid hash function which consists of the 117 | // concatenation of an MD5 and SHA1 hash. 118 | func md5SHA1Hash(slices [][]byte) []byte { 119 | md5sha1 := make([]byte, md5.Size+sha1.Size) 120 | hmd5 := md5.New() 121 | for _, slice := range slices { 122 | hmd5.Write(slice) 123 | } 124 | copy(md5sha1, hmd5.Sum(nil)) 125 | copy(md5sha1[md5.Size:], sha1Hash(slices)) 126 | return md5sha1 127 | } 128 | 129 | // hashForServerKeyExchange hashes the given slices and returns their digest 130 | // using the given hash function (for TLS 1.2) or using a default based on 131 | // the sigType (for earlier TLS versions). For Ed25519 signatures, which don't 132 | // do pre-hashing, it returns the concatenation of the slices. 133 | func hashForServerKeyExchange(sigType uint8, hashFunc crypto.Hash, version uint16, slices ...[]byte) []byte { 134 | if sigType == signatureEd25519 { 135 | var signed []byte 136 | for _, slice := range slices { 137 | signed = append(signed, slice...) 138 | } 139 | return signed 140 | } 141 | if version >= VersionTLS12 { 142 | h := hashFunc.New() 143 | for _, slice := range slices { 144 | h.Write(slice) 145 | } 146 | digest := h.Sum(nil) 147 | return digest 148 | } 149 | if sigType == signatureECDSA { 150 | return sha1Hash(slices) 151 | } 152 | return md5SHA1Hash(slices) 153 | } 154 | 155 | // ecdheKeyAgreement implements a TLS key agreement where the server 156 | // generates an ephemeral EC public/private key pair and signs it. The 157 | // pre-master secret is then calculated using ECDH. The signature may 158 | // be ECDSA, Ed25519 or RSA. 159 | type ecdheKeyAgreement struct { 160 | version uint16 161 | isRSA bool 162 | key *ecdh.PrivateKey 163 | 164 | // ckx and preMasterSecret are generated in processServerKeyExchange 165 | // and returned in generateClientKeyExchange. 166 | ckx *clientKeyExchangeMsg 167 | preMasterSecret []byte 168 | } 169 | 170 | func (ka *ecdheKeyAgreement) generateServerKeyExchange(config *Config, cert *Certificate, clientHello *clientHelloMsg, hello *serverHelloMsg) (*serverKeyExchangeMsg, error) { 171 | var curveID CurveID 172 | for _, c := range clientHello.supportedCurves { 173 | if config.supportsCurve(ka.version, c) { 174 | curveID = c 175 | break 176 | } 177 | } 178 | 179 | if curveID == 0 { 180 | return nil, errors.New("tls: no supported elliptic curves offered") 181 | } 182 | if _, ok := curveForCurveID(curveID); !ok { 183 | return nil, errors.New("tls: CurvePreferences includes unsupported curve") 184 | } 185 | 186 | key, err := generateECDHEKey(config.rand(), curveID) 187 | if err != nil { 188 | return nil, err 189 | } 190 | ka.key = key 191 | 192 | // See RFC 4492, Section 5.4. 193 | ecdhePublic := key.PublicKey().Bytes() 194 | serverECDHEParams := make([]byte, 1+2+1+len(ecdhePublic)) 195 | serverECDHEParams[0] = 3 // named curve 196 | serverECDHEParams[1] = byte(curveID >> 8) 197 | serverECDHEParams[2] = byte(curveID) 198 | serverECDHEParams[3] = byte(len(ecdhePublic)) 199 | copy(serverECDHEParams[4:], ecdhePublic) 200 | 201 | priv, ok := cert.PrivateKey.(crypto.Signer) 202 | if !ok { 203 | return nil, fmt.Errorf("tls: certificate private key of type %T does not implement crypto.Signer", cert.PrivateKey) 204 | } 205 | 206 | var signatureAlgorithm SignatureScheme 207 | var sigType uint8 208 | var sigHash crypto.Hash 209 | if ka.version >= VersionTLS12 { 210 | signatureAlgorithm, err = selectSignatureScheme(ka.version, cert, clientHello.supportedSignatureAlgorithms) 211 | if err != nil { 212 | return nil, err 213 | } 214 | sigType, sigHash, err = typeAndHashFromSignatureScheme(signatureAlgorithm) 215 | if err != nil { 216 | return nil, err 217 | } 218 | } else { 219 | sigType, sigHash, err = legacyTypeAndHashFromPublicKey(priv.Public()) 220 | if err != nil { 221 | return nil, err 222 | } 223 | } 224 | if (sigType == signaturePKCS1v15 || sigType == signatureRSAPSS) != ka.isRSA { 225 | return nil, errors.New("tls: certificate cannot be used with the selected cipher suite") 226 | } 227 | 228 | signed := hashForServerKeyExchange(sigType, sigHash, ka.version, clientHello.random, hello.random, serverECDHEParams) 229 | 230 | signOpts := crypto.SignerOpts(sigHash) 231 | if sigType == signatureRSAPSS { 232 | signOpts = &rsa.PSSOptions{SaltLength: rsa.PSSSaltLengthEqualsHash, Hash: sigHash} 233 | } 234 | sig, err := priv.Sign(config.rand(), signed, signOpts) 235 | if err != nil { 236 | return nil, errors.New("tls: failed to sign ECDHE parameters: " + err.Error()) 237 | } 238 | 239 | skx := new(serverKeyExchangeMsg) 240 | sigAndHashLen := 0 241 | if ka.version >= VersionTLS12 { 242 | sigAndHashLen = 2 243 | } 244 | skx.key = make([]byte, len(serverECDHEParams)+sigAndHashLen+2+len(sig)) 245 | copy(skx.key, serverECDHEParams) 246 | k := skx.key[len(serverECDHEParams):] 247 | if ka.version >= VersionTLS12 { 248 | k[0] = byte(signatureAlgorithm >> 8) 249 | k[1] = byte(signatureAlgorithm) 250 | k = k[2:] 251 | } 252 | k[0] = byte(len(sig) >> 8) 253 | k[1] = byte(len(sig)) 254 | copy(k[2:], sig) 255 | 256 | return skx, nil 257 | } 258 | 259 | func (ka *ecdheKeyAgreement) processClientKeyExchange(config *Config, cert *Certificate, ckx *clientKeyExchangeMsg, version uint16) ([]byte, error) { 260 | if len(ckx.ciphertext) == 0 || int(ckx.ciphertext[0]) != len(ckx.ciphertext)-1 { 261 | return nil, errClientKeyExchange 262 | } 263 | 264 | peerKey, err := ka.key.Curve().NewPublicKey(ckx.ciphertext[1:]) 265 | if err != nil { 266 | return nil, errClientKeyExchange 267 | } 268 | preMasterSecret, err := ka.key.ECDH(peerKey) 269 | if err != nil { 270 | return nil, errClientKeyExchange 271 | } 272 | 273 | return preMasterSecret, nil 274 | } 275 | 276 | func (ka *ecdheKeyAgreement) processServerKeyExchange(config *Config, clientHello *clientHelloMsg, serverHello *serverHelloMsg, cert *x509.Certificate, skx *serverKeyExchangeMsg) error { 277 | if len(skx.key) < 4 { 278 | return errServerKeyExchange 279 | } 280 | if skx.key[0] != 3 { // named curve 281 | return errors.New("tls: server selected unsupported curve") 282 | } 283 | curveID := CurveID(skx.key[1])<<8 | CurveID(skx.key[2]) 284 | 285 | publicLen := int(skx.key[3]) 286 | if publicLen+4 > len(skx.key) { 287 | return errServerKeyExchange 288 | } 289 | serverECDHEParams := skx.key[:4+publicLen] 290 | publicKey := serverECDHEParams[4:] 291 | 292 | sig := skx.key[4+publicLen:] 293 | if len(sig) < 2 { 294 | return errServerKeyExchange 295 | } 296 | 297 | if !slices.Contains(clientHello.supportedCurves, curveID) { 298 | return errors.New("tls: server selected unoffered curve") 299 | } 300 | 301 | if _, ok := curveForCurveID(curveID); !ok { 302 | return errors.New("tls: server selected unsupported curve") 303 | } 304 | 305 | key, err := generateECDHEKey(config.rand(), curveID) 306 | if err != nil { 307 | return err 308 | } 309 | ka.key = key 310 | 311 | peerKey, err := key.Curve().NewPublicKey(publicKey) 312 | if err != nil { 313 | return errServerKeyExchange 314 | } 315 | ka.preMasterSecret, err = key.ECDH(peerKey) 316 | if err != nil { 317 | return errServerKeyExchange 318 | } 319 | 320 | ourPublicKey := key.PublicKey().Bytes() 321 | ka.ckx = new(clientKeyExchangeMsg) 322 | ka.ckx.ciphertext = make([]byte, 1+len(ourPublicKey)) 323 | ka.ckx.ciphertext[0] = byte(len(ourPublicKey)) 324 | copy(ka.ckx.ciphertext[1:], ourPublicKey) 325 | 326 | var sigType uint8 327 | var sigHash crypto.Hash 328 | if ka.version >= VersionTLS12 { 329 | signatureAlgorithm := SignatureScheme(sig[0])<<8 | SignatureScheme(sig[1]) 330 | sig = sig[2:] 331 | if len(sig) < 2 { 332 | return errServerKeyExchange 333 | } 334 | 335 | if !isSupportedSignatureAlgorithm(signatureAlgorithm, clientHello.supportedSignatureAlgorithms) { 336 | return errors.New("tls: certificate used with invalid signature algorithm") 337 | } 338 | sigType, sigHash, err = typeAndHashFromSignatureScheme(signatureAlgorithm) 339 | if err != nil { 340 | return err 341 | } 342 | } else { 343 | sigType, sigHash, err = legacyTypeAndHashFromPublicKey(cert.PublicKey) 344 | if err != nil { 345 | return err 346 | } 347 | } 348 | if (sigType == signaturePKCS1v15 || sigType == signatureRSAPSS) != ka.isRSA { 349 | return errServerKeyExchange 350 | } 351 | 352 | sigLen := int(sig[0])<<8 | int(sig[1]) 353 | if sigLen+2 != len(sig) { 354 | return errServerKeyExchange 355 | } 356 | sig = sig[2:] 357 | 358 | signed := hashForServerKeyExchange(sigType, sigHash, ka.version, clientHello.random, serverHello.random, serverECDHEParams) 359 | if err := verifyHandshakeSignature(sigType, cert.PublicKey, sigHash, signed, sig); err != nil { 360 | return errors.New("tls: invalid signature by the server certificate: " + err.Error()) 361 | } 362 | return nil 363 | } 364 | 365 | func (ka *ecdheKeyAgreement) generateClientKeyExchange(config *Config, clientHello *clientHelloMsg, cert *x509.Certificate) ([]byte, *clientKeyExchangeMsg, error) { 366 | if ka.ckx == nil { 367 | return nil, nil, errors.New("tls: missing ServerKeyExchange message") 368 | } 369 | 370 | return ka.preMasterSecret, ka.ckx, nil 371 | } 372 | -------------------------------------------------------------------------------- /key_schedule.go: -------------------------------------------------------------------------------- 1 | // Copyright 2018 The Go Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE-Go file. 4 | 5 | package reality 6 | 7 | import ( 8 | "crypto/ecdh" 9 | "crypto/hmac" 10 | "crypto/mlkem" 11 | "errors" 12 | "hash" 13 | "io" 14 | 15 | "github.com/xtls/reality/tls13" 16 | ) 17 | 18 | // This file contains the functions necessary to compute the TLS 1.3 key 19 | // schedule. See RFC 8446, Section 7. 20 | 21 | // nextTrafficSecret generates the next traffic secret, given the current one, 22 | // according to RFC 8446, Section 7.2. 23 | func (c *cipherSuiteTLS13) nextTrafficSecret(trafficSecret []byte) []byte { 24 | return tls13.ExpandLabel(c.hash.New, trafficSecret, "traffic upd", nil, c.hash.Size()) 25 | } 26 | 27 | // trafficKey generates traffic keys according to RFC 8446, Section 7.3. 28 | func (c *cipherSuiteTLS13) trafficKey(trafficSecret []byte) (key, iv []byte) { 29 | key = tls13.ExpandLabel(c.hash.New, trafficSecret, "key", nil, c.keyLen) 30 | iv = tls13.ExpandLabel(c.hash.New, trafficSecret, "iv", nil, aeadNonceLength) 31 | return 32 | } 33 | 34 | // finishedHash generates the Finished verify_data or PskBinderEntry according 35 | // to RFC 8446, Section 4.4.4. See sections 4.4 and 4.2.11.2 for the baseKey 36 | // selection. 37 | func (c *cipherSuiteTLS13) finishedHash(baseKey []byte, transcript hash.Hash) []byte { 38 | finishedKey := tls13.ExpandLabel(c.hash.New, baseKey, "finished", nil, c.hash.Size()) 39 | verifyData := hmac.New(c.hash.New, finishedKey) 40 | verifyData.Write(transcript.Sum(nil)) 41 | return verifyData.Sum(nil) 42 | } 43 | 44 | // exportKeyingMaterial implements RFC5705 exporters for TLS 1.3 according to 45 | // RFC 8446, Section 7.5. 46 | func (c *cipherSuiteTLS13) exportKeyingMaterial(s *tls13.MasterSecret, transcript hash.Hash) func(string, []byte, int) ([]byte, error) { 47 | expMasterSecret := s.ExporterMasterSecret(transcript) 48 | return func(label string, context []byte, length int) ([]byte, error) { 49 | return expMasterSecret.Exporter(label, context, length), nil 50 | } 51 | } 52 | 53 | type keySharePrivateKeys struct { 54 | curveID CurveID 55 | ecdhe *ecdh.PrivateKey 56 | mlkem *mlkem.DecapsulationKey768 57 | } 58 | 59 | const x25519PublicKeySize = 32 60 | 61 | // generateECDHEKey returns a PrivateKey that implements Diffie-Hellman 62 | // according to RFC 8446, Section 4.2.8.2. 63 | func generateECDHEKey(rand io.Reader, curveID CurveID) (*ecdh.PrivateKey, error) { 64 | curve, ok := curveForCurveID(curveID) 65 | if !ok { 66 | return nil, errors.New("tls: internal error: unsupported curve") 67 | } 68 | 69 | return curve.GenerateKey(rand) 70 | } 71 | 72 | func curveForCurveID(id CurveID) (ecdh.Curve, bool) { 73 | switch id { 74 | case X25519: 75 | return ecdh.X25519(), true 76 | case CurveP256: 77 | return ecdh.P256(), true 78 | case CurveP384: 79 | return ecdh.P384(), true 80 | case CurveP521: 81 | return ecdh.P521(), true 82 | default: 83 | return nil, false 84 | } 85 | } -------------------------------------------------------------------------------- /prf.go: -------------------------------------------------------------------------------- 1 | // Copyright 2009 The Go Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE-Go file. 4 | 5 | package reality 6 | 7 | import ( 8 | "crypto" 9 | "crypto/hmac" 10 | "crypto/md5" 11 | "crypto/sha1" 12 | "crypto/sha256" 13 | "crypto/sha512" 14 | "errors" 15 | "fmt" 16 | "hash" 17 | 18 | "github.com/xtls/reality/tls12" 19 | ) 20 | 21 | type prfFunc func(secret []byte, label string, seed []byte, keyLen int) []byte 22 | 23 | // Split a premaster secret in two as specified in RFC 4346, Section 5. 24 | func splitPreMasterSecret(secret []byte) (s1, s2 []byte) { 25 | s1 = secret[0 : (len(secret)+1)/2] 26 | s2 = secret[len(secret)/2:] 27 | return 28 | } 29 | 30 | // pHash implements the P_hash function, as defined in RFC 4346, Section 5. 31 | func pHash(result, secret, seed []byte, hash func() hash.Hash) { 32 | h := hmac.New(hash, secret) 33 | h.Write(seed) 34 | a := h.Sum(nil) 35 | 36 | j := 0 37 | for j < len(result) { 38 | h.Reset() 39 | h.Write(a) 40 | h.Write(seed) 41 | b := h.Sum(nil) 42 | copy(result[j:], b) 43 | j += len(b) 44 | 45 | h.Reset() 46 | h.Write(a) 47 | a = h.Sum(nil) 48 | } 49 | } 50 | 51 | // prf10 implements the TLS 1.0 pseudo-random function, as defined in RFC 2246, Section 5. 52 | func prf10(secret []byte, label string, seed []byte, keyLen int) []byte { 53 | result := make([]byte, keyLen) 54 | hashSHA1 := sha1.New 55 | hashMD5 := md5.New 56 | 57 | labelAndSeed := make([]byte, len(label)+len(seed)) 58 | copy(labelAndSeed, label) 59 | copy(labelAndSeed[len(label):], seed) 60 | 61 | s1, s2 := splitPreMasterSecret(secret) 62 | pHash(result, s1, labelAndSeed, hashMD5) 63 | result2 := make([]byte, len(result)) 64 | pHash(result2, s2, labelAndSeed, hashSHA1) 65 | 66 | for i, b := range result2 { 67 | result[i] ^= b 68 | } 69 | 70 | return result 71 | } 72 | 73 | // prf12 implements the TLS 1.2 pseudo-random function, as defined in RFC 5246, Section 5. 74 | func prf12(hashFunc func() hash.Hash) prfFunc { 75 | return func(secret []byte, label string, seed []byte, keyLen int) []byte { 76 | return tls12.PRF(hashFunc, secret, label, seed, keyLen) 77 | } 78 | } 79 | 80 | const ( 81 | masterSecretLength = 48 // Length of a master secret in TLS 1.1. 82 | finishedVerifyLength = 12 // Length of verify_data in a Finished message. 83 | ) 84 | 85 | const masterSecretLabel = "master secret" 86 | const extendedMasterSecretLabel = "extended master secret" 87 | const keyExpansionLabel = "key expansion" 88 | const clientFinishedLabel = "client finished" 89 | const serverFinishedLabel = "server finished" 90 | 91 | func prfAndHashForVersion(version uint16, suite *cipherSuite) (prfFunc, crypto.Hash) { 92 | switch version { 93 | case VersionTLS10, VersionTLS11: 94 | return prf10, crypto.Hash(0) 95 | case VersionTLS12: 96 | if suite.flags&suiteSHA384 != 0 { 97 | return prf12(sha512.New384), crypto.SHA384 98 | } 99 | return prf12(sha256.New), crypto.SHA256 100 | default: 101 | panic("unknown version") 102 | } 103 | } 104 | 105 | func prfForVersion(version uint16, suite *cipherSuite) prfFunc { 106 | prf, _ := prfAndHashForVersion(version, suite) 107 | return prf 108 | } 109 | 110 | // masterFromPreMasterSecret generates the master secret from the pre-master 111 | // secret. See RFC 5246, Section 8.1. 112 | func masterFromPreMasterSecret(version uint16, suite *cipherSuite, preMasterSecret, clientRandom, serverRandom []byte) []byte { 113 | seed := make([]byte, 0, len(clientRandom)+len(serverRandom)) 114 | seed = append(seed, clientRandom...) 115 | seed = append(seed, serverRandom...) 116 | 117 | return prfForVersion(version, suite)(preMasterSecret, masterSecretLabel, seed, masterSecretLength) 118 | } 119 | 120 | // extMasterFromPreMasterSecret generates the extended master secret from the 121 | // pre-master secret. See RFC 7627. 122 | func extMasterFromPreMasterSecret(version uint16, suite *cipherSuite, preMasterSecret, transcript []byte) []byte { 123 | prf, hash := prfAndHashForVersion(version, suite) 124 | if version == VersionTLS12 { 125 | // Use the FIPS 140-3 module only for TLS 1.2 with EMS, which is the 126 | // only TLS 1.0-1.2 approved mode per IG D.Q. 127 | return tls12.MasterSecret(hash.New, preMasterSecret, transcript) 128 | } 129 | return prf(preMasterSecret, extendedMasterSecretLabel, transcript, masterSecretLength) 130 | } 131 | 132 | // keysFromMasterSecret generates the connection keys from the master 133 | // secret, given the lengths of the MAC key, cipher key and IV, as defined in 134 | // RFC 2246, Section 6.3. 135 | func keysFromMasterSecret(version uint16, suite *cipherSuite, masterSecret, clientRandom, serverRandom []byte, macLen, keyLen, ivLen int) (clientMAC, serverMAC, clientKey, serverKey, clientIV, serverIV []byte) { 136 | seed := make([]byte, 0, len(serverRandom)+len(clientRandom)) 137 | seed = append(seed, serverRandom...) 138 | seed = append(seed, clientRandom...) 139 | 140 | n := 2*macLen + 2*keyLen + 2*ivLen 141 | keyMaterial := prfForVersion(version, suite)(masterSecret, keyExpansionLabel, seed, n) 142 | clientMAC = keyMaterial[:macLen] 143 | keyMaterial = keyMaterial[macLen:] 144 | serverMAC = keyMaterial[:macLen] 145 | keyMaterial = keyMaterial[macLen:] 146 | clientKey = keyMaterial[:keyLen] 147 | keyMaterial = keyMaterial[keyLen:] 148 | serverKey = keyMaterial[:keyLen] 149 | keyMaterial = keyMaterial[keyLen:] 150 | clientIV = keyMaterial[:ivLen] 151 | keyMaterial = keyMaterial[ivLen:] 152 | serverIV = keyMaterial[:ivLen] 153 | return 154 | } 155 | 156 | func newFinishedHash(version uint16, cipherSuite *cipherSuite) finishedHash { 157 | var buffer []byte 158 | if version >= VersionTLS12 { 159 | buffer = []byte{} 160 | } 161 | 162 | prf, hash := prfAndHashForVersion(version, cipherSuite) 163 | if hash != 0 { 164 | return finishedHash{hash.New(), hash.New(), nil, nil, buffer, version, prf} 165 | } 166 | 167 | return finishedHash{sha1.New(), sha1.New(), md5.New(), md5.New(), buffer, version, prf} 168 | } 169 | 170 | // A finishedHash calculates the hash of a set of handshake messages suitable 171 | // for including in a Finished message. 172 | type finishedHash struct { 173 | client hash.Hash 174 | server hash.Hash 175 | 176 | // Prior to TLS 1.2, an additional MD5 hash is required. 177 | clientMD5 hash.Hash 178 | serverMD5 hash.Hash 179 | 180 | // In TLS 1.2, a full buffer is sadly required. 181 | buffer []byte 182 | 183 | version uint16 184 | prf prfFunc 185 | } 186 | 187 | func (h *finishedHash) Write(msg []byte) (n int, err error) { 188 | h.client.Write(msg) 189 | h.server.Write(msg) 190 | 191 | if h.version < VersionTLS12 { 192 | h.clientMD5.Write(msg) 193 | h.serverMD5.Write(msg) 194 | } 195 | 196 | if h.buffer != nil { 197 | h.buffer = append(h.buffer, msg...) 198 | } 199 | 200 | return len(msg), nil 201 | } 202 | 203 | func (h finishedHash) Sum() []byte { 204 | if h.version >= VersionTLS12 { 205 | return h.client.Sum(nil) 206 | } 207 | 208 | out := make([]byte, 0, md5.Size+sha1.Size) 209 | out = h.clientMD5.Sum(out) 210 | return h.client.Sum(out) 211 | } 212 | 213 | // clientSum returns the contents of the verify_data member of a client's 214 | // Finished message. 215 | func (h finishedHash) clientSum(masterSecret []byte) []byte { 216 | return h.prf(masterSecret, clientFinishedLabel, h.Sum(), finishedVerifyLength) 217 | } 218 | 219 | // serverSum returns the contents of the verify_data member of a server's 220 | // Finished message. 221 | func (h finishedHash) serverSum(masterSecret []byte) []byte { 222 | return h.prf(masterSecret, serverFinishedLabel, h.Sum(), finishedVerifyLength) 223 | } 224 | 225 | // hashForClientCertificate returns the handshake messages so far, pre-hashed if 226 | // necessary, suitable for signing by a TLS client certificate. 227 | func (h finishedHash) hashForClientCertificate(sigType uint8, hashAlg crypto.Hash) []byte { 228 | if (h.version >= VersionTLS12 || sigType == signatureEd25519) && h.buffer == nil { 229 | panic("tls: handshake hash for a client certificate requested after discarding the handshake buffer") 230 | } 231 | 232 | if sigType == signatureEd25519 { 233 | return h.buffer 234 | } 235 | 236 | if h.version >= VersionTLS12 { 237 | hash := hashAlg.New() 238 | hash.Write(h.buffer) 239 | return hash.Sum(nil) 240 | } 241 | 242 | if sigType == signatureECDSA { 243 | return h.server.Sum(nil) 244 | } 245 | 246 | return h.Sum() 247 | } 248 | 249 | // discardHandshakeBuffer is called when there is no more need to 250 | // buffer the entirety of the handshake messages. 251 | func (h *finishedHash) discardHandshakeBuffer() { 252 | h.buffer = nil 253 | } 254 | 255 | // noEKMBecauseRenegotiation is used as a value of 256 | // ConnectionState.ekm when renegotiation is enabled and thus 257 | // we wish to fail all key-material export requests. 258 | func noEKMBecauseRenegotiation(label string, context []byte, length int) ([]byte, error) { 259 | return nil, errors.New("crypto/tls: ExportKeyingMaterial is unavailable when renegotiation is enabled") 260 | } 261 | 262 | // noEKMBecauseNoEMS is used as a value of ConnectionState.ekm when Extended 263 | // Master Secret is not negotiated and thus we wish to fail all key-material 264 | // export requests. 265 | func noEKMBecauseNoEMS(label string, context []byte, length int) ([]byte, error) { 266 | return nil, errors.New("crypto/tls: ExportKeyingMaterial is unavailable when neither TLS 1.3 nor Extended Master Secret are negotiated; override with GODEBUG=tlsunsafeekm=1") 267 | } 268 | 269 | // ekmFromMasterSecret generates exported keying material as defined in RFC 5705. 270 | func ekmFromMasterSecret(version uint16, suite *cipherSuite, masterSecret, clientRandom, serverRandom []byte) func(string, []byte, int) ([]byte, error) { 271 | return func(label string, context []byte, length int) ([]byte, error) { 272 | switch label { 273 | case "client finished", "server finished", "master secret", "key expansion": 274 | // These values are reserved and may not be used. 275 | return nil, fmt.Errorf("crypto/tls: reserved ExportKeyingMaterial label: %s", label) 276 | } 277 | 278 | seedLen := len(serverRandom) + len(clientRandom) 279 | if context != nil { 280 | seedLen += 2 + len(context) 281 | } 282 | seed := make([]byte, 0, seedLen) 283 | 284 | seed = append(seed, clientRandom...) 285 | seed = append(seed, serverRandom...) 286 | 287 | if context != nil { 288 | if len(context) >= 1<<16 { 289 | return nil, fmt.Errorf("crypto/tls: ExportKeyingMaterial context too long") 290 | } 291 | seed = append(seed, byte(len(context)>>8), byte(len(context))) 292 | seed = append(seed, context...) 293 | } 294 | 295 | return prfForVersion(version, suite)(masterSecret, label, seed, length), nil 296 | } 297 | } 298 | -------------------------------------------------------------------------------- /quic.go: -------------------------------------------------------------------------------- 1 | // Copyright 2023 The Go Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package reality 6 | 7 | import ( 8 | "context" 9 | "errors" 10 | "fmt" 11 | ) 12 | 13 | // QUICEncryptionLevel represents a QUIC encryption level used to transmit 14 | // handshake messages. 15 | type QUICEncryptionLevel int 16 | 17 | const ( 18 | QUICEncryptionLevelInitial = QUICEncryptionLevel(iota) 19 | QUICEncryptionLevelEarly 20 | QUICEncryptionLevelHandshake 21 | QUICEncryptionLevelApplication 22 | ) 23 | 24 | func (l QUICEncryptionLevel) String() string { 25 | switch l { 26 | case QUICEncryptionLevelInitial: 27 | return "Initial" 28 | case QUICEncryptionLevelEarly: 29 | return "Early" 30 | case QUICEncryptionLevelHandshake: 31 | return "Handshake" 32 | case QUICEncryptionLevelApplication: 33 | return "Application" 34 | default: 35 | return fmt.Sprintf("QUICEncryptionLevel(%v)", int(l)) 36 | } 37 | } 38 | 39 | // A QUICConn represents a connection which uses a QUIC implementation as the underlying 40 | // transport as described in RFC 9001. 41 | // 42 | // Methods of QUICConn are not safe for concurrent use. 43 | type QUICConn struct { 44 | conn *Conn 45 | 46 | sessionTicketSent bool 47 | } 48 | 49 | // A QUICConfig configures a [QUICConn]. 50 | type QUICConfig struct { 51 | TLSConfig *Config 52 | 53 | // EnableSessionEvents may be set to true to enable the 54 | // [QUICStoreSession] and [QUICResumeSession] events for client connections. 55 | // When this event is enabled, sessions are not automatically 56 | // stored in the client session cache. 57 | // The application should use [QUICConn.StoreSession] to store sessions. 58 | EnableSessionEvents bool 59 | } 60 | 61 | // A QUICEventKind is a type of operation on a QUIC connection. 62 | type QUICEventKind int 63 | 64 | const ( 65 | // QUICNoEvent indicates that there are no events available. 66 | QUICNoEvent QUICEventKind = iota 67 | 68 | // QUICSetReadSecret and QUICSetWriteSecret provide the read and write 69 | // secrets for a given encryption level. 70 | // QUICEvent.Level, QUICEvent.Data, and QUICEvent.Suite are set. 71 | // 72 | // Secrets for the Initial encryption level are derived from the initial 73 | // destination connection ID, and are not provided by the QUICConn. 74 | QUICSetReadSecret 75 | QUICSetWriteSecret 76 | 77 | // QUICWriteData provides data to send to the peer in CRYPTO frames. 78 | // QUICEvent.Data is set. 79 | QUICWriteData 80 | 81 | // QUICTransportParameters provides the peer's QUIC transport parameters. 82 | // QUICEvent.Data is set. 83 | QUICTransportParameters 84 | 85 | // QUICTransportParametersRequired indicates that the caller must provide 86 | // QUIC transport parameters to send to the peer. The caller should set 87 | // the transport parameters with QUICConn.SetTransportParameters and call 88 | // QUICConn.NextEvent again. 89 | // 90 | // If transport parameters are set before calling QUICConn.Start, the 91 | // connection will never generate a QUICTransportParametersRequired event. 92 | QUICTransportParametersRequired 93 | 94 | // QUICRejectedEarlyData indicates that the server rejected 0-RTT data even 95 | // if we offered it. It's returned before QUICEncryptionLevelApplication 96 | // keys are returned. 97 | // This event only occurs on client connections. 98 | QUICRejectedEarlyData 99 | 100 | // QUICHandshakeDone indicates that the TLS handshake has completed. 101 | QUICHandshakeDone 102 | 103 | // QUICResumeSession indicates that a client is attempting to resume a previous session. 104 | // [QUICEvent.SessionState] is set. 105 | // 106 | // For client connections, this event occurs when the session ticket is selected. 107 | // For server connections, this event occurs when receiving the client's session ticket. 108 | // 109 | // The application may set [QUICEvent.SessionState.EarlyData] to false before the 110 | // next call to [QUICConn.NextEvent] to decline 0-RTT even if the session supports it. 111 | QUICResumeSession 112 | 113 | // QUICStoreSession indicates that the server has provided state permitting 114 | // the client to resume the session. 115 | // [QUICEvent.SessionState] is set. 116 | // The application should use [QUICConn.StoreSession] session to store the [SessionState]. 117 | // The application may modify the [SessionState] before storing it. 118 | // This event only occurs on client connections. 119 | QUICStoreSession 120 | ) 121 | 122 | // A QUICEvent is an event occurring on a QUIC connection. 123 | // 124 | // The type of event is specified by the Kind field. 125 | // The contents of the other fields are kind-specific. 126 | type QUICEvent struct { 127 | Kind QUICEventKind 128 | 129 | // Set for QUICSetReadSecret, QUICSetWriteSecret, and QUICWriteData. 130 | Level QUICEncryptionLevel 131 | 132 | // Set for QUICTransportParameters, QUICSetReadSecret, QUICSetWriteSecret, and QUICWriteData. 133 | // The contents are owned by crypto/tls, and are valid until the next NextEvent call. 134 | Data []byte 135 | 136 | // Set for QUICSetReadSecret and QUICSetWriteSecret. 137 | Suite uint16 138 | 139 | // Set for QUICResumeSession and QUICStoreSession. 140 | SessionState *SessionState 141 | } 142 | 143 | type quicState struct { 144 | events []QUICEvent 145 | nextEvent int 146 | 147 | // eventArr is a statically allocated event array, large enough to handle 148 | // the usual maximum number of events resulting from a single call: transport 149 | // parameters, Initial data, Early read secret, Handshake write and read 150 | // secrets, Handshake data, Application write secret, Application data. 151 | eventArr [8]QUICEvent 152 | 153 | started bool 154 | signalc chan struct{} // handshake data is available to be read 155 | blockedc chan struct{} // handshake is waiting for data, closed when done 156 | cancelc <-chan struct{} // handshake has been canceled 157 | cancel context.CancelFunc 158 | 159 | waitingForDrain bool 160 | 161 | // readbuf is shared between HandleData and the handshake goroutine. 162 | // HandshakeCryptoData passes ownership to the handshake goroutine by 163 | // reading from signalc, and reclaims ownership by reading from blockedc. 164 | readbuf []byte 165 | 166 | transportParams []byte // to send to the peer 167 | 168 | enableSessionEvents bool 169 | } 170 | 171 | // QUICClient returns a new TLS client side connection using QUICTransport as the 172 | // underlying transport. The config cannot be nil. 173 | // 174 | // The config's MinVersion must be at least TLS 1.3. 175 | func QUICClient(config *QUICConfig) *QUICConn { 176 | return newQUICConn(Client(nil, config.TLSConfig), config) 177 | } 178 | 179 | // QUICServer returns a new TLS server side connection using QUICTransport as the 180 | // underlying transport. The config cannot be nil. 181 | // 182 | // The config's MinVersion must be at least TLS 1.3. 183 | func QUICServer(config *QUICConfig) *QUICConn { 184 | c, _ := Server(context.Background(), nil, config.TLSConfig) 185 | return newQUICConn(c, config) 186 | } 187 | 188 | func newQUICConn(conn *Conn, config *QUICConfig) *QUICConn { 189 | conn.quic = &quicState{ 190 | signalc: make(chan struct{}), 191 | blockedc: make(chan struct{}), 192 | enableSessionEvents: config.EnableSessionEvents, 193 | } 194 | conn.quic.events = conn.quic.eventArr[:0] 195 | return &QUICConn{ 196 | conn: conn, 197 | } 198 | } 199 | 200 | // Start starts the client or server handshake protocol. 201 | // It may produce connection events, which may be read with [QUICConn.NextEvent]. 202 | // 203 | // Start must be called at most once. 204 | func (q *QUICConn) Start(ctx context.Context) error { 205 | if q.conn.quic.started { 206 | return quicError(errors.New("tls: Start called more than once")) 207 | } 208 | q.conn.quic.started = true 209 | if q.conn.config.MinVersion < VersionTLS13 { 210 | return quicError(errors.New("tls: Config MinVersion must be at least TLS 1.3")) 211 | } 212 | go q.conn.HandshakeContext(ctx) 213 | if _, ok := <-q.conn.quic.blockedc; !ok { 214 | return q.conn.handshakeErr 215 | } 216 | return nil 217 | } 218 | 219 | // NextEvent returns the next event occurring on the connection. 220 | // It returns an event with a Kind of [QUICNoEvent] when no events are available. 221 | func (q *QUICConn) NextEvent() QUICEvent { 222 | qs := q.conn.quic 223 | if last := qs.nextEvent - 1; last >= 0 && len(qs.events[last].Data) > 0 { 224 | // Write over some of the previous event's data, 225 | // to catch callers erroniously retaining it. 226 | qs.events[last].Data[0] = 0 227 | } 228 | if qs.nextEvent >= len(qs.events) && qs.waitingForDrain { 229 | qs.waitingForDrain = false 230 | <-qs.signalc 231 | <-qs.blockedc 232 | } 233 | if qs.nextEvent >= len(qs.events) { 234 | qs.events = qs.events[:0] 235 | qs.nextEvent = 0 236 | return QUICEvent{Kind: QUICNoEvent} 237 | } 238 | e := qs.events[qs.nextEvent] 239 | qs.events[qs.nextEvent] = QUICEvent{} // zero out references to data 240 | qs.nextEvent++ 241 | return e 242 | } 243 | 244 | // Close closes the connection and stops any in-progress handshake. 245 | func (q *QUICConn) Close() error { 246 | if q.conn.quic.cancel == nil { 247 | return nil // never started 248 | } 249 | q.conn.quic.cancel() 250 | for range q.conn.quic.blockedc { 251 | // Wait for the handshake goroutine to return. 252 | } 253 | return q.conn.handshakeErr 254 | } 255 | 256 | // HandleData handles handshake bytes received from the peer. 257 | // It may produce connection events, which may be read with [QUICConn.NextEvent]. 258 | func (q *QUICConn) HandleData(level QUICEncryptionLevel, data []byte) error { 259 | c := q.conn 260 | if c.in.level != level { 261 | return quicError(c.in.setErrorLocked(errors.New("tls: handshake data received at wrong level"))) 262 | } 263 | c.quic.readbuf = data 264 | <-c.quic.signalc 265 | _, ok := <-c.quic.blockedc 266 | if ok { 267 | // The handshake goroutine is waiting for more data. 268 | return nil 269 | } 270 | // The handshake goroutine has exited. 271 | c.handshakeMutex.Lock() 272 | defer c.handshakeMutex.Unlock() 273 | c.hand.Write(c.quic.readbuf) 274 | c.quic.readbuf = nil 275 | for q.conn.hand.Len() >= 4 && q.conn.handshakeErr == nil { 276 | b := q.conn.hand.Bytes() 277 | n := int(b[1])<<16 | int(b[2])<<8 | int(b[3]) 278 | if n > maxHandshake { 279 | q.conn.handshakeErr = fmt.Errorf("tls: handshake message of length %d bytes exceeds maximum of %d bytes", n, maxHandshake) 280 | break 281 | } 282 | if len(b) < 4+n { 283 | return nil 284 | } 285 | if err := q.conn.handlePostHandshakeMessage(); err != nil { 286 | q.conn.handshakeErr = err 287 | } 288 | } 289 | if q.conn.handshakeErr != nil { 290 | return quicError(q.conn.handshakeErr) 291 | } 292 | return nil 293 | } 294 | 295 | type QUICSessionTicketOptions struct { 296 | // EarlyData specifies whether the ticket may be used for 0-RTT. 297 | EarlyData bool 298 | Extra [][]byte 299 | } 300 | 301 | // SendSessionTicket sends a session ticket to the client. 302 | // It produces connection events, which may be read with [QUICConn.NextEvent]. 303 | // Currently, it can only be called once. 304 | func (q *QUICConn) SendSessionTicket(opts QUICSessionTicketOptions) error { 305 | c := q.conn 306 | if !c.isHandshakeComplete.Load() { 307 | return quicError(errors.New("tls: SendSessionTicket called before handshake completed")) 308 | } 309 | if c.isClient { 310 | return quicError(errors.New("tls: SendSessionTicket called on the client")) 311 | } 312 | if q.sessionTicketSent { 313 | return quicError(errors.New("tls: SendSessionTicket called multiple times")) 314 | } 315 | q.sessionTicketSent = true 316 | return quicError(c.sendSessionTicket(opts.EarlyData, opts.Extra)) 317 | } 318 | 319 | // StoreSession stores a session previously received in a QUICStoreSession event 320 | // in the ClientSessionCache. 321 | // The application may process additional events or modify the SessionState 322 | // before storing the session. 323 | func (q *QUICConn) StoreSession(session *SessionState) error { 324 | c := q.conn 325 | if !c.isClient { 326 | return quicError(errors.New("tls: StoreSessionTicket called on the server")) 327 | } 328 | cacheKey := c.clientSessionCacheKey() 329 | if cacheKey == "" { 330 | return nil 331 | } 332 | cs := &ClientSessionState{session: session} 333 | c.config.ClientSessionCache.Put(cacheKey, cs) 334 | return nil 335 | } 336 | 337 | // ConnectionState returns basic TLS details about the connection. 338 | func (q *QUICConn) ConnectionState() ConnectionState { 339 | return q.conn.ConnectionState() 340 | } 341 | 342 | // SetTransportParameters sets the transport parameters to send to the peer. 343 | // 344 | // Server connections may delay setting the transport parameters until after 345 | // receiving the client's transport parameters. See [QUICTransportParametersRequired]. 346 | func (q *QUICConn) SetTransportParameters(params []byte) { 347 | if params == nil { 348 | params = []byte{} 349 | } 350 | q.conn.quic.transportParams = params 351 | if q.conn.quic.started { 352 | <-q.conn.quic.signalc 353 | <-q.conn.quic.blockedc 354 | } 355 | } 356 | 357 | // quicError ensures err is an AlertError. 358 | // If err is not already, quicError wraps it with alertInternalError. 359 | func quicError(err error) error { 360 | if err == nil { 361 | return nil 362 | } 363 | var ae AlertError 364 | if errors.As(err, &ae) { 365 | return err 366 | } 367 | var a alert 368 | if !errors.As(err, &a) { 369 | a = alertInternalError 370 | } 371 | // Return an error wrapping the original error and an AlertError. 372 | // Truncate the text of the alert to 0 characters. 373 | return fmt.Errorf("%w%.0w", err, AlertError(a)) 374 | } 375 | 376 | func (c *Conn) quicReadHandshakeBytes(n int) error { 377 | for c.hand.Len() < n { 378 | if err := c.quicWaitForSignal(); err != nil { 379 | return err 380 | } 381 | } 382 | return nil 383 | } 384 | 385 | func (c *Conn) quicSetReadSecret(level QUICEncryptionLevel, suite uint16, secret []byte) { 386 | c.quic.events = append(c.quic.events, QUICEvent{ 387 | Kind: QUICSetReadSecret, 388 | Level: level, 389 | Suite: suite, 390 | Data: secret, 391 | }) 392 | } 393 | 394 | func (c *Conn) quicSetWriteSecret(level QUICEncryptionLevel, suite uint16, secret []byte) { 395 | c.quic.events = append(c.quic.events, QUICEvent{ 396 | Kind: QUICSetWriteSecret, 397 | Level: level, 398 | Suite: suite, 399 | Data: secret, 400 | }) 401 | } 402 | 403 | func (c *Conn) quicWriteCryptoData(level QUICEncryptionLevel, data []byte) { 404 | var last *QUICEvent 405 | if len(c.quic.events) > 0 { 406 | last = &c.quic.events[len(c.quic.events)-1] 407 | } 408 | if last == nil || last.Kind != QUICWriteData || last.Level != level { 409 | c.quic.events = append(c.quic.events, QUICEvent{ 410 | Kind: QUICWriteData, 411 | Level: level, 412 | }) 413 | last = &c.quic.events[len(c.quic.events)-1] 414 | } 415 | last.Data = append(last.Data, data...) 416 | } 417 | 418 | func (c *Conn) quicResumeSession(session *SessionState) error { 419 | c.quic.events = append(c.quic.events, QUICEvent{ 420 | Kind: QUICResumeSession, 421 | SessionState: session, 422 | }) 423 | c.quic.waitingForDrain = true 424 | for c.quic.waitingForDrain { 425 | if err := c.quicWaitForSignal(); err != nil { 426 | return err 427 | } 428 | } 429 | return nil 430 | } 431 | 432 | func (c *Conn) quicStoreSession(session *SessionState) { 433 | c.quic.events = append(c.quic.events, QUICEvent{ 434 | Kind: QUICStoreSession, 435 | SessionState: session, 436 | }) 437 | } 438 | 439 | func (c *Conn) quicSetTransportParameters(params []byte) { 440 | c.quic.events = append(c.quic.events, QUICEvent{ 441 | Kind: QUICTransportParameters, 442 | Data: params, 443 | }) 444 | } 445 | 446 | func (c *Conn) quicGetTransportParameters() ([]byte, error) { 447 | if c.quic.transportParams == nil { 448 | c.quic.events = append(c.quic.events, QUICEvent{ 449 | Kind: QUICTransportParametersRequired, 450 | }) 451 | } 452 | for c.quic.transportParams == nil { 453 | if err := c.quicWaitForSignal(); err != nil { 454 | return nil, err 455 | } 456 | } 457 | return c.quic.transportParams, nil 458 | } 459 | 460 | func (c *Conn) quicHandshakeComplete() { 461 | c.quic.events = append(c.quic.events, QUICEvent{ 462 | Kind: QUICHandshakeDone, 463 | }) 464 | } 465 | 466 | func (c *Conn) quicRejectedEarlyData() { 467 | c.quic.events = append(c.quic.events, QUICEvent{ 468 | Kind: QUICRejectedEarlyData, 469 | }) 470 | } 471 | 472 | // quicWaitForSignal notifies the QUICConn that handshake progress is blocked, 473 | // and waits for a signal that the handshake should proceed. 474 | // 475 | // The handshake may become blocked waiting for handshake bytes 476 | // or for the user to provide transport parameters. 477 | func (c *Conn) quicWaitForSignal() error { 478 | // Drop the handshake mutex while blocked to allow the user 479 | // to call ConnectionState before the handshake completes. 480 | c.handshakeMutex.Unlock() 481 | defer c.handshakeMutex.Lock() 482 | // Send on blockedc to notify the QUICConn that the handshake is blocked. 483 | // Exported methods of QUICConn wait for the handshake to become blocked 484 | // before returning to the user. 485 | select { 486 | case c.quic.blockedc <- struct{}{}: 487 | case <-c.quic.cancelc: 488 | return c.sendAlertLocked(alertCloseNotify) 489 | } 490 | // The QUICConn reads from signalc to notify us that the handshake may 491 | // be able to proceed. (The QUICConn reads, because we close signalc to 492 | // indicate that the handshake has completed.) 493 | select { 494 | case c.quic.signalc <- struct{}{}: 495 | c.hand.Write(c.quic.readbuf) 496 | c.quic.readbuf = nil 497 | case <-c.quic.cancelc: 498 | return c.sendAlertLocked(alertCloseNotify) 499 | } 500 | return nil 501 | } -------------------------------------------------------------------------------- /ticket.go: -------------------------------------------------------------------------------- 1 | // Copyright 2012 The Go Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE-Go file. 4 | 5 | package reality 6 | 7 | import ( 8 | "crypto/aes" 9 | "crypto/cipher" 10 | "crypto/hmac" 11 | "crypto/sha256" 12 | "crypto/subtle" 13 | "crypto/x509" 14 | "errors" 15 | "io" 16 | 17 | "golang.org/x/crypto/cryptobyte" 18 | ) 19 | 20 | // A SessionState is a resumable session. 21 | type SessionState struct { 22 | // Encoded as a SessionState (in the language of RFC 8446, Section 3). 23 | // 24 | // enum { server(1), client(2) } SessionStateType; 25 | // 26 | // opaque Certificate<1..2^24-1>; 27 | // 28 | // Certificate CertificateChain<0..2^24-1>; 29 | // 30 | // opaque Extra<0..2^24-1>; 31 | // 32 | // struct { 33 | // uint16 version; 34 | // SessionStateType type; 35 | // uint16 cipher_suite; 36 | // uint64 created_at; 37 | // opaque secret<1..2^8-1>; 38 | // Extra extra<0..2^24-1>; 39 | // uint8 ext_master_secret = { 0, 1 }; 40 | // uint8 early_data = { 0, 1 }; 41 | // CertificateEntry certificate_list<0..2^24-1>; 42 | // CertificateChain verified_chains<0..2^24-1>; /* excluding leaf */ 43 | // select (SessionState.early_data) { 44 | // case 0: Empty; 45 | // case 1: opaque alpn<1..2^8-1>; 46 | // }; 47 | // select (SessionState.version) { 48 | // case VersionTLS10..VersionTLS12: uint16 curve_id; 49 | // case VersionTLS13: select (SessionState.type) { 50 | // case server: Empty; 51 | // case client: struct { 52 | // uint64 use_by; 53 | // uint32 age_add; 54 | // }; 55 | // }; 56 | // }; 57 | // } SessionState; 58 | // 59 | // The format can be extended backwards-compatibly by adding new fields at 60 | // the end. Otherwise, a new SessionStateType must be used, as different Go 61 | // versions may share the same session ticket encryption key. 62 | 63 | // Extra is ignored by crypto/tls, but is encoded by [SessionState.Bytes] 64 | // and parsed by [ParseSessionState]. 65 | // 66 | // This allows [Config.UnwrapSession]/[Config.WrapSession] and 67 | // [ClientSessionCache] implementations to store and retrieve additional 68 | // data alongside this session. 69 | // 70 | // To allow different layers in a protocol stack to share this field, 71 | // applications must only append to it, not replace it, and must use entries 72 | // that can be recognized even if out of order (for example, by starting 73 | // with an id and version prefix). 74 | Extra [][]byte 75 | 76 | // EarlyData indicates whether the ticket can be used for 0-RTT in a QUIC 77 | // connection. The application may set this to false if it is true to 78 | // decline to offer 0-RTT even if supported. 79 | EarlyData bool 80 | 81 | version uint16 82 | isClient bool 83 | cipherSuite uint16 84 | // createdAt is the generation time of the secret on the sever (which for 85 | // TLS 1.0–1.2 might be earlier than the current session) and the time at 86 | // which the ticket was received on the client. 87 | createdAt uint64 // seconds since UNIX epoch 88 | secret []byte // master secret for TLS 1.2, or the PSK for TLS 1.3 89 | extMasterSecret bool 90 | peerCertificates []*x509.Certificate 91 | ocspResponse []byte 92 | scts [][]byte 93 | verifiedChains [][]*x509.Certificate 94 | alpnProtocol string // only set if EarlyData is true 95 | 96 | // Client-side TLS 1.3-only fields. 97 | useBy uint64 // seconds since UNIX epoch 98 | ageAdd uint32 99 | ticket []byte 100 | 101 | // TLS 1.0–1.2 only fields. 102 | curveID CurveID 103 | } 104 | 105 | // Bytes encodes the session, including any private fields, so that it can be 106 | // parsed by [ParseSessionState]. The encoding contains secret values critical 107 | // to the security of future and possibly past sessions. 108 | // 109 | // The specific encoding should be considered opaque and may change incompatibly 110 | // between Go versions. 111 | func (s *SessionState) Bytes() ([]byte, error) { 112 | var b cryptobyte.Builder 113 | b.AddUint16(s.version) 114 | if s.isClient { 115 | b.AddUint8(2) // client 116 | } else { 117 | b.AddUint8(1) // server 118 | } 119 | b.AddUint16(s.cipherSuite) 120 | addUint64(&b, s.createdAt) 121 | b.AddUint8LengthPrefixed(func(b *cryptobyte.Builder) { 122 | b.AddBytes(s.secret) 123 | }) 124 | b.AddUint24LengthPrefixed(func(b *cryptobyte.Builder) { 125 | for _, extra := range s.Extra { 126 | b.AddUint24LengthPrefixed(func(b *cryptobyte.Builder) { 127 | b.AddBytes(extra) 128 | }) 129 | } 130 | }) 131 | if s.extMasterSecret { 132 | b.AddUint8(1) 133 | } else { 134 | b.AddUint8(0) 135 | } 136 | if s.EarlyData { 137 | b.AddUint8(1) 138 | } else { 139 | b.AddUint8(0) 140 | } 141 | marshalCertificate(&b, Certificate{ 142 | Certificate: certificatesToBytesSlice(s.peerCertificates), 143 | OCSPStaple: s.ocspResponse, 144 | SignedCertificateTimestamps: s.scts, 145 | }) 146 | b.AddUint24LengthPrefixed(func(b *cryptobyte.Builder) { 147 | for _, chain := range s.verifiedChains { 148 | b.AddUint24LengthPrefixed(func(b *cryptobyte.Builder) { 149 | // We elide the first certificate because it's always the leaf. 150 | if len(chain) == 0 { 151 | b.SetError(errors.New("tls: internal error: empty verified chain")) 152 | return 153 | } 154 | for _, cert := range chain[1:] { 155 | b.AddUint24LengthPrefixed(func(b *cryptobyte.Builder) { 156 | b.AddBytes(cert.Raw) 157 | }) 158 | } 159 | }) 160 | } 161 | }) 162 | if s.EarlyData { 163 | b.AddUint8LengthPrefixed(func(b *cryptobyte.Builder) { 164 | b.AddBytes([]byte(s.alpnProtocol)) 165 | }) 166 | } 167 | if s.version >= VersionTLS13 { 168 | if s.isClient { 169 | addUint64(&b, s.useBy) 170 | b.AddUint32(s.ageAdd) 171 | } 172 | } else { 173 | b.AddUint16(uint16(s.curveID)) 174 | } 175 | return b.Bytes() 176 | } 177 | 178 | func certificatesToBytesSlice(certs []*x509.Certificate) [][]byte { 179 | s := make([][]byte, 0, len(certs)) 180 | for _, c := range certs { 181 | s = append(s, c.Raw) 182 | } 183 | return s 184 | } 185 | 186 | // ParseSessionState parses a [SessionState] encoded by [SessionState.Bytes]. 187 | func ParseSessionState(data []byte) (*SessionState, error) { 188 | ss := &SessionState{} 189 | s := cryptobyte.String(data) 190 | var typ, extMasterSecret, earlyData uint8 191 | var cert Certificate 192 | var extra cryptobyte.String 193 | if !s.ReadUint16(&ss.version) || 194 | !s.ReadUint8(&typ) || 195 | !s.ReadUint16(&ss.cipherSuite) || 196 | !readUint64(&s, &ss.createdAt) || 197 | !readUint8LengthPrefixed(&s, &ss.secret) || 198 | !s.ReadUint24LengthPrefixed(&extra) || 199 | !s.ReadUint8(&extMasterSecret) || 200 | !s.ReadUint8(&earlyData) || 201 | len(ss.secret) == 0 || 202 | !unmarshalCertificate(&s, &cert) { 203 | return nil, errors.New("tls: invalid session encoding") 204 | } 205 | for !extra.Empty() { 206 | var e []byte 207 | if !readUint24LengthPrefixed(&extra, &e) { 208 | return nil, errors.New("tls: invalid session encoding") 209 | } 210 | ss.Extra = append(ss.Extra, e) 211 | } 212 | switch typ { 213 | case 1: 214 | ss.isClient = false 215 | case 2: 216 | ss.isClient = true 217 | default: 218 | return nil, errors.New("tls: unknown session encoding") 219 | } 220 | switch extMasterSecret { 221 | case 0: 222 | ss.extMasterSecret = false 223 | case 1: 224 | ss.extMasterSecret = true 225 | default: 226 | return nil, errors.New("tls: invalid session encoding") 227 | } 228 | switch earlyData { 229 | case 0: 230 | ss.EarlyData = false 231 | case 1: 232 | ss.EarlyData = true 233 | default: 234 | return nil, errors.New("tls: invalid session encoding") 235 | } 236 | for _, cert := range cert.Certificate { 237 | c, err := globalCertCache.newCert(cert) 238 | if err != nil { 239 | return nil, err 240 | } 241 | ss.peerCertificates = append(ss.peerCertificates, c) 242 | } 243 | if ss.isClient && len(ss.peerCertificates) == 0 { 244 | return nil, errors.New("tls: no server certificates in client session") 245 | } 246 | ss.ocspResponse = cert.OCSPStaple 247 | ss.scts = cert.SignedCertificateTimestamps 248 | var chainList cryptobyte.String 249 | if !s.ReadUint24LengthPrefixed(&chainList) { 250 | return nil, errors.New("tls: invalid session encoding") 251 | } 252 | for !chainList.Empty() { 253 | var certList cryptobyte.String 254 | if !chainList.ReadUint24LengthPrefixed(&certList) { 255 | return nil, errors.New("tls: invalid session encoding") 256 | } 257 | var chain []*x509.Certificate 258 | if len(ss.peerCertificates) == 0 { 259 | return nil, errors.New("tls: invalid session encoding") 260 | } 261 | chain = append(chain, ss.peerCertificates[0]) 262 | for !certList.Empty() { 263 | var cert []byte 264 | if !readUint24LengthPrefixed(&certList, &cert) { 265 | return nil, errors.New("tls: invalid session encoding") 266 | } 267 | c, err := globalCertCache.newCert(cert) 268 | if err != nil { 269 | return nil, err 270 | } 271 | chain = append(chain, c) 272 | } 273 | ss.verifiedChains = append(ss.verifiedChains, chain) 274 | } 275 | if ss.EarlyData { 276 | var alpn []byte 277 | if !readUint8LengthPrefixed(&s, &alpn) { 278 | return nil, errors.New("tls: invalid session encoding") 279 | } 280 | ss.alpnProtocol = string(alpn) 281 | } 282 | if ss.version >= VersionTLS13 { 283 | if ss.isClient { 284 | if !s.ReadUint64(&ss.useBy) || !s.ReadUint32(&ss.ageAdd) { 285 | return nil, errors.New("tls: invalid session encoding") 286 | } 287 | } 288 | } else { 289 | if !s.ReadUint16((*uint16)(&ss.curveID)) { 290 | return nil, errors.New("tls: invalid session encoding") 291 | } 292 | } 293 | return ss, nil 294 | } 295 | 296 | // sessionState returns a partially filled-out [SessionState] with information 297 | // from the current connection. 298 | func (c *Conn) sessionState() *SessionState { 299 | return &SessionState{ 300 | version: c.vers, 301 | cipherSuite: c.cipherSuite, 302 | createdAt: uint64(c.config.time().Unix()), 303 | alpnProtocol: c.clientProtocol, 304 | peerCertificates: c.peerCertificates, 305 | ocspResponse: c.ocspResponse, 306 | scts: c.scts, 307 | isClient: c.isClient, 308 | extMasterSecret: c.extMasterSecret, 309 | verifiedChains: c.verifiedChains, 310 | curveID: c.curveID, 311 | } 312 | } 313 | 314 | // EncryptTicket encrypts a ticket with the [Config]'s configured (or default) 315 | // session ticket keys. It can be used as a [Config.WrapSession] implementation. 316 | func (c *Config) EncryptTicket(cs ConnectionState, ss *SessionState) ([]byte, error) { 317 | ticketKeys := c.ticketKeys(nil) 318 | stateBytes, err := ss.Bytes() 319 | if err != nil { 320 | return nil, err 321 | } 322 | return c.encryptTicket(stateBytes, ticketKeys) 323 | } 324 | 325 | func (c *Config) encryptTicket(state []byte, ticketKeys []ticketKey) ([]byte, error) { 326 | if len(ticketKeys) == 0 { 327 | return nil, errors.New("tls: internal error: session ticket keys unavailable") 328 | } 329 | 330 | encrypted := make([]byte, aes.BlockSize+len(state)+sha256.Size) 331 | iv := encrypted[:aes.BlockSize] 332 | ciphertext := encrypted[aes.BlockSize : len(encrypted)-sha256.Size] 333 | authenticated := encrypted[:len(encrypted)-sha256.Size] 334 | macBytes := encrypted[len(encrypted)-sha256.Size:] 335 | 336 | if _, err := io.ReadFull(c.rand(), iv); err != nil { 337 | return nil, err 338 | } 339 | key := ticketKeys[0] 340 | block, err := aes.NewCipher(key.aesKey[:]) 341 | if err != nil { 342 | return nil, errors.New("tls: failed to create cipher while encrypting ticket: " + err.Error()) 343 | } 344 | cipher.NewCTR(block, iv).XORKeyStream(ciphertext, state) 345 | 346 | mac := hmac.New(sha256.New, key.hmacKey[:]) 347 | mac.Write(authenticated) 348 | mac.Sum(macBytes[:0]) 349 | 350 | return encrypted, nil 351 | } 352 | 353 | // DecryptTicket decrypts a ticket encrypted by [Config.EncryptTicket]. It can 354 | // be used as a [Config.UnwrapSession] implementation. 355 | // 356 | // If the ticket can't be decrypted or parsed, DecryptTicket returns (nil, nil). 357 | func (c *Config) DecryptTicket(identity []byte, cs ConnectionState) (*SessionState, error) { 358 | ticketKeys := c.ticketKeys(nil) 359 | stateBytes := c.decryptTicket(identity, ticketKeys) 360 | if stateBytes == nil { 361 | return nil, nil 362 | } 363 | s, err := ParseSessionState(stateBytes) 364 | if err != nil { 365 | return nil, nil // drop unparsable tickets on the floor 366 | } 367 | return s, nil 368 | } 369 | 370 | func (c *Config) decryptTicket(encrypted []byte, ticketKeys []ticketKey) []byte { 371 | if len(encrypted) < aes.BlockSize+sha256.Size { 372 | return nil 373 | } 374 | 375 | iv := encrypted[:aes.BlockSize] 376 | ciphertext := encrypted[aes.BlockSize : len(encrypted)-sha256.Size] 377 | authenticated := encrypted[:len(encrypted)-sha256.Size] 378 | macBytes := encrypted[len(encrypted)-sha256.Size:] 379 | for _, key := range ticketKeys { 380 | mac := hmac.New(sha256.New, key.hmacKey[:]) 381 | mac.Write(authenticated) 382 | expected := mac.Sum(nil) 383 | 384 | if subtle.ConstantTimeCompare(macBytes, expected) != 1 { 385 | continue 386 | } 387 | 388 | block, err := aes.NewCipher(key.aesKey[:]) 389 | if err != nil { 390 | return nil 391 | } 392 | plaintext := make([]byte, len(ciphertext)) 393 | cipher.NewCTR(block, iv).XORKeyStream(plaintext, ciphertext) 394 | 395 | return plaintext 396 | } 397 | 398 | return nil 399 | } 400 | 401 | // ClientSessionState contains the state needed by a client to 402 | // resume a previous TLS session. 403 | type ClientSessionState struct { 404 | session *SessionState 405 | } 406 | 407 | // ResumptionState returns the session ticket sent by the server (also known as 408 | // the session's identity) and the state necessary to resume this session. 409 | // 410 | // It can be called by [ClientSessionCache.Put] to serialize (with 411 | // [SessionState.Bytes]) and store the session. 412 | func (cs *ClientSessionState) ResumptionState() (ticket []byte, state *SessionState, err error) { 413 | if cs == nil || cs.session == nil { 414 | return nil, nil, nil 415 | } 416 | return cs.session.ticket, cs.session, nil 417 | } 418 | 419 | // NewResumptionState returns a state value that can be returned by 420 | // [ClientSessionCache.Get] to resume a previous session. 421 | // 422 | // state needs to be returned by [ParseSessionState], and the ticket and session 423 | // state must have been returned by [ClientSessionState.ResumptionState]. 424 | func NewResumptionState(ticket []byte, state *SessionState) (*ClientSessionState, error) { 425 | state.ticket = ticket 426 | return &ClientSessionState{ 427 | session: state, 428 | }, nil 429 | } 430 | -------------------------------------------------------------------------------- /tls.go: -------------------------------------------------------------------------------- 1 | // Copyright 2009 The Go Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE-Go file. 4 | 5 | // Server side implementation of REALITY protocol, a fork of package tls in latest Go. 6 | // For client side, please follow https://github.com/XTLS/Xray-core/blob/main/transport/internet/reality/reality.go. 7 | 8 | // Package tls partially implements TLS 1.2, as specified in RFC 5246, 9 | // and TLS 1.3, as specified in RFC 8446. 10 | // 11 | // # FIPS 140-3 mode 12 | // 13 | // When the program is in [FIPS 140-3 mode], this package behaves as if only 14 | // SP 800-140C and SP 800-140D approved protocol versions, cipher suites, 15 | // signature algorithms, certificate public key types and sizes, and key 16 | // exchange and derivation algorithms were implemented. Others are silently 17 | // ignored and not negotiated, or rejected. This set may depend on the 18 | // algorithms supported by the FIPS 140-3 Go Cryptographic Module selected with 19 | // GOFIPS140, and may change across Go versions. 20 | // 21 | // [FIPS 140-3 mode]: https://go.dev/doc/security/fips140 22 | package reality 23 | 24 | // BUG(agl): The crypto/tls package only implements some countermeasures 25 | // against Lucky13 attacks on CBC-mode encryption, and only on SHA1 26 | // variants. See http://www.isg.rhul.ac.uk/tls/TLStiming.pdf and 27 | // https://www.imperialviolet.org/2013/02/04/luckythirteen.html. 28 | 29 | import ( 30 | "bytes" 31 | "context" 32 | "crypto" 33 | "crypto/aes" 34 | "crypto/cipher" 35 | "crypto/ecdsa" 36 | "crypto/ed25519" 37 | "crypto/mlkem" 38 | "crypto/rsa" 39 | "crypto/sha256" 40 | "crypto/x509" 41 | "encoding/binary" 42 | "encoding/pem" 43 | "errors" 44 | "fmt" 45 | "io" 46 | "net" 47 | "os" 48 | "runtime" 49 | "strings" 50 | "sync" 51 | "time" 52 | 53 | "github.com/pires/go-proxyproto" 54 | "golang.org/x/crypto/curve25519" 55 | "golang.org/x/crypto/hkdf" 56 | ) 57 | 58 | type CloseWriteConn interface { 59 | net.Conn 60 | CloseWrite() error 61 | } 62 | 63 | type MirrorConn struct { 64 | *sync.Mutex 65 | net.Conn 66 | Target net.Conn 67 | } 68 | 69 | func (c *MirrorConn) Read(b []byte) (int, error) { 70 | c.Unlock() 71 | runtime.Gosched() 72 | n, err := c.Conn.Read(b) 73 | c.Lock() // calling c.Lock() before c.Target.Write(), to make sure that this goroutine has the priority to make the next move 74 | if n != 0 { 75 | c.Target.Write(b[:n]) 76 | } 77 | if err != nil { 78 | c.Target.Close() 79 | } 80 | return n, err 81 | } 82 | 83 | func (c *MirrorConn) Write(b []byte) (int, error) { 84 | return 0, fmt.Errorf("Write(%v)", len(b)) 85 | } 86 | 87 | func (c *MirrorConn) Close() error { 88 | return fmt.Errorf("Close()") 89 | } 90 | 91 | func (c *MirrorConn) SetDeadline(t time.Time) error { 92 | return nil 93 | } 94 | 95 | func (c *MirrorConn) SetReadDeadline(t time.Time) error { 96 | return nil 97 | } 98 | 99 | func (c *MirrorConn) SetWriteDeadline(t time.Time) error { 100 | return nil 101 | } 102 | 103 | var ( 104 | size = 8192 105 | empty = make([]byte, size) 106 | types = [7]string{ 107 | "Server Hello", 108 | "Change Cipher Spec", 109 | "Encrypted Extensions", 110 | "Certificate", 111 | "Certificate Verify", 112 | "Finished", 113 | "New Session Ticket", 114 | } 115 | ) 116 | 117 | func Value(vals ...byte) (value int) { 118 | for i, val := range vals { 119 | value |= int(val) << ((len(vals) - i - 1) * 8) 120 | } 121 | return 122 | } 123 | 124 | // Server returns a new TLS server side connection 125 | // using conn as the underlying transport. 126 | // The configuration config must be non-nil and must include 127 | // at least one certificate or else set GetCertificate. 128 | func Server(ctx context.Context, conn net.Conn, config *Config) (*Conn, error) { 129 | remoteAddr := conn.RemoteAddr().String() 130 | if config.Show { 131 | fmt.Printf("REALITY remoteAddr: %v\n", remoteAddr) 132 | } 133 | 134 | target, err := config.DialContext(ctx, config.Type, config.Dest) 135 | if err != nil { 136 | conn.Close() 137 | return nil, errors.New("REALITY: failed to dial dest: " + err.Error()) 138 | } 139 | 140 | if config.Xver == 1 || config.Xver == 2 { 141 | if _, err = proxyproto.HeaderProxyFromAddrs(config.Xver, conn.RemoteAddr(), conn.LocalAddr()).WriteTo(target); err != nil { 142 | target.Close() 143 | conn.Close() 144 | return nil, errors.New("REALITY: failed to send PROXY protocol: " + err.Error()) 145 | } 146 | } 147 | 148 | raw := conn 149 | if pc, ok := conn.(*proxyproto.Conn); ok { 150 | raw = pc.Raw() // for TCP splicing in io.Copy() 151 | } 152 | underlying := raw.(CloseWriteConn) // *net.TCPConn or *net.UnixConn 153 | 154 | mutex := new(sync.Mutex) 155 | 156 | hs := serverHandshakeStateTLS13{ 157 | c: &Conn{ 158 | conn: &MirrorConn{ 159 | Mutex: mutex, 160 | Conn: conn, 161 | Target: target, 162 | }, 163 | config: config, 164 | }, 165 | ctx: context.Background(), 166 | } 167 | 168 | copying := false 169 | 170 | waitGroup := new(sync.WaitGroup) 171 | waitGroup.Add(2) 172 | 173 | go func() { 174 | for { 175 | mutex.Lock() 176 | hs.clientHello, _, err = hs.c.readClientHello(context.Background()) // TODO: Change some rules in this function. 177 | if copying || err != nil || hs.c.vers != VersionTLS13 || !config.ServerNames[hs.clientHello.serverName] { 178 | break 179 | } 180 | for _, keyShare := range hs.clientHello.keyShares { 181 | if keyShare.group != X25519 || len(keyShare.data) != 32 { 182 | continue 183 | } 184 | if hs.c.AuthKey, err = curve25519.X25519(config.PrivateKey, keyShare.data); err != nil { 185 | break 186 | } 187 | if _, err = hkdf.New(sha256.New, hs.c.AuthKey, hs.clientHello.random[:20], []byte("REALITY")).Read(hs.c.AuthKey); err != nil { 188 | break 189 | } 190 | block, _ := aes.NewCipher(hs.c.AuthKey) 191 | aead, _ := cipher.NewGCM(block) 192 | if config.Show { 193 | fmt.Printf("REALITY remoteAddr: %v\ths.c.AuthKey[:16]: %v\tAEAD: %T\n", remoteAddr, hs.c.AuthKey[:16], aead) 194 | } 195 | ciphertext := make([]byte, 32) 196 | plainText := make([]byte, 32) 197 | copy(ciphertext, hs.clientHello.sessionId) 198 | copy(hs.clientHello.sessionId, plainText) // hs.clientHello.sessionId points to hs.clientHello.raw[39:] 199 | if _, err = aead.Open(plainText[:0], hs.clientHello.random[20:], ciphertext, hs.clientHello.original); err != nil { 200 | break 201 | } 202 | copy(hs.clientHello.sessionId, ciphertext) 203 | copy(hs.c.ClientVer[:], plainText) 204 | hs.c.ClientTime = time.Unix(int64(binary.BigEndian.Uint32(plainText[4:])), 0) 205 | copy(hs.c.ClientShortId[:], plainText[8:]) 206 | if config.Show { 207 | fmt.Printf("REALITY remoteAddr: %v\ths.c.ClientVer: %v\n", remoteAddr, hs.c.ClientVer) 208 | fmt.Printf("REALITY remoteAddr: %v\ths.c.ClientTime: %v\n", remoteAddr, hs.c.ClientTime) 209 | fmt.Printf("REALITY remoteAddr: %v\ths.c.ClientShortId: %v\n", remoteAddr, hs.c.ClientShortId) 210 | } 211 | if (config.MinClientVer == nil || Value(hs.c.ClientVer[:]...) >= Value(config.MinClientVer...)) && 212 | (config.MaxClientVer == nil || Value(hs.c.ClientVer[:]...) <= Value(config.MaxClientVer...)) && 213 | (config.MaxTimeDiff == 0 || time.Since(hs.c.ClientTime).Abs() <= config.MaxTimeDiff) && 214 | (config.ShortIds[hs.c.ClientShortId]) { 215 | hs.c.conn = conn 216 | } 217 | break 218 | } 219 | if config.Show { 220 | fmt.Printf("REALITY remoteAddr: %v\ths.c.conn == conn: %v\n", remoteAddr, hs.c.conn == conn) 221 | } 222 | break 223 | } 224 | mutex.Unlock() 225 | if hs.c.conn != conn { 226 | if config.Show && hs.clientHello != nil { 227 | fmt.Printf("REALITY remoteAddr: %v\tforwarded SNI: %v\n", remoteAddr, hs.clientHello.serverName) 228 | } 229 | io.Copy(target, underlying) 230 | } 231 | waitGroup.Done() 232 | }() 233 | 234 | go func() { 235 | s2cSaved := make([]byte, 0, size) 236 | buf := make([]byte, size) 237 | handshakeLen := 0 238 | f: 239 | for { 240 | runtime.Gosched() 241 | n, err := target.Read(buf) 242 | if n == 0 { 243 | if err != nil { 244 | conn.Close() 245 | waitGroup.Done() 246 | return 247 | } 248 | continue 249 | } 250 | mutex.Lock() 251 | s2cSaved = append(s2cSaved, buf[:n]...) 252 | if hs.c.conn != conn { 253 | copying = true // if the target already sent some data, just start bidirectional direct forwarding 254 | break 255 | } 256 | if len(s2cSaved) > size { 257 | break 258 | } 259 | for i, t := range types { 260 | if hs.c.out.handshakeLen[i] != 0 { 261 | continue 262 | } 263 | if i == 6 && len(s2cSaved) == 0 { 264 | break 265 | } 266 | if handshakeLen == 0 && len(s2cSaved) > recordHeaderLen { 267 | if Value(s2cSaved[1:3]...) != VersionTLS12 || 268 | (i == 0 && (recordType(s2cSaved[0]) != recordTypeHandshake || s2cSaved[5] != typeServerHello)) || 269 | (i == 1 && (recordType(s2cSaved[0]) != recordTypeChangeCipherSpec || s2cSaved[5] != 1)) || 270 | (i > 1 && recordType(s2cSaved[0]) != recordTypeApplicationData) { 271 | break f 272 | } 273 | handshakeLen = recordHeaderLen + Value(s2cSaved[3:5]...) 274 | } 275 | if config.Show { 276 | fmt.Printf("REALITY remoteAddr: %v\tlen(s2cSaved): %v\t%v: %v\n", remoteAddr, len(s2cSaved), t, handshakeLen) 277 | } 278 | if handshakeLen > size { // too long 279 | break f 280 | } 281 | if i == 1 && handshakeLen > 0 && handshakeLen != 6 { 282 | break f 283 | } 284 | if i == 2 && handshakeLen > 512 { 285 | hs.c.out.handshakeLen[i] = handshakeLen 286 | hs.c.out.handshakeBuf = buf[:0] 287 | break 288 | } 289 | if i == 6 && handshakeLen > 0 { 290 | hs.c.out.handshakeLen[i] = handshakeLen 291 | break 292 | } 293 | if handshakeLen == 0 || len(s2cSaved) < handshakeLen { 294 | mutex.Unlock() 295 | continue f 296 | } 297 | if i == 0 { 298 | hs.hello = new(serverHelloMsg) 299 | if !hs.hello.unmarshal(s2cSaved[recordHeaderLen:handshakeLen]) || 300 | hs.hello.vers != VersionTLS12 || hs.hello.supportedVersion != VersionTLS13 || 301 | cipherSuiteTLS13ByID(hs.hello.cipherSuite) == nil || 302 | (!(hs.hello.serverShare.group == X25519 && len(hs.hello.serverShare.data) == 32) && 303 | !(hs.hello.serverShare.group == X25519MLKEM768 && len(hs.hello.serverShare.data) == mlkem.CiphertextSize768+32)) { 304 | break f 305 | } 306 | } 307 | hs.c.out.handshakeLen[i] = handshakeLen 308 | s2cSaved = s2cSaved[handshakeLen:] 309 | handshakeLen = 0 310 | } 311 | start := time.Now() 312 | err = hs.handshake() 313 | if config.Show { 314 | fmt.Printf("REALITY remoteAddr: %v\ths.handshake() err: %v\n", remoteAddr, err) 315 | } 316 | if err != nil { 317 | break 318 | } 319 | go func() { // TODO: Probe target's maxUselessRecords and some time-outs in advance. 320 | if handshakeLen-len(s2cSaved) > 0 { 321 | io.ReadFull(target, buf[:handshakeLen-len(s2cSaved)]) 322 | } 323 | if n, err := target.Read(buf); !hs.c.isHandshakeComplete.Load() { 324 | if err != nil { 325 | conn.Close() 326 | } 327 | if config.Show { 328 | fmt.Printf("REALITY remoteAddr: %v\ttime.Since(start): %v\tn: %v\terr: %v\n", remoteAddr, time.Since(start), n, err) 329 | } 330 | } 331 | }() 332 | err = hs.readClientFinished() 333 | if config.Show { 334 | fmt.Printf("REALITY remoteAddr: %v\ths.readClientFinished() err: %v\n", remoteAddr, err) 335 | } 336 | if err != nil { 337 | break 338 | } 339 | hs.c.isHandshakeComplete.Store(true) 340 | break 341 | } 342 | mutex.Unlock() 343 | if hs.c.out.handshakeLen[0] == 0 { // if the target sent an incorrect Server Hello, or before that 344 | if hs.c.conn == conn { // if we processed the Client Hello successfully but the target did not 345 | waitGroup.Add(1) 346 | go func() { 347 | io.Copy(target, underlying) 348 | waitGroup.Done() 349 | }() 350 | } 351 | conn.Write(s2cSaved) 352 | io.Copy(underlying, target) 353 | // Here is bidirectional direct forwarding: 354 | // client ---underlying--- server ---target--- dest 355 | // Call `underlying.CloseWrite()` once `io.Copy()` returned 356 | underlying.CloseWrite() 357 | } 358 | waitGroup.Done() 359 | }() 360 | 361 | waitGroup.Wait() 362 | target.Close() 363 | if config.Show { 364 | fmt.Printf("REALITY remoteAddr: %v\ths.c.handshakeStatus: %v\n", remoteAddr, hs.c.isHandshakeComplete.Load()) 365 | } 366 | if hs.c.isHandshakeComplete.Load() { 367 | return hs.c, nil 368 | } 369 | conn.Close() 370 | return nil, errors.New("REALITY: processed invalid connection") // TODO: Add details. 371 | 372 | /* 373 | c := &Conn{ 374 | conn: conn, 375 | config: config, 376 | } 377 | c.handshakeFn = c.serverHandshake 378 | return c 379 | */ 380 | } 381 | 382 | // Client returns a new TLS client side connection 383 | // using conn as the underlying transport. 384 | // The config cannot be nil: users must set either ServerName or 385 | // InsecureSkipVerify in the config. 386 | func Client(conn net.Conn, config *Config) *Conn { 387 | c := &Conn{ 388 | conn: conn, 389 | config: config, 390 | isClient: true, 391 | } 392 | c.handshakeFn = c.clientHandshake 393 | return c 394 | } 395 | 396 | // A listener implements a network listener (net.Listener) for TLS connections. 397 | type listener struct { 398 | net.Listener 399 | config *Config 400 | conns chan net.Conn 401 | err error 402 | } 403 | 404 | // Accept waits for and returns the next incoming TLS connection. 405 | // The returned connection is of type *Conn. 406 | func (l *listener) Accept() (net.Conn, error) { 407 | /* 408 | c, err := l.Listener.Accept() 409 | if err != nil { 410 | return nil, err 411 | } 412 | return Server(c, l.config), nil 413 | */ 414 | if c, ok := <-l.conns; ok { 415 | return c, nil 416 | } 417 | return nil, l.err 418 | } 419 | 420 | // NewListener creates a Listener which accepts connections from an inner 421 | // Listener and wraps each connection with [Server]. 422 | // The configuration config must be non-nil and must include 423 | // at least one certificate or else set GetCertificate. 424 | func NewListener(inner net.Listener, config *Config) net.Listener { 425 | l := new(listener) 426 | l.Listener = inner 427 | l.config = config 428 | { 429 | l.conns = make(chan net.Conn) 430 | go func() { 431 | for { 432 | c, err := l.Listener.Accept() 433 | if err != nil { 434 | l.err = err 435 | close(l.conns) 436 | return 437 | } 438 | go func() { 439 | defer recover() 440 | c, err = Server(context.Background(), c, l.config) 441 | if err == nil { 442 | l.conns <- c 443 | } 444 | }() 445 | } 446 | }() 447 | } 448 | return l 449 | } 450 | 451 | // Listen creates a TLS listener accepting connections on the 452 | // given network address using net.Listen. 453 | // The configuration config must be non-nil and must include 454 | // at least one certificate or else set GetCertificate. 455 | func Listen(network, laddr string, config *Config) (net.Listener, error) { 456 | // If this condition changes, consider updating http.Server.ServeTLS too. 457 | if config == nil || len(config.Certificates) == 0 && 458 | config.GetCertificate == nil && config.GetConfigForClient == nil { 459 | return nil, errors.New("tls: neither Certificates, GetCertificate, nor GetConfigForClient set in Config") 460 | } 461 | l, err := net.Listen(network, laddr) 462 | if err != nil { 463 | return nil, err 464 | } 465 | return NewListener(l, config), nil 466 | } 467 | 468 | type timeoutError struct{} 469 | 470 | func (timeoutError) Error() string { return "tls: DialWithDialer timed out" } 471 | func (timeoutError) Timeout() bool { return true } 472 | func (timeoutError) Temporary() bool { return true } 473 | 474 | // DialWithDialer connects to the given network address using dialer.Dial and 475 | // then initiates a TLS handshake, returning the resulting TLS connection. Any 476 | // timeout or deadline given in the dialer apply to connection and TLS 477 | // handshake as a whole. 478 | // 479 | // DialWithDialer interprets a nil configuration as equivalent to the zero 480 | // configuration; see the documentation of [Config] for the defaults. 481 | // 482 | // DialWithDialer uses context.Background internally; to specify the context, 483 | // use [Dialer.DialContext] with NetDialer set to the desired dialer. 484 | func DialWithDialer(dialer *net.Dialer, network, addr string, config *Config) (*Conn, error) { 485 | return dial(context.Background(), dialer, network, addr, config) 486 | } 487 | 488 | func dial(ctx context.Context, netDialer *net.Dialer, network, addr string, config *Config) (*Conn, error) { 489 | if netDialer.Timeout != 0 { 490 | var cancel context.CancelFunc 491 | ctx, cancel = context.WithTimeout(ctx, netDialer.Timeout) 492 | defer cancel() 493 | } 494 | 495 | if !netDialer.Deadline.IsZero() { 496 | var cancel context.CancelFunc 497 | ctx, cancel = context.WithDeadline(ctx, netDialer.Deadline) 498 | defer cancel() 499 | } 500 | 501 | rawConn, err := netDialer.DialContext(ctx, network, addr) 502 | if err != nil { 503 | return nil, err 504 | } 505 | 506 | colonPos := strings.LastIndex(addr, ":") 507 | if colonPos == -1 { 508 | colonPos = len(addr) 509 | } 510 | hostname := addr[:colonPos] 511 | 512 | if config == nil { 513 | config = defaultConfig() 514 | } 515 | // If no ServerName is set, infer the ServerName 516 | // from the hostname we're connecting to. 517 | if config.ServerName == "" { 518 | // Make a copy to avoid polluting argument or default. 519 | c := config.Clone() 520 | c.ServerName = hostname 521 | config = c 522 | } 523 | 524 | conn := Client(rawConn, config) 525 | if err := conn.HandshakeContext(ctx); err != nil { 526 | rawConn.Close() 527 | return nil, err 528 | } 529 | return conn, nil 530 | } 531 | 532 | // Dial connects to the given network address using net.Dial 533 | // and then initiates a TLS handshake, returning the resulting 534 | // TLS connection. 535 | // Dial interprets a nil configuration as equivalent to 536 | // the zero configuration; see the documentation of Config 537 | // for the defaults. 538 | func Dial(network, addr string, config *Config) (*Conn, error) { 539 | return DialWithDialer(new(net.Dialer), network, addr, config) 540 | } 541 | 542 | // Dialer dials TLS connections given a configuration and a Dialer for the 543 | // underlying connection. 544 | type Dialer struct { 545 | // NetDialer is the optional dialer to use for the TLS connections' 546 | // underlying TCP connections. 547 | // A nil NetDialer is equivalent to the net.Dialer zero value. 548 | NetDialer *net.Dialer 549 | 550 | // Config is the TLS configuration to use for new connections. 551 | // A nil configuration is equivalent to the zero 552 | // configuration; see the documentation of Config for the 553 | // defaults. 554 | Config *Config 555 | } 556 | 557 | // Dial connects to the given network address and initiates a TLS 558 | // handshake, returning the resulting TLS connection. 559 | // 560 | // The returned [Conn], if any, will always be of type *[Conn]. 561 | // 562 | // Dial uses context.Background internally; to specify the context, 563 | // use [Dialer.DialContext]. 564 | func (d *Dialer) Dial(network, addr string) (net.Conn, error) { 565 | return d.DialContext(context.Background(), network, addr) 566 | } 567 | 568 | func (d *Dialer) netDialer() *net.Dialer { 569 | if d.NetDialer != nil { 570 | return d.NetDialer 571 | } 572 | return new(net.Dialer) 573 | } 574 | 575 | // DialContext connects to the given network address and initiates a TLS 576 | // handshake, returning the resulting TLS connection. 577 | // 578 | // The provided Context must be non-nil. If the context expires before 579 | // the connection is complete, an error is returned. Once successfully 580 | // connected, any expiration of the context will not affect the 581 | // connection. 582 | // 583 | // The returned [Conn], if any, will always be of type *[Conn]. 584 | func (d *Dialer) DialContext(ctx context.Context, network, addr string) (net.Conn, error) { 585 | c, err := dial(ctx, d.netDialer(), network, addr, d.Config) 586 | if err != nil { 587 | // Don't return c (a typed nil) in an interface. 588 | return nil, err 589 | } 590 | return c, nil 591 | } 592 | 593 | // LoadX509KeyPair reads and parses a public/private key pair from a pair of 594 | // files. The files must contain PEM encoded data. The certificate file may 595 | // contain intermediate certificates following the leaf certificate to form a 596 | // certificate chain. On successful return, Certificate.Leaf will be populated. 597 | // 598 | // Before Go 1.23 Certificate.Leaf was left nil, and the parsed certificate was 599 | // discarded. This behavior can be re-enabled by setting "x509keypairleaf=0" 600 | // in the GODEBUG environment variable. 601 | func LoadX509KeyPair(certFile, keyFile string) (Certificate, error) { 602 | certPEMBlock, err := os.ReadFile(certFile) 603 | if err != nil { 604 | return Certificate{}, err 605 | } 606 | keyPEMBlock, err := os.ReadFile(keyFile) 607 | if err != nil { 608 | return Certificate{}, err 609 | } 610 | return X509KeyPair(certPEMBlock, keyPEMBlock) 611 | } 612 | 613 | // X509KeyPair parses a public/private key pair from a pair of 614 | // PEM encoded data. On successful return, Certificate.Leaf will be populated. 615 | // 616 | // Before Go 1.23 Certificate.Leaf was left nil, and the parsed certificate was 617 | // discarded. This behavior can be re-enabled by setting "x509keypairleaf=0" 618 | // in the GODEBUG environment variable. 619 | func X509KeyPair(certPEMBlock, keyPEMBlock []byte) (Certificate, error) { 620 | fail := func(err error) (Certificate, error) { return Certificate{}, err } 621 | 622 | var cert Certificate 623 | var skippedBlockTypes []string 624 | for { 625 | var certDERBlock *pem.Block 626 | certDERBlock, certPEMBlock = pem.Decode(certPEMBlock) 627 | if certDERBlock == nil { 628 | break 629 | } 630 | if certDERBlock.Type == "CERTIFICATE" { 631 | cert.Certificate = append(cert.Certificate, certDERBlock.Bytes) 632 | } else { 633 | skippedBlockTypes = append(skippedBlockTypes, certDERBlock.Type) 634 | } 635 | } 636 | 637 | if len(cert.Certificate) == 0 { 638 | if len(skippedBlockTypes) == 0 { 639 | return fail(errors.New("tls: failed to find any PEM data in certificate input")) 640 | } 641 | if len(skippedBlockTypes) == 1 && strings.HasSuffix(skippedBlockTypes[0], "PRIVATE KEY") { 642 | return fail(errors.New("tls: failed to find certificate PEM data in certificate input, but did find a private key; PEM inputs may have been switched")) 643 | } 644 | return fail(fmt.Errorf("tls: failed to find \"CERTIFICATE\" PEM block in certificate input after skipping PEM blocks of the following types: %v", skippedBlockTypes)) 645 | } 646 | 647 | skippedBlockTypes = skippedBlockTypes[:0] 648 | var keyDERBlock *pem.Block 649 | for { 650 | keyDERBlock, keyPEMBlock = pem.Decode(keyPEMBlock) 651 | if keyDERBlock == nil { 652 | if len(skippedBlockTypes) == 0 { 653 | return fail(errors.New("tls: failed to find any PEM data in key input")) 654 | } 655 | if len(skippedBlockTypes) == 1 && skippedBlockTypes[0] == "CERTIFICATE" { 656 | return fail(errors.New("tls: found a certificate rather than a key in the PEM for the private key")) 657 | } 658 | return fail(fmt.Errorf("tls: failed to find PEM block with type ending in \"PRIVATE KEY\" in key input after skipping PEM blocks of the following types: %v", skippedBlockTypes)) 659 | } 660 | if keyDERBlock.Type == "PRIVATE KEY" || strings.HasSuffix(keyDERBlock.Type, " PRIVATE KEY") { 661 | break 662 | } 663 | skippedBlockTypes = append(skippedBlockTypes, keyDERBlock.Type) 664 | } 665 | 666 | // We don't need to parse the public key for TLS, but we so do anyway 667 | // to check that it looks sane and matches the private key. 668 | x509Cert, err := x509.ParseCertificate(cert.Certificate[0]) 669 | if err != nil { 670 | return fail(err) 671 | } 672 | 673 | cert.Leaf = x509Cert 674 | 675 | cert.PrivateKey, err = parsePrivateKey(keyDERBlock.Bytes) 676 | if err != nil { 677 | return fail(err) 678 | } 679 | 680 | switch pub := x509Cert.PublicKey.(type) { 681 | case *rsa.PublicKey: 682 | priv, ok := cert.PrivateKey.(*rsa.PrivateKey) 683 | if !ok { 684 | return fail(errors.New("tls: private key type does not match public key type")) 685 | } 686 | if pub.N.Cmp(priv.N) != 0 { 687 | return fail(errors.New("tls: private key does not match public key")) 688 | } 689 | case *ecdsa.PublicKey: 690 | priv, ok := cert.PrivateKey.(*ecdsa.PrivateKey) 691 | if !ok { 692 | return fail(errors.New("tls: private key type does not match public key type")) 693 | } 694 | if pub.X.Cmp(priv.X) != 0 || pub.Y.Cmp(priv.Y) != 0 { 695 | return fail(errors.New("tls: private key does not match public key")) 696 | } 697 | case ed25519.PublicKey: 698 | priv, ok := cert.PrivateKey.(ed25519.PrivateKey) 699 | if !ok { 700 | return fail(errors.New("tls: private key type does not match public key type")) 701 | } 702 | if !bytes.Equal(priv.Public().(ed25519.PublicKey), pub) { 703 | return fail(errors.New("tls: private key does not match public key")) 704 | } 705 | default: 706 | return fail(errors.New("tls: unknown public key algorithm")) 707 | } 708 | 709 | return cert, nil 710 | } 711 | 712 | // Attempt to parse the given private key DER block. OpenSSL 0.9.8 generates 713 | // PKCS #1 private keys by default, while OpenSSL 1.0.0 generates PKCS #8 keys. 714 | // OpenSSL ecparam generates SEC1 EC private keys for ECDSA. We try all three. 715 | func parsePrivateKey(der []byte) (crypto.PrivateKey, error) { 716 | if key, err := x509.ParsePKCS1PrivateKey(der); err == nil { 717 | return key, nil 718 | } 719 | if key, err := x509.ParsePKCS8PrivateKey(der); err == nil { 720 | switch key := key.(type) { 721 | case *rsa.PrivateKey, *ecdsa.PrivateKey, ed25519.PrivateKey: 722 | return key, nil 723 | default: 724 | return nil, errors.New("tls: found unknown private key type in PKCS#8 wrapping") 725 | } 726 | } 727 | if key, err := x509.ParseECPrivateKey(der); err == nil { 728 | return key, nil 729 | } 730 | 731 | return nil, errors.New("tls: failed to parse private key") 732 | } 733 | -------------------------------------------------------------------------------- /tls12/tls12.go: -------------------------------------------------------------------------------- 1 | // Copyright 2024 The Go Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package tls12 6 | 7 | import ( 8 | "crypto/hmac" 9 | "hash" 10 | ) 11 | 12 | // PRF implements the TLS 1.2 pseudo-random function, as defined in RFC 5246, 13 | // Section 5 and allowed by SP 800-135, Revision 1, Section 4.2.2. 14 | func PRF[H hash.Hash](hash func() H, secret []byte, label string, seed []byte, keyLen int) []byte { 15 | labelAndSeed := make([]byte, len(label)+len(seed)) 16 | copy(labelAndSeed, label) 17 | copy(labelAndSeed[len(label):], seed) 18 | 19 | result := make([]byte, keyLen) 20 | pHash(hash, result, secret, labelAndSeed) 21 | return result 22 | } 23 | 24 | // pHash implements the P_hash function, as defined in RFC 5246, Section 5. 25 | func pHash[H hash.Hash](hash1 func() H, result, secret, seed []byte) { 26 | h := hmac.New(any(hash1).(func() hash.Hash), secret) 27 | h.Write(seed) 28 | a := h.Sum(nil) 29 | 30 | for len(result) > 0 { 31 | h.Reset() 32 | h.Write(a) 33 | h.Write(seed) 34 | b := h.Sum(nil) 35 | n := copy(result, b) 36 | result = result[n:] 37 | 38 | h.Reset() 39 | h.Write(a) 40 | a = h.Sum(nil) 41 | } 42 | } 43 | 44 | const masterSecretLength = 48 45 | const extendedMasterSecretLabel = "extended master secret" 46 | 47 | // MasterSecret implements the TLS 1.2 extended master secret derivation, as 48 | // defined in RFC 7627 and allowed by SP 800-135, Revision 1, Section 4.2.2. 49 | func MasterSecret[H hash.Hash](hash func() H, preMasterSecret, transcript []byte) []byte { 50 | // "The TLS 1.2 KDF is an approved KDF when the following conditions are 51 | // satisfied: [...] (3) P_HASH uses either SHA-256, SHA-384 or SHA-512." 52 | //h := hash() 53 | hash() 54 | // switch any(h).(type) { 55 | // case *sha256.Digest: 56 | // if h.Size() != 32 { 57 | // fips140.RecordNonApproved() 58 | // } 59 | // case *sha512.Digest: 60 | // if h.Size() != 46 && h.Size() != 64 { 61 | // fips140.RecordNonApproved() 62 | // } 63 | // default: 64 | // fips140.RecordNonApproved() 65 | // } 66 | 67 | return PRF(hash, preMasterSecret, extendedMasterSecretLabel, transcript, masterSecretLength) 68 | } -------------------------------------------------------------------------------- /tls13/tls13.go: -------------------------------------------------------------------------------- 1 | // Copyright 2024 The Go Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | // Package tls13 implements the TLS 1.3 Key Schedule as specified in RFC 8446, 6 | // Section 7.1 and allowed by FIPS 140-3 IG 2.4.B Resolution 7. 7 | package tls13 8 | 9 | import ( 10 | "crypto/hkdf" 11 | "encoding/binary" 12 | "hash" 13 | ) 14 | 15 | // We don't set the service indicator in this package but we delegate that to 16 | // the underlying functions because the TLS 1.3 KDF does not have a standard of 17 | // its own. 18 | 19 | // ExpandLabel implements HKDF-Expand-Label from RFC 8446, Section 7.1. 20 | func ExpandLabel[H hash.Hash](hash func() H, secret []byte, label string, context []byte, length int) []byte { 21 | if len("tls13 ")+len(label) > 255 || len(context) > 255 { 22 | // It should be impossible for this to panic: labels are fixed strings, 23 | // and context is either a fixed-length computed hash, or parsed from a 24 | // field which has the same length limitation. 25 | // 26 | // Another reasonable approach might be to return a randomized slice if 27 | // we encounter an error, which would break the connection, but avoid 28 | // panicking. This would perhaps be safer but significantly more 29 | // confusing to users. 30 | panic("tls13: label or context too long") 31 | } 32 | hkdfLabel := make([]byte, 0, 2+1+len("tls13 ")+len(label)+1+len(context)) 33 | hkdfLabel = binary.BigEndian.AppendUint16(hkdfLabel, uint16(length)) 34 | hkdfLabel = append(hkdfLabel, byte(len("tls13 ")+len(label))) 35 | hkdfLabel = append(hkdfLabel, "tls13 "...) 36 | hkdfLabel = append(hkdfLabel, label...) 37 | hkdfLabel = append(hkdfLabel, byte(len(context))) 38 | hkdfLabel = append(hkdfLabel, context...) 39 | b, _ := hkdf.Expand(hash, secret, string(hkdfLabel), length) 40 | return b 41 | } 42 | 43 | func extract[H hash.Hash](hash func() H, newSecret, currentSecret []byte) []byte { 44 | if newSecret == nil { 45 | newSecret = make([]byte, hash().Size()) 46 | } 47 | b, _ := hkdf.Extract(hash, newSecret, currentSecret) 48 | return b 49 | } 50 | 51 | func deriveSecret[H hash.Hash](hash func() H, secret []byte, label string, transcript hash.Hash) []byte { 52 | if transcript == nil { 53 | transcript = hash() 54 | } 55 | return ExpandLabel(hash, secret, label, transcript.Sum(nil), transcript.Size()) 56 | } 57 | 58 | const ( 59 | resumptionBinderLabel = "res binder" 60 | clientEarlyTrafficLabel = "c e traffic" 61 | clientHandshakeTrafficLabel = "c hs traffic" 62 | serverHandshakeTrafficLabel = "s hs traffic" 63 | clientApplicationTrafficLabel = "c ap traffic" 64 | serverApplicationTrafficLabel = "s ap traffic" 65 | earlyExporterLabel = "e exp master" 66 | exporterLabel = "exp master" 67 | resumptionLabel = "res master" 68 | ) 69 | 70 | type EarlySecret struct { 71 | secret []byte 72 | hash func() hash.Hash 73 | } 74 | 75 | func NewEarlySecret[H hash.Hash](h func() H, psk []byte) *EarlySecret { 76 | return &EarlySecret{ 77 | secret: extract(h, psk, nil), 78 | hash: func() hash.Hash { return h() }, 79 | } 80 | } 81 | 82 | func (s *EarlySecret) ResumptionBinderKey() []byte { 83 | return deriveSecret(s.hash, s.secret, resumptionBinderLabel, nil) 84 | } 85 | 86 | // ClientEarlyTrafficSecret derives the client_early_traffic_secret from the 87 | // early secret and the transcript up to the ClientHello. 88 | func (s *EarlySecret) ClientEarlyTrafficSecret(transcript hash.Hash) []byte { 89 | return deriveSecret(s.hash, s.secret, clientEarlyTrafficLabel, transcript) 90 | } 91 | 92 | type HandshakeSecret struct { 93 | secret []byte 94 | hash func() hash.Hash 95 | } 96 | 97 | func (s *EarlySecret) HandshakeSecret(sharedSecret []byte) *HandshakeSecret { 98 | derived := deriveSecret(s.hash, s.secret, "derived", nil) 99 | return &HandshakeSecret{ 100 | secret: extract(s.hash, sharedSecret, derived), 101 | hash: s.hash, 102 | } 103 | } 104 | 105 | // ClientHandshakeTrafficSecret derives the client_handshake_traffic_secret from 106 | // the handshake secret and the transcript up to the ServerHello. 107 | func (s *HandshakeSecret) ClientHandshakeTrafficSecret(transcript hash.Hash) []byte { 108 | return deriveSecret(s.hash, s.secret, clientHandshakeTrafficLabel, transcript) 109 | } 110 | 111 | // ServerHandshakeTrafficSecret derives the server_handshake_traffic_secret from 112 | // the handshake secret and the transcript up to the ServerHello. 113 | func (s *HandshakeSecret) ServerHandshakeTrafficSecret(transcript hash.Hash) []byte { 114 | return deriveSecret(s.hash, s.secret, serverHandshakeTrafficLabel, transcript) 115 | } 116 | 117 | type MasterSecret struct { 118 | secret []byte 119 | hash func() hash.Hash 120 | } 121 | 122 | func (s *HandshakeSecret) MasterSecret() *MasterSecret { 123 | derived := deriveSecret(s.hash, s.secret, "derived", nil) 124 | return &MasterSecret{ 125 | secret: extract(s.hash, nil, derived), 126 | hash: s.hash, 127 | } 128 | } 129 | 130 | // ClientApplicationTrafficSecret derives the client_application_traffic_secret_0 131 | // from the master secret and the transcript up to the server Finished. 132 | func (s *MasterSecret) ClientApplicationTrafficSecret(transcript hash.Hash) []byte { 133 | return deriveSecret(s.hash, s.secret, clientApplicationTrafficLabel, transcript) 134 | } 135 | 136 | // ServerApplicationTrafficSecret derives the server_application_traffic_secret_0 137 | // from the master secret and the transcript up to the server Finished. 138 | func (s *MasterSecret) ServerApplicationTrafficSecret(transcript hash.Hash) []byte { 139 | return deriveSecret(s.hash, s.secret, serverApplicationTrafficLabel, transcript) 140 | } 141 | 142 | // ResumptionMasterSecret derives the resumption_master_secret from the master secret 143 | // and the transcript up to the client Finished. 144 | func (s *MasterSecret) ResumptionMasterSecret(transcript hash.Hash) []byte { 145 | return deriveSecret(s.hash, s.secret, resumptionLabel, transcript) 146 | } 147 | 148 | type ExporterMasterSecret struct { 149 | secret []byte 150 | hash func() hash.Hash 151 | } 152 | 153 | // ExporterMasterSecret derives the exporter_master_secret from the master secret 154 | // and the transcript up to the server Finished. 155 | func (s *MasterSecret) ExporterMasterSecret(transcript hash.Hash) *ExporterMasterSecret { 156 | return &ExporterMasterSecret{ 157 | secret: deriveSecret(s.hash, s.secret, exporterLabel, transcript), 158 | hash: s.hash, 159 | } 160 | } 161 | 162 | // EarlyExporterMasterSecret derives the exporter_master_secret from the early secret 163 | // and the transcript up to the ClientHello. 164 | func (s *EarlySecret) EarlyExporterMasterSecret(transcript hash.Hash) *ExporterMasterSecret { 165 | return &ExporterMasterSecret{ 166 | secret: deriveSecret(s.hash, s.secret, earlyExporterLabel, transcript), 167 | hash: s.hash, 168 | } 169 | } 170 | 171 | func (s *ExporterMasterSecret) Exporter(label string, context []byte, length int) []byte { 172 | secret := deriveSecret(s.hash, s.secret, label, nil) 173 | h := s.hash() 174 | h.Write(context) 175 | return ExpandLabel(s.hash, secret, "exporter", h.Sum(nil), length) 176 | } 177 | 178 | func TestingOnlyExporterSecret(s *ExporterMasterSecret) []byte { 179 | return s.secret 180 | } --------------------------------------------------------------------------------