l4openvpn

package
v0.0.0-...-ec8fae2 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Nov 4, 2024 License: Apache-2.0 Imports: 27 Imported by: 0

Documentation

Index

Constants

View Source
const (
	AuthHMACBytesMax = sha512.Size
	AuthHMACBytesMin = md5.Size

	CryptHMACBytesTotal = sha256.Size

	StaticKeyBytesTotal   = 256
	StaticKeyBytesHalf    = StaticKeyBytesTotal / 2
	StaticKeyBytesQuarter = StaticKeyBytesTotal / 4
)
View Source
const (
	GroupKeyDirectionBidi    = "bidi"
	GroupKeyDirectionBidi2   = "bidirectional"
	GroupKeyDirectionInverse = "inverse"
	GroupKeyDirectionNormal  = "normal"

	ModeAuth   = "auth"
	ModeCrypt  = "crypt"
	ModeCrypt2 = "crypt2"
	ModePlain  = "plain"
)
View Source
const (
	OpcodeControlHardResetClientV2 uint8 = 7
	OpcodeControlHardResetClientV3 uint8 = 10

	KeyIDMask uint8 = 0b1<<OpcodeShift - 1

	OpcodeShift = 3

	AckPacketIDsCountBytesTotal = 1
	LengthBytesTotal            = 2
	MetaDataPayloadBytesMax     = WrappedKeyBytesMax - MetaDataTypeBytesTotal - WrappedKeyBytesMin
	MetaDataTypeBytesTotal      = 1
	OpcodeKeyIDBytesTotal       = 1
	PacketIDBytesTotal          = 4
	SessionIDBytesTotal         = 8
	TimestampBytesTotal         = 4

	WrappedKeyBytesMax = 1024
	WrappedKeyBytesMin = CryptHMACBytesTotal + StaticKeyBytesTotal + LengthBytesTotal

	TimestampValidationInterval = 15 * time.Second

	MessagePlainBytesTotalHL = SessionIDBytesTotal + AckPacketIDsCountBytesTotal + PacketIDBytesTotal
	MessagePlainBytesTotal   = OpcodeKeyIDBytesTotal + MessagePlainBytesTotalHL
	MessageAuthBytesMaxHL    = MessagePlainBytesTotalHL + AuthHMACBytesMax + PacketIDBytesTotal + TimestampBytesTotal
	MessageAuthBytesMax      = OpcodeKeyIDBytesTotal + MessageAuthBytesMaxHL
	MessageAuthBytesMinHL    = MessagePlainBytesTotalHL + AuthHMACBytesMin + PacketIDBytesTotal + TimestampBytesTotal
	MessageAuthBytesMin      = OpcodeKeyIDBytesTotal + MessageAuthBytesMinHL
	MessageCryptBytesTotalHL = MessagePlainBytesTotalHL + PacketIDBytesTotal + TimestampBytesTotal + CryptHMACBytesTotal
	MessageCryptBytesTotal   = OpcodeKeyIDBytesTotal + MessageCryptBytesTotalHL
	MessageCrypt2BytesMinHL  = MessageCryptBytesTotalHL + LengthBytesTotal + CryptHMACBytesTotal + StaticKeyBytesTotal
	MessageCrypt2BytesMin    = OpcodeKeyIDBytesTotal + MessageCrypt2BytesMinHL
	MessageCrypt2BytesMaxHL  = MessageCrypt2BytesMinHL + MetaDataTypeBytesTotal + MetaDataPayloadBytesMax
	MessageCrypt2BytesMax    = OpcodeKeyIDBytesTotal + MessageCrypt2BytesMaxHL
)

Variables

View Source
var (
	ErrInvalidAuthDigest        = errors.New("invalid auth digest")
	ErrInvalidClientKey         = errors.New("invalid client key")
	ErrInvalidGroupKey          = errors.New("invalid group key")
	ErrInvalidGroupKeyDirection = errors.New("invalid group key direction")
	ErrInvalidMode              = errors.New("invalid mode")
	ErrInvalidServerKey         = errors.New("invalid server key")
)
View Source
var (
	BytesOrder = binary.BigEndian

	ErrInvalidAuthPrerequisites  = errors.New("invalid auth prerequisites")
	ErrInvalidCryptPrerequisites = errors.New("invalid crypt prerequisites")
	ErrInvalidEncryptedLength    = errors.New("invalid encrypted length")
	ErrInvalidHeaderOpcode       = errors.New("invalid header opcode")
	ErrInvalidHMACLength         = errors.New("invalid HMAC length")
	ErrInvalidPlainLength        = errors.New("invalid plain length")
	ErrInvalidSourceLength       = errors.New("invalid source length")
	ErrMissingReusableHeader     = errors.New("missing reusable header")
)
View Source
var AuthDigestDefault = AuthDigestFindByName("SHA-256")

AuthDigestDefault is the default AuthDigest used in the crypt and crypt2 modes (SHA-256).

View Source
var AuthDigestSizes = func() []int {
	presence := make([]bool, AuthHMACBytesMax+1)
	n := 0
	for _, ad := range AuthDigests {
		if !presence[ad.Size] {
			n++
			presence[ad.Size] = true
		}
	}
	sizes := make([]int, 0, n)
	for i, present := range presence {
		if present {
			sizes = append(sizes, i)
		}
	}
	return sizes
}()

AuthDigestSizes contains sizes of all the supported items of AuthDigest type.

View Source
var AuthDigests = []*AuthDigest{

	{Creator: md5.New, Names: []string{"MD5", "SSL3-MD5", "md5", "ssl3-md5"}, Size: md5.Size},
	{Creator: sha1.New, Names: []string{"SHA-1", "SHA1", "SSL3-SHA1", "sha-1", "sha1", "ssl3-sha1"}, Size: sha1.Size},
	{Creator: ripemd160.New, Names: []string{"RIPEMD-160", "RMD-160", "RIPEMD160", "RIPEMD", "RMD160", "ripemd-160", "rmd-160", "ripemd160", "ripemd", "rmd160"}, Size: ripemd160.Size},

	{Creator: sha256.New224, Names: []string{"SHA-224", "SHA2-224", "SHA224", "sha-224", "sha2-224", "sha224"}, Size: sha256.Size224},
	{Creator: sha256.New, Names: []string{"SHA-256", "SHA2-256", "SHA256", "sha-256", "sha2-256", "sha256"}, Size: sha256.Size},
	{Creator: sha512.New384, Names: []string{"SHA-384", "SHA2-384", "SHA384", "sha-384", "sha2-384", "sha384"}, Size: sha512.Size384},
	{Creator: sha512.New, Names: []string{"SHA-512", "SHA2-512", "SHA512", "sha-512", "sha2-512", "sha512"}, Size: sha512.Size},
	{Creator: sha512.New512_224, Names: []string{"SHA-512/224", "SHA2-512/224", "SHA512-224", "sha-512/224", "sha2-512/224", "sha512-224"}, Size: sha512.Size224},
	{Creator: sha512.New512_256, Names: []string{"SHA-512/256", "SHA2-512/256", "SHA512-256", "sha-512/256", "sha2-512/256", "sha512-256"}, Size: sha512.Size256},

	{Creator: sha3.New224, Names: []string{"SHA3-224", "sha3-224"}, Size: 28},
	{Creator: sha3.New256, Names: []string{"SHA3-256", "sha3-256"}, Size: 32},
	{Creator: sha3.New384, Names: []string{"SHA3-384", "sha3-384"}, Size: 48},
	{Creator: sha3.New512, Names: []string{"SHA3-512", "sha3-512"}, Size: 64},

	{
		Creator: func() hash.Hash {
			h, _ := blake2s.New256(nil)
			return h
		},
		Names: []string{"BLAKE2s-256", "BLAKE2S-256", "blake2s-256", "blake2S-256"},
		Size:  blake2s.Size,
	},
	{
		Creator: func() hash.Hash {
			h, _ := blake2b.New512(nil)
			return h
		},
		Names: []string{"BLAKE2b-512", "BLAKE2B-512", "blake2b-512", "blake2B-512"},
		Size:  blake2b.Size,
	},

	{
		Creator: func() hash.Hash {
			return sha3.NewShake128()
		},
		Names: []string{"SHAKE-128", "SHAKE128", "shake-128", "shake128"},
		Size:  32,
	},
	{
		Creator: func() hash.Hash {
			return sha3.NewShake256()
		},
		Names: []string{"SHAKE-256", "SHAKE256", "shake-256", "shake256"},
		Size:  64,
	},

	{

		Generator: func(key, plain []byte) []byte {
			hmacMD5 := hmac.New(md5.New, key[:md5.Size])
			hmacMD5.Write(plain)
			hmacSHA1 := hmac.New(sha1.New, key[:sha1.Size])
			hmacSHA1.Write(plain)
			result := make([]byte, 0, md5.Size+sha1.Size)
			return hmacSHA1.Sum(hmacMD5.Sum(result))
		},
		Names: []string{"MD5+SHA1", "MD5-SHA1", "MD5SHA1", "md5+sha1", "md5-sha1", "md5sha1"},
		Size:  md5.Size + sha1.Size,
	},
}

AuthDigests contains all the supported items of AuthDigest type.

View Source
var CryptCipherDefault = CryptCipherFindByName("AES-256-CTR")

CryptCipherDefault is the default CryptCipher used in the crypt and crypt2 modes (AES-256-CTR).

View Source
var CryptCiphers = []*CryptCipher{
	{
		Decryptor: func(key, iv, encrypted []byte) []byte {
			plain := make([]byte, len(encrypted))
			block, _ := aes.NewCipher(key)
			ctr := cipher.NewCTR(block, iv)
			ctr.XORKeyStream(plain, encrypted)
			return plain
		},
		Encryptor: func(key, iv, plain []byte) []byte {
			encrypted := make([]byte, len(plain))
			block, _ := aes.NewCipher(key)
			ctr := cipher.NewCTR(block, iv)
			ctr.XORKeyStream(encrypted, plain)
			return encrypted
		},
		Names:     []string{"AES-256-CTR", "aes-256-ctr"},
		SizeBlock: 16,
		SizeKey:   32,
	},
}

CryptCiphers contains all the supported items of CryptCipher type.

View Source
var (
	ErrInvalidStaticKeyFileContents = errors.New("invalid static key file contents")
)
View Source
var StaticKeyFromFileBase64 = regexp.MustCompile("^(?:#.*?\\r?\\n)*" +
	"-----BEGIN OpenVPN tls-crypt-v2 (?:client|server) key-----\\r?\\n" +
	"([0-9a-zA-Z+=\\/\\r\\n]+)" +
	"-----END OpenVPN tls-crypt-v2 (?:client|server) key-----(?:\\r?\\n)?$")
View Source
var StaticKeyFromFileHex = regexp.MustCompile("^(?:#.*?\\r?\\n)*" +
	"-----BEGIN OpenVPN Static key V1-----\\r?\\n" +
	"([0-9a-fA-F\\r\\n]+)" +
	"-----END OpenVPN Static key V1-----(?:\\r?\\n)?$")

Functions

func HMACCreateAndGenerate

func HMACCreateAndGenerate(creator func() hash.Hash, key, plain []byte) []byte

HMACCreateAndGenerate uses a given digest creator to compute an HMAC of a given plain text with a given key.

Types

type AuthDigest

type AuthDigest struct {
	// Creator is a function returning something that implements hash.Hash interface.
	// Creator is required whenever Generator is nil.
	Creator func() hash.Hash
	// Generator is a function returning an HMAC for a given set of key and plain bytes.
	// Generator is optional, but it takes precedence over Creator.
	Generator func(key, plain []byte) []byte
	// Names contains a list of digest names in various notations.
	Names []string
	// Size is a number of bytes all computed HMACs will have.
	Size int
}

AuthDigest represents a digest used for computing HMACs of control messages.

func AuthDigestFindByName

func AuthDigestFindByName(name string) *AuthDigest

AuthDigestFindByName returns a pointer to AuthDigest having a given name or nil.

func (*AuthDigest) HMACGenerateOnClient

func (ad *AuthDigest) HMACGenerateOnClient(sk *StaticKey, plain []byte) []byte

HMACGenerateOnClient computes an HMAC of a given plain text with a part of a given StaticKey (to be sent by the client to the server).

func (*AuthDigest) HMACGenerateOnServer

func (ad *AuthDigest) HMACGenerateOnServer(sk *StaticKey, plain []byte) []byte

HMACGenerateOnServer computes an HMAC of a given plain text with a part of a given StaticKey (to be sent by the server to the client).

func (*AuthDigest) HMACValidateOnClient

func (ad *AuthDigest) HMACValidateOnClient(sk *StaticKey, plain, expected []byte) bool

HMACValidateOnClient compares an expected HMAC (as received by the client from the server) with an actual HMAC of a given plain text it computes with a part of a given StaticKey.

func (*AuthDigest) HMACValidateOnServer

func (ad *AuthDigest) HMACValidateOnServer(sk *StaticKey, plain, expected []byte) bool

HMACValidateOnServer compares an expected HMAC (as received by the server from the client) with an actual HMAC of a given plain text it computes with a part of a given StaticKey.

type CryptCipher

type CryptCipher struct {
	// Decryptor is a function returning plain bytes from encrypted ones.
	Decryptor func(key, iv, encrypted []byte) []byte
	// Encryptor is a function returning encrypted bytes from plain ones.
	Encryptor func(key, iv, plain []byte) []byte
	// Names contains a list of cipher names in various notations.
	Names []string
	// SizeBlock is a number of bytes an initialization vector (IV) must have.
	SizeBlock int
	// SizeKey is a number of bytes an en/decryption key must have.
	SizeKey int
}

CryptCipher represents a cipher used for en/decrypting control messages.

func CryptCipherFindByName

func CryptCipherFindByName(name string) *CryptCipher

CryptCipherFindByName returns a pointer to CryptCipher having a given name or nil.

func (*CryptCipher) DecryptOnClient

func (cc *CryptCipher) DecryptOnClient(sk *StaticKey, iv, encrypted []byte) []byte

DecryptOnClient decrypts given encrypted bytes with a part of a given StaticKey (as received by the client from the server).

func (*CryptCipher) DecryptOnServer

func (cc *CryptCipher) DecryptOnServer(sk *StaticKey, iv, encrypted []byte) []byte

DecryptOnServer decrypts given encrypted bytes with a part of a given StaticKey (as received by the server from the client).

func (*CryptCipher) EncryptOnClient

func (cc *CryptCipher) EncryptOnClient(sk *StaticKey, iv, plain []byte) []byte

EncryptOnClient encrypts given plain bytes with a part of a given StaticKey (to be sent by the client to the server).

func (*CryptCipher) EncryptOnServer

func (cc *CryptCipher) EncryptOnServer(sk *StaticKey, iv, plain []byte) []byte

EncryptOnServer encrypts given plain bytes with a part of a given StaticKey (to be sent by the server to the client).

type MatchOpenVPN

type MatchOpenVPN struct {

	// Modes contains a list of supported OpenVPN modes to match against incoming client reset messages:
	//
	//	- `plain` mode messages have no replay protection, authentication or encryption;
	//
	//	- `auth` mode messages have no encryption, but provide for replay protection and authentication
	//	with a pre-shared 2048-bit group key, a variable key direction, and plenty digest algorithms;
	//
	//	- 'crypt' mode messages feature replay protection, authentication and encryption with
	//	a pre-shared 2048-bit group key, a fixed key direction, and SHA-256 + AES-256-CTR algorithms;
	//
	//	- `crypt2` mode messages are essentially `crypt` messages with an individual 2048-bit client key
	//	used for authentication and encryption attached to client reset messages in a protected form
	//	(a 1024-bit server key is used for its authentication end encryption).
	//
	// Notes: Each mode shall only be present once in the list. Values in the list are case-insensitive.
	// If the list is empty, MatchOpenVPN will consider all modes as accepted and try them one by one.
	Modes []string `json:"modes,omitempty"`

	// IgnoreCrypto makes MatchOpenVPN skip decryption and authentication if set to true.
	//
	// Notes: IgnoreCrypto impacts the auth, crypt and crypt2 modes at once and makes sense only if/when
	// the relevant static keys are provided. If neither GroupKey nor GroupKeyFile is set, decryption
	// (if applicable) and authentication are automatically skipped in the auth and crypt modes only. If
	// neither ServerKey nor ServerKeyFile is provided, decryption and authentication are automatically
	// skipped in the crypt2 mode (unless there is a client key). If neither ClientKeys nor ClientKeyFiles
	// are provided, decryption and authentication are automatically skipped in the crypt2 mode (unless
	// there is a server key). In the crypt2 mode, when there is a client key and there is no server key,
	// decryption of a WrappedKey is impossible, and this part of the incoming message is authenticated by
	// comparing it with what has been included in the matching client key.
	IgnoreCrypto bool `json:"ignore_crypto,omitempty"`
	// IgnoreTimestamp makes MatchOpenVPN skip replay timestamps validation if set to true.
	//
	// Note: A 30-seconds time window is applicable by default, i.e. a timestamp of up to 15 seconds behind
	// or ahead of now is accepted.
	IgnoreTimestamp bool `json:"ignore_timestamp,omitempty"`

	// GroupKey contains a hex string representing a pre-shared 2048-bit group key. This key may be
	// present in OpenVPN config files inside `<tls-auth/>` or `<tls-crypt/>` blocks or generated with
	// `openvpn --genkey tls-auth|tls-crypt` command. No comments (starting with '#' or '-') are allowed.
	GroupKey string `json:"group_key,omitempty"`
	// GroupKeyFile is a path to a file containing a pre-shared 2048-bit group key which may be present
	// in OpenVPN config files after `tls-auth` or `tls-crypt` directives. It is the same key as the one
	// GroupKey introduces, so these fields are mutually exclusive. If both are set, GroupKey always takes
	// precedence. Any comments in the file (starting with '#' or '-') are ignored.
	GroupKeyFile string `json:"group_key_file,omitempty"`

	// AuthDigest is a name of a digest algorithm used for authentication (HMAC generation and validation) of
	// the auth mode messages. If no value is provided, MatchOpenVPN will try all the algorithms it supports.
	//
	// Notes: OpenVPN binaries may support a larger number of digest algorithms thanks to the OpenSSL library
	// used under the hood. A few legacy and exotic digest algorithms are known to be missing, so IgnoreCrypto
	// may be set to true to ensure successful message matching if a desired digest algorithm isn't listed below.
	//
	// List of the supported digest algorithms:
	//	- MD5
	//	- SHA-1
	//	- RIPEMD-160
	//	- SHA-224
	//	- SHA-256
	//	- SHA-384
	//	- SHA-512
	//	- SHA-512/224
	//	- SHA-512/256
	//	- SHA3-224
	//	- SHA3-256
	//	- SHA3-384
	//	- SHA3-512
	//	- BLAKE2s-256
	//	- BLAKE2b-512
	//	- SHAKE-128
	//	- SHAKE-256
	//
	// Note: Digest algorithm names are recognised in a number of popular notations, including lowercase.
	// Please, refer to the source code (AuthDigests variable in crypto.go) for details.
	AuthDigest string `json:"auth_digest,omitempty"`
	// GroupKeyDirection is a group key direction and may contain one of the following three values:
	//
	//	- `normal` means the server config has `tls-auth [...] 0` or `key-direction 0`,
	//	while the client configs have `tls-auth [...] 1` or `key-direction 1`;
	//
	//	- `inverse` means the server config has `tls-auth [...] 1` or `key-direction 1`,
	//	while the client config have `tls-auth [...] 0` or `key-direction 0`;
	//
	//	- `bidi` or `bidirectional` means key direction is omitted (e.g. `tls-auth [...]`)
	//	in both the server config and client configs.
	//
	// Notes: Values are case-insensitive. If no value is specified, the normal key direction is implied.
	// The inverse key direction is a violation of the OpenVPN official recommendations, and the bidi one
	// provides for a lower level of DoS and message replay attacks resilience.
	GroupKeyDirection string `json:"group_key_direction,omitempty"`

	// ClientKeys contains a list of base64 strings representing 2048-bit client keys (each one in a decrypted
	// form followed by an encrypted and authenticated form also known as WKc in the OpenVPN docs). These keys
	// may be present in OpenVPN client config files inside `<tls-crypt-v2/>` block or generated with `openvpn
	// --tls-crypt-v2 [server.key] --genkey tls-crypt-v2-client` command. No comments (starting with '#' or '-')
	// are allowed.
	ClientKeys []string `json:"client_keys,omitempty"`
	// ClientKeyFiles is a list of paths to files containing 2048-bit client key which may be present in OpenVPN
	// config files after `tls-crypt-v2` directive. These are the same keys as those ClientKeys introduce, but
	// these fields are complementary. If both are set, a joint list of client keys is created. Any comments in
	// the files (starting with '#' or '-') are ignored.
	ClientKeyFiles []string `json:"client_key_files,omitempty"`

	// ServerKey contains a base64 string representing a 1024-bit server key used only for authentication and
	// encryption of client keys. This key may be present in OpenVPN server config files inside `<tls-crypt-v2/>`
	// block or generated with `openvpn --genkey tls-crypt-v2-server` command. No comments (starting with '#'
	// or '-') are allowed.
	ServerKey string `json:"server_key,omitempty"`
	// ServerKeyFile is a path to a file containing a 1024-bit server key which may be present in OpenVPN
	// config files after `tls-crypt-v2` directive. It is the same key as the one ServerKey introduces, so
	// these fields are mutually exclusive. If both are set, ServerKey always takes precedence. Any comments
	// in the file (starting with '#' or '-') are ignored.
	ServerKeyFile string `json:"server_key_file,omitempty"`
	// contains filtered or unexported fields
}

MatchOpenVPN is able to match OpenVPN connections.

func (*MatchOpenVPN) CaddyModule

func (m *MatchOpenVPN) CaddyModule() caddy.ModuleInfo

CaddyModule returns the Caddy module information.

func (*MatchOpenVPN) Match

func (m *MatchOpenVPN) Match(cx *layer4.Connection) (bool, error)

Match returns true if the connection looks like OpenVPN.

func (*MatchOpenVPN) Provision

func (m *MatchOpenVPN) Provision(_ caddy.Context) error

Provision prepares m's internal structures.

func (*MatchOpenVPN) UnmarshalCaddyfile

func (m *MatchOpenVPN) UnmarshalCaddyfile(d *caddyfile.Dispenser) error

UnmarshalCaddyfile sets up the MatchOpenVPN from Caddyfile tokens. Syntax:

openvpn {
	modes <plain|auth|crypt|crypt2> [<...>]

	ignore_crypto
	ignore_timestamp

	group_key <hex>
	group_key_file <path>

	auth_digest <digest>
	group_key_direction <normal|inverse|bidi|bidirectional>

	server_key <base64>
	server_key_file <path>

	client_key <base64>
	client_key_file <path>
}
openvpn

Note: multiple 'client_key' and 'client_key_file' options are allowed.

type MessageAuth

type MessageAuth struct {
	MessagePlain
	MessageTraitAuth
	MessageTraitReplay
}

MessageAuth is a P_CONTROL_HARD_RESET_CLIENT_V2-type OpenVPN message with authentication.

func (*MessageAuth) Authenticate

func (msg *MessageAuth) Authenticate(ad *AuthDigest, sk *StaticKey) bool

Authenticate returns true if msg has a valid HMAC.

func (*MessageAuth) FromBytes

func (msg *MessageAuth) FromBytes(src []byte) error

FromBytes fills msg's internal structures from a slice of bytes.

func (*MessageAuth) FromBytesHeadless

func (msg *MessageAuth) FromBytesHeadless(src []byte, hdr *MessageHeader) error

FromBytesHeadless fills msg's internal structures from a slice of bytes and uses a pre-filled header.

func (*MessageAuth) Match

func (msg *MessageAuth) Match(ignoreTimestamp, ignoreCrypto bool, ad *AuthDigest, sk *StaticKey) bool

Match returns true if msg's internal structures have valid values.

func (*MessageAuth) Sign

func (msg *MessageAuth) Sign(ad *AuthDigest, sk *StaticKey) error

Sign computes and fills msg's HMAC.

func (*MessageAuth) ToBytes

func (msg *MessageAuth) ToBytes() []byte

ToBytes returns a slice of bytes representing msg's internal structures.

func (*MessageAuth) ToBytesAuth

func (msg *MessageAuth) ToBytesAuth() []byte

ToBytesAuth returns a slice of bytes representing msg's internal structures without HMAC.

type MessageCrypt

type MessageCrypt struct {
	MessageAuth
	MessageTraitCrypt
}

MessageCrypt is a P_CONTROL_HARD_RESET_CLIENT_V2-type OpenVPN message with authentication and encryption.

func (*MessageCrypt) Authenticate

func (msg *MessageCrypt) Authenticate(ad *AuthDigest, sk *StaticKey) bool

Authenticate returns true if msg has a valid HMAC.

func (*MessageCrypt) DecryptAndAuthenticate

func (msg *MessageCrypt) DecryptAndAuthenticate(ad *AuthDigest, sk *StaticKey) bool

DecryptAndAuthenticate decrypts msg's encrypted bytes before calling Authenticate.

func (*MessageCrypt) EncryptAndSign

func (msg *MessageCrypt) EncryptAndSign(ad *AuthDigest, sk *StaticKey) error

EncryptAndSign encrypts msg's plain bytes before calling Sign.

func (*MessageCrypt) FromBytes

func (msg *MessageCrypt) FromBytes(src []byte) error

FromBytes fills msg's internal structures from a slice of bytes.

func (*MessageCrypt) FromBytesCrypt

func (msg *MessageCrypt) FromBytesCrypt(plain []byte) error

FromBytesCrypt fills msg's internal structures from a slice of bytes after decryption.

func (*MessageCrypt) FromBytesHeadless

func (msg *MessageCrypt) FromBytesHeadless(src []byte, hdr *MessageHeader) error

FromBytesHeadless fills msg's internal structures from a slice of bytes and uses a pre-filled header.

func (*MessageCrypt) Match

func (msg *MessageCrypt) Match(ignoreTimestamp, ignoreCrypto bool, ad *AuthDigest, sk *StaticKey) bool

Match returns true if msg's internal structures have valid values.

func (*MessageCrypt) Sign

func (msg *MessageCrypt) Sign(ad *AuthDigest, sk *StaticKey) error

Sign computes and fills msg's HMAC.

func (*MessageCrypt) ToBytes

func (msg *MessageCrypt) ToBytes() []byte

ToBytes returns a slice of bytes representing msg's internal structures.

func (*MessageCrypt) ToBytesAuth

func (msg *MessageCrypt) ToBytesAuth() []byte

ToBytesAuth returns a slice of bytes representing msg's internal structures without HMAC.

func (*MessageCrypt) ToBytesCrypt

func (msg *MessageCrypt) ToBytesCrypt() []byte

ToBytesCrypt returns a slice of bytes representing msg's internal structures before encryption.

type MessageCrypt2

type MessageCrypt2 struct {
	MessageCrypt
	WrappedKey
}

MessageCrypt2 is a P_CONTROL_HARD_RESET_CLIENT_V3-type OpenVPN message with authentication and encryption using a wrapped client key which is authenticated and encrypted with a server key.

func (*MessageCrypt2) DecryptAndAuthenticate

func (msg *MessageCrypt2) DecryptAndAuthenticate(ad *AuthDigest, sk *StaticKey) bool

DecryptAndAuthenticate decrypts and authenticates msg's encrypted bytes (WrappedKey before MessageCrypt).

func (*MessageCrypt2) EncryptAndSign

func (msg *MessageCrypt2) EncryptAndSign(ad *AuthDigest, sk *StaticKey) error

EncryptAndSign encrypts and signs msg's plain bytes (WrappedKey before MessageCrypt).

func (*MessageCrypt2) FromBytes

func (msg *MessageCrypt2) FromBytes(src []byte) error

FromBytes fills msg's internal structures from a slice of bytes.

func (*MessageCrypt2) FromBytesHeadless

func (msg *MessageCrypt2) FromBytesHeadless(src []byte, hdr *MessageHeader) error

FromBytesHeadless fills msg's internal structures from a slice of bytes and uses a pre-filled header.

func (*MessageCrypt2) Match

func (msg *MessageCrypt2) Match(ignoreTimestamp, ignoreCrypto bool, ad *AuthDigest, sk *StaticKey, cks []*WrappedKey) bool

Match returns true if msg's internal structures have valid values.

func (*MessageCrypt2) ToBytes

func (msg *MessageCrypt2) ToBytes() []byte

ToBytes returns a slice of bytes representing msg's internal structures.

type MessageHeader

type MessageHeader struct {
	// Opcode is a type of message that follows.
	Opcode uint8
	// KeyID refers to an already negotiated TLS session. It must equal zero for client reset messages.
	KeyID uint8
}

MessageHeader is an OpenVPN message header.

func (*MessageHeader) FromBytes

func (msg *MessageHeader) FromBytes(src []byte) error

FromBytes fills msg's internal structures from source bytes.

func (*MessageHeader) ToBytes

func (msg *MessageHeader) ToBytes() []byte

ToBytes return a slice of bytes representing msg's internal structures.

type MessagePlain

type MessagePlain struct {
	MessageHeader

	// LocalSessionID contains an 8-byte session ID assigned on the client. It must be non-zero.
	LocalSessionID uint64
	// PrevPacketIDsCount indicates how many previous packet IDs will follow. It must equal zero.
	PrevPacketIDsCount uint8
	// ThisPacketID contains a 4-byte packet ID of the current message. It must equal zero.
	ThisPacketID uint32
}

MessagePlain is a P_CONTROL_HARD_RESET_CLIENT_V2-type OpenVPN message with no authentication.

func (*MessagePlain) FromBytes

func (msg *MessagePlain) FromBytes(src []byte) error

FromBytes fills msg's internal structures from a slice of bytes.

func (*MessagePlain) FromBytesHeadless

func (msg *MessagePlain) FromBytesHeadless(src []byte, hdr *MessageHeader) error

FromBytesHeadless fills msg's internal structures from a slice of bytes and uses a pre-filled header.

func (*MessagePlain) Match

func (msg *MessagePlain) Match() bool

Match returns true if msg's internal structures have valid values.

func (*MessagePlain) ToBytes

func (msg *MessagePlain) ToBytes() []byte

ToBytes return a slice of bytes representing msg's internal structures.

type MessageTraitAuth

type MessageTraitAuth struct {
	// Digest is a pointer to AuthDigest to be used for authentication.
	Digest *AuthDigest
	// HMAC is a hash-based messaged authentication code used to verify message integrity.
	HMAC []byte
}

MessageTraitAuth contains fields and implements features related to authentication.

func (*MessageTraitAuth) AuthenticateOnClient

func (msg *MessageTraitAuth) AuthenticateOnClient(ad *AuthDigest, sk *StaticKey, xp func() []byte) bool

AuthenticateOnClient returns true if msg composed on the client has a valid HMAC.

func (*MessageTraitAuth) AuthenticateOnServer

func (msg *MessageTraitAuth) AuthenticateOnServer(ad *AuthDigest, sk *StaticKey, xp func() []byte) bool

AuthenticateOnServer returns true if msg composed on the server has a valid HMAC.

func (*MessageTraitAuth) SignOnClient

func (msg *MessageTraitAuth) SignOnClient(ad *AuthDigest, sk *StaticKey, xp func() []byte) error

SignOnClient computes an HMAC for msg composed on the client.

func (*MessageTraitAuth) SignOnServer

func (msg *MessageTraitAuth) SignOnServer(ad *AuthDigest, sk *StaticKey, xp func() []byte) error

SignOnServer computes an HMAC for msg composed on the server.

type MessageTraitCrypt

type MessageTraitCrypt struct {
	// Cipher is a pointer to CryptCipher to be used for encryption.
	Cipher *CryptCipher
	// Encrypted contains a number of bytes to be decrypted.
	Encrypted []byte
}

MessageTraitCrypt contains fields and implements features related to en-/decryption.

func (*MessageTraitCrypt) DecryptOnClient

func (msg *MessageTraitCrypt) DecryptOnClient(sk *StaticKey, ta *MessageTraitAuth, xd func([]byte) error) error

DecryptOnClient decrypts msg's encrypted bytes with an encryption key used by the server.

func (*MessageTraitCrypt) DecryptOnServer

func (msg *MessageTraitCrypt) DecryptOnServer(sk *StaticKey, ta *MessageTraitAuth, xd func([]byte) error) error

DecryptOnServer decrypts msg's encrypted bytes with an encryption key used by the client.

func (*MessageTraitCrypt) EncryptOnClient

func (msg *MessageTraitCrypt) EncryptOnClient(sk *StaticKey, ta *MessageTraitAuth, xe func() []byte) error

EncryptOnClient encrypts msg's plain bytes with a decryption key used by the server.

func (*MessageTraitCrypt) EncryptOnServer

func (msg *MessageTraitCrypt) EncryptOnServer(sk *StaticKey, ta *MessageTraitAuth, xe func() []byte) error

EncryptOnServer encrypts msg's plain bytes with a decryption key used by the client.

type MessageTraitReplay

type MessageTraitReplay struct {
	// ReplayPacketID is a 4-byte packet ID used for replay protection.
	ReplayPacketID uint32
	// ReplayTimestamp is a 4-byte timestamp used for replay protection.
	ReplayTimestamp uint32
}

MessageTraitReplay contains fields and implements features related to replay protection.

func (*MessageTraitReplay) ValidateReplayTimestamp

func (msg *MessageTraitReplay) ValidateReplayTimestamp(t time.Time) bool

ValidateReplayTimestamp returns true if msg has a valid ReplayTimestamp (relative to the provided time).

type MetaData

type MetaData struct {
	// Payload contains a number of bytes of variable length corresponding to Type.
	Payload []byte
	// Type indicates how to parse Payload correctly. It may equal 0x00 for any user defined data
	// and 0x01 for a 4-byte timestamp which enables discarding old client keys on the server.
	Type uint8
}

MetaData is an optional set of Type and Payload that may be included into WrappedKey.

type StaticKey

type StaticKey struct {
	// Bidi mimics `key-direction` omitted for both the server and the client.
	Bidi bool
	// Inverse mimics `key-direction 1` set for the server and `key-direction 0` set for the client.
	Inverse bool
	// KeyBytes must contain 128 or 256 bytes of the static key.
	KeyBytes []byte
}

StaticKey is an OpenVPN static key used for authentication and encryption of control messages.

Notes:

Authentication. If no key direction is set (i.e. a bidirectional key), OpenVPN uses key[64:64+size] for computing and validating HMACs on both the client and the server. If the client has `key-direction 1` and the server has `key-direction 0`, OpenVPN uses key[192:192+size] for computing HMACs on the client and validating them on the server. If the client has `key-direction 0` and the server has `key-direction 1` (i.e. an inverse direction in violation of the recommendations), OpenVPN uses key[64:64+size] for computing HMACs on the client and validating them on the server. Inverse and Bidi are mutually exclusive. If both are set, Bidi takes precedence.

En/decryption. OpenVPN always takes 2 different keys for encryption and decryption, so Bidi is completely ignored. Unless Inverse is set, key[128:128+size] is used for encryption on the client and key[0:0+size] is used for decryption on the client with the server applying these keys in the other way.

func StaticKeyNewFromBase64

func StaticKeyNewFromBase64(s string, inverse bool, bidi bool) *StaticKey

StaticKeyNewFromBase64 returns a pointer to StaticKey filled with bytes from a given base64 string.

func StaticKeyNewFromHex

func StaticKeyNewFromHex(s string, inverse bool, bidi bool) *StaticKey

StaticKeyNewFromHex returns a pointer to StaticKey filled with bytes from a given hex string.

func (*StaticKey) FromBase64

func (sk *StaticKey) FromBase64(s string) (err error)

FromBase64 fills sk's KeyBytes from a given base64 string.

func (*StaticKey) FromFile

func (sk *StaticKey) FromFile(path string, re *regexp.Regexp, size int, from func(string) error) error

FromFile fills sk's KeyBytes from a given file.

func (*StaticKey) FromGroupKeyFile

func (sk *StaticKey) FromGroupKeyFile(path string) error

FromGroupKeyFile fills sk's KeyBytes from a given group key file.

func (*StaticKey) FromHex

func (sk *StaticKey) FromHex(s string) (err error)

FromHex fills sk's KeyBytes from a given hex string.

func (*StaticKey) FromServerKeyFile

func (sk *StaticKey) FromServerKeyFile(path string) error

FromServerKeyFile fills sk's KeyBytes from a given server key file.

func (*StaticKey) GetClientAuthBytes

func (sk *StaticKey) GetClientAuthBytes() []byte

GetClientAuthBytes returns a quarter of KeyBytes to be used for authentication of control messages composed by the client.

func (*StaticKey) GetClientAuthKey

func (sk *StaticKey) GetClientAuthKey(size int) []byte

GetClientAuthKey returns a key of a given size from GetClientAuthBytes.

func (*StaticKey) GetClientDecryptBytes

func (sk *StaticKey) GetClientDecryptBytes() []byte

GetClientDecryptBytes returns a quarter of KeyBytes to be used for decryption of control messages received by the client.

func (*StaticKey) GetClientDecryptKey

func (sk *StaticKey) GetClientDecryptKey(size int) []byte

GetClientDecryptKey returns a key of a given size from GetClientDecryptBytes.

func (*StaticKey) GetClientEncryptBytes

func (sk *StaticKey) GetClientEncryptBytes() []byte

GetClientEncryptBytes returns a quarter of KeyBytes to be used for encryption of control messages composed by the client.

func (*StaticKey) GetClientEncryptKey

func (sk *StaticKey) GetClientEncryptKey(size int) []byte

GetClientEncryptKey returns a key of a given size from GetClientEncryptBytes.

func (*StaticKey) GetQuarterBytes

func (sk *StaticKey) GetQuarterBytes(q uint) []byte

GetQuarterBytes returns a nth (0-based) quarter of KeyBytes

func (*StaticKey) GetServerAuthBytes

func (sk *StaticKey) GetServerAuthBytes() []byte

GetServerAuthBytes returns a quarter of KeyBytes to be used for authentication of control messages composed by the server.

func (*StaticKey) GetServerAuthKey

func (sk *StaticKey) GetServerAuthKey(size int) []byte

GetServerAuthKey returns a key of a given size from GetServerAuthKey.

func (*StaticKey) GetServerDecryptBytes

func (sk *StaticKey) GetServerDecryptBytes() []byte

GetServerDecryptBytes returns a quarter of KeyBytes to be used for decryption of control messages received by the server.

func (*StaticKey) GetServerDecryptKey

func (sk *StaticKey) GetServerDecryptKey(size int) []byte

GetServerDecryptKey returns a key of a given size from GetServerDecryptBytes.

func (*StaticKey) GetServerEncryptBytes

func (sk *StaticKey) GetServerEncryptBytes() []byte

GetServerEncryptBytes returns a quarter of KeyBytes to be used for encryption of control messages composed by the server.

func (*StaticKey) GetServerEncryptKey

func (sk *StaticKey) GetServerEncryptKey(size int) []byte

GetServerEncryptKey returns a key of a given size from GetServerEncryptBytes.

func (*StaticKey) ToBase64

func (sk *StaticKey) ToBase64() string

ToBase64 returns a base64 string representing KeyBytes.

func (*StaticKey) ToHex

func (sk *StaticKey) ToHex() string

ToHex returns a hex string representing KeyBytes.

type WrappedKey

WrappedKey is an authenticated and encrypted client key used to encrypt MessageCrypt in the crypt2 mode.

func WrappedKeyNewFromBase64

func WrappedKeyNewFromBase64(s string) *WrappedKey

WrappedKeyNewFromBase64 returns a pointer to WrappedKey filled with bytes from a given base64 string.

func (*WrappedKey) Authenticate

func (wk *WrappedKey) Authenticate(ad *AuthDigest, sk *StaticKey) bool

Authenticate returns true if wk's HMAC is valid.

func (*WrappedKey) DecryptAndAuthenticate

func (wk *WrappedKey) DecryptAndAuthenticate(ad *AuthDigest, sk *StaticKey) bool

DecryptAndAuthenticate decrypts wk's encrypted bytes before calling Authenticate.

func (*WrappedKey) EncryptAndSign

func (wk *WrappedKey) EncryptAndSign(ad *AuthDigest, sk *StaticKey) error

EncryptAndSign encrypts wk's plain bytes before calling Sign.

func (*WrappedKey) FromBase64

func (wk *WrappedKey) FromBase64(s string) error

FromBase64 fills wk's internal structures (including decrypted StaticKey bytes) from a base64 string.

func (*WrappedKey) FromBytes

func (wk *WrappedKey) FromBytes(src []byte) error

FromBytes fills wk's internal structures from a slice of bytes.

func (*WrappedKey) FromBytesCrypt

func (wk *WrappedKey) FromBytesCrypt(plain []byte) error

FromBytesCrypt fills wk's internal structures from a slice of bytes after decryption.

func (*WrappedKey) FromClientKeyFile

func (wk *WrappedKey) FromClientKeyFile(path string) error

FromClientKeyFile fills wk's internal structures (including decrypted StaticKey bytes) from a given file.

func (*WrappedKey) Sign

func (wk *WrappedKey) Sign(ad *AuthDigest, sk *StaticKey) error

Sign computes and fills wk's HMAC.

func (*WrappedKey) ToBytes

func (wk *WrappedKey) ToBytes() []byte

ToBytes returns a slice of bytes representing wk's internal structures.

func (*WrappedKey) ToBytesAuth

func (wk *WrappedKey) ToBytesAuth() []byte

ToBytesAuth returns a slice of bytes representing wk's internal structures without HMAC.

func (*WrappedKey) ToBytesCrypt

func (wk *WrappedKey) ToBytesCrypt() []byte

ToBytesCrypt returns a slice of bytes representing wk's internal structures before encryption.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL