Bence Béky | bac0405 | 2022-04-07 15:44:29 -0400 | [diff] [blame] | 1 | // Copyright (c) 2022 The Chromium Authors. All rights reserved. |
| 2 | // Use of this source code is governed by a BSD-style license that can be |
| 3 | // found in the LICENSE file. |
| 4 | |
bnc | e5642f3 | 2022-04-11 13:45:33 -0700 | [diff] [blame] | 5 | #ifndef QUICHE_QUIC_LOAD_BALANCER_LOAD_BALANCER_CONFIG_H_ |
| 6 | #define QUICHE_QUIC_LOAD_BALANCER_LOAD_BALANCER_CONFIG_H_ |
Bence Béky | bac0405 | 2022-04-07 15:44:29 -0400 | [diff] [blame] | 7 | |
vasilvv | daa2fda | 2022-04-11 14:08:36 -0700 | [diff] [blame] | 8 | #include "openssl/aes.h" |
Bence Béky | bac0405 | 2022-04-07 15:44:29 -0400 | [diff] [blame] | 9 | #include "quiche/quic/core/quic_types.h" |
| 10 | #include "quiche/quic/platform/api/quic_export.h" |
| 11 | |
| 12 | namespace quic { |
| 13 | |
martinduke | 77084d5 | 2022-04-07 12:27:31 -0700 | [diff] [blame] | 14 | inline constexpr uint8_t kNumLoadBalancerConfigs = 3; |
Bence Béky | bac0405 | 2022-04-07 15:44:29 -0400 | [diff] [blame] | 15 | inline constexpr uint8_t kLoadBalancerKeyLen = 16; |
| 16 | // Regardless of key length, the AES block size is always 16 Bytes. |
| 17 | inline constexpr uint8_t kLoadBalancerBlockSize = 16; |
| 18 | // The spec says nonces can be 18 bytes, but 16 lets it be a uint128. |
| 19 | inline constexpr uint8_t kLoadBalancerMaxNonceLen = 16; |
| 20 | inline constexpr uint8_t kLoadBalancerMinNonceLen = 4; |
martinduke | 77084d5 | 2022-04-07 12:27:31 -0700 | [diff] [blame] | 21 | inline constexpr uint8_t kNumLoadBalancerCryptoPasses = 4; |
Bence Béky | bac0405 | 2022-04-07 15:44:29 -0400 | [diff] [blame] | 22 | |
| 23 | // This the base class for QUIC-LB configuration. It contains configuration |
| 24 | // elements usable by both encoders (servers) and decoders (load balancers). |
| 25 | // Confusingly, it is called "LoadBalancerConfig" because it pertains to objects |
| 26 | // that both servers and load balancers use to interact with each other. |
| 27 | class QUIC_EXPORT_PRIVATE LoadBalancerConfig { |
| 28 | public: |
| 29 | // This factory function initializes an encrypted LoadBalancerConfig and |
| 30 | // returns it in absl::optional, which is empty if the config is invalid. |
| 31 | // config_id: The first two bits of the Connection Id. Must be no larger than |
| 32 | // 2. |
| 33 | // server_id_len: Expected length of the server ids associated with this |
| 34 | // config. Must be greater than 0 and less than 16. |
| 35 | // nonce_len: Length of the nonce. Must be at least 4 and no larger than 16. |
| 36 | // Further the server_id_len + nonce_len must be no larger than 19. |
| 37 | // key: The encryption key must be 16B long. |
| 38 | static absl::optional<LoadBalancerConfig> Create(const uint8_t config_id, |
| 39 | const uint8_t server_id_len, |
| 40 | const uint8_t nonce_len, |
| 41 | const absl::string_view key); |
| 42 | |
| 43 | // Creates an unencrypted config. |
| 44 | static absl::optional<LoadBalancerConfig> CreateUnencrypted( |
| 45 | const uint8_t config_id, const uint8_t server_id_len, |
| 46 | const uint8_t nonce_len); |
| 47 | |
| 48 | // Handles one pass of 4-pass encryption. Encoder and decoder use of this |
| 49 | // function varies substantially, so they are not implemented here. |
martinduke | 76b4dae | 2022-04-13 11:11:09 -0700 | [diff] [blame] | 50 | // Returns false if the config is not encrypted, or if |target| isn't long |
| 51 | // enough. |
| 52 | ABSL_MUST_USE_RESULT bool EncryptionPass(absl::Span<uint8_t> target, |
Bence Béky | bac0405 | 2022-04-07 15:44:29 -0400 | [diff] [blame] | 53 | const uint8_t index) const; |
| 54 | // Use the key to do a block encryption, which is used both in all cases of |
| 55 | // encrypted configs. Returns false if there's no key. |
| 56 | ABSL_MUST_USE_RESULT bool BlockEncrypt( |
| 57 | const uint8_t plaintext[kLoadBalancerBlockSize], |
| 58 | uint8_t ciphertext[kLoadBalancerBlockSize]) const; |
| 59 | // Returns false if the config does not require block decryption. |
| 60 | ABSL_MUST_USE_RESULT bool BlockDecrypt( |
| 61 | const uint8_t ciphertext[kLoadBalancerBlockSize], |
| 62 | uint8_t plaintext[kLoadBalancerBlockSize]) const; |
| 63 | |
| 64 | uint8_t config_id() const { return config_id_; } |
| 65 | uint8_t server_id_len() const { return server_id_len_; } |
| 66 | uint8_t nonce_len() const { return nonce_len_; } |
martinduke | 77084d5 | 2022-04-07 12:27:31 -0700 | [diff] [blame] | 67 | // Returns length of all but the first octet. |
| 68 | uint8_t plaintext_len() const { return server_id_len_ + nonce_len_; } |
| 69 | // Returns length of the entire connection ID. |
| 70 | uint8_t total_len() const { return server_id_len_ + nonce_len_ + 1; } |
Bence Béky | bac0405 | 2022-04-07 15:44:29 -0400 | [diff] [blame] | 71 | bool IsEncrypted() const { return key_.has_value(); } |
| 72 | |
| 73 | private: |
| 74 | // Constructor is private because it doesn't validate input. |
| 75 | LoadBalancerConfig(uint8_t config_id, uint8_t server_id_len, |
| 76 | uint8_t nonce_len, absl::string_view key); |
| 77 | |
| 78 | uint8_t config_id_; |
| 79 | uint8_t server_id_len_; |
| 80 | uint8_t nonce_len_; |
| 81 | // All Connection ID encryption and decryption uses the AES_encrypt function |
| 82 | // at root, so there is a single key for all of it. This is empty if the |
| 83 | // config is not encrypted. |
| 84 | absl::optional<AES_KEY> key_; |
| 85 | // The one exception is that when total_len == 16, connection ID decryption |
| 86 | // uses AES_decrypt. The bytes that comprise the key are the same, but |
| 87 | // AES_decrypt requires an AES_KEY that is initialized differently. In all |
| 88 | // other cases, block_decrypt_key_ is empty. |
| 89 | absl::optional<AES_KEY> block_decrypt_key_; |
| 90 | }; |
| 91 | |
| 92 | } // namespace quic |
| 93 | |
bnc | e5642f3 | 2022-04-11 13:45:33 -0700 | [diff] [blame] | 94 | #endif // QUICHE_QUIC_LOAD_BALANCER_LOAD_BALANCER_CONFIG_H_ |