github.com/mholt/caddy-l4@v0.0.0-20241104153248-ec8fae209322/modules/l4openvpn/messages.go (about) 1 // Copyright 2024 VNXME 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 package l4openvpn 16 17 import ( 18 "bytes" 19 "encoding/base64" 20 "encoding/binary" 21 "errors" 22 "slices" 23 "time" 24 ) 25 26 // MessageHeader is an OpenVPN message header. 27 type MessageHeader struct { 28 // Opcode is a type of message that follows. 29 Opcode uint8 30 // KeyID refers to an already negotiated TLS session. It must equal zero for client reset messages. 31 KeyID uint8 32 } 33 34 // FromBytes fills msg's internal structures from source bytes. 35 func (msg *MessageHeader) FromBytes(src []byte) error { 36 // Any MessageHeader has exactly 1 byte. 37 if len(src) != OpcodeKeyIDBytesTotal { 38 return ErrInvalidSourceLength 39 } 40 41 // Opcode occupies the high 5 bits, KeyID extends over the low 3 bits. 42 msg.KeyID, msg.Opcode = src[0]&KeyIDMask, src[0]>>OpcodeShift 43 44 return nil 45 } 46 47 // ToBytes return a slice of bytes representing msg's internal structures. 48 func (msg *MessageHeader) ToBytes() []byte { 49 dst := make([]byte, 0, OpcodeKeyIDBytesTotal) 50 dst = append(dst, msg.KeyID|(msg.Opcode<<OpcodeShift)) 51 return dst 52 } 53 54 // MessagePlain is a P_CONTROL_HARD_RESET_CLIENT_V2-type OpenVPN message with no authentication. 55 type MessagePlain struct { 56 MessageHeader 57 58 // LocalSessionID contains an 8-byte session ID assigned on the client. It must be non-zero. 59 LocalSessionID uint64 60 // PrevPacketIDsCount indicates how many previous packet IDs will follow. It must equal zero. 61 PrevPacketIDsCount uint8 62 // ThisPacketID contains a 4-byte packet ID of the current message. It must equal zero. 63 ThisPacketID uint32 64 } 65 66 // FromBytes fills msg's internal structures from a slice of bytes. 67 func (msg *MessagePlain) FromBytes(src []byte) error { 68 // Any MessagePlain is exactly 14 bytes (with a header). 69 if len(src) != MessagePlainBytesTotal { 70 return ErrInvalidSourceLength 71 } 72 73 // Parse MessageHeader 74 hdr := &MessageHeader{} 75 if err := hdr.FromBytes(src[:OpcodeKeyIDBytesTotal]); err != nil { 76 return err 77 } 78 79 // Match MessageHeader.Opcode 80 if hdr.Opcode != OpcodeControlHardResetClientV2 { 81 return ErrInvalidHeaderOpcode 82 } 83 84 // Parse everything else 85 return msg.FromBytesHeadless(src[OpcodeKeyIDBytesTotal:], hdr) 86 } 87 88 // FromBytesHeadless fills msg's internal structures from a slice of bytes and uses a pre-filled header. 89 func (msg *MessagePlain) FromBytesHeadless(src []byte, hdr *MessageHeader) error { 90 91 // Any MessagePlain is exactly 13 bytes long (without a header). 92 if len(src) != MessagePlainBytesTotalHL { 93 return ErrInvalidSourceLength 94 } 95 96 // Check for a non-empty MessageHeader. 97 if hdr == nil { 98 return ErrMissingReusableHeader 99 } 100 101 // Assign Header to the specified pointer. 102 msg.MessageHeader = *hdr 103 104 // Any MessagePlain has an 8-byte LocalSessionID at the beginning. 105 msg.LocalSessionID = BytesOrder.Uint64(src[:SessionIDBytesTotal]) 106 107 // Any MessagePlain has a 1-byte PrevPacketIDsCount between LocalSessionID and ThisPacketID. 108 msg.PrevPacketIDsCount = src[SessionIDBytesTotal] 109 110 // Any MessagePlain has a 4-byte ThisPacketID at the end. 111 msg.ThisPacketID = BytesOrder.Uint32(src[len(src)-PacketIDBytesTotal:]) 112 113 return nil 114 } 115 116 // Match returns true if msg's internal structures have valid values. 117 func (msg *MessagePlain) Match() bool { 118 return msg.LocalSessionID > 0 && msg.PrevPacketIDsCount == 0 && msg.ThisPacketID == 0 119 } 120 121 // ToBytes return a slice of bytes representing msg's internal structures. 122 func (msg *MessagePlain) ToBytes() []byte { 123 dst := make([]byte, 0, MessagePlainBytesTotal) 124 dst = append(dst, msg.MessageHeader.ToBytes()...) 125 dst = BytesOrder.AppendUint64(dst, msg.LocalSessionID) 126 dst = append(dst, msg.PrevPacketIDsCount) 127 dst = BytesOrder.AppendUint32(dst, msg.ThisPacketID) 128 return dst 129 } 130 131 // MessageAuth is a P_CONTROL_HARD_RESET_CLIENT_V2-type OpenVPN message with authentication. 132 type MessageAuth struct { 133 MessagePlain 134 MessageTraitAuth 135 MessageTraitReplay 136 } 137 138 // Authenticate returns true if msg has a valid HMAC. 139 func (msg *MessageAuth) Authenticate(ad *AuthDigest, sk *StaticKey) bool { 140 return msg.MessageTraitAuth.AuthenticateOnServer(ad, sk, msg.ToBytesAuth) 141 } 142 143 // FromBytes fills msg's internal structures from a slice of bytes. 144 func (msg *MessageAuth) FromBytes(src []byte) error { 145 // Any MessageAuth is between 38 and 86 bytes (with a header). 146 if len(src) < MessageAuthBytesMin || len(src) > MessageAuthBytesMax { 147 return ErrInvalidSourceLength 148 } 149 150 // Parse MessageHeader 151 hdr := &MessageHeader{} 152 if err := hdr.FromBytes(src[:OpcodeKeyIDBytesTotal]); err != nil { 153 return err 154 } 155 156 // Match MessageHeader.Opcode 157 if hdr.Opcode != OpcodeControlHardResetClientV2 { 158 return ErrInvalidHeaderOpcode 159 } 160 161 // Parse everything else 162 return msg.FromBytesHeadless(src[OpcodeKeyIDBytesTotal:], hdr) 163 } 164 165 // FromBytesHeadless fills msg's internal structures from a slice of bytes and uses a pre-filled header. 166 func (msg *MessageAuth) FromBytesHeadless(src []byte, hdr *MessageHeader) error { 167 // Any MessageAuth is between 37 and 85 bytes long (without a header). 168 if len(src) < MessageAuthBytesMinHL || len(src) > MessageAuthBytesMaxHL { 169 return ErrInvalidSourceLength 170 } 171 172 // Check for a non-empty MessageHeader. 173 if hdr == nil { 174 return ErrMissingReusableHeader 175 } 176 177 // Assign Header to the specified pointer. 178 msg.MessageHeader = *hdr 179 180 // Any MessageAuth has an 8-byte LocalSessionID at the beginning. 181 msg.LocalSessionID = BytesOrder.Uint64(src[:SessionIDBytesTotal]) 182 183 // Any MessageAuth has a 16-to-64-byte HMAC between LocalSessionID and ReplayPacketID. 184 off1, off2 := SessionIDBytesTotal, len(src)-2*PacketIDBytesTotal-OpcodeKeyIDBytesTotal-TimestampBytesTotal 185 msg.HMAC = src[off1:off2] 186 187 // Check whether a valid HMAC length is provided. 188 if !slices.Contains(AuthDigestSizes, len(msg.HMAC)) { 189 return ErrInvalidHMACLength 190 } 191 192 // Any MessageAuth has a 4-byte ReplayPacketID between HMAC and ReplayTimestamp. 193 off1, off2 = off2, off2+PacketIDBytesTotal 194 msg.ReplayPacketID = BytesOrder.Uint32(src[off1:off2]) 195 196 // Any MessageAuth has a 4-byte ReplayTimestamp between ReplayPacketID and PrevPacketIDsCount. 197 off1, off2 = off2, off2+TimestampBytesTotal 198 msg.ReplayTimestamp = BytesOrder.Uint32(src[off1:off2]) 199 200 // Any MessageAuth has a 1-byte PrevPacketIDsCount between ReplayTimestamp and ThisPacketID. 201 off1, off2 = off2, off2+OpcodeKeyIDBytesTotal 202 msg.PrevPacketIDsCount = src[off1] 203 204 // Any MessageAuth has a 4-byte ThisPacketID at the end. 205 msg.ThisPacketID = BytesOrder.Uint32(src[off2:]) 206 207 return nil 208 } 209 210 // Match returns true if msg's internal structures have valid values. 211 func (msg *MessageAuth) Match(ignoreTimestamp, ignoreCrypto bool, ad *AuthDigest, sk *StaticKey) bool { 212 return msg.MessagePlain.Match() && 213 msg.ReplayPacketID == 1 && (ignoreTimestamp || msg.ValidateReplayTimestamp(time.Now())) && 214 (ad == nil || ad.Size == len(msg.MessageTraitAuth.HMAC)) && 215 (ignoreCrypto || sk == nil || msg.Authenticate(ad, sk)) 216 } 217 218 // Sign computes and fills msg's HMAC. 219 func (msg *MessageAuth) Sign(ad *AuthDigest, sk *StaticKey) error { 220 return msg.MessageTraitAuth.SignOnClient(ad, sk, msg.ToBytesAuth) 221 } 222 223 // ToBytes returns a slice of bytes representing msg's internal structures. 224 func (msg *MessageAuth) ToBytes() []byte { 225 dst := make([]byte, 0, MessagePlainBytesTotal+len(msg.HMAC)+PacketIDBytesTotal+TimestampBytesTotal) 226 dst = append(dst, msg.MessageHeader.ToBytes()...) 227 dst = BytesOrder.AppendUint64(dst, msg.LocalSessionID) 228 dst = append(dst, msg.HMAC...) 229 dst = BytesOrder.AppendUint32(dst, msg.ReplayPacketID) 230 dst = BytesOrder.AppendUint32(dst, msg.ReplayTimestamp) 231 dst = append(dst, msg.PrevPacketIDsCount) 232 dst = BytesOrder.AppendUint32(dst, msg.ThisPacketID) 233 return dst 234 } 235 236 // ToBytesAuth returns a slice of bytes representing msg's internal structures without HMAC. 237 func (msg *MessageAuth) ToBytesAuth() []byte { 238 dst := make([]byte, 0, MessagePlainBytesTotal+PacketIDBytesTotal+TimestampBytesTotal) 239 dst = BytesOrder.AppendUint32(dst, msg.ReplayPacketID) 240 dst = BytesOrder.AppendUint32(dst, msg.ReplayTimestamp) 241 dst = append(dst, msg.MessageHeader.ToBytes()...) 242 dst = BytesOrder.AppendUint64(dst, msg.LocalSessionID) 243 dst = append(dst, msg.PrevPacketIDsCount) 244 dst = BytesOrder.AppendUint32(dst, msg.ThisPacketID) 245 return dst 246 } 247 248 // MessageCrypt is a P_CONTROL_HARD_RESET_CLIENT_V2-type OpenVPN message with authentication and encryption. 249 type MessageCrypt struct { 250 MessageAuth 251 MessageTraitCrypt 252 } 253 254 // Authenticate returns true if msg has a valid HMAC. 255 func (msg *MessageCrypt) Authenticate(ad *AuthDigest, sk *StaticKey) bool { 256 return msg.MessageTraitAuth.AuthenticateOnServer(ad, sk, msg.ToBytesAuth) 257 } 258 259 // DecryptAndAuthenticate decrypts msg's encrypted bytes before calling Authenticate. 260 func (msg *MessageCrypt) DecryptAndAuthenticate(ad *AuthDigest, sk *StaticKey) bool { 261 if len(msg.Encrypted) != OpcodeKeyIDBytesTotal+PacketIDBytesTotal || 262 msg.MessageTraitCrypt.DecryptOnServer(sk, &msg.MessageTraitAuth, msg.FromBytesCrypt) != nil { 263 return false 264 } 265 return msg.Authenticate(ad, sk) 266 } 267 268 // EncryptAndSign encrypts msg's plain bytes before calling Sign. 269 func (msg *MessageCrypt) EncryptAndSign(ad *AuthDigest, sk *StaticKey) error { 270 if err := msg.MessageTraitCrypt.EncryptOnClient(sk, &msg.MessageTraitAuth, msg.ToBytesCrypt); err != nil { 271 return err 272 } 273 return msg.Sign(ad, sk) 274 } 275 276 // FromBytes fills msg's internal structures from a slice of bytes. 277 func (msg *MessageCrypt) FromBytes(src []byte) error { 278 // Any MessageCrypt is between 54 bytes (with a header). 279 if len(src) != MessageCryptBytesTotal { 280 return ErrInvalidSourceLength 281 } 282 283 // Parse MessageHeader 284 hdr := &MessageHeader{} 285 if err := hdr.FromBytes(src[:OpcodeKeyIDBytesTotal]); err != nil { 286 return err 287 } 288 289 // Match MessageHeader.Opcode 290 if hdr.Opcode != OpcodeControlHardResetClientV2 { 291 return ErrInvalidHeaderOpcode 292 } 293 294 // Parse everything else 295 return msg.FromBytesHeadless(src[OpcodeKeyIDBytesTotal:], hdr) 296 } 297 298 // FromBytesHeadless fills msg's internal structures from a slice of bytes and uses a pre-filled header. 299 func (msg *MessageCrypt) FromBytesHeadless(src []byte, hdr *MessageHeader) error { 300 // Any MessageCrypt is exactly 53 bytes long (without a header). 301 if len(src) != MessageCryptBytesTotalHL { 302 return ErrInvalidSourceLength 303 } 304 305 // Check for a non-empty MessageHeader. 306 if hdr == nil { 307 return ErrMissingReusableHeader 308 } 309 310 // Assign Header to the specified pointer. 311 msg.MessageHeader = *hdr 312 313 // Any MessageCrypt has an 8-byte LocalSessionID at the beginning. 314 msg.LocalSessionID = BytesOrder.Uint64(src[:SessionIDBytesTotal]) 315 316 // Any MessageCrypt has a 4-byte ReplayPacketID between LocalSessionID and ReplayTimestamp. 317 off1, off2 := SessionIDBytesTotal, SessionIDBytesTotal+PacketIDBytesTotal 318 msg.ReplayPacketID = BytesOrder.Uint32(src[off1:off2]) 319 320 // Any MessageCrypt has a 4-byte ReplayTimestamp between ReplayPacketID and HMAC. 321 off1, off2 = off2, off2+TimestampBytesTotal 322 msg.ReplayTimestamp = BytesOrder.Uint32(src[off1:off2]) 323 324 // Any MessageCrypt has a 32-byte SHA-256 HMAC between ReplayTimestamp and Encrypted bytes. 325 off1, off2 = off2, off2+AuthDigestDefault.Size 326 msg.Digest, msg.HMAC = AuthDigestDefault, src[off1:off2] 327 328 // Any MessageCrypt has a 5-byte Encrypted part at the end. 329 msg.Cipher, msg.Encrypted = CryptCipherDefault, src[off2:] 330 331 return nil 332 } 333 334 // FromBytesCrypt fills msg's internal structures from a slice of bytes after decryption. 335 func (msg *MessageCrypt) FromBytesCrypt(plain []byte) error { 336 if len(plain) != len(msg.Encrypted) { 337 return ErrInvalidPlainLength 338 } 339 340 // Any MessageCrypt has a PrevPacketIDsCount at the beginning of the plain text. 341 msg.PrevPacketIDsCount = plain[0] 342 343 // Any MessageCrypt has a ThisPacketID at the end of the plain text. 344 msg.ThisPacketID = BytesOrder.Uint32(plain[OpcodeKeyIDBytesTotal:]) 345 346 return nil 347 } 348 349 // Match returns true if msg's internal structures have valid values. 350 func (msg *MessageCrypt) Match(ignoreTimestamp, ignoreCrypto bool, ad *AuthDigest, sk *StaticKey) bool { 351 return msg.LocalSessionID > 0 && 352 msg.ReplayPacketID == 1 && (ignoreTimestamp || msg.ValidateReplayTimestamp(time.Now())) && 353 (ignoreCrypto || sk == nil || (msg.DecryptAndAuthenticate(ad, sk) && 354 msg.PrevPacketIDsCount == 0 && msg.ThisPacketID == 0)) 355 } 356 357 // Sign computes and fills msg's HMAC. 358 func (msg *MessageCrypt) Sign(ad *AuthDigest, sk *StaticKey) error { 359 return msg.MessageTraitAuth.SignOnClient(ad, sk, msg.ToBytesAuth) 360 } 361 362 // ToBytes returns a slice of bytes representing msg's internal structures. 363 func (msg *MessageCrypt) ToBytes() []byte { 364 dst := make([]byte, 0, MessagePlainBytesTotal+len(msg.HMAC)+PacketIDBytesTotal+TimestampBytesTotal) 365 dst = append(dst, msg.MessageHeader.ToBytes()...) 366 dst = BytesOrder.AppendUint64(dst, msg.LocalSessionID) 367 dst = BytesOrder.AppendUint32(dst, msg.ReplayPacketID) 368 dst = BytesOrder.AppendUint32(dst, msg.ReplayTimestamp) 369 dst = append(dst, msg.HMAC...) 370 dst = append(dst, msg.Encrypted...) 371 return dst 372 } 373 374 // ToBytesAuth returns a slice of bytes representing msg's internal structures without HMAC. 375 func (msg *MessageCrypt) ToBytesAuth() []byte { 376 dst := make([]byte, 0, MessagePlainBytesTotal+PacketIDBytesTotal+TimestampBytesTotal) 377 dst = append(dst, msg.MessageHeader.ToBytes()...) 378 dst = BytesOrder.AppendUint64(dst, msg.LocalSessionID) 379 dst = BytesOrder.AppendUint32(dst, msg.ReplayPacketID) 380 dst = BytesOrder.AppendUint32(dst, msg.ReplayTimestamp) 381 dst = append(dst, msg.PrevPacketIDsCount) 382 dst = BytesOrder.AppendUint32(dst, msg.ThisPacketID) 383 return dst 384 } 385 386 // ToBytesCrypt returns a slice of bytes representing msg's internal structures before encryption. 387 func (msg *MessageCrypt) ToBytesCrypt() []byte { 388 dst := make([]byte, 0, OpcodeKeyIDBytesTotal+PacketIDBytesTotal) 389 dst = append(dst, msg.PrevPacketIDsCount) 390 dst = BytesOrder.AppendUint32(dst, msg.ThisPacketID) 391 return dst 392 } 393 394 // MessageCrypt2 is a P_CONTROL_HARD_RESET_CLIENT_V3-type OpenVPN message with authentication and encryption 395 // using a wrapped client key which is authenticated and encrypted with a server key. 396 type MessageCrypt2 struct { 397 MessageCrypt 398 WrappedKey 399 } 400 401 // DecryptAndAuthenticate decrypts and authenticates msg's encrypted bytes (WrappedKey before MessageCrypt). 402 func (msg *MessageCrypt2) DecryptAndAuthenticate(ad *AuthDigest, sk *StaticKey) bool { 403 if !msg.WrappedKey.DecryptAndAuthenticate(ad, sk) { 404 return false 405 } 406 return msg.MessageCrypt.DecryptAndAuthenticate(ad, &msg.WrappedKey.StaticKey) 407 } 408 409 // EncryptAndSign encrypts and signs msg's plain bytes (WrappedKey before MessageCrypt). 410 func (msg *MessageCrypt2) EncryptAndSign(ad *AuthDigest, sk *StaticKey) error { 411 if err := msg.WrappedKey.EncryptAndSign(ad, sk); err != nil { 412 return err 413 } 414 return msg.MessageCrypt.EncryptAndSign(ad, &msg.WrappedKey.StaticKey) 415 } 416 417 // FromBytes fills msg's internal structures from a slice of bytes. 418 func (msg *MessageCrypt2) FromBytes(src []byte) error { 419 // Any MessageCrypt2 is between 344 and 600 bytes (with a header). 420 if len(src) < MessageCrypt2BytesMin || len(src) > MessageCrypt2BytesMax { 421 return ErrInvalidSourceLength 422 } 423 424 // Parse MessageHeader 425 hdr := &MessageHeader{} 426 if err := hdr.FromBytes(src[:OpcodeKeyIDBytesTotal]); err != nil { 427 return err 428 } 429 430 // Match MessageHeader.Opcode 431 if hdr.Opcode != OpcodeControlHardResetClientV3 { 432 return ErrInvalidHeaderOpcode 433 } 434 435 // Parse everything else 436 return msg.FromBytesHeadless(src[OpcodeKeyIDBytesTotal:], hdr) 437 } 438 439 // FromBytesHeadless fills msg's internal structures from a slice of bytes and uses a pre-filled header. 440 func (msg *MessageCrypt2) FromBytesHeadless(src []byte, hdr *MessageHeader) error { 441 // Any MessageCrypt2 is between 343 and 1077 bytes long (without a header). 442 if len(src) < MessageCrypt2BytesMinHL || len(src) > MessageCrypt2BytesMaxHL { 443 return ErrInvalidSourceLength 444 } 445 446 if err := msg.MessageCrypt.FromBytesHeadless(src[:MessageCryptBytesTotalHL], hdr); err != nil { 447 return err 448 } 449 450 return msg.WrappedKey.FromBytes(src[MessageCryptBytesTotalHL:]) 451 } 452 453 // Match returns true if msg's internal structures have valid values. 454 func (msg *MessageCrypt2) Match(ignoreTimestamp, ignoreCrypto bool, ad *AuthDigest, sk *StaticKey, cks []*WrappedKey) bool { 455 if !(msg.LocalSessionID > 0 && (msg.ReplayPacketID == 1 || msg.ReplayPacketID == 0x0f000001) && 456 (ignoreTimestamp || msg.ValidateReplayTimestamp(time.Now()))) { 457 return false 458 } 459 460 if ignoreCrypto { 461 return true 462 } 463 464 if len(cks) > 0 { 465 for _, ck := range cks { 466 if bytes.Equal(ck.HMAC, msg.WrappedKey.HMAC) && bytes.Equal(ck.Encrypted, msg.WrappedKey.Encrypted) { 467 return msg.MessageCrypt.DecryptAndAuthenticate(ad, &ck.StaticKey) && 468 msg.PrevPacketIDsCount == 0 && msg.ThisPacketID == 0 469 } 470 } 471 return false 472 } 473 474 return sk == nil || (msg.DecryptAndAuthenticate(ad, sk) && msg.PrevPacketIDsCount == 0 && msg.ThisPacketID == 0) 475 } 476 477 // ToBytes returns a slice of bytes representing msg's internal structures. 478 func (msg *MessageCrypt2) ToBytes() []byte { 479 return slices.Concat(msg.MessageCrypt.ToBytes(), msg.WrappedKey.ToBytes()) 480 } 481 482 // MessageTraitAuth contains fields and implements features related to authentication. 483 type MessageTraitAuth struct { 484 // Digest is a pointer to AuthDigest to be used for authentication. 485 Digest *AuthDigest 486 // HMAC is a hash-based messaged authentication code used to verify message integrity. 487 HMAC []byte 488 } 489 490 // AuthenticateOnClient returns true if msg composed on the client has a valid HMAC. 491 func (msg *MessageTraitAuth) AuthenticateOnClient(ad *AuthDigest, sk *StaticKey, xp func() []byte) bool { 492 // No supported digest returns an HMAC of 0 bytes. 493 if len(msg.HMAC) == 0 { 494 return false 495 } 496 497 // Check that there is a valid StaticKey. 498 // A half key may be provided as a server key to validate a WrappedKey. 499 if sk == nil || !(len(sk.KeyBytes) == StaticKeyBytesTotal || len(sk.KeyBytes) == StaticKeyBytesHalf) { 500 return false 501 } 502 503 // Obtain a slice of bytes to compute a digest of. 504 plain := xp() 505 506 // Firstly, try the given digest. 507 if ad != nil { 508 if len(msg.HMAC) == ad.Size && ad.HMACValidateOnClient(sk, plain, msg.HMAC) { 509 msg.Digest = ad 510 return true 511 } 512 return false 513 } 514 515 // Secondly, try the last successful one saved as Digest. 516 if msg.Digest != nil && len(msg.HMAC) == msg.Digest.Size && msg.Digest.HMACValidateOnClient(sk, plain, msg.HMAC) { 517 return true 518 } 519 520 // Finally, try all other supported digests one by one. 521 for _, mad := range AuthDigests { 522 if mad != msg.Digest && len(msg.HMAC) == mad.Size && mad.HMACValidateOnClient(sk, plain, msg.HMAC) { 523 msg.Digest = mad 524 return true 525 } 526 } 527 528 return false 529 } 530 531 // AuthenticateOnServer returns true if msg composed on the server has a valid HMAC. 532 func (msg *MessageTraitAuth) AuthenticateOnServer(ad *AuthDigest, sk *StaticKey, xp func() []byte) bool { 533 // No supported digest returns an HMAC of 0 bytes. 534 if len(msg.HMAC) == 0 { 535 return false 536 } 537 538 // Check that there is a valid StaticKey. 539 if sk == nil || len(sk.KeyBytes) != StaticKeyBytesTotal { 540 return false 541 } 542 543 // Obtain a slice of bytes to compute a digest of. 544 plain := xp() 545 546 // Firstly, try the given digest. 547 if ad != nil { 548 if len(msg.HMAC) == ad.Size && ad.HMACValidateOnServer(sk, plain, msg.HMAC) { 549 msg.Digest = ad 550 return true 551 } 552 return false 553 } 554 555 // Secondly, try the last successful one saved as Digest. 556 if msg.Digest != nil && len(msg.HMAC) == msg.Digest.Size && msg.Digest.HMACValidateOnServer(sk, plain, msg.HMAC) { 557 return true 558 } 559 560 // Finally, try all other supported digests one by one. 561 for _, mad := range AuthDigests { 562 if mad != msg.Digest && len(msg.HMAC) == mad.Size && mad.HMACValidateOnServer(sk, plain, msg.HMAC) { 563 msg.Digest = mad 564 return true 565 } 566 } 567 568 return false 569 } 570 571 // SignOnClient computes an HMAC for msg composed on the client. 572 func (msg *MessageTraitAuth) SignOnClient(ad *AuthDigest, sk *StaticKey, xp func() []byte) error { 573 // Check that there is a valid StaticKey. 574 // A half key may be provided as a server key to sign a WrappedKey. 575 if sk == nil || !(len(sk.KeyBytes) == StaticKeyBytesTotal || len(sk.KeyBytes) == StaticKeyBytesHalf) { 576 return ErrInvalidAuthPrerequisites 577 } 578 579 // Obtain a slice of bytes to compute a digest of. 580 plain := xp() 581 582 // Firstly, try the given digest. 583 if ad != nil { 584 msg.HMAC = ad.HMACGenerateOnClient(sk, plain) 585 } 586 587 // Secondly, try the internal Digest. 588 if msg.Digest != nil { 589 msg.HMAC = msg.Digest.HMACGenerateOnClient(sk, plain) 590 } 591 592 // Finally, use the default digest. 593 msg.Digest, msg.HMAC = AuthDigestDefault, AuthDigestDefault.HMACGenerateOnClient(sk, plain) 594 595 return nil 596 } 597 598 // SignOnServer computes an HMAC for msg composed on the server. 599 func (msg *MessageTraitAuth) SignOnServer(ad *AuthDigest, sk *StaticKey, xp func() []byte) error { 600 // Check that there is a valid StaticKey. 601 // A half key may be provided as a server key to sign a WrappedKey. 602 if sk == nil || !(len(sk.KeyBytes) == StaticKeyBytesTotal || len(sk.KeyBytes) == StaticKeyBytesHalf) { 603 return ErrInvalidAuthPrerequisites 604 } 605 606 // Obtain a slice of bytes to compute a digest of. 607 plain := xp() 608 609 // Firstly, try the given digest. 610 if ad != nil { 611 msg.HMAC = ad.HMACGenerateOnServer(sk, plain) 612 } 613 614 // Secondly, try the internal Digest. 615 if msg.Digest != nil { 616 msg.HMAC = msg.Digest.HMACGenerateOnServer(sk, plain) 617 } 618 619 // Finally, use the default digest. 620 msg.Digest, msg.HMAC = AuthDigestDefault, AuthDigestDefault.HMACGenerateOnServer(sk, plain) 621 622 return nil 623 } 624 625 // MessageTraitCrypt contains fields and implements features related to en-/decryption. 626 type MessageTraitCrypt struct { 627 // Cipher is a pointer to CryptCipher to be used for encryption. 628 Cipher *CryptCipher 629 // Encrypted contains a number of bytes to be decrypted. 630 Encrypted []byte 631 } 632 633 // DecryptOnClient decrypts msg's encrypted bytes with an encryption key used by the server. 634 func (msg *MessageTraitCrypt) DecryptOnClient(sk *StaticKey, ta *MessageTraitAuth, xd func([]byte) error) error { 635 if sk == nil || msg.Cipher == nil || ta.Digest == nil || len(ta.HMAC) != ta.Digest.Size { 636 return ErrInvalidCryptPrerequisites 637 } 638 639 plain := msg.Cipher.DecryptOnClient(sk, ta.HMAC[:min(msg.Cipher.SizeBlock, ta.Digest.Size)], msg.Encrypted) 640 641 return xd(plain) 642 } 643 644 // DecryptOnServer decrypts msg's encrypted bytes with an encryption key used by the client. 645 func (msg *MessageTraitCrypt) DecryptOnServer(sk *StaticKey, ta *MessageTraitAuth, xd func([]byte) error) error { 646 if sk == nil || msg.Cipher == nil || ta.Digest == nil || len(ta.HMAC) != ta.Digest.Size { 647 return ErrInvalidCryptPrerequisites 648 } 649 650 plain := msg.Cipher.DecryptOnServer(sk, ta.HMAC[:min(msg.Cipher.SizeBlock, ta.Digest.Size)], msg.Encrypted) 651 652 return xd(plain) 653 } 654 655 // EncryptOnClient encrypts msg's plain bytes with a decryption key used by the server. 656 func (msg *MessageTraitCrypt) EncryptOnClient(sk *StaticKey, ta *MessageTraitAuth, xe func() []byte) error { 657 if sk == nil || msg.Cipher == nil || ta.Digest == nil || len(ta.HMAC) != ta.Digest.Size { 658 return ErrInvalidCryptPrerequisites 659 } 660 661 plain := xe() 662 663 msg.Encrypted = msg.Cipher.EncryptOnClient(sk, ta.HMAC[:min(msg.Cipher.SizeBlock, ta.Digest.Size)], plain) 664 if len(plain) != len(msg.Encrypted) { 665 return ErrInvalidEncryptedLength 666 } 667 668 return nil 669 } 670 671 // EncryptOnServer encrypts msg's plain bytes with a decryption key used by the client. 672 func (msg *MessageTraitCrypt) EncryptOnServer(sk *StaticKey, ta *MessageTraitAuth, xe func() []byte) error { 673 if sk == nil || msg.Cipher == nil || ta.Digest == nil || len(ta.HMAC) != ta.Digest.Size { 674 return ErrInvalidCryptPrerequisites 675 } 676 677 plain := xe() 678 679 msg.Encrypted = msg.Cipher.EncryptOnServer(sk, ta.HMAC[:min(msg.Cipher.SizeBlock, ta.Digest.Size)], plain) 680 if len(plain) != len(msg.Encrypted) { 681 return ErrInvalidEncryptedLength 682 } 683 684 return nil 685 } 686 687 // MessageTraitReplay contains fields and implements features related to replay protection. 688 type MessageTraitReplay struct { 689 // ReplayPacketID is a 4-byte packet ID used for replay protection. 690 ReplayPacketID uint32 691 // ReplayTimestamp is a 4-byte timestamp used for replay protection. 692 ReplayTimestamp uint32 693 } 694 695 // ValidateReplayTimestamp returns true if msg has a valid ReplayTimestamp (relative to the provided time). 696 func (msg *MessageTraitReplay) ValidateReplayTimestamp(t time.Time) bool { 697 tReplay := time.Unix(int64(msg.ReplayTimestamp), 0) 698 tNowLow := t.UTC().Add(-TimestampValidationInterval) 699 tNowHigh := t.UTC().Add(TimestampValidationInterval) 700 return tReplay.After(tNowLow) && tReplay.Before(tNowHigh) 701 } 702 703 // MetaData is an optional set of Type and Payload that may be included into WrappedKey. 704 type MetaData struct { 705 // Payload contains a number of bytes of variable length corresponding to Type. 706 Payload []byte 707 // Type indicates how to parse Payload correctly. It may equal 0x00 for any user defined data 708 // and 0x01 for a 4-byte timestamp which enables discarding old client keys on the server. 709 Type uint8 710 } 711 712 // WrappedKey is an authenticated and encrypted client key used to encrypt MessageCrypt in the crypt2 mode. 713 type WrappedKey struct { 714 MetaData 715 StaticKey 716 MessageTraitAuth 717 MessageTraitCrypt 718 } 719 720 // Authenticate returns true if wk's HMAC is valid. 721 func (wk *WrappedKey) Authenticate(ad *AuthDigest, sk *StaticKey) bool { 722 return wk.MessageTraitAuth.AuthenticateOnClient(ad, sk, wk.ToBytesAuth) 723 } 724 725 // DecryptAndAuthenticate decrypts wk's encrypted bytes before calling Authenticate. 726 func (wk *WrappedKey) DecryptAndAuthenticate(ad *AuthDigest, sk *StaticKey) bool { 727 if len(wk.Encrypted) < StaticKeyBytesTotal || 728 len(wk.Encrypted) > WrappedKeyBytesMax-LengthBytesTotal-CryptHMACBytesTotal || 729 wk.MessageTraitCrypt.DecryptOnClient(sk, &wk.MessageTraitAuth, wk.FromBytesCrypt) != nil { 730 return false 731 } 732 return wk.Authenticate(ad, sk) 733 } 734 735 // EncryptAndSign encrypts wk's plain bytes before calling Sign. 736 func (wk *WrappedKey) EncryptAndSign(ad *AuthDigest, sk *StaticKey) error { 737 if err := wk.MessageTraitCrypt.EncryptOnServer(sk, &wk.MessageTraitAuth, wk.ToBytesCrypt); err != nil { 738 return err 739 } 740 return wk.Sign(ad, sk) 741 } 742 743 // FromBase64 fills wk's internal structures (including decrypted StaticKey bytes) from a base64 string. 744 func (wk *WrappedKey) FromBase64(s string) error { 745 src, err := base64.StdEncoding.DecodeString(s) 746 if err != nil { 747 return err 748 } 749 750 if len(src) < WrappedKeyBytesMin+StaticKeyBytesTotal || len(src) > WrappedKeyBytesMax+StaticKeyBytesTotal { 751 return ErrInvalidSourceLength 752 } 753 754 wk.StaticKey.KeyBytes = src[:StaticKeyBytesTotal] 755 756 return wk.FromBytes(src[StaticKeyBytesTotal:]) 757 } 758 759 // FromBytes fills wk's internal structures from a slice of bytes. 760 func (wk *WrappedKey) FromBytes(src []byte) error { 761 // Any WrappedKey has a 2-byte length at the end. Ensure that it has a valid value. 762 if len(src) < WrappedKeyBytesMin || len(src) > WrappedKeyBytesMax || 763 len(src) != int(BytesOrder.Uint16(src[len(src)-LengthBytesTotal:])) { 764 return ErrInvalidSourceLength 765 } 766 767 // Any WrappedKey has a 32-byte SHA-256 HMAC at the beginning. 768 wk.Digest, wk.HMAC = AuthDigestDefault, src[:CryptHMACBytesTotal] 769 770 // Any WrappedKey has an Encrypted part of at least 256 bytes between HMAC and Length. 771 wk.Cipher, wk.Encrypted = CryptCipherDefault, src[CryptHMACBytesTotal:len(src)-LengthBytesTotal] 772 773 return nil 774 } 775 776 // FromBytesCrypt fills wk's internal structures from a slice of bytes after decryption. 777 func (wk *WrappedKey) FromBytesCrypt(plain []byte) error { 778 if len(plain) != len(wk.Encrypted) { 779 return ErrInvalidPlainLength 780 } 781 782 // Any WrappedKey has a StaticKey at the beginning of the plain text. 783 wk.StaticKey.KeyBytes = plain[:StaticKeyBytesTotal] 784 785 // Any WrappedKey may have a MetaData.Type between StaticKey and MetaData in the plain text. 786 if len(plain) > StaticKeyBytesTotal { 787 wk.MetaData.Type = plain[StaticKeyBytesTotal] 788 } 789 790 // Any KeyMata may have MetaData.Payload at the end of the plain text. 791 if len(plain) > StaticKeyBytesTotal+MetaDataTypeBytesTotal { 792 wk.MetaData.Payload = plain[StaticKeyBytesTotal+MetaDataTypeBytesTotal:] 793 } 794 795 return nil 796 } 797 798 // FromClientKeyFile fills wk's internal structures (including decrypted StaticKey bytes) from a given file. 799 func (wk *WrappedKey) FromClientKeyFile(path string) error { 800 err := wk.StaticKey.FromFile(path, StaticKeyFromFileBase64, 0, wk.StaticKey.FromBase64) 801 if err != nil { 802 return err 803 } 804 805 if len(wk.StaticKey.KeyBytes) < WrappedKeyBytesMin || len(wk.StaticKey.KeyBytes) > WrappedKeyBytesMax { 806 return ErrInvalidStaticKeyFileContents 807 } 808 809 err = wk.FromBytes(wk.StaticKey.KeyBytes[StaticKeyBytesTotal:]) 810 if err != nil { 811 return err 812 } 813 814 wk.StaticKey.KeyBytes = wk.StaticKey.KeyBytes[:StaticKeyBytesTotal] 815 return nil 816 } 817 818 // Sign computes and fills wk's HMAC. 819 func (wk *WrappedKey) Sign(ad *AuthDigest, sk *StaticKey) error { 820 return wk.MessageTraitAuth.SignOnClient(ad, sk, wk.ToBytesAuth) 821 } 822 823 // ToBytes returns a slice of bytes representing wk's internal structures. 824 func (wk *WrappedKey) ToBytes() []byte { 825 dst := make([]byte, 0, len(wk.HMAC)+len(wk.Encrypted)+LengthBytesTotal) 826 dst = append(dst, wk.HMAC...) 827 dst = append(dst, wk.Encrypted...) 828 dst = BytesOrder.AppendUint16(dst, uint16(cap(dst))) 829 return dst 830 } 831 832 // ToBytesAuth returns a slice of bytes representing wk's internal structures without HMAC. 833 func (wk *WrappedKey) ToBytesAuth() []byte { 834 if len(wk.MetaData.Payload) > 0 { 835 dst := make([]byte, 0, LengthBytesTotal+len(wk.StaticKey.KeyBytes)+MetaDataTypeBytesTotal+len(wk.MetaData.Payload)) 836 dst = BytesOrder.AppendUint16(dst, uint16(cap(dst)+CryptHMACBytesTotal)) 837 dst = append(dst, wk.StaticKey.KeyBytes...) 838 dst = append(dst, wk.MetaData.Type) 839 dst = append(dst, wk.MetaData.Payload...) 840 return dst 841 } else { 842 dst := make([]byte, 0, LengthBytesTotal+len(wk.StaticKey.KeyBytes)) 843 dst = BytesOrder.AppendUint16(dst, uint16(cap(dst)+CryptHMACBytesTotal)) 844 dst = append(dst, wk.StaticKey.KeyBytes...) 845 return dst 846 } 847 } 848 849 // ToBytesCrypt returns a slice of bytes representing wk's internal structures before encryption. 850 func (wk *WrappedKey) ToBytesCrypt() []byte { 851 if len(wk.MetaData.Payload) > 0 { 852 dst := make([]byte, 0, len(wk.StaticKey.KeyBytes)+MetaDataTypeBytesTotal+len(wk.MetaData.Payload)) 853 dst = append(dst, wk.StaticKey.KeyBytes...) 854 dst = append(dst, wk.MetaData.Type) 855 dst = append(dst, wk.MetaData.Payload...) 856 return dst 857 } else { 858 return wk.StaticKey.KeyBytes 859 } 860 } 861 862 var ( 863 BytesOrder = binary.BigEndian 864 865 ErrInvalidAuthPrerequisites = errors.New("invalid auth prerequisites") 866 ErrInvalidCryptPrerequisites = errors.New("invalid crypt prerequisites") 867 ErrInvalidEncryptedLength = errors.New("invalid encrypted length") 868 ErrInvalidHeaderOpcode = errors.New("invalid header opcode") 869 ErrInvalidHMACLength = errors.New("invalid HMAC length") 870 ErrInvalidPlainLength = errors.New("invalid plain length") 871 ErrInvalidSourceLength = errors.New("invalid source length") 872 ErrMissingReusableHeader = errors.New("missing reusable header") 873 ) 874 875 const ( 876 /* 877 * Irrelevant MessageHeader.Opcode values: 878 * 879 * OpcodeControlHardResetClientV1 uint8 = 1 880 * OpcodeControlHardResetServerV1 uint8 = 2 881 * OpcodeControlSoftResetV1 uint8 = 3 882 * OpcodeControlV1 uint8 = 4 883 * OpcodeAckV1 uint8 = 5 884 * OpcodeDataV1 uint8 = 6 885 * OpcodeControlHardResetServerV2 uint8 = 8 886 * OpcodeDataV2 uint8 = 9 887 * OpcodeControlWrappedClientKeyV1 uint8 = 11 888 */ 889 890 OpcodeControlHardResetClientV2 uint8 = 7 891 OpcodeControlHardResetClientV3 uint8 = 10 892 893 KeyIDMask uint8 = 0b1<<OpcodeShift - 1 894 895 OpcodeShift = 3 896 897 AckPacketIDsCountBytesTotal = 1 898 LengthBytesTotal = 2 899 MetaDataPayloadBytesMax = WrappedKeyBytesMax - MetaDataTypeBytesTotal - WrappedKeyBytesMin 900 MetaDataTypeBytesTotal = 1 901 OpcodeKeyIDBytesTotal = 1 902 PacketIDBytesTotal = 4 903 SessionIDBytesTotal = 8 904 TimestampBytesTotal = 4 905 906 WrappedKeyBytesMax = 1024 907 WrappedKeyBytesMin = CryptHMACBytesTotal + StaticKeyBytesTotal + LengthBytesTotal 908 909 TimestampValidationInterval = 15 * time.Second 910 911 MessagePlainBytesTotalHL = SessionIDBytesTotal + AckPacketIDsCountBytesTotal + PacketIDBytesTotal 912 MessagePlainBytesTotal = OpcodeKeyIDBytesTotal + MessagePlainBytesTotalHL 913 MessageAuthBytesMaxHL = MessagePlainBytesTotalHL + AuthHMACBytesMax + PacketIDBytesTotal + TimestampBytesTotal 914 MessageAuthBytesMax = OpcodeKeyIDBytesTotal + MessageAuthBytesMaxHL 915 MessageAuthBytesMinHL = MessagePlainBytesTotalHL + AuthHMACBytesMin + PacketIDBytesTotal + TimestampBytesTotal 916 MessageAuthBytesMin = OpcodeKeyIDBytesTotal + MessageAuthBytesMinHL 917 MessageCryptBytesTotalHL = MessagePlainBytesTotalHL + PacketIDBytesTotal + TimestampBytesTotal + CryptHMACBytesTotal 918 MessageCryptBytesTotal = OpcodeKeyIDBytesTotal + MessageCryptBytesTotalHL 919 MessageCrypt2BytesMinHL = MessageCryptBytesTotalHL + LengthBytesTotal + CryptHMACBytesTotal + StaticKeyBytesTotal 920 MessageCrypt2BytesMin = OpcodeKeyIDBytesTotal + MessageCrypt2BytesMinHL 921 MessageCrypt2BytesMaxHL = MessageCrypt2BytesMinHL + MetaDataTypeBytesTotal + MetaDataPayloadBytesMax 922 MessageCrypt2BytesMax = OpcodeKeyIDBytesTotal + MessageCrypt2BytesMaxHL 923 ) 924 925 // WrappedKeyNewFromBase64 returns a pointer to WrappedKey filled with bytes from a given base64 string. 926 func WrappedKeyNewFromBase64(s string) *WrappedKey { 927 wk := &WrappedKey{} 928 _ = wk.FromBase64(s) 929 return wk 930 } 931 932 // References: 933 // 934 // - Official manuals: 935 // https://openvpn.net/community-resources/openvpn-cryptographic-layer/ 936 // https://openvpn.net/community-resources/openvpn-protocol/ 937 // https://openvpn.net/community-resources/reference-manual-for-openvpn-2-6/ 938 // https://openvpn.net/faq/changed-hex-bytes-in-the-static-key-the-key-still-connects-to-a-remote-peer-using-the-original-key/ 939 // 940 // - OpenVPN codebase: 941 // https://github.com/OpenVPN/openvpn/ 942 // https://github.com/OpenVPN/openvpn3/ 943 // 944 // - Third-party solutions: 945 // https://github.com/corelight/zeek-openvpn/blob/master/src/openvpn-analyzer.pac 946 // https://github.com/ntop/nDPI/blob/dev/src/lib/protocols/openvpn.c 947 // https://github.com/yrutschle/sslh/blob/master/probe.c 948 // https://github.com/wireshark/wireshark/blob/master/epan/dissectors/packet-openvpn.c