Esempio n. 1
0
int SSL_export_keying_material(SSL *ssl, uint8_t *out, size_t out_len,
                               const char *label, size_t label_len,
                               const uint8_t *context, size_t context_len,
                               int use_context) {
  if (!ssl->s3->have_version || ssl->version == SSL3_VERSION) {
    return 0;
  }

  /* Exporters may not be used in the middle of a renegotiation. */
  if (SSL_in_init(ssl) && !SSL_in_false_start(ssl)) {
    return 0;
  }

  if (ssl3_protocol_version(ssl) >= TLS1_3_VERSION) {
    return tls13_export_keying_material(ssl, out, out_len, label, label_len,
                                        context, context_len, use_context);
  }

  size_t seed_len = 2 * SSL3_RANDOM_SIZE;
  if (use_context) {
    if (context_len >= 1u << 16) {
      OPENSSL_PUT_ERROR(SSL, ERR_R_OVERFLOW);
      return 0;
    }
    seed_len += 2 + context_len;
  }
  uint8_t *seed = OPENSSL_malloc(seed_len);
  if (seed == NULL) {
    OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE);
    return 0;
  }

  OPENSSL_memcpy(seed, ssl->s3->client_random, SSL3_RANDOM_SIZE);
  OPENSSL_memcpy(seed + SSL3_RANDOM_SIZE, ssl->s3->server_random,
                 SSL3_RANDOM_SIZE);
  if (use_context) {
    seed[2 * SSL3_RANDOM_SIZE] = (uint8_t)(context_len >> 8);
    seed[2 * SSL3_RANDOM_SIZE + 1] = (uint8_t)context_len;
    OPENSSL_memcpy(seed + 2 * SSL3_RANDOM_SIZE + 2, context, context_len);
  }

  const EVP_MD *digest = ssl_get_handshake_digest(
      SSL_get_session(ssl)->cipher->algorithm_prf, ssl3_protocol_version(ssl));
  if (digest == NULL) {
    OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR);
    return 0;
  }
  int ret = tls1_prf(digest, out, out_len, SSL_get_session(ssl)->master_key,
                     SSL_get_session(ssl)->master_key_length, label, label_len,
                     seed, seed_len, NULL, 0);
  OPENSSL_free(seed);
  return ret;
}
Esempio n. 2
0
int ssl_private_key_supports_signature_algorithm(SSL *ssl,
                                                 uint16_t signature_algorithm) {
  const EVP_MD *md;
  if (is_rsa_pkcs1(&md, signature_algorithm) &&
      ssl3_protocol_version(ssl) < TLS1_3_VERSION) {
    return ssl_private_key_type(ssl) == NID_rsaEncryption;
  }

  int curve;
  if (is_ecdsa(&curve, &md, signature_algorithm)) {
    int type = ssl_private_key_type(ssl);
    if (!ssl_is_ecdsa_key_type(type)) {
      return 0;
    }

    /* Prior to TLS 1.3, ECDSA curves did not match the signature algorithm. */
    if (ssl3_protocol_version(ssl) < TLS1_3_VERSION) {
      return 1;
    }

    return curve != NID_undef && type == curve;
  }

  if (is_rsa_pss(&md, signature_algorithm)) {
    if (ssl_private_key_type(ssl) != NID_rsaEncryption) {
      return 0;
    }

    /* Ensure the RSA key is large enough for the hash. RSASSA-PSS requires that
     * emLen be at least hLen + sLen + 2. Both hLen and sLen are the size of the
     * hash in TLS. Reasonable RSA key sizes are large enough for the largest
     * defined RSASSA-PSS algorithm, but 1024-bit RSA is slightly too large for
     * SHA-512. 1024-bit RSA is sometimes used for test credentials, so check
     * the size to fall back to another algorithm. */
    if (ssl_private_key_max_signature_len(ssl) < 2 * EVP_MD_size(md) + 2) {
      return 0;
    }

    /* RSA-PSS is only supported by message-based private keys. */
    if (ssl->cert->key_method != NULL && ssl->cert->key_method->sign == NULL) {
      return 0;
    }

    return 1;
  }

  return 0;
}
Esempio n. 3
0
static int ssl_verify_ecdsa(SSL *ssl, const uint8_t *signature,
                            size_t signature_len, int curve, const EVP_MD *md,
                            EVP_PKEY *pkey, const uint8_t *in, size_t in_len) {
  EC_KEY *ec_key = EVP_PKEY_get0_EC_KEY(pkey);
  if (ec_key == NULL) {
    OPENSSL_PUT_ERROR(SSL, SSL_R_WRONG_SIGNATURE_TYPE);
    return 0;
  }

  /* In TLS 1.3, the curve is also specified by the signature algorithm. */
  if (ssl3_protocol_version(ssl) >= TLS1_3_VERSION &&
      (curve == NID_undef ||
       EC_GROUP_get_curve_name(EC_KEY_get0_group(ec_key)) != curve)) {
    OPENSSL_PUT_ERROR(SSL, SSL_R_WRONG_SIGNATURE_TYPE);
    return 0;
  }

  EVP_MD_CTX md_ctx;
  EVP_MD_CTX_init(&md_ctx);
  int ret = EVP_DigestVerifyInit(&md_ctx, NULL, md, NULL, pkey) &&
            EVP_DigestVerifyUpdate(&md_ctx, in, in_len) &&
            EVP_DigestVerifyFinal(&md_ctx, signature, signature_len);
  EVP_MD_CTX_cleanup(&md_ctx);
  return ret;
}
Esempio n. 4
0
static int ssl_sign_ecdsa(SSL *ssl, uint8_t *out, size_t *out_len,
                          size_t max_out, int curve, const EVP_MD *md,
                          const uint8_t *in, size_t in_len) {
  EC_KEY *ec_key = EVP_PKEY_get0_EC_KEY(ssl->cert->privatekey);
  if (ec_key == NULL) {
    OPENSSL_PUT_ERROR(SSL, SSL_R_WRONG_SIGNATURE_TYPE);
    return 0;
  }

  /* In TLS 1.3, the curve is also specified by the signature algorithm. */
  if (ssl3_protocol_version(ssl) >= TLS1_3_VERSION &&
      (curve == NID_undef ||
       EC_GROUP_get_curve_name(EC_KEY_get0_group(ec_key)) != curve)) {
    OPENSSL_PUT_ERROR(SSL, SSL_R_WRONG_SIGNATURE_TYPE);
    return 0;
  }

  EVP_MD_CTX ctx;
  EVP_MD_CTX_init(&ctx);
  *out_len = max_out;
  int ret = EVP_DigestSignInit(&ctx, NULL, md, NULL, ssl->cert->privatekey) &&
            EVP_DigestSignUpdate(&ctx, in, in_len) &&
            EVP_DigestSignFinal(&ctx, out, out_len);
  EVP_MD_CTX_cleanup(&ctx);
  return ret;
}
Esempio n. 5
0
int tls1_change_cipher_state(SSL *ssl, int which) {
  /* Ensure the key block is set up. */
  if (!tls1_setup_key_block(ssl)) {
    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 ==
         ssl->s3->tmp.key_block_length);

  const uint8_t *key_data = ssl->s3->tmp.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->s3->tmp.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);
}
Esempio n. 6
0
int ssl3_cert_verify_hash(SSL *ssl, const EVP_MD **out_md, uint8_t *out,
                          size_t *out_len, uint16_t signature_algorithm) {
  assert(ssl3_protocol_version(ssl) == SSL3_VERSION);

  if (signature_algorithm == SSL_SIGN_RSA_PKCS1_MD5_SHA1) {
    if (ssl3_handshake_mac(ssl, NID_md5, NULL, 0, out) == 0 ||
        ssl3_handshake_mac(ssl, NID_sha1, NULL, 0,
                           out + MD5_DIGEST_LENGTH) == 0) {
      return 0;
    }
    *out_md = EVP_md5_sha1();
    *out_len = MD5_DIGEST_LENGTH + SHA_DIGEST_LENGTH;
  } else if (signature_algorithm == SSL_SIGN_ECDSA_SHA1) {
    if (ssl3_handshake_mac(ssl, NID_sha1, NULL, 0, out) == 0) {
      return 0;
    }
    *out_md = EVP_sha1();
    *out_len = SHA_DIGEST_LENGTH;
  } else {
    OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR);
    return 0;
  }

  return 1;
}
Esempio n. 7
0
int ssl_private_key_supports_signature_algorithm(SSL *ssl,
                                                 uint16_t signature_algorithm) {
  const EVP_MD *md;
  if (is_rsa_pkcs1(&md, signature_algorithm)) {
    return ssl_private_key_type(ssl) == EVP_PKEY_RSA;
  }

  int curve;
  if (is_ecdsa(&curve, &md, signature_algorithm)) {
    if (ssl_private_key_type(ssl) != EVP_PKEY_EC) {
      return 0;
    }

    /* For non-custom keys, also check the curve matches. Custom private keys
     * must instead configure the signature algorithms accordingly. */
    if (ssl3_protocol_version(ssl) >= TLS1_3_VERSION &&
        ssl->cert->key_method == NULL) {
      EC_KEY *ec_key = EVP_PKEY_get0_EC_KEY(ssl->cert->privatekey);
      if (curve == NID_undef ||
          EC_GROUP_get_curve_name(EC_KEY_get0_group(ec_key)) != curve) {
        return 0;
      }
    }
    return 1;
  }

  if (is_rsa_pss(&md, signature_algorithm)) {
    if (ssl3_protocol_version(ssl) < TLS1_3_VERSION ||
        ssl_private_key_type(ssl) != EVP_PKEY_RSA) {
      return 0;
    }

    /* Ensure the RSA key is large enough for the hash. RSASSA-PSS requires that
     * emLen be at least hLen + sLen + 2. Both hLen and sLen are the size of the
     * hash in TLS. Reasonable RSA key sizes are large enough for the largest
     * defined RSASSA-PSS algorithm, but 1024-bit RSA is slightly too large for
     * SHA-512. 1024-bit RSA is sometimes used for test credentials, so check
     * the size to fall back to another algorithm. */
    if (ssl_private_key_max_signature_len(ssl) < 2 * EVP_MD_size(md) + 2) {
      return 0;
    }

    return 1;
  }

  return 0;
}
Esempio n. 8
0
/* If we are using default SHA1+MD5 algorithms switch to new SHA256 PRF and
 * handshake macs if required. */
uint32_t ssl_get_algorithm_prf(const SSL *ssl) {
  uint32_t algorithm_prf = ssl->s3->tmp.new_cipher->algorithm_prf;
  if (algorithm_prf == SSL_HANDSHAKE_MAC_DEFAULT &&
      ssl3_protocol_version(ssl) >= TLS1_2_VERSION) {
    return SSL_HANDSHAKE_MAC_SHA256;
  }
  return algorithm_prf;
}
Esempio n. 9
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;
}
Esempio n. 10
0
enum ssl_private_key_result_t ssl_private_key_sign(
    SSL *ssl, uint8_t *out, size_t *out_len, size_t max_out,
    uint16_t signature_algorithm, const uint8_t *in, size_t in_len) {
  if (ssl->cert->key_method != NULL) {
    if (ssl->cert->key_method->sign != NULL) {
      return ssl->cert->key_method->sign(ssl, out, out_len, max_out,
                                         signature_algorithm, in, in_len);
    }

    /* TODO(davidben): Remove support for |sign_digest|-only
     * |SSL_PRIVATE_KEY_METHOD|s. */
    const EVP_MD *md;
    int curve;
    if (!is_rsa_pkcs1(&md, signature_algorithm) &&
        !is_ecdsa(&curve, &md, signature_algorithm)) {
      OPENSSL_PUT_ERROR(SSL, SSL_R_UNSUPPORTED_PROTOCOL_FOR_CUSTOM_KEY);
      return ssl_private_key_failure;
    }

    uint8_t hash[EVP_MAX_MD_SIZE];
    unsigned hash_len;
    if (!EVP_Digest(in, in_len, hash, &hash_len, md, NULL)) {
      return ssl_private_key_failure;
    }

    return ssl->cert->key_method->sign_digest(ssl, out, out_len, max_out, md,
                                              hash, hash_len);
  }

  const EVP_MD *md;
  if (is_rsa_pkcs1(&md, signature_algorithm) &&
      ssl3_protocol_version(ssl) < TLS1_3_VERSION) {
    return ssl_sign_rsa_pkcs1(ssl, out, out_len, max_out, md, in, in_len)
               ? ssl_private_key_success
               : ssl_private_key_failure;
  }

  int curve;
  if (is_ecdsa(&curve, &md, signature_algorithm)) {
    return ssl_sign_ecdsa(ssl, out, out_len, max_out, curve, md, in, in_len)
               ? ssl_private_key_success
               : ssl_private_key_failure;
  }

  if (is_rsa_pss(&md, signature_algorithm)) {
    return ssl_sign_rsa_pss(ssl, out, out_len, max_out, md, in, in_len)
               ? ssl_private_key_success
               : ssl_private_key_failure;
  }

  OPENSSL_PUT_ERROR(SSL, SSL_R_WRONG_SIGNATURE_TYPE);
  return ssl_private_key_failure;
}
Esempio n. 11
0
int ssl3_read_app_data(SSL *ssl, int *out_got_handshake, uint8_t *buf, int len,
                       int peek) {
  assert(!SSL_in_init(ssl));
  assert(ssl->s3->initial_handshake_complete);
  *out_got_handshake = 0;

  SSL3_RECORD *rr = &ssl->s3->rrec;

  for (;;) {
    /* A previous iteration may have read a partial handshake message. Do not
     * allow more app data in that case. */
    int has_hs_data = ssl->init_buf != NULL && ssl->init_buf->length > 0;

    /* Get new packet if necessary. */
    if (rr->length == 0 && !has_hs_data) {
      int ret = ssl3_get_record(ssl);
      if (ret <= 0) {
        return ret;
      }
    }

    if (has_hs_data || rr->type == SSL3_RT_HANDSHAKE) {
      /* Post-handshake data prior to TLS 1.3 is always renegotiation, which we
       * never accept as a server. Otherwise |ssl3_get_message| will send
       * |SSL_R_EXCESSIVE_MESSAGE_SIZE|. */
      if (ssl->server && ssl3_protocol_version(ssl) < TLS1_3_VERSION) {
        ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_NO_RENEGOTIATION);
        OPENSSL_PUT_ERROR(SSL, SSL_R_NO_RENEGOTIATION);
        return -1;
      }

      /* Parse post-handshake handshake messages. */
      int ret = ssl3_get_message(ssl, -1, ssl_dont_hash_message);
      if (ret <= 0) {
        return ret;
      }
      *out_got_handshake = 1;
      return -1;
    }

    if (rr->type != SSL3_RT_APPLICATION_DATA) {
      OPENSSL_PUT_ERROR(SSL, SSL_R_UNEXPECTED_RECORD);
      ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_UNEXPECTED_MESSAGE);
      return -1;
    }

    if (rr->length != 0) {
      return consume_record(ssl, buf, len, peek);
    }

    /* Discard empty records and loop again. */
  }
}
Esempio n. 12
0
int SSL_generate_key_block(const SSL *ssl, uint8_t *out, size_t out_len) {
  if (ssl3_protocol_version(ssl) == SSL3_VERSION) {
    return ssl3_prf(out, out_len, SSL_get_session(ssl)->master_key,
                    SSL_get_session(ssl)->master_key_length,
                    TLS_MD_KEY_EXPANSION_CONST, TLS_MD_KEY_EXPANSION_CONST_SIZE,
                    ssl->s3->server_random, SSL3_RANDOM_SIZE,
                    ssl->s3->client_random, SSL3_RANDOM_SIZE);
  }

  const EVP_MD *digest = ssl_get_handshake_digest(
      SSL_get_session(ssl)->cipher->algorithm_prf, ssl3_protocol_version(ssl));
  if (digest == NULL) {
    OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR);
    return 0;
  }
  return tls1_prf(digest, out, out_len, SSL_get_session(ssl)->master_key,
                  SSL_get_session(ssl)->master_key_length,
                  TLS_MD_KEY_EXPANSION_CONST, TLS_MD_KEY_EXPANSION_CONST_SIZE,
                  ssl->s3->server_random, SSL3_RANDOM_SIZE,
                  ssl->s3->client_random, SSL3_RANDOM_SIZE);
}
Esempio n. 13
0
enum ssl_private_key_result_t ssl_private_key_sign(
    SSL *ssl, uint8_t *out, size_t *out_len, size_t max_out,
    uint16_t signature_algorithm, const uint8_t *in, size_t in_len) {
  if (ssl->cert->key_method != NULL) {
    /* For now, custom private keys can only handle pre-TLS-1.3 signature
     * algorithms.
     *
     * TODO(davidben): Switch SSL_PRIVATE_KEY_METHOD to message-based APIs. */
    const EVP_MD *md;
    int curve;
    if (!is_rsa_pkcs1(&md, signature_algorithm) &&
        !is_ecdsa(&curve, &md, signature_algorithm)) {
      OPENSSL_PUT_ERROR(SSL, SSL_R_UNSUPPORTED_PROTOCOL_FOR_CUSTOM_KEY);
      return ssl_private_key_failure;
    }

    uint8_t hash[EVP_MAX_MD_SIZE];
    unsigned hash_len;
    if (!EVP_Digest(in, in_len, hash, &hash_len, md, NULL)) {
      return ssl_private_key_failure;
    }

    return ssl->cert->key_method->sign(ssl, out, out_len, max_out, md, hash,
                                       hash_len);
  }

  const EVP_MD *md;
  if (is_rsa_pkcs1(&md, signature_algorithm)) {
    return ssl_sign_rsa_pkcs1(ssl, out, out_len, max_out, md, in, in_len)
               ? ssl_private_key_success
               : ssl_private_key_failure;
  }

  int curve;
  if (is_ecdsa(&curve, &md, signature_algorithm)) {
    return ssl_sign_ecdsa(ssl, out, out_len, max_out, curve, md, in, in_len)
               ? ssl_private_key_success
               : ssl_private_key_failure;
  }

  if (is_rsa_pss(&md, signature_algorithm) &&
      ssl3_protocol_version(ssl) >= TLS1_3_VERSION) {
    return ssl_sign_rsa_pss(ssl, out, out_len, max_out, md, in, in_len)
               ? ssl_private_key_success
               : ssl_private_key_failure;
  }

  OPENSSL_PUT_ERROR(SSL, SSL_R_WRONG_SIGNATURE_TYPE);
  return ssl_private_key_failure;
}
Esempio n. 14
0
static const SSL_CIPHER *choose_tls13_cipher(
    const SSL *ssl, const SSL_CLIENT_HELLO *client_hello) {
  if (client_hello->cipher_suites_len % 2 != 0) {
    return NULL;
  }

  CBS cipher_suites;
  CBS_init(&cipher_suites, client_hello->cipher_suites,
           client_hello->cipher_suites_len);

  const int aes_is_fine = EVP_has_aes_hardware();
  const uint16_t version = ssl3_protocol_version(ssl);

  const SSL_CIPHER *best = NULL;
  while (CBS_len(&cipher_suites) > 0) {
    uint16_t cipher_suite;
    if (!CBS_get_u16(&cipher_suites, &cipher_suite)) {
      return NULL;
    }

    /* Limit to TLS 1.3 ciphers we know about. */
    const SSL_CIPHER *candidate = SSL_get_cipher_by_value(cipher_suite);
    if (candidate == NULL ||
        SSL_CIPHER_get_min_version(candidate) > version ||
        SSL_CIPHER_get_max_version(candidate) < version) {
      continue;
    }

    /* TLS 1.3 removes legacy ciphers, so honor the client order, but prefer
     * ChaCha20 if we do not have AES hardware. */
    if (aes_is_fine) {
      return candidate;
    }

    if (candidate->algorithm_enc == SSL_CHACHA20POLY1305) {
      return candidate;
    }

    if (best == NULL) {
      best = candidate;
    }
  }

  return best;
}
Esempio n. 15
0
int SSL_export_keying_material(SSL *ssl, uint8_t *out, size_t out_len,
                               const char *label, size_t label_len,
                               const uint8_t *context, size_t context_len,
                               int use_context) {
  if (!ssl->s3->have_version || ssl->version == SSL3_VERSION) {
    return 0;
  }

  if (ssl3_protocol_version(ssl) >= TLS1_3_VERSION) {
    return tls13_export_keying_material(ssl, out, out_len, label, label_len,
                                        context, context_len, use_context);
  }

  size_t seed_len = 2 * SSL3_RANDOM_SIZE;
  if (use_context) {
    if (context_len >= 1u << 16) {
      OPENSSL_PUT_ERROR(SSL, ERR_R_OVERFLOW);
      return 0;
    }
    seed_len += 2 + context_len;
  }
  uint8_t *seed = OPENSSL_malloc(seed_len);
  if (seed == NULL) {
    OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE);
    return 0;
  }

  memcpy(seed, ssl->s3->client_random, SSL3_RANDOM_SIZE);
  memcpy(seed + SSL3_RANDOM_SIZE, ssl->s3->server_random, SSL3_RANDOM_SIZE);
  if (use_context) {
    seed[2 * SSL3_RANDOM_SIZE] = (uint8_t)(context_len >> 8);
    seed[2 * SSL3_RANDOM_SIZE + 1] = (uint8_t)context_len;
    memcpy(seed + 2 * SSL3_RANDOM_SIZE + 2, context, context_len);
  }

  int ret =
      ssl->s3->enc_method->prf(ssl, out, out_len,
                               SSL_get_session(ssl)->master_key,
                               SSL_get_session(ssl)->master_key_length, label,
                               label_len, seed, seed_len, NULL, 0);
  OPENSSL_free(seed);
  return ret;
}
Esempio n. 16
0
static int ssl3_can_renegotiate(SSL *ssl) {
  if (ssl->server || ssl3_protocol_version(ssl) >= TLS1_3_VERSION) {
    return 0;
  }

  switch (ssl->renegotiate_mode) {
    case ssl_renegotiate_never:
      return 0;
    case ssl_renegotiate_once:
      return ssl->s3->total_renegotiations == 0;
    case ssl_renegotiate_freely:
      return 1;
    case ssl_renegotiate_ignore:
      return 1;
  }

  assert(0);
  return 0;
}
Esempio n. 17
0
int ssl_check_leaf_certificate(SSL_HANDSHAKE *hs, EVP_PKEY *pkey,
                               const CRYPTO_BUFFER *leaf) {
  SSL *const ssl = hs->ssl;
  assert(ssl3_protocol_version(ssl) < TLS1_3_VERSION);

  /* Check the certificate's type matches the cipher. */
  if (!(hs->new_cipher->algorithm_auth & ssl_cipher_auth_mask_for_key(pkey))) {
    OPENSSL_PUT_ERROR(SSL, SSL_R_WRONG_CERTIFICATE_TYPE);
    return 0;
  }

  /* Check key usages for all key types but RSA. This is needed to distinguish
   * ECDH certificates, which we do not support, from ECDSA certificates. In
   * principle, we should check RSA key usages based on cipher, but this breaks
   * buggy antivirus deployments. Other key types are always used for signing.
   *
   * TODO(davidben): Get more recent data on RSA key usages. */
  if (EVP_PKEY_id(pkey) != EVP_PKEY_RSA) {
    CBS leaf_cbs;
    CBS_init(&leaf_cbs, CRYPTO_BUFFER_data(leaf), CRYPTO_BUFFER_len(leaf));
    if (!ssl_cert_check_digital_signature_key_usage(&leaf_cbs)) {
      return 0;
    }
  }

  if (EVP_PKEY_id(pkey) == EVP_PKEY_EC) {
    /* Check the key's group and point format are acceptable. */
    EC_KEY *ec_key = EVP_PKEY_get0_EC_KEY(pkey);
    uint16_t group_id;
    if (!ssl_nid_to_group_id(
            &group_id, EC_GROUP_get_curve_name(EC_KEY_get0_group(ec_key))) ||
        !tls1_check_group_id(ssl, group_id) ||
        EC_KEY_get_conv_form(ec_key) != POINT_CONVERSION_UNCOMPRESSED) {
      OPENSSL_PUT_ERROR(SSL, SSL_R_BAD_ECC_CERT);
      return 0;
    }
  }

  return 1;
}
Esempio n. 18
0
int ssl3_cert_verify_hash(SSL *ssl, uint8_t *out, size_t *out_len,
                          const EVP_MD **out_md, int pkey_type) {
  /* For TLS v1.2 send signature algorithm and signature using
   * agreed digest and cached handshake records. Otherwise, use
   * SHA1 or MD5 + SHA1 depending on key type.  */
  if (ssl3_protocol_version(ssl) >= TLS1_2_VERSION) {
    EVP_MD_CTX mctx;
    unsigned len;

    EVP_MD_CTX_init(&mctx);
    if (!EVP_DigestInit_ex(&mctx, *out_md, NULL) ||
        !EVP_DigestUpdate(&mctx, ssl->s3->handshake_buffer->data,
                          ssl->s3->handshake_buffer->length) ||
        !EVP_DigestFinal(&mctx, out, &len)) {
      OPENSSL_PUT_ERROR(SSL, ERR_R_EVP_LIB);
      EVP_MD_CTX_cleanup(&mctx);
      return 0;
    }
    *out_len = len;
  } else if (pkey_type == EVP_PKEY_RSA) {
    if (ssl->s3->enc_method->cert_verify_mac(ssl, NID_md5, out) == 0 ||
        ssl->s3->enc_method->cert_verify_mac(ssl, NID_sha1,
                                             out + MD5_DIGEST_LENGTH) == 0) {
      return 0;
    }
    *out_len = MD5_DIGEST_LENGTH + SHA_DIGEST_LENGTH;
    *out_md = EVP_md5_sha1();
  } else if (pkey_type == EVP_PKEY_EC) {
    if (ssl->s3->enc_method->cert_verify_mac(ssl, NID_sha1, out) == 0) {
      return 0;
    }
    *out_len = SHA_DIGEST_LENGTH;
    *out_md = EVP_sha1();
  } else {
    OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR);
    return 0;
  }

  return 1;
}
Esempio n. 19
0
int tls1_generate_master_secret(SSL_HANDSHAKE *hs, uint8_t *out,
                                const uint8_t *premaster,
                                size_t premaster_len) {
  const SSL *ssl = hs->ssl;
  if (hs->extended_master_secret) {
    uint8_t digests[EVP_MAX_MD_SIZE];
    size_t digests_len;
    if (!SSL_TRANSCRIPT_get_hash(&hs->transcript, digests, &digests_len) ||
        !tls1_prf(SSL_TRANSCRIPT_md(&hs->transcript), out,
                  SSL3_MASTER_SECRET_SIZE, premaster, premaster_len,
                  TLS_MD_EXTENDED_MASTER_SECRET_CONST,
                  TLS_MD_EXTENDED_MASTER_SECRET_CONST_SIZE, digests,
                  digests_len, NULL, 0)) {
      return 0;
    }
  } else {
    if (ssl3_protocol_version(ssl) == SSL3_VERSION) {
      if (!ssl3_prf(out, SSL3_MASTER_SECRET_SIZE, premaster, premaster_len,
                    TLS_MD_MASTER_SECRET_CONST, TLS_MD_MASTER_SECRET_CONST_SIZE,
                    ssl->s3->client_random, SSL3_RANDOM_SIZE,
                    ssl->s3->server_random, SSL3_RANDOM_SIZE)) {
        return 0;
      }
    } else {
      if (!tls1_prf(SSL_TRANSCRIPT_md(&hs->transcript), out,
                    SSL3_MASTER_SECRET_SIZE, premaster, premaster_len,
                    TLS_MD_MASTER_SECRET_CONST, TLS_MD_MASTER_SECRET_CONST_SIZE,
                    ssl->s3->client_random, SSL3_RANDOM_SIZE,
                    ssl->s3->server_random, SSL3_RANDOM_SIZE)) {
        return 0;
      }
    }
  }

  return SSL3_MASTER_SECRET_SIZE;
}
Esempio n. 20
0
int ssl_public_key_verify(SSL *ssl, const uint8_t *signature,
                          size_t signature_len, uint16_t signature_algorithm,
                          EVP_PKEY *pkey, const uint8_t *in, size_t in_len) {
  const EVP_MD *md;
  if (is_rsa_pkcs1(&md, signature_algorithm) &&
      ssl3_protocol_version(ssl) < TLS1_3_VERSION) {
    return ssl_verify_rsa_pkcs1(ssl, signature, signature_len, md, pkey, in,
                                in_len);
  }

  int curve;
  if (is_ecdsa(&curve, &md, signature_algorithm)) {
    return ssl_verify_ecdsa(ssl, signature, signature_len, curve, md, pkey, in,
                            in_len);
  }

  if (is_rsa_pss(&md, signature_algorithm)) {
    return ssl_verify_rsa_pss(ssl, signature, signature_len, md, pkey, in,
                              in_len);
  }

  OPENSSL_PUT_ERROR(SSL, SSL_R_WRONG_SIGNATURE_TYPE);
  return 0;
}
Esempio n. 21
0
static enum ssl_hs_wait_t do_process_server_hello(SSL *ssl, SSL_HANDSHAKE *hs) {
  if (!tls13_check_message_type(ssl, SSL3_MT_SERVER_HELLO)) {
    return ssl_hs_error;
  }

  CBS cbs, server_random, extensions;
  uint16_t server_wire_version;
  uint16_t cipher_suite;
  CBS_init(&cbs, ssl->init_msg, ssl->init_num);
  if (!CBS_get_u16(&cbs, &server_wire_version) ||
      !CBS_get_bytes(&cbs, &server_random, SSL3_RANDOM_SIZE) ||
      !CBS_get_u16(&cbs, &cipher_suite) ||
      !CBS_get_u16_length_prefixed(&cbs, &extensions) ||
      CBS_len(&cbs) != 0) {
    ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_DECODE_ERROR);
    OPENSSL_PUT_ERROR(SSL, SSL_R_DECODE_ERROR);
    return ssl_hs_error;
  }

  if (server_wire_version != ssl->version) {
    ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_DECODE_ERROR);
    OPENSSL_PUT_ERROR(SSL, SSL_R_WRONG_VERSION_NUMBER);
    return ssl_hs_error;
  }

  /* Parse out the extensions. */
  int have_key_share = 0;
  CBS key_share;
  while (CBS_len(&extensions) != 0) {
    uint16_t type;
    CBS extension;
    if (!CBS_get_u16(&extensions, &type) ||
        !CBS_get_u16_length_prefixed(&extensions, &extension)) {
      OPENSSL_PUT_ERROR(SSL, SSL_R_PARSE_TLSEXT);
      ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_DECODE_ERROR);
      return ssl_hs_error;
    }

    switch (type) {
      case TLSEXT_TYPE_key_share:
        if (have_key_share) {
          OPENSSL_PUT_ERROR(SSL, SSL_R_DUPLICATE_EXTENSION);
          ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_DECODE_ERROR);
          return ssl_hs_error;
        }
        key_share = extension;
        have_key_share = 1;
        break;
      default:
        OPENSSL_PUT_ERROR(SSL, SSL_R_UNEXPECTED_EXTENSION);
        ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_UNSUPPORTED_EXTENSION);
        return ssl_hs_error;
    }
  }

  assert(ssl->s3->have_version);
  memcpy(ssl->s3->server_random, CBS_data(&server_random), SSL3_RANDOM_SIZE);

  ssl->hit = 0;
  if (!ssl_get_new_session(ssl, 0)) {
    ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_INTERNAL_ERROR);
    return ssl_hs_error;
  }

  const SSL_CIPHER *cipher = SSL_get_cipher_by_value(cipher_suite);
  if (cipher == NULL) {
    OPENSSL_PUT_ERROR(SSL, SSL_R_UNKNOWN_CIPHER_RETURNED);
    ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_ILLEGAL_PARAMETER);
    return ssl_hs_error;
  }

  /* Check if the cipher is disabled. */
  if ((cipher->algorithm_mkey & ssl->cert->mask_k) ||
      (cipher->algorithm_auth & ssl->cert->mask_a) ||
      SSL_CIPHER_get_min_version(cipher) > ssl3_protocol_version(ssl) ||
      SSL_CIPHER_get_max_version(cipher) < ssl3_protocol_version(ssl) ||
      !sk_SSL_CIPHER_find(ssl_get_ciphers_by_id(ssl), NULL, cipher)) {
    OPENSSL_PUT_ERROR(SSL, SSL_R_WRONG_CIPHER_RETURNED);
    ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_ILLEGAL_PARAMETER);
    return ssl_hs_error;
  }

  ssl->session->cipher = cipher;
  ssl->s3->tmp.new_cipher = cipher;

  /* The PRF hash is now known. Set up the key schedule. */
  static const uint8_t kZeroes[EVP_MAX_MD_SIZE] = {0};
  size_t hash_len =
      EVP_MD_size(ssl_get_handshake_digest(ssl_get_algorithm_prf(ssl)));
  if (!tls13_init_key_schedule(ssl, kZeroes, hash_len)) {
    return ssl_hs_error;
  }

  /* Resolve PSK and incorporate it into the secret. */
  if (cipher->algorithm_auth == SSL_aPSK) {
    /* TODO(davidben): Support PSK. */
    OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR);
    return ssl_hs_error;
  } else if (!tls13_advance_key_schedule(ssl, kZeroes, hash_len)) {
    return ssl_hs_error;
  }

  /* Resolve ECDHE and incorporate it into the secret. */
  if (cipher->algorithm_mkey == SSL_kECDHE) {
    if (!have_key_share) {
      OPENSSL_PUT_ERROR(SSL, SSL_R_MISSING_KEY_SHARE);
      ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_MISSING_EXTENSION);
      return ssl_hs_error;
    }

    uint8_t *dhe_secret;
    size_t dhe_secret_len;
    uint8_t alert = SSL_AD_DECODE_ERROR;
    if (!ext_key_share_parse_serverhello(ssl, &dhe_secret, &dhe_secret_len,
                                         &alert, &key_share)) {
      ssl3_send_alert(ssl, SSL3_AL_FATAL, alert);
      return ssl_hs_error;
    }

    int ok = tls13_advance_key_schedule(ssl, dhe_secret, dhe_secret_len);
    OPENSSL_free(dhe_secret);
    if (!ok) {
      return ssl_hs_error;
    }
  } else {
    if (have_key_share) {
      OPENSSL_PUT_ERROR(SSL, SSL_R_UNEXPECTED_EXTENSION);
      ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_UNSUPPORTED_EXTENSION);
      return ssl_hs_error;
    }
    if (!tls13_advance_key_schedule(ssl, kZeroes, hash_len)) {
      return ssl_hs_error;
    }
  }

  /* If there was no HelloRetryRequest, the version negotiation logic has
   * already hashed the message. */
  if (ssl->s3->hs->retry_group != 0 &&
      !ssl->method->hash_current_message(ssl)) {
    return ssl_hs_error;
  }

  if (!tls13_set_handshake_traffic(ssl)) {
    return ssl_hs_error;
  }

  hs->state = state_process_encrypted_extensions;
  return ssl_hs_read_message;
}
Esempio n. 22
0
int tls13_set_traffic_key(SSL *ssl, enum tls_record_type_t type,
                          enum evp_aead_direction_t direction,
                          const uint8_t *traffic_secret,
                          size_t traffic_secret_len) {
    if (traffic_secret_len > 0xff) {
        OPENSSL_PUT_ERROR(SSL, ERR_R_OVERFLOW);
        return 0;
    }

    const char *phase;
    switch (type) {
    case type_early_handshake:
        phase = "early handshake key expansion, ";
        break;
    case type_early_data:
        phase = "early application data key expansion, ";
        break;
    case type_handshake:
        phase = "handshake key expansion, ";
        break;
    case type_data:
        phase = "application data key expansion, ";
        break;
    default:
        return 0;
    }
    size_t phase_len = strlen(phase);

    const char *purpose = "client write key";
    if ((ssl->server && direction == evp_aead_seal) ||
            (!ssl->server && direction == evp_aead_open)) {
        purpose = "server write key";
    }
    size_t purpose_len = strlen(purpose);

    /* The longest label has length 38 (type_early_data) + 16 (either purpose
     * value). */
    uint8_t label[38 + 16];
    size_t label_len = phase_len + purpose_len;
    if (label_len > sizeof(label)) {
        assert(0);
        return 0;
    }
    memcpy(label, phase, phase_len);
    memcpy(label + phase_len, purpose, purpose_len);

    /* Look up cipher suite properties. */
    const EVP_AEAD *aead;
    const EVP_MD *digest = ssl_get_handshake_digest(ssl_get_algorithm_prf(ssl));
    size_t mac_secret_len, fixed_iv_len;
    if (!ssl_cipher_get_evp_aead(&aead, &mac_secret_len, &fixed_iv_len,
                                 ssl->session->cipher,
                                 ssl3_protocol_version(ssl))) {
        return 0;
    }

    /* Derive the key. */
    size_t key_len = EVP_AEAD_key_length(aead);
    uint8_t key[EVP_AEAD_MAX_KEY_LENGTH];
    if (!hkdf_expand_label(key, digest, traffic_secret, traffic_secret_len, label,
                           label_len, NULL, 0, key_len)) {
        return 0;
    }

    /* The IV's label ends in "iv" instead of "key". */
    if (label_len < 3) {
        assert(0);
        return 0;
    }
    label_len--;
    label[label_len - 2] = 'i';
    label[label_len - 1] = 'v';

    /* Derive the IV. */
    size_t iv_len = EVP_AEAD_nonce_length(aead);
    uint8_t iv[EVP_AEAD_MAX_NONCE_LENGTH];
    if (!hkdf_expand_label(iv, digest, traffic_secret, traffic_secret_len, label,
                           label_len, NULL, 0, iv_len)) {
        return 0;
    }

    SSL_AEAD_CTX *traffic_aead = SSL_AEAD_CTX_new(direction,
                                 ssl3_protocol_version(ssl),
                                 ssl->session->cipher,
                                 key, key_len, NULL, 0,
                                 iv, iv_len);
    if (traffic_aead == NULL) {
        return 0;
    }

    if (direction == evp_aead_open) {
        if (!ssl->method->set_read_state(ssl, traffic_aead)) {
            return 0;
        }
    } else {
        if (!ssl->method->set_write_state(ssl, traffic_aead)) {
            return 0;
        }
    }

    /* Save the traffic secret. */
    if (direction == evp_aead_open) {
        memcpy(ssl->s3->read_traffic_secret, traffic_secret, traffic_secret_len);
        ssl->s3->read_traffic_secret_len = traffic_secret_len;
    } else {
        memcpy(ssl->s3->write_traffic_secret, traffic_secret, traffic_secret_len);
        ssl->s3->write_traffic_secret_len = traffic_secret_len;
    }

    return 1;
}
Esempio n. 23
0
const SSL_CIPHER *ssl3_choose_cipher(
    SSL *ssl, const struct ssl_early_callback_ctx *client_hello,
    const struct ssl_cipher_preference_list_st *server_pref) {
  const SSL_CIPHER *c, *ret = NULL;
  STACK_OF(SSL_CIPHER) *srvr = server_pref->ciphers, *prio, *allow;
  int ok;
  size_t cipher_index;
  uint32_t alg_k, alg_a, mask_k, mask_a;
  /* in_group_flags will either be NULL, or will point to an array of bytes
   * which indicate equal-preference groups in the |prio| stack. See the
   * comment about |in_group_flags| in the |ssl_cipher_preference_list_st|
   * struct. */
  const uint8_t *in_group_flags;
  /* group_min contains the minimal index so far found in a group, or -1 if no
   * such value exists yet. */
  int group_min = -1;

  STACK_OF(SSL_CIPHER) *clnt = ssl_parse_client_cipher_list(client_hello);
  if (clnt == NULL) {
    return NULL;
  }

  if (ssl->options & SSL_OP_CIPHER_SERVER_PREFERENCE) {
    prio = srvr;
    in_group_flags = server_pref->in_group_flags;
    allow = clnt;
  } else {
    prio = clnt;
    in_group_flags = NULL;
    allow = srvr;
  }

  ssl_get_compatible_server_ciphers(ssl, &mask_k, &mask_a);

  for (size_t i = 0; i < sk_SSL_CIPHER_num(prio); i++) {
    c = sk_SSL_CIPHER_value(prio, i);

    ok = 1;

    /* Check the TLS version. */
    if (SSL_CIPHER_get_min_version(c) > ssl3_protocol_version(ssl) ||
        SSL_CIPHER_get_max_version(c) < ssl3_protocol_version(ssl)) {
      ok = 0;
    }

    alg_k = c->algorithm_mkey;
    alg_a = c->algorithm_auth;

    ok = ok && (alg_k & mask_k) && (alg_a & mask_a);

    if (ok && sk_SSL_CIPHER_find(allow, &cipher_index, c)) {
      if (in_group_flags != NULL && in_group_flags[i] == 1) {
        /* This element of |prio| is in a group. Update the minimum index found
         * so far and continue looking. */
        if (group_min == -1 || (size_t)group_min > cipher_index) {
          group_min = cipher_index;
        }
      } else {
        if (group_min != -1 && (size_t)group_min < cipher_index) {
          cipher_index = group_min;
        }
        ret = sk_SSL_CIPHER_value(allow, cipher_index);
        break;
      }
    }

    if (in_group_flags != NULL && in_group_flags[i] == 0 && group_min != -1) {
      /* We are about to leave a group, but we found a match in it, so that's
       * our answer. */
      ret = sk_SSL_CIPHER_value(allow, group_min);
      break;
    }
  }

  sk_SSL_CIPHER_free(clnt);
  return ret;
}
Esempio n. 24
0
/* Return up to 'len' payload bytes received in 'type' records.
 * 'type' is one of the following:
 *
 *   -  SSL3_RT_HANDSHAKE (when ssl3_get_message calls us)
 *   -  SSL3_RT_APPLICATION_DATA (when ssl3_read_app_data calls us)
 *
 * If we don't have stored data to work from, read a SSL/TLS record first
 * (possibly multiple records if we still don't have anything to return).
 *
 * This function must handle any surprises the peer may have for us, such as
 * Alert records (e.g. close_notify) or renegotiation requests. */
int ssl3_read_bytes(SSL *ssl, int type, uint8_t *buf, int len, int peek) {
  int al, i, ret;
  unsigned int n;
  SSL3_RECORD *rr;

  if ((type != SSL3_RT_APPLICATION_DATA && type != SSL3_RT_HANDSHAKE) ||
      (peek && type != SSL3_RT_APPLICATION_DATA)) {
    OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR);
    return -1;
  }

start:
  /* ssl->s3->rrec.type    - is the type of record
   * ssl->s3->rrec.data    - data
   * ssl->s3->rrec.off     - offset into 'data' for next read
   * ssl->s3->rrec.length  - number of bytes. */
  rr = &ssl->s3->rrec;

  /* get new packet if necessary */
  if (rr->length == 0) {
    ret = ssl3_get_record(ssl);
    if (ret <= 0) {
      return ret;
    }
  }

  /* we now have a packet which can be read and processed */

  if (type == rr->type) {
    /* Discard empty records. */
    if (rr->length == 0) {
      goto start;
    }

    if (len <= 0) {
      return len;
    }

    if ((unsigned int)len > rr->length) {
      n = rr->length;
    } else {
      n = (unsigned int)len;
    }

    memcpy(buf, rr->data, n);
    if (!peek) {
      rr->length -= n;
      rr->data += n;
      if (rr->length == 0) {
        /* The record has been consumed, so we may now clear the buffer. */
        ssl_read_buffer_discard(ssl);
      }
    }

    return n;
  }

  /* Process unexpected records. */

  if (type == SSL3_RT_APPLICATION_DATA && rr->type == SSL3_RT_HANDSHAKE) {
    if (ssl3_protocol_version(ssl) >= TLS1_3_VERSION) {
      /* TODO(svaldez): Handle TLS 1.3 post-handshake messages. For now,
       * silently drop all handshake records. */
      rr->length = 0;
      goto start;
    }

    /* If peer renegotiations are disabled, all out-of-order handshake records
     * are fatal. Renegotiations as a server are never supported. */
    if (ssl->server || !ssl3_can_renegotiate(ssl)) {
      al = SSL_AD_NO_RENEGOTIATION;
      OPENSSL_PUT_ERROR(SSL, SSL_R_NO_RENEGOTIATION);
      goto f_err;
    }

    /* This must be a HelloRequest, possibly fragmented over multiple records.
     * Consume data from the handshake protocol until it is complete. */
    static const uint8_t kHelloRequest[] = {SSL3_MT_HELLO_REQUEST, 0, 0, 0};
    while (ssl->s3->hello_request_len < sizeof(kHelloRequest)) {
      if (rr->length == 0) {
        /* Get a new record. */
        goto start;
      }
      if (rr->data[0] != kHelloRequest[ssl->s3->hello_request_len]) {
        al = SSL_AD_DECODE_ERROR;
        OPENSSL_PUT_ERROR(SSL, SSL_R_BAD_HELLO_REQUEST);
        goto f_err;
      }
      rr->data++;
      rr->length--;
      ssl->s3->hello_request_len++;
    }
    ssl->s3->hello_request_len = 0;

    ssl_do_msg_callback(ssl, 0 /* read */, ssl->version, SSL3_RT_HANDSHAKE,
                        kHelloRequest, sizeof(kHelloRequest));

    if (ssl->renegotiate_mode == ssl_renegotiate_ignore) {
      goto start;
    }

    /* Renegotiation is only supported at quiescent points in the application
     * protocol, namely in HTTPS, just before reading the HTTP response. Require
     * the record-layer be idle and avoid complexities of sending a handshake
     * record while an application_data record is being written. */
    if (ssl_write_buffer_is_pending(ssl)) {
      al = SSL_AD_NO_RENEGOTIATION;
      OPENSSL_PUT_ERROR(SSL, SSL_R_NO_RENEGOTIATION);
      goto f_err;
    }

    /* Begin a new handshake. */
    ssl->s3->total_renegotiations++;
    ssl->state = SSL_ST_CONNECT;
    i = ssl->handshake_func(ssl);
    if (i < 0) {
      return i;
    }
    if (i == 0) {
      OPENSSL_PUT_ERROR(SSL, SSL_R_SSL_HANDSHAKE_FAILURE);
      return -1;
    }

    /* The handshake completed synchronously. Continue reading records. */
    goto start;
  }

  al = SSL_AD_UNEXPECTED_MESSAGE;
  OPENSSL_PUT_ERROR(SSL, SSL_R_UNEXPECTED_RECORD);

f_err:
  ssl3_send_alert(ssl, SSL3_AL_FATAL, al);
  return -1;
}
Esempio n. 25
0
int ssl_get_new_session(SSL_HANDSHAKE *hs, int is_server) {
  SSL *const ssl = hs->ssl;
  if (ssl->mode & SSL_MODE_NO_SESSION_CREATION) {
    OPENSSL_PUT_ERROR(SSL, SSL_R_SESSION_MAY_NOT_BE_CREATED);
    return 0;
  }

  SSL_SESSION *session = ssl_session_new(ssl->ctx->x509_method);
  if (session == NULL) {
    return 0;
  }

  session->is_server = is_server;
  session->ssl_version = ssl->version;

  /* Fill in the time from the |SSL_CTX|'s clock. */
  struct OPENSSL_timeval now;
  ssl_get_current_time(ssl, &now);
  session->time = now.tv_sec;

  uint16_t version = ssl3_protocol_version(ssl);
  if (version >= TLS1_3_VERSION) {
    /* TLS 1.3 uses tickets as authenticators, so we are willing to use them for
     * longer. */
    session->timeout = ssl->session_ctx->session_psk_dhe_timeout;
    session->auth_timeout = SSL_DEFAULT_SESSION_AUTH_TIMEOUT;
  } else {
    /* TLS 1.2 resumption does not incorporate new key material, so we use a
     * much shorter timeout. */
    session->timeout = ssl->session_ctx->session_timeout;
    session->auth_timeout = ssl->session_ctx->session_timeout;
  }

  if (is_server) {
    if (hs->ticket_expected || version >= TLS1_3_VERSION) {
      /* Don't set session IDs for sessions resumed with tickets. This will keep
       * them out of the session cache. */
      session->session_id_length = 0;
    } else {
      session->session_id_length = SSL3_SSL_SESSION_ID_LENGTH;
      if (!RAND_bytes(session->session_id, session->session_id_length)) {
        goto err;
      }
    }
  } else {
    session->session_id_length = 0;
  }

  if (ssl->cert->sid_ctx_length > sizeof(session->sid_ctx)) {
    OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR);
    goto err;
  }
  OPENSSL_memcpy(session->sid_ctx, ssl->cert->sid_ctx,
                 ssl->cert->sid_ctx_length);
  session->sid_ctx_length = ssl->cert->sid_ctx_length;

  /* The session is marked not resumable until it is completely filled in. */
  session->not_resumable = 1;
  session->verify_result = X509_V_ERR_INVALID_CALL;

  SSL_SESSION_free(hs->new_session);
  hs->new_session = session;
  ssl_set_session(ssl, NULL);
  return 1;

err:
  SSL_SESSION_free(session);
  return 0;
}