示例#1
0
/*
 * Create an SSL connection, but does not ready any post-handshake
 * NewSessionTicket messages.
 */
int create_bare_ssl_connection(SSL *serverssl, SSL *clientssl, int want)
{
    int retc = -1, rets = -1, err, abortctr = 0;
    int clienterr = 0, servererr = 0;
    int isdtls = SSL_is_dtls(serverssl);

    do {
        err = SSL_ERROR_WANT_WRITE;
        while (!clienterr && retc <= 0 && err == SSL_ERROR_WANT_WRITE) {
            retc = SSL_connect(clientssl);
            if (retc <= 0)
                err = SSL_get_error(clientssl, retc);
        }

        if (!clienterr && retc <= 0 && err != SSL_ERROR_WANT_READ) {
            TEST_info("SSL_connect() failed %d, %d", retc, err);
            clienterr = 1;
        }
        if (want != SSL_ERROR_NONE && err == want)
            return 0;

        err = SSL_ERROR_WANT_WRITE;
        while (!servererr && rets <= 0 && err == SSL_ERROR_WANT_WRITE) {
            rets = SSL_accept(serverssl);
            if (rets <= 0)
                err = SSL_get_error(serverssl, rets);
        }

        if (!servererr && rets <= 0
                && err != SSL_ERROR_WANT_READ
                && err != SSL_ERROR_WANT_X509_LOOKUP) {
            TEST_info("SSL_accept() failed %d, %d", rets, err);
            servererr = 1;
        }
        if (want != SSL_ERROR_NONE && err == want)
            return 0;
        if (clienterr && servererr)
            return 0;
        if (isdtls) {
            if (rets > 0 && retc <= 0)
                DTLSv1_handle_timeout(serverssl);
            if (retc > 0 && rets <= 0)
                DTLSv1_handle_timeout(clientssl);
        }
        if (++abortctr == MAXLOOPS) {
            TEST_info("No progress made");
            return 0;
        }
        if (isdtls && abortctr <= 50 && (abortctr % 10) == 0) {
            /*
             * It looks like we're just spinning. Pause for a short period to
             * give the DTLS timer a chance to do something. We only do this for
             * the first few times to prevent hangs.
             */
            ossl_sleep(50);
        }
    } while (retc <=0 || rets <= 0);

    return 1;
}
示例#2
0
int tls1_change_cipher_state(SSL_HANDSHAKE *hs, int which) {
  SSL *const ssl = hs->ssl;
  /* Ensure the key block is set up. */
  if (!tls1_setup_key_block(hs)) {
    return 0;
  }

  /* is_read is true if we have just read a ChangeCipherSpec message - i.e. we
   * need to update the read cipherspec. Otherwise we have just written one. */
  const char is_read = (which & SSL3_CC_READ) != 0;
  /* use_client_keys is true if we wish to use the keys for the "client write"
   * direction. This is the case if we're a client sending a ChangeCipherSpec,
   * or a server reading a client's ChangeCipherSpec. */
  const char use_client_keys = which == SSL3_CHANGE_CIPHER_CLIENT_WRITE ||
                               which == SSL3_CHANGE_CIPHER_SERVER_READ;

  size_t mac_secret_len = ssl->s3->tmp.new_mac_secret_len;
  size_t key_len = ssl->s3->tmp.new_key_len;
  size_t iv_len = ssl->s3->tmp.new_fixed_iv_len;
  assert((mac_secret_len + key_len + iv_len) * 2 == hs->key_block_len);

  const uint8_t *key_data = hs->key_block;
  const uint8_t *client_write_mac_secret = key_data;
  key_data += mac_secret_len;
  const uint8_t *server_write_mac_secret = key_data;
  key_data += mac_secret_len;
  const uint8_t *client_write_key = key_data;
  key_data += key_len;
  const uint8_t *server_write_key = key_data;
  key_data += key_len;
  const uint8_t *client_write_iv = key_data;
  key_data += iv_len;
  const uint8_t *server_write_iv = key_data;
  key_data += iv_len;

  const uint8_t *mac_secret, *key, *iv;
  if (use_client_keys) {
    mac_secret = client_write_mac_secret;
    key = client_write_key;
    iv = client_write_iv;
  } else {
    mac_secret = server_write_mac_secret;
    key = server_write_key;
    iv = server_write_iv;
  }

  SSL_AEAD_CTX *aead_ctx = SSL_AEAD_CTX_new(
      is_read ? evp_aead_open : evp_aead_seal, ssl3_protocol_version(ssl), SSL_is_dtls(ssl),
      hs->new_cipher, key, key_len, mac_secret, mac_secret_len, iv, iv_len);
  if (aead_ctx == NULL) {
    return 0;
  }

  if (is_read) {
    return ssl->method->set_read_state(ssl, aead_ctx);
  }

  return ssl->method->set_write_state(ssl, aead_ctx);
}
示例#3
0
static int tls1_setup_key_block(SSL_HANDSHAKE *hs) {
  SSL *const ssl = hs->ssl;
  if (hs->key_block_len != 0) {
    return 1;
  }

  SSL_SESSION *session = ssl->session;
  if (hs->new_session != NULL) {
    session = hs->new_session;
  }

  const EVP_AEAD *aead = NULL;
  size_t mac_secret_len, fixed_iv_len;
  if (session->cipher == NULL ||
      !ssl_cipher_get_evp_aead(&aead, &mac_secret_len, &fixed_iv_len,
                               session->cipher, ssl3_protocol_version(ssl),
                               SSL_is_dtls(ssl))) {
    OPENSSL_PUT_ERROR(SSL, SSL_R_CIPHER_OR_HASH_UNAVAILABLE);
    return 0;
  }
  size_t key_len = EVP_AEAD_key_length(aead);
  if (mac_secret_len > 0) {
    /* For "stateful" AEADs (i.e. compatibility with pre-AEAD cipher suites) the
     * key length reported by |EVP_AEAD_key_length| will include the MAC key
     * bytes and initial implicit IV. */
    if (key_len < mac_secret_len + fixed_iv_len) {
      OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR);
      return 0;
    }
    key_len -= mac_secret_len + fixed_iv_len;
  }

  assert(mac_secret_len < 256);
  assert(key_len < 256);
  assert(fixed_iv_len < 256);

  ssl->s3->tmp.new_mac_secret_len = (uint8_t)mac_secret_len;
  ssl->s3->tmp.new_key_len = (uint8_t)key_len;
  ssl->s3->tmp.new_fixed_iv_len = (uint8_t)fixed_iv_len;

  size_t key_block_len = SSL_get_key_block_len(ssl);

  uint8_t *keyblock = OPENSSL_malloc(key_block_len);
  if (keyblock == NULL) {
    OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE);
    return 0;
  }

  if (!SSL_generate_key_block(ssl, keyblock, key_block_len)) {
    OPENSSL_free(keyblock);
    return 0;
  }

  assert(key_block_len < 256);
  hs->key_block_len = (uint8_t)key_block_len;
  hs->key_block = keyblock;
  return 1;
}
示例#4
0
/*
 * NOTE: Transfers control of the BIOs - this function will free them on error
 */
int create_ssl_objects(SSL_CTX *serverctx, SSL_CTX *clientctx, SSL **sssl,
                          SSL **cssl, BIO *s_to_c_fbio, BIO *c_to_s_fbio)
{
    SSL *serverssl = NULL, *clientssl = NULL;
    BIO *s_to_c_bio = NULL, *c_to_s_bio = NULL;

    if (*sssl != NULL)
        serverssl = *sssl;
    else if (!TEST_ptr(serverssl = SSL_new(serverctx)))
        goto error;
    if (*cssl != NULL)
        clientssl = *cssl;
    else if (!TEST_ptr(clientssl = SSL_new(clientctx)))
        goto error;

    if (SSL_is_dtls(clientssl)) {
        if (!TEST_ptr(s_to_c_bio = BIO_new(bio_s_mempacket_test()))
                || !TEST_ptr(c_to_s_bio = BIO_new(bio_s_mempacket_test())))
            goto error;
    } else {
        if (!TEST_ptr(s_to_c_bio = BIO_new(BIO_s_mem()))
                || !TEST_ptr(c_to_s_bio = BIO_new(BIO_s_mem())))
            goto error;
    }

    if (s_to_c_fbio != NULL
            && !TEST_ptr(s_to_c_bio = BIO_push(s_to_c_fbio, s_to_c_bio)))
        goto error;
    if (c_to_s_fbio != NULL
            && !TEST_ptr(c_to_s_bio = BIO_push(c_to_s_fbio, c_to_s_bio)))
        goto error;

    /* Set Non-blocking IO behaviour */
    BIO_set_mem_eof_return(s_to_c_bio, -1);
    BIO_set_mem_eof_return(c_to_s_bio, -1);

    /* Up ref these as we are passing them to two SSL objects */
    SSL_set_bio(serverssl, c_to_s_bio, s_to_c_bio);
    BIO_up_ref(s_to_c_bio);
    BIO_up_ref(c_to_s_bio);
    SSL_set_bio(clientssl, s_to_c_bio, c_to_s_bio);
    *sssl = serverssl;
    *cssl = clientssl;
    return 1;

 error:
    SSL_free(serverssl);
    SSL_free(clientssl);
    BIO_free(s_to_c_bio);
    BIO_free(c_to_s_bio);
    BIO_free(s_to_c_fbio);
    BIO_free(c_to_s_fbio);

    return 0;
}
示例#5
0
static enum ssl_hs_wait_t do_send_server_finished(SSL_HANDSHAKE *hs) {
  SSL *const ssl = hs->ssl;
  if (!tls13_add_finished(hs) ||
      /* Update the secret to the master secret and derive traffic keys. */
      !tls13_advance_key_schedule(hs, kZeroes, hs->hash_len) ||
      !tls13_derive_application_secrets(hs) ||
      !tls13_set_traffic_key(ssl, evp_aead_seal, hs->server_traffic_secret_0,
                             hs->hash_len)) {
    return ssl_hs_error;
  }

  if (ssl->early_data_accepted) {
    /* If accepting 0-RTT, we send tickets half-RTT. This gets the tickets on
     * the wire sooner and also avoids triggering a write on |SSL_read| when
     * processing the client Finished. This requires computing the client
     * Finished early. See draft-ietf-tls-tls13-18, section 4.5.1. */
    size_t finished_len;
    if (!tls13_finished_mac(hs, hs->expected_client_finished, &finished_len,
                            0 /* client */)) {
      return ssl_hs_error;
    }

    if (finished_len != hs->hash_len) {
      OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR);
      return ssl_hs_error;
    }

    /* Feed the predicted Finished into the transcript. This allows us to derive
     * the resumption secret early and send half-RTT tickets.
     *
     * TODO(davidben): This will need to be updated for DTLS 1.3. */
    assert(!SSL_is_dtls(hs->ssl));
    uint8_t header[4] = {SSL3_MT_FINISHED, 0, 0, hs->hash_len};
    if (!SSL_TRANSCRIPT_update(&hs->transcript, header, sizeof(header)) ||
        !SSL_TRANSCRIPT_update(&hs->transcript, hs->expected_client_finished,
                               hs->hash_len) ||
        !tls13_derive_resumption_secret(hs) ||
        !add_new_session_tickets(hs)) {
      return ssl_hs_error;
    }
  }

  hs->tls13_state = state_read_second_client_flight;
  return ssl_hs_flush;
}
示例#6
0
文件: d1_lib.c 项目: eggyo/eggyo-node
int DTLSv1_get_timeout(const SSL *ssl, struct timeval *out) {
  if (!SSL_is_dtls(ssl)) {
    return 0;
  }

  /* If no timeout is set, just return NULL */
  if (ssl->d1->next_timeout.tv_sec == 0 && ssl->d1->next_timeout.tv_usec == 0) {
    return 0;
  }

  struct timeval timenow;
  ssl_get_current_time(ssl, &timenow);

  /* If timer already expired, set remaining time to 0 */
  if (ssl->d1->next_timeout.tv_sec < timenow.tv_sec ||
      (ssl->d1->next_timeout.tv_sec == timenow.tv_sec &&
       ssl->d1->next_timeout.tv_usec <= timenow.tv_usec)) {
    memset(out, 0, sizeof(struct timeval));
    return 1;
  }

  /* Calculate time left until timer expires */
  memcpy(out, &ssl->d1->next_timeout, sizeof(struct timeval));
  out->tv_sec -= timenow.tv_sec;
  out->tv_usec -= timenow.tv_usec;
  if (out->tv_usec < 0) {
    out->tv_sec--;
    out->tv_usec += 1000000;
  }

  /* If remaining time is less than 15 ms, set it to 0 to prevent issues
   * because of small devergences with socket timeouts. */
  if (out->tv_sec == 0 && out->tv_usec < 15000) {
    memset(out, 0, sizeof(struct timeval));
  }

  return 1;
}
示例#7
0
文件: d1_lib.c 项目: eggyo/eggyo-node
int DTLSv1_handle_timeout(SSL *ssl) {
  ssl->rwstate = SSL_NOTHING;
  /* Functions which use SSL_get_error must clear the error queue on entry. */
  ERR_clear_error();

  if (!SSL_is_dtls(ssl)) {
    return -1;
  }

  /* if no timer is expired, don't do anything */
  if (!dtls1_is_timer_expired(ssl)) {
    return 0;
  }

  dtls1_double_timeout(ssl);

  if (dtls1_check_timeout_num(ssl) < 0) {
    return -1;
  }

  dtls1_start_timer(ssl);
  return dtls1_retransmit_outgoing_messages(ssl);
}
示例#8
0
/*
 * Create an SSL connection, but does not ready any post-handshake
 * NewSessionTicket messages.
 * If |read| is set and we're using DTLS then we will attempt to SSL_read on
 * the connection once we've completed one half of it, to ensure any retransmits
 * get triggered.
 */
int create_bare_ssl_connection(SSL *serverssl, SSL *clientssl, int want,
                               int read)
{
    int retc = -1, rets = -1, err, abortctr = 0;
    int clienterr = 0, servererr = 0;
    int isdtls = SSL_is_dtls(serverssl);

    do {
        err = SSL_ERROR_WANT_WRITE;
        while (!clienterr && retc <= 0 && err == SSL_ERROR_WANT_WRITE) {
            retc = SSL_connect(clientssl);
            if (retc <= 0)
                err = SSL_get_error(clientssl, retc);
        }

        if (!clienterr && retc <= 0 && err != SSL_ERROR_WANT_READ) {
            TEST_info("SSL_connect() failed %d, %d", retc, err);
            clienterr = 1;
        }
        if (want != SSL_ERROR_NONE && err == want)
            return 0;

        err = SSL_ERROR_WANT_WRITE;
        while (!servererr && rets <= 0 && err == SSL_ERROR_WANT_WRITE) {
            rets = SSL_accept(serverssl);
            if (rets <= 0)
                err = SSL_get_error(serverssl, rets);
        }

        if (!servererr && rets <= 0
                && err != SSL_ERROR_WANT_READ
                && err != SSL_ERROR_WANT_X509_LOOKUP) {
            TEST_info("SSL_accept() failed %d, %d", rets, err);
            servererr = 1;
        }
        if (want != SSL_ERROR_NONE && err == want)
            return 0;
        if (clienterr && servererr)
            return 0;
        if (isdtls && read) {
            unsigned char buf[20];

            /* Trigger any retransmits that may be appropriate */
            if (rets > 0 && retc <= 0) {
                if (SSL_read(serverssl, buf, sizeof(buf)) > 0) {
                    /* We don't expect this to succeed! */
                    TEST_info("Unexpected SSL_read() success!");
                    return 0;
                }
            }
            if (retc > 0 && rets <= 0) {
                if (SSL_read(clientssl, buf, sizeof(buf)) > 0) {
                    /* We don't expect this to succeed! */
                    TEST_info("Unexpected SSL_read() success!");
                    return 0;
                }
            }
        }
        if (++abortctr == MAXLOOPS) {
            TEST_info("No progress made");
            return 0;
        }
        if (isdtls && abortctr <= 50 && (abortctr % 10) == 0) {
            /*
             * It looks like we're just spinning. Pause for a short period to
             * give the DTLS timer a chance to do something. We only do this for
             * the first few times to prevent hangs.
             */
            ossl_sleep(50);
        }
    } while (retc <=0 || rets <= 0);

    return 1;
}