2018-01-03 19:19:49 +00:00
|
|
|
package mint
|
|
|
|
|
|
|
|
import (
|
|
|
|
"fmt"
|
|
|
|
"strconv"
|
|
|
|
)
|
|
|
|
|
|
|
|
const (
|
2018-01-17 04:32:31 +00:00
|
|
|
supportedVersion uint16 = 0x7f16 // draft-22
|
|
|
|
tls12Version uint16 = 0x0303
|
|
|
|
tls10Version uint16 = 0x0301
|
|
|
|
dtls12WireVersion uint16 = 0xfefd
|
2018-01-03 19:19:49 +00:00
|
|
|
)
|
|
|
|
|
|
|
|
var (
|
|
|
|
// Flags for some minor compat issues
|
|
|
|
allowWrongVersionNumber = true
|
|
|
|
allowPKCS1 = true
|
|
|
|
)
|
|
|
|
|
|
|
|
// enum {...} ContentType;
|
|
|
|
type RecordType byte
|
|
|
|
|
|
|
|
const (
|
|
|
|
RecordTypeAlert RecordType = 21
|
|
|
|
RecordTypeHandshake RecordType = 22
|
|
|
|
RecordTypeApplicationData RecordType = 23
|
|
|
|
)
|
|
|
|
|
|
|
|
// enum {...} HandshakeType;
|
|
|
|
type HandshakeType byte
|
|
|
|
|
|
|
|
const (
|
|
|
|
// Omitted: *_RESERVED
|
|
|
|
HandshakeTypeClientHello HandshakeType = 1
|
|
|
|
HandshakeTypeServerHello HandshakeType = 2
|
|
|
|
HandshakeTypeNewSessionTicket HandshakeType = 4
|
|
|
|
HandshakeTypeEndOfEarlyData HandshakeType = 5
|
|
|
|
HandshakeTypeHelloRetryRequest HandshakeType = 6
|
|
|
|
HandshakeTypeEncryptedExtensions HandshakeType = 8
|
|
|
|
HandshakeTypeCertificate HandshakeType = 11
|
|
|
|
HandshakeTypeCertificateRequest HandshakeType = 13
|
|
|
|
HandshakeTypeCertificateVerify HandshakeType = 15
|
|
|
|
HandshakeTypeServerConfiguration HandshakeType = 17
|
|
|
|
HandshakeTypeFinished HandshakeType = 20
|
|
|
|
HandshakeTypeKeyUpdate HandshakeType = 24
|
|
|
|
HandshakeTypeMessageHash HandshakeType = 254
|
|
|
|
)
|
|
|
|
|
|
|
|
var hrrRandomSentinel = [32]byte{
|
|
|
|
0xcf, 0x21, 0xad, 0x74, 0xe5, 0x9a, 0x61, 0x11,
|
|
|
|
0xbe, 0x1d, 0x8c, 0x02, 0x1e, 0x65, 0xb8, 0x91,
|
|
|
|
0xc2, 0xa2, 0x11, 0x16, 0x7a, 0xbb, 0x8c, 0x5e,
|
|
|
|
0x07, 0x9e, 0x09, 0xe2, 0xc8, 0xa8, 0x33, 0x9c,
|
|
|
|
}
|
|
|
|
|
|
|
|
// uint8 CipherSuite[2];
|
|
|
|
type CipherSuite uint16
|
|
|
|
|
|
|
|
const (
|
|
|
|
// XXX: Actually TLS_NULL_WITH_NULL_NULL, but we need a way to label the zero
|
|
|
|
// value for this type so that we can detect when a field is set.
|
|
|
|
CIPHER_SUITE_UNKNOWN CipherSuite = 0x0000
|
|
|
|
TLS_AES_128_GCM_SHA256 CipherSuite = 0x1301
|
|
|
|
TLS_AES_256_GCM_SHA384 CipherSuite = 0x1302
|
|
|
|
TLS_CHACHA20_POLY1305_SHA256 CipherSuite = 0x1303
|
|
|
|
TLS_AES_128_CCM_SHA256 CipherSuite = 0x1304
|
|
|
|
TLS_AES_256_CCM_8_SHA256 CipherSuite = 0x1305
|
|
|
|
)
|
|
|
|
|
|
|
|
func (c CipherSuite) String() string {
|
|
|
|
switch c {
|
|
|
|
case CIPHER_SUITE_UNKNOWN:
|
|
|
|
return "unknown"
|
|
|
|
case TLS_AES_128_GCM_SHA256:
|
|
|
|
return "TLS_AES_128_GCM_SHA256"
|
|
|
|
case TLS_AES_256_GCM_SHA384:
|
|
|
|
return "TLS_AES_256_GCM_SHA384"
|
|
|
|
case TLS_CHACHA20_POLY1305_SHA256:
|
|
|
|
return "TLS_CHACHA20_POLY1305_SHA256"
|
|
|
|
case TLS_AES_128_CCM_SHA256:
|
|
|
|
return "TLS_AES_128_CCM_SHA256"
|
|
|
|
case TLS_AES_256_CCM_8_SHA256:
|
|
|
|
return "TLS_AES_256_CCM_8_SHA256"
|
|
|
|
}
|
|
|
|
// cannot use %x here, since it calls String(), leading to infinite recursion
|
|
|
|
return fmt.Sprintf("invalid CipherSuite value: 0x%s", strconv.FormatUint(uint64(c), 16))
|
|
|
|
}
|
|
|
|
|
|
|
|
// enum {...} SignatureScheme
|
|
|
|
type SignatureScheme uint16
|
|
|
|
|
|
|
|
const (
|
|
|
|
// RSASSA-PKCS1-v1_5 algorithms
|
|
|
|
RSA_PKCS1_SHA1 SignatureScheme = 0x0201
|
|
|
|
RSA_PKCS1_SHA256 SignatureScheme = 0x0401
|
|
|
|
RSA_PKCS1_SHA384 SignatureScheme = 0x0501
|
|
|
|
RSA_PKCS1_SHA512 SignatureScheme = 0x0601
|
|
|
|
// ECDSA algorithms
|
|
|
|
ECDSA_P256_SHA256 SignatureScheme = 0x0403
|
|
|
|
ECDSA_P384_SHA384 SignatureScheme = 0x0503
|
|
|
|
ECDSA_P521_SHA512 SignatureScheme = 0x0603
|
|
|
|
// RSASSA-PSS algorithms
|
|
|
|
RSA_PSS_SHA256 SignatureScheme = 0x0804
|
|
|
|
RSA_PSS_SHA384 SignatureScheme = 0x0805
|
|
|
|
RSA_PSS_SHA512 SignatureScheme = 0x0806
|
|
|
|
// EdDSA algorithms
|
|
|
|
Ed25519 SignatureScheme = 0x0807
|
|
|
|
Ed448 SignatureScheme = 0x0808
|
|
|
|
)
|
|
|
|
|
|
|
|
// enum {...} ExtensionType
|
|
|
|
type ExtensionType uint16
|
|
|
|
|
|
|
|
const (
|
|
|
|
ExtensionTypeServerName ExtensionType = 0
|
|
|
|
ExtensionTypeSupportedGroups ExtensionType = 10
|
|
|
|
ExtensionTypeSignatureAlgorithms ExtensionType = 13
|
|
|
|
ExtensionTypeALPN ExtensionType = 16
|
|
|
|
ExtensionTypeKeyShare ExtensionType = 40
|
|
|
|
ExtensionTypePreSharedKey ExtensionType = 41
|
|
|
|
ExtensionTypeEarlyData ExtensionType = 42
|
|
|
|
ExtensionTypeSupportedVersions ExtensionType = 43
|
|
|
|
ExtensionTypeCookie ExtensionType = 44
|
|
|
|
ExtensionTypePSKKeyExchangeModes ExtensionType = 45
|
|
|
|
ExtensionTypeTicketEarlyDataInfo ExtensionType = 46
|
|
|
|
)
|
|
|
|
|
|
|
|
// enum {...} NamedGroup
|
|
|
|
type NamedGroup uint16
|
|
|
|
|
|
|
|
const (
|
|
|
|
// Elliptic Curve Groups.
|
|
|
|
P256 NamedGroup = 23
|
|
|
|
P384 NamedGroup = 24
|
|
|
|
P521 NamedGroup = 25
|
|
|
|
// ECDH functions.
|
|
|
|
X25519 NamedGroup = 29
|
|
|
|
X448 NamedGroup = 30
|
|
|
|
// Finite field groups.
|
|
|
|
FFDHE2048 NamedGroup = 256
|
|
|
|
FFDHE3072 NamedGroup = 257
|
|
|
|
FFDHE4096 NamedGroup = 258
|
|
|
|
FFDHE6144 NamedGroup = 259
|
|
|
|
FFDHE8192 NamedGroup = 260
|
|
|
|
)
|
|
|
|
|
|
|
|
// enum {...} PskKeyExchangeMode;
|
|
|
|
type PSKKeyExchangeMode uint8
|
|
|
|
|
|
|
|
const (
|
|
|
|
PSKModeKE PSKKeyExchangeMode = 0
|
|
|
|
PSKModeDHEKE PSKKeyExchangeMode = 1
|
|
|
|
)
|
|
|
|
|
|
|
|
// enum {
|
|
|
|
// update_not_requested(0), update_requested(1), (255)
|
|
|
|
// } KeyUpdateRequest;
|
|
|
|
type KeyUpdateRequest uint8
|
|
|
|
|
|
|
|
const (
|
|
|
|
KeyUpdateNotRequested KeyUpdateRequest = 0
|
|
|
|
KeyUpdateRequested KeyUpdateRequest = 1
|
|
|
|
)
|
|
|
|
|
|
|
|
type State uint8
|
|
|
|
|
|
|
|
const (
|
|
|
|
// states valid for the client
|
|
|
|
StateClientStart State = iota
|
|
|
|
StateClientWaitSH
|
|
|
|
StateClientWaitEE
|
|
|
|
StateClientWaitCert
|
|
|
|
StateClientWaitCV
|
|
|
|
StateClientWaitFinished
|
|
|
|
StateClientWaitCertCR
|
|
|
|
StateClientConnected
|
|
|
|
// states valid for the server
|
|
|
|
StateServerStart State = iota
|
|
|
|
StateServerRecvdCH
|
|
|
|
StateServerNegotiated
|
|
|
|
StateServerWaitEOED
|
|
|
|
StateServerWaitFlight2
|
|
|
|
StateServerWaitCert
|
|
|
|
StateServerWaitCV
|
|
|
|
StateServerWaitFinished
|
|
|
|
StateServerConnected
|
|
|
|
)
|
|
|
|
|
|
|
|
func (s State) String() string {
|
|
|
|
switch s {
|
|
|
|
case StateClientStart:
|
|
|
|
return "Client START"
|
|
|
|
case StateClientWaitSH:
|
|
|
|
return "Client WAIT_SH"
|
|
|
|
case StateClientWaitEE:
|
|
|
|
return "Client WAIT_EE"
|
|
|
|
case StateClientWaitCert:
|
|
|
|
return "Client WAIT_CERT"
|
|
|
|
case StateClientWaitCV:
|
|
|
|
return "Client WAIT_CV"
|
|
|
|
case StateClientWaitFinished:
|
|
|
|
return "Client WAIT_FINISHED"
|
|
|
|
case StateClientConnected:
|
|
|
|
return "Client CONNECTED"
|
|
|
|
case StateServerStart:
|
|
|
|
return "Server START"
|
|
|
|
case StateServerRecvdCH:
|
|
|
|
return "Server RECVD_CH"
|
|
|
|
case StateServerNegotiated:
|
|
|
|
return "Server NEGOTIATED"
|
|
|
|
case StateServerWaitEOED:
|
|
|
|
return "Server WAIT_EOED"
|
|
|
|
case StateServerWaitFlight2:
|
|
|
|
return "Server WAIT_FLIGHT2"
|
|
|
|
case StateServerWaitCert:
|
|
|
|
return "Server WAIT_CERT"
|
|
|
|
case StateServerWaitCV:
|
|
|
|
return "Server WAIT_CV"
|
|
|
|
case StateServerWaitFinished:
|
|
|
|
return "Server WAIT_FINISHED"
|
|
|
|
case StateServerConnected:
|
|
|
|
return "Server CONNECTED"
|
|
|
|
default:
|
|
|
|
return fmt.Sprintf("unknown state: %d", s)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Epochs for DTLS (also used for key phase labelling)
|
|
|
|
type Epoch uint16
|
|
|
|
|
|
|
|
const (
|
|
|
|
EpochClear Epoch = 0
|
|
|
|
EpochEarlyData Epoch = 1
|
|
|
|
EpochHandshakeData Epoch = 2
|
|
|
|
EpochApplicationData Epoch = 3
|
|
|
|
EpochUpdate Epoch = 4
|
|
|
|
)
|
|
|
|
|
|
|
|
func (e Epoch) label() string {
|
|
|
|
switch e {
|
|
|
|
case EpochClear:
|
|
|
|
return "clear"
|
|
|
|
case EpochEarlyData:
|
|
|
|
return "early data"
|
|
|
|
case EpochHandshakeData:
|
|
|
|
return "handshake"
|
|
|
|
case EpochApplicationData:
|
|
|
|
return "application data"
|
|
|
|
}
|
|
|
|
return "Application data (updated)"
|
|
|
|
}
|