LCOV - code coverage report
Current view: top level - src/core/tsi - ssl_transport_security.c (source / functions) Hit Total Coverage
Test: tmp.zDYK9MVh93 Lines: 588 789 74.5 %
Date: 2015-10-10 Functions: 42 46 91.3 %

          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      531791 : static void openssl_locking_cb(int mode, int type, const char *file, int line) {
     121      531791 :   if (mode & CRYPTO_LOCK) {
     122      265880 :     gpr_mu_lock(&openssl_mutexes[type]);
     123             :   } else {
     124      265911 :     gpr_mu_unlock(&openssl_mutexes[type]);
     125             :   }
     126      531842 : }
     127             : 
     128       36271 : static unsigned long openssl_thread_id_cb(void) {
     129       36271 :   return (unsigned long)gpr_thd_currentid();
     130             : }
     131             : 
     132         121 : static void init_openssl(void) {
     133             :   int i;
     134             :   int num_locks;
     135         121 :   SSL_library_init();
     136         121 :   SSL_load_error_strings();
     137         121 :   OpenSSL_add_all_algorithms();
     138         121 :   num_locks = CRYPTO_num_locks();
     139         121 :   GPR_ASSERT(num_locks > 0);
     140         121 :   openssl_mutexes = malloc((size_t)num_locks * sizeof(gpr_mu));
     141         121 :   GPR_ASSERT(openssl_mutexes != NULL);
     142        5082 :   for (i = 0; i < CRYPTO_num_locks(); i++) {
     143        4961 :     gpr_mu_init(&openssl_mutexes[i]);
     144             :   }
     145         121 :   CRYPTO_set_locking_callback(openssl_locking_cb);
     146         121 :   CRYPTO_set_id_callback(openssl_thread_id_cb);
     147         121 : }
     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       39945 : static void ssl_log_where_info(const SSL *ssl, int where, int flag,
     178             :                                const char *msg) {
     179       39945 :   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       39945 : }
     184             : 
     185             : /* Used for debugging. TODO(jboeuf): Remove when code is mature enough. */
     186       13315 : static void ssl_info_callback(const SSL *ssl, int where, int ret) {
     187       13315 :   if (ret == 0) {
     188           0 :     gpr_log(GPR_ERROR, "ssl_info_callback: error occured.\n");
     189       13315 :     return;
     190             :   }
     191             : 
     192       13315 :   ssl_log_where_info(ssl, where, SSL_CB_LOOP, "LOOP");
     193       13315 :   ssl_log_where_info(ssl, where, SSL_CB_HANDSHAKE_START, "HANDSHAKE START");
     194       13315 :   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        1559 : static int looks_like_ip_address(const char *name) {
     201             :   size_t i;
     202        1559 :   size_t dot_count = 0;
     203        1559 :   size_t num_size = 0;
     204        1574 :   for (i = 0; i < strlen(name); i++) {
     205        1573 :     if (name[i] >= '0' && name[i] <= '9') {
     206          12 :       if (num_size > 3) return 0;
     207          12 :       num_size++;
     208        1561 :     } 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        1557 :       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         803 : static tsi_result ssl_get_x509_common_name(X509 *cert, unsigned char **utf8,
     222             :                                            size_t *utf8_size) {
     223         803 :   int common_name_index = -1;
     224         803 :   X509_NAME_ENTRY *common_name_entry = NULL;
     225         803 :   ASN1_STRING *common_name_asn1 = NULL;
     226         803 :   X509_NAME *subject_name = X509_get_subject_name(cert);
     227         803 :   int utf8_returned_size = 0;
     228         803 :   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         803 :   common_name_index =
     233             :       X509_NAME_get_index_by_NID(subject_name, NID_commonName, -1);
     234         803 :   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         803 :   common_name_entry = X509_NAME_get_entry(subject_name, common_name_index);
     240         803 :   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         803 :   common_name_asn1 = X509_NAME_ENTRY_get_data(common_name_entry);
     245         803 :   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         803 :   utf8_returned_size = ASN1_STRING_to_UTF8(utf8, common_name_asn1);
     251         803 :   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         803 :   *utf8_size = (size_t)utf8_returned_size;
     256         803 :   return TSI_OK;
     257             : }
     258             : 
     259             : /* Gets the subject CN of an X509 cert as a tsi_peer_property. */
     260         803 : 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         803 :   tsi_result result =
     265             :       ssl_get_x509_common_name(cert, &common_name, &common_name_size);
     266         803 :   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        1606 :   result = tsi_construct_string_peer_property(
     275             :       TSI_X509_SUBJECT_COMMON_NAME_PEER_PROPERTY,
     276         803 :       common_name == NULL ? "" : (const char *)common_name, common_name_size,
     277             :       property);
     278         803 :   OPENSSL_free(common_name);
     279         803 :   return result;
     280             : }
     281             : 
     282             : /* Gets the subject SANs from an X509 cert as a tsi_peer_property. */
     283         803 : 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         803 :   tsi_result result = TSI_OK;
     288             : 
     289             :   /* Reset for DNS entries filtering. */
     290         803 :   peer->property_count -= subject_alt_name_count;
     291             : 
     292        4015 :   for (i = 0; i < subject_alt_name_count; i++) {
     293        3212 :     GENERAL_NAME *subject_alt_name =
     294        3212 :         sk_GENERAL_NAME_value(subject_alt_names, (int)i);
     295             :     /* Filter out the non-dns entries names. */
     296        3212 :     if (subject_alt_name->type == GEN_DNS) {
     297        2409 :       unsigned char *dns_name = NULL;
     298        2409 :       int dns_name_size =
     299        2409 :           ASN1_STRING_to_UTF8(&dns_name, subject_alt_name->d.dNSName);
     300        2409 :       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        2409 :       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        2409 :           &peer->properties[peer->property_count++]);
     309        2409 :       OPENSSL_free(dns_name);
     310        2409 :       if (result != TSI_OK) break;
     311             :     }
     312             :   }
     313         803 :   return result;
     314             : }
     315             : 
     316             : /* Gets information about the peer's X509 cert as a tsi_peer object. */
     317         803 : static tsi_result peer_from_x509(X509 *cert, int include_certificate_type,
     318             :                                  tsi_peer *peer) {
     319             :   /* TODO(jboeuf): Maybe add more properties. */
     320         803 :   GENERAL_NAMES *subject_alt_names =
     321             :       X509_get_ext_d2i(cert, NID_subject_alt_name, 0, 0);
     322         803 :   int subject_alt_name_count =
     323         803 :       (subject_alt_names != NULL) ? sk_GENERAL_NAME_num(subject_alt_names) : 0;
     324             :   size_t property_count;
     325             :   tsi_result result;
     326         803 :   GPR_ASSERT(subject_alt_name_count >= 0);
     327        1606 :   property_count = (include_certificate_type ? (size_t)1 : 0) +
     328         803 :                    1 /* common name */ + (size_t)subject_alt_name_count;
     329         803 :   result = tsi_construct_peer(property_count, peer);
     330         803 :   if (result != TSI_OK) return result;
     331             :   do {
     332         803 :     if (include_certificate_type) {
     333         365 :       result = tsi_construct_string_peer_property_from_cstring(
     334             :           TSI_CERTIFICATE_TYPE_PEER_PROPERTY, TSI_X509_CERTIFICATE_TYPE,
     335             :           &peer->properties[0]);
     336         365 :       if (result != TSI_OK) break;
     337             :     }
     338         803 :     result = peer_property_from_x509_common_name(
     339         803 :         cert, &peer->properties[include_certificate_type ? 1 : 0]);
     340         803 :     if (result != TSI_OK) break;
     341             : 
     342         803 :     if (subject_alt_name_count != 0) {
     343         803 :       result = add_subject_alt_names_properties_to_peer(
     344             :           peer, subject_alt_names, (size_t)subject_alt_name_count);
     345         803 :       if (result != TSI_OK) break;
     346             :     }
     347             :   } while (0);
     348             : 
     349         803 :   if (subject_alt_names != NULL) {
     350         803 :     sk_GENERAL_NAME_pop_free(subject_alt_names, GENERAL_NAME_free);
     351             :   }
     352         803 :   if (result != TSI_OK) tsi_peer_destruct(peer);
     353         803 :   return result;
     354             : }
     355             : 
     356             : /* Logs the SSL error stack. */
     357           0 : static void log_ssl_error_stack(void) {
     358             :   unsigned long err;
     359           0 :   while ((err = ERR_get_error()) != 0) {
     360             :     char details[256];
     361           0 :     ERR_error_string_n(err, details, sizeof(details));
     362           0 :     gpr_log(GPR_ERROR, "%s", details);
     363             :   }
     364           0 : }
     365             : 
     366             : /* Performs an SSL_read and handle errors. */
     367       20659 : static tsi_result do_ssl_read(SSL *ssl, unsigned char *unprotected_bytes,
     368             :                               size_t *unprotected_bytes_size) {
     369             :   int read_from_ssl;
     370       20659 :   GPR_ASSERT(*unprotected_bytes_size <= INT_MAX);
     371       20659 :   read_from_ssl =
     372       20659 :       SSL_read(ssl, unprotected_bytes, (int)*unprotected_bytes_size);
     373       20659 :   if (read_from_ssl == 0) {
     374           0 :     gpr_log(GPR_ERROR, "SSL_read returned 0 unexpectedly.");
     375           0 :     return TSI_INTERNAL_ERROR;
     376             :   }
     377       20659 :   if (read_from_ssl < 0) {
     378       14012 :     read_from_ssl = SSL_get_error(ssl, read_from_ssl);
     379       14012 :     switch (read_from_ssl) {
     380             :       case SSL_ERROR_WANT_READ:
     381             :         /* We need more data to finish the frame. */
     382       14012 :         *unprotected_bytes_size = 0;
     383       14012 :         return TSI_OK;
     384             :       case SSL_ERROR_WANT_WRITE:
     385           0 :         gpr_log(
     386             :             GPR_ERROR,
     387             :             "Peer tried to renegotiate SSL connection. This is unsupported.");
     388           0 :         return TSI_UNIMPLEMENTED;
     389             :       case SSL_ERROR_SSL:
     390           0 :         gpr_log(GPR_ERROR, "Corruption detected.");
     391           0 :         log_ssl_error_stack();
     392           0 :         return TSI_DATA_CORRUPTED;
     393             :       default:
     394           0 :         gpr_log(GPR_ERROR, "SSL_read failed with error %s.",
     395             :                 ssl_error_string(read_from_ssl));
     396           0 :         return TSI_PROTOCOL_FAILURE;
     397             :     }
     398             :   }
     399        6647 :   *unprotected_bytes_size = (size_t)read_from_ssl;
     400        6647 :   return TSI_OK;
     401             : }
     402             : 
     403             : /* Performs an SSL_write and handle errors. */
     404        5626 : static tsi_result do_ssl_write(SSL *ssl, unsigned char *unprotected_bytes,
     405             :                                size_t unprotected_bytes_size) {
     406             :   int ssl_write_result;
     407        5626 :   GPR_ASSERT(unprotected_bytes_size <= INT_MAX);
     408        5626 :   ssl_write_result =
     409        5626 :       SSL_write(ssl, unprotected_bytes, (int)unprotected_bytes_size);
     410        5626 :   if (ssl_write_result < 0) {
     411           0 :     ssl_write_result = SSL_get_error(ssl, ssl_write_result);
     412           0 :     if (ssl_write_result == SSL_ERROR_WANT_READ) {
     413           0 :       gpr_log(GPR_ERROR,
     414             :               "Peer tried to renegotiate SSL connection. This is unsupported.");
     415           0 :       return TSI_UNIMPLEMENTED;
     416             :     } else {
     417           0 :       gpr_log(GPR_ERROR, "SSL_write failed with error %s.",
     418             :               ssl_error_string(ssl_write_result));
     419           0 :       return TSI_INTERNAL_ERROR;
     420             :     }
     421             :   }
     422        5626 :   return TSI_OK;
     423             : }
     424             : 
     425             : /* Loads an in-memory PEM certificate chain into the SSL context. */
     426         438 : static tsi_result ssl_ctx_use_certificate_chain(
     427             :     SSL_CTX *context, const unsigned char *pem_cert_chain,
     428             :     size_t pem_cert_chain_size) {
     429         438 :   tsi_result result = TSI_OK;
     430         438 :   X509 *certificate = NULL;
     431             :   BIO *pem;
     432         438 :   GPR_ASSERT(pem_cert_chain_size <= INT_MAX);
     433         438 :   pem = BIO_new_mem_buf((void *)pem_cert_chain, (int)pem_cert_chain_size);
     434         438 :   if (pem == NULL) return TSI_OUT_OF_RESOURCES;
     435             : 
     436             :   do {
     437         438 :     certificate = PEM_read_bio_X509_AUX(pem, NULL, NULL, "");
     438         438 :     if (certificate == NULL) {
     439           0 :       result = TSI_INVALID_ARGUMENT;
     440           0 :       break;
     441             :     }
     442         438 :     if (!SSL_CTX_use_certificate(context, certificate)) {
     443           0 :       result = TSI_INVALID_ARGUMENT;
     444           0 :       break;
     445             :     }
     446             :     while (1) {
     447         438 :       X509 *certificate_authority = PEM_read_bio_X509(pem, NULL, NULL, "");
     448         438 :       if (certificate_authority == NULL) {
     449         438 :         ERR_clear_error();
     450         438 :         break; /* Done reading. */
     451             :       }
     452           0 :       if (!SSL_CTX_add_extra_chain_cert(context, certificate_authority)) {
     453           0 :         X509_free(certificate_authority);
     454           0 :         result = TSI_INVALID_ARGUMENT;
     455           0 :         break;
     456             :       }
     457             :       /* We don't need to free certificate_authority as its ownership has been
     458             :          transfered to the context. That is not the case for certificate though.
     459             :        */
     460           0 :     }
     461             :   } while (0);
     462             : 
     463         438 :   if (certificate != NULL) X509_free(certificate);
     464         438 :   BIO_free(pem);
     465         438 :   return result;
     466             : }
     467             : 
     468             : /* Loads an in-memory PEM private key into the SSL context. */
     469         438 : static tsi_result ssl_ctx_use_private_key(SSL_CTX *context,
     470             :                                           const unsigned char *pem_key,
     471             :                                           size_t pem_key_size) {
     472         438 :   tsi_result result = TSI_OK;
     473         438 :   EVP_PKEY *private_key = NULL;
     474             :   BIO *pem;
     475         438 :   GPR_ASSERT(pem_key_size <= INT_MAX);
     476         438 :   pem = BIO_new_mem_buf((void *)pem_key, (int)pem_key_size);
     477         438 :   if (pem == NULL) return TSI_OUT_OF_RESOURCES;
     478             :   do {
     479         438 :     private_key = PEM_read_bio_PrivateKey(pem, NULL, NULL, "");
     480         438 :     if (private_key == NULL) {
     481           0 :       result = TSI_INVALID_ARGUMENT;
     482           0 :       break;
     483             :     }
     484         438 :     if (!SSL_CTX_use_PrivateKey(context, private_key)) {
     485           0 :       result = TSI_INVALID_ARGUMENT;
     486           0 :       break;
     487             :     }
     488             :   } while (0);
     489         438 :   if (private_key != NULL) EVP_PKEY_free(private_key);
     490         438 :   BIO_free(pem);
     491         438 :   return result;
     492             : }
     493             : 
     494             : /* Loads in-memory PEM verification certs into the SSL context and optionally
     495             :    returns the verification cert names (root_names can be NULL). */
     496         434 : static tsi_result ssl_ctx_load_verification_certs(
     497             :     SSL_CTX *context, const unsigned char *pem_roots, size_t pem_roots_size,
     498             :     STACK_OF(X509_NAME) * *root_names) {
     499         434 :   tsi_result result = TSI_OK;
     500         434 :   size_t num_roots = 0;
     501         434 :   X509 *root = NULL;
     502         434 :   X509_NAME *root_name = NULL;
     503             :   BIO *pem;
     504             :   X509_STORE *root_store;
     505         434 :   GPR_ASSERT(pem_roots_size <= INT_MAX);
     506         434 :   pem = BIO_new_mem_buf((void *)pem_roots, (int)pem_roots_size);
     507         434 :   root_store = SSL_CTX_get_cert_store(context);
     508         434 :   if (root_store == NULL) return TSI_INVALID_ARGUMENT;
     509         434 :   if (pem == NULL) return TSI_OUT_OF_RESOURCES;
     510         434 :   if (root_names != NULL) {
     511           0 :     *root_names = sk_X509_NAME_new_null();
     512           0 :     if (*root_names == NULL) return TSI_OUT_OF_RESOURCES;
     513             :   }
     514             : 
     515             :   while (1) {
     516         868 :     root = PEM_read_bio_X509_AUX(pem, NULL, NULL, "");
     517         868 :     if (root == NULL) {
     518         434 :       ERR_clear_error();
     519         434 :       break; /* We're at the end of stream. */
     520             :     }
     521         434 :     if (root_names != NULL) {
     522           0 :       root_name = X509_get_subject_name(root);
     523           0 :       if (root_name == NULL) {
     524           0 :         gpr_log(GPR_ERROR, "Could not get name from root certificate.");
     525           0 :         result = TSI_INVALID_ARGUMENT;
     526           0 :         break;
     527             :       }
     528           0 :       root_name = X509_NAME_dup(root_name);
     529           0 :       if (root_name == NULL) {
     530           0 :         result = TSI_OUT_OF_RESOURCES;
     531           0 :         break;
     532             :       }
     533           0 :       sk_X509_NAME_push(*root_names, root_name);
     534           0 :       root_name = NULL;
     535             :     }
     536         434 :     if (!X509_STORE_add_cert(root_store, root)) {
     537           0 :       gpr_log(GPR_ERROR, "Could not add root certificate to ssl context.");
     538           0 :       result = TSI_INTERNAL_ERROR;
     539           0 :       break;
     540             :     }
     541         434 :     X509_free(root);
     542         434 :     num_roots++;
     543         434 :   }
     544             : 
     545         434 :   if (num_roots == 0) {
     546           0 :     gpr_log(GPR_ERROR, "Could not load any root certificate.");
     547           0 :     result = TSI_INVALID_ARGUMENT;
     548             :   }
     549             : 
     550         434 :   if (result != TSI_OK) {
     551           0 :     if (root != NULL) X509_free(root);
     552           0 :     if (root_names != NULL) {
     553           0 :       sk_X509_NAME_pop_free(*root_names, X509_NAME_free);
     554           0 :       *root_names = NULL;
     555           0 :       if (root_name != NULL) X509_NAME_free(root_name);
     556             :     }
     557             :   }
     558         434 :   BIO_free(pem);
     559         434 :   return result;
     560             : }
     561             : 
     562             : /* Populates the SSL context with a private key and a cert chain, and sets the
     563             :    cipher list and the ephemeral ECDH key. */
     564         872 : static tsi_result populate_ssl_context(
     565             :     SSL_CTX *context, const unsigned char *pem_private_key,
     566             :     size_t pem_private_key_size, const unsigned char *pem_certificate_chain,
     567             :     size_t pem_certificate_chain_size, const char *cipher_list) {
     568         872 :   tsi_result result = TSI_OK;
     569         872 :   if (pem_certificate_chain != NULL) {
     570         438 :     result = ssl_ctx_use_certificate_chain(context, pem_certificate_chain,
     571             :                                            pem_certificate_chain_size);
     572         438 :     if (result != TSI_OK) {
     573           0 :       gpr_log(GPR_ERROR, "Invalid cert chain file.");
     574           0 :       return result;
     575             :     }
     576             :   }
     577         872 :   if (pem_private_key != NULL) {
     578         438 :     result =
     579             :         ssl_ctx_use_private_key(context, pem_private_key, pem_private_key_size);
     580         438 :     if (result != TSI_OK || !SSL_CTX_check_private_key(context)) {
     581           0 :       gpr_log(GPR_ERROR, "Invalid private key.");
     582           0 :       return result != TSI_OK ? result : TSI_INVALID_ARGUMENT;
     583             :     }
     584             :   }
     585         872 :   if ((cipher_list != NULL) && !SSL_CTX_set_cipher_list(context, cipher_list)) {
     586           0 :     gpr_log(GPR_ERROR, "Invalid cipher list: %s.", cipher_list);
     587           0 :     return TSI_INVALID_ARGUMENT;
     588             :   }
     589             :   {
     590         872 :     EC_KEY *ecdh = EC_KEY_new_by_curve_name(NID_X9_62_prime256v1);
     591         872 :     if (!SSL_CTX_set_tmp_ecdh(context, ecdh)) {
     592           0 :       gpr_log(GPR_ERROR, "Could not set ephemeral ECDH key.");
     593           0 :       EC_KEY_free(ecdh);
     594           0 :       return TSI_INTERNAL_ERROR;
     595             :     }
     596         872 :     SSL_CTX_set_options(context, SSL_OP_SINGLE_ECDH_USE);
     597         872 :     EC_KEY_free(ecdh);
     598             :   }
     599         872 :   return TSI_OK;
     600             : }
     601             : 
     602             : /* Extracts the CN and the SANs from an X509 cert as a peer object. */
     603         438 : static tsi_result extract_x509_subject_names_from_pem_cert(
     604             :     const unsigned char *pem_cert, size_t pem_cert_size, tsi_peer *peer) {
     605         438 :   tsi_result result = TSI_OK;
     606         438 :   X509 *cert = NULL;
     607             :   BIO *pem;
     608         438 :   GPR_ASSERT(pem_cert_size <= INT_MAX);
     609         438 :   pem = BIO_new_mem_buf((void *)pem_cert, (int)pem_cert_size);
     610         438 :   if (pem == NULL) return TSI_OUT_OF_RESOURCES;
     611             : 
     612         438 :   cert = PEM_read_bio_X509(pem, NULL, NULL, "");
     613         438 :   if (cert == NULL) {
     614           0 :     gpr_log(GPR_ERROR, "Invalid certificate");
     615           0 :     result = TSI_INVALID_ARGUMENT;
     616             :   } else {
     617         438 :     result = peer_from_x509(cert, 0, peer);
     618             :   }
     619         438 :   if (cert != NULL) X509_free(cert);
     620         438 :   BIO_free(pem);
     621         438 :   return result;
     622             : }
     623             : 
     624             : /* Builds the alpn protocol name list according to rfc 7301. */
     625         872 : static tsi_result build_alpn_protocol_name_list(
     626             :     const unsigned char **alpn_protocols,
     627             :     const unsigned char *alpn_protocols_lengths, uint16_t num_alpn_protocols,
     628             :     unsigned char **protocol_name_list, size_t *protocol_name_list_length) {
     629             :   uint16_t i;
     630             :   unsigned char *current;
     631         872 :   *protocol_name_list = NULL;
     632         872 :   *protocol_name_list_length = 0;
     633         872 :   if (num_alpn_protocols == 0) return TSI_INVALID_ARGUMENT;
     634        1744 :   for (i = 0; i < num_alpn_protocols; i++) {
     635         872 :     if (alpn_protocols_lengths[i] == 0) {
     636           0 :       gpr_log(GPR_ERROR, "Invalid 0-length protocol name.");
     637           0 :       return TSI_INVALID_ARGUMENT;
     638             :     }
     639         872 :     *protocol_name_list_length += (size_t)alpn_protocols_lengths[i] + 1;
     640             :   }
     641         872 :   *protocol_name_list = malloc(*protocol_name_list_length);
     642         872 :   if (*protocol_name_list == NULL) return TSI_OUT_OF_RESOURCES;
     643         872 :   current = *protocol_name_list;
     644        1744 :   for (i = 0; i < num_alpn_protocols; i++) {
     645         872 :     *(current++) = alpn_protocols_lengths[i];
     646         872 :     memcpy(current, alpn_protocols[i], alpn_protocols_lengths[i]);
     647         872 :     current += alpn_protocols_lengths[i];
     648             :   }
     649             :   /* Safety check. */
     650        1744 :   if ((current < *protocol_name_list) ||
     651         872 :       ((gpr_uintptr)(current - *protocol_name_list) !=
     652         872 :        *protocol_name_list_length)) {
     653           0 :     return TSI_INTERNAL_ERROR;
     654             :   }
     655         872 :   return TSI_OK;
     656             : }
     657             : 
     658             : /* --- tsi_frame_protector methods implementation. ---*/
     659             : 
     660       23646 : static tsi_result ssl_protector_protect(tsi_frame_protector *self,
     661             :                                         const unsigned char *unprotected_bytes,
     662             :                                         size_t *unprotected_bytes_size,
     663             :                                         unsigned char *protected_output_frames,
     664             :                                         size_t *protected_output_frames_size) {
     665       23646 :   tsi_ssl_frame_protector *impl = (tsi_ssl_frame_protector *)self;
     666             :   int read_from_ssl;
     667             :   size_t available;
     668       23646 :   tsi_result result = TSI_OK;
     669             : 
     670             :   /* First see if we have some pending data in the SSL BIO. */
     671       23646 :   int pending_in_ssl = BIO_pending(impl->from_ssl);
     672       23646 :   if (pending_in_ssl > 0) {
     673        1741 :     *unprotected_bytes_size = 0;
     674        1741 :     GPR_ASSERT(*protected_output_frames_size <= INT_MAX);
     675        1741 :     read_from_ssl = BIO_read(impl->from_ssl, protected_output_frames,
     676        1741 :                              (int)*protected_output_frames_size);
     677        1741 :     if (read_from_ssl < 0) {
     678           0 :       gpr_log(GPR_ERROR,
     679             :               "Could not read from BIO even though some data is pending");
     680           0 :       return TSI_INTERNAL_ERROR;
     681             :     }
     682        1741 :     *protected_output_frames_size = (size_t)read_from_ssl;
     683        1741 :     return TSI_OK;
     684             :   }
     685             : 
     686             :   /* Now see if we can send a complete frame. */
     687       21905 :   available = impl->buffer_size - impl->buffer_offset;
     688       21905 :   if (available > *unprotected_bytes_size) {
     689             :     /* If we cannot, just copy the data in our internal buffer. */
     690       21207 :     memcpy(impl->buffer + impl->buffer_offset, unprotected_bytes,
     691             :            *unprotected_bytes_size);
     692       21207 :     impl->buffer_offset += *unprotected_bytes_size;
     693       21207 :     *protected_output_frames_size = 0;
     694       21207 :     return TSI_OK;
     695             :   }
     696             : 
     697             :   /* If we can, prepare the buffer, send it to SSL_write and read. */
     698         698 :   memcpy(impl->buffer + impl->buffer_offset, unprotected_bytes, available);
     699         698 :   result = do_ssl_write(impl->ssl, impl->buffer, impl->buffer_size);
     700         698 :   if (result != TSI_OK) return result;
     701             : 
     702         698 :   GPR_ASSERT(*protected_output_frames_size <= INT_MAX);
     703         698 :   read_from_ssl = BIO_read(impl->from_ssl, protected_output_frames,
     704         698 :                            (int)*protected_output_frames_size);
     705         698 :   if (read_from_ssl < 0) {
     706           0 :     gpr_log(GPR_ERROR, "Could not read from BIO after SSL_write.");
     707           0 :     return TSI_INTERNAL_ERROR;
     708             :   }
     709         698 :   *protected_output_frames_size = (size_t)read_from_ssl;
     710         698 :   *unprotected_bytes_size = available;
     711         698 :   impl->buffer_offset = 0;
     712         698 :   return TSI_OK;
     713             : }
     714             : 
     715        4954 : static tsi_result ssl_protector_protect_flush(
     716             :     tsi_frame_protector *self, unsigned char *protected_output_frames,
     717             :     size_t *protected_output_frames_size, size_t *still_pending_size) {
     718        4954 :   tsi_result result = TSI_OK;
     719        4954 :   tsi_ssl_frame_protector *impl = (tsi_ssl_frame_protector *)self;
     720        4954 :   int read_from_ssl = 0;
     721             :   int pending;
     722             : 
     723        4954 :   if (impl->buffer_offset != 0) {
     724        4928 :     result = do_ssl_write(impl->ssl, impl->buffer, impl->buffer_offset);
     725        4928 :     if (result != TSI_OK) return result;
     726        4928 :     impl->buffer_offset = 0;
     727             :   }
     728             : 
     729        4954 :   pending = BIO_pending(impl->from_ssl);
     730        4954 :   GPR_ASSERT(pending >= 0);
     731        4954 :   *still_pending_size = (size_t)pending;
     732        4954 :   if (*still_pending_size == 0) return TSI_OK;
     733             : 
     734        4954 :   GPR_ASSERT(*protected_output_frames_size <= INT_MAX);
     735        4954 :   read_from_ssl = BIO_read(impl->from_ssl, protected_output_frames,
     736        4954 :                            (int)*protected_output_frames_size);
     737        4954 :   if (read_from_ssl <= 0) {
     738           0 :     gpr_log(GPR_ERROR, "Could not read from BIO after SSL_write.");
     739           0 :     return TSI_INTERNAL_ERROR;
     740             :   }
     741        4954 :   *protected_output_frames_size = (size_t)read_from_ssl;
     742        4954 :   pending = BIO_pending(impl->from_ssl);
     743        4954 :   GPR_ASSERT(pending >= 0);
     744        4954 :   *still_pending_size = (size_t)pending;
     745        4954 :   return TSI_OK;
     746             : }
     747             : 
     748       10664 : static tsi_result ssl_protector_unprotect(
     749             :     tsi_frame_protector *self, const unsigned char *protected_frames_bytes,
     750             :     size_t *protected_frames_bytes_size, unsigned char *unprotected_bytes,
     751             :     size_t *unprotected_bytes_size) {
     752       10664 :   tsi_result result = TSI_OK;
     753       10664 :   int written_into_ssl = 0;
     754       10664 :   size_t output_bytes_size = *unprotected_bytes_size;
     755       10664 :   size_t output_bytes_offset = 0;
     756       10664 :   tsi_ssl_frame_protector *impl = (tsi_ssl_frame_protector *)self;
     757             : 
     758             :   /* First, try to read remaining data from ssl. */
     759       10664 :   result = do_ssl_read(impl->ssl, unprotected_bytes, unprotected_bytes_size);
     760       10665 :   if (result != TSI_OK) return result;
     761       10665 :   if (*unprotected_bytes_size == output_bytes_size) {
     762             :     /* We have read everything we could and cannot process any more input. */
     763         670 :     *protected_frames_bytes_size = 0;
     764         670 :     return TSI_OK;
     765             :   }
     766        9995 :   output_bytes_offset = *unprotected_bytes_size;
     767        9995 :   unprotected_bytes += output_bytes_offset;
     768        9995 :   *unprotected_bytes_size = output_bytes_size - output_bytes_offset;
     769             : 
     770             :   /* Then, try to write some data to ssl. */
     771        9995 :   GPR_ASSERT(*protected_frames_bytes_size <= INT_MAX);
     772        9995 :   written_into_ssl = BIO_write(impl->into_ssl, protected_frames_bytes,
     773        9995 :                                (int)*protected_frames_bytes_size);
     774        9995 :   if (written_into_ssl < 0) {
     775           0 :     gpr_log(GPR_ERROR, "Sending protected frame to ssl failed with %d",
     776             :             written_into_ssl);
     777           0 :     return TSI_INTERNAL_ERROR;
     778             :   }
     779        9995 :   *protected_frames_bytes_size = (size_t)written_into_ssl;
     780             : 
     781             :   /* Now try to read some data again. */
     782        9995 :   result = do_ssl_read(impl->ssl, unprotected_bytes, unprotected_bytes_size);
     783        9992 :   if (result == TSI_OK) {
     784             :     /* Don't forget to output the total number of bytes read. */
     785        9992 :     *unprotected_bytes_size += output_bytes_offset;
     786             :   }
     787        9992 :   return result;
     788             : }
     789             : 
     790         732 : static void ssl_protector_destroy(tsi_frame_protector *self) {
     791         732 :   tsi_ssl_frame_protector *impl = (tsi_ssl_frame_protector *)self;
     792         732 :   if (impl->buffer != NULL) free(impl->buffer);
     793         732 :   if (impl->ssl != NULL) SSL_free(impl->ssl);
     794         732 :   free(self);
     795         732 : }
     796             : 
     797             : static const tsi_frame_protector_vtable frame_protector_vtable = {
     798             :     ssl_protector_protect, ssl_protector_protect_flush, ssl_protector_unprotect,
     799             :     ssl_protector_destroy,
     800             : };
     801             : 
     802             : /* --- tsi_handshaker methods implementation. ---*/
     803             : 
     804        2239 : static tsi_result ssl_handshaker_get_bytes_to_send_to_peer(tsi_handshaker *self,
     805             :                                                            unsigned char *bytes,
     806             :                                                            size_t *bytes_size) {
     807        2239 :   tsi_ssl_handshaker *impl = (tsi_ssl_handshaker *)self;
     808        2239 :   int bytes_read_from_ssl = 0;
     809        4478 :   if (bytes == NULL || bytes_size == NULL || *bytes_size == 0 ||
     810        2239 :       *bytes_size > INT_MAX) {
     811           0 :     return TSI_INVALID_ARGUMENT;
     812             :   }
     813        2239 :   GPR_ASSERT(*bytes_size <= INT_MAX);
     814        2239 :   bytes_read_from_ssl = BIO_read(impl->from_ssl, bytes, (int)*bytes_size);
     815        2239 :   if (bytes_read_from_ssl < 0) {
     816         377 :     *bytes_size = 0;
     817         377 :     if (!BIO_should_retry(impl->from_ssl)) {
     818           0 :       impl->result = TSI_INTERNAL_ERROR;
     819           0 :       return impl->result;
     820             :     } else {
     821         377 :       return TSI_OK;
     822             :     }
     823             :   }
     824        1862 :   *bytes_size = (size_t)bytes_read_from_ssl;
     825        1862 :   return BIO_pending(impl->from_ssl) == 0 ? TSI_OK : TSI_INCOMPLETE_DATA;
     826             : }
     827             : 
     828        7381 : static tsi_result ssl_handshaker_get_result(tsi_handshaker *self) {
     829        7381 :   tsi_ssl_handshaker *impl = (tsi_ssl_handshaker *)self;
     830       12566 :   if ((impl->result == TSI_HANDSHAKE_IN_PROGRESS) &&
     831        5185 :       SSL_is_init_finished(impl->ssl)) {
     832         732 :     impl->result = TSI_OK;
     833             :   }
     834        7381 :   return impl->result;
     835             : }
     836             : 
     837        1475 : static tsi_result ssl_handshaker_process_bytes_from_peer(
     838             :     tsi_handshaker *self, const unsigned char *bytes, size_t *bytes_size) {
     839        1475 :   tsi_ssl_handshaker *impl = (tsi_ssl_handshaker *)self;
     840        1475 :   int bytes_written_into_ssl_size = 0;
     841        1475 :   if (bytes == NULL || bytes_size == 0 || *bytes_size > INT_MAX) {
     842           0 :     return TSI_INVALID_ARGUMENT;
     843             :   }
     844        1475 :   GPR_ASSERT(*bytes_size <= INT_MAX);
     845        1475 :   bytes_written_into_ssl_size =
     846        1475 :       BIO_write(impl->into_ssl, bytes, (int)*bytes_size);
     847        1475 :   if (bytes_written_into_ssl_size < 0) {
     848           0 :     gpr_log(GPR_ERROR, "Could not write to memory BIO.");
     849           0 :     impl->result = TSI_INTERNAL_ERROR;
     850           0 :     return impl->result;
     851             :   }
     852        1475 :   *bytes_size = (size_t)bytes_written_into_ssl_size;
     853             : 
     854        1475 :   if (!tsi_handshaker_is_in_progress(self)) {
     855           0 :     impl->result = TSI_OK;
     856           0 :     return impl->result;
     857             :   } else {
     858             :     /* Get ready to get some bytes from SSL. */
     859        1475 :     int ssl_result = SSL_do_handshake(impl->ssl);
     860        1475 :     ssl_result = SSL_get_error(impl->ssl, ssl_result);
     861        1475 :     switch (ssl_result) {
     862             :       case SSL_ERROR_WANT_READ:
     863         743 :         if (BIO_pending(impl->from_ssl) == 0) {
     864             :           /* We need more data. */
     865           0 :           return TSI_INCOMPLETE_DATA;
     866             :         } else {
     867         743 :           return TSI_OK;
     868             :         }
     869             :       case SSL_ERROR_NONE:
     870         732 :         return TSI_OK;
     871             :       default: {
     872             :         char err_str[256];
     873           0 :         ERR_error_string_n(ERR_get_error(), err_str, sizeof(err_str));
     874           0 :         gpr_log(GPR_ERROR, "Handshake failed with fatal error %s: %s.",
     875             :                 ssl_error_string(ssl_result), err_str);
     876           0 :         impl->result = TSI_PROTOCOL_FAILURE;
     877           0 :         return impl->result;
     878             :       }
     879             :     }
     880             :   }
     881             : }
     882             : 
     883         732 : static tsi_result ssl_handshaker_extract_peer(tsi_handshaker *self,
     884             :                                               tsi_peer *peer) {
     885         732 :   tsi_result result = TSI_OK;
     886         732 :   const unsigned char *alpn_selected = NULL;
     887             :   unsigned int alpn_selected_len;
     888         732 :   tsi_ssl_handshaker *impl = (tsi_ssl_handshaker *)self;
     889         732 :   X509 *peer_cert = SSL_get_peer_certificate(impl->ssl);
     890         732 :   if (peer_cert != NULL) {
     891         365 :     result = peer_from_x509(peer_cert, 1, peer);
     892         365 :     X509_free(peer_cert);
     893         365 :     if (result != TSI_OK) return result;
     894             :   }
     895             : #if TSI_OPENSSL_ALPN_SUPPORT
     896         732 :   SSL_get0_alpn_selected(impl->ssl, &alpn_selected, &alpn_selected_len);
     897             : #endif /* TSI_OPENSSL_ALPN_SUPPORT */
     898         732 :   if (alpn_selected == NULL) {
     899             :     /* Try npn. */
     900           0 :     SSL_get0_next_proto_negotiated(impl->ssl, &alpn_selected,
     901             :                                    &alpn_selected_len);
     902             :   }
     903         732 :   if (alpn_selected != NULL) {
     904             :     size_t i;
     905         732 :     tsi_peer_property *new_properties =
     906         732 :         calloc(1, sizeof(tsi_peer_property) * (peer->property_count + 1));
     907         732 :     if (new_properties == NULL) return TSI_OUT_OF_RESOURCES;
     908        2557 :     for (i = 0; i < peer->property_count; i++) {
     909        1825 :       new_properties[i] = peer->properties[i];
     910             :     }
     911         732 :     result = tsi_construct_string_peer_property(
     912             :         TSI_SSL_ALPN_SELECTED_PROTOCOL, (const char *)alpn_selected,
     913         732 :         alpn_selected_len, &new_properties[peer->property_count]);
     914         732 :     if (result != TSI_OK) {
     915           0 :       free(new_properties);
     916           0 :       return result;
     917             :     }
     918         732 :     if (peer->properties != NULL) free(peer->properties);
     919         732 :     peer->property_count++;
     920         732 :     peer->properties = new_properties;
     921             :   }
     922         732 :   return result;
     923             : }
     924             : 
     925         732 : static tsi_result ssl_handshaker_create_frame_protector(
     926             :     tsi_handshaker *self, size_t *max_output_protected_frame_size,
     927             :     tsi_frame_protector **protector) {
     928         732 :   size_t actual_max_output_protected_frame_size =
     929             :       TSI_SSL_MAX_PROTECTED_FRAME_SIZE_UPPER_BOUND;
     930         732 :   tsi_ssl_handshaker *impl = (tsi_ssl_handshaker *)self;
     931         732 :   tsi_ssl_frame_protector *protector_impl =
     932             :       calloc(1, sizeof(tsi_ssl_frame_protector));
     933         732 :   if (protector_impl == NULL) {
     934           0 :     return TSI_OUT_OF_RESOURCES;
     935             :   }
     936             : 
     937         732 :   if (max_output_protected_frame_size != NULL) {
     938           0 :     if (*max_output_protected_frame_size >
     939             :         TSI_SSL_MAX_PROTECTED_FRAME_SIZE_UPPER_BOUND) {
     940           0 :       *max_output_protected_frame_size =
     941             :           TSI_SSL_MAX_PROTECTED_FRAME_SIZE_UPPER_BOUND;
     942           0 :     } else if (*max_output_protected_frame_size <
     943             :                TSI_SSL_MAX_PROTECTED_FRAME_SIZE_LOWER_BOUND) {
     944           0 :       *max_output_protected_frame_size =
     945             :           TSI_SSL_MAX_PROTECTED_FRAME_SIZE_LOWER_BOUND;
     946             :     }
     947           0 :     actual_max_output_protected_frame_size = *max_output_protected_frame_size;
     948             :   }
     949         732 :   protector_impl->buffer_size =
     950         732 :       actual_max_output_protected_frame_size - TSI_SSL_MAX_PROTECTION_OVERHEAD;
     951         732 :   protector_impl->buffer = malloc(protector_impl->buffer_size);
     952         732 :   if (protector_impl->buffer == NULL) {
     953           0 :     gpr_log(GPR_ERROR,
     954             :             "Could not allocated buffer for tsi_ssl_frame_protector.");
     955           0 :     free(protector_impl);
     956           0 :     return TSI_INTERNAL_ERROR;
     957             :   }
     958             : 
     959             :   /* Transfer ownership of ssl to the frame protector. It is OK as the caller
     960             :    * cannot call anything else but destroy on the handshaker after this call. */
     961         732 :   protector_impl->ssl = impl->ssl;
     962         732 :   impl->ssl = NULL;
     963         732 :   protector_impl->into_ssl = impl->into_ssl;
     964         732 :   protector_impl->from_ssl = impl->from_ssl;
     965             : 
     966         732 :   protector_impl->base.vtable = &frame_protector_vtable;
     967         732 :   *protector = &protector_impl->base;
     968         732 :   return TSI_OK;
     969             : }
     970             : 
     971         750 : static void ssl_handshaker_destroy(tsi_handshaker *self) {
     972         750 :   tsi_ssl_handshaker *impl = (tsi_ssl_handshaker *)self;
     973         750 :   SSL_free(impl->ssl); /* The BIO objects are owned by ssl */
     974         750 :   free(impl);
     975         750 : }
     976             : 
     977             : static const tsi_handshaker_vtable handshaker_vtable = {
     978             :     ssl_handshaker_get_bytes_to_send_to_peer,
     979             :     ssl_handshaker_process_bytes_from_peer, ssl_handshaker_get_result,
     980             :     ssl_handshaker_extract_peer, ssl_handshaker_create_frame_protector,
     981             :     ssl_handshaker_destroy,
     982             : };
     983             : 
     984             : /* --- tsi_ssl_handshaker_factory common methods. --- */
     985             : 
     986         750 : tsi_result tsi_ssl_handshaker_factory_create_handshaker(
     987             :     tsi_ssl_handshaker_factory *self, const char *server_name_indication,
     988             :     tsi_handshaker **handshaker) {
     989         750 :   if (self == NULL || handshaker == NULL) return TSI_INVALID_ARGUMENT;
     990         750 :   return self->create_handshaker(self, server_name_indication, handshaker);
     991             : }
     992             : 
     993         872 : void tsi_ssl_handshaker_factory_destroy(tsi_ssl_handshaker_factory *self) {
     994        1744 :   if (self == NULL) return;
     995         872 :   self->destroy(self);
     996             : }
     997             : 
     998         750 : static tsi_result create_tsi_ssl_handshaker(SSL_CTX *ctx, int is_client,
     999             :                                             const char *server_name_indication,
    1000             :                                             tsi_handshaker **handshaker) {
    1001         750 :   SSL *ssl = SSL_new(ctx);
    1002         750 :   BIO *into_ssl = NULL;
    1003         750 :   BIO *from_ssl = NULL;
    1004         750 :   tsi_ssl_handshaker *impl = NULL;
    1005         750 :   *handshaker = NULL;
    1006         750 :   if (ctx == NULL) {
    1007           0 :     gpr_log(GPR_ERROR, "SSL Context is null. Should never happen.");
    1008           0 :     return TSI_INTERNAL_ERROR;
    1009             :   }
    1010         750 :   if (ssl == NULL) {
    1011           0 :     return TSI_OUT_OF_RESOURCES;
    1012             :   }
    1013         750 :   SSL_set_info_callback(ssl, ssl_info_callback);
    1014             : 
    1015         749 :   into_ssl = BIO_new(BIO_s_mem());
    1016         750 :   from_ssl = BIO_new(BIO_s_mem());
    1017         750 :   if (into_ssl == NULL || from_ssl == NULL) {
    1018           0 :     gpr_log(GPR_ERROR, "BIO_new failed.");
    1019           0 :     SSL_free(ssl);
    1020           0 :     if (into_ssl != NULL) BIO_free(into_ssl);
    1021           0 :     if (from_ssl != NULL) BIO_free(into_ssl);
    1022           0 :     return TSI_OUT_OF_RESOURCES;
    1023             :   }
    1024         750 :   SSL_set_bio(ssl, into_ssl, from_ssl);
    1025         750 :   if (is_client) {
    1026             :     int ssl_result;
    1027         373 :     SSL_set_connect_state(ssl);
    1028         373 :     if (server_name_indication != NULL) {
    1029         373 :       if (!SSL_set_tlsext_host_name(ssl, server_name_indication)) {
    1030           0 :         gpr_log(GPR_ERROR, "Invalid server name indication %s.",
    1031             :                 server_name_indication);
    1032           0 :         SSL_free(ssl);
    1033           0 :         return TSI_INTERNAL_ERROR;
    1034             :       }
    1035             :     }
    1036         373 :     ssl_result = SSL_do_handshake(ssl);
    1037         373 :     ssl_result = SSL_get_error(ssl, ssl_result);
    1038         373 :     if (ssl_result != SSL_ERROR_WANT_READ) {
    1039           0 :       gpr_log(GPR_ERROR,
    1040             :               "Unexpected error received from first SSL_do_handshake call: %s",
    1041             :               ssl_error_string(ssl_result));
    1042           0 :       SSL_free(ssl);
    1043           0 :       return TSI_INTERNAL_ERROR;
    1044             :     }
    1045             :   } else {
    1046         377 :     SSL_set_accept_state(ssl);
    1047             :   }
    1048             : 
    1049         750 :   impl = calloc(1, sizeof(tsi_ssl_handshaker));
    1050         750 :   if (impl == NULL) {
    1051           0 :     SSL_free(ssl);
    1052           0 :     return TSI_OUT_OF_RESOURCES;
    1053             :   }
    1054         750 :   impl->ssl = ssl;
    1055         750 :   impl->into_ssl = into_ssl;
    1056         750 :   impl->from_ssl = from_ssl;
    1057         750 :   impl->result = TSI_HANDSHAKE_IN_PROGRESS;
    1058         750 :   impl->base.vtable = &handshaker_vtable;
    1059         750 :   *handshaker = &impl->base;
    1060         750 :   return TSI_OK;
    1061             : }
    1062             : 
    1063         373 : static int select_protocol_list(const unsigned char **out,
    1064             :                                 unsigned char *outlen,
    1065             :                                 const unsigned char *client_list,
    1066             :                                 size_t client_list_len,
    1067             :                                 const unsigned char *server_list,
    1068             :                                 size_t server_list_len) {
    1069         373 :   const unsigned char *client_current = client_list;
    1070         746 :   while ((unsigned int)(client_current - client_list) < client_list_len) {
    1071         373 :     unsigned char client_current_len = *(client_current++);
    1072         373 :     const unsigned char *server_current = server_list;
    1073        1119 :     while ((server_current >= server_list) &&
    1074         373 :            (gpr_uintptr)(server_current - server_list) < server_list_len) {
    1075         373 :       unsigned char server_current_len = *(server_current++);
    1076         746 :       if ((client_current_len == server_current_len) &&
    1077         373 :           !memcmp(client_current, server_current, server_current_len)) {
    1078         373 :         *out = server_current;
    1079         373 :         *outlen = server_current_len;
    1080         373 :         return SSL_TLSEXT_ERR_OK;
    1081             :       }
    1082           0 :       server_current += server_current_len;
    1083             :     }
    1084           0 :     client_current += client_current_len;
    1085             :   }
    1086           0 :   return SSL_TLSEXT_ERR_NOACK;
    1087             : }
    1088             : 
    1089             : /* --- tsi_ssl__client_handshaker_factory methods implementation. --- */
    1090             : 
    1091         373 : static tsi_result ssl_client_handshaker_factory_create_handshaker(
    1092             :     tsi_ssl_handshaker_factory *self, const char *server_name_indication,
    1093             :     tsi_handshaker **handshaker) {
    1094         373 :   tsi_ssl_client_handshaker_factory *impl =
    1095             :       (tsi_ssl_client_handshaker_factory *)self;
    1096         373 :   return create_tsi_ssl_handshaker(impl->ssl_context, 1, server_name_indication,
    1097             :                                    handshaker);
    1098             : }
    1099             : 
    1100         434 : static void ssl_client_handshaker_factory_destroy(
    1101             :     tsi_ssl_handshaker_factory *self) {
    1102         434 :   tsi_ssl_client_handshaker_factory *impl =
    1103             :       (tsi_ssl_client_handshaker_factory *)self;
    1104         434 :   if (impl->ssl_context != NULL) SSL_CTX_free(impl->ssl_context);
    1105         434 :   if (impl->alpn_protocol_list != NULL) free(impl->alpn_protocol_list);
    1106         434 :   free(impl);
    1107         434 : }
    1108             : 
    1109           0 : static int client_handshaker_factory_npn_callback(SSL *ssl, unsigned char **out,
    1110             :                                                   unsigned char *outlen,
    1111             :                                                   const unsigned char *in,
    1112             :                                                   unsigned int inlen,
    1113             :                                                   void *arg) {
    1114           0 :   tsi_ssl_client_handshaker_factory *factory =
    1115             :       (tsi_ssl_client_handshaker_factory *)arg;
    1116           0 :   return select_protocol_list((const unsigned char **)out, outlen,
    1117           0 :                               factory->alpn_protocol_list,
    1118             :                               factory->alpn_protocol_list_length, in, inlen);
    1119             : }
    1120             : 
    1121             : /* --- tsi_ssl_server_handshaker_factory methods implementation. --- */
    1122             : 
    1123         377 : static tsi_result ssl_server_handshaker_factory_create_handshaker(
    1124             :     tsi_ssl_handshaker_factory *self, const char *server_name_indication,
    1125             :     tsi_handshaker **handshaker) {
    1126         377 :   tsi_ssl_server_handshaker_factory *impl =
    1127             :       (tsi_ssl_server_handshaker_factory *)self;
    1128         377 :   if (impl->ssl_context_count == 0 || server_name_indication != NULL) {
    1129           0 :     return TSI_INVALID_ARGUMENT;
    1130             :   }
    1131             :   /* Create the handshaker with the first context. We will switch if needed
    1132             :      because of SNI in ssl_server_handshaker_factory_servername_callback.  */
    1133         377 :   return create_tsi_ssl_handshaker(impl->ssl_contexts[0], 0, NULL, handshaker);
    1134             : }
    1135             : 
    1136         438 : static void ssl_server_handshaker_factory_destroy(
    1137             :     tsi_ssl_handshaker_factory *self) {
    1138         438 :   tsi_ssl_server_handshaker_factory *impl =
    1139             :       (tsi_ssl_server_handshaker_factory *)self;
    1140             :   size_t i;
    1141         876 :   for (i = 0; i < impl->ssl_context_count; i++) {
    1142         438 :     if (impl->ssl_contexts[i] != NULL) {
    1143         438 :       SSL_CTX_free(impl->ssl_contexts[i]);
    1144         438 :       tsi_peer_destruct(&impl->ssl_context_x509_subject_names[i]);
    1145             :     }
    1146             :   }
    1147         438 :   if (impl->ssl_contexts != NULL) free(impl->ssl_contexts);
    1148         438 :   if (impl->ssl_context_x509_subject_names != NULL) {
    1149         438 :     free(impl->ssl_context_x509_subject_names);
    1150             :   }
    1151         438 :   if (impl->alpn_protocol_list != NULL) free(impl->alpn_protocol_list);
    1152         438 :   free(impl);
    1153         438 : }
    1154             : 
    1155        1577 : static int does_entry_match_name(const char *entry, size_t entry_length,
    1156             :                                  const char *name) {
    1157             :   const char *dot;
    1158        1577 :   const char *name_subdomain = NULL;
    1159        1577 :   size_t name_length = strlen(name);
    1160             :   size_t name_subdomain_length;
    1161        1577 :   if (entry_length == 0) return 0;
    1162             : 
    1163             :   /* Take care of '.' terminations. */
    1164        1576 :   if (name[name_length - 1] == '.') {
    1165          10 :     name_length--;
    1166             :   }
    1167        1576 :   if (entry[entry_length - 1] == '.') {
    1168          11 :     entry_length--;
    1169          11 :     if (entry_length == 0) return 0;
    1170             :   }
    1171             : 
    1172        1590 :   if ((name_length == entry_length) &&
    1173          15 :       strncmp(name, entry, entry_length) == 0) {
    1174          10 :     return 1; /* Perfect match. */
    1175             :   }
    1176        1565 :   if (entry[0] != '*') return 0;
    1177             : 
    1178             :   /* Wildchar subdomain matching. */
    1179        1541 :   if (entry_length < 3 || entry[1] != '.') { /* At least *.x */
    1180           6 :     gpr_log(GPR_ERROR, "Invalid wildchar entry.");
    1181           6 :     return 0;
    1182             :   }
    1183        1535 :   name_subdomain = strchr(name, '.');
    1184        1535 :   if (name_subdomain == NULL) return 0;
    1185        1535 :   name_subdomain_length = strlen(name_subdomain);
    1186        1535 :   if (name_subdomain_length < 2) return 0;
    1187        1535 :   name_subdomain++; /* Starts after the dot. */
    1188        1535 :   name_subdomain_length--;
    1189        1535 :   entry += 2; /* Remove *. */
    1190        1535 :   entry_length -= 2;
    1191        1535 :   dot = strchr(name_subdomain, '.');
    1192        1535 :   if ((dot == NULL) || (dot == &name_subdomain[name_subdomain_length - 1])) {
    1193          10 :     gpr_log(GPR_ERROR, "Invalid toplevel subdomain: %s", name_subdomain);
    1194          10 :     return 0;
    1195             :   }
    1196        1525 :   if (name_subdomain[name_subdomain_length - 1] == '.') {
    1197           2 :     name_subdomain_length--;
    1198             :   }
    1199        3037 :   return ((entry_length > 0) && (name_subdomain_length == entry_length) &&
    1200        1512 :           strncmp(entry, name_subdomain, entry_length) == 0);
    1201             : }
    1202             : 
    1203         373 : static int ssl_server_handshaker_factory_servername_callback(SSL *ssl, int *ap,
    1204             :                                                              void *arg) {
    1205         373 :   tsi_ssl_server_handshaker_factory *impl =
    1206             :       (tsi_ssl_server_handshaker_factory *)arg;
    1207         373 :   size_t i = 0;
    1208         373 :   const char *servername = SSL_get_servername(ssl, TLSEXT_NAMETYPE_host_name);
    1209         373 :   if (servername == NULL || strlen(servername) == 0) {
    1210           0 :     return SSL_TLSEXT_ERR_NOACK;
    1211             :   }
    1212             : 
    1213         373 :   for (i = 0; i < impl->ssl_context_count; i++) {
    1214         373 :     if (tsi_ssl_peer_matches_name(&impl->ssl_context_x509_subject_names[i],
    1215             :                                   servername)) {
    1216         373 :       SSL_set_SSL_CTX(ssl, impl->ssl_contexts[i]);
    1217         373 :       return SSL_TLSEXT_ERR_OK;
    1218             :     }
    1219             :   }
    1220           0 :   gpr_log(GPR_ERROR, "No match found for server name: %s.", servername);
    1221           0 :   return SSL_TLSEXT_ERR_ALERT_WARNING;
    1222             : }
    1223             : 
    1224             : #if TSI_OPENSSL_ALPN_SUPPORT
    1225         373 : static int server_handshaker_factory_alpn_callback(
    1226             :     SSL *ssl, const unsigned char **out, unsigned char *outlen,
    1227             :     const unsigned char *in, unsigned int inlen, void *arg) {
    1228         373 :   tsi_ssl_server_handshaker_factory *factory =
    1229             :       (tsi_ssl_server_handshaker_factory *)arg;
    1230         746 :   return select_protocol_list(out, outlen, in, inlen,
    1231         373 :                               factory->alpn_protocol_list,
    1232             :                               factory->alpn_protocol_list_length);
    1233             : }
    1234             : #endif /* TSI_OPENSSL_ALPN_SUPPORT */
    1235             : 
    1236           0 : static int server_handshaker_factory_npn_advertised_callback(
    1237             :     SSL *ssl, const unsigned char **out, unsigned int *outlen, void *arg) {
    1238           0 :   tsi_ssl_server_handshaker_factory *factory =
    1239             :       (tsi_ssl_server_handshaker_factory *)arg;
    1240           0 :   *out = factory->alpn_protocol_list;
    1241           0 :   GPR_ASSERT(factory->alpn_protocol_list_length <= UINT_MAX);
    1242           0 :   *outlen = (unsigned int)factory->alpn_protocol_list_length;
    1243           0 :   return SSL_TLSEXT_ERR_OK;
    1244             : }
    1245             : 
    1246             : /* --- tsi_ssl_handshaker_factory constructors. --- */
    1247             : 
    1248         434 : tsi_result tsi_create_ssl_client_handshaker_factory(
    1249             :     const unsigned char *pem_private_key, size_t pem_private_key_size,
    1250             :     const unsigned char *pem_cert_chain, size_t pem_cert_chain_size,
    1251             :     const unsigned char *pem_root_certs, size_t pem_root_certs_size,
    1252             :     const char *cipher_list, const unsigned char **alpn_protocols,
    1253             :     const unsigned char *alpn_protocols_lengths, uint16_t num_alpn_protocols,
    1254             :     tsi_ssl_handshaker_factory **factory) {
    1255         434 :   SSL_CTX *ssl_context = NULL;
    1256         434 :   tsi_ssl_client_handshaker_factory *impl = NULL;
    1257         434 :   tsi_result result = TSI_OK;
    1258             : 
    1259         434 :   gpr_once_init(&init_openssl_once, init_openssl);
    1260             : 
    1261         434 :   if (factory == NULL) return TSI_INVALID_ARGUMENT;
    1262         434 :   *factory = NULL;
    1263         434 :   if (pem_root_certs == NULL) return TSI_INVALID_ARGUMENT;
    1264             : 
    1265         434 :   ssl_context = SSL_CTX_new(TLSv1_2_method());
    1266         434 :   if (ssl_context == NULL) {
    1267           0 :     gpr_log(GPR_ERROR, "Could not create ssl context.");
    1268           0 :     return TSI_INVALID_ARGUMENT;
    1269             :   }
    1270             : 
    1271         434 :   impl = calloc(1, sizeof(tsi_ssl_client_handshaker_factory));
    1272         434 :   if (impl == NULL) {
    1273           0 :     SSL_CTX_free(ssl_context);
    1274           0 :     return TSI_OUT_OF_RESOURCES;
    1275             :   }
    1276         434 :   impl->ssl_context = ssl_context;
    1277             : 
    1278             :   do {
    1279         434 :     result =
    1280             :         populate_ssl_context(ssl_context, pem_private_key, pem_private_key_size,
    1281             :                              pem_cert_chain, pem_cert_chain_size, cipher_list);
    1282         434 :     if (result != TSI_OK) break;
    1283         434 :     result = ssl_ctx_load_verification_certs(ssl_context, pem_root_certs,
    1284             :                                              pem_root_certs_size, NULL);
    1285         434 :     if (result != TSI_OK) {
    1286           0 :       gpr_log(GPR_ERROR, "Cannot load server root certificates.");
    1287           0 :       break;
    1288             :     }
    1289             : 
    1290         434 :     if (num_alpn_protocols != 0) {
    1291         434 :       result = build_alpn_protocol_name_list(
    1292             :           alpn_protocols, alpn_protocols_lengths, num_alpn_protocols,
    1293             :           &impl->alpn_protocol_list, &impl->alpn_protocol_list_length);
    1294         434 :       if (result != TSI_OK) {
    1295           0 :         gpr_log(GPR_ERROR, "Building alpn list failed with error %s.",
    1296             :                 tsi_result_to_string(result));
    1297           0 :         break;
    1298             :       }
    1299             : #if TSI_OPENSSL_ALPN_SUPPORT
    1300         434 :       GPR_ASSERT(impl->alpn_protocol_list_length < UINT_MAX);
    1301         868 :       if (SSL_CTX_set_alpn_protos(
    1302         434 :               ssl_context, impl->alpn_protocol_list,
    1303         434 :               (unsigned int)impl->alpn_protocol_list_length)) {
    1304           0 :         gpr_log(GPR_ERROR, "Could not set alpn protocol list to context.");
    1305           0 :         result = TSI_INVALID_ARGUMENT;
    1306           0 :         break;
    1307             :       }
    1308             : #endif /* TSI_OPENSSL_ALPN_SUPPORT */
    1309         434 :       SSL_CTX_set_next_proto_select_cb(
    1310             :           ssl_context, client_handshaker_factory_npn_callback, impl);
    1311             :     }
    1312             :   } while (0);
    1313         434 :   if (result != TSI_OK) {
    1314           0 :     ssl_client_handshaker_factory_destroy(&impl->base);
    1315           0 :     return result;
    1316             :   }
    1317         434 :   SSL_CTX_set_verify(ssl_context, SSL_VERIFY_PEER, NULL);
    1318             :   /* TODO(jboeuf): Add revocation verification. */
    1319             : 
    1320         434 :   impl->base.create_handshaker =
    1321             :       ssl_client_handshaker_factory_create_handshaker;
    1322         434 :   impl->base.destroy = ssl_client_handshaker_factory_destroy;
    1323         434 :   *factory = &impl->base;
    1324         434 :   return TSI_OK;
    1325             : }
    1326             : 
    1327         438 : tsi_result tsi_create_ssl_server_handshaker_factory(
    1328             :     const unsigned char **pem_private_keys,
    1329             :     const size_t *pem_private_keys_sizes, const unsigned char **pem_cert_chains,
    1330             :     const size_t *pem_cert_chains_sizes, size_t key_cert_pair_count,
    1331             :     const unsigned char *pem_client_root_certs,
    1332             :     size_t pem_client_root_certs_size, int force_client_auth,
    1333             :     const char *cipher_list, const unsigned char **alpn_protocols,
    1334             :     const unsigned char *alpn_protocols_lengths, uint16_t num_alpn_protocols,
    1335             :     tsi_ssl_handshaker_factory **factory) {
    1336         438 :   tsi_ssl_server_handshaker_factory *impl = NULL;
    1337         438 :   tsi_result result = TSI_OK;
    1338         438 :   size_t i = 0;
    1339             : 
    1340         438 :   gpr_once_init(&init_openssl_once, init_openssl);
    1341             : 
    1342         438 :   if (factory == NULL) return TSI_INVALID_ARGUMENT;
    1343         438 :   *factory = NULL;
    1344         438 :   if (key_cert_pair_count == 0 || pem_private_keys == NULL ||
    1345             :       pem_cert_chains == NULL) {
    1346           0 :     return TSI_INVALID_ARGUMENT;
    1347             :   }
    1348             : 
    1349         438 :   impl = calloc(1, sizeof(tsi_ssl_server_handshaker_factory));
    1350         438 :   if (impl == NULL) return TSI_OUT_OF_RESOURCES;
    1351         438 :   impl->base.create_handshaker =
    1352             :       ssl_server_handshaker_factory_create_handshaker;
    1353         438 :   impl->base.destroy = ssl_server_handshaker_factory_destroy;
    1354         438 :   impl->ssl_contexts = calloc(key_cert_pair_count, sizeof(SSL_CTX *));
    1355         438 :   impl->ssl_context_x509_subject_names =
    1356         438 :       calloc(key_cert_pair_count, sizeof(tsi_peer));
    1357         876 :   if (impl->ssl_contexts == NULL ||
    1358         438 :       impl->ssl_context_x509_subject_names == NULL) {
    1359           0 :     tsi_ssl_handshaker_factory_destroy(&impl->base);
    1360           0 :     return TSI_OUT_OF_RESOURCES;
    1361             :   }
    1362         438 :   impl->ssl_context_count = key_cert_pair_count;
    1363             : 
    1364         438 :   if (num_alpn_protocols > 0) {
    1365         438 :     result = build_alpn_protocol_name_list(
    1366             :         alpn_protocols, alpn_protocols_lengths, num_alpn_protocols,
    1367             :         &impl->alpn_protocol_list, &impl->alpn_protocol_list_length);
    1368         438 :     if (result != TSI_OK) {
    1369           0 :       tsi_ssl_handshaker_factory_destroy(&impl->base);
    1370           0 :       return result;
    1371             :     }
    1372             :   }
    1373             : 
    1374         876 :   for (i = 0; i < key_cert_pair_count; i++) {
    1375             :     do {
    1376         438 :       impl->ssl_contexts[i] = SSL_CTX_new(TLSv1_2_method());
    1377         438 :       if (impl->ssl_contexts[i] == NULL) {
    1378           0 :         gpr_log(GPR_ERROR, "Could not create ssl context.");
    1379           0 :         result = TSI_OUT_OF_RESOURCES;
    1380           0 :         break;
    1381             :       }
    1382        2190 :       result = populate_ssl_context(
    1383        1314 :           impl->ssl_contexts[i], pem_private_keys[i], pem_private_keys_sizes[i],
    1384         876 :           pem_cert_chains[i], pem_cert_chains_sizes[i], cipher_list);
    1385         438 :       if (result != TSI_OK) break;
    1386             : 
    1387         438 :       if (pem_client_root_certs != NULL) {
    1388           0 :         int flags = SSL_VERIFY_PEER;
    1389           0 :         STACK_OF(X509_NAME) *root_names = NULL;
    1390           0 :         result = ssl_ctx_load_verification_certs(
    1391           0 :             impl->ssl_contexts[i], pem_client_root_certs,
    1392             :             pem_client_root_certs_size, &root_names);
    1393           0 :         if (result != TSI_OK) {
    1394           0 :           gpr_log(GPR_ERROR, "Invalid verification certs.");
    1395           0 :           break;
    1396             :         }
    1397           0 :         SSL_CTX_set_client_CA_list(impl->ssl_contexts[i], root_names);
    1398           0 :         if (force_client_auth) flags |= SSL_VERIFY_FAIL_IF_NO_PEER_CERT;
    1399           0 :         SSL_CTX_set_verify(impl->ssl_contexts[i], flags, NULL);
    1400             :         /* TODO(jboeuf): Add revocation verification. */
    1401             :       }
    1402             : 
    1403        1314 :       result = extract_x509_subject_names_from_pem_cert(
    1404         876 :           pem_cert_chains[i], pem_cert_chains_sizes[i],
    1405         438 :           &impl->ssl_context_x509_subject_names[i]);
    1406         438 :       if (result != TSI_OK) break;
    1407             : 
    1408         438 :       SSL_CTX_set_tlsext_servername_callback(
    1409             :           impl->ssl_contexts[i],
    1410             :           ssl_server_handshaker_factory_servername_callback);
    1411         438 :       SSL_CTX_set_tlsext_servername_arg(impl->ssl_contexts[i], impl);
    1412             : #if TSI_OPENSSL_ALPN_SUPPORT
    1413         438 :       SSL_CTX_set_alpn_select_cb(impl->ssl_contexts[i],
    1414             :                                  server_handshaker_factory_alpn_callback, impl);
    1415             : #endif /* TSI_OPENSSL_ALPN_SUPPORT */
    1416         438 :       SSL_CTX_set_next_protos_advertised_cb(
    1417         438 :           impl->ssl_contexts[i],
    1418             :           server_handshaker_factory_npn_advertised_callback, impl);
    1419             :     } while (0);
    1420             : 
    1421         438 :     if (result != TSI_OK) {
    1422           0 :       tsi_ssl_handshaker_factory_destroy(&impl->base);
    1423           0 :       return result;
    1424             :     }
    1425             :   }
    1426         438 :   *factory = &impl->base;
    1427         438 :   return TSI_OK;
    1428             : }
    1429             : 
    1430             : /* --- tsi_ssl utils. --- */
    1431             : 
    1432        1559 : int tsi_ssl_peer_matches_name(const tsi_peer *peer, const char *name) {
    1433        1559 :   size_t i = 0;
    1434        1559 :   size_t san_count = 0;
    1435        1559 :   const tsi_peer_property *cn_property = NULL;
    1436             : 
    1437             :   /* For now reject what looks like an IP address. */
    1438        1559 :   if (looks_like_ip_address(name)) return 0;
    1439             : 
    1440             :   /* Check the SAN first. */
    1441        4265 :   for (i = 0; i < peer->property_count; i++) {
    1442        4207 :     const tsi_peer_property *property = &peer->properties[i];
    1443        4207 :     if (property->name == NULL) continue;
    1444        4207 :     if (strcmp(property->name,
    1445             :                TSI_X509_SUBJECT_ALTERNATIVE_NAME_PEER_PROPERTY) == 0) {
    1446        1524 :       san_count++;
    1447        1524 :       if (does_entry_match_name(property->value.data, property->value.length,
    1448             :                                 name)) {
    1449        1500 :         return 1;
    1450             :       }
    1451        2683 :     } else if (strcmp(property->name,
    1452             :                       TSI_X509_SUBJECT_COMMON_NAME_PEER_PROPERTY) == 0) {
    1453        1558 :       cn_property = property;
    1454             :     }
    1455             :   }
    1456             : 
    1457             :   /* If there's no SAN, try the CN. */
    1458          58 :   if (san_count == 0 && cn_property != NULL) {
    1459          53 :     if (does_entry_match_name(cn_property->value.data,
    1460             :                               cn_property->value.length, name)) {
    1461          21 :       return 1;
    1462             :     }
    1463             :   }
    1464             : 
    1465          37 :   return 0; /* Not found. */
    1466             : }

Generated by: LCOV version 1.10