예제 #1
0
static int ssl_encrypt_ticket_with_method(SSL *ssl, CBB *out,
                                          const uint8_t *session_buf,
                                          size_t session_len) {
  const SSL_TICKET_AEAD_METHOD *method = ssl->session_ctx->ticket_aead_method;
  const size_t max_overhead = method->max_overhead(ssl);
  const size_t max_out = session_len + max_overhead;
  if (max_out < max_overhead) {
    OPENSSL_PUT_ERROR(SSL, ERR_R_OVERFLOW);
    return 0;
  }

  uint8_t *ptr;
  if (!CBB_reserve(out, &ptr, max_out)) {
    return 0;
  }

  size_t out_len;
  if (!method->seal(ssl, ptr, &out_len, max_out, session_buf, session_len)) {
    OPENSSL_PUT_ERROR(SSL, SSL_R_TICKET_ENCRYPTION_FAILED);
    return 0;
  }

  if (!CBB_did_write(out, out_len)) {
    return 0;
  }

  return 1;
}
예제 #2
0
enum ssl_private_key_result_t tls13_prepare_certificate_verify(
    SSL *ssl, int is_first_run) {
  enum ssl_private_key_result_t ret = ssl_private_key_failure;
  uint8_t *msg = NULL;
  size_t msg_len;
  CBB cbb, body;
  CBB_zero(&cbb);

  uint16_t signature_algorithm;
  if (!tls1_choose_signature_algorithm(ssl, &signature_algorithm)) {
    goto err;
  }
  if (!ssl->method->init_message(ssl, &cbb, &body,
                                 SSL3_MT_CERTIFICATE_VERIFY) ||
      !CBB_add_u16(&body, signature_algorithm)) {
    OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR);
    goto err;
  }

  /* Sign the digest. */
  CBB child;
  const size_t max_sig_len = ssl_private_key_max_signature_len(ssl);
  uint8_t *sig;
  size_t sig_len;
  if (!CBB_add_u16_length_prefixed(&body, &child) ||
      !CBB_reserve(&child, &sig, max_sig_len)) {
    ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_INTERNAL_ERROR);
    goto err;
  }

  enum ssl_private_key_result_t sign_result;
  if (is_first_run) {
    if (!tls13_get_cert_verify_signature_input(ssl, &msg, &msg_len,
                                               ssl->server)) {
      ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_INTERNAL_ERROR);
      goto err;
    }
    sign_result = ssl_private_key_sign(ssl, sig, &sig_len, max_sig_len,
                                       signature_algorithm, msg, msg_len);
  } else {
    sign_result = ssl_private_key_complete(ssl, sig, &sig_len, max_sig_len);
  }

  if (sign_result != ssl_private_key_success) {
    ret = sign_result;
    goto err;
  }

  if (!CBB_did_write(&child, sig_len) ||
      !ssl->method->finish_message(ssl, &cbb)) {
    goto err;
  }

  ret = ssl_private_key_success;

err:
  CBB_cleanup(&cbb);
  OPENSSL_free(msg);
  return ret;
}
예제 #3
0
static int ssl_encrypt_ticket_with_cipher_ctx(SSL *ssl, CBB *out,
                                              const uint8_t *session_buf,
                                              size_t session_len) {
  int ret = 0;

  EVP_CIPHER_CTX ctx;
  EVP_CIPHER_CTX_init(&ctx);
  HMAC_CTX hctx;
  HMAC_CTX_init(&hctx);

  /* If the session is too long, emit a dummy value rather than abort the
   * connection. */
  static const size_t kMaxTicketOverhead =
      16 + EVP_MAX_IV_LENGTH + EVP_MAX_BLOCK_LENGTH + EVP_MAX_MD_SIZE;
  if (session_len > 0xffff - kMaxTicketOverhead) {
    static const char kTicketPlaceholder[] = "TICKET TOO LARGE";
    if (CBB_add_bytes(out, (const uint8_t *)kTicketPlaceholder,
                      strlen(kTicketPlaceholder))) {
      ret = 1;
    }
    goto err;
  }

  /* Initialize HMAC and cipher contexts. If callback present it does all the
   * work otherwise use generated values from parent ctx. */
  SSL_CTX *tctx = ssl->session_ctx;
  uint8_t iv[EVP_MAX_IV_LENGTH];
  uint8_t key_name[16];
  if (tctx->tlsext_ticket_key_cb != NULL) {
    if (tctx->tlsext_ticket_key_cb(ssl, key_name, iv, &ctx, &hctx,
                                   1 /* encrypt */) < 0) {
      goto err;
    }
  } else {
    if (!RAND_bytes(iv, 16) ||
        !EVP_EncryptInit_ex(&ctx, EVP_aes_128_cbc(), NULL,
                            tctx->tlsext_tick_aes_key, iv) ||
        !HMAC_Init_ex(&hctx, tctx->tlsext_tick_hmac_key, 16, tlsext_tick_md(),
                      NULL)) {
      goto err;
    }
    OPENSSL_memcpy(key_name, tctx->tlsext_tick_key_name, 16);
  }

  uint8_t *ptr;
  if (!CBB_add_bytes(out, key_name, 16) ||
      !CBB_add_bytes(out, iv, EVP_CIPHER_CTX_iv_length(&ctx)) ||
      !CBB_reserve(out, &ptr, session_len + EVP_MAX_BLOCK_LENGTH)) {
    goto err;
  }

  size_t total = 0;
#if defined(BORINGSSL_UNSAFE_FUZZER_MODE)
  OPENSSL_memcpy(ptr, session_buf, session_len);
  total = session_len;
#else
  int len;
  if (!EVP_EncryptUpdate(&ctx, ptr + total, &len, session_buf, session_len)) {
    goto err;
  }
  total += len;
  if (!EVP_EncryptFinal_ex(&ctx, ptr + total, &len)) {
    goto err;
  }
  total += len;
#endif
  if (!CBB_did_write(out, total)) {
    goto err;
  }

  unsigned hlen;
  if (!HMAC_Update(&hctx, CBB_data(out), CBB_len(out)) ||
      !CBB_reserve(out, &ptr, EVP_MAX_MD_SIZE) ||
      !HMAC_Final(&hctx, ptr, &hlen) ||
      !CBB_did_write(out, hlen)) {
    goto err;
  }

  ret = 1;

err:
  EVP_CIPHER_CTX_cleanup(&ctx);
  HMAC_CTX_cleanup(&hctx);
  return ret;
}