LCOV - code coverage report
Current view: top level - core/tsi - ssl_transport_security.c (source / functions) Hit Total Coverage
Test: tmp.CaZ6RjdVn2 Lines: 613 789 77.7 %
Date: 2015-12-10 22:15:08 Functions: 44 46 95.7 %

          Line data    Source code
       1             : /*
       2             :  *
       3             :  * Copyright 2015, Google Inc.
       4             :  * 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 are
       8             :  * met:
       9             :  *
      10             :  *     * Redistributions of source code must retain the above copyright
      11             :  * notice, this list of conditions and the following disclaimer.
      12             :  *     * Redistributions in binary form must reproduce the above
      13             :  * copyright notice, this list of conditions and the following disclaimer
      14             :  * in the documentation and/or other materials provided with the
      15             :  * distribution.
      16             :  *     * Neither the name of Google Inc. nor the names of its
      17             :  * contributors may be used to endorse or promote products derived from
      18             :  * this software without specific prior written permission.
      19             :  *
      20             :  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
      21             :  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
      22             :  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
      23             :  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
      24             :  * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
      25             :  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
      26             :  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
      27             :  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
      28             :  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
      29             :  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
      30             :  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
      31             :  *
      32             :  */
      33             : 
      34             : #include "src/core/tsi/ssl_transport_security.h"
      35             : 
      36             : #include <limits.h>
      37             : #include <string.h>
      38             : 
      39             : #include <grpc/support/log.h>
      40             : #include <grpc/support/sync.h>
      41             : #include <grpc/support/thd.h>
      42             : #include <grpc/support/useful.h>
      43             : #include "src/core/tsi/transport_security.h"
      44             : 
      45             : #include <openssl/bio.h>
      46             : #include <openssl/crypto.h> /* For OPENSSL_free */
      47             : #include <openssl/err.h>
      48             : #include <openssl/ssl.h>
      49             : #include <openssl/x509.h>
      50             : #include <openssl/x509v3.h>
      51             : 
      52             : /* --- Constants. ---*/
      53             : 
      54             : #define TSI_SSL_MAX_PROTECTED_FRAME_SIZE_UPPER_BOUND 16384
      55             : #define TSI_SSL_MAX_PROTECTED_FRAME_SIZE_LOWER_BOUND 1024
      56             : 
      57             : /* Putting a macro like this and littering the source file with #if is really
      58             :    bad practice.
      59             :    TODO(jboeuf): refactor all the #if / #endif in a separate module. */
      60             : #ifndef TSI_OPENSSL_ALPN_SUPPORT
      61             : #define TSI_OPENSSL_ALPN_SUPPORT 1
      62             : #endif
      63             : 
      64             : /* TODO(jboeuf): I have not found a way to get this number dynamically from the
      65             :    SSL structure. This is what we would ultimately want though... */
      66             : #define TSI_SSL_MAX_PROTECTION_OVERHEAD 100
      67             : 
      68             : /* --- Structure definitions. ---*/
      69             : 
      70             : struct tsi_ssl_handshaker_factory {
      71             :   tsi_result (*create_handshaker)(tsi_ssl_handshaker_factory *self,
      72             :                                   const char *server_name_indication,
      73             :                                   tsi_handshaker **handshaker);
      74             :   void (*destroy)(tsi_ssl_handshaker_factory *self);
      75             : };
      76             : 
      77             : typedef struct {
      78             :   tsi_ssl_handshaker_factory base;
      79             :   SSL_CTX *ssl_context;
      80             :   unsigned char *alpn_protocol_list;
      81             :   size_t alpn_protocol_list_length;
      82             : } tsi_ssl_client_handshaker_factory;
      83             : 
      84             : typedef struct {
      85             :   tsi_ssl_handshaker_factory base;
      86             : 
      87             :   /* Several contexts to support SNI.
      88             :      The tsi_peer array contains the subject names of the server certificates
      89             :      associated with the contexts at the same index.  */
      90             :   SSL_CTX **ssl_contexts;
      91             :   tsi_peer *ssl_context_x509_subject_names;
      92             :   size_t ssl_context_count;
      93             :   unsigned char *alpn_protocol_list;
      94             :   size_t alpn_protocol_list_length;
      95             : } tsi_ssl_server_handshaker_factory;
      96             : 
      97             : typedef struct {
      98             :   tsi_handshaker base;
      99             :   SSL *ssl;
     100             :   BIO *into_ssl;
     101             :   BIO *from_ssl;
     102             :   tsi_result result;
     103             : } tsi_ssl_handshaker;
     104             : 
     105             : typedef struct {
     106             :   tsi_frame_protector base;
     107             :   SSL *ssl;
     108             :   BIO *into_ssl;
     109             :   BIO *from_ssl;
     110             :   unsigned char *buffer;
     111             :   size_t buffer_size;
     112             :   size_t buffer_offset;
     113             : } tsi_ssl_frame_protector;
     114             : 
     115             : /* --- Library Initialization. ---*/
     116             : 
     117             : static gpr_once init_openssl_once = GPR_ONCE_INIT;
     118             : static gpr_mu *openssl_mutexes = NULL;
     119             : 
     120     5245080 : static void openssl_locking_cb(int mode, int type, const char *file, int line) {
     121     5245080 :   if (mode & CRYPTO_LOCK) {
     122     2622518 :     gpr_mu_lock(&openssl_mutexes[type]);
     123             :   } else {
     124     2622562 :     gpr_mu_unlock(&openssl_mutexes[type]);
     125             :   }
     126     5245149 : }
     127             : 
     128      802941 : static unsigned long openssl_thread_id_cb(void) {
     129      802941 :   return (unsigned long)gpr_thd_currentid();
     130             : }
     131             : 
     132         134 : static void init_openssl(void) {
     133             :   int i;
     134             :   int num_locks;
     135         134 :   SSL_library_init();
     136         134 :   SSL_load_error_strings();
     137         134 :   OpenSSL_add_all_algorithms();
     138         134 :   num_locks = CRYPTO_num_locks();
     139         134 :   GPR_ASSERT(num_locks > 0);
     140         134 :   openssl_mutexes = malloc((size_t)num_locks * sizeof(gpr_mu));
     141         134 :   GPR_ASSERT(openssl_mutexes != NULL);
     142        5627 :   for (i = 0; i < CRYPTO_num_locks(); i++) {
     143        5494 :     gpr_mu_init(&openssl_mutexes[i]);
     144             :   }
     145         134 :   CRYPTO_set_locking_callback(openssl_locking_cb);
     146         134 :   CRYPTO_set_id_callback(openssl_thread_id_cb);
     147         134 : }
     148             : 
     149             : /* --- Ssl utils. ---*/
     150             : 
     151           0 : static const char *ssl_error_string(int error) {
     152           0 :   switch (error) {
     153             :     case SSL_ERROR_NONE:
     154           0 :       return "SSL_ERROR_NONE";
     155             :     case SSL_ERROR_ZERO_RETURN:
     156           0 :       return "SSL_ERROR_ZERO_RETURN";
     157             :     case SSL_ERROR_WANT_READ:
     158           0 :       return "SSL_ERROR_WANT_READ";
     159             :     case SSL_ERROR_WANT_WRITE:
     160           0 :       return "SSL_ERROR_WANT_WRITE";
     161             :     case SSL_ERROR_WANT_CONNECT:
     162           0 :       return "SSL_ERROR_WANT_CONNECT";
     163             :     case SSL_ERROR_WANT_ACCEPT:
     164           0 :       return "SSL_ERROR_WANT_ACCEPT";
     165             :     case SSL_ERROR_WANT_X509_LOOKUP:
     166           0 :       return "SSL_ERROR_WANT_X509_LOOKUP";
     167             :     case SSL_ERROR_SYSCALL:
     168           0 :       return "SSL_ERROR_SYSCALL";
     169             :     case SSL_ERROR_SSL:
     170           0 :       return "SSL_ERROR_SSL";
     171             :     default:
     172           0 :       return "Unknown error";
     173             :   }
     174             : }
     175             : 
     176             : /* TODO(jboeuf): Remove when we are past the debugging phase with this code. */
     177       52308 : static void ssl_log_where_info(const SSL *ssl, int where, int flag,
     178             :                                const char *msg) {
     179       52308 :   if ((where & flag) && tsi_tracing_enabled) {
     180           0 :     gpr_log(GPR_INFO, "%20.20s - %30.30s  - %5.10s", msg,
     181             :             SSL_state_string_long(ssl), SSL_state_string(ssl));
     182             :   }
     183       52308 : }
     184             : 
     185             : /* Used for debugging. TODO(jboeuf): Remove when code is mature enough. */
     186       17436 : static void ssl_info_callback(const SSL *ssl, int where, int ret) {
     187       17436 :   if (ret == 0) {
     188           0 :     gpr_log(GPR_ERROR, "ssl_info_callback: error occured.\n");
     189       17436 :     return;
     190             :   }
     191             : 
     192       17436 :   ssl_log_where_info(ssl, where, SSL_CB_LOOP, "LOOP");
     193       17436 :   ssl_log_where_info(ssl, where, SSL_CB_HANDSHAKE_START, "HANDSHAKE START");
     194       17436 :   ssl_log_where_info(ssl, where, SSL_CB_HANDSHAKE_DONE, "HANDSHAKE DONE");
     195             : }
     196             : 
     197             : /* Returns 1 if name looks like an IP address, 0 otherwise.
     198             :    This is a very rough heuristic as it does not handle IPV6 or things like:
     199             :    0300.0250.00.01, 0xC0.0Xa8.0x0.0x1, 000030052000001, 0xc0.052000001 */
     200      127154 : static int looks_like_ip_address(const char *name) {
     201             :   size_t i;
     202      127097 :   size_t dot_count = 0;
     203      127097 :   size_t num_size = 0;
     204      127169 :   for (i = 0; i < strlen(name); i++) {
     205      127168 :     if (name[i] >= '0' && name[i] <= '9') {
     206          12 :       if (num_size > 3) return 0;
     207          12 :       num_size++;
     208      127156 :     } else if (name[i] == '.') {
     209           4 :       if (dot_count > 3 || num_size == 0) return 0;
     210           3 :       dot_count++;
     211           3 :       num_size = 0;
     212             :     } else {
     213      127095 :       return 0;
     214             :     }
     215             :   }
     216           1 :   if (dot_count < 3 || num_size == 0) return 0;
     217           1 :   return 1;
     218             : }
     219             : 
     220             : /* Gets the subject CN from an X509 cert. */
     221        1058 : static tsi_result ssl_get_x509_common_name(X509 *cert, unsigned char **utf8,
     222             :                                            size_t *utf8_size) {
     223        1038 :   int common_name_index = -1;
     224        1038 :   X509_NAME_ENTRY *common_name_entry = NULL;
     225        1038 :   ASN1_STRING *common_name_asn1 = NULL;
     226        1058 :   X509_NAME *subject_name = X509_get_subject_name(cert);
     227        1038 :   int utf8_returned_size = 0;
     228        1058 :   if (subject_name == NULL) {
     229           0 :     gpr_log(GPR_ERROR, "Could not get subject name from certificate.");
     230           0 :     return TSI_NOT_FOUND;
     231             :   }
     232        1058 :   common_name_index =
     233             :       X509_NAME_get_index_by_NID(subject_name, NID_commonName, -1);
     234        1058 :   if (common_name_index == -1) {
     235           0 :     gpr_log(GPR_ERROR,
     236             :             "Could not get common name of subject from certificate.");
     237           0 :     return TSI_NOT_FOUND;
     238             :   }
     239        1058 :   common_name_entry = X509_NAME_get_entry(subject_name, common_name_index);
     240        1058 :   if (common_name_entry == NULL) {
     241           0 :     gpr_log(GPR_ERROR, "Could not get common name entry from certificate.");
     242           0 :     return TSI_INTERNAL_ERROR;
     243             :   }
     244        1058 :   common_name_asn1 = X509_NAME_ENTRY_get_data(common_name_entry);
     245        1058 :   if (common_name_asn1 == NULL) {
     246           0 :     gpr_log(GPR_ERROR,
     247             :             "Could not get common name entry asn1 from certificate.");
     248           0 :     return TSI_INTERNAL_ERROR;
     249             :   }
     250        1058 :   utf8_returned_size = ASN1_STRING_to_UTF8(utf8, common_name_asn1);
     251        1058 :   if (utf8_returned_size < 0) {
     252           0 :     gpr_log(GPR_ERROR, "Could not extract utf8 from asn1 string.");
     253           0 :     return TSI_OUT_OF_RESOURCES;
     254             :   }
     255        1058 :   *utf8_size = (size_t)utf8_returned_size;
     256        1058 :   return TSI_OK;
     257             : }
     258             : 
     259             : /* Gets the subject CN of an X509 cert as a tsi_peer_property. */
     260        1058 : static tsi_result peer_property_from_x509_common_name(
     261             :     X509 *cert, tsi_peer_property *property) {
     262             :   unsigned char *common_name;
     263             :   size_t common_name_size;
     264        1058 :   tsi_result result =
     265             :       ssl_get_x509_common_name(cert, &common_name, &common_name_size);
     266        1058 :   if (result != TSI_OK) {
     267           0 :     if (result == TSI_NOT_FOUND) {
     268           0 :       common_name = NULL;
     269           0 :       common_name_size = 0;
     270             :     } else {
     271           0 :       return result;
     272             :     }
     273             :   }
     274        2116 :   result = tsi_construct_string_peer_property(
     275             :       TSI_X509_SUBJECT_COMMON_NAME_PEER_PROPERTY,
     276        1058 :       common_name == NULL ? "" : (const char *)common_name, common_name_size,
     277             :       property);
     278        1058 :   OPENSSL_free(common_name);
     279        1058 :   return result;
     280             : }
     281             : 
     282             : /* Gets the subject SANs from an X509 cert as a tsi_peer_property. */
     283        1058 : static tsi_result add_subject_alt_names_properties_to_peer(
     284             :     tsi_peer *peer, GENERAL_NAMES *subject_alt_names,
     285             :     size_t subject_alt_name_count) {
     286             :   size_t i;
     287        1038 :   tsi_result result = TSI_OK;
     288             : 
     289             :   /* Reset for DNS entries filtering. */
     290        1058 :   peer->property_count -= subject_alt_name_count;
     291             : 
     292        5290 :   for (i = 0; i < subject_alt_name_count; i++) {
     293        4232 :     GENERAL_NAME *subject_alt_name =
     294        4232 :         sk_GENERAL_NAME_value(subject_alt_names, (int)i);
     295             :     /* Filter out the non-dns entries names. */
     296        4232 :     if (subject_alt_name->type == GEN_DNS) {
     297        3174 :       unsigned char *dns_name = NULL;
     298        3174 :       int dns_name_size =
     299        3174 :           ASN1_STRING_to_UTF8(&dns_name, subject_alt_name->d.dNSName);
     300        3174 :       if (dns_name_size < 0) {
     301           0 :         gpr_log(GPR_ERROR, "Could not get utf8 from asn1 string.");
     302           0 :         result = TSI_INTERNAL_ERROR;
     303           0 :         break;
     304             :       }
     305        3174 :       result = tsi_construct_string_peer_property(
     306             :           TSI_X509_SUBJECT_ALTERNATIVE_NAME_PEER_PROPERTY,
     307             :           (const char *)dns_name, (size_t)dns_name_size,
     308        3174 :           &peer->properties[peer->property_count++]);
     309        3174 :       OPENSSL_free(dns_name);
     310        3174 :       if (result != TSI_OK) break;
     311             :     }
     312             :   }
     313        1058 :   return result;
     314             : }
     315             : 
     316             : /* Gets information about the peer's X509 cert as a tsi_peer object. */
     317        1058 : static tsi_result peer_from_x509(X509 *cert, int include_certificate_type,
     318             :                                  tsi_peer *peer) {
     319             :   /* TODO(jboeuf): Maybe add more properties. */
     320        1058 :   GENERAL_NAMES *subject_alt_names =
     321             :       X509_get_ext_d2i(cert, NID_subject_alt_name, 0, 0);
     322        1038 :   int subject_alt_name_count = (subject_alt_names != NULL)
     323             :                                    ? (int)sk_GENERAL_NAME_num(subject_alt_names)
     324        1058 :                                    : 0;
     325             :   size_t property_count;
     326             :   tsi_result result;
     327        1058 :   GPR_ASSERT(subject_alt_name_count >= 0);
     328        2116 :   property_count = (include_certificate_type ? (size_t)1 : 0) +
     329        1058 :                    1 /* common name */ + (size_t)subject_alt_name_count;
     330        1058 :   result = tsi_construct_peer(property_count, peer);
     331        1058 :   if (result != TSI_OK) return result;
     332             :   do {
     333        1058 :     if (include_certificate_type) {
     334         481 :       result = tsi_construct_string_peer_property_from_cstring(
     335             :           TSI_CERTIFICATE_TYPE_PEER_PROPERTY, TSI_X509_CERTIFICATE_TYPE,
     336             :           &peer->properties[0]);
     337         481 :       if (result != TSI_OK) break;
     338             :     }
     339        1058 :     result = peer_property_from_x509_common_name(
     340        1058 :         cert, &peer->properties[include_certificate_type ? 1 : 0]);
     341        1058 :     if (result != TSI_OK) break;
     342             : 
     343        1058 :     if (subject_alt_name_count != 0) {
     344        1058 :       result = add_subject_alt_names_properties_to_peer(
     345             :           peer, subject_alt_names, (size_t)subject_alt_name_count);
     346        1038 :       if (result != TSI_OK) break;
     347             :     }
     348             :   } while (0);
     349             : 
     350        1058 :   if (subject_alt_names != NULL) {
     351        1058 :     sk_GENERAL_NAME_pop_free(subject_alt_names, GENERAL_NAME_free);
     352             :   }
     353        1058 :   if (result != TSI_OK) tsi_peer_destruct(peer);
     354        1058 :   return result;
     355             : }
     356             : 
     357             : /* Logs the SSL error stack. */
     358           0 : static void log_ssl_error_stack(void) {
     359             :   unsigned long err;
     360           0 :   while ((err = ERR_get_error()) != 0) {
     361             :     char details[256];
     362           0 :     ERR_error_string_n((uint32_t)err, details, sizeof(details));
     363           0 :     gpr_log(GPR_ERROR, "%s", details);
     364             :   }
     365           0 : }
     366             : 
     367             : /* Performs an SSL_read and handle errors. */
     368     1037868 : static tsi_result do_ssl_read(SSL *ssl, unsigned char *unprotected_bytes,
     369             :                               size_t *unprotected_bytes_size) {
     370             :   int read_from_ssl;
     371     1037868 :   GPR_ASSERT(*unprotected_bytes_size <= INT_MAX);
     372     1037868 :   read_from_ssl =
     373     1037868 :       SSL_read(ssl, unprotected_bytes, (int)*unprotected_bytes_size);
     374     1037867 :   if (read_from_ssl == 0) {
     375           0 :     gpr_log(GPR_ERROR, "SSL_read returned 0 unexpectedly.");
     376           0 :     return TSI_INTERNAL_ERROR;
     377             :   }
     378     1037867 :   if (read_from_ssl < 0) {
     379      776666 :     read_from_ssl = SSL_get_error(ssl, read_from_ssl);
     380      776669 :     switch (read_from_ssl) {
     381             :       case SSL_ERROR_WANT_READ:
     382             :         /* We need more data to finish the frame. */
     383      776669 :         *unprotected_bytes_size = 0;
     384      776669 :         return TSI_OK;
     385             :       case SSL_ERROR_WANT_WRITE:
     386           0 :         gpr_log(
     387             :             GPR_ERROR,
     388             :             "Peer tried to renegotiate SSL connection. This is unsupported.");
     389           0 :         return TSI_UNIMPLEMENTED;
     390             :       case SSL_ERROR_SSL:
     391           0 :         gpr_log(GPR_ERROR, "Corruption detected.");
     392           0 :         log_ssl_error_stack();
     393           0 :         return TSI_DATA_CORRUPTED;
     394             :       default:
     395           0 :         gpr_log(GPR_ERROR, "SSL_read failed with error %s.",
     396             :                 ssl_error_string(read_from_ssl));
     397           0 :         return TSI_PROTOCOL_FAILURE;
     398             :     }
     399             :   }
     400      261201 :   *unprotected_bytes_size = (size_t)read_from_ssl;
     401      261201 :   return TSI_OK;
     402             : }
     403             : 
     404             : /* Performs an SSL_write and handle errors. */
     405      257140 : static tsi_result do_ssl_write(SSL *ssl, unsigned char *unprotected_bytes,
     406             :                                size_t unprotected_bytes_size) {
     407             :   int ssl_write_result;
     408      257140 :   GPR_ASSERT(unprotected_bytes_size <= INT_MAX);
     409      257140 :   ssl_write_result =
     410      257140 :       SSL_write(ssl, unprotected_bytes, (int)unprotected_bytes_size);
     411      257141 :   if (ssl_write_result < 0) {
     412           0 :     ssl_write_result = SSL_get_error(ssl, ssl_write_result);
     413           0 :     if (ssl_write_result == SSL_ERROR_WANT_READ) {
     414           0 :       gpr_log(GPR_ERROR,
     415             :               "Peer tried to renegotiate SSL connection. This is unsupported.");
     416           0 :       return TSI_UNIMPLEMENTED;
     417             :     } else {
     418           0 :       gpr_log(GPR_ERROR, "SSL_write failed with error %s.",
     419             :               ssl_error_string(ssl_write_result));
     420           0 :       return TSI_INTERNAL_ERROR;
     421             :     }
     422             :   }
     423      256823 :   return TSI_OK;
     424             : }
     425             : 
     426             : /* Loads an in-memory PEM certificate chain into the SSL context. */
     427         578 : static tsi_result ssl_ctx_use_certificate_chain(
     428             :     SSL_CTX *context, const unsigned char *pem_cert_chain,
     429             :     size_t pem_cert_chain_size) {
     430         575 :   tsi_result result = TSI_OK;
     431         575 :   X509 *certificate = NULL;
     432             :   BIO *pem;
     433         578 :   GPR_ASSERT(pem_cert_chain_size <= INT_MAX);
     434         578 :   pem = BIO_new_mem_buf((void *)pem_cert_chain, (int)pem_cert_chain_size);
     435         578 :   if (pem == NULL) return TSI_OUT_OF_RESOURCES;
     436             : 
     437             :   do {
     438         578 :     certificate = PEM_read_bio_X509_AUX(pem, NULL, NULL, "");
     439         578 :     if (certificate == NULL) {
     440           0 :       result = TSI_INVALID_ARGUMENT;
     441           0 :       break;
     442             :     }
     443         578 :     if (!SSL_CTX_use_certificate(context, certificate)) {
     444           0 :       result = TSI_INVALID_ARGUMENT;
     445           0 :       break;
     446             :     }
     447             :     while (1) {
     448         578 :       X509 *certificate_authority = PEM_read_bio_X509(pem, NULL, NULL, "");
     449         578 :       if (certificate_authority == NULL) {
     450         578 :         ERR_clear_error();
     451         578 :         break; /* Done reading. */
     452             :       }
     453           0 :       if (!SSL_CTX_add_extra_chain_cert(context, certificate_authority)) {
     454           0 :         X509_free(certificate_authority);
     455           0 :         result = TSI_INVALID_ARGUMENT;
     456           0 :         break;
     457             :       }
     458             :       /* We don't need to free certificate_authority as its ownership has been
     459             :          transfered to the context. That is not the case for certificate though.
     460             :        */
     461           0 :     }
     462             :   } while (0);
     463             : 
     464         578 :   if (certificate != NULL) X509_free(certificate);
     465         578 :   BIO_free(pem);
     466         578 :   return result;
     467             : }
     468             : 
     469             : /* Loads an in-memory PEM private key into the SSL context. */
     470         578 : static tsi_result ssl_ctx_use_private_key(SSL_CTX *context,
     471             :                                           const unsigned char *pem_key,
     472             :                                           size_t pem_key_size) {
     473         575 :   tsi_result result = TSI_OK;
     474         575 :   EVP_PKEY *private_key = NULL;
     475             :   BIO *pem;
     476         578 :   GPR_ASSERT(pem_key_size <= INT_MAX);
     477         578 :   pem = BIO_new_mem_buf((void *)pem_key, (int)pem_key_size);
     478         578 :   if (pem == NULL) return TSI_OUT_OF_RESOURCES;
     479             :   do {
     480         578 :     private_key = PEM_read_bio_PrivateKey(pem, NULL, NULL, "");
     481         578 :     if (private_key == NULL) {
     482           0 :       result = TSI_INVALID_ARGUMENT;
     483           0 :       break;
     484             :     }
     485         578 :     if (!SSL_CTX_use_PrivateKey(context, private_key)) {
     486           0 :       result = TSI_INVALID_ARGUMENT;
     487           0 :       break;
     488             :     }
     489             :   } while (0);
     490         578 :   if (private_key != NULL) EVP_PKEY_free(private_key);
     491         578 :   BIO_free(pem);
     492         578 :   return result;
     493             : }
     494             : 
     495             : /* Loads in-memory PEM verification certs into the SSL context and optionally
     496             :    returns the verification cert names (root_names can be NULL). */
     497         591 : static tsi_result ssl_ctx_load_verification_certs(
     498             :     SSL_CTX *context, const unsigned char *pem_roots, size_t pem_roots_size,
     499             :     STACK_OF(X509_NAME) * *root_names) {
     500         573 :   tsi_result result = TSI_OK;
     501         573 :   size_t num_roots = 0;
     502         573 :   X509 *root = NULL;
     503         573 :   X509_NAME *root_name = NULL;
     504             :   BIO *pem;
     505             :   X509_STORE *root_store;
     506         591 :   GPR_ASSERT(pem_roots_size <= INT_MAX);
     507         591 :   pem = BIO_new_mem_buf((void *)pem_roots, (int)pem_roots_size);
     508         591 :   root_store = SSL_CTX_get_cert_store(context);
     509         591 :   if (root_store == NULL) return TSI_INVALID_ARGUMENT;
     510         591 :   if (pem == NULL) return TSI_OUT_OF_RESOURCES;
     511         591 :   if (root_names != NULL) {
     512           1 :     *root_names = sk_X509_NAME_new_null();
     513           1 :     if (*root_names == NULL) return TSI_OUT_OF_RESOURCES;
     514             :   }
     515             : 
     516             :   while (1) {
     517        1182 :     root = PEM_read_bio_X509_AUX(pem, NULL, NULL, "");
     518        1182 :     if (root == NULL) {
     519         591 :       ERR_clear_error();
     520         591 :       break; /* We're at the end of stream. */
     521             :     }
     522         591 :     if (root_names != NULL) {
     523           1 :       root_name = X509_get_subject_name(root);
     524           1 :       if (root_name == NULL) {
     525           0 :         gpr_log(GPR_ERROR, "Could not get name from root certificate.");
     526           0 :         result = TSI_INVALID_ARGUMENT;
     527           0 :         break;
     528             :       }
     529           1 :       root_name = X509_NAME_dup(root_name);
     530           1 :       if (root_name == NULL) {
     531           0 :         result = TSI_OUT_OF_RESOURCES;
     532           0 :         break;
     533             :       }
     534           1 :       sk_X509_NAME_push(*root_names, root_name);
     535           1 :       root_name = NULL;
     536             :     }
     537         591 :     if (!X509_STORE_add_cert(root_store, root)) {
     538           0 :       gpr_log(GPR_ERROR, "Could not add root certificate to ssl context.");
     539           0 :       result = TSI_INTERNAL_ERROR;
     540           0 :       break;
     541             :     }
     542         591 :     X509_free(root);
     543         591 :     num_roots++;
     544         591 :   }
     545             : 
     546         591 :   if (num_roots == 0) {
     547           0 :     gpr_log(GPR_ERROR, "Could not load any root certificate.");
     548           0 :     result = TSI_INVALID_ARGUMENT;
     549             :   }
     550             : 
     551         591 :   if (result != TSI_OK) {
     552           0 :     if (root != NULL) X509_free(root);
     553           0 :     if (root_names != NULL) {
     554           0 :       sk_X509_NAME_pop_free(*root_names, X509_NAME_free);
     555           0 :       *root_names = NULL;
     556           0 :       if (root_name != NULL) X509_NAME_free(root_name);
     557             :     }
     558             :   }
     559         591 :   BIO_free(pem);
     560         591 :   return result;
     561             : }
     562             : 
     563             : /* Populates the SSL context with a private key and a cert chain, and sets the
     564             :    cipher list and the ephemeral ECDH key. */
     565        1167 : static tsi_result populate_ssl_context(
     566             :     SSL_CTX *context, const unsigned char *pem_private_key,
     567             :     size_t pem_private_key_size, const unsigned char *pem_certificate_chain,
     568             :     size_t pem_certificate_chain_size, const char *cipher_list) {
     569        1146 :   tsi_result result = TSI_OK;
     570        1167 :   if (pem_certificate_chain != NULL) {
     571         578 :     result = ssl_ctx_use_certificate_chain(context, pem_certificate_chain,
     572             :                                            pem_certificate_chain_size);
     573         578 :     if (result != TSI_OK) {
     574           0 :       gpr_log(GPR_ERROR, "Invalid cert chain file.");
     575           0 :       return result;
     576             :     }
     577             :   }
     578        1167 :   if (pem_private_key != NULL) {
     579         578 :     result =
     580             :         ssl_ctx_use_private_key(context, pem_private_key, pem_private_key_size);
     581         578 :     if (result != TSI_OK || !SSL_CTX_check_private_key(context)) {
     582           0 :       gpr_log(GPR_ERROR, "Invalid private key.");
     583           0 :       return result != TSI_OK ? result : TSI_INVALID_ARGUMENT;
     584             :     }
     585             :   }
     586        1167 :   if ((cipher_list != NULL) && !SSL_CTX_set_cipher_list(context, cipher_list)) {
     587           0 :     gpr_log(GPR_ERROR, "Invalid cipher list: %s.", cipher_list);
     588           0 :     return TSI_INVALID_ARGUMENT;
     589             :   }
     590             :   {
     591        1167 :     EC_KEY *ecdh = EC_KEY_new_by_curve_name(NID_X9_62_prime256v1);
     592        1167 :     if (!SSL_CTX_set_tmp_ecdh(context, ecdh)) {
     593           0 :       gpr_log(GPR_ERROR, "Could not set ephemeral ECDH key.");
     594           0 :       EC_KEY_free(ecdh);
     595           0 :       return TSI_INTERNAL_ERROR;
     596             :     }
     597        1167 :     SSL_CTX_set_options(context, SSL_OP_SINGLE_ECDH_USE);
     598        1167 :     EC_KEY_free(ecdh);
     599             :   }
     600        1167 :   return TSI_OK;
     601             : }
     602             : 
     603             : /* Extracts the CN and the SANs from an X509 cert as a peer object. */
     604         577 : static tsi_result extract_x509_subject_names_from_pem_cert(
     605             :     const unsigned char *pem_cert, size_t pem_cert_size, tsi_peer *peer) {
     606         574 :   tsi_result result = TSI_OK;
     607         574 :   X509 *cert = NULL;
     608             :   BIO *pem;
     609         577 :   GPR_ASSERT(pem_cert_size <= INT_MAX);
     610         577 :   pem = BIO_new_mem_buf((void *)pem_cert, (int)pem_cert_size);
     611         577 :   if (pem == NULL) return TSI_OUT_OF_RESOURCES;
     612             : 
     613         577 :   cert = PEM_read_bio_X509(pem, NULL, NULL, "");
     614         577 :   if (cert == NULL) {
     615           0 :     gpr_log(GPR_ERROR, "Invalid certificate");
     616           0 :     result = TSI_INVALID_ARGUMENT;
     617             :   } else {
     618         577 :     result = peer_from_x509(cert, 0, peer);
     619             :   }
     620         577 :   if (cert != NULL) X509_free(cert);
     621         577 :   BIO_free(pem);
     622         577 :   return result;
     623             : }
     624             : 
     625             : /* Builds the alpn protocol name list according to rfc 7301. */
     626        1165 : static tsi_result build_alpn_protocol_name_list(
     627             :     const unsigned char **alpn_protocols,
     628             :     const unsigned char *alpn_protocols_lengths, uint16_t num_alpn_protocols,
     629             :     unsigned char **protocol_name_list, size_t *protocol_name_list_length) {
     630             :   uint16_t i;
     631             :   unsigned char *current;
     632        1165 :   *protocol_name_list = NULL;
     633        1165 :   *protocol_name_list_length = 0;
     634        1165 :   if (num_alpn_protocols == 0) return TSI_INVALID_ARGUMENT;
     635        2309 :   for (i = 0; i < num_alpn_protocols; i++) {
     636        1165 :     if (alpn_protocols_lengths[i] == 0) {
     637           0 :       gpr_log(GPR_ERROR, "Invalid 0-length protocol name.");
     638           0 :       return TSI_INVALID_ARGUMENT;
     639             :     }
     640        1165 :     *protocol_name_list_length += (size_t)alpn_protocols_lengths[i] + 1;
     641             :   }
     642        1165 :   *protocol_name_list = malloc(*protocol_name_list_length);
     643        1165 :   if (*protocol_name_list == NULL) return TSI_OUT_OF_RESOURCES;
     644        1144 :   current = *protocol_name_list;
     645        2309 :   for (i = 0; i < num_alpn_protocols; i++) {
     646        1165 :     *(current++) = alpn_protocols_lengths[i];
     647        1165 :     memcpy(current, alpn_protocols[i], alpn_protocols_lengths[i]);
     648        1165 :     current += alpn_protocols_lengths[i];
     649             :   }
     650             :   /* Safety check. */
     651        2330 :   if ((current < *protocol_name_list) ||
     652        1165 :       ((gpr_uintptr)(current - *protocol_name_list) !=
     653        1165 :        *protocol_name_list_length)) {
     654           0 :     return TSI_INTERNAL_ERROR;
     655             :   }
     656        1165 :   return TSI_OK;
     657             : }
     658             : 
     659             : /* --- tsi_frame_protector methods implementation. ---*/
     660             : 
     661     2510597 : static tsi_result ssl_protector_protect(tsi_frame_protector *self,
     662             :                                         const unsigned char *unprotected_bytes,
     663             :                                         size_t *unprotected_bytes_size,
     664             :                                         unsigned char *protected_output_frames,
     665             :                                         size_t *protected_output_frames_size) {
     666     2508774 :   tsi_ssl_frame_protector *impl = (tsi_ssl_frame_protector *)self;
     667             :   int read_from_ssl;
     668             :   size_t available;
     669     2508774 :   tsi_result result = TSI_OK;
     670             : 
     671             :   /* First see if we have some pending data in the SSL BIO. */
     672     2510597 :   int pending_in_ssl = (int)BIO_pending(impl->from_ssl);
     673     2510591 :   if (pending_in_ssl > 0) {
     674        2356 :     *unprotected_bytes_size = 0;
     675        2356 :     GPR_ASSERT(*protected_output_frames_size <= INT_MAX);
     676        2356 :     read_from_ssl = BIO_read(impl->from_ssl, protected_output_frames,
     677        2140 :                              (int)*protected_output_frames_size);
     678        2356 :     if (read_from_ssl < 0) {
     679           0 :       gpr_log(GPR_ERROR,
     680             :               "Could not read from BIO even though some data is pending");
     681           0 :       return TSI_INTERNAL_ERROR;
     682             :     }
     683        2356 :     *protected_output_frames_size = (size_t)read_from_ssl;
     684        2356 :     return TSI_OK;
     685             :   }
     686             : 
     687             :   /* Now see if we can send a complete frame. */
     688     2508235 :   available = impl->buffer_size - impl->buffer_offset;
     689     2508235 :   if (available > *unprotected_bytes_size) {
     690             :     /* If we cannot, just copy the data in our internal buffer. */
     691     2507285 :     memcpy(impl->buffer + impl->buffer_offset, unprotected_bytes,
     692             :            *unprotected_bytes_size);
     693     2507285 :     impl->buffer_offset += *unprotected_bytes_size;
     694     2507285 :     *protected_output_frames_size = 0;
     695     2507285 :     return TSI_OK;
     696             :   }
     697             : 
     698             :   /* If we can, prepare the buffer, send it to SSL_write and read. */
     699         950 :   memcpy(impl->buffer + impl->buffer_offset, unprotected_bytes, available);
     700         950 :   result = do_ssl_write(impl->ssl, impl->buffer, impl->buffer_size);
     701         950 :   if (result != TSI_OK) return result;
     702             : 
     703         950 :   GPR_ASSERT(*protected_output_frames_size <= INT_MAX);
     704         950 :   read_from_ssl = BIO_read(impl->from_ssl, protected_output_frames,
     705         848 :                            (int)*protected_output_frames_size);
     706         950 :   if (read_from_ssl < 0) {
     707           0 :     gpr_log(GPR_ERROR, "Could not read from BIO after SSL_write.");
     708           0 :     return TSI_INTERNAL_ERROR;
     709             :   }
     710         950 :   *protected_output_frames_size = (size_t)read_from_ssl;
     711         950 :   *unprotected_bytes_size = available;
     712         950 :   impl->buffer_offset = 0;
     713         950 :   return TSI_OK;
     714             : }
     715             : 
     716      259710 : static tsi_result ssl_protector_protect_flush(
     717             :     tsi_frame_protector *self, unsigned char *protected_output_frames,
     718             :     size_t *protected_output_frames_size, size_t *still_pending_size) {
     719      259472 :   tsi_result result = TSI_OK;
     720      259472 :   tsi_ssl_frame_protector *impl = (tsi_ssl_frame_protector *)self;
     721      259472 :   int read_from_ssl = 0;
     722             :   int pending;
     723             : 
     724      259710 :   if (impl->buffer_offset != 0) {
     725      256190 :     result = do_ssl_write(impl->ssl, impl->buffer, impl->buffer_offset);
     726      256191 :     if (result != TSI_OK) return result;
     727      256191 :     impl->buffer_offset = 0;
     728             :   }
     729             : 
     730      259711 :   pending = (int)BIO_pending(impl->from_ssl);
     731      259711 :   GPR_ASSERT(pending >= 0);
     732      259711 :   *still_pending_size = (size_t)pending;
     733      259711 :   if (*still_pending_size == 0) return TSI_OK;
     734             : 
     735      259711 :   GPR_ASSERT(*protected_output_frames_size <= INT_MAX);
     736      259711 :   read_from_ssl = BIO_read(impl->from_ssl, protected_output_frames,
     737      259473 :                            (int)*protected_output_frames_size);
     738      259711 :   if (read_from_ssl <= 0) {
     739           0 :     gpr_log(GPR_ERROR, "Could not read from BIO after SSL_write.");
     740           0 :     return TSI_INTERNAL_ERROR;
     741             :   }
     742      259711 :   *protected_output_frames_size = (size_t)read_from_ssl;
     743      259711 :   pending = (int)BIO_pending(impl->from_ssl);
     744      259711 :   GPR_ASSERT(pending >= 0);
     745      259711 :   *still_pending_size = (size_t)pending;
     746      259711 :   return TSI_OK;
     747             : }
     748             : 
     749      519396 : static tsi_result ssl_protector_unprotect(
     750             :     tsi_frame_protector *self, const unsigned char *protected_frames_bytes,
     751             :     size_t *protected_frames_bytes_size, unsigned char *unprotected_bytes,
     752             :     size_t *unprotected_bytes_size) {
     753      518502 :   tsi_result result = TSI_OK;
     754      518502 :   int written_into_ssl = 0;
     755      519396 :   size_t output_bytes_size = *unprotected_bytes_size;
     756      518502 :   size_t output_bytes_offset = 0;
     757      518502 :   tsi_ssl_frame_protector *impl = (tsi_ssl_frame_protector *)self;
     758             : 
     759             :   /* First, try to read remaining data from ssl. */
     760      519396 :   result = do_ssl_read(impl->ssl, unprotected_bytes, unprotected_bytes_size);
     761      519396 :   if (result != TSI_OK) return result;
     762      519396 :   if (*unprotected_bytes_size == output_bytes_size) {
     763             :     /* We have read everything we could and cannot process any more input. */
     764         920 :     *protected_frames_bytes_size = 0;
     765         920 :     return TSI_OK;
     766             :   }
     767      517679 :   output_bytes_offset = *unprotected_bytes_size;
     768      518476 :   unprotected_bytes += output_bytes_offset;
     769      518476 :   *unprotected_bytes_size = output_bytes_size - output_bytes_offset;
     770             : 
     771             :   /* Then, try to write some data to ssl. */
     772      518476 :   GPR_ASSERT(*protected_frames_bytes_size <= INT_MAX);
     773      518476 :   written_into_ssl = BIO_write(impl->into_ssl, protected_frames_bytes,
     774      517679 :                                (int)*protected_frames_bytes_size);
     775      518475 :   if (written_into_ssl < 0) {
     776           0 :     gpr_log(GPR_ERROR, "Sending protected frame to ssl failed with %d",
     777             :             written_into_ssl);
     778           0 :     return TSI_INTERNAL_ERROR;
     779             :   }
     780      518475 :   *protected_frames_bytes_size = (size_t)written_into_ssl;
     781             : 
     782             :   /* Now try to read some data again. */
     783      518475 :   result = do_ssl_read(impl->ssl, unprotected_bytes, unprotected_bytes_size);
     784      518473 :   if (result == TSI_OK) {
     785             :     /* Don't forget to output the total number of bytes read. */
     786      518473 :     *unprotected_bytes_size += output_bytes_offset;
     787             :   }
     788      518473 :   return result;
     789             : }
     790             : 
     791         963 : static void ssl_protector_destroy(tsi_frame_protector *self) {
     792         929 :   tsi_ssl_frame_protector *impl = (tsi_ssl_frame_protector *)self;
     793         963 :   if (impl->buffer != NULL) free(impl->buffer);
     794         963 :   if (impl->ssl != NULL) SSL_free(impl->ssl);
     795         963 :   free(self);
     796         963 : }
     797             : 
     798             : static const tsi_frame_protector_vtable frame_protector_vtable = {
     799             :     ssl_protector_protect, ssl_protector_protect_flush, ssl_protector_unprotect,
     800             :     ssl_protector_destroy,
     801             : };
     802             : 
     803             : /* --- tsi_handshaker methods implementation. ---*/
     804             : 
     805        2917 : static tsi_result ssl_handshaker_get_bytes_to_send_to_peer(tsi_handshaker *self,
     806             :                                                            unsigned char *bytes,
     807             :                                                            size_t *bytes_size) {
     808        2815 :   tsi_ssl_handshaker *impl = (tsi_ssl_handshaker *)self;
     809        2815 :   int bytes_read_from_ssl = 0;
     810        5732 :   if (bytes == NULL || bytes_size == NULL || *bytes_size == 0 ||
     811        2815 :       *bytes_size > INT_MAX) {
     812           0 :     return TSI_INVALID_ARGUMENT;
     813             :   }
     814        2917 :   GPR_ASSERT(*bytes_size <= INT_MAX);
     815        2917 :   bytes_read_from_ssl = BIO_read(impl->from_ssl, bytes, (int)*bytes_size);
     816        2917 :   if (bytes_read_from_ssl < 0) {
     817         488 :     *bytes_size = 0;
     818         488 :     if (!BIO_should_retry(impl->from_ssl)) {
     819           0 :       impl->result = TSI_INTERNAL_ERROR;
     820           0 :       return impl->result;
     821             :     } else {
     822         471 :       return TSI_OK;
     823             :     }
     824             :   }
     825        2429 :   *bytes_size = (size_t)bytes_read_from_ssl;
     826        2429 :   return BIO_pending(impl->from_ssl) == 0 ? TSI_OK : TSI_INCOMPLETE_DATA;
     827             : }
     828             : 
     829        9665 : static tsi_result ssl_handshaker_get_result(tsi_handshaker *self) {
     830        9325 :   tsi_ssl_handshaker *impl = (tsi_ssl_handshaker *)self;
     831       16441 :   if ((impl->result == TSI_HANDSHAKE_IN_PROGRESS) &&
     832        6776 :       SSL_is_init_finished(impl->ssl)) {
     833         963 :     impl->result = TSI_OK;
     834             :   }
     835        9665 :   return impl->result;
     836             : }
     837             : 
     838        1932 : static tsi_result ssl_handshaker_process_bytes_from_peer(
     839             :     tsi_handshaker *self, const unsigned char *bytes, size_t *bytes_size) {
     840        1864 :   tsi_ssl_handshaker *impl = (tsi_ssl_handshaker *)self;
     841        1864 :   int bytes_written_into_ssl_size = 0;
     842        1932 :   if (bytes == NULL || bytes_size == 0 || *bytes_size > INT_MAX) {
     843           0 :     return TSI_INVALID_ARGUMENT;
     844             :   }
     845        1932 :   GPR_ASSERT(*bytes_size <= INT_MAX);
     846        1932 :   bytes_written_into_ssl_size =
     847        1932 :       BIO_write(impl->into_ssl, bytes, (int)*bytes_size);
     848        1932 :   if (bytes_written_into_ssl_size < 0) {
     849           0 :     gpr_log(GPR_ERROR, "Could not write to memory BIO.");
     850           0 :     impl->result = TSI_INTERNAL_ERROR;
     851           0 :     return impl->result;
     852             :   }
     853        1932 :   *bytes_size = (size_t)bytes_written_into_ssl_size;
     854             : 
     855        1932 :   if (!tsi_handshaker_is_in_progress(self)) {
     856           0 :     impl->result = TSI_OK;
     857           0 :     return impl->result;
     858             :   } else {
     859             :     /* Get ready to get some bytes from SSL. */
     860        1932 :     int ssl_result = SSL_do_handshake(impl->ssl);
     861        1932 :     ssl_result = SSL_get_error(impl->ssl, ssl_result);
     862        1932 :     switch (ssl_result) {
     863             :       case SSL_ERROR_WANT_READ:
     864         969 :         if (BIO_pending(impl->from_ssl) == 0) {
     865             :           /* We need more data. */
     866           0 :           return TSI_INCOMPLETE_DATA;
     867             :         } else {
     868         969 :           return TSI_OK;
     869             :         }
     870             :       case SSL_ERROR_NONE:
     871         929 :         return TSI_OK;
     872             :       default: {
     873             :         char err_str[256];
     874           0 :         ERR_error_string_n(ERR_get_error(), err_str, sizeof(err_str));
     875           0 :         gpr_log(GPR_ERROR, "Handshake failed with fatal error %s: %s.",
     876             :                 ssl_error_string(ssl_result), err_str);
     877           0 :         impl->result = TSI_PROTOCOL_FAILURE;
     878           0 :         return impl->result;
     879             :       }
     880             :     }
     881             :   }
     882             : }
     883             : 
     884         963 : static tsi_result ssl_handshaker_extract_peer(tsi_handshaker *self,
     885             :                                               tsi_peer *peer) {
     886         929 :   tsi_result result = TSI_OK;
     887         963 :   const unsigned char *alpn_selected = NULL;
     888             :   unsigned int alpn_selected_len;
     889         929 :   tsi_ssl_handshaker *impl = (tsi_ssl_handshaker *)self;
     890         963 :   X509 *peer_cert = SSL_get_peer_certificate(impl->ssl);
     891         963 :   if (peer_cert != NULL) {
     892         481 :     result = peer_from_x509(peer_cert, 1, peer);
     893         481 :     X509_free(peer_cert);
     894         481 :     if (result != TSI_OK) return result;
     895             :   }
     896             : #if TSI_OPENSSL_ALPN_SUPPORT
     897         929 :   SSL_get0_alpn_selected(impl->ssl, &alpn_selected, &alpn_selected_len);
     898             : #endif /* TSI_OPENSSL_ALPN_SUPPORT */
     899         963 :   if (alpn_selected == NULL) {
     900             :     /* Try npn. */
     901          36 :     SSL_get0_next_proto_negotiated(impl->ssl, &alpn_selected,
     902             :                                    &alpn_selected_len);
     903             :   }
     904         963 :   if (alpn_selected != NULL) {
     905             :     size_t i;
     906         961 :     tsi_peer_property *new_properties =
     907         961 :         calloc(1, sizeof(tsi_peer_property) * (peer->property_count + 1));
     908         961 :     if (new_properties == NULL) return TSI_OUT_OF_RESOURCES;
     909        3322 :     for (i = 0; i < peer->property_count; i++) {
     910        2395 :       new_properties[i] = peer->properties[i];
     911             :     }
     912         961 :     result = tsi_construct_string_peer_property(
     913             :         TSI_SSL_ALPN_SELECTED_PROTOCOL, (const char *)alpn_selected,
     914         961 :         alpn_selected_len, &new_properties[peer->property_count]);
     915         961 :     if (result != TSI_OK) {
     916           0 :       free(new_properties);
     917           0 :       return result;
     918             :     }
     919         961 :     if (peer->properties != NULL) free(peer->properties);
     920         961 :     peer->property_count++;
     921         961 :     peer->properties = new_properties;
     922             :   }
     923         963 :   return result;
     924             : }
     925             : 
     926         963 : static tsi_result ssl_handshaker_create_frame_protector(
     927             :     tsi_handshaker *self, size_t *max_output_protected_frame_size,
     928             :     tsi_frame_protector **protector) {
     929         929 :   size_t actual_max_output_protected_frame_size =
     930             :       TSI_SSL_MAX_PROTECTED_FRAME_SIZE_UPPER_BOUND;
     931         929 :   tsi_ssl_handshaker *impl = (tsi_ssl_handshaker *)self;
     932         963 :   tsi_ssl_frame_protector *protector_impl =
     933             :       calloc(1, sizeof(tsi_ssl_frame_protector));
     934         963 :   if (protector_impl == NULL) {
     935           0 :     return TSI_OUT_OF_RESOURCES;
     936             :   }
     937             : 
     938         963 :   if (max_output_protected_frame_size != NULL) {
     939           0 :     if (*max_output_protected_frame_size >
     940             :         TSI_SSL_MAX_PROTECTED_FRAME_SIZE_UPPER_BOUND) {
     941           0 :       *max_output_protected_frame_size =
     942             :           TSI_SSL_MAX_PROTECTED_FRAME_SIZE_UPPER_BOUND;
     943           0 :     } else if (*max_output_protected_frame_size <
     944             :                TSI_SSL_MAX_PROTECTED_FRAME_SIZE_LOWER_BOUND) {
     945           0 :       *max_output_protected_frame_size =
     946             :           TSI_SSL_MAX_PROTECTED_FRAME_SIZE_LOWER_BOUND;
     947             :     }
     948           0 :     actual_max_output_protected_frame_size = *max_output_protected_frame_size;
     949             :   }
     950         963 :   protector_impl->buffer_size =
     951         963 :       actual_max_output_protected_frame_size - TSI_SSL_MAX_PROTECTION_OVERHEAD;
     952         963 :   protector_impl->buffer = malloc(protector_impl->buffer_size);
     953         963 :   if (protector_impl->buffer == NULL) {
     954           0 :     gpr_log(GPR_ERROR,
     955             :             "Could not allocated buffer for tsi_ssl_frame_protector.");
     956           0 :     free(protector_impl);
     957           0 :     return TSI_INTERNAL_ERROR;
     958             :   }
     959             : 
     960             :   /* Transfer ownership of ssl to the frame protector. It is OK as the caller
     961             :    * cannot call anything else but destroy on the handshaker after this call. */
     962         963 :   protector_impl->ssl = impl->ssl;
     963         963 :   impl->ssl = NULL;
     964         963 :   protector_impl->into_ssl = impl->into_ssl;
     965         963 :   protector_impl->from_ssl = impl->from_ssl;
     966             : 
     967         963 :   protector_impl->base.vtable = &frame_protector_vtable;
     968         963 :   *protector = &protector_impl->base;
     969         963 :   return TSI_OK;
     970             : }
     971             : 
     972         974 : static void ssl_handshaker_destroy(tsi_handshaker *self) {
     973         940 :   tsi_ssl_handshaker *impl = (tsi_ssl_handshaker *)self;
     974         974 :   SSL_free(impl->ssl); /* The BIO objects are owned by ssl */
     975         974 :   free(impl);
     976         974 : }
     977             : 
     978             : static const tsi_handshaker_vtable handshaker_vtable = {
     979             :     ssl_handshaker_get_bytes_to_send_to_peer,
     980             :     ssl_handshaker_process_bytes_from_peer, ssl_handshaker_get_result,
     981             :     ssl_handshaker_extract_peer, ssl_handshaker_create_frame_protector,
     982             :     ssl_handshaker_destroy,
     983             : };
     984             : 
     985             : /* --- tsi_ssl_handshaker_factory common methods. --- */
     986             : 
     987         974 : tsi_result tsi_ssl_handshaker_factory_create_handshaker(
     988             :     tsi_ssl_handshaker_factory *self, const char *server_name_indication,
     989             :     tsi_handshaker **handshaker) {
     990         974 :   if (self == NULL || handshaker == NULL) return TSI_INVALID_ARGUMENT;
     991         974 :   return self->create_handshaker(self, server_name_indication, handshaker);
     992             : }
     993             : 
     994        1145 : void tsi_ssl_handshaker_factory_destroy(tsi_ssl_handshaker_factory *self) {
     995        2290 :   if (self == NULL) return;
     996        1145 :   self->destroy(self);
     997             : }
     998             : 
     999         973 : static tsi_result create_tsi_ssl_handshaker(SSL_CTX *ctx, int is_client,
    1000             :                                             const char *server_name_indication,
    1001             :                                             tsi_handshaker **handshaker) {
    1002         973 :   SSL *ssl = SSL_new(ctx);
    1003         940 :   BIO *into_ssl = NULL;
    1004         940 :   BIO *from_ssl = NULL;
    1005         940 :   tsi_ssl_handshaker *impl = NULL;
    1006         974 :   *handshaker = NULL;
    1007         974 :   if (ctx == NULL) {
    1008           0 :     gpr_log(GPR_ERROR, "SSL Context is null. Should never happen.");
    1009           0 :     return TSI_INTERNAL_ERROR;
    1010             :   }
    1011         974 :   if (ssl == NULL) {
    1012           0 :     return TSI_OUT_OF_RESOURCES;
    1013             :   }
    1014         974 :   SSL_set_info_callback(ssl, ssl_info_callback);
    1015             : 
    1016         974 :   into_ssl = BIO_new(BIO_s_mem());
    1017         974 :   from_ssl = BIO_new(BIO_s_mem());
    1018         974 :   if (into_ssl == NULL || from_ssl == NULL) {
    1019           0 :     gpr_log(GPR_ERROR, "BIO_new failed.");
    1020           0 :     SSL_free(ssl);
    1021           0 :     if (into_ssl != NULL) BIO_free(into_ssl);
    1022           0 :     if (from_ssl != NULL) BIO_free(into_ssl);
    1023           0 :     return TSI_OUT_OF_RESOURCES;
    1024             :   }
    1025         974 :   SSL_set_bio(ssl, into_ssl, from_ssl);
    1026         974 :   if (is_client) {
    1027             :     int ssl_result;
    1028         486 :     SSL_set_connect_state(ssl);
    1029         486 :     if (server_name_indication != NULL) {
    1030         486 :       if (!SSL_set_tlsext_host_name(ssl, server_name_indication)) {
    1031           0 :         gpr_log(GPR_ERROR, "Invalid server name indication %s.",
    1032             :                 server_name_indication);
    1033           0 :         SSL_free(ssl);
    1034           0 :         return TSI_INTERNAL_ERROR;
    1035             :       }
    1036             :     }
    1037         486 :     ssl_result = SSL_do_handshake(ssl);
    1038         486 :     ssl_result = SSL_get_error(ssl, ssl_result);
    1039         486 :     if (ssl_result != SSL_ERROR_WANT_READ) {
    1040           0 :       gpr_log(GPR_ERROR,
    1041             :               "Unexpected error received from first SSL_do_handshake call: %s",
    1042             :               ssl_error_string(ssl_result));
    1043           0 :       SSL_free(ssl);
    1044           0 :       return TSI_INTERNAL_ERROR;
    1045             :     }
    1046             :   } else {
    1047         488 :     SSL_set_accept_state(ssl);
    1048             :   }
    1049             : 
    1050         974 :   impl = calloc(1, sizeof(tsi_ssl_handshaker));
    1051         974 :   if (impl == NULL) {
    1052           0 :     SSL_free(ssl);
    1053           0 :     return TSI_OUT_OF_RESOURCES;
    1054             :   }
    1055         974 :   impl->ssl = ssl;
    1056         974 :   impl->into_ssl = into_ssl;
    1057         974 :   impl->from_ssl = from_ssl;
    1058         974 :   impl->result = TSI_HANDSHAKE_IN_PROGRESS;
    1059         974 :   impl->base.vtable = &handshaker_vtable;
    1060         974 :   *handshaker = &impl->base;
    1061         974 :   return TSI_OK;
    1062             : }
    1063             : 
    1064         484 : static int select_protocol_list(const unsigned char **out,
    1065             :                                 unsigned char *outlen,
    1066             :                                 const unsigned char *client_list,
    1067             :                                 size_t client_list_len,
    1068             :                                 const unsigned char *server_list,
    1069             :                                 size_t server_list_len) {
    1070         467 :   const unsigned char *client_current = client_list;
    1071         968 :   while ((unsigned int)(client_current - client_list) < client_list_len) {
    1072         484 :     unsigned char client_current_len = *(client_current++);
    1073         467 :     const unsigned char *server_current = server_list;
    1074        1452 :     while ((server_current >= server_list) &&
    1075         484 :            (gpr_uintptr)(server_current - server_list) < server_list_len) {
    1076         484 :       unsigned char server_current_len = *(server_current++);
    1077         968 :       if ((client_current_len == server_current_len) &&
    1078         484 :           !memcmp(client_current, server_current, server_current_len)) {
    1079         484 :         *out = server_current;
    1080         484 :         *outlen = server_current_len;
    1081         484 :         return SSL_TLSEXT_ERR_OK;
    1082             :       }
    1083           0 :       server_current += server_current_len;
    1084             :     }
    1085           0 :     client_current += client_current_len;
    1086             :   }
    1087           0 :   return SSL_TLSEXT_ERR_NOACK;
    1088             : }
    1089             : 
    1090             : /* --- tsi_ssl__client_handshaker_factory methods implementation. --- */
    1091             : 
    1092         486 : static tsi_result ssl_client_handshaker_factory_create_handshaker(
    1093             :     tsi_ssl_handshaker_factory *self, const char *server_name_indication,
    1094             :     tsi_handshaker **handshaker) {
    1095         469 :   tsi_ssl_client_handshaker_factory *impl =
    1096             :       (tsi_ssl_client_handshaker_factory *)self;
    1097         486 :   return create_tsi_ssl_handshaker(impl->ssl_context, 1, server_name_indication,
    1098             :                                    handshaker);
    1099             : }
    1100             : 
    1101         569 : static void ssl_client_handshaker_factory_destroy(
    1102             :     tsi_ssl_handshaker_factory *self) {
    1103         569 :   tsi_ssl_client_handshaker_factory *impl =
    1104             :       (tsi_ssl_client_handshaker_factory *)self;
    1105         569 :   if (impl->ssl_context != NULL) SSL_CTX_free(impl->ssl_context);
    1106         569 :   if (impl->alpn_protocol_list != NULL) free(impl->alpn_protocol_list);
    1107         569 :   free(impl);
    1108         569 : }
    1109             : 
    1110          17 : static int client_handshaker_factory_npn_callback(SSL *ssl, unsigned char **out,
    1111             :                                                   unsigned char *outlen,
    1112             :                                                   const unsigned char *in,
    1113             :                                                   unsigned int inlen,
    1114             :                                                   void *arg) {
    1115           0 :   tsi_ssl_client_handshaker_factory *factory =
    1116             :       (tsi_ssl_client_handshaker_factory *)arg;
    1117          34 :   return select_protocol_list((const unsigned char **)out, outlen,
    1118          17 :                               factory->alpn_protocol_list,
    1119             :                               factory->alpn_protocol_list_length, in, inlen);
    1120             : }
    1121             : 
    1122             : /* --- tsi_ssl_server_handshaker_factory methods implementation. --- */
    1123             : 
    1124         488 : static tsi_result ssl_server_handshaker_factory_create_handshaker(
    1125             :     tsi_ssl_handshaker_factory *self, const char *server_name_indication,
    1126             :     tsi_handshaker **handshaker) {
    1127         471 :   tsi_ssl_server_handshaker_factory *impl =
    1128             :       (tsi_ssl_server_handshaker_factory *)self;
    1129         488 :   if (impl->ssl_context_count == 0 || server_name_indication != NULL) {
    1130           0 :     return TSI_INVALID_ARGUMENT;
    1131             :   }
    1132             :   /* Create the handshaker with the first context. We will switch if needed
    1133             :      because of SNI in ssl_server_handshaker_factory_servername_callback.  */
    1134         488 :   return create_tsi_ssl_handshaker(impl->ssl_contexts[0], 0, NULL, handshaker);
    1135             : }
    1136             : 
    1137         576 : static void ssl_server_handshaker_factory_destroy(
    1138             :     tsi_ssl_handshaker_factory *self) {
    1139         574 :   tsi_ssl_server_handshaker_factory *impl =
    1140             :       (tsi_ssl_server_handshaker_factory *)self;
    1141             :   size_t i;
    1142        1152 :   for (i = 0; i < impl->ssl_context_count; i++) {
    1143         576 :     if (impl->ssl_contexts[i] != NULL) {
    1144         576 :       SSL_CTX_free(impl->ssl_contexts[i]);
    1145         576 :       tsi_peer_destruct(&impl->ssl_context_x509_subject_names[i]);
    1146             :     }
    1147             :   }
    1148         576 :   if (impl->ssl_contexts != NULL) free(impl->ssl_contexts);
    1149         576 :   if (impl->ssl_context_x509_subject_names != NULL) {
    1150         576 :     free(impl->ssl_context_x509_subject_names);
    1151             :   }
    1152         576 :   if (impl->alpn_protocol_list != NULL) free(impl->alpn_protocol_list);
    1153         576 :   free(impl);
    1154         576 : }
    1155             : 
    1156      127172 : static int does_entry_match_name(const char *entry, size_t entry_length,
    1157             :                                  const char *name) {
    1158             :   const char *dot;
    1159      127115 :   const char *name_subdomain = NULL;
    1160      127172 :   size_t name_length = strlen(name);
    1161             :   size_t name_subdomain_length;
    1162      127172 :   if (entry_length == 0) return 0;
    1163             : 
    1164             :   /* Take care of '.' terminations. */
    1165      127171 :   if (name[name_length - 1] == '.') {
    1166          10 :     name_length--;
    1167             :   }
    1168      127171 :   if (entry[entry_length - 1] == '.') {
    1169          11 :     entry_length--;
    1170          11 :     if (entry_length == 0) return 0;
    1171             :   }
    1172             : 
    1173      127185 :   if ((name_length == entry_length) &&
    1174          15 :       strncmp(name, entry, entry_length) == 0) {
    1175          10 :     return 1; /* Perfect match. */
    1176             :   }
    1177      127160 :   if (entry[0] != '*') return 0;
    1178             : 
    1179             :   /* Wildchar subdomain matching. */
    1180      127136 :   if (entry_length < 3 || entry[1] != '.') { /* At least *.x */
    1181           6 :     gpr_log(GPR_ERROR, "Invalid wildchar entry.");
    1182           6 :     return 0;
    1183             :   }
    1184      127130 :   name_subdomain = strchr(name, '.');
    1185      127130 :   if (name_subdomain == NULL) return 0;
    1186      127130 :   name_subdomain_length = strlen(name_subdomain);
    1187      127130 :   if (name_subdomain_length < 2) return 0;
    1188      127130 :   name_subdomain++; /* Starts after the dot. */
    1189      127130 :   name_subdomain_length--;
    1190      127130 :   entry += 2; /* Remove *. */
    1191      127130 :   entry_length -= 2;
    1192      127130 :   dot = strchr(name_subdomain, '.');
    1193      127130 :   if ((dot == NULL) || (dot == &name_subdomain[name_subdomain_length - 1])) {
    1194          10 :     gpr_log(GPR_ERROR, "Invalid toplevel subdomain: %s", name_subdomain);
    1195          10 :     return 0;
    1196             :   }
    1197      127120 :   if (name_subdomain[name_subdomain_length - 1] == '.') {
    1198           2 :     name_subdomain_length--;
    1199             :   }
    1200      254227 :   return ((entry_length > 0) && (name_subdomain_length == entry_length) &&
    1201      127107 :           strncmp(entry, name_subdomain, entry_length) == 0);
    1202             : }
    1203             : 
    1204         484 : static int ssl_server_handshaker_factory_servername_callback(SSL *ssl, int *ap,
    1205             :                                                              void *arg) {
    1206         467 :   tsi_ssl_server_handshaker_factory *impl =
    1207             :       (tsi_ssl_server_handshaker_factory *)arg;
    1208         467 :   size_t i = 0;
    1209         484 :   const char *servername = SSL_get_servername(ssl, TLSEXT_NAMETYPE_host_name);
    1210         484 :   if (servername == NULL || strlen(servername) == 0) {
    1211           0 :     return SSL_TLSEXT_ERR_NOACK;
    1212             :   }
    1213             : 
    1214         467 :   for (i = 0; i < impl->ssl_context_count; i++) {
    1215         484 :     if (tsi_ssl_peer_matches_name(&impl->ssl_context_x509_subject_names[i],
    1216             :                                   servername)) {
    1217         484 :       SSL_set_SSL_CTX(ssl, impl->ssl_contexts[i]);
    1218         484 :       return SSL_TLSEXT_ERR_OK;
    1219             :     }
    1220             :   }
    1221           0 :   gpr_log(GPR_ERROR, "No match found for server name: %s.", servername);
    1222           0 :   return SSL_TLSEXT_ERR_ALERT_WARNING;
    1223             : }
    1224             : 
    1225             : #if TSI_OPENSSL_ALPN_SUPPORT
    1226         467 : static int server_handshaker_factory_alpn_callback(
    1227             :     SSL *ssl, const unsigned char **out, unsigned char *outlen,
    1228             :     const unsigned char *in, unsigned int inlen, void *arg) {
    1229         467 :   tsi_ssl_server_handshaker_factory *factory =
    1230             :       (tsi_ssl_server_handshaker_factory *)arg;
    1231         934 :   return select_protocol_list(out, outlen, in, inlen,
    1232         467 :                               factory->alpn_protocol_list,
    1233             :                               factory->alpn_protocol_list_length);
    1234             : }
    1235             : #endif /* TSI_OPENSSL_ALPN_SUPPORT */
    1236             : 
    1237          17 : static int server_handshaker_factory_npn_advertised_callback(
    1238             :     SSL *ssl, const unsigned char **out, unsigned int *outlen, void *arg) {
    1239           0 :   tsi_ssl_server_handshaker_factory *factory =
    1240             :       (tsi_ssl_server_handshaker_factory *)arg;
    1241          17 :   *out = factory->alpn_protocol_list;
    1242          17 :   GPR_ASSERT(factory->alpn_protocol_list_length <= UINT_MAX);
    1243          17 :   *outlen = (unsigned int)factory->alpn_protocol_list_length;
    1244          17 :   return SSL_TLSEXT_ERR_OK;
    1245             : }
    1246             : 
    1247             : /* --- tsi_ssl_handshaker_factory constructors. --- */
    1248             : 
    1249         590 : tsi_result tsi_create_ssl_client_handshaker_factory(
    1250             :     const unsigned char *pem_private_key, size_t pem_private_key_size,
    1251             :     const unsigned char *pem_cert_chain, size_t pem_cert_chain_size,
    1252             :     const unsigned char *pem_root_certs, size_t pem_root_certs_size,
    1253             :     const char *cipher_list, const unsigned char **alpn_protocols,
    1254             :     const unsigned char *alpn_protocols_lengths, uint16_t num_alpn_protocols,
    1255             :     tsi_ssl_handshaker_factory **factory) {
    1256         572 :   SSL_CTX *ssl_context = NULL;
    1257         572 :   tsi_ssl_client_handshaker_factory *impl = NULL;
    1258         572 :   tsi_result result = TSI_OK;
    1259             : 
    1260         590 :   gpr_once_init(&init_openssl_once, init_openssl);
    1261             : 
    1262         590 :   if (factory == NULL) return TSI_INVALID_ARGUMENT;
    1263         590 :   *factory = NULL;
    1264         590 :   if (pem_root_certs == NULL) return TSI_INVALID_ARGUMENT;
    1265             : 
    1266         590 :   ssl_context = SSL_CTX_new(TLSv1_2_method());
    1267         590 :   if (ssl_context == NULL) {
    1268           0 :     gpr_log(GPR_ERROR, "Could not create ssl context.");
    1269           0 :     return TSI_INVALID_ARGUMENT;
    1270             :   }
    1271             : 
    1272         590 :   impl = calloc(1, sizeof(tsi_ssl_client_handshaker_factory));
    1273         590 :   if (impl == NULL) {
    1274           0 :     SSL_CTX_free(ssl_context);
    1275           0 :     return TSI_OUT_OF_RESOURCES;
    1276             :   }
    1277         590 :   impl->ssl_context = ssl_context;
    1278             : 
    1279             :   do {
    1280         590 :     result =
    1281             :         populate_ssl_context(ssl_context, pem_private_key, pem_private_key_size,
    1282             :                              pem_cert_chain, pem_cert_chain_size, cipher_list);
    1283         590 :     if (result != TSI_OK) break;
    1284         590 :     result = ssl_ctx_load_verification_certs(ssl_context, pem_root_certs,
    1285             :                                              pem_root_certs_size, NULL);
    1286         590 :     if (result != TSI_OK) {
    1287           0 :       gpr_log(GPR_ERROR, "Cannot load server root certificates.");
    1288           0 :       break;
    1289             :     }
    1290             : 
    1291         590 :     if (num_alpn_protocols != 0) {
    1292         588 :       result = build_alpn_protocol_name_list(
    1293             :           alpn_protocols, alpn_protocols_lengths, num_alpn_protocols,
    1294             :           &impl->alpn_protocol_list, &impl->alpn_protocol_list_length);
    1295         588 :       if (result != TSI_OK) {
    1296           0 :         gpr_log(GPR_ERROR, "Building alpn list failed with error %s.",
    1297             :                 tsi_result_to_string(result));
    1298           0 :         break;
    1299             :       }
    1300             : #if TSI_OPENSSL_ALPN_SUPPORT
    1301         570 :       GPR_ASSERT(impl->alpn_protocol_list_length < UINT_MAX);
    1302        1140 :       if (SSL_CTX_set_alpn_protos(
    1303         570 :               ssl_context, impl->alpn_protocol_list,
    1304         570 :               (unsigned int)impl->alpn_protocol_list_length)) {
    1305           0 :         gpr_log(GPR_ERROR, "Could not set alpn protocol list to context.");
    1306           0 :         result = TSI_INVALID_ARGUMENT;
    1307           0 :         break;
    1308             :       }
    1309             : #endif /* TSI_OPENSSL_ALPN_SUPPORT */
    1310         588 :       SSL_CTX_set_next_proto_select_cb(
    1311             :           ssl_context, client_handshaker_factory_npn_callback, impl);
    1312             :     }
    1313             :   } while (0);
    1314         590 :   if (result != TSI_OK) {
    1315           0 :     ssl_client_handshaker_factory_destroy(&impl->base);
    1316           0 :     return result;
    1317             :   }
    1318         590 :   SSL_CTX_set_verify(ssl_context, SSL_VERIFY_PEER, NULL);
    1319             :   /* TODO(jboeuf): Add revocation verification. */
    1320             : 
    1321         590 :   impl->base.create_handshaker =
    1322             :       ssl_client_handshaker_factory_create_handshaker;
    1323         590 :   impl->base.destroy = ssl_client_handshaker_factory_destroy;
    1324         590 :   *factory = &impl->base;
    1325         590 :   return TSI_OK;
    1326             : }
    1327             : 
    1328         577 : tsi_result tsi_create_ssl_server_handshaker_factory(
    1329             :     const unsigned char **pem_private_keys,
    1330             :     const size_t *pem_private_keys_sizes, const unsigned char **pem_cert_chains,
    1331             :     const size_t *pem_cert_chains_sizes, size_t key_cert_pair_count,
    1332             :     const unsigned char *pem_client_root_certs,
    1333             :     size_t pem_client_root_certs_size, int force_client_auth,
    1334             :     const char *cipher_list, const unsigned char **alpn_protocols,
    1335             :     const unsigned char *alpn_protocols_lengths, uint16_t num_alpn_protocols,
    1336             :     tsi_ssl_handshaker_factory **factory) {
    1337         574 :   tsi_ssl_server_handshaker_factory *impl = NULL;
    1338         574 :   tsi_result result = TSI_OK;
    1339         574 :   size_t i = 0;
    1340             : 
    1341         577 :   gpr_once_init(&init_openssl_once, init_openssl);
    1342             : 
    1343         577 :   if (factory == NULL) return TSI_INVALID_ARGUMENT;
    1344         577 :   *factory = NULL;
    1345         577 :   if (key_cert_pair_count == 0 || pem_private_keys == NULL ||
    1346             :       pem_cert_chains == NULL) {
    1347           0 :     return TSI_INVALID_ARGUMENT;
    1348             :   }
    1349             : 
    1350         577 :   impl = calloc(1, sizeof(tsi_ssl_server_handshaker_factory));
    1351         577 :   if (impl == NULL) return TSI_OUT_OF_RESOURCES;
    1352         577 :   impl->base.create_handshaker =
    1353             :       ssl_server_handshaker_factory_create_handshaker;
    1354         577 :   impl->base.destroy = ssl_server_handshaker_factory_destroy;
    1355         577 :   impl->ssl_contexts = calloc(key_cert_pair_count, sizeof(SSL_CTX *));
    1356         577 :   impl->ssl_context_x509_subject_names =
    1357         577 :       calloc(key_cert_pair_count, sizeof(tsi_peer));
    1358        1151 :   if (impl->ssl_contexts == NULL ||
    1359         574 :       impl->ssl_context_x509_subject_names == NULL) {
    1360           0 :     tsi_ssl_handshaker_factory_destroy(&impl->base);
    1361           0 :     return TSI_OUT_OF_RESOURCES;
    1362             :   }
    1363         577 :   impl->ssl_context_count = key_cert_pair_count;
    1364             : 
    1365         577 :   if (num_alpn_protocols > 0) {
    1366         577 :     result = build_alpn_protocol_name_list(
    1367             :         alpn_protocols, alpn_protocols_lengths, num_alpn_protocols,
    1368             :         &impl->alpn_protocol_list, &impl->alpn_protocol_list_length);
    1369         577 :     if (result != TSI_OK) {
    1370           0 :       tsi_ssl_handshaker_factory_destroy(&impl->base);
    1371           0 :       return result;
    1372             :     }
    1373             :   }
    1374             : 
    1375        1151 :   for (i = 0; i < key_cert_pair_count; i++) {
    1376             :     do {
    1377         577 :       impl->ssl_contexts[i] = SSL_CTX_new(TLSv1_2_method());
    1378         577 :       if (impl->ssl_contexts[i] == NULL) {
    1379           0 :         gpr_log(GPR_ERROR, "Could not create ssl context.");
    1380           0 :         result = TSI_OUT_OF_RESOURCES;
    1381           0 :         break;
    1382             :       }
    1383        2882 :       result = populate_ssl_context(
    1384        1728 :           impl->ssl_contexts[i], pem_private_keys[i], pem_private_keys_sizes[i],
    1385        1154 :           pem_cert_chains[i], pem_cert_chains_sizes[i], cipher_list);
    1386         577 :       if (result != TSI_OK) break;
    1387             : 
    1388         577 :       if (pem_client_root_certs != NULL) {
    1389           1 :         int flags = SSL_VERIFY_PEER;
    1390           1 :         STACK_OF(X509_NAME) *root_names = NULL;
    1391           1 :         result = ssl_ctx_load_verification_certs(
    1392           1 :             impl->ssl_contexts[i], pem_client_root_certs,
    1393             :             pem_client_root_certs_size, &root_names);
    1394           1 :         if (result != TSI_OK) {
    1395           0 :           gpr_log(GPR_ERROR, "Invalid verification certs.");
    1396           0 :           break;
    1397             :         }
    1398           1 :         SSL_CTX_set_client_CA_list(impl->ssl_contexts[i], root_names);
    1399           1 :         if (force_client_auth) flags |= SSL_VERIFY_FAIL_IF_NO_PEER_CERT;
    1400           1 :         SSL_CTX_set_verify(impl->ssl_contexts[i], flags, NULL);
    1401             :         /* TODO(jboeuf): Add revocation verification. */
    1402             :       }
    1403             : 
    1404        1725 :       result = extract_x509_subject_names_from_pem_cert(
    1405        1148 :           pem_cert_chains[i], pem_cert_chains_sizes[i],
    1406         577 :           &impl->ssl_context_x509_subject_names[i]);
    1407         577 :       if (result != TSI_OK) break;
    1408             : 
    1409         577 :       SSL_CTX_set_tlsext_servername_callback(
    1410             :           impl->ssl_contexts[i],
    1411             :           ssl_server_handshaker_factory_servername_callback);
    1412         577 :       SSL_CTX_set_tlsext_servername_arg(impl->ssl_contexts[i], impl);
    1413             : #if TSI_OPENSSL_ALPN_SUPPORT
    1414         574 :       SSL_CTX_set_alpn_select_cb(impl->ssl_contexts[i],
    1415             :                                  server_handshaker_factory_alpn_callback, impl);
    1416             : #endif /* TSI_OPENSSL_ALPN_SUPPORT */
    1417         577 :       SSL_CTX_set_next_protos_advertised_cb(
    1418         577 :           impl->ssl_contexts[i],
    1419             :           server_handshaker_factory_npn_advertised_callback, impl);
    1420             :     } while (0);
    1421             : 
    1422         577 :     if (result != TSI_OK) {
    1423           0 :       tsi_ssl_handshaker_factory_destroy(&impl->base);
    1424           0 :       return result;
    1425             :     }
    1426             :   }
    1427         577 :   *factory = &impl->base;
    1428         577 :   return TSI_OK;
    1429             : }
    1430             : 
    1431             : /* --- tsi_ssl utils. --- */
    1432             : 
    1433      127154 : int tsi_ssl_peer_matches_name(const tsi_peer *peer, const char *name) {
    1434      127097 :   size_t i = 0;
    1435      127097 :   size_t san_count = 0;
    1436      127097 :   const tsi_peer_property *cn_property = NULL;
    1437             : 
    1438             :   /* For now reject what looks like an IP address. */
    1439      127154 :   if (looks_like_ip_address(name)) return 0;
    1440             : 
    1441             :   /* Check the SAN first. */
    1442      380882 :   for (i = 0; i < peer->property_count; i++) {
    1443      380881 :     const tsi_peer_property *property = &peer->properties[i];
    1444      380881 :     if (property->name == NULL) continue;
    1445      380881 :     if (strcmp(property->name,
    1446             :                TSI_X509_SUBJECT_ALTERNATIVE_NAME_PEER_PROPERTY) == 0) {
    1447      127119 :       san_count++;
    1448      127119 :       if (does_entry_match_name(property->value.data, property->value.length,
    1449             :                                 name)) {
    1450      127038 :         return 1;
    1451             :       }
    1452      253762 :     } else if (strcmp(property->name,
    1453             :                       TSI_X509_SUBJECT_COMMON_NAME_PEER_PROPERTY) == 0) {
    1454      127096 :       cn_property = property;
    1455             :     }
    1456             :   }
    1457             : 
    1458             :   /* If there's no SAN, try the CN. */
    1459          58 :   if (san_count == 0 && cn_property != NULL) {
    1460          53 :     if (does_entry_match_name(cn_property->value.data,
    1461             :                               cn_property->value.length, name)) {
    1462          21 :       return 1;
    1463             :     }
    1464             :   }
    1465             : 
    1466          37 :   return 0; /* Not found. */
    1467             : }

Generated by: LCOV version 1.11