12c593315Sopenharmony_ci/*
22c593315Sopenharmony_ci * nghttp2 - HTTP/2 C Library
32c593315Sopenharmony_ci *
42c593315Sopenharmony_ci * Copyright (c) 2014 Tatsuhiro Tsujikawa
52c593315Sopenharmony_ci *
62c593315Sopenharmony_ci * Permission is hereby granted, free of charge, to any person obtaining
72c593315Sopenharmony_ci * a copy of this software and associated documentation files (the
82c593315Sopenharmony_ci * "Software"), to deal in the Software without restriction, including
92c593315Sopenharmony_ci * without limitation the rights to use, copy, modify, merge, publish,
102c593315Sopenharmony_ci * distribute, sublicense, and/or sell copies of the Software, and to
112c593315Sopenharmony_ci * permit persons to whom the Software is furnished to do so, subject to
122c593315Sopenharmony_ci * the following conditions:
132c593315Sopenharmony_ci *
142c593315Sopenharmony_ci * The above copyright notice and this permission notice shall be
152c593315Sopenharmony_ci * included in all copies or substantial portions of the Software.
162c593315Sopenharmony_ci *
172c593315Sopenharmony_ci * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
182c593315Sopenharmony_ci * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
192c593315Sopenharmony_ci * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
202c593315Sopenharmony_ci * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
212c593315Sopenharmony_ci * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
222c593315Sopenharmony_ci * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
232c593315Sopenharmony_ci * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
242c593315Sopenharmony_ci */
252c593315Sopenharmony_ci#include "tls.h"
262c593315Sopenharmony_ci
272c593315Sopenharmony_ci#include <cassert>
282c593315Sopenharmony_ci#include <vector>
292c593315Sopenharmony_ci#include <mutex>
302c593315Sopenharmony_ci#include <iostream>
312c593315Sopenharmony_ci
322c593315Sopenharmony_ci#include <openssl/crypto.h>
332c593315Sopenharmony_ci#include <openssl/conf.h>
342c593315Sopenharmony_ci
352c593315Sopenharmony_ci#include "ssl_compat.h"
362c593315Sopenharmony_ci
372c593315Sopenharmony_cinamespace nghttp2 {
382c593315Sopenharmony_ci
392c593315Sopenharmony_cinamespace tls {
402c593315Sopenharmony_ci
412c593315Sopenharmony_ci#if OPENSSL_1_1_API
422c593315Sopenharmony_ci
432c593315Sopenharmony_ci// CRYPTO_LOCK is deprecated as of OpenSSL 1.1.0
442c593315Sopenharmony_ciLibsslGlobalLock::LibsslGlobalLock() {}
452c593315Sopenharmony_ci
462c593315Sopenharmony_ci#else // !OPENSSL_1_1_API
472c593315Sopenharmony_ci
482c593315Sopenharmony_cinamespace {
492c593315Sopenharmony_cistd::mutex *ssl_global_locks;
502c593315Sopenharmony_ci} // namespace
512c593315Sopenharmony_ci
522c593315Sopenharmony_cinamespace {
532c593315Sopenharmony_civoid ssl_locking_cb(int mode, int type, const char *file, int line) {
542c593315Sopenharmony_ci  if (mode & CRYPTO_LOCK) {
552c593315Sopenharmony_ci    ssl_global_locks[type].lock();
562c593315Sopenharmony_ci  } else {
572c593315Sopenharmony_ci    ssl_global_locks[type].unlock();
582c593315Sopenharmony_ci  }
592c593315Sopenharmony_ci}
602c593315Sopenharmony_ci} // namespace
612c593315Sopenharmony_ci
622c593315Sopenharmony_ciLibsslGlobalLock::LibsslGlobalLock() {
632c593315Sopenharmony_ci  if (ssl_global_locks) {
642c593315Sopenharmony_ci    std::cerr << "OpenSSL global lock has been already set" << std::endl;
652c593315Sopenharmony_ci    assert(0);
662c593315Sopenharmony_ci  }
672c593315Sopenharmony_ci  ssl_global_locks = new std::mutex[CRYPTO_num_locks()];
682c593315Sopenharmony_ci  // CRYPTO_set_id_callback(ssl_thread_id); OpenSSL manual says that
692c593315Sopenharmony_ci  // if threadid_func is not specified using
702c593315Sopenharmony_ci  // CRYPTO_THREADID_set_callback(), then default implementation is
712c593315Sopenharmony_ci  // used. We use this default one.
722c593315Sopenharmony_ci  CRYPTO_set_locking_callback(ssl_locking_cb);
732c593315Sopenharmony_ci}
742c593315Sopenharmony_ci
752c593315Sopenharmony_ci#endif // !OPENSSL_1_1_API
762c593315Sopenharmony_ci
772c593315Sopenharmony_ciconst char *get_tls_protocol(SSL *ssl) {
782c593315Sopenharmony_ci  switch (SSL_version(ssl)) {
792c593315Sopenharmony_ci  case SSL2_VERSION:
802c593315Sopenharmony_ci    return "SSLv2";
812c593315Sopenharmony_ci  case SSL3_VERSION:
822c593315Sopenharmony_ci    return "SSLv3";
832c593315Sopenharmony_ci#ifdef TLS1_3_VERSION
842c593315Sopenharmony_ci  case TLS1_3_VERSION:
852c593315Sopenharmony_ci    return "TLSv1.3";
862c593315Sopenharmony_ci#endif // TLS1_3_VERSION
872c593315Sopenharmony_ci  case TLS1_2_VERSION:
882c593315Sopenharmony_ci    return "TLSv1.2";
892c593315Sopenharmony_ci  case TLS1_1_VERSION:
902c593315Sopenharmony_ci    return "TLSv1.1";
912c593315Sopenharmony_ci  case TLS1_VERSION:
922c593315Sopenharmony_ci    return "TLSv1";
932c593315Sopenharmony_ci  default:
942c593315Sopenharmony_ci    return "unknown";
952c593315Sopenharmony_ci  }
962c593315Sopenharmony_ci}
972c593315Sopenharmony_ci
982c593315Sopenharmony_ciTLSSessionInfo *get_tls_session_info(TLSSessionInfo *tls_info, SSL *ssl) {
992c593315Sopenharmony_ci  if (!ssl) {
1002c593315Sopenharmony_ci    return nullptr;
1012c593315Sopenharmony_ci  }
1022c593315Sopenharmony_ci
1032c593315Sopenharmony_ci  auto session = SSL_get_session(ssl);
1042c593315Sopenharmony_ci  if (!session) {
1052c593315Sopenharmony_ci    return nullptr;
1062c593315Sopenharmony_ci  }
1072c593315Sopenharmony_ci
1082c593315Sopenharmony_ci  tls_info->cipher = SSL_get_cipher_name(ssl);
1092c593315Sopenharmony_ci  tls_info->protocol = get_tls_protocol(ssl);
1102c593315Sopenharmony_ci  tls_info->session_reused = SSL_session_reused(ssl);
1112c593315Sopenharmony_ci
1122c593315Sopenharmony_ci  unsigned int session_id_length;
1132c593315Sopenharmony_ci  tls_info->session_id = SSL_SESSION_get_id(session, &session_id_length);
1142c593315Sopenharmony_ci  tls_info->session_id_length = session_id_length;
1152c593315Sopenharmony_ci
1162c593315Sopenharmony_ci  return tls_info;
1172c593315Sopenharmony_ci}
1182c593315Sopenharmony_ci
1192c593315Sopenharmony_ci/* Conditional logic w/ lookup tables to check if id is one of the
1202c593315Sopenharmony_ci   the block listed cipher suites for HTTP/2 described in RFC 7540.
1212c593315Sopenharmony_ci   https://github.com/jay/http2_blacklisted_ciphers
1222c593315Sopenharmony_ci*/
1232c593315Sopenharmony_ci#define IS_CIPHER_BANNED_METHOD2(id)                                           \
1242c593315Sopenharmony_ci  ((0x0000 <= id && id <= 0x00FF &&                                            \
1252c593315Sopenharmony_ci    "\xFF\xFF\xFF\xCF\xFF\xFF\xFF\xFF\x7F\x00\x00\x00\x80\x3F\x00\x00"         \
1262c593315Sopenharmony_ci    "\xF0\xFF\xFF\x3F\xF3\xF3\xFF\xFF\x3F\x00\x00\x00\x00\x00\x00\x80"         \
1272c593315Sopenharmony_ci            [(id & 0xFF) / 8] &                                                \
1282c593315Sopenharmony_ci        (1 << (id % 8))) ||                                                    \
1292c593315Sopenharmony_ci   (0xC000 <= id && id <= 0xC0FF &&                                            \
1302c593315Sopenharmony_ci    "\xFE\xFF\xFF\xFF\xFF\x67\xFE\xFF\xFF\xFF\x33\xCF\xFC\xCF\xFF\xCF"         \
1312c593315Sopenharmony_ci    "\x3C\xF3\xFC\x3F\x33\x03\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"         \
1322c593315Sopenharmony_ci            [(id & 0xFF) / 8] &                                                \
1332c593315Sopenharmony_ci        (1 << (id % 8))))
1342c593315Sopenharmony_ci
1352c593315Sopenharmony_cibool check_http2_cipher_block_list(SSL *ssl) {
1362c593315Sopenharmony_ci  int id = SSL_CIPHER_get_id(SSL_get_current_cipher(ssl)) & 0xFFFFFF;
1372c593315Sopenharmony_ci
1382c593315Sopenharmony_ci  return IS_CIPHER_BANNED_METHOD2(id);
1392c593315Sopenharmony_ci}
1402c593315Sopenharmony_ci
1412c593315Sopenharmony_cibool check_http2_tls_version(SSL *ssl) {
1422c593315Sopenharmony_ci  auto tls_ver = SSL_version(ssl);
1432c593315Sopenharmony_ci
1442c593315Sopenharmony_ci  return tls_ver >= TLS1_2_VERSION;
1452c593315Sopenharmony_ci}
1462c593315Sopenharmony_ci
1472c593315Sopenharmony_cibool check_http2_requirement(SSL *ssl) {
1482c593315Sopenharmony_ci  return check_http2_tls_version(ssl) && !check_http2_cipher_block_list(ssl);
1492c593315Sopenharmony_ci}
1502c593315Sopenharmony_ci
1512c593315Sopenharmony_civoid libssl_init() {
1522c593315Sopenharmony_ci#if OPENSSL_1_1_API
1532c593315Sopenharmony_ci// No explicit initialization is required.
1542c593315Sopenharmony_ci#elif defined(OPENSSL_IS_BORINGSSL)
1552c593315Sopenharmony_ci  CRYPTO_library_init();
1562c593315Sopenharmony_ci#else  // !OPENSSL_1_1_API && !defined(OPENSSL_IS_BORINGSSL)
1572c593315Sopenharmony_ci  OPENSSL_config(nullptr);
1582c593315Sopenharmony_ci  SSL_load_error_strings();
1592c593315Sopenharmony_ci  SSL_library_init();
1602c593315Sopenharmony_ci  OpenSSL_add_all_algorithms();
1612c593315Sopenharmony_ci#endif // !OPENSSL_1_1_API && !defined(OPENSSL_IS_BORINGSSL)
1622c593315Sopenharmony_ci}
1632c593315Sopenharmony_ci
1642c593315Sopenharmony_ciint ssl_ctx_set_proto_versions(SSL_CTX *ssl_ctx, int min, int max) {
1652c593315Sopenharmony_ci#if OPENSSL_1_1_API || defined(OPENSSL_IS_BORINGSSL)
1662c593315Sopenharmony_ci  if (SSL_CTX_set_min_proto_version(ssl_ctx, min) != 1 ||
1672c593315Sopenharmony_ci      SSL_CTX_set_max_proto_version(ssl_ctx, max) != 1) {
1682c593315Sopenharmony_ci    return -1;
1692c593315Sopenharmony_ci  }
1702c593315Sopenharmony_ci  return 0;
1712c593315Sopenharmony_ci#else  // !OPENSSL_1_1_API && !defined(OPENSSL_IS_BORINGSSL)
1722c593315Sopenharmony_ci  long int opts = 0;
1732c593315Sopenharmony_ci
1742c593315Sopenharmony_ci  // TODO We depends on the ordering of protocol version macro in
1752c593315Sopenharmony_ci  // OpenSSL.
1762c593315Sopenharmony_ci  if (min > TLS1_VERSION) {
1772c593315Sopenharmony_ci    opts |= SSL_OP_NO_TLSv1;
1782c593315Sopenharmony_ci  }
1792c593315Sopenharmony_ci  if (min > TLS1_1_VERSION) {
1802c593315Sopenharmony_ci    opts |= SSL_OP_NO_TLSv1_1;
1812c593315Sopenharmony_ci  }
1822c593315Sopenharmony_ci  if (min > TLS1_2_VERSION) {
1832c593315Sopenharmony_ci    opts |= SSL_OP_NO_TLSv1_2;
1842c593315Sopenharmony_ci  }
1852c593315Sopenharmony_ci
1862c593315Sopenharmony_ci  if (max < TLS1_2_VERSION) {
1872c593315Sopenharmony_ci    opts |= SSL_OP_NO_TLSv1_2;
1882c593315Sopenharmony_ci  }
1892c593315Sopenharmony_ci  if (max < TLS1_1_VERSION) {
1902c593315Sopenharmony_ci    opts |= SSL_OP_NO_TLSv1_1;
1912c593315Sopenharmony_ci  }
1922c593315Sopenharmony_ci
1932c593315Sopenharmony_ci  SSL_CTX_set_options(ssl_ctx, opts);
1942c593315Sopenharmony_ci
1952c593315Sopenharmony_ci  return 0;
1962c593315Sopenharmony_ci#endif // !OPENSSL_1_1_API && !defined(OPENSSL_IS_BORINGSSL)
1972c593315Sopenharmony_ci}
1982c593315Sopenharmony_ci
1992c593315Sopenharmony_ci} // namespace tls
2002c593315Sopenharmony_ci
2012c593315Sopenharmony_ci} // namespace nghttp2
202