• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  *
3  * Copyright 2015 gRPC authors.
4  *
5  * Licensed under the Apache License, Version 2.0 (the "License");
6  * you may not use this file except in compliance with the License.
7  * You may obtain a copy of the License at
8  *
9  *     http://www.apache.org/licenses/LICENSE-2.0
10  *
11  * Unless required by applicable law or agreed to in writing, software
12  * distributed under the License is distributed on an "AS IS" BASIS,
13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  * See the License for the specific language governing permissions and
15  * limitations under the License.
16  *
17  */
18 
19 #ifndef GRPC_CORE_TSI_SSL_TRANSPORT_SECURITY_H
20 #define GRPC_CORE_TSI_SSL_TRANSPORT_SECURITY_H
21 
22 #include <grpc/support/port_platform.h>
23 
24 #include <grpc/grpc_security_constants.h>
25 #include "absl/strings/string_view.h"
26 #include "src/core/tsi/transport_security_interface.h"
27 
28 extern "C" {
29 #include <openssl/x509.h>
30 }
31 
32 /* Value for the TSI_CERTIFICATE_TYPE_PEER_PROPERTY property for X509 certs. */
33 #define TSI_X509_CERTIFICATE_TYPE "X509"
34 
35 /* This property is of type TSI_PEER_PROPERTY_STRING.  */
36 #define TSI_X509_SUBJECT_COMMON_NAME_PEER_PROPERTY "x509_subject_common_name"
37 #define TSI_X509_SUBJECT_ALTERNATIVE_NAME_PEER_PROPERTY \
38   "x509_subject_alternative_name"
39 #define TSI_SSL_SESSION_REUSED_PEER_PROPERTY "ssl_session_reused"
40 #define TSI_X509_PEM_CERT_PROPERTY "x509_pem_cert"
41 #define TSI_X509_PEM_CERT_CHAIN_PROPERTY "x509_pem_cert_chain"
42 #define TSI_SSL_ALPN_SELECTED_PROTOCOL "ssl_alpn_selected_protocol"
43 #define TSI_X509_DNS_PEER_PROPERTY "x509_dns"
44 #define TSI_X509_URI_PEER_PROPERTY "x509_uri"
45 #define TSI_X509_EMAIL_PEER_PROPERTY "x509_email"
46 #define TSI_X509_IP_PEER_PROPERTY "x509_ip"
47 
48 /* --- tsi_ssl_root_certs_store object ---
49 
50    This object stores SSL root certificates. It can be shared by multiple SSL
51    context. */
52 typedef struct tsi_ssl_root_certs_store tsi_ssl_root_certs_store;
53 
54 /* Given a NULL-terminated string containing the PEM encoding of the root
55    certificates, creates a tsi_ssl_root_certs_store object. */
56 tsi_ssl_root_certs_store* tsi_ssl_root_certs_store_create(
57     const char* pem_roots);
58 
59 /* Destroys the tsi_ssl_root_certs_store object. */
60 void tsi_ssl_root_certs_store_destroy(tsi_ssl_root_certs_store* self);
61 
62 /* --- tsi_ssl_session_cache object ---
63 
64    Cache for SSL sessions for sessions resumption.  */
65 
66 typedef struct tsi_ssl_session_cache tsi_ssl_session_cache;
67 
68 /* Create LRU cache for SSL sessions with \a capacity.  */
69 tsi_ssl_session_cache* tsi_ssl_session_cache_create_lru(size_t capacity);
70 
71 /* Increment reference counter of \a cache.  */
72 void tsi_ssl_session_cache_ref(tsi_ssl_session_cache* cache);
73 
74 /* Decrement reference counter of \a cache.  */
75 void tsi_ssl_session_cache_unref(tsi_ssl_session_cache* cache);
76 
77 /* --- tsi_ssl_client_handshaker_factory object ---
78 
79    This object creates a client tsi_handshaker objects implemented in terms of
80    the TLS 1.2 specificiation.  */
81 
82 typedef struct tsi_ssl_client_handshaker_factory
83     tsi_ssl_client_handshaker_factory;
84 
85 /* Object that holds a private key / certificate chain pair in PEM format. */
86 struct tsi_ssl_pem_key_cert_pair {
87   /* private_key is the NULL-terminated string containing the PEM encoding of
88      the client's private key. */
89   const char* private_key;
90 
91   /* cert_chain is the NULL-terminated string containing the PEM encoding of
92      the client's certificate chain. */
93   const char* cert_chain;
94 };
95 /* TO BE DEPRECATED.
96    Creates a client handshaker factory.
97    - pem_key_cert_pair is a pointer to the object containing client's private
98      key and certificate chain. This parameter can be NULL if the client does
99      not have such a key/cert pair.
100    - pem_roots_cert is the NULL-terminated string containing the PEM encoding of
101      the server root certificates.
102    - cipher_suites contains an optional list of the ciphers that the client
103      supports. The format of this string is described in:
104      https://www.openssl.org/docs/apps/ciphers.html.
105      This parameter can be set to NULL to use the default set of ciphers.
106      TODO(jboeuf): Revisit the format of this parameter.
107    - alpn_protocols is an array containing the NULL terminated protocol names
108      that the handshakers created with this factory support. This parameter can
109      be NULL.
110    - num_alpn_protocols is the number of alpn protocols and associated lengths
111      specified. If this parameter is 0, the other alpn parameters must be NULL.
112    - factory is the address of the factory pointer to be created.
113 
114    - This method returns TSI_OK on success or TSI_INVALID_PARAMETER in the case
115      where a parameter is invalid.  */
116 tsi_result tsi_create_ssl_client_handshaker_factory(
117     const tsi_ssl_pem_key_cert_pair* pem_key_cert_pair,
118     const char* pem_root_certs, const char* cipher_suites,
119     const char** alpn_protocols, uint16_t num_alpn_protocols,
120     tsi_ssl_client_handshaker_factory** factory);
121 
122 struct tsi_ssl_client_handshaker_options {
123   /* pem_key_cert_pair is a pointer to the object containing client's private
124      key and certificate chain. This parameter can be NULL if the client does
125      not have such a key/cert pair. */
126   const tsi_ssl_pem_key_cert_pair* pem_key_cert_pair;
127   /* pem_roots_cert is the NULL-terminated string containing the PEM encoding of
128      the client root certificates. */
129   const char* pem_root_certs;
130   /* root_store is a pointer to the ssl_root_certs_store object. If root_store
131     is not nullptr and SSL implementation permits, root_store will be used as
132     root certificates. Otherwise, pem_roots_cert will be used to load server
133     root certificates. */
134   const tsi_ssl_root_certs_store* root_store;
135   /* cipher_suites contains an optional list of the ciphers that the client
136      supports. The format of this string is described in:
137      https://www.openssl.org/docs/apps/ciphers.html.
138      This parameter can be set to NULL to use the default set of ciphers.
139      TODO(jboeuf): Revisit the format of this parameter. */
140   const char* cipher_suites;
141   /* alpn_protocols is an array containing the NULL terminated protocol names
142      that the handshakers created with this factory support. This parameter can
143      be NULL. */
144   const char** alpn_protocols;
145   /* num_alpn_protocols is the number of alpn protocols and associated lengths
146      specified. If this parameter is 0, the other alpn parameters must be
147      NULL. */
148   size_t num_alpn_protocols;
149   /* ssl_session_cache is a cache for reusable client-side sessions. */
150   tsi_ssl_session_cache* session_cache;
151 
152   /* skip server certificate verification. */
153   bool skip_server_certificate_verification;
154 
155   /* The min and max TLS versions that will be negotiated by the handshaker. */
156   tsi_tls_version min_tls_version;
157   tsi_tls_version max_tls_version;
158 
tsi_ssl_client_handshaker_optionstsi_ssl_client_handshaker_options159   tsi_ssl_client_handshaker_options()
160       : pem_key_cert_pair(nullptr),
161         pem_root_certs(nullptr),
162         root_store(nullptr),
163         cipher_suites(nullptr),
164         alpn_protocols(nullptr),
165         num_alpn_protocols(0),
166         session_cache(nullptr),
167         skip_server_certificate_verification(false),
168         min_tls_version(tsi_tls_version::TSI_TLS1_2),
169         max_tls_version(tsi_tls_version::TSI_TLS1_3) {}
170 };
171 
172 /* Creates a client handshaker factory.
173    - options is the options used to create a factory.
174    - factory is the address of the factory pointer to be created.
175 
176    - This method returns TSI_OK on success or TSI_INVALID_PARAMETER in the case
177      where a parameter is invalid. */
178 tsi_result tsi_create_ssl_client_handshaker_factory_with_options(
179     const tsi_ssl_client_handshaker_options* options,
180     tsi_ssl_client_handshaker_factory** factory);
181 
182 /* Creates a client handshaker.
183   - factory is the factory from which the handshaker will be created.
184   - server_name_indication indicates the name of the server the client is
185     trying to connect to which will be relayed to the server using the SNI
186     extension.
187   - handshaker is the address of the handshaker pointer to be created.
188 
189   - This method returns TSI_OK on success or TSI_INVALID_PARAMETER in the case
190     where a parameter is invalid.  */
191 tsi_result tsi_ssl_client_handshaker_factory_create_handshaker(
192     tsi_ssl_client_handshaker_factory* factory,
193     const char* server_name_indication, tsi_handshaker** handshaker);
194 
195 /* Decrements reference count of the handshaker factory. Handshaker factory will
196  * be destroyed once no references exist. */
197 void tsi_ssl_client_handshaker_factory_unref(
198     tsi_ssl_client_handshaker_factory* factory);
199 
200 /* --- tsi_ssl_server_handshaker_factory object ---
201 
202    This object creates a client tsi_handshaker objects implemented in terms of
203    the TLS 1.2 specificiation.  */
204 
205 typedef struct tsi_ssl_server_handshaker_factory
206     tsi_ssl_server_handshaker_factory;
207 
208 /* TO BE DEPRECATED.
209    Creates a server handshaker factory.
210    - pem_key_cert_pairs is an array private key / certificate chains of the
211      server.
212    - num_key_cert_pairs is the number of items in the pem_key_cert_pairs array.
213    - pem_root_certs is the NULL-terminated string containing the PEM encoding
214      of the client root certificates. This parameter may be NULL if the server
215      does not want the client to be authenticated with SSL.
216    - cipher_suites contains an optional list of the ciphers that the server
217      supports. The format of this string is described in:
218      https://www.openssl.org/docs/apps/ciphers.html.
219      This parameter can be set to NULL to use the default set of ciphers.
220      TODO(jboeuf): Revisit the format of this parameter.
221    - alpn_protocols is an array containing the NULL terminated protocol names
222      that the handshakers created with this factory support. This parameter can
223      be NULL.
224    - num_alpn_protocols is the number of alpn protocols and associated lengths
225      specified. If this parameter is 0, the other alpn parameters must be NULL.
226    - factory is the address of the factory pointer to be created.
227 
228    - This method returns TSI_OK on success or TSI_INVALID_PARAMETER in the case
229      where a parameter is invalid.  */
230 tsi_result tsi_create_ssl_server_handshaker_factory(
231     const tsi_ssl_pem_key_cert_pair* pem_key_cert_pairs,
232     size_t num_key_cert_pairs, const char* pem_client_root_certs,
233     int force_client_auth, const char* cipher_suites,
234     const char** alpn_protocols, uint16_t num_alpn_protocols,
235     tsi_ssl_server_handshaker_factory** factory);
236 
237 /* TO BE DEPRECATED.
238    Same as tsi_create_ssl_server_handshaker_factory method except uses
239    tsi_client_certificate_request_type to support more ways to handle client
240    certificate authentication.
241    - client_certificate_request, if set to non-zero will force the client to
242      authenticate with an SSL cert. Note that this option is ignored if
243      pem_client_root_certs is NULL or pem_client_roots_certs_size is 0 */
244 tsi_result tsi_create_ssl_server_handshaker_factory_ex(
245     const tsi_ssl_pem_key_cert_pair* pem_key_cert_pairs,
246     size_t num_key_cert_pairs, const char* pem_client_root_certs,
247     tsi_client_certificate_request_type client_certificate_request,
248     const char* cipher_suites, const char** alpn_protocols,
249     uint16_t num_alpn_protocols, tsi_ssl_server_handshaker_factory** factory);
250 
251 struct tsi_ssl_server_handshaker_options {
252   /* pem_key_cert_pairs is an array private key / certificate chains of the
253      server. */
254   const tsi_ssl_pem_key_cert_pair* pem_key_cert_pairs;
255   /* num_key_cert_pairs is the number of items in the pem_key_cert_pairs
256      array. */
257   size_t num_key_cert_pairs;
258   /* pem_root_certs is the NULL-terminated string containing the PEM encoding
259      of the server root certificates. This parameter may be NULL if the server
260      does not want the client to be authenticated with SSL. */
261   const char* pem_client_root_certs;
262   /* client_certificate_request, if set to non-zero will force the client to
263      authenticate with an SSL cert. Note that this option is ignored if
264      pem_client_root_certs is NULL or pem_client_roots_certs_size is 0. */
265   tsi_client_certificate_request_type client_certificate_request;
266   /* cipher_suites contains an optional list of the ciphers that the server
267      supports. The format of this string is described in:
268      https://www.openssl.org/docs/apps/ciphers.html.
269      This parameter can be set to NULL to use the default set of ciphers.
270      TODO(jboeuf): Revisit the format of this parameter. */
271   const char* cipher_suites;
272   /* alpn_protocols is an array containing the NULL terminated protocol names
273      that the handshakers created with this factory support. This parameter can
274      be NULL. */
275   const char** alpn_protocols;
276   /* num_alpn_protocols is the number of alpn protocols and associated lengths
277      specified. If this parameter is 0, the other alpn parameters must be
278      NULL. */
279   uint16_t num_alpn_protocols;
280   /* session_ticket_key is optional key for encrypting session keys. If
281      parameter is not specified it must be NULL. */
282   const char* session_ticket_key;
283   /* session_ticket_key_size is a size of session ticket encryption key. */
284   size_t session_ticket_key_size;
285   /* The min and max TLS versions that will be negotiated by the handshaker. */
286   tsi_tls_version min_tls_version;
287   tsi_tls_version max_tls_version;
288 
tsi_ssl_server_handshaker_optionstsi_ssl_server_handshaker_options289   tsi_ssl_server_handshaker_options()
290       : pem_key_cert_pairs(nullptr),
291         num_key_cert_pairs(0),
292         pem_client_root_certs(nullptr),
293         client_certificate_request(TSI_DONT_REQUEST_CLIENT_CERTIFICATE),
294         cipher_suites(nullptr),
295         alpn_protocols(nullptr),
296         num_alpn_protocols(0),
297         session_ticket_key(nullptr),
298         session_ticket_key_size(0),
299         min_tls_version(tsi_tls_version::TSI_TLS1_2),
300         max_tls_version(tsi_tls_version::TSI_TLS1_3) {}
301 };
302 
303 /* Creates a server handshaker factory.
304    - options is the options used to create a factory.
305    - factory is the address of the factory pointer to be created.
306 
307    - This method returns TSI_OK on success or TSI_INVALID_PARAMETER in the case
308      where a parameter is invalid. */
309 tsi_result tsi_create_ssl_server_handshaker_factory_with_options(
310     const tsi_ssl_server_handshaker_options* options,
311     tsi_ssl_server_handshaker_factory** factory);
312 
313 /* Creates a server handshaker.
314   - factory is the factory from which the handshaker will be created.
315   - handshaker is the address of the handshaker pointer to be created.
316 
317   - This method returns TSI_OK on success or TSI_INVALID_PARAMETER in the case
318     where a parameter is invalid.  */
319 tsi_result tsi_ssl_server_handshaker_factory_create_handshaker(
320     tsi_ssl_server_handshaker_factory* factory, tsi_handshaker** handshaker);
321 
322 /* Decrements reference count of the handshaker factory. Handshaker factory will
323  * be destroyed once no references exist. */
324 void tsi_ssl_server_handshaker_factory_unref(
325     tsi_ssl_server_handshaker_factory* factory);
326 
327 /* Util that checks that an ssl peer matches a specific name.
328    Still TODO(jboeuf):
329    - handle mixed case.
330    - handle %encoded chars.
331    - handle public suffix wildchar more strictly (e.g. *.co.uk) */
332 int tsi_ssl_peer_matches_name(const tsi_peer* peer, absl::string_view name);
333 
334 /* --- Testing support. ---
335 
336    These functions and typedefs are not intended to be used outside of testing.
337    */
338 
339 /* Base type of client and server handshaker factories. */
340 typedef struct tsi_ssl_handshaker_factory tsi_ssl_handshaker_factory;
341 
342 /* Function pointer to handshaker_factory destructor. */
343 typedef void (*tsi_ssl_handshaker_factory_destructor)(
344     tsi_ssl_handshaker_factory* factory);
345 
346 /* Virtual table for tsi_ssl_handshaker_factory. */
347 struct tsi_ssl_handshaker_factory_vtable {
348   tsi_ssl_handshaker_factory_destructor destroy;
349 };
350 /* Set destructor of handshaker_factory to new_destructor, returns previous
351    destructor. */
352 const tsi_ssl_handshaker_factory_vtable* tsi_ssl_handshaker_factory_swap_vtable(
353     tsi_ssl_handshaker_factory* factory,
354     tsi_ssl_handshaker_factory_vtable* new_vtable);
355 
356 /* Exposed for testing only. */
357 tsi_result tsi_ssl_extract_x509_subject_names_from_pem_cert(
358     const char* pem_cert, tsi_peer* peer);
359 
360 /* Exposed for testing only. */
361 tsi_result tsi_ssl_get_cert_chain_contents(STACK_OF(X509) * peer_chain,
362                                            tsi_peer_property* property);
363 
364 #endif /* GRPC_CORE_TSI_SSL_TRANSPORT_SECURITY_H */
365