mirror of
https://github.com/refraction-networking/utls.git
synced 2025-04-06 21:47:36 +03:00
new: UtlsPreSharedKeyExtension
In `u_pre_shared_key.go`, create `PreSharedKeyExtension` as an interface, with 3 implementations: - `UtlsPreSharedKeyExtension` implements full support for `pre_shared_key` less resuming after seeing HRR. - `FakePreSharedKeyExtension` uses CipherSuiteID, SessionSecret and Identities to calculate the corresponding binders and send them, without setting the internal states. Therefore if the server accepts the PSK and tries to resume, the connection fails. - `HardcodedPreSharedKeyExtension` allows user to hardcode Identities and Binders to be sent in the extension without setting the internal states. Therefore if the server accepts the PSK and tries to resume, the connection fails. TODO: Only one of FakePreSharedKeyExtension and HardcodedPreSharedKeyExtension should be kept, the other one should be just removed. We still need to learn more of the safety of hardcoding both Identities and Binders without recalculating the latter.
This commit is contained in:
parent
f687104aad
commit
af86ad8176
9 changed files with 590 additions and 228 deletions
|
@ -47,8 +47,8 @@ func ExtensionFromID(id uint16) TLSExtension {
|
|||
return &FakeDelegatedCredentialsExtension{}
|
||||
case extensionSessionTicket:
|
||||
return &SessionTicketExtension{}
|
||||
case extensionPreSharedKey:
|
||||
return &FakePreSharedKeyExtension{}
|
||||
// case extensionPreSharedKey:
|
||||
// return &HardcodedPreSharedKeyExtension{} // TODO: redesign how to create proper PSK from ID
|
||||
// case extensionEarlyData:
|
||||
// return &EarlyDataExtension{}
|
||||
case extensionSupportedVersions:
|
||||
|
@ -1893,175 +1893,3 @@ func (e *FakeDelegatedCredentialsExtension) UnmarshalJSON(data []byte) error {
|
|||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// FakePreSharedKeyExtension is an extension used to set the PSK extension in the
|
||||
// ClientHello.
|
||||
//
|
||||
// Unfortunately, even when the PSK extension is set, there will be no PSK-based
|
||||
// resumption since crypto/tls does not implement PSK.
|
||||
type FakePreSharedKeyExtension struct {
|
||||
PskIdentities []PskIdentity `json:"identities"`
|
||||
PskBinders [][]byte `json:"binders"`
|
||||
}
|
||||
|
||||
func (e *FakePreSharedKeyExtension) writeToUConn(uc *UConn) error {
|
||||
if uc.config.ClientSessionCache == nil {
|
||||
return nil // don't write the extension if there is no session cache
|
||||
}
|
||||
if session, ok := uc.config.ClientSessionCache.Get(uc.clientSessionCacheKey()); !ok || session == nil {
|
||||
return nil // don't write the extension if there is no session cache available for this session
|
||||
}
|
||||
uc.HandshakeState.Hello.PskIdentities = e.PskIdentities
|
||||
uc.HandshakeState.Hello.PskBinders = e.PskBinders
|
||||
return nil
|
||||
}
|
||||
|
||||
func (e *FakePreSharedKeyExtension) Len() int {
|
||||
length := 4 // extension type + extension length
|
||||
length += 2 // identities length
|
||||
for _, identity := range e.PskIdentities {
|
||||
length += 2 + len(identity.Label) + 4 // identity length + identity + obfuscated ticket age
|
||||
}
|
||||
length += 2 // binders length
|
||||
for _, binder := range e.PskBinders {
|
||||
length += len(binder)
|
||||
}
|
||||
return length
|
||||
}
|
||||
|
||||
func (e *FakePreSharedKeyExtension) Read(b []byte) (int, error) {
|
||||
if len(b) < e.Len() {
|
||||
return 0, io.ErrShortBuffer
|
||||
}
|
||||
|
||||
b[0] = byte(extensionPreSharedKey >> 8)
|
||||
b[1] = byte(extensionPreSharedKey)
|
||||
b[2] = byte((e.Len() - 4) >> 8)
|
||||
b[3] = byte(e.Len() - 4)
|
||||
|
||||
// identities length
|
||||
identitiesLength := 0
|
||||
for _, identity := range e.PskIdentities {
|
||||
identitiesLength += 2 + len(identity.Label) + 4 // identity length + identity + obfuscated ticket age
|
||||
}
|
||||
b[4] = byte(identitiesLength >> 8)
|
||||
b[5] = byte(identitiesLength)
|
||||
|
||||
// identities
|
||||
offset := 6
|
||||
for _, identity := range e.PskIdentities {
|
||||
b[offset] = byte(len(identity.Label) >> 8)
|
||||
b[offset+1] = byte(len(identity.Label))
|
||||
offset += 2
|
||||
copy(b[offset:], identity.Label)
|
||||
offset += len(identity.Label)
|
||||
b[offset] = byte(identity.ObfuscatedTicketAge >> 24)
|
||||
b[offset+1] = byte(identity.ObfuscatedTicketAge >> 16)
|
||||
b[offset+2] = byte(identity.ObfuscatedTicketAge >> 8)
|
||||
b[offset+3] = byte(identity.ObfuscatedTicketAge)
|
||||
offset += 4
|
||||
}
|
||||
|
||||
// binders length
|
||||
bindersLength := 0
|
||||
for _, binder := range e.PskBinders {
|
||||
bindersLength += len(binder)
|
||||
}
|
||||
b[offset] = byte(bindersLength >> 8)
|
||||
b[offset+1] = byte(bindersLength)
|
||||
offset += 2
|
||||
|
||||
// binders
|
||||
for _, binder := range e.PskBinders {
|
||||
copy(b[offset:], binder)
|
||||
offset += len(binder)
|
||||
}
|
||||
|
||||
return e.Len(), io.EOF
|
||||
}
|
||||
|
||||
func (e *FakePreSharedKeyExtension) Write(b []byte) (n int, err error) {
|
||||
fullLen := len(b)
|
||||
s := cryptobyte.String(b)
|
||||
|
||||
var identitiesLength uint16
|
||||
if !s.ReadUint16(&identitiesLength) {
|
||||
return 0, errors.New("tls: invalid PSK extension")
|
||||
}
|
||||
|
||||
// identities
|
||||
for identitiesLength > 0 {
|
||||
var identityLength uint16
|
||||
if !s.ReadUint16(&identityLength) {
|
||||
return 0, errors.New("tls: invalid PSK extension")
|
||||
}
|
||||
identitiesLength -= 2
|
||||
|
||||
if identityLength > identitiesLength {
|
||||
return 0, errors.New("tls: invalid PSK extension")
|
||||
}
|
||||
|
||||
var identity []byte
|
||||
if !s.ReadBytes(&identity, int(identityLength)) {
|
||||
return 0, errors.New("tls: invalid PSK extension")
|
||||
}
|
||||
|
||||
identitiesLength -= identityLength // identity
|
||||
|
||||
var obfuscatedTicketAge uint32
|
||||
if !s.ReadUint32(&obfuscatedTicketAge) {
|
||||
return 0, errors.New("tls: invalid PSK extension")
|
||||
}
|
||||
|
||||
e.PskIdentities = append(e.PskIdentities, PskIdentity{
|
||||
Label: identity,
|
||||
ObfuscatedTicketAge: obfuscatedTicketAge,
|
||||
})
|
||||
|
||||
identitiesLength -= 4 // obfuscated ticket age
|
||||
}
|
||||
|
||||
var bindersLength uint16
|
||||
if !s.ReadUint16(&bindersLength) {
|
||||
return 0, errors.New("tls: invalid PSK extension")
|
||||
}
|
||||
|
||||
// binders
|
||||
for bindersLength > 0 {
|
||||
var binderLength uint8
|
||||
if !s.ReadUint8(&binderLength) {
|
||||
return 0, errors.New("tls: invalid PSK extension")
|
||||
}
|
||||
bindersLength -= 1
|
||||
|
||||
if uint16(binderLength) > bindersLength {
|
||||
return 0, errors.New("tls: invalid PSK extension")
|
||||
}
|
||||
|
||||
var binder []byte
|
||||
if !s.ReadBytes(&binder, int(binderLength)) {
|
||||
return 0, errors.New("tls: invalid PSK extension")
|
||||
}
|
||||
|
||||
e.PskBinders = append(e.PskBinders, binder)
|
||||
|
||||
bindersLength -= uint16(binderLength)
|
||||
}
|
||||
|
||||
return fullLen, nil
|
||||
}
|
||||
|
||||
func (e *FakePreSharedKeyExtension) UnmarshalJSON(data []byte) error {
|
||||
var pskAccepter struct {
|
||||
PskIdentities []PskIdentity `json:"identities"`
|
||||
PskBinders [][]byte `json:"binders"`
|
||||
}
|
||||
|
||||
if err := json.Unmarshal(data, &pskAccepter); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
e.PskIdentities = pskAccepter.PskIdentities
|
||||
e.PskBinders = pskAccepter.PskBinders
|
||||
return nil
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue