├── LICENSE ├── README.md ├── bio.go ├── build.go ├── common.go ├── conn.go ├── ctx.go ├── hostname.c ├── init.go ├── init_posix.go ├── init_windows.go ├── internal ├── cipherhw │ ├── asm_amd64.s │ ├── asm_s390x.s │ ├── cipherhw_amd64.go │ ├── cipherhw_s390x.go │ ├── doc.go │ └── generic.go ├── errgroup │ └── errgroup.go └── future │ └── future.go ├── mapping.go ├── shim.c ├── shim.h ├── sni.c └── ssl.go /LICENSE: -------------------------------------------------------------------------------- 1 | Apache License 2 | Version 2.0, January 2004 3 | http://www.apache.org/licenses/ 4 | 5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 6 | 7 | 1. Definitions. 8 | 9 | "License" shall mean the terms and conditions for use, reproduction, 10 | and distribution as defined by Sections 1 through 9 of this document. 11 | 12 | "Licensor" shall mean the copyright owner or entity authorized by 13 | the copyright owner that is granting the License. 14 | 15 | "Legal Entity" shall mean the union of the acting entity and all 16 | other entities that control, are controlled by, or are under common 17 | control with that entity. For the purposes of this definition, 18 | "control" means (i) the power, direct or indirect, to cause the 19 | direction or management of such entity, whether by contract or 20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 21 | outstanding shares, or (iii) beneficial ownership of such entity. 22 | 23 | "You" (or "Your") shall mean an individual or Legal Entity 24 | exercising permissions granted by this License. 25 | 26 | "Source" form shall mean the preferred form for making modifications, 27 | including but not limited to software source code, documentation 28 | source, and configuration files. 29 | 30 | "Object" form shall mean any form resulting from mechanical 31 | transformation or translation of a Source form, including but 32 | not limited to compiled object code, generated documentation, 33 | and conversions to other media types. 34 | 35 | "Work" shall mean the work of authorship, whether in Source or 36 | Object form, made available under the License, as indicated by a 37 | copyright notice that is included in or attached to the work 38 | (an example is provided in the Appendix below). 39 | 40 | "Derivative Works" shall mean any work, whether in Source or Object 41 | form, that is based on (or derived from) the Work and for which the 42 | editorial revisions, annotations, elaborations, or other modifications 43 | represent, as a whole, an original work of authorship. For the purposes 44 | of this License, Derivative Works shall not include works that remain 45 | separable from, or merely link (or bind by name) to the interfaces of, 46 | the Work and Derivative Works thereof. 47 | 48 | "Contribution" shall mean any work of authorship, including 49 | the original version of the Work and any modifications or additions 50 | to that Work or Derivative Works thereof, that is intentionally 51 | submitted to Licensor for inclusion in the Work by the copyright owner 52 | or by an individual or Legal Entity authorized to submit on behalf of 53 | the copyright owner. For the purposes of this definition, "submitted" 54 | means any form of electronic, verbal, or written communication sent 55 | to the Licensor or its representatives, including but not limited to 56 | communication on electronic mailing lists, source code control systems, 57 | and issue tracking systems that are managed by, or on behalf of, the 58 | Licensor for the purpose of discussing and improving the Work, but 59 | excluding communication that is conspicuously marked or otherwise 60 | designated in writing by the copyright owner as "Not a Contribution." 61 | 62 | "Contributor" shall mean Licensor and any individual or Legal Entity 63 | on behalf of whom a Contribution has been received by Licensor and 64 | subsequently incorporated within the Work. 65 | 66 | 2. Grant of Copyright License. Subject to the terms and conditions of 67 | this License, each Contributor hereby grants to You a perpetual, 68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 69 | copyright license to reproduce, prepare Derivative Works of, 70 | publicly display, publicly perform, sublicense, and distribute the 71 | Work and such Derivative Works in Source or Object form. 72 | 73 | 3. Grant of Patent License. Subject to the terms and conditions of 74 | this License, each Contributor hereby grants to You a perpetual, 75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 76 | (except as stated in this section) patent license to make, have made, 77 | use, offer to sell, sell, import, and otherwise transfer the Work, 78 | where such license applies only to those patent claims licensable 79 | by such Contributor that are necessarily infringed by their 80 | Contribution(s) alone or by combination of their Contribution(s) 81 | with the Work to which such Contribution(s) was submitted. If You 82 | institute patent litigation against any entity (including a 83 | cross-claim or counterclaim in a lawsuit) alleging that the Work 84 | or a Contribution incorporated within the Work constitutes direct 85 | or contributory patent infringement, then any patent licenses 86 | granted to You under this License for that Work shall terminate 87 | as of the date such litigation is filed. 88 | 89 | 4. Redistribution. You may reproduce and distribute copies of the 90 | Work or Derivative Works thereof in any medium, with or without 91 | modifications, and in Source or Object form, provided that You 92 | meet the following conditions: 93 | 94 | (a) You must give any other recipients of the Work or 95 | Derivative Works a copy of this License; and 96 | 97 | (b) You must cause any modified files to carry prominent notices 98 | stating that You changed the files; and 99 | 100 | (c) You must retain, in the Source form of any Derivative Works 101 | that You distribute, all copyright, patent, trademark, and 102 | attribution notices from the Source form of the Work, 103 | excluding those notices that do not pertain to any part of 104 | the Derivative Works; and 105 | 106 | (d) If the Work includes a "NOTICE" text file as part of its 107 | distribution, then any Derivative Works that You distribute must 108 | include a readable copy of the attribution notices contained 109 | within such NOTICE file, excluding those notices that do not 110 | pertain to any part of the Derivative Works, in at least one 111 | of the following places: within a NOTICE text file distributed 112 | as part of the Derivative Works; within the Source form or 113 | documentation, if provided along with the Derivative Works; or, 114 | within a display generated by the Derivative Works, if and 115 | wherever such third-party notices normally appear. The contents 116 | of the NOTICE file are for informational purposes only and 117 | do not modify the License. You may add Your own attribution 118 | notices within Derivative Works that You distribute, alongside 119 | or as an addendum to the NOTICE text from the Work, provided 120 | that such additional attribution notices cannot be construed 121 | as modifying the License. 122 | 123 | You may add Your own copyright statement to Your modifications and 124 | may provide additional or different license terms and conditions 125 | for use, reproduction, or distribution of Your modifications, or 126 | for any such Derivative Works as a whole, provided Your use, 127 | reproduction, and distribution of the Work otherwise complies with 128 | the conditions stated in this License. 129 | 130 | 5. Submission of Contributions. Unless You explicitly state otherwise, 131 | any Contribution intentionally submitted for inclusion in the Work 132 | by You to the Licensor shall be under the terms and conditions of 133 | this License, without any additional terms or conditions. 134 | Notwithstanding the above, nothing herein shall supersede or modify 135 | the terms of any separate license agreement you may have executed 136 | with Licensor regarding such Contributions. 137 | 138 | 6. Trademarks. This License does not grant permission to use the trade 139 | names, trademarks, service marks, or product names of the Licensor, 140 | except as required for reasonable and customary use in describing the 141 | origin of the Work and reproducing the content of the NOTICE file. 142 | 143 | 7. Disclaimer of Warranty. Unless required by applicable law or 144 | agreed to in writing, Licensor provides the Work (and each 145 | Contributor provides its Contributions) on an "AS IS" BASIS, 146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 147 | implied, including, without limitation, any warranties or conditions 148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 149 | PARTICULAR PURPOSE. You are solely responsible for determining the 150 | appropriateness of using or redistributing the Work and assume any 151 | risks associated with Your exercise of permissions under this License. 152 | 153 | 8. Limitation of Liability. In no event and under no legal theory, 154 | whether in tort (including negligence), contract, or otherwise, 155 | unless required by applicable law (such as deliberate and grossly 156 | negligent acts) or agreed to in writing, shall any Contributor be 157 | liable to You for damages, including any direct, indirect, special, 158 | incidental, or consequential damages of any character arising as a 159 | result of this License or out of the use or inability to use the 160 | Work (including but not limited to damages for loss of goodwill, 161 | work stoppage, computer failure or malfunction, or any and all 162 | other commercial damages or losses), even if such Contributor 163 | has been advised of the possibility of such damages. 164 | 165 | 9. Accepting Warranty or Additional Liability. While redistributing 166 | the Work or Derivative Works thereof, You may choose to offer, 167 | and charge a fee for, acceptance of support, warranty, indemnity, 168 | or other liability obligations and/or rights consistent with this 169 | License. However, in accepting such obligations, You may act only 170 | on Your own behalf and on Your sole responsibility, not on behalf 171 | of any other Contributor, and only if You agree to indemnify, 172 | defend, and hold each Contributor harmless for any liability 173 | incurred by, or claims asserted against, such Contributor by reason 174 | of your accepting any such warranty or additional liability. 175 | 176 | END OF TERMS AND CONDITIONS 177 | 178 | APPENDIX: How to apply the Apache License to your work. 179 | 180 | To apply the Apache License to your work, attach the following 181 | boilerplate notice, with the fields enclosed by brackets "{}" 182 | replaced with your own identifying information. (Don't include 183 | the brackets!) The text should be enclosed in the appropriate 184 | comment syntax for the file format. We also recommend that a 185 | file or class name and description of purpose be included on the 186 | same "printed page" as the copyright notice for easier 187 | identification within third-party archives. 188 | 189 | Copyright {yyyy} {name of copyright owner} 190 | 191 | Licensed under the Apache License, Version 2.0 (the "License"); 192 | you may not use this file except in compliance with the License. 193 | You may obtain a copy of the License at 194 | 195 | http://www.apache.org/licenses/LICENSE-2.0 196 | 197 | Unless required by applicable law or agreed to in writing, software 198 | distributed under the License is distributed on an "AS IS" BASIS, 199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 200 | See the License for the specific language governing permissions and 201 | limitations under the License. 202 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | tls 2 | ====== 3 | OpenSSL bindings for Go, compatible with `crypto/tls`,faster and more features. 4 | 5 | ## NOTE 6 | It is in the early stages of development, not stable yet. 7 | -------------------------------------------------------------------------------- /bio.go: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2017. See AUTHORS. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | package tls 16 | 17 | // #include "shim.h" 18 | import "C" 19 | 20 | import ( 21 | "errors" 22 | "io" 23 | "reflect" 24 | "sync" 25 | "unsafe" 26 | ) 27 | 28 | const ( 29 | SSLRecordSize = 16 * 1024 30 | ) 31 | 32 | func nonCopyGoBytes(ptr uintptr, length int) []byte { 33 | var slice []byte 34 | header := (*reflect.SliceHeader)(unsafe.Pointer(&slice)) 35 | header.Cap = length 36 | header.Len = length 37 | header.Data = ptr 38 | return slice 39 | } 40 | 41 | func nonCopyCString(data *C.char, size C.int) []byte { 42 | return nonCopyGoBytes(uintptr(unsafe.Pointer(data)), int(size)) 43 | } 44 | 45 | var writeBioMapping = newMapping() 46 | 47 | type writeBio struct { 48 | data_mtx sync.Mutex 49 | op_mtx sync.Mutex 50 | buf []byte 51 | release_buffers bool 52 | } 53 | 54 | func loadWritePtr(b *C.BIO) *writeBio { 55 | t := token(C.X_BIO_get_data(b)) 56 | return (*writeBio)(writeBioMapping.Get(t)) 57 | } 58 | 59 | func bioClearRetryFlags(b *C.BIO) { 60 | C.X_BIO_clear_flags(b, C.BIO_FLAGS_RWS|C.BIO_FLAGS_SHOULD_RETRY) 61 | } 62 | 63 | func bioSetRetryRead(b *C.BIO) { 64 | C.X_BIO_set_flags(b, C.BIO_FLAGS_READ|C.BIO_FLAGS_SHOULD_RETRY) 65 | } 66 | 67 | //export go_write_bio_write 68 | func go_write_bio_write(b *C.BIO, data *C.char, size C.int) (rc C.int) { 69 | defer func() { 70 | if err := recover(); err != nil { 71 | //logger.Critf("openssl: writeBioWrite panic'd: %v", err) 72 | rc = -1 73 | } 74 | }() 75 | ptr := loadWritePtr(b) 76 | if ptr == nil || data == nil || size < 0 { 77 | return -1 78 | } 79 | ptr.data_mtx.Lock() 80 | defer ptr.data_mtx.Unlock() 81 | bioClearRetryFlags(b) 82 | ptr.buf = append(ptr.buf, nonCopyCString(data, size)...) 83 | return size 84 | } 85 | 86 | //export go_write_bio_ctrl 87 | func go_write_bio_ctrl(b *C.BIO, cmd C.int, arg1 C.long, arg2 unsafe.Pointer) ( 88 | rc C.long) { 89 | defer func() { 90 | if err := recover(); err != nil { 91 | //logger.Critf("openssl: writeBioCtrl panic'd: %v", err) 92 | rc = -1 93 | } 94 | }() 95 | switch cmd { 96 | case C.BIO_CTRL_WPENDING: 97 | return writeBioPending(b) 98 | case C.BIO_CTRL_DUP, C.BIO_CTRL_FLUSH: 99 | return 1 100 | default: 101 | return 0 102 | } 103 | } 104 | 105 | func writeBioPending(b *C.BIO) C.long { 106 | ptr := loadWritePtr(b) 107 | if ptr == nil { 108 | return 0 109 | } 110 | ptr.data_mtx.Lock() 111 | defer ptr.data_mtx.Unlock() 112 | return C.long(len(ptr.buf)) 113 | } 114 | 115 | func (b *writeBio) WriteTo(w io.Writer) (rv int64, err error) { 116 | b.op_mtx.Lock() 117 | defer b.op_mtx.Unlock() 118 | 119 | // write whatever data we currently have 120 | b.data_mtx.Lock() 121 | data := b.buf 122 | b.data_mtx.Unlock() 123 | 124 | if len(data) == 0 { 125 | return 0, nil 126 | } 127 | n, err := w.Write(data) 128 | 129 | // subtract however much data we wrote from the buffer 130 | b.data_mtx.Lock() 131 | b.buf = b.buf[:copy(b.buf, b.buf[n:])] 132 | if b.release_buffers && len(b.buf) == 0 { 133 | b.buf = nil 134 | } 135 | b.data_mtx.Unlock() 136 | 137 | return int64(n), err 138 | } 139 | 140 | func (self *writeBio) Disconnect(b *C.BIO) { 141 | if loadWritePtr(b) == self { 142 | writeBioMapping.Del(token(C.X_BIO_get_data(b))) 143 | C.X_BIO_set_data(b, nil) 144 | } 145 | } 146 | 147 | func (b *writeBio) MakeCBIO() *C.BIO { 148 | rv := C.X_BIO_new_write_bio() 149 | token := writeBioMapping.Add(unsafe.Pointer(b)) 150 | C.X_BIO_set_data(rv, unsafe.Pointer(token)) 151 | return rv 152 | } 153 | 154 | var readBioMapping = newMapping() 155 | 156 | type readBio struct { 157 | data_mtx sync.Mutex 158 | op_mtx sync.Mutex 159 | buf []byte 160 | eof bool 161 | release_buffers bool 162 | } 163 | 164 | func loadReadPtr(b *C.BIO) *readBio { 165 | return (*readBio)(readBioMapping.Get(token(C.X_BIO_get_data(b)))) 166 | } 167 | 168 | //export go_read_bio_read 169 | func go_read_bio_read(b *C.BIO, data *C.char, size C.int) (rc C.int) { 170 | defer func() { 171 | if err := recover(); err != nil { 172 | //logger.Critf("openssl: go_read_bio_read panic'd: %v", err) 173 | rc = -1 174 | } 175 | }() 176 | ptr := loadReadPtr(b) 177 | if ptr == nil || size < 0 { 178 | return -1 179 | } 180 | ptr.data_mtx.Lock() 181 | defer ptr.data_mtx.Unlock() 182 | bioClearRetryFlags(b) 183 | if len(ptr.buf) == 0 { 184 | if ptr.eof { 185 | return 0 186 | } 187 | bioSetRetryRead(b) 188 | return -1 189 | } 190 | if size == 0 || data == nil { 191 | return C.int(len(ptr.buf)) 192 | } 193 | n := copy(nonCopyCString(data, size), ptr.buf) 194 | ptr.buf = ptr.buf[:copy(ptr.buf, ptr.buf[n:])] 195 | if ptr.release_buffers && len(ptr.buf) == 0 { 196 | ptr.buf = nil 197 | } 198 | return C.int(n) 199 | } 200 | 201 | //export go_read_bio_ctrl 202 | func go_read_bio_ctrl(b *C.BIO, cmd C.int, arg1 C.long, arg2 unsafe.Pointer) ( 203 | rc C.long) { 204 | 205 | defer func() { 206 | if err := recover(); err != nil { 207 | //logger.Critf("openssl: readBioCtrl panic'd: %v", err) 208 | rc = -1 209 | } 210 | }() 211 | switch cmd { 212 | case C.BIO_CTRL_PENDING: 213 | return readBioPending(b) 214 | case C.BIO_CTRL_DUP, C.BIO_CTRL_FLUSH: 215 | return 1 216 | default: 217 | return 0 218 | } 219 | } 220 | 221 | func readBioPending(b *C.BIO) C.long { 222 | ptr := loadReadPtr(b) 223 | if ptr == nil { 224 | return 0 225 | } 226 | ptr.data_mtx.Lock() 227 | defer ptr.data_mtx.Unlock() 228 | return C.long(len(ptr.buf)) 229 | } 230 | 231 | func (b *readBio) ReadFromOnce(r io.Reader) (n int, err error) { 232 | b.op_mtx.Lock() 233 | defer b.op_mtx.Unlock() 234 | 235 | // make sure we have a destination that fits at least one SSL record 236 | b.data_mtx.Lock() 237 | if cap(b.buf) < len(b.buf)+SSLRecordSize { 238 | new_buf := make([]byte, len(b.buf), len(b.buf)+SSLRecordSize) 239 | copy(new_buf, b.buf) 240 | b.buf = new_buf 241 | } 242 | dst := b.buf[len(b.buf):cap(b.buf)] 243 | dst_slice := b.buf 244 | b.data_mtx.Unlock() 245 | 246 | n, err = r.Read(dst) 247 | b.data_mtx.Lock() 248 | defer b.data_mtx.Unlock() 249 | if n > 0 { 250 | if len(dst_slice) != len(b.buf) { 251 | // someone shrunk the buffer, so we read in too far ahead and we 252 | // need to slide backwards 253 | copy(b.buf[len(b.buf):len(b.buf)+n], dst) 254 | } 255 | b.buf = b.buf[:len(b.buf)+n] 256 | } 257 | return n, err 258 | } 259 | 260 | func (b *readBio) MakeCBIO() *C.BIO { 261 | rv := C.X_BIO_new_read_bio() 262 | token := readBioMapping.Add(unsafe.Pointer(b)) 263 | C.X_BIO_set_data(rv, unsafe.Pointer(token)) 264 | return rv 265 | } 266 | 267 | func (self *readBio) Disconnect(b *C.BIO) { 268 | if loadReadPtr(b) == self { 269 | readBioMapping.Del(token(C.X_BIO_get_data(b))) 270 | C.X_BIO_set_data(b, nil) 271 | } 272 | } 273 | 274 | func (b *readBio) MarkEOF() { 275 | b.data_mtx.Lock() 276 | defer b.data_mtx.Unlock() 277 | b.eof = true 278 | } 279 | 280 | type anyBio C.BIO 281 | 282 | func asAnyBio(b *C.BIO) *anyBio { return (*anyBio)(b) } 283 | 284 | func (b *anyBio) Read(buf []byte) (n int, err error) { 285 | if len(buf) == 0 { 286 | return 0, nil 287 | } 288 | n = int(C.X_BIO_read((*C.BIO)(b), unsafe.Pointer(&buf[0]), C.int(len(buf)))) 289 | if n <= 0 { 290 | return 0, io.EOF 291 | } 292 | return n, nil 293 | } 294 | 295 | func (b *anyBio) Write(buf []byte) (written int, err error) { 296 | if len(buf) == 0 { 297 | return 0, nil 298 | } 299 | n := int(C.X_BIO_write((*C.BIO)(b), unsafe.Pointer(&buf[0]), 300 | C.int(len(buf)))) 301 | if n != len(buf) { 302 | return n, errors.New("BIO write failed") 303 | } 304 | return n, nil 305 | } 306 | -------------------------------------------------------------------------------- /build.go: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2017. See AUTHORS. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | package tls 16 | 17 | // #cgo pkg-config: libssl libcrypto 18 | // #cgo linux CFLAGS: -Wno-deprecated-declarations 19 | // #cgo darwin CFLAGS: -I/usr/local/opt/openssl@1.1/include -I/usr/local/opt/openssl/include -Wno-deprecated-declarations 20 | // #cgo darwin LDFLAGS: -w -L/usr/local/opt/openssl@1.1/lib -L/usr/local/opt/openssl/lib 21 | // #cgo windows CFLAGS: -DWIN32_LEAN_AND_MEAN 22 | import "C" 23 | -------------------------------------------------------------------------------- /common.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 file. 4 | 5 | package tls 6 | 7 | import ( 8 | "container/list" 9 | "crypto" 10 | "crypto/rand" 11 | "crypto/sha512" 12 | "crypto/x509" 13 | "errors" 14 | "fmt" 15 | "io" 16 | "math/big" 17 | "net" 18 | "strings" 19 | "sync" 20 | "time" 21 | ) 22 | 23 | const ( 24 | VersionSSL30 = 0x0300 25 | VersionTLS10 = 0x0301 26 | VersionTLS11 = 0x0302 27 | VersionTLS12 = 0x0303 28 | ) 29 | 30 | const ( 31 | maxPlaintext = 16384 // maximum plaintext payload length 32 | maxCiphertext = 16384 + 2048 // maximum ciphertext payload length 33 | recordHeaderLen = 5 // record header length 34 | maxHandshake = 65536 // maximum handshake we support (protocol max is 16 MB) 35 | 36 | minVersion = VersionTLS10 37 | maxVersion = VersionTLS12 38 | ) 39 | 40 | // TLS record types. 41 | type recordType uint8 42 | 43 | const ( 44 | recordTypeChangeCipherSpec recordType = 20 45 | recordTypeAlert recordType = 21 46 | recordTypeHandshake recordType = 22 47 | recordTypeApplicationData recordType = 23 48 | ) 49 | 50 | // TLS handshake message types. 51 | const ( 52 | typeHelloRequest uint8 = 0 53 | typeClientHello uint8 = 1 54 | typeServerHello uint8 = 2 55 | typeNewSessionTicket uint8 = 4 56 | typeCertificate uint8 = 11 57 | typeServerKeyExchange uint8 = 12 58 | typeCertificateRequest uint8 = 13 59 | typeServerHelloDone uint8 = 14 60 | typeCertificateVerify uint8 = 15 61 | typeClientKeyExchange uint8 = 16 62 | typeFinished uint8 = 20 63 | typeCertificateStatus uint8 = 22 64 | typeNextProtocol uint8 = 67 // Not IANA assigned 65 | ) 66 | 67 | // TLS compression types. 68 | const ( 69 | compressionNone uint8 = 0 70 | ) 71 | 72 | // TLS extension numbers 73 | const ( 74 | extensionServerName uint16 = 0 75 | extensionStatusRequest uint16 = 5 76 | extensionSupportedCurves uint16 = 10 77 | extensionSupportedPoints uint16 = 11 78 | extensionSignatureAlgorithms uint16 = 13 79 | extensionALPN uint16 = 16 80 | extensionSCT uint16 = 18 // https://tools.ietf.org/html/rfc6962#section-6 81 | extensionSessionTicket uint16 = 35 82 | extensionNextProtoNeg uint16 = 13172 // not IANA assigned 83 | extensionRenegotiationInfo uint16 = 0xff01 84 | ) 85 | 86 | // TLS signaling cipher suite values 87 | const ( 88 | scsvRenegotiation uint16 = 0x00ff 89 | ) 90 | 91 | // CurveID is the type of a TLS identifier for an elliptic curve. See 92 | // http://www.iana.org/assignments/tls-parameters/tls-parameters.xml#tls-parameters-8 93 | type CurveID uint16 94 | 95 | const ( 96 | CurveP256 CurveID = 23 97 | CurveP384 CurveID = 24 98 | CurveP521 CurveID = 25 99 | X25519 CurveID = 29 100 | ) 101 | 102 | // TLS Elliptic Curve Point Formats 103 | // http://www.iana.org/assignments/tls-parameters/tls-parameters.xml#tls-parameters-9 104 | const ( 105 | pointFormatUncompressed uint8 = 0 106 | ) 107 | 108 | // TLS CertificateStatusType (RFC 3546) 109 | const ( 110 | statusTypeOCSP uint8 = 1 111 | ) 112 | 113 | // Certificate types (for certificateRequestMsg) 114 | const ( 115 | certTypeRSASign = 1 // A certificate containing an RSA key 116 | certTypeDSSSign = 2 // A certificate containing a DSA key 117 | certTypeRSAFixedDH = 3 // A certificate containing a static DH key 118 | certTypeDSSFixedDH = 4 // A certificate containing a static DH key 119 | 120 | // See RFC 4492 sections 3 and 5.5. 121 | certTypeECDSASign = 64 // A certificate containing an ECDSA-capable public key, signed with ECDSA. 122 | certTypeRSAFixedECDH = 65 // A certificate containing an ECDH-capable public key, signed with RSA. 123 | certTypeECDSAFixedECDH = 66 // A certificate containing an ECDH-capable public key, signed with ECDSA. 124 | 125 | // Rest of these are reserved by the TLS spec 126 | ) 127 | 128 | // Hash functions for TLS 1.2 (See RFC 5246, section A.4.1) 129 | const ( 130 | hashSHA1 uint8 = 2 131 | hashSHA256 uint8 = 4 132 | hashSHA384 uint8 = 5 133 | ) 134 | 135 | // Signature algorithms for TLS 1.2 (See RFC 5246, section A.4.1) 136 | const ( 137 | signatureRSA uint8 = 1 138 | signatureECDSA uint8 = 3 139 | ) 140 | 141 | // signatureAndHash mirrors the TLS 1.2, SignatureAndHashAlgorithm struct. See 142 | // RFC 5246, section A.4.1. 143 | type signatureAndHash struct { 144 | hash, signature uint8 145 | } 146 | 147 | // supportedSignatureAlgorithms contains the signature and hash algorithms that 148 | // the code advertises as supported in a TLS 1.2 ClientHello and in a TLS 1.2 149 | // CertificateRequest. 150 | var supportedSignatureAlgorithms = []signatureAndHash{ 151 | {hashSHA256, signatureRSA}, 152 | {hashSHA256, signatureECDSA}, 153 | {hashSHA384, signatureRSA}, 154 | {hashSHA384, signatureECDSA}, 155 | {hashSHA1, signatureRSA}, 156 | {hashSHA1, signatureECDSA}, 157 | } 158 | 159 | // ConnectionState records basic TLS details about the connection. 160 | type ConnectionState struct { 161 | Version uint16 // TLS version used by the connection (e.g. VersionTLS12) 162 | HandshakeComplete bool // TLS handshake is complete 163 | DidResume bool // connection resumes a previous TLS connection 164 | CipherSuite uint16 // cipher suite in use (TLS_RSA_WITH_RC4_128_SHA, ...) 165 | NegotiatedProtocol string // negotiated next protocol (from Config.NextProtos) 166 | NegotiatedProtocolIsMutual bool // negotiated protocol was advertised by server 167 | ServerName string // server name requested by client, if any (server side only) 168 | PeerCertificates []*x509.Certificate // certificate chain presented by remote peer 169 | VerifiedChains [][]*x509.Certificate // verified chains built from PeerCertificates 170 | SignedCertificateTimestamps [][]byte // SCTs from the server, if any 171 | OCSPResponse []byte // stapled OCSP response from server, if any 172 | 173 | // TLSUnique contains the "tls-unique" channel binding value (see RFC 174 | // 5929, section 3). For resumed sessions this value will be nil 175 | // because resumption does not include enough context (see 176 | // https://secure-resumption.com/#channelbindings). This will change in 177 | // future versions of Go once the TLS master-secret fix has been 178 | // standardized and implemented. 179 | TLSUnique []byte 180 | } 181 | 182 | // ClientAuthType declares the policy the server will follow for 183 | // TLS Client Authentication. 184 | type ClientAuthType int 185 | 186 | const ( 187 | NoClientCert ClientAuthType = iota 188 | RequestClientCert 189 | RequireAnyClientCert 190 | VerifyClientCertIfGiven 191 | RequireAndVerifyClientCert 192 | ) 193 | 194 | // ClientSessionState contains the state needed by clients to resume TLS 195 | // sessions. 196 | type ClientSessionState struct { 197 | sessionTicket []uint8 // Encrypted ticket used for session resumption with server 198 | vers uint16 // SSL/TLS version negotiated for the session 199 | cipherSuite uint16 // Ciphersuite negotiated for the session 200 | masterSecret []byte // MasterSecret generated by client on a full handshake 201 | serverCertificates []*x509.Certificate // Certificate chain presented by the server 202 | verifiedChains [][]*x509.Certificate // Certificate chains we built for verification 203 | } 204 | 205 | // ClientSessionCache is a cache of ClientSessionState objects that can be used 206 | // by a client to resume a TLS session with a given server. ClientSessionCache 207 | // implementations should expect to be called concurrently from different 208 | // goroutines. 209 | type ClientSessionCache interface { 210 | // Get searches for a ClientSessionState associated with the given key. 211 | // On return, ok is true if one was found. 212 | Get(sessionKey string) (session *ClientSessionState, ok bool) 213 | 214 | // Put adds the ClientSessionState to the cache with the given key. 215 | Put(sessionKey string, cs *ClientSessionState) 216 | } 217 | 218 | // SignatureScheme identifies a signature algorithm supported by TLS. See 219 | // https://tools.ietf.org/html/draft-ietf-tls-tls13-18#section-4.2.3. 220 | type SignatureScheme uint16 221 | 222 | const ( 223 | PKCS1WithSHA1 SignatureScheme = 0x0201 224 | PKCS1WithSHA256 SignatureScheme = 0x0401 225 | PKCS1WithSHA384 SignatureScheme = 0x0501 226 | PKCS1WithSHA512 SignatureScheme = 0x0601 227 | 228 | PSSWithSHA256 SignatureScheme = 0x0804 229 | PSSWithSHA384 SignatureScheme = 0x0805 230 | PSSWithSHA512 SignatureScheme = 0x0806 231 | 232 | ECDSAWithP256AndSHA256 SignatureScheme = 0x0403 233 | ECDSAWithP384AndSHA384 SignatureScheme = 0x0503 234 | ECDSAWithP521AndSHA512 SignatureScheme = 0x0603 235 | ) 236 | 237 | // ClientHelloInfo contains information from a ClientHello message in order to 238 | // guide certificate selection in the GetCertificate callback. 239 | type ClientHelloInfo struct { 240 | // CipherSuites lists the CipherSuites supported by the client (e.g. 241 | // TLS_RSA_WITH_RC4_128_SHA). 242 | CipherSuites []uint16 243 | 244 | // ServerName indicates the name of the server requested by the client 245 | // in order to support virtual hosting. ServerName is only set if the 246 | // client is using SNI (see 247 | // http://tools.ietf.org/html/rfc4366#section-3.1). 248 | ServerName string 249 | 250 | // SupportedCurves lists the elliptic curves supported by the client. 251 | // SupportedCurves is set only if the Supported Elliptic Curves 252 | // Extension is being used (see 253 | // http://tools.ietf.org/html/rfc4492#section-5.1.1). 254 | SupportedCurves []CurveID 255 | 256 | // SupportedPoints lists the point formats supported by the client. 257 | // SupportedPoints is set only if the Supported Point Formats Extension 258 | // is being used (see 259 | // http://tools.ietf.org/html/rfc4492#section-5.1.2). 260 | SupportedPoints []uint8 261 | 262 | // SignatureSchemes lists the signature and hash schemes that the client 263 | // is willing to verify. SignatureSchemes is set only if the Signature 264 | // Algorithms Extension is being used (see 265 | // https://tools.ietf.org/html/rfc5246#section-7.4.1.4.1). 266 | SignatureSchemes []SignatureScheme 267 | 268 | // SupportedProtos lists the application protocols supported by the client. 269 | // SupportedProtos is set only if the Application-Layer Protocol 270 | // Negotiation Extension is being used (see 271 | // https://tools.ietf.org/html/rfc7301#section-3.1). 272 | // 273 | // Servers can select a protocol by setting Config.NextProtos in a 274 | // GetConfigForClient return value. 275 | SupportedProtos []string 276 | 277 | // SupportedVersions lists the TLS versions supported by the client. 278 | // For TLS versions less than 1.3, this is extrapolated from the max 279 | // version advertised by the client, so values other than the greatest 280 | // might be rejected if used. 281 | SupportedVersions []uint16 282 | 283 | // Conn is the underlying net.Conn for the connection. Do not read 284 | // from, or write to, this connection; that will cause the TLS 285 | // connection to fail. 286 | Conn net.Conn 287 | } 288 | 289 | // CertificateRequestInfo contains information from a server's 290 | // CertificateRequest message, which is used to demand a certificate and proof 291 | // of control from a client. 292 | type CertificateRequestInfo struct { 293 | // AcceptableCAs contains zero or more, DER-encoded, X.501 294 | // Distinguished Names. These are the names of root or intermediate CAs 295 | // that the server wishes the returned certificate to be signed by. An 296 | // empty slice indicates that the server has no preference. 297 | AcceptableCAs [][]byte 298 | 299 | // SignatureSchemes lists the signature schemes that the server is 300 | // willing to verify. 301 | SignatureSchemes []SignatureScheme 302 | } 303 | 304 | // RenegotiationSupport enumerates the different levels of support for TLS 305 | // renegotiation. TLS renegotiation is the act of performing subsequent 306 | // handshakes on a connection after the first. This significantly complicates 307 | // the state machine and has been the source of numerous, subtle security 308 | // issues. Initiating a renegotiation is not supported, but support for 309 | // accepting renegotiation requests may be enabled. 310 | // 311 | // Even when enabled, the server may not change its identity between handshakes 312 | // (i.e. the leaf certificate must be the same). Additionally, concurrent 313 | // handshake and application data flow is not permitted so renegotiation can 314 | // only be used with protocols that synchronise with the renegotiation, such as 315 | // HTTPS. 316 | type RenegotiationSupport int 317 | 318 | const ( 319 | // RenegotiateNever disables renegotiation. 320 | RenegotiateNever RenegotiationSupport = iota 321 | 322 | // RenegotiateOnceAsClient allows a remote server to request 323 | // renegotiation once per connection. 324 | RenegotiateOnceAsClient 325 | 326 | // RenegotiateFreelyAsClient allows a remote server to repeatedly 327 | // request renegotiation. 328 | RenegotiateFreelyAsClient 329 | ) 330 | 331 | // A Config structure is used to configure a TLS client or server. 332 | // After one has been passed to a TLS function it must not be 333 | // modified. A Config may be reused; the tls package will also not 334 | // modify it. 335 | type Config struct { 336 | // Rand provides the source of entropy for nonces and RSA blinding. 337 | // If Rand is nil, TLS uses the cryptographic random reader in package 338 | // crypto/rand. 339 | // The Reader must be safe for use by multiple goroutines. 340 | Rand io.Reader 341 | 342 | // Time returns the current time as the number of seconds since the epoch. 343 | // If Time is nil, TLS uses time.Now. 344 | Time func() time.Time 345 | 346 | // Certificates contains one or more certificate chains to present to 347 | // the other side of the connection. Server configurations must include 348 | // at least one certificate or else set GetCertificate. Clients doing 349 | // client-authentication may set either Certificates or 350 | // GetClientCertificate. 351 | Certificates []Certificate 352 | 353 | // NameToCertificate maps from a certificate name to an element of 354 | // Certificates. Note that a certificate name can be of the form 355 | // '*.example.com' and so doesn't have to be a domain name as such. 356 | // See Config.BuildNameToCertificate 357 | // The nil value causes the first element of Certificates to be used 358 | // for all connections. 359 | NameToCertificate map[string]*Certificate 360 | 361 | // GetCertificate returns a Certificate based on the given 362 | // ClientHelloInfo. It will only be called if the client supplies SNI 363 | // information or if Certificates is empty. 364 | // 365 | // If GetCertificate is nil or returns nil, then the certificate is 366 | // retrieved from NameToCertificate. If NameToCertificate is nil, the 367 | // first element of Certificates will be used. 368 | GetCertificate func(*ClientHelloInfo) (*Certificate, error) 369 | 370 | // GetClientCertificate, if not nil, is called when a server requests a 371 | // certificate from a client. If set, the contents of Certificates will 372 | // be ignored. 373 | // 374 | // If GetClientCertificate returns an error, the handshake will be 375 | // aborted and that error will be returned. Otherwise 376 | // GetClientCertificate must return a non-nil Certificate. If 377 | // Certificate.Certificate is empty then no certificate will be sent to 378 | // the server. If this is unacceptable to the server then it may abort 379 | // the handshake. 380 | // 381 | // GetClientCertificate may be called multiple times for the same 382 | // connection if renegotiation occurs or if TLS 1.3 is in use. 383 | GetClientCertificate func(*CertificateRequestInfo) (*Certificate, error) 384 | 385 | // GetConfigForClient, if not nil, is called after a ClientHello is 386 | // received from a client. It may return a non-nil Config in order to 387 | // change the Config that will be used to handle this connection. If 388 | // the returned Config is nil, the original Config will be used. The 389 | // Config returned by this callback may not be subsequently modified. 390 | // 391 | // If GetConfigForClient is nil, the Config passed to Server() will be 392 | // used for all connections. 393 | // 394 | // Uniquely for the fields in the returned Config, session ticket keys 395 | // will be duplicated from the original Config if not set. 396 | // Specifically, if SetSessionTicketKeys was called on the original 397 | // config but not on the returned config then the ticket keys from the 398 | // original config will be copied into the new config before use. 399 | // Otherwise, if SessionTicketKey was set in the original config but 400 | // not in the returned config then it will be copied into the returned 401 | // config before use. If neither of those cases applies then the key 402 | // material from the returned config will be used for session tickets. 403 | GetConfigForClient func(*ClientHelloInfo) (*Config, error) 404 | 405 | // VerifyPeerCertificate, if not nil, is called after normal 406 | // certificate verification by either a TLS client or server. It 407 | // receives the raw ASN.1 certificates provided by the peer and also 408 | // any verified chains that normal processing found. If it returns a 409 | // non-nil error, the handshake is aborted and that error results. 410 | // 411 | // If normal verification fails then the handshake will abort before 412 | // considering this callback. If normal verification is disabled by 413 | // setting InsecureSkipVerify then this callback will be considered but 414 | // the verifiedChains argument will always be nil. 415 | VerifyPeerCertificate func(rawCerts [][]byte, verifiedChains [][]*x509.Certificate) error 416 | 417 | // RootCAs defines the set of root certificate authorities 418 | // that clients use when verifying server certificates. 419 | // If RootCAs is nil, TLS uses the host's root CA set. 420 | RootCAs *x509.CertPool 421 | 422 | // NextProtos is a list of supported, application level protocols. 423 | NextProtos []string 424 | 425 | // ServerName is used to verify the hostname on the returned 426 | // certificates unless InsecureSkipVerify is given. It is also included 427 | // in the client's handshake to support virtual hosting unless it is 428 | // an IP address. 429 | ServerName string 430 | 431 | // ClientAuth determines the server's policy for 432 | // TLS Client Authentication. The default is NoClientCert. 433 | ClientAuth ClientAuthType 434 | 435 | // ClientCAs defines the set of root certificate authorities 436 | // that servers use if required to verify a client certificate 437 | // by the policy in ClientAuth. 438 | ClientCAs *x509.CertPool 439 | 440 | // InsecureSkipVerify controls whether a client verifies the 441 | // server's certificate chain and host name. 442 | // If InsecureSkipVerify is true, TLS accepts any certificate 443 | // presented by the server and any host name in that certificate. 444 | // In this mode, TLS is susceptible to man-in-the-middle attacks. 445 | // This should be used only for testing. 446 | InsecureSkipVerify bool 447 | 448 | // CipherSuites is a list of supported cipher suites. If CipherSuites 449 | // is nil, TLS uses a list of suites supported by the implementation. 450 | CipherSuites []uint16 451 | 452 | // PreferServerCipherSuites controls whether the server selects the 453 | // client's most preferred ciphersuite, or the server's most preferred 454 | // ciphersuite. If true then the server's preference, as expressed in 455 | // the order of elements in CipherSuites, is used. 456 | PreferServerCipherSuites bool 457 | 458 | // SessionTicketsDisabled may be set to true to disable session ticket 459 | // (resumption) support. 460 | SessionTicketsDisabled bool 461 | 462 | // SessionTicketKey is used by TLS servers to provide session 463 | // resumption. See RFC 5077. If zero, it will be filled with 464 | // random data before the first server handshake. 465 | // 466 | // If multiple servers are terminating connections for the same host 467 | // they should all have the same SessionTicketKey. If the 468 | // SessionTicketKey leaks, previously recorded and future TLS 469 | // connections using that key are compromised. 470 | SessionTicketKey [32]byte 471 | 472 | // SessionCache is a cache of ClientSessionState entries for TLS session 473 | // resumption. 474 | ClientSessionCache ClientSessionCache 475 | 476 | // MinVersion contains the minimum SSL/TLS version that is acceptable. 477 | // If zero, then TLS 1.0 is taken as the minimum. 478 | MinVersion uint16 479 | 480 | // MaxVersion contains the maximum SSL/TLS version that is acceptable. 481 | // If zero, then the maximum version supported by this package is used, 482 | // which is currently TLS 1.2. 483 | MaxVersion uint16 484 | 485 | // CurvePreferences contains the elliptic curves that will be used in 486 | // an ECDHE handshake, in preference order. If empty, the default will 487 | // be used. 488 | CurvePreferences []CurveID 489 | 490 | // DynamicRecordSizingDisabled disables adaptive sizing of TLS records. 491 | // When true, the largest possible TLS record size is always used. When 492 | // false, the size of TLS records may be adjusted in an attempt to 493 | // improve latency. 494 | DynamicRecordSizingDisabled bool 495 | 496 | // Renegotiation controls what types of renegotiation are supported. 497 | // The default, none, is correct for the vast majority of applications. 498 | Renegotiation RenegotiationSupport 499 | 500 | // KeyLogWriter optionally specifies a destination for TLS master secrets 501 | // in NSS key log format that can be used to allow external programs 502 | // such as Wireshark to decrypt TLS connections. 503 | // See https://developer.mozilla.org/en-US/docs/Mozilla/Projects/NSS/Key_Log_Format. 504 | // Use of KeyLogWriter compromises security and should only be 505 | // used for debugging. 506 | KeyLogWriter io.Writer 507 | 508 | serverInitOnce sync.Once // guards calling (*Config).serverInit 509 | 510 | // mutex protects sessionTicketKeys and originalConfig. 511 | mutex sync.RWMutex 512 | // sessionTicketKeys contains zero or more ticket keys. If the length 513 | // is zero, SessionTicketsDisabled must be true. The first key is used 514 | // for new tickets and any subsequent keys can be used to decrypt old 515 | // tickets. 516 | sessionTicketKeys []ticketKey 517 | // originalConfig is set to the Config that was passed to Server if 518 | // this Config is returned by a GetConfigForClient callback. It's used 519 | // by serverInit in order to copy session ticket keys if needed. 520 | originalConfig *Config 521 | } 522 | 523 | // ticketKeyNameLen is the number of bytes of identifier that is prepended to 524 | // an encrypted session ticket in order to identify the key used to encrypt it. 525 | const ticketKeyNameLen = 16 526 | 527 | // ticketKey is the internal representation of a session ticket key. 528 | type ticketKey struct { 529 | // keyName is an opaque byte string that serves to identify the session 530 | // ticket key. It's exposed as plaintext in every session ticket. 531 | keyName [ticketKeyNameLen]byte 532 | aesKey [16]byte 533 | hmacKey [16]byte 534 | } 535 | 536 | // ticketKeyFromBytes converts from the external representation of a session 537 | // ticket key to a ticketKey. Externally, session ticket keys are 32 random 538 | // bytes and this function expands that into sufficient name and key material. 539 | func ticketKeyFromBytes(b [32]byte) (key ticketKey) { 540 | hashed := sha512.Sum512(b[:]) 541 | copy(key.keyName[:], hashed[:ticketKeyNameLen]) 542 | copy(key.aesKey[:], hashed[ticketKeyNameLen:ticketKeyNameLen+16]) 543 | copy(key.hmacKey[:], hashed[ticketKeyNameLen+16:ticketKeyNameLen+32]) 544 | return key 545 | } 546 | 547 | // Clone returns a shallow clone of c. It is safe to clone a Config that is 548 | // being used concurrently by a TLS client or server. 549 | func (c *Config) Clone() *Config { 550 | // Running serverInit ensures that it's safe to read 551 | // SessionTicketsDisabled. 552 | c.serverInitOnce.Do(c.serverInit) 553 | 554 | var sessionTicketKeys []ticketKey 555 | c.mutex.RLock() 556 | sessionTicketKeys = c.sessionTicketKeys 557 | c.mutex.RUnlock() 558 | 559 | return &Config{ 560 | Rand: c.Rand, 561 | Time: c.Time, 562 | Certificates: c.Certificates, 563 | NameToCertificate: c.NameToCertificate, 564 | GetCertificate: c.GetCertificate, 565 | GetClientCertificate: c.GetClientCertificate, 566 | GetConfigForClient: c.GetConfigForClient, 567 | VerifyPeerCertificate: c.VerifyPeerCertificate, 568 | RootCAs: c.RootCAs, 569 | NextProtos: c.NextProtos, 570 | ServerName: c.ServerName, 571 | ClientAuth: c.ClientAuth, 572 | ClientCAs: c.ClientCAs, 573 | InsecureSkipVerify: c.InsecureSkipVerify, 574 | CipherSuites: c.CipherSuites, 575 | PreferServerCipherSuites: c.PreferServerCipherSuites, 576 | SessionTicketsDisabled: c.SessionTicketsDisabled, 577 | SessionTicketKey: c.SessionTicketKey, 578 | ClientSessionCache: c.ClientSessionCache, 579 | MinVersion: c.MinVersion, 580 | MaxVersion: c.MaxVersion, 581 | CurvePreferences: c.CurvePreferences, 582 | DynamicRecordSizingDisabled: c.DynamicRecordSizingDisabled, 583 | Renegotiation: c.Renegotiation, 584 | KeyLogWriter: c.KeyLogWriter, 585 | sessionTicketKeys: sessionTicketKeys, 586 | // originalConfig is deliberately not duplicated. 587 | } 588 | } 589 | 590 | func (c *Config) serverInit() { 591 | if c.SessionTicketsDisabled || len(c.ticketKeys()) != 0 { 592 | return 593 | } 594 | 595 | var originalConfig *Config 596 | c.mutex.Lock() 597 | originalConfig, c.originalConfig = c.originalConfig, nil 598 | c.mutex.Unlock() 599 | 600 | alreadySet := false 601 | for _, b := range c.SessionTicketKey { 602 | if b != 0 { 603 | alreadySet = true 604 | break 605 | } 606 | } 607 | 608 | if !alreadySet { 609 | if originalConfig != nil { 610 | copy(c.SessionTicketKey[:], originalConfig.SessionTicketKey[:]) 611 | } else if _, err := io.ReadFull(c.rand(), c.SessionTicketKey[:]); err != nil { 612 | c.SessionTicketsDisabled = true 613 | return 614 | } 615 | } 616 | 617 | if originalConfig != nil { 618 | originalConfig.mutex.RLock() 619 | c.sessionTicketKeys = originalConfig.sessionTicketKeys 620 | originalConfig.mutex.RUnlock() 621 | } else { 622 | c.sessionTicketKeys = []ticketKey{ticketKeyFromBytes(c.SessionTicketKey)} 623 | } 624 | } 625 | 626 | func (c *Config) ticketKeys() []ticketKey { 627 | c.mutex.RLock() 628 | // c.sessionTicketKeys is constant once created. SetSessionTicketKeys 629 | // will only update it by replacing it with a new value. 630 | ret := c.sessionTicketKeys 631 | c.mutex.RUnlock() 632 | return ret 633 | } 634 | 635 | // SetSessionTicketKeys updates the session ticket keys for a server. The first 636 | // key will be used when creating new tickets, while all keys can be used for 637 | // decrypting tickets. It is safe to call this function while the server is 638 | // running in order to rotate the session ticket keys. The function will panic 639 | // if keys is empty. 640 | func (c *Config) SetSessionTicketKeys(keys [][32]byte) { 641 | if len(keys) == 0 { 642 | panic("tls: keys must have at least one key") 643 | } 644 | 645 | newKeys := make([]ticketKey, len(keys)) 646 | for i, bytes := range keys { 647 | newKeys[i] = ticketKeyFromBytes(bytes) 648 | } 649 | 650 | c.mutex.Lock() 651 | c.sessionTicketKeys = newKeys 652 | c.mutex.Unlock() 653 | } 654 | 655 | func (c *Config) rand() io.Reader { 656 | r := c.Rand 657 | if r == nil { 658 | return rand.Reader 659 | } 660 | return r 661 | } 662 | 663 | func (c *Config) time() time.Time { 664 | t := c.Time 665 | if t == nil { 666 | t = time.Now 667 | } 668 | return t() 669 | } 670 | 671 | func (c *Config) minVersion() uint16 { 672 | if c == nil || c.MinVersion == 0 { 673 | return minVersion 674 | } 675 | return c.MinVersion 676 | } 677 | 678 | func (c *Config) maxVersion() uint16 { 679 | if c == nil || c.MaxVersion == 0 { 680 | return maxVersion 681 | } 682 | return c.MaxVersion 683 | } 684 | 685 | var defaultCurvePreferences = []CurveID{X25519, CurveP256, CurveP384, CurveP521} 686 | 687 | func (c *Config) curvePreferences() []CurveID { 688 | if c == nil || len(c.CurvePreferences) == 0 { 689 | return defaultCurvePreferences 690 | } 691 | return c.CurvePreferences 692 | } 693 | 694 | // mutualVersion returns the protocol version to use given the advertised 695 | // version of the peer. 696 | func (c *Config) mutualVersion(vers uint16) (uint16, bool) { 697 | minVersion := c.minVersion() 698 | maxVersion := c.maxVersion() 699 | 700 | if vers < minVersion { 701 | return 0, false 702 | } 703 | if vers > maxVersion { 704 | vers = maxVersion 705 | } 706 | return vers, true 707 | } 708 | 709 | // getCertificate returns the best certificate for the given ClientHelloInfo, 710 | // defaulting to the first element of c.Certificates. 711 | func (c *Config) getCertificate(clientHello *ClientHelloInfo) (*Certificate, error) { 712 | if c.GetCertificate != nil && 713 | (len(c.Certificates) == 0 || len(clientHello.ServerName) > 0) { 714 | cert, err := c.GetCertificate(clientHello) 715 | if cert != nil || err != nil { 716 | return cert, err 717 | } 718 | } 719 | 720 | if len(c.Certificates) == 0 { 721 | return nil, errors.New("tls: no certificates configured") 722 | } 723 | 724 | if len(c.Certificates) == 1 || c.NameToCertificate == nil { 725 | // There's only one choice, so no point doing any work. 726 | return &c.Certificates[0], nil 727 | } 728 | 729 | name := strings.ToLower(clientHello.ServerName) 730 | for len(name) > 0 && name[len(name)-1] == '.' { 731 | name = name[:len(name)-1] 732 | } 733 | 734 | if cert, ok := c.NameToCertificate[name]; ok { 735 | return cert, nil 736 | } 737 | 738 | // try replacing labels in the name with wildcards until we get a 739 | // match. 740 | labels := strings.Split(name, ".") 741 | for i := range labels { 742 | labels[i] = "*" 743 | candidate := strings.Join(labels, ".") 744 | if cert, ok := c.NameToCertificate[candidate]; ok { 745 | return cert, nil 746 | } 747 | } 748 | 749 | // If nothing matches, return the first certificate. 750 | return &c.Certificates[0], nil 751 | } 752 | 753 | // BuildNameToCertificate parses c.Certificates and builds c.NameToCertificate 754 | // from the CommonName and SubjectAlternateName fields of each of the leaf 755 | // certificates. 756 | func (c *Config) BuildNameToCertificate() { 757 | c.NameToCertificate = make(map[string]*Certificate) 758 | for i := range c.Certificates { 759 | cert := &c.Certificates[i] 760 | x509Cert, err := x509.ParseCertificate(cert.Certificate[0]) 761 | if err != nil { 762 | continue 763 | } 764 | if len(x509Cert.Subject.CommonName) > 0 { 765 | c.NameToCertificate[x509Cert.Subject.CommonName] = cert 766 | } 767 | for _, san := range x509Cert.DNSNames { 768 | c.NameToCertificate[san] = cert 769 | } 770 | } 771 | } 772 | 773 | // writeKeyLog logs client random and master secret if logging was enabled by 774 | // setting c.KeyLogWriter. 775 | func (c *Config) writeKeyLog(clientRandom, masterSecret []byte) error { 776 | if c.KeyLogWriter == nil { 777 | return nil 778 | } 779 | 780 | logLine := []byte(fmt.Sprintf("CLIENT_RANDOM %x %x\n", clientRandom, masterSecret)) 781 | 782 | writerMutex.Lock() 783 | _, err := c.KeyLogWriter.Write(logLine) 784 | writerMutex.Unlock() 785 | 786 | return err 787 | } 788 | 789 | // writerMutex protects all KeyLogWriters globally. It is rarely enabled, 790 | // and is only for debugging, so a global mutex saves space. 791 | var writerMutex sync.Mutex 792 | 793 | // A Certificate is a chain of one or more certificates, leaf first. 794 | type Certificate struct { 795 | Certificate [][]byte 796 | // PrivateKey contains the private key corresponding to the public key 797 | // in Leaf. For a server, this must implement crypto.Signer and/or 798 | // crypto.Decrypter, with an RSA or ECDSA PublicKey. For a client 799 | // (performing client authentication), this must be a crypto.Signer 800 | // with an RSA or ECDSA PublicKey. 801 | PrivateKey crypto.PrivateKey 802 | // OCSPStaple contains an optional OCSP response which will be served 803 | // to clients that request it. 804 | OCSPStaple []byte 805 | // SignedCertificateTimestamps contains an optional list of Signed 806 | // Certificate Timestamps which will be served to clients that request it. 807 | SignedCertificateTimestamps [][]byte 808 | // Leaf is the parsed form of the leaf certificate, which may be 809 | // initialized using x509.ParseCertificate to reduce per-handshake 810 | // processing for TLS clients doing client authentication. If nil, the 811 | // leaf certificate will be parsed as needed. 812 | Leaf *x509.Certificate 813 | } 814 | 815 | type handshakeMessage interface { 816 | marshal() []byte 817 | unmarshal([]byte) bool 818 | } 819 | 820 | // lruSessionCache is a ClientSessionCache implementation that uses an LRU 821 | // caching strategy. 822 | type lruSessionCache struct { 823 | sync.Mutex 824 | 825 | m map[string]*list.Element 826 | q *list.List 827 | capacity int 828 | } 829 | 830 | type lruSessionCacheEntry struct { 831 | sessionKey string 832 | state *ClientSessionState 833 | } 834 | 835 | // NewLRUClientSessionCache returns a ClientSessionCache with the given 836 | // capacity that uses an LRU strategy. If capacity is < 1, a default capacity 837 | // is used instead. 838 | func NewLRUClientSessionCache(capacity int) ClientSessionCache { 839 | const defaultSessionCacheCapacity = 64 840 | 841 | if capacity < 1 { 842 | capacity = defaultSessionCacheCapacity 843 | } 844 | return &lruSessionCache{ 845 | m: make(map[string]*list.Element), 846 | q: list.New(), 847 | capacity: capacity, 848 | } 849 | } 850 | 851 | // Put adds the provided (sessionKey, cs) pair to the cache. 852 | func (c *lruSessionCache) Put(sessionKey string, cs *ClientSessionState) { 853 | c.Lock() 854 | defer c.Unlock() 855 | 856 | if elem, ok := c.m[sessionKey]; ok { 857 | entry := elem.Value.(*lruSessionCacheEntry) 858 | entry.state = cs 859 | c.q.MoveToFront(elem) 860 | return 861 | } 862 | 863 | if c.q.Len() < c.capacity { 864 | entry := &lruSessionCacheEntry{sessionKey, cs} 865 | c.m[sessionKey] = c.q.PushFront(entry) 866 | return 867 | } 868 | 869 | elem := c.q.Back() 870 | entry := elem.Value.(*lruSessionCacheEntry) 871 | delete(c.m, entry.sessionKey) 872 | entry.sessionKey = sessionKey 873 | entry.state = cs 874 | c.q.MoveToFront(elem) 875 | c.m[sessionKey] = elem 876 | } 877 | 878 | // Get returns the ClientSessionState value associated with a given key. It 879 | // returns (nil, false) if no value is found. 880 | func (c *lruSessionCache) Get(sessionKey string) (*ClientSessionState, bool) { 881 | c.Lock() 882 | defer c.Unlock() 883 | 884 | if elem, ok := c.m[sessionKey]; ok { 885 | c.q.MoveToFront(elem) 886 | return elem.Value.(*lruSessionCacheEntry).state, true 887 | } 888 | return nil, false 889 | } 890 | 891 | // TODO(jsing): Make these available to both crypto/x509 and crypto/tls. 892 | type dsaSignature struct { 893 | R, S *big.Int 894 | } 895 | 896 | type ecdsaSignature dsaSignature 897 | 898 | var emptyConfig Config 899 | 900 | func defaultConfig() *Config { 901 | return &emptyConfig 902 | } 903 | 904 | var ( 905 | once sync.Once 906 | varDefaultCipherSuites []uint16 907 | ) 908 | 909 | func unexpectedMessageError(wanted, got interface{}) error { 910 | return fmt.Errorf("tls: received unexpected handshake message of type %T when waiting for %T", got, wanted) 911 | } 912 | 913 | func isSupportedSignatureAndHash(sigHash signatureAndHash, sigHashes []signatureAndHash) bool { 914 | for _, s := range sigHashes { 915 | if s == sigHash { 916 | return true 917 | } 918 | } 919 | return false 920 | } 921 | -------------------------------------------------------------------------------- /conn.go: -------------------------------------------------------------------------------- 1 | package tls 2 | 3 | // #include "shim.h" 4 | import "C" 5 | import ( 6 | "errors" 7 | "fmt" 8 | "io" 9 | "net" 10 | "runtime" 11 | "strings" 12 | "sync" 13 | "time" 14 | "unsafe" 15 | 16 | "github.com/imroc/tls/internal/errgroup" 17 | "github.com/imroc/tls/internal/future" 18 | ) 19 | 20 | var ( 21 | zeroReturn = errors.New("zero return") 22 | wantRead = errors.New("want read") 23 | wantWrite = errors.New("want write") 24 | tryAgain = errors.New("try again") 25 | ) 26 | 27 | // Server returns a new TLS server side connection 28 | // using conn as the underlying transport. 29 | // The configuration config must be non-nil and must include 30 | // at least one certificate or else set GetCertificate. 31 | func Server(conn net.Conn, config *Config) *Conn { 32 | return &Conn{conn: conn, config: config} 33 | } 34 | 35 | // Client returns a new TLS client side connection 36 | // using conn as the underlying transport. 37 | // The config cannot be nil: users must set either ServerName or 38 | // InsecureSkipVerify in the config. 39 | func Client(conn net.Conn, config *Config) *Conn { 40 | return &Conn{conn: conn, config: config, isClient: true} 41 | } 42 | 43 | type Conn struct { 44 | ssl *ssl 45 | ctx *ssl_ctx 46 | 47 | conn net.Conn 48 | isClient bool 49 | config *Config // configuration passed to constructor 50 | 51 | want_read_future *future.Future 52 | 53 | // handshakeComplete is true if the connection is currently transferring 54 | // application data (i.e. is not currently processing a handshake). 55 | handshakeComplete bool 56 | 57 | // constant after handshake; protected by mu 58 | mu sync.Mutex // mu < in.Mutex, out.Mutex, errMutex 59 | // handshakeCond, if not nil, indicates that a goroutine is committed 60 | // to running the handshake for this Conn. Other goroutines that need 61 | // to wait for the handshake can wait on this, under mu. 62 | handshakeCond *sync.Cond 63 | handshakeErr error // error resulting from handshake 64 | // handshakes counts the number of handshakes performed on the 65 | // connection so far. If renegotiation is disabled then this is either 66 | // zero or one. 67 | handshakes int 68 | 69 | into_ssl *readBio 70 | from_ssl *writeBio 71 | is_shutdown bool 72 | //mu sync.Mutex 73 | } 74 | 75 | // Access to net.Conn methods. 76 | // Cannot just embed net.Conn because that would 77 | // export the struct field too. 78 | 79 | // LocalAddr returns the local network address. 80 | func (c *Conn) LocalAddr() net.Addr { 81 | return c.conn.LocalAddr() 82 | } 83 | 84 | // RemoteAddr returns the remote network address. 85 | func (c *Conn) RemoteAddr() net.Addr { 86 | return c.conn.RemoteAddr() 87 | } 88 | 89 | // SetDeadline sets the read and write deadlines associated with the connection. 90 | // A zero value for t means Read and Write will not time out. 91 | // After a Write has timed out, the TLS state is corrupt and all future writes will return the same error. 92 | func (c *Conn) SetDeadline(t time.Time) error { 93 | return c.conn.SetDeadline(t) 94 | } 95 | 96 | // SetReadDeadline sets the read deadline on the underlying connection. 97 | // A zero value for t means Read will not time out. 98 | func (c *Conn) SetReadDeadline(t time.Time) error { 99 | return c.conn.SetReadDeadline(t) 100 | } 101 | 102 | // SetWriteDeadline sets the write deadline on the underlying connection. 103 | // A zero value for t means Write will not time out. 104 | // After a Write has timed out, the TLS state is corrupt and all future writes will return the same error. 105 | func (c *Conn) SetWriteDeadline(t time.Time) error { 106 | return c.conn.SetWriteDeadline(t) 107 | } 108 | 109 | // Dial connects to the given network address using net.Dial 110 | // and then initiates a TLS handshake, returning the resulting 111 | // TLS connection. 112 | // Dial interprets a nil configuration as equivalent to 113 | // the zero configuration; see the documentation of Config 114 | // for the defaults. 115 | func Dial(network, addr string, config *Config) (*Conn, error) { 116 | return DialWithDialer(new(net.Dialer), network, addr, config) 117 | } 118 | 119 | type timeoutError struct{} 120 | 121 | func (timeoutError) Error() string { return "tls: DialWithDialer timed out" } 122 | func (timeoutError) Timeout() bool { return true } 123 | func (timeoutError) Temporary() bool { return true } 124 | 125 | func DialWithDialer(dialer *net.Dialer, network, addr string, config *Config) (*Conn, error) { 126 | // We want the Timeout and Deadline values from dialer to cover the 127 | // whole process: TCP connection and TLS handshake. This means that we 128 | // also need to start our own timers now. 129 | timeout := dialer.Timeout 130 | 131 | if !dialer.Deadline.IsZero() { 132 | deadlineTimeout := time.Until(dialer.Deadline) 133 | if timeout == 0 || deadlineTimeout < timeout { 134 | timeout = deadlineTimeout 135 | } 136 | } 137 | 138 | var errChannel chan error 139 | 140 | if timeout != 0 { 141 | errChannel = make(chan error, 2) 142 | time.AfterFunc(timeout, func() { 143 | errChannel <- timeoutError{} 144 | }) 145 | } 146 | 147 | rawConn, err := dialer.Dial(network, addr) 148 | if err != nil { 149 | return nil, err 150 | } 151 | 152 | colonPos := strings.LastIndex(addr, ":") 153 | if colonPos == -1 { 154 | colonPos = len(addr) 155 | } 156 | hostname := addr[:colonPos] 157 | 158 | if config == nil { 159 | config = defaultConfig() 160 | } 161 | // If no ServerName is set, infer the ServerName 162 | // from the hostname we're connecting to. 163 | if config.ServerName == "" { 164 | // Make a copy to avoid polluting argument or default. 165 | c := config.Clone() 166 | c.ServerName = hostname 167 | config = c 168 | } 169 | 170 | conn := Client(rawConn, config) 171 | 172 | if timeout == 0 { 173 | err = conn.Handshake() 174 | } else { 175 | go func() { 176 | errChannel <- conn.Handshake() 177 | }() 178 | 179 | err = <-errChannel 180 | } 181 | 182 | if err != nil { 183 | rawConn.Close() 184 | return nil, err 185 | } 186 | 187 | return conn, nil 188 | } 189 | 190 | //func newCtxWithVersion(version int) *C.SSL_CTX { 191 | //switch version { 192 | //case VersionTLS12: 193 | //method = C.X_TLSv1_2_method() 194 | //case VersionTLS11: 195 | //method = C.X_TLSv1_1_method() 196 | //case VersionTLS10: 197 | //method = C.X_TLSv1_method() 198 | //case VersionSSL30: 199 | //method = C.X_SSLv3_method() 200 | //} 201 | //} 202 | 203 | func (c *Conn) init() error { 204 | conf := c.config 205 | if conf == nil { 206 | return errors.New("tls: no tls.Config") 207 | } 208 | 209 | // method 210 | var method *C.SSL_METHOD 211 | method = C.X_SSLv23_method() // TODO 暂时不支持最大最小版本设置,统统全支持 212 | if method == nil { 213 | return errorFromErrorQueue() 214 | } 215 | 216 | // ctx 217 | ctx, err := newCtx(method) // TODO 更多ctx设置(根据配置),暂时不管 218 | if err != nil { 219 | return err 220 | } 221 | 222 | // ssl 223 | ssl_c, err := newSSL(ctx.ctx) 224 | if err != nil { 225 | return err 226 | } 227 | if c.isClient { 228 | C.SSL_set_connect_state(ssl_c) 229 | } else { 230 | C.SSL_set_accept_state(ssl_c) 231 | } 232 | 233 | // bio 234 | into_ssl := &readBio{} 235 | from_ssl := &writeBio{} 236 | 237 | if ctx.GetMode()&ReleaseBuffers > 0 { 238 | into_ssl.release_buffers = true 239 | from_ssl.release_buffers = true 240 | } 241 | 242 | into_ssl_cbio := into_ssl.MakeCBIO() 243 | from_ssl_cbio := from_ssl.MakeCBIO() 244 | 245 | if into_ssl_cbio == nil || from_ssl_cbio == nil { 246 | // these frees are null safe 247 | C.BIO_free(into_ssl_cbio) 248 | C.BIO_free(from_ssl_cbio) 249 | C.SSL_free(ssl_c) 250 | return errors.New("failed to allocate memory BIO") 251 | } 252 | 253 | // the ssl object takes ownership of these objects now 254 | C.SSL_set_bio(ssl_c, into_ssl_cbio, from_ssl_cbio) 255 | 256 | s := &ssl{ssl: ssl_c} 257 | C.SSL_set_ex_data(ssl_c, get_ssl_idx(), unsafe.Pointer(s)) 258 | 259 | c.ssl = s 260 | c.ctx = ctx 261 | c.into_ssl = into_ssl 262 | c.from_ssl = from_ssl 263 | 264 | runtime.SetFinalizer(c, func(c *Conn) { 265 | c.into_ssl.Disconnect(into_ssl_cbio) 266 | c.from_ssl.Disconnect(from_ssl_cbio) 267 | C.SSL_free(ssl_c) 268 | }) 269 | 270 | return nil 271 | } 272 | 273 | // Handshake runs the client or server handshake 274 | // protocol if it has not yet been run. 275 | // Most uses of this package need not call Handshake 276 | // explicitly: the first Read or Write will call it automatically. 277 | func (c *Conn) Handshake() error { 278 | // c.handshakeErr and c.handshakeComplete are protected by 279 | // c.mu. In order to perform a handshake, we need to lock 280 | // c.in also and c.mu must be locked after c.in. 281 | // 282 | // However, if a Read() operation is hanging then it'll be holding the 283 | // lock on c.in and so taking it here would cause all operations that 284 | // need to check whether a handshake is pending (such as Write) to 285 | // block. 286 | // 287 | // Thus we first take c.mu to check whether a handshake is 288 | // needed. 289 | // 290 | // If so then, previously, this code would unlock mu and 291 | // then lock c.in and mu in the correct order to run the 292 | // handshake. The problem was that it was possible for a Read to 293 | // complete the handshake once mu was unlocked and then 294 | // keep c.in while waiting for network data. Thus a concurrent 295 | // operation could be blocked on c.in. 296 | // 297 | // Thus handshakeCond is used to signal that a goroutine is committed 298 | // to running the handshake and other goroutines can wait on it if they 299 | // need. handshakeCond is protected by mu. 300 | c.mu.Lock() 301 | defer c.mu.Unlock() 302 | 303 | for { 304 | if err := c.handshakeErr; err != nil { 305 | return err 306 | } 307 | if c.handshakeComplete { 308 | return nil 309 | } 310 | if c.handshakeCond == nil { 311 | break 312 | } 313 | 314 | c.handshakeCond.Wait() 315 | } 316 | 317 | // Set handshakeCond to indicate that this goroutine is committing to 318 | // running the handshake. 319 | c.handshakeCond = sync.NewCond(&c.mu) 320 | 321 | // The handshake cannot have completed when mu was unlocked 322 | // because this goroutine set handshakeCond. 323 | if c.handshakeErr != nil || c.handshakeComplete { 324 | panic("handshake should not have been able to complete after handshakeCond was set") 325 | } 326 | 327 | err := c.init() 328 | if err != nil { 329 | return err 330 | } 331 | 332 | c.handshakeErr = c.handshake() 333 | 334 | if c.handshakeErr == nil { 335 | c.handshakes++ 336 | } 337 | 338 | if c.handshakeErr == nil && !c.handshakeComplete { 339 | panic("handshake should have had a result.") 340 | } 341 | 342 | // Wake any other goroutines that are waiting for this handshake to 343 | // complete. 344 | c.handshakeCond.Broadcast() 345 | c.handshakeCond = nil 346 | 347 | return c.handshakeErr 348 | } 349 | 350 | func (c *Conn) fillInputBuffer() error { 351 | for { 352 | n, err := c.into_ssl.ReadFromOnce(c.conn) 353 | if n == 0 && err == nil { 354 | continue 355 | } 356 | if err == io.EOF { 357 | c.into_ssl.MarkEOF() 358 | return c.Close() 359 | } 360 | return err 361 | } 362 | } 363 | 364 | func (c *Conn) flushOutputBuffer() error { 365 | _, err := c.from_ssl.WriteTo(c.conn) 366 | return err 367 | } 368 | 369 | func (c *Conn) getErrorHandler(rv C.int, errno error) func() error { 370 | errcode := C.SSL_get_error(c.ssl.ssl, rv) 371 | switch errcode { 372 | case C.SSL_ERROR_ZERO_RETURN: 373 | return func() error { 374 | c.Close() 375 | return io.ErrUnexpectedEOF 376 | } 377 | case C.SSL_ERROR_WANT_READ: 378 | go c.flushOutputBuffer() 379 | if c.want_read_future != nil { 380 | want_read_future := c.want_read_future 381 | return func() error { 382 | _, err := want_read_future.Get() 383 | return err 384 | } 385 | } 386 | c.want_read_future = future.New() 387 | want_read_future := c.want_read_future 388 | return func() (err error) { 389 | defer func() { 390 | //c.mu.Lock() 391 | c.want_read_future = nil 392 | //c.mu.Unlock() 393 | want_read_future.Set(nil, err) 394 | }() 395 | err = c.fillInputBuffer() 396 | if err != nil { 397 | return err 398 | } 399 | return tryAgain 400 | } 401 | case C.SSL_ERROR_WANT_WRITE: 402 | return func() error { 403 | err := c.flushOutputBuffer() 404 | if err != nil { 405 | return err 406 | } 407 | return tryAgain 408 | } 409 | case C.SSL_ERROR_SYSCALL: 410 | var err error 411 | if C.ERR_peek_error() == 0 { 412 | switch rv { 413 | case 0: 414 | err = errors.New("protocol-violating EOF") 415 | case -1: 416 | err = errno 417 | default: 418 | err = errorFromErrorQueue() 419 | } 420 | } else { 421 | err = errorFromErrorQueue() 422 | } 423 | return func() error { return err } 424 | default: 425 | err := errorFromErrorQueue() 426 | return func() error { return err } 427 | } 428 | } 429 | 430 | func (c *Conn) handleError(errcb func() error) error { 431 | if errcb != nil { 432 | return errcb() 433 | } 434 | return nil 435 | } 436 | 437 | func (c *Conn) doHandshake() func() error { 438 | if c.is_shutdown { 439 | return func() error { return io.ErrUnexpectedEOF } 440 | } 441 | runtime.LockOSThread() 442 | defer runtime.UnlockOSThread() 443 | rv, errno := C.SSL_do_handshake(c.ssl.ssl) 444 | fmt.Println(rv, errno) 445 | if rv > 0 { 446 | return nil 447 | } 448 | return c.getErrorHandler(rv, errno) 449 | } 450 | 451 | // Handshake performs an SSL handshake. If a handshake is not manually 452 | // triggered, it will run before the first I/O on the encrypted stream. 453 | func (c *Conn) handshake() error { 454 | err := tryAgain 455 | for err == tryAgain { 456 | fmt.Println("try before") 457 | err = c.handleError(c.doHandshake()) 458 | fmt.Println("try after", err) 459 | } 460 | go c.flushOutputBuffer() 461 | 462 | if err != nil { 463 | return err 464 | } 465 | 466 | c.handshakeComplete = true 467 | 468 | //if c.isClient && !c.config.InsecureSkipVerify { // TODO 证书检查 469 | //} 470 | return err 471 | } 472 | 473 | // Write will encrypt the contents of b and write it to the underlying stream. 474 | // Performance will be vastly improved if the size of b is a multiple of 475 | // SSLRecordSize. 476 | func (c *Conn) Write(b []byte) (written int, err error) { 477 | if len(b) == 0 { 478 | return 0, nil 479 | } 480 | err = tryAgain 481 | for err == tryAgain { 482 | n, errcb := c.write(b) 483 | err = c.handleError(errcb) 484 | if err == nil { 485 | return n, c.flushOutputBuffer() 486 | } 487 | } 488 | return 0, err 489 | } 490 | 491 | func (c *Conn) write(b []byte) (int, func() error) { 492 | if len(b) == 0 { 493 | return 0, nil 494 | } 495 | c.mu.Lock() 496 | defer c.mu.Unlock() 497 | if c.is_shutdown { 498 | err := errors.New("connection closed") 499 | return 0, func() error { return err } 500 | } 501 | runtime.LockOSThread() 502 | defer runtime.UnlockOSThread() 503 | rv, errno := C.SSL_write(c.ssl.ssl, unsafe.Pointer(&b[0]), C.int(len(b))) 504 | if rv > 0 { 505 | return int(rv), nil 506 | } 507 | return 0, c.getErrorHandler(rv, errno) 508 | } 509 | 510 | func (c *Conn) shutdown() func() error { 511 | c.mu.Lock() 512 | defer c.mu.Unlock() 513 | runtime.LockOSThread() 514 | defer runtime.UnlockOSThread() 515 | rv, errno := C.SSL_shutdown(c.ssl.ssl) 516 | if rv > 0 { 517 | return nil 518 | } 519 | if rv == 0 { 520 | // The OpenSSL docs say that in this case, the shutdown is not 521 | // finished, and we should call SSL_shutdown() a second time, if a 522 | // bidirectional shutdown is going to be performed. Further, the 523 | // output of SSL_get_error may be misleading, as an erroneous 524 | // SSL_ERROR_SYSCALL may be flagged even though no error occurred. 525 | // So, TODO: revisit bidrectional shutdown, possibly trying again. 526 | // Note: some broken clients won't engage in bidirectional shutdown 527 | // without tickling them to close by sending a TCP_FIN packet, or 528 | // shutting down the write-side of the connection. 529 | return nil 530 | } else { 531 | return c.getErrorHandler(rv, errno) 532 | } 533 | } 534 | 535 | func (c *Conn) shutdownLoop() error { 536 | err := tryAgain 537 | shutdown_tries := 0 538 | for err == tryAgain { 539 | shutdown_tries = shutdown_tries + 1 540 | err = c.handleError(c.shutdown()) 541 | if err == nil { 542 | return c.flushOutputBuffer() 543 | } 544 | if err == tryAgain && shutdown_tries >= 2 { 545 | return errors.New("shutdown requested a third time?") 546 | } 547 | } 548 | if err == io.ErrUnexpectedEOF { 549 | err = nil 550 | } 551 | return err 552 | } 553 | 554 | // Close shuts down the SSL connection and closes the underlying wrapped 555 | // connection. 556 | func (c *Conn) Close() error { 557 | c.mu.Lock() 558 | if c.is_shutdown { 559 | c.mu.Unlock() 560 | return nil 561 | } 562 | c.is_shutdown = true 563 | c.mu.Unlock() 564 | var errs errgroup.ErrorGroup 565 | errs.Add(c.shutdownLoop()) 566 | errs.Add(c.conn.Close()) 567 | return errs.Finalize() 568 | } 569 | 570 | func (c *Conn) read(b []byte) (int, func() error) { 571 | if len(b) == 0 { 572 | return 0, nil 573 | } 574 | c.mu.Lock() 575 | defer c.mu.Unlock() 576 | if c.is_shutdown { 577 | return 0, func() error { return io.EOF } 578 | } 579 | runtime.LockOSThread() 580 | defer runtime.UnlockOSThread() 581 | rv, errno := C.SSL_read(c.ssl.ssl, unsafe.Pointer(&b[0]), C.int(len(b))) 582 | if rv > 0 { 583 | return int(rv), nil 584 | } 585 | return 0, c.getErrorHandler(rv, errno) 586 | } 587 | 588 | // Read reads up to len(b) bytes into b. It returns the number of bytes read 589 | // and an error if applicable. io.EOF is returned when the caller can expect 590 | // to see no more data. 591 | func (c *Conn) Read(b []byte) (n int, err error) { 592 | if len(b) == 0 { 593 | return 0, nil 594 | } 595 | err = tryAgain 596 | for err == tryAgain { 597 | n, errcb := c.read(b) 598 | err = c.handleError(errcb) 599 | if err == nil { 600 | go c.flushOutputBuffer() 601 | return n, nil 602 | } 603 | if err == io.ErrUnexpectedEOF { 604 | err = io.EOF 605 | } 606 | } 607 | return 0, err 608 | } 609 | -------------------------------------------------------------------------------- /ctx.go: -------------------------------------------------------------------------------- 1 | package tls 2 | 3 | import ( 4 | "runtime" 5 | "unsafe" 6 | ) 7 | 8 | // #include "shim.h" 9 | import "C" 10 | 11 | var ( 12 | ssl_ctx_idx = C.X_SSL_CTX_new_index() 13 | ) 14 | 15 | //export get_ssl_ctx_idx 16 | func get_ssl_ctx_idx() C.int { 17 | return ssl_ctx_idx 18 | } 19 | 20 | type ssl_ctx struct { 21 | ctx *C.SSL_CTX 22 | } 23 | 24 | func newCtx(method *C.SSL_METHOD) (*ssl_ctx, error) { 25 | 26 | runtime.LockOSThread() 27 | defer runtime.UnlockOSThread() 28 | 29 | ctx := C.SSL_CTX_new(method) 30 | if ctx == nil { 31 | return nil, errorFromErrorQueue() 32 | } 33 | 34 | c := &ssl_ctx{ctx: ctx} 35 | C.SSL_CTX_set_ex_data(ctx, get_ssl_ctx_idx(), unsafe.Pointer(c)) 36 | 37 | runtime.SetFinalizer(c, func(c *ssl_ctx) { 38 | C.SSL_CTX_free(c.ctx) 39 | }) 40 | 41 | return c, nil 42 | } 43 | 44 | type Modes int 45 | 46 | const ( 47 | // ReleaseBuffers is only valid if you are using OpenSSL 1.0.1 or newer 48 | ReleaseBuffers Modes = C.SSL_MODE_RELEASE_BUFFERS 49 | ) 50 | 51 | // SetMode sets context modes. See 52 | // http://www.openssl.org/docs/ssl/SSL_CTX_set_mode.html 53 | func (c *ssl_ctx) SetMode(modes Modes) Modes { 54 | return Modes(C.X_SSL_CTX_set_mode(c.ctx, C.long(modes))) 55 | } 56 | 57 | // GetMode returns context modes. See 58 | // http://www.openssl.org/docs/ssl/SSL_CTX_set_mode.html 59 | func (c *ssl_ctx) GetMode() Modes { 60 | return Modes(C.X_SSL_CTX_get_mode(c.ctx)) 61 | } 62 | -------------------------------------------------------------------------------- /hostname.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Go-OpenSSL notice: 3 | * This file is required for all OpenSSL versions prior to 1.1.0. This simply 4 | * provides the new 1.1.0 X509_check_* methods for hostname validation if they 5 | * don't already exist. 6 | */ 7 | 8 | #include 9 | 10 | #ifndef X509_CHECK_FLAG_ALWAYS_CHECK_SUBJECT 11 | 12 | /* portions from x509v3.h and v3_utl.c */ 13 | /* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL 14 | * project. 15 | */ 16 | /* ==================================================================== 17 | * Copyright (c) 1999-2003 The OpenSSL Project. All rights reserved. 18 | * 19 | * Redistribution and use in source and binary forms, with or without 20 | * modification, are permitted provided that the following conditions 21 | * are met: 22 | * 23 | * 1. Redistributions of source code must retain the above copyright 24 | * notice, this list of conditions and the following disclaimer. 25 | * 26 | * 2. Redistributions in binary form must reproduce the above copyright 27 | * notice, this list of conditions and the following disclaimer in 28 | * the documentation and/or other materials provided with the 29 | * distribution. 30 | * 31 | * 3. All advertising materials mentioning features or use of this 32 | * software must display the following acknowledgment: 33 | * "This product includes software developed by the OpenSSL Project 34 | * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)" 35 | * 36 | * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to 37 | * endorse or promote products derived from this software without 38 | * prior written permission. For written permission, please contact 39 | * licensing@OpenSSL.org. 40 | * 41 | * 5. Products derived from this software may not be called "OpenSSL" 42 | * nor may "OpenSSL" appear in their names without prior written 43 | * permission of the OpenSSL Project. 44 | * 45 | * 6. Redistributions of any form whatsoever must retain the following 46 | * acknowledgment: 47 | * "This product includes software developed by the OpenSSL Project 48 | * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)" 49 | * 50 | * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY 51 | * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 52 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 53 | * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR 54 | * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 55 | * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 56 | * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 57 | * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 58 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 59 | * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 60 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED 61 | * OF THE POSSIBILITY OF SUCH DAMAGE. 62 | * ==================================================================== 63 | * 64 | * This product includes cryptographic software written by Eric Young 65 | * (eay@cryptsoft.com). This product includes software written by Tim 66 | * Hudson (tjh@cryptsoft.com). 67 | * 68 | */ 69 | /* X509 v3 extension utilities */ 70 | 71 | #include 72 | #include 73 | #include 74 | #include 75 | #include 76 | 77 | #define X509_CHECK_FLAG_ALWAYS_CHECK_SUBJECT 0x1 78 | #define X509_CHECK_FLAG_NO_WILDCARDS 0x2 79 | 80 | typedef int (*equal_fn)(const unsigned char *pattern, size_t pattern_len, 81 | const unsigned char *subject, size_t subject_len); 82 | 83 | /* Compare while ASCII ignoring case. */ 84 | static int equal_nocase(const unsigned char *pattern, size_t pattern_len, 85 | const unsigned char *subject, size_t subject_len) 86 | { 87 | if (pattern_len != subject_len) 88 | return 0; 89 | while (pattern_len) 90 | { 91 | unsigned char l = *pattern; 92 | unsigned char r = *subject; 93 | /* The pattern must not contain NUL characters. */ 94 | if (l == 0) 95 | return 0; 96 | if (l != r) 97 | { 98 | if ('A' <= l && l <= 'Z') 99 | l = (l - 'A') + 'a'; 100 | if ('A' <= r && r <= 'Z') 101 | r = (r - 'A') + 'a'; 102 | if (l != r) 103 | return 0; 104 | } 105 | ++pattern; 106 | ++subject; 107 | --pattern_len; 108 | } 109 | return 1; 110 | } 111 | 112 | /* Compare using memcmp. */ 113 | static int equal_case(const unsigned char *pattern, size_t pattern_len, 114 | const unsigned char *subject, size_t subject_len) 115 | { 116 | /* The pattern must not contain NUL characters. */ 117 | if (memchr(pattern, '\0', pattern_len) != NULL) 118 | return 0; 119 | if (pattern_len != subject_len) 120 | return 0; 121 | return !memcmp(pattern, subject, pattern_len); 122 | } 123 | 124 | /* RFC 5280, section 7.5, requires that only the domain is compared in 125 | a case-insensitive manner. */ 126 | static int equal_email(const unsigned char *a, size_t a_len, 127 | const unsigned char *b, size_t b_len) 128 | { 129 | size_t i = a_len; 130 | if (a_len != b_len) 131 | return 0; 132 | /* We search backwards for the '@' character, so that we do 133 | not have to deal with quoted local-parts. The domain part 134 | is compared in a case-insensitive manner. */ 135 | while (i > 0) 136 | { 137 | --i; 138 | if (a[i] == '@' || b[i] == '@') 139 | { 140 | if (!equal_nocase(a + i, a_len - i, 141 | b + i, a_len - i)) 142 | return 0; 143 | break; 144 | } 145 | } 146 | if (i == 0) 147 | i = a_len; 148 | return equal_case(a, i, b, i); 149 | } 150 | 151 | /* Compare the prefix and suffix with the subject, and check that the 152 | characters in-between are valid. */ 153 | static int wildcard_match(const unsigned char *prefix, size_t prefix_len, 154 | const unsigned char *suffix, size_t suffix_len, 155 | const unsigned char *subject, size_t subject_len) 156 | { 157 | const unsigned char *wildcard_start; 158 | const unsigned char *wildcard_end; 159 | const unsigned char *p; 160 | if (subject_len < prefix_len + suffix_len) 161 | return 0; 162 | if (!equal_nocase(prefix, prefix_len, subject, prefix_len)) 163 | return 0; 164 | wildcard_start = subject + prefix_len; 165 | wildcard_end = subject + (subject_len - suffix_len); 166 | if (!equal_nocase(wildcard_end, suffix_len, suffix, suffix_len)) 167 | return 0; 168 | /* The wildcard must match at least one character. */ 169 | if (wildcard_start == wildcard_end) 170 | return 0; 171 | /* Check that the part matched by the wildcard contains only 172 | permitted characters and only matches a single label. */ 173 | for (p = wildcard_start; p != wildcard_end; ++p) 174 | if (!(('0' <= *p && *p <= '9') || 175 | ('A' <= *p && *p <= 'Z') || 176 | ('a' <= *p && *p <= 'z') || 177 | *p == '-')) 178 | return 0; 179 | return 1; 180 | } 181 | 182 | /* Checks if the memory region consistens of [0-9A-Za-z.-]. */ 183 | static int valid_domain_characters(const unsigned char *p, size_t len) 184 | { 185 | while (len) 186 | { 187 | if (!(('0' <= *p && *p <= '9') || 188 | ('A' <= *p && *p <= 'Z') || 189 | ('a' <= *p && *p <= 'z') || 190 | *p == '-' || *p == '.')) 191 | return 0; 192 | ++p; 193 | --len; 194 | } 195 | return 1; 196 | } 197 | 198 | /* Find the '*' in a wildcard pattern. If no such character is found 199 | or the pattern is otherwise invalid, returns NULL. */ 200 | static const unsigned char *wildcard_find_star(const unsigned char *pattern, 201 | size_t pattern_len) 202 | { 203 | const unsigned char *star = memchr(pattern, '*', pattern_len); 204 | size_t dot_count = 0; 205 | const unsigned char *suffix_start; 206 | size_t suffix_length; 207 | if (star == NULL) 208 | return NULL; 209 | suffix_start = star + 1; 210 | suffix_length = (pattern + pattern_len) - (star + 1); 211 | if (!(valid_domain_characters(pattern, star - pattern) && 212 | valid_domain_characters(suffix_start, suffix_length))) 213 | return NULL; 214 | /* Check that the suffix matches at least two labels. */ 215 | while (suffix_length) 216 | { 217 | if (*suffix_start == '.') 218 | ++dot_count; 219 | ++suffix_start; 220 | --suffix_length; 221 | } 222 | if (dot_count < 2) 223 | return NULL; 224 | return star; 225 | } 226 | 227 | /* Compare using wildcards. */ 228 | static int equal_wildcard(const unsigned char *pattern, size_t pattern_len, 229 | const unsigned char *subject, size_t subject_len) 230 | { 231 | const unsigned char *star = wildcard_find_star(pattern, pattern_len); 232 | if (star == NULL) 233 | return equal_nocase(pattern, pattern_len, 234 | subject, subject_len); 235 | return wildcard_match(pattern, star - pattern, 236 | star + 1, (pattern + pattern_len) - star - 1, 237 | subject, subject_len); 238 | } 239 | 240 | /* Compare an ASN1_STRING to a supplied string. If they match 241 | * return 1. If cmp_type > 0 only compare if string matches the 242 | * type, otherwise convert it to UTF8. 243 | */ 244 | 245 | static int do_check_string(ASN1_STRING *a, int cmp_type, equal_fn equal, 246 | const unsigned char *b, size_t blen) 247 | { 248 | if (!a->data || !a->length) 249 | return 0; 250 | if (cmp_type > 0) 251 | { 252 | if (cmp_type != a->type) 253 | return 0; 254 | if (cmp_type == V_ASN1_IA5STRING) 255 | return equal(a->data, a->length, b, blen); 256 | if (a->length == (int)blen && !memcmp(a->data, b, blen)) 257 | return 1; 258 | else 259 | return 0; 260 | } 261 | else 262 | { 263 | int astrlen, rv; 264 | unsigned char *astr; 265 | astrlen = ASN1_STRING_to_UTF8(&astr, a); 266 | if (astrlen < 0) 267 | return -1; 268 | rv = equal(astr, astrlen, b, blen); 269 | OPENSSL_free(astr); 270 | return rv; 271 | } 272 | } 273 | 274 | static int do_x509_check(X509 *x, const unsigned char *chk, size_t chklen, 275 | unsigned int flags, int check_type) 276 | { 277 | STACK_OF(GENERAL_NAME) *gens = NULL; 278 | X509_NAME *name = NULL; 279 | int i; 280 | int cnid; 281 | int alt_type; 282 | equal_fn equal; 283 | if (check_type == GEN_EMAIL) 284 | { 285 | cnid = NID_pkcs9_emailAddress; 286 | alt_type = V_ASN1_IA5STRING; 287 | equal = equal_email; 288 | } 289 | else if (check_type == GEN_DNS) 290 | { 291 | cnid = NID_commonName; 292 | alt_type = V_ASN1_IA5STRING; 293 | if (flags & X509_CHECK_FLAG_NO_WILDCARDS) 294 | equal = equal_nocase; 295 | else 296 | equal = equal_wildcard; 297 | } 298 | else 299 | { 300 | cnid = 0; 301 | alt_type = V_ASN1_OCTET_STRING; 302 | equal = equal_case; 303 | } 304 | 305 | if (chklen == 0) 306 | chklen = strlen((const char *)chk); 307 | 308 | gens = X509_get_ext_d2i(x, NID_subject_alt_name, NULL, NULL); 309 | if (gens) 310 | { 311 | int rv = 0; 312 | for (i = 0; i < sk_GENERAL_NAME_num(gens); i++) 313 | { 314 | GENERAL_NAME *gen; 315 | ASN1_STRING *cstr; 316 | gen = sk_GENERAL_NAME_value(gens, i); 317 | if(gen->type != check_type) 318 | continue; 319 | if (check_type == GEN_EMAIL) 320 | cstr = gen->d.rfc822Name; 321 | else if (check_type == GEN_DNS) 322 | cstr = gen->d.dNSName; 323 | else 324 | cstr = gen->d.iPAddress; 325 | if (do_check_string(cstr, alt_type, equal, chk, chklen)) 326 | { 327 | rv = 1; 328 | break; 329 | } 330 | } 331 | GENERAL_NAMES_free(gens); 332 | if (rv) 333 | return 1; 334 | if (!(flags & X509_CHECK_FLAG_ALWAYS_CHECK_SUBJECT) || !cnid) 335 | return 0; 336 | } 337 | i = -1; 338 | name = X509_get_subject_name(x); 339 | while((i = X509_NAME_get_index_by_NID(name, cnid, i)) >= 0) 340 | { 341 | X509_NAME_ENTRY *ne; 342 | ASN1_STRING *str; 343 | ne = X509_NAME_get_entry(name, i); 344 | str = X509_NAME_ENTRY_get_data(ne); 345 | if (do_check_string(str, -1, equal, chk, chklen)) 346 | return 1; 347 | } 348 | return 0; 349 | } 350 | 351 | #if OPENSSL_VERSION_NUMBER < 0x1000200fL 352 | 353 | int X509_check_host(X509 *x, const unsigned char *chk, size_t chklen, 354 | unsigned int flags, char **peername) 355 | { 356 | return do_x509_check(x, chk, chklen, flags, GEN_DNS); 357 | } 358 | 359 | int X509_check_email(X509 *x, const unsigned char *chk, size_t chklen, 360 | unsigned int flags) 361 | { 362 | return do_x509_check(x, chk, chklen, flags, GEN_EMAIL); 363 | } 364 | 365 | int X509_check_ip(X509 *x, const unsigned char *chk, size_t chklen, 366 | unsigned int flags) 367 | { 368 | return do_x509_check(x, chk, chklen, flags, GEN_IPADD); 369 | } 370 | 371 | #endif /* OPENSSL_VERSION_NUMBER < 0x1000200fL */ 372 | 373 | #endif 374 | -------------------------------------------------------------------------------- /init.go: -------------------------------------------------------------------------------- 1 | package tls 2 | 3 | // #include "shim.h" 4 | import "C" 5 | 6 | import ( 7 | "errors" 8 | "fmt" 9 | "strings" 10 | ) 11 | 12 | func init() { 13 | if rc := C.X_shim_init(); rc != 0 { 14 | panic(fmt.Errorf("X_shim_init failed with %d", rc)) 15 | } 16 | } 17 | 18 | // errorFromErrorQueue needs to run in the same OS thread as the operation 19 | // that caused the possible error 20 | func errorFromErrorQueue() error { 21 | var errs []string 22 | for { 23 | err := C.ERR_get_error() 24 | if err == 0 { 25 | break 26 | } 27 | errs = append(errs, fmt.Sprintf("%s:%s:%s", 28 | C.GoString(C.ERR_lib_error_string(err)), 29 | C.GoString(C.ERR_func_error_string(err)), 30 | C.GoString(C.ERR_reason_error_string(err)))) 31 | } 32 | return errors.New(fmt.Sprintf("SSL errors: %s", strings.Join(errs, "\n"))) 33 | } 34 | -------------------------------------------------------------------------------- /init_posix.go: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2017. See AUTHORS. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | // +build linux darwin 16 | // +build !windows 17 | 18 | package tls 19 | 20 | /* 21 | #include 22 | #include 23 | #include 24 | 25 | pthread_mutex_t* goopenssl_locks; 26 | 27 | int go_init_locks() { 28 | int rc = 0; 29 | int nlock; 30 | int i; 31 | int locks_needed = CRYPTO_num_locks(); 32 | 33 | goopenssl_locks = (pthread_mutex_t*)malloc( 34 | sizeof(pthread_mutex_t) * locks_needed); 35 | if (!goopenssl_locks) { 36 | return ENOMEM; 37 | } 38 | for (nlock = 0; nlock < locks_needed; ++nlock) { 39 | rc = pthread_mutex_init(&goopenssl_locks[nlock], NULL); 40 | if (rc != 0) { 41 | break; 42 | } 43 | } 44 | 45 | if (rc != 0) { 46 | for (i = nlock - 1; i >= 0; --i) { 47 | pthread_mutex_destroy(&goopenssl_locks[i]); 48 | } 49 | free(goopenssl_locks); 50 | goopenssl_locks = NULL; 51 | } 52 | return rc; 53 | } 54 | 55 | void go_thread_locking_callback(int mode, int n, const char *file, 56 | int line) { 57 | if (mode & CRYPTO_LOCK) { 58 | pthread_mutex_lock(&goopenssl_locks[n]); 59 | } else { 60 | pthread_mutex_unlock(&goopenssl_locks[n]); 61 | } 62 | } 63 | */ 64 | import "C" 65 | -------------------------------------------------------------------------------- /init_windows.go: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2017. See AUTHORS. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | // +build windows 16 | 17 | package tls 18 | 19 | /* 20 | 21 | #cgo pkg-config: libssl 22 | 23 | #ifndef WIN32_LEAN_AND_MEAN 24 | #define WIN32_LEAN_AND_MEAN 25 | #endif 26 | #include 27 | #include 28 | #include 29 | 30 | CRITICAL_SECTION* goopenssl_locks; 31 | 32 | int go_init_locks() { 33 | int rc = 0; 34 | int nlock; 35 | int i; 36 | int locks_needed = CRYPTO_num_locks(); 37 | 38 | goopenssl_locks = (CRITICAL_SECTION*)malloc( 39 | sizeof(*goopenssl_locks) * locks_needed); 40 | if (!goopenssl_locks) { 41 | return ENOMEM; 42 | } 43 | for (nlock = 0; nlock < locks_needed; ++nlock) { 44 | InitializeCriticalSection(&goopenssl_locks[nlock]); 45 | } 46 | 47 | return 0; 48 | } 49 | 50 | void go_thread_locking_callback(int mode, int n, const char *file, 51 | int line) { 52 | if (mode & CRYPTO_LOCK) { 53 | EnterCriticalSection(&goopenssl_locks[n]); 54 | } else { 55 | LeaveCriticalSection(&goopenssl_locks[n]); 56 | } 57 | } 58 | */ 59 | import "C" 60 | -------------------------------------------------------------------------------- /internal/cipherhw/asm_amd64.s: -------------------------------------------------------------------------------- 1 | // Copyright 2016 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 | // +build amd64,!gccgo,!appengine 6 | 7 | #include "textflag.h" 8 | 9 | // func hasAESNI() bool 10 | TEXT ·hasAESNI(SB),NOSPLIT,$0 11 | XORQ AX, AX 12 | INCL AX 13 | CPUID 14 | SHRQ $25, CX 15 | ANDQ $1, CX 16 | MOVB CX, ret+0(FP) 17 | RET 18 | -------------------------------------------------------------------------------- /internal/cipherhw/asm_s390x.s: -------------------------------------------------------------------------------- 1 | // Copyright 2016 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 | // +build s390x,!gccgo,!appengine 6 | 7 | #include "textflag.h" 8 | 9 | // func hasHWSupport() bool 10 | TEXT ·hasHWSupport(SB),NOSPLIT,$16-1 11 | XOR R0, R0 // set function code to 0 (query) 12 | LA mask-16(SP), R1 // 16-byte stack variable for mask 13 | MOVD $(0x38<<40), R3 // mask for bits 18-20 (big endian) 14 | 15 | // check for KM AES functions 16 | WORD $0xB92E0024 // cipher message (KM) 17 | MOVD mask-16(SP), R2 18 | AND R3, R2 19 | CMPBNE R2, R3, notfound 20 | 21 | // check for KMC AES functions 22 | WORD $0xB92F0024 // cipher message with chaining (KMC) 23 | MOVD mask-16(SP), R2 24 | AND R3, R2 25 | CMPBNE R2, R3, notfound 26 | 27 | // check for KMCTR AES functions 28 | WORD $0xB92D4024 // cipher message with counter (KMCTR) 29 | MOVD mask-16(SP), R2 30 | AND R3, R2 31 | CMPBNE R2, R3, notfound 32 | 33 | // check for KIMD GHASH function 34 | WORD $0xB93E0024 // compute intermediate message digest (KIMD) 35 | MOVD mask-8(SP), R2 // bits 64-127 36 | MOVD $(1<<62), R5 37 | AND R5, R2 38 | CMPBNE R2, R5, notfound 39 | 40 | MOVB $1, ret+0(FP) 41 | RET 42 | notfound: 43 | MOVB $0, ret+0(FP) 44 | RET 45 | -------------------------------------------------------------------------------- /internal/cipherhw/cipherhw_amd64.go: -------------------------------------------------------------------------------- 1 | // Copyright 2016 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 | // +build amd64,!gccgo,!appengine 6 | 7 | package cipherhw 8 | 9 | // defined in asm_amd64.s 10 | func hasAESNI() bool 11 | 12 | // AESGCMSupport returns true if the Go standard library supports AES-GCM in 13 | // hardware. 14 | func AESGCMSupport() bool { 15 | return hasAESNI() 16 | } 17 | -------------------------------------------------------------------------------- /internal/cipherhw/cipherhw_s390x.go: -------------------------------------------------------------------------------- 1 | // Copyright 2016 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 | // +build s390x,!gccgo,!appengine 6 | 7 | package cipherhw 8 | 9 | // hasHWSupport reports whether the AES-128, AES-192 and AES-256 cipher message 10 | // (KM) function codes are supported. Note that this function is expensive. 11 | // defined in asm_s390x.s 12 | func hasHWSupport() bool 13 | 14 | var hwSupport = hasHWSupport() 15 | 16 | func AESGCMSupport() bool { 17 | return hwSupport 18 | } 19 | -------------------------------------------------------------------------------- /internal/cipherhw/doc.go: -------------------------------------------------------------------------------- 1 | // Copyright 2016 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 cipherhw exposes common functions for detecting whether hardware 6 | // support for certain ciphers and authenticators is present. 7 | package cipherhw 8 | -------------------------------------------------------------------------------- /internal/cipherhw/generic.go: -------------------------------------------------------------------------------- 1 | // Copyright 2016 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 | // +build !amd64,!s390x gccgo appengine 6 | 7 | package cipherhw 8 | 9 | func AESGCMSupport() bool { 10 | return false 11 | } 12 | -------------------------------------------------------------------------------- /internal/errgroup/errgroup.go: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2014 Space Monkey, Inc. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | package errgroup 16 | 17 | import ( 18 | "errors" 19 | "strings" 20 | ) 21 | 22 | // ErrorGroup collates errors 23 | type ErrorGroup struct { 24 | Errors []error 25 | } 26 | 27 | // Add adds an error to an existing error group 28 | func (e *ErrorGroup) Add(err error) { 29 | if err != nil { 30 | e.Errors = append(e.Errors, err) 31 | } 32 | } 33 | 34 | // Finalize returns an error corresponding to the ErrorGroup state. If there's 35 | // no errors in the group, finalize returns nil. If there's only one error, 36 | // Finalize returns that error. Otherwise, Finalize will make a new error 37 | // consisting of the messages from the constituent errors. 38 | func (e *ErrorGroup) Finalize() error { 39 | if len(e.Errors) == 0 { 40 | return nil 41 | } 42 | if len(e.Errors) == 1 { 43 | return e.Errors[0] 44 | } 45 | msgs := make([]string, 0, len(e.Errors)) 46 | for _, err := range e.Errors { 47 | msgs = append(msgs, err.Error()) 48 | } 49 | return errors.New(strings.Join(msgs, "\n")) 50 | } 51 | -------------------------------------------------------------------------------- /internal/future/future.go: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2014 Space Monkey, Inc. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | package future 16 | 17 | import ( 18 | "sync" 19 | ) 20 | 21 | // Future is a type that is essentially the inverse of a channel. With a 22 | // channel, you have multiple senders and one receiver. With a future, you can 23 | // have multiple receivers and one sender. Additionally, a future protects 24 | // against double-sends. Since this is usually used for returning function 25 | // results, we also capture and return error values as well. Use NewFuture 26 | // to initialize. 27 | type Future struct { 28 | mutex *sync.Mutex 29 | cond *sync.Cond 30 | received bool 31 | val interface{} 32 | err error 33 | } 34 | 35 | // NewFuture returns an initialized and ready Future. 36 | func New() *Future { 37 | mutex := &sync.Mutex{} 38 | return &Future{ 39 | mutex: mutex, 40 | cond: sync.NewCond(mutex), 41 | received: false, 42 | val: nil, 43 | err: nil, 44 | } 45 | } 46 | 47 | // Get blocks until the Future has a value set. 48 | func (self *Future) Get() (interface{}, error) { 49 | self.mutex.Lock() 50 | defer self.mutex.Unlock() 51 | for { 52 | if self.received { 53 | return self.val, self.err 54 | } 55 | self.cond.Wait() 56 | } 57 | } 58 | 59 | // Fired returns whether or not a value has been set. If Fired is true, Get 60 | // won't block. 61 | func (self *Future) Fired() bool { 62 | self.mutex.Lock() 63 | defer self.mutex.Unlock() 64 | return self.received 65 | } 66 | 67 | // Set provides the value to present and future Get calls. If Set has already 68 | // been called, this is a no-op. 69 | func (self *Future) Set(val interface{}, err error) { 70 | self.mutex.Lock() 71 | defer self.mutex.Unlock() 72 | if self.received { 73 | return 74 | } 75 | self.received = true 76 | self.val = val 77 | self.err = err 78 | self.cond.Broadcast() 79 | } 80 | -------------------------------------------------------------------------------- /mapping.go: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2017. See AUTHORS. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | package tls 16 | 17 | import ( 18 | "sync" 19 | "unsafe" 20 | ) 21 | 22 | // #include 23 | import "C" 24 | 25 | type mapping struct { 26 | lock sync.Mutex 27 | values map[token]unsafe.Pointer 28 | } 29 | 30 | func newMapping() *mapping { 31 | return &mapping{ 32 | values: make(map[token]unsafe.Pointer), 33 | } 34 | } 35 | 36 | type token unsafe.Pointer 37 | 38 | func (m *mapping) Add(x unsafe.Pointer) token { 39 | res := token(C.malloc(1)) 40 | 41 | m.lock.Lock() 42 | m.values[res] = x 43 | m.lock.Unlock() 44 | 45 | return res 46 | } 47 | 48 | func (m *mapping) Get(x token) unsafe.Pointer { 49 | m.lock.Lock() 50 | res := m.values[x] 51 | m.lock.Unlock() 52 | 53 | return res 54 | } 55 | 56 | func (m *mapping) Del(x token) { 57 | m.lock.Lock() 58 | delete(m.values, x) 59 | m.lock.Unlock() 60 | 61 | C.free(unsafe.Pointer(x)) 62 | } 63 | -------------------------------------------------------------------------------- /shim.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2014 Space Monkey, Inc. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * 16 | */ 17 | 18 | #include 19 | 20 | #include 21 | 22 | #include 23 | #include 24 | #include 25 | #include 26 | #include 27 | #include 28 | 29 | #include "_cgo_export.h" 30 | 31 | /* 32 | * Functions defined in other .c files 33 | */ 34 | extern int go_init_locks(); 35 | extern void go_thread_locking_callback(int, int, const char*, int); 36 | static int go_write_bio_puts(BIO *b, const char *str) { 37 | return go_write_bio_write(b, (char*)str, (int)strlen(str)); 38 | } 39 | 40 | /* 41 | ************************************************ 42 | * v1.1.X and later implementation 43 | ************************************************ 44 | */ 45 | #if OPENSSL_VERSION_NUMBER >= 0x1010000fL 46 | 47 | void X_BIO_set_data(BIO* bio, void* data) { 48 | BIO_set_data(bio, data); 49 | } 50 | 51 | void* X_BIO_get_data(BIO* bio) { 52 | return BIO_get_data(bio); 53 | } 54 | 55 | EVP_MD_CTX* X_EVP_MD_CTX_new() { 56 | return EVP_MD_CTX_new(); 57 | } 58 | 59 | void X_EVP_MD_CTX_free(EVP_MD_CTX* ctx) { 60 | EVP_MD_CTX_free(ctx); 61 | } 62 | 63 | static int x_bio_create(BIO *b) { 64 | BIO_set_shutdown(b, 1); 65 | BIO_set_init(b, 1); 66 | BIO_set_data(b, NULL); 67 | BIO_clear_flags(b, ~0); 68 | return 1; 69 | } 70 | 71 | static int x_bio_free(BIO *b) { 72 | return 1; 73 | } 74 | 75 | static BIO_METHOD *writeBioMethod; 76 | static BIO_METHOD *readBioMethod; 77 | 78 | BIO_METHOD* BIO_s_readBio() { return readBioMethod; } 79 | BIO_METHOD* BIO_s_writeBio() { return writeBioMethod; } 80 | 81 | int x_bio_init_methods() { 82 | writeBioMethod = BIO_meth_new(BIO_TYPE_SOURCE_SINK, "Go Write BIO"); 83 | if (!writeBioMethod) { 84 | return 1; 85 | } 86 | if (1 != BIO_meth_set_write(writeBioMethod, 87 | (int (*)(BIO *, const char *, int))go_write_bio_write)) { 88 | return 2; 89 | } 90 | if (1 != BIO_meth_set_puts(writeBioMethod, go_write_bio_puts)) { 91 | return 3; 92 | } 93 | if (1 != BIO_meth_set_ctrl(writeBioMethod, go_write_bio_ctrl)) { 94 | return 4; 95 | } 96 | if (1 != BIO_meth_set_create(writeBioMethod, x_bio_create)) { 97 | return 5; 98 | } 99 | if (1 != BIO_meth_set_destroy(writeBioMethod, x_bio_free)) { 100 | return 6; 101 | } 102 | 103 | readBioMethod = BIO_meth_new(BIO_TYPE_SOURCE_SINK, "Go Read BIO"); 104 | if (!readBioMethod) { 105 | return 7; 106 | } 107 | if (1 != BIO_meth_set_read(readBioMethod, go_read_bio_read)) { 108 | return 8; 109 | } 110 | if (1 != BIO_meth_set_ctrl(readBioMethod, go_read_bio_ctrl)) { 111 | return 9; 112 | } 113 | if (1 != BIO_meth_set_create(readBioMethod, x_bio_create)) { 114 | return 10; 115 | } 116 | if (1 != BIO_meth_set_destroy(readBioMethod, x_bio_free)) { 117 | return 11; 118 | } 119 | 120 | return 0; 121 | } 122 | 123 | const EVP_MD *X_EVP_dss() { 124 | return NULL; 125 | } 126 | 127 | const EVP_MD *X_EVP_dss1() { 128 | return NULL; 129 | } 130 | 131 | const EVP_MD *X_EVP_sha() { 132 | return NULL; 133 | } 134 | 135 | int X_EVP_CIPHER_CTX_encrypting(const EVP_CIPHER_CTX *ctx) { 136 | return EVP_CIPHER_CTX_encrypting(ctx); 137 | } 138 | 139 | int X_X509_add_ref(X509* x509) { 140 | return X509_up_ref(x509); 141 | } 142 | 143 | const ASN1_TIME *X_X509_get0_notBefore(const X509 *x) { 144 | return X509_get0_notBefore(x); 145 | } 146 | 147 | const ASN1_TIME *X_X509_get0_notAfter(const X509 *x) { 148 | return X509_get0_notAfter(x); 149 | } 150 | 151 | HMAC_CTX *X_HMAC_CTX_new(void) { 152 | return HMAC_CTX_new(); 153 | } 154 | 155 | void X_HMAC_CTX_free(HMAC_CTX *ctx) { 156 | HMAC_CTX_free(ctx); 157 | } 158 | 159 | #endif 160 | 161 | 162 | 163 | /* 164 | ************************************************ 165 | * v1.0.X implementation 166 | ************************************************ 167 | */ 168 | #if OPENSSL_VERSION_NUMBER < 0x1010000fL 169 | 170 | static int x_bio_create(BIO *b) { 171 | b->shutdown = 1; 172 | b->init = 1; 173 | b->num = -1; 174 | b->ptr = NULL; 175 | b->flags = 0; 176 | return 1; 177 | } 178 | 179 | static int x_bio_free(BIO *b) { 180 | return 1; 181 | } 182 | 183 | static BIO_METHOD writeBioMethod = { 184 | BIO_TYPE_SOURCE_SINK, 185 | "Go Write BIO", 186 | (int (*)(BIO *, const char *, int))go_write_bio_write, 187 | NULL, 188 | go_write_bio_puts, 189 | NULL, 190 | go_write_bio_ctrl, 191 | x_bio_create, 192 | x_bio_free, 193 | NULL}; 194 | 195 | static BIO_METHOD* BIO_s_writeBio() { return &writeBioMethod; } 196 | 197 | static BIO_METHOD readBioMethod = { 198 | BIO_TYPE_SOURCE_SINK, 199 | "Go Read BIO", 200 | NULL, 201 | go_read_bio_read, 202 | NULL, 203 | NULL, 204 | go_read_bio_ctrl, 205 | x_bio_create, 206 | x_bio_free, 207 | NULL}; 208 | 209 | static BIO_METHOD* BIO_s_readBio() { return &readBioMethod; } 210 | 211 | int x_bio_init_methods() { 212 | /* statically initialized above */ 213 | return 0; 214 | } 215 | 216 | void X_BIO_set_data(BIO* bio, void* data) { 217 | bio->ptr = data; 218 | } 219 | 220 | void* X_BIO_get_data(BIO* bio) { 221 | return bio->ptr; 222 | } 223 | 224 | EVP_MD_CTX* X_EVP_MD_CTX_new() { 225 | return EVP_MD_CTX_create(); 226 | } 227 | 228 | void X_EVP_MD_CTX_free(EVP_MD_CTX* ctx) { 229 | EVP_MD_CTX_destroy(ctx); 230 | } 231 | 232 | int X_X509_add_ref(X509* x509) { 233 | CRYPTO_add(&x509->references, 1, CRYPTO_LOCK_X509); 234 | return 1; 235 | } 236 | 237 | const ASN1_TIME *X_X509_get0_notBefore(const X509 *x) { 238 | return x->cert_info->validity->notBefore; 239 | } 240 | 241 | const ASN1_TIME *X_X509_get0_notAfter(const X509 *x) { 242 | return x->cert_info->validity->notAfter; 243 | } 244 | 245 | const EVP_MD *X_EVP_dss() { 246 | return EVP_dss(); 247 | } 248 | 249 | const EVP_MD *X_EVP_dss1() { 250 | return EVP_dss1(); 251 | } 252 | 253 | const EVP_MD *X_EVP_sha() { 254 | return EVP_sha(); 255 | } 256 | 257 | int X_EVP_CIPHER_CTX_encrypting(const EVP_CIPHER_CTX *ctx) { 258 | return ctx->encrypt; 259 | } 260 | 261 | HMAC_CTX *X_HMAC_CTX_new(void) { 262 | /* v1.1.0 uses a OPENSSL_zalloc to allocate the memory which does not exist 263 | * in previous versions. malloc+memset to get the same behavior */ 264 | HMAC_CTX *ctx = (HMAC_CTX *)OPENSSL_malloc(sizeof(HMAC_CTX)); 265 | if (ctx) { 266 | memset(ctx, 0, sizeof(HMAC_CTX)); 267 | HMAC_CTX_init(ctx); 268 | } 269 | return ctx; 270 | } 271 | 272 | void X_HMAC_CTX_free(HMAC_CTX *ctx) { 273 | if (ctx) { 274 | HMAC_CTX_cleanup(ctx); 275 | OPENSSL_free(ctx); 276 | } 277 | } 278 | 279 | #endif 280 | 281 | 282 | 283 | /* 284 | ************************************************ 285 | * common implementation 286 | ************************************************ 287 | */ 288 | 289 | int X_shim_init() { 290 | int rc = 0; 291 | 292 | OPENSSL_config(NULL); 293 | ENGINE_load_builtin_engines(); 294 | SSL_load_error_strings(); 295 | SSL_library_init(); 296 | OpenSSL_add_all_algorithms(); 297 | // 298 | // Set up OPENSSL thread safety callbacks. We only set the locking 299 | // callback because the default id callback implementation is good 300 | // enough for us. 301 | rc = go_init_locks(); 302 | if (rc != 0) { 303 | return rc; 304 | } 305 | CRYPTO_set_locking_callback(go_thread_locking_callback); 306 | 307 | rc = x_bio_init_methods(); 308 | if (rc != 0) { 309 | return rc; 310 | } 311 | 312 | return 0; 313 | } 314 | 315 | void X_OPENSSL_free(void *ref) { 316 | OPENSSL_free(ref); 317 | } 318 | 319 | long X_SSL_set_options(SSL* ssl, long options) { 320 | return SSL_set_options(ssl, options); 321 | } 322 | 323 | long X_SSL_get_options(SSL* ssl) { 324 | return SSL_get_options(ssl); 325 | } 326 | 327 | long X_SSL_clear_options(SSL* ssl, long options) { 328 | return SSL_clear_options(ssl, options); 329 | } 330 | 331 | long X_SSL_set_tlsext_host_name(SSL *ssl, const char *name) { 332 | return SSL_set_tlsext_host_name(ssl, name); 333 | } 334 | const char * X_SSL_get_cipher_name(const SSL *ssl) { 335 | return SSL_get_cipher_name(ssl); 336 | } 337 | int X_SSL_session_reused(SSL *ssl) { 338 | return SSL_session_reused(ssl); 339 | } 340 | 341 | int X_SSL_new_index() { 342 | return SSL_get_ex_new_index(0, NULL, NULL, NULL, NULL); 343 | } 344 | 345 | /* 346 | int X_SSL_verify_cb(int ok, X509_STORE_CTX* store) { 347 | SSL* ssl = (SSL *)X509_STORE_CTX_get_ex_data(store, 348 | SSL_get_ex_data_X509_STORE_CTX_idx()); 349 | void* p = SSL_get_ex_data(ssl, get_ssl_idx()); 350 | // get the pointer to the go Ctx object and pass it back into the thunk 351 | return go_ssl_verify_cb_thunk(p, ok, store); 352 | } 353 | */ 354 | 355 | const SSL_METHOD *X_SSLv23_method() { 356 | return SSLv23_method(); 357 | } 358 | 359 | const SSL_METHOD *X_SSLv3_method() { 360 | #ifndef OPENSSL_NO_SSL3_METHOD 361 | return SSLv3_method(); 362 | #else 363 | return NULL; 364 | #endif 365 | } 366 | 367 | const SSL_METHOD *X_TLSv1_method() { 368 | return TLSv1_method(); 369 | } 370 | 371 | const SSL_METHOD *X_TLSv1_1_method() { 372 | #if defined(TLS1_1_VERSION) && !defined(OPENSSL_SYSNAME_MACOSX) 373 | return TLSv1_1_method(); 374 | #else 375 | return NULL; 376 | #endif 377 | } 378 | 379 | const SSL_METHOD *X_TLSv1_2_method() { 380 | #if defined(TLS1_2_VERSION) && !defined(OPENSSL_SYSNAME_MACOSX) 381 | return TLSv1_2_method(); 382 | #else 383 | return NULL; 384 | #endif 385 | } 386 | 387 | 388 | int X_SSL_CTX_new_index() { 389 | return SSL_CTX_get_ex_new_index(0, NULL, NULL, NULL, NULL); 390 | } 391 | 392 | long X_SSL_CTX_set_options(SSL_CTX* ctx, long options) { 393 | return SSL_CTX_set_options(ctx, options); 394 | } 395 | 396 | long X_SSL_CTX_clear_options(SSL_CTX* ctx, long options) { 397 | return SSL_CTX_clear_options(ctx, options); 398 | } 399 | 400 | long X_SSL_CTX_get_options(SSL_CTX* ctx) { 401 | return SSL_CTX_get_options(ctx); 402 | } 403 | 404 | long X_SSL_CTX_set_mode(SSL_CTX* ctx, long modes) { 405 | return SSL_CTX_set_mode(ctx, modes); 406 | } 407 | 408 | long X_SSL_CTX_get_mode(SSL_CTX* ctx) { 409 | return SSL_CTX_get_mode(ctx); 410 | } 411 | 412 | long X_SSL_CTX_set_session_cache_mode(SSL_CTX* ctx, long modes) { 413 | return SSL_CTX_set_session_cache_mode(ctx, modes); 414 | } 415 | 416 | long X_SSL_CTX_sess_set_cache_size(SSL_CTX* ctx, long t) { 417 | return SSL_CTX_sess_set_cache_size(ctx, t); 418 | } 419 | 420 | long X_SSL_CTX_sess_get_cache_size(SSL_CTX* ctx) { 421 | return SSL_CTX_sess_get_cache_size(ctx); 422 | } 423 | 424 | long X_SSL_CTX_set_timeout(SSL_CTX* ctx, long t) { 425 | return SSL_CTX_set_timeout(ctx, t); 426 | } 427 | 428 | long X_SSL_CTX_get_timeout(SSL_CTX* ctx) { 429 | return SSL_CTX_get_timeout(ctx); 430 | } 431 | 432 | long X_SSL_CTX_add_extra_chain_cert(SSL_CTX* ctx, X509 *cert) { 433 | return SSL_CTX_add_extra_chain_cert(ctx, cert); 434 | } 435 | 436 | long X_SSL_CTX_set_tmp_ecdh(SSL_CTX* ctx, EC_KEY *key) { 437 | return SSL_CTX_set_tmp_ecdh(ctx, key); 438 | } 439 | 440 | long X_SSL_CTX_set_tlsext_servername_callback( 441 | SSL_CTX* ctx, int (*cb)(SSL *con, int *ad, void *args)) { 442 | return SSL_CTX_set_tlsext_servername_callback(ctx, cb); 443 | } 444 | 445 | /* 446 | int X_SSL_CTX_verify_cb(int ok, X509_STORE_CTX* store) { 447 | SSL* ssl = (SSL *)X509_STORE_CTX_get_ex_data(store, 448 | SSL_get_ex_data_X509_STORE_CTX_idx()); 449 | SSL_CTX* ssl_ctx = SSL_get_SSL_CTX(ssl); 450 | void* p = SSL_CTX_get_ex_data(ssl_ctx, get_ssl_ctx_idx()); 451 | // get the pointer to the go Ctx object and pass it back into the thunk 452 | return go_ssl_ctx_verify_cb_thunk(p, ok, store); 453 | } 454 | */ 455 | 456 | long X_SSL_CTX_set_tmp_dh(SSL_CTX* ctx, DH *dh) { 457 | return SSL_CTX_set_tmp_dh(ctx, dh); 458 | } 459 | 460 | long X_PEM_read_DHparams(SSL_CTX* ctx, DH *dh) { 461 | return SSL_CTX_set_tmp_dh(ctx, dh); 462 | } 463 | 464 | int X_SSL_CTX_set_tlsext_ticket_key_cb(SSL_CTX *sslctx, 465 | int (*cb)(SSL *s, unsigned char key_name[16], 466 | unsigned char iv[EVP_MAX_IV_LENGTH], 467 | EVP_CIPHER_CTX *ctx, HMAC_CTX *hctx, int enc)) { 468 | return SSL_CTX_set_tlsext_ticket_key_cb(sslctx, cb); 469 | } 470 | 471 | /* 472 | int X_SSL_CTX_ticket_key_cb(SSL *s, unsigned char key_name[16], 473 | unsigned char iv[EVP_MAX_IV_LENGTH], 474 | EVP_CIPHER_CTX *cctx, HMAC_CTX *hctx, int enc) { 475 | 476 | SSL_CTX* ssl_ctx = SSL_get_SSL_CTX(s); 477 | void* p = SSL_CTX_get_ex_data(ssl_ctx, get_ssl_ctx_idx()); 478 | // get the pointer to the go Ctx object and pass it back into the thunk 479 | return go_ticket_key_cb_thunk(p, s, key_name, iv, cctx, hctx, enc); 480 | } 481 | */ 482 | 483 | int X_BIO_get_flags(BIO *b) { 484 | return BIO_get_flags(b); 485 | } 486 | 487 | void X_BIO_set_flags(BIO *b, int flags) { 488 | return BIO_set_flags(b, flags); 489 | } 490 | 491 | void X_BIO_clear_flags(BIO *b, int flags) { 492 | BIO_clear_flags(b, flags); 493 | } 494 | 495 | int X_BIO_read(BIO *b, void *buf, int len) { 496 | return BIO_read(b, buf, len); 497 | } 498 | 499 | int X_BIO_write(BIO *b, const void *buf, int len) { 500 | return BIO_write(b, buf, len); 501 | } 502 | 503 | BIO *X_BIO_new_write_bio() { 504 | return BIO_new(BIO_s_writeBio()); 505 | } 506 | 507 | BIO *X_BIO_new_read_bio() { 508 | return BIO_new(BIO_s_readBio()); 509 | } 510 | 511 | const EVP_MD *X_EVP_get_digestbyname(const char *name) { 512 | return EVP_get_digestbyname(name); 513 | } 514 | 515 | const EVP_MD *X_EVP_md_null() { 516 | return EVP_md_null(); 517 | } 518 | 519 | const EVP_MD *X_EVP_md5() { 520 | return EVP_md5(); 521 | } 522 | 523 | const EVP_MD *X_EVP_ripemd160() { 524 | return EVP_ripemd160(); 525 | } 526 | 527 | const EVP_MD *X_EVP_sha224() { 528 | return EVP_sha224(); 529 | } 530 | 531 | const EVP_MD *X_EVP_sha1() { 532 | return EVP_sha1(); 533 | } 534 | 535 | const EVP_MD *X_EVP_sha256() { 536 | return EVP_sha256(); 537 | } 538 | 539 | const EVP_MD *X_EVP_sha384() { 540 | return EVP_sha384(); 541 | } 542 | 543 | const EVP_MD *X_EVP_sha512() { 544 | return EVP_sha512(); 545 | } 546 | 547 | int X_EVP_MD_size(const EVP_MD *md) { 548 | return EVP_MD_size(md); 549 | } 550 | 551 | int X_EVP_DigestInit_ex(EVP_MD_CTX *ctx, const EVP_MD *type, ENGINE *impl) { 552 | return EVP_DigestInit_ex(ctx, type, impl); 553 | } 554 | 555 | int X_EVP_DigestUpdate(EVP_MD_CTX *ctx, const void *d, size_t cnt) { 556 | return EVP_DigestUpdate(ctx, d, cnt); 557 | } 558 | 559 | int X_EVP_DigestFinal_ex(EVP_MD_CTX *ctx, unsigned char *md, unsigned int *s) { 560 | return EVP_DigestFinal_ex(ctx, md, s); 561 | } 562 | 563 | int X_EVP_SignInit(EVP_MD_CTX *ctx, const EVP_MD *type) { 564 | return EVP_SignInit(ctx, type); 565 | } 566 | 567 | int X_EVP_SignUpdate(EVP_MD_CTX *ctx, const void *d, unsigned int cnt) { 568 | return EVP_SignUpdate(ctx, d, cnt); 569 | } 570 | 571 | EVP_PKEY *X_EVP_PKEY_new(void) { 572 | return EVP_PKEY_new(); 573 | } 574 | 575 | void X_EVP_PKEY_free(EVP_PKEY *pkey) { 576 | EVP_PKEY_free(pkey); 577 | } 578 | 579 | int X_EVP_PKEY_size(EVP_PKEY *pkey) { 580 | return EVP_PKEY_size(pkey); 581 | } 582 | 583 | struct rsa_st *X_EVP_PKEY_get1_RSA(EVP_PKEY *pkey) { 584 | return EVP_PKEY_get1_RSA(pkey); 585 | } 586 | 587 | int X_EVP_PKEY_set1_RSA(EVP_PKEY *pkey, struct rsa_st *key) { 588 | return EVP_PKEY_set1_RSA(pkey, key); 589 | } 590 | 591 | int X_EVP_PKEY_assign_charp(EVP_PKEY *pkey, int type, char *key) { 592 | return EVP_PKEY_assign(pkey, type, key); 593 | } 594 | 595 | int X_EVP_SignFinal(EVP_MD_CTX *ctx, unsigned char *md, unsigned int *s, EVP_PKEY *pkey) { 596 | return EVP_SignFinal(ctx, md, s, pkey); 597 | } 598 | 599 | int X_EVP_VerifyInit(EVP_MD_CTX *ctx, const EVP_MD *type) { 600 | return EVP_VerifyInit(ctx, type); 601 | } 602 | 603 | int X_EVP_VerifyUpdate(EVP_MD_CTX *ctx, const void *d, 604 | unsigned int cnt) { 605 | return EVP_VerifyUpdate(ctx, d, cnt); 606 | } 607 | 608 | int X_EVP_VerifyFinal(EVP_MD_CTX *ctx, const unsigned char *sigbuf, unsigned int siglen, EVP_PKEY *pkey) { 609 | return EVP_VerifyFinal(ctx, sigbuf, siglen, pkey); 610 | } 611 | 612 | int X_EVP_CIPHER_block_size(EVP_CIPHER *c) { 613 | return EVP_CIPHER_block_size(c); 614 | } 615 | 616 | int X_EVP_CIPHER_key_length(EVP_CIPHER *c) { 617 | return EVP_CIPHER_key_length(c); 618 | } 619 | 620 | int X_EVP_CIPHER_iv_length(EVP_CIPHER *c) { 621 | return EVP_CIPHER_iv_length(c); 622 | } 623 | 624 | int X_EVP_CIPHER_nid(EVP_CIPHER *c) { 625 | return EVP_CIPHER_nid(c); 626 | } 627 | 628 | int X_EVP_CIPHER_CTX_block_size(EVP_CIPHER_CTX *ctx) { 629 | return EVP_CIPHER_CTX_block_size(ctx); 630 | } 631 | 632 | int X_EVP_CIPHER_CTX_key_length(EVP_CIPHER_CTX *ctx) { 633 | return EVP_CIPHER_CTX_key_length(ctx); 634 | } 635 | 636 | int X_EVP_CIPHER_CTX_iv_length(EVP_CIPHER_CTX *ctx) { 637 | return EVP_CIPHER_CTX_iv_length(ctx); 638 | } 639 | 640 | const EVP_CIPHER *X_EVP_CIPHER_CTX_cipher(EVP_CIPHER_CTX *ctx) { 641 | return EVP_CIPHER_CTX_cipher(ctx); 642 | } 643 | 644 | size_t X_HMAC_size(const HMAC_CTX *e) { 645 | return HMAC_size(e); 646 | } 647 | 648 | int X_HMAC_Init_ex(HMAC_CTX *ctx, const void *key, int len, const EVP_MD *md, ENGINE *impl) { 649 | return HMAC_Init_ex(ctx, key, len, md, impl); 650 | } 651 | 652 | int X_HMAC_Update(HMAC_CTX *ctx, const unsigned char *data, size_t len) { 653 | return HMAC_Update(ctx, data, len); 654 | } 655 | 656 | int X_HMAC_Final(HMAC_CTX *ctx, unsigned char *md, unsigned int *len) { 657 | return HMAC_Final(ctx, md, len); 658 | } 659 | 660 | int X_sk_X509_num(STACK_OF(X509) *sk) { 661 | return sk_X509_num(sk); 662 | } 663 | 664 | X509 *X_sk_X509_value(STACK_OF(X509)* sk, int i) { 665 | return sk_X509_value(sk, i); 666 | } 667 | -------------------------------------------------------------------------------- /shim.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2014 Space Monkey, Inc. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * 16 | */ 17 | 18 | #include 19 | #include 20 | 21 | #include 22 | #include 23 | #include 24 | #include 25 | #include 26 | #include 27 | #include 28 | #include 29 | #include 30 | 31 | #ifndef SSL_MODE_RELEASE_BUFFERS 32 | #define SSL_MODE_RELEASE_BUFFERS 0 33 | #endif 34 | 35 | #ifndef SSL_OP_NO_COMPRESSION 36 | #define SSL_OP_NO_COMPRESSION 0 37 | #endif 38 | 39 | /* shim methods */ 40 | extern int X_shim_init(); 41 | 42 | /* Library methods */ 43 | extern void X_OPENSSL_free(void *ref); 44 | 45 | /* SSL methods */ 46 | extern long X_SSL_set_options(SSL* ssl, long options); 47 | extern long X_SSL_get_options(SSL* ssl); 48 | extern long X_SSL_clear_options(SSL* ssl, long options); 49 | extern long X_SSL_set_tlsext_host_name(SSL *ssl, const char *name); 50 | extern const char * X_SSL_get_cipher_name(const SSL *ssl); 51 | extern int X_SSL_session_reused(SSL *ssl); 52 | extern int X_SSL_new_index(); 53 | 54 | extern const SSL_METHOD *X_SSLv23_method(); 55 | extern const SSL_METHOD *X_SSLv3_method(); 56 | extern const SSL_METHOD *X_TLSv1_method(); 57 | extern const SSL_METHOD *X_TLSv1_1_method(); 58 | extern const SSL_METHOD *X_TLSv1_2_method(); 59 | 60 | #if defined SSL_CTRL_SET_TLSEXT_HOSTNAME 61 | extern int sni_cb(SSL *ssl_conn, int *ad, void *arg); 62 | #endif 63 | extern int X_SSL_verify_cb(int ok, X509_STORE_CTX* store); 64 | 65 | /* SSL_CTX methods */ 66 | extern int X_SSL_CTX_new_index(); 67 | extern long X_SSL_CTX_set_options(SSL_CTX* ctx, long options); 68 | extern long X_SSL_CTX_clear_options(SSL_CTX* ctx, long options); 69 | extern long X_SSL_CTX_get_options(SSL_CTX* ctx); 70 | extern long X_SSL_CTX_set_mode(SSL_CTX* ctx, long modes); 71 | extern long X_SSL_CTX_get_mode(SSL_CTX* ctx); 72 | extern long X_SSL_CTX_set_session_cache_mode(SSL_CTX* ctx, long modes); 73 | extern long X_SSL_CTX_sess_set_cache_size(SSL_CTX* ctx, long t); 74 | extern long X_SSL_CTX_sess_get_cache_size(SSL_CTX* ctx); 75 | extern long X_SSL_CTX_set_timeout(SSL_CTX* ctx, long t); 76 | extern long X_SSL_CTX_get_timeout(SSL_CTX* ctx); 77 | extern long X_SSL_CTX_add_extra_chain_cert(SSL_CTX* ctx, X509 *cert); 78 | extern long X_SSL_CTX_set_tmp_ecdh(SSL_CTX* ctx, EC_KEY *key); 79 | extern long X_SSL_CTX_set_tlsext_servername_callback(SSL_CTX* ctx, int (*cb)(SSL *con, int *ad, void *args)); 80 | extern int X_SSL_CTX_verify_cb(int ok, X509_STORE_CTX* store); 81 | extern long X_SSL_CTX_set_tmp_dh(SSL_CTX* ctx, DH *dh); 82 | extern long X_PEM_read_DHparams(SSL_CTX* ctx, DH *dh); 83 | extern int X_SSL_CTX_set_tlsext_ticket_key_cb(SSL_CTX *sslctx, 84 | int (*cb)(SSL *s, unsigned char key_name[16], 85 | unsigned char iv[EVP_MAX_IV_LENGTH], 86 | EVP_CIPHER_CTX *ctx, HMAC_CTX *hctx, int enc)); 87 | extern int X_SSL_CTX_ticket_key_cb(SSL *s, unsigned char key_name[16], 88 | unsigned char iv[EVP_MAX_IV_LENGTH], 89 | EVP_CIPHER_CTX *cctx, HMAC_CTX *hctx, int enc); 90 | 91 | /* BIO methods */ 92 | extern int X_BIO_get_flags(BIO *b); 93 | extern void X_BIO_set_flags(BIO *bio, int flags); 94 | extern void X_BIO_clear_flags(BIO *bio, int flags); 95 | extern void X_BIO_set_data(BIO *bio, void* data); 96 | extern void *X_BIO_get_data(BIO *bio); 97 | extern int X_BIO_read(BIO *b, void *buf, int len); 98 | extern int X_BIO_write(BIO *b, const void *buf, int len); 99 | extern BIO *X_BIO_new_write_bio(); 100 | extern BIO *X_BIO_new_read_bio(); 101 | 102 | /* EVP methods */ 103 | extern const EVP_MD *X_EVP_get_digestbyname(const char *name); 104 | extern EVP_MD_CTX *X_EVP_MD_CTX_new(); 105 | extern void X_EVP_MD_CTX_free(EVP_MD_CTX *ctx); 106 | extern const EVP_MD *X_EVP_md_null(); 107 | extern const EVP_MD *X_EVP_md5(); 108 | extern const EVP_MD *X_EVP_sha(); 109 | extern const EVP_MD *X_EVP_sha1(); 110 | extern const EVP_MD *X_EVP_dss(); 111 | extern const EVP_MD *X_EVP_dss1(); 112 | extern const EVP_MD *X_EVP_ripemd160(); 113 | extern const EVP_MD *X_EVP_sha224(); 114 | extern const EVP_MD *X_EVP_sha256(); 115 | extern const EVP_MD *X_EVP_sha384(); 116 | extern const EVP_MD *X_EVP_sha512(); 117 | extern int X_EVP_MD_size(const EVP_MD *md); 118 | extern int X_EVP_DigestInit_ex(EVP_MD_CTX *ctx, const EVP_MD *type, ENGINE *impl); 119 | extern int X_EVP_DigestUpdate(EVP_MD_CTX *ctx, const void *d, size_t cnt); 120 | extern int X_EVP_DigestFinal_ex(EVP_MD_CTX *ctx, unsigned char *md, unsigned int *s); 121 | extern int X_EVP_SignInit(EVP_MD_CTX *ctx, const EVP_MD *type); 122 | extern int X_EVP_SignUpdate(EVP_MD_CTX *ctx, const void *d, unsigned int cnt); 123 | extern EVP_PKEY *X_EVP_PKEY_new(void); 124 | extern void X_EVP_PKEY_free(EVP_PKEY *pkey); 125 | extern int X_EVP_PKEY_size(EVP_PKEY *pkey); 126 | extern struct rsa_st *X_EVP_PKEY_get1_RSA(EVP_PKEY *pkey); 127 | extern int X_EVP_PKEY_set1_RSA(EVP_PKEY *pkey, struct rsa_st *key); 128 | extern int X_EVP_PKEY_assign_charp(EVP_PKEY *pkey, int type, char *key); 129 | extern int X_EVP_SignFinal(EVP_MD_CTX *ctx, unsigned char *md, unsigned int *s, EVP_PKEY *pkey); 130 | extern int X_EVP_VerifyInit(EVP_MD_CTX *ctx, const EVP_MD *type); 131 | extern int X_EVP_VerifyUpdate(EVP_MD_CTX *ctx, const void *d, unsigned int cnt); 132 | extern int X_EVP_VerifyFinal(EVP_MD_CTX *ctx, const unsigned char *sigbuf, unsigned int siglen, EVP_PKEY *pkey); 133 | extern int X_EVP_CIPHER_block_size(EVP_CIPHER *c); 134 | extern int X_EVP_CIPHER_key_length(EVP_CIPHER *c); 135 | extern int X_EVP_CIPHER_iv_length(EVP_CIPHER *c); 136 | extern int X_EVP_CIPHER_nid(EVP_CIPHER *c); 137 | extern int X_EVP_CIPHER_CTX_block_size(EVP_CIPHER_CTX *ctx); 138 | extern int X_EVP_CIPHER_CTX_key_length(EVP_CIPHER_CTX *ctx); 139 | extern int X_EVP_CIPHER_CTX_iv_length(EVP_CIPHER_CTX *ctx); 140 | extern const EVP_CIPHER *X_EVP_CIPHER_CTX_cipher(EVP_CIPHER_CTX *ctx); 141 | extern int X_EVP_CIPHER_CTX_encrypting(const EVP_CIPHER_CTX *ctx); 142 | 143 | /* HMAC methods */ 144 | extern size_t X_HMAC_size(const HMAC_CTX *e); 145 | extern HMAC_CTX *X_HMAC_CTX_new(void); 146 | extern void X_HMAC_CTX_free(HMAC_CTX *ctx); 147 | extern int X_HMAC_Init_ex(HMAC_CTX *ctx, const void *key, int len, const EVP_MD *md, ENGINE *impl); 148 | extern int X_HMAC_Update(HMAC_CTX *ctx, const unsigned char *data, size_t len); 149 | extern int X_HMAC_Final(HMAC_CTX *ctx, unsigned char *md, unsigned int *len); 150 | 151 | /* X509 methods */ 152 | extern int X_X509_add_ref(X509* x509); 153 | extern const ASN1_TIME *X_X509_get0_notBefore(const X509 *x); 154 | extern const ASN1_TIME *X_X509_get0_notAfter(const X509 *x); 155 | extern int X_sk_X509_num(STACK_OF(X509) *sk); 156 | extern X509 *X_sk_X509_value(STACK_OF(X509)* sk, int i); 157 | 158 | -------------------------------------------------------------------------------- /sni.c: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2017. See AUTHORS. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | #include 16 | #include "_cgo_export.h" 17 | #include 18 | 19 | /* 20 | int sni_cb(SSL *con, int *ad, void *arg) { 21 | SSL_CTX* ssl_ctx = ssl_ctx = SSL_get_SSL_CTX(con); 22 | void* p = SSL_CTX_get_ex_data(ssl_ctx, get_ssl_ctx_idx()); 23 | return sni_cb_thunk(p, con, ad, arg); 24 | } 25 | */ 26 | -------------------------------------------------------------------------------- /ssl.go: -------------------------------------------------------------------------------- 1 | package tls 2 | 3 | // #include "shim.h" 4 | import "C" 5 | import "runtime" 6 | 7 | var ( 8 | ssl_idx = C.X_SSL_new_index() 9 | ) 10 | 11 | //export get_ssl_idx 12 | func get_ssl_idx() C.int { 13 | return ssl_idx 14 | } 15 | 16 | type ssl struct { 17 | ssl *C.SSL 18 | } 19 | 20 | func newSSL(ctx *C.SSL_CTX) (*C.SSL, error) { 21 | runtime.LockOSThread() 22 | defer runtime.UnlockOSThread() 23 | ssl := C.SSL_new(ctx) 24 | if ssl == nil { 25 | return nil, errorFromErrorQueue() 26 | } 27 | return ssl, nil 28 | } 29 | 30 | type SSLTLSExtErr int 31 | 32 | const ( 33 | SSLTLSExtErrOK SSLTLSExtErr = C.SSL_TLSEXT_ERR_OK 34 | SSLTLSExtErrAlertWarning SSLTLSExtErr = C.SSL_TLSEXT_ERR_ALERT_WARNING 35 | SSLTLSEXTErrAlertFatal SSLTLSExtErr = C.SSL_TLSEXT_ERR_ALERT_FATAL 36 | SSLTLSEXTErrNoAck SSLTLSExtErr = C.SSL_TLSEXT_ERR_NOACK 37 | ) 38 | --------------------------------------------------------------------------------