1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
|
#include "mbedtls.h"
#include "util_ct.h"
#include "util_rt.h"
#include "pth.h"
#include <errno.h>
#include <string.h>
#include <unistd.h>
#include <fcntl.h>
#include <mbedtls/ssl.h>
#include <mbedtls/entropy_poll.h>
int prne_mbedtls_x509_crt_verify_cb (
void *param,
mbedtls_x509_crt *crt,
int crt_depth,
uint32_t *flags)
{
*flags &= ~(uint32_t)MBEDTLS_X509_BADCERT_EXPIRED;
return 0;
}
int prne_mbedtls_ssl_send_cb (
void *ctx,
const unsigned char *buf,
size_t len)
{
const int fd = *(int*)ctx;
ssize_t ret;
ret = write(fd, buf, len);
if (ret < 0) {
switch (errno) {
#if EAGAIN == EWOULDBLOCK
case EAGAIN:
#else
case EAGAIN:
case EWOULDBLOCK:
#endif
return MBEDTLS_ERR_SSL_WANT_WRITE;
}
}
return ret;
}
int prne_mbedtls_ssl_recv_cb (void *ctx, unsigned char *buf, size_t len) {
const int fd = *(int*)ctx;
ssize_t ret;
ret = read(fd, buf, len);
if (ret < 0) {
switch (errno) {
#if EAGAIN == EWOULDBLOCK
case EAGAIN:
#else
case EAGAIN:
case EWOULDBLOCK:
#endif
return MBEDTLS_ERR_SSL_WANT_READ;
}
}
return ret;
}
static int prne_mbedtls_entropy_urand_src_f (
void *data,
unsigned char *output,
size_t len,
size_t *olen)
{
const int fd = open("/dev/urandom", O_RDONLY);
int func_ret = 0;
if (fd < 0 || read(fd, output, len) != (ssize_t)len) {
func_ret = MBEDTLS_ERR_ENTROPY_SOURCE_FAILED;
}
*olen = len;
if (fd >= 0) {
close(fd);
}
return func_ret;
}
typedef struct {
pid_t pid;
pid_t ppid;
clock_t clock;
struct timespec now;
struct timespec datetime;
} ent_buf_t;
static int prne_mbedtls_entropy_proc_src_f (
void *data,
unsigned char *output,
size_t len,
size_t *olen)
{
ent_buf_t buf;
prne_memzero(&buf, sizeof(buf));
buf.pid = getpid();
buf.ppid = getppid();
buf.clock = clock();
clock_gettime(CLOCK_MONOTONIC, &buf.now);
clock_gettime(CLOCK_REALTIME, &buf.datetime);
*olen = prne_op_min(len, sizeof(buf));
memcpy(output, &buf, sizeof(*olen));
return 0;
}
void prne_mbedtls_entropy_init (mbedtls_entropy_context *ctx) {
mbedtls_entropy_init(ctx);
/*
* Remove platform source, which could call getrandom().
* Add our own implementation as the one just got removed could be the only
* source.
*/
for (int i = 0; i < ctx->source_count; i += 1) {
if (ctx->source[i].f_source == mbedtls_platform_entropy_poll) {
memmove(
ctx->source + i,
ctx->source + i + 1,
sizeof(mbedtls_entropy_source_state) *
(ctx->source_count - i - 1));
ctx->source_count -= 1;
mbedtls_entropy_add_source(
ctx,
prne_mbedtls_entropy_urand_src_f,
NULL,
MBEDTLS_ENTROPY_MIN_PLATFORM,
MBEDTLS_ENTROPY_SOURCE_STRONG);
mbedtls_entropy_add_source(
ctx,
prne_mbedtls_entropy_proc_src_f,
NULL,
sizeof(ent_buf_t),
MBEDTLS_ENTROPY_SOURCE_STRONG);
break;
}
}
}
bool prne_mbedtls_pth_handle (
mbedtls_ssl_context *ssl,
int(*mbedtls_f)(mbedtls_ssl_context*),
const int fd,
pth_event_t ev)
{
int pollret;
struct pollfd pfd;
pfd.fd = fd;
while (true) {
switch (mbedtls_f(ssl)) {
case MBEDTLS_ERR_SSL_WANT_READ:
pfd.events = POLLIN;
break;
case MBEDTLS_ERR_SSL_WANT_WRITE:
pfd.events = POLLOUT;
break;
case 0:
return true;
default:
return false;
}
do {
pollret = prne_pth_poll(&pfd, 1, -1, ev);
if (pollret < 0) {
return false;
}
} while (false);
}
}
|