dtls_record.cc revision 921ef2c09591ea1f04625e01b800ac4493a8916d
1/* DTLS implementation written by Nagendra Modadugu 2 * (nagendra@cs.stanford.edu) for the OpenSSL project 2005. */ 3/* ==================================================================== 4 * Copyright (c) 1998-2005 The OpenSSL Project. All rights reserved. 5 * 6 * Redistribution and use in source and binary forms, with or without 7 * modification, are permitted provided that the following conditions 8 * are met: 9 * 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * 13 * 2. Redistributions in binary form must reproduce the above copyright 14 * notice, this list of conditions and the following disclaimer in 15 * the documentation and/or other materials provided with the 16 * distribution. 17 * 18 * 3. All advertising materials mentioning features or use of this 19 * software must display the following acknowledgment: 20 * "This product includes software developed by the OpenSSL Project 21 * for use in the OpenSSL Toolkit. (http://www.openssl.org/)" 22 * 23 * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to 24 * endorse or promote products derived from this software without 25 * prior written permission. For written permission, please contact 26 * openssl-core@openssl.org. 27 * 28 * 5. Products derived from this software may not be called "OpenSSL" 29 * nor may "OpenSSL" appear in their names without prior written 30 * permission of the OpenSSL Project. 31 * 32 * 6. Redistributions of any form whatsoever must retain the following 33 * acknowledgment: 34 * "This product includes software developed by the OpenSSL Project 35 * for use in the OpenSSL Toolkit (http://www.openssl.org/)" 36 * 37 * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY 38 * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 39 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 40 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR 41 * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 42 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 43 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 44 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 45 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 46 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 47 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED 48 * OF THE POSSIBILITY OF SUCH DAMAGE. 49 * ==================================================================== 50 * 51 * This product includes cryptographic software written by Eric Young 52 * (eay@cryptsoft.com). This product includes software written by Tim 53 * Hudson (tjh@cryptsoft.com). 54 * 55 */ 56/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) 57 * All rights reserved. 58 * 59 * This package is an SSL implementation written 60 * by Eric Young (eay@cryptsoft.com). 61 * The implementation was written so as to conform with Netscapes SSL. 62 * 63 * This library is free for commercial and non-commercial use as long as 64 * the following conditions are aheared to. The following conditions 65 * apply to all code found in this distribution, be it the RC4, RSA, 66 * lhash, DES, etc., code; not just the SSL code. The SSL documentation 67 * included with this distribution is covered by the same copyright terms 68 * except that the holder is Tim Hudson (tjh@cryptsoft.com). 69 * 70 * Copyright remains Eric Young's, and as such any Copyright notices in 71 * the code are not to be removed. 72 * If this package is used in a product, Eric Young should be given attribution 73 * as the author of the parts of the library used. 74 * This can be in the form of a textual message at program startup or 75 * in documentation (online or textual) provided with the package. 76 * 77 * Redistribution and use in source and binary forms, with or without 78 * modification, are permitted provided that the following conditions 79 * are met: 80 * 1. Redistributions of source code must retain the copyright 81 * notice, this list of conditions and the following disclaimer. 82 * 2. Redistributions in binary form must reproduce the above copyright 83 * notice, this list of conditions and the following disclaimer in the 84 * documentation and/or other materials provided with the distribution. 85 * 3. All advertising materials mentioning features or use of this software 86 * must display the following acknowledgement: 87 * "This product includes cryptographic software written by 88 * Eric Young (eay@cryptsoft.com)" 89 * The word 'cryptographic' can be left out if the rouines from the library 90 * being used are not cryptographic related :-). 91 * 4. If you include any Windows specific code (or a derivative thereof) from 92 * the apps directory (application code) you must include an acknowledgement: 93 * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" 94 * 95 * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND 96 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 97 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 98 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 99 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 100 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 101 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 102 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 103 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 104 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 105 * SUCH DAMAGE. 106 * 107 * The licence and distribution terms for any publically available version or 108 * derivative of this code cannot be changed. i.e. this code cannot simply be 109 * copied and put under another distribution licence 110 * [including the GNU Public Licence.] */ 111 112#include <openssl/ssl.h> 113 114#include <assert.h> 115#include <string.h> 116 117#include <openssl/bytestring.h> 118#include <openssl/err.h> 119 120#include "internal.h" 121#include "../crypto/internal.h" 122 123 124namespace bssl { 125 126// to_u64_be treats |in| as a 8-byte big-endian integer and returns the value as 127// a |uint64_t|. 128static uint64_t to_u64_be(const uint8_t in[8]) { 129 uint64_t ret = 0; 130 unsigned i; 131 for (i = 0; i < 8; i++) { 132 ret <<= 8; 133 ret |= in[i]; 134 } 135 return ret; 136} 137 138// dtls1_bitmap_should_discard returns one if |seq_num| has been seen in 139// |bitmap| or is stale. Otherwise it returns zero. 140static int dtls1_bitmap_should_discard(DTLS1_BITMAP *bitmap, 141 const uint8_t seq_num[8]) { 142 const unsigned kWindowSize = sizeof(bitmap->map) * 8; 143 144 uint64_t seq_num_u = to_u64_be(seq_num); 145 if (seq_num_u > bitmap->max_seq_num) { 146 return 0; 147 } 148 uint64_t idx = bitmap->max_seq_num - seq_num_u; 149 return idx >= kWindowSize || (bitmap->map & (((uint64_t)1) << idx)); 150} 151 152// dtls1_bitmap_record updates |bitmap| to record receipt of sequence number 153// |seq_num|. It slides the window forward if needed. It is an error to call 154// this function on a stale sequence number. 155static void dtls1_bitmap_record(DTLS1_BITMAP *bitmap, 156 const uint8_t seq_num[8]) { 157 const unsigned kWindowSize = sizeof(bitmap->map) * 8; 158 159 uint64_t seq_num_u = to_u64_be(seq_num); 160 // Shift the window if necessary. 161 if (seq_num_u > bitmap->max_seq_num) { 162 uint64_t shift = seq_num_u - bitmap->max_seq_num; 163 if (shift >= kWindowSize) { 164 bitmap->map = 0; 165 } else { 166 bitmap->map <<= shift; 167 } 168 bitmap->max_seq_num = seq_num_u; 169 } 170 171 uint64_t idx = bitmap->max_seq_num - seq_num_u; 172 if (idx < kWindowSize) { 173 bitmap->map |= ((uint64_t)1) << idx; 174 } 175} 176 177enum ssl_open_record_t dtls_open_record(SSL *ssl, uint8_t *out_type, 178 Span<uint8_t> *out, 179 size_t *out_consumed, 180 uint8_t *out_alert, Span<uint8_t> in) { 181 *out_consumed = 0; 182 switch (ssl->s3->read_shutdown) { 183 case ssl_shutdown_none: 184 break; 185 case ssl_shutdown_fatal_alert: 186 OPENSSL_PUT_ERROR(SSL, SSL_R_PROTOCOL_IS_SHUTDOWN); 187 *out_alert = 0; 188 return ssl_open_record_error; 189 case ssl_shutdown_close_notify: 190 return ssl_open_record_close_notify; 191 } 192 193 if (in.empty()) { 194 return ssl_open_record_partial; 195 } 196 197 CBS cbs = CBS(in); 198 199 // Decode the record. 200 uint8_t type; 201 uint16_t version; 202 uint8_t sequence[8]; 203 CBS body; 204 if (!CBS_get_u8(&cbs, &type) || 205 !CBS_get_u16(&cbs, &version) || 206 !CBS_copy_bytes(&cbs, sequence, 8) || 207 !CBS_get_u16_length_prefixed(&cbs, &body) || 208 CBS_len(&body) > SSL3_RT_MAX_ENCRYPTED_LENGTH) { 209 // The record header was incomplete or malformed. Drop the entire packet. 210 *out_consumed = in.size(); 211 return ssl_open_record_discard; 212 } 213 214 bool version_ok; 215 if (ssl->s3->aead_read_ctx->is_null_cipher()) { 216 // Only check the first byte. Enforcing beyond that can prevent decoding 217 // version negotiation failure alerts. 218 version_ok = (version >> 8) == DTLS1_VERSION_MAJOR; 219 } else { 220 version_ok = version == ssl->s3->aead_read_ctx->RecordVersion(); 221 } 222 223 if (!version_ok) { 224 // The record header was incomplete or malformed. Drop the entire packet. 225 *out_consumed = in.size(); 226 return ssl_open_record_discard; 227 } 228 229 ssl_do_msg_callback(ssl, 0 /* read */, SSL3_RT_HEADER, 230 in.subspan(0, DTLS1_RT_HEADER_LENGTH)); 231 232 uint16_t epoch = (((uint16_t)sequence[0]) << 8) | sequence[1]; 233 if (epoch != ssl->d1->r_epoch || 234 dtls1_bitmap_should_discard(&ssl->d1->bitmap, sequence)) { 235 // Drop this record. It's from the wrong epoch or is a replay. Note that if 236 // |epoch| is the next epoch, the record could be buffered for later. For 237 // simplicity, drop it and expect retransmit to handle it later; DTLS must 238 // handle packet loss anyway. 239 *out_consumed = in.size() - CBS_len(&cbs); 240 return ssl_open_record_discard; 241 } 242 243 // discard the body in-place. 244 if (!ssl->s3->aead_read_ctx->Open( 245 out, type, version, sequence, 246 MakeSpan(const_cast<uint8_t *>(CBS_data(&body)), CBS_len(&body)))) { 247 // Bad packets are silently dropped in DTLS. See section 4.2.1 of RFC 6347. 248 // Clear the error queue of any errors decryption may have added. Drop the 249 // entire packet as it must not have come from the peer. 250 // 251 // TODO(davidben): This doesn't distinguish malloc failures from encryption 252 // failures. 253 ERR_clear_error(); 254 *out_consumed = in.size() - CBS_len(&cbs); 255 return ssl_open_record_discard; 256 } 257 *out_consumed = in.size() - CBS_len(&cbs); 258 259 // Check the plaintext length. 260 if (out->size() > SSL3_RT_MAX_PLAIN_LENGTH) { 261 OPENSSL_PUT_ERROR(SSL, SSL_R_DATA_LENGTH_TOO_LONG); 262 *out_alert = SSL_AD_RECORD_OVERFLOW; 263 return ssl_open_record_error; 264 } 265 266 dtls1_bitmap_record(&ssl->d1->bitmap, sequence); 267 268 // TODO(davidben): Limit the number of empty records as in TLS? This is only 269 // useful if we also limit discarded packets. 270 271 if (type == SSL3_RT_ALERT) { 272 return ssl_process_alert(ssl, out_alert, *out); 273 } 274 275 ssl->s3->warning_alert_count = 0; 276 277 *out_type = type; 278 return ssl_open_record_success; 279} 280 281static const SSLAEADContext *get_write_aead(const SSL *ssl, 282 enum dtls1_use_epoch_t use_epoch) { 283 if (use_epoch == dtls1_use_previous_epoch) { 284 assert(ssl->d1->w_epoch >= 1); 285 return ssl->d1->last_aead_write_ctx; 286 } 287 288 return ssl->s3->aead_write_ctx; 289} 290 291size_t dtls_max_seal_overhead(const SSL *ssl, 292 enum dtls1_use_epoch_t use_epoch) { 293 return DTLS1_RT_HEADER_LENGTH + get_write_aead(ssl, use_epoch)->MaxOverhead(); 294} 295 296size_t dtls_seal_prefix_len(const SSL *ssl, enum dtls1_use_epoch_t use_epoch) { 297 return DTLS1_RT_HEADER_LENGTH + 298 get_write_aead(ssl, use_epoch)->ExplicitNonceLen(); 299} 300 301int dtls_seal_record(SSL *ssl, uint8_t *out, size_t *out_len, size_t max_out, 302 uint8_t type, const uint8_t *in, size_t in_len, 303 enum dtls1_use_epoch_t use_epoch) { 304 const size_t prefix = dtls_seal_prefix_len(ssl, use_epoch); 305 if (buffers_alias(in, in_len, out, max_out) && 306 (max_out < prefix || out + prefix != in)) { 307 OPENSSL_PUT_ERROR(SSL, SSL_R_OUTPUT_ALIASES_INPUT); 308 return 0; 309 } 310 311 // Determine the parameters for the current epoch. 312 uint16_t epoch = ssl->d1->w_epoch; 313 SSLAEADContext *aead = ssl->s3->aead_write_ctx; 314 uint8_t *seq = ssl->s3->write_sequence; 315 if (use_epoch == dtls1_use_previous_epoch) { 316 assert(ssl->d1->w_epoch >= 1); 317 epoch = ssl->d1->w_epoch - 1; 318 aead = ssl->d1->last_aead_write_ctx; 319 seq = ssl->d1->last_write_sequence; 320 } 321 322 if (max_out < DTLS1_RT_HEADER_LENGTH) { 323 OPENSSL_PUT_ERROR(SSL, SSL_R_BUFFER_TOO_SMALL); 324 return 0; 325 } 326 327 out[0] = type; 328 329 uint16_t record_version = ssl->s3->aead_write_ctx->RecordVersion(); 330 out[1] = record_version >> 8; 331 out[2] = record_version & 0xff; 332 333 out[3] = epoch >> 8; 334 out[4] = epoch & 0xff; 335 OPENSSL_memcpy(&out[5], &seq[2], 6); 336 337 size_t ciphertext_len; 338 if (!aead->Seal(out + DTLS1_RT_HEADER_LENGTH, &ciphertext_len, 339 max_out - DTLS1_RT_HEADER_LENGTH, type, record_version, 340 &out[3] /* seq */, in, in_len) || 341 !ssl_record_sequence_update(&seq[2], 6)) { 342 return 0; 343 } 344 345 if (ciphertext_len >= 1 << 16) { 346 OPENSSL_PUT_ERROR(SSL, ERR_R_OVERFLOW); 347 return 0; 348 } 349 out[11] = ciphertext_len >> 8; 350 out[12] = ciphertext_len & 0xff; 351 352 *out_len = DTLS1_RT_HEADER_LENGTH + ciphertext_len; 353 354 ssl_do_msg_callback(ssl, 1 /* write */, SSL3_RT_HEADER, 355 MakeSpan(out, DTLS1_RT_HEADER_LENGTH)); 356 357 return 1; 358} 359 360} // namespace bssl 361