Absolute File Name: | /home/opencoverage/opencoverage/guest-scripts/libressl/src/tls/tls.c |
Source code | Switch to Preprocessed file |
Line | Source | Count | ||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
1 | /* $OpenBSD: tls.c,v 1.80 2018/04/07 16:30:59 jsing Exp $ */ | - | ||||||||||||
2 | /* | - | ||||||||||||
3 | * Copyright (c) 2014 Joel Sing <jsing@openbsd.org> | - | ||||||||||||
4 | * | - | ||||||||||||
5 | * Permission to use, copy, modify, and distribute this software for any | - | ||||||||||||
6 | * purpose with or without fee is hereby granted, provided that the above | - | ||||||||||||
7 | * copyright notice and this permission notice appear in all copies. | - | ||||||||||||
8 | * | - | ||||||||||||
9 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES | - | ||||||||||||
10 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF | - | ||||||||||||
11 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR | - | ||||||||||||
12 | * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES | - | ||||||||||||
13 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN | - | ||||||||||||
14 | * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF | - | ||||||||||||
15 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | - | ||||||||||||
16 | */ | - | ||||||||||||
17 | - | |||||||||||||
18 | #include <sys/socket.h> | - | ||||||||||||
19 | - | |||||||||||||
20 | #include <errno.h> | - | ||||||||||||
21 | #include <limits.h> | - | ||||||||||||
22 | #include <pthread.h> | - | ||||||||||||
23 | #include <stdlib.h> | - | ||||||||||||
24 | #include <unistd.h> | - | ||||||||||||
25 | - | |||||||||||||
26 | #include <openssl/bio.h> | - | ||||||||||||
27 | #include <openssl/err.h> | - | ||||||||||||
28 | #include <openssl/evp.h> | - | ||||||||||||
29 | #include <openssl/pem.h> | - | ||||||||||||
30 | #include <openssl/safestack.h> | - | ||||||||||||
31 | #include <openssl/ssl.h> | - | ||||||||||||
32 | #include <openssl/x509.h> | - | ||||||||||||
33 | - | |||||||||||||
34 | #include <tls.h> | - | ||||||||||||
35 | #include "tls_internal.h" | - | ||||||||||||
36 | - | |||||||||||||
37 | static struct tls_config *tls_config_default; | - | ||||||||||||
38 | - | |||||||||||||
39 | static int tls_init_rv = -1; | - | ||||||||||||
40 | - | |||||||||||||
41 | static void | - | ||||||||||||
42 | tls_do_init(void) | - | ||||||||||||
43 | { | - | ||||||||||||
44 | OPENSSL_init_ssl(OPENSSL_INIT_NO_LOAD_CONFIG, NULL); | - | ||||||||||||
45 | - | |||||||||||||
46 | if (BIO_sock_init() != 1)
| 0-3 | ||||||||||||
47 | return; never executed: return; | 0 | ||||||||||||
48 | - | |||||||||||||
49 | if ((tls_config_default = tls_config_new_internal()) == NULL)
| 0-3 | ||||||||||||
50 | return; never executed: return; | 0 | ||||||||||||
51 | - | |||||||||||||
52 | tls_config_default->refcount++; | - | ||||||||||||
53 | - | |||||||||||||
54 | tls_init_rv = 0; | - | ||||||||||||
55 | } executed 3 times by 3 tests: end of block Executed by:
| 3 | ||||||||||||
56 | - | |||||||||||||
57 | int | - | ||||||||||||
58 | tls_init(void) | - | ||||||||||||
59 | { | - | ||||||||||||
60 | static pthread_once_t once = PTHREAD_ONCE_INIT; | - | ||||||||||||
61 | - | |||||||||||||
62 | if (pthread_once(&once, tls_do_init) != 0)
| 0-38 | ||||||||||||
63 | return -1; never executed: return -1; | 0 | ||||||||||||
64 | - | |||||||||||||
65 | return tls_init_rv; executed 38 times by 3 tests: return tls_init_rv; Executed by:
| 38 | ||||||||||||
66 | } | - | ||||||||||||
67 | - | |||||||||||||
68 | const char * | - | ||||||||||||
69 | tls_error(struct tls *ctx) | - | ||||||||||||
70 | { | - | ||||||||||||
71 | return ctx->error.msg; never executed: return ctx->error.msg; | 0 | ||||||||||||
72 | } | - | ||||||||||||
73 | - | |||||||||||||
74 | void | - | ||||||||||||
75 | tls_error_clear(struct tls_error *error) | - | ||||||||||||
76 | { | - | ||||||||||||
77 | free(error->msg); | - | ||||||||||||
78 | error->msg = NULL; | - | ||||||||||||
79 | error->num = 0; | - | ||||||||||||
80 | error->tls = 0; | - | ||||||||||||
81 | } executed 53 times by 2 tests: end of block Executed by:
| 53 | ||||||||||||
82 | - | |||||||||||||
83 | static int | - | ||||||||||||
84 | tls_error_vset(struct tls_error *error, int errnum, const char *fmt, va_list ap) | - | ||||||||||||
85 | { | - | ||||||||||||
86 | char *errmsg = NULL; | - | ||||||||||||
87 | int rv = -1; | - | ||||||||||||
88 | - | |||||||||||||
89 | tls_error_clear(error); | - | ||||||||||||
90 | - | |||||||||||||
91 | error->num = errnum; | - | ||||||||||||
92 | error->tls = 1; | - | ||||||||||||
93 | - | |||||||||||||
94 | if (vasprintf(&errmsg, fmt, ap) == -1) {
| 0-14 | ||||||||||||
95 | errmsg = NULL; | - | ||||||||||||
96 | goto err; never executed: goto err; | 0 | ||||||||||||
97 | } | - | ||||||||||||
98 | - | |||||||||||||
99 | if (errnum == -1) {
| 0-14 | ||||||||||||
100 | error->msg = errmsg; | - | ||||||||||||
101 | return (0); executed 14 times by 2 tests: return (0); Executed by:
| 14 | ||||||||||||
102 | } | - | ||||||||||||
103 | - | |||||||||||||
104 | if (asprintf(&error->msg, "%s: %s", errmsg, strerror(errnum)) == -1) {
| 0 | ||||||||||||
105 | error->msg = NULL; | - | ||||||||||||
106 | goto err; never executed: goto err; | 0 | ||||||||||||
107 | } | - | ||||||||||||
108 | rv = 0; | - | ||||||||||||
109 | - | |||||||||||||
110 | err: code before this statement never executed: err: | 0 | ||||||||||||
111 | free(errmsg); | - | ||||||||||||
112 | - | |||||||||||||
113 | return (rv); never executed: return (rv); | 0 | ||||||||||||
114 | } | - | ||||||||||||
115 | - | |||||||||||||
116 | int | - | ||||||||||||
117 | tls_error_set(struct tls_error *error, const char *fmt, ...) | - | ||||||||||||
118 | { | - | ||||||||||||
119 | va_list ap; | - | ||||||||||||
120 | int errnum, rv; | - | ||||||||||||
121 | - | |||||||||||||
122 | errnum = errno; | - | ||||||||||||
123 | - | |||||||||||||
124 | va_start(ap, fmt); | - | ||||||||||||
125 | rv = tls_error_vset(error, errnum, fmt, ap); | - | ||||||||||||
126 | va_end(ap); | - | ||||||||||||
127 | - | |||||||||||||
128 | return (rv); never executed: return (rv); | 0 | ||||||||||||
129 | } | - | ||||||||||||
130 | - | |||||||||||||
131 | int | - | ||||||||||||
132 | tls_error_setx(struct tls_error *error, const char *fmt, ...) | - | ||||||||||||
133 | { | - | ||||||||||||
134 | va_list ap; | - | ||||||||||||
135 | int rv; | - | ||||||||||||
136 | - | |||||||||||||
137 | va_start(ap, fmt); | - | ||||||||||||
138 | rv = tls_error_vset(error, -1, fmt, ap); | - | ||||||||||||
139 | va_end(ap); | - | ||||||||||||
140 | - | |||||||||||||
141 | return (rv); never executed: return (rv); | 0 | ||||||||||||
142 | } | - | ||||||||||||
143 | - | |||||||||||||
144 | int | - | ||||||||||||
145 | tls_config_set_error(struct tls_config *config, const char *fmt, ...) | - | ||||||||||||
146 | { | - | ||||||||||||
147 | va_list ap; | - | ||||||||||||
148 | int errnum, rv; | - | ||||||||||||
149 | - | |||||||||||||
150 | errnum = errno; | - | ||||||||||||
151 | - | |||||||||||||
152 | va_start(ap, fmt); | - | ||||||||||||
153 | rv = tls_error_vset(&config->error, errnum, fmt, ap); | - | ||||||||||||
154 | va_end(ap); | - | ||||||||||||
155 | - | |||||||||||||
156 | return (rv); never executed: return (rv); | 0 | ||||||||||||
157 | } | - | ||||||||||||
158 | - | |||||||||||||
159 | int | - | ||||||||||||
160 | tls_config_set_errorx(struct tls_config *config, const char *fmt, ...) | - | ||||||||||||
161 | { | - | ||||||||||||
162 | va_list ap; | - | ||||||||||||
163 | int rv; | - | ||||||||||||
164 | - | |||||||||||||
165 | va_start(ap, fmt); | - | ||||||||||||
166 | rv = tls_error_vset(&config->error, -1, fmt, ap); | - | ||||||||||||
167 | va_end(ap); | - | ||||||||||||
168 | - | |||||||||||||
169 | return (rv); never executed: return (rv); | 0 | ||||||||||||
170 | } | - | ||||||||||||
171 | - | |||||||||||||
172 | int | - | ||||||||||||
173 | tls_set_error(struct tls *ctx, const char *fmt, ...) | - | ||||||||||||
174 | { | - | ||||||||||||
175 | va_list ap; | - | ||||||||||||
176 | int errnum, rv; | - | ||||||||||||
177 | - | |||||||||||||
178 | errnum = errno; | - | ||||||||||||
179 | - | |||||||||||||
180 | va_start(ap, fmt); | - | ||||||||||||
181 | rv = tls_error_vset(&ctx->error, errnum, fmt, ap); | - | ||||||||||||
182 | va_end(ap); | - | ||||||||||||
183 | - | |||||||||||||
184 | return (rv); never executed: return (rv); | 0 | ||||||||||||
185 | } | - | ||||||||||||
186 | - | |||||||||||||
187 | int | - | ||||||||||||
188 | tls_set_errorx(struct tls *ctx, const char *fmt, ...) | - | ||||||||||||
189 | { | - | ||||||||||||
190 | va_list ap; | - | ||||||||||||
191 | int rv; | - | ||||||||||||
192 | - | |||||||||||||
193 | va_start(ap, fmt); | - | ||||||||||||
194 | rv = tls_error_vset(&ctx->error, -1, fmt, ap); | - | ||||||||||||
195 | va_end(ap); | - | ||||||||||||
196 | - | |||||||||||||
197 | return (rv); executed 14 times by 2 tests: return (rv); Executed by:
| 14 | ||||||||||||
198 | } | - | ||||||||||||
199 | - | |||||||||||||
200 | int | - | ||||||||||||
201 | tls_set_ssl_errorx(struct tls *ctx, const char *fmt, ...) | - | ||||||||||||
202 | { | - | ||||||||||||
203 | va_list ap; | - | ||||||||||||
204 | int rv; | - | ||||||||||||
205 | - | |||||||||||||
206 | /* Only set an error if a more specific one does not already exist. */ | - | ||||||||||||
207 | if (ctx->error.tls != 0)
| 0 | ||||||||||||
208 | return (0); never executed: return (0); | 0 | ||||||||||||
209 | - | |||||||||||||
210 | va_start(ap, fmt); | - | ||||||||||||
211 | rv = tls_error_vset(&ctx->error, -1, fmt, ap); | - | ||||||||||||
212 | va_end(ap); | - | ||||||||||||
213 | - | |||||||||||||
214 | return (rv); never executed: return (rv); | 0 | ||||||||||||
215 | } | - | ||||||||||||
216 | - | |||||||||||||
217 | struct tls_sni_ctx * | - | ||||||||||||
218 | tls_sni_ctx_new(void) | - | ||||||||||||
219 | { | - | ||||||||||||
220 | return (calloc(1, sizeof(struct tls_sni_ctx))); never executed: return (calloc(1, sizeof(struct tls_sni_ctx))); | 0 | ||||||||||||
221 | } | - | ||||||||||||
222 | - | |||||||||||||
223 | void | - | ||||||||||||
224 | tls_sni_ctx_free(struct tls_sni_ctx *sni_ctx) | - | ||||||||||||
225 | { | - | ||||||||||||
226 | if (sni_ctx == NULL)
| 0 | ||||||||||||
227 | return; never executed: return; | 0 | ||||||||||||
228 | - | |||||||||||||
229 | SSL_CTX_free(sni_ctx->ssl_ctx); | - | ||||||||||||
230 | X509_free(sni_ctx->ssl_cert); | - | ||||||||||||
231 | - | |||||||||||||
232 | free(sni_ctx); | - | ||||||||||||
233 | } never executed: end of block | 0 | ||||||||||||
234 | - | |||||||||||||
235 | struct tls * | - | ||||||||||||
236 | tls_new(void) | - | ||||||||||||
237 | { | - | ||||||||||||
238 | struct tls *ctx; | - | ||||||||||||
239 | - | |||||||||||||
240 | if ((ctx = calloc(1, sizeof(*ctx))) == NULL)
| 0-36 | ||||||||||||
241 | return (NULL); never executed: return ( ((void *)0) ); | 0 | ||||||||||||
242 | - | |||||||||||||
243 | tls_reset(ctx); | - | ||||||||||||
244 | - | |||||||||||||
245 | if (tls_configure(ctx, tls_config_default) == -1) {
| 0-36 | ||||||||||||
246 | free(ctx); | - | ||||||||||||
247 | return NULL; never executed: return ((void *)0) ; | 0 | ||||||||||||
248 | } | - | ||||||||||||
249 | - | |||||||||||||
250 | return (ctx); executed 36 times by 2 tests: return (ctx); Executed by:
| 36 | ||||||||||||
251 | } | - | ||||||||||||
252 | - | |||||||||||||
253 | int | - | ||||||||||||
254 | tls_configure(struct tls *ctx, struct tls_config *config) | - | ||||||||||||
255 | { | - | ||||||||||||
256 | if (config == NULL)
| 0-44 | ||||||||||||
257 | config = tls_config_default; never executed: config = tls_config_default; | 0 | ||||||||||||
258 | - | |||||||||||||
259 | config->refcount++; | - | ||||||||||||
260 | - | |||||||||||||
261 | tls_config_free(ctx->config); | - | ||||||||||||
262 | - | |||||||||||||
263 | ctx->config = config; | - | ||||||||||||
264 | ctx->keypair = config->keypair; | - | ||||||||||||
265 | - | |||||||||||||
266 | if ((ctx->flags & TLS_SERVER) != 0)
| 4-40 | ||||||||||||
267 | return (tls_configure_server(ctx)); executed 4 times by 1 test: return (tls_configure_server(ctx)); Executed by:
| 4 | ||||||||||||
268 | - | |||||||||||||
269 | return (0); executed 40 times by 2 tests: return (0); Executed by:
| 40 | ||||||||||||
270 | } | - | ||||||||||||
271 | - | |||||||||||||
272 | int | - | ||||||||||||
273 | tls_cert_hash(X509 *cert, char **hash) | - | ||||||||||||
274 | { | - | ||||||||||||
275 | char d[EVP_MAX_MD_SIZE], *dhex = NULL; | - | ||||||||||||
276 | int dlen, rv = -1; | - | ||||||||||||
277 | - | |||||||||||||
278 | free(*hash); | - | ||||||||||||
279 | *hash = NULL; | - | ||||||||||||
280 | - | |||||||||||||
281 | if (X509_digest(cert, EVP_sha256(), d, &dlen) != 1)
| 0-4 | ||||||||||||
282 | goto err; never executed: goto err; | 0 | ||||||||||||
283 | - | |||||||||||||
284 | if (tls_hex_string(d, dlen, &dhex, NULL) != 0)
| 0-4 | ||||||||||||
285 | goto err; never executed: goto err; | 0 | ||||||||||||
286 | - | |||||||||||||
287 | if (asprintf(hash, "SHA256:%s", dhex) == -1) {
| 0-4 | ||||||||||||
288 | *hash = NULL; | - | ||||||||||||
289 | goto err; never executed: goto err; | 0 | ||||||||||||
290 | } | - | ||||||||||||
291 | - | |||||||||||||
292 | rv = 0; | - | ||||||||||||
293 | err: code before this statement executed 4 times by 1 test: err: Executed by:
| 4 | ||||||||||||
294 | free(dhex); | - | ||||||||||||
295 | - | |||||||||||||
296 | return (rv); executed 4 times by 1 test: return (rv); Executed by:
| 4 | ||||||||||||
297 | } | - | ||||||||||||
298 | - | |||||||||||||
299 | int | - | ||||||||||||
300 | tls_cert_pubkey_hash(X509 *cert, char **hash) | - | ||||||||||||
301 | { | - | ||||||||||||
302 | char d[EVP_MAX_MD_SIZE], *dhex = NULL; | - | ||||||||||||
303 | int dlen, rv = -1; | - | ||||||||||||
304 | - | |||||||||||||
305 | free(*hash); | - | ||||||||||||
306 | *hash = NULL; | - | ||||||||||||
307 | - | |||||||||||||
308 | if (X509_pubkey_digest(cert, EVP_sha256(), d, &dlen) != 1)
| 0-4 | ||||||||||||
309 | goto err; never executed: goto err; | 0 | ||||||||||||
310 | - | |||||||||||||
311 | if (tls_hex_string(d, dlen, &dhex, NULL) != 0)
| 0-4 | ||||||||||||
312 | goto err; never executed: goto err; | 0 | ||||||||||||
313 | - | |||||||||||||
314 | if (asprintf(hash, "SHA256:%s", dhex) == -1) {
| 0-4 | ||||||||||||
315 | *hash = NULL; | - | ||||||||||||
316 | goto err; never executed: goto err; | 0 | ||||||||||||
317 | } | - | ||||||||||||
318 | - | |||||||||||||
319 | rv = 0; | - | ||||||||||||
320 | - | |||||||||||||
321 | err: code before this statement executed 4 times by 2 tests: err: Executed by:
| 4 | ||||||||||||
322 | free(dhex); | - | ||||||||||||
323 | - | |||||||||||||
324 | return (rv); executed 4 times by 2 tests: return (rv); Executed by:
| 4 | ||||||||||||
325 | } | - | ||||||||||||
326 | - | |||||||||||||
327 | int | - | ||||||||||||
328 | tls_configure_ssl_keypair(struct tls *ctx, SSL_CTX *ssl_ctx, | - | ||||||||||||
329 | struct tls_keypair *keypair, int required) | - | ||||||||||||
330 | { | - | ||||||||||||
331 | EVP_PKEY *pkey = NULL; | - | ||||||||||||
332 | BIO *bio = NULL; | - | ||||||||||||
333 | - | |||||||||||||
334 | if (!required &&
| 4 | ||||||||||||
335 | keypair->cert_mem == NULL &&
| 0-4 | ||||||||||||
336 | keypair->key_mem == NULL)
| 0-4 | ||||||||||||
337 | return(0); executed 4 times by 1 test: return(0); Executed by:
| 4 | ||||||||||||
338 | - | |||||||||||||
339 | if (keypair->cert_mem != NULL) {
| 0-4 | ||||||||||||
340 | if (keypair->cert_len > INT_MAX) {
| 0-4 | ||||||||||||
341 | tls_set_errorx(ctx, "certificate too long"); | - | ||||||||||||
342 | goto err; never executed: goto err; | 0 | ||||||||||||
343 | } | - | ||||||||||||
344 | - | |||||||||||||
345 | if (SSL_CTX_use_certificate_chain_mem(ssl_ctx,
| 0-4 | ||||||||||||
346 | keypair->cert_mem, keypair->cert_len) != 1) {
| 0-4 | ||||||||||||
347 | tls_set_errorx(ctx, "failed to load certificate"); | - | ||||||||||||
348 | goto err; never executed: goto err; | 0 | ||||||||||||
349 | } | - | ||||||||||||
350 | } executed 4 times by 1 test: end of block Executed by:
| 4 | ||||||||||||
351 | - | |||||||||||||
352 | if (keypair->key_mem != NULL) {
| 0-4 | ||||||||||||
353 | if (keypair->key_len > INT_MAX) {
| 0-4 | ||||||||||||
354 | tls_set_errorx(ctx, "key too long"); | - | ||||||||||||
355 | goto err; never executed: goto err; | 0 | ||||||||||||
356 | } | - | ||||||||||||
357 | - | |||||||||||||
358 | if ((bio = BIO_new_mem_buf(keypair->key_mem,
| 0-4 | ||||||||||||
359 | keypair->key_len)) == NULL) {
| 0-4 | ||||||||||||
360 | tls_set_errorx(ctx, "failed to create buffer"); | - | ||||||||||||
361 | goto err; never executed: goto err; | 0 | ||||||||||||
362 | } | - | ||||||||||||
363 | if ((pkey = PEM_read_bio_PrivateKey(bio, NULL, tls_password_cb,
| 0-4 | ||||||||||||
364 | NULL)) == NULL) {
| 0-4 | ||||||||||||
365 | tls_set_errorx(ctx, "failed to read private key"); | - | ||||||||||||
366 | goto err; never executed: goto err; | 0 | ||||||||||||
367 | } | - | ||||||||||||
368 | - | |||||||||||||
369 | if (keypair->pubkey_hash != NULL) {
| 0-4 | ||||||||||||
370 | RSA *rsa; | - | ||||||||||||
371 | /* XXX only RSA for now for relayd privsep */ | - | ||||||||||||
372 | if ((rsa = EVP_PKEY_get1_RSA(pkey)) != NULL) {
| 0-4 | ||||||||||||
373 | RSA_set_ex_data(rsa, 0, keypair->pubkey_hash); | - | ||||||||||||
374 | RSA_free(rsa); | - | ||||||||||||
375 | } executed 4 times by 1 test: end of block Executed by:
| 4 | ||||||||||||
376 | } executed 4 times by 1 test: end of block Executed by:
| 4 | ||||||||||||
377 | - | |||||||||||||
378 | if (SSL_CTX_use_PrivateKey(ssl_ctx, pkey) != 1) {
| 0-4 | ||||||||||||
379 | tls_set_errorx(ctx, "failed to load private key"); | - | ||||||||||||
380 | goto err; never executed: goto err; | 0 | ||||||||||||
381 | } | - | ||||||||||||
382 | BIO_free(bio); | - | ||||||||||||
383 | bio = NULL; | - | ||||||||||||
384 | EVP_PKEY_free(pkey); | - | ||||||||||||
385 | pkey = NULL; | - | ||||||||||||
386 | } executed 4 times by 1 test: end of block Executed by:
| 4 | ||||||||||||
387 | - | |||||||||||||
388 | if (!ctx->config->skip_private_key_check &&
| 0-4 | ||||||||||||
389 | SSL_CTX_check_private_key(ssl_ctx) != 1) {
| 0-4 | ||||||||||||
390 | tls_set_errorx(ctx, "private/public key mismatch"); | - | ||||||||||||
391 | goto err; never executed: goto err; | 0 | ||||||||||||
392 | } | - | ||||||||||||
393 | - | |||||||||||||
394 | return (0); executed 4 times by 1 test: return (0); Executed by:
| 4 | ||||||||||||
395 | - | |||||||||||||
396 | err: | - | ||||||||||||
397 | EVP_PKEY_free(pkey); | - | ||||||||||||
398 | BIO_free(bio); | - | ||||||||||||
399 | - | |||||||||||||
400 | return (1); never executed: return (1); | 0 | ||||||||||||
401 | } | - | ||||||||||||
402 | - | |||||||||||||
403 | int | - | ||||||||||||
404 | tls_configure_ssl(struct tls *ctx, SSL_CTX *ssl_ctx) | - | ||||||||||||
405 | { | - | ||||||||||||
406 | SSL_CTX_set_mode(ssl_ctx, SSL_MODE_ENABLE_PARTIAL_WRITE); | - | ||||||||||||
407 | SSL_CTX_set_mode(ssl_ctx, SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER); | - | ||||||||||||
408 | - | |||||||||||||
409 | SSL_CTX_set_options(ssl_ctx, SSL_OP_NO_SSLv2); | - | ||||||||||||
410 | SSL_CTX_set_options(ssl_ctx, SSL_OP_NO_SSLv3); | - | ||||||||||||
411 | - | |||||||||||||
412 | SSL_CTX_clear_options(ssl_ctx, SSL_OP_NO_TLSv1); | - | ||||||||||||
413 | SSL_CTX_clear_options(ssl_ctx, SSL_OP_NO_TLSv1_1); | - | ||||||||||||
414 | SSL_CTX_clear_options(ssl_ctx, SSL_OP_NO_TLSv1_2); | - | ||||||||||||
415 | - | |||||||||||||
416 | if ((ctx->config->protocols & TLS_PROTOCOL_TLSv1_0) == 0)
| 0-8 | ||||||||||||
417 | SSL_CTX_set_options(ssl_ctx, SSL_OP_NO_TLSv1); executed 8 times by 1 test: SSL_CTX_ctrl((ssl_ctx),32,(0x04000000L), ((void *)0) ); Executed by:
| 8 | ||||||||||||
418 | if ((ctx->config->protocols & TLS_PROTOCOL_TLSv1_1) == 0)
| 0-8 | ||||||||||||
419 | SSL_CTX_set_options(ssl_ctx, SSL_OP_NO_TLSv1_1); executed 8 times by 1 test: SSL_CTX_ctrl((ssl_ctx),32,(0x10000000L), ((void *)0) ); Executed by:
| 8 | ||||||||||||
420 | if ((ctx->config->protocols & TLS_PROTOCOL_TLSv1_2) == 0)
| 0-8 | ||||||||||||
421 | SSL_CTX_set_options(ssl_ctx, SSL_OP_NO_TLSv1_2); never executed: SSL_CTX_ctrl((ssl_ctx),32,(0x08000000L), ((void *)0) ); | 0 | ||||||||||||
422 | - | |||||||||||||
423 | if (ctx->config->alpn != NULL) {
| 0-8 | ||||||||||||
424 | if (SSL_CTX_set_alpn_protos(ssl_ctx, ctx->config->alpn,
| 0 | ||||||||||||
425 | ctx->config->alpn_len) != 0) {
| 0 | ||||||||||||
426 | tls_set_errorx(ctx, "failed to set alpn"); | - | ||||||||||||
427 | goto err; never executed: goto err; | 0 | ||||||||||||
428 | } | - | ||||||||||||
429 | } never executed: end of block | 0 | ||||||||||||
430 | - | |||||||||||||
431 | if (ctx->config->ciphers != NULL) {
| 0-8 | ||||||||||||
432 | if (SSL_CTX_set_cipher_list(ssl_ctx,
| 0-8 | ||||||||||||
433 | ctx->config->ciphers) != 1) {
| 0-8 | ||||||||||||
434 | tls_set_errorx(ctx, "failed to set ciphers"); | - | ||||||||||||
435 | goto err; never executed: goto err; | 0 | ||||||||||||
436 | } | - | ||||||||||||
437 | } executed 8 times by 1 test: end of block Executed by:
| 8 | ||||||||||||
438 | - | |||||||||||||
439 | if (ctx->config->verify_time == 0) {
| 0-8 | ||||||||||||
440 | X509_VERIFY_PARAM_set_flags(ssl_ctx->param, | - | ||||||||||||
441 | X509_V_FLAG_NO_CHECK_TIME); | - | ||||||||||||
442 | } never executed: end of block | 0 | ||||||||||||
443 | - | |||||||||||||
444 | /* Disable any form of session caching by default */ | - | ||||||||||||
445 | SSL_CTX_set_session_cache_mode(ssl_ctx, SSL_SESS_CACHE_OFF); | - | ||||||||||||
446 | SSL_CTX_set_options(ssl_ctx, SSL_OP_NO_TICKET); | - | ||||||||||||
447 | - | |||||||||||||
448 | return (0); executed 8 times by 1 test: return (0); Executed by:
| 8 | ||||||||||||
449 | - | |||||||||||||
450 | err: | - | ||||||||||||
451 | return (-1); never executed: return (-1); | 0 | ||||||||||||
452 | } | - | ||||||||||||
453 | - | |||||||||||||
454 | static int | - | ||||||||||||
455 | tls_ssl_cert_verify_cb(X509_STORE_CTX *x509_ctx, void *arg) | - | ||||||||||||
456 | { | - | ||||||||||||
457 | struct tls *ctx = arg; | - | ||||||||||||
458 | int x509_err; | - | ||||||||||||
459 | - | |||||||||||||
460 | if (ctx->config->verify_cert == 0)
| 0-4 | ||||||||||||
461 | return (1); never executed: return (1); | 0 | ||||||||||||
462 | - | |||||||||||||
463 | if ((X509_verify_cert(x509_ctx)) < 0) {
| 0-4 | ||||||||||||
464 | tls_set_errorx(ctx, "X509 verify cert failed"); | - | ||||||||||||
465 | return (0); never executed: return (0); | 0 | ||||||||||||
466 | } | - | ||||||||||||
467 | - | |||||||||||||
468 | x509_err = X509_STORE_CTX_get_error(x509_ctx); | - | ||||||||||||
469 | if (x509_err == X509_V_OK)
| 0-4 | ||||||||||||
470 | return (1); executed 4 times by 1 test: return (1); Executed by:
| 4 | ||||||||||||
471 | - | |||||||||||||
472 | tls_set_errorx(ctx, "certificate verification failed: %s", | - | ||||||||||||
473 | X509_verify_cert_error_string(x509_err)); | - | ||||||||||||
474 | - | |||||||||||||
475 | return (0); never executed: return (0); | 0 | ||||||||||||
476 | } | - | ||||||||||||
477 | - | |||||||||||||
478 | int | - | ||||||||||||
479 | tls_configure_ssl_verify(struct tls *ctx, SSL_CTX *ssl_ctx, int verify) | - | ||||||||||||
480 | { | - | ||||||||||||
481 | size_t ca_len = ctx->config->ca_len; | - | ||||||||||||
482 | char *ca_mem = ctx->config->ca_mem; | - | ||||||||||||
483 | char *crl_mem = ctx->config->crl_mem; | - | ||||||||||||
484 | size_t crl_len = ctx->config->crl_len; | - | ||||||||||||
485 | char *ca_free = NULL; | - | ||||||||||||
486 | STACK_OF(X509_INFO) *xis = NULL; | - | ||||||||||||
487 | X509_STORE *store; | - | ||||||||||||
488 | X509_INFO *xi; | - | ||||||||||||
489 | BIO *bio = NULL; | - | ||||||||||||
490 | int rv = -1; | - | ||||||||||||
491 | int i; | - | ||||||||||||
492 | - | |||||||||||||
493 | SSL_CTX_set_verify(ssl_ctx, verify, NULL); | - | ||||||||||||
494 | SSL_CTX_set_cert_verify_callback(ssl_ctx, tls_ssl_cert_verify_cb, ctx); | - | ||||||||||||
495 | - | |||||||||||||
496 | if (ctx->config->verify_depth >= 0)
| 0-4 | ||||||||||||
497 | SSL_CTX_set_verify_depth(ssl_ctx, ctx->config->verify_depth); executed 4 times by 1 test: SSL_CTX_set_verify_depth(ssl_ctx, ctx->config->verify_depth); Executed by:
| 4 | ||||||||||||
498 | - | |||||||||||||
499 | if (ctx->config->verify_cert == 0)
| 0-4 | ||||||||||||
500 | goto done; never executed: goto done; | 0 | ||||||||||||
501 | - | |||||||||||||
502 | /* If no CA has been specified, attempt to load the default. */ | - | ||||||||||||
503 | if (ctx->config->ca_mem == NULL && ctx->config->ca_path == NULL) {
| 0-4 | ||||||||||||
504 | if (tls_config_load_file(&ctx->error, "CA", _PATH_SSL_CA_FILE,
| 0 | ||||||||||||
505 | &ca_mem, &ca_len) != 0)
| 0 | ||||||||||||
506 | goto err; never executed: goto err; | 0 | ||||||||||||
507 | ca_free = ca_mem; | - | ||||||||||||
508 | } never executed: end of block | 0 | ||||||||||||
509 | - | |||||||||||||
510 | if (ca_mem != NULL) {
| 0-4 | ||||||||||||
511 | if (ca_len > INT_MAX) {
| 0-4 | ||||||||||||
512 | tls_set_errorx(ctx, "ca too long"); | - | ||||||||||||
513 | goto err; never executed: goto err; | 0 | ||||||||||||
514 | } | - | ||||||||||||
515 | if (SSL_CTX_load_verify_mem(ssl_ctx, ca_mem, ca_len) != 1) {
| 0-4 | ||||||||||||
516 | tls_set_errorx(ctx, "ssl verify memory setup failure"); | - | ||||||||||||
517 | goto err; never executed: goto err; | 0 | ||||||||||||
518 | } | - | ||||||||||||
519 | } else if (SSL_CTX_load_verify_locations(ssl_ctx, NULL, executed 4 times by 1 test: end of block Executed by:
| 0-4 | ||||||||||||
520 | ctx->config->ca_path) != 1) {
| 0 | ||||||||||||
521 | tls_set_errorx(ctx, "ssl verify locations failure"); | - | ||||||||||||
522 | goto err; never executed: goto err; | 0 | ||||||||||||
523 | } | - | ||||||||||||
524 | - | |||||||||||||
525 | if (crl_mem != NULL) {
| 0-4 | ||||||||||||
526 | if (crl_len > INT_MAX) {
| 0 | ||||||||||||
527 | tls_set_errorx(ctx, "crl too long"); | - | ||||||||||||
528 | goto err; never executed: goto err; | 0 | ||||||||||||
529 | } | - | ||||||||||||
530 | if ((bio = BIO_new_mem_buf(crl_mem, crl_len)) == NULL) {
| 0 | ||||||||||||
531 | tls_set_errorx(ctx, "failed to create buffer"); | - | ||||||||||||
532 | goto err; never executed: goto err; | 0 | ||||||||||||
533 | } | - | ||||||||||||
534 | if ((xis = PEM_X509_INFO_read_bio(bio, NULL, tls_password_cb,
| 0 | ||||||||||||
535 | NULL)) == NULL) {
| 0 | ||||||||||||
536 | tls_set_errorx(ctx, "failed to parse crl"); | - | ||||||||||||
537 | goto err; never executed: goto err; | 0 | ||||||||||||
538 | } | - | ||||||||||||
539 | store = SSL_CTX_get_cert_store(ssl_ctx); | - | ||||||||||||
540 | for (i = 0; i < sk_X509_INFO_num(xis); i++) {
| 0 | ||||||||||||
541 | xi = sk_X509_INFO_value(xis, i); | - | ||||||||||||
542 | if (xi->crl == NULL)
| 0 | ||||||||||||
543 | continue; never executed: continue; | 0 | ||||||||||||
544 | if (!X509_STORE_add_crl(store, xi->crl)) {
| 0 | ||||||||||||
545 | tls_set_error(ctx, "failed to add crl"); | - | ||||||||||||
546 | goto err; never executed: goto err; | 0 | ||||||||||||
547 | } | - | ||||||||||||
548 | xi->crl = NULL; | - | ||||||||||||
549 | } never executed: end of block | 0 | ||||||||||||
550 | X509_VERIFY_PARAM_set_flags(store->param, | - | ||||||||||||
551 | X509_V_FLAG_CRL_CHECK | X509_V_FLAG_CRL_CHECK_ALL); | - | ||||||||||||
552 | } never executed: end of block | 0 | ||||||||||||
553 | - | |||||||||||||
554 | done: code before this statement executed 4 times by 1 test: done: Executed by:
| 4 | ||||||||||||
555 | rv = 0; | - | ||||||||||||
556 | - | |||||||||||||
557 | err: code before this statement executed 4 times by 1 test: err: Executed by:
| 4 | ||||||||||||
558 | sk_X509_INFO_pop_free(xis, X509_INFO_free); | - | ||||||||||||
559 | BIO_free(bio); | - | ||||||||||||
560 | free(ca_free); | - | ||||||||||||
561 | - | |||||||||||||
562 | return (rv); executed 4 times by 1 test: return (rv); Executed by:
| 4 | ||||||||||||
563 | } | - | ||||||||||||
564 | - | |||||||||||||
565 | void | - | ||||||||||||
566 | tls_free(struct tls *ctx) | - | ||||||||||||
567 | { | - | ||||||||||||
568 | if (ctx == NULL)
| 0-36 | ||||||||||||
569 | return; never executed: return; | 0 | ||||||||||||
570 | - | |||||||||||||
571 | tls_reset(ctx); | - | ||||||||||||
572 | - | |||||||||||||
573 | free(ctx); | - | ||||||||||||
574 | } executed 36 times by 2 tests: end of block Executed by:
| 36 | ||||||||||||
575 | - | |||||||||||||
576 | void | - | ||||||||||||
577 | tls_reset(struct tls *ctx) | - | ||||||||||||
578 | { | - | ||||||||||||
579 | struct tls_sni_ctx *sni, *nsni; | - | ||||||||||||
580 | - | |||||||||||||
581 | tls_config_free(ctx->config); | - | ||||||||||||
582 | ctx->config = NULL; | - | ||||||||||||
583 | - | |||||||||||||
584 | SSL_CTX_free(ctx->ssl_ctx); | - | ||||||||||||
585 | SSL_free(ctx->ssl_conn); | - | ||||||||||||
586 | X509_free(ctx->ssl_peer_cert); | - | ||||||||||||
587 | - | |||||||||||||
588 | ctx->ssl_conn = NULL; | - | ||||||||||||
589 | ctx->ssl_ctx = NULL; | - | ||||||||||||
590 | ctx->ssl_peer_cert = NULL; | - | ||||||||||||
591 | /* X509 objects in chain are freed with the SSL */ | - | ||||||||||||
592 | ctx->ssl_peer_chain = NULL; | - | ||||||||||||
593 | - | |||||||||||||
594 | ctx->socket = -1; | - | ||||||||||||
595 | ctx->state = 0; | - | ||||||||||||
596 | - | |||||||||||||
597 | free(ctx->servername); | - | ||||||||||||
598 | ctx->servername = NULL; | - | ||||||||||||
599 | - | |||||||||||||
600 | free(ctx->error.msg); | - | ||||||||||||
601 | ctx->error.msg = NULL; | - | ||||||||||||
602 | ctx->error.num = -1; | - | ||||||||||||
603 | - | |||||||||||||
604 | tls_conninfo_free(ctx->conninfo); | - | ||||||||||||
605 | ctx->conninfo = NULL; | - | ||||||||||||
606 | - | |||||||||||||
607 | tls_ocsp_free(ctx->ocsp); | - | ||||||||||||
608 | ctx->ocsp = NULL; | - | ||||||||||||
609 | - | |||||||||||||
610 | for (sni = ctx->sni_ctx; sni != NULL; sni = nsni) {
| 0-78 | ||||||||||||
611 | nsni = sni->next; | - | ||||||||||||
612 | tls_sni_ctx_free(sni); | - | ||||||||||||
613 | } never executed: end of block | 0 | ||||||||||||
614 | ctx->sni_ctx = NULL; | - | ||||||||||||
615 | - | |||||||||||||
616 | ctx->read_cb = NULL; | - | ||||||||||||
617 | ctx->write_cb = NULL; | - | ||||||||||||
618 | ctx->cb_arg = NULL; | - | ||||||||||||
619 | } executed 78 times by 2 tests: end of block Executed by:
| 78 | ||||||||||||
620 | - | |||||||||||||
621 | int | - | ||||||||||||
622 | tls_ssl_error(struct tls *ctx, SSL *ssl_conn, int ssl_ret, const char *prefix) | - | ||||||||||||
623 | { | - | ||||||||||||
624 | const char *errstr = "unknown error"; | - | ||||||||||||
625 | unsigned long err; | - | ||||||||||||
626 | int ssl_err; | - | ||||||||||||
627 | - | |||||||||||||
628 | ssl_err = SSL_get_error(ssl_conn, ssl_ret); | - | ||||||||||||
629 | switch (ssl_err) { | - | ||||||||||||
630 | case SSL_ERROR_NONE: never executed: case 0: | 0 | ||||||||||||
631 | case SSL_ERROR_ZERO_RETURN: never executed: case 6: | 0 | ||||||||||||
632 | return (0); never executed: return (0); | 0 | ||||||||||||
633 | - | |||||||||||||
634 | case SSL_ERROR_WANT_READ: executed 16 times by 1 test: case 2: Executed by:
| 16 | ||||||||||||
635 | return (TLS_WANT_POLLIN); executed 16 times by 1 test: return (-2); Executed by:
| 16 | ||||||||||||
636 | - | |||||||||||||
637 | case SSL_ERROR_WANT_WRITE: executed 4 times by 1 test: case 3: Executed by:
| 4 | ||||||||||||
638 | return (TLS_WANT_POLLOUT); executed 4 times by 1 test: return (-3); Executed by:
| 4 | ||||||||||||
639 | - | |||||||||||||
640 | case SSL_ERROR_SYSCALL: never executed: case 5: | 0 | ||||||||||||
641 | if ((err = ERR_peek_error()) != 0) {
| 0 | ||||||||||||
642 | errstr = ERR_error_string(err, NULL); | - | ||||||||||||
643 | } else if (ssl_ret == 0) { never executed: end of block
| 0 | ||||||||||||
644 | if ((ctx->state & TLS_HANDSHAKE_COMPLETE) != 0) {
| 0 | ||||||||||||
645 | ctx->state |= TLS_EOF_NO_CLOSE_NOTIFY; | - | ||||||||||||
646 | return (0); never executed: return (0); | 0 | ||||||||||||
647 | } | - | ||||||||||||
648 | errstr = "unexpected EOF"; | - | ||||||||||||
649 | } else if (ssl_ret == -1) { never executed: end of block
| 0 | ||||||||||||
650 | errstr = strerror(errno); | - | ||||||||||||
651 | } never executed: end of block | 0 | ||||||||||||
652 | tls_set_ssl_errorx(ctx, "%s failed: %s", prefix, errstr); | - | ||||||||||||
653 | return (-1); never executed: return (-1); | 0 | ||||||||||||
654 | - | |||||||||||||
655 | case SSL_ERROR_SSL: never executed: case 1: | 0 | ||||||||||||
656 | if ((err = ERR_peek_error()) != 0) {
| 0 | ||||||||||||
657 | errstr = ERR_error_string(err, NULL); | - | ||||||||||||
658 | } never executed: end of block | 0 | ||||||||||||
659 | tls_set_ssl_errorx(ctx, "%s failed: %s", prefix, errstr); | - | ||||||||||||
660 | return (-1); never executed: return (-1); | 0 | ||||||||||||
661 | - | |||||||||||||
662 | case SSL_ERROR_WANT_CONNECT: never executed: case 7: | 0 | ||||||||||||
663 | case SSL_ERROR_WANT_ACCEPT: never executed: case 8: | 0 | ||||||||||||
664 | case SSL_ERROR_WANT_X509_LOOKUP: never executed: case 4: | 0 | ||||||||||||
665 | default: never executed: default: | 0 | ||||||||||||
666 | tls_set_ssl_errorx(ctx, "%s failed (%i)", prefix, ssl_err); | - | ||||||||||||
667 | return (-1); never executed: return (-1); | 0 | ||||||||||||
668 | } | - | ||||||||||||
669 | } | - | ||||||||||||
670 | - | |||||||||||||
671 | int | - | ||||||||||||
672 | tls_handshake(struct tls *ctx) | - | ||||||||||||
673 | { | - | ||||||||||||
674 | int rv = -1; | - | ||||||||||||
675 | - | |||||||||||||
676 | tls_error_clear(&ctx->error); | - | ||||||||||||
677 | - | |||||||||||||
678 | if ((ctx->flags & (TLS_CLIENT | TLS_SERVER_CONN)) == 0) {
| 0-31 | ||||||||||||
679 | tls_set_errorx(ctx, "invalid operation for context"); | - | ||||||||||||
680 | goto out; never executed: goto out; | 0 | ||||||||||||
681 | } | - | ||||||||||||
682 | - | |||||||||||||
683 | if ((ctx->state & TLS_HANDSHAKE_COMPLETE) != 0) {
| 2-29 | ||||||||||||
684 | tls_set_errorx(ctx, "handshake already completed"); | - | ||||||||||||
685 | goto out; executed 2 times by 1 test: goto out; Executed by:
| 2 | ||||||||||||
686 | } | - | ||||||||||||
687 | - | |||||||||||||
688 | if ((ctx->flags & TLS_CLIENT) != 0)
| 12-17 | ||||||||||||
689 | rv = tls_handshake_client(ctx); executed 17 times by 1 test: rv = tls_handshake_client(ctx); Executed by:
| 17 | ||||||||||||
690 | else if ((ctx->flags & TLS_SERVER_CONN) != 0)
| 0-12 | ||||||||||||
691 | rv = tls_handshake_server(ctx); executed 12 times by 1 test: rv = tls_handshake_server(ctx); Executed by:
| 12 | ||||||||||||
692 | - | |||||||||||||
693 | if (rv == 0) {
| 8-21 | ||||||||||||
694 | ctx->ssl_peer_cert = SSL_get_peer_certificate(ctx->ssl_conn); | - | ||||||||||||
695 | ctx->ssl_peer_chain = SSL_get_peer_cert_chain(ctx->ssl_conn); | - | ||||||||||||
696 | if (tls_conninfo_populate(ctx) == -1)
| 0-8 | ||||||||||||
697 | rv = -1; never executed: rv = -1; | 0 | ||||||||||||
698 | if (ctx->ocsp == NULL)
| 0-8 | ||||||||||||
699 | ctx->ocsp = tls_ocsp_setup_from_peer(ctx); executed 8 times by 1 test: ctx->ocsp = tls_ocsp_setup_from_peer(ctx); Executed by:
| 8 | ||||||||||||
700 | } executed 8 times by 1 test: end of block Executed by:
| 8 | ||||||||||||
701 | out: code before this statement executed 29 times by 1 test: out: Executed by:
| 29 | ||||||||||||
702 | /* Prevent callers from performing incorrect error handling */ | - | ||||||||||||
703 | errno = 0; | - | ||||||||||||
704 | return (rv); executed 31 times by 1 test: return (rv); Executed by:
| 31 | ||||||||||||
705 | } | - | ||||||||||||
706 | - | |||||||||||||
707 | ssize_t | - | ||||||||||||
708 | tls_read(struct tls *ctx, void *buf, size_t buflen) | - | ||||||||||||
709 | { | - | ||||||||||||
710 | ssize_t rv = -1; | - | ||||||||||||
711 | int ssl_ret; | - | ||||||||||||
712 | - | |||||||||||||
713 | tls_error_clear(&ctx->error); | - | ||||||||||||
714 | - | |||||||||||||
715 | if ((ctx->state & TLS_HANDSHAKE_COMPLETE) == 0) {
| 0 | ||||||||||||
716 | if ((rv = tls_handshake(ctx)) != 0)
| 0 | ||||||||||||
717 | goto out; never executed: goto out; | 0 | ||||||||||||
718 | } never executed: end of block | 0 | ||||||||||||
719 | - | |||||||||||||
720 | if (buflen > INT_MAX) {
| 0 | ||||||||||||
721 | tls_set_errorx(ctx, "buflen too long"); | - | ||||||||||||
722 | goto out; never executed: goto out; | 0 | ||||||||||||
723 | } | - | ||||||||||||
724 | - | |||||||||||||
725 | ERR_clear_error(); | - | ||||||||||||
726 | if ((ssl_ret = SSL_read(ctx->ssl_conn, buf, buflen)) > 0) {
| 0 | ||||||||||||
727 | rv = (ssize_t)ssl_ret; | - | ||||||||||||
728 | goto out; never executed: goto out; | 0 | ||||||||||||
729 | } | - | ||||||||||||
730 | rv = (ssize_t)tls_ssl_error(ctx, ctx->ssl_conn, ssl_ret, "read"); | - | ||||||||||||
731 | - | |||||||||||||
732 | out: code before this statement never executed: out: | 0 | ||||||||||||
733 | /* Prevent callers from performing incorrect error handling */ | - | ||||||||||||
734 | errno = 0; | - | ||||||||||||
735 | return (rv); never executed: return (rv); | 0 | ||||||||||||
736 | } | - | ||||||||||||
737 | - | |||||||||||||
738 | ssize_t | - | ||||||||||||
739 | tls_write(struct tls *ctx, const void *buf, size_t buflen) | - | ||||||||||||
740 | { | - | ||||||||||||
741 | ssize_t rv = -1; | - | ||||||||||||
742 | int ssl_ret; | - | ||||||||||||
743 | - | |||||||||||||
744 | tls_error_clear(&ctx->error); | - | ||||||||||||
745 | - | |||||||||||||
746 | if ((ctx->state & TLS_HANDSHAKE_COMPLETE) == 0) {
| 0 | ||||||||||||
747 | if ((rv = tls_handshake(ctx)) != 0)
| 0 | ||||||||||||
748 | goto out; never executed: goto out; | 0 | ||||||||||||
749 | } never executed: end of block | 0 | ||||||||||||
750 | - | |||||||||||||
751 | if (buflen > INT_MAX) {
| 0 | ||||||||||||
752 | tls_set_errorx(ctx, "buflen too long"); | - | ||||||||||||
753 | goto out; never executed: goto out; | 0 | ||||||||||||
754 | } | - | ||||||||||||
755 | - | |||||||||||||
756 | ERR_clear_error(); | - | ||||||||||||
757 | if ((ssl_ret = SSL_write(ctx->ssl_conn, buf, buflen)) > 0) {
| 0 | ||||||||||||
758 | rv = (ssize_t)ssl_ret; | - | ||||||||||||
759 | goto out; never executed: goto out; | 0 | ||||||||||||
760 | } | - | ||||||||||||
761 | rv = (ssize_t)tls_ssl_error(ctx, ctx->ssl_conn, ssl_ret, "write"); | - | ||||||||||||
762 | - | |||||||||||||
763 | out: code before this statement never executed: out: | 0 | ||||||||||||
764 | /* Prevent callers from performing incorrect error handling */ | - | ||||||||||||
765 | errno = 0; | - | ||||||||||||
766 | return (rv); never executed: return (rv); | 0 | ||||||||||||
767 | } | - | ||||||||||||
768 | - | |||||||||||||
769 | int | - | ||||||||||||
770 | tls_close(struct tls *ctx) | - | ||||||||||||
771 | { | - | ||||||||||||
772 | int ssl_ret; | - | ||||||||||||
773 | int rv = 0; | - | ||||||||||||
774 | - | |||||||||||||
775 | tls_error_clear(&ctx->error); | - | ||||||||||||
776 | - | |||||||||||||
777 | if ((ctx->flags & (TLS_CLIENT | TLS_SERVER_CONN)) == 0) {
| 0-8 | ||||||||||||
778 | tls_set_errorx(ctx, "invalid operation for context"); | - | ||||||||||||
779 | rv = -1; | - | ||||||||||||
780 | goto out; never executed: goto out; | 0 | ||||||||||||
781 | } | - | ||||||||||||
782 | - | |||||||||||||
783 | if (ctx->state & TLS_SSL_NEEDS_SHUTDOWN) {
| 0-8 | ||||||||||||
784 | ERR_clear_error(); | - | ||||||||||||
785 | ssl_ret = SSL_shutdown(ctx->ssl_conn); | - | ||||||||||||
786 | if (ssl_ret < 0) {
| 0-8 | ||||||||||||
787 | rv = tls_ssl_error(ctx, ctx->ssl_conn, ssl_ret, | - | ||||||||||||
788 | "shutdown"); | - | ||||||||||||
789 | if (rv == TLS_WANT_POLLIN || rv == TLS_WANT_POLLOUT)
| 0 | ||||||||||||
790 | goto out; never executed: goto out; | 0 | ||||||||||||
791 | } never executed: end of block | 0 | ||||||||||||
792 | ctx->state &= ~TLS_SSL_NEEDS_SHUTDOWN; | - | ||||||||||||
793 | } executed 8 times by 1 test: end of block Executed by:
| 8 | ||||||||||||
794 | - | |||||||||||||
795 | if (ctx->socket != -1) {
| 0-8 | ||||||||||||
796 | if (shutdown(ctx->socket, SHUT_RDWR) != 0) {
| 0 | ||||||||||||
797 | if (rv == 0 &&
| 0 | ||||||||||||
798 | errno != ENOTCONN && errno != ECONNRESET) {
| 0 | ||||||||||||
799 | tls_set_error(ctx, "shutdown"); | - | ||||||||||||
800 | rv = -1; | - | ||||||||||||
801 | } never executed: end of block | 0 | ||||||||||||
802 | } never executed: end of block | 0 | ||||||||||||
803 | if (close(ctx->socket) != 0) {
| 0 | ||||||||||||
804 | if (rv == 0) {
| 0 | ||||||||||||
805 | tls_set_error(ctx, "close"); | - | ||||||||||||
806 | rv = -1; | - | ||||||||||||
807 | } never executed: end of block | 0 | ||||||||||||
808 | } never executed: end of block | 0 | ||||||||||||
809 | ctx->socket = -1; | - | ||||||||||||
810 | } never executed: end of block | 0 | ||||||||||||
811 | - | |||||||||||||
812 | if ((ctx->state & TLS_EOF_NO_CLOSE_NOTIFY) != 0) {
| 0-8 | ||||||||||||
813 | tls_set_errorx(ctx, "EOF without close notify"); | - | ||||||||||||
814 | rv = -1; | - | ||||||||||||
815 | } never executed: end of block | 0 | ||||||||||||
816 | - | |||||||||||||
817 | out: code before this statement executed 8 times by 1 test: out: Executed by:
| 8 | ||||||||||||
818 | /* Prevent callers from performing incorrect error handling */ | - | ||||||||||||
819 | errno = 0; | - | ||||||||||||
820 | return (rv); executed 8 times by 1 test: return (rv); Executed by:
| 8 | ||||||||||||
821 | } | - | ||||||||||||
Source code | Switch to Preprocessed file |