github.com/Carcraftz/utls@v0.0.0-20220413235215-6b7c52fd78b6/CONTRIBUTORS_GUIDE.md (about) 1 # How this package works 2 ### Chapter 1: [Making private things public](./u_public.go) 3 There are numerous handshake-related structs in crypto/tls, most of which are either private or have private fields. 4 One of them — `clientHandshakeState` — has private function `handshake()`, 5 which is called in the beginning of default handshake. 6 Unfortunately, user will not be able to directly access this struct outside of tls package. 7 As a result, we decided to employ following workaround: declare public copies of private structs. 8 Now user is free to manipulate fields of public `ClientHandshakeState`. 9 Then, right before handshake, we can shallow-copy public state into private `clientHandshakeState`, 10 call `handshake()` on it and carry on with default Golang handshake process. 11 After handshake is done we shallow-copy private state back to public, allowing user to read results of handshake. 12 13 ### Chapter 2: [TLSExtension](./u_tls_extensions.go) 14 The way we achieve reasonable flexibilty with extensions is inspired by 15 [ztls'](https://github.com/zmap/zcrypto/blob/master/tls/handshake_extensions.go) design. 16 However, our design has several differences, so we wrote it from scratch. 17 This design allows us to have an array of `TLSExtension` objects and then marshal them in order: 18 ```Golang 19 type TLSExtension interface { 20 writeToUConn(*UConn) error 21 22 Len() int // includes header 23 24 // Read reads up to len(p) bytes into p. 25 // It returns the number of bytes read (0 <= n <= len(p)) and any error encountered. 26 Read(p []byte) (n int, err error) // implements io.Reader 27 } 28 ``` 29 `writeToUConn()` applies appropriate per-extension changes to `UConn`. 30 31 `Len()` provides the size of marshaled extension, so we can allocate appropriate buffer beforehand, 32 catch out-of-bound errors easily and guide size-dependent extensions such as padding. 33 34 `Read(buffer []byte)` _writes(see: io.Reader interface)_ marshaled extensions into provided buffer. 35 This avoids extra allocations. 36 37 ### Chapter 3: [UConn](./u_conn.go) 38 `UConn` extends standard `tls.Conn`. Most notably, it stores slice with `TLSExtension`s and public 39 `ClientHandshakeState`. 40 Whenever `UConn.BuildHandshakeState()` gets called (happens automatically in `UConn.Handshake()` 41 or could be called manually), config will be applied according to chosen `ClientHelloID`. 42 From contributor's view there are 2 main behaviors: 43 * `HelloGolang` simply calls default Golang's [`makeClientHello()`](./handshake_client.go) 44 and directly stores it into `HandshakeState.Hello`. utls-specific stuff is ignored. 45 * Other ClientHelloIDs fill `UConn.Hello.{Random, CipherSuites, CompressionMethods}` and `UConn.Extensions` with 46 per-parrot setup, which then gets applied to appropriate standard tls structs, 47 and then marshaled by utls into `HandshakeState.Hello`. 48 49 ### Chapter 4: Tests 50 51 Tests exist, but coverage is very limited. What's covered is a conjunction of 52 * TLS 1.2 53 * Working parrots without any unsupported extensions (only Android 5.1 at this time) 54 * Ciphersuites offered by parrot. 55 * Ciphersuites supported by Golang 56 * Simple conversation with reference implementation of OpenSSL. 57 (e.g. no automatic checks for renegotiations, parroting quality and such) 58 59 plus we test some other minor things. 60 Basically, current tests aim to provide a sanity check. 61 62 # Merging upstream 63 ```Bash 64 git remote add -f golang git@github.com:golang/go.git 65 git checkout -b golang-upstream golang/master 66 git subtree split -P src/crypto/tls/ -b golang-tls-upstream 67 git checkout master 68 git merge --no-commit golang-tls-upstream 69 ```