diff options
author | Colin Watson <cjwatson@debian.org> | 2020-09-20 16:14:20 +0100 |
---|---|---|
committer | Colin Watson <cjwatson@debian.org> | 2020-09-20 16:14:20 +0100 |
commit | 173bfbf7886608a4a7abbfac6a42ac4bf4a3432d (patch) | |
tree | b97833d8754f257f92d99dd2f5c9e9d557e3f689 /src/io.c | |
parent | 75073d0a8478441cc97a6efa10b566c5fb1dac81 (diff) |
New upstream version 1.5.0
Diffstat (limited to 'src/io.c')
-rw-r--r-- | src/io.c | 94 |
1 files changed, 56 insertions, 38 deletions
@@ -20,11 +20,11 @@ struct frame { | |||
20 | uint8_t cmd; | 20 | uint8_t cmd; |
21 | uint8_t bcnth; | 21 | uint8_t bcnth; |
22 | uint8_t bcntl; | 22 | uint8_t bcntl; |
23 | uint8_t data[CTAP_RPT_SIZE - 7]; | 23 | uint8_t data[CTAP_MAX_REPORT_LEN - CTAP_INIT_HEADER_LEN]; |
24 | } init; | 24 | } init; |
25 | struct { | 25 | struct { |
26 | uint8_t seq; | 26 | uint8_t seq; |
27 | uint8_t data[CTAP_RPT_SIZE - 5]; | 27 | uint8_t data[CTAP_MAX_REPORT_LEN - CTAP_CONT_HEADER_LEN]; |
28 | } cont; | 28 | } cont; |
29 | } body; | 29 | } body; |
30 | }) | 30 | }) |
@@ -38,6 +38,7 @@ tx_empty(fido_dev_t *d, uint8_t cmd) | |||
38 | { | 38 | { |
39 | struct frame *fp; | 39 | struct frame *fp; |
40 | unsigned char pkt[sizeof(*fp) + 1]; | 40 | unsigned char pkt[sizeof(*fp) + 1]; |
41 | const size_t len = d->tx_len + 1; | ||
41 | int n; | 42 | int n; |
42 | 43 | ||
43 | memset(&pkt, 0, sizeof(pkt)); | 44 | memset(&pkt, 0, sizeof(pkt)); |
@@ -45,8 +46,8 @@ tx_empty(fido_dev_t *d, uint8_t cmd) | |||
45 | fp->cid = d->cid; | 46 | fp->cid = d->cid; |
46 | fp->body.init.cmd = CTAP_FRAME_INIT | cmd; | 47 | fp->body.init.cmd = CTAP_FRAME_INIT | cmd; |
47 | 48 | ||
48 | n = d->io.write(d->io_handle, pkt, sizeof(pkt)); | 49 | if (len > sizeof(pkt) || (n = d->io.write(d->io_handle, pkt, |
49 | if (n < 0 || (size_t)n != sizeof(pkt)) | 50 | len)) < 0 || (size_t)n != len) |
50 | return (-1); | 51 | return (-1); |
51 | 52 | ||
52 | return (0); | 53 | return (0); |
@@ -57,19 +58,23 @@ tx_preamble(fido_dev_t *d, uint8_t cmd, const void *buf, size_t count) | |||
57 | { | 58 | { |
58 | struct frame *fp; | 59 | struct frame *fp; |
59 | unsigned char pkt[sizeof(*fp) + 1]; | 60 | unsigned char pkt[sizeof(*fp) + 1]; |
61 | const size_t len = d->tx_len + 1; | ||
60 | int n; | 62 | int n; |
61 | 63 | ||
64 | if (d->tx_len - CTAP_INIT_HEADER_LEN > sizeof(fp->body.init.data)) | ||
65 | return (0); | ||
66 | |||
62 | memset(&pkt, 0, sizeof(pkt)); | 67 | memset(&pkt, 0, sizeof(pkt)); |
63 | fp = (struct frame *)(pkt + 1); | 68 | fp = (struct frame *)(pkt + 1); |
64 | fp->cid = d->cid; | 69 | fp->cid = d->cid; |
65 | fp->body.init.cmd = CTAP_FRAME_INIT | cmd; | 70 | fp->body.init.cmd = CTAP_FRAME_INIT | cmd; |
66 | fp->body.init.bcnth = (count >> 8) & 0xff; | 71 | fp->body.init.bcnth = (count >> 8) & 0xff; |
67 | fp->body.init.bcntl = count & 0xff; | 72 | fp->body.init.bcntl = count & 0xff; |
68 | count = MIN(count, sizeof(fp->body.init.data)); | 73 | count = MIN(count, d->tx_len - CTAP_INIT_HEADER_LEN); |
69 | memcpy(&fp->body.init.data, buf, count); | 74 | memcpy(&fp->body.init.data, buf, count); |
70 | 75 | ||
71 | n = d->io.write(d->io_handle, pkt, sizeof(pkt)); | 76 | if (len > sizeof(pkt) || (n = d->io.write(d->io_handle, pkt, |
72 | if (n < 0 || (size_t)n != sizeof(pkt)) | 77 | len)) < 0 || (size_t)n != len) |
73 | return (0); | 78 | return (0); |
74 | 79 | ||
75 | return (count); | 80 | return (count); |
@@ -80,17 +85,21 @@ tx_frame(fido_dev_t *d, uint8_t seq, const void *buf, size_t count) | |||
80 | { | 85 | { |
81 | struct frame *fp; | 86 | struct frame *fp; |
82 | unsigned char pkt[sizeof(*fp) + 1]; | 87 | unsigned char pkt[sizeof(*fp) + 1]; |
88 | const size_t len = d->tx_len + 1; | ||
83 | int n; | 89 | int n; |
84 | 90 | ||
91 | if (d->tx_len - CTAP_CONT_HEADER_LEN > sizeof(fp->body.cont.data)) | ||
92 | return (0); | ||
93 | |||
85 | memset(&pkt, 0, sizeof(pkt)); | 94 | memset(&pkt, 0, sizeof(pkt)); |
86 | fp = (struct frame *)(pkt + 1); | 95 | fp = (struct frame *)(pkt + 1); |
87 | fp->cid = d->cid; | 96 | fp->cid = d->cid; |
88 | fp->body.cont.seq = seq; | 97 | fp->body.cont.seq = seq; |
89 | count = MIN(count, sizeof(fp->body.cont.data)); | 98 | count = MIN(count, d->tx_len - CTAP_CONT_HEADER_LEN); |
90 | memcpy(&fp->body.cont.data, buf, count); | 99 | memcpy(&fp->body.cont.data, buf, count); |
91 | 100 | ||
92 | n = d->io.write(d->io_handle, pkt, sizeof(pkt)); | 101 | if (len > sizeof(pkt) || (n = d->io.write(d->io_handle, pkt, |
93 | if (n < 0 || (size_t)n != sizeof(pkt)) | 102 | len)) < 0 || (size_t)n != len) |
94 | return (0); | 103 | return (0); |
95 | 104 | ||
96 | return (count); | 105 | return (count); |
@@ -129,16 +138,12 @@ fido_tx(fido_dev_t *d, uint8_t cmd, const void *buf, size_t count) | |||
129 | 138 | ||
130 | if (d->transport.tx != NULL) | 139 | if (d->transport.tx != NULL) |
131 | return (d->transport.tx(d, cmd, buf, count)); | 140 | return (d->transport.tx(d, cmd, buf, count)); |
132 | |||
133 | if (d->io_handle == NULL || d->io.write == NULL || count > UINT16_MAX) { | 141 | if (d->io_handle == NULL || d->io.write == NULL || count > UINT16_MAX) { |
134 | fido_log_debug("%s: invalid argument", __func__); | 142 | fido_log_debug("%s: invalid argument", __func__); |
135 | return (-1); | 143 | return (-1); |
136 | } | 144 | } |
137 | 145 | ||
138 | if (count == 0) | 146 | return (count == 0 ? tx_empty(d, cmd) : tx(d, cmd, buf, count)); |
139 | return (tx_empty(d, cmd)); | ||
140 | |||
141 | return (tx(d, cmd, buf, count)); | ||
142 | } | 147 | } |
143 | 148 | ||
144 | static int | 149 | static int |
@@ -146,8 +151,10 @@ rx_frame(fido_dev_t *d, struct frame *fp, int ms) | |||
146 | { | 151 | { |
147 | int n; | 152 | int n; |
148 | 153 | ||
149 | n = d->io.read(d->io_handle, (unsigned char *)fp, sizeof(*fp), ms); | 154 | memset(fp, 0, sizeof(*fp)); |
150 | if (n < 0 || (size_t)n != sizeof(*fp)) | 155 | |
156 | if (d->rx_len > sizeof(*fp) || (n = d->io.read(d->io_handle, | ||
157 | (unsigned char *)fp, d->rx_len, ms)) < 0 || (size_t)n != d->rx_len) | ||
151 | return (-1); | 158 | return (-1); |
152 | 159 | ||
153 | return (0); | 160 | return (0); |
@@ -165,8 +172,11 @@ rx_preamble(fido_dev_t *d, uint8_t cmd, struct frame *fp, int ms) | |||
165 | } while (fp->cid == d->cid && | 172 | } while (fp->cid == d->cid && |
166 | fp->body.init.cmd == (CTAP_FRAME_INIT | CTAP_KEEPALIVE)); | 173 | fp->body.init.cmd == (CTAP_FRAME_INIT | CTAP_KEEPALIVE)); |
167 | 174 | ||
175 | if (d->rx_len > sizeof(*fp)) | ||
176 | return (-1); | ||
177 | |||
168 | fido_log_debug("%s: initiation frame at %p", __func__, (void *)fp); | 178 | fido_log_debug("%s: initiation frame at %p", __func__, (void *)fp); |
169 | fido_log_xxd(fp, sizeof(*fp)); | 179 | fido_log_xxd(fp, d->rx_len); |
170 | 180 | ||
171 | #ifdef FIDO_FUZZ | 181 | #ifdef FIDO_FUZZ |
172 | fp->body.init.cmd = (CTAP_FRAME_INIT | cmd); | 182 | fp->body.init.cmd = (CTAP_FRAME_INIT | cmd); |
@@ -185,30 +195,41 @@ static int | |||
185 | rx(fido_dev_t *d, uint8_t cmd, unsigned char *buf, size_t count, int ms) | 195 | rx(fido_dev_t *d, uint8_t cmd, unsigned char *buf, size_t count, int ms) |
186 | { | 196 | { |
187 | struct frame f; | 197 | struct frame f; |
188 | uint16_t r, payload_len; | 198 | size_t r, payload_len, init_data_len, cont_data_len; |
199 | |||
200 | if (d->rx_len <= CTAP_INIT_HEADER_LEN || | ||
201 | d->rx_len <= CTAP_CONT_HEADER_LEN) | ||
202 | return (-1); | ||
203 | |||
204 | init_data_len = d->rx_len - CTAP_INIT_HEADER_LEN; | ||
205 | cont_data_len = d->rx_len - CTAP_CONT_HEADER_LEN; | ||
206 | |||
207 | if (init_data_len > sizeof(f.body.init.data) || | ||
208 | cont_data_len > sizeof(f.body.cont.data)) | ||
209 | return (-1); | ||
189 | 210 | ||
190 | if (rx_preamble(d, cmd, &f, ms) < 0) { | 211 | if (rx_preamble(d, cmd, &f, ms) < 0) { |
191 | fido_log_debug("%s: rx_preamble", __func__); | 212 | fido_log_debug("%s: rx_preamble", __func__); |
192 | return (-1); | 213 | return (-1); |
193 | } | 214 | } |
194 | 215 | ||
195 | payload_len = (f.body.init.bcnth << 8) | f.body.init.bcntl; | 216 | payload_len = (size_t)((f.body.init.bcnth << 8) | f.body.init.bcntl); |
196 | fido_log_debug("%s: payload_len=%zu", __func__, (size_t)payload_len); | 217 | fido_log_debug("%s: payload_len=%zu", __func__, payload_len); |
197 | 218 | ||
198 | if (count < (size_t)payload_len) { | 219 | if (count < payload_len) { |
199 | fido_log_debug("%s: count < payload_len", __func__); | 220 | fido_log_debug("%s: count < payload_len", __func__); |
200 | return (-1); | 221 | return (-1); |
201 | } | 222 | } |
202 | 223 | ||
203 | if (payload_len < sizeof(f.body.init.data)) { | 224 | if (payload_len < init_data_len) { |
204 | memcpy(buf, f.body.init.data, payload_len); | 225 | memcpy(buf, f.body.init.data, payload_len); |
205 | return (payload_len); | 226 | return ((int)payload_len); |
206 | } | 227 | } |
207 | 228 | ||
208 | memcpy(buf, f.body.init.data, sizeof(f.body.init.data)); | 229 | memcpy(buf, f.body.init.data, init_data_len); |
209 | r = sizeof(f.body.init.data); | 230 | r = init_data_len; |
210 | 231 | ||
211 | for (int seq = 0; (size_t)r < payload_len; seq++) { | 232 | for (int seq = 0; r < payload_len; seq++) { |
212 | if (rx_frame(d, &f, ms) < 0) { | 233 | if (rx_frame(d, &f, ms) < 0) { |
213 | fido_log_debug("%s: rx_frame", __func__); | 234 | fido_log_debug("%s: rx_frame", __func__); |
214 | return (-1); | 235 | return (-1); |
@@ -216,11 +237,11 @@ rx(fido_dev_t *d, uint8_t cmd, unsigned char *buf, size_t count, int ms) | |||
216 | 237 | ||
217 | fido_log_debug("%s: continuation frame at %p", __func__, | 238 | fido_log_debug("%s: continuation frame at %p", __func__, |
218 | (void *)&f); | 239 | (void *)&f); |
219 | fido_log_xxd(&f, sizeof(f)); | 240 | fido_log_xxd(&f, d->rx_len); |
220 | 241 | ||
221 | #ifdef FIDO_FUZZ | 242 | #ifdef FIDO_FUZZ |
222 | f.cid = d->cid; | 243 | f.cid = d->cid; |
223 | f.body.cont.seq = seq; | 244 | f.body.cont.seq = (uint8_t)seq; |
224 | #endif | 245 | #endif |
225 | 246 | ||
226 | if (f.cid != d->cid || f.body.cont.seq != seq) { | 247 | if (f.cid != d->cid || f.body.cont.seq != seq) { |
@@ -229,17 +250,16 @@ rx(fido_dev_t *d, uint8_t cmd, unsigned char *buf, size_t count, int ms) | |||
229 | return (-1); | 250 | return (-1); |
230 | } | 251 | } |
231 | 252 | ||
232 | if ((size_t)(payload_len - r) > sizeof(f.body.cont.data)) { | 253 | if (payload_len - r > cont_data_len) { |
233 | memcpy(buf + r, f.body.cont.data, | 254 | memcpy(buf + r, f.body.cont.data, cont_data_len); |
234 | sizeof(f.body.cont.data)); | 255 | r += cont_data_len; |
235 | r += sizeof(f.body.cont.data); | ||
236 | } else { | 256 | } else { |
237 | memcpy(buf + r, f.body.cont.data, payload_len - r); | 257 | memcpy(buf + r, f.body.cont.data, payload_len - r); |
238 | r += (payload_len - r); /* break */ | 258 | r += payload_len - r; /* break */ |
239 | } | 259 | } |
240 | } | 260 | } |
241 | 261 | ||
242 | return (r); | 262 | return ((int)r); |
243 | } | 263 | } |
244 | 264 | ||
245 | int | 265 | int |
@@ -252,15 +272,13 @@ fido_rx(fido_dev_t *d, uint8_t cmd, void *buf, size_t count, int ms) | |||
252 | 272 | ||
253 | if (d->transport.rx != NULL) | 273 | if (d->transport.rx != NULL) |
254 | return (d->transport.rx(d, cmd, buf, count, ms)); | 274 | return (d->transport.rx(d, cmd, buf, count, ms)); |
255 | |||
256 | if (d->io_handle == NULL || d->io.read == NULL || count > UINT16_MAX) { | 275 | if (d->io_handle == NULL || d->io.read == NULL || count > UINT16_MAX) { |
257 | fido_log_debug("%s: invalid argument", __func__); | 276 | fido_log_debug("%s: invalid argument", __func__); |
258 | return (-1); | 277 | return (-1); |
259 | } | 278 | } |
260 | |||
261 | if ((n = rx(d, cmd, buf, count, ms)) >= 0) { | 279 | if ((n = rx(d, cmd, buf, count, ms)) >= 0) { |
262 | fido_log_debug("%s: buf=%p, len=%d", __func__, (void *)buf, n); | 280 | fido_log_debug("%s: buf=%p, len=%d", __func__, (void *)buf, n); |
263 | fido_log_xxd(buf, n); | 281 | fido_log_xxd(buf, (size_t)n); |
264 | } | 282 | } |
265 | 283 | ||
266 | return (n); | 284 | return (n); |