refactor+feat: Custom Client Handshake + Implement ALPS extension (#142)

* refactor: split `CompressCertExtension` changes

- Split most of changes for `CompressCertExtension` made to `crypto/tls` files out and moved them to `u_` files.
- Edited some `crypto/tls` files to achieve better programmability for uTLS.
- Minor styling fix.

* feat: implement ALPS Extension draft

- Made necessary modifications to existing types to support ALPS.
- Ported `ApplicationSettingsExtension` implementation from `ulixee/utls` by @blakebyrnes with some adaptation.

Co-Authored-By: Blake Byrnes <115056+blakebyrnes@users.noreply.github.com>

* feat: utlsFakeCustomExtension in ALPS

- Introducing `utlsFakeCustomExtension` to enable implementation for custom extensions to be exchanged via ALPS.
- currently it doesn't do anything.

Co-Authored-By: Blake Byrnes <115056+blakebyrnes@users.noreply.github.com>

* fix: magic number in `StatusRequestV2Extension`

- Fixed magic number `17` in `StatusRequestV2Extension` with pre-defined enum `extensionStatusRequestV2`.

Co-authored-by: Blake Byrnes <115056+blakebyrnes@users.noreply.github.com>
This commit is contained in:
Gaukas Wang 2022-11-17 14:04:29 -07:00 committed by GitHub
parent 1b3a9ad4c5
commit fb99df2a2e
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
13 changed files with 375 additions and 140 deletions

View file

@ -1,3 +1,7 @@
// Copyright 2022 uTLS Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package tls
import (
@ -8,7 +12,7 @@ import (
// Alternate certificate message formats (https://datatracker.ietf.org/doc/html/rfc7250) are not
// supported.
// https://datatracker.ietf.org/doc/html/rfc8879
type compressedCertificateMsg struct {
type utlsCompressedCertificateMsg struct {
raw []byte
algorithm uint16
@ -16,13 +20,13 @@ type compressedCertificateMsg struct {
compressedCertificateMessage []byte
}
func (m *compressedCertificateMsg) marshal() []byte {
func (m *utlsCompressedCertificateMsg) marshal() []byte {
if m.raw != nil {
return m.raw
}
var b cryptobyte.Builder
b.AddUint8(typeCompressedCertificate)
b.AddUint8(utlsTypeCompressedCertificate)
b.AddUint24LengthPrefixed(func(b *cryptobyte.Builder) {
b.AddUint16(m.algorithm)
b.AddUint24(m.uncompressedLength)
@ -35,8 +39,8 @@ func (m *compressedCertificateMsg) marshal() []byte {
return m.raw
}
func (m *compressedCertificateMsg) unmarshal(data []byte) bool {
*m = compressedCertificateMsg{raw: data}
func (m *utlsCompressedCertificateMsg) unmarshal(data []byte) bool {
*m = utlsCompressedCertificateMsg{raw: data}
s := cryptobyte.String(data)
if !s.Skip(4) || // message type and uint24 length field
@ -47,3 +51,83 @@ func (m *compressedCertificateMsg) unmarshal(data []byte) bool {
}
return true
}
type utlsEncryptedExtensionsMsgExtraFields struct {
hasApplicationSettings bool
applicationSettings []byte
customExtension []byte
}
func (m *encryptedExtensionsMsg) utlsUnmarshal(extension uint16, extData cryptobyte.String) bool {
switch extension {
case utlsExtensionApplicationSettings:
m.utls.hasApplicationSettings = true
m.utls.applicationSettings = []byte(extData)
}
return true // success/unknown extension
}
type utlsClientEncryptedExtensionsMsg struct {
raw []byte
applicationSettings []byte
hasApplicationSettings bool
customExtension []byte
}
func (m *utlsClientEncryptedExtensionsMsg) marshal() (x []byte) {
if m.raw != nil {
return m.raw
}
var builder cryptobyte.Builder
builder.AddUint8(typeEncryptedExtensions)
builder.AddUint24LengthPrefixed(func(body *cryptobyte.Builder) {
body.AddUint16LengthPrefixed(func(extensions *cryptobyte.Builder) {
if m.hasApplicationSettings {
extensions.AddUint16(utlsExtensionApplicationSettings)
extensions.AddUint16LengthPrefixed(func(msg *cryptobyte.Builder) {
msg.AddBytes(m.applicationSettings)
})
}
if len(m.customExtension) > 0 {
extensions.AddUint16(utlsFakeExtensionCustom)
extensions.AddUint16LengthPrefixed(func(msg *cryptobyte.Builder) {
msg.AddBytes(m.customExtension)
})
}
})
})
m.raw = builder.BytesOrPanic()
return m.raw
}
func (m *utlsClientEncryptedExtensionsMsg) unmarshal(data []byte) bool {
*m = utlsClientEncryptedExtensionsMsg{raw: data}
s := cryptobyte.String(data)
var extensions cryptobyte.String
if !s.Skip(4) || // message type and uint24 length field
!s.ReadUint16LengthPrefixed(&extensions) || !s.Empty() {
return false
}
for !extensions.Empty() {
var extension uint16
var extData cryptobyte.String
if !extensions.ReadUint16(&extension) ||
!extensions.ReadUint16LengthPrefixed(&extData) {
return false
}
switch extension {
case utlsExtensionApplicationSettings:
m.hasApplicationSettings = true
m.applicationSettings = []byte(extData)
default:
// Unknown extensions are illegal in EncryptedExtensions.
return false
}
}
return true
}