GCC Code Coverage Report
Directory: ./ Exec Total Coverage
File: lib/libtls/tls_bio_cb.c Lines: 30 41 73.2 %
Date: 2017-11-13 Branches: 10 17 58.8 %

Line Branch Exec Source
1
/* $OpenBSD: tls_bio_cb.c,v 1.19 2017/01/12 16:18:39 jsing Exp $ */
2
/*
3
 * Copyright (c) 2016 Tobias Pape <tobias@netshed.de>
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 <fcntl.h>
19
#include <stdlib.h>
20
#include <unistd.h>
21
22
#include <openssl/bio.h>
23
24
#include <tls.h>
25
#include "tls_internal.h"
26
27
static int bio_cb_write(BIO *bio, const char *buf, int num);
28
static int bio_cb_read(BIO *bio, char *buf, int size);
29
static int bio_cb_puts(BIO *bio, const char *str);
30
static long bio_cb_ctrl(BIO *bio, int cmd, long num, void *ptr);
31
32
static BIO_METHOD bio_cb_method = {
33
	.type = BIO_TYPE_MEM,
34
	.name = "libtls_callbacks",
35
	.bwrite = bio_cb_write,
36
	.bread = bio_cb_read,
37
	.bputs = bio_cb_puts,
38
	.ctrl = bio_cb_ctrl,
39
};
40
41
static BIO_METHOD *
42
bio_s_cb(void)
43
{
44
24
	return (&bio_cb_method);
45
}
46
47
static int
48
bio_cb_puts(BIO *bio, const char *str)
49
{
50
	return (bio_cb_write(bio, str, strlen(str)));
51
}
52
53
static long
54
bio_cb_ctrl(BIO *bio, int cmd, long num, void *ptr)
55
{
56
	long ret = 1;
57
58

108
	switch (cmd) {
59
	case BIO_CTRL_GET_CLOSE:
60
		ret = (long)bio->shutdown;
61
		break;
62
	case BIO_CTRL_SET_CLOSE:
63
		bio->shutdown = (int)num;
64
		break;
65
	case BIO_CTRL_DUP:
66
	case BIO_CTRL_FLUSH:
67
		break;
68
	case BIO_CTRL_INFO:
69
	case BIO_CTRL_GET:
70
	case BIO_CTRL_SET:
71
	default:
72
24
		ret = BIO_ctrl(bio->next_bio, cmd, num, ptr);
73
24
	}
74
75
42
	return (ret);
76
}
77
78
static int
79
bio_cb_write(BIO *bio, const char *buf, int num)
80
{
81
120
	struct tls *ctx = bio->ptr;
82
	int rv;
83
84
60
	BIO_clear_retry_flags(bio);
85
60
	rv = (ctx->write_cb)(ctx, buf, num, ctx->cb_arg);
86
60
	if (rv == TLS_WANT_POLLIN) {
87
		BIO_set_retry_read(bio);
88
		rv = -1;
89
60
	} else if (rv == TLS_WANT_POLLOUT) {
90
12
		BIO_set_retry_write(bio);
91
		rv = -1;
92
12
	}
93
60
	return (rv);
94
}
95
96
static int
97
bio_cb_read(BIO *bio, char *buf, int size)
98
{
99
324
	struct tls *ctx = bio->ptr;
100
	int rv;
101
102
162
	BIO_clear_retry_flags(bio);
103
162
	rv = (ctx->read_cb)(ctx, buf, size, ctx->cb_arg);
104
162
	if (rv == TLS_WANT_POLLIN) {
105
30
		BIO_set_retry_read(bio);
106
		rv = -1;
107
162
	} else if (rv == TLS_WANT_POLLOUT) {
108
		BIO_set_retry_write(bio);
109
		rv = -1;
110
	}
111
162
	return (rv);
112
}
113
114
int
115
tls_set_cbs(struct tls *ctx, tls_read_cb read_cb, tls_write_cb write_cb,
116
    void *cb_arg)
117
{
118
	int rv = -1;
119
	BIO *bio;
120
121
24
	if (read_cb == NULL || write_cb == NULL) {
122
		tls_set_errorx(ctx, "no callbacks provided");
123
		goto err;
124
	}
125
126
12
	ctx->read_cb = read_cb;
127
12
	ctx->write_cb = write_cb;
128
12
	ctx->cb_arg = cb_arg;
129
130
12
	if ((bio = BIO_new(bio_s_cb())) == NULL) {
131
		tls_set_errorx(ctx, "failed to create callback i/o");
132
		goto err;
133
	}
134
12
	bio->ptr = ctx;
135
12
	bio->init = 1;
136
137
12
	SSL_set_bio(ctx->ssl_conn, bio, bio);
138
139
12
	rv = 0;
140
141
 err:
142
12
	return (rv);
143
}