Home | History | Annotate | Download | only in ssl
      1 /* DTLS implementation written by Nagendra Modadugu
      2  * (nagendra (at) 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 (at) 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 (at) cryptsoft.com).  This product includes software written by Tim
     53  * Hudson (tjh (at) cryptsoft.com).
     54  *
     55  */
     56 /* Copyright (C) 1995-1998 Eric Young (eay (at) cryptsoft.com)
     57  * All rights reserved.
     58  *
     59  * This package is an SSL implementation written
     60  * by Eric Young (eay (at) 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 (at) 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 (at) 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 (at) 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/bio.h>
    118 #include <openssl/buf.h>
    119 #include <openssl/bytestring.h>
    120 #include <openssl/mem.h>
    121 #include <openssl/evp.h>
    122 #include <openssl/err.h>
    123 #include <openssl/rand.h>
    124 
    125 #include "../crypto/internal.h"
    126 #include "internal.h"
    127 
    128 
    129 namespace bssl {
    130 
    131 ssl_open_record_t dtls1_open_app_data(SSL *ssl, Span<uint8_t> *out,
    132                                       size_t *out_consumed, uint8_t *out_alert,
    133                                       Span<uint8_t> in) {
    134   assert(!SSL_in_init(ssl));
    135 
    136   uint8_t type;
    137   Span<uint8_t> record;
    138   auto ret = dtls_open_record(ssl, &type, &record, out_consumed, out_alert, in);
    139   if (ret != ssl_open_record_success) {
    140     return ret;
    141   }
    142 
    143   if (type == SSL3_RT_HANDSHAKE) {
    144     // Parse the first fragment header to determine if this is a pre-CCS or
    145     // post-CCS handshake record. DTLS resets handshake message numbers on each
    146     // handshake, so renegotiations and retransmissions are ambiguous.
    147     CBS cbs, body;
    148     struct hm_header_st msg_hdr;
    149     CBS_init(&cbs, record.data(), record.size());
    150     if (!dtls1_parse_fragment(&cbs, &msg_hdr, &body)) {
    151       OPENSSL_PUT_ERROR(SSL, SSL_R_BAD_HANDSHAKE_RECORD);
    152       *out_alert = SSL_AD_DECODE_ERROR;
    153       return ssl_open_record_error;
    154     }
    155 
    156     if (msg_hdr.type == SSL3_MT_FINISHED &&
    157         msg_hdr.seq == ssl->d1->handshake_read_seq - 1) {
    158       if (msg_hdr.frag_off == 0) {
    159         // Retransmit our last flight of messages. If the peer sends the second
    160         // Finished, they may not have received ours. Only do this for the
    161         // first fragment, in case the Finished was fragmented.
    162         if (!dtls1_check_timeout_num(ssl)) {
    163           *out_alert = 0;  // TODO(davidben): Send an alert?
    164           return ssl_open_record_error;
    165         }
    166 
    167         dtls1_retransmit_outgoing_messages(ssl);
    168       }
    169       return ssl_open_record_discard;
    170     }
    171 
    172     // Otherwise, this is a pre-CCS handshake message from an unsupported
    173     // renegotiation attempt. Fall through to the error path.
    174   }
    175 
    176   if (type != SSL3_RT_APPLICATION_DATA) {
    177     OPENSSL_PUT_ERROR(SSL, SSL_R_UNEXPECTED_RECORD);
    178     *out_alert = SSL_AD_UNEXPECTED_MESSAGE;
    179     return ssl_open_record_error;
    180   }
    181 
    182   if (record.empty()) {
    183     return ssl_open_record_discard;
    184   }
    185 
    186   *out = record;
    187   return ssl_open_record_success;
    188 }
    189 
    190 int dtls1_write_app_data(SSL *ssl, bool *out_needs_handshake, const uint8_t *in,
    191                          int len) {
    192   assert(!SSL_in_init(ssl));
    193   *out_needs_handshake = false;
    194 
    195   if (ssl->s3->write_shutdown != ssl_shutdown_none) {
    196     OPENSSL_PUT_ERROR(SSL, SSL_R_PROTOCOL_IS_SHUTDOWN);
    197     return -1;
    198   }
    199 
    200   if (len > SSL3_RT_MAX_PLAIN_LENGTH) {
    201     OPENSSL_PUT_ERROR(SSL, SSL_R_DTLS_MESSAGE_TOO_BIG);
    202     return -1;
    203   }
    204 
    205   if (len < 0) {
    206     OPENSSL_PUT_ERROR(SSL, SSL_R_BAD_LENGTH);
    207     return -1;
    208   }
    209 
    210   if (len == 0) {
    211     return 0;
    212   }
    213 
    214   int ret = dtls1_write_record(ssl, SSL3_RT_APPLICATION_DATA, in, (size_t)len,
    215                                dtls1_use_current_epoch);
    216   if (ret <= 0) {
    217     return ret;
    218   }
    219   return len;
    220 }
    221 
    222 int dtls1_write_record(SSL *ssl, int type, const uint8_t *in, size_t len,
    223                        enum dtls1_use_epoch_t use_epoch) {
    224   SSLBuffer *buf = &ssl->s3->write_buffer;
    225   assert(len <= SSL3_RT_MAX_PLAIN_LENGTH);
    226   // There should never be a pending write buffer in DTLS. One can't write half
    227   // a datagram, so the write buffer is always dropped in
    228   // |ssl_write_buffer_flush|.
    229   assert(buf->empty());
    230 
    231   if (len > SSL3_RT_MAX_PLAIN_LENGTH) {
    232     OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR);
    233     return -1;
    234   }
    235 
    236   size_t ciphertext_len;
    237   if (!buf->EnsureCap(ssl_seal_align_prefix_len(ssl),
    238                       len + SSL_max_seal_overhead(ssl)) ||
    239       !dtls_seal_record(ssl, buf->remaining().data(), &ciphertext_len,
    240                         buf->remaining().size(), type, in, len, use_epoch)) {
    241     buf->Clear();
    242     return -1;
    243   }
    244   buf->DidWrite(ciphertext_len);
    245 
    246   int ret = ssl_write_buffer_flush(ssl);
    247   if (ret <= 0) {
    248     return ret;
    249   }
    250   return 1;
    251 }
    252 
    253 int dtls1_dispatch_alert(SSL *ssl) {
    254   int ret = dtls1_write_record(ssl, SSL3_RT_ALERT, &ssl->s3->send_alert[0], 2,
    255                                dtls1_use_current_epoch);
    256   if (ret <= 0) {
    257     return ret;
    258   }
    259   ssl->s3->alert_dispatch = 0;
    260 
    261   // If the alert is fatal, flush the BIO now.
    262   if (ssl->s3->send_alert[0] == SSL3_AL_FATAL) {
    263     BIO_flush(ssl->wbio);
    264   }
    265 
    266   ssl_do_msg_callback(ssl, 1 /* write */, SSL3_RT_ALERT, ssl->s3->send_alert);
    267 
    268   int alert = (ssl->s3->send_alert[0] << 8) | ssl->s3->send_alert[1];
    269   ssl_do_info_callback(ssl, SSL_CB_WRITE_ALERT, alert);
    270 
    271   return 1;
    272 }
    273 
    274 }  // namespace bssl
    275