1 /** @file
2  *
3  *  A brief file description
4  *
5  *  @section license License
6  *
7  *  Licensed to the Apache Software Foundation (ASF) under one
8  *  or more contributor license agreements.  See the NOTICE file
9  *  distributed with this work for additional information
10  *  regarding copyright ownership.  The ASF licenses this file
11  *  to you under the Apache License, Version 2.0 (the
12  *  "License"); you may not use this file except in compliance
13  *  with the License.  You may obtain a copy of the License at
14  *
15  *      http://www.apache.org/licenses/LICENSE-2.0
16  *
17  *  Unless required by applicable law or agreed to in writing, software
18  *  distributed under the License is distributed on an "AS IS" BASIS,
19  *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
20  *  See the License for the specific language governing permissions and
21  *  limitations under the License.
22  */
23 
24 #include <cstdlib>
25 #include "tscore/Diags.h"
26 #include "QUICGlobals.h"
27 #include "QUICIntUtil.h"
28 #include "QUICTransportParameters.h"
29 #include "QUICConnection.h"
30 #include "QUICHandshake.h"
31 #include "QUICDebugNames.h"
32 #include "QUICTLS.h"
33 #include "QUICTypes.h"
34 
35 static constexpr char tag[] = "quic_handshake";
36 
37 static constexpr uint32_t TP_ERROR_LENGTH = 0x010000;
38 static constexpr uint32_t TP_ERROR_VALUE  = 0x020000;
39 // static constexpr uint32_t TP_ERROR_MUST_EXIST     = 0x030000;
40 static constexpr uint32_t TP_ERROR_MUST_NOT_EXIST = 0x040000;
41 
Value(const uint8_t * data,uint16_t len)42 QUICTransportParameters::Value::Value(const uint8_t *data, uint16_t len) : _len(len)
43 {
44   this->_data = static_cast<uint8_t *>(ats_malloc(len));
45   memcpy(this->_data, data, len);
46 }
47 
~Value()48 QUICTransportParameters::Value::~Value()
49 {
50   ats_free(this->_data);
51   this->_data = nullptr;
52 }
53 
54 bool
is_valid() const55 QUICTransportParameters::is_valid() const
56 {
57   return this->_valid;
58 }
59 
60 const uint8_t *
data() const61 QUICTransportParameters::Value::data() const
62 {
63   return this->_data;
64 }
65 
66 uint16_t
len() const67 QUICTransportParameters::Value::len() const
68 {
69   return this->_len;
70 }
71 
~QUICTransportParameters()72 QUICTransportParameters::~QUICTransportParameters()
73 {
74   for (auto p : this->_parameters) {
75     delete p.second;
76   }
77 }
78 
79 void
_load(const uint8_t * buf,size_t len)80 QUICTransportParameters::_load(const uint8_t *buf, size_t len)
81 {
82   bool has_error   = false;
83   const uint8_t *p = buf;
84 
85   // Read size of parameters field
86   uint16_t nbytes = (p[0] << 8) + p[1];
87   p += 2;
88 
89   // Read parameters
90   const uint8_t *end = p + nbytes;
91   while (p < end) {
92     // Read ID
93     uint16_t id = 0;
94     if (end - p >= 2) {
95       id = (p[0] << 8) + p[1];
96       p += 2;
97     } else {
98       has_error = true;
99       break;
100     }
101 
102     // Check duplication
103     // An endpoint MUST treat receipt of duplicate transport parameters as a connection error of type TRANSPORT_PARAMETER_ERROR
104     if (this->_parameters.find(id) != this->_parameters.end()) {
105       has_error = true;
106       break;
107     }
108 
109     // Read length of value
110     uint16_t len = 0;
111     if (end - p >= 2) {
112       len = (p[0] << 8) + p[1];
113       p += 2;
114     } else {
115       has_error = true;
116       break;
117     }
118 
119     // Store parameter
120     if (end - p >= len) {
121       this->_parameters.insert(std::make_pair(id, new Value(p, len)));
122       p += len;
123     } else {
124       has_error = true;
125       break;
126     }
127   }
128 
129   if (has_error) {
130     this->_valid = false;
131     return;
132   }
133 
134   // Validate parameters
135   int res = this->_validate_parameters();
136   if (res < 0) {
137     Debug(tag, "Transport parameter is not valid (err=%d)", res);
138     this->_valid = false;
139   } else {
140     this->_valid = true;
141   }
142 }
143 
144 int
_validate_parameters() const145 QUICTransportParameters::_validate_parameters() const
146 {
147   decltype(this->_parameters)::const_iterator ite;
148 
149   // MUSTs
150 
151   // MAYs
152   if ((ite = this->_parameters.find(QUICTransportParameterId::INITIAL_MAX_DATA)) != this->_parameters.end()) {
153   }
154 
155   if ((ite = this->_parameters.find(QUICTransportParameterId::INITIAL_MAX_STREAMS_BIDI)) != this->_parameters.end()) {
156   }
157 
158   if ((ite = this->_parameters.find(QUICTransportParameterId::INITIAL_MAX_STREAMS_UNI)) != this->_parameters.end()) {
159   }
160 
161   if ((ite = this->_parameters.find(QUICTransportParameterId::IDLE_TIMEOUT)) != this->_parameters.end()) {
162   }
163 
164   if ((ite = this->_parameters.find(QUICTransportParameterId::MAX_PACKET_SIZE)) != this->_parameters.end()) {
165     if (QUICIntUtil::read_nbytes_as_uint(ite->second->data(), ite->second->len()) < 1200) {
166       return -(TP_ERROR_VALUE | QUICTransportParameterId::MAX_PACKET_SIZE);
167     }
168   }
169 
170   if ((ite = this->_parameters.find(QUICTransportParameterId::ACK_DELAY_EXPONENT)) != this->_parameters.end()) {
171     if (QUICIntUtil::read_nbytes_as_uint(ite->second->data(), ite->second->len()) > 20) {
172       return -(TP_ERROR_VALUE | QUICTransportParameterId::ACK_DELAY_EXPONENT);
173     }
174   }
175 
176   // MAYs (initial values for the flow control on each type of stream)
177   if ((ite = this->_parameters.find(QUICTransportParameterId::INITIAL_MAX_STREAM_DATA_BIDI_LOCAL)) != this->_parameters.end()) {
178   }
179 
180   if ((ite = this->_parameters.find(QUICTransportParameterId::INITIAL_MAX_STREAM_DATA_BIDI_REMOTE)) != this->_parameters.end()) {
181   }
182 
183   if ((ite = this->_parameters.find(QUICTransportParameterId::INITIAL_MAX_STREAM_DATA_UNI)) != this->_parameters.end()) {
184   }
185 
186   if ((ite = this->_parameters.find(QUICTransportParameterId::DISABLE_ACTIVE_MIGRATION)) != this->_parameters.end()) {
187   }
188 
189   if ((ite = this->_parameters.find(QUICTransportParameterId::MAX_ACK_DELAY)) != this->_parameters.end()) {
190   }
191 
192   return 0;
193 }
194 
195 const uint8_t *
getAsBytes(QUICTransportParameterId tpid,uint16_t & len) const196 QUICTransportParameters::getAsBytes(QUICTransportParameterId tpid, uint16_t &len) const
197 {
198   auto p = this->_parameters.find(tpid);
199   if (p != this->_parameters.end()) {
200     len = p->second->len();
201     return p->second->data();
202   }
203 
204   len = 0;
205   return nullptr;
206 }
207 
208 uint64_t
getAsUInt(QUICTransportParameterId tpid) const209 QUICTransportParameters::getAsUInt(QUICTransportParameterId tpid) const
210 {
211   uint64_t int_value       = 0;
212   size_t int_value_len     = 0;
213   uint16_t raw_value_len   = 0;
214   const uint8_t *raw_value = this->getAsBytes(tpid, raw_value_len);
215   if (raw_value) {
216     QUICVariableInt::decode(int_value, int_value_len, raw_value, raw_value_len);
217     return int_value;
218   } else {
219     return 0;
220   }
221 }
222 
223 bool
contains(QUICTransportParameterId id) const224 QUICTransportParameters::contains(QUICTransportParameterId id) const
225 {
226   // Use std::map::contains when C++20 is supported
227   auto p = this->_parameters.find(id);
228   return (p != this->_parameters.end());
229 }
230 
231 void
set(QUICTransportParameterId id,const uint8_t * value,uint16_t value_len)232 QUICTransportParameters::set(QUICTransportParameterId id, const uint8_t *value, uint16_t value_len)
233 {
234   if (this->_parameters.find(id) != this->_parameters.end()) {
235     this->_parameters.erase(id);
236   }
237   this->_parameters.insert(std::make_pair(id, new Value(value, value_len)));
238 }
239 
240 void
set(QUICTransportParameterId id,uint64_t value)241 QUICTransportParameters::set(QUICTransportParameterId id, uint64_t value)
242 {
243   uint8_t v[8];
244   size_t n;
245   QUICIntUtil::write_QUICVariableInt(value, v, &n);
246   this->set(id, v, n);
247 }
248 
249 void
store(uint8_t * buf,uint16_t * len) const250 QUICTransportParameters::store(uint8_t *buf, uint16_t *len) const
251 {
252   uint8_t *p = buf;
253 
254   // Write QUIC versions
255   this->_store(p, len);
256   p += *len;
257 
258   // Write parameters
259   // XXX parameters_size will be written later
260   uint8_t *parameters_size = p;
261   p += sizeof(uint16_t);
262 
263   for (auto &it : this->_parameters) {
264     // TODO Skip non-MUST parameters that have their default values
265     p[0] = (it.first & 0xff00) >> 8;
266     p[1] = it.first & 0xff;
267     p += 2;
268     p[0] = (it.second->len() & 0xff00) >> 8;
269     p[1] = it.second->len() & 0xff;
270     p += 2;
271     memcpy(p, it.second->data(), it.second->len());
272     p += it.second->len();
273   }
274 
275   ptrdiff_t n = p - parameters_size - sizeof(uint16_t);
276 
277   parameters_size[0] = (n & 0xff00) >> 8;
278   parameters_size[1] = n & 0xff;
279 
280   *len = (p - buf);
281 }
282 
283 void
_print() const284 QUICTransportParameters::_print() const
285 {
286   for (auto &p : this->_parameters) {
287     if (p.second->len() == 0) {
288       Debug(tag, "%s: (no value)", QUICDebugNames::transport_parameter_id(p.first));
289     } else if (p.second->len() <= 8) {
290       uint64_t int_value;
291       size_t int_value_len;
292       QUICVariableInt::decode(int_value, int_value_len, p.second->data(), p.second->len());
293       Debug(tag, "%s (%" PRIu32 "): 0x%" PRIx64 " (%" PRIu64 ")", QUICDebugNames::transport_parameter_id(p.first),
294             static_cast<uint16_t>(p.first), int_value, int_value);
295     } else if (p.second->len() <= 24) {
296       char hex_str[65];
297       to_hex_str(hex_str, sizeof(hex_str), p.second->data(), p.second->len());
298       Debug(tag, "%s (%" PRIu32 "): %s", QUICDebugNames::transport_parameter_id(p.first), static_cast<uint16_t>(p.first), hex_str);
299     } else if (QUICTransportParameterId::PREFERRED_ADDRESS == p.first) {
300       QUICPreferredAddress pref_addr(p.second->data(), p.second->len());
301       char cid_hex_str[QUICConnectionId::MAX_HEX_STR_LENGTH];
302       char token_hex_str[QUICStatelessResetToken::LEN * 2 + 1];
303       char ep_ipv4_hex_str[512];
304       char ep_ipv6_hex_str[512];
305       pref_addr.cid().hex(cid_hex_str, sizeof(cid_hex_str));
306       to_hex_str(token_hex_str, sizeof(token_hex_str), pref_addr.token().buf(), QUICStatelessResetToken::LEN);
307       ats_ip_nptop(pref_addr.endpoint_ipv4(), ep_ipv4_hex_str, sizeof(ep_ipv4_hex_str));
308       ats_ip_nptop(pref_addr.endpoint_ipv6(), ep_ipv6_hex_str, sizeof(ep_ipv6_hex_str));
309       Debug(tag, "%s: Endpoint(IPv4)=%s, Endpoint(IPv6)=%s, CID=%s, Token=%s", QUICDebugNames::transport_parameter_id(p.first),
310             ep_ipv4_hex_str, ep_ipv6_hex_str, cid_hex_str, token_hex_str);
311     } else {
312       Debug(tag, "%s: (long data)", QUICDebugNames::transport_parameter_id(p.first));
313     }
314   }
315 }
316 
317 //
318 // QUICTransportParametersInClientHello
319 //
320 
QUICTransportParametersInClientHello(const uint8_t * buf,size_t len)321 QUICTransportParametersInClientHello::QUICTransportParametersInClientHello(const uint8_t *buf, size_t len)
322 {
323   this->_load(buf, len);
324   if (is_debug_tag_set(tag)) {
325     this->_print();
326   }
327 }
328 
329 void
_store(uint8_t * buf,uint16_t * len) const330 QUICTransportParametersInClientHello::_store(uint8_t *buf, uint16_t *len) const
331 {
332   *len = 0;
333 }
334 
335 std::ptrdiff_t
_parameters_offset(const uint8_t *) const336 QUICTransportParametersInClientHello::_parameters_offset(const uint8_t *) const
337 {
338   return 4; // sizeof(QUICVersion)
339 }
340 
341 int
_validate_parameters() const342 QUICTransportParametersInClientHello::_validate_parameters() const
343 {
344   int res = QUICTransportParameters::_validate_parameters();
345   if (res < 0) {
346     return res;
347   }
348 
349   decltype(this->_parameters)::const_iterator ite;
350 
351   // MUST NOTs
352   if ((ite = this->_parameters.find(QUICTransportParameterId::STATELESS_RESET_TOKEN)) != this->_parameters.end()) {
353     return -(TP_ERROR_MUST_NOT_EXIST | QUICTransportParameterId::STATELESS_RESET_TOKEN);
354   }
355 
356   if ((ite = this->_parameters.find(QUICTransportParameterId::PREFERRED_ADDRESS)) != this->_parameters.end()) {
357     return -(TP_ERROR_MUST_NOT_EXIST | QUICTransportParameterId::PREFERRED_ADDRESS);
358   }
359 
360   return 0;
361 }
362 
363 //
364 // QUICTransportParametersInEncryptedExtensions
365 //
366 
QUICTransportParametersInEncryptedExtensions(const uint8_t * buf,size_t len)367 QUICTransportParametersInEncryptedExtensions::QUICTransportParametersInEncryptedExtensions(const uint8_t *buf, size_t len)
368 {
369   this->_load(buf, len);
370   if (is_debug_tag_set(tag)) {
371     this->_print();
372   }
373 }
374 
375 void
_store(uint8_t * buf,uint16_t * len) const376 QUICTransportParametersInEncryptedExtensions::_store(uint8_t *buf, uint16_t *len) const
377 {
378   *len = 0;
379 }
380 
381 void
add_version(QUICVersion version)382 QUICTransportParametersInEncryptedExtensions::add_version(QUICVersion version)
383 {
384   this->_versions[this->_n_versions++] = version;
385 }
386 
387 std::ptrdiff_t
_parameters_offset(const uint8_t * buf) const388 QUICTransportParametersInEncryptedExtensions::_parameters_offset(const uint8_t *buf) const
389 {
390   return 4 + 1 + buf[4];
391 }
392 
393 int
_validate_parameters() const394 QUICTransportParametersInEncryptedExtensions::_validate_parameters() const
395 {
396   int res = QUICTransportParameters::_validate_parameters();
397   if (res < 0) {
398     return res;
399   }
400 
401   decltype(this->_parameters)::const_iterator ite;
402 
403   // MUSTs if the server sent a Retry packet
404   if ((ite = this->_parameters.find(QUICTransportParameterId::ORIGINAL_CONNECTION_ID)) != this->_parameters.end()) {
405     // We cannot check the length because it's not a fixed length.
406   } else {
407     // TODO Need a way that checks if we received a Retry from the server
408     // return -(TP_ERROR_MUST_EXIST | QUICTransportParameterId::ORIGINAL_CONNECTION_ID);
409   }
410 
411   // MAYs
412   if ((ite = this->_parameters.find(QUICTransportParameterId::STATELESS_RESET_TOKEN)) != this->_parameters.end()) {
413     if (ite->second->len() != 16) {
414       return -(TP_ERROR_LENGTH | QUICTransportParameterId::STATELESS_RESET_TOKEN);
415     }
416   }
417 
418   if ((ite = this->_parameters.find(QUICTransportParameterId::PREFERRED_ADDRESS)) != this->_parameters.end()) {
419     if (ite->second->len() < QUICPreferredAddress::MIN_LEN || QUICPreferredAddress::MAX_LEN < ite->second->len()) {
420       return -(TP_ERROR_LENGTH | QUICTransportParameterId::PREFERRED_ADDRESS);
421     }
422   }
423 
424   return 0;
425 }
426 
427 #ifndef OPENSSL_IS_BORINGSSL
428 
429 static constexpr int TRANSPORT_PARAMETERS_MAXIMUM_SIZE = 65535;
430 
431 //
432 // QUICTransportParametersHandler
433 //
434 
435 int
add(SSL * s,unsigned int ext_type,unsigned int context,const unsigned char ** out,size_t * outlen,X509 * x,size_t chainidx,int * al,void * add_arg)436 QUICTransportParametersHandler::add(SSL *s, unsigned int ext_type, unsigned int context, const unsigned char **out, size_t *outlen,
437                                     X509 *x, size_t chainidx, int *al, void *add_arg)
438 {
439   QUICTLS *qtls = static_cast<QUICTLS *>(SSL_get_ex_data(s, QUIC::ssl_quic_tls_index));
440   *out          = reinterpret_cast<const unsigned char *>(ats_malloc(TRANSPORT_PARAMETERS_MAXIMUM_SIZE));
441   qtls->local_transport_parameters()->store(const_cast<uint8_t *>(*out), reinterpret_cast<uint16_t *>(outlen));
442 
443   return 1;
444 }
445 
446 void
free(SSL * s,unsigned int ext_type,unsigned int context,const unsigned char * out,void * add_arg)447 QUICTransportParametersHandler::free(SSL *s, unsigned int ext_type, unsigned int context, const unsigned char *out, void *add_arg)
448 {
449   ats_free(const_cast<unsigned char *>(out));
450 }
451 
452 int
parse(SSL * s,unsigned int ext_type,unsigned int context,const unsigned char * in,size_t inlen,X509 * x,size_t chainidx,int * al,void * parse_arg)453 QUICTransportParametersHandler::parse(SSL *s, unsigned int ext_type, unsigned int context, const unsigned char *in, size_t inlen,
454                                       X509 *x, size_t chainidx, int *al, void *parse_arg)
455 {
456   QUICTLS *qtls = static_cast<QUICTLS *>(SSL_get_ex_data(s, QUIC::ssl_quic_tls_index));
457 
458   switch (context) {
459   case SSL_EXT_CLIENT_HELLO:
460     qtls->set_remote_transport_parameters(std::make_shared<QUICTransportParametersInClientHello>(in, inlen));
461     break;
462   case SSL_EXT_TLS1_3_ENCRYPTED_EXTENSIONS:
463     qtls->set_remote_transport_parameters(std::make_shared<QUICTransportParametersInEncryptedExtensions>(in, inlen));
464     break;
465   default:
466     // Do nothing
467     break;
468   }
469 
470   return 1;
471 }
472 #endif
473