1*6236dae4SAndroid Build Coastguard Worker /***************************************************************************
2*6236dae4SAndroid Build Coastguard Worker * _ _ ____ _
3*6236dae4SAndroid Build Coastguard Worker * Project ___| | | | _ \| |
4*6236dae4SAndroid Build Coastguard Worker * / __| | | | |_) | |
5*6236dae4SAndroid Build Coastguard Worker * | (__| |_| | _ <| |___
6*6236dae4SAndroid Build Coastguard Worker * \___|\___/|_| \_\_____|
7*6236dae4SAndroid Build Coastguard Worker *
8*6236dae4SAndroid Build Coastguard Worker * Copyright (C) Daniel Stenberg, <[email protected]>, et al.
9*6236dae4SAndroid Build Coastguard Worker *
10*6236dae4SAndroid Build Coastguard Worker * This software is licensed as described in the file COPYING, which
11*6236dae4SAndroid Build Coastguard Worker * you should have received as part of this distribution. The terms
12*6236dae4SAndroid Build Coastguard Worker * are also available at https://curl.se/docs/copyright.html.
13*6236dae4SAndroid Build Coastguard Worker *
14*6236dae4SAndroid Build Coastguard Worker * You may opt to use, copy, modify, merge, publish, distribute and/or sell
15*6236dae4SAndroid Build Coastguard Worker * copies of the Software, and permit persons to whom the Software is
16*6236dae4SAndroid Build Coastguard Worker * furnished to do so, under the terms of the COPYING file.
17*6236dae4SAndroid Build Coastguard Worker *
18*6236dae4SAndroid Build Coastguard Worker * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
19*6236dae4SAndroid Build Coastguard Worker * KIND, either express or implied.
20*6236dae4SAndroid Build Coastguard Worker *
21*6236dae4SAndroid Build Coastguard Worker * SPDX-License-Identifier: curl
22*6236dae4SAndroid Build Coastguard Worker *
23*6236dae4SAndroid Build Coastguard Worker ***************************************************************************/
24*6236dae4SAndroid Build Coastguard Worker
25*6236dae4SAndroid Build Coastguard Worker /*
26*6236dae4SAndroid Build Coastguard Worker * Source file for all GnuTLS-specific code for the TLS/SSL layer. No code
27*6236dae4SAndroid Build Coastguard Worker * but vtls.c should ever call or use these functions.
28*6236dae4SAndroid Build Coastguard Worker *
29*6236dae4SAndroid Build Coastguard Worker * Note: do not use the GnuTLS' *_t variable type names in this source code,
30*6236dae4SAndroid Build Coastguard Worker * since they were not present in 1.0.X.
31*6236dae4SAndroid Build Coastguard Worker */
32*6236dae4SAndroid Build Coastguard Worker
33*6236dae4SAndroid Build Coastguard Worker #include "curl_setup.h"
34*6236dae4SAndroid Build Coastguard Worker
35*6236dae4SAndroid Build Coastguard Worker #ifdef USE_GNUTLS
36*6236dae4SAndroid Build Coastguard Worker
37*6236dae4SAndroid Build Coastguard Worker #include <gnutls/abstract.h>
38*6236dae4SAndroid Build Coastguard Worker #include <gnutls/gnutls.h>
39*6236dae4SAndroid Build Coastguard Worker #include <gnutls/x509.h>
40*6236dae4SAndroid Build Coastguard Worker #include <gnutls/crypto.h>
41*6236dae4SAndroid Build Coastguard Worker #include <nettle/sha2.h>
42*6236dae4SAndroid Build Coastguard Worker
43*6236dae4SAndroid Build Coastguard Worker #include "urldata.h"
44*6236dae4SAndroid Build Coastguard Worker #include "sendf.h"
45*6236dae4SAndroid Build Coastguard Worker #include "inet_pton.h"
46*6236dae4SAndroid Build Coastguard Worker #include "keylog.h"
47*6236dae4SAndroid Build Coastguard Worker #include "gtls.h"
48*6236dae4SAndroid Build Coastguard Worker #include "vtls.h"
49*6236dae4SAndroid Build Coastguard Worker #include "vtls_int.h"
50*6236dae4SAndroid Build Coastguard Worker #include "vauth/vauth.h"
51*6236dae4SAndroid Build Coastguard Worker #include "parsedate.h"
52*6236dae4SAndroid Build Coastguard Worker #include "connect.h" /* for the connect timeout */
53*6236dae4SAndroid Build Coastguard Worker #include "progress.h"
54*6236dae4SAndroid Build Coastguard Worker #include "select.h"
55*6236dae4SAndroid Build Coastguard Worker #include "strcase.h"
56*6236dae4SAndroid Build Coastguard Worker #include "warnless.h"
57*6236dae4SAndroid Build Coastguard Worker #include "x509asn1.h"
58*6236dae4SAndroid Build Coastguard Worker #include "multiif.h"
59*6236dae4SAndroid Build Coastguard Worker #include "curl_printf.h"
60*6236dae4SAndroid Build Coastguard Worker #include "curl_memory.h"
61*6236dae4SAndroid Build Coastguard Worker /* The last #include file should be: */
62*6236dae4SAndroid Build Coastguard Worker #include "memdebug.h"
63*6236dae4SAndroid Build Coastguard Worker
64*6236dae4SAndroid Build Coastguard Worker #ifndef ARRAYSIZE
65*6236dae4SAndroid Build Coastguard Worker #define ARRAYSIZE(A) (sizeof(A)/sizeof((A)[0]))
66*6236dae4SAndroid Build Coastguard Worker #endif
67*6236dae4SAndroid Build Coastguard Worker
68*6236dae4SAndroid Build Coastguard Worker #define QUIC_PRIORITY \
69*6236dae4SAndroid Build Coastguard Worker "NORMAL:-VERS-ALL:+VERS-TLS1.3:-CIPHER-ALL:+AES-128-GCM:+AES-256-GCM:" \
70*6236dae4SAndroid Build Coastguard Worker "+CHACHA20-POLY1305:+AES-128-CCM:-GROUP-ALL:+GROUP-SECP256R1:" \
71*6236dae4SAndroid Build Coastguard Worker "+GROUP-X25519:+GROUP-SECP384R1:+GROUP-SECP521R1:" \
72*6236dae4SAndroid Build Coastguard Worker "%DISABLE_TLS13_COMPAT_MODE"
73*6236dae4SAndroid Build Coastguard Worker
74*6236dae4SAndroid Build Coastguard Worker /* Enable GnuTLS debugging by defining GTLSDEBUG */
75*6236dae4SAndroid Build Coastguard Worker /*#define GTLSDEBUG */
76*6236dae4SAndroid Build Coastguard Worker
77*6236dae4SAndroid Build Coastguard Worker #ifdef GTLSDEBUG
tls_log_func(int level,const char * str)78*6236dae4SAndroid Build Coastguard Worker static void tls_log_func(int level, const char *str)
79*6236dae4SAndroid Build Coastguard Worker {
80*6236dae4SAndroid Build Coastguard Worker fprintf(stderr, "|<%d>| %s", level, str);
81*6236dae4SAndroid Build Coastguard Worker }
82*6236dae4SAndroid Build Coastguard Worker #endif
83*6236dae4SAndroid Build Coastguard Worker static bool gtls_inited = FALSE;
84*6236dae4SAndroid Build Coastguard Worker
85*6236dae4SAndroid Build Coastguard Worker #if !defined(GNUTLS_VERSION_NUMBER) || (GNUTLS_VERSION_NUMBER < 0x03010a)
86*6236dae4SAndroid Build Coastguard Worker #error "too old GnuTLS version"
87*6236dae4SAndroid Build Coastguard Worker #endif
88*6236dae4SAndroid Build Coastguard Worker
89*6236dae4SAndroid Build Coastguard Worker # include <gnutls/ocsp.h>
90*6236dae4SAndroid Build Coastguard Worker
91*6236dae4SAndroid Build Coastguard Worker struct gtls_ssl_backend_data {
92*6236dae4SAndroid Build Coastguard Worker struct gtls_ctx gtls;
93*6236dae4SAndroid Build Coastguard Worker };
94*6236dae4SAndroid Build Coastguard Worker
gtls_push(void * s,const void * buf,size_t blen)95*6236dae4SAndroid Build Coastguard Worker static ssize_t gtls_push(void *s, const void *buf, size_t blen)
96*6236dae4SAndroid Build Coastguard Worker {
97*6236dae4SAndroid Build Coastguard Worker struct Curl_cfilter *cf = s;
98*6236dae4SAndroid Build Coastguard Worker struct ssl_connect_data *connssl = cf->ctx;
99*6236dae4SAndroid Build Coastguard Worker struct gtls_ssl_backend_data *backend =
100*6236dae4SAndroid Build Coastguard Worker (struct gtls_ssl_backend_data *)connssl->backend;
101*6236dae4SAndroid Build Coastguard Worker struct Curl_easy *data = CF_DATA_CURRENT(cf);
102*6236dae4SAndroid Build Coastguard Worker ssize_t nwritten;
103*6236dae4SAndroid Build Coastguard Worker CURLcode result;
104*6236dae4SAndroid Build Coastguard Worker
105*6236dae4SAndroid Build Coastguard Worker DEBUGASSERT(data);
106*6236dae4SAndroid Build Coastguard Worker nwritten = Curl_conn_cf_send(cf->next, data, buf, blen, FALSE, &result);
107*6236dae4SAndroid Build Coastguard Worker CURL_TRC_CF(data, cf, "gtls_push(len=%zu) -> %zd, err=%d",
108*6236dae4SAndroid Build Coastguard Worker blen, nwritten, result);
109*6236dae4SAndroid Build Coastguard Worker backend->gtls.io_result = result;
110*6236dae4SAndroid Build Coastguard Worker if(nwritten < 0) {
111*6236dae4SAndroid Build Coastguard Worker gnutls_transport_set_errno(backend->gtls.session,
112*6236dae4SAndroid Build Coastguard Worker (CURLE_AGAIN == result) ? EAGAIN : EINVAL);
113*6236dae4SAndroid Build Coastguard Worker nwritten = -1;
114*6236dae4SAndroid Build Coastguard Worker }
115*6236dae4SAndroid Build Coastguard Worker return nwritten;
116*6236dae4SAndroid Build Coastguard Worker }
117*6236dae4SAndroid Build Coastguard Worker
gtls_pull(void * s,void * buf,size_t blen)118*6236dae4SAndroid Build Coastguard Worker static ssize_t gtls_pull(void *s, void *buf, size_t blen)
119*6236dae4SAndroid Build Coastguard Worker {
120*6236dae4SAndroid Build Coastguard Worker struct Curl_cfilter *cf = s;
121*6236dae4SAndroid Build Coastguard Worker struct ssl_connect_data *connssl = cf->ctx;
122*6236dae4SAndroid Build Coastguard Worker struct gtls_ssl_backend_data *backend =
123*6236dae4SAndroid Build Coastguard Worker (struct gtls_ssl_backend_data *)connssl->backend;
124*6236dae4SAndroid Build Coastguard Worker struct Curl_easy *data = CF_DATA_CURRENT(cf);
125*6236dae4SAndroid Build Coastguard Worker ssize_t nread;
126*6236dae4SAndroid Build Coastguard Worker CURLcode result;
127*6236dae4SAndroid Build Coastguard Worker
128*6236dae4SAndroid Build Coastguard Worker DEBUGASSERT(data);
129*6236dae4SAndroid Build Coastguard Worker if(!backend->gtls.shared_creds->trust_setup) {
130*6236dae4SAndroid Build Coastguard Worker result = Curl_gtls_client_trust_setup(cf, data, &backend->gtls);
131*6236dae4SAndroid Build Coastguard Worker if(result) {
132*6236dae4SAndroid Build Coastguard Worker gnutls_transport_set_errno(backend->gtls.session, EINVAL);
133*6236dae4SAndroid Build Coastguard Worker backend->gtls.io_result = result;
134*6236dae4SAndroid Build Coastguard Worker return -1;
135*6236dae4SAndroid Build Coastguard Worker }
136*6236dae4SAndroid Build Coastguard Worker }
137*6236dae4SAndroid Build Coastguard Worker
138*6236dae4SAndroid Build Coastguard Worker nread = Curl_conn_cf_recv(cf->next, data, buf, blen, &result);
139*6236dae4SAndroid Build Coastguard Worker CURL_TRC_CF(data, cf, "glts_pull(len=%zu) -> %zd, err=%d",
140*6236dae4SAndroid Build Coastguard Worker blen, nread, result);
141*6236dae4SAndroid Build Coastguard Worker backend->gtls.io_result = result;
142*6236dae4SAndroid Build Coastguard Worker if(nread < 0) {
143*6236dae4SAndroid Build Coastguard Worker gnutls_transport_set_errno(backend->gtls.session,
144*6236dae4SAndroid Build Coastguard Worker (CURLE_AGAIN == result) ? EAGAIN : EINVAL);
145*6236dae4SAndroid Build Coastguard Worker nread = -1;
146*6236dae4SAndroid Build Coastguard Worker }
147*6236dae4SAndroid Build Coastguard Worker else if(nread == 0)
148*6236dae4SAndroid Build Coastguard Worker connssl->peer_closed = TRUE;
149*6236dae4SAndroid Build Coastguard Worker return nread;
150*6236dae4SAndroid Build Coastguard Worker }
151*6236dae4SAndroid Build Coastguard Worker
152*6236dae4SAndroid Build Coastguard Worker /* gtls_init()
153*6236dae4SAndroid Build Coastguard Worker *
154*6236dae4SAndroid Build Coastguard Worker * Global GnuTLS init, called from Curl_ssl_init(). This calls functions that
155*6236dae4SAndroid Build Coastguard Worker * are not thread-safe and thus this function itself is not thread-safe and
156*6236dae4SAndroid Build Coastguard Worker * must only be called from within curl_global_init() to keep the thread
157*6236dae4SAndroid Build Coastguard Worker * situation under control!
158*6236dae4SAndroid Build Coastguard Worker */
gtls_init(void)159*6236dae4SAndroid Build Coastguard Worker static int gtls_init(void)
160*6236dae4SAndroid Build Coastguard Worker {
161*6236dae4SAndroid Build Coastguard Worker int ret = 1;
162*6236dae4SAndroid Build Coastguard Worker if(!gtls_inited) {
163*6236dae4SAndroid Build Coastguard Worker ret = gnutls_global_init() ? 0 : 1;
164*6236dae4SAndroid Build Coastguard Worker #ifdef GTLSDEBUG
165*6236dae4SAndroid Build Coastguard Worker gnutls_global_set_log_function(tls_log_func);
166*6236dae4SAndroid Build Coastguard Worker gnutls_global_set_log_level(2);
167*6236dae4SAndroid Build Coastguard Worker #endif
168*6236dae4SAndroid Build Coastguard Worker gtls_inited = TRUE;
169*6236dae4SAndroid Build Coastguard Worker }
170*6236dae4SAndroid Build Coastguard Worker return ret;
171*6236dae4SAndroid Build Coastguard Worker }
172*6236dae4SAndroid Build Coastguard Worker
gtls_cleanup(void)173*6236dae4SAndroid Build Coastguard Worker static void gtls_cleanup(void)
174*6236dae4SAndroid Build Coastguard Worker {
175*6236dae4SAndroid Build Coastguard Worker if(gtls_inited) {
176*6236dae4SAndroid Build Coastguard Worker gnutls_global_deinit();
177*6236dae4SAndroid Build Coastguard Worker gtls_inited = FALSE;
178*6236dae4SAndroid Build Coastguard Worker }
179*6236dae4SAndroid Build Coastguard Worker }
180*6236dae4SAndroid Build Coastguard Worker
181*6236dae4SAndroid Build Coastguard Worker #ifndef CURL_DISABLE_VERBOSE_STRINGS
showtime(struct Curl_easy * data,const char * text,time_t stamp)182*6236dae4SAndroid Build Coastguard Worker static void showtime(struct Curl_easy *data,
183*6236dae4SAndroid Build Coastguard Worker const char *text,
184*6236dae4SAndroid Build Coastguard Worker time_t stamp)
185*6236dae4SAndroid Build Coastguard Worker {
186*6236dae4SAndroid Build Coastguard Worker struct tm buffer;
187*6236dae4SAndroid Build Coastguard Worker const struct tm *tm = &buffer;
188*6236dae4SAndroid Build Coastguard Worker char str[96];
189*6236dae4SAndroid Build Coastguard Worker CURLcode result = Curl_gmtime(stamp, &buffer);
190*6236dae4SAndroid Build Coastguard Worker if(result)
191*6236dae4SAndroid Build Coastguard Worker return;
192*6236dae4SAndroid Build Coastguard Worker
193*6236dae4SAndroid Build Coastguard Worker msnprintf(str,
194*6236dae4SAndroid Build Coastguard Worker sizeof(str),
195*6236dae4SAndroid Build Coastguard Worker " %s: %s, %02d %s %4d %02d:%02d:%02d GMT",
196*6236dae4SAndroid Build Coastguard Worker text,
197*6236dae4SAndroid Build Coastguard Worker Curl_wkday[tm->tm_wday ? tm->tm_wday-1 : 6],
198*6236dae4SAndroid Build Coastguard Worker tm->tm_mday,
199*6236dae4SAndroid Build Coastguard Worker Curl_month[tm->tm_mon],
200*6236dae4SAndroid Build Coastguard Worker tm->tm_year + 1900,
201*6236dae4SAndroid Build Coastguard Worker tm->tm_hour,
202*6236dae4SAndroid Build Coastguard Worker tm->tm_min,
203*6236dae4SAndroid Build Coastguard Worker tm->tm_sec);
204*6236dae4SAndroid Build Coastguard Worker infof(data, "%s", str);
205*6236dae4SAndroid Build Coastguard Worker }
206*6236dae4SAndroid Build Coastguard Worker #endif
207*6236dae4SAndroid Build Coastguard Worker
load_file(const char * file)208*6236dae4SAndroid Build Coastguard Worker static gnutls_datum_t load_file(const char *file)
209*6236dae4SAndroid Build Coastguard Worker {
210*6236dae4SAndroid Build Coastguard Worker FILE *f;
211*6236dae4SAndroid Build Coastguard Worker gnutls_datum_t loaded_file = { NULL, 0 };
212*6236dae4SAndroid Build Coastguard Worker long filelen;
213*6236dae4SAndroid Build Coastguard Worker void *ptr;
214*6236dae4SAndroid Build Coastguard Worker
215*6236dae4SAndroid Build Coastguard Worker f = fopen(file, "rb");
216*6236dae4SAndroid Build Coastguard Worker if(!f)
217*6236dae4SAndroid Build Coastguard Worker return loaded_file;
218*6236dae4SAndroid Build Coastguard Worker if(fseek(f, 0, SEEK_END) != 0
219*6236dae4SAndroid Build Coastguard Worker || (filelen = ftell(f)) < 0
220*6236dae4SAndroid Build Coastguard Worker || fseek(f, 0, SEEK_SET) != 0
221*6236dae4SAndroid Build Coastguard Worker || !(ptr = malloc((size_t)filelen)))
222*6236dae4SAndroid Build Coastguard Worker goto out;
223*6236dae4SAndroid Build Coastguard Worker if(fread(ptr, 1, (size_t)filelen, f) < (size_t)filelen) {
224*6236dae4SAndroid Build Coastguard Worker free(ptr);
225*6236dae4SAndroid Build Coastguard Worker goto out;
226*6236dae4SAndroid Build Coastguard Worker }
227*6236dae4SAndroid Build Coastguard Worker
228*6236dae4SAndroid Build Coastguard Worker loaded_file.data = ptr;
229*6236dae4SAndroid Build Coastguard Worker loaded_file.size = (unsigned int)filelen;
230*6236dae4SAndroid Build Coastguard Worker out:
231*6236dae4SAndroid Build Coastguard Worker fclose(f);
232*6236dae4SAndroid Build Coastguard Worker return loaded_file;
233*6236dae4SAndroid Build Coastguard Worker }
234*6236dae4SAndroid Build Coastguard Worker
unload_file(gnutls_datum_t data)235*6236dae4SAndroid Build Coastguard Worker static void unload_file(gnutls_datum_t data)
236*6236dae4SAndroid Build Coastguard Worker {
237*6236dae4SAndroid Build Coastguard Worker free(data.data);
238*6236dae4SAndroid Build Coastguard Worker }
239*6236dae4SAndroid Build Coastguard Worker
240*6236dae4SAndroid Build Coastguard Worker
241*6236dae4SAndroid Build Coastguard Worker /* this function does a SSL/TLS (re-)handshake */
handshake(struct Curl_cfilter * cf,struct Curl_easy * data,bool duringconnect,bool nonblocking)242*6236dae4SAndroid Build Coastguard Worker static CURLcode handshake(struct Curl_cfilter *cf,
243*6236dae4SAndroid Build Coastguard Worker struct Curl_easy *data,
244*6236dae4SAndroid Build Coastguard Worker bool duringconnect,
245*6236dae4SAndroid Build Coastguard Worker bool nonblocking)
246*6236dae4SAndroid Build Coastguard Worker {
247*6236dae4SAndroid Build Coastguard Worker struct ssl_connect_data *connssl = cf->ctx;
248*6236dae4SAndroid Build Coastguard Worker struct gtls_ssl_backend_data *backend =
249*6236dae4SAndroid Build Coastguard Worker (struct gtls_ssl_backend_data *)connssl->backend;
250*6236dae4SAndroid Build Coastguard Worker gnutls_session_t session;
251*6236dae4SAndroid Build Coastguard Worker curl_socket_t sockfd = Curl_conn_cf_get_socket(cf, data);
252*6236dae4SAndroid Build Coastguard Worker
253*6236dae4SAndroid Build Coastguard Worker DEBUGASSERT(backend);
254*6236dae4SAndroid Build Coastguard Worker session = backend->gtls.session;
255*6236dae4SAndroid Build Coastguard Worker connssl->connecting_state = ssl_connect_2;
256*6236dae4SAndroid Build Coastguard Worker
257*6236dae4SAndroid Build Coastguard Worker for(;;) {
258*6236dae4SAndroid Build Coastguard Worker timediff_t timeout_ms;
259*6236dae4SAndroid Build Coastguard Worker int rc;
260*6236dae4SAndroid Build Coastguard Worker
261*6236dae4SAndroid Build Coastguard Worker /* check allowed time left */
262*6236dae4SAndroid Build Coastguard Worker timeout_ms = Curl_timeleft(data, NULL, duringconnect);
263*6236dae4SAndroid Build Coastguard Worker
264*6236dae4SAndroid Build Coastguard Worker if(timeout_ms < 0) {
265*6236dae4SAndroid Build Coastguard Worker /* no need to continue if time already is up */
266*6236dae4SAndroid Build Coastguard Worker failf(data, "SSL connection timeout");
267*6236dae4SAndroid Build Coastguard Worker return CURLE_OPERATION_TIMEDOUT;
268*6236dae4SAndroid Build Coastguard Worker }
269*6236dae4SAndroid Build Coastguard Worker
270*6236dae4SAndroid Build Coastguard Worker /* if ssl is expecting something, check if it is available. */
271*6236dae4SAndroid Build Coastguard Worker if(connssl->io_need) {
272*6236dae4SAndroid Build Coastguard Worker int what;
273*6236dae4SAndroid Build Coastguard Worker curl_socket_t writefd = (connssl->io_need & CURL_SSL_IO_NEED_SEND) ?
274*6236dae4SAndroid Build Coastguard Worker sockfd : CURL_SOCKET_BAD;
275*6236dae4SAndroid Build Coastguard Worker curl_socket_t readfd = (connssl->io_need & CURL_SSL_IO_NEED_RECV) ?
276*6236dae4SAndroid Build Coastguard Worker sockfd : CURL_SOCKET_BAD;
277*6236dae4SAndroid Build Coastguard Worker
278*6236dae4SAndroid Build Coastguard Worker what = Curl_socket_check(readfd, CURL_SOCKET_BAD, writefd,
279*6236dae4SAndroid Build Coastguard Worker nonblocking ? 0 :
280*6236dae4SAndroid Build Coastguard Worker timeout_ms ? timeout_ms : 1000);
281*6236dae4SAndroid Build Coastguard Worker if(what < 0) {
282*6236dae4SAndroid Build Coastguard Worker /* fatal error */
283*6236dae4SAndroid Build Coastguard Worker failf(data, "select/poll on SSL socket, errno: %d", SOCKERRNO);
284*6236dae4SAndroid Build Coastguard Worker return CURLE_SSL_CONNECT_ERROR;
285*6236dae4SAndroid Build Coastguard Worker }
286*6236dae4SAndroid Build Coastguard Worker else if(0 == what) {
287*6236dae4SAndroid Build Coastguard Worker if(nonblocking)
288*6236dae4SAndroid Build Coastguard Worker return CURLE_AGAIN;
289*6236dae4SAndroid Build Coastguard Worker else if(timeout_ms) {
290*6236dae4SAndroid Build Coastguard Worker /* timeout */
291*6236dae4SAndroid Build Coastguard Worker failf(data, "SSL connection timeout at %ld", (long)timeout_ms);
292*6236dae4SAndroid Build Coastguard Worker return CURLE_OPERATION_TIMEDOUT;
293*6236dae4SAndroid Build Coastguard Worker }
294*6236dae4SAndroid Build Coastguard Worker }
295*6236dae4SAndroid Build Coastguard Worker /* socket is readable or writable */
296*6236dae4SAndroid Build Coastguard Worker }
297*6236dae4SAndroid Build Coastguard Worker
298*6236dae4SAndroid Build Coastguard Worker connssl->io_need = CURL_SSL_IO_NEED_NONE;
299*6236dae4SAndroid Build Coastguard Worker backend->gtls.io_result = CURLE_OK;
300*6236dae4SAndroid Build Coastguard Worker rc = gnutls_handshake(session);
301*6236dae4SAndroid Build Coastguard Worker
302*6236dae4SAndroid Build Coastguard Worker if(!backend->gtls.shared_creds->trust_setup) {
303*6236dae4SAndroid Build Coastguard Worker /* After having send off the ClientHello, we prepare the trust
304*6236dae4SAndroid Build Coastguard Worker * store to verify the coming certificate from the server */
305*6236dae4SAndroid Build Coastguard Worker CURLcode result = Curl_gtls_client_trust_setup(cf, data, &backend->gtls);
306*6236dae4SAndroid Build Coastguard Worker if(result)
307*6236dae4SAndroid Build Coastguard Worker return result;
308*6236dae4SAndroid Build Coastguard Worker }
309*6236dae4SAndroid Build Coastguard Worker
310*6236dae4SAndroid Build Coastguard Worker if((rc == GNUTLS_E_AGAIN) || (rc == GNUTLS_E_INTERRUPTED)) {
311*6236dae4SAndroid Build Coastguard Worker connssl->io_need =
312*6236dae4SAndroid Build Coastguard Worker gnutls_record_get_direction(session) ?
313*6236dae4SAndroid Build Coastguard Worker CURL_SSL_IO_NEED_SEND : CURL_SSL_IO_NEED_RECV;
314*6236dae4SAndroid Build Coastguard Worker continue;
315*6236dae4SAndroid Build Coastguard Worker }
316*6236dae4SAndroid Build Coastguard Worker else if((rc < 0) && !gnutls_error_is_fatal(rc)) {
317*6236dae4SAndroid Build Coastguard Worker const char *strerr = NULL;
318*6236dae4SAndroid Build Coastguard Worker
319*6236dae4SAndroid Build Coastguard Worker if(rc == GNUTLS_E_WARNING_ALERT_RECEIVED) {
320*6236dae4SAndroid Build Coastguard Worker gnutls_alert_description_t alert = gnutls_alert_get(session);
321*6236dae4SAndroid Build Coastguard Worker strerr = gnutls_alert_get_name(alert);
322*6236dae4SAndroid Build Coastguard Worker }
323*6236dae4SAndroid Build Coastguard Worker
324*6236dae4SAndroid Build Coastguard Worker if(!strerr)
325*6236dae4SAndroid Build Coastguard Worker strerr = gnutls_strerror(rc);
326*6236dae4SAndroid Build Coastguard Worker
327*6236dae4SAndroid Build Coastguard Worker infof(data, "gnutls_handshake() warning: %s", strerr);
328*6236dae4SAndroid Build Coastguard Worker continue;
329*6236dae4SAndroid Build Coastguard Worker }
330*6236dae4SAndroid Build Coastguard Worker else if((rc < 0) && backend->gtls.io_result) {
331*6236dae4SAndroid Build Coastguard Worker return backend->gtls.io_result;
332*6236dae4SAndroid Build Coastguard Worker }
333*6236dae4SAndroid Build Coastguard Worker else if(rc < 0) {
334*6236dae4SAndroid Build Coastguard Worker const char *strerr = NULL;
335*6236dae4SAndroid Build Coastguard Worker
336*6236dae4SAndroid Build Coastguard Worker if(rc == GNUTLS_E_FATAL_ALERT_RECEIVED) {
337*6236dae4SAndroid Build Coastguard Worker gnutls_alert_description_t alert = gnutls_alert_get(session);
338*6236dae4SAndroid Build Coastguard Worker strerr = gnutls_alert_get_name(alert);
339*6236dae4SAndroid Build Coastguard Worker }
340*6236dae4SAndroid Build Coastguard Worker
341*6236dae4SAndroid Build Coastguard Worker if(!strerr)
342*6236dae4SAndroid Build Coastguard Worker strerr = gnutls_strerror(rc);
343*6236dae4SAndroid Build Coastguard Worker
344*6236dae4SAndroid Build Coastguard Worker failf(data, "GnuTLS, handshake failed: %s", strerr);
345*6236dae4SAndroid Build Coastguard Worker return CURLE_SSL_CONNECT_ERROR;
346*6236dae4SAndroid Build Coastguard Worker }
347*6236dae4SAndroid Build Coastguard Worker
348*6236dae4SAndroid Build Coastguard Worker /* Reset our connect state machine */
349*6236dae4SAndroid Build Coastguard Worker connssl->connecting_state = ssl_connect_1;
350*6236dae4SAndroid Build Coastguard Worker return CURLE_OK;
351*6236dae4SAndroid Build Coastguard Worker }
352*6236dae4SAndroid Build Coastguard Worker }
353*6236dae4SAndroid Build Coastguard Worker
gnutls_do_file_type(const char * type)354*6236dae4SAndroid Build Coastguard Worker static gnutls_x509_crt_fmt_t gnutls_do_file_type(const char *type)
355*6236dae4SAndroid Build Coastguard Worker {
356*6236dae4SAndroid Build Coastguard Worker if(!type || !type[0])
357*6236dae4SAndroid Build Coastguard Worker return GNUTLS_X509_FMT_PEM;
358*6236dae4SAndroid Build Coastguard Worker if(strcasecompare(type, "PEM"))
359*6236dae4SAndroid Build Coastguard Worker return GNUTLS_X509_FMT_PEM;
360*6236dae4SAndroid Build Coastguard Worker if(strcasecompare(type, "DER"))
361*6236dae4SAndroid Build Coastguard Worker return GNUTLS_X509_FMT_DER;
362*6236dae4SAndroid Build Coastguard Worker return GNUTLS_X509_FMT_PEM; /* default to PEM */
363*6236dae4SAndroid Build Coastguard Worker }
364*6236dae4SAndroid Build Coastguard Worker
365*6236dae4SAndroid Build Coastguard Worker #define GNUTLS_CIPHERS "NORMAL:-ARCFOUR-128:-CTYPE-ALL:+CTYPE-X509"
366*6236dae4SAndroid Build Coastguard Worker /* If GnuTLS was compiled without support for SRP it will error out if SRP is
367*6236dae4SAndroid Build Coastguard Worker requested in the priority string, so treat it specially
368*6236dae4SAndroid Build Coastguard Worker */
369*6236dae4SAndroid Build Coastguard Worker #define GNUTLS_SRP "+SRP"
370*6236dae4SAndroid Build Coastguard Worker
371*6236dae4SAndroid Build Coastguard Worker static CURLcode
gnutls_set_ssl_version_min_max(struct Curl_easy * data,struct ssl_peer * peer,struct ssl_primary_config * conn_config,const char ** prioritylist,const char * tls13support)372*6236dae4SAndroid Build Coastguard Worker gnutls_set_ssl_version_min_max(struct Curl_easy *data,
373*6236dae4SAndroid Build Coastguard Worker struct ssl_peer *peer,
374*6236dae4SAndroid Build Coastguard Worker struct ssl_primary_config *conn_config,
375*6236dae4SAndroid Build Coastguard Worker const char **prioritylist,
376*6236dae4SAndroid Build Coastguard Worker const char *tls13support)
377*6236dae4SAndroid Build Coastguard Worker {
378*6236dae4SAndroid Build Coastguard Worker long ssl_version = conn_config->version;
379*6236dae4SAndroid Build Coastguard Worker long ssl_version_max = conn_config->version_max;
380*6236dae4SAndroid Build Coastguard Worker
381*6236dae4SAndroid Build Coastguard Worker if((ssl_version == CURL_SSLVERSION_DEFAULT) ||
382*6236dae4SAndroid Build Coastguard Worker (ssl_version == CURL_SSLVERSION_TLSv1))
383*6236dae4SAndroid Build Coastguard Worker ssl_version = CURL_SSLVERSION_TLSv1_0;
384*6236dae4SAndroid Build Coastguard Worker if(ssl_version_max == CURL_SSLVERSION_MAX_NONE)
385*6236dae4SAndroid Build Coastguard Worker ssl_version_max = CURL_SSLVERSION_MAX_DEFAULT;
386*6236dae4SAndroid Build Coastguard Worker
387*6236dae4SAndroid Build Coastguard Worker if(peer->transport == TRNSPRT_QUIC) {
388*6236dae4SAndroid Build Coastguard Worker if((ssl_version_max != CURL_SSLVERSION_MAX_DEFAULT) &&
389*6236dae4SAndroid Build Coastguard Worker (ssl_version_max < CURL_SSLVERSION_MAX_TLSv1_3)) {
390*6236dae4SAndroid Build Coastguard Worker failf(data, "QUIC needs at least TLS version 1.3");
391*6236dae4SAndroid Build Coastguard Worker return CURLE_SSL_CONNECT_ERROR;
392*6236dae4SAndroid Build Coastguard Worker }
393*6236dae4SAndroid Build Coastguard Worker *prioritylist = QUIC_PRIORITY;
394*6236dae4SAndroid Build Coastguard Worker return CURLE_OK;
395*6236dae4SAndroid Build Coastguard Worker }
396*6236dae4SAndroid Build Coastguard Worker
397*6236dae4SAndroid Build Coastguard Worker if(!tls13support) {
398*6236dae4SAndroid Build Coastguard Worker /* If the running GnuTLS does not support TLS 1.3, we must not specify a
399*6236dae4SAndroid Build Coastguard Worker prioritylist involving that since it will make GnuTLS return an en
400*6236dae4SAndroid Build Coastguard Worker error back at us */
401*6236dae4SAndroid Build Coastguard Worker if((ssl_version_max == CURL_SSLVERSION_MAX_TLSv1_3) ||
402*6236dae4SAndroid Build Coastguard Worker (ssl_version_max == CURL_SSLVERSION_MAX_DEFAULT)) {
403*6236dae4SAndroid Build Coastguard Worker ssl_version_max = CURL_SSLVERSION_MAX_TLSv1_2;
404*6236dae4SAndroid Build Coastguard Worker }
405*6236dae4SAndroid Build Coastguard Worker }
406*6236dae4SAndroid Build Coastguard Worker else if(ssl_version_max == CURL_SSLVERSION_MAX_DEFAULT) {
407*6236dae4SAndroid Build Coastguard Worker ssl_version_max = CURL_SSLVERSION_MAX_TLSv1_3;
408*6236dae4SAndroid Build Coastguard Worker }
409*6236dae4SAndroid Build Coastguard Worker
410*6236dae4SAndroid Build Coastguard Worker switch(ssl_version | ssl_version_max) {
411*6236dae4SAndroid Build Coastguard Worker case CURL_SSLVERSION_TLSv1_0 | CURL_SSLVERSION_MAX_TLSv1_0:
412*6236dae4SAndroid Build Coastguard Worker *prioritylist = GNUTLS_CIPHERS ":-VERS-SSL3.0:-VERS-TLS-ALL:"
413*6236dae4SAndroid Build Coastguard Worker "+VERS-TLS1.0";
414*6236dae4SAndroid Build Coastguard Worker return CURLE_OK;
415*6236dae4SAndroid Build Coastguard Worker case CURL_SSLVERSION_TLSv1_0 | CURL_SSLVERSION_MAX_TLSv1_1:
416*6236dae4SAndroid Build Coastguard Worker *prioritylist = GNUTLS_CIPHERS ":-VERS-SSL3.0:-VERS-TLS-ALL:"
417*6236dae4SAndroid Build Coastguard Worker "+VERS-TLS1.1:+VERS-TLS1.0";
418*6236dae4SAndroid Build Coastguard Worker return CURLE_OK;
419*6236dae4SAndroid Build Coastguard Worker case CURL_SSLVERSION_TLSv1_0 | CURL_SSLVERSION_MAX_TLSv1_2:
420*6236dae4SAndroid Build Coastguard Worker *prioritylist = GNUTLS_CIPHERS ":-VERS-SSL3.0:-VERS-TLS-ALL:"
421*6236dae4SAndroid Build Coastguard Worker "+VERS-TLS1.2:+VERS-TLS1.1:+VERS-TLS1.0";
422*6236dae4SAndroid Build Coastguard Worker return CURLE_OK;
423*6236dae4SAndroid Build Coastguard Worker case CURL_SSLVERSION_TLSv1_1 | CURL_SSLVERSION_MAX_TLSv1_1:
424*6236dae4SAndroid Build Coastguard Worker *prioritylist = GNUTLS_CIPHERS ":-VERS-SSL3.0:-VERS-TLS-ALL:"
425*6236dae4SAndroid Build Coastguard Worker "+VERS-TLS1.1";
426*6236dae4SAndroid Build Coastguard Worker return CURLE_OK;
427*6236dae4SAndroid Build Coastguard Worker case CURL_SSLVERSION_TLSv1_1 | CURL_SSLVERSION_MAX_TLSv1_2:
428*6236dae4SAndroid Build Coastguard Worker *prioritylist = GNUTLS_CIPHERS ":-VERS-SSL3.0:-VERS-TLS-ALL:"
429*6236dae4SAndroid Build Coastguard Worker "+VERS-TLS1.2:+VERS-TLS1.1";
430*6236dae4SAndroid Build Coastguard Worker return CURLE_OK;
431*6236dae4SAndroid Build Coastguard Worker case CURL_SSLVERSION_TLSv1_2 | CURL_SSLVERSION_MAX_TLSv1_2:
432*6236dae4SAndroid Build Coastguard Worker *prioritylist = GNUTLS_CIPHERS ":-VERS-SSL3.0:-VERS-TLS-ALL:"
433*6236dae4SAndroid Build Coastguard Worker "+VERS-TLS1.2";
434*6236dae4SAndroid Build Coastguard Worker return CURLE_OK;
435*6236dae4SAndroid Build Coastguard Worker case CURL_SSLVERSION_TLSv1_3 | CURL_SSLVERSION_MAX_TLSv1_3:
436*6236dae4SAndroid Build Coastguard Worker *prioritylist = GNUTLS_CIPHERS ":-VERS-SSL3.0:-VERS-TLS-ALL:"
437*6236dae4SAndroid Build Coastguard Worker "+VERS-TLS1.3";
438*6236dae4SAndroid Build Coastguard Worker return CURLE_OK;
439*6236dae4SAndroid Build Coastguard Worker case CURL_SSLVERSION_TLSv1_0 | CURL_SSLVERSION_MAX_TLSv1_3:
440*6236dae4SAndroid Build Coastguard Worker *prioritylist = GNUTLS_CIPHERS ":-VERS-SSL3.0";
441*6236dae4SAndroid Build Coastguard Worker return CURLE_OK;
442*6236dae4SAndroid Build Coastguard Worker case CURL_SSLVERSION_TLSv1_1 | CURL_SSLVERSION_MAX_TLSv1_3:
443*6236dae4SAndroid Build Coastguard Worker *prioritylist = GNUTLS_CIPHERS ":-VERS-SSL3.0:-VERS-TLS-ALL:"
444*6236dae4SAndroid Build Coastguard Worker "+VERS-TLS1.3:+VERS-TLS1.2:+VERS-TLS1.1";
445*6236dae4SAndroid Build Coastguard Worker return CURLE_OK;
446*6236dae4SAndroid Build Coastguard Worker case CURL_SSLVERSION_TLSv1_2 | CURL_SSLVERSION_MAX_TLSv1_3:
447*6236dae4SAndroid Build Coastguard Worker *prioritylist = GNUTLS_CIPHERS ":-VERS-SSL3.0:-VERS-TLS-ALL:"
448*6236dae4SAndroid Build Coastguard Worker "+VERS-TLS1.3:+VERS-TLS1.2";
449*6236dae4SAndroid Build Coastguard Worker return CURLE_OK;
450*6236dae4SAndroid Build Coastguard Worker }
451*6236dae4SAndroid Build Coastguard Worker
452*6236dae4SAndroid Build Coastguard Worker failf(data, "GnuTLS: cannot set ssl protocol");
453*6236dae4SAndroid Build Coastguard Worker return CURLE_SSL_CONNECT_ERROR;
454*6236dae4SAndroid Build Coastguard Worker }
455*6236dae4SAndroid Build Coastguard Worker
Curl_gtls_shared_creds_create(struct Curl_easy * data,struct gtls_shared_creds ** pcreds)456*6236dae4SAndroid Build Coastguard Worker CURLcode Curl_gtls_shared_creds_create(struct Curl_easy *data,
457*6236dae4SAndroid Build Coastguard Worker struct gtls_shared_creds **pcreds)
458*6236dae4SAndroid Build Coastguard Worker {
459*6236dae4SAndroid Build Coastguard Worker struct gtls_shared_creds *shared;
460*6236dae4SAndroid Build Coastguard Worker int rc;
461*6236dae4SAndroid Build Coastguard Worker
462*6236dae4SAndroid Build Coastguard Worker *pcreds = NULL;
463*6236dae4SAndroid Build Coastguard Worker shared = calloc(1, sizeof(*shared));
464*6236dae4SAndroid Build Coastguard Worker if(!shared)
465*6236dae4SAndroid Build Coastguard Worker return CURLE_OUT_OF_MEMORY;
466*6236dae4SAndroid Build Coastguard Worker
467*6236dae4SAndroid Build Coastguard Worker rc = gnutls_certificate_allocate_credentials(&shared->creds);
468*6236dae4SAndroid Build Coastguard Worker if(rc != GNUTLS_E_SUCCESS) {
469*6236dae4SAndroid Build Coastguard Worker failf(data, "gnutls_cert_all_cred() failed: %s", gnutls_strerror(rc));
470*6236dae4SAndroid Build Coastguard Worker free(shared);
471*6236dae4SAndroid Build Coastguard Worker return CURLE_SSL_CONNECT_ERROR;
472*6236dae4SAndroid Build Coastguard Worker }
473*6236dae4SAndroid Build Coastguard Worker
474*6236dae4SAndroid Build Coastguard Worker shared->refcount = 1;
475*6236dae4SAndroid Build Coastguard Worker shared->time = Curl_now();
476*6236dae4SAndroid Build Coastguard Worker *pcreds = shared;
477*6236dae4SAndroid Build Coastguard Worker return CURLE_OK;
478*6236dae4SAndroid Build Coastguard Worker }
479*6236dae4SAndroid Build Coastguard Worker
Curl_gtls_shared_creds_up_ref(struct gtls_shared_creds * creds)480*6236dae4SAndroid Build Coastguard Worker CURLcode Curl_gtls_shared_creds_up_ref(struct gtls_shared_creds *creds)
481*6236dae4SAndroid Build Coastguard Worker {
482*6236dae4SAndroid Build Coastguard Worker DEBUGASSERT(creds);
483*6236dae4SAndroid Build Coastguard Worker if(creds->refcount < SIZE_T_MAX) {
484*6236dae4SAndroid Build Coastguard Worker ++creds->refcount;
485*6236dae4SAndroid Build Coastguard Worker return CURLE_OK;
486*6236dae4SAndroid Build Coastguard Worker }
487*6236dae4SAndroid Build Coastguard Worker return CURLE_BAD_FUNCTION_ARGUMENT;
488*6236dae4SAndroid Build Coastguard Worker }
489*6236dae4SAndroid Build Coastguard Worker
Curl_gtls_shared_creds_free(struct gtls_shared_creds ** pcreds)490*6236dae4SAndroid Build Coastguard Worker void Curl_gtls_shared_creds_free(struct gtls_shared_creds **pcreds)
491*6236dae4SAndroid Build Coastguard Worker {
492*6236dae4SAndroid Build Coastguard Worker struct gtls_shared_creds *shared = *pcreds;
493*6236dae4SAndroid Build Coastguard Worker *pcreds = NULL;
494*6236dae4SAndroid Build Coastguard Worker if(shared) {
495*6236dae4SAndroid Build Coastguard Worker --shared->refcount;
496*6236dae4SAndroid Build Coastguard Worker if(!shared->refcount) {
497*6236dae4SAndroid Build Coastguard Worker gnutls_certificate_free_credentials(shared->creds);
498*6236dae4SAndroid Build Coastguard Worker free(shared->CAfile);
499*6236dae4SAndroid Build Coastguard Worker free(shared);
500*6236dae4SAndroid Build Coastguard Worker }
501*6236dae4SAndroid Build Coastguard Worker }
502*6236dae4SAndroid Build Coastguard Worker }
503*6236dae4SAndroid Build Coastguard Worker
gtls_populate_creds(struct Curl_cfilter * cf,struct Curl_easy * data,gnutls_certificate_credentials_t creds)504*6236dae4SAndroid Build Coastguard Worker static CURLcode gtls_populate_creds(struct Curl_cfilter *cf,
505*6236dae4SAndroid Build Coastguard Worker struct Curl_easy *data,
506*6236dae4SAndroid Build Coastguard Worker gnutls_certificate_credentials_t creds)
507*6236dae4SAndroid Build Coastguard Worker {
508*6236dae4SAndroid Build Coastguard Worker struct ssl_primary_config *config = Curl_ssl_cf_get_primary_config(cf);
509*6236dae4SAndroid Build Coastguard Worker struct ssl_config_data *ssl_config = Curl_ssl_cf_get_config(cf, data);
510*6236dae4SAndroid Build Coastguard Worker int rc;
511*6236dae4SAndroid Build Coastguard Worker
512*6236dae4SAndroid Build Coastguard Worker if(config->verifypeer) {
513*6236dae4SAndroid Build Coastguard Worker bool imported_native_ca = FALSE;
514*6236dae4SAndroid Build Coastguard Worker
515*6236dae4SAndroid Build Coastguard Worker if(ssl_config->native_ca_store) {
516*6236dae4SAndroid Build Coastguard Worker rc = gnutls_certificate_set_x509_system_trust(creds);
517*6236dae4SAndroid Build Coastguard Worker if(rc < 0)
518*6236dae4SAndroid Build Coastguard Worker infof(data, "error reading native ca store (%s), continuing anyway",
519*6236dae4SAndroid Build Coastguard Worker gnutls_strerror(rc));
520*6236dae4SAndroid Build Coastguard Worker else {
521*6236dae4SAndroid Build Coastguard Worker infof(data, "found %d certificates in native ca store", rc);
522*6236dae4SAndroid Build Coastguard Worker if(rc > 0)
523*6236dae4SAndroid Build Coastguard Worker imported_native_ca = TRUE;
524*6236dae4SAndroid Build Coastguard Worker }
525*6236dae4SAndroid Build Coastguard Worker }
526*6236dae4SAndroid Build Coastguard Worker
527*6236dae4SAndroid Build Coastguard Worker if(config->CAfile) {
528*6236dae4SAndroid Build Coastguard Worker /* set the trusted CA cert bundle file */
529*6236dae4SAndroid Build Coastguard Worker gnutls_certificate_set_verify_flags(creds,
530*6236dae4SAndroid Build Coastguard Worker GNUTLS_VERIFY_ALLOW_X509_V1_CA_CRT);
531*6236dae4SAndroid Build Coastguard Worker
532*6236dae4SAndroid Build Coastguard Worker rc = gnutls_certificate_set_x509_trust_file(creds,
533*6236dae4SAndroid Build Coastguard Worker config->CAfile,
534*6236dae4SAndroid Build Coastguard Worker GNUTLS_X509_FMT_PEM);
535*6236dae4SAndroid Build Coastguard Worker if(rc < 0) {
536*6236dae4SAndroid Build Coastguard Worker infof(data, "error reading ca cert file %s (%s)%s",
537*6236dae4SAndroid Build Coastguard Worker config->CAfile, gnutls_strerror(rc),
538*6236dae4SAndroid Build Coastguard Worker (imported_native_ca ? ", continuing anyway" : ""));
539*6236dae4SAndroid Build Coastguard Worker if(!imported_native_ca) {
540*6236dae4SAndroid Build Coastguard Worker ssl_config->certverifyresult = rc;
541*6236dae4SAndroid Build Coastguard Worker return CURLE_SSL_CACERT_BADFILE;
542*6236dae4SAndroid Build Coastguard Worker }
543*6236dae4SAndroid Build Coastguard Worker }
544*6236dae4SAndroid Build Coastguard Worker else
545*6236dae4SAndroid Build Coastguard Worker infof(data, "found %d certificates in %s", rc, config->CAfile);
546*6236dae4SAndroid Build Coastguard Worker }
547*6236dae4SAndroid Build Coastguard Worker
548*6236dae4SAndroid Build Coastguard Worker if(config->CApath) {
549*6236dae4SAndroid Build Coastguard Worker /* set the trusted CA cert directory */
550*6236dae4SAndroid Build Coastguard Worker rc = gnutls_certificate_set_x509_trust_dir(creds, config->CApath,
551*6236dae4SAndroid Build Coastguard Worker GNUTLS_X509_FMT_PEM);
552*6236dae4SAndroid Build Coastguard Worker if(rc < 0) {
553*6236dae4SAndroid Build Coastguard Worker infof(data, "error reading ca cert file %s (%s)%s",
554*6236dae4SAndroid Build Coastguard Worker config->CApath, gnutls_strerror(rc),
555*6236dae4SAndroid Build Coastguard Worker (imported_native_ca ? ", continuing anyway" : ""));
556*6236dae4SAndroid Build Coastguard Worker if(!imported_native_ca) {
557*6236dae4SAndroid Build Coastguard Worker ssl_config->certverifyresult = rc;
558*6236dae4SAndroid Build Coastguard Worker return CURLE_SSL_CACERT_BADFILE;
559*6236dae4SAndroid Build Coastguard Worker }
560*6236dae4SAndroid Build Coastguard Worker }
561*6236dae4SAndroid Build Coastguard Worker else
562*6236dae4SAndroid Build Coastguard Worker infof(data, "found %d certificates in %s", rc, config->CApath);
563*6236dae4SAndroid Build Coastguard Worker }
564*6236dae4SAndroid Build Coastguard Worker }
565*6236dae4SAndroid Build Coastguard Worker
566*6236dae4SAndroid Build Coastguard Worker if(config->CRLfile) {
567*6236dae4SAndroid Build Coastguard Worker /* set the CRL list file */
568*6236dae4SAndroid Build Coastguard Worker rc = gnutls_certificate_set_x509_crl_file(creds, config->CRLfile,
569*6236dae4SAndroid Build Coastguard Worker GNUTLS_X509_FMT_PEM);
570*6236dae4SAndroid Build Coastguard Worker if(rc < 0) {
571*6236dae4SAndroid Build Coastguard Worker failf(data, "error reading crl file %s (%s)",
572*6236dae4SAndroid Build Coastguard Worker config->CRLfile, gnutls_strerror(rc));
573*6236dae4SAndroid Build Coastguard Worker return CURLE_SSL_CRL_BADFILE;
574*6236dae4SAndroid Build Coastguard Worker }
575*6236dae4SAndroid Build Coastguard Worker else
576*6236dae4SAndroid Build Coastguard Worker infof(data, "found %d CRL in %s", rc, config->CRLfile);
577*6236dae4SAndroid Build Coastguard Worker }
578*6236dae4SAndroid Build Coastguard Worker
579*6236dae4SAndroid Build Coastguard Worker return CURLE_OK;
580*6236dae4SAndroid Build Coastguard Worker }
581*6236dae4SAndroid Build Coastguard Worker
582*6236dae4SAndroid Build Coastguard Worker /* key to use at `multi->proto_hash` */
583*6236dae4SAndroid Build Coastguard Worker #define MPROTO_GTLS_X509_KEY "tls:gtls:x509:share"
584*6236dae4SAndroid Build Coastguard Worker
gtls_shared_creds_expired(const struct Curl_easy * data,const struct gtls_shared_creds * sc)585*6236dae4SAndroid Build Coastguard Worker static bool gtls_shared_creds_expired(const struct Curl_easy *data,
586*6236dae4SAndroid Build Coastguard Worker const struct gtls_shared_creds *sc)
587*6236dae4SAndroid Build Coastguard Worker {
588*6236dae4SAndroid Build Coastguard Worker const struct ssl_general_config *cfg = &data->set.general_ssl;
589*6236dae4SAndroid Build Coastguard Worker struct curltime now = Curl_now();
590*6236dae4SAndroid Build Coastguard Worker timediff_t elapsed_ms = Curl_timediff(now, sc->time);
591*6236dae4SAndroid Build Coastguard Worker timediff_t timeout_ms = cfg->ca_cache_timeout * (timediff_t)1000;
592*6236dae4SAndroid Build Coastguard Worker
593*6236dae4SAndroid Build Coastguard Worker if(timeout_ms < 0)
594*6236dae4SAndroid Build Coastguard Worker return FALSE;
595*6236dae4SAndroid Build Coastguard Worker
596*6236dae4SAndroid Build Coastguard Worker return elapsed_ms >= timeout_ms;
597*6236dae4SAndroid Build Coastguard Worker }
598*6236dae4SAndroid Build Coastguard Worker
gtls_shared_creds_different(struct Curl_cfilter * cf,const struct gtls_shared_creds * sc)599*6236dae4SAndroid Build Coastguard Worker static bool gtls_shared_creds_different(struct Curl_cfilter *cf,
600*6236dae4SAndroid Build Coastguard Worker const struct gtls_shared_creds *sc)
601*6236dae4SAndroid Build Coastguard Worker {
602*6236dae4SAndroid Build Coastguard Worker struct ssl_primary_config *conn_config = Curl_ssl_cf_get_primary_config(cf);
603*6236dae4SAndroid Build Coastguard Worker if(!sc->CAfile || !conn_config->CAfile)
604*6236dae4SAndroid Build Coastguard Worker return sc->CAfile != conn_config->CAfile;
605*6236dae4SAndroid Build Coastguard Worker
606*6236dae4SAndroid Build Coastguard Worker return strcmp(sc->CAfile, conn_config->CAfile);
607*6236dae4SAndroid Build Coastguard Worker }
608*6236dae4SAndroid Build Coastguard Worker
609*6236dae4SAndroid Build Coastguard Worker static struct gtls_shared_creds*
gtls_get_cached_creds(struct Curl_cfilter * cf,struct Curl_easy * data)610*6236dae4SAndroid Build Coastguard Worker gtls_get_cached_creds(struct Curl_cfilter *cf, struct Curl_easy *data)
611*6236dae4SAndroid Build Coastguard Worker {
612*6236dae4SAndroid Build Coastguard Worker struct gtls_shared_creds *shared_creds;
613*6236dae4SAndroid Build Coastguard Worker
614*6236dae4SAndroid Build Coastguard Worker if(data->multi) {
615*6236dae4SAndroid Build Coastguard Worker shared_creds = Curl_hash_pick(&data->multi->proto_hash,
616*6236dae4SAndroid Build Coastguard Worker (void *)MPROTO_GTLS_X509_KEY,
617*6236dae4SAndroid Build Coastguard Worker sizeof(MPROTO_GTLS_X509_KEY)-1);
618*6236dae4SAndroid Build Coastguard Worker if(shared_creds && shared_creds->creds &&
619*6236dae4SAndroid Build Coastguard Worker !gtls_shared_creds_expired(data, shared_creds) &&
620*6236dae4SAndroid Build Coastguard Worker !gtls_shared_creds_different(cf, shared_creds)) {
621*6236dae4SAndroid Build Coastguard Worker return shared_creds;
622*6236dae4SAndroid Build Coastguard Worker }
623*6236dae4SAndroid Build Coastguard Worker }
624*6236dae4SAndroid Build Coastguard Worker return NULL;
625*6236dae4SAndroid Build Coastguard Worker }
626*6236dae4SAndroid Build Coastguard Worker
gtls_shared_creds_hash_free(void * key,size_t key_len,void * p)627*6236dae4SAndroid Build Coastguard Worker static void gtls_shared_creds_hash_free(void *key, size_t key_len, void *p)
628*6236dae4SAndroid Build Coastguard Worker {
629*6236dae4SAndroid Build Coastguard Worker struct gtls_shared_creds *sc = p;
630*6236dae4SAndroid Build Coastguard Worker DEBUGASSERT(key_len == (sizeof(MPROTO_GTLS_X509_KEY)-1));
631*6236dae4SAndroid Build Coastguard Worker DEBUGASSERT(!memcmp(MPROTO_GTLS_X509_KEY, key, key_len));
632*6236dae4SAndroid Build Coastguard Worker (void)key;
633*6236dae4SAndroid Build Coastguard Worker (void)key_len;
634*6236dae4SAndroid Build Coastguard Worker Curl_gtls_shared_creds_free(&sc); /* down reference */
635*6236dae4SAndroid Build Coastguard Worker }
636*6236dae4SAndroid Build Coastguard Worker
gtls_set_cached_creds(struct Curl_cfilter * cf,struct Curl_easy * data,struct gtls_shared_creds * sc)637*6236dae4SAndroid Build Coastguard Worker static void gtls_set_cached_creds(struct Curl_cfilter *cf,
638*6236dae4SAndroid Build Coastguard Worker struct Curl_easy *data,
639*6236dae4SAndroid Build Coastguard Worker struct gtls_shared_creds *sc)
640*6236dae4SAndroid Build Coastguard Worker {
641*6236dae4SAndroid Build Coastguard Worker struct ssl_primary_config *conn_config = Curl_ssl_cf_get_primary_config(cf);
642*6236dae4SAndroid Build Coastguard Worker
643*6236dae4SAndroid Build Coastguard Worker DEBUGASSERT(sc);
644*6236dae4SAndroid Build Coastguard Worker DEBUGASSERT(sc->creds);
645*6236dae4SAndroid Build Coastguard Worker DEBUGASSERT(!sc->CAfile);
646*6236dae4SAndroid Build Coastguard Worker DEBUGASSERT(sc->refcount == 1);
647*6236dae4SAndroid Build Coastguard Worker if(!data->multi)
648*6236dae4SAndroid Build Coastguard Worker return;
649*6236dae4SAndroid Build Coastguard Worker
650*6236dae4SAndroid Build Coastguard Worker if(conn_config->CAfile) {
651*6236dae4SAndroid Build Coastguard Worker sc->CAfile = strdup(conn_config->CAfile);
652*6236dae4SAndroid Build Coastguard Worker if(!sc->CAfile)
653*6236dae4SAndroid Build Coastguard Worker return;
654*6236dae4SAndroid Build Coastguard Worker }
655*6236dae4SAndroid Build Coastguard Worker
656*6236dae4SAndroid Build Coastguard Worker if(Curl_gtls_shared_creds_up_ref(sc))
657*6236dae4SAndroid Build Coastguard Worker return;
658*6236dae4SAndroid Build Coastguard Worker
659*6236dae4SAndroid Build Coastguard Worker if(!Curl_hash_add2(&data->multi->proto_hash,
660*6236dae4SAndroid Build Coastguard Worker (void *)MPROTO_GTLS_X509_KEY,
661*6236dae4SAndroid Build Coastguard Worker sizeof(MPROTO_GTLS_X509_KEY)-1,
662*6236dae4SAndroid Build Coastguard Worker sc, gtls_shared_creds_hash_free)) {
663*6236dae4SAndroid Build Coastguard Worker Curl_gtls_shared_creds_free(&sc); /* down reference again */
664*6236dae4SAndroid Build Coastguard Worker return;
665*6236dae4SAndroid Build Coastguard Worker }
666*6236dae4SAndroid Build Coastguard Worker }
667*6236dae4SAndroid Build Coastguard Worker
Curl_gtls_client_trust_setup(struct Curl_cfilter * cf,struct Curl_easy * data,struct gtls_ctx * gtls)668*6236dae4SAndroid Build Coastguard Worker CURLcode Curl_gtls_client_trust_setup(struct Curl_cfilter *cf,
669*6236dae4SAndroid Build Coastguard Worker struct Curl_easy *data,
670*6236dae4SAndroid Build Coastguard Worker struct gtls_ctx *gtls)
671*6236dae4SAndroid Build Coastguard Worker {
672*6236dae4SAndroid Build Coastguard Worker struct ssl_primary_config *conn_config = Curl_ssl_cf_get_primary_config(cf);
673*6236dae4SAndroid Build Coastguard Worker struct ssl_config_data *ssl_config = Curl_ssl_cf_get_config(cf, data);
674*6236dae4SAndroid Build Coastguard Worker struct gtls_shared_creds *cached_creds = NULL;
675*6236dae4SAndroid Build Coastguard Worker bool cache_criteria_met;
676*6236dae4SAndroid Build Coastguard Worker CURLcode result;
677*6236dae4SAndroid Build Coastguard Worker int rc;
678*6236dae4SAndroid Build Coastguard Worker
679*6236dae4SAndroid Build Coastguard Worker
680*6236dae4SAndroid Build Coastguard Worker /* Consider the X509 store cacheable if it comes exclusively from a CAfile,
681*6236dae4SAndroid Build Coastguard Worker or no source is provided and we are falling back to OpenSSL's built-in
682*6236dae4SAndroid Build Coastguard Worker default. */
683*6236dae4SAndroid Build Coastguard Worker cache_criteria_met = (data->set.general_ssl.ca_cache_timeout != 0) &&
684*6236dae4SAndroid Build Coastguard Worker conn_config->verifypeer &&
685*6236dae4SAndroid Build Coastguard Worker !conn_config->CApath &&
686*6236dae4SAndroid Build Coastguard Worker !conn_config->ca_info_blob &&
687*6236dae4SAndroid Build Coastguard Worker !ssl_config->primary.CRLfile &&
688*6236dae4SAndroid Build Coastguard Worker !ssl_config->native_ca_store &&
689*6236dae4SAndroid Build Coastguard Worker !conn_config->clientcert; /* GnuTLS adds client cert to its credentials! */
690*6236dae4SAndroid Build Coastguard Worker
691*6236dae4SAndroid Build Coastguard Worker if(cache_criteria_met)
692*6236dae4SAndroid Build Coastguard Worker cached_creds = gtls_get_cached_creds(cf, data);
693*6236dae4SAndroid Build Coastguard Worker
694*6236dae4SAndroid Build Coastguard Worker if(cached_creds && !Curl_gtls_shared_creds_up_ref(cached_creds)) {
695*6236dae4SAndroid Build Coastguard Worker CURL_TRC_CF(data, cf, "using shared trust anchors and CRLs");
696*6236dae4SAndroid Build Coastguard Worker Curl_gtls_shared_creds_free(>ls->shared_creds);
697*6236dae4SAndroid Build Coastguard Worker gtls->shared_creds = cached_creds;
698*6236dae4SAndroid Build Coastguard Worker rc = gnutls_credentials_set(gtls->session, GNUTLS_CRD_CERTIFICATE,
699*6236dae4SAndroid Build Coastguard Worker gtls->shared_creds->creds);
700*6236dae4SAndroid Build Coastguard Worker if(rc != GNUTLS_E_SUCCESS) {
701*6236dae4SAndroid Build Coastguard Worker failf(data, "gnutls_credentials_set() failed: %s", gnutls_strerror(rc));
702*6236dae4SAndroid Build Coastguard Worker return CURLE_SSL_CONNECT_ERROR;
703*6236dae4SAndroid Build Coastguard Worker }
704*6236dae4SAndroid Build Coastguard Worker }
705*6236dae4SAndroid Build Coastguard Worker else {
706*6236dae4SAndroid Build Coastguard Worker CURL_TRC_CF(data, cf, "loading trust anchors and CRLs");
707*6236dae4SAndroid Build Coastguard Worker result = gtls_populate_creds(cf, data, gtls->shared_creds->creds);
708*6236dae4SAndroid Build Coastguard Worker if(result)
709*6236dae4SAndroid Build Coastguard Worker return result;
710*6236dae4SAndroid Build Coastguard Worker gtls->shared_creds->trust_setup = TRUE;
711*6236dae4SAndroid Build Coastguard Worker if(cache_criteria_met)
712*6236dae4SAndroid Build Coastguard Worker gtls_set_cached_creds(cf, data, gtls->shared_creds);
713*6236dae4SAndroid Build Coastguard Worker }
714*6236dae4SAndroid Build Coastguard Worker return CURLE_OK;
715*6236dae4SAndroid Build Coastguard Worker }
716*6236dae4SAndroid Build Coastguard Worker
gtls_sessionid_free(void * sessionid,size_t idsize)717*6236dae4SAndroid Build Coastguard Worker static void gtls_sessionid_free(void *sessionid, size_t idsize)
718*6236dae4SAndroid Build Coastguard Worker {
719*6236dae4SAndroid Build Coastguard Worker (void)idsize;
720*6236dae4SAndroid Build Coastguard Worker free(sessionid);
721*6236dae4SAndroid Build Coastguard Worker }
722*6236dae4SAndroid Build Coastguard Worker
Curl_gtls_update_session_id(struct Curl_cfilter * cf,struct Curl_easy * data,gnutls_session_t session,struct ssl_peer * peer,const char * alpn)723*6236dae4SAndroid Build Coastguard Worker CURLcode Curl_gtls_update_session_id(struct Curl_cfilter *cf,
724*6236dae4SAndroid Build Coastguard Worker struct Curl_easy *data,
725*6236dae4SAndroid Build Coastguard Worker gnutls_session_t session,
726*6236dae4SAndroid Build Coastguard Worker struct ssl_peer *peer,
727*6236dae4SAndroid Build Coastguard Worker const char *alpn)
728*6236dae4SAndroid Build Coastguard Worker {
729*6236dae4SAndroid Build Coastguard Worker struct ssl_config_data *ssl_config = Curl_ssl_cf_get_config(cf, data);
730*6236dae4SAndroid Build Coastguard Worker void *connect_sessionid;
731*6236dae4SAndroid Build Coastguard Worker size_t connect_idsize = 0;
732*6236dae4SAndroid Build Coastguard Worker CURLcode result = CURLE_OK;
733*6236dae4SAndroid Build Coastguard Worker
734*6236dae4SAndroid Build Coastguard Worker if(!ssl_config->primary.cache_session)
735*6236dae4SAndroid Build Coastguard Worker return CURLE_OK;
736*6236dae4SAndroid Build Coastguard Worker
737*6236dae4SAndroid Build Coastguard Worker /* we always unconditionally get the session id here, as even if we
738*6236dae4SAndroid Build Coastguard Worker already got it from the cache and asked to use it in the connection, it
739*6236dae4SAndroid Build Coastguard Worker might've been rejected and then a new one is in use now and we need to
740*6236dae4SAndroid Build Coastguard Worker detect that. */
741*6236dae4SAndroid Build Coastguard Worker
742*6236dae4SAndroid Build Coastguard Worker /* get the session ID data size */
743*6236dae4SAndroid Build Coastguard Worker gnutls_session_get_data(session, NULL, &connect_idsize);
744*6236dae4SAndroid Build Coastguard Worker if(!connect_idsize) /* gnutls does this for some version combinations */
745*6236dae4SAndroid Build Coastguard Worker return CURLE_OK;
746*6236dae4SAndroid Build Coastguard Worker
747*6236dae4SAndroid Build Coastguard Worker connect_sessionid = malloc(connect_idsize); /* get a buffer for it */
748*6236dae4SAndroid Build Coastguard Worker if(!connect_sessionid)
749*6236dae4SAndroid Build Coastguard Worker return CURLE_OUT_OF_MEMORY;
750*6236dae4SAndroid Build Coastguard Worker
751*6236dae4SAndroid Build Coastguard Worker /* extract session ID to the allocated buffer */
752*6236dae4SAndroid Build Coastguard Worker gnutls_session_get_data(session, connect_sessionid, &connect_idsize);
753*6236dae4SAndroid Build Coastguard Worker
754*6236dae4SAndroid Build Coastguard Worker CURL_TRC_CF(data, cf, "get session id (len=%zu, alpn=%s) and store in cache",
755*6236dae4SAndroid Build Coastguard Worker connect_idsize, alpn ? alpn : "-");
756*6236dae4SAndroid Build Coastguard Worker Curl_ssl_sessionid_lock(data);
757*6236dae4SAndroid Build Coastguard Worker /* store this session id, takes ownership */
758*6236dae4SAndroid Build Coastguard Worker result = Curl_ssl_set_sessionid(cf, data, peer, alpn,
759*6236dae4SAndroid Build Coastguard Worker connect_sessionid, connect_idsize,
760*6236dae4SAndroid Build Coastguard Worker gtls_sessionid_free);
761*6236dae4SAndroid Build Coastguard Worker Curl_ssl_sessionid_unlock(data);
762*6236dae4SAndroid Build Coastguard Worker return result;
763*6236dae4SAndroid Build Coastguard Worker }
764*6236dae4SAndroid Build Coastguard Worker
cf_gtls_update_session_id(struct Curl_cfilter * cf,struct Curl_easy * data,gnutls_session_t session)765*6236dae4SAndroid Build Coastguard Worker static CURLcode cf_gtls_update_session_id(struct Curl_cfilter *cf,
766*6236dae4SAndroid Build Coastguard Worker struct Curl_easy *data,
767*6236dae4SAndroid Build Coastguard Worker gnutls_session_t session)
768*6236dae4SAndroid Build Coastguard Worker {
769*6236dae4SAndroid Build Coastguard Worker struct ssl_connect_data *connssl = cf->ctx;
770*6236dae4SAndroid Build Coastguard Worker return Curl_gtls_update_session_id(cf, data, session, &connssl->peer,
771*6236dae4SAndroid Build Coastguard Worker connssl->alpn_negotiated);
772*6236dae4SAndroid Build Coastguard Worker }
773*6236dae4SAndroid Build Coastguard Worker
gtls_handshake_cb(gnutls_session_t session,unsigned int htype,unsigned when,unsigned int incoming,const gnutls_datum_t * msg)774*6236dae4SAndroid Build Coastguard Worker static int gtls_handshake_cb(gnutls_session_t session, unsigned int htype,
775*6236dae4SAndroid Build Coastguard Worker unsigned when, unsigned int incoming,
776*6236dae4SAndroid Build Coastguard Worker const gnutls_datum_t *msg)
777*6236dae4SAndroid Build Coastguard Worker {
778*6236dae4SAndroid Build Coastguard Worker struct Curl_cfilter *cf = gnutls_session_get_ptr(session);
779*6236dae4SAndroid Build Coastguard Worker
780*6236dae4SAndroid Build Coastguard Worker (void)msg;
781*6236dae4SAndroid Build Coastguard Worker (void)incoming;
782*6236dae4SAndroid Build Coastguard Worker if(when) { /* after message has been processed */
783*6236dae4SAndroid Build Coastguard Worker struct Curl_easy *data = CF_DATA_CURRENT(cf);
784*6236dae4SAndroid Build Coastguard Worker if(data) {
785*6236dae4SAndroid Build Coastguard Worker CURL_TRC_CF(data, cf, "handshake: %s message type %d",
786*6236dae4SAndroid Build Coastguard Worker incoming ? "incoming" : "outgoing", htype);
787*6236dae4SAndroid Build Coastguard Worker switch(htype) {
788*6236dae4SAndroid Build Coastguard Worker case GNUTLS_HANDSHAKE_NEW_SESSION_TICKET: {
789*6236dae4SAndroid Build Coastguard Worker cf_gtls_update_session_id(cf, data, session);
790*6236dae4SAndroid Build Coastguard Worker break;
791*6236dae4SAndroid Build Coastguard Worker }
792*6236dae4SAndroid Build Coastguard Worker default:
793*6236dae4SAndroid Build Coastguard Worker break;
794*6236dae4SAndroid Build Coastguard Worker }
795*6236dae4SAndroid Build Coastguard Worker }
796*6236dae4SAndroid Build Coastguard Worker }
797*6236dae4SAndroid Build Coastguard Worker return 0;
798*6236dae4SAndroid Build Coastguard Worker }
799*6236dae4SAndroid Build Coastguard Worker
gtls_client_init(struct Curl_cfilter * cf,struct Curl_easy * data,struct ssl_peer * peer,struct gtls_ctx * gtls)800*6236dae4SAndroid Build Coastguard Worker static CURLcode gtls_client_init(struct Curl_cfilter *cf,
801*6236dae4SAndroid Build Coastguard Worker struct Curl_easy *data,
802*6236dae4SAndroid Build Coastguard Worker struct ssl_peer *peer,
803*6236dae4SAndroid Build Coastguard Worker struct gtls_ctx *gtls)
804*6236dae4SAndroid Build Coastguard Worker {
805*6236dae4SAndroid Build Coastguard Worker struct ssl_primary_config *config = Curl_ssl_cf_get_primary_config(cf);
806*6236dae4SAndroid Build Coastguard Worker struct ssl_config_data *ssl_config = Curl_ssl_cf_get_config(cf, data);
807*6236dae4SAndroid Build Coastguard Worker unsigned int init_flags;
808*6236dae4SAndroid Build Coastguard Worker int rc;
809*6236dae4SAndroid Build Coastguard Worker bool sni = TRUE; /* default is SNI enabled */
810*6236dae4SAndroid Build Coastguard Worker const char *prioritylist;
811*6236dae4SAndroid Build Coastguard Worker const char *err = NULL;
812*6236dae4SAndroid Build Coastguard Worker const char *tls13support;
813*6236dae4SAndroid Build Coastguard Worker CURLcode result;
814*6236dae4SAndroid Build Coastguard Worker
815*6236dae4SAndroid Build Coastguard Worker if(!gtls_inited)
816*6236dae4SAndroid Build Coastguard Worker gtls_init();
817*6236dae4SAndroid Build Coastguard Worker
818*6236dae4SAndroid Build Coastguard Worker if(config->version == CURL_SSLVERSION_SSLv2) {
819*6236dae4SAndroid Build Coastguard Worker failf(data, "GnuTLS does not support SSLv2");
820*6236dae4SAndroid Build Coastguard Worker return CURLE_SSL_CONNECT_ERROR;
821*6236dae4SAndroid Build Coastguard Worker }
822*6236dae4SAndroid Build Coastguard Worker else if(config->version == CURL_SSLVERSION_SSLv3)
823*6236dae4SAndroid Build Coastguard Worker sni = FALSE; /* SSLv3 has no SNI */
824*6236dae4SAndroid Build Coastguard Worker
825*6236dae4SAndroid Build Coastguard Worker /* allocate a shared creds struct */
826*6236dae4SAndroid Build Coastguard Worker result = Curl_gtls_shared_creds_create(data, >ls->shared_creds);
827*6236dae4SAndroid Build Coastguard Worker if(result)
828*6236dae4SAndroid Build Coastguard Worker return result;
829*6236dae4SAndroid Build Coastguard Worker
830*6236dae4SAndroid Build Coastguard Worker #ifdef USE_GNUTLS_SRP
831*6236dae4SAndroid Build Coastguard Worker if(config->username && Curl_auth_allowed_to_host(data)) {
832*6236dae4SAndroid Build Coastguard Worker infof(data, "Using TLS-SRP username: %s", config->username);
833*6236dae4SAndroid Build Coastguard Worker
834*6236dae4SAndroid Build Coastguard Worker rc = gnutls_srp_allocate_client_credentials(>ls->srp_client_cred);
835*6236dae4SAndroid Build Coastguard Worker if(rc != GNUTLS_E_SUCCESS) {
836*6236dae4SAndroid Build Coastguard Worker failf(data, "gnutls_srp_allocate_client_cred() failed: %s",
837*6236dae4SAndroid Build Coastguard Worker gnutls_strerror(rc));
838*6236dae4SAndroid Build Coastguard Worker return CURLE_OUT_OF_MEMORY;
839*6236dae4SAndroid Build Coastguard Worker }
840*6236dae4SAndroid Build Coastguard Worker
841*6236dae4SAndroid Build Coastguard Worker rc = gnutls_srp_set_client_credentials(gtls->srp_client_cred,
842*6236dae4SAndroid Build Coastguard Worker config->username,
843*6236dae4SAndroid Build Coastguard Worker config->password);
844*6236dae4SAndroid Build Coastguard Worker if(rc != GNUTLS_E_SUCCESS) {
845*6236dae4SAndroid Build Coastguard Worker failf(data, "gnutls_srp_set_client_cred() failed: %s",
846*6236dae4SAndroid Build Coastguard Worker gnutls_strerror(rc));
847*6236dae4SAndroid Build Coastguard Worker return CURLE_BAD_FUNCTION_ARGUMENT;
848*6236dae4SAndroid Build Coastguard Worker }
849*6236dae4SAndroid Build Coastguard Worker }
850*6236dae4SAndroid Build Coastguard Worker #endif
851*6236dae4SAndroid Build Coastguard Worker
852*6236dae4SAndroid Build Coastguard Worker ssl_config->certverifyresult = 0;
853*6236dae4SAndroid Build Coastguard Worker
854*6236dae4SAndroid Build Coastguard Worker /* Initialize TLS session as a client */
855*6236dae4SAndroid Build Coastguard Worker init_flags = GNUTLS_CLIENT;
856*6236dae4SAndroid Build Coastguard Worker
857*6236dae4SAndroid Build Coastguard Worker #if defined(GNUTLS_FORCE_CLIENT_CERT)
858*6236dae4SAndroid Build Coastguard Worker init_flags |= GNUTLS_FORCE_CLIENT_CERT;
859*6236dae4SAndroid Build Coastguard Worker #endif
860*6236dae4SAndroid Build Coastguard Worker
861*6236dae4SAndroid Build Coastguard Worker #if defined(GNUTLS_NO_TICKETS_TLS12)
862*6236dae4SAndroid Build Coastguard Worker init_flags |= GNUTLS_NO_TICKETS_TLS12;
863*6236dae4SAndroid Build Coastguard Worker #elif defined(GNUTLS_NO_TICKETS)
864*6236dae4SAndroid Build Coastguard Worker /* Disable TLS session tickets for non 1.3 connections */
865*6236dae4SAndroid Build Coastguard Worker if((config->version != CURL_SSLVERSION_TLSv1_3) &&
866*6236dae4SAndroid Build Coastguard Worker (config->version != CURL_SSLVERSION_DEFAULT))
867*6236dae4SAndroid Build Coastguard Worker init_flags |= GNUTLS_NO_TICKETS;
868*6236dae4SAndroid Build Coastguard Worker #endif
869*6236dae4SAndroid Build Coastguard Worker
870*6236dae4SAndroid Build Coastguard Worker #if defined(GNUTLS_NO_STATUS_REQUEST)
871*6236dae4SAndroid Build Coastguard Worker if(!config->verifystatus)
872*6236dae4SAndroid Build Coastguard Worker /* Disable the "status_request" TLS extension, enabled by default since
873*6236dae4SAndroid Build Coastguard Worker GnuTLS 3.8.0. */
874*6236dae4SAndroid Build Coastguard Worker init_flags |= GNUTLS_NO_STATUS_REQUEST;
875*6236dae4SAndroid Build Coastguard Worker #endif
876*6236dae4SAndroid Build Coastguard Worker
877*6236dae4SAndroid Build Coastguard Worker rc = gnutls_init(>ls->session, init_flags);
878*6236dae4SAndroid Build Coastguard Worker if(rc != GNUTLS_E_SUCCESS) {
879*6236dae4SAndroid Build Coastguard Worker failf(data, "gnutls_init() failed: %d", rc);
880*6236dae4SAndroid Build Coastguard Worker return CURLE_SSL_CONNECT_ERROR;
881*6236dae4SAndroid Build Coastguard Worker }
882*6236dae4SAndroid Build Coastguard Worker
883*6236dae4SAndroid Build Coastguard Worker if(sni && peer->sni) {
884*6236dae4SAndroid Build Coastguard Worker if(gnutls_server_name_set(gtls->session, GNUTLS_NAME_DNS,
885*6236dae4SAndroid Build Coastguard Worker peer->sni, strlen(peer->sni)) < 0) {
886*6236dae4SAndroid Build Coastguard Worker failf(data, "Failed to set SNI");
887*6236dae4SAndroid Build Coastguard Worker return CURLE_SSL_CONNECT_ERROR;
888*6236dae4SAndroid Build Coastguard Worker }
889*6236dae4SAndroid Build Coastguard Worker }
890*6236dae4SAndroid Build Coastguard Worker
891*6236dae4SAndroid Build Coastguard Worker /* Use default priorities */
892*6236dae4SAndroid Build Coastguard Worker rc = gnutls_set_default_priority(gtls->session);
893*6236dae4SAndroid Build Coastguard Worker if(rc != GNUTLS_E_SUCCESS)
894*6236dae4SAndroid Build Coastguard Worker return CURLE_SSL_CONNECT_ERROR;
895*6236dae4SAndroid Build Coastguard Worker
896*6236dae4SAndroid Build Coastguard Worker /* "In GnuTLS 3.6.5, TLS 1.3 is enabled by default" */
897*6236dae4SAndroid Build Coastguard Worker tls13support = gnutls_check_version("3.6.5");
898*6236dae4SAndroid Build Coastguard Worker
899*6236dae4SAndroid Build Coastguard Worker /* Ensure +SRP comes at the *end* of all relevant strings so that it can be
900*6236dae4SAndroid Build Coastguard Worker * removed if a runtime error indicates that SRP is not supported by this
901*6236dae4SAndroid Build Coastguard Worker * GnuTLS version */
902*6236dae4SAndroid Build Coastguard Worker
903*6236dae4SAndroid Build Coastguard Worker if(config->version == CURL_SSLVERSION_SSLv2 ||
904*6236dae4SAndroid Build Coastguard Worker config->version == CURL_SSLVERSION_SSLv3) {
905*6236dae4SAndroid Build Coastguard Worker failf(data, "GnuTLS does not support SSLv2 or SSLv3");
906*6236dae4SAndroid Build Coastguard Worker return CURLE_SSL_CONNECT_ERROR;
907*6236dae4SAndroid Build Coastguard Worker }
908*6236dae4SAndroid Build Coastguard Worker
909*6236dae4SAndroid Build Coastguard Worker if(config->version == CURL_SSLVERSION_TLSv1_3) {
910*6236dae4SAndroid Build Coastguard Worker if(!tls13support) {
911*6236dae4SAndroid Build Coastguard Worker failf(data, "This GnuTLS installation does not support TLS 1.3");
912*6236dae4SAndroid Build Coastguard Worker return CURLE_SSL_CONNECT_ERROR;
913*6236dae4SAndroid Build Coastguard Worker }
914*6236dae4SAndroid Build Coastguard Worker }
915*6236dae4SAndroid Build Coastguard Worker
916*6236dae4SAndroid Build Coastguard Worker /* At this point we know we have a supported TLS version, so set it */
917*6236dae4SAndroid Build Coastguard Worker result = gnutls_set_ssl_version_min_max(data, peer,
918*6236dae4SAndroid Build Coastguard Worker config, &prioritylist, tls13support);
919*6236dae4SAndroid Build Coastguard Worker if(result)
920*6236dae4SAndroid Build Coastguard Worker return result;
921*6236dae4SAndroid Build Coastguard Worker
922*6236dae4SAndroid Build Coastguard Worker #ifdef USE_GNUTLS_SRP
923*6236dae4SAndroid Build Coastguard Worker /* Only add SRP to the cipher list if SRP is requested. Otherwise
924*6236dae4SAndroid Build Coastguard Worker * GnuTLS will disable TLS 1.3 support. */
925*6236dae4SAndroid Build Coastguard Worker if(config->username) {
926*6236dae4SAndroid Build Coastguard Worker char *prioritysrp = aprintf("%s:" GNUTLS_SRP, prioritylist);
927*6236dae4SAndroid Build Coastguard Worker if(!prioritysrp)
928*6236dae4SAndroid Build Coastguard Worker return CURLE_OUT_OF_MEMORY;
929*6236dae4SAndroid Build Coastguard Worker rc = gnutls_priority_set_direct(gtls->session, prioritysrp, &err);
930*6236dae4SAndroid Build Coastguard Worker free(prioritysrp);
931*6236dae4SAndroid Build Coastguard Worker
932*6236dae4SAndroid Build Coastguard Worker if((rc == GNUTLS_E_INVALID_REQUEST) && err) {
933*6236dae4SAndroid Build Coastguard Worker infof(data, "This GnuTLS does not support SRP");
934*6236dae4SAndroid Build Coastguard Worker }
935*6236dae4SAndroid Build Coastguard Worker }
936*6236dae4SAndroid Build Coastguard Worker else {
937*6236dae4SAndroid Build Coastguard Worker #endif
938*6236dae4SAndroid Build Coastguard Worker infof(data, "GnuTLS ciphers: %s", prioritylist);
939*6236dae4SAndroid Build Coastguard Worker rc = gnutls_priority_set_direct(gtls->session, prioritylist, &err);
940*6236dae4SAndroid Build Coastguard Worker #ifdef USE_GNUTLS_SRP
941*6236dae4SAndroid Build Coastguard Worker }
942*6236dae4SAndroid Build Coastguard Worker #endif
943*6236dae4SAndroid Build Coastguard Worker
944*6236dae4SAndroid Build Coastguard Worker if(rc != GNUTLS_E_SUCCESS) {
945*6236dae4SAndroid Build Coastguard Worker failf(data, "Error %d setting GnuTLS cipher list starting with %s",
946*6236dae4SAndroid Build Coastguard Worker rc, err);
947*6236dae4SAndroid Build Coastguard Worker return CURLE_SSL_CONNECT_ERROR;
948*6236dae4SAndroid Build Coastguard Worker }
949*6236dae4SAndroid Build Coastguard Worker
950*6236dae4SAndroid Build Coastguard Worker if(config->clientcert) {
951*6236dae4SAndroid Build Coastguard Worker if(!gtls->shared_creds->trust_setup) {
952*6236dae4SAndroid Build Coastguard Worker result = Curl_gtls_client_trust_setup(cf, data, gtls);
953*6236dae4SAndroid Build Coastguard Worker if(result)
954*6236dae4SAndroid Build Coastguard Worker return result;
955*6236dae4SAndroid Build Coastguard Worker }
956*6236dae4SAndroid Build Coastguard Worker if(ssl_config->cert_type && strcasecompare(ssl_config->cert_type, "P12")) {
957*6236dae4SAndroid Build Coastguard Worker rc = gnutls_certificate_set_x509_simple_pkcs12_file(
958*6236dae4SAndroid Build Coastguard Worker gtls->shared_creds->creds, config->clientcert, GNUTLS_X509_FMT_DER,
959*6236dae4SAndroid Build Coastguard Worker ssl_config->key_passwd ? ssl_config->key_passwd : "");
960*6236dae4SAndroid Build Coastguard Worker if(rc != GNUTLS_E_SUCCESS) {
961*6236dae4SAndroid Build Coastguard Worker failf(data,
962*6236dae4SAndroid Build Coastguard Worker "error reading X.509 potentially-encrypted key or certificate "
963*6236dae4SAndroid Build Coastguard Worker "file: %s",
964*6236dae4SAndroid Build Coastguard Worker gnutls_strerror(rc));
965*6236dae4SAndroid Build Coastguard Worker return CURLE_SSL_CONNECT_ERROR;
966*6236dae4SAndroid Build Coastguard Worker }
967*6236dae4SAndroid Build Coastguard Worker }
968*6236dae4SAndroid Build Coastguard Worker else if(ssl_config->key_passwd) {
969*6236dae4SAndroid Build Coastguard Worker const unsigned int supported_key_encryption_algorithms =
970*6236dae4SAndroid Build Coastguard Worker GNUTLS_PKCS_USE_PKCS12_3DES | GNUTLS_PKCS_USE_PKCS12_ARCFOUR |
971*6236dae4SAndroid Build Coastguard Worker GNUTLS_PKCS_USE_PKCS12_RC2_40 | GNUTLS_PKCS_USE_PBES2_3DES |
972*6236dae4SAndroid Build Coastguard Worker GNUTLS_PKCS_USE_PBES2_AES_128 | GNUTLS_PKCS_USE_PBES2_AES_192 |
973*6236dae4SAndroid Build Coastguard Worker GNUTLS_PKCS_USE_PBES2_AES_256;
974*6236dae4SAndroid Build Coastguard Worker rc = gnutls_certificate_set_x509_key_file2(
975*6236dae4SAndroid Build Coastguard Worker gtls->shared_creds->creds,
976*6236dae4SAndroid Build Coastguard Worker config->clientcert,
977*6236dae4SAndroid Build Coastguard Worker ssl_config->key ? ssl_config->key : config->clientcert,
978*6236dae4SAndroid Build Coastguard Worker gnutls_do_file_type(ssl_config->cert_type),
979*6236dae4SAndroid Build Coastguard Worker ssl_config->key_passwd,
980*6236dae4SAndroid Build Coastguard Worker supported_key_encryption_algorithms);
981*6236dae4SAndroid Build Coastguard Worker if(rc != GNUTLS_E_SUCCESS) {
982*6236dae4SAndroid Build Coastguard Worker failf(data,
983*6236dae4SAndroid Build Coastguard Worker "error reading X.509 potentially-encrypted key file: %s",
984*6236dae4SAndroid Build Coastguard Worker gnutls_strerror(rc));
985*6236dae4SAndroid Build Coastguard Worker return CURLE_SSL_CONNECT_ERROR;
986*6236dae4SAndroid Build Coastguard Worker }
987*6236dae4SAndroid Build Coastguard Worker }
988*6236dae4SAndroid Build Coastguard Worker else {
989*6236dae4SAndroid Build Coastguard Worker if(gnutls_certificate_set_x509_key_file(
990*6236dae4SAndroid Build Coastguard Worker gtls->shared_creds->creds,
991*6236dae4SAndroid Build Coastguard Worker config->clientcert,
992*6236dae4SAndroid Build Coastguard Worker ssl_config->key ? ssl_config->key : config->clientcert,
993*6236dae4SAndroid Build Coastguard Worker gnutls_do_file_type(ssl_config->cert_type) ) !=
994*6236dae4SAndroid Build Coastguard Worker GNUTLS_E_SUCCESS) {
995*6236dae4SAndroid Build Coastguard Worker failf(data, "error reading X.509 key or certificate file");
996*6236dae4SAndroid Build Coastguard Worker return CURLE_SSL_CONNECT_ERROR;
997*6236dae4SAndroid Build Coastguard Worker }
998*6236dae4SAndroid Build Coastguard Worker }
999*6236dae4SAndroid Build Coastguard Worker }
1000*6236dae4SAndroid Build Coastguard Worker
1001*6236dae4SAndroid Build Coastguard Worker #ifdef USE_GNUTLS_SRP
1002*6236dae4SAndroid Build Coastguard Worker /* put the credentials to the current session */
1003*6236dae4SAndroid Build Coastguard Worker if(config->username) {
1004*6236dae4SAndroid Build Coastguard Worker rc = gnutls_credentials_set(gtls->session, GNUTLS_CRD_SRP,
1005*6236dae4SAndroid Build Coastguard Worker gtls->srp_client_cred);
1006*6236dae4SAndroid Build Coastguard Worker if(rc != GNUTLS_E_SUCCESS) {
1007*6236dae4SAndroid Build Coastguard Worker failf(data, "gnutls_credentials_set() failed: %s", gnutls_strerror(rc));
1008*6236dae4SAndroid Build Coastguard Worker return CURLE_SSL_CONNECT_ERROR;
1009*6236dae4SAndroid Build Coastguard Worker }
1010*6236dae4SAndroid Build Coastguard Worker }
1011*6236dae4SAndroid Build Coastguard Worker else
1012*6236dae4SAndroid Build Coastguard Worker #endif
1013*6236dae4SAndroid Build Coastguard Worker {
1014*6236dae4SAndroid Build Coastguard Worker rc = gnutls_credentials_set(gtls->session, GNUTLS_CRD_CERTIFICATE,
1015*6236dae4SAndroid Build Coastguard Worker gtls->shared_creds->creds);
1016*6236dae4SAndroid Build Coastguard Worker if(rc != GNUTLS_E_SUCCESS) {
1017*6236dae4SAndroid Build Coastguard Worker failf(data, "gnutls_credentials_set() failed: %s", gnutls_strerror(rc));
1018*6236dae4SAndroid Build Coastguard Worker return CURLE_SSL_CONNECT_ERROR;
1019*6236dae4SAndroid Build Coastguard Worker }
1020*6236dae4SAndroid Build Coastguard Worker }
1021*6236dae4SAndroid Build Coastguard Worker
1022*6236dae4SAndroid Build Coastguard Worker if(config->verifystatus) {
1023*6236dae4SAndroid Build Coastguard Worker rc = gnutls_ocsp_status_request_enable_client(gtls->session,
1024*6236dae4SAndroid Build Coastguard Worker NULL, 0, NULL);
1025*6236dae4SAndroid Build Coastguard Worker if(rc != GNUTLS_E_SUCCESS) {
1026*6236dae4SAndroid Build Coastguard Worker failf(data, "gnutls_ocsp_status_request_enable_client() failed: %d", rc);
1027*6236dae4SAndroid Build Coastguard Worker return CURLE_SSL_CONNECT_ERROR;
1028*6236dae4SAndroid Build Coastguard Worker }
1029*6236dae4SAndroid Build Coastguard Worker }
1030*6236dae4SAndroid Build Coastguard Worker
1031*6236dae4SAndroid Build Coastguard Worker return CURLE_OK;
1032*6236dae4SAndroid Build Coastguard Worker }
1033*6236dae4SAndroid Build Coastguard Worker
keylog_callback(gnutls_session_t session,const char * label,const gnutls_datum_t * secret)1034*6236dae4SAndroid Build Coastguard Worker static int keylog_callback(gnutls_session_t session, const char *label,
1035*6236dae4SAndroid Build Coastguard Worker const gnutls_datum_t *secret)
1036*6236dae4SAndroid Build Coastguard Worker {
1037*6236dae4SAndroid Build Coastguard Worker gnutls_datum_t crandom;
1038*6236dae4SAndroid Build Coastguard Worker gnutls_datum_t srandom;
1039*6236dae4SAndroid Build Coastguard Worker
1040*6236dae4SAndroid Build Coastguard Worker gnutls_session_get_random(session, &crandom, &srandom);
1041*6236dae4SAndroid Build Coastguard Worker if(crandom.size != 32) {
1042*6236dae4SAndroid Build Coastguard Worker return -1;
1043*6236dae4SAndroid Build Coastguard Worker }
1044*6236dae4SAndroid Build Coastguard Worker
1045*6236dae4SAndroid Build Coastguard Worker Curl_tls_keylog_write(label, crandom.data, secret->data, secret->size);
1046*6236dae4SAndroid Build Coastguard Worker return 0;
1047*6236dae4SAndroid Build Coastguard Worker }
1048*6236dae4SAndroid Build Coastguard Worker
Curl_gtls_ctx_init(struct gtls_ctx * gctx,struct Curl_cfilter * cf,struct Curl_easy * data,struct ssl_peer * peer,const unsigned char * alpn,size_t alpn_len,struct ssl_connect_data * connssl,Curl_gtls_ctx_setup_cb * cb_setup,void * cb_user_data,void * ssl_user_data)1049*6236dae4SAndroid Build Coastguard Worker CURLcode Curl_gtls_ctx_init(struct gtls_ctx *gctx,
1050*6236dae4SAndroid Build Coastguard Worker struct Curl_cfilter *cf,
1051*6236dae4SAndroid Build Coastguard Worker struct Curl_easy *data,
1052*6236dae4SAndroid Build Coastguard Worker struct ssl_peer *peer,
1053*6236dae4SAndroid Build Coastguard Worker const unsigned char *alpn, size_t alpn_len,
1054*6236dae4SAndroid Build Coastguard Worker struct ssl_connect_data *connssl,
1055*6236dae4SAndroid Build Coastguard Worker Curl_gtls_ctx_setup_cb *cb_setup,
1056*6236dae4SAndroid Build Coastguard Worker void *cb_user_data,
1057*6236dae4SAndroid Build Coastguard Worker void *ssl_user_data)
1058*6236dae4SAndroid Build Coastguard Worker {
1059*6236dae4SAndroid Build Coastguard Worker struct ssl_primary_config *conn_config = Curl_ssl_cf_get_primary_config(cf);
1060*6236dae4SAndroid Build Coastguard Worker struct ssl_config_data *ssl_config = Curl_ssl_cf_get_config(cf, data);
1061*6236dae4SAndroid Build Coastguard Worker gnutls_datum_t gtls_alpns[5];
1062*6236dae4SAndroid Build Coastguard Worker size_t gtls_alpns_count = 0;
1063*6236dae4SAndroid Build Coastguard Worker CURLcode result;
1064*6236dae4SAndroid Build Coastguard Worker
1065*6236dae4SAndroid Build Coastguard Worker DEBUGASSERT(gctx);
1066*6236dae4SAndroid Build Coastguard Worker
1067*6236dae4SAndroid Build Coastguard Worker result = gtls_client_init(cf, data, peer, gctx);
1068*6236dae4SAndroid Build Coastguard Worker if(result)
1069*6236dae4SAndroid Build Coastguard Worker return result;
1070*6236dae4SAndroid Build Coastguard Worker
1071*6236dae4SAndroid Build Coastguard Worker gnutls_session_set_ptr(gctx->session, ssl_user_data);
1072*6236dae4SAndroid Build Coastguard Worker
1073*6236dae4SAndroid Build Coastguard Worker if(cb_setup) {
1074*6236dae4SAndroid Build Coastguard Worker result = cb_setup(cf, data, cb_user_data);
1075*6236dae4SAndroid Build Coastguard Worker if(result)
1076*6236dae4SAndroid Build Coastguard Worker return result;
1077*6236dae4SAndroid Build Coastguard Worker }
1078*6236dae4SAndroid Build Coastguard Worker
1079*6236dae4SAndroid Build Coastguard Worker /* Open the file if a TLS or QUIC backend has not done this before. */
1080*6236dae4SAndroid Build Coastguard Worker Curl_tls_keylog_open();
1081*6236dae4SAndroid Build Coastguard Worker if(Curl_tls_keylog_enabled()) {
1082*6236dae4SAndroid Build Coastguard Worker gnutls_session_set_keylog_function(gctx->session, keylog_callback);
1083*6236dae4SAndroid Build Coastguard Worker }
1084*6236dae4SAndroid Build Coastguard Worker
1085*6236dae4SAndroid Build Coastguard Worker /* This might be a reconnect, so we check for a session ID in the cache
1086*6236dae4SAndroid Build Coastguard Worker to speed up things */
1087*6236dae4SAndroid Build Coastguard Worker if(conn_config->cache_session) {
1088*6236dae4SAndroid Build Coastguard Worker void *ssl_sessionid;
1089*6236dae4SAndroid Build Coastguard Worker size_t ssl_idsize;
1090*6236dae4SAndroid Build Coastguard Worker char *session_alpn;
1091*6236dae4SAndroid Build Coastguard Worker Curl_ssl_sessionid_lock(data);
1092*6236dae4SAndroid Build Coastguard Worker if(!Curl_ssl_getsessionid(cf, data, peer,
1093*6236dae4SAndroid Build Coastguard Worker &ssl_sessionid, &ssl_idsize, &session_alpn)) {
1094*6236dae4SAndroid Build Coastguard Worker /* we got a session id, use it! */
1095*6236dae4SAndroid Build Coastguard Worker int rc;
1096*6236dae4SAndroid Build Coastguard Worker
1097*6236dae4SAndroid Build Coastguard Worker rc = gnutls_session_set_data(gctx->session, ssl_sessionid, ssl_idsize);
1098*6236dae4SAndroid Build Coastguard Worker if(rc < 0)
1099*6236dae4SAndroid Build Coastguard Worker infof(data, "SSL failed to set session ID");
1100*6236dae4SAndroid Build Coastguard Worker else {
1101*6236dae4SAndroid Build Coastguard Worker infof(data, "SSL reusing session ID (size=%zu, alpn=%s)",
1102*6236dae4SAndroid Build Coastguard Worker ssl_idsize, session_alpn ? session_alpn : "-");
1103*6236dae4SAndroid Build Coastguard Worker #ifdef DEBUGBUILD
1104*6236dae4SAndroid Build Coastguard Worker if((ssl_config->earlydata || !!getenv("CURL_USE_EARLYDATA")) &&
1105*6236dae4SAndroid Build Coastguard Worker #else
1106*6236dae4SAndroid Build Coastguard Worker if(ssl_config->earlydata &&
1107*6236dae4SAndroid Build Coastguard Worker #endif
1108*6236dae4SAndroid Build Coastguard Worker !cf->conn->connect_only && connssl &&
1109*6236dae4SAndroid Build Coastguard Worker (gnutls_protocol_get_version(gctx->session) == GNUTLS_TLS1_3) &&
1110*6236dae4SAndroid Build Coastguard Worker Curl_alpn_contains_proto(connssl->alpn, session_alpn)) {
1111*6236dae4SAndroid Build Coastguard Worker connssl->earlydata_max =
1112*6236dae4SAndroid Build Coastguard Worker gnutls_record_get_max_early_data_size(gctx->session);
1113*6236dae4SAndroid Build Coastguard Worker if((!connssl->earlydata_max ||
1114*6236dae4SAndroid Build Coastguard Worker connssl->earlydata_max == 0xFFFFFFFFUL)) {
1115*6236dae4SAndroid Build Coastguard Worker /* Seems to be GnuTLS way to signal no EarlyData in session */
1116*6236dae4SAndroid Build Coastguard Worker CURL_TRC_CF(data, cf, "TLS session does not allow earlydata");
1117*6236dae4SAndroid Build Coastguard Worker }
1118*6236dae4SAndroid Build Coastguard Worker else {
1119*6236dae4SAndroid Build Coastguard Worker CURL_TRC_CF(data, cf, "TLS session allows %zu earlydata bytes, "
1120*6236dae4SAndroid Build Coastguard Worker "reusing ALPN '%s'",
1121*6236dae4SAndroid Build Coastguard Worker connssl->earlydata_max, session_alpn);
1122*6236dae4SAndroid Build Coastguard Worker connssl->earlydata_state = ssl_earlydata_use;
1123*6236dae4SAndroid Build Coastguard Worker connssl->state = ssl_connection_deferred;
1124*6236dae4SAndroid Build Coastguard Worker result = Curl_alpn_set_negotiated(cf, data, connssl,
1125*6236dae4SAndroid Build Coastguard Worker (const unsigned char *)session_alpn,
1126*6236dae4SAndroid Build Coastguard Worker session_alpn ? strlen(session_alpn) : 0);
1127*6236dae4SAndroid Build Coastguard Worker if(result)
1128*6236dae4SAndroid Build Coastguard Worker return result;
1129*6236dae4SAndroid Build Coastguard Worker /* We only try the ALPN protocol the session used before,
1130*6236dae4SAndroid Build Coastguard Worker * otherwise we might send early data for the wrong protocol */
1131*6236dae4SAndroid Build Coastguard Worker gtls_alpns[0].data = (unsigned char *)session_alpn;
1132*6236dae4SAndroid Build Coastguard Worker gtls_alpns[0].size = (unsigned)strlen(session_alpn);
1133*6236dae4SAndroid Build Coastguard Worker gtls_alpns_count = 1;
1134*6236dae4SAndroid Build Coastguard Worker }
1135*6236dae4SAndroid Build Coastguard Worker }
1136*6236dae4SAndroid Build Coastguard Worker }
1137*6236dae4SAndroid Build Coastguard Worker }
1138*6236dae4SAndroid Build Coastguard Worker Curl_ssl_sessionid_unlock(data);
1139*6236dae4SAndroid Build Coastguard Worker }
1140*6236dae4SAndroid Build Coastguard Worker
1141*6236dae4SAndroid Build Coastguard Worker /* convert the ALPN string from our arguments to a list of strings that
1142*6236dae4SAndroid Build Coastguard Worker * gnutls wants and will convert internally back to this string for sending
1143*6236dae4SAndroid Build Coastguard Worker * to the server. nice. */
1144*6236dae4SAndroid Build Coastguard Worker if(!gtls_alpns_count && alpn && alpn_len) {
1145*6236dae4SAndroid Build Coastguard Worker size_t i, alen = alpn_len;
1146*6236dae4SAndroid Build Coastguard Worker unsigned char *s = (unsigned char *)alpn;
1147*6236dae4SAndroid Build Coastguard Worker unsigned char slen;
1148*6236dae4SAndroid Build Coastguard Worker for(i = 0; (i < ARRAYSIZE(gtls_alpns)) && alen; ++i) {
1149*6236dae4SAndroid Build Coastguard Worker slen = s[0];
1150*6236dae4SAndroid Build Coastguard Worker if(slen >= alen)
1151*6236dae4SAndroid Build Coastguard Worker return CURLE_FAILED_INIT;
1152*6236dae4SAndroid Build Coastguard Worker gtls_alpns[i].data = s + 1;
1153*6236dae4SAndroid Build Coastguard Worker gtls_alpns[i].size = slen;
1154*6236dae4SAndroid Build Coastguard Worker s += slen + 1;
1155*6236dae4SAndroid Build Coastguard Worker alen -= (size_t)slen + 1;
1156*6236dae4SAndroid Build Coastguard Worker }
1157*6236dae4SAndroid Build Coastguard Worker if(alen) /* not all alpn chars used, wrong format or too many */
1158*6236dae4SAndroid Build Coastguard Worker return CURLE_FAILED_INIT;
1159*6236dae4SAndroid Build Coastguard Worker gtls_alpns_count = i;
1160*6236dae4SAndroid Build Coastguard Worker }
1161*6236dae4SAndroid Build Coastguard Worker
1162*6236dae4SAndroid Build Coastguard Worker if(gtls_alpns_count &&
1163*6236dae4SAndroid Build Coastguard Worker gnutls_alpn_set_protocols(gctx->session,
1164*6236dae4SAndroid Build Coastguard Worker gtls_alpns, (unsigned int)gtls_alpns_count,
1165*6236dae4SAndroid Build Coastguard Worker GNUTLS_ALPN_MANDATORY)) {
1166*6236dae4SAndroid Build Coastguard Worker failf(data, "failed setting ALPN");
1167*6236dae4SAndroid Build Coastguard Worker return CURLE_SSL_CONNECT_ERROR;
1168*6236dae4SAndroid Build Coastguard Worker }
1169*6236dae4SAndroid Build Coastguard Worker
1170*6236dae4SAndroid Build Coastguard Worker return CURLE_OK;
1171*6236dae4SAndroid Build Coastguard Worker }
1172*6236dae4SAndroid Build Coastguard Worker
1173*6236dae4SAndroid Build Coastguard Worker static CURLcode
gtls_connect_step1(struct Curl_cfilter * cf,struct Curl_easy * data)1174*6236dae4SAndroid Build Coastguard Worker gtls_connect_step1(struct Curl_cfilter *cf, struct Curl_easy *data)
1175*6236dae4SAndroid Build Coastguard Worker {
1176*6236dae4SAndroid Build Coastguard Worker struct ssl_connect_data *connssl = cf->ctx;
1177*6236dae4SAndroid Build Coastguard Worker struct gtls_ssl_backend_data *backend =
1178*6236dae4SAndroid Build Coastguard Worker (struct gtls_ssl_backend_data *)connssl->backend;
1179*6236dae4SAndroid Build Coastguard Worker struct alpn_proto_buf proto;
1180*6236dae4SAndroid Build Coastguard Worker CURLcode result;
1181*6236dae4SAndroid Build Coastguard Worker
1182*6236dae4SAndroid Build Coastguard Worker DEBUGASSERT(backend);
1183*6236dae4SAndroid Build Coastguard Worker DEBUGASSERT(ssl_connect_1 == connssl->connecting_state);
1184*6236dae4SAndroid Build Coastguard Worker
1185*6236dae4SAndroid Build Coastguard Worker if(connssl->state == ssl_connection_complete)
1186*6236dae4SAndroid Build Coastguard Worker /* to make us tolerant against being called more than once for the
1187*6236dae4SAndroid Build Coastguard Worker same connection */
1188*6236dae4SAndroid Build Coastguard Worker return CURLE_OK;
1189*6236dae4SAndroid Build Coastguard Worker
1190*6236dae4SAndroid Build Coastguard Worker memset(&proto, 0, sizeof(proto));
1191*6236dae4SAndroid Build Coastguard Worker if(connssl->alpn) {
1192*6236dae4SAndroid Build Coastguard Worker result = Curl_alpn_to_proto_buf(&proto, connssl->alpn);
1193*6236dae4SAndroid Build Coastguard Worker if(result) {
1194*6236dae4SAndroid Build Coastguard Worker failf(data, "Error determining ALPN");
1195*6236dae4SAndroid Build Coastguard Worker return CURLE_SSL_CONNECT_ERROR;
1196*6236dae4SAndroid Build Coastguard Worker }
1197*6236dae4SAndroid Build Coastguard Worker }
1198*6236dae4SAndroid Build Coastguard Worker
1199*6236dae4SAndroid Build Coastguard Worker result = Curl_gtls_ctx_init(&backend->gtls, cf, data, &connssl->peer,
1200*6236dae4SAndroid Build Coastguard Worker proto.data, proto.len, connssl, NULL, NULL, cf);
1201*6236dae4SAndroid Build Coastguard Worker if(result)
1202*6236dae4SAndroid Build Coastguard Worker return result;
1203*6236dae4SAndroid Build Coastguard Worker
1204*6236dae4SAndroid Build Coastguard Worker if(connssl->alpn && (connssl->state != ssl_connection_deferred)) {
1205*6236dae4SAndroid Build Coastguard Worker Curl_alpn_to_proto_str(&proto, connssl->alpn);
1206*6236dae4SAndroid Build Coastguard Worker infof(data, VTLS_INFOF_ALPN_OFFER_1STR, proto.data);
1207*6236dae4SAndroid Build Coastguard Worker }
1208*6236dae4SAndroid Build Coastguard Worker
1209*6236dae4SAndroid Build Coastguard Worker gnutls_handshake_set_hook_function(backend->gtls.session,
1210*6236dae4SAndroid Build Coastguard Worker GNUTLS_HANDSHAKE_ANY, GNUTLS_HOOK_POST,
1211*6236dae4SAndroid Build Coastguard Worker gtls_handshake_cb);
1212*6236dae4SAndroid Build Coastguard Worker
1213*6236dae4SAndroid Build Coastguard Worker /* register callback functions and handle to send and receive data. */
1214*6236dae4SAndroid Build Coastguard Worker gnutls_transport_set_ptr(backend->gtls.session, cf);
1215*6236dae4SAndroid Build Coastguard Worker gnutls_transport_set_push_function(backend->gtls.session, gtls_push);
1216*6236dae4SAndroid Build Coastguard Worker gnutls_transport_set_pull_function(backend->gtls.session, gtls_pull);
1217*6236dae4SAndroid Build Coastguard Worker
1218*6236dae4SAndroid Build Coastguard Worker return CURLE_OK;
1219*6236dae4SAndroid Build Coastguard Worker }
1220*6236dae4SAndroid Build Coastguard Worker
pkp_pin_peer_pubkey(struct Curl_easy * data,gnutls_x509_crt_t cert,const char * pinnedpubkey)1221*6236dae4SAndroid Build Coastguard Worker static CURLcode pkp_pin_peer_pubkey(struct Curl_easy *data,
1222*6236dae4SAndroid Build Coastguard Worker gnutls_x509_crt_t cert,
1223*6236dae4SAndroid Build Coastguard Worker const char *pinnedpubkey)
1224*6236dae4SAndroid Build Coastguard Worker {
1225*6236dae4SAndroid Build Coastguard Worker /* Scratch */
1226*6236dae4SAndroid Build Coastguard Worker size_t len1 = 0, len2 = 0;
1227*6236dae4SAndroid Build Coastguard Worker unsigned char *buff1 = NULL;
1228*6236dae4SAndroid Build Coastguard Worker
1229*6236dae4SAndroid Build Coastguard Worker gnutls_pubkey_t key = NULL;
1230*6236dae4SAndroid Build Coastguard Worker
1231*6236dae4SAndroid Build Coastguard Worker /* Result is returned to caller */
1232*6236dae4SAndroid Build Coastguard Worker CURLcode result = CURLE_SSL_PINNEDPUBKEYNOTMATCH;
1233*6236dae4SAndroid Build Coastguard Worker
1234*6236dae4SAndroid Build Coastguard Worker /* if a path was not specified, do not pin */
1235*6236dae4SAndroid Build Coastguard Worker if(!pinnedpubkey)
1236*6236dae4SAndroid Build Coastguard Worker return CURLE_OK;
1237*6236dae4SAndroid Build Coastguard Worker
1238*6236dae4SAndroid Build Coastguard Worker if(!cert)
1239*6236dae4SAndroid Build Coastguard Worker return result;
1240*6236dae4SAndroid Build Coastguard Worker
1241*6236dae4SAndroid Build Coastguard Worker do {
1242*6236dae4SAndroid Build Coastguard Worker int ret;
1243*6236dae4SAndroid Build Coastguard Worker
1244*6236dae4SAndroid Build Coastguard Worker /* Begin Gyrations to get the public key */
1245*6236dae4SAndroid Build Coastguard Worker gnutls_pubkey_init(&key);
1246*6236dae4SAndroid Build Coastguard Worker
1247*6236dae4SAndroid Build Coastguard Worker ret = gnutls_pubkey_import_x509(key, cert, 0);
1248*6236dae4SAndroid Build Coastguard Worker if(ret < 0)
1249*6236dae4SAndroid Build Coastguard Worker break; /* failed */
1250*6236dae4SAndroid Build Coastguard Worker
1251*6236dae4SAndroid Build Coastguard Worker ret = gnutls_pubkey_export(key, GNUTLS_X509_FMT_DER, NULL, &len1);
1252*6236dae4SAndroid Build Coastguard Worker if(ret != GNUTLS_E_SHORT_MEMORY_BUFFER || len1 == 0)
1253*6236dae4SAndroid Build Coastguard Worker break; /* failed */
1254*6236dae4SAndroid Build Coastguard Worker
1255*6236dae4SAndroid Build Coastguard Worker buff1 = malloc(len1);
1256*6236dae4SAndroid Build Coastguard Worker if(!buff1)
1257*6236dae4SAndroid Build Coastguard Worker break; /* failed */
1258*6236dae4SAndroid Build Coastguard Worker
1259*6236dae4SAndroid Build Coastguard Worker len2 = len1;
1260*6236dae4SAndroid Build Coastguard Worker
1261*6236dae4SAndroid Build Coastguard Worker ret = gnutls_pubkey_export(key, GNUTLS_X509_FMT_DER, buff1, &len2);
1262*6236dae4SAndroid Build Coastguard Worker if(ret < 0 || len1 != len2)
1263*6236dae4SAndroid Build Coastguard Worker break; /* failed */
1264*6236dae4SAndroid Build Coastguard Worker
1265*6236dae4SAndroid Build Coastguard Worker /* End Gyrations */
1266*6236dae4SAndroid Build Coastguard Worker
1267*6236dae4SAndroid Build Coastguard Worker /* The one good exit point */
1268*6236dae4SAndroid Build Coastguard Worker result = Curl_pin_peer_pubkey(data, pinnedpubkey, buff1, len1);
1269*6236dae4SAndroid Build Coastguard Worker } while(0);
1270*6236dae4SAndroid Build Coastguard Worker
1271*6236dae4SAndroid Build Coastguard Worker if(key)
1272*6236dae4SAndroid Build Coastguard Worker gnutls_pubkey_deinit(key);
1273*6236dae4SAndroid Build Coastguard Worker
1274*6236dae4SAndroid Build Coastguard Worker Curl_safefree(buff1);
1275*6236dae4SAndroid Build Coastguard Worker
1276*6236dae4SAndroid Build Coastguard Worker return result;
1277*6236dae4SAndroid Build Coastguard Worker }
1278*6236dae4SAndroid Build Coastguard Worker
1279*6236dae4SAndroid Build Coastguard Worker CURLcode
Curl_gtls_verifyserver(struct Curl_easy * data,gnutls_session_t session,struct ssl_primary_config * config,struct ssl_config_data * ssl_config,struct ssl_peer * peer,const char * pinned_key)1280*6236dae4SAndroid Build Coastguard Worker Curl_gtls_verifyserver(struct Curl_easy *data,
1281*6236dae4SAndroid Build Coastguard Worker gnutls_session_t session,
1282*6236dae4SAndroid Build Coastguard Worker struct ssl_primary_config *config,
1283*6236dae4SAndroid Build Coastguard Worker struct ssl_config_data *ssl_config,
1284*6236dae4SAndroid Build Coastguard Worker struct ssl_peer *peer,
1285*6236dae4SAndroid Build Coastguard Worker const char *pinned_key)
1286*6236dae4SAndroid Build Coastguard Worker {
1287*6236dae4SAndroid Build Coastguard Worker unsigned int cert_list_size;
1288*6236dae4SAndroid Build Coastguard Worker const gnutls_datum_t *chainp;
1289*6236dae4SAndroid Build Coastguard Worker unsigned int verify_status = 0;
1290*6236dae4SAndroid Build Coastguard Worker gnutls_x509_crt_t x509_cert, x509_issuer;
1291*6236dae4SAndroid Build Coastguard Worker gnutls_datum_t issuerp;
1292*6236dae4SAndroid Build Coastguard Worker gnutls_datum_t certfields;
1293*6236dae4SAndroid Build Coastguard Worker char certname[65] = ""; /* limited to 64 chars by ASN.1 */
1294*6236dae4SAndroid Build Coastguard Worker size_t size;
1295*6236dae4SAndroid Build Coastguard Worker time_t certclock;
1296*6236dae4SAndroid Build Coastguard Worker int rc;
1297*6236dae4SAndroid Build Coastguard Worker CURLcode result = CURLE_OK;
1298*6236dae4SAndroid Build Coastguard Worker #ifndef CURL_DISABLE_VERBOSE_STRINGS
1299*6236dae4SAndroid Build Coastguard Worker const char *ptr;
1300*6236dae4SAndroid Build Coastguard Worker int algo;
1301*6236dae4SAndroid Build Coastguard Worker unsigned int bits;
1302*6236dae4SAndroid Build Coastguard Worker gnutls_protocol_t version = gnutls_protocol_get_version(session);
1303*6236dae4SAndroid Build Coastguard Worker #endif
1304*6236dae4SAndroid Build Coastguard Worker long * const certverifyresult = &ssl_config->certverifyresult;
1305*6236dae4SAndroid Build Coastguard Worker
1306*6236dae4SAndroid Build Coastguard Worker #ifndef CURL_DISABLE_VERBOSE_STRINGS
1307*6236dae4SAndroid Build Coastguard Worker /* the name of the cipher suite used, e.g. ECDHE_RSA_AES_256_GCM_SHA384. */
1308*6236dae4SAndroid Build Coastguard Worker ptr = gnutls_cipher_suite_get_name(gnutls_kx_get(session),
1309*6236dae4SAndroid Build Coastguard Worker gnutls_cipher_get(session),
1310*6236dae4SAndroid Build Coastguard Worker gnutls_mac_get(session));
1311*6236dae4SAndroid Build Coastguard Worker
1312*6236dae4SAndroid Build Coastguard Worker infof(data, "SSL connection using %s / %s",
1313*6236dae4SAndroid Build Coastguard Worker gnutls_protocol_get_name(version), ptr);
1314*6236dae4SAndroid Build Coastguard Worker #endif
1315*6236dae4SAndroid Build Coastguard Worker
1316*6236dae4SAndroid Build Coastguard Worker /* This function will return the peer's raw certificate (chain) as sent by
1317*6236dae4SAndroid Build Coastguard Worker the peer. These certificates are in raw format (DER encoded for
1318*6236dae4SAndroid Build Coastguard Worker X.509). In case of a X.509 then a certificate list may be present. The
1319*6236dae4SAndroid Build Coastguard Worker first certificate in the list is the peer's certificate, following the
1320*6236dae4SAndroid Build Coastguard Worker issuer's certificate, then the issuer's issuer etc. */
1321*6236dae4SAndroid Build Coastguard Worker
1322*6236dae4SAndroid Build Coastguard Worker chainp = gnutls_certificate_get_peers(session, &cert_list_size);
1323*6236dae4SAndroid Build Coastguard Worker if(!chainp) {
1324*6236dae4SAndroid Build Coastguard Worker if(config->verifypeer ||
1325*6236dae4SAndroid Build Coastguard Worker config->verifyhost ||
1326*6236dae4SAndroid Build Coastguard Worker config->issuercert) {
1327*6236dae4SAndroid Build Coastguard Worker #ifdef USE_GNUTLS_SRP
1328*6236dae4SAndroid Build Coastguard Worker if(ssl_config->primary.username && !config->verifypeer &&
1329*6236dae4SAndroid Build Coastguard Worker gnutls_cipher_get(session)) {
1330*6236dae4SAndroid Build Coastguard Worker /* no peer cert, but auth is ok if we have SRP user and cipher and no
1331*6236dae4SAndroid Build Coastguard Worker peer verify */
1332*6236dae4SAndroid Build Coastguard Worker }
1333*6236dae4SAndroid Build Coastguard Worker else {
1334*6236dae4SAndroid Build Coastguard Worker #endif
1335*6236dae4SAndroid Build Coastguard Worker failf(data, "failed to get server cert");
1336*6236dae4SAndroid Build Coastguard Worker *certverifyresult = GNUTLS_E_NO_CERTIFICATE_FOUND;
1337*6236dae4SAndroid Build Coastguard Worker return CURLE_PEER_FAILED_VERIFICATION;
1338*6236dae4SAndroid Build Coastguard Worker #ifdef USE_GNUTLS_SRP
1339*6236dae4SAndroid Build Coastguard Worker }
1340*6236dae4SAndroid Build Coastguard Worker #endif
1341*6236dae4SAndroid Build Coastguard Worker }
1342*6236dae4SAndroid Build Coastguard Worker infof(data, " common name: WARNING could not obtain");
1343*6236dae4SAndroid Build Coastguard Worker }
1344*6236dae4SAndroid Build Coastguard Worker
1345*6236dae4SAndroid Build Coastguard Worker if(data->set.ssl.certinfo && chainp) {
1346*6236dae4SAndroid Build Coastguard Worker unsigned int i;
1347*6236dae4SAndroid Build Coastguard Worker
1348*6236dae4SAndroid Build Coastguard Worker result = Curl_ssl_init_certinfo(data, (int)cert_list_size);
1349*6236dae4SAndroid Build Coastguard Worker if(result)
1350*6236dae4SAndroid Build Coastguard Worker return result;
1351*6236dae4SAndroid Build Coastguard Worker
1352*6236dae4SAndroid Build Coastguard Worker for(i = 0; i < cert_list_size; i++) {
1353*6236dae4SAndroid Build Coastguard Worker const char *beg = (const char *) chainp[i].data;
1354*6236dae4SAndroid Build Coastguard Worker const char *end = beg + chainp[i].size;
1355*6236dae4SAndroid Build Coastguard Worker
1356*6236dae4SAndroid Build Coastguard Worker result = Curl_extract_certinfo(data, (int)i, beg, end);
1357*6236dae4SAndroid Build Coastguard Worker if(result)
1358*6236dae4SAndroid Build Coastguard Worker return result;
1359*6236dae4SAndroid Build Coastguard Worker }
1360*6236dae4SAndroid Build Coastguard Worker }
1361*6236dae4SAndroid Build Coastguard Worker
1362*6236dae4SAndroid Build Coastguard Worker if(config->verifypeer) {
1363*6236dae4SAndroid Build Coastguard Worker /* This function will try to verify the peer's certificate and return its
1364*6236dae4SAndroid Build Coastguard Worker status (trusted, invalid etc.). The value of status should be one or
1365*6236dae4SAndroid Build Coastguard Worker more of the gnutls_certificate_status_t enumerated elements bitwise
1366*6236dae4SAndroid Build Coastguard Worker or'd. To avoid denial of service attacks some default upper limits
1367*6236dae4SAndroid Build Coastguard Worker regarding the certificate key size and chain size are set. To override
1368*6236dae4SAndroid Build Coastguard Worker them use gnutls_certificate_set_verify_limits(). */
1369*6236dae4SAndroid Build Coastguard Worker
1370*6236dae4SAndroid Build Coastguard Worker rc = gnutls_certificate_verify_peers2(session, &verify_status);
1371*6236dae4SAndroid Build Coastguard Worker if(rc < 0) {
1372*6236dae4SAndroid Build Coastguard Worker failf(data, "server cert verify failed: %d", rc);
1373*6236dae4SAndroid Build Coastguard Worker *certverifyresult = rc;
1374*6236dae4SAndroid Build Coastguard Worker return CURLE_SSL_CONNECT_ERROR;
1375*6236dae4SAndroid Build Coastguard Worker }
1376*6236dae4SAndroid Build Coastguard Worker
1377*6236dae4SAndroid Build Coastguard Worker *certverifyresult = verify_status;
1378*6236dae4SAndroid Build Coastguard Worker
1379*6236dae4SAndroid Build Coastguard Worker /* verify_status is a bitmask of gnutls_certificate_status bits */
1380*6236dae4SAndroid Build Coastguard Worker if(verify_status & GNUTLS_CERT_INVALID) {
1381*6236dae4SAndroid Build Coastguard Worker if(config->verifypeer) {
1382*6236dae4SAndroid Build Coastguard Worker const char *cause = "certificate error, no details available";
1383*6236dae4SAndroid Build Coastguard Worker if(verify_status & GNUTLS_CERT_EXPIRED)
1384*6236dae4SAndroid Build Coastguard Worker cause = "certificate has expired";
1385*6236dae4SAndroid Build Coastguard Worker else if(verify_status & GNUTLS_CERT_SIGNER_NOT_FOUND)
1386*6236dae4SAndroid Build Coastguard Worker cause = "certificate signer not trusted";
1387*6236dae4SAndroid Build Coastguard Worker else if(verify_status & GNUTLS_CERT_INSECURE_ALGORITHM)
1388*6236dae4SAndroid Build Coastguard Worker cause = "certificate uses insecure algorithm";
1389*6236dae4SAndroid Build Coastguard Worker else if(verify_status & GNUTLS_CERT_INVALID_OCSP_STATUS)
1390*6236dae4SAndroid Build Coastguard Worker cause = "attached OCSP status response is invalid";
1391*6236dae4SAndroid Build Coastguard Worker failf(data, "server verification failed: %s. (CAfile: %s "
1392*6236dae4SAndroid Build Coastguard Worker "CRLfile: %s)", cause,
1393*6236dae4SAndroid Build Coastguard Worker config->CAfile ? config->CAfile : "none",
1394*6236dae4SAndroid Build Coastguard Worker ssl_config->primary.CRLfile ?
1395*6236dae4SAndroid Build Coastguard Worker ssl_config->primary.CRLfile : "none");
1396*6236dae4SAndroid Build Coastguard Worker return CURLE_PEER_FAILED_VERIFICATION;
1397*6236dae4SAndroid Build Coastguard Worker }
1398*6236dae4SAndroid Build Coastguard Worker else
1399*6236dae4SAndroid Build Coastguard Worker infof(data, " server certificate verification FAILED");
1400*6236dae4SAndroid Build Coastguard Worker }
1401*6236dae4SAndroid Build Coastguard Worker else
1402*6236dae4SAndroid Build Coastguard Worker infof(data, " server certificate verification OK");
1403*6236dae4SAndroid Build Coastguard Worker }
1404*6236dae4SAndroid Build Coastguard Worker else
1405*6236dae4SAndroid Build Coastguard Worker infof(data, " server certificate verification SKIPPED");
1406*6236dae4SAndroid Build Coastguard Worker
1407*6236dae4SAndroid Build Coastguard Worker if(config->verifystatus) {
1408*6236dae4SAndroid Build Coastguard Worker gnutls_datum_t status_request;
1409*6236dae4SAndroid Build Coastguard Worker gnutls_ocsp_resp_t ocsp_resp;
1410*6236dae4SAndroid Build Coastguard Worker gnutls_ocsp_cert_status_t status;
1411*6236dae4SAndroid Build Coastguard Worker gnutls_x509_crl_reason_t reason;
1412*6236dae4SAndroid Build Coastguard Worker
1413*6236dae4SAndroid Build Coastguard Worker rc = gnutls_ocsp_status_request_get(session, &status_request);
1414*6236dae4SAndroid Build Coastguard Worker
1415*6236dae4SAndroid Build Coastguard Worker if(rc == GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE) {
1416*6236dae4SAndroid Build Coastguard Worker failf(data, "No OCSP response received");
1417*6236dae4SAndroid Build Coastguard Worker return CURLE_SSL_INVALIDCERTSTATUS;
1418*6236dae4SAndroid Build Coastguard Worker }
1419*6236dae4SAndroid Build Coastguard Worker
1420*6236dae4SAndroid Build Coastguard Worker if(rc < 0) {
1421*6236dae4SAndroid Build Coastguard Worker failf(data, "Invalid OCSP response received");
1422*6236dae4SAndroid Build Coastguard Worker return CURLE_SSL_INVALIDCERTSTATUS;
1423*6236dae4SAndroid Build Coastguard Worker }
1424*6236dae4SAndroid Build Coastguard Worker
1425*6236dae4SAndroid Build Coastguard Worker gnutls_ocsp_resp_init(&ocsp_resp);
1426*6236dae4SAndroid Build Coastguard Worker
1427*6236dae4SAndroid Build Coastguard Worker rc = gnutls_ocsp_resp_import(ocsp_resp, &status_request);
1428*6236dae4SAndroid Build Coastguard Worker if(rc < 0) {
1429*6236dae4SAndroid Build Coastguard Worker failf(data, "Invalid OCSP response received");
1430*6236dae4SAndroid Build Coastguard Worker return CURLE_SSL_INVALIDCERTSTATUS;
1431*6236dae4SAndroid Build Coastguard Worker }
1432*6236dae4SAndroid Build Coastguard Worker
1433*6236dae4SAndroid Build Coastguard Worker (void)gnutls_ocsp_resp_get_single(ocsp_resp, 0, NULL, NULL, NULL, NULL,
1434*6236dae4SAndroid Build Coastguard Worker &status, NULL, NULL, NULL, &reason);
1435*6236dae4SAndroid Build Coastguard Worker
1436*6236dae4SAndroid Build Coastguard Worker switch(status) {
1437*6236dae4SAndroid Build Coastguard Worker case GNUTLS_OCSP_CERT_GOOD:
1438*6236dae4SAndroid Build Coastguard Worker break;
1439*6236dae4SAndroid Build Coastguard Worker
1440*6236dae4SAndroid Build Coastguard Worker case GNUTLS_OCSP_CERT_REVOKED: {
1441*6236dae4SAndroid Build Coastguard Worker const char *crl_reason;
1442*6236dae4SAndroid Build Coastguard Worker
1443*6236dae4SAndroid Build Coastguard Worker switch(reason) {
1444*6236dae4SAndroid Build Coastguard Worker default:
1445*6236dae4SAndroid Build Coastguard Worker case GNUTLS_X509_CRLREASON_UNSPECIFIED:
1446*6236dae4SAndroid Build Coastguard Worker crl_reason = "unspecified reason";
1447*6236dae4SAndroid Build Coastguard Worker break;
1448*6236dae4SAndroid Build Coastguard Worker
1449*6236dae4SAndroid Build Coastguard Worker case GNUTLS_X509_CRLREASON_KEYCOMPROMISE:
1450*6236dae4SAndroid Build Coastguard Worker crl_reason = "private key compromised";
1451*6236dae4SAndroid Build Coastguard Worker break;
1452*6236dae4SAndroid Build Coastguard Worker
1453*6236dae4SAndroid Build Coastguard Worker case GNUTLS_X509_CRLREASON_CACOMPROMISE:
1454*6236dae4SAndroid Build Coastguard Worker crl_reason = "CA compromised";
1455*6236dae4SAndroid Build Coastguard Worker break;
1456*6236dae4SAndroid Build Coastguard Worker
1457*6236dae4SAndroid Build Coastguard Worker case GNUTLS_X509_CRLREASON_AFFILIATIONCHANGED:
1458*6236dae4SAndroid Build Coastguard Worker crl_reason = "affiliation has changed";
1459*6236dae4SAndroid Build Coastguard Worker break;
1460*6236dae4SAndroid Build Coastguard Worker
1461*6236dae4SAndroid Build Coastguard Worker case GNUTLS_X509_CRLREASON_SUPERSEDED:
1462*6236dae4SAndroid Build Coastguard Worker crl_reason = "certificate superseded";
1463*6236dae4SAndroid Build Coastguard Worker break;
1464*6236dae4SAndroid Build Coastguard Worker
1465*6236dae4SAndroid Build Coastguard Worker case GNUTLS_X509_CRLREASON_CESSATIONOFOPERATION:
1466*6236dae4SAndroid Build Coastguard Worker crl_reason = "operation has ceased";
1467*6236dae4SAndroid Build Coastguard Worker break;
1468*6236dae4SAndroid Build Coastguard Worker
1469*6236dae4SAndroid Build Coastguard Worker case GNUTLS_X509_CRLREASON_CERTIFICATEHOLD:
1470*6236dae4SAndroid Build Coastguard Worker crl_reason = "certificate is on hold";
1471*6236dae4SAndroid Build Coastguard Worker break;
1472*6236dae4SAndroid Build Coastguard Worker
1473*6236dae4SAndroid Build Coastguard Worker case GNUTLS_X509_CRLREASON_REMOVEFROMCRL:
1474*6236dae4SAndroid Build Coastguard Worker crl_reason = "will be removed from delta CRL";
1475*6236dae4SAndroid Build Coastguard Worker break;
1476*6236dae4SAndroid Build Coastguard Worker
1477*6236dae4SAndroid Build Coastguard Worker case GNUTLS_X509_CRLREASON_PRIVILEGEWITHDRAWN:
1478*6236dae4SAndroid Build Coastguard Worker crl_reason = "privilege withdrawn";
1479*6236dae4SAndroid Build Coastguard Worker break;
1480*6236dae4SAndroid Build Coastguard Worker
1481*6236dae4SAndroid Build Coastguard Worker case GNUTLS_X509_CRLREASON_AACOMPROMISE:
1482*6236dae4SAndroid Build Coastguard Worker crl_reason = "AA compromised";
1483*6236dae4SAndroid Build Coastguard Worker break;
1484*6236dae4SAndroid Build Coastguard Worker }
1485*6236dae4SAndroid Build Coastguard Worker
1486*6236dae4SAndroid Build Coastguard Worker failf(data, "Server certificate was revoked: %s", crl_reason);
1487*6236dae4SAndroid Build Coastguard Worker break;
1488*6236dae4SAndroid Build Coastguard Worker }
1489*6236dae4SAndroid Build Coastguard Worker
1490*6236dae4SAndroid Build Coastguard Worker default:
1491*6236dae4SAndroid Build Coastguard Worker case GNUTLS_OCSP_CERT_UNKNOWN:
1492*6236dae4SAndroid Build Coastguard Worker failf(data, "Server certificate status is unknown");
1493*6236dae4SAndroid Build Coastguard Worker break;
1494*6236dae4SAndroid Build Coastguard Worker }
1495*6236dae4SAndroid Build Coastguard Worker
1496*6236dae4SAndroid Build Coastguard Worker gnutls_ocsp_resp_deinit(ocsp_resp);
1497*6236dae4SAndroid Build Coastguard Worker if(status != GNUTLS_OCSP_CERT_GOOD)
1498*6236dae4SAndroid Build Coastguard Worker return CURLE_SSL_INVALIDCERTSTATUS;
1499*6236dae4SAndroid Build Coastguard Worker }
1500*6236dae4SAndroid Build Coastguard Worker else
1501*6236dae4SAndroid Build Coastguard Worker infof(data, " server certificate status verification SKIPPED");
1502*6236dae4SAndroid Build Coastguard Worker
1503*6236dae4SAndroid Build Coastguard Worker /* initialize an X.509 certificate structure. */
1504*6236dae4SAndroid Build Coastguard Worker gnutls_x509_crt_init(&x509_cert);
1505*6236dae4SAndroid Build Coastguard Worker
1506*6236dae4SAndroid Build Coastguard Worker if(chainp)
1507*6236dae4SAndroid Build Coastguard Worker /* convert the given DER or PEM encoded Certificate to the native
1508*6236dae4SAndroid Build Coastguard Worker gnutls_x509_crt_t format */
1509*6236dae4SAndroid Build Coastguard Worker gnutls_x509_crt_import(x509_cert, chainp, GNUTLS_X509_FMT_DER);
1510*6236dae4SAndroid Build Coastguard Worker
1511*6236dae4SAndroid Build Coastguard Worker if(config->issuercert) {
1512*6236dae4SAndroid Build Coastguard Worker gnutls_x509_crt_init(&x509_issuer);
1513*6236dae4SAndroid Build Coastguard Worker issuerp = load_file(config->issuercert);
1514*6236dae4SAndroid Build Coastguard Worker gnutls_x509_crt_import(x509_issuer, &issuerp, GNUTLS_X509_FMT_PEM);
1515*6236dae4SAndroid Build Coastguard Worker rc = (int)gnutls_x509_crt_check_issuer(x509_cert, x509_issuer);
1516*6236dae4SAndroid Build Coastguard Worker gnutls_x509_crt_deinit(x509_issuer);
1517*6236dae4SAndroid Build Coastguard Worker unload_file(issuerp);
1518*6236dae4SAndroid Build Coastguard Worker if(rc <= 0) {
1519*6236dae4SAndroid Build Coastguard Worker failf(data, "server certificate issuer check failed (IssuerCert: %s)",
1520*6236dae4SAndroid Build Coastguard Worker config->issuercert ? config->issuercert : "none");
1521*6236dae4SAndroid Build Coastguard Worker gnutls_x509_crt_deinit(x509_cert);
1522*6236dae4SAndroid Build Coastguard Worker return CURLE_SSL_ISSUER_ERROR;
1523*6236dae4SAndroid Build Coastguard Worker }
1524*6236dae4SAndroid Build Coastguard Worker infof(data, " server certificate issuer check OK (Issuer Cert: %s)",
1525*6236dae4SAndroid Build Coastguard Worker config->issuercert ? config->issuercert : "none");
1526*6236dae4SAndroid Build Coastguard Worker }
1527*6236dae4SAndroid Build Coastguard Worker
1528*6236dae4SAndroid Build Coastguard Worker size = sizeof(certname);
1529*6236dae4SAndroid Build Coastguard Worker rc = gnutls_x509_crt_get_dn_by_oid(x509_cert, GNUTLS_OID_X520_COMMON_NAME,
1530*6236dae4SAndroid Build Coastguard Worker 0, /* the first and only one */
1531*6236dae4SAndroid Build Coastguard Worker FALSE,
1532*6236dae4SAndroid Build Coastguard Worker certname,
1533*6236dae4SAndroid Build Coastguard Worker &size);
1534*6236dae4SAndroid Build Coastguard Worker if(rc) {
1535*6236dae4SAndroid Build Coastguard Worker infof(data, "error fetching CN from cert:%s",
1536*6236dae4SAndroid Build Coastguard Worker gnutls_strerror(rc));
1537*6236dae4SAndroid Build Coastguard Worker }
1538*6236dae4SAndroid Build Coastguard Worker
1539*6236dae4SAndroid Build Coastguard Worker /* This function will check if the given certificate's subject matches the
1540*6236dae4SAndroid Build Coastguard Worker given hostname. This is a basic implementation of the matching described
1541*6236dae4SAndroid Build Coastguard Worker in RFC2818 (HTTPS), which takes into account wildcards, and the subject
1542*6236dae4SAndroid Build Coastguard Worker alternative name PKIX extension. Returns non zero on success, and zero on
1543*6236dae4SAndroid Build Coastguard Worker failure. */
1544*6236dae4SAndroid Build Coastguard Worker
1545*6236dae4SAndroid Build Coastguard Worker /* This function does not handle trailing dots, so if we have an SNI name
1546*6236dae4SAndroid Build Coastguard Worker use that and fallback to the hostname only if there is no SNI (like for
1547*6236dae4SAndroid Build Coastguard Worker IP addresses) */
1548*6236dae4SAndroid Build Coastguard Worker rc = (int)gnutls_x509_crt_check_hostname(x509_cert,
1549*6236dae4SAndroid Build Coastguard Worker peer->sni ? peer->sni :
1550*6236dae4SAndroid Build Coastguard Worker peer->hostname);
1551*6236dae4SAndroid Build Coastguard Worker #if GNUTLS_VERSION_NUMBER < 0x030306
1552*6236dae4SAndroid Build Coastguard Worker /* Before 3.3.6, gnutls_x509_crt_check_hostname() did not check IP
1553*6236dae4SAndroid Build Coastguard Worker addresses. */
1554*6236dae4SAndroid Build Coastguard Worker if(!rc) {
1555*6236dae4SAndroid Build Coastguard Worker #ifdef USE_IPV6
1556*6236dae4SAndroid Build Coastguard Worker #define use_addr in6_addr
1557*6236dae4SAndroid Build Coastguard Worker #else
1558*6236dae4SAndroid Build Coastguard Worker #define use_addr in_addr
1559*6236dae4SAndroid Build Coastguard Worker #endif
1560*6236dae4SAndroid Build Coastguard Worker unsigned char addrbuf[sizeof(struct use_addr)];
1561*6236dae4SAndroid Build Coastguard Worker size_t addrlen = 0;
1562*6236dae4SAndroid Build Coastguard Worker
1563*6236dae4SAndroid Build Coastguard Worker if(Curl_inet_pton(AF_INET, peer->hostname, addrbuf) > 0)
1564*6236dae4SAndroid Build Coastguard Worker addrlen = 4;
1565*6236dae4SAndroid Build Coastguard Worker #ifdef USE_IPV6
1566*6236dae4SAndroid Build Coastguard Worker else if(Curl_inet_pton(AF_INET6, peer->hostname, addrbuf) > 0)
1567*6236dae4SAndroid Build Coastguard Worker addrlen = 16;
1568*6236dae4SAndroid Build Coastguard Worker #endif
1569*6236dae4SAndroid Build Coastguard Worker
1570*6236dae4SAndroid Build Coastguard Worker if(addrlen) {
1571*6236dae4SAndroid Build Coastguard Worker unsigned char certaddr[sizeof(struct use_addr)];
1572*6236dae4SAndroid Build Coastguard Worker int i;
1573*6236dae4SAndroid Build Coastguard Worker
1574*6236dae4SAndroid Build Coastguard Worker for(i = 0; ; i++) {
1575*6236dae4SAndroid Build Coastguard Worker size_t certaddrlen = sizeof(certaddr);
1576*6236dae4SAndroid Build Coastguard Worker int ret = gnutls_x509_crt_get_subject_alt_name(x509_cert, i, certaddr,
1577*6236dae4SAndroid Build Coastguard Worker &certaddrlen, NULL);
1578*6236dae4SAndroid Build Coastguard Worker /* If this happens, it was not an IP address. */
1579*6236dae4SAndroid Build Coastguard Worker if(ret == GNUTLS_E_SHORT_MEMORY_BUFFER)
1580*6236dae4SAndroid Build Coastguard Worker continue;
1581*6236dae4SAndroid Build Coastguard Worker if(ret < 0)
1582*6236dae4SAndroid Build Coastguard Worker break;
1583*6236dae4SAndroid Build Coastguard Worker if(ret != GNUTLS_SAN_IPADDRESS)
1584*6236dae4SAndroid Build Coastguard Worker continue;
1585*6236dae4SAndroid Build Coastguard Worker if(certaddrlen == addrlen && !memcmp(addrbuf, certaddr, addrlen)) {
1586*6236dae4SAndroid Build Coastguard Worker rc = 1;
1587*6236dae4SAndroid Build Coastguard Worker break;
1588*6236dae4SAndroid Build Coastguard Worker }
1589*6236dae4SAndroid Build Coastguard Worker }
1590*6236dae4SAndroid Build Coastguard Worker }
1591*6236dae4SAndroid Build Coastguard Worker }
1592*6236dae4SAndroid Build Coastguard Worker #endif
1593*6236dae4SAndroid Build Coastguard Worker if(!rc) {
1594*6236dae4SAndroid Build Coastguard Worker if(config->verifyhost) {
1595*6236dae4SAndroid Build Coastguard Worker failf(data, "SSL: certificate subject name (%s) does not match "
1596*6236dae4SAndroid Build Coastguard Worker "target hostname '%s'", certname, peer->dispname);
1597*6236dae4SAndroid Build Coastguard Worker gnutls_x509_crt_deinit(x509_cert);
1598*6236dae4SAndroid Build Coastguard Worker return CURLE_PEER_FAILED_VERIFICATION;
1599*6236dae4SAndroid Build Coastguard Worker }
1600*6236dae4SAndroid Build Coastguard Worker else
1601*6236dae4SAndroid Build Coastguard Worker infof(data, " common name: %s (does not match '%s')",
1602*6236dae4SAndroid Build Coastguard Worker certname, peer->dispname);
1603*6236dae4SAndroid Build Coastguard Worker }
1604*6236dae4SAndroid Build Coastguard Worker else
1605*6236dae4SAndroid Build Coastguard Worker infof(data, " common name: %s (matched)", certname);
1606*6236dae4SAndroid Build Coastguard Worker
1607*6236dae4SAndroid Build Coastguard Worker /* Check for time-based validity */
1608*6236dae4SAndroid Build Coastguard Worker certclock = gnutls_x509_crt_get_expiration_time(x509_cert);
1609*6236dae4SAndroid Build Coastguard Worker
1610*6236dae4SAndroid Build Coastguard Worker if(certclock == (time_t)-1) {
1611*6236dae4SAndroid Build Coastguard Worker if(config->verifypeer) {
1612*6236dae4SAndroid Build Coastguard Worker failf(data, "server cert expiration date verify failed");
1613*6236dae4SAndroid Build Coastguard Worker *certverifyresult = GNUTLS_CERT_EXPIRED;
1614*6236dae4SAndroid Build Coastguard Worker gnutls_x509_crt_deinit(x509_cert);
1615*6236dae4SAndroid Build Coastguard Worker return CURLE_SSL_CONNECT_ERROR;
1616*6236dae4SAndroid Build Coastguard Worker }
1617*6236dae4SAndroid Build Coastguard Worker else
1618*6236dae4SAndroid Build Coastguard Worker infof(data, " server certificate expiration date verify FAILED");
1619*6236dae4SAndroid Build Coastguard Worker }
1620*6236dae4SAndroid Build Coastguard Worker else {
1621*6236dae4SAndroid Build Coastguard Worker if(certclock < time(NULL)) {
1622*6236dae4SAndroid Build Coastguard Worker if(config->verifypeer) {
1623*6236dae4SAndroid Build Coastguard Worker failf(data, "server certificate expiration date has passed.");
1624*6236dae4SAndroid Build Coastguard Worker *certverifyresult = GNUTLS_CERT_EXPIRED;
1625*6236dae4SAndroid Build Coastguard Worker gnutls_x509_crt_deinit(x509_cert);
1626*6236dae4SAndroid Build Coastguard Worker return CURLE_PEER_FAILED_VERIFICATION;
1627*6236dae4SAndroid Build Coastguard Worker }
1628*6236dae4SAndroid Build Coastguard Worker else
1629*6236dae4SAndroid Build Coastguard Worker infof(data, " server certificate expiration date FAILED");
1630*6236dae4SAndroid Build Coastguard Worker }
1631*6236dae4SAndroid Build Coastguard Worker else
1632*6236dae4SAndroid Build Coastguard Worker infof(data, " server certificate expiration date OK");
1633*6236dae4SAndroid Build Coastguard Worker }
1634*6236dae4SAndroid Build Coastguard Worker
1635*6236dae4SAndroid Build Coastguard Worker certclock = gnutls_x509_crt_get_activation_time(x509_cert);
1636*6236dae4SAndroid Build Coastguard Worker
1637*6236dae4SAndroid Build Coastguard Worker if(certclock == (time_t)-1) {
1638*6236dae4SAndroid Build Coastguard Worker if(config->verifypeer) {
1639*6236dae4SAndroid Build Coastguard Worker failf(data, "server cert activation date verify failed");
1640*6236dae4SAndroid Build Coastguard Worker *certverifyresult = GNUTLS_CERT_NOT_ACTIVATED;
1641*6236dae4SAndroid Build Coastguard Worker gnutls_x509_crt_deinit(x509_cert);
1642*6236dae4SAndroid Build Coastguard Worker return CURLE_SSL_CONNECT_ERROR;
1643*6236dae4SAndroid Build Coastguard Worker }
1644*6236dae4SAndroid Build Coastguard Worker else
1645*6236dae4SAndroid Build Coastguard Worker infof(data, " server certificate activation date verify FAILED");
1646*6236dae4SAndroid Build Coastguard Worker }
1647*6236dae4SAndroid Build Coastguard Worker else {
1648*6236dae4SAndroid Build Coastguard Worker if(certclock > time(NULL)) {
1649*6236dae4SAndroid Build Coastguard Worker if(config->verifypeer) {
1650*6236dae4SAndroid Build Coastguard Worker failf(data, "server certificate not activated yet.");
1651*6236dae4SAndroid Build Coastguard Worker *certverifyresult = GNUTLS_CERT_NOT_ACTIVATED;
1652*6236dae4SAndroid Build Coastguard Worker gnutls_x509_crt_deinit(x509_cert);
1653*6236dae4SAndroid Build Coastguard Worker return CURLE_PEER_FAILED_VERIFICATION;
1654*6236dae4SAndroid Build Coastguard Worker }
1655*6236dae4SAndroid Build Coastguard Worker else
1656*6236dae4SAndroid Build Coastguard Worker infof(data, " server certificate activation date FAILED");
1657*6236dae4SAndroid Build Coastguard Worker }
1658*6236dae4SAndroid Build Coastguard Worker else
1659*6236dae4SAndroid Build Coastguard Worker infof(data, " server certificate activation date OK");
1660*6236dae4SAndroid Build Coastguard Worker }
1661*6236dae4SAndroid Build Coastguard Worker
1662*6236dae4SAndroid Build Coastguard Worker if(pinned_key) {
1663*6236dae4SAndroid Build Coastguard Worker result = pkp_pin_peer_pubkey(data, x509_cert, pinned_key);
1664*6236dae4SAndroid Build Coastguard Worker if(result != CURLE_OK) {
1665*6236dae4SAndroid Build Coastguard Worker failf(data, "SSL: public key does not match pinned public key");
1666*6236dae4SAndroid Build Coastguard Worker gnutls_x509_crt_deinit(x509_cert);
1667*6236dae4SAndroid Build Coastguard Worker return result;
1668*6236dae4SAndroid Build Coastguard Worker }
1669*6236dae4SAndroid Build Coastguard Worker }
1670*6236dae4SAndroid Build Coastguard Worker
1671*6236dae4SAndroid Build Coastguard Worker /* Show:
1672*6236dae4SAndroid Build Coastguard Worker
1673*6236dae4SAndroid Build Coastguard Worker - subject
1674*6236dae4SAndroid Build Coastguard Worker - start date
1675*6236dae4SAndroid Build Coastguard Worker - expire date
1676*6236dae4SAndroid Build Coastguard Worker - common name
1677*6236dae4SAndroid Build Coastguard Worker - issuer
1678*6236dae4SAndroid Build Coastguard Worker
1679*6236dae4SAndroid Build Coastguard Worker */
1680*6236dae4SAndroid Build Coastguard Worker
1681*6236dae4SAndroid Build Coastguard Worker #ifndef CURL_DISABLE_VERBOSE_STRINGS
1682*6236dae4SAndroid Build Coastguard Worker /* public key algorithm's parameters */
1683*6236dae4SAndroid Build Coastguard Worker algo = gnutls_x509_crt_get_pk_algorithm(x509_cert, &bits);
1684*6236dae4SAndroid Build Coastguard Worker infof(data, " certificate public key: %s",
1685*6236dae4SAndroid Build Coastguard Worker gnutls_pk_algorithm_get_name((gnutls_pk_algorithm_t)algo));
1686*6236dae4SAndroid Build Coastguard Worker
1687*6236dae4SAndroid Build Coastguard Worker /* version of the X.509 certificate. */
1688*6236dae4SAndroid Build Coastguard Worker infof(data, " certificate version: #%d",
1689*6236dae4SAndroid Build Coastguard Worker gnutls_x509_crt_get_version(x509_cert));
1690*6236dae4SAndroid Build Coastguard Worker
1691*6236dae4SAndroid Build Coastguard Worker
1692*6236dae4SAndroid Build Coastguard Worker rc = gnutls_x509_crt_get_dn2(x509_cert, &certfields);
1693*6236dae4SAndroid Build Coastguard Worker if(rc)
1694*6236dae4SAndroid Build Coastguard Worker infof(data, "Failed to get certificate name");
1695*6236dae4SAndroid Build Coastguard Worker else {
1696*6236dae4SAndroid Build Coastguard Worker infof(data, " subject: %s", certfields.data);
1697*6236dae4SAndroid Build Coastguard Worker
1698*6236dae4SAndroid Build Coastguard Worker certclock = gnutls_x509_crt_get_activation_time(x509_cert);
1699*6236dae4SAndroid Build Coastguard Worker showtime(data, "start date", certclock);
1700*6236dae4SAndroid Build Coastguard Worker
1701*6236dae4SAndroid Build Coastguard Worker certclock = gnutls_x509_crt_get_expiration_time(x509_cert);
1702*6236dae4SAndroid Build Coastguard Worker showtime(data, "expire date", certclock);
1703*6236dae4SAndroid Build Coastguard Worker
1704*6236dae4SAndroid Build Coastguard Worker gnutls_free(certfields.data);
1705*6236dae4SAndroid Build Coastguard Worker }
1706*6236dae4SAndroid Build Coastguard Worker
1707*6236dae4SAndroid Build Coastguard Worker rc = gnutls_x509_crt_get_issuer_dn2(x509_cert, &certfields);
1708*6236dae4SAndroid Build Coastguard Worker if(rc)
1709*6236dae4SAndroid Build Coastguard Worker infof(data, "Failed to get certificate issuer");
1710*6236dae4SAndroid Build Coastguard Worker else {
1711*6236dae4SAndroid Build Coastguard Worker infof(data, " issuer: %s", certfields.data);
1712*6236dae4SAndroid Build Coastguard Worker
1713*6236dae4SAndroid Build Coastguard Worker gnutls_free(certfields.data);
1714*6236dae4SAndroid Build Coastguard Worker }
1715*6236dae4SAndroid Build Coastguard Worker #endif
1716*6236dae4SAndroid Build Coastguard Worker
1717*6236dae4SAndroid Build Coastguard Worker gnutls_x509_crt_deinit(x509_cert);
1718*6236dae4SAndroid Build Coastguard Worker
1719*6236dae4SAndroid Build Coastguard Worker return result;
1720*6236dae4SAndroid Build Coastguard Worker }
1721*6236dae4SAndroid Build Coastguard Worker
gtls_verifyserver(struct Curl_cfilter * cf,struct Curl_easy * data,gnutls_session_t session)1722*6236dae4SAndroid Build Coastguard Worker static CURLcode gtls_verifyserver(struct Curl_cfilter *cf,
1723*6236dae4SAndroid Build Coastguard Worker struct Curl_easy *data,
1724*6236dae4SAndroid Build Coastguard Worker gnutls_session_t session)
1725*6236dae4SAndroid Build Coastguard Worker {
1726*6236dae4SAndroid Build Coastguard Worker struct ssl_connect_data *connssl = cf->ctx;
1727*6236dae4SAndroid Build Coastguard Worker struct ssl_primary_config *conn_config = Curl_ssl_cf_get_primary_config(cf);
1728*6236dae4SAndroid Build Coastguard Worker struct ssl_config_data *ssl_config = Curl_ssl_cf_get_config(cf, data);
1729*6236dae4SAndroid Build Coastguard Worker #ifndef CURL_DISABLE_PROXY
1730*6236dae4SAndroid Build Coastguard Worker const char *pinned_key = Curl_ssl_cf_is_proxy(cf) ?
1731*6236dae4SAndroid Build Coastguard Worker data->set.str[STRING_SSL_PINNEDPUBLICKEY_PROXY] :
1732*6236dae4SAndroid Build Coastguard Worker data->set.str[STRING_SSL_PINNEDPUBLICKEY];
1733*6236dae4SAndroid Build Coastguard Worker #else
1734*6236dae4SAndroid Build Coastguard Worker const char *pinned_key = data->set.str[STRING_SSL_PINNEDPUBLICKEY];
1735*6236dae4SAndroid Build Coastguard Worker #endif
1736*6236dae4SAndroid Build Coastguard Worker CURLcode result;
1737*6236dae4SAndroid Build Coastguard Worker
1738*6236dae4SAndroid Build Coastguard Worker result = Curl_gtls_verifyserver(data, session, conn_config, ssl_config,
1739*6236dae4SAndroid Build Coastguard Worker &connssl->peer, pinned_key);
1740*6236dae4SAndroid Build Coastguard Worker if(result)
1741*6236dae4SAndroid Build Coastguard Worker goto out;
1742*6236dae4SAndroid Build Coastguard Worker
1743*6236dae4SAndroid Build Coastguard Worker /* Only on TLSv1.2 or lower do we have the session id now. For
1744*6236dae4SAndroid Build Coastguard Worker * TLSv1.3 we get it via a SESSION_TICKET message that arrives later. */
1745*6236dae4SAndroid Build Coastguard Worker if(gnutls_protocol_get_version(session) < GNUTLS_TLS1_3)
1746*6236dae4SAndroid Build Coastguard Worker result = cf_gtls_update_session_id(cf, data, session);
1747*6236dae4SAndroid Build Coastguard Worker
1748*6236dae4SAndroid Build Coastguard Worker out:
1749*6236dae4SAndroid Build Coastguard Worker return result;
1750*6236dae4SAndroid Build Coastguard Worker }
1751*6236dae4SAndroid Build Coastguard Worker
gtls_set_earlydata(struct Curl_cfilter * cf,struct Curl_easy * data,const void * buf,size_t blen)1752*6236dae4SAndroid Build Coastguard Worker static CURLcode gtls_set_earlydata(struct Curl_cfilter *cf,
1753*6236dae4SAndroid Build Coastguard Worker struct Curl_easy *data,
1754*6236dae4SAndroid Build Coastguard Worker const void *buf, size_t blen)
1755*6236dae4SAndroid Build Coastguard Worker {
1756*6236dae4SAndroid Build Coastguard Worker struct ssl_connect_data *connssl = cf->ctx;
1757*6236dae4SAndroid Build Coastguard Worker ssize_t nwritten = 0;
1758*6236dae4SAndroid Build Coastguard Worker CURLcode result = CURLE_OK;
1759*6236dae4SAndroid Build Coastguard Worker
1760*6236dae4SAndroid Build Coastguard Worker DEBUGASSERT(connssl->earlydata_state == ssl_earlydata_use);
1761*6236dae4SAndroid Build Coastguard Worker DEBUGASSERT(Curl_bufq_is_empty(&connssl->earlydata));
1762*6236dae4SAndroid Build Coastguard Worker if(blen) {
1763*6236dae4SAndroid Build Coastguard Worker if(blen > connssl->earlydata_max)
1764*6236dae4SAndroid Build Coastguard Worker blen = connssl->earlydata_max;
1765*6236dae4SAndroid Build Coastguard Worker nwritten = Curl_bufq_write(&connssl->earlydata, buf, blen, &result);
1766*6236dae4SAndroid Build Coastguard Worker CURL_TRC_CF(data, cf, "gtls_set_earlydata(len=%zu) -> %zd",
1767*6236dae4SAndroid Build Coastguard Worker blen, nwritten);
1768*6236dae4SAndroid Build Coastguard Worker if(nwritten < 0)
1769*6236dae4SAndroid Build Coastguard Worker return result;
1770*6236dae4SAndroid Build Coastguard Worker }
1771*6236dae4SAndroid Build Coastguard Worker connssl->earlydata_state = ssl_earlydata_sending;
1772*6236dae4SAndroid Build Coastguard Worker connssl->earlydata_skip = Curl_bufq_len(&connssl->earlydata);
1773*6236dae4SAndroid Build Coastguard Worker return CURLE_OK;
1774*6236dae4SAndroid Build Coastguard Worker }
1775*6236dae4SAndroid Build Coastguard Worker
gtls_send_earlydata(struct Curl_cfilter * cf,struct Curl_easy * data)1776*6236dae4SAndroid Build Coastguard Worker static CURLcode gtls_send_earlydata(struct Curl_cfilter *cf,
1777*6236dae4SAndroid Build Coastguard Worker struct Curl_easy *data)
1778*6236dae4SAndroid Build Coastguard Worker {
1779*6236dae4SAndroid Build Coastguard Worker struct ssl_connect_data *connssl = cf->ctx;
1780*6236dae4SAndroid Build Coastguard Worker struct gtls_ssl_backend_data *backend =
1781*6236dae4SAndroid Build Coastguard Worker (struct gtls_ssl_backend_data *)connssl->backend;
1782*6236dae4SAndroid Build Coastguard Worker CURLcode result = CURLE_OK;
1783*6236dae4SAndroid Build Coastguard Worker const unsigned char *buf;
1784*6236dae4SAndroid Build Coastguard Worker size_t blen;
1785*6236dae4SAndroid Build Coastguard Worker ssize_t n;
1786*6236dae4SAndroid Build Coastguard Worker
1787*6236dae4SAndroid Build Coastguard Worker DEBUGASSERT(connssl->earlydata_state == ssl_earlydata_sending);
1788*6236dae4SAndroid Build Coastguard Worker backend->gtls.io_result = CURLE_OK;
1789*6236dae4SAndroid Build Coastguard Worker while(Curl_bufq_peek(&connssl->earlydata, &buf, &blen)) {
1790*6236dae4SAndroid Build Coastguard Worker n = gnutls_record_send_early_data(backend->gtls.session, buf, blen);
1791*6236dae4SAndroid Build Coastguard Worker CURL_TRC_CF(data, cf, "gtls_send_earlydata(len=%zu) -> %zd",
1792*6236dae4SAndroid Build Coastguard Worker blen, n);
1793*6236dae4SAndroid Build Coastguard Worker if(n < 0) {
1794*6236dae4SAndroid Build Coastguard Worker if(n == GNUTLS_E_AGAIN)
1795*6236dae4SAndroid Build Coastguard Worker result = CURLE_AGAIN;
1796*6236dae4SAndroid Build Coastguard Worker else
1797*6236dae4SAndroid Build Coastguard Worker result = backend->gtls.io_result ?
1798*6236dae4SAndroid Build Coastguard Worker backend->gtls.io_result : CURLE_SEND_ERROR;
1799*6236dae4SAndroid Build Coastguard Worker goto out;
1800*6236dae4SAndroid Build Coastguard Worker }
1801*6236dae4SAndroid Build Coastguard Worker else if(!n) {
1802*6236dae4SAndroid Build Coastguard Worker /* gnutls is buggy, it *SHOULD* return the amount of bytes it took in.
1803*6236dae4SAndroid Build Coastguard Worker * Instead it returns 0 if everything was written. */
1804*6236dae4SAndroid Build Coastguard Worker n = (ssize_t)blen;
1805*6236dae4SAndroid Build Coastguard Worker }
1806*6236dae4SAndroid Build Coastguard Worker
1807*6236dae4SAndroid Build Coastguard Worker Curl_bufq_skip(&connssl->earlydata, (size_t)n);
1808*6236dae4SAndroid Build Coastguard Worker }
1809*6236dae4SAndroid Build Coastguard Worker /* sent everything there was */
1810*6236dae4SAndroid Build Coastguard Worker infof(data, "SSL sending %" FMT_OFF_T " bytes of early data",
1811*6236dae4SAndroid Build Coastguard Worker connssl->earlydata_skip);
1812*6236dae4SAndroid Build Coastguard Worker out:
1813*6236dae4SAndroid Build Coastguard Worker return result;
1814*6236dae4SAndroid Build Coastguard Worker }
1815*6236dae4SAndroid Build Coastguard Worker
1816*6236dae4SAndroid Build Coastguard Worker /*
1817*6236dae4SAndroid Build Coastguard Worker * This function is called after the TCP connect has completed. Setup the TLS
1818*6236dae4SAndroid Build Coastguard Worker * layer and do all necessary magic.
1819*6236dae4SAndroid Build Coastguard Worker */
1820*6236dae4SAndroid Build Coastguard Worker /* We use connssl->connecting_state to keep track of the connection status;
1821*6236dae4SAndroid Build Coastguard Worker there are three states: 'ssl_connect_1' (not started yet or complete),
1822*6236dae4SAndroid Build Coastguard Worker 'ssl_connect_2' (doing handshake with the server), and
1823*6236dae4SAndroid Build Coastguard Worker 'ssl_connect_3' (verifying and getting stats).
1824*6236dae4SAndroid Build Coastguard Worker */
1825*6236dae4SAndroid Build Coastguard Worker static CURLcode
gtls_connect_common(struct Curl_cfilter * cf,struct Curl_easy * data,bool nonblocking,bool * done)1826*6236dae4SAndroid Build Coastguard Worker gtls_connect_common(struct Curl_cfilter *cf,
1827*6236dae4SAndroid Build Coastguard Worker struct Curl_easy *data,
1828*6236dae4SAndroid Build Coastguard Worker bool nonblocking,
1829*6236dae4SAndroid Build Coastguard Worker bool *done) {
1830*6236dae4SAndroid Build Coastguard Worker struct ssl_connect_data *connssl = cf->ctx;
1831*6236dae4SAndroid Build Coastguard Worker struct gtls_ssl_backend_data *backend =
1832*6236dae4SAndroid Build Coastguard Worker (struct gtls_ssl_backend_data *)connssl->backend;
1833*6236dae4SAndroid Build Coastguard Worker CURLcode result = CURLE_OK;
1834*6236dae4SAndroid Build Coastguard Worker
1835*6236dae4SAndroid Build Coastguard Worker DEBUGASSERT(backend);
1836*6236dae4SAndroid Build Coastguard Worker
1837*6236dae4SAndroid Build Coastguard Worker /* Initiate the connection, if not already done */
1838*6236dae4SAndroid Build Coastguard Worker if(connssl->connecting_state == ssl_connect_1) {
1839*6236dae4SAndroid Build Coastguard Worker result = gtls_connect_step1(cf, data);
1840*6236dae4SAndroid Build Coastguard Worker if(result)
1841*6236dae4SAndroid Build Coastguard Worker goto out;
1842*6236dae4SAndroid Build Coastguard Worker connssl->connecting_state = ssl_connect_2;
1843*6236dae4SAndroid Build Coastguard Worker }
1844*6236dae4SAndroid Build Coastguard Worker
1845*6236dae4SAndroid Build Coastguard Worker if(connssl->connecting_state == ssl_connect_2) {
1846*6236dae4SAndroid Build Coastguard Worker if(connssl->earlydata_state == ssl_earlydata_use) {
1847*6236dae4SAndroid Build Coastguard Worker goto out;
1848*6236dae4SAndroid Build Coastguard Worker }
1849*6236dae4SAndroid Build Coastguard Worker else if(connssl->earlydata_state == ssl_earlydata_sending) {
1850*6236dae4SAndroid Build Coastguard Worker result = gtls_send_earlydata(cf, data);
1851*6236dae4SAndroid Build Coastguard Worker if(result)
1852*6236dae4SAndroid Build Coastguard Worker goto out;
1853*6236dae4SAndroid Build Coastguard Worker connssl->earlydata_state = ssl_earlydata_sent;
1854*6236dae4SAndroid Build Coastguard Worker if(!Curl_ssl_cf_is_proxy(cf))
1855*6236dae4SAndroid Build Coastguard Worker Curl_pgrsEarlyData(data, (curl_off_t)connssl->earlydata_skip);
1856*6236dae4SAndroid Build Coastguard Worker }
1857*6236dae4SAndroid Build Coastguard Worker DEBUGASSERT((connssl->earlydata_state == ssl_earlydata_none) ||
1858*6236dae4SAndroid Build Coastguard Worker (connssl->earlydata_state == ssl_earlydata_sent));
1859*6236dae4SAndroid Build Coastguard Worker
1860*6236dae4SAndroid Build Coastguard Worker result = handshake(cf, data, TRUE, nonblocking);
1861*6236dae4SAndroid Build Coastguard Worker if(result)
1862*6236dae4SAndroid Build Coastguard Worker goto out;
1863*6236dae4SAndroid Build Coastguard Worker connssl->connecting_state = ssl_connect_3;
1864*6236dae4SAndroid Build Coastguard Worker }
1865*6236dae4SAndroid Build Coastguard Worker
1866*6236dae4SAndroid Build Coastguard Worker /* Finish connecting once the handshake is done */
1867*6236dae4SAndroid Build Coastguard Worker if(connssl->connecting_state == ssl_connect_3) {
1868*6236dae4SAndroid Build Coastguard Worker gnutls_datum_t proto;
1869*6236dae4SAndroid Build Coastguard Worker int rc;
1870*6236dae4SAndroid Build Coastguard Worker result = gtls_verifyserver(cf, data, backend->gtls.session);
1871*6236dae4SAndroid Build Coastguard Worker if(result)
1872*6236dae4SAndroid Build Coastguard Worker goto out;
1873*6236dae4SAndroid Build Coastguard Worker
1874*6236dae4SAndroid Build Coastguard Worker connssl->state = ssl_connection_complete;
1875*6236dae4SAndroid Build Coastguard Worker connssl->connecting_state = ssl_connect_1;
1876*6236dae4SAndroid Build Coastguard Worker
1877*6236dae4SAndroid Build Coastguard Worker rc = gnutls_alpn_get_selected_protocol(backend->gtls.session, &proto);
1878*6236dae4SAndroid Build Coastguard Worker if(rc) { /* No ALPN from server */
1879*6236dae4SAndroid Build Coastguard Worker proto.data = NULL;
1880*6236dae4SAndroid Build Coastguard Worker proto.size = 0;
1881*6236dae4SAndroid Build Coastguard Worker }
1882*6236dae4SAndroid Build Coastguard Worker
1883*6236dae4SAndroid Build Coastguard Worker result = Curl_alpn_set_negotiated(cf, data, connssl,
1884*6236dae4SAndroid Build Coastguard Worker proto.data, proto.size);
1885*6236dae4SAndroid Build Coastguard Worker if(result)
1886*6236dae4SAndroid Build Coastguard Worker goto out;
1887*6236dae4SAndroid Build Coastguard Worker
1888*6236dae4SAndroid Build Coastguard Worker if(connssl->earlydata_state == ssl_earlydata_sent) {
1889*6236dae4SAndroid Build Coastguard Worker if(gnutls_session_get_flags(backend->gtls.session) &
1890*6236dae4SAndroid Build Coastguard Worker GNUTLS_SFLAGS_EARLY_DATA) {
1891*6236dae4SAndroid Build Coastguard Worker connssl->earlydata_state = ssl_earlydata_accepted;
1892*6236dae4SAndroid Build Coastguard Worker infof(data, "Server accepted %zu bytes of TLS early data.",
1893*6236dae4SAndroid Build Coastguard Worker connssl->earlydata_skip);
1894*6236dae4SAndroid Build Coastguard Worker }
1895*6236dae4SAndroid Build Coastguard Worker else {
1896*6236dae4SAndroid Build Coastguard Worker connssl->earlydata_state = ssl_earlydata_rejected;
1897*6236dae4SAndroid Build Coastguard Worker if(!Curl_ssl_cf_is_proxy(cf))
1898*6236dae4SAndroid Build Coastguard Worker Curl_pgrsEarlyData(data, -(curl_off_t)connssl->earlydata_skip);
1899*6236dae4SAndroid Build Coastguard Worker infof(data, "Server rejected TLS early data.");
1900*6236dae4SAndroid Build Coastguard Worker connssl->earlydata_skip = 0;
1901*6236dae4SAndroid Build Coastguard Worker }
1902*6236dae4SAndroid Build Coastguard Worker }
1903*6236dae4SAndroid Build Coastguard Worker }
1904*6236dae4SAndroid Build Coastguard Worker
1905*6236dae4SAndroid Build Coastguard Worker out:
1906*6236dae4SAndroid Build Coastguard Worker if(result == CURLE_AGAIN) {
1907*6236dae4SAndroid Build Coastguard Worker *done = FALSE;
1908*6236dae4SAndroid Build Coastguard Worker return CURLE_OK;
1909*6236dae4SAndroid Build Coastguard Worker }
1910*6236dae4SAndroid Build Coastguard Worker *done = ((connssl->connecting_state == ssl_connect_1) ||
1911*6236dae4SAndroid Build Coastguard Worker (connssl->state == ssl_connection_deferred));
1912*6236dae4SAndroid Build Coastguard Worker return result;
1913*6236dae4SAndroid Build Coastguard Worker }
1914*6236dae4SAndroid Build Coastguard Worker
gtls_connect_nonblocking(struct Curl_cfilter * cf,struct Curl_easy * data,bool * done)1915*6236dae4SAndroid Build Coastguard Worker static CURLcode gtls_connect_nonblocking(struct Curl_cfilter *cf,
1916*6236dae4SAndroid Build Coastguard Worker struct Curl_easy *data,
1917*6236dae4SAndroid Build Coastguard Worker bool *done)
1918*6236dae4SAndroid Build Coastguard Worker {
1919*6236dae4SAndroid Build Coastguard Worker struct ssl_connect_data *connssl = cf->ctx;
1920*6236dae4SAndroid Build Coastguard Worker if(connssl->state == ssl_connection_deferred) {
1921*6236dae4SAndroid Build Coastguard Worker /* We refuse to be pushed, we are waiting for someone to send/recv. */
1922*6236dae4SAndroid Build Coastguard Worker *done = TRUE;
1923*6236dae4SAndroid Build Coastguard Worker return CURLE_OK;
1924*6236dae4SAndroid Build Coastguard Worker }
1925*6236dae4SAndroid Build Coastguard Worker return gtls_connect_common(cf, data, TRUE, done);
1926*6236dae4SAndroid Build Coastguard Worker }
1927*6236dae4SAndroid Build Coastguard Worker
gtls_connect(struct Curl_cfilter * cf,struct Curl_easy * data)1928*6236dae4SAndroid Build Coastguard Worker static CURLcode gtls_connect(struct Curl_cfilter *cf,
1929*6236dae4SAndroid Build Coastguard Worker struct Curl_easy *data)
1930*6236dae4SAndroid Build Coastguard Worker {
1931*6236dae4SAndroid Build Coastguard Worker CURLcode result;
1932*6236dae4SAndroid Build Coastguard Worker bool done = FALSE;
1933*6236dae4SAndroid Build Coastguard Worker
1934*6236dae4SAndroid Build Coastguard Worker result = gtls_connect_common(cf, data, FALSE, &done);
1935*6236dae4SAndroid Build Coastguard Worker if(result)
1936*6236dae4SAndroid Build Coastguard Worker return result;
1937*6236dae4SAndroid Build Coastguard Worker
1938*6236dae4SAndroid Build Coastguard Worker DEBUGASSERT(done);
1939*6236dae4SAndroid Build Coastguard Worker
1940*6236dae4SAndroid Build Coastguard Worker return CURLE_OK;
1941*6236dae4SAndroid Build Coastguard Worker }
1942*6236dae4SAndroid Build Coastguard Worker
gtls_connect_deferred(struct Curl_cfilter * cf,struct Curl_easy * data,const void * buf,size_t blen,bool * done)1943*6236dae4SAndroid Build Coastguard Worker static CURLcode gtls_connect_deferred(struct Curl_cfilter *cf,
1944*6236dae4SAndroid Build Coastguard Worker struct Curl_easy *data,
1945*6236dae4SAndroid Build Coastguard Worker const void *buf,
1946*6236dae4SAndroid Build Coastguard Worker size_t blen,
1947*6236dae4SAndroid Build Coastguard Worker bool *done)
1948*6236dae4SAndroid Build Coastguard Worker {
1949*6236dae4SAndroid Build Coastguard Worker struct ssl_connect_data *connssl = cf->ctx;
1950*6236dae4SAndroid Build Coastguard Worker CURLcode result = CURLE_OK;
1951*6236dae4SAndroid Build Coastguard Worker
1952*6236dae4SAndroid Build Coastguard Worker DEBUGASSERT(connssl->state == ssl_connection_deferred);
1953*6236dae4SAndroid Build Coastguard Worker *done = FALSE;
1954*6236dae4SAndroid Build Coastguard Worker if(connssl->earlydata_state == ssl_earlydata_use) {
1955*6236dae4SAndroid Build Coastguard Worker result = gtls_set_earlydata(cf, data, buf, blen);
1956*6236dae4SAndroid Build Coastguard Worker if(result)
1957*6236dae4SAndroid Build Coastguard Worker return result;
1958*6236dae4SAndroid Build Coastguard Worker }
1959*6236dae4SAndroid Build Coastguard Worker
1960*6236dae4SAndroid Build Coastguard Worker return gtls_connect_common(cf, data, TRUE, done);
1961*6236dae4SAndroid Build Coastguard Worker }
1962*6236dae4SAndroid Build Coastguard Worker
gtls_data_pending(struct Curl_cfilter * cf,const struct Curl_easy * data)1963*6236dae4SAndroid Build Coastguard Worker static bool gtls_data_pending(struct Curl_cfilter *cf,
1964*6236dae4SAndroid Build Coastguard Worker const struct Curl_easy *data)
1965*6236dae4SAndroid Build Coastguard Worker {
1966*6236dae4SAndroid Build Coastguard Worker struct ssl_connect_data *ctx = cf->ctx;
1967*6236dae4SAndroid Build Coastguard Worker struct gtls_ssl_backend_data *backend;
1968*6236dae4SAndroid Build Coastguard Worker
1969*6236dae4SAndroid Build Coastguard Worker (void)data;
1970*6236dae4SAndroid Build Coastguard Worker DEBUGASSERT(ctx && ctx->backend);
1971*6236dae4SAndroid Build Coastguard Worker backend = (struct gtls_ssl_backend_data *)ctx->backend;
1972*6236dae4SAndroid Build Coastguard Worker if(backend->gtls.session &&
1973*6236dae4SAndroid Build Coastguard Worker 0 != gnutls_record_check_pending(backend->gtls.session))
1974*6236dae4SAndroid Build Coastguard Worker return TRUE;
1975*6236dae4SAndroid Build Coastguard Worker return FALSE;
1976*6236dae4SAndroid Build Coastguard Worker }
1977*6236dae4SAndroid Build Coastguard Worker
gtls_send(struct Curl_cfilter * cf,struct Curl_easy * data,const void * buf,size_t blen,CURLcode * curlcode)1978*6236dae4SAndroid Build Coastguard Worker static ssize_t gtls_send(struct Curl_cfilter *cf,
1979*6236dae4SAndroid Build Coastguard Worker struct Curl_easy *data,
1980*6236dae4SAndroid Build Coastguard Worker const void *buf,
1981*6236dae4SAndroid Build Coastguard Worker size_t blen,
1982*6236dae4SAndroid Build Coastguard Worker CURLcode *curlcode)
1983*6236dae4SAndroid Build Coastguard Worker {
1984*6236dae4SAndroid Build Coastguard Worker struct ssl_connect_data *connssl = cf->ctx;
1985*6236dae4SAndroid Build Coastguard Worker struct gtls_ssl_backend_data *backend =
1986*6236dae4SAndroid Build Coastguard Worker (struct gtls_ssl_backend_data *)connssl->backend;
1987*6236dae4SAndroid Build Coastguard Worker ssize_t rc;
1988*6236dae4SAndroid Build Coastguard Worker size_t nwritten, total_written = 0;
1989*6236dae4SAndroid Build Coastguard Worker
1990*6236dae4SAndroid Build Coastguard Worker DEBUGASSERT(backend);
1991*6236dae4SAndroid Build Coastguard Worker
1992*6236dae4SAndroid Build Coastguard Worker if(connssl->state == ssl_connection_deferred) {
1993*6236dae4SAndroid Build Coastguard Worker bool done = FALSE;
1994*6236dae4SAndroid Build Coastguard Worker *curlcode = gtls_connect_deferred(cf, data, buf, blen, &done);
1995*6236dae4SAndroid Build Coastguard Worker if(*curlcode) {
1996*6236dae4SAndroid Build Coastguard Worker rc = -1;
1997*6236dae4SAndroid Build Coastguard Worker goto out;
1998*6236dae4SAndroid Build Coastguard Worker }
1999*6236dae4SAndroid Build Coastguard Worker else if(!done) {
2000*6236dae4SAndroid Build Coastguard Worker *curlcode = CURLE_AGAIN;
2001*6236dae4SAndroid Build Coastguard Worker rc = -1;
2002*6236dae4SAndroid Build Coastguard Worker goto out;
2003*6236dae4SAndroid Build Coastguard Worker }
2004*6236dae4SAndroid Build Coastguard Worker DEBUGASSERT(connssl->state == ssl_connection_complete);
2005*6236dae4SAndroid Build Coastguard Worker }
2006*6236dae4SAndroid Build Coastguard Worker
2007*6236dae4SAndroid Build Coastguard Worker if(connssl->earlydata_skip) {
2008*6236dae4SAndroid Build Coastguard Worker if(connssl->earlydata_skip >= blen) {
2009*6236dae4SAndroid Build Coastguard Worker connssl->earlydata_skip -= blen;
2010*6236dae4SAndroid Build Coastguard Worker *curlcode = CURLE_OK;
2011*6236dae4SAndroid Build Coastguard Worker rc = (ssize_t)blen;
2012*6236dae4SAndroid Build Coastguard Worker goto out;
2013*6236dae4SAndroid Build Coastguard Worker }
2014*6236dae4SAndroid Build Coastguard Worker else {
2015*6236dae4SAndroid Build Coastguard Worker total_written += connssl->earlydata_skip;
2016*6236dae4SAndroid Build Coastguard Worker buf = ((const char *)buf) + connssl->earlydata_skip;
2017*6236dae4SAndroid Build Coastguard Worker blen -= connssl->earlydata_skip;
2018*6236dae4SAndroid Build Coastguard Worker connssl->earlydata_skip = 0;
2019*6236dae4SAndroid Build Coastguard Worker }
2020*6236dae4SAndroid Build Coastguard Worker }
2021*6236dae4SAndroid Build Coastguard Worker
2022*6236dae4SAndroid Build Coastguard Worker while(blen) {
2023*6236dae4SAndroid Build Coastguard Worker backend->gtls.io_result = CURLE_OK;
2024*6236dae4SAndroid Build Coastguard Worker rc = gnutls_record_send(backend->gtls.session, buf, blen);
2025*6236dae4SAndroid Build Coastguard Worker
2026*6236dae4SAndroid Build Coastguard Worker if(rc < 0) {
2027*6236dae4SAndroid Build Coastguard Worker if(total_written && (rc == GNUTLS_E_AGAIN)) {
2028*6236dae4SAndroid Build Coastguard Worker *curlcode = CURLE_OK;
2029*6236dae4SAndroid Build Coastguard Worker rc = (ssize_t)total_written;
2030*6236dae4SAndroid Build Coastguard Worker goto out;
2031*6236dae4SAndroid Build Coastguard Worker }
2032*6236dae4SAndroid Build Coastguard Worker *curlcode = (rc == GNUTLS_E_AGAIN) ?
2033*6236dae4SAndroid Build Coastguard Worker CURLE_AGAIN :
2034*6236dae4SAndroid Build Coastguard Worker (backend->gtls.io_result ? backend->gtls.io_result : CURLE_SEND_ERROR);
2035*6236dae4SAndroid Build Coastguard Worker
2036*6236dae4SAndroid Build Coastguard Worker rc = -1;
2037*6236dae4SAndroid Build Coastguard Worker goto out;
2038*6236dae4SAndroid Build Coastguard Worker }
2039*6236dae4SAndroid Build Coastguard Worker nwritten = (size_t)rc;
2040*6236dae4SAndroid Build Coastguard Worker total_written += nwritten;
2041*6236dae4SAndroid Build Coastguard Worker DEBUGASSERT(nwritten <= blen);
2042*6236dae4SAndroid Build Coastguard Worker buf = (char *)buf + nwritten;
2043*6236dae4SAndroid Build Coastguard Worker blen -= nwritten;
2044*6236dae4SAndroid Build Coastguard Worker }
2045*6236dae4SAndroid Build Coastguard Worker rc = total_written;
2046*6236dae4SAndroid Build Coastguard Worker
2047*6236dae4SAndroid Build Coastguard Worker out:
2048*6236dae4SAndroid Build Coastguard Worker return rc;
2049*6236dae4SAndroid Build Coastguard Worker }
2050*6236dae4SAndroid Build Coastguard Worker
2051*6236dae4SAndroid Build Coastguard Worker /*
2052*6236dae4SAndroid Build Coastguard Worker * This function is called to shut down the SSL layer but keep the
2053*6236dae4SAndroid Build Coastguard Worker * socket open (CCC - Clear Command Channel)
2054*6236dae4SAndroid Build Coastguard Worker */
gtls_shutdown(struct Curl_cfilter * cf,struct Curl_easy * data,bool send_shutdown,bool * done)2055*6236dae4SAndroid Build Coastguard Worker static CURLcode gtls_shutdown(struct Curl_cfilter *cf,
2056*6236dae4SAndroid Build Coastguard Worker struct Curl_easy *data,
2057*6236dae4SAndroid Build Coastguard Worker bool send_shutdown, bool *done)
2058*6236dae4SAndroid Build Coastguard Worker {
2059*6236dae4SAndroid Build Coastguard Worker struct ssl_connect_data *connssl = cf->ctx;
2060*6236dae4SAndroid Build Coastguard Worker struct gtls_ssl_backend_data *backend =
2061*6236dae4SAndroid Build Coastguard Worker (struct gtls_ssl_backend_data *)connssl->backend;
2062*6236dae4SAndroid Build Coastguard Worker char buf[1024];
2063*6236dae4SAndroid Build Coastguard Worker CURLcode result = CURLE_OK;
2064*6236dae4SAndroid Build Coastguard Worker ssize_t nread;
2065*6236dae4SAndroid Build Coastguard Worker size_t i;
2066*6236dae4SAndroid Build Coastguard Worker
2067*6236dae4SAndroid Build Coastguard Worker DEBUGASSERT(backend);
2068*6236dae4SAndroid Build Coastguard Worker /* If we have no handshaked connection or already shut down */
2069*6236dae4SAndroid Build Coastguard Worker if(!backend->gtls.session || cf->shutdown ||
2070*6236dae4SAndroid Build Coastguard Worker connssl->state != ssl_connection_complete) {
2071*6236dae4SAndroid Build Coastguard Worker *done = TRUE;
2072*6236dae4SAndroid Build Coastguard Worker goto out;
2073*6236dae4SAndroid Build Coastguard Worker }
2074*6236dae4SAndroid Build Coastguard Worker
2075*6236dae4SAndroid Build Coastguard Worker connssl->io_need = CURL_SSL_IO_NEED_NONE;
2076*6236dae4SAndroid Build Coastguard Worker *done = FALSE;
2077*6236dae4SAndroid Build Coastguard Worker
2078*6236dae4SAndroid Build Coastguard Worker if(!backend->gtls.sent_shutdown) {
2079*6236dae4SAndroid Build Coastguard Worker /* do this only once */
2080*6236dae4SAndroid Build Coastguard Worker backend->gtls.sent_shutdown = TRUE;
2081*6236dae4SAndroid Build Coastguard Worker if(send_shutdown) {
2082*6236dae4SAndroid Build Coastguard Worker int ret = gnutls_bye(backend->gtls.session, GNUTLS_SHUT_RDWR);
2083*6236dae4SAndroid Build Coastguard Worker if((ret == GNUTLS_E_AGAIN) || (ret == GNUTLS_E_INTERRUPTED)) {
2084*6236dae4SAndroid Build Coastguard Worker CURL_TRC_CF(data, cf, "SSL shutdown, gnutls_bye EAGAIN");
2085*6236dae4SAndroid Build Coastguard Worker connssl->io_need = gnutls_record_get_direction(backend->gtls.session) ?
2086*6236dae4SAndroid Build Coastguard Worker CURL_SSL_IO_NEED_SEND : CURL_SSL_IO_NEED_RECV;
2087*6236dae4SAndroid Build Coastguard Worker backend->gtls.sent_shutdown = FALSE;
2088*6236dae4SAndroid Build Coastguard Worker result = CURLE_OK;
2089*6236dae4SAndroid Build Coastguard Worker goto out;
2090*6236dae4SAndroid Build Coastguard Worker }
2091*6236dae4SAndroid Build Coastguard Worker if(ret != GNUTLS_E_SUCCESS) {
2092*6236dae4SAndroid Build Coastguard Worker CURL_TRC_CF(data, cf, "SSL shutdown, gnutls_bye error: '%s'(%d)",
2093*6236dae4SAndroid Build Coastguard Worker gnutls_strerror((int)ret), (int)ret);
2094*6236dae4SAndroid Build Coastguard Worker result = CURLE_RECV_ERROR;
2095*6236dae4SAndroid Build Coastguard Worker goto out;
2096*6236dae4SAndroid Build Coastguard Worker }
2097*6236dae4SAndroid Build Coastguard Worker }
2098*6236dae4SAndroid Build Coastguard Worker }
2099*6236dae4SAndroid Build Coastguard Worker
2100*6236dae4SAndroid Build Coastguard Worker /* SSL should now have started the shutdown from our side. Since it
2101*6236dae4SAndroid Build Coastguard Worker * was not complete, we are lacking the close notify from the server. */
2102*6236dae4SAndroid Build Coastguard Worker for(i = 0; i < 10; ++i) {
2103*6236dae4SAndroid Build Coastguard Worker nread = gnutls_record_recv(backend->gtls.session, buf, sizeof(buf));
2104*6236dae4SAndroid Build Coastguard Worker if(nread <= 0)
2105*6236dae4SAndroid Build Coastguard Worker break;
2106*6236dae4SAndroid Build Coastguard Worker }
2107*6236dae4SAndroid Build Coastguard Worker if(nread > 0) {
2108*6236dae4SAndroid Build Coastguard Worker /* still data coming in? */
2109*6236dae4SAndroid Build Coastguard Worker }
2110*6236dae4SAndroid Build Coastguard Worker else if(nread == 0) {
2111*6236dae4SAndroid Build Coastguard Worker /* We got the close notify alert and are done. */
2112*6236dae4SAndroid Build Coastguard Worker *done = TRUE;
2113*6236dae4SAndroid Build Coastguard Worker }
2114*6236dae4SAndroid Build Coastguard Worker else if((nread == GNUTLS_E_AGAIN) || (nread == GNUTLS_E_INTERRUPTED)) {
2115*6236dae4SAndroid Build Coastguard Worker connssl->io_need = gnutls_record_get_direction(backend->gtls.session) ?
2116*6236dae4SAndroid Build Coastguard Worker CURL_SSL_IO_NEED_SEND : CURL_SSL_IO_NEED_RECV;
2117*6236dae4SAndroid Build Coastguard Worker }
2118*6236dae4SAndroid Build Coastguard Worker else {
2119*6236dae4SAndroid Build Coastguard Worker CURL_TRC_CF(data, cf, "SSL shutdown, error: '%s'(%d)",
2120*6236dae4SAndroid Build Coastguard Worker gnutls_strerror((int)nread), (int)nread);
2121*6236dae4SAndroid Build Coastguard Worker result = CURLE_RECV_ERROR;
2122*6236dae4SAndroid Build Coastguard Worker }
2123*6236dae4SAndroid Build Coastguard Worker
2124*6236dae4SAndroid Build Coastguard Worker out:
2125*6236dae4SAndroid Build Coastguard Worker cf->shutdown = (result || *done);
2126*6236dae4SAndroid Build Coastguard Worker return result;
2127*6236dae4SAndroid Build Coastguard Worker }
2128*6236dae4SAndroid Build Coastguard Worker
gtls_close(struct Curl_cfilter * cf,struct Curl_easy * data)2129*6236dae4SAndroid Build Coastguard Worker static void gtls_close(struct Curl_cfilter *cf,
2130*6236dae4SAndroid Build Coastguard Worker struct Curl_easy *data)
2131*6236dae4SAndroid Build Coastguard Worker {
2132*6236dae4SAndroid Build Coastguard Worker struct ssl_connect_data *connssl = cf->ctx;
2133*6236dae4SAndroid Build Coastguard Worker struct gtls_ssl_backend_data *backend =
2134*6236dae4SAndroid Build Coastguard Worker (struct gtls_ssl_backend_data *)connssl->backend;
2135*6236dae4SAndroid Build Coastguard Worker
2136*6236dae4SAndroid Build Coastguard Worker (void) data;
2137*6236dae4SAndroid Build Coastguard Worker DEBUGASSERT(backend);
2138*6236dae4SAndroid Build Coastguard Worker CURL_TRC_CF(data, cf, "close");
2139*6236dae4SAndroid Build Coastguard Worker if(backend->gtls.session) {
2140*6236dae4SAndroid Build Coastguard Worker gnutls_deinit(backend->gtls.session);
2141*6236dae4SAndroid Build Coastguard Worker backend->gtls.session = NULL;
2142*6236dae4SAndroid Build Coastguard Worker }
2143*6236dae4SAndroid Build Coastguard Worker if(backend->gtls.shared_creds) {
2144*6236dae4SAndroid Build Coastguard Worker Curl_gtls_shared_creds_free(&backend->gtls.shared_creds);
2145*6236dae4SAndroid Build Coastguard Worker }
2146*6236dae4SAndroid Build Coastguard Worker #ifdef USE_GNUTLS_SRP
2147*6236dae4SAndroid Build Coastguard Worker if(backend->gtls.srp_client_cred) {
2148*6236dae4SAndroid Build Coastguard Worker gnutls_srp_free_client_credentials(backend->gtls.srp_client_cred);
2149*6236dae4SAndroid Build Coastguard Worker backend->gtls.srp_client_cred = NULL;
2150*6236dae4SAndroid Build Coastguard Worker }
2151*6236dae4SAndroid Build Coastguard Worker #endif
2152*6236dae4SAndroid Build Coastguard Worker }
2153*6236dae4SAndroid Build Coastguard Worker
gtls_recv(struct Curl_cfilter * cf,struct Curl_easy * data,char * buf,size_t buffersize,CURLcode * curlcode)2154*6236dae4SAndroid Build Coastguard Worker static ssize_t gtls_recv(struct Curl_cfilter *cf,
2155*6236dae4SAndroid Build Coastguard Worker struct Curl_easy *data,
2156*6236dae4SAndroid Build Coastguard Worker char *buf,
2157*6236dae4SAndroid Build Coastguard Worker size_t buffersize,
2158*6236dae4SAndroid Build Coastguard Worker CURLcode *curlcode)
2159*6236dae4SAndroid Build Coastguard Worker {
2160*6236dae4SAndroid Build Coastguard Worker struct ssl_connect_data *connssl = cf->ctx;
2161*6236dae4SAndroid Build Coastguard Worker struct gtls_ssl_backend_data *backend =
2162*6236dae4SAndroid Build Coastguard Worker (struct gtls_ssl_backend_data *)connssl->backend;
2163*6236dae4SAndroid Build Coastguard Worker ssize_t ret;
2164*6236dae4SAndroid Build Coastguard Worker
2165*6236dae4SAndroid Build Coastguard Worker (void)data;
2166*6236dae4SAndroid Build Coastguard Worker DEBUGASSERT(backend);
2167*6236dae4SAndroid Build Coastguard Worker
2168*6236dae4SAndroid Build Coastguard Worker if(connssl->state == ssl_connection_deferred) {
2169*6236dae4SAndroid Build Coastguard Worker bool done = FALSE;
2170*6236dae4SAndroid Build Coastguard Worker *curlcode = gtls_connect_deferred(cf, data, NULL, 0, &done);
2171*6236dae4SAndroid Build Coastguard Worker if(*curlcode) {
2172*6236dae4SAndroid Build Coastguard Worker ret = -1;
2173*6236dae4SAndroid Build Coastguard Worker goto out;
2174*6236dae4SAndroid Build Coastguard Worker }
2175*6236dae4SAndroid Build Coastguard Worker else if(!done) {
2176*6236dae4SAndroid Build Coastguard Worker *curlcode = CURLE_AGAIN;
2177*6236dae4SAndroid Build Coastguard Worker ret = -1;
2178*6236dae4SAndroid Build Coastguard Worker goto out;
2179*6236dae4SAndroid Build Coastguard Worker }
2180*6236dae4SAndroid Build Coastguard Worker DEBUGASSERT(connssl->state == ssl_connection_complete);
2181*6236dae4SAndroid Build Coastguard Worker }
2182*6236dae4SAndroid Build Coastguard Worker
2183*6236dae4SAndroid Build Coastguard Worker ret = gnutls_record_recv(backend->gtls.session, buf, buffersize);
2184*6236dae4SAndroid Build Coastguard Worker if((ret == GNUTLS_E_AGAIN) || (ret == GNUTLS_E_INTERRUPTED)) {
2185*6236dae4SAndroid Build Coastguard Worker *curlcode = CURLE_AGAIN;
2186*6236dae4SAndroid Build Coastguard Worker ret = -1;
2187*6236dae4SAndroid Build Coastguard Worker goto out;
2188*6236dae4SAndroid Build Coastguard Worker }
2189*6236dae4SAndroid Build Coastguard Worker
2190*6236dae4SAndroid Build Coastguard Worker if(ret == GNUTLS_E_REHANDSHAKE) {
2191*6236dae4SAndroid Build Coastguard Worker /* BLOCKING call, this is bad but a work-around for now. Fixing this "the
2192*6236dae4SAndroid Build Coastguard Worker proper way" takes a whole lot of work. */
2193*6236dae4SAndroid Build Coastguard Worker CURLcode result = handshake(cf, data, FALSE, FALSE);
2194*6236dae4SAndroid Build Coastguard Worker if(result)
2195*6236dae4SAndroid Build Coastguard Worker /* handshake() writes error message on its own */
2196*6236dae4SAndroid Build Coastguard Worker *curlcode = result;
2197*6236dae4SAndroid Build Coastguard Worker else
2198*6236dae4SAndroid Build Coastguard Worker *curlcode = CURLE_AGAIN; /* then return as if this was a wouldblock */
2199*6236dae4SAndroid Build Coastguard Worker ret = -1;
2200*6236dae4SAndroid Build Coastguard Worker goto out;
2201*6236dae4SAndroid Build Coastguard Worker }
2202*6236dae4SAndroid Build Coastguard Worker
2203*6236dae4SAndroid Build Coastguard Worker if(ret < 0) {
2204*6236dae4SAndroid Build Coastguard Worker failf(data, "GnuTLS recv error (%d): %s",
2205*6236dae4SAndroid Build Coastguard Worker (int)ret, gnutls_strerror((int)ret));
2206*6236dae4SAndroid Build Coastguard Worker *curlcode = backend->gtls.io_result ?
2207*6236dae4SAndroid Build Coastguard Worker backend->gtls.io_result : CURLE_RECV_ERROR;
2208*6236dae4SAndroid Build Coastguard Worker ret = -1;
2209*6236dae4SAndroid Build Coastguard Worker goto out;
2210*6236dae4SAndroid Build Coastguard Worker }
2211*6236dae4SAndroid Build Coastguard Worker
2212*6236dae4SAndroid Build Coastguard Worker out:
2213*6236dae4SAndroid Build Coastguard Worker return ret;
2214*6236dae4SAndroid Build Coastguard Worker }
2215*6236dae4SAndroid Build Coastguard Worker
gtls_version(char * buffer,size_t size)2216*6236dae4SAndroid Build Coastguard Worker static size_t gtls_version(char *buffer, size_t size)
2217*6236dae4SAndroid Build Coastguard Worker {
2218*6236dae4SAndroid Build Coastguard Worker return msnprintf(buffer, size, "GnuTLS/%s", gnutls_check_version(NULL));
2219*6236dae4SAndroid Build Coastguard Worker }
2220*6236dae4SAndroid Build Coastguard Worker
2221*6236dae4SAndroid Build Coastguard Worker /* data might be NULL! */
gtls_random(struct Curl_easy * data,unsigned char * entropy,size_t length)2222*6236dae4SAndroid Build Coastguard Worker static CURLcode gtls_random(struct Curl_easy *data,
2223*6236dae4SAndroid Build Coastguard Worker unsigned char *entropy, size_t length)
2224*6236dae4SAndroid Build Coastguard Worker {
2225*6236dae4SAndroid Build Coastguard Worker int rc;
2226*6236dae4SAndroid Build Coastguard Worker (void)data;
2227*6236dae4SAndroid Build Coastguard Worker rc = gnutls_rnd(GNUTLS_RND_RANDOM, entropy, length);
2228*6236dae4SAndroid Build Coastguard Worker return rc ? CURLE_FAILED_INIT : CURLE_OK;
2229*6236dae4SAndroid Build Coastguard Worker }
2230*6236dae4SAndroid Build Coastguard Worker
gtls_sha256sum(const unsigned char * tmp,size_t tmplen,unsigned char * sha256sum,size_t sha256len)2231*6236dae4SAndroid Build Coastguard Worker static CURLcode gtls_sha256sum(const unsigned char *tmp, /* input */
2232*6236dae4SAndroid Build Coastguard Worker size_t tmplen,
2233*6236dae4SAndroid Build Coastguard Worker unsigned char *sha256sum, /* output */
2234*6236dae4SAndroid Build Coastguard Worker size_t sha256len)
2235*6236dae4SAndroid Build Coastguard Worker {
2236*6236dae4SAndroid Build Coastguard Worker struct sha256_ctx SHA256pw;
2237*6236dae4SAndroid Build Coastguard Worker sha256_init(&SHA256pw);
2238*6236dae4SAndroid Build Coastguard Worker sha256_update(&SHA256pw, (unsigned int)tmplen, tmp);
2239*6236dae4SAndroid Build Coastguard Worker sha256_digest(&SHA256pw, (unsigned int)sha256len, sha256sum);
2240*6236dae4SAndroid Build Coastguard Worker return CURLE_OK;
2241*6236dae4SAndroid Build Coastguard Worker }
2242*6236dae4SAndroid Build Coastguard Worker
gtls_cert_status_request(void)2243*6236dae4SAndroid Build Coastguard Worker static bool gtls_cert_status_request(void)
2244*6236dae4SAndroid Build Coastguard Worker {
2245*6236dae4SAndroid Build Coastguard Worker return TRUE;
2246*6236dae4SAndroid Build Coastguard Worker }
2247*6236dae4SAndroid Build Coastguard Worker
gtls_get_internals(struct ssl_connect_data * connssl,CURLINFO info UNUSED_PARAM)2248*6236dae4SAndroid Build Coastguard Worker static void *gtls_get_internals(struct ssl_connect_data *connssl,
2249*6236dae4SAndroid Build Coastguard Worker CURLINFO info UNUSED_PARAM)
2250*6236dae4SAndroid Build Coastguard Worker {
2251*6236dae4SAndroid Build Coastguard Worker struct gtls_ssl_backend_data *backend =
2252*6236dae4SAndroid Build Coastguard Worker (struct gtls_ssl_backend_data *)connssl->backend;
2253*6236dae4SAndroid Build Coastguard Worker (void)info;
2254*6236dae4SAndroid Build Coastguard Worker DEBUGASSERT(backend);
2255*6236dae4SAndroid Build Coastguard Worker return backend->gtls.session;
2256*6236dae4SAndroid Build Coastguard Worker }
2257*6236dae4SAndroid Build Coastguard Worker
2258*6236dae4SAndroid Build Coastguard Worker const struct Curl_ssl Curl_ssl_gnutls = {
2259*6236dae4SAndroid Build Coastguard Worker { CURLSSLBACKEND_GNUTLS, "gnutls" }, /* info */
2260*6236dae4SAndroid Build Coastguard Worker
2261*6236dae4SAndroid Build Coastguard Worker SSLSUPP_CA_PATH |
2262*6236dae4SAndroid Build Coastguard Worker SSLSUPP_CERTINFO |
2263*6236dae4SAndroid Build Coastguard Worker SSLSUPP_PINNEDPUBKEY |
2264*6236dae4SAndroid Build Coastguard Worker SSLSUPP_HTTPS_PROXY |
2265*6236dae4SAndroid Build Coastguard Worker SSLSUPP_CA_CACHE,
2266*6236dae4SAndroid Build Coastguard Worker
2267*6236dae4SAndroid Build Coastguard Worker sizeof(struct gtls_ssl_backend_data),
2268*6236dae4SAndroid Build Coastguard Worker
2269*6236dae4SAndroid Build Coastguard Worker gtls_init, /* init */
2270*6236dae4SAndroid Build Coastguard Worker gtls_cleanup, /* cleanup */
2271*6236dae4SAndroid Build Coastguard Worker gtls_version, /* version */
2272*6236dae4SAndroid Build Coastguard Worker Curl_none_check_cxn, /* check_cxn */
2273*6236dae4SAndroid Build Coastguard Worker gtls_shutdown, /* shutdown */
2274*6236dae4SAndroid Build Coastguard Worker gtls_data_pending, /* data_pending */
2275*6236dae4SAndroid Build Coastguard Worker gtls_random, /* random */
2276*6236dae4SAndroid Build Coastguard Worker gtls_cert_status_request, /* cert_status_request */
2277*6236dae4SAndroid Build Coastguard Worker gtls_connect, /* connect */
2278*6236dae4SAndroid Build Coastguard Worker gtls_connect_nonblocking, /* connect_nonblocking */
2279*6236dae4SAndroid Build Coastguard Worker Curl_ssl_adjust_pollset, /* adjust_pollset */
2280*6236dae4SAndroid Build Coastguard Worker gtls_get_internals, /* get_internals */
2281*6236dae4SAndroid Build Coastguard Worker gtls_close, /* close_one */
2282*6236dae4SAndroid Build Coastguard Worker Curl_none_close_all, /* close_all */
2283*6236dae4SAndroid Build Coastguard Worker Curl_none_set_engine, /* set_engine */
2284*6236dae4SAndroid Build Coastguard Worker Curl_none_set_engine_default, /* set_engine_default */
2285*6236dae4SAndroid Build Coastguard Worker Curl_none_engines_list, /* engines_list */
2286*6236dae4SAndroid Build Coastguard Worker Curl_none_false_start, /* false_start */
2287*6236dae4SAndroid Build Coastguard Worker gtls_sha256sum, /* sha256sum */
2288*6236dae4SAndroid Build Coastguard Worker NULL, /* associate_connection */
2289*6236dae4SAndroid Build Coastguard Worker NULL, /* disassociate_connection */
2290*6236dae4SAndroid Build Coastguard Worker gtls_recv, /* recv decrypted data */
2291*6236dae4SAndroid Build Coastguard Worker gtls_send, /* send data to encrypt */
2292*6236dae4SAndroid Build Coastguard Worker NULL, /* get_channel_binding */
2293*6236dae4SAndroid Build Coastguard Worker };
2294*6236dae4SAndroid Build Coastguard Worker
2295*6236dae4SAndroid Build Coastguard Worker #endif /* USE_GNUTLS */
2296