Documentation ¶
Index ¶
- Constants
- Variables
- func HMACCreateAndGenerate(creator func() hash.Hash, key, plain []byte) []byte
- type AuthDigest
- func (ad *AuthDigest) HMACGenerateOnClient(sk *StaticKey, plain []byte) []byte
- func (ad *AuthDigest) HMACGenerateOnServer(sk *StaticKey, plain []byte) []byte
- func (ad *AuthDigest) HMACValidateOnClient(sk *StaticKey, plain, expected []byte) bool
- func (ad *AuthDigest) HMACValidateOnServer(sk *StaticKey, plain, expected []byte) bool
- type CryptCipher
- func (cc *CryptCipher) DecryptOnClient(sk *StaticKey, iv, encrypted []byte) []byte
- func (cc *CryptCipher) DecryptOnServer(sk *StaticKey, iv, encrypted []byte) []byte
- func (cc *CryptCipher) EncryptOnClient(sk *StaticKey, iv, plain []byte) []byte
- func (cc *CryptCipher) EncryptOnServer(sk *StaticKey, iv, plain []byte) []byte
- type MatchOpenVPN
- type MessageAuth
- func (msg *MessageAuth) Authenticate(ad *AuthDigest, sk *StaticKey) bool
- func (msg *MessageAuth) FromBytes(src []byte) error
- func (msg *MessageAuth) FromBytesHeadless(src []byte, hdr *MessageHeader) error
- func (msg *MessageAuth) Match(ignoreTimestamp, ignoreCrypto bool, ad *AuthDigest, sk *StaticKey) bool
- func (msg *MessageAuth) Sign(ad *AuthDigest, sk *StaticKey) error
- func (msg *MessageAuth) ToBytes() []byte
- func (msg *MessageAuth) ToBytesAuth() []byte
- type MessageCrypt
- func (msg *MessageCrypt) Authenticate(ad *AuthDigest, sk *StaticKey) bool
- func (msg *MessageCrypt) DecryptAndAuthenticate(ad *AuthDigest, sk *StaticKey) bool
- func (msg *MessageCrypt) EncryptAndSign(ad *AuthDigest, sk *StaticKey) error
- func (msg *MessageCrypt) FromBytes(src []byte) error
- func (msg *MessageCrypt) FromBytesCrypt(plain []byte) error
- func (msg *MessageCrypt) FromBytesHeadless(src []byte, hdr *MessageHeader) error
- func (msg *MessageCrypt) Match(ignoreTimestamp, ignoreCrypto bool, ad *AuthDigest, sk *StaticKey) bool
- func (msg *MessageCrypt) Sign(ad *AuthDigest, sk *StaticKey) error
- func (msg *MessageCrypt) ToBytes() []byte
- func (msg *MessageCrypt) ToBytesAuth() []byte
- func (msg *MessageCrypt) ToBytesCrypt() []byte
- type MessageCrypt2
- func (msg *MessageCrypt2) DecryptAndAuthenticate(ad *AuthDigest, sk *StaticKey) bool
- func (msg *MessageCrypt2) EncryptAndSign(ad *AuthDigest, sk *StaticKey) error
- func (msg *MessageCrypt2) FromBytes(src []byte) error
- func (msg *MessageCrypt2) FromBytesHeadless(src []byte, hdr *MessageHeader) error
- func (msg *MessageCrypt2) Match(ignoreTimestamp, ignoreCrypto bool, ad *AuthDigest, sk *StaticKey, ...) bool
- func (msg *MessageCrypt2) ToBytes() []byte
- type MessageHeader
- type MessagePlain
- type MessageTraitAuth
- func (msg *MessageTraitAuth) AuthenticateOnClient(ad *AuthDigest, sk *StaticKey, xp func() []byte) bool
- func (msg *MessageTraitAuth) AuthenticateOnServer(ad *AuthDigest, sk *StaticKey, xp func() []byte) bool
- func (msg *MessageTraitAuth) SignOnClient(ad *AuthDigest, sk *StaticKey, xp func() []byte) error
- func (msg *MessageTraitAuth) SignOnServer(ad *AuthDigest, sk *StaticKey, xp func() []byte) error
- type MessageTraitCrypt
- func (msg *MessageTraitCrypt) DecryptOnClient(sk *StaticKey, ta *MessageTraitAuth, xd func([]byte) error) error
- func (msg *MessageTraitCrypt) DecryptOnServer(sk *StaticKey, ta *MessageTraitAuth, xd func([]byte) error) error
- func (msg *MessageTraitCrypt) EncryptOnClient(sk *StaticKey, ta *MessageTraitAuth, xe func() []byte) error
- func (msg *MessageTraitCrypt) EncryptOnServer(sk *StaticKey, ta *MessageTraitAuth, xe func() []byte) error
- type MessageTraitReplay
- type MetaData
- type StaticKey
- func (sk *StaticKey) FromBase64(s string) (err error)
- func (sk *StaticKey) FromFile(path string, re *regexp.Regexp, size int, from func(string) error) error
- func (sk *StaticKey) FromGroupKeyFile(path string) error
- func (sk *StaticKey) FromHex(s string) (err error)
- func (sk *StaticKey) FromServerKeyFile(path string) error
- func (sk *StaticKey) GetClientAuthBytes() []byte
- func (sk *StaticKey) GetClientAuthKey(size int) []byte
- func (sk *StaticKey) GetClientDecryptBytes() []byte
- func (sk *StaticKey) GetClientDecryptKey(size int) []byte
- func (sk *StaticKey) GetClientEncryptBytes() []byte
- func (sk *StaticKey) GetClientEncryptKey(size int) []byte
- func (sk *StaticKey) GetQuarterBytes(q uint) []byte
- func (sk *StaticKey) GetServerAuthBytes() []byte
- func (sk *StaticKey) GetServerAuthKey(size int) []byte
- func (sk *StaticKey) GetServerDecryptBytes() []byte
- func (sk *StaticKey) GetServerDecryptKey(size int) []byte
- func (sk *StaticKey) GetServerEncryptBytes() []byte
- func (sk *StaticKey) GetServerEncryptKey(size int) []byte
- func (sk *StaticKey) ToBase64() string
- func (sk *StaticKey) ToHex() string
- type WrappedKey
- func (wk *WrappedKey) Authenticate(ad *AuthDigest, sk *StaticKey) bool
- func (wk *WrappedKey) DecryptAndAuthenticate(ad *AuthDigest, sk *StaticKey) bool
- func (wk *WrappedKey) EncryptAndSign(ad *AuthDigest, sk *StaticKey) error
- func (wk *WrappedKey) FromBase64(s string) error
- func (wk *WrappedKey) FromBytes(src []byte) error
- func (wk *WrappedKey) FromBytesCrypt(plain []byte) error
- func (wk *WrappedKey) FromClientKeyFile(path string) error
- func (wk *WrappedKey) Sign(ad *AuthDigest, sk *StaticKey) error
- func (wk *WrappedKey) ToBytes() []byte
- func (wk *WrappedKey) ToBytesAuth() []byte
- func (wk *WrappedKey) ToBytesCrypt() []byte
Constants ¶
const ( AuthHMACBytesMax = sha512.Size AuthHMACBytesMin = md5.Size CryptHMACBytesTotal = sha256.Size StaticKeyBytesTotal = 256 StaticKeyBytesHalf = StaticKeyBytesTotal / 2 StaticKeyBytesQuarter = StaticKeyBytesTotal / 4 )
const ( GroupKeyDirectionBidi = "bidi" GroupKeyDirectionBidi2 = "bidirectional" GroupKeyDirectionInverse = "inverse" GroupKeyDirectionNormal = "normal" ModeAuth = "auth" ModeCrypt = "crypt" ModeCrypt2 = "crypt2" ModePlain = "plain" )
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 ¶
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") )
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") )
var AuthDigestDefault = AuthDigestFindByName("SHA-256")
AuthDigestDefault is the default AuthDigest used in the crypt and crypt2 modes (SHA-256).
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.
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.
var CryptCipherDefault = CryptCipherFindByName("AES-256-CTR")
CryptCipherDefault is the default CryptCipher used in the crypt and crypt2 modes (AES-256-CTR).
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.
var (
ErrInvalidStaticKeyFileContents = errors.New("invalid static key file contents")
)
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)?$")
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 ¶
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 ¶
StaticKeyNewFromBase64 returns a pointer to StaticKey filled with bytes from a given base64 string.
func StaticKeyNewFromHex ¶
StaticKeyNewFromHex returns a pointer to StaticKey filled with bytes from a given hex string.
func (*StaticKey) FromBase64 ¶
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 ¶
FromGroupKeyFile fills sk's KeyBytes from a given group key file.
func (*StaticKey) FromServerKeyFile ¶
FromServerKeyFile fills sk's KeyBytes from a given server key file.
func (*StaticKey) GetClientAuthBytes ¶
GetClientAuthBytes returns a quarter of KeyBytes to be used for authentication of control messages composed by the client.
func (*StaticKey) GetClientAuthKey ¶
GetClientAuthKey returns a key of a given size from GetClientAuthBytes.
func (*StaticKey) GetClientDecryptBytes ¶
GetClientDecryptBytes returns a quarter of KeyBytes to be used for decryption of control messages received by the client.
func (*StaticKey) GetClientDecryptKey ¶
GetClientDecryptKey returns a key of a given size from GetClientDecryptBytes.
func (*StaticKey) GetClientEncryptBytes ¶
GetClientEncryptBytes returns a quarter of KeyBytes to be used for encryption of control messages composed by the client.
func (*StaticKey) GetClientEncryptKey ¶
GetClientEncryptKey returns a key of a given size from GetClientEncryptBytes.
func (*StaticKey) GetQuarterBytes ¶
GetQuarterBytes returns a nth (0-based) quarter of KeyBytes
func (*StaticKey) GetServerAuthBytes ¶
GetServerAuthBytes returns a quarter of KeyBytes to be used for authentication of control messages composed by the server.
func (*StaticKey) GetServerAuthKey ¶
GetServerAuthKey returns a key of a given size from GetServerAuthKey.
func (*StaticKey) GetServerDecryptBytes ¶
GetServerDecryptBytes returns a quarter of KeyBytes to be used for decryption of control messages received by the server.
func (*StaticKey) GetServerDecryptKey ¶
GetServerDecryptKey returns a key of a given size from GetServerDecryptBytes.
func (*StaticKey) GetServerEncryptBytes ¶
GetServerEncryptBytes returns a quarter of KeyBytes to be used for encryption of control messages composed by the server.
func (*StaticKey) GetServerEncryptKey ¶
GetServerEncryptKey returns a key of a given size from GetServerEncryptBytes.
type WrappedKey ¶
type WrappedKey struct { MetaData StaticKey MessageTraitAuth MessageTraitCrypt }
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.