Seregon/Hermes

Hermes/Dyforge is a program written in c++ allows you to inject a dll that can analyze all processes in a program, can be used for mod and reverse engeneering

C/3.8 KB/No license
DyMain/mongoose.c
Hermes / DyMain / mongoose.c
1// Copyright (c) 2004-2013 Sergey Lyubka
2// Copyright (c) 2013-2025 Cesanta Software Limited
3// All rights reserved
4//
5// This software is dual-licensed: you can redistribute it and/or modify
6// it under the terms of the GNU General Public License version 2 as
7// published by the Free Software Foundation. For the terms of this
8// license, see http://www.gnu.org/licenses/
9//
10// You are free to use this software under the terms of the GNU General
11// Public License, but WITHOUT ANY WARRANTY; without even the implied
12// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
13// See the GNU General Public License for more details.
14//
15// Alternatively, you can license this software under a commercial
16// license, as set out in https://www.mongoose.ws/licensing/
17//
18// SPDX-License-Identifier: GPL-2.0-only or commercial
19 
20#include "mongoose.h"
21 
22#ifdef MG_ENABLE_LINES
23#line 1 "src/base64.c"
24#endif
25 
26 
27static int mg_base64_encode_single(int c) {
28 if (c < 26) {
29 return c + 'A';
30 } else if (c < 52) {
31 return c - 26 + 'a';
32 } else if (c < 62) {
33 return c - 52 + '0';
34 } else {
35 return c == 62 ? '+' : '/';
36 }
37}
38 
39static int mg_base64_decode_single(int c) {
40 if (c >= 'A' && c <= 'Z') {
41 return c - 'A';
42 } else if (c >= 'a' && c <= 'z') {
43 return c + 26 - 'a';
44 } else if (c >= '0' && c <= '9') {
45 return c + 52 - '0';
46 } else if (c == '+') {
47 return 62;
48 } else if (c == '/') {
49 return 63;
50 } else if (c == '=') {
51 return 64;
52 } else {
53 return -1;
54 }
55}
56 
57size_t mg_base64_update(unsigned char ch, char *to, size_t n) {
58 unsigned long rem = (n & 3) % 3;
59 if (rem == 0) {
60 to[n] = (char) mg_base64_encode_single(ch >> 2);
61 to[++n] = (char) ((ch & 3) << 4);
62 } else if (rem == 1) {
63 to[n] = (char) mg_base64_encode_single(to[n] | (ch >> 4));
64 to[++n] = (char) ((ch & 15) << 2);
65 } else {
66 to[n] = (char) mg_base64_encode_single(to[n] | (ch >> 6));
67 to[++n] = (char) mg_base64_encode_single(ch & 63);
68 n++;
69 }
70 return n;
71}
72 
73size_t mg_base64_final(char *to, size_t n) {
74 size_t saved = n;
75 // printf("---[%.*s]\n", n, to);
76 if (n & 3) n = mg_base64_update(0, to, n);
77 if ((saved & 3) == 2) n--;
78 // printf(" %d[%.*s]\n", n, n, to);
79 while (n & 3) to[n++] = '=';
80 to[n] = '\0';
81 return n;
82}
83 
84size_t mg_base64_encode(const unsigned char *p, size_t n, char *to, size_t dl) {
85 size_t i, len = 0;
86 if (dl > 0) to[0] = '\0';
87 if (dl < ((n / 3) + (n % 3 ? 1 : 0)) * 4 + 1) return 0;
88 for (i = 0; i < n; i++) len = mg_base64_update(p[i], to, len);
89 len = mg_base64_final(to, len);
90 return len;
91}
92 
93size_t mg_base64_decode(const char *src, size_t n, char *dst, size_t dl) {
94 const char *end = src == NULL ? NULL : src + n; // Cannot add to NULL
95 size_t len = 0;
96 if (dl < n / 4 * 3 + 1) goto fail;
97 while (src != NULL && src + 3 < end) {
98 int a = mg_base64_decode_single(src[0]),
99 b = mg_base64_decode_single(src[1]),
100 c = mg_base64_decode_single(src[2]),
101 d = mg_base64_decode_single(src[3]);
102 if (a == 64 || a < 0 || b == 64 || b < 0 || c < 0 || d < 0) {
103 goto fail;
104 }
105 dst[len++] = (char) ((a << 2) | (b >> 4));
106 if (src[2] != '=') {
107 dst[len++] = (char) ((b << 4) | (c >> 2));
108 if (src[3] != '=') dst[len++] = (char) ((c << 6) | d);
109 }
110 src += 4;
111 }
112 dst[len] = '\0';
113 return len;
114fail:
115 if (dl > 0) dst[0] = '\0';
116 return 0;
117}
118 
119#ifdef MG_ENABLE_LINES
120#line 1 "src/dns.c"
121#endif
122 
123 
124 
125 
126 
127 
128 
129 
130struct dns_data {
131 struct dns_data *next;
132 struct mg_connection *c;
133 uint64_t expire;
134 uint16_t txnid;
135};
136 
137static void mg_sendnsreq(struct mg_connection *, struct mg_str *, int,
138 struct mg_dns *, bool);
139 
140static void mg_dns_free(struct dns_data **head, struct dns_data *d) {
141 LIST_DELETE(struct dns_data, head, d);
142 free(d);
143}
144 
145void mg_resolve_cancel(struct mg_connection *c) {
146 struct dns_data *tmp, *d;
147 struct dns_data **head = (struct dns_data **) &c->mgr->active_dns_requests;
148 for (d = *head; d != NULL; d = tmp) {
149 tmp = d->next;
150 if (d->c == c) mg_dns_free(head, d);
151 }
152}
153 
154static size_t mg_dns_parse_name_depth(const uint8_t *s, size_t len, size_t ofs,
155 char *to, size_t tolen, size_t j,
156 int depth) {
157 size_t i = 0;
158 if (tolen > 0 && depth == 0) to[0] = '\0';
159 if (depth > 5) return 0;
160 // MG_INFO(("ofs %lx %x %x", (unsigned long) ofs, s[ofs], s[ofs + 1]));
161 while (ofs + i + 1 < len) {
162 size_t n = s[ofs + i];
163 if (n == 0) {
164 i++;
165 break;
166 }
167 if (n & 0xc0) {
168 size_t ptr = (((n & 0x3f) << 8) | s[ofs + i + 1]); // 12 is hdr len
169 // MG_INFO(("PTR %lx", (unsigned long) ptr));
170 if (ptr + 1 < len && (s[ptr] & 0xc0) == 0 &&
171 mg_dns_parse_name_depth(s, len, ptr, to, tolen, j, depth + 1) == 0)
172 return 0;
173 i += 2;
174 break;
175 }
176 if (ofs + i + n + 1 >= len) return 0;
177 if (j > 0) {
178 if (j < tolen) to[j] = '.';
179 j++;
180 }
181 if (j + n < tolen) memcpy(&to[j], &s[ofs + i + 1], n);
182 j += n;
183 i += n + 1;
184 if (j < tolen) to[j] = '\0'; // Zero-terminate this chunk
185 // MG_INFO(("--> [%s]", to));
186 }
187 if (tolen > 0) to[tolen - 1] = '\0'; // Make sure make sure it is nul-term
188 return i;
189}
190 
191static size_t mg_dns_parse_name(const uint8_t *s, size_t n, size_t ofs,
192 char *dst, size_t dstlen) {
193 return mg_dns_parse_name_depth(s, n, ofs, dst, dstlen, 0, 0);
194}
195 
196size_t mg_dns_parse_rr(const uint8_t *buf, size_t len, size_t ofs,
197 bool is_question, struct mg_dns_rr *rr) {
198 const uint8_t *s = buf + ofs, *e = &buf[len];
199 
200 memset(rr, 0, sizeof(*rr));
201 if (len < sizeof(struct mg_dns_header)) return 0; // Too small
202 if (len > 512) return 0; // Too large, we don't expect that
203 if (s >= e) return 0; // Overflow
204 
205 if ((rr->nlen = (uint16_t) mg_dns_parse_name(buf, len, ofs, NULL, 0)) == 0)
206 return 0;
207 s += rr->nlen + 4;
208 if (s > e) return 0;
209 rr->atype = (uint16_t) (((uint16_t) s[-4] << 8) | s[-3]);
210 rr->aclass = (uint16_t) (((uint16_t) s[-2] << 8) | s[-1]);
211 if (is_question) return (size_t) (rr->nlen + 4);
212 
213 s += 6;
214 if (s > e) return 0;
215 rr->alen = (uint16_t) (((uint16_t) s[-2] << 8) | s[-1]);
216 if (s + rr->alen > e) return 0;
217 return (size_t) (rr->nlen + rr->alen + 10);
218}
219 
220bool mg_dns_parse(const uint8_t *buf, size_t len, struct mg_dns_message *dm) {
221 const struct mg_dns_header *h = (struct mg_dns_header *) buf;
222 struct mg_dns_rr rr;
223 size_t i, n, num_answers, ofs = sizeof(*h);
224 bool is_response;
225 memset(dm, 0, sizeof(*dm));
226 
227 if (len < sizeof(*h)) return 0; // Too small, headers dont fit
228 if (mg_ntohs(h->num_questions) > 1) return 0; // Sanity
229 num_answers = mg_ntohs(h->num_answers);
230 if (num_answers > 10) {
231 MG_DEBUG(("Got %u answers, ignoring beyond 10th one", num_answers));
232 num_answers = 10; // Sanity cap
233 }
234 dm->txnid = mg_ntohs(h->txnid);
235 is_response = mg_ntohs(h->flags) & 0x8000;
236 
237 for (i = 0; i < mg_ntohs(h->num_questions); i++) {
238 if ((n = mg_dns_parse_rr(buf, len, ofs, true, &rr)) == 0) return false;
239 // MG_INFO(("Q %lu %lu %hu/%hu", ofs, n, rr.atype, rr.aclass));
240 mg_dns_parse_name(buf, len, ofs, dm->name, sizeof(dm->name));
241 ofs += n;
242 }
243 
244 if (!is_response) {
245 // For queries, there is no need to parse the answers. In this way,
246 // we also ensure the domain name (dm->name) is parsed from
247 // the question field.
248 return true;
249 }
250 
251 for (i = 0; i < num_answers; i++) {
252 if ((n = mg_dns_parse_rr(buf, len, ofs, false, &rr)) == 0) return false;
253 // MG_INFO(("A -- %lu %lu %hu/%hu %s", ofs, n, rr.atype, rr.aclass,
254 // dm->name));
255 mg_dns_parse_name(buf, len, ofs, dm->name, sizeof(dm->name));
256 ofs += n;
257 
258 if (rr.alen == 4 && rr.atype == 1 && rr.aclass == 1) {
259 dm->addr.is_ip6 = false;
260 memcpy(&dm->addr.ip, &buf[ofs - 4], 4);
261 dm->resolved = true;
262 break; // Return success
263 } else if (rr.alen == 16 && rr.atype == 28 && rr.aclass == 1) {
264 dm->addr.is_ip6 = true;
265 memcpy(&dm->addr.ip, &buf[ofs - 16], 16);
266 dm->resolved = true;
267 break; // Return success
268 }
269 }
270 return true;
271}
272 
273static void dns_cb(struct mg_connection *c, int ev, void *ev_data) {
274 struct dns_data *d, *tmp;
275 struct dns_data **head = (struct dns_data **) &c->mgr->active_dns_requests;
276 if (ev == MG_EV_POLL) {
277 uint64_t now = *(uint64_t *) ev_data;
278 for (d = *head; d != NULL; d = tmp) {
279 tmp = d->next;
280 // MG_DEBUG ("%lu %lu dns poll", d->expire, now));
281 if (now > d->expire) mg_error(d->c, "DNS timeout");
282 }
283 } else if (ev == MG_EV_READ) {
284 struct mg_dns_message dm;
285 int resolved = 0;
286 if (mg_dns_parse(c->recv.buf, c->recv.len, &dm) == false) {
287 MG_ERROR(("Unexpected DNS response:"));
288 mg_hexdump(c->recv.buf, c->recv.len);
289 } else {
290 // MG_VERBOSE(("%s %d", dm.name, dm.resolved));
291 for (d = *head; d != NULL; d = tmp) {
292 tmp = d->next;
293 // MG_INFO(("d %p %hu %hu", d, d->txnid, dm.txnid));
294 if (dm.txnid != d->txnid) continue;
295 if (d->c->is_resolving) {
296 if (dm.resolved) {
297 dm.addr.port = d->c->rem.port; // Save port
298 d->c->rem = dm.addr; // Copy resolved address
299 MG_DEBUG(
300 ("%lu %s is %M", d->c->id, dm.name, mg_print_ip, &d->c->rem));
301 mg_connect_resolved(d->c);
302#if MG_ENABLE_IPV6
303 } else if (dm.addr.is_ip6 == false && dm.name[0] != '\0' &&
304 c->mgr->use_dns6 == false) {
305 struct mg_str x = mg_str(dm.name);
306 mg_sendnsreq(d->c, &x, c->mgr->dnstimeout, &c->mgr->dns6, true);
307#endif
308 } else {
309 mg_error(d->c, "%s DNS lookup failed", dm.name);
310 }
311 } else {
312 MG_ERROR(("%lu already resolved", d->c->id));
313 }
314 mg_dns_free(head, d);
315 resolved = 1;
316 }
317 }
318 if (!resolved) MG_ERROR(("stray DNS reply"));
319 c->recv.len = 0;
320 } else if (ev == MG_EV_CLOSE) {
321 for (d = *head; d != NULL; d = tmp) {
322 tmp = d->next;
323 mg_error(d->c, "DNS error");
324 mg_dns_free(head, d);
325 }
326 }
327}
328 
329static bool mg_dns_send(struct mg_connection *c, const struct mg_str *name,
330 uint16_t txnid, bool ipv6) {
331 struct {
332 struct mg_dns_header header;
333 uint8_t data[256];
334 } pkt;
335 size_t i, n;
336 memset(&pkt, 0, sizeof(pkt));
337 pkt.header.txnid = mg_htons(txnid);
338 pkt.header.flags = mg_htons(0x100);
339 pkt.header.num_questions = mg_htons(1);
340 for (i = n = 0; i < sizeof(pkt.data) - 5; i++) {
341 if (name->buf[i] == '.' || i >= name->len) {
342 pkt.data[n] = (uint8_t) (i - n);
343 memcpy(&pkt.data[n + 1], name->buf + n, i - n);
344 n = i + 1;
345 }
346 if (i >= name->len) break;
347 }
348 memcpy(&pkt.data[n], "\x00\x00\x01\x00\x01", 5); // A query
349 n += 5;
350 if (ipv6) pkt.data[n - 3] = 0x1c; // AAAA query
351 // memcpy(&pkt.data[n], "\xc0\x0c\x00\x1c\x00\x01", 6); // AAAA query
352 // n += 6;
353 return mg_send(c, &pkt, sizeof(pkt.header) + n);
354}
355 
356static void mg_sendnsreq(struct mg_connection *c, struct mg_str *name, int ms,
357 struct mg_dns *dnsc, bool ipv6) {
358 struct dns_data *d = NULL;
359 if (dnsc->url == NULL) {
360 mg_error(c, "DNS server URL is NULL. Call mg_mgr_init()");
361 } else if (dnsc->c == NULL) {
362 dnsc->c = mg_connect(c->mgr, dnsc->url, NULL, NULL);
363 if (dnsc->c != NULL) {
364 dnsc->c->pfn = dns_cb;
365 // dnsc->c->is_hexdumping = 1;
366 }
367 }
368 if (dnsc->c == NULL) {
369 mg_error(c, "resolver");
370 } else if ((d = (struct dns_data *) calloc(1, sizeof(*d))) == NULL) {
371 mg_error(c, "resolve OOM");
372 } else {
373 struct dns_data *reqs = (struct dns_data *) c->mgr->active_dns_requests;
374 d->txnid = reqs ? (uint16_t) (reqs->txnid + 1) : 1;
375 d->next = (struct dns_data *) c->mgr->active_dns_requests;
376 c->mgr->active_dns_requests = d;
377 d->expire = mg_millis() + (uint64_t) ms;
378 d->c = c;
379 c->is_resolving = 1;
380 MG_VERBOSE(("%lu resolving %.*s @ %s, txnid %hu", c->id, (int) name->len,
381 name->buf, dnsc->url, d->txnid));
382 if (!mg_dns_send(dnsc->c, name, d->txnid, ipv6)) {
383 mg_error(dnsc->c, "DNS send");
384 }
385 }
386}
387 
388void mg_resolve(struct mg_connection *c, const char *url) {
389 struct mg_str host = mg_url_host(url);
390 c->rem.port = mg_htons(mg_url_port(url));
391 if (mg_aton(host, &c->rem)) {
392 // host is an IP address, do not fire name resolution
393 mg_connect_resolved(c);
394 } else {
395 // host is not an IP, send DNS resolution request
396 struct mg_dns *dns = c->mgr->use_dns6 ? &c->mgr->dns6 : &c->mgr->dns4;
397 mg_sendnsreq(c, &host, c->mgr->dnstimeout, dns, c->mgr->use_dns6);
398 }
399}
400 
401static const uint8_t mdns_answer[] = {
402 0, 1, // 2 bytes - record type, A
403 0, 1, // 2 bytes - address class, INET
404 0, 0, 0, 120, // 4 bytes - TTL
405 0, 4 // 2 bytes - address length
406};
407 
408static void mdns_cb(struct mg_connection *c, int ev, void *ev_data) {
409 if (ev == MG_EV_READ) {
410 struct mg_dns_header *qh = (struct mg_dns_header *) c->recv.buf;
411 if (c->recv.len > 12 && (qh->flags & mg_htons(0xF800)) == 0) {
412 // flags -> !resp, opcode=0 => query; ignore other opcodes and responses
413 struct mg_dns_rr rr; // Parse first question, offset 12 is header size
414 size_t n = mg_dns_parse_rr(c->recv.buf, c->recv.len, 12, true, &rr);
415 MG_VERBOSE(("mDNS request parsed, result=%d", (int) n));
416 if (n > 0) {
417 // RFC-6762 Appendix C, RFC2181 11: m(n + 1-63), max 255 + 0x0
418 // buf and h declared here to ease future expansion to DNS-SD
419 uint8_t buf[sizeof(struct mg_dns_header) + 256 + sizeof(mdns_answer) + 4];
420 struct mg_dns_header *h = (struct mg_dns_header *) buf;
421 char local_name[63 + 7]; // name label + '.' + local label + '\0'
422 uint8_t name_len = (uint8_t) strlen((char *)c->fn_data);
423 struct mg_dns_message dm;
424 bool unicast = (rr.aclass & MG_BIT(15)) != 0; // QU
425 // uint16_t q = mg_ntohs(qh->num_questions);
426 rr.aclass &= (uint16_t) ~MG_BIT(15); // remove "QU" (unicast response)
427 qh->num_questions = mg_htons(1); // parser sanity
428 mg_dns_parse(c->recv.buf, c->recv.len, &dm);
429 if (name_len > (sizeof(local_name) - 7)) // leave room for .local\0
430 name_len = sizeof(local_name) - 7;
431 memcpy(local_name, c->fn_data, name_len);
432 strcpy(local_name + name_len, ".local"); // ensure proper name.local\0
433 if (strcmp(local_name, dm.name) == 0) {
434 uint8_t *p = &buf[sizeof(*h)];
435 memset(h, 0, sizeof(*h)); // clear header
436 h->txnid = unicast ? qh->txnid : 0; // RFC-6762 18.1
437 // RFC-6762 6: 0 questions, 1 Answer, 0 Auth, 0 Additional RRs
438 h->num_answers = mg_htons(1); // only one answer
439 h->flags = mg_htons(0x8400); // Authoritative response
440 *p++ = name_len; // label 1
441 memcpy(p, c->fn_data, name_len), p += name_len;
442 *p++ = 5; // label 2
443 memcpy(p, "local", 5), p += 5;
444 *p++ = 0; // no more labels
445 memcpy(p, mdns_answer, sizeof(mdns_answer)), p += sizeof(mdns_answer);
446#if MG_ENABLE_TCPIP
447 memcpy(p, &c->mgr->ifp->ip, 4), p += 4;
448#else
449 memcpy(p, c->data, 4), p += 4;
450#endif
451 if (!unicast) memcpy(&c->rem, &c->loc, sizeof(c->rem));
452 mg_send(c, buf, (size_t)(p - buf)); // And send it!
453 MG_DEBUG(("mDNS %c response sent", unicast ? 'U' : 'M'));
454 }
455 }
456 }
457 mg_iobuf_del(&c->recv, 0, c->recv.len);
458 }
459 (void) ev_data;
460}
461 
462void mg_multicast_add(struct mg_connection *c, char *ip);
463struct mg_connection *mg_mdns_listen(struct mg_mgr *mgr, char *name) {
464 struct mg_connection *c =
465 mg_listen(mgr, "udp://224.0.0.251:5353", mdns_cb, name);
466 if (c != NULL) mg_multicast_add(c, (char *)"224.0.0.251");
467 return c;
468}
469 
470#ifdef MG_ENABLE_LINES
471#line 1 "src/event.c"
472#endif
473 
474 
475 
476 
477 
478 
479void mg_call(struct mg_connection *c, int ev, void *ev_data) {
480#if MG_ENABLE_PROFILE
481 const char *names[] = {
482 "EV_ERROR", "EV_OPEN", "EV_POLL", "EV_RESOLVE",
483 "EV_CONNECT", "EV_ACCEPT", "EV_TLS_HS", "EV_READ",
484 "EV_WRITE", "EV_CLOSE", "EV_HTTP_MSG", "EV_HTTP_CHUNK",
485 "EV_WS_OPEN", "EV_WS_MSG", "EV_WS_CTL", "EV_MQTT_CMD",
486 "EV_MQTT_MSG", "EV_MQTT_OPEN", "EV_SNTP_TIME", "EV_USER"};
487 if (ev != MG_EV_POLL && ev < (int) (sizeof(names) / sizeof(names[0]))) {
488 MG_PROF_ADD(c, names[ev]);
489 }
490#endif
491 // Fire protocol handler first, user handler second. See #2559
492 if (c->pfn != NULL) c->pfn(c, ev, ev_data);
493 if (c->fn != NULL) c->fn(c, ev, ev_data);
494}
495 
496void mg_error(struct mg_connection *c, const char *fmt, ...) {
497 char buf[64];
498 va_list ap;
499 va_start(ap, fmt);
500 mg_vsnprintf(buf, sizeof(buf), fmt, &ap);
501 va_end(ap);
502 MG_ERROR(("%lu %ld %s", c->id, c->fd, buf));
503 c->is_closing = 1; // Set is_closing before sending MG_EV_CALL
504 mg_call(c, MG_EV_ERROR, buf); // Let user handler override it
505}
506 
507#ifdef MG_ENABLE_LINES
508#line 1 "src/flash.c"
509#endif
510 
511 
512 
513 
514 
515#if MG_OTA != MG_OTA_NONE && MG_OTA != MG_OTA_CUSTOM
516 
517static char *s_addr; // Current address to write to
518static size_t s_size; // Firmware size to flash. In-progress indicator
519static uint32_t s_crc32; // Firmware checksum
520 
521bool mg_ota_flash_begin(size_t new_firmware_size, struct mg_flash *flash) {
522 bool ok = false;
523 if (s_size) {
524 MG_ERROR(("OTA already in progress. Call mg_ota_end()"));
525 } else {
526 size_t half = flash->size / 2;
527 s_crc32 = 0;
528 s_addr = (char *) flash->start + half;
529 MG_DEBUG(("FW %lu bytes, max %lu", new_firmware_size, half));
530 if (new_firmware_size < half) {
531 ok = true;
532 s_size = new_firmware_size;
533 MG_INFO(("Starting OTA, firmware size %lu", s_size));
534 } else {
535 MG_ERROR(("Firmware %lu is too big to fit %lu", new_firmware_size, half));
536 }
537 }
538 return ok;
539}
540 
541bool mg_ota_flash_write(const void *buf, size_t len, struct mg_flash *flash) {
542 bool ok = false;
543 if (s_size == 0) {
544 MG_ERROR(("OTA is not started, call mg_ota_begin()"));
545 } else {
546 size_t len_aligned_down = MG_ROUND_DOWN(len, flash->align);
547 if (len_aligned_down) ok = flash->write_fn(s_addr, buf, len_aligned_down);
548 if (len_aligned_down < len) {
549 size_t left = len - len_aligned_down;
550 char tmp[flash->align];
551 memset(tmp, 0xff, sizeof(tmp));
552 memcpy(tmp, (char *) buf + len_aligned_down, left);
553 ok = flash->write_fn(s_addr + len_aligned_down, tmp, sizeof(tmp));
554 }
555 s_crc32 = mg_crc32(s_crc32, (char *) buf, len); // Update CRC
556 MG_DEBUG(("%#x %p %lu -> %d", s_addr - len, buf, len, ok));
557 s_addr += len;
558 }
559 return ok;
560}
561 
562bool mg_ota_flash_end(struct mg_flash *flash) {
563 char *base = (char *) flash->start + flash->size / 2;
564 bool ok = false;
565 if (s_size) {
566 size_t size = (size_t) (s_addr - base);
567 uint32_t crc32 = mg_crc32(0, base, s_size);
568 if (size == s_size && crc32 == s_crc32) ok = true;
569 MG_DEBUG(("CRC: %x/%x, size: %lu/%lu, status: %s", s_crc32, crc32, s_size,
570 size, ok ? "ok" : "fail"));
571 s_size = 0;
572 if (ok) ok = flash->swap_fn();
573 }
574 MG_INFO(("Finishing OTA: %s", ok ? "ok" : "fail"));
575 return ok;
576}
577 
578#endif
579 
580#ifdef MG_ENABLE_LINES
581#line 1 "src/fmt.c"
582#endif
583 
584 
585 
586 
587static bool is_digit(int c) {
588 return c >= '0' && c <= '9';
589}
590 
591static int addexp(char *buf, int e, int sign) {
592 int n = 0;
593 buf[n++] = 'e';
594 buf[n++] = (char) sign;
595 if (e > 400) return 0;
596 if (e < 10) buf[n++] = '0';
597 if (e >= 100) buf[n++] = (char) (e / 100 + '0'), e -= 100 * (e / 100);
598 if (e >= 10) buf[n++] = (char) (e / 10 + '0'), e -= 10 * (e / 10);
599 buf[n++] = (char) (e + '0');
600 return n;
601}
602 
603static int xisinf(double x) {
604 union {
605 double f;
606 uint64_t u;
607 } ieee754 = {x};
608 return ((unsigned) (ieee754.u >> 32) & 0x7fffffff) == 0x7ff00000 &&
609 ((unsigned) ieee754.u == 0);
610}
611 
612static int xisnan(double x) {
613 union {
614 double f;
615 uint64_t u;
616 } ieee754 = {x};
617 return ((unsigned) (ieee754.u >> 32) & 0x7fffffff) +
618 ((unsigned) ieee754.u != 0) >
619 0x7ff00000;
620}
621 
622static size_t mg_dtoa(char *dst, size_t dstlen, double d, int width, bool tz) {
623 char buf[40];
624 int i, s = 0, n = 0, e = 0;
625 double t, mul, saved;
626 if (d == 0.0) return mg_snprintf(dst, dstlen, "%s", "0");
627 if (xisinf(d)) return mg_snprintf(dst, dstlen, "%s", d > 0 ? "inf" : "-inf");
628 if (xisnan(d)) return mg_snprintf(dst, dstlen, "%s", "nan");
629 if (d < 0.0) d = -d, buf[s++] = '-';
630 
631 // Round
632 saved = d;
633 if (tz) {
634 mul = 1.0;
635 while (d >= 10.0 && d / mul >= 10.0) mul *= 10.0;
636 } else {
637 mul = 0.1;
638 }
639 
640 while (d <= 1.0 && d / mul <= 1.0) mul /= 10.0;
641 for (i = 0, t = mul * 5; i < width; i++) t /= 10.0;
642 
643 d += t;
644 
645 // Calculate exponent, and 'mul' for scientific representation
646 mul = 1.0;
647 while (d >= 10.0 && d / mul >= 10.0) mul *= 10.0, e++;
648 while (d < 1.0 && d / mul < 1.0) mul /= 10.0, e--;
649 // printf(" --> %g %d %g %g\n", saved, e, t, mul);
650 
651 if (tz && e >= width && width > 1) {
652 n = (int) mg_dtoa(buf, sizeof(buf), saved / mul, width, tz);
653 // printf(" --> %.*g %d [%.*s]\n", 10, d / t, e, n, buf);
654 n += addexp(buf + s + n, e, '+');
655 return mg_snprintf(dst, dstlen, "%.*s", n, buf);
656 } else if (tz && e <= -width && width > 1) {
657 n = (int) mg_dtoa(buf, sizeof(buf), saved / mul, width, tz);
658 // printf(" --> %.*g %d [%.*s]\n", 10, d / mul, e, n, buf);
659 n += addexp(buf + s + n, -e, '-');
660 return mg_snprintf(dst, dstlen, "%.*s", n, buf);
661 } else {
662 int targ_width = width;
663 for (i = 0, t = mul; t >= 1.0 && s + n < (int) sizeof(buf); i++) {
664 int ch = (int) (d / t);
665 if (n > 0 || ch > 0) buf[s + n++] = (char) (ch + '0');
666 d -= ch * t;
667 t /= 10.0;
668 }
669 // printf(" --> [%g] -> %g %g (%d) [%.*s]\n", saved, d, t, n, s + n, buf);
670 if (n == 0) buf[s++] = '0';
671 while (t >= 1.0 && n + s < (int) sizeof(buf)) buf[n++] = '0', t /= 10.0;
672 if (s + n < (int) sizeof(buf)) buf[n + s++] = '.';
673 // printf(" 1--> [%g] -> [%.*s]\n", saved, s + n, buf);
674 if (!tz && n > 0) targ_width = width + n;
675 for (i = 0, t = 0.1; s + n < (int) sizeof(buf) && n < targ_width; i++) {
676 int ch = (int) (d / t);
677 buf[s + n++] = (char) (ch + '0');
678 d -= ch * t;
679 t /= 10.0;
680 }
681 }
682 
683 while (tz && n > 0 && buf[s + n - 1] == '0') n--; // Trim trailing zeroes
684 if (tz && n > 0 && buf[s + n - 1] == '.') n--; // Trim trailing dot
685 n += s;
686 if (n >= (int) sizeof(buf)) n = (int) sizeof(buf) - 1;
687 buf[n] = '\0';
688 return mg_snprintf(dst, dstlen, "%s", buf);
689}
690 
691static size_t mg_lld(char *buf, int64_t val, bool is_signed, bool is_hex) {
692 const char *letters = "0123456789abcdef";
693 uint64_t v = (uint64_t) val;
694 size_t s = 0, n, i;
695 if (is_signed && val < 0) buf[s++] = '-', v = (uint64_t) (-val);
696 // This loop prints a number in reverse order. I guess this is because we
697 // write numbers from right to left: least significant digit comes last.
698 // Maybe because we use Arabic numbers, and Arabs write RTL?
699 if (is_hex) {
700 for (n = 0; v; v >>= 4) buf[s + n++] = letters[v & 15];
701 } else {
702 for (n = 0; v; v /= 10) buf[s + n++] = letters[v % 10];
703 }
704 // Reverse a string
705 for (i = 0; i < n / 2; i++) {
706 char t = buf[s + i];
707 buf[s + i] = buf[s + n - i - 1], buf[s + n - i - 1] = t;
708 }
709 if (val == 0) buf[n++] = '0'; // Handle special case
710 return n + s;
711}
712 
713static size_t scpy(void (*out)(char, void *), void *ptr, char *buf,
714 size_t len) {
715 size_t i = 0;
716 while (i < len && buf[i] != '\0') out(buf[i++], ptr);
717 return i;
718}
719 
720size_t mg_xprintf(void (*out)(char, void *), void *ptr, const char *fmt, ...) {
721 size_t len = 0;
722 va_list ap;
723 va_start(ap, fmt);
724 len = mg_vxprintf(out, ptr, fmt, &ap);
725 va_end(ap);
726 return len;
727}
728 
729size_t mg_vxprintf(void (*out)(char, void *), void *param, const char *fmt,
730 va_list *ap) {
731 size_t i = 0, n = 0;
732 while (fmt[i] != '\0') {
733 if (fmt[i] == '%') {
734 size_t j, k, x = 0, is_long = 0, w = 0 /* width */, pr = ~0U /* prec */;
735 char pad = ' ', minus = 0, c = fmt[++i];
736 if (c == '#') x++, c = fmt[++i];
737 if (c == '-') minus++, c = fmt[++i];
738 if (c == '0') pad = '0', c = fmt[++i];
739 while (is_digit(c)) w *= 10, w += (size_t) (c - '0'), c = fmt[++i];
740 if (c == '.') {
741 c = fmt[++i];
742 if (c == '*') {
743 pr = (size_t) va_arg(*ap, int);
744 c = fmt[++i];
745 } else {
746 pr = 0;
747 while (is_digit(c)) pr *= 10, pr += (size_t) (c - '0'), c = fmt[++i];
748 }
749 }
750 while (c == 'h') c = fmt[++i]; // Treat h and hh as int
751 if (c == 'l') {
752 is_long++, c = fmt[++i];
753 if (c == 'l') is_long++, c = fmt[++i];
754 }
755 if (c == 'p') x = 1, is_long = 1;
756 if (c == 'd' || c == 'u' || c == 'x' || c == 'X' || c == 'p' ||
757 c == 'g' || c == 'f') {
758 bool s = (c == 'd'), h = (c == 'x' || c == 'X' || c == 'p');
759 char tmp[40];
760 size_t xl = x ? 2 : 0;
761 if (c == 'g' || c == 'f') {
762 double v = va_arg(*ap, double);
763 if (pr == ~0U) pr = 6;
764 k = mg_dtoa(tmp, sizeof(tmp), v, (int) pr, c == 'g');
765 } else if (is_long == 2) {
766 int64_t v = va_arg(*ap, int64_t);
767 k = mg_lld(tmp, v, s, h);
768 } else if (is_long == 1) {
769 long v = va_arg(*ap, long);
770 k = mg_lld(tmp, s ? (int64_t) v : (int64_t) (unsigned long) v, s, h);
771 } else {
772 int v = va_arg(*ap, int);
773 k = mg_lld(tmp, s ? (int64_t) v : (int64_t) (unsigned) v, s, h);
774 }
775 for (j = 0; j < xl && w > 0; j++) w--;
776 for (j = 0; pad == ' ' && !minus && k < w && j + k < w; j++)
777 n += scpy(out, param, &pad, 1);
778 n += scpy(out, param, (char *) "0x", xl);
779 for (j = 0; pad == '0' && k < w && j + k < w; j++)
780 n += scpy(out, param, &pad, 1);
781 n += scpy(out, param, tmp, k);
782 for (j = 0; pad == ' ' && minus && k < w && j + k < w; j++)
783 n += scpy(out, param, &pad, 1);
784 } else if (c == 'm' || c == 'M') {
785 mg_pm_t f = va_arg(*ap, mg_pm_t);
786 if (c == 'm') out('"', param);
787 n += f(out, param, ap);
788 if (c == 'm') n += 2, out('"', param);
789 } else if (c == 'c') {
790 int ch = va_arg(*ap, int);
791 out((char) ch, param);
792 n++;
793 } else if (c == 's') {
794 char *p = va_arg(*ap, char *);
795 if (pr == ~0U) pr = p == NULL ? 0 : strlen(p);
796 for (j = 0; !minus && pr < w && j + pr < w; j++)
797 n += scpy(out, param, &pad, 1);
798 n += scpy(out, param, p, pr);
799 for (j = 0; minus && pr < w && j + pr < w; j++)
800 n += scpy(out, param, &pad, 1);
801 } else if (c == '%') {
802 out('%', param);
803 n++;
804 } else {
805 out('%', param);
806 out(c, param);
807 n += 2;
808 }
809 i++;
810 } else {
811 out(fmt[i], param), n++, i++;
812 }
813 }
814 return n;
815}
816 
817#ifdef MG_ENABLE_LINES
818#line 1 "src/fs.c"
819#endif
820 
821 
822 
823 
824struct mg_fd *mg_fs_open(struct mg_fs *fs, const char *path, int flags) {
825 struct mg_fd *fd = (struct mg_fd *) calloc(1, sizeof(*fd));
826 if (fd != NULL) {
827 fd->fd = fs->op(path, flags);
828 fd->fs = fs;
829 if (fd->fd == NULL) {
830 free(fd);
831 fd = NULL;
832 }
833 }
834 return fd;
835}
836 
837void mg_fs_close(struct mg_fd *fd) {
838 if (fd != NULL) {
839 fd->fs->cl(fd->fd);
840 free(fd);
841 }
842}
843 
844struct mg_str mg_file_read(struct mg_fs *fs, const char *path) {
845 struct mg_str result = {NULL, 0};
846 void *fp;
847 fs->st(path, &result.len, NULL);
848 if ((fp = fs->op(path, MG_FS_READ)) != NULL) {
849 result.buf = (char *) calloc(1, result.len + 1);
850 if (result.buf != NULL &&
851 fs->rd(fp, (void *) result.buf, result.len) != result.len) {
852 free((void *) result.buf);
853 result.buf = NULL;
854 }
855 fs->cl(fp);
856 }
857 if (result.buf == NULL) result.len = 0;
858 return result;
859}
860 
861bool mg_file_write(struct mg_fs *fs, const char *path, const void *buf,
862 size_t len) {
863 bool result = false;
864 struct mg_fd *fd;
865 char tmp[MG_PATH_MAX];
866 mg_snprintf(tmp, sizeof(tmp), "%s..%d", path, rand());
867 if ((fd = mg_fs_open(fs, tmp, MG_FS_WRITE)) != NULL) {
868 result = fs->wr(fd->fd, buf, len) == len;
869 mg_fs_close(fd);
870 if (result) {
871 fs->rm(path);
872 fs->mv(tmp, path);
873 } else {
874 fs->rm(tmp);
875 }
876 }
877 return result;
878}
879 
880bool mg_file_printf(struct mg_fs *fs, const char *path, const char *fmt, ...) {
881 va_list ap;
882 char *data;
883 bool result = false;
884 va_start(ap, fmt);
885 data = mg_vmprintf(fmt, &ap);
886 va_end(ap);
887 result = mg_file_write(fs, path, data, strlen(data));
888 free(data);
889 return result;
890}
891 
892// This helper function allows to scan a filesystem in a sequential way,
893// without using callback function:
894// char buf[100] = "";
895// while (mg_fs_ls(&mg_fs_posix, "./", buf, sizeof(buf))) {
896// ...
897static void mg_fs_ls_fn(const char *filename, void *param) {
898 struct mg_str *s = (struct mg_str *) param;
899 if (s->buf[0] == '\0') {
900 mg_snprintf((char *) s->buf, s->len, "%s", filename);
901 } else if (strcmp(s->buf, filename) == 0) {
902 ((char *) s->buf)[0] = '\0'; // Fetch next file
903 }
904}
905 
906bool mg_fs_ls(struct mg_fs *fs, const char *path, char *buf, size_t len) {
907 struct mg_str s = {buf, len};
908 fs->ls(path, mg_fs_ls_fn, &s);
909 return buf[0] != '\0';
910}
911 
912#ifdef MG_ENABLE_LINES
913#line 1 "src/fs_fat.c"
914#endif
915 
916 
917 
918#if MG_ENABLE_FATFS
919#include <ff.h>
920 
921static int mg_days_from_epoch(int y, int m, int d) {
922 y -= m <= 2;
923 int era = y / 400;
924 int yoe = y - era * 400;
925 int doy = (153 * (m + (m > 2 ? -3 : 9)) + 2) / 5 + d - 1;
926 int doe = yoe * 365 + yoe / 4 - yoe / 100 + doy;
927 return era * 146097 + doe - 719468;
928}
929 
930static time_t mg_timegm(const struct tm *t) {
931 int year = t->tm_year + 1900;
932 int month = t->tm_mon; // 0-11
933 if (month > 11) {
934 year += month / 12;
935 month %= 12;
936 } else if (month < 0) {
937 int years_diff = (11 - month) / 12;
938 year -= years_diff;
939 month += 12 * years_diff;
940 }
941 int x = mg_days_from_epoch(year, month + 1, t->tm_mday);
942 return 60 * (60 * (24L * x + t->tm_hour) + t->tm_min) + t->tm_sec;
943}
944 
945static time_t ff_time_to_epoch(uint16_t fdate, uint16_t ftime) {
946 struct tm tm;
947 memset(&tm, 0, sizeof(struct tm));
948 tm.tm_sec = (ftime << 1) & 0x3e;
949 tm.tm_min = ((ftime >> 5) & 0x3f);
950 tm.tm_hour = ((ftime >> 11) & 0x1f);
951 tm.tm_mday = (fdate & 0x1f);
952 tm.tm_mon = ((fdate >> 5) & 0x0f) - 1;
953 tm.tm_year = ((fdate >> 9) & 0x7f) + 80;
954 return mg_timegm(&tm);
955}
956 
957static int ff_stat(const char *path, size_t *size, time_t *mtime) {
958 FILINFO fi;
959 if (path[0] == '\0') {
960 if (size) *size = 0;
961 if (mtime) *mtime = 0;
962 return MG_FS_DIR;
963 } else if (f_stat(path, &fi) == 0) {
964 if (size) *size = (size_t) fi.fsize;
965 if (mtime) *mtime = ff_time_to_epoch(fi.fdate, fi.ftime);
966 return MG_FS_READ | MG_FS_WRITE | ((fi.fattrib & AM_DIR) ? MG_FS_DIR : 0);
967 } else {
968 return 0;
969 }
970}
971 
972static void ff_list(const char *dir, void (*fn)(const char *, void *),
973 void *userdata) {
974 DIR d;
975 FILINFO fi;
976 if (f_opendir(&d, dir) == FR_OK) {
977 while (f_readdir(&d, &fi) == FR_OK && fi.fname[0] != '\0') {
978 if (!strcmp(fi.fname, ".") || !strcmp(fi.fname, "..")) continue;
979 fn(fi.fname, userdata);
980 }
981 f_closedir(&d);
982 }
983}
984 
985static void *ff_open(const char *path, int flags) {
986 FIL f;
987 unsigned char mode = FA_READ;
988 if (flags & MG_FS_WRITE) mode |= FA_WRITE | FA_OPEN_ALWAYS | FA_OPEN_APPEND;
989 if (f_open(&f, path, mode) == 0) {
990 FIL *fp;
991 if ((fp = calloc(1, sizeof(*fp))) != NULL) {
992 memcpy(fp, &f, sizeof(*fp));
993 return fp;
994 }
995 }
996 return NULL;
997}
998 
999static void ff_close(void *fp) {
1000 if (fp != NULL) {
1001 f_close((FIL *) fp);
1002 free(fp);
1003 }
1004}
1005 
1006static size_t ff_read(void *fp, void *buf, size_t len) {
1007 UINT n = 0, misalign = ((size_t) buf) & 3;
1008 if (misalign) {
1009 char aligned[4];
1010 f_read((FIL *) fp, aligned, len > misalign ? misalign : len, &n);
1011 memcpy(buf, aligned, n);
1012 } else {
1013 f_read((FIL *) fp, buf, len, &n);
1014 }
1015 return n;
1016}
1017 
1018static size_t ff_write(void *fp, const void *buf, size_t len) {
1019 UINT n = 0;
1020 return f_write((FIL *) fp, (char *) buf, len, &n) == FR_OK ? n : 0;
1021}
1022 
1023static size_t ff_seek(void *fp, size_t offset) {
1024 f_lseek((FIL *) fp, offset);
1025 return offset;
1026}
1027 
1028static bool ff_rename(const char *from, const char *to) {
1029 return f_rename(from, to) == FR_OK;
1030}
1031 
1032static bool ff_remove(const char *path) {
1033 return f_unlink(path) == FR_OK;
1034}
1035 
1036static bool ff_mkdir(const char *path) {
1037 return f_mkdir(path) == FR_OK;
1038}
1039 
1040struct mg_fs mg_fs_fat = {ff_stat, ff_list, ff_open, ff_close, ff_read,
1041 ff_write, ff_seek, ff_rename, ff_remove, ff_mkdir};
1042#endif
1043 
1044#ifdef MG_ENABLE_LINES
1045#line 1 "src/fs_packed.c"
1046#endif
1047 
1048 
1049 
1050 
1051struct packed_file {
1052 const char *data;
1053 size_t size;
1054 size_t pos;
1055};
1056 
1057#if MG_ENABLE_PACKED_FS
1058#else
1059const char *mg_unpack(const char *path, size_t *size, time_t *mtime) {
1060 if (size != NULL) *size = 0;
1061 if (mtime != NULL) *mtime = 0;
1062 (void) path;
1063 return NULL;
1064}
1065const char *mg_unlist(size_t no) {
1066 (void) no;
1067 return NULL;
1068}
1069#endif
1070 
1071struct mg_str mg_unpacked(const char *path) {
1072 size_t len = 0;
1073 const char *buf = mg_unpack(path, &len, NULL);
1074 return mg_str_n(buf, len);
1075}
1076 
1077static int is_dir_prefix(const char *prefix, size_t n, const char *path) {
1078 // MG_INFO(("[%.*s] [%s] %c", (int) n, prefix, path, path[n]));
1079 return n < strlen(path) && strncmp(prefix, path, n) == 0 &&
1080 (n == 0 || path[n] == '/' || path[n - 1] == '/');
1081}
1082 
1083static int packed_stat(const char *path, size_t *size, time_t *mtime) {
1084 const char *p;
1085 size_t i, n = strlen(path);
1086 if (mg_unpack(path, size, mtime)) return MG_FS_READ; // Regular file
1087 // Scan all files. If `path` is a dir prefix for any of them, it's a dir
1088 for (i = 0; (p = mg_unlist(i)) != NULL; i++) {
1089 if (is_dir_prefix(path, n, p)) return MG_FS_DIR;
1090 }
1091 return 0;
1092}
1093 
1094static void packed_list(const char *dir, void (*fn)(const char *, void *),
1095 void *userdata) {
1096 char buf[MG_PATH_MAX], tmp[sizeof(buf)];
1097 const char *path, *begin, *end;
1098 size_t i, n = strlen(dir);
1099 tmp[0] = '\0'; // Previously listed entry
1100 for (i = 0; (path = mg_unlist(i)) != NULL; i++) {
1101 if (!is_dir_prefix(dir, n, path)) continue;
1102 begin = &path[n + 1];
1103 end = strchr(begin, '/');
1104 if (end == NULL) end = begin + strlen(begin);
1105 mg_snprintf(buf, sizeof(buf), "%.*s", (int) (end - begin), begin);
1106 buf[sizeof(buf) - 1] = '\0';
1107 // If this entry has been already listed, skip
1108 // NOTE: we're assuming that file list is sorted alphabetically
1109 if (strcmp(buf, tmp) == 0) continue;
1110 fn(buf, userdata); // Not yet listed, call user function
1111 strcpy(tmp, buf); // And save this entry as listed
1112 }
1113}
1114 
1115static void *packed_open(const char *path, int flags) {
1116 size_t size = 0;
1117 const char *data = mg_unpack(path, &size, NULL);
1118 struct packed_file *fp = NULL;
1119 if (data == NULL) return NULL;
1120 if (flags & MG_FS_WRITE) return NULL;
1121 if ((fp = (struct packed_file *) calloc(1, sizeof(*fp))) != NULL) {
1122 fp->size = size;
1123 fp->data = data;
1124 }
1125 return (void *) fp;
1126}
1127 
1128static void packed_close(void *fp) {
1129 if (fp != NULL) free(fp);
1130}
1131 
1132static size_t packed_read(void *fd, void *buf, size_t len) {
1133 struct packed_file *fp = (struct packed_file *) fd;
1134 if (fp->pos + len > fp->size) len = fp->size - fp->pos;
1135 memcpy(buf, &fp->data[fp->pos], len);
1136 fp->pos += len;
1137 return len;
1138}
1139 
1140static size_t packed_write(void *fd, const void *buf, size_t len) {
1141 (void) fd, (void) buf, (void) len;
1142 return 0;
1143}
1144 
1145static size_t packed_seek(void *fd, size_t offset) {
1146 struct packed_file *fp = (struct packed_file *) fd;
1147 fp->pos = offset;
1148 if (fp->pos > fp->size) fp->pos = fp->size;
1149 return fp->pos;
1150}
1151 
1152static bool packed_rename(const char *from, const char *to) {
1153 (void) from, (void) to;
1154 return false;
1155}
1156 
1157static bool packed_remove(const char *path) {
1158 (void) path;
1159 return false;
1160}
1161 
1162static bool packed_mkdir(const char *path) {
1163 (void) path;
1164 return false;
1165}
1166 
1167struct mg_fs mg_fs_packed = {
1168 packed_stat, packed_list, packed_open, packed_close, packed_read,
1169 packed_write, packed_seek, packed_rename, packed_remove, packed_mkdir};
1170 
1171#ifdef MG_ENABLE_LINES
1172#line 1 "src/fs_posix.c"
1173#endif
1174 
1175 
1176#if MG_ENABLE_POSIX_FS
1177 
1178#ifndef MG_STAT_STRUCT
1179#define MG_STAT_STRUCT stat
1180#endif
1181 
1182#ifndef MG_STAT_FUNC
1183#define MG_STAT_FUNC stat
1184#endif
1185 
1186static int p_stat(const char *path, size_t *size, time_t *mtime) {
1187#if !defined(S_ISDIR)
1188 MG_ERROR(("stat() API is not supported. %p %p %p", path, size, mtime));
1189 return 0;
1190#else
1191#if MG_ARCH == MG_ARCH_WIN32
1192 struct _stati64 st;
1193 wchar_t tmp[MG_PATH_MAX];
1194 MultiByteToWideChar(CP_UTF8, 0, path, -1, tmp, sizeof(tmp) / sizeof(tmp[0]));
1195 if (_wstati64(tmp, &st) != 0) return 0;
1196 // If path is a symlink, windows reports 0 in st.st_size.
1197 // Get a real file size by opening it and jumping to the end
1198 if (st.st_size == 0 && (st.st_mode & _S_IFREG)) {
1199 FILE *fp = _wfopen(tmp, L"rb");
1200 if (fp != NULL) {
1201 fseek(fp, 0, SEEK_END);
1202 if (ftell(fp) > 0) st.st_size = ftell(fp); // Use _ftelli64 on win10+
1203 fclose(fp);
1204 }
1205 }
1206#else
1207 struct MG_STAT_STRUCT st;
1208 if (MG_STAT_FUNC(path, &st) != 0) return 0;
1209#endif
1210 if (size) *size = (size_t) st.st_size;
1211 if (mtime) *mtime = st.st_mtime;
1212 return MG_FS_READ | MG_FS_WRITE | (S_ISDIR(st.st_mode) ? MG_FS_DIR : 0);
1213#endif
1214}
1215 
1216#if MG_ARCH == MG_ARCH_WIN32
1217struct dirent {
1218 char d_name[MAX_PATH];
1219};
1220 
1221typedef struct win32_dir {
1222 HANDLE handle;
1223 WIN32_FIND_DATAW info;
1224 struct dirent result;
1225} DIR;
1226 
1227#if 0
1228int gettimeofday(struct timeval *tv, void *tz) {
1229 FILETIME ft;
1230 unsigned __int64 tmpres = 0;
1231 
1232 if (tv != NULL) {
1233 GetSystemTimeAsFileTime(&ft);
1234 tmpres |= ft.dwHighDateTime;
1235 tmpres <<= 32;
1236 tmpres |= ft.dwLowDateTime;
1237 tmpres /= 10; // convert into microseconds
1238 tmpres -= (int64_t) 11644473600000000;
1239 tv->tv_sec = (long) (tmpres / 1000000UL);
1240 tv->tv_usec = (long) (tmpres % 1000000UL);
1241 }
1242 (void) tz;
1243 return 0;
1244}
1245#endif
1246 
1247static int to_wchar(const char *path, wchar_t *wbuf, size_t wbuf_len) {
1248 int ret;
1249 char buf[MAX_PATH * 2], buf2[MAX_PATH * 2], *p;
1250 strncpy(buf, path, sizeof(buf));
1251 buf[sizeof(buf) - 1] = '\0';
1252 // Trim trailing slashes. Leave backslash for paths like "X:\"
1253 p = buf + strlen(buf) - 1;
1254 while (p > buf && p[-1] != ':' && (p[0] == '\\' || p[0] == '/')) *p-- = '\0';
1255 memset(wbuf, 0, wbuf_len * sizeof(wchar_t));
1256 ret = MultiByteToWideChar(CP_UTF8, 0, buf, -1, wbuf, (int) wbuf_len);
1257 // Convert back to Unicode. If doubly-converted string does not match the
1258 // original, something is fishy, reject.
1259 WideCharToMultiByte(CP_UTF8, 0, wbuf, (int) wbuf_len, buf2, sizeof(buf2),
1260 NULL, NULL);
1261 if (strcmp(buf, buf2) != 0) {
1262 wbuf[0] = L'\0';
1263 ret = 0;
1264 }
1265 return ret;
1266}
1267 
1268DIR *opendir(const char *name) {
1269 DIR *d = NULL;
1270 wchar_t wpath[MAX_PATH];
1271 DWORD attrs;
1272 
1273 if (name == NULL) {
1274 SetLastError(ERROR_BAD_ARGUMENTS);
1275 } else if ((d = (DIR *) calloc(1, sizeof(*d))) == NULL) {
1276 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
1277 } else {
1278 to_wchar(name, wpath, sizeof(wpath) / sizeof(wpath[0]));
1279 attrs = GetFileAttributesW(wpath);
1280 if (attrs != 0Xffffffff && (attrs & FILE_ATTRIBUTE_DIRECTORY)) {
1281 (void) wcscat(wpath, L"\\*");
1282 d->handle = FindFirstFileW(wpath, &d->info);
1283 d->result.d_name[0] = '\0';
1284 } else {
1285 free(d);
1286 d = NULL;
1287 }
1288 }
1289 return d;
1290}
1291 
1292int closedir(DIR *d) {
1293 int result = 0;
1294 if (d != NULL) {
1295 if (d->handle != INVALID_HANDLE_VALUE)
1296 result = FindClose(d->handle) ? 0 : -1;
1297 free(d);
1298 } else {
1299 result = -1;
1300 SetLastError(ERROR_BAD_ARGUMENTS);
1301 }
1302 return result;
1303}
1304 
1305struct dirent *readdir(DIR *d) {
1306 struct dirent *result = NULL;
1307 if (d != NULL) {
1308 memset(&d->result, 0, sizeof(d->result));
1309 if (d->handle != INVALID_HANDLE_VALUE) {
1310 result = &d->result;
1311 WideCharToMultiByte(CP_UTF8, 0, d->info.cFileName, -1, result->d_name,
1312 sizeof(result->d_name), NULL, NULL);
1313 if (!FindNextFileW(d->handle, &d->info)) {
1314 FindClose(d->handle);
1315 d->handle = INVALID_HANDLE_VALUE;
1316 }
1317 } else {
1318 SetLastError(ERROR_FILE_NOT_FOUND);
1319 }
1320 } else {
1321 SetLastError(ERROR_BAD_ARGUMENTS);
1322 }
1323 return result;
1324}
1325#endif
1326 
1327static void p_list(const char *dir, void (*fn)(const char *, void *),
1328 void *userdata) {
1329#if MG_ENABLE_DIRLIST
1330 struct dirent *dp;
1331 DIR *dirp;
1332 if ((dirp = (opendir(dir))) == NULL) return;
1333 while ((dp = readdir(dirp)) != NULL) {
1334 if (!strcmp(dp->d_name, ".") || !strcmp(dp->d_name, "..")) continue;
1335 fn(dp->d_name, userdata);
1336 }
1337 closedir(dirp);
1338#else
1339 (void) dir, (void) fn, (void) userdata;
1340#endif
1341}
1342 
1343static void *p_open(const char *path, int flags) {
1344#if MG_ARCH == MG_ARCH_WIN32
1345 const char *mode = flags == MG_FS_READ ? "rb" : "a+b";
1346 wchar_t b1[MG_PATH_MAX], b2[10];
1347 MultiByteToWideChar(CP_UTF8, 0, path, -1, b1, sizeof(b1) / sizeof(b1[0]));
1348 MultiByteToWideChar(CP_UTF8, 0, mode, -1, b2, sizeof(b2) / sizeof(b2[0]));
1349 return (void *) _wfopen(b1, b2);
1350#else
1351 const char *mode = flags == MG_FS_READ ? "rbe" : "a+be"; // e for CLOEXEC
1352 return (void *) fopen(path, mode);
1353#endif
1354}
1355 
1356static void p_close(void *fp) {
1357 fclose((FILE *) fp);
1358}
1359 
1360static size_t p_read(void *fp, void *buf, size_t len) {
1361 return fread(buf, 1, len, (FILE *) fp);
1362}
1363 
1364static size_t p_write(void *fp, const void *buf, size_t len) {
1365 return fwrite(buf, 1, len, (FILE *) fp);
1366}
1367 
1368static size_t p_seek(void *fp, size_t offset) {
1369#if (defined(_FILE_OFFSET_BITS) && _FILE_OFFSET_BITS == 64) || \
1370 (defined(_POSIX_C_SOURCE) && _POSIX_C_SOURCE >= 200112L) || \
1371 (defined(_XOPEN_SOURCE) && _XOPEN_SOURCE >= 600)
1372 if (fseeko((FILE *) fp, (off_t) offset, SEEK_SET) != 0) (void) 0;
1373#else
1374 if (fseek((FILE *) fp, (long) offset, SEEK_SET) != 0) (void) 0;
1375#endif
1376 return (size_t) ftell((FILE *) fp);
1377}
1378 
1379static bool p_rename(const char *from, const char *to) {
1380 return rename(from, to) == 0;
1381}
1382 
1383static bool p_remove(const char *path) {
1384 return remove(path) == 0;
1385}
1386 
1387static bool p_mkdir(const char *path) {
1388 return mkdir(path, 0775) == 0;
1389}
1390 
1391#else
1392 
1393static int p_stat(const char *path, size_t *size, time_t *mtime) {
1394 (void) path, (void) size, (void) mtime;
1395 return 0;
1396}
1397static void p_list(const char *path, void (*fn)(const char *, void *),
1398 void *userdata) {
1399 (void) path, (void) fn, (void) userdata;
1400}
1401static void *p_open(const char *path, int flags) {
1402 (void) path, (void) flags;
1403 return NULL;
1404}
1405static void p_close(void *fp) {
1406 (void) fp;
1407}
1408static size_t p_read(void *fd, void *buf, size_t len) {
1409 (void) fd, (void) buf, (void) len;
1410 return 0;
1411}
1412static size_t p_write(void *fd, const void *buf, size_t len) {
1413 (void) fd, (void) buf, (void) len;
1414 return 0;
1415}
1416static size_t p_seek(void *fd, size_t offset) {
1417 (void) fd, (void) offset;
1418 return (size_t) ~0;
1419}
1420static bool p_rename(const char *from, const char *to) {
1421 (void) from, (void) to;
1422 return false;
1423}
1424static bool p_remove(const char *path) {
1425 (void) path;
1426 return false;
1427}
1428static bool p_mkdir(const char *path) {
1429 (void) path;
1430 return false;
1431}
1432#endif
1433 
1434struct mg_fs mg_fs_posix = {p_stat, p_list, p_open, p_close, p_read,
1435 p_write, p_seek, p_rename, p_remove, p_mkdir};
1436 
1437#ifdef MG_ENABLE_LINES
1438#line 1 "src/http.c"
1439#endif
1440 
1441 
1442 
1443 
1444 
1445 
1446 
1447 
1448 
1449 
1450 
1451 
1452 
1453static int mg_ncasecmp(const char *s1, const char *s2, size_t len) {
1454 int diff = 0;
1455 if (len > 0) do {
1456 int c = *s1++, d = *s2++;
1457 if (c >= 'A' && c <= 'Z') c += 'a' - 'A';
1458 if (d >= 'A' && d <= 'Z') d += 'a' - 'A';
1459 diff = c - d;
1460 } while (diff == 0 && s1[-1] != '\0' && --len > 0);
1461 return diff;
1462}
1463 
1464bool mg_to_size_t(struct mg_str str, size_t *val);
1465bool mg_to_size_t(struct mg_str str, size_t *val) {
1466 size_t i = 0, max = (size_t) -1, max2 = max / 10, result = 0, ndigits = 0;
1467 while (i < str.len && (str.buf[i] == ' ' || str.buf[i] == '\t')) i++;
1468 if (i < str.len && str.buf[i] == '-') return false;
1469 while (i < str.len && str.buf[i] >= '0' && str.buf[i] <= '9') {
1470 size_t digit = (size_t) (str.buf[i] - '0');
1471 if (result > max2) return false; // Overflow
1472 result *= 10;
1473 if (result > max - digit) return false; // Overflow
1474 result += digit;
1475 i++, ndigits++;
1476 }
1477 while (i < str.len && (str.buf[i] == ' ' || str.buf[i] == '\t')) i++;
1478 if (ndigits == 0) return false; // #2322: Content-Length = 1 * DIGIT
1479 if (i != str.len) return false; // Ditto
1480 *val = (size_t) result;
1481 return true;
1482}
1483 
1484// Chunk deletion marker is the MSB in the "processed" counter
1485#define MG_DMARK ((size_t) 1 << (sizeof(size_t) * 8 - 1))
1486 
1487// Multipart POST example:
1488// --xyz
1489// Content-Disposition: form-data; name="val"
1490//
1491// abcdef
1492// --xyz
1493// Content-Disposition: form-data; name="foo"; filename="a.txt"
1494// Content-Type: text/plain
1495//
1496// hello world
1497//
1498// --xyz--
1499size_t mg_http_next_multipart(struct mg_str body, size_t ofs,
1500 struct mg_http_part *part) {
1501 struct mg_str cd = mg_str_n("Content-Disposition", 19);
1502 const char *s = body.buf;
1503 size_t b = ofs, h1, h2, b1, b2, max = body.len;
1504 
1505 // Init part params
1506 if (part != NULL) part->name = part->filename = part->body = mg_str_n(0, 0);
1507 
1508 // Skip boundary
1509 while (b + 2 < max && s[b] != '\r' && s[b + 1] != '\n') b++;
1510 if (b <= ofs || b + 2 >= max) return 0;
1511 // MG_INFO(("B: %zu %zu [%.*s]", ofs, b - ofs, (int) (b - ofs), s));
1512 
1513 // Skip headers
1514 h1 = h2 = b + 2;
1515 for (;;) {
1516 while (h2 + 2 < max && s[h2] != '\r' && s[h2 + 1] != '\n') h2++;
1517 if (h2 == h1) break;
1518 if (h2 + 2 >= max) return 0;
1519 // MG_INFO(("Header: [%.*s]", (int) (h2 - h1), &s[h1]));
1520 if (part != NULL && h1 + cd.len + 2 < h2 && s[h1 + cd.len] == ':' &&
1521 mg_ncasecmp(&s[h1], cd.buf, cd.len) == 0) {
1522 struct mg_str v = mg_str_n(&s[h1 + cd.len + 2], h2 - (h1 + cd.len + 2));
1523 part->name = mg_http_get_header_var(v, mg_str_n("name", 4));
1524 part->filename = mg_http_get_header_var(v, mg_str_n("filename", 8));
1525 }
1526 h1 = h2 = h2 + 2;
1527 }
1528 b1 = b2 = h2 + 2;
1529 while (b2 + 2 + (b - ofs) + 2 < max && !(s[b2] == '\r' && s[b2 + 1] == '\n' &&
1530 memcmp(&s[b2 + 2], s, b - ofs) == 0))
1531 b2++;
1532 
1533 if (b2 + 2 >= max) return 0;
1534 if (part != NULL) part->body = mg_str_n(&s[b1], b2 - b1);
1535 // MG_INFO(("Body: [%.*s]", (int) (b2 - b1), &s[b1]));
1536 return b2 + 2;
1537}
1538 
1539void mg_http_bauth(struct mg_connection *c, const char *user,
1540 const char *pass) {
1541 struct mg_str u = mg_str(user), p = mg_str(pass);
1542 size_t need = c->send.len + 36 + (u.len + p.len) * 2;
1543 if (c->send.size < need) mg_iobuf_resize(&c->send, need);
1544 if (c->send.size >= need) {
1545 size_t i, n = 0;
1546 char *buf = (char *) &c->send.buf[c->send.len];
1547 memcpy(buf, "Authorization: Basic ", 21); // DON'T use mg_send!
1548 for (i = 0; i < u.len; i++) {
1549 n = mg_base64_update(((unsigned char *) u.buf)[i], buf + 21, n);
1550 }
1551 if (p.len > 0) {
1552 n = mg_base64_update(':', buf + 21, n);
1553 for (i = 0; i < p.len; i++) {
1554 n = mg_base64_update(((unsigned char *) p.buf)[i], buf + 21, n);
1555 }
1556 }
1557 n = mg_base64_final(buf + 21, n);
1558 c->send.len += 21 + (size_t) n + 2;
1559 memcpy(&c->send.buf[c->send.len - 2], "\r\n", 2);
1560 } else {
1561 MG_ERROR(("%lu oom %d->%d ", c->id, (int) c->send.size, (int) need));
1562 }
1563}
1564 
1565struct mg_str mg_http_var(struct mg_str buf, struct mg_str name) {
1566 struct mg_str entry, k, v, result = mg_str_n(NULL, 0);
1567 while (mg_span(buf, &entry, &buf, '&')) {
1568 if (mg_span(entry, &k, &v, '=') && name.len == k.len &&
1569 mg_ncasecmp(name.buf, k.buf, k.len) == 0) {
1570 result = v;
1571 break;
1572 }
1573 }
1574 return result;
1575}
1576 
1577int mg_http_get_var(const struct mg_str *buf, const char *name, char *dst,
1578 size_t dst_len) {
1579 int len;
1580 if (dst != NULL && dst_len > 0) {
1581 dst[0] = '\0'; // If destination buffer is valid, always nul-terminate it
1582 }
1583 if (dst == NULL || dst_len == 0) {
1584 len = -2; // Bad destination
1585 } else if (buf->buf == NULL || name == NULL || buf->len == 0) {
1586 len = -1; // Bad source
1587 } else {
1588 struct mg_str v = mg_http_var(*buf, mg_str(name));
1589 if (v.buf == NULL) {
1590 len = -4; // Name does not exist
1591 } else {
1592 len = mg_url_decode(v.buf, v.len, dst, dst_len, 1);
1593 if (len < 0) len = -3; // Failed to decode
1594 }
1595 }
1596 return len;
1597}
1598 
1599static bool isx(int c) {
1600 return (c >= '0' && c <= '9') || (c >= 'a' && c <= 'f') ||
1601 (c >= 'A' && c <= 'F');
1602}
1603 
1604int mg_url_decode(const char *src, size_t src_len, char *dst, size_t dst_len,
1605 int is_form_url_encoded) {
1606 size_t i, j;
1607 for (i = j = 0; i < src_len && j + 1 < dst_len; i++, j++) {
1608 if (src[i] == '%') {
1609 // Use `i + 2 < src_len`, not `i < src_len - 2`, note small src_len
1610 if (i + 2 < src_len && isx(src[i + 1]) && isx(src[i + 2])) {
1611 mg_str_to_num(mg_str_n(src + i + 1, 2), 16, &dst[j], sizeof(uint8_t));
1612 i += 2;
1613 } else {
1614 return -1;
1615 }
1616 } else if (is_form_url_encoded && src[i] == '+') {
1617 dst[j] = ' ';
1618 } else {
1619 dst[j] = src[i];
1620 }
1621 }
1622 if (j < dst_len) dst[j] = '\0'; // Null-terminate the destination
1623 return i >= src_len && j < dst_len ? (int) j : -1;
1624}
1625 
1626static bool isok(uint8_t c) {
1627 return c == '\n' || c == '\r' || c == '\t' || c >= ' ';
1628}
1629 
1630int mg_http_get_request_len(const unsigned char *buf, size_t buf_len) {
1631 size_t i;
1632 for (i = 0; i < buf_len; i++) {
1633 if (!isok(buf[i])) return -1;
1634 if ((i > 0 && buf[i] == '\n' && buf[i - 1] == '\n') ||
1635 (i > 3 && buf[i] == '\n' && buf[i - 1] == '\r' && buf[i - 2] == '\n'))
1636 return (int) i + 1;
1637 }
1638 return 0;
1639}
1640struct mg_str *mg_http_get_header(struct mg_http_message *h, const char *name) {
1641 size_t i, n = strlen(name), max = sizeof(h->headers) / sizeof(h->headers[0]);
1642 for (i = 0; i < max && h->headers[i].name.len > 0; i++) {
1643 struct mg_str *k = &h->headers[i].name, *v = &h->headers[i].value;
1644 if (n == k->len && mg_ncasecmp(k->buf, name, n) == 0) return v;
1645 }
1646 return NULL;
1647}
1648 
1649// Is it a valid utf-8 continuation byte
1650static bool vcb(uint8_t c) {
1651 return (c & 0xc0) == 0x80;
1652}
1653 
1654// Get character length (valid utf-8). Used to parse method, URI, headers
1655static size_t clen(const char *s, const char *end) {
1656 const unsigned char *u = (unsigned char *) s, c = *u;
1657 long n = (long) (end - s);
1658 if (c > ' ' && c < '~') return 1; // Usual ascii printed char
1659 if ((c & 0xe0) == 0xc0 && n > 1 && vcb(u[1])) return 2; // 2-byte UTF8
1660 if ((c & 0xf0) == 0xe0 && n > 2 && vcb(u[1]) && vcb(u[2])) return 3;
1661 if ((c & 0xf8) == 0xf0 && n > 3 && vcb(u[1]) && vcb(u[2]) && vcb(u[3]))
1662 return 4;
1663 return 0;
1664}
1665 
1666// Skip until the newline. Return advanced `s`, or NULL on error
1667static const char *skiptorn(const char *s, const char *end, struct mg_str *v) {
1668 v->buf = (char *) s;
1669 while (s < end && s[0] != '\n' && s[0] != '\r') s++, v->len++; // To newline
1670 if (s >= end || (s[0] == '\r' && s[1] != '\n')) return NULL; // Stray \r
1671 if (s < end && s[0] == '\r') s++; // Skip \r
1672 if (s >= end || *s++ != '\n') return NULL; // Skip \n
1673 return s;
1674}
1675 
1676static bool mg_http_parse_headers(const char *s, const char *end,
1677 struct mg_http_header *h, size_t max_hdrs) {
1678 size_t i, n;
1679 for (i = 0; i < max_hdrs; i++) {
1680 struct mg_str k = {NULL, 0}, v = {NULL, 0};
1681 if (s >= end) return false;
1682 if (s[0] == '\n' || (s[0] == '\r' && s[1] == '\n')) break;
1683 k.buf = (char *) s;
1684 while (s < end && s[0] != ':' && (n = clen(s, end)) > 0) s += n, k.len += n;
1685 if (k.len == 0) return false; // Empty name
1686 if (s >= end || clen(s, end) == 0) return false; // Invalid UTF-8
1687 if (*s++ != ':') return false; // Invalid, not followed by :
1688 // if (clen(s, end) == 0) return false; // Invalid UTF-8
1689 while (s < end && (s[0] == ' ' || s[0] == '\t')) s++; // Skip spaces
1690 if ((s = skiptorn(s, end, &v)) == NULL) return false;
1691 while (v.len > 0 && (v.buf[v.len - 1] == ' ' || v.buf[v.len - 1] == '\t')) {
1692 v.len--; // Trim spaces
1693 }
1694 // MG_INFO(("--HH [%.*s] [%.*s]", (int) k.len, k.buf, (int) v.len, v.buf));
1695 h[i].name = k, h[i].value = v; // Success. Assign values
1696 }
1697 return true;
1698}
1699 
1700int mg_http_parse(const char *s, size_t len, struct mg_http_message *hm) {
1701 int is_response, req_len = mg_http_get_request_len((unsigned char *) s, len);
1702 const char *end = s == NULL ? NULL : s + req_len, *qs; // Cannot add to NULL
1703 const struct mg_str *cl;
1704 size_t n;
1705 bool version_prefix_valid;
1706 
1707 memset(hm, 0, sizeof(*hm));
1708 if (req_len <= 0) return req_len;
1709 
1710 hm->message.buf = hm->head.buf = (char *) s;
1711 hm->body.buf = (char *) end;
1712 hm->head.len = (size_t) req_len;
1713 hm->message.len = hm->body.len = (size_t) -1; // Set body length to infinite
1714 
1715 // Parse request line
1716 hm->method.buf = (char *) s;
1717 while (s < end && (n = clen(s, end)) > 0) s += n, hm->method.len += n;
1718 while (s < end && s[0] == ' ') s++; // Skip spaces
1719 hm->uri.buf = (char *) s;
1720 while (s < end && (n = clen(s, end)) > 0) s += n, hm->uri.len += n;
1721 while (s < end && s[0] == ' ') s++; // Skip spaces
1722 is_response = hm->method.len > 5 &&
1723 (mg_ncasecmp(hm->method.buf, "HTTP/", 5) == 0);
1724 if ((s = skiptorn(s, end, &hm->proto)) == NULL) return false;
1725 // If we're given a version, check that it is HTTP/x.x
1726 version_prefix_valid = hm->proto.len > 5 &&
1727 (mg_ncasecmp(hm->proto.buf, "HTTP/", 5) == 0);
1728 if (!is_response && hm->proto.len > 0 &&
1729 (!version_prefix_valid || hm->proto.len != 8 ||
1730 (hm->proto.buf[5] < '0' || hm->proto.buf[5] > '9') ||
1731 (hm->proto.buf[6] != '.') ||
1732 (hm->proto.buf[7] < '0' || hm->proto.buf[7] > '9'))) {
1733 return -1;
1734 }
1735 
1736 // If URI contains '?' character, setup query string
1737 if ((qs = (const char *) memchr(hm->uri.buf, '?', hm->uri.len)) != NULL) {
1738 hm->query.buf = (char *) qs + 1;
1739 hm->query.len = (size_t) (&hm->uri.buf[hm->uri.len] - (qs + 1));
1740 hm->uri.len = (size_t) (qs - hm->uri.buf);
1741 }
1742 
1743 // Sanity check. Allow protocol/reason to be empty
1744 // Do this check after hm->method.len and hm->uri.len are finalised
1745 if (hm->method.len == 0 || hm->uri.len == 0) return -1;
1746 
1747 if (!mg_http_parse_headers(s, end, hm->headers,
1748 sizeof(hm->headers) / sizeof(hm->headers[0])))
1749 return -1; // error when parsing
1750 if ((cl = mg_http_get_header(hm, "Content-Length")) != NULL) {
1751 if (mg_to_size_t(*cl, &hm->body.len) == false) return -1;
1752 hm->message.len = (size_t) req_len + hm->body.len;
1753 }
1754 
1755 // mg_http_parse() is used to parse both HTTP requests and HTTP
1756 // responses. If HTTP response does not have Content-Length set, then
1757 // body is read until socket is closed, i.e. body.len is infinite (~0).
1758 //
1759 // For HTTP requests though, according to
1760 // http://tools.ietf.org/html/rfc7231#section-8.1.3,
1761 // only POST and PUT methods have defined body semantics.
1762 // Therefore, if Content-Length is not specified and methods are
1763 // not one of PUT or POST, set body length to 0.
1764 //
1765 // So, if it is HTTP request, and Content-Length is not set,
1766 // and method is not (PUT or POST) then reset body length to zero.
1767 if (hm->body.len == (size_t) ~0 && !is_response &&
1768 mg_strcasecmp(hm->method, mg_str("PUT")) != 0 &&
1769 mg_strcasecmp(hm->method, mg_str("POST")) != 0) {
1770 hm->body.len = 0;
1771 hm->message.len = (size_t) req_len;
1772 }
1773 
1774 // The 204 (No content) responses also have 0 body length
1775 if (hm->body.len == (size_t) ~0 && is_response &&
1776 mg_strcasecmp(hm->uri, mg_str("204")) == 0) {
1777 hm->body.len = 0;
1778 hm->message.len = (size_t) req_len;
1779 }
1780 if (hm->message.len < (size_t) req_len) return -1; // Overflow protection
1781 
1782 return req_len;
1783}
1784 
1785static void mg_http_vprintf_chunk(struct mg_connection *c, const char *fmt,
1786 va_list *ap) {
1787 size_t len = c->send.len;
1788 mg_send(c, " \r\n", 10);
1789 mg_vxprintf(mg_pfn_iobuf, &c->send, fmt, ap);
1790 if (c->send.len >= len + 10) {
1791 mg_snprintf((char *) c->send.buf + len, 9, "%08lx", c->send.len - len - 10);
1792 c->send.buf[len + 8] = '\r';
1793 if (c->send.len == len + 10) c->is_resp = 0; // Last chunk, reset marker
1794 }
1795 mg_send(c, "\r\n", 2);
1796}
1797 
1798void mg_http_printf_chunk(struct mg_connection *c, const char *fmt, ...) {
1799 va_list ap;
1800 va_start(ap, fmt);
1801 mg_http_vprintf_chunk(c, fmt, &ap);
1802 va_end(ap);
1803}
1804 
1805void mg_http_write_chunk(struct mg_connection *c, const char *buf, size_t len) {
1806 mg_printf(c, "%lx\r\n", (unsigned long) len);
1807 mg_send(c, buf, len);
1808 mg_send(c, "\r\n", 2);
1809 if (len == 0) c->is_resp = 0;
1810}
1811 
1812// clang-format off
1813static const char *mg_http_status_code_str(int status_code) {
1814 switch (status_code) {
1815 case 100: return "Continue";
1816 case 101: return "Switching Protocols";
1817 case 102: return "Processing";
1818 case 200: return "OK";
1819 case 201: return "Created";
1820 case 202: return "Accepted";
1821 case 203: return "Non-authoritative Information";
1822 case 204: return "No Content";
1823 case 205: return "Reset Content";
1824 case 206: return "Partial Content";
1825 case 207: return "Multi-Status";
1826 case 208: return "Already Reported";
1827 case 226: return "IM Used";
1828 case 300: return "Multiple Choices";
1829 case 301: return "Moved Permanently";
1830 case 302: return "Found";
1831 case 303: return "See Other";
1832 case 304: return "Not Modified";
1833 case 305: return "Use Proxy";
1834 case 307: return "Temporary Redirect";
1835 case 308: return "Permanent Redirect";
1836 case 400: return "Bad Request";
1837 case 401: return "Unauthorized";
1838 case 402: return "Payment Required";
1839 case 403: return "Forbidden";
1840 case 404: return "Not Found";
1841 case 405: return "Method Not Allowed";
1842 case 406: return "Not Acceptable";
1843 case 407: return "Proxy Authentication Required";
1844 case 408: return "Request Timeout";
1845 case 409: return "Conflict";
1846 case 410: return "Gone";
1847 case 411: return "Length Required";
1848 case 412: return "Precondition Failed";
1849 case 413: return "Payload Too Large";
1850 case 414: return "Request-URI Too Long";
1851 case 415: return "Unsupported Media Type";
1852 case 416: return "Requested Range Not Satisfiable";
1853 case 417: return "Expectation Failed";
1854 case 418: return "I'm a teapot";
1855 case 421: return "Misdirected Request";
1856 case 422: return "Unprocessable Entity";
1857 case 423: return "Locked";
1858 case 424: return "Failed Dependency";
1859 case 426: return "Upgrade Required";
1860 case 428: return "Precondition Required";
1861 case 429: return "Too Many Requests";
1862 case 431: return "Request Header Fields Too Large";
1863 case 444: return "Connection Closed Without Response";
1864 case 451: return "Unavailable For Legal Reasons";
1865 case 499: return "Client Closed Request";
1866 case 500: return "Internal Server Error";
1867 case 501: return "Not Implemented";
1868 case 502: return "Bad Gateway";
1869 case 503: return "Service Unavailable";
1870 case 504: return "Gateway Timeout";
1871 case 505: return "HTTP Version Not Supported";
1872 case 506: return "Variant Also Negotiates";
1873 case 507: return "Insufficient Storage";
1874 case 508: return "Loop Detected";
1875 case 510: return "Not Extended";
1876 case 511: return "Network Authentication Required";
1877 case 599: return "Network Connect Timeout Error";
1878 default: return "";
1879 }
1880}
1881// clang-format on
1882 
1883void mg_http_reply(struct mg_connection *c, int code, const char *headers,
1884 const char *fmt, ...) {
1885 va_list ap;
1886 size_t len;
1887 mg_printf(c, "HTTP/1.1 %d %s\r\n%sContent-Length: \r\n\r\n", code,
1888 mg_http_status_code_str(code), headers == NULL ? "" : headers);
1889 len = c->send.len;
1890 va_start(ap, fmt);
1891 mg_vxprintf(mg_pfn_iobuf, &c->send, fmt, &ap);
1892 va_end(ap);
1893 if (c->send.len > 16) {
1894 size_t n = mg_snprintf((char *) &c->send.buf[len - 15], 11, "%-10lu",
1895 (unsigned long) (c->send.len - len));
1896 c->send.buf[len - 15 + n] = ' '; // Change ending 0 to space
1897 }
1898 c->is_resp = 0;
1899}
1900 
1901static void http_cb(struct mg_connection *, int, void *);
1902static void restore_http_cb(struct mg_connection *c) {
1903 mg_fs_close((struct mg_fd *) c->pfn_data);
1904 c->pfn_data = NULL;
1905 c->pfn = http_cb;
1906 c->is_resp = 0;
1907}
1908 
1909char *mg_http_etag(char *buf, size_t len, size_t size, time_t mtime);
1910char *mg_http_etag(char *buf, size_t len, size_t size, time_t mtime) {
1911 mg_snprintf(buf, len, "\"%lld.%lld\"", (int64_t) mtime, (int64_t) size);
1912 return buf;
1913}
1914 
1915static void static_cb(struct mg_connection *c, int ev, void *ev_data) {
1916 if (ev == MG_EV_WRITE || ev == MG_EV_POLL) {
1917 struct mg_fd *fd = (struct mg_fd *) c->pfn_data;
1918 // Read to send IO buffer directly, avoid extra on-stack buffer
1919 size_t n, max = MG_IO_SIZE, space;
1920 size_t *cl = (size_t *) &c->data[(sizeof(c->data) - sizeof(size_t)) /
1921 sizeof(size_t) * sizeof(size_t)];
1922 if (c->send.size < max) mg_iobuf_resize(&c->send, max);
1923 if (c->send.len >= c->send.size) return; // Rate limit
1924 if ((space = c->send.size - c->send.len) > *cl) space = *cl;
1925 n = fd->fs->rd(fd->fd, c->send.buf + c->send.len, space);
1926 c->send.len += n;
1927 *cl -= n;
1928 if (n == 0) restore_http_cb(c);
1929 } else if (ev == MG_EV_CLOSE) {
1930 restore_http_cb(c);
1931 }
1932 (void) ev_data;
1933}
1934 
1935// Known mime types. Keep it outside guess_content_type() function, since
1936// some environments don't like it defined there.
1937// clang-format off
1938#define MG_C_STR(a) { (char *) (a), sizeof(a) - 1 }
1939static struct mg_str s_known_types[] = {
1940 MG_C_STR("html"), MG_C_STR("text/html; charset=utf-8"),
1941 MG_C_STR("htm"), MG_C_STR("text/html; charset=utf-8"),
1942 MG_C_STR("css"), MG_C_STR("text/css; charset=utf-8"),
1943 MG_C_STR("js"), MG_C_STR("text/javascript; charset=utf-8"),
1944 MG_C_STR("mjs"), MG_C_STR("text/javascript; charset=utf-8"),
1945 MG_C_STR("gif"), MG_C_STR("image/gif"),
1946 MG_C_STR("png"), MG_C_STR("image/png"),
1947 MG_C_STR("jpg"), MG_C_STR("image/jpeg"),
1948 MG_C_STR("jpeg"), MG_C_STR("image/jpeg"),
1949 MG_C_STR("woff"), MG_C_STR("font/woff"),
1950 MG_C_STR("ttf"), MG_C_STR("font/ttf"),
1951 MG_C_STR("svg"), MG_C_STR("image/svg+xml"),
1952 MG_C_STR("txt"), MG_C_STR("text/plain; charset=utf-8"),
1953 MG_C_STR("avi"), MG_C_STR("video/x-msvideo"),
1954 MG_C_STR("csv"), MG_C_STR("text/csv"),
1955 MG_C_STR("doc"), MG_C_STR("application/msword"),
1956 MG_C_STR("exe"), MG_C_STR("application/octet-stream"),
1957 MG_C_STR("gz"), MG_C_STR("application/gzip"),
1958 MG_C_STR("ico"), MG_C_STR("image/x-icon"),
1959 MG_C_STR("json"), MG_C_STR("application/json"),
1960 MG_C_STR("mov"), MG_C_STR("video/quicktime"),
1961 MG_C_STR("mp3"), MG_C_STR("audio/mpeg"),
1962 MG_C_STR("mp4"), MG_C_STR("video/mp4"),
1963 MG_C_STR("mpeg"), MG_C_STR("video/mpeg"),
1964 MG_C_STR("pdf"), MG_C_STR("application/pdf"),
1965 MG_C_STR("shtml"), MG_C_STR("text/html; charset=utf-8"),
1966 MG_C_STR("tgz"), MG_C_STR("application/tar-gz"),
1967 MG_C_STR("wav"), MG_C_STR("audio/wav"),
1968 MG_C_STR("webp"), MG_C_STR("image/webp"),
1969 MG_C_STR("zip"), MG_C_STR("application/zip"),
1970 MG_C_STR("3gp"), MG_C_STR("video/3gpp"),
1971 {0, 0},
1972};
1973// clang-format on
1974 
1975static struct mg_str guess_content_type(struct mg_str path, const char *extra) {
1976 struct mg_str entry, k, v, s = mg_str(extra), asterisk = mg_str_n("*", 1);
1977 size_t i = 0;
1978 
1979 // Shrink path to its extension only
1980 while (i < path.len && path.buf[path.len - i - 1] != '.') i++;
1981 path.buf += path.len - i;
1982 path.len = i;
1983 
1984 // Process user-provided mime type overrides, if any
1985 while (mg_span(s, &entry, &s, ',')) {
1986 if (mg_span(entry, &k, &v, '=') &&
1987 (mg_strcmp(asterisk, k) == 0 || mg_strcmp(path, k) == 0))
1988 return v;
1989 }
1990 
1991 // Process built-in mime types
1992 for (i = 0; s_known_types[i].buf != NULL; i += 2) {
1993 if (mg_strcmp(path, s_known_types[i]) == 0) return s_known_types[i + 1];
1994 }
1995 
1996 return mg_str("text/plain; charset=utf-8");
1997}
1998 
1999static int getrange(struct mg_str *s, size_t *a, size_t *b) {
2000 size_t i, numparsed = 0;
2001 for (i = 0; i + 6 < s->len; i++) {
2002 struct mg_str k, v = mg_str_n(s->buf + i + 6, s->len - i - 6);
2003 if (memcmp(&s->buf[i], "bytes=", 6) != 0) continue;
2004 if (mg_span(v, &k, &v, '-')) {
2005 if (mg_to_size_t(k, a)) numparsed++;
2006 if (v.len > 0 && mg_to_size_t(v, b)) numparsed++;
2007 } else {
2008 if (mg_to_size_t(v, a)) numparsed++;
2009 }
2010 break;
2011 }
2012 return (int) numparsed;
2013}
2014 
2015void mg_http_serve_file(struct mg_connection *c, struct mg_http_message *hm,
2016 const char *path,
2017 const struct mg_http_serve_opts *opts) {
2018 char etag[64], tmp[MG_PATH_MAX];
2019 struct mg_fs *fs = opts->fs == NULL ? &mg_fs_posix : opts->fs;
2020 struct mg_fd *fd = NULL;
2021 size_t size = 0;
2022 time_t mtime = 0;
2023 struct mg_str *inm = NULL;
2024 struct mg_str mime = guess_content_type(mg_str(path), opts->mime_types);
2025 bool gzip = false;
2026 
2027 if (path != NULL) {
2028 // If a browser sends us "Accept-Encoding: gzip", try to open .gz first
2029 struct mg_str *ae = mg_http_get_header(hm, "Accept-Encoding");
2030 if (ae != NULL) {
2031 char *ae_ = mg_mprintf("%.*s", ae->len, ae->buf);
2032 if (ae_ != NULL && strstr(ae_, "gzip") != NULL) {
2033 mg_snprintf(tmp, sizeof(tmp), "%s.gz", path);
2034 fd = mg_fs_open(fs, tmp, MG_FS_READ);
2035 if (fd != NULL) gzip = true, path = tmp;
2036 }
2037 free(ae_);
2038 }
2039 // No luck opening .gz? Open what we've told to open
2040 if (fd == NULL) fd = mg_fs_open(fs, path, MG_FS_READ);
2041 }
2042 
2043 // Failed to open, and page404 is configured? Open it, then
2044 if (fd == NULL && opts->page404 != NULL) {
2045 fd = mg_fs_open(fs, opts->page404, MG_FS_READ);
2046 path = opts->page404;
2047 mime = guess_content_type(mg_str(path), opts->mime_types);
2048 }
2049 
2050 if (fd == NULL || fs->st(path, &size, &mtime) == 0) {
2051 mg_http_reply(c, 404, opts->extra_headers, "Not found\n");
2052 mg_fs_close(fd);
2053 // NOTE: mg_http_etag() call should go first!
2054 } else if (mg_http_etag(etag, sizeof(etag), size, mtime) != NULL &&
2055 (inm = mg_http_get_header(hm, "If-None-Match")) != NULL &&
2056 mg_strcasecmp(*inm, mg_str(etag)) == 0) {
2057 mg_fs_close(fd);
2058 mg_http_reply(c, 304, opts->extra_headers, "");
2059 } else {
2060 int n, status = 200;
2061 char range[100];
2062 size_t r1 = 0, r2 = 0, cl = size;
2063 
2064 // Handle Range header
2065 struct mg_str *rh = mg_http_get_header(hm, "Range");
2066 range[0] = '\0';
2067 if (rh != NULL && (n = getrange(rh, &r1, &r2)) > 0) {
2068 // If range is specified like "400-", set second limit to content len
2069 if (n == 1) r2 = cl - 1;
2070 if (r1 > r2 || r2 >= cl) {
2071 status = 416;
2072 cl = 0;
2073 mg_snprintf(range, sizeof(range), "Content-Range: bytes */%lld\r\n",
2074 (int64_t) size);
2075 } else {
2076 status = 206;
2077 cl = r2 - r1 + 1;
2078 mg_snprintf(range, sizeof(range),
2079 "Content-Range: bytes %llu-%llu/%llu\r\n", (uint64_t) r1,
2080 (uint64_t) (r1 + cl - 1), (uint64_t) size);
2081 fs->sk(fd->fd, r1);
2082 }
2083 }
2084 mg_printf(c,
2085 "HTTP/1.1 %d %s\r\n"
2086 "Content-Type: %.*s\r\n"
2087 "Etag: %s\r\n"
2088 "Content-Length: %llu\r\n"
2089 "%s%s%s\r\n",
2090 status, mg_http_status_code_str(status), (int) mime.len, mime.buf,
2091 etag, (uint64_t) cl, gzip ? "Content-Encoding: gzip\r\n" : "",
2092 range, opts->extra_headers ? opts->extra_headers : "");
2093 if (mg_strcasecmp(hm->method, mg_str("HEAD")) == 0) {
2094 c->is_resp = 0;
2095 mg_fs_close(fd);
2096 } else {
2097 // Track to-be-sent content length at the end of c->data, aligned
2098 size_t *clp = (size_t *) &c->data[(sizeof(c->data) - sizeof(size_t)) /
2099 sizeof(size_t) * sizeof(size_t)];
2100 c->pfn = static_cb;
2101 c->pfn_data = fd;
2102 *clp = cl;
2103 }
2104 }
2105}
2106 
2107struct printdirentrydata {
2108 struct mg_connection *c;
2109 struct mg_http_message *hm;
2110 const struct mg_http_serve_opts *opts;
2111 const char *dir;
2112};
2113 
2114#if MG_ENABLE_DIRLIST
2115static void printdirentry(const char *name, void *userdata) {
2116 struct printdirentrydata *d = (struct printdirentrydata *) userdata;
2117 struct mg_fs *fs = d->opts->fs == NULL ? &mg_fs_posix : d->opts->fs;
2118 size_t size = 0;
2119 time_t t = 0;
2120 char path[MG_PATH_MAX], sz[40], mod[40];
2121 int flags, n = 0;
2122 
2123 // MG_DEBUG(("[%s] [%s]", d->dir, name));
2124 if (mg_snprintf(path, sizeof(path), "%s%c%s", d->dir, '/', name) >
2125 sizeof(path)) {
2126 MG_ERROR(("%s truncated", name));
2127 } else if ((flags = fs->st(path, &size, &t)) == 0) {
2128 MG_ERROR(("%lu stat(%s): %d", d->c->id, path, errno));
2129 } else {
2130 const char *slash = flags & MG_FS_DIR ? "/" : "";
2131 if (flags & MG_FS_DIR) {
2132 mg_snprintf(sz, sizeof(sz), "%s", "[DIR]");
2133 } else {
2134 mg_snprintf(sz, sizeof(sz), "%lld", (uint64_t) size);
2135 }
2136#if defined(MG_HTTP_DIRLIST_TIME_FMT)
2137 {
2138 char time_str[40];
2139 struct tm *time_info = localtime(&t);
2140 strftime(time_str, sizeof time_str, "%Y/%m/%d %H:%M:%S", time_info);
2141 mg_snprintf(mod, sizeof(mod), "%s", time_str);
2142 }
2143#else
2144 mg_snprintf(mod, sizeof(mod), "%lu", (unsigned long) t);
2145#endif
2146 n = (int) mg_url_encode(name, strlen(name), path, sizeof(path));
2147 mg_printf(d->c,
2148 " <tr><td><a href=\"%.*s%s\">%s%s</a></td>"
2149 "<td name=%lu>%s</td><td name=%lld>%s</td></tr>\n",
2150 n, path, slash, name, slash, (unsigned long) t, mod,
2151 flags & MG_FS_DIR ? (int64_t) -1 : (int64_t) size, sz);
2152 }
2153}
2154 
2155static void listdir(struct mg_connection *c, struct mg_http_message *hm,
2156 const struct mg_http_serve_opts *opts, char *dir) {
2157 const char *sort_js_code =
2158 "<script>function srt(tb, sc, so, d) {"
2159 "var tr = Array.prototype.slice.call(tb.rows, 0),"
2160 "tr = tr.sort(function (a, b) { var c1 = a.cells[sc], c2 = b.cells[sc],"
2161 "n1 = c1.getAttribute('name'), n2 = c2.getAttribute('name'), "
2162 "t1 = a.cells[2].getAttribute('name'), "
2163 "t2 = b.cells[2].getAttribute('name'); "
2164 "return so * (t1 < 0 && t2 >= 0 ? -1 : t2 < 0 && t1 >= 0 ? 1 : "
2165 "n1 ? parseInt(n2) - parseInt(n1) : "
2166 "c1.textContent.trim().localeCompare(c2.textContent.trim())); });";
2167 const char *sort_js_code2 =
2168 "for (var i = 0; i < tr.length; i++) tb.appendChild(tr[i]); "
2169 "if (!d) window.location.hash = ('sc=' + sc + '&so=' + so); "
2170 "};"
2171 "window.onload = function() {"
2172 "var tb = document.getElementById('tb');"
2173 "var m = /sc=([012]).so=(1|-1)/.exec(window.location.hash) || [0, 2, 1];"
2174 "var sc = m[1], so = m[2]; document.onclick = function(ev) { "
2175 "var c = ev.target.rel; if (c) {if (c == sc) so *= -1; srt(tb, c, so); "
2176 "sc = c; ev.preventDefault();}};"
2177 "srt(tb, sc, so, true);"
2178 "}"
2179 "</script>";
2180 struct mg_fs *fs = opts->fs == NULL ? &mg_fs_posix : opts->fs;
2181 struct printdirentrydata d = {c, hm, opts, dir};
2182 char tmp[10], buf[MG_PATH_MAX];
2183 size_t off, n;
2184 int len = mg_url_decode(hm->uri.buf, hm->uri.len, buf, sizeof(buf), 0);
2185 struct mg_str uri = len > 0 ? mg_str_n(buf, (size_t) len) : hm->uri;
2186 
2187 mg_printf(c,
2188 "HTTP/1.1 200 OK\r\n"
2189 "Content-Type: text/html; charset=utf-8\r\n"
2190 "%s"
2191 "Content-Length: \r\n\r\n",
2192 opts->extra_headers == NULL ? "" : opts->extra_headers);
2193 off = c->send.len; // Start of body
2194 mg_printf(c,
2195 "<!DOCTYPE html><html><head><title>Index of %.*s</title>%s%s"
2196 "<style>th,td {text-align: left; padding-right: 1em; "
2197 "font-family: monospace; }</style></head>"
2198 "<body><h1>Index of %.*s</h1><table cellpadding=\"0\"><thead>"
2199 "<tr><th><a href=\"#\" rel=\"0\">Name</a></th><th>"
2200 "<a href=\"#\" rel=\"1\">Modified</a></th>"
2201 "<th><a href=\"#\" rel=\"2\">Size</a></th></tr>"
2202 "<tr><td colspan=\"3\"><hr></td></tr>"
2203 "</thead>"
2204 "<tbody id=\"tb\">\n",
2205 (int) uri.len, uri.buf, sort_js_code, sort_js_code2, (int) uri.len,
2206 uri.buf);
2207 mg_printf(c, "%s",
2208 " <tr><td><a href=\"..\">..</a></td>"
2209 "<td name=-1></td><td name=-1>[DIR]</td></tr>\n");
2210 
2211 fs->ls(dir, printdirentry, &d);
2212 mg_printf(c,
2213 "</tbody><tfoot><tr><td colspan=\"3\"><hr></td></tr></tfoot>"
2214 "</table><address>Mongoose v.%s</address></body></html>\n",
2215 MG_VERSION);
2216 n = mg_snprintf(tmp, sizeof(tmp), "%lu", (unsigned long) (c->send.len - off));
2217 if (n > sizeof(tmp)) n = 0;
2218 memcpy(c->send.buf + off - 12, tmp, n); // Set content length
2219 c->is_resp = 0; // Mark response end
2220}
2221#endif
2222 
2223// Resolve requested file into `path` and return its fs->st() result
2224static int uri_to_path2(struct mg_connection *c, struct mg_http_message *hm,
2225 struct mg_fs *fs, struct mg_str url, struct mg_str dir,
2226 char *path, size_t path_size) {
2227 int flags, tmp;
2228 // Append URI to the root_dir, and sanitize it
2229 size_t n = mg_snprintf(path, path_size, "%.*s", (int) dir.len, dir.buf);
2230 if (n + 2 >= path_size) {
2231 mg_http_reply(c, 400, "", "Exceeded path size");
2232 return -1;
2233 }
2234 path[path_size - 1] = '\0';
2235 // Terminate root dir with slash
2236 if (n > 0 && path[n - 1] != '/') path[n++] = '/', path[n] = '\0';
2237 if (url.len < hm->uri.len) {
2238 mg_url_decode(hm->uri.buf + url.len, hm->uri.len - url.len, path + n,
2239 path_size - n, 0);
2240 }
2241 path[path_size - 1] = '\0'; // Double-check
2242 if (!mg_path_is_sane(mg_str_n(path, path_size))) {
2243 mg_http_reply(c, 400, "", "Invalid path");
2244 return -1;
2245 }
2246 n = strlen(path);
2247 while (n > 1 && path[n - 1] == '/') path[--n] = 0; // Trim trailing slashes
2248 flags = mg_strcmp(hm->uri, mg_str("/")) == 0 ? MG_FS_DIR
2249 : fs->st(path, NULL, NULL);
2250 MG_VERBOSE(("%lu %.*s -> %s %d", c->id, (int) hm->uri.len, hm->uri.buf, path,
2251 flags));
2252 if (flags == 0) {
2253 // Do nothing - let's caller decide
2254 } else if ((flags & MG_FS_DIR) && hm->uri.len > 0 &&
2255 hm->uri.buf[hm->uri.len - 1] != '/') {
2256 mg_printf(c,
2257 "HTTP/1.1 301 Moved\r\n"
2258 "Location: %.*s/\r\n"
2259 "Content-Length: 0\r\n"
2260 "\r\n",
2261 (int) hm->uri.len, hm->uri.buf);
2262 c->is_resp = 0;
2263 flags = -1;
2264 } else if (flags & MG_FS_DIR) {
2265 if (((mg_snprintf(path + n, path_size - n, "/" MG_HTTP_INDEX) > 0 &&
2266 (tmp = fs->st(path, NULL, NULL)) != 0) ||
2267 (mg_snprintf(path + n, path_size - n, "/index.shtml") > 0 &&
2268 (tmp = fs->st(path, NULL, NULL)) != 0))) {
2269 flags = tmp;
2270 } else if ((mg_snprintf(path + n, path_size - n, "/" MG_HTTP_INDEX ".gz") >
2271 0 &&
2272 (tmp = fs->st(path, NULL, NULL)) !=
2273 0)) { // check for gzipped index
2274 flags = tmp;
2275 path[n + 1 + strlen(MG_HTTP_INDEX)] =
2276 '\0'; // Remove appended .gz in index file name
2277 } else {
2278 path[n] = '\0'; // Remove appended index file name
2279 }
2280 }
2281 return flags;
2282}
2283 
2284static int uri_to_path(struct mg_connection *c, struct mg_http_message *hm,
2285 const struct mg_http_serve_opts *opts, char *path,
2286 size_t path_size) {
2287 struct mg_fs *fs = opts->fs == NULL ? &mg_fs_posix : opts->fs;
2288 struct mg_str k, v, part, s = mg_str(opts->root_dir), u = {NULL, 0}, p = u;
2289 while (mg_span(s, &part, &s, ',')) {
2290 if (!mg_span(part, &k, &v, '=')) k = part, v = mg_str_n(NULL, 0);
2291 if (v.len == 0) v = k, k = mg_str("/"), u = k, p = v;
2292 if (hm->uri.len < k.len) continue;
2293 if (mg_strcmp(k, mg_str_n(hm->uri.buf, k.len)) != 0) continue;
2294 u = k, p = v;
2295 }
2296 return uri_to_path2(c, hm, fs, u, p, path, path_size);
2297}
2298 
2299void mg_http_serve_dir(struct mg_connection *c, struct mg_http_message *hm,
2300 const struct mg_http_serve_opts *opts) {
2301 char path[MG_PATH_MAX];
2302 const char *sp = opts->ssi_pattern;
2303 int flags = uri_to_path(c, hm, opts, path, sizeof(path));
2304 if (flags < 0) {
2305 // Do nothing: the response has already been sent by uri_to_path()
2306 } else if (flags & MG_FS_DIR) {
2307#if MG_ENABLE_DIRLIST
2308 listdir(c, hm, opts, path);
2309#else
2310 mg_http_reply(c, 403, "", "Forbidden\n");
2311#endif
2312 } else if (flags && sp != NULL && mg_match(mg_str(path), mg_str(sp), NULL)) {
2313 mg_http_serve_ssi(c, opts->root_dir, path);
2314 } else {
2315 mg_http_serve_file(c, hm, path, opts);
2316 }
2317}
2318 
2319static bool mg_is_url_safe(int c) {
2320 return (c >= '0' && c <= '9') || (c >= 'a' && c <= 'z') ||
2321 (c >= 'A' && c <= 'Z') || c == '.' || c == '_' || c == '-' || c == '~';
2322}
2323 
2324size_t mg_url_encode(const char *s, size_t sl, char *buf, size_t len) {
2325 size_t i, n = 0;
2326 for (i = 0; i < sl; i++) {
2327 int c = *(unsigned char *) &s[i];
2328 if (n + 4 >= len) return 0;
2329 if (mg_is_url_safe(c)) {
2330 buf[n++] = s[i];
2331 } else {
2332 mg_snprintf(&buf[n], 4, "%%%M", mg_print_hex, 1, &s[i]);
2333 n += 3;
2334 }
2335 }
2336 if (len > 0 && n < len - 1) buf[n] = '\0'; // Null-terminate the destination
2337 if (len > 0) buf[len - 1] = '\0'; // Always.
2338 return n;
2339}
2340 
2341void mg_http_creds(struct mg_http_message *hm, char *user, size_t userlen,
2342 char *pass, size_t passlen) {
2343 struct mg_str *v = mg_http_get_header(hm, "Authorization");
2344 user[0] = pass[0] = '\0';
2345 if (v != NULL && v->len > 6 && memcmp(v->buf, "Basic ", 6) == 0) {
2346 char buf[256];
2347 size_t n = mg_base64_decode(v->buf + 6, v->len - 6, buf, sizeof(buf));
2348 const char *p = (const char *) memchr(buf, ':', n > 0 ? n : 0);
2349 if (p != NULL) {
2350 mg_snprintf(user, userlen, "%.*s", p - buf, buf);
2351 mg_snprintf(pass, passlen, "%.*s", n - (size_t) (p - buf) - 1, p + 1);
2352 }
2353 } else if (v != NULL && v->len > 7 && memcmp(v->buf, "Bearer ", 7) == 0) {
2354 mg_snprintf(pass, passlen, "%.*s", (int) v->len - 7, v->buf + 7);
2355 } else if ((v = mg_http_get_header(hm, "Cookie")) != NULL) {
2356 struct mg_str t = mg_http_get_header_var(*v, mg_str_n("access_token", 12));
2357 if (t.len > 0) mg_snprintf(pass, passlen, "%.*s", (int) t.len, t.buf);
2358 } else {
2359 mg_http_get_var(&hm->query, "access_token", pass, passlen);
2360 }
2361}
2362 
2363static struct mg_str stripquotes(struct mg_str s) {
2364 return s.len > 1 && s.buf[0] == '"' && s.buf[s.len - 1] == '"'
2365 ? mg_str_n(s.buf + 1, s.len - 2)
2366 : s;
2367}
2368 
2369struct mg_str mg_http_get_header_var(struct mg_str s, struct mg_str v) {
2370 size_t i;
2371 for (i = 0; v.len > 0 && i + v.len + 2 < s.len; i++) {
2372 if (s.buf[i + v.len] == '=' && memcmp(&s.buf[i], v.buf, v.len) == 0) {
2373 const char *p = &s.buf[i + v.len + 1], *b = p, *x = &s.buf[s.len];
2374 int q = p < x && *p == '"' ? 1 : 0;
2375 while (p < x &&
2376 (q ? p == b || *p != '"' : *p != ';' && *p != ' ' && *p != ','))
2377 p++;
2378 // MG_INFO(("[%.*s] [%.*s] [%.*s]", (int) s.len, s.buf, (int) v.len,
2379 // v.buf, (int) (p - b), b));
2380 return stripquotes(mg_str_n(b, (size_t) (p - b + q)));
2381 }
2382 }
2383 return mg_str_n(NULL, 0);
2384}
2385 
2386long mg_http_upload(struct mg_connection *c, struct mg_http_message *hm,
2387 struct mg_fs *fs, const char *dir, size_t max_size) {
2388 char buf[20] = "0", file[MG_PATH_MAX], path[MG_PATH_MAX];
2389 long res = 0, offset;
2390 mg_http_get_var(&hm->query, "offset", buf, sizeof(buf));
2391 mg_http_get_var(&hm->query, "file", file, sizeof(file));
2392 offset = strtol(buf, NULL, 0);
2393 mg_snprintf(path, sizeof(path), "%s%c%s", dir, MG_DIRSEP, file);
2394 if (hm->body.len == 0) {
2395 mg_http_reply(c, 200, "", "%ld", res); // Nothing to write
2396 } else if (file[0] == '\0') {
2397 mg_http_reply(c, 400, "", "file required");
2398 res = -1;
2399 } else if (mg_path_is_sane(mg_str(file)) == false) {
2400 mg_http_reply(c, 400, "", "%s: invalid file", file);
2401 res = -2;
2402 } else if (offset < 0) {
2403 mg_http_reply(c, 400, "", "offset required");
2404 res = -3;
2405 } else if ((size_t) offset + hm->body.len > max_size) {
2406 mg_http_reply(c, 400, "", "%s: over max size of %lu", path,
2407 (unsigned long) max_size);
2408 res = -4;
2409 } else {
2410 struct mg_fd *fd;
2411 size_t current_size = 0;
2412 MG_DEBUG(("%s -> %lu bytes @ %ld", path, hm->body.len, offset));
2413 if (offset == 0) fs->rm(path); // If offset if 0, truncate file
2414 fs->st(path, &current_size, NULL);
2415 if (offset > 0 && current_size != (size_t) offset) {
2416 mg_http_reply(c, 400, "", "%s: offset mismatch", path);
2417 res = -5;
2418 } else if ((fd = mg_fs_open(fs, path, MG_FS_WRITE)) == NULL) {
2419 mg_http_reply(c, 400, "", "open(%s): %d", path, errno);
2420 res = -6;
2421 } else {
2422 res = offset + (long) fs->wr(fd->fd, hm->body.buf, hm->body.len);
2423 mg_fs_close(fd);
2424 mg_http_reply(c, 200, "", "%ld", res);
2425 }
2426 }
2427 return res;
2428}
2429 
2430int mg_http_status(const struct mg_http_message *hm) {
2431 return atoi(hm->uri.buf);
2432}
2433 
2434static bool is_hex_digit(int c) {
2435 return (c >= '0' && c <= '9') || (c >= 'a' && c <= 'f') ||
2436 (c >= 'A' && c <= 'F');
2437}
2438 
2439static int skip_chunk(const char *buf, int len, int *pl, int *dl) {
2440 int i = 0, n = 0;
2441 if (len < 3) return 0;
2442 while (i < len && is_hex_digit(buf[i])) i++;
2443 if (i == 0) return -1; // Error, no length specified
2444 if (i > (int) sizeof(int) * 2) return -1; // Chunk length is too big
2445 if (len < i + 1 || buf[i] != '\r' || buf[i + 1] != '\n') return -1; // Error
2446 if (mg_str_to_num(mg_str_n(buf, (size_t) i), 16, &n, sizeof(int)) == false)
2447 return -1; // Decode chunk length, overflow
2448 if (n < 0) return -1; // Error. TODO(): some checks now redundant
2449 if (n > len - i - 4) return 0; // Chunk not yet fully buffered
2450 if (buf[i + n + 2] != '\r' || buf[i + n + 3] != '\n') return -1; // Error
2451 *pl = i + 2, *dl = n;
2452 return i + 2 + n + 2;
2453}
2454 
2455static void http_cb(struct mg_connection *c, int ev, void *ev_data) {
2456 if (ev == MG_EV_READ || ev == MG_EV_CLOSE ||
2457 (ev == MG_EV_POLL && c->is_accepted && !c->is_draining &&
2458 c->recv.len > 0)) { // see #2796
2459 struct mg_http_message hm;
2460 size_t ofs = 0; // Parsing offset
2461 while (c->is_resp == 0 && ofs < c->recv.len) {
2462 const char *buf = (char *) c->recv.buf + ofs;
2463 int n = mg_http_parse(buf, c->recv.len - ofs, &hm);
2464 struct mg_str *te; // Transfer - encoding header
2465 bool is_chunked = false;
2466 size_t old_len = c->recv.len;
2467 if (n < 0) {
2468 // We don't use mg_error() here, to avoid closing pipelined requests
2469 // prematurely, see #2592
2470 MG_ERROR(("HTTP parse, %lu bytes", c->recv.len));
2471 c->is_draining = 1;
2472 mg_hexdump(buf, c->recv.len - ofs > 16 ? 16 : c->recv.len - ofs);
2473 c->recv.len = 0;
2474 return;
2475 }
2476 if (n == 0) break; // Request is not buffered yet
2477 mg_call(c, MG_EV_HTTP_HDRS, &hm); // Got all HTTP headers
2478 if (c->recv.len != old_len) {
2479 // User manipulated received data. Wash our hands
2480 MG_DEBUG(("%lu detaching HTTP handler", c->id));
2481 c->pfn = NULL;
2482 return;
2483 }
2484 if (ev == MG_EV_CLOSE) { // If client did not set Content-Length
2485 hm.message.len = c->recv.len - ofs; // and closes now, deliver MSG
2486 hm.body.len = hm.message.len - (size_t) (hm.body.buf - hm.message.buf);
2487 }
2488 if ((te = mg_http_get_header(&hm, "Transfer-Encoding")) != NULL) {
2489 if (mg_strcasecmp(*te, mg_str("chunked")) == 0) {
2490 is_chunked = true;
2491 } else {
2492 mg_error(c, "Invalid Transfer-Encoding"); // See #2460
2493 return;
2494 }
2495 } else if (mg_http_get_header(&hm, "Content-length") == NULL) {
2496 // #2593: HTTP packets must contain either Transfer-Encoding or
2497 // Content-length
2498 bool is_response = mg_ncasecmp(hm.method.buf, "HTTP/", 5) == 0;
2499 bool require_content_len = false;
2500 if (!is_response && (mg_strcasecmp(hm.method, mg_str("POST")) == 0 ||
2501 mg_strcasecmp(hm.method, mg_str("PUT")) == 0)) {
2502 // POST and PUT should include an entity body. Therefore, they should
2503 // contain a Content-length header. Other requests can also contain a
2504 // body, but their content has no defined semantics (RFC 7231)
2505 require_content_len = true;
2506 ofs += (size_t) n; // this request has been processed
2507 } else if (is_response) {
2508 // HTTP spec 7.2 Entity body: All other responses must include a body
2509 // or Content-Length header field defined with a value of 0.
2510 int status = mg_http_status(&hm);
2511 require_content_len = status >= 200 && status != 204 && status != 304;
2512 }
2513 if (require_content_len) {
2514 if (!c->is_client) mg_http_reply(c, 411, "", "");
2515 MG_ERROR(("Content length missing from %s", is_response ? "response" : "request"));
2516 }
2517 }
2518 
2519 if (is_chunked) {
2520 // For chunked data, strip off prefixes and suffixes from chunks
2521 // and relocate them right after the headers, then report a message
2522 char *s = (char *) c->recv.buf + ofs + n;
2523 int o = 0, pl, dl, cl, len = (int) (c->recv.len - ofs - (size_t) n);
2524 
2525 // Find zero-length chunk (the end of the body)
2526 while ((cl = skip_chunk(s + o, len - o, &pl, &dl)) > 0 && dl) o += cl;
2527 if (cl == 0) break; // No zero-len chunk, buffer more data
2528 if (cl < 0) {
2529 mg_error(c, "Invalid chunk");
2530 break;
2531 }
2532 
2533 // Zero chunk found. Second pass: strip + relocate
2534 o = 0, hm.body.len = 0, hm.message.len = (size_t) n;
2535 while ((cl = skip_chunk(s + o, len - o, &pl, &dl)) > 0) {
2536 memmove(s + hm.body.len, s + o + pl, (size_t) dl);
2537 o += cl, hm.body.len += (size_t) dl, hm.message.len += (size_t) dl;
2538 if (dl == 0) break;
2539 }
2540 ofs += (size_t) (n + o);
2541 } else { // Normal, non-chunked data
2542 size_t len = c->recv.len - ofs - (size_t) n;
2543 if (hm.body.len > len) break; // Buffer more data
2544 ofs += (size_t) n + hm.body.len;
2545 }
2546 
2547 if (c->is_accepted) c->is_resp = 1; // Start generating response
2548 mg_call(c, MG_EV_HTTP_MSG, &hm); // User handler can clear is_resp
2549 if (c->is_accepted && !c->is_resp) {
2550 struct mg_str *cc = mg_http_get_header(&hm, "Connection");
2551 if (cc != NULL && mg_strcasecmp(*cc, mg_str("close")) == 0) {
2552 c->is_draining = 1; // honor "Connection: close"
2553 break;
2554 }
2555 }
2556 }
2557 if (ofs > 0) mg_iobuf_del(&c->recv, 0, ofs); // Delete processed data
2558 }
2559 (void) ev_data;
2560}
2561 
2562static void mg_hfn(struct mg_connection *c, int ev, void *ev_data) {
2563 if (ev == MG_EV_HTTP_MSG) {
2564 struct mg_http_message *hm = (struct mg_http_message *) ev_data;
2565 if (mg_match(hm->uri, mg_str("/quit"), NULL)) {
2566 mg_http_reply(c, 200, "", "ok\n");
2567 c->is_draining = 1;
2568 c->data[0] = 'X';
2569 } else if (mg_match(hm->uri, mg_str("/debug"), NULL)) {
2570 int level = (int) mg_json_get_long(hm->body, "$.level", MG_LL_DEBUG);
2571 mg_log_set(level);
2572 mg_http_reply(c, 200, "", "Debug level set to %d\n", level);
2573 } else {
2574 mg_http_reply(c, 200, "", "hi\n");
2575 }
2576 } else if (ev == MG_EV_CLOSE) {
2577 if (c->data[0] == 'X') *(bool *) c->fn_data = true;
2578 }
2579}
2580 
2581void mg_hello(const char *url) {
2582 struct mg_mgr mgr;
2583 bool done = false;
2584 mg_mgr_init(&mgr);
2585 if (mg_http_listen(&mgr, url, mg_hfn, &done) == NULL) done = true;
2586 while (done == false) mg_mgr_poll(&mgr, 100);
2587 mg_mgr_free(&mgr);
2588}
2589 
2590struct mg_connection *mg_http_connect(struct mg_mgr *mgr, const char *url,
2591 mg_event_handler_t fn, void *fn_data) {
2592 struct mg_connection *c = mg_connect(mgr, url, fn, fn_data);
2593 if (c != NULL) c->pfn = http_cb;
2594 return c;
2595}
2596 
2597struct mg_connection *mg_http_listen(struct mg_mgr *mgr, const char *url,
2598 mg_event_handler_t fn, void *fn_data) {
2599 struct mg_connection *c = mg_listen(mgr, url, fn, fn_data);
2600 if (c != NULL) c->pfn = http_cb;
2601 return c;
2602}
2603 
2604#ifdef MG_ENABLE_LINES
2605#line 1 "src/iobuf.c"
2606#endif
2607 
2608 
2609 
2610 
2611 
2612static size_t roundup(size_t size, size_t align) {
2613 return align == 0 ? size : (size + align - 1) / align * align;
2614}
2615 
2616int mg_iobuf_resize(struct mg_iobuf *io, size_t new_size) {
2617 int ok = 1;
2618 new_size = roundup(new_size, io->align);
2619 if (new_size == 0) {
2620 mg_bzero(io->buf, io->size);
2621 free(io->buf);
2622 io->buf = NULL;
2623 io->len = io->size = 0;
2624 } else if (new_size != io->size) {
2625 // NOTE(lsm): do not use realloc here. Use calloc/free only, to ease the
2626 // porting to some obscure platforms like FreeRTOS
2627 void *p = calloc(1, new_size);
2628 if (p != NULL) {
2629 size_t len = new_size < io->len ? new_size : io->len;
2630 if (len > 0 && io->buf != NULL) memmove(p, io->buf, len);
2631 mg_bzero(io->buf, io->size);
2632 free(io->buf);
2633 io->buf = (unsigned char *) p;
2634 io->size = new_size;
2635 } else {
2636 ok = 0;
2637 MG_ERROR(("%lld->%lld", (uint64_t) io->size, (uint64_t) new_size));
2638 }
2639 }
2640 return ok;
2641}
2642 
2643int mg_iobuf_init(struct mg_iobuf *io, size_t size, size_t align) {
2644 io->buf = NULL;
2645 io->align = align;
2646 io->size = io->len = 0;
2647 return mg_iobuf_resize(io, size);
2648}
2649 
2650size_t mg_iobuf_add(struct mg_iobuf *io, size_t ofs, const void *buf,
2651 size_t len) {
2652 size_t new_size = roundup(io->len + len, io->align);
2653 mg_iobuf_resize(io, new_size); // Attempt to resize
2654 if (new_size != io->size) len = 0; // Resize failure, append nothing
2655 if (ofs < io->len) memmove(io->buf + ofs + len, io->buf + ofs, io->len - ofs);
2656 if (buf != NULL) memmove(io->buf + ofs, buf, len);
2657 if (ofs > io->len) io->len += ofs - io->len;
2658 io->len += len;
2659 return len;
2660}
2661 
2662size_t mg_iobuf_del(struct mg_iobuf *io, size_t ofs, size_t len) {
2663 if (ofs > io->len) ofs = io->len;
2664 if (ofs + len > io->len) len = io->len - ofs;
2665 if (io->buf) memmove(io->buf + ofs, io->buf + ofs + len, io->len - ofs - len);
2666 if (io->buf) mg_bzero(io->buf + io->len - len, len);
2667 io->len -= len;
2668 return len;
2669}
2670 
2671void mg_iobuf_free(struct mg_iobuf *io) {
2672 mg_iobuf_resize(io, 0);
2673}
2674 
2675#ifdef MG_ENABLE_LINES
2676#line 1 "src/json.c"
2677#endif
2678 
2679 
2680 
2681 
2682static const char *escapeseq(int esc) {
2683 return esc ? "\b\f\n\r\t\\\"" : "bfnrt\\\"";
2684}
2685 
2686static char json_esc(int c, int esc) {
2687 const char *p, *esc1 = escapeseq(esc), *esc2 = escapeseq(!esc);
2688 for (p = esc1; *p != '\0'; p++) {
2689 if (*p == c) return esc2[p - esc1];
2690 }
2691 return 0;
2692}
2693 
2694static int mg_pass_string(const char *s, int len) {
2695 int i;
2696 for (i = 0; i < len; i++) {
2697 if (s[i] == '\\' && i + 1 < len && json_esc(s[i + 1], 1)) {
2698 i++;
2699 } else if (s[i] == '\0') {
2700 return MG_JSON_INVALID;
2701 } else if (s[i] == '"') {
2702 return i;
2703 }
2704 }
2705 return MG_JSON_INVALID;
2706}
2707 
2708static double mg_atod(const char *p, int len, int *numlen) {
2709 double d = 0.0;
2710 int i = 0, sign = 1;
2711 
2712 // Sign
2713 if (i < len && *p == '-') {
2714 sign = -1, i++;
2715 } else if (i < len && *p == '+') {
2716 i++;
2717 }
2718 
2719 // Decimal
2720 for (; i < len && p[i] >= '0' && p[i] <= '9'; i++) {
2721 d *= 10.0;
2722 d += p[i] - '0';
2723 }
2724 d *= sign;
2725 
2726 // Fractional
2727 if (i < len && p[i] == '.') {
2728 double frac = 0.0, base = 0.1;
2729 i++;
2730 for (; i < len && p[i] >= '0' && p[i] <= '9'; i++) {
2731 frac += base * (p[i] - '0');
2732 base /= 10.0;
2733 }
2734 d += frac * sign;
2735 }
2736 
2737 // Exponential
2738 if (i < len && (p[i] == 'e' || p[i] == 'E')) {
2739 int j, exp = 0, minus = 0;
2740 i++;
2741 if (i < len && p[i] == '-') minus = 1, i++;
2742 if (i < len && p[i] == '+') i++;
2743 while (i < len && p[i] >= '0' && p[i] <= '9' && exp < 308)
2744 exp = exp * 10 + (p[i++] - '0');
2745 if (minus) exp = -exp;
2746 for (j = 0; j < exp; j++) d *= 10.0;
2747 for (j = 0; j < -exp; j++) d /= 10.0;
2748 }
2749 
2750 if (numlen != NULL) *numlen = i;
2751 return d;
2752}
2753 
2754// Iterate over object or array elements
2755size_t mg_json_next(struct mg_str obj, size_t ofs, struct mg_str *key,
2756 struct mg_str *val) {
2757 if (ofs >= obj.len) {
2758 ofs = 0; // Out of boundaries, stop scanning
2759 } else if (obj.len < 2 || (*obj.buf != '{' && *obj.buf != '[')) {
2760 ofs = 0; // Not an array or object, stop
2761 } else {
2762 struct mg_str sub = mg_str_n(obj.buf + ofs, obj.len - ofs);
2763 if (ofs == 0) ofs++, sub.buf++, sub.len--;
2764 if (*obj.buf == '[') { // Iterate over an array
2765 int n = 0, o = mg_json_get(sub, "$", &n);
2766 if (n < 0 || o < 0 || (size_t) (o + n) > sub.len) {
2767 ofs = 0; // Error parsing key, stop scanning
2768 } else {
2769 if (key) *key = mg_str_n(NULL, 0);
2770 if (val) *val = mg_str_n(sub.buf + o, (size_t) n);
2771 ofs = (size_t) (&sub.buf[o + n] - obj.buf);
2772 }
2773 } else { // Iterate over an object
2774 int n = 0, o = mg_json_get(sub, "$", &n);
2775 if (n < 0 || o < 0 || (size_t) (o + n) > sub.len) {
2776 ofs = 0; // Error parsing key, stop scanning
2777 } else {
2778 if (key) *key = mg_str_n(sub.buf + o, (size_t) n);
2779 sub.buf += o + n, sub.len -= (size_t) (o + n);
2780 while (sub.len > 0 && *sub.buf != ':') sub.len--, sub.buf++;
2781 if (sub.len > 0 && *sub.buf == ':') sub.len--, sub.buf++;
2782 n = 0, o = mg_json_get(sub, "$", &n);
2783 if (n < 0 || o < 0 || (size_t) (o + n) > sub.len) {
2784 ofs = 0; // Error parsing value, stop scanning
2785 } else {
2786 if (val) *val = mg_str_n(sub.buf + o, (size_t) n);
2787 ofs = (size_t) (&sub.buf[o + n] - obj.buf);
2788 }
2789 }
2790 }
2791 // MG_INFO(("SUB ofs %u %.*s", ofs, sub.len, sub.buf));
2792 while (ofs && ofs < obj.len &&
2793 (obj.buf[ofs] == ' ' || obj.buf[ofs] == '\t' ||
2794 obj.buf[ofs] == '\n' || obj.buf[ofs] == '\r')) {
2795 ofs++;
2796 }
2797 if (ofs && ofs < obj.len && obj.buf[ofs] == ',') ofs++;
2798 if (ofs > obj.len) ofs = 0;
2799 }
2800 return ofs;
2801}
2802 
2803int mg_json_get(struct mg_str json, const char *path, int *toklen) {
2804 const char *s = json.buf;
2805 int len = (int) json.len;
2806 enum { S_VALUE, S_KEY, S_COLON, S_COMMA_OR_EOO } expecting = S_VALUE;
2807 unsigned char nesting[MG_JSON_MAX_DEPTH];
2808 int i = 0; // Current offset in `s`
2809 int j = 0; // Offset in `s` we're looking for (return value)
2810 int depth = 0; // Current depth (nesting level)
2811 int ed = 0; // Expected depth
2812 int pos = 1; // Current position in `path`
2813 int ci = -1, ei = -1; // Current and expected index in array
2814 
2815 if (toklen) *toklen = 0;
2816 if (path[0] != '$') return MG_JSON_INVALID;
2817 
2818#define MG_CHECKRET(x) \
2819 do { \
2820 if (depth == ed && path[pos] == '\0' && ci == ei) { \
2821 if (toklen) *toklen = i - j + 1; \
2822 return j; \
2823 } \
2824 } while (0)
2825 
2826// In the ascii table, the distance between `[` and `]` is 2.
2827// Ditto for `{` and `}`. Hence +2 in the code below.
2828#define MG_EOO(x) \
2829 do { \
2830 if (depth == ed && ci != ei) return MG_JSON_NOT_FOUND; \
2831 if (c != nesting[depth - 1] + 2) return MG_JSON_INVALID; \
2832 depth--; \
2833 MG_CHECKRET(x); \
2834 } while (0)
2835 
2836 for (i = 0; i < len; i++) {
2837 unsigned char c = ((unsigned char *) s)[i];
2838 if (c == ' ' || c == '\t' || c == '\n' || c == '\r') continue;
2839 switch (expecting) {
2840 case S_VALUE:
2841 // p("V %s [%.*s] %d %d %d %d\n", path, pos, path, depth, ed, ci, ei);
2842 if (depth == ed) j = i;
2843 if (c == '{') {
2844 if (depth >= (int) sizeof(nesting)) return MG_JSON_TOO_DEEP;
2845 if (depth == ed && path[pos] == '.' && ci == ei) {
2846 // If we start the object, reset array indices
2847 ed++, pos++, ci = ei = -1;
2848 }
2849 nesting[depth++] = c;
2850 expecting = S_KEY;
2851 break;
2852 } else if (c == '[') {
2853 if (depth >= (int) sizeof(nesting)) return MG_JSON_TOO_DEEP;
2854 if (depth == ed && path[pos] == '[' && ei == ci) {
2855 ed++, pos++, ci = 0;
2856 for (ei = 0; path[pos] != ']' && path[pos] != '\0'; pos++) {
2857 ei *= 10;
2858 ei += path[pos] - '0';
2859 }
2860 if (path[pos] != 0) pos++;
2861 }
2862 nesting[depth++] = c;
2863 break;
2864 } else if (c == ']' && depth > 0) { // Empty array
2865 MG_EOO(']');
2866 } else if (c == 't' && i + 3 < len && memcmp(&s[i], "true", 4) == 0) {
2867 i += 3;
2868 } else if (c == 'n' && i + 3 < len && memcmp(&s[i], "null", 4) == 0) {
2869 i += 3;
2870 } else if (c == 'f' && i + 4 < len && memcmp(&s[i], "false", 5) == 0) {
2871 i += 4;
2872 } else if (c == '-' || ((c >= '0' && c <= '9'))) {
2873 int numlen = 0;
2874 mg_atod(&s[i], len - i, &numlen);
2875 i += numlen - 1;
2876 } else if (c == '"') {
2877 int n = mg_pass_string(&s[i + 1], len - i - 1);
2878 if (n < 0) return n;
2879 i += n + 1;
2880 } else {
2881 return MG_JSON_INVALID;
2882 }
2883 MG_CHECKRET('V');
2884 if (depth == ed && ei >= 0) ci++;
2885 expecting = S_COMMA_OR_EOO;
2886 break;
2887 
2888 case S_KEY:
2889 if (c == '"') {
2890 int n = mg_pass_string(&s[i + 1], len - i - 1);
2891 if (n < 0) return n;
2892 if (i + 1 + n >= len) return MG_JSON_NOT_FOUND;
2893 if (depth < ed) return MG_JSON_NOT_FOUND;
2894 if (depth == ed && path[pos - 1] != '.') return MG_JSON_NOT_FOUND;
2895 // printf("K %s [%.*s] [%.*s] %d %d %d %d %d\n", path, pos, path, n,
2896 // &s[i + 1], n, depth, ed, ci, ei);
2897 // NOTE(cpq): in the check sequence below is important.
2898 // strncmp() must go first: it fails fast if the remaining length
2899 // of the path is smaller than `n`.
2900 if (depth == ed && path[pos - 1] == '.' &&
2901 strncmp(&s[i + 1], &path[pos], (size_t) n) == 0 &&
2902 (path[pos + n] == '\0' || path[pos + n] == '.' ||
2903 path[pos + n] == '[')) {
2904 pos += n;
2905 }
2906 i += n + 1;
2907 expecting = S_COLON;
2908 } else if (c == '}') { // Empty object
2909 MG_EOO('}');
2910 expecting = S_COMMA_OR_EOO;
2911 if (depth == ed && ei >= 0) ci++;
2912 } else {
2913 return MG_JSON_INVALID;
2914 }
2915 break;
2916 
2917 case S_COLON:
2918 if (c == ':') {
2919 expecting = S_VALUE;
2920 } else {
2921 return MG_JSON_INVALID;
2922 }
2923 break;
2924 
2925 case S_COMMA_OR_EOO:
2926 if (depth <= 0) {
2927 return MG_JSON_INVALID;
2928 } else if (c == ',') {
2929 expecting = (nesting[depth - 1] == '{') ? S_KEY : S_VALUE;
2930 } else if (c == ']' || c == '}') {
2931 if (depth == ed && c == '}' && path[pos - 1] == '.')
2932 return MG_JSON_NOT_FOUND;
2933 if (depth == ed && c == ']' && path[pos - 1] == ',')
2934 return MG_JSON_NOT_FOUND;
2935 MG_EOO('O');
2936 if (depth == ed && ei >= 0) ci++;
2937 } else {
2938 return MG_JSON_INVALID;
2939 }
2940 break;
2941 }
2942 }
2943 return MG_JSON_NOT_FOUND;
2944}
2945 
2946struct mg_str mg_json_get_tok(struct mg_str json, const char *path) {
2947 int len = 0, ofs = mg_json_get(json, path, &len);
2948 return mg_str_n(ofs < 0 ? NULL : json.buf + ofs,
2949 (size_t) (len < 0 ? 0 : len));
2950}
2951 
2952bool mg_json_get_num(struct mg_str json, const char *path, double *v) {
2953 int n, toklen, found = 0;
2954 if ((n = mg_json_get(json, path, &toklen)) >= 0 &&
2955 (json.buf[n] == '-' || (json.buf[n] >= '0' && json.buf[n] <= '9'))) {
2956 if (v != NULL) *v = mg_atod(json.buf + n, toklen, NULL);
2957 found = 1;
2958 }
2959 return found;
2960}
2961 
2962bool mg_json_get_bool(struct mg_str json, const char *path, bool *v) {
2963 int found = 0, off = mg_json_get(json, path, NULL);
2964 if (off >= 0 && (json.buf[off] == 't' || json.buf[off] == 'f')) {
2965 if (v != NULL) *v = json.buf[off] == 't';
2966 found = 1;
2967 }
2968 return found;
2969}
2970 
2971bool mg_json_unescape(struct mg_str s, char *to, size_t n) {
2972 size_t i, j;
2973 for (i = 0, j = 0; i < s.len && j < n; i++, j++) {
2974 if (s.buf[i] == '\\' && i + 5 < s.len && s.buf[i + 1] == 'u') {
2975 // \uXXXX escape. We process simple one-byte chars \u00xx within ASCII
2976 // range. More complex chars would require dragging in a UTF8 library,
2977 // which is too much for us
2978 if (mg_str_to_num(mg_str_n(s.buf + i + 2, 4), 16, &to[j],
2979 sizeof(uint8_t)) == false)
2980 return false;
2981 i += 5;
2982 } else if (s.buf[i] == '\\' && i + 1 < s.len) {
2983 char c = json_esc(s.buf[i + 1], 0);
2984 if (c == 0) return false;
2985 to[j] = c;
2986 i++;
2987 } else {
2988 to[j] = s.buf[i];
2989 }
2990 }
2991 if (j >= n) return false;
2992 if (n > 0) to[j] = '\0';
2993 return true;
2994}
2995 
2996char *mg_json_get_str(struct mg_str json, const char *path) {
2997 char *result = NULL;
2998 int len = 0, off = mg_json_get(json, path, &len);
2999 if (off >= 0 && len > 1 && json.buf[off] == '"') {
3000 if ((result = (char *) calloc(1, (size_t) len)) != NULL &&
3001 !mg_json_unescape(mg_str_n(json.buf + off + 1, (size_t) (len - 2)),
3002 result, (size_t) len)) {
3003 free(result);
3004 result = NULL;
3005 }
3006 }
3007 return result;
3008}
3009 
3010char *mg_json_get_b64(struct mg_str json, const char *path, int *slen) {
3011 char *result = NULL;
3012 int len = 0, off = mg_json_get(json, path, &len);
3013 if (off >= 0 && json.buf[off] == '"' && len > 1 &&
3014 (result = (char *) calloc(1, (size_t) len)) != NULL) {
3015 size_t k = mg_base64_decode(json.buf + off + 1, (size_t) (len - 2), result,
3016 (size_t) len);
3017 if (slen != NULL) *slen = (int) k;
3018 }
3019 return result;
3020}
3021 
3022char *mg_json_get_hex(struct mg_str json, const char *path, int *slen) {
3023 char *result = NULL;
3024 int len = 0, off = mg_json_get(json, path, &len);
3025 if (off >= 0 && json.buf[off] == '"' && len > 1 &&
3026 (result = (char *) calloc(1, (size_t) len / 2)) != NULL) {
3027 int i;
3028 for (i = 0; i < len - 2; i += 2) {
3029 mg_str_to_num(mg_str_n(json.buf + off + 1 + i, 2), 16, &result[i >> 1],
3030 sizeof(uint8_t));
3031 }
3032 result[len / 2 - 1] = '\0';
3033 if (slen != NULL) *slen = len / 2 - 1;
3034 }
3035 return result;
3036}
3037 
3038long mg_json_get_long(struct mg_str json, const char *path, long dflt) {
3039 double dv;
3040 long result = dflt;
3041 if (mg_json_get_num(json, path, &dv)) result = (long) dv;
3042 return result;
3043}
3044 
3045#ifdef MG_ENABLE_LINES
3046#line 1 "src/log.c"
3047#endif
3048 
3049 
3050 
3051 
3052 
3053int mg_log_level = MG_LL_INFO;
3054static mg_pfn_t s_log_func = mg_pfn_stdout;
3055static void *s_log_func_param = NULL;
3056 
3057void mg_log_set_fn(mg_pfn_t fn, void *param) {
3058 s_log_func = fn;
3059 s_log_func_param = param;
3060}
3061 
3062static void logc(unsigned char c) {
3063 s_log_func((char) c, s_log_func_param);
3064}
3065 
3066static void logs(const char *buf, size_t len) {
3067 size_t i;
3068 for (i = 0; i < len; i++) logc(((unsigned char *) buf)[i]);
3069}
3070 
3071#if MG_ENABLE_CUSTOM_LOG
3072// Let user define their own mg_log_prefix() and mg_log()
3073#else
3074void mg_log_prefix(int level, const char *file, int line, const char *fname) {
3075 const char *p = strrchr(file, '/');
3076 char buf[41];
3077 size_t n;
3078 if (p == NULL) p = strrchr(file, '\\');
3079 n = mg_snprintf(buf, sizeof(buf), "%-6llx %d %s:%d:%s", mg_millis(), level,
3080 p == NULL ? file : p + 1, line, fname);
3081 if (n > sizeof(buf) - 2) n = sizeof(buf) - 2;
3082 while (n < sizeof(buf)) buf[n++] = ' ';
3083 logs(buf, n - 1);
3084}
3085 
3086void mg_log(const char *fmt, ...) {
3087 va_list ap;
3088 va_start(ap, fmt);
3089 mg_vxprintf(s_log_func, s_log_func_param, fmt, &ap);
3090 va_end(ap);
3091 logs("\r\n", 2);
3092}
3093#endif
3094 
3095static unsigned char nibble(unsigned c) {
3096 return (unsigned char) (c < 10 ? c + '0' : c + 'W');
3097}
3098 
3099#define ISPRINT(x) ((x) >= ' ' && (x) <= '~')
3100void mg_hexdump(const void *buf, size_t len) {
3101 const unsigned char *p = (const unsigned char *) buf;
3102 unsigned char ascii[16], alen = 0;
3103 size_t i;
3104 for (i = 0; i < len; i++) {
3105 if ((i % 16) == 0) {
3106 // Print buffered ascii chars
3107 if (i > 0)
3108 logs(" ", 2), logs((char *) ascii, 16), logs("\r\n", 2), alen = 0;
3109 // Print hex address, then \t
3110 logc(nibble((i >> 12) & 15)), logc(nibble((i >> 8) & 15)),
3111 logc(nibble((i >> 4) & 15)), logc('0'), logs(" ", 3);
3112 }
3113 logc(nibble(p[i] >> 4)), logc(nibble(p[i] & 15)); // Two nibbles, e.g. c5
3114 logc(' '); // Space after hex number
3115 ascii[alen++] = ISPRINT(p[i]) ? p[i] : '.'; // Add to the ascii buf
3116 }
3117 while (alen < 16) logs(" ", 3), ascii[alen++] = ' ';
3118 logs(" ", 2), logs((char *) ascii, 16), logs("\r\n", 2);
3119}
3120 
3121#ifdef MG_ENABLE_LINES
3122#line 1 "src/md5.c"
3123#endif
3124 
3125 
3126 
3127// This code implements the MD5 message-digest algorithm.
3128// The algorithm is due to Ron Rivest. This code was
3129// written by Colin Plumb in 1993, no copyright is claimed.
3130// This code is in the public domain; do with it what you wish.
3131//
3132// Equivalent code is available from RSA Data Security, Inc.
3133// This code has been tested against that, and is equivalent,
3134// except that you don't need to include two pages of legalese
3135// with every copy.
3136//
3137// To compute the message digest of a chunk of bytes, declare an
3138// MD5Context structure, pass it to MD5Init, call MD5Update as
3139// needed on buffers full of bytes, and then call MD5Final, which
3140// will fill a supplied 16-byte array with the digest.
3141 
3142#if defined(MG_ENABLE_MD5) && MG_ENABLE_MD5
3143 
3144static void mg_byte_reverse(unsigned char *buf, unsigned longs) {
3145 if (MG_BIG_ENDIAN) {
3146 do {
3147 uint32_t t = (uint32_t) ((unsigned) buf[3] << 8 | buf[2]) << 16 |
3148 ((unsigned) buf[1] << 8 | buf[0]);
3149 *(uint32_t *) buf = t;
3150 buf += 4;
3151 } while (--longs);
3152 } else {
3153 (void) buf, (void) longs; // Little endian. Do nothing
3154 }
3155}
3156 
3157#define F1(x, y, z) (z ^ (x & (y ^ z)))
3158#define F2(x, y, z) F1(z, x, y)
3159#define F3(x, y, z) (x ^ y ^ z)
3160#define F4(x, y, z) (y ^ (x | ~z))
3161 
3162#define MD5STEP(f, w, x, y, z, data, s) \
3163 (w += f(x, y, z) + data, w = w << s | w >> (32 - s), w += x)
3164 
3165/*
3166 * Start MD5 accumulation. Set bit count to 0 and buffer to mysterious
3167 * initialization constants.
3168 */
3169void mg_md5_init(mg_md5_ctx *ctx) {
3170 ctx->buf[0] = 0x67452301;
3171 ctx->buf[1] = 0xefcdab89;
3172 ctx->buf[2] = 0x98badcfe;
3173 ctx->buf[3] = 0x10325476;
3174 
3175 ctx->bits[0] = 0;
3176 ctx->bits[1] = 0;
3177}
3178 
3179static void mg_md5_transform(uint32_t buf[4], uint32_t const in[16]) {
3180 uint32_t a, b, c, d;
3181 
3182 a = buf[0];
3183 b = buf[1];
3184 c = buf[2];
3185 d = buf[3];
3186 
3187 MD5STEP(F1, a, b, c, d, in[0] + 0xd76aa478, 7);
3188 MD5STEP(F1, d, a, b, c, in[1] + 0xe8c7b756, 12);
3189 MD5STEP(F1, c, d, a, b, in[2] + 0x242070db, 17);
3190 MD5STEP(F1, b, c, d, a, in[3] + 0xc1bdceee, 22);
3191 MD5STEP(F1, a, b, c, d, in[4] + 0xf57c0faf, 7);
3192 MD5STEP(F1, d, a, b, c, in[5] + 0x4787c62a, 12);
3193 MD5STEP(F1, c, d, a, b, in[6] + 0xa8304613, 17);
3194 MD5STEP(F1, b, c, d, a, in[7] + 0xfd469501, 22);
3195 MD5STEP(F1, a, b, c, d, in[8] + 0x698098d8, 7);
3196 MD5STEP(F1, d, a, b, c, in[9] + 0x8b44f7af, 12);
3197 MD5STEP(F1, c, d, a, b, in[10] + 0xffff5bb1, 17);
3198 MD5STEP(F1, b, c, d, a, in[11] + 0x895cd7be, 22);
3199 MD5STEP(F1, a, b, c, d, in[12] + 0x6b901122, 7);
3200 MD5STEP(F1, d, a, b, c, in[13] + 0xfd987193, 12);
3201 MD5STEP(F1, c, d, a, b, in[14] + 0xa679438e, 17);
3202 MD5STEP(F1, b, c, d, a, in[15] + 0x49b40821, 22);
3203 
3204 MD5STEP(F2, a, b, c, d, in[1] + 0xf61e2562, 5);
3205 MD5STEP(F2, d, a, b, c, in[6] + 0xc040b340, 9);
3206 MD5STEP(F2, c, d, a, b, in[11] + 0x265e5a51, 14);
3207 MD5STEP(F2, b, c, d, a, in[0] + 0xe9b6c7aa, 20);
3208 MD5STEP(F2, a, b, c, d, in[5] + 0xd62f105d, 5);
3209 MD5STEP(F2, d, a, b, c, in[10] + 0x02441453, 9);
3210 MD5STEP(F2, c, d, a, b, in[15] + 0xd8a1e681, 14);
3211 MD5STEP(F2, b, c, d, a, in[4] + 0xe7d3fbc8, 20);
3212 MD5STEP(F2, a, b, c, d, in[9] + 0x21e1cde6, 5);
3213 MD5STEP(F2, d, a, b, c, in[14] + 0xc33707d6, 9);
3214 MD5STEP(F2, c, d, a, b, in[3] + 0xf4d50d87, 14);
3215 MD5STEP(F2, b, c, d, a, in[8] + 0x455a14ed, 20);
3216 MD5STEP(F2, a, b, c, d, in[13] + 0xa9e3e905, 5);
3217 MD5STEP(F2, d, a, b, c, in[2] + 0xfcefa3f8, 9);
3218 MD5STEP(F2, c, d, a, b, in[7] + 0x676f02d9, 14);
3219 MD5STEP(F2, b, c, d, a, in[12] + 0x8d2a4c8a, 20);
3220 
3221 MD5STEP(F3, a, b, c, d, in[5] + 0xfffa3942, 4);
3222 MD5STEP(F3, d, a, b, c, in[8] + 0x8771f681, 11);
3223 MD5STEP(F3, c, d, a, b, in[11] + 0x6d9d6122, 16);
3224 MD5STEP(F3, b, c, d, a, in[14] + 0xfde5380c, 23);
3225 MD5STEP(F3, a, b, c, d, in[1] + 0xa4beea44, 4);
3226 MD5STEP(F3, d, a, b, c, in[4] + 0x4bdecfa9, 11);
3227 MD5STEP(F3, c, d, a, b, in[7] + 0xf6bb4b60, 16);
3228 MD5STEP(F3, b, c, d, a, in[10] + 0xbebfbc70, 23);
3229 MD5STEP(F3, a, b, c, d, in[13] + 0x289b7ec6, 4);
3230 MD5STEP(F3, d, a, b, c, in[0] + 0xeaa127fa, 11);
3231 MD5STEP(F3, c, d, a, b, in[3] + 0xd4ef3085, 16);
3232 MD5STEP(F3, b, c, d, a, in[6] + 0x04881d05, 23);
3233 MD5STEP(F3, a, b, c, d, in[9] + 0xd9d4d039, 4);
3234 MD5STEP(F3, d, a, b, c, in[12] + 0xe6db99e5, 11);
3235 MD5STEP(F3, c, d, a, b, in[15] + 0x1fa27cf8, 16);
3236 MD5STEP(F3, b, c, d, a, in[2] + 0xc4ac5665, 23);
3237 
3238 MD5STEP(F4, a, b, c, d, in[0] + 0xf4292244, 6);
3239 MD5STEP(F4, d, a, b, c, in[7] + 0x432aff97, 10);
3240 MD5STEP(F4, c, d, a, b, in[14] + 0xab9423a7, 15);
3241 MD5STEP(F4, b, c, d, a, in[5] + 0xfc93a039, 21);
3242 MD5STEP(F4, a, b, c, d, in[12] + 0x655b59c3, 6);
3243 MD5STEP(F4, d, a, b, c, in[3] + 0x8f0ccc92, 10);
3244 MD5STEP(F4, c, d, a, b, in[10] + 0xffeff47d, 15);
3245 MD5STEP(F4, b, c, d, a, in[1] + 0x85845dd1, 21);
3246 MD5STEP(F4, a, b, c, d, in[8] + 0x6fa87e4f, 6);
3247 MD5STEP(F4, d, a, b, c, in[15] + 0xfe2ce6e0, 10);
3248 MD5STEP(F4, c, d, a, b, in[6] + 0xa3014314, 15);
3249 MD5STEP(F4, b, c, d, a, in[13] + 0x4e0811a1, 21);
3250 MD5STEP(F4, a, b, c, d, in[4] + 0xf7537e82, 6);
3251 MD5STEP(F4, d, a, b, c, in[11] + 0xbd3af235, 10);
3252 MD5STEP(F4, c, d, a, b, in[2] + 0x2ad7d2bb, 15);
3253 MD5STEP(F4, b, c, d, a, in[9] + 0xeb86d391, 21);
3254 
3255 buf[0] += a;
3256 buf[1] += b;
3257 buf[2] += c;
3258 buf[3] += d;
3259}
3260 
3261void mg_md5_update(mg_md5_ctx *ctx, const unsigned char *buf, size_t len) {
3262 uint32_t t;
3263 
3264 t = ctx->bits[0];
3265 if ((ctx->bits[0] = t + ((uint32_t) len << 3)) < t) ctx->bits[1]++;
3266 ctx->bits[1] += (uint32_t) len >> 29;
3267 
3268 t = (t >> 3) & 0x3f;
3269 
3270 if (t) {
3271 unsigned char *p = (unsigned char *) ctx->in + t;
3272 
3273 t = 64 - t;
3274 if (len < t) {
3275 memcpy(p, buf, len);
3276 return;
3277 }
3278 memcpy(p, buf, t);
3279 mg_byte_reverse(ctx->in, 16);
3280 mg_md5_transform(ctx->buf, (uint32_t *) ctx->in);
3281 buf += t;
3282 len -= t;
3283 }
3284 
3285 while (len >= 64) {
3286 memcpy(ctx->in, buf, 64);
3287 mg_byte_reverse(ctx->in, 16);
3288 mg_md5_transform(ctx->buf, (uint32_t *) ctx->in);
3289 buf += 64;
3290 len -= 64;
3291 }
3292 
3293 memcpy(ctx->in, buf, len);
3294}
3295 
3296void mg_md5_final(mg_md5_ctx *ctx, unsigned char digest[16]) {
3297 unsigned count;
3298 unsigned char *p;
3299 uint32_t *a;
3300 
3301 count = (ctx->bits[0] >> 3) & 0x3F;
3302 
3303 p = ctx->in + count;
3304 *p++ = 0x80;
3305 count = 64 - 1 - count;
3306 if (count < 8) {
3307 memset(p, 0, count);
3308 mg_byte_reverse(ctx->in, 16);
3309 mg_md5_transform(ctx->buf, (uint32_t *) ctx->in);
3310 memset(ctx->in, 0, 56);
3311 } else {
3312 memset(p, 0, count - 8);
3313 }
3314 mg_byte_reverse(ctx->in, 14);
3315 
3316 a = (uint32_t *) ctx->in;
3317 a[14] = ctx->bits[0];
3318 a[15] = ctx->bits[1];
3319 
3320 mg_md5_transform(ctx->buf, (uint32_t *) ctx->in);
3321 mg_byte_reverse((unsigned char *) ctx->buf, 4);
3322 memcpy(digest, ctx->buf, 16);
3323 memset((char *) ctx, 0, sizeof(*ctx));
3324}
3325#endif
3326 
3327#ifdef MG_ENABLE_LINES
3328#line 1 "src/mqtt.c"
3329#endif
3330 
3331 
3332 
3333 
3334 
3335 
3336 
3337 
3338#define MQTT_CLEAN_SESSION 0x02
3339#define MQTT_HAS_WILL 0x04
3340#define MQTT_WILL_RETAIN 0x20
3341#define MQTT_HAS_PASSWORD 0x40
3342#define MQTT_HAS_USER_NAME 0x80
3343 
3344struct mg_mqtt_pmap {
3345 uint8_t id;
3346 uint8_t type;
3347};
3348 
3349static const struct mg_mqtt_pmap s_prop_map[] = {
3350 {MQTT_PROP_PAYLOAD_FORMAT_INDICATOR, MQTT_PROP_TYPE_BYTE},
3351 {MQTT_PROP_MESSAGE_EXPIRY_INTERVAL, MQTT_PROP_TYPE_INT},
3352 {MQTT_PROP_CONTENT_TYPE, MQTT_PROP_TYPE_STRING},
3353 {MQTT_PROP_RESPONSE_TOPIC, MQTT_PROP_TYPE_STRING},
3354 {MQTT_PROP_CORRELATION_DATA, MQTT_PROP_TYPE_BINARY_DATA},
3355 {MQTT_PROP_SUBSCRIPTION_IDENTIFIER, MQTT_PROP_TYPE_VARIABLE_INT},
3356 {MQTT_PROP_SESSION_EXPIRY_INTERVAL, MQTT_PROP_TYPE_INT},
3357 {MQTT_PROP_ASSIGNED_CLIENT_IDENTIFIER, MQTT_PROP_TYPE_STRING},
3358 {MQTT_PROP_SERVER_KEEP_ALIVE, MQTT_PROP_TYPE_SHORT},
3359 {MQTT_PROP_AUTHENTICATION_METHOD, MQTT_PROP_TYPE_STRING},
3360 {MQTT_PROP_AUTHENTICATION_DATA, MQTT_PROP_TYPE_BINARY_DATA},
3361 {MQTT_PROP_REQUEST_PROBLEM_INFORMATION, MQTT_PROP_TYPE_BYTE},
3362 {MQTT_PROP_WILL_DELAY_INTERVAL, MQTT_PROP_TYPE_INT},
3363 {MQTT_PROP_REQUEST_RESPONSE_INFORMATION, MQTT_PROP_TYPE_BYTE},
3364 {MQTT_PROP_RESPONSE_INFORMATION, MQTT_PROP_TYPE_STRING},
3365 {MQTT_PROP_SERVER_REFERENCE, MQTT_PROP_TYPE_STRING},
3366 {MQTT_PROP_REASON_STRING, MQTT_PROP_TYPE_STRING},
3367 {MQTT_PROP_RECEIVE_MAXIMUM, MQTT_PROP_TYPE_SHORT},
3368 {MQTT_PROP_TOPIC_ALIAS_MAXIMUM, MQTT_PROP_TYPE_SHORT},
3369 {MQTT_PROP_TOPIC_ALIAS, MQTT_PROP_TYPE_SHORT},
3370 {MQTT_PROP_MAXIMUM_QOS, MQTT_PROP_TYPE_BYTE},
3371 {MQTT_PROP_RETAIN_AVAILABLE, MQTT_PROP_TYPE_BYTE},
3372 {MQTT_PROP_USER_PROPERTY, MQTT_PROP_TYPE_STRING_PAIR},
3373 {MQTT_PROP_MAXIMUM_PACKET_SIZE, MQTT_PROP_TYPE_INT},
3374 {MQTT_PROP_WILDCARD_SUBSCRIPTION_AVAILABLE, MQTT_PROP_TYPE_BYTE},
3375 {MQTT_PROP_SUBSCRIPTION_IDENTIFIER_AVAILABLE, MQTT_PROP_TYPE_BYTE},
3376 {MQTT_PROP_SHARED_SUBSCRIPTION_AVAILABLE, MQTT_PROP_TYPE_BYTE}};
3377 
3378void mg_mqtt_send_header(struct mg_connection *c, uint8_t cmd, uint8_t flags,
3379 uint32_t len) {
3380 uint8_t buf[1 + sizeof(len)], *vlen = &buf[1];
3381 buf[0] = (uint8_t) ((cmd << 4) | flags);
3382 do {
3383 *vlen = len % 0x80;
3384 len /= 0x80;
3385 if (len > 0) *vlen |= 0x80;
3386 vlen++;
3387 } while (len > 0 && vlen < &buf[sizeof(buf)]);
3388 mg_send(c, buf, (size_t) (vlen - buf));
3389}
3390 
3391static void mg_send_u16(struct mg_connection *c, uint16_t value) {
3392 mg_send(c, &value, sizeof(value));
3393}
3394 
3395static void mg_send_u32(struct mg_connection *c, uint32_t value) {
3396 mg_send(c, &value, sizeof(value));
3397}
3398 
3399static uint8_t varint_size(size_t length) {
3400 uint8_t bytes_needed = 0;
3401 do {
3402 bytes_needed++;
3403 length /= 0x80;
3404 } while (length > 0);
3405 return bytes_needed;
3406}
3407 
3408static size_t encode_varint(uint8_t *buf, size_t value) {
3409 size_t len = 0;
3410 
3411 do {
3412 uint8_t b = (uint8_t) (value % 128);
3413 value /= 128;
3414 if (value > 0) b |= 0x80;
3415 buf[len++] = b;
3416 } while (value > 0);
3417 
3418 return len;
3419}
3420 
3421static size_t decode_varint(const uint8_t *buf, size_t len, size_t *value) {
3422 size_t multiplier = 1, offset;
3423 *value = 0;
3424 
3425 for (offset = 0; offset < 4 && offset < len; offset++) {
3426 uint8_t encoded_byte = buf[offset];
3427 *value += (encoded_byte & 0x7f) * multiplier;
3428 multiplier *= 128;
3429 
3430 if ((encoded_byte & 0x80) == 0) return offset + 1;
3431 }
3432 
3433 return 0;
3434}
3435 
3436static int mqtt_prop_type_by_id(uint8_t prop_id) {
3437 size_t i, num_properties = sizeof(s_prop_map) / sizeof(s_prop_map[0]);
3438 for (i = 0; i < num_properties; ++i) {
3439 if (s_prop_map[i].id == prop_id) return s_prop_map[i].type;
3440 }
3441 return -1; // Property ID not found
3442}
3443 
3444// Returns the size of the properties section, without the
3445// size of the content's length
3446static size_t get_properties_length(struct mg_mqtt_prop *props, size_t count) {
3447 size_t i, size = 0;
3448 for (i = 0; i < count; i++) {
3449 size++; // identifier
3450 switch (mqtt_prop_type_by_id(props[i].id)) {
3451 case MQTT_PROP_TYPE_STRING_PAIR:
3452 size += (uint32_t) (props[i].val.len + props[i].key.len +
3453 2 * sizeof(uint16_t));
3454 break;
3455 case MQTT_PROP_TYPE_STRING:
3456 size += (uint32_t) (props[i].val.len + sizeof(uint16_t));
3457 break;
3458 case MQTT_PROP_TYPE_BINARY_DATA:
3459 size += (uint32_t) (props[i].val.len + sizeof(uint16_t));
3460 break;
3461 case MQTT_PROP_TYPE_VARIABLE_INT:
3462 size += varint_size((uint32_t) props[i].iv);
3463 break;
3464 case MQTT_PROP_TYPE_INT:
3465 size += (uint32_t) sizeof(uint32_t);
3466 break;
3467 case MQTT_PROP_TYPE_SHORT:
3468 size += (uint32_t) sizeof(uint16_t);
3469 break;
3470 case MQTT_PROP_TYPE_BYTE:
3471 size += (uint32_t) sizeof(uint8_t);
3472 break;
3473 default:
3474 return size; // cannot parse further down
3475 }
3476 }
3477 
3478 return size;
3479}
3480 
3481// returns the entire size of the properties section, including the
3482// size of the variable length of the content
3483static size_t get_props_size(struct mg_mqtt_prop *props, size_t count) {
3484 size_t size = get_properties_length(props, count);
3485 size += varint_size(size);
3486 return size;
3487}
3488 
3489static void mg_send_mqtt_properties(struct mg_connection *c,
3490 struct mg_mqtt_prop *props, size_t nprops) {
3491 size_t total_size = get_properties_length(props, nprops);
3492 uint8_t buf_v[4] = {0, 0, 0, 0};
3493 uint8_t buf[4] = {0, 0, 0, 0};
3494 size_t i, len = encode_varint(buf, total_size);
3495 
3496 mg_send(c, buf, (size_t) len);
3497 for (i = 0; i < nprops; i++) {
3498 mg_send(c, &props[i].id, sizeof(props[i].id));
3499 switch (mqtt_prop_type_by_id(props[i].id)) {
3500 case MQTT_PROP_TYPE_STRING_PAIR:
3501 mg_send_u16(c, mg_htons((uint16_t) props[i].key.len));
3502 mg_send(c, props[i].key.buf, props[i].key.len);
3503 mg_send_u16(c, mg_htons((uint16_t) props[i].val.len));
3504 mg_send(c, props[i].val.buf, props[i].val.len);
3505 break;
3506 case MQTT_PROP_TYPE_BYTE:
3507 mg_send(c, &props[i].iv, sizeof(uint8_t));
3508 break;
3509 case MQTT_PROP_TYPE_SHORT:
3510 mg_send_u16(c, mg_htons((uint16_t) props[i].iv));
3511 break;
3512 case MQTT_PROP_TYPE_INT:
3513 mg_send_u32(c, mg_htonl((uint32_t) props[i].iv));
3514 break;
3515 case MQTT_PROP_TYPE_STRING:
3516 mg_send_u16(c, mg_htons((uint16_t) props[i].val.len));
3517 mg_send(c, props[i].val.buf, props[i].val.len);
3518 break;
3519 case MQTT_PROP_TYPE_BINARY_DATA:
3520 mg_send_u16(c, mg_htons((uint16_t) props[i].val.len));
3521 mg_send(c, props[i].val.buf, props[i].val.len);
3522 break;
3523 case MQTT_PROP_TYPE_VARIABLE_INT:
3524 len = encode_varint(buf_v, props[i].iv);
3525 mg_send(c, buf_v, (size_t) len);
3526 break;
3527 }
3528 }
3529}
3530 
3531size_t mg_mqtt_next_prop(struct mg_mqtt_message *msg, struct mg_mqtt_prop *prop,
3532 size_t ofs) {
3533 uint8_t *i = (uint8_t *) msg->dgram.buf + msg->props_start + ofs;
3534 uint8_t *end = (uint8_t *) msg->dgram.buf + msg->dgram.len;
3535 size_t new_pos = ofs, len;
3536 prop->id = i[0];
3537 
3538 if (ofs >= msg->dgram.len || ofs >= msg->props_start + msg->props_size)
3539 return 0;
3540 i++, new_pos++;
3541 
3542 switch (mqtt_prop_type_by_id(prop->id)) {
3543 case MQTT_PROP_TYPE_STRING_PAIR:
3544 prop->key.len = (uint16_t) ((((uint16_t) i[0]) << 8) | i[1]);
3545 prop->key.buf = (char *) i + 2;
3546 i += 2 + prop->key.len;
3547 prop->val.len = (uint16_t) ((((uint16_t) i[0]) << 8) | i[1]);
3548 prop->val.buf = (char *) i + 2;
3549 new_pos += 2 * sizeof(uint16_t) + prop->val.len + prop->key.len;
3550 break;
3551 case MQTT_PROP_TYPE_BYTE:
3552 prop->iv = (uint8_t) i[0];
3553 new_pos++;
3554 break;
3555 case MQTT_PROP_TYPE_SHORT:
3556 prop->iv = (uint16_t) ((((uint16_t) i[0]) << 8) | i[1]);
3557 new_pos += sizeof(uint16_t);
3558 break;
3559 case MQTT_PROP_TYPE_INT:
3560 prop->iv = ((uint32_t) i[0] << 24) | ((uint32_t) i[1] << 16) |
3561 ((uint32_t) i[2] << 8) | i[3];
3562 new_pos += sizeof(uint32_t);
3563 break;
3564 case MQTT_PROP_TYPE_STRING:
3565 prop->val.len = (uint16_t) ((((uint16_t) i[0]) << 8) | i[1]);
3566 prop->val.buf = (char *) i + 2;
3567 new_pos += 2 + prop->val.len;
3568 break;
3569 case MQTT_PROP_TYPE_BINARY_DATA:
3570 prop->val.len = (uint16_t) ((((uint16_t) i[0]) << 8) | i[1]);
3571 prop->val.buf = (char *) i + 2;
3572 new_pos += 2 + prop->val.len;
3573 break;
3574 case MQTT_PROP_TYPE_VARIABLE_INT:
3575 len = decode_varint(i, (size_t) (end - i), (size_t *) &prop->iv);
3576 new_pos = (!len) ? 0 : new_pos + len;
3577 break;
3578 default:
3579 new_pos = 0;
3580 }
3581 
3582 return new_pos;
3583}
3584 
3585void mg_mqtt_login(struct mg_connection *c, const struct mg_mqtt_opts *opts) {
3586 char client_id[21];
3587 struct mg_str cid = opts->client_id;
3588 size_t total_len = 7 + 1 + 2 + 2;
3589 uint8_t hdr[8] = {0, 4, 'M', 'Q', 'T', 'T', opts->version, 0};
3590 
3591 if (cid.len == 0) {
3592 mg_random_str(client_id, sizeof(client_id) - 1);
3593 client_id[sizeof(client_id) - 1] = '\0';
3594 cid = mg_str(client_id);
3595 }
3596 
3597 if (hdr[6] == 0) hdr[6] = 4; // If version is not set, use 4 (3.1.1)
3598 c->is_mqtt5 = hdr[6] == 5; // Set version 5 flag
3599 hdr[7] = (uint8_t) ((opts->qos & 3) << 3); // Connection flags
3600 if (opts->user.len > 0) {
3601 total_len += 2 + (uint32_t) opts->user.len;
3602 hdr[7] |= MQTT_HAS_USER_NAME;
3603 }
3604 if (opts->pass.len > 0) {
3605 total_len += 2 + (uint32_t) opts->pass.len;
3606 hdr[7] |= MQTT_HAS_PASSWORD;
3607 }
3608 if (opts->topic.len > 0) { // allow zero-length msgs, message.len is size_t
3609 total_len += 4 + (uint32_t) opts->topic.len + (uint32_t) opts->message.len;
3610 hdr[7] |= MQTT_HAS_WILL;
3611 }
3612 if (opts->clean || cid.len == 0) hdr[7] |= MQTT_CLEAN_SESSION;
3613 if (opts->retain) hdr[7] |= MQTT_WILL_RETAIN;
3614 total_len += (uint32_t) cid.len;
3615 if (c->is_mqtt5) {
3616 total_len += get_props_size(opts->props, opts->num_props);
3617 if (hdr[7] & MQTT_HAS_WILL)
3618 total_len += get_props_size(opts->will_props, opts->num_will_props);
3619 }
3620 
3621 mg_mqtt_send_header(c, MQTT_CMD_CONNECT, 0, (uint32_t) total_len);
3622 mg_send(c, hdr, sizeof(hdr));
3623 // keepalive == 0 means "do not disconnect us!"
3624 mg_send_u16(c, mg_htons((uint16_t) opts->keepalive));
3625 
3626 if (c->is_mqtt5) mg_send_mqtt_properties(c, opts->props, opts->num_props);
3627 
3628 mg_send_u16(c, mg_htons((uint16_t) cid.len));
3629 mg_send(c, cid.buf, cid.len);
3630 
3631 if (hdr[7] & MQTT_HAS_WILL) {
3632 if (c->is_mqtt5)
3633 mg_send_mqtt_properties(c, opts->will_props, opts->num_will_props);
3634 
3635 mg_send_u16(c, mg_htons((uint16_t) opts->topic.len));
3636 mg_send(c, opts->topic.buf, opts->topic.len);
3637 mg_send_u16(c, mg_htons((uint16_t) opts->message.len));
3638 mg_send(c, opts->message.buf, opts->message.len);
3639 }
3640 if (opts->user.len > 0) {
3641 mg_send_u16(c, mg_htons((uint16_t) opts->user.len));
3642 mg_send(c, opts->user.buf, opts->user.len);
3643 }
3644 if (opts->pass.len > 0) {
3645 mg_send_u16(c, mg_htons((uint16_t) opts->pass.len));
3646 mg_send(c, opts->pass.buf, opts->pass.len);
3647 }
3648}
3649 
3650uint16_t mg_mqtt_pub(struct mg_connection *c, const struct mg_mqtt_opts *opts) {
3651 uint16_t id = opts->retransmit_id;
3652 uint8_t flags = (uint8_t) (((opts->qos & 3) << 1) | (opts->retain ? 1 : 0));
3653 size_t len = 2 + opts->topic.len + opts->message.len;
3654 MG_DEBUG(("%lu [%.*s] <- [%.*s%c", c->id, (int) opts->topic.len,
3655 (char *) opts->topic.buf,
3656 (int) (opts->message.len <= 10 ? opts->message.len : 10),
3657 (char *) opts->message.buf, opts->message.len <= 10 ? ']' : ' '));
3658 if (opts->qos > 0) len += 2;
3659 if (c->is_mqtt5) len += get_props_size(opts->props, opts->num_props);
3660 
3661 if (opts->qos > 0 && id != 0) flags |= 1 << 3;
3662 mg_mqtt_send_header(c, MQTT_CMD_PUBLISH, flags, (uint32_t) len);
3663 mg_send_u16(c, mg_htons((uint16_t) opts->topic.len));
3664 mg_send(c, opts->topic.buf, opts->topic.len);
3665 if (opts->qos > 0) { // need to send 'id' field
3666 if (id == 0) { // generate new one if not resending
3667 if (++c->mgr->mqtt_id == 0) ++c->mgr->mqtt_id;
3668 id = c->mgr->mqtt_id;
3669 }
3670 mg_send_u16(c, mg_htons(id));
3671 }
3672 
3673 if (c->is_mqtt5) mg_send_mqtt_properties(c, opts->props, opts->num_props);
3674 
3675 if (opts->message.len > 0) mg_send(c, opts->message.buf, opts->message.len);
3676 return id;
3677}
3678 
3679void mg_mqtt_sub(struct mg_connection *c, const struct mg_mqtt_opts *opts) {
3680 uint8_t qos_ = opts->qos & 3;
3681 size_t plen = c->is_mqtt5 ? get_props_size(opts->props, opts->num_props) : 0;
3682 size_t len = 2 + opts->topic.len + 2 + 1 + plen;
3683 
3684 mg_mqtt_send_header(c, MQTT_CMD_SUBSCRIBE, 2, (uint32_t) len);
3685 if (++c->mgr->mqtt_id == 0) ++c->mgr->mqtt_id;
3686 mg_send_u16(c, mg_htons(c->mgr->mqtt_id));
3687 if (c->is_mqtt5) mg_send_mqtt_properties(c, opts->props, opts->num_props);
3688 
3689 mg_send_u16(c, mg_htons((uint16_t) opts->topic.len));
3690 mg_send(c, opts->topic.buf, opts->topic.len);
3691 mg_send(c, &qos_, sizeof(qos_));
3692}
3693 
3694int mg_mqtt_parse(const uint8_t *buf, size_t len, uint8_t version,
3695 struct mg_mqtt_message *m) {
3696 uint8_t lc = 0, *p, *end;
3697 uint32_t n = 0, len_len = 0;
3698 
3699 memset(m, 0, sizeof(*m));
3700 m->dgram.buf = (char *) buf;
3701 if (len < 2) return MQTT_INCOMPLETE;
3702 m->cmd = (uint8_t) (buf[0] >> 4);
3703 m->qos = (buf[0] >> 1) & 3;
3704 
3705 n = len_len = 0;
3706 p = (uint8_t *) buf + 1;
3707 while ((size_t) (p - buf) < len) {
3708 lc = *((uint8_t *) p++);
3709 n += (uint32_t) ((lc & 0x7f) << 7 * len_len);
3710 len_len++;
3711 if (!(lc & 0x80)) break;
3712 if (len_len >= 4) return MQTT_MALFORMED;
3713 }
3714 end = p + n;
3715 if ((lc & 0x80) || (end > buf + len)) return MQTT_INCOMPLETE;
3716 m->dgram.len = (size_t) (end - buf);
3717 
3718 switch (m->cmd) {
3719 case MQTT_CMD_CONNACK:
3720 if (end - p < 2) return MQTT_MALFORMED;
3721 m->ack = p[1];
3722 break;
3723 case MQTT_CMD_PUBACK:
3724 case MQTT_CMD_PUBREC:
3725 case MQTT_CMD_PUBREL:
3726 case MQTT_CMD_PUBCOMP:
3727 case MQTT_CMD_SUBSCRIBE:
3728 case MQTT_CMD_SUBACK:
3729 case MQTT_CMD_UNSUBSCRIBE:
3730 case MQTT_CMD_UNSUBACK:
3731 if (p + 2 > end) return MQTT_MALFORMED;
3732 m->id = (uint16_t) ((((uint16_t) p[0]) << 8) | p[1]);
3733 p += 2;
3734 break;
3735 case MQTT_CMD_PUBLISH: {
3736 if (p + 2 > end) return MQTT_MALFORMED;
3737 m->topic.len = (uint16_t) ((((uint16_t) p[0]) << 8) | p[1]);
3738 m->topic.buf = (char *) p + 2;
3739 p += 2 + m->topic.len;
3740 if (p > end) return MQTT_MALFORMED;
3741 if (m->qos > 0) {
3742 if (p + 2 > end) return MQTT_MALFORMED;
3743 m->id = (uint16_t) ((((uint16_t) p[0]) << 8) | p[1]);
3744 p += 2;
3745 }
3746 if (p > end) return MQTT_MALFORMED;
3747 if (version == 5 && p + 2 < end) {
3748 len_len =
3749 (uint32_t) decode_varint(p, (size_t) (end - p), &m->props_size);
3750 if (!len_len) return MQTT_MALFORMED;
3751 m->props_start = (size_t) (p + len_len - buf);
3752 p += len_len + m->props_size;
3753 }
3754 if (p > end) return MQTT_MALFORMED;
3755 m->data.buf = (char *) p;
3756 m->data.len = (size_t) (end - p);
3757 break;
3758 }
3759 default:
3760 break;
3761 }
3762 return MQTT_OK;
3763}
3764 
3765static void mqtt_cb(struct mg_connection *c, int ev, void *ev_data) {
3766 if (ev == MG_EV_READ) {
3767 for (;;) {
3768 uint8_t version = c->is_mqtt5 ? 5 : 4;
3769 struct mg_mqtt_message mm;
3770 int rc = mg_mqtt_parse(c->recv.buf, c->recv.len, version, &mm);
3771 if (rc == MQTT_MALFORMED) {
3772 MG_ERROR(("%lu MQTT malformed message", c->id));
3773 c->is_closing = 1;
3774 break;
3775 } else if (rc == MQTT_OK) {
3776 MG_VERBOSE(("%lu MQTT CMD %d len %d [%.*s]", c->id, mm.cmd,
3777 (int) mm.dgram.len, (int) mm.data.len, mm.data.buf));
3778 switch (mm.cmd) {
3779 case MQTT_CMD_CONNACK:
3780 mg_call(c, MG_EV_MQTT_OPEN, &mm.ack);
3781 if (mm.ack == 0) {
3782 MG_DEBUG(("%lu Connected", c->id));
3783 } else {
3784 MG_ERROR(("%lu MQTT auth failed, code %d", c->id, mm.ack));
3785 c->is_closing = 1;
3786 }
3787 break;
3788 case MQTT_CMD_PUBLISH: {
3789 MG_DEBUG(("%lu [%.*s] -> [%.*s%c", c->id, (int) mm.topic.len,
3790 mm.topic.buf,
3791 (int) (mm.data.len <= 10 ? mm.data.len : 10), mm.data.buf,
3792 mm.data.len <= 10 ? ']' : ' '));
3793 if (mm.qos > 0) {
3794 uint16_t id = mg_ntohs(mm.id);
3795 uint32_t remaining_len = sizeof(id);
3796 if (c->is_mqtt5) remaining_len += 2; // 3.4.2
3797 
3798 mg_mqtt_send_header(
3799 c,
3800 (uint8_t) (mm.qos == 2 ? MQTT_CMD_PUBREC : MQTT_CMD_PUBACK),
3801 0, remaining_len);
3802 mg_send(c, &id, sizeof(id));
3803 
3804 if (c->is_mqtt5) {
3805 uint16_t zero = 0;
3806 mg_send(c, &zero, sizeof(zero));
3807 }
3808 }
3809 mg_call(c, MG_EV_MQTT_MSG, &mm); // let the app handle qos stuff
3810 break;
3811 }
3812 case MQTT_CMD_PUBREC: { // MQTT5: 3.5.2-1 TODO(): variable header rc
3813 uint16_t id = mg_ntohs(mm.id);
3814 uint32_t remaining_len = sizeof(id); // MQTT5 3.6.2-1
3815 mg_mqtt_send_header(c, MQTT_CMD_PUBREL, 2, remaining_len);
3816 mg_send(c, &id, sizeof(id)); // MQTT5 3.6.1-1, flags = 2
3817 break;
3818 }
3819 case MQTT_CMD_PUBREL: { // MQTT5: 3.6.2-1 TODO(): variable header rc
3820 uint16_t id = mg_ntohs(mm.id);
3821 uint32_t remaining_len = sizeof(id); // MQTT5 3.7.2-1
3822 mg_mqtt_send_header(c, MQTT_CMD_PUBCOMP, 0, remaining_len);
3823 mg_send(c, &id, sizeof(id));
3824 break;
3825 }
3826 }
3827 mg_call(c, MG_EV_MQTT_CMD, &mm);
3828 mg_iobuf_del(&c->recv, 0, mm.dgram.len);
3829 } else {
3830 break;
3831 }
3832 }
3833 }
3834 (void) ev_data;
3835}
3836 
3837void mg_mqtt_ping(struct mg_connection *nc) {
3838 mg_mqtt_send_header(nc, MQTT_CMD_PINGREQ, 0, 0);
3839}
3840 
3841void mg_mqtt_pong(struct mg_connection *nc) {
3842 mg_mqtt_send_header(nc, MQTT_CMD_PINGRESP, 0, 0);
3843}
3844 
3845void mg_mqtt_disconnect(struct mg_connection *c,
3846 const struct mg_mqtt_opts *opts) {
3847 size_t len = 0;
3848 if (c->is_mqtt5) len = 1 + get_props_size(opts->props, opts->num_props);
3849 mg_mqtt_send_header(c, MQTT_CMD_DISCONNECT, 0, (uint32_t) len);
3850 
3851 if (c->is_mqtt5) {
3852 uint8_t zero = 0;
3853 mg_send(c, &zero, sizeof(zero)); // reason code
3854 mg_send_mqtt_properties(c, opts->props, opts->num_props);
3855 }
3856}
3857 
3858struct mg_connection *mg_mqtt_connect(struct mg_mgr *mgr, const char *url,
3859 const struct mg_mqtt_opts *opts,
3860 mg_event_handler_t fn, void *fn_data) {
3861 struct mg_connection *c = mg_connect(mgr, url, fn, fn_data);
3862 if (c != NULL) {
3863 struct mg_mqtt_opts empty;
3864 memset(&empty, 0, sizeof(empty));
3865 mg_mqtt_login(c, opts == NULL ? &empty : opts);
3866 c->pfn = mqtt_cb;
3867 }
3868 return c;
3869}
3870 
3871struct mg_connection *mg_mqtt_listen(struct mg_mgr *mgr, const char *url,
3872 mg_event_handler_t fn, void *fn_data) {
3873 struct mg_connection *c = mg_listen(mgr, url, fn, fn_data);
3874 if (c != NULL) c->pfn = mqtt_cb, c->pfn_data = mgr;
3875 return c;
3876}
3877 
3878#ifdef MG_ENABLE_LINES
3879#line 1 "src/net.c"
3880#endif
3881 
3882 
3883 
3884 
3885 
3886 
3887 
3888 
3889 
3890size_t mg_vprintf(struct mg_connection *c, const char *fmt, va_list *ap) {
3891 size_t old = c->send.len;
3892 mg_vxprintf(mg_pfn_iobuf, &c->send, fmt, ap);
3893 return c->send.len - old;
3894}
3895 
3896size_t mg_printf(struct mg_connection *c, const char *fmt, ...) {
3897 size_t len = 0;
3898 va_list ap;
3899 va_start(ap, fmt);
3900 len = mg_vprintf(c, fmt, &ap);
3901 va_end(ap);
3902 return len;
3903}
3904 
3905static bool mg_atonl(struct mg_str str, struct mg_addr *addr) {
3906 uint32_t localhost = mg_htonl(0x7f000001);
3907 if (mg_strcasecmp(str, mg_str("localhost")) != 0) return false;
3908 memcpy(addr->ip, &localhost, sizeof(uint32_t));
3909 addr->is_ip6 = false;
3910 return true;
3911}
3912 
3913static bool mg_atone(struct mg_str str, struct mg_addr *addr) {
3914 if (str.len > 0) return false;
3915 memset(addr->ip, 0, sizeof(addr->ip));
3916 addr->is_ip6 = false;
3917 return true;
3918}
3919 
3920static bool mg_aton4(struct mg_str str, struct mg_addr *addr) {
3921 uint8_t data[4] = {0, 0, 0, 0};
3922 size_t i, num_dots = 0;
3923 for (i = 0; i < str.len; i++) {
3924 if (str.buf[i] >= '0' && str.buf[i] <= '9') {
3925 int octet = data[num_dots] * 10 + (str.buf[i] - '0');
3926 if (octet > 255) return false;
3927 data[num_dots] = (uint8_t) octet;
3928 } else if (str.buf[i] == '.') {
3929 if (num_dots >= 3 || i == 0 || str.buf[i - 1] == '.') return false;
3930 num_dots++;
3931 } else {
3932 return false;
3933 }
3934 }
3935 if (num_dots != 3 || str.buf[i - 1] == '.') return false;
3936 memcpy(&addr->ip, data, sizeof(data));
3937 addr->is_ip6 = false;
3938 return true;
3939}
3940 
3941static bool mg_v4mapped(struct mg_str str, struct mg_addr *addr) {
3942 int i;
3943 uint32_t ipv4;
3944 if (str.len < 14) return false;
3945 if (str.buf[0] != ':' || str.buf[1] != ':' || str.buf[6] != ':') return false;
3946 for (i = 2; i < 6; i++) {
3947 if (str.buf[i] != 'f' && str.buf[i] != 'F') return false;
3948 }
3949 // struct mg_str s = mg_str_n(&str.buf[7], str.len - 7);
3950 if (!mg_aton4(mg_str_n(&str.buf[7], str.len - 7), addr)) return false;
3951 memcpy(&ipv4, addr->ip, sizeof(ipv4));
3952 memset(addr->ip, 0, sizeof(addr->ip));
3953 addr->ip[10] = addr->ip[11] = 255;
3954 memcpy(&addr->ip[12], &ipv4, 4);
3955 addr->is_ip6 = true;
3956 return true;
3957}
3958 
3959static bool mg_aton6(struct mg_str str, struct mg_addr *addr) {
3960 size_t i, j = 0, n = 0, dc = 42;
3961 addr->scope_id = 0;
3962 if (str.len > 2 && str.buf[0] == '[') str.buf++, str.len -= 2;
3963 if (mg_v4mapped(str, addr)) return true;
3964 for (i = 0; i < str.len; i++) {
3965 if ((str.buf[i] >= '0' && str.buf[i] <= '9') ||
3966 (str.buf[i] >= 'a' && str.buf[i] <= 'f') ||
3967 (str.buf[i] >= 'A' && str.buf[i] <= 'F')) {
3968 unsigned long val = 0; // TODO(): This loops on chars, refactor
3969 if (i > j + 3) return false;
3970 // MG_DEBUG(("%lu %lu [%.*s]", i, j, (int) (i - j + 1), &str.buf[j]));
3971 mg_str_to_num(mg_str_n(&str.buf[j], i - j + 1), 16, &val, sizeof(val));
3972 addr->ip[n] = (uint8_t) ((val >> 8) & 255);
3973 addr->ip[n + 1] = (uint8_t) (val & 255);
3974 } else if (str.buf[i] == ':') {
3975 j = i + 1;
3976 if (i > 0 && str.buf[i - 1] == ':') {
3977 dc = n; // Double colon
3978 if (i > 1 && str.buf[i - 2] == ':') return false;
3979 } else if (i > 0) {
3980 n += 2;
3981 }
3982 if (n > 14) return false;
3983 addr->ip[n] = addr->ip[n + 1] = 0; // For trailing ::
3984 } else if (str.buf[i] == '%') { // Scope ID, last in string
3985 return mg_str_to_num(mg_str_n(&str.buf[i + 1], str.len - i - 1), 10,
3986 &addr->scope_id, sizeof(uint8_t));
3987 } else {
3988 return false;
3989 }
3990 }
3991 if (n < 14 && dc == 42) return false;
3992 if (n < 14) {
3993 memmove(&addr->ip[dc + (14 - n)], &addr->ip[dc], n - dc + 2);
3994 memset(&addr->ip[dc], 0, 14 - n);
3995 }
3996 
3997 addr->is_ip6 = true;
3998 return true;
3999}
4000 
4001bool mg_aton(struct mg_str str, struct mg_addr *addr) {
4002 // MG_INFO(("[%.*s]", (int) str.len, str.buf));
4003 return mg_atone(str, addr) || mg_atonl(str, addr) || mg_aton4(str, addr) ||
4004 mg_aton6(str, addr);
4005}
4006 
4007struct mg_connection *mg_alloc_conn(struct mg_mgr *mgr) {
4008 struct mg_connection *c =
4009 (struct mg_connection *) calloc(1, sizeof(*c) + mgr->extraconnsize);
4010 if (c != NULL) {
4011 c->mgr = mgr;
4012 c->send.align = c->recv.align = c->rtls.align = MG_IO_SIZE;
4013 c->id = ++mgr->nextid;
4014 MG_PROF_INIT(c);
4015 }
4016 return c;
4017}
4018 
4019void mg_close_conn(struct mg_connection *c) {
4020 mg_resolve_cancel(c); // Close any pending DNS query
4021 LIST_DELETE(struct mg_connection, &c->mgr->conns, c);
4022 if (c == c->mgr->dns4.c) c->mgr->dns4.c = NULL;
4023 if (c == c->mgr->dns6.c) c->mgr->dns6.c = NULL;
4024 // Order of operations is important. `MG_EV_CLOSE` event must be fired
4025 // before we deallocate received data, see #1331
4026 mg_call(c, MG_EV_CLOSE, NULL);
4027 MG_DEBUG(("%lu %ld closed", c->id, c->fd));
4028 MG_PROF_DUMP(c);
4029 MG_PROF_FREE(c);
4030 
4031 mg_tls_free(c);
4032 mg_iobuf_free(&c->recv);
4033 mg_iobuf_free(&c->send);
4034 mg_iobuf_free(&c->rtls);
4035 mg_bzero((unsigned char *) c, sizeof(*c));
4036 free(c);
4037}
4038 
4039struct mg_connection *mg_connect(struct mg_mgr *mgr, const char *url,
4040 mg_event_handler_t fn, void *fn_data) {
4041 struct mg_connection *c = NULL;
4042 if (url == NULL || url[0] == '\0') {
4043 MG_ERROR(("null url"));
4044 } else if ((c = mg_alloc_conn(mgr)) == NULL) {
4045 MG_ERROR(("OOM"));
4046 } else {
4047 LIST_ADD_HEAD(struct mg_connection, &mgr->conns, c);
4048 c->is_udp = (strncmp(url, "udp:", 4) == 0);
4049 c->fd = (void *) (size_t) MG_INVALID_SOCKET;
4050 c->fn = fn;
4051 c->is_client = true;
4052 c->fn_data = fn_data;
4053 MG_DEBUG(("%lu %ld %s", c->id, c->fd, url));
4054 mg_call(c, MG_EV_OPEN, (void *) url);
4055 mg_resolve(c, url);
4056 }
4057 return c;
4058}
4059 
4060struct mg_connection *mg_listen(struct mg_mgr *mgr, const char *url,
4061 mg_event_handler_t fn, void *fn_data) {
4062 struct mg_connection *c = NULL;
4063 if ((c = mg_alloc_conn(mgr)) == NULL) {
4064 MG_ERROR(("OOM %s", url));
4065 } else if (!mg_open_listener(c, url)) {
4066 MG_ERROR(("Failed: %s, errno %d", url, errno));
4067 MG_PROF_FREE(c);
4068 free(c);
4069 c = NULL;
4070 } else {
4071 c->is_listening = 1;
4072 c->is_udp = strncmp(url, "udp:", 4) == 0;
4073 LIST_ADD_HEAD(struct mg_connection, &mgr->conns, c);
4074 c->fn = fn;
4075 c->fn_data = fn_data;
4076 mg_call(c, MG_EV_OPEN, NULL);
4077 if (mg_url_is_ssl(url)) c->is_tls = 1; // Accepted connection must
4078 MG_DEBUG(("%lu %ld %s", c->id, c->fd, url));
4079 }
4080 return c;
4081}
4082 
4083struct mg_connection *mg_wrapfd(struct mg_mgr *mgr, int fd,
4084 mg_event_handler_t fn, void *fn_data) {
4085 struct mg_connection *c = mg_alloc_conn(mgr);
4086 if (c != NULL) {
4087 c->fd = (void *) (size_t) fd;
4088 c->fn = fn;
4089 c->fn_data = fn_data;
4090 MG_EPOLL_ADD(c);
4091 mg_call(c, MG_EV_OPEN, NULL);
4092 LIST_ADD_HEAD(struct mg_connection, &mgr->conns, c);
4093 }
4094 return c;
4095}
4096 
4097struct mg_timer *mg_timer_add(struct mg_mgr *mgr, uint64_t milliseconds,
4098 unsigned flags, void (*fn)(void *), void *arg) {
4099 struct mg_timer *t = (struct mg_timer *) calloc(1, sizeof(*t));
4100 if (t != NULL) {
4101 flags |= MG_TIMER_AUTODELETE; // We have calloc-ed it, so autodelete
4102 mg_timer_init(&mgr->timers, t, milliseconds, flags, fn, arg);
4103 }
4104 return t;
4105}
4106 
4107long mg_io_recv(struct mg_connection *c, void *buf, size_t len) {
4108 if (c->rtls.len == 0) return MG_IO_WAIT;
4109 if (len > c->rtls.len) len = c->rtls.len;
4110 memcpy(buf, c->rtls.buf, len);
4111 mg_iobuf_del(&c->rtls, 0, len);
4112 return (long) len;
4113}
4114 
4115void mg_mgr_free(struct mg_mgr *mgr) {
4116 struct mg_connection *c;
4117 struct mg_timer *tmp, *t = mgr->timers;
4118 while (t != NULL) tmp = t->next, free(t), t = tmp;
4119 mgr->timers = NULL; // Important. Next call to poll won't touch timers
4120 for (c = mgr->conns; c != NULL; c = c->next) c->is_closing = 1;
4121 mg_mgr_poll(mgr, 0);
4122#if MG_ENABLE_FREERTOS_TCP
4123 FreeRTOS_DeleteSocketSet(mgr->ss);
4124#endif
4125 MG_DEBUG(("All connections closed"));
4126#if MG_ENABLE_EPOLL
4127 if (mgr->epoll_fd >= 0) close(mgr->epoll_fd), mgr->epoll_fd = -1;
4128#endif
4129 mg_tls_ctx_free(mgr);
4130}
4131 
4132void mg_mgr_init(struct mg_mgr *mgr) {
4133 memset(mgr, 0, sizeof(*mgr));
4134#if MG_ENABLE_EPOLL
4135 if ((mgr->epoll_fd = epoll_create1(EPOLL_CLOEXEC)) < 0)
4136 MG_ERROR(("epoll_create1 errno %d", errno));
4137#else
4138 mgr->epoll_fd = -1;
4139#endif
4140#if MG_ARCH == MG_ARCH_WIN32 && MG_ENABLE_WINSOCK
4141 // clang-format off
4142 { WSADATA data; WSAStartup(MAKEWORD(2, 2), &data); }
4143 // clang-format on
4144#elif MG_ENABLE_FREERTOS_TCP
4145 mgr->ss = FreeRTOS_CreateSocketSet();
4146#elif defined(__unix) || defined(__unix__) || defined(__APPLE__)
4147 // Ignore SIGPIPE signal, so if client cancels the request, it
4148 // won't kill the whole process.
4149 signal(SIGPIPE, SIG_IGN);
4150#elif MG_ENABLE_TCPIP_DRIVER_INIT && defined(MG_TCPIP_DRIVER_INIT)
4151 MG_TCPIP_DRIVER_INIT(mgr);
4152#endif
4153 mgr->pipe = MG_INVALID_SOCKET;
4154 mgr->dnstimeout = 3000;
4155 mgr->dns4.url = "udp://8.8.8.8:53";
4156 mgr->dns6.url = "udp://[2001:4860:4860::8888]:53";
4157 mg_tls_ctx_init(mgr);
4158}
4159 
4160#ifdef MG_ENABLE_LINES
4161#line 1 "src/net_builtin.c"
4162#endif
4163 
4164 
4165#if defined(MG_ENABLE_TCPIP) && MG_ENABLE_TCPIP
4166#define MG_EPHEMERAL_PORT_BASE 32768
4167#define PDIFF(a, b) ((size_t) (((char *) (b)) - ((char *) (a))))
4168 
4169#ifndef MIP_TCP_KEEPALIVE_MS
4170#define MIP_TCP_KEEPALIVE_MS 45000 // TCP keep-alive period, ms
4171#endif
4172 
4173#define MIP_TCP_ACK_MS 150 // Timeout for ACKing
4174#define MIP_ARP_RESP_MS 100 // Timeout for ARP response
4175#define MIP_TCP_SYN_MS 15000 // Timeout for connection establishment
4176#define MIP_TCP_FIN_MS 1000 // Timeout for closing connection
4177#define MIP_TCP_WIN 6000 // TCP window size
4178 
4179struct connstate {
4180 uint32_t seq, ack; // TCP seq/ack counters
4181 uint64_t timer; // TCP keep-alive / ACK timer
4182 uint32_t acked; // Last ACK-ed number
4183 size_t unacked; // Not acked bytes
4184 uint8_t mac[6]; // Peer MAC address
4185 uint8_t ttype; // Timer type. 0: ack, 1: keep-alive
4186#define MIP_TTYPE_KEEPALIVE 0 // Connection is idle for long, send keepalive
4187#define MIP_TTYPE_ACK 1 // Peer sent us data, we have to ack it soon
4188#define MIP_TTYPE_ARP 2 // ARP resolve sent, waiting for response
4189#define MIP_TTYPE_SYN 3 // SYN sent, waiting for response
4190#define MIP_TTYPE_FIN 4 // FIN sent, waiting until terminating the connection
4191 uint8_t tmiss; // Number of keep-alive misses
4192 struct mg_iobuf raw; // For TLS only. Incoming raw data
4193 bool fin_rcvd; // We have received FIN from the peer
4194 bool twclosure; // 3-way closure done
4195};
4196 
4197#pragma pack(push, 1)
4198 
4199struct lcp {
4200 uint8_t addr, ctrl, proto[2], code, id, len[2];
4201};
4202 
4203struct eth {
4204 uint8_t dst[6]; // Destination MAC address
4205 uint8_t src[6]; // Source MAC address
4206 uint16_t type; // Ethernet type
4207};
4208 
4209struct ip {
4210 uint8_t ver; // Version
4211 uint8_t tos; // Unused
4212 uint16_t len; // Length
4213 uint16_t id; // Unused
4214 uint16_t frag; // Fragmentation
4215#define IP_FRAG_OFFSET_MSK 0x1fff
4216#define IP_MORE_FRAGS_MSK 0x2000
4217 uint8_t ttl; // Time to live
4218 uint8_t proto; // Upper level protocol
4219 uint16_t csum; // Checksum
4220 uint32_t src; // Source IP
4221 uint32_t dst; // Destination IP
4222};
4223 
4224struct ip6 {
4225 uint8_t ver; // Version
4226 uint8_t opts[3]; // Options
4227 uint16_t len; // Length
4228 uint8_t proto; // Upper level protocol
4229 uint8_t ttl; // Time to live
4230 uint8_t src[16]; // Source IP
4231 uint8_t dst[16]; // Destination IP
4232};
4233 
4234struct icmp {
4235 uint8_t type;
4236 uint8_t code;
4237 uint16_t csum;
4238};
4239 
4240struct arp {
4241 uint16_t fmt; // Format of hardware address
4242 uint16_t pro; // Format of protocol address
4243 uint8_t hlen; // Length of hardware address
4244 uint8_t plen; // Length of protocol address
4245 uint16_t op; // Operation
4246 uint8_t sha[6]; // Sender hardware address
4247 uint32_t spa; // Sender protocol address
4248 uint8_t tha[6]; // Target hardware address
4249 uint32_t tpa; // Target protocol address
4250};
4251 
4252struct tcp {
4253 uint16_t sport; // Source port
4254 uint16_t dport; // Destination port
4255 uint32_t seq; // Sequence number
4256 uint32_t ack; // Acknowledgement number
4257 uint8_t off; // Data offset
4258 uint8_t flags; // TCP flags
4259#define TH_FIN 0x01
4260#define TH_SYN 0x02
4261#define TH_RST 0x04
4262#define TH_PUSH 0x08
4263#define TH_ACK 0x10
4264#define TH_URG 0x20
4265#define TH_ECE 0x40
4266#define TH_CWR 0x80
4267 uint16_t win; // Window
4268 uint16_t csum; // Checksum
4269 uint16_t urp; // Urgent pointer
4270};
4271 
4272struct udp {
4273 uint16_t sport; // Source port
4274 uint16_t dport; // Destination port
4275 uint16_t len; // UDP length
4276 uint16_t csum; // UDP checksum
4277};
4278 
4279struct dhcp {
4280 uint8_t op, htype, hlen, hops;
4281 uint32_t xid;
4282 uint16_t secs, flags;
4283 uint32_t ciaddr, yiaddr, siaddr, giaddr;
4284 uint8_t hwaddr[208];
4285 uint32_t magic;
4286 uint8_t options[30 + sizeof(((struct mg_tcpip_if *) 0)->dhcp_name)];
4287};
4288 
4289#pragma pack(pop)
4290 
4291struct pkt {
4292 struct mg_str raw; // Raw packet data
4293 struct mg_str pay; // Payload data
4294 struct eth *eth;
4295 struct llc *llc;
4296 struct arp *arp;
4297 struct ip *ip;
4298 struct ip6 *ip6;
4299 struct icmp *icmp;
4300 struct tcp *tcp;
4301 struct udp *udp;
4302 struct dhcp *dhcp;
4303};
4304 
4305static void mg_tcpip_call(struct mg_tcpip_if *ifp, int ev, void *ev_data) {
4306 if (ifp->fn != NULL) ifp->fn(ifp, ev, ev_data);
4307}
4308 
4309static void send_syn(struct mg_connection *c);
4310 
4311static void mkpay(struct pkt *pkt, void *p) {
4312 pkt->pay =
4313 mg_str_n((char *) p, (size_t) (&pkt->raw.buf[pkt->raw.len] - (char *) p));
4314}
4315 
4316static uint32_t csumup(uint32_t sum, const void *buf, size_t len) {
4317 size_t i;
4318 const uint8_t *p = (const uint8_t *) buf;
4319 for (i = 0; i < len; i++) sum += i & 1 ? p[i] : ((uint32_t) p[i]) << 8;
4320 return sum;
4321}
4322 
4323static uint16_t csumfin(uint32_t sum) {
4324 while (sum >> 16) sum = (sum & 0xffff) + (sum >> 16);
4325 return mg_htons(~sum & 0xffff);
4326}
4327 
4328static uint16_t ipcsum(const void *buf, size_t len) {
4329 uint32_t sum = csumup(0, buf, len);
4330 return csumfin(sum);
4331}
4332 
4333static void settmout(struct mg_connection *c, uint8_t type) {
4334 struct mg_tcpip_if *ifp = c->mgr->ifp;
4335 struct connstate *s = (struct connstate *) (c + 1);
4336 unsigned n = type == MIP_TTYPE_ACK ? MIP_TCP_ACK_MS
4337 : type == MIP_TTYPE_ARP ? MIP_ARP_RESP_MS
4338 : type == MIP_TTYPE_SYN ? MIP_TCP_SYN_MS
4339 : type == MIP_TTYPE_FIN ? MIP_TCP_FIN_MS
4340 : MIP_TCP_KEEPALIVE_MS;
4341 s->timer = ifp->now + n;
4342 s->ttype = type;
4343 MG_VERBOSE(("%lu %d -> %llx", c->id, type, s->timer));
4344}
4345 
4346static size_t ether_output(struct mg_tcpip_if *ifp, size_t len) {
4347 size_t n = ifp->driver->tx(ifp->tx.buf, len, ifp);
4348 if (n == len) ifp->nsent++;
4349 return n;
4350}
4351 
4352void mg_tcpip_arp_request(struct mg_tcpip_if *ifp, uint32_t ip, uint8_t *mac) {
4353 struct eth *eth = (struct eth *) ifp->tx.buf;
4354 struct arp *arp = (struct arp *) (eth + 1);
4355 memset(eth->dst, 255, sizeof(eth->dst));
4356 memcpy(eth->src, ifp->mac, sizeof(eth->src));
4357 eth->type = mg_htons(0x806);
4358 memset(arp, 0, sizeof(*arp));
4359 arp->fmt = mg_htons(1), arp->pro = mg_htons(0x800), arp->hlen = 6,
4360 arp->plen = 4;
4361 arp->op = mg_htons(1), arp->tpa = ip, arp->spa = ifp->ip;
4362 memcpy(arp->sha, ifp->mac, sizeof(arp->sha));
4363 if (mac != NULL) memcpy(arp->tha, mac, sizeof(arp->tha));
4364 ether_output(ifp, PDIFF(eth, arp + 1));
4365}
4366 
4367static void onstatechange(struct mg_tcpip_if *ifp) {
4368 if (ifp->state == MG_TCPIP_STATE_READY) {
4369 MG_INFO(("READY, IP: %M", mg_print_ip4, &ifp->ip));
4370 MG_INFO((" GW: %M", mg_print_ip4, &ifp->gw));
4371 MG_INFO((" MAC: %M", mg_print_mac, &ifp->mac));
4372 } else if (ifp->state == MG_TCPIP_STATE_IP) {
4373 MG_ERROR(("Got IP"));
4374 mg_tcpip_arp_request(ifp, ifp->gw, NULL); // unsolicited GW ARP request
4375 } else if (ifp->state == MG_TCPIP_STATE_UP) {
4376 MG_ERROR(("Link up"));
4377 srand((unsigned int) mg_millis());
4378 } else if (ifp->state == MG_TCPIP_STATE_DOWN) {
4379 MG_ERROR(("Link down"));
4380 }
4381 mg_tcpip_call(ifp, MG_TCPIP_EV_ST_CHG, &ifp->state);
4382}
4383 
4384static struct ip *tx_ip(struct mg_tcpip_if *ifp, uint8_t *mac_dst,
4385 uint8_t proto, uint32_t ip_src, uint32_t ip_dst,
4386 size_t plen) {
4387 struct eth *eth = (struct eth *) ifp->tx.buf;
4388 struct ip *ip = (struct ip *) (eth + 1);
4389 memcpy(eth->dst, mac_dst, sizeof(eth->dst));
4390 memcpy(eth->src, ifp->mac, sizeof(eth->src)); // Use our MAC
4391 eth->type = mg_htons(0x800);
4392 memset(ip, 0, sizeof(*ip));
4393 ip->ver = 0x45; // Version 4, header length 5 words
4394 ip->frag = mg_htons(0x4000); // Don't fragment
4395 ip->len = mg_htons((uint16_t) (sizeof(*ip) + plen));
4396 ip->ttl = 64;
4397 ip->proto = proto;
4398 ip->src = ip_src;
4399 ip->dst = ip_dst;
4400 ip->csum = ipcsum(ip, sizeof(*ip));
4401 return ip;
4402}
4403 
4404static void tx_udp(struct mg_tcpip_if *ifp, uint8_t *mac_dst, uint32_t ip_src,
4405 uint16_t sport, uint32_t ip_dst, uint16_t dport,
4406 const void *buf, size_t len) {
4407 struct ip *ip =
4408 tx_ip(ifp, mac_dst, 17, ip_src, ip_dst, len + sizeof(struct udp));
4409 struct udp *udp = (struct udp *) (ip + 1);
4410 // MG_DEBUG(("UDP XX LEN %d %d", (int) len, (int) ifp->tx.len));
4411 udp->sport = sport;
4412 udp->dport = dport;
4413 udp->len = mg_htons((uint16_t) (sizeof(*udp) + len));
4414 udp->csum = 0;
4415 uint32_t cs = csumup(0, udp, sizeof(*udp));
4416 cs = csumup(cs, buf, len);
4417 cs = csumup(cs, &ip->src, sizeof(ip->src));
4418 cs = csumup(cs, &ip->dst, sizeof(ip->dst));
4419 cs += (uint32_t) (ip->proto + sizeof(*udp) + len);
4420 udp->csum = csumfin(cs);
4421 memmove(udp + 1, buf, len);
4422 // MG_DEBUG(("UDP LEN %d %d", (int) len, (int) ifp->frame_len));
4423 ether_output(ifp, sizeof(struct eth) + sizeof(*ip) + sizeof(*udp) + len);
4424}
4425 
4426static void tx_dhcp(struct mg_tcpip_if *ifp, uint8_t *mac_dst, uint32_t ip_src,
4427 uint32_t ip_dst, uint8_t *opts, size_t optslen,
4428 bool ciaddr) {
4429 // https://datatracker.ietf.org/doc/html/rfc2132#section-9.6
4430 struct dhcp dhcp = {1, 1, 6, 0, 0, 0, 0, 0, 0, 0, 0, {0}, 0, {0}};
4431 dhcp.magic = mg_htonl(0x63825363);
4432 memcpy(&dhcp.hwaddr, ifp->mac, sizeof(ifp->mac));
4433 memcpy(&dhcp.xid, ifp->mac + 2, sizeof(dhcp.xid));
4434 memcpy(&dhcp.options, opts, optslen);
4435 if (ciaddr) dhcp.ciaddr = ip_src;
4436 tx_udp(ifp, mac_dst, ip_src, mg_htons(68), ip_dst, mg_htons(67), &dhcp,
4437 sizeof(dhcp));
4438}
4439 
4440static const uint8_t broadcast[] = {255, 255, 255, 255, 255, 255};
4441 
4442// RFC-2131 #4.3.6, #4.4.1; RFC-2132 #9.8
4443static void tx_dhcp_request_sel(struct mg_tcpip_if *ifp, uint32_t ip_req,
4444 uint32_t ip_srv) {
4445 uint8_t extra = (uint8_t) ((ifp->enable_req_dns ? 1 : 0) +
4446 (ifp->enable_req_sntp ? 1 : 0));
4447 size_t len = strlen(ifp->dhcp_name);
4448 size_t olen = 21 + len + extra + 2 + 1; // Total length of options
4449#define OPTS_MAXLEN (21 + sizeof(ifp->dhcp_name) + 2 + 2 + 1)
4450 uint8_t opts[OPTS_MAXLEN]; // Allocate options (max size possible)
4451 uint8_t *p = opts;
4452 assert(olen <= sizeof(opts));
4453 memset(opts, 0, sizeof(opts));
4454 *p++ = 53, *p++ = 1, *p++ = 3; // Type: DHCP request
4455 *p++ = 54, *p++ = 4, memcpy(p, &ip_srv, 4), p += 4; // DHCP server ID
4456 *p++ = 50, *p++ = 4, memcpy(p, &ip_req, 4), p += 4; // Requested IP
4457 *p++ = 12, *p++ = (uint8_t) (len & 255); // DHCP host
4458 memcpy(p, ifp->dhcp_name, len), p += len; // name
4459 *p++ = 55, *p++ = 2 + extra, *p++ = 1, *p++ = 3; // GW, MASK
4460 if (ifp->enable_req_dns) *p++ = 6; // DNS
4461 if (ifp->enable_req_sntp) *p++ = 42; // SNTP
4462 *p++ = 255; // End of options
4463 // assert((size_t) (p - opts) < olen);
4464 tx_dhcp(ifp, (uint8_t *) broadcast, 0, 0xffffffff, opts, olen, 0);
4465 MG_DEBUG(("DHCP req sent"));
4466}
4467 
4468// RFC-2131 #4.3.6, #4.4.5 (renewing: unicast, rebinding: bcast)
4469static void tx_dhcp_request_re(struct mg_tcpip_if *ifp, uint8_t *mac_dst,
4470 uint32_t ip_src, uint32_t ip_dst) {
4471 uint8_t opts[] = {
4472 53, 1, 3, // Type: DHCP request
4473 255 // End of options
4474 };
4475 tx_dhcp(ifp, mac_dst, ip_src, ip_dst, opts, sizeof(opts), true);
4476 MG_DEBUG(("DHCP req sent"));
4477}
4478 
4479static void tx_dhcp_discover(struct mg_tcpip_if *ifp) {
4480 uint8_t opts[] = {
4481 53, 1, 1, // Type: DHCP discover
4482 55, 2, 1, 3, // Parameters: ip, mask
4483 255 // End of options
4484 };
4485 tx_dhcp(ifp, (uint8_t *) broadcast, 0, 0xffffffff, opts, sizeof(opts), false);
4486 MG_DEBUG(("DHCP discover sent. Our MAC: %M", mg_print_mac, ifp->mac));
4487}
4488 
4489static struct mg_connection *getpeer(struct mg_mgr *mgr, struct pkt *pkt,
4490 bool lsn) {
4491 struct mg_connection *c = NULL;
4492 for (c = mgr->conns; c != NULL; c = c->next) {
4493 if (c->is_arplooking && pkt->arp &&
4494 memcmp(&pkt->arp->spa, c->rem.ip, sizeof(pkt->arp->spa)) == 0)
4495 break;
4496 if (c->is_udp && pkt->udp && c->loc.port == pkt->udp->dport) break;
4497 if (!c->is_udp && pkt->tcp && c->loc.port == pkt->tcp->dport &&
4498 lsn == c->is_listening && (lsn || c->rem.port == pkt->tcp->sport))
4499 break;
4500 }
4501 return c;
4502}
4503 
4504static void mac_resolved(struct mg_connection *c);
4505 
4506static void rx_arp(struct mg_tcpip_if *ifp, struct pkt *pkt) {
4507 if (pkt->arp->op == mg_htons(1) && pkt->arp->tpa == ifp->ip) {
4508 // ARP request. Make a response, then send
4509 // MG_DEBUG(("ARP op %d %M: %M", mg_ntohs(pkt->arp->op), mg_print_ip4,
4510 // &pkt->arp->spa, mg_print_ip4, &pkt->arp->tpa));
4511 struct eth *eth = (struct eth *) ifp->tx.buf;
4512 struct arp *arp = (struct arp *) (eth + 1);
4513 memcpy(eth->dst, pkt->eth->src, sizeof(eth->dst));
4514 memcpy(eth->src, ifp->mac, sizeof(eth->src));
4515 eth->type = mg_htons(0x806);
4516 *arp = *pkt->arp;
4517 arp->op = mg_htons(2);
4518 memcpy(arp->tha, pkt->arp->sha, sizeof(pkt->arp->tha));
4519 memcpy(arp->sha, ifp->mac, sizeof(pkt->arp->sha));
4520 arp->tpa = pkt->arp->spa;
4521 arp->spa = ifp->ip;
4522 MG_DEBUG(("ARP: tell %M we're %M", mg_print_ip4, &arp->tpa, mg_print_mac,
4523 &ifp->mac));
4524 ether_output(ifp, PDIFF(eth, arp + 1));
4525 } else if (pkt->arp->op == mg_htons(2)) {
4526 if (memcmp(pkt->arp->tha, ifp->mac, sizeof(pkt->arp->tha)) != 0) return;
4527 if (pkt->arp->spa == ifp->gw) {
4528 // Got response for the GW ARP request. Set ifp->gwmac and IP -> READY
4529 memcpy(ifp->gwmac, pkt->arp->sha, sizeof(ifp->gwmac));
4530 if (ifp->state == MG_TCPIP_STATE_IP) {
4531 ifp->state = MG_TCPIP_STATE_READY;
4532 onstatechange(ifp);
4533 }
4534 } else {
4535 struct mg_connection *c = getpeer(ifp->mgr, pkt, false);
4536 if (c != NULL && c->is_arplooking) {
4537 struct connstate *s = (struct connstate *) (c + 1);
4538 memcpy(s->mac, pkt->arp->sha, sizeof(s->mac));
4539 MG_DEBUG(("%lu ARP resolved %M -> %M", c->id, mg_print_ip4, c->rem.ip,
4540 mg_print_mac, s->mac));
4541 c->is_arplooking = 0;
4542 mac_resolved(c);
4543 }
4544 }
4545 }
4546}
4547 
4548static void rx_icmp(struct mg_tcpip_if *ifp, struct pkt *pkt) {
4549 // MG_DEBUG(("ICMP %d", (int) len));
4550 if (pkt->icmp->type == 8 && pkt->ip != NULL && pkt->ip->dst == ifp->ip) {
4551 size_t hlen = sizeof(struct eth) + sizeof(struct ip) + sizeof(struct icmp);
4552 size_t space = ifp->tx.len - hlen, plen = pkt->pay.len;
4553 if (plen > space) plen = space;
4554 struct ip *ip = tx_ip(ifp, pkt->eth->src, 1, ifp->ip, pkt->ip->src,
4555 sizeof(struct icmp) + plen);
4556 struct icmp *icmp = (struct icmp *) (ip + 1);
4557 memset(icmp, 0, sizeof(*icmp)); // Set csum to 0
4558 memcpy(icmp + 1, pkt->pay.buf, plen); // Copy RX payload to TX
4559 icmp->csum = ipcsum(icmp, sizeof(*icmp) + plen);
4560 ether_output(ifp, hlen + plen);
4561 }
4562}
4563 
4564static void rx_dhcp_client(struct mg_tcpip_if *ifp, struct pkt *pkt) {
4565 uint32_t ip = 0, gw = 0, mask = 0, lease = 0, dns = 0, sntp = 0;
4566 uint8_t msgtype = 0, state = ifp->state;
4567 // perform size check first, then access fields
4568 uint8_t *p = pkt->dhcp->options,
4569 *end = (uint8_t *) &pkt->raw.buf[pkt->raw.len];
4570 if (end < (uint8_t *) (pkt->dhcp + 1)) return;
4571 if (memcmp(&pkt->dhcp->xid, ifp->mac + 2, sizeof(pkt->dhcp->xid))) return;
4572 while (p + 1 < end && p[0] != 255) { // Parse options RFC-1533 #9
4573 if (p[0] == 1 && p[1] == sizeof(ifp->mask) && p + 6 < end) { // Mask
4574 memcpy(&mask, p + 2, sizeof(mask));
4575 } else if (p[0] == 3 && p[1] == sizeof(ifp->gw) && p + 6 < end) { // GW
4576 memcpy(&gw, p + 2, sizeof(gw));
4577 ip = pkt->dhcp->yiaddr;
4578 } else if (ifp->enable_req_dns && p[0] == 6 && p[1] == sizeof(dns) &&
4579 p + 6 < end) { // DNS
4580 memcpy(&dns, p + 2, sizeof(dns));
4581 } else if (ifp->enable_req_sntp && p[0] == 42 && p[1] == sizeof(sntp) &&
4582 p + 6 < end) { // SNTP
4583 memcpy(&sntp, p + 2, sizeof(sntp));
4584 } else if (p[0] == 51 && p[1] == 4 && p + 6 < end) { // Lease
4585 memcpy(&lease, p + 2, sizeof(lease));
4586 lease = mg_ntohl(lease);
4587 } else if (p[0] == 53 && p[1] == 1 && p + 6 < end) { // Msg Type
4588 msgtype = p[2];
4589 }
4590 p += p[1] + 2;
4591 }
4592 // Process message type, RFC-1533 (9.4); RFC-2131 (3.1, 4)
4593 if (msgtype == 6 && ifp->ip == ip) { // DHCPNACK, release IP
4594 ifp->state = MG_TCPIP_STATE_UP, ifp->ip = 0;
4595 } else if (msgtype == 2 && ifp->state == MG_TCPIP_STATE_UP && ip && gw &&
4596 lease) { // DHCPOFFER
4597 // select IP, (4.4.1) (fallback to IP source addr on foul play)
4598 tx_dhcp_request_sel(ifp, ip,
4599 pkt->dhcp->siaddr ? pkt->dhcp->siaddr : pkt->ip->src);
4600 ifp->state = MG_TCPIP_STATE_REQ; // REQUESTING state
4601 } else if (msgtype == 5) { // DHCPACK
4602 if (ifp->state == MG_TCPIP_STATE_REQ && ip && gw && lease) { // got an IP
4603 ifp->lease_expire = ifp->now + lease * 1000;
4604 MG_INFO(("Lease: %u sec (%lld)", lease, ifp->lease_expire / 1000));
4605 // assume DHCP server = router until ARP resolves
4606 memcpy(ifp->gwmac, pkt->eth->src, sizeof(ifp->gwmac));
4607 ifp->ip = ip, ifp->gw = gw, ifp->mask = mask;
4608 ifp->state = MG_TCPIP_STATE_IP; // BOUND state
4609 uint64_t rand;
4610 mg_random(&rand, sizeof(rand));
4611 srand((unsigned int) (rand + mg_millis()));
4612 if (ifp->enable_req_dns && dns != 0)
4613 mg_tcpip_call(ifp, MG_TCPIP_EV_DHCP_DNS, &dns);
4614 if (ifp->enable_req_sntp && sntp != 0)
4615 mg_tcpip_call(ifp, MG_TCPIP_EV_DHCP_SNTP, &sntp);
4616 } else if (ifp->state == MG_TCPIP_STATE_READY && ifp->ip == ip) { // renew
4617 ifp->lease_expire = ifp->now + lease * 1000;
4618 MG_INFO(("Lease: %u sec (%lld)", lease, ifp->lease_expire / 1000));
4619 } // TODO(): accept provided T1/T2 and store server IP for renewal (4.4)
4620 }
4621 if (ifp->state != state) onstatechange(ifp);
4622}
4623 
4624// Simple DHCP server that assigns a next IP address: ifp->ip + 1
4625static void rx_dhcp_server(struct mg_tcpip_if *ifp, struct pkt *pkt) {
4626 uint8_t op = 0, *p = pkt->dhcp->options,
4627 *end = (uint8_t *) &pkt->raw.buf[pkt->raw.len];
4628 if (end < (uint8_t *) (pkt->dhcp + 1)) return;
4629 // struct dhcp *req = pkt->dhcp;
4630 struct dhcp res = {2, 1, 6, 0, 0, 0, 0, 0, 0, 0, 0, {0}, 0, {0}};
4631 res.yiaddr = ifp->ip;
4632 ((uint8_t *) (&res.yiaddr))[3]++; // Offer our IP + 1
4633 while (p + 1 < end && p[0] != 255) { // Parse options
4634 if (p[0] == 53 && p[1] == 1 && p + 2 < end) { // Message type
4635 op = p[2];
4636 }
4637 p += p[1] + 2;
4638 }
4639 if (op == 1 || op == 3) { // DHCP Discover or DHCP Request
4640 uint8_t msg = op == 1 ? 2 : 5; // Message type: DHCP OFFER or DHCP ACK
4641 uint8_t opts[] = {
4642 53, 1, msg, // Message type
4643 1, 4, 0, 0, 0, 0, // Subnet mask
4644 54, 4, 0, 0, 0, 0, // Server ID
4645 12, 3, 'm', 'i', 'p', // Host name: "mip"
4646 51, 4, 255, 255, 255, 255, // Lease time
4647 255 // End of options
4648 };
4649 memcpy(&res.hwaddr, pkt->dhcp->hwaddr, 6);
4650 memcpy(opts + 5, &ifp->mask, sizeof(ifp->mask));
4651 memcpy(opts + 11, &ifp->ip, sizeof(ifp->ip));
4652 memcpy(&res.options, opts, sizeof(opts));
4653 res.magic = pkt->dhcp->magic;
4654 res.xid = pkt->dhcp->xid;
4655 if (ifp->enable_get_gateway) {
4656 ifp->gw = res.yiaddr; // set gw IP, best-effort gwmac as DHCP server's
4657 memcpy(ifp->gwmac, pkt->eth->src, sizeof(ifp->gwmac));
4658 }
4659 tx_udp(ifp, pkt->eth->src, ifp->ip, mg_htons(67),
4660 op == 1 ? ~0U : res.yiaddr, mg_htons(68), &res, sizeof(res));
4661 }
4662}
4663 
4664static void rx_udp(struct mg_tcpip_if *ifp, struct pkt *pkt) {
4665 struct mg_connection *c = getpeer(ifp->mgr, pkt, true);
4666 if (c == NULL) {
4667 // No UDP listener on this port. Should send ICMP, but keep silent.
4668 } else {
4669 c->rem.port = pkt->udp->sport;
4670 memcpy(c->rem.ip, &pkt->ip->src, sizeof(uint32_t));
4671 struct connstate *s = (struct connstate *) (c + 1);
4672 memcpy(s->mac, pkt->eth->src, sizeof(s->mac));
4673 if (c->recv.len >= MG_MAX_RECV_SIZE) {
4674 mg_error(c, "max_recv_buf_size reached");
4675 } else if (c->recv.size - c->recv.len < pkt->pay.len &&
4676 !mg_iobuf_resize(&c->recv, c->recv.len + pkt->pay.len)) {
4677 mg_error(c, "oom");
4678 } else {
4679 memcpy(&c->recv.buf[c->recv.len], pkt->pay.buf, pkt->pay.len);
4680 c->recv.len += pkt->pay.len;
4681 mg_call(c, MG_EV_READ, &pkt->pay.len);
4682 }
4683 }
4684}
4685 
4686static size_t tx_tcp(struct mg_tcpip_if *ifp, uint8_t *dst_mac, uint32_t dst_ip,
4687 uint8_t flags, uint16_t sport, uint16_t dport,
4688 uint32_t seq, uint32_t ack, const void *buf, size_t len) {
4689#if 0
4690 uint8_t opts[] = {2, 4, 5, 0xb4, 4, 2, 0, 0}; // MSS = 1460, SACK permitted
4691 if (flags & TH_SYN) {
4692 // Handshake? Set MSS
4693 buf = opts;
4694 len = sizeof(opts);
4695 }
4696#endif
4697 struct ip *ip =
4698 tx_ip(ifp, dst_mac, 6, ifp->ip, dst_ip, sizeof(struct tcp) + len);
4699 struct tcp *tcp = (struct tcp *) (ip + 1);
4700 memset(tcp, 0, sizeof(*tcp));
4701 if (buf != NULL && len) memmove(tcp + 1, buf, len);
4702 tcp->sport = sport;
4703 tcp->dport = dport;
4704 tcp->seq = seq;
4705 tcp->ack = ack;
4706 tcp->flags = flags;
4707 tcp->win = mg_htons(MIP_TCP_WIN);
4708 tcp->off = (uint8_t) (sizeof(*tcp) / 4 << 4);
4709 // if (flags & TH_SYN) tcp->off = 0x70; // Handshake? header size 28 bytes
4710 
4711 uint32_t cs = 0;
4712 uint16_t n = (uint16_t) (sizeof(*tcp) + len);
4713 uint8_t pseudo[] = {0, ip->proto, (uint8_t) (n >> 8), (uint8_t) (n & 255)};
4714 cs = csumup(cs, tcp, n);
4715 cs = csumup(cs, &ip->src, sizeof(ip->src));
4716 cs = csumup(cs, &ip->dst, sizeof(ip->dst));
4717 cs = csumup(cs, pseudo, sizeof(pseudo));
4718 tcp->csum = csumfin(cs);
4719 MG_VERBOSE(("TCP %M:%hu -> %M:%hu fl %x len %u", mg_print_ip4, &ip->src,
4720 mg_ntohs(tcp->sport), mg_print_ip4, &ip->dst,
4721 mg_ntohs(tcp->dport), tcp->flags, len));
4722 // mg_hexdump(ifp->tx.buf, PDIFF(ifp->tx.buf, tcp + 1) + len);
4723 return ether_output(ifp, PDIFF(ifp->tx.buf, tcp + 1) + len);
4724}
4725 
4726static size_t tx_tcp_pkt(struct mg_tcpip_if *ifp, struct pkt *pkt,
4727 uint8_t flags, uint32_t seq, const void *buf,
4728 size_t len) {
4729 uint32_t delta = (pkt->tcp->flags & (TH_SYN | TH_FIN)) ? 1 : 0;
4730 return tx_tcp(ifp, pkt->eth->src, pkt->ip->src, flags, pkt->tcp->dport,
4731 pkt->tcp->sport, seq, mg_htonl(mg_ntohl(pkt->tcp->seq) + delta),
4732 buf, len);
4733}
4734 
4735static struct mg_connection *accept_conn(struct mg_connection *lsn,
4736 struct pkt *pkt) {
4737 struct mg_connection *c = mg_alloc_conn(lsn->mgr);
4738 if (c == NULL) {
4739 MG_ERROR(("OOM"));
4740 return NULL;
4741 }
4742 struct connstate *s = (struct connstate *) (c + 1);
4743 s->seq = mg_ntohl(pkt->tcp->ack), s->ack = mg_ntohl(pkt->tcp->seq);
4744 memcpy(s->mac, pkt->eth->src, sizeof(s->mac));
4745 settmout(c, MIP_TTYPE_KEEPALIVE);
4746 memcpy(c->rem.ip, &pkt->ip->src, sizeof(uint32_t));
4747 c->rem.port = pkt->tcp->sport;
4748 MG_DEBUG(("%lu accepted %M", c->id, mg_print_ip_port, &c->rem));
4749 LIST_ADD_HEAD(struct mg_connection, &lsn->mgr->conns, c);
4750 c->is_accepted = 1;
4751 c->is_hexdumping = lsn->is_hexdumping;
4752 c->pfn = lsn->pfn;
4753 c->loc = lsn->loc;
4754 c->pfn_data = lsn->pfn_data;
4755 c->fn = lsn->fn;
4756 c->fn_data = lsn->fn_data;
4757 mg_call(c, MG_EV_OPEN, NULL);
4758 mg_call(c, MG_EV_ACCEPT, NULL);
4759 return c;
4760}
4761 
4762static size_t trim_len(struct mg_connection *c, size_t len) {
4763 struct mg_tcpip_if *ifp = c->mgr->ifp;
4764 size_t eth_h_len = 14, ip_max_h_len = 24, tcp_max_h_len = 60, udp_h_len = 8;
4765 size_t max_headers_len =
4766 eth_h_len + ip_max_h_len + (c->is_udp ? udp_h_len : tcp_max_h_len);
4767 size_t min_mtu = c->is_udp ? 68 /* RFC-791 */ : max_headers_len - eth_h_len;
4768 
4769 // If the frame exceeds the available buffer, trim the length
4770 if (len + max_headers_len > ifp->tx.len) {
4771 len = ifp->tx.len - max_headers_len;
4772 }
4773 // Ensure the MTU isn't lower than the minimum allowed value
4774 if (ifp->mtu < min_mtu) {
4775 MG_ERROR(("MTU is lower than minimum, capping to %lu", min_mtu));
4776 ifp->mtu = (uint16_t) min_mtu;
4777 }
4778 // If the total packet size exceeds the MTU, trim the length
4779 if (len + max_headers_len - eth_h_len > ifp->mtu) {
4780 len = ifp->mtu - max_headers_len + eth_h_len;
4781 if (c->is_udp) {
4782 MG_ERROR(("UDP datagram exceeds MTU. Truncating it."));
4783 }
4784 }
4785 
4786 return len;
4787}
4788 
4789long mg_io_send(struct mg_connection *c, const void *buf, size_t len) {
4790 struct mg_tcpip_if *ifp = c->mgr->ifp;
4791 struct connstate *s = (struct connstate *) (c + 1);
4792 uint32_t dst_ip = *(uint32_t *) c->rem.ip;
4793 len = trim_len(c, len);
4794 if (c->is_udp) {
4795 tx_udp(ifp, s->mac, ifp->ip, c->loc.port, dst_ip, c->rem.port, buf, len);
4796 } else {
4797 size_t sent =
4798 tx_tcp(ifp, s->mac, dst_ip, TH_PUSH | TH_ACK, c->loc.port, c->rem.port,
4799 mg_htonl(s->seq), mg_htonl(s->ack), buf, len);
4800 if (sent == 0) {
4801 return MG_IO_WAIT;
4802 } else if (sent == (size_t) -1) {
4803 return MG_IO_ERR;
4804 } else {
4805 s->seq += (uint32_t) len;
4806 if (s->ttype == MIP_TTYPE_ACK) settmout(c, MIP_TTYPE_KEEPALIVE);
4807 }
4808 }
4809 return (long) len;
4810}
4811 
4812static void handle_tls_recv(struct mg_connection *c) {
4813 size_t avail = mg_tls_pending(c);
4814 size_t min = avail > MG_MAX_RECV_SIZE ? MG_MAX_RECV_SIZE : avail;
4815 struct mg_iobuf *io = &c->recv;
4816 if (io->size - io->len < min && !mg_iobuf_resize(io, io->len + min)) {
4817 mg_error(c, "oom");
4818 } else {
4819 // Decrypt data directly into c->recv
4820 long n = mg_tls_recv(c, io->buf != NULL ? &io->buf[io->len] : io->buf,
4821 io->size - io->len);
4822 if (n == MG_IO_ERR) {
4823 mg_error(c, "TLS recv error");
4824 } else if (n > 0) {
4825 // Decrypted successfully - trigger MG_EV_READ
4826 io->len += (size_t) n;
4827 mg_call(c, MG_EV_READ, &n);
4828 } // else n < 0: outstanding data to be moved to c->recv
4829 }
4830}
4831 
4832static void read_conn(struct mg_connection *c, struct pkt *pkt) {
4833 struct connstate *s = (struct connstate *) (c + 1);
4834 struct mg_iobuf *io = c->is_tls ? &c->rtls : &c->recv;
4835 uint32_t seq = mg_ntohl(pkt->tcp->seq);
4836 uint32_t rem_ip;
4837 memcpy(&rem_ip, c->rem.ip, sizeof(uint32_t));
4838 if (pkt->tcp->flags & TH_FIN) {
4839 // If we initiated the closure, we reply with ACK upon receiving FIN
4840 // If we didn't initiate it, we reply with FIN as part of the normal TCP
4841 // closure process
4842 uint8_t flags = TH_ACK;
4843 s->ack = (uint32_t) (mg_htonl(pkt->tcp->seq) + pkt->pay.len + 1);
4844 s->fin_rcvd = true;
4845 if (c->is_draining && s->ttype == MIP_TTYPE_FIN) {
4846 if (s->seq == mg_htonl(pkt->tcp->ack)) { // Simultaneous closure ?
4847 s->seq++; // Yes. Increment our SEQ
4848 } else { // Otherwise,
4849 s->seq = mg_htonl(pkt->tcp->ack); // Set to peer's ACK
4850 }
4851 s->twclosure = true;
4852 } else {
4853 flags |= TH_FIN;
4854 c->is_draining = 1;
4855 settmout(c, MIP_TTYPE_FIN);
4856 }
4857 tx_tcp(c->mgr->ifp, s->mac, rem_ip, flags, c->loc.port, c->rem.port,
4858 mg_htonl(s->seq), mg_htonl(s->ack), "", 0);
4859 if (pkt->pay.len == 0) return; // if no data, we're done
4860 } else if (pkt->pay.len == 0) { // this is an ACK
4861 if (s->fin_rcvd && s->ttype == MIP_TTYPE_FIN) s->twclosure = true;
4862 return; // no data to process
4863 } else if (seq != s->ack) {
4864 uint32_t ack = (uint32_t) (mg_htonl(pkt->tcp->seq) + pkt->pay.len);
4865 if (s->ack == ack) {
4866 MG_VERBOSE(("ignoring duplicate pkt"));
4867 } else {
4868 MG_VERBOSE(("SEQ != ACK: %x %x %x", seq, s->ack, ack));
4869 tx_tcp(c->mgr->ifp, s->mac, rem_ip, TH_ACK, c->loc.port, c->rem.port,
4870 mg_htonl(s->seq), mg_htonl(s->ack), "", 0);
4871 }
4872 return; // drop it
4873 } else if (io->size - io->len < pkt->pay.len &&
4874 !mg_iobuf_resize(io, io->len + pkt->pay.len)) {
4875 mg_error(c, "oom");
4876 return; // drop it
4877 }
4878 // Copy TCP payload into the IO buffer. If the connection is plain text,
4879 // we copy to c->recv. If the connection is TLS, this data is encrypted,
4880 // therefore we copy that encrypted data to the c->rtls iobuffer instead,
4881 // and then call mg_tls_recv() to decrypt it. NOTE: mg_tls_recv() will
4882 // call back mg_io_recv() which grabs raw data from c->rtls
4883 memcpy(&io->buf[io->len], pkt->pay.buf, pkt->pay.len);
4884 io->len += pkt->pay.len;
4885 MG_VERBOSE(("%lu SEQ %x -> %x", c->id, mg_htonl(pkt->tcp->seq), s->ack));
4886 // Advance ACK counter
4887 s->ack = (uint32_t) (mg_htonl(pkt->tcp->seq) + pkt->pay.len);
4888 s->unacked += pkt->pay.len;
4889 // size_t diff = s->acked <= s->ack ? s->ack - s->acked : s->ack;
4890 if (s->unacked > MIP_TCP_WIN / 2 && s->acked != s->ack) {
4891 // Send ACK immediately
4892 MG_VERBOSE(("%lu imm ACK %lu", c->id, s->acked));
4893 tx_tcp(c->mgr->ifp, s->mac, rem_ip, TH_ACK, c->loc.port, c->rem.port,
4894 mg_htonl(s->seq), mg_htonl(s->ack), NULL, 0);
4895 s->unacked = 0;
4896 s->acked = s->ack;
4897 if (s->ttype != MIP_TTYPE_KEEPALIVE) settmout(c, MIP_TTYPE_KEEPALIVE);
4898 } else {
4899 // if not already running, setup a timer to send an ACK later
4900 if (s->ttype != MIP_TTYPE_ACK) settmout(c, MIP_TTYPE_ACK);
4901 }
4902 if (c->is_tls && c->is_tls_hs) {
4903 mg_tls_handshake(c);
4904 } else if (c->is_tls) {
4905 handle_tls_recv(c);
4906 } else {
4907 // Plain text connection, data is already in c->recv, trigger MG_EV_READ
4908 mg_call(c, MG_EV_READ, &pkt->pay.len);
4909 }
4910}
4911 
4912static void rx_tcp(struct mg_tcpip_if *ifp, struct pkt *pkt) {
4913 struct mg_connection *c = getpeer(ifp->mgr, pkt, false);
4914 struct connstate *s = c == NULL ? NULL : (struct connstate *) (c + 1);
4915#if 0
4916 MG_INFO(("%lu %hhu %d", c ? c->id : 0, pkt->tcp->flags, (int) pkt->pay.len));
4917#endif
4918 if (c != NULL && c->is_connecting && pkt->tcp->flags == (TH_SYN | TH_ACK)) {
4919 s->seq = mg_ntohl(pkt->tcp->ack), s->ack = mg_ntohl(pkt->tcp->seq) + 1;
4920 tx_tcp_pkt(ifp, pkt, TH_ACK, pkt->tcp->ack, NULL, 0);
4921 c->is_connecting = 0; // Client connected
4922 settmout(c, MIP_TTYPE_KEEPALIVE);
4923 mg_call(c, MG_EV_CONNECT, NULL); // Let user know
4924 if (c->is_tls_hs) mg_tls_handshake(c);
4925 } else if (c != NULL && c->is_connecting && pkt->tcp->flags != TH_ACK) {
4926 // mg_hexdump(pkt->raw.buf, pkt->raw.len);
4927 tx_tcp_pkt(ifp, pkt, TH_RST | TH_ACK, pkt->tcp->ack, NULL, 0);
4928 } else if (c != NULL && pkt->tcp->flags & TH_RST) {
4929 mg_error(c, "peer RST"); // RFC-1122 4.2.2.13
4930 } else if (c != NULL) {
4931#if 0
4932 MG_DEBUG(("%lu %d %M:%hu -> %M:%hu", c->id, (int) pkt->raw.len,
4933 mg_print_ip4, &pkt->ip->src, mg_ntohs(pkt->tcp->sport),
4934 mg_print_ip4, &pkt->ip->dst, mg_ntohs(pkt->tcp->dport)));
4935 mg_hexdump(pkt->pay.buf, pkt->pay.len);
4936#endif
4937 s->tmiss = 0; // Reset missed keep-alive counter
4938 if (s->ttype == MIP_TTYPE_KEEPALIVE) // Advance keep-alive timer
4939 settmout(c,
4940 MIP_TTYPE_KEEPALIVE); // unless a former ACK timeout is pending
4941 read_conn(c, pkt); // Override timer with ACK timeout if needed
4942 } else if ((c = getpeer(ifp->mgr, pkt, true)) == NULL) {
4943 tx_tcp_pkt(ifp, pkt, TH_RST | TH_ACK, pkt->tcp->ack, NULL, 0);
4944 } else if (pkt->tcp->flags & TH_RST) {
4945 if (c->is_accepted) mg_error(c, "peer RST"); // RFC-1122 4.2.2.13
4946 // ignore RST if not connected
4947 } else if (pkt->tcp->flags & TH_SYN) {
4948 // Use peer's source port as ISN, in order to recognise the handshake
4949 uint32_t isn = mg_htonl((uint32_t) mg_ntohs(pkt->tcp->sport));
4950 tx_tcp_pkt(ifp, pkt, TH_SYN | TH_ACK, isn, NULL, 0);
4951 } else if (pkt->tcp->flags & TH_FIN) {
4952 tx_tcp_pkt(ifp, pkt, TH_FIN | TH_ACK, pkt->tcp->ack, NULL, 0);
4953 } else if (mg_htonl(pkt->tcp->ack) == mg_htons(pkt->tcp->sport) + 1U) {
4954 accept_conn(c, pkt);
4955 } else if (!c->is_accepted) { // no peer
4956 tx_tcp_pkt(ifp, pkt, TH_RST | TH_ACK, pkt->tcp->ack, NULL, 0);
4957 } else {
4958 // MG_VERBOSE(("dropped silently.."));
4959 }
4960}
4961 
4962static void rx_ip(struct mg_tcpip_if *ifp, struct pkt *pkt) {
4963 uint16_t frag = mg_ntohs(pkt->ip->frag);
4964 if (frag & IP_MORE_FRAGS_MSK || frag & IP_FRAG_OFFSET_MSK) {
4965 if (pkt->ip->proto == 17) pkt->udp = (struct udp *) (pkt->ip + 1);
4966 if (pkt->ip->proto == 6) pkt->tcp = (struct tcp *) (pkt->ip + 1);
4967 struct mg_connection *c = getpeer(ifp->mgr, pkt, false);
4968 if (c) mg_error(c, "Received fragmented packet");
4969 } else if (pkt->ip->proto == 1) {
4970 pkt->icmp = (struct icmp *) (pkt->ip + 1);
4971 if (pkt->pay.len < sizeof(*pkt->icmp)) return;
4972 mkpay(pkt, pkt->icmp + 1);
4973 rx_icmp(ifp, pkt);
4974 } else if (pkt->ip->proto == 17) {
4975 pkt->udp = (struct udp *) (pkt->ip + 1);
4976 if (pkt->pay.len < sizeof(*pkt->udp)) return;
4977 mkpay(pkt, pkt->udp + 1);
4978 MG_VERBOSE(("UDP %M:%hu -> %M:%hu len %u", mg_print_ip4, &pkt->ip->src,
4979 mg_ntohs(pkt->udp->sport), mg_print_ip4, &pkt->ip->dst,
4980 mg_ntohs(pkt->udp->dport), (int) pkt->pay.len));
4981 if (ifp->enable_dhcp_client && pkt->udp->dport == mg_htons(68)) {
4982 pkt->dhcp = (struct dhcp *) (pkt->udp + 1);
4983 mkpay(pkt, pkt->dhcp + 1);
4984 rx_dhcp_client(ifp, pkt);
4985 } else if (ifp->enable_dhcp_server && pkt->udp->dport == mg_htons(67)) {
4986 pkt->dhcp = (struct dhcp *) (pkt->udp + 1);
4987 mkpay(pkt, pkt->dhcp + 1);
4988 rx_dhcp_server(ifp, pkt);
4989 } else {
4990 rx_udp(ifp, pkt);
4991 }
4992 } else if (pkt->ip->proto == 6) {
4993 pkt->tcp = (struct tcp *) (pkt->ip + 1);
4994 if (pkt->pay.len < sizeof(*pkt->tcp)) return;
4995 mkpay(pkt, pkt->tcp + 1);
4996 uint16_t iplen = mg_ntohs(pkt->ip->len);
4997 uint16_t off = (uint16_t) (sizeof(*pkt->ip) + ((pkt->tcp->off >> 4) * 4U));
4998 if (iplen >= off) pkt->pay.len = (size_t) (iplen - off);
4999 MG_VERBOSE(("TCP %M:%hu -> %M:%hu len %u", mg_print_ip4, &pkt->ip->src,
5000 mg_ntohs(pkt->tcp->sport), mg_print_ip4, &pkt->ip->dst,
5001 mg_ntohs(pkt->tcp->dport), (int) pkt->pay.len));
5002 rx_tcp(ifp, pkt);
5003 }
5004}
5005 
5006static void rx_ip6(struct mg_tcpip_if *ifp, struct pkt *pkt) {
5007 // MG_DEBUG(("IP %d", (int) len));
5008 if (pkt->ip6->proto == 1 || pkt->ip6->proto == 58) {
5009 pkt->icmp = (struct icmp *) (pkt->ip6 + 1);
5010 if (pkt->pay.len < sizeof(*pkt->icmp)) return;
5011 mkpay(pkt, pkt->icmp + 1);
5012 rx_icmp(ifp, pkt);
5013 } else if (pkt->ip6->proto == 17) {
5014 pkt->udp = (struct udp *) (pkt->ip6 + 1);
5015 if (pkt->pay.len < sizeof(*pkt->udp)) return;
5016 // MG_DEBUG((" UDP %u %u -> %u", len, mg_htons(udp->sport),
5017 // mg_htons(udp->dport)));
5018 mkpay(pkt, pkt->udp + 1);
5019 }
5020}
5021 
5022static void mg_tcpip_rx(struct mg_tcpip_if *ifp, void *buf, size_t len) {
5023 struct pkt pkt;
5024 memset(&pkt, 0, sizeof(pkt));
5025 pkt.raw.buf = (char *) buf;
5026 pkt.raw.len = len;
5027 pkt.eth = (struct eth *) buf;
5028 // mg_hexdump(buf, len > 16 ? 16: len);
5029 if (pkt.raw.len < sizeof(*pkt.eth)) return; // Truncated - runt?
5030 if (ifp->enable_mac_check &&
5031 memcmp(pkt.eth->dst, ifp->mac, sizeof(pkt.eth->dst)) != 0 &&
5032 memcmp(pkt.eth->dst, broadcast, sizeof(pkt.eth->dst)) != 0)
5033 return;
5034 if (ifp->enable_crc32_check && len > 4) {
5035 len -= 4; // TODO(scaprile): check on bigendian
5036 uint32_t crc = mg_crc32(0, (const char *) buf, len);
5037 if (memcmp((void *) ((size_t) buf + len), &crc, sizeof(crc))) return;
5038 }
5039 if (pkt.eth->type == mg_htons(0x806)) {
5040 pkt.arp = (struct arp *) (pkt.eth + 1);
5041 if (sizeof(*pkt.eth) + sizeof(*pkt.arp) > pkt.raw.len) return; // Truncated
5042 mg_tcpip_call(ifp, MG_TCPIP_EV_ARP, &pkt.raw);
5043 rx_arp(ifp, &pkt);
5044 } else if (pkt.eth->type == mg_htons(0x86dd)) {
5045 pkt.ip6 = (struct ip6 *) (pkt.eth + 1);
5046 if (pkt.raw.len < sizeof(*pkt.eth) + sizeof(*pkt.ip6)) return; // Truncated
5047 if ((pkt.ip6->ver >> 4) != 0x6) return; // Not IP
5048 mkpay(&pkt, pkt.ip6 + 1);
5049 rx_ip6(ifp, &pkt);
5050 } else if (pkt.eth->type == mg_htons(0x800)) {
5051 pkt.ip = (struct ip *) (pkt.eth + 1);
5052 if (pkt.raw.len < sizeof(*pkt.eth) + sizeof(*pkt.ip)) return; // Truncated
5053 // Truncate frame to what IP header tells us
5054 if ((size_t) mg_ntohs(pkt.ip->len) + sizeof(struct eth) < pkt.raw.len) {
5055 pkt.raw.len = (size_t) mg_ntohs(pkt.ip->len) + sizeof(struct eth);
5056 }
5057 if (pkt.raw.len < sizeof(*pkt.eth) + sizeof(*pkt.ip)) return; // Truncated
5058 if ((pkt.ip->ver >> 4) != 4) return; // Not IP
5059 mkpay(&pkt, pkt.ip + 1);
5060 rx_ip(ifp, &pkt);
5061 } else {
5062 MG_DEBUG(("Unknown eth type %x", mg_htons(pkt.eth->type)));
5063 if (mg_log_level >= MG_LL_VERBOSE) mg_hexdump(buf, len >= 32 ? 32 : len);
5064 }
5065}
5066 
5067static void mg_tcpip_poll(struct mg_tcpip_if *ifp, uint64_t now) {
5068 struct mg_connection *c;
5069 bool expired_1000ms = mg_timer_expired(&ifp->timer_1000ms, 1000, now);
5070 ifp->now = now;
5071 
5072 if (expired_1000ms) {
5073#if MG_ENABLE_TCPIP_PRINT_DEBUG_STATS
5074 const char *names[] = {"down", "up", "req", "ip", "ready"};
5075 MG_INFO(("Status: %s, IP: %M, rx:%u, tx:%u, dr:%u, er:%u",
5076 names[ifp->state], mg_print_ip4, &ifp->ip, ifp->nrecv, ifp->nsent,
5077 ifp->ndrop, ifp->nerr));
5078#endif
5079 }
5080 // Handle gw ARP request timeout, order is important
5081 if (expired_1000ms && ifp->state == MG_TCPIP_STATE_IP) {
5082 ifp->state = MG_TCPIP_STATE_READY; // keep best-effort MAC
5083 onstatechange(ifp);
5084 }
5085 // poll driver
5086 if (ifp->driver->poll) {
5087 bool up = ifp->driver->poll(ifp, expired_1000ms);
5088 // Handle physical interface up/down status
5089 if (expired_1000ms) {
5090 bool current = ifp->state != MG_TCPIP_STATE_DOWN;
5091 if (!up && ifp->enable_dhcp_client) ifp->ip = 0;
5092 if (up != current) { // link state has changed
5093 ifp->state = up == false ? MG_TCPIP_STATE_DOWN
5094 : ifp->enable_dhcp_client || ifp->ip == 0
5095 ? MG_TCPIP_STATE_UP
5096 : MG_TCPIP_STATE_IP;
5097 onstatechange(ifp);
5098 } else if (!ifp->enable_dhcp_client && ifp->state == MG_TCPIP_STATE_UP &&
5099 ifp->ip) {
5100 ifp->state = MG_TCPIP_STATE_IP; // ifp->fn has set an IP
5101 onstatechange(ifp);
5102 }
5103 if (ifp->state == MG_TCPIP_STATE_DOWN) MG_ERROR(("Network is down"));
5104 mg_tcpip_call(ifp, MG_TCPIP_EV_TIMER_1S, NULL);
5105 }
5106 }
5107 if (ifp->state == MG_TCPIP_STATE_DOWN) return;
5108 
5109 // DHCP RFC-2131 (4.4)
5110 if (ifp->enable_dhcp_client && expired_1000ms) {
5111 if (ifp->state == MG_TCPIP_STATE_UP) {
5112 tx_dhcp_discover(ifp); // INIT (4.4.1)
5113 } else if (ifp->state == MG_TCPIP_STATE_READY &&
5114 ifp->lease_expire > 0) { // BOUND / RENEWING / REBINDING
5115 if (ifp->now >= ifp->lease_expire) {
5116 ifp->state = MG_TCPIP_STATE_UP, ifp->ip = 0; // expired, release IP
5117 onstatechange(ifp);
5118 } else if (ifp->now + 30UL * 60UL * 1000UL > ifp->lease_expire &&
5119 ((ifp->now / 1000) % 60) == 0) {
5120 // hack: 30 min before deadline, try to rebind (4.3.6) every min
5121 tx_dhcp_request_re(ifp, (uint8_t *) broadcast, ifp->ip, 0xffffffff);
5122 } // TODO(): Handle T1 (RENEWING) and T2 (REBINDING) (4.4.5)
5123 }
5124 }
5125 
5126 // Read data from the network
5127 if (ifp->driver->rx != NULL) { // Simple polling driver, returns one frame
5128 size_t len =
5129 ifp->driver->rx(ifp->recv_queue.buf, ifp->recv_queue.size, ifp);
5130 if (len > 0) {
5131 ifp->nrecv++;
5132 mg_tcpip_rx(ifp, ifp->recv_queue.buf, len);
5133 }
5134 } else { // Complex poll / Interrupt-based driver. Queues recvd frames
5135 char *buf;
5136 size_t len = mg_queue_next(&ifp->recv_queue, &buf);
5137 if (len > 0) {
5138 mg_tcpip_rx(ifp, buf, len);
5139 mg_queue_del(&ifp->recv_queue, len);
5140 }
5141 }
5142 
5143 // Process timeouts
5144 for (c = ifp->mgr->conns; c != NULL; c = c->next) {
5145 if ((c->is_udp && !c->is_arplooking) || c->is_listening || c->is_resolving)
5146 continue;
5147 struct connstate *s = (struct connstate *) (c + 1);
5148 uint32_t rem_ip;
5149 memcpy(&rem_ip, c->rem.ip, sizeof(uint32_t));
5150 if (ifp->now > s->timer) {
5151 if (s->ttype == MIP_TTYPE_ARP) {
5152 mg_error(c, "ARP timeout");
5153 } else if (c->is_udp) {
5154 continue;
5155 } else if (s->ttype == MIP_TTYPE_ACK && s->acked != s->ack) {
5156 MG_VERBOSE(("%lu ack %x %x", c->id, s->seq, s->ack));
5157 tx_tcp(ifp, s->mac, rem_ip, TH_ACK, c->loc.port, c->rem.port,
5158 mg_htonl(s->seq), mg_htonl(s->ack), NULL, 0);
5159 s->acked = s->ack;
5160 } else if (s->ttype == MIP_TTYPE_SYN) {
5161 mg_error(c, "Connection timeout");
5162 } else if (s->ttype == MIP_TTYPE_FIN) {
5163 c->is_closing = 1;
5164 continue;
5165 } else {
5166 if (s->tmiss++ > 2) {
5167 mg_error(c, "keepalive");
5168 } else {
5169 MG_VERBOSE(("%lu keepalive", c->id));
5170 tx_tcp(ifp, s->mac, rem_ip, TH_ACK, c->loc.port, c->rem.port,
5171 mg_htonl(s->seq - 1), mg_htonl(s->ack), NULL, 0);
5172 }
5173 }
5174 
5175 settmout(c, MIP_TTYPE_KEEPALIVE);
5176 }
5177 }
5178}
5179 
5180// This function executes in interrupt context, thus it should copy data
5181// somewhere fast. Note that newlib's malloc is not thread safe, thus use
5182// our lock-free queue with preallocated buffer to copy data and return asap
5183void mg_tcpip_qwrite(void *buf, size_t len, struct mg_tcpip_if *ifp) {
5184 char *p;
5185 if (mg_queue_book(&ifp->recv_queue, &p, len) >= len) {
5186 memcpy(p, buf, len);
5187 mg_queue_add(&ifp->recv_queue, len);
5188 ifp->nrecv++;
5189 } else {
5190 ifp->ndrop++;
5191 }
5192}
5193 
5194void mg_tcpip_init(struct mg_mgr *mgr, struct mg_tcpip_if *ifp) {
5195 // If MAC address is not set, make a random one
5196 if (ifp->mac[0] == 0 && ifp->mac[1] == 0 && ifp->mac[2] == 0 &&
5197 ifp->mac[3] == 0 && ifp->mac[4] == 0 && ifp->mac[5] == 0) {
5198 ifp->mac[0] = 0x02; // Locally administered, unicast
5199 mg_random(&ifp->mac[1], sizeof(ifp->mac) - 1);
5200 MG_INFO(("MAC not set. Generated random: %M", mg_print_mac, ifp->mac));
5201 }
5202 
5203 // Uf DHCP name is not set, use "mip"
5204 if (ifp->dhcp_name[0] == '\0') {
5205 memcpy(ifp->dhcp_name, "mip", 4);
5206 }
5207 ifp->dhcp_name[sizeof(ifp->dhcp_name) - 1] = '\0'; // Just in case
5208 
5209 if (ifp->driver->init && !ifp->driver->init(ifp)) {
5210 MG_ERROR(("driver init failed"));
5211 } else {
5212 size_t framesize = 1540;
5213 ifp->tx.buf = (char *) calloc(1, framesize), ifp->tx.len = framesize;
5214 if (ifp->recv_queue.size == 0)
5215 ifp->recv_queue.size = ifp->driver->rx ? framesize : 8192;
5216 ifp->recv_queue.buf = (char *) calloc(1, ifp->recv_queue.size);
5217 ifp->timer_1000ms = mg_millis();
5218 mgr->ifp = ifp;
5219 ifp->mgr = mgr;
5220 ifp->mtu = MG_TCPIP_MTU_DEFAULT;
5221 mgr->extraconnsize = sizeof(struct connstate);
5222 if (ifp->ip == 0) ifp->enable_dhcp_client = true;
5223 memset(ifp->gwmac, 255, sizeof(ifp->gwmac)); // Set best-effort to bcast
5224 mg_random(&ifp->eport, sizeof(ifp->eport)); // Random from 0 to 65535
5225 ifp->eport |= MG_EPHEMERAL_PORT_BASE; // Random from
5226 // MG_EPHEMERAL_PORT_BASE to 65535
5227 if (ifp->tx.buf == NULL || ifp->recv_queue.buf == NULL) MG_ERROR(("OOM"));
5228 }
5229}
5230 
5231void mg_tcpip_free(struct mg_tcpip_if *ifp) {
5232 free(ifp->recv_queue.buf);
5233 free(ifp->tx.buf);
5234}
5235 
5236static void send_syn(struct mg_connection *c) {
5237 struct connstate *s = (struct connstate *) (c + 1);
5238 uint32_t isn = mg_htonl((uint32_t) mg_ntohs(c->loc.port));
5239 uint32_t rem_ip;
5240 memcpy(&rem_ip, c->rem.ip, sizeof(uint32_t));
5241 tx_tcp(c->mgr->ifp, s->mac, rem_ip, TH_SYN, c->loc.port, c->rem.port, isn, 0,
5242 NULL, 0);
5243}
5244 
5245static void mac_resolved(struct mg_connection *c) {
5246 if (c->is_udp) {
5247 c->is_connecting = 0;
5248 mg_call(c, MG_EV_CONNECT, NULL);
5249 } else {
5250 send_syn(c);
5251 settmout(c, MIP_TTYPE_SYN);
5252 }
5253}
5254 
5255static void ip4_mcastmac(uint8_t *mac, uint32_t *ip) {
5256 uint8_t mcastp[3] = {0x01, 0x00, 0x5E}; // multicast group MAC
5257 memcpy(mac, mcastp, 3);
5258 memcpy(mac + 3, ((uint8_t *) ip) + 1, 3); // 23 LSb
5259 mac[3] &= 0x7F;
5260}
5261 
5262void mg_connect_resolved(struct mg_connection *c) {
5263 struct mg_tcpip_if *ifp = c->mgr->ifp;
5264 uint32_t rem_ip;
5265 memcpy(&rem_ip, c->rem.ip, sizeof(uint32_t));
5266 c->is_resolving = 0;
5267 if (ifp->eport < MG_EPHEMERAL_PORT_BASE) ifp->eport = MG_EPHEMERAL_PORT_BASE;
5268 memcpy(c->loc.ip, &ifp->ip, sizeof(uint32_t));
5269 c->loc.port = mg_htons(ifp->eport++);
5270 MG_DEBUG(("%lu %M -> %M", c->id, mg_print_ip_port, &c->loc, mg_print_ip_port,
5271 &c->rem));
5272 mg_call(c, MG_EV_RESOLVE, NULL);
5273 c->is_connecting = 1;
5274 if (c->is_udp && (rem_ip == 0xffffffff || rem_ip == (ifp->ip | ~ifp->mask))) {
5275 struct connstate *s = (struct connstate *) (c + 1);
5276 memset(s->mac, 0xFF, sizeof(s->mac)); // global or local broadcast
5277 mac_resolved(c);
5278 } else if (ifp->ip && ((rem_ip & ifp->mask) == (ifp->ip & ifp->mask)) &&
5279 rem_ip != ifp->gw) { // skip if gw (onstatechange -> READY -> ARP)
5280 // If we're in the same LAN, fire an ARP lookup.
5281 MG_DEBUG(("%lu ARP lookup...", c->id));
5282 mg_tcpip_arp_request(ifp, rem_ip, NULL);
5283 settmout(c, MIP_TTYPE_ARP);
5284 c->is_arplooking = 1;
5285 } else if ((*((uint8_t *) &rem_ip) & 0xE0) == 0xE0) {
5286 struct connstate *s = (struct connstate *) (c + 1); // 224 to 239, E0 to EF
5287 ip4_mcastmac(s->mac, &rem_ip); // multicast group
5288 mac_resolved(c);
5289 } else {
5290 struct connstate *s = (struct connstate *) (c + 1);
5291 memcpy(s->mac, ifp->gwmac, sizeof(ifp->gwmac));
5292 mac_resolved(c);
5293 }
5294}
5295 
5296bool mg_open_listener(struct mg_connection *c, const char *url) {
5297 c->loc.port = mg_htons(mg_url_port(url));
5298 if (!mg_aton(mg_url_host(url), &c->loc)) {
5299 MG_ERROR(("invalid listening URL: %s", url));
5300 return false;
5301 }
5302 return true;
5303}
5304 
5305static void write_conn(struct mg_connection *c) {
5306 long len = c->is_tls ? mg_tls_send(c, c->send.buf, c->send.len)
5307 : mg_io_send(c, c->send.buf, c->send.len);
5308 if (len == MG_IO_ERR) {
5309 mg_error(c, "tx err");
5310 } else if (len > 0) {
5311 mg_iobuf_del(&c->send, 0, (size_t) len);
5312 mg_call(c, MG_EV_WRITE, &len);
5313 }
5314}
5315 
5316static void init_closure(struct mg_connection *c) {
5317 struct connstate *s = (struct connstate *) (c + 1);
5318 if (c->is_udp == false && c->is_listening == false &&
5319 c->is_connecting == false) { // For TCP conns,
5320 uint32_t rem_ip;
5321 memcpy(&rem_ip, c->rem.ip, sizeof(uint32_t));
5322 tx_tcp(c->mgr->ifp, s->mac, rem_ip, TH_FIN | TH_ACK, c->loc.port,
5323 c->rem.port, mg_htonl(s->seq), mg_htonl(s->ack), NULL, 0);
5324 settmout(c, MIP_TTYPE_FIN);
5325 }
5326}
5327 
5328static void close_conn(struct mg_connection *c) {
5329 struct connstate *s = (struct connstate *) (c + 1);
5330 mg_iobuf_free(&s->raw); // For TLS connections, release raw data
5331 mg_close_conn(c);
5332}
5333 
5334static bool can_write(struct mg_connection *c) {
5335 return c->is_connecting == 0 && c->is_resolving == 0 && c->send.len > 0 &&
5336 c->is_tls_hs == 0 && c->is_arplooking == 0;
5337}
5338 
5339void mg_mgr_poll(struct mg_mgr *mgr, int ms) {
5340 struct mg_connection *c, *tmp;
5341 uint64_t now = mg_millis();
5342 mg_timer_poll(&mgr->timers, now);
5343 if (mgr->ifp == NULL || mgr->ifp->driver == NULL) return;
5344 mg_tcpip_poll(mgr->ifp, now);
5345 for (c = mgr->conns; c != NULL; c = tmp) {
5346 tmp = c->next;
5347 struct connstate *s = (struct connstate *) (c + 1);
5348 mg_call(c, MG_EV_POLL, &now);
5349 MG_VERBOSE(("%lu .. %c%c%c%c%c %lu %lu", c->id, c->is_tls ? 'T' : 't',
5350 c->is_connecting ? 'C' : 'c', c->is_tls_hs ? 'H' : 'h',
5351 c->is_resolving ? 'R' : 'r', c->is_closing ? 'C' : 'c',
5352 mg_tls_pending(c), c->rtls.len));
5353 // order is important, TLS conn close with > 1 record in buffer (below)
5354 if (c->is_tls && (c->rtls.len > 0 || mg_tls_pending(c) > 0))
5355 handle_tls_recv(c);
5356 if (can_write(c)) write_conn(c);
5357 if (c->is_draining && c->send.len == 0 && s->ttype != MIP_TTYPE_FIN)
5358 init_closure(c);
5359 // For non-TLS, close immediately upon completing the 3-way closure
5360 // For TLS, handle any pending data (above) until MIP_TTYPE_FIN expires
5361 if (s->twclosure &&
5362 (!c->is_tls || (c->rtls.len == 0 && mg_tls_pending(c) == 0)))
5363 c->is_closing = 1;
5364 if (c->is_closing) close_conn(c);
5365 }
5366 (void) ms;
5367}
5368 
5369bool mg_send(struct mg_connection *c, const void *buf, size_t len) {
5370 struct mg_tcpip_if *ifp = c->mgr->ifp;
5371 bool res = false;
5372 uint32_t rem_ip;
5373 memcpy(&rem_ip, c->rem.ip, sizeof(uint32_t));
5374 if (ifp->ip == 0 || ifp->state != MG_TCPIP_STATE_READY) {
5375 mg_error(c, "net down");
5376 } else if (c->is_udp && (c->is_arplooking || c->is_resolving)) {
5377 // Fail to send, no target MAC or IP
5378 MG_VERBOSE(("still resolving..."));
5379 } else if (c->is_udp) {
5380 struct connstate *s = (struct connstate *) (c + 1);
5381 len = trim_len(c, len); // Trimming length if necessary
5382 tx_udp(ifp, s->mac, ifp->ip, c->loc.port, rem_ip, c->rem.port, buf, len);
5383 res = true;
5384 } else {
5385 res = mg_iobuf_add(&c->send, c->send.len, buf, len);
5386 }
5387 return res;
5388}
5389 
5390uint8_t mcast_addr[6] = {0x01, 0x00, 0x5e, 0x00, 0x00, 0xfb};
5391void mg_multicast_add(struct mg_connection *c, char *ip) {
5392 (void) ip; // ip4_mcastmac(mcast_mac, &ip);
5393 // TODO(): actual IP -> MAC; check database, update
5394 c->mgr->ifp->update_mac_hash_table = true; // mark dirty
5395}
5396 
5397#endif // MG_ENABLE_TCPIP
5398 
5399#ifdef MG_ENABLE_LINES
5400#line 1 "src/ota_ch32v307.c"
5401#endif
5402 
5403 
5404 
5405 
5406#if MG_OTA == MG_OTA_CH32V307
5407// RM: https://www.wch-ic.com/downloads/CH32FV2x_V3xRM_PDF.html
5408 
5409static bool mg_ch32v307_write(void *, const void *, size_t);
5410static bool mg_ch32v307_swap(void);
5411 
5412static struct mg_flash s_mg_flash_ch32v307 = {
5413 (void *) 0x08000000, // Start
5414 480 * 1024, // Size, first 320k is 0-wait
5415 4 * 1024, // Sector size, 4k
5416 4, // Align, 32 bit
5417 mg_ch32v307_write,
5418 mg_ch32v307_swap,
5419};
5420 
5421#define FLASH_BASE 0x40022000
5422#define FLASH_ACTLR (FLASH_BASE + 0)
5423#define FLASH_KEYR (FLASH_BASE + 4)
5424#define FLASH_OBKEYR (FLASH_BASE + 8)
5425#define FLASH_STATR (FLASH_BASE + 12)
5426#define FLASH_CTLR (FLASH_BASE + 16)
5427#define FLASH_ADDR (FLASH_BASE + 20)
5428#define FLASH_OBR (FLASH_BASE + 28)
5429#define FLASH_WPR (FLASH_BASE + 32)
5430 
5431MG_IRAM static void flash_unlock(void) {
5432 static bool unlocked;
5433 if (unlocked == false) {
5434 MG_REG(FLASH_KEYR) = 0x45670123;
5435 MG_REG(FLASH_KEYR) = 0xcdef89ab;
5436 unlocked = true;
5437 }
5438}
5439 
5440MG_IRAM static void flash_wait(void) {
5441 while (MG_REG(FLASH_STATR) & MG_BIT(0)) (void) 0;
5442}
5443 
5444MG_IRAM static void mg_ch32v307_erase(void *addr) {
5445 // MG_INFO(("%p", addr));
5446 flash_unlock();
5447 flash_wait();
5448 MG_REG(FLASH_ADDR) = (uint32_t) addr;
5449 MG_REG(FLASH_CTLR) |= MG_BIT(1) | MG_BIT(6); // PER | STRT;
5450 flash_wait();
5451}
5452 
5453MG_IRAM static bool is_page_boundary(const void *addr) {
5454 uint32_t val = (uint32_t) addr;
5455 return (val & (s_mg_flash_ch32v307.secsz - 1)) == 0;
5456}
5457 
5458MG_IRAM static bool mg_ch32v307_write(void *addr, const void *buf, size_t len) {
5459 // MG_INFO(("%p %p %lu", addr, buf, len));
5460 // mg_hexdump(buf, len);
5461 flash_unlock();
5462 const uint16_t *src = (uint16_t *) buf, *end = &src[len / 2];
5463 uint16_t *dst = (uint16_t *) addr;
5464 MG_REG(FLASH_CTLR) |= MG_BIT(0); // Set PG
5465 // MG_INFO(("CTLR: %#lx", MG_REG(FLASH_CTLR)));
5466 while (src < end) {
5467 if (is_page_boundary(dst)) mg_ch32v307_erase(dst);
5468 *dst++ = *src++;
5469 flash_wait();
5470 }
5471 MG_REG(FLASH_CTLR) &= ~MG_BIT(0); // Clear PG
5472 return true;
5473}
5474 
5475MG_IRAM bool mg_ch32v307_swap(void) {
5476 return true;
5477}
5478 
5479// just overwrite instead of swap
5480MG_IRAM static void single_bank_swap(char *p1, char *p2, size_t s, size_t ss) {
5481 // no stdlib calls here
5482 for (size_t ofs = 0; ofs < s; ofs += ss) {
5483 mg_ch32v307_write(p1 + ofs, p2 + ofs, ss);
5484 }
5485 *((volatile uint32_t *) 0xbeef0000) |= 1U << 7; // NVIC_SystemReset()
5486}
5487 
5488bool mg_ota_begin(size_t new_firmware_size) {
5489 return mg_ota_flash_begin(new_firmware_size, &s_mg_flash_ch32v307);
5490}
5491 
5492bool mg_ota_write(const void *buf, size_t len) {
5493 return mg_ota_flash_write(buf, len, &s_mg_flash_ch32v307);
5494}
5495 
5496bool mg_ota_end(void) {
5497 if (mg_ota_flash_end(&s_mg_flash_ch32v307)) {
5498 // Swap partitions. Pray power does not go away
5499 MG_INFO(("Swapping partitions, size %u (%u sectors)",
5500 s_mg_flash_ch32v307.size,
5501 s_mg_flash_ch32v307.size / s_mg_flash_ch32v307.secsz));
5502 MG_INFO(("Do NOT power off..."));
5503 mg_log_level = MG_LL_NONE;
5504 // TODO() disable IRQ, s_flash_irq_disabled = true;
5505 // Runs in RAM, will reset when finished
5506 single_bank_swap(
5507 (char *) s_mg_flash_ch32v307.start,
5508 (char *) s_mg_flash_ch32v307.start + s_mg_flash_ch32v307.size / 2,
5509 s_mg_flash_ch32v307.size / 2, s_mg_flash_ch32v307.secsz);
5510 }
5511 return false;
5512}
5513#endif
5514 
5515#ifdef MG_ENABLE_LINES
5516#line 1 "src/ota_dummy.c"
5517#endif
5518 
5519 
5520 
5521#if MG_OTA == MG_OTA_NONE
5522bool mg_ota_begin(size_t new_firmware_size) {
5523 (void) new_firmware_size;
5524 return true;
5525}
5526bool mg_ota_write(const void *buf, size_t len) {
5527 (void) buf, (void) len;
5528 return true;
5529}
5530bool mg_ota_end(void) {
5531 return true;
5532}
5533#endif
5534 
5535#ifdef MG_ENABLE_LINES
5536#line 1 "src/ota_esp32.c"
5537#endif
5538 
5539 
5540#if MG_ARCH == MG_ARCH_ESP32 && MG_OTA == MG_OTA_ESP32
5541 
5542static const esp_partition_t *s_ota_update_partition;
5543static esp_ota_handle_t s_ota_update_handle;
5544static bool s_ota_success;
5545 
5546// Those empty macros do nothing, but mark places in the code which could
5547// potentially trigger a watchdog reboot due to the log flash erase operation
5548#define disable_wdt()
5549#define enable_wdt()
5550 
5551bool mg_ota_begin(size_t new_firmware_size) {
5552 if (s_ota_update_partition != NULL) {
5553 MG_ERROR(("Update in progress. Call mg_ota_end() ?"));
5554 return false;
5555 } else {
5556 s_ota_success = false;
5557 disable_wdt();
5558 s_ota_update_partition = esp_ota_get_next_update_partition(NULL);
5559 esp_err_t err = esp_ota_begin(s_ota_update_partition, new_firmware_size,
5560 &s_ota_update_handle);
5561 enable_wdt();
5562 MG_DEBUG(("esp_ota_begin(): %d", err));
5563 s_ota_success = (err == ESP_OK);
5564 }
5565 return s_ota_success;
5566}
5567 
5568bool mg_ota_write(const void *buf, size_t len) {
5569 disable_wdt();
5570 esp_err_t err = esp_ota_write(s_ota_update_handle, buf, len);
5571 enable_wdt();
5572 MG_INFO(("esp_ota_write(): %d", err));
5573 s_ota_success = err == ESP_OK;
5574 return s_ota_success;
5575}
5576 
5577bool mg_ota_end(void) {
5578 esp_err_t err = esp_ota_end(s_ota_update_handle);
5579 MG_DEBUG(("esp_ota_end(%p): %d", s_ota_update_handle, err));
5580 if (s_ota_success && err == ESP_OK) {
5581 err = esp_ota_set_boot_partition(s_ota_update_partition);
5582 s_ota_success = (err == ESP_OK);
5583 }
5584 MG_DEBUG(("Finished ESP32 OTA, success: %d", s_ota_success));
5585 s_ota_update_partition = NULL;
5586 return s_ota_success;
5587}
5588 
5589#endif
5590 
5591#ifdef MG_ENABLE_LINES
5592#line 1 "src/ota_imxrt.c"
5593#endif
5594 
5595 
5596 
5597 
5598#if MG_OTA >= MG_OTA_RT1020 && MG_OTA <= MG_OTA_RT1170
5599 
5600static bool mg_imxrt_write(void *, const void *, size_t);
5601static bool mg_imxrt_swap(void);
5602 
5603#if MG_OTA <= MG_OTA_RT1060
5604#define MG_IMXRT_FLASH_START 0x60000000
5605#define FLEXSPI_NOR_INSTANCE 0
5606#elif MG_OTA == MG_OTA_RT1064
5607#define MG_IMXRT_FLASH_START 0x70000000
5608#define FLEXSPI_NOR_INSTANCE 1
5609#else // RT1170
5610#define MG_IMXRT_FLASH_START 0x30000000
5611#define FLEXSPI_NOR_INSTANCE 1
5612#endif
5613 
5614#if MG_OTA == MG_OTA_RT1050
5615#define MG_IMXRT_SECTOR_SIZE (256 * 1024)
5616#define MG_IMXRT_PAGE_SIZE 512
5617#else
5618#define MG_IMXRT_SECTOR_SIZE (4 * 1024)
5619#define MG_IMXRT_PAGE_SIZE 256
5620#endif
5621 
5622// TODO(): fill at init, support more devices in a dynamic way
5623// TODO(): then, check alignment is <= 256, see Wizard's #251
5624static struct mg_flash s_mg_flash_imxrt = {
5625 (void *) MG_IMXRT_FLASH_START, // Start,
5626 4 * 1024 * 1024, // Size, 4mb
5627 MG_IMXRT_SECTOR_SIZE, // Sector size
5628 MG_IMXRT_PAGE_SIZE, // Align
5629 mg_imxrt_write,
5630 mg_imxrt_swap,
5631};
5632 
5633struct mg_flexspi_lut_seq {
5634 uint8_t seqNum;
5635 uint8_t seqId;
5636 uint16_t reserved;
5637};
5638 
5639struct mg_flexspi_mem_config {
5640 uint32_t tag;
5641 uint32_t version;
5642 uint32_t reserved0;
5643 uint8_t readSampleClkSrc;
5644 uint8_t csHoldTime;
5645 uint8_t csSetupTime;
5646 uint8_t columnAddressWidth;
5647 uint8_t deviceModeCfgEnable;
5648 uint8_t deviceModeType;
5649 uint16_t waitTimeCfgCommands;
5650 struct mg_flexspi_lut_seq deviceModeSeq;
5651 uint32_t deviceModeArg;
5652 uint8_t configCmdEnable;
5653 uint8_t configModeType[3];
5654 struct mg_flexspi_lut_seq configCmdSeqs[3];
5655 uint32_t reserved1;
5656 uint32_t configCmdArgs[3];
5657 uint32_t reserved2;
5658 uint32_t controllerMiscOption;
5659 uint8_t deviceType;
5660 uint8_t sflashPadType;
5661 uint8_t serialClkFreq;
5662 uint8_t lutCustomSeqEnable;
5663 uint32_t reserved3[2];
5664 uint32_t sflashA1Size;
5665 uint32_t sflashA2Size;
5666 uint32_t sflashB1Size;
5667 uint32_t sflashB2Size;
5668 uint32_t csPadSettingOverride;
5669 uint32_t sclkPadSettingOverride;
5670 uint32_t dataPadSettingOverride;
5671 uint32_t dqsPadSettingOverride;
5672 uint32_t timeoutInMs;
5673 uint32_t commandInterval;
5674 uint16_t dataValidTime[2];
5675 uint16_t busyOffset;
5676 uint16_t busyBitPolarity;
5677 uint32_t lookupTable[64];
5678 struct mg_flexspi_lut_seq lutCustomSeq[12];
5679 uint32_t reserved4[4];
5680};
5681 
5682struct mg_flexspi_nor_config {
5683 struct mg_flexspi_mem_config memConfig;
5684 uint32_t pageSize;
5685 uint32_t sectorSize;
5686 uint8_t ipcmdSerialClkFreq;
5687 uint8_t isUniformBlockSize;
5688 uint8_t reserved0[2];
5689 uint8_t serialNorType;
5690 uint8_t needExitNoCmdMode;
5691 uint8_t halfClkForNonReadCmd;
5692 uint8_t needRestoreNoCmdMode;
5693 uint32_t blockSize;
5694 uint32_t reserve2[11];
5695};
5696 
5697/* FLEXSPI memory config block related defintions */
5698#define MG_FLEXSPI_CFG_BLK_TAG (0x42464346UL) // ascii "FCFB" Big Endian
5699#define MG_FLEXSPI_CFG_BLK_VERSION (0x56010400UL) // V1.4.0
5700 
5701#define MG_FLEXSPI_LUT_SEQ(cmd0, pad0, op0, cmd1, pad1, op1) \
5702 (MG_FLEXSPI_LUT_OPERAND0(op0) | MG_FLEXSPI_LUT_NUM_PADS0(pad0) | \
5703 MG_FLEXSPI_LUT_OPCODE0(cmd0) | MG_FLEXSPI_LUT_OPERAND1(op1) | \
5704 MG_FLEXSPI_LUT_NUM_PADS1(pad1) | MG_FLEXSPI_LUT_OPCODE1(cmd1))
5705 
5706#define MG_CMD_SDR 0x01
5707#define MG_CMD_DDR 0x21
5708#define MG_DUMMY_SDR 0x0C
5709#define MG_DUMMY_DDR 0x2C
5710#define MG_DUMMY_RWDS_DDR 0x2D
5711#define MG_RADDR_SDR 0x02
5712#define MG_RADDR_DDR 0x22
5713#define MG_CADDR_DDR 0x23
5714#define MG_READ_SDR 0x09
5715#define MG_READ_DDR 0x29
5716#define MG_WRITE_SDR 0x08
5717#define MG_WRITE_DDR 0x28
5718#define MG_STOP 0
5719 
5720#define MG_FLEXSPI_1PAD 0
5721#define MG_FLEXSPI_2PAD 1
5722#define MG_FLEXSPI_4PAD 2
5723#define MG_FLEXSPI_8PAD 3
5724 
5725#define MG_FLEXSPI_QSPI_LUT \
5726 { \
5727 [0] = MG_FLEXSPI_LUT_SEQ(MG_CMD_SDR, MG_FLEXSPI_1PAD, 0xEB, MG_RADDR_SDR, \
5728 MG_FLEXSPI_4PAD, 0x18), \
5729 [1] = MG_FLEXSPI_LUT_SEQ(MG_DUMMY_SDR, MG_FLEXSPI_4PAD, 0x06, MG_READ_SDR, \
5730 MG_FLEXSPI_4PAD, 0x04), \
5731 [4 * 1 + 0] = MG_FLEXSPI_LUT_SEQ(MG_CMD_SDR, MG_FLEXSPI_1PAD, 0x05, \
5732 MG_READ_SDR, MG_FLEXSPI_1PAD, 0x04), \
5733 [4 * 3 + 0] = MG_FLEXSPI_LUT_SEQ(MG_CMD_SDR, MG_FLEXSPI_1PAD, 0x06, \
5734 MG_STOP, MG_FLEXSPI_1PAD, 0x0), \
5735 [4 * 5 + 0] = MG_FLEXSPI_LUT_SEQ(MG_CMD_SDR, MG_FLEXSPI_1PAD, 0x20, \
5736 MG_RADDR_SDR, MG_FLEXSPI_1PAD, 0x18), \
5737 [4 * 8 + 0] = MG_FLEXSPI_LUT_SEQ(MG_CMD_SDR, MG_FLEXSPI_1PAD, 0xD8, \
5738 MG_RADDR_SDR, MG_FLEXSPI_1PAD, 0x18), \
5739 [4 * 9 + 0] = MG_FLEXSPI_LUT_SEQ(MG_CMD_SDR, MG_FLEXSPI_1PAD, 0x02, \
5740 MG_RADDR_SDR, MG_FLEXSPI_1PAD, 0x18), \
5741 [4 * 9 + 1] = MG_FLEXSPI_LUT_SEQ(MG_WRITE_SDR, MG_FLEXSPI_1PAD, 0x04, \
5742 MG_STOP, MG_FLEXSPI_1PAD, 0x0), \
5743 [4 * 11 + 0] = MG_FLEXSPI_LUT_SEQ(MG_CMD_SDR, MG_FLEXSPI_1PAD, 0x60, \
5744 MG_STOP, MG_FLEXSPI_1PAD, 0x0), \
5745 }
5746 
5747#define MG_FLEXSPI_HYPER_LUT \
5748 { \
5749 [0] = MG_FLEXSPI_LUT_SEQ(MG_CMD_DDR, MG_FLEXSPI_8PAD, 0xA0, MG_RADDR_DDR, \
5750 MG_FLEXSPI_8PAD, 0x18), \
5751 [1] = MG_FLEXSPI_LUT_SEQ(MG_CADDR_DDR, MG_FLEXSPI_8PAD, 0x10, \
5752 MG_DUMMY_DDR, MG_FLEXSPI_8PAD, 0x0C), \
5753 [2] = MG_FLEXSPI_LUT_SEQ(MG_READ_DDR, MG_FLEXSPI_8PAD, 0x04, MG_STOP, \
5754 MG_FLEXSPI_1PAD, 0x0), \
5755 [4 * 1 + 0] = MG_FLEXSPI_LUT_SEQ(MG_CMD_DDR, MG_FLEXSPI_8PAD, 0x0, \
5756 MG_CMD_DDR, MG_FLEXSPI_8PAD, 0x0), \
5757 [4 * 1 + 1] = MG_FLEXSPI_LUT_SEQ(MG_CMD_DDR, MG_FLEXSPI_8PAD, 0x0, \
5758 MG_CMD_DDR, MG_FLEXSPI_8PAD, 0xAA), \
5759 [4 * 1 + 2] = MG_FLEXSPI_LUT_SEQ(MG_CMD_DDR, MG_FLEXSPI_8PAD, 0x0, \
5760 MG_CMD_DDR, MG_FLEXSPI_8PAD, 0x05), \
5761 [4 * 1 + 3] = MG_FLEXSPI_LUT_SEQ(MG_CMD_DDR, MG_FLEXSPI_8PAD, 0x0, \
5762 MG_CMD_DDR, MG_FLEXSPI_8PAD, 0x70), \
5763 [4 * 2 + 0] = MG_FLEXSPI_LUT_SEQ(MG_CMD_DDR, MG_FLEXSPI_8PAD, 0xA0, \
5764 MG_RADDR_DDR, MG_FLEXSPI_8PAD, 0x18), \
5765 [4 * 2 + 1] = \
5766 MG_FLEXSPI_LUT_SEQ(MG_CADDR_DDR, MG_FLEXSPI_8PAD, 0x10, \
5767 MG_DUMMY_RWDS_DDR, MG_FLEXSPI_8PAD, 0x0B), \
5768 [4 * 2 + 2] = MG_FLEXSPI_LUT_SEQ(MG_READ_DDR, MG_FLEXSPI_8PAD, 0x4, \
5769 MG_STOP, MG_FLEXSPI_1PAD, 0x0), \
5770 [4 * 3 + 0] = MG_FLEXSPI_LUT_SEQ(MG_CMD_DDR, MG_FLEXSPI_8PAD, 0x0, \
5771 MG_CMD_DDR, MG_FLEXSPI_8PAD, 0x0), \
5772 [4 * 3 + 1] = MG_FLEXSPI_LUT_SEQ(MG_CMD_DDR, MG_FLEXSPI_8PAD, 0x0, \
5773 MG_CMD_DDR, MG_FLEXSPI_8PAD, 0xAA), \
5774 [4 * 3 + 2] = MG_FLEXSPI_LUT_SEQ(MG_CMD_DDR, MG_FLEXSPI_8PAD, 0x0, \
5775 MG_CMD_DDR, MG_FLEXSPI_8PAD, 0x05), \
5776 [4 * 3 + 3] = MG_FLEXSPI_LUT_SEQ(MG_CMD_DDR, MG_FLEXSPI_8PAD, 0x0, \
5777 MG_CMD_DDR, MG_FLEXSPI_8PAD, 0xAA), \
5778 [4 * 4 + 0] = MG_FLEXSPI_LUT_SEQ(MG_CMD_DDR, MG_FLEXSPI_8PAD, 0x0, \
5779 MG_CMD_DDR, MG_FLEXSPI_8PAD, 0x0), \
5780 [4 * 4 + 1] = MG_FLEXSPI_LUT_SEQ(MG_CMD_DDR, MG_FLEXSPI_8PAD, 0x0, \
5781 MG_CMD_DDR, MG_FLEXSPI_8PAD, 0x55), \
5782 [4 * 4 + 2] = MG_FLEXSPI_LUT_SEQ(MG_CMD_DDR, MG_FLEXSPI_8PAD, 0x0, \
5783 MG_CMD_DDR, MG_FLEXSPI_8PAD, 0x02), \
5784 [4 * 4 + 3] = MG_FLEXSPI_LUT_SEQ(MG_CMD_DDR, MG_FLEXSPI_8PAD, 0x0, \
5785 MG_CMD_DDR, MG_FLEXSPI_8PAD, 0x55), \
5786 [4 * 5 + 0] = MG_FLEXSPI_LUT_SEQ(MG_CMD_DDR, MG_FLEXSPI_8PAD, 0x0, \
5787 MG_CMD_DDR, MG_FLEXSPI_8PAD, 0x0), \
5788 [4 * 5 + 1] = MG_FLEXSPI_LUT_SEQ(MG_CMD_DDR, MG_FLEXSPI_8PAD, 0x0, \
5789 MG_CMD_DDR, MG_FLEXSPI_8PAD, 0xAA), \
5790 [4 * 5 + 2] = MG_FLEXSPI_LUT_SEQ(MG_CMD_DDR, MG_FLEXSPI_8PAD, 0x0, \
5791 MG_CMD_DDR, MG_FLEXSPI_8PAD, 0x05), \
5792 [4 * 5 + 3] = MG_FLEXSPI_LUT_SEQ(MG_CMD_DDR, MG_FLEXSPI_8PAD, 0x0, \
5793 MG_CMD_DDR, MG_FLEXSPI_8PAD, 0x80), \
5794 [4 * 6 + 0] = MG_FLEXSPI_LUT_SEQ(MG_CMD_DDR, MG_FLEXSPI_8PAD, 0x0, \
5795 MG_CMD_DDR, MG_FLEXSPI_8PAD, 0x0), \
5796 [4 * 6 + 1] = MG_FLEXSPI_LUT_SEQ(MG_CMD_DDR, MG_FLEXSPI_8PAD, 0x0, \
5797 MG_CMD_DDR, MG_FLEXSPI_8PAD, 0xAA), \
5798 [4 * 6 + 2] = MG_FLEXSPI_LUT_SEQ(MG_CMD_DDR, MG_FLEXSPI_8PAD, 0x0, \
5799 MG_CMD_DDR, MG_FLEXSPI_8PAD, 0x05), \
5800 [4 * 6 + 3] = MG_FLEXSPI_LUT_SEQ(MG_CMD_DDR, MG_FLEXSPI_8PAD, 0x0, \
5801 MG_CMD_DDR, MG_FLEXSPI_8PAD, 0xAA), \
5802 [4 * 7 + 0] = MG_FLEXSPI_LUT_SEQ(MG_CMD_DDR, MG_FLEXSPI_8PAD, 0x0, \
5803 MG_CMD_DDR, MG_FLEXSPI_8PAD, 0x0), \
5804 [4 * 7 + 1] = MG_FLEXSPI_LUT_SEQ(MG_CMD_DDR, MG_FLEXSPI_8PAD, 0x0, \
5805 MG_CMD_DDR, MG_FLEXSPI_8PAD, 0x55), \
5806 [4 * 7 + 2] = MG_FLEXSPI_LUT_SEQ(MG_CMD_DDR, MG_FLEXSPI_8PAD, 0x0, \
5807 MG_CMD_DDR, MG_FLEXSPI_8PAD, 0x02), \
5808 [4 * 7 + 3] = MG_FLEXSPI_LUT_SEQ(MG_CMD_DDR, MG_FLEXSPI_8PAD, 0x0, \
5809 MG_CMD_DDR, MG_FLEXSPI_8PAD, 0x55), \
5810 [4 * 8 + 0] = MG_FLEXSPI_LUT_SEQ(MG_CMD_DDR, MG_FLEXSPI_8PAD, 0x0, \
5811 MG_RADDR_DDR, MG_FLEXSPI_8PAD, 0x18), \
5812 [4 * 8 + 1] = MG_FLEXSPI_LUT_SEQ(MG_CADDR_DDR, MG_FLEXSPI_8PAD, 0x10, \
5813 MG_CMD_DDR, MG_FLEXSPI_8PAD, 0x0), \
5814 [4 * 8 + 2] = MG_FLEXSPI_LUT_SEQ(MG_CMD_DDR, MG_FLEXSPI_8PAD, 0x30, \
5815 MG_STOP, MG_FLEXSPI_1PAD, 0x0), \
5816 [4 * 9 + 0] = MG_FLEXSPI_LUT_SEQ(MG_CMD_DDR, MG_FLEXSPI_8PAD, 0x0, \
5817 MG_CMD_DDR, MG_FLEXSPI_8PAD, 0x0), \
5818 [4 * 9 + 1] = MG_FLEXSPI_LUT_SEQ(MG_CMD_DDR, MG_FLEXSPI_8PAD, 0x0, \
5819 MG_CMD_DDR, MG_FLEXSPI_8PAD, 0xAA), \
5820 [4 * 9 + 2] = MG_FLEXSPI_LUT_SEQ(MG_CMD_DDR, MG_FLEXSPI_8PAD, 0x0, \
5821 MG_CMD_DDR, MG_FLEXSPI_8PAD, 0x05), \
5822 [4 * 9 + 3] = MG_FLEXSPI_LUT_SEQ(MG_CMD_DDR, MG_FLEXSPI_8PAD, 0x0, \
5823 MG_CMD_DDR, MG_FLEXSPI_8PAD, 0xA0), \
5824 [4 * 10 + 0] = MG_FLEXSPI_LUT_SEQ(MG_CMD_DDR, MG_FLEXSPI_8PAD, 0x0, \
5825 MG_RADDR_DDR, MG_FLEXSPI_8PAD, 0x18), \
5826 [4 * 10 + 1] = MG_FLEXSPI_LUT_SEQ(MG_CADDR_DDR, MG_FLEXSPI_8PAD, 0x10, \
5827 MG_WRITE_DDR, MG_FLEXSPI_8PAD, 0x80), \
5828 [4 * 11 + 0] = MG_FLEXSPI_LUT_SEQ(MG_CMD_DDR, MG_FLEXSPI_8PAD, 0x0, \
5829 MG_CMD_DDR, MG_FLEXSPI_8PAD, 0x0), \
5830 [4 * 11 + 1] = MG_FLEXSPI_LUT_SEQ(MG_CMD_DDR, MG_FLEXSPI_8PAD, 0x0, \
5831 MG_CMD_DDR, MG_FLEXSPI_8PAD, 0xAA), \
5832 [4 * 11 + 2] = MG_FLEXSPI_LUT_SEQ(MG_CMD_DDR, MG_FLEXSPI_8PAD, 0x0, \
5833 MG_CMD_DDR, MG_FLEXSPI_8PAD, 0x05), \
5834 [4 * 11 + 3] = MG_FLEXSPI_LUT_SEQ(MG_CMD_DDR, MG_FLEXSPI_8PAD, 0x0, \
5835 MG_CMD_DDR, MG_FLEXSPI_8PAD, 0x80), \
5836 [4 * 12 + 0] = MG_FLEXSPI_LUT_SEQ(MG_CMD_DDR, MG_FLEXSPI_8PAD, 0x0, \
5837 MG_CMD_DDR, MG_FLEXSPI_8PAD, 0x0), \
5838 [4 * 12 + 1] = MG_FLEXSPI_LUT_SEQ(MG_CMD_DDR, MG_FLEXSPI_8PAD, 0x0, \
5839 MG_CMD_DDR, MG_FLEXSPI_8PAD, 0xAA), \
5840 [4 * 12 + 2] = MG_FLEXSPI_LUT_SEQ(MG_CMD_DDR, MG_FLEXSPI_8PAD, 0x0, \
5841 MG_CMD_DDR, MG_FLEXSPI_8PAD, 0x05), \
5842 [4 * 12 + 3] = MG_FLEXSPI_LUT_SEQ(MG_CMD_DDR, MG_FLEXSPI_8PAD, 0x0, \
5843 MG_CMD_DDR, MG_FLEXSPI_8PAD, 0xAA), \
5844 [4 * 13 + 0] = MG_FLEXSPI_LUT_SEQ(MG_CMD_DDR, MG_FLEXSPI_8PAD, 0x0, \
5845 MG_CMD_DDR, MG_FLEXSPI_8PAD, 0x0), \
5846 [4 * 13 + 1] = MG_FLEXSPI_LUT_SEQ(MG_CMD_DDR, MG_FLEXSPI_8PAD, 0x0, \
5847 MG_CMD_DDR, MG_FLEXSPI_8PAD, 0x55), \
5848 [4 * 13 + 2] = MG_FLEXSPI_LUT_SEQ(MG_CMD_DDR, MG_FLEXSPI_8PAD, 0x0, \
5849 MG_CMD_DDR, MG_FLEXSPI_8PAD, 0x02), \
5850 [4 * 13 + 3] = MG_FLEXSPI_LUT_SEQ(MG_CMD_DDR, MG_FLEXSPI_8PAD, 0x0, \
5851 MG_CMD_DDR, MG_FLEXSPI_8PAD, 0x55), \
5852 [4 * 14 + 0] = MG_FLEXSPI_LUT_SEQ(MG_CMD_DDR, MG_FLEXSPI_8PAD, 0x0, \
5853 MG_CMD_DDR, MG_FLEXSPI_8PAD, 0x0), \
5854 [4 * 14 + 1] = MG_FLEXSPI_LUT_SEQ(MG_CMD_DDR, MG_FLEXSPI_8PAD, 0x0, \
5855 MG_CMD_DDR, MG_FLEXSPI_8PAD, 0xAA), \
5856 [4 * 14 + 2] = MG_FLEXSPI_LUT_SEQ(MG_CMD_DDR, MG_FLEXSPI_8PAD, 0x0, \
5857 MG_CMD_DDR, MG_FLEXSPI_8PAD, 0x05), \
5858 [4 * 14 + 3] = MG_FLEXSPI_LUT_SEQ(MG_CMD_DDR, MG_FLEXSPI_8PAD, 0x0, \
5859 MG_CMD_DDR, MG_FLEXSPI_8PAD, 0x10), \
5860 }
5861 
5862#define MG_LUT_CUSTOM_SEQ \
5863 { \
5864 {.seqNum = 0, .seqId = 0, .reserved = 0}, \
5865 {.seqNum = 2, .seqId = 1, .reserved = 0}, \
5866 {.seqNum = 2, .seqId = 3, .reserved = 0}, \
5867 {.seqNum = 4, .seqId = 5, .reserved = 0}, \
5868 {.seqNum = 2, .seqId = 9, .reserved = 0}, \
5869 {.seqNum = 4, .seqId = 11, .reserved = 0}, \
5870 }
5871 
5872#define MG_FLEXSPI_LUT_OPERAND0(x) (((uint32_t) (((uint32_t) (x)))) & 0xFFU)
5873#define MG_FLEXSPI_LUT_NUM_PADS0(x) \
5874 (((uint32_t) (((uint32_t) (x)) << 8U)) & 0x300U)
5875#define MG_FLEXSPI_LUT_OPCODE0(x) \
5876 (((uint32_t) (((uint32_t) (x)) << 10U)) & 0xFC00U)
5877#define MG_FLEXSPI_LUT_OPERAND1(x) \
5878 (((uint32_t) (((uint32_t) (x)) << 16U)) & 0xFF0000U)
5879#define MG_FLEXSPI_LUT_NUM_PADS1(x) \
5880 (((uint32_t) (((uint32_t) (x)) << 24U)) & 0x3000000U)
5881#define MG_FLEXSPI_LUT_OPCODE1(x) \
5882 (((uint32_t) (((uint32_t) (x)) << 26U)) & 0xFC000000U)
5883 
5884#if MG_OTA == MG_OTA_RT1020 || MG_OTA == MG_OTA_RT1050
5885// RT102X and RT105x boards support ROM API version 1.4
5886struct mg_flexspi_nor_driver_interface {
5887 uint32_t version;
5888 int (*init)(uint32_t instance, struct mg_flexspi_nor_config *config);
5889 int (*program)(uint32_t instance, struct mg_flexspi_nor_config *config,
5890 uint32_t dst_addr, const uint32_t *src);
5891 uint32_t reserved;
5892 int (*erase)(uint32_t instance, struct mg_flexspi_nor_config *config,
5893 uint32_t start, uint32_t lengthInBytes);
5894 uint32_t reserved2;
5895 int (*update_lut)(uint32_t instance, uint32_t seqIndex,
5896 const uint32_t *lutBase, uint32_t seqNumber);
5897 int (*xfer)(uint32_t instance, char *xfer);
5898 void (*clear_cache)(uint32_t instance);
5899};
5900#elif MG_OTA <= MG_OTA_RT1064
5901// RT104x and RT106x support ROM API version 1.5
5902struct mg_flexspi_nor_driver_interface {
5903 uint32_t version;
5904 int (*init)(uint32_t instance, struct mg_flexspi_nor_config *config);
5905 int (*program)(uint32_t instance, struct mg_flexspi_nor_config *config,
5906 uint32_t dst_addr, const uint32_t *src);
5907 int (*erase_all)(uint32_t instance, struct mg_flexspi_nor_config *config);
5908 int (*erase)(uint32_t instance, struct mg_flexspi_nor_config *config,
5909 uint32_t start, uint32_t lengthInBytes);
5910 int (*read)(uint32_t instance, struct mg_flexspi_nor_config *config,
5911 uint32_t *dst, uint32_t addr, uint32_t lengthInBytes);
5912 void (*clear_cache)(uint32_t instance);
5913 int (*xfer)(uint32_t instance, char *xfer);
5914 int (*update_lut)(uint32_t instance, uint32_t seqIndex,
5915 const uint32_t *lutBase, uint32_t seqNumber);
5916 int (*get_config)(uint32_t instance, struct mg_flexspi_nor_config *config,
5917 uint32_t *option);
5918};
5919#else
5920// RT117x support ROM API version 1.7
5921struct mg_flexspi_nor_driver_interface {
5922 uint32_t version;
5923 int (*init)(uint32_t instance, struct mg_flexspi_nor_config *config);
5924 int (*program)(uint32_t instance, struct mg_flexspi_nor_config *config,
5925 uint32_t dst_addr, const uint32_t *src);
5926 int (*erase_all)(uint32_t instance, struct mg_flexspi_nor_config *config);
5927 int (*erase)(uint32_t instance, struct mg_flexspi_nor_config *config,
5928 uint32_t start, uint32_t lengthInBytes);
5929 int (*read)(uint32_t instance, struct mg_flexspi_nor_config *config,
5930 uint32_t *dst, uint32_t addr, uint32_t lengthInBytes);
5931 uint32_t reserved;
5932 int (*xfer)(uint32_t instance, char *xfer);
5933 int (*update_lut)(uint32_t instance, uint32_t seqIndex,
5934 const uint32_t *lutBase, uint32_t seqNumber);
5935 int (*get_config)(uint32_t instance, struct mg_flexspi_nor_config *config,
5936 uint32_t *option);
5937 int (*erase_sector)(uint32_t instance, struct mg_flexspi_nor_config *config,
5938 uint32_t address);
5939 int (*erase_block)(uint32_t instance, struct mg_flexspi_nor_config *config,
5940 uint32_t address);
5941 void (*hw_reset)(uint32_t instance, uint32_t resetLogic);
5942 int (*wait_busy)(uint32_t instance, struct mg_flexspi_nor_config *config,
5943 bool isParallelMode, uint32_t address);
5944 int (*set_clock_source)(uint32_t instance, uint32_t clockSrc);
5945 void (*config_clock)(uint32_t instance, uint32_t freqOption,
5946 uint32_t sampleClkMode);
5947};
5948#endif
5949 
5950#if MG_OTA <= MG_OTA_RT1064
5951#define MG_FLEXSPI_BASE 0x402A8000
5952#define flexspi_nor \
5953 (*((struct mg_flexspi_nor_driver_interface **) (*(uint32_t *) 0x0020001c + \
5954 16)))
5955#else
5956#define MG_FLEXSPI_BASE 0x400CC000
5957#define flexspi_nor \
5958 (*((struct mg_flexspi_nor_driver_interface **) (*(uint32_t *) 0x0021001c + \
5959 12)))
5960#endif
5961 
5962static bool s_flash_irq_disabled;
5963 
5964MG_IRAM static bool flash_page_start(volatile uint32_t *dst) {
5965 char *base = (char *) s_mg_flash_imxrt.start,
5966 *end = base + s_mg_flash_imxrt.size;
5967 volatile char *p = (char *) dst;
5968 return p >= base && p < end && ((p - base) % s_mg_flash_imxrt.secsz) == 0;
5969}
5970 
5971#if MG_OTA == MG_OTA_RT1050
5972// Configuration for Hyper flash memory
5973static struct mg_flexspi_nor_config default_config = {
5974 .memConfig =
5975 {
5976 .tag = MG_FLEXSPI_CFG_BLK_TAG,
5977 .version = MG_FLEXSPI_CFG_BLK_VERSION,
5978 .readSampleClkSrc = 3, // ReadSampleClk_LoopbackFromDqsPad
5979 .csHoldTime = 3,
5980 .csSetupTime = 3,
5981 .columnAddressWidth = 3u,
5982 .controllerMiscOption =
5983 MG_BIT(6) | MG_BIT(4) | MG_BIT(3) | MG_BIT(0),
5984 .deviceType = 1, // serial NOR
5985 .sflashPadType = 8,
5986 .serialClkFreq = 7, // 133MHz
5987 .sflashA1Size = 64 * 1024 * 1024,
5988 .dataValidTime = {15, 0},
5989 .busyOffset = 15,
5990 .busyBitPolarity = 1,
5991 .lutCustomSeqEnable = 0x1,
5992 .lookupTable = MG_FLEXSPI_HYPER_LUT,
5993 .lutCustomSeq = MG_LUT_CUSTOM_SEQ,
5994 },
5995 .pageSize = 512,
5996 .sectorSize = 256 * 1024,
5997 .ipcmdSerialClkFreq = 1,
5998 .serialNorType = 1u,
5999 .blockSize = 256 * 1024,
6000 .isUniformBlockSize = true};
6001#else
6002// Note: this QSPI configuration works for RTs supporting QSPI
6003// Configuration for QSPI memory
6004static struct mg_flexspi_nor_config default_config = {
6005 .memConfig = {.tag = MG_FLEXSPI_CFG_BLK_TAG,
6006 .version = MG_FLEXSPI_CFG_BLK_VERSION,
6007 .readSampleClkSrc = 1, // ReadSampleClk_LoopbackFromDqsPad
6008 .csHoldTime = 3,
6009 .csSetupTime = 3,
6010 .controllerMiscOption = MG_BIT(4),
6011 .deviceType = 1, // serial NOR
6012 .sflashPadType = 4,
6013 .serialClkFreq = 7, // 133MHz
6014 .sflashA1Size = 8 * 1024 * 1024,
6015 .lookupTable = MG_FLEXSPI_QSPI_LUT},
6016 .pageSize = 256,
6017 .sectorSize = 4 * 1024,
6018 .ipcmdSerialClkFreq = 1,
6019 .blockSize = 64 * 1024,
6020 .isUniformBlockSize = false};
6021#endif
6022 
6023// must reside in RAM, as flash will be erased
6024MG_IRAM static int flexspi_nor_get_config(
6025 struct mg_flexspi_nor_config **config) {
6026 *config = &default_config;
6027 return 0;
6028}
6029 
6030#if 0
6031// ROM API get_config call (ROM version >= 1.5)
6032MG_IRAM static int flexspi_nor_get_config(
6033 struct mg_flexspi_nor_config **config) {
6034 uint32_t options[] = {0xc0000000, 0x00};
6035 
6036 MG_ARM_DISABLE_IRQ();
6037 uint32_t status =
6038 flexspi_nor->get_config(FLEXSPI_NOR_INSTANCE, *config, options);
6039 if (!s_flash_irq_disabled) {
6040 MG_ARM_ENABLE_IRQ();
6041 }
6042 if (status) {
6043 MG_ERROR(("Failed to extract flash configuration: status %u", status));
6044 }
6045 return status;
6046}
6047#endif
6048 
6049MG_IRAM static void mg_spin(volatile uint32_t count) {
6050 while (count--) (void) 0;
6051}
6052 
6053MG_IRAM static void flash_wait(void) {
6054 while ((*((volatile uint32_t *) (MG_FLEXSPI_BASE + 0xE0)) & MG_BIT(1)) == 0)
6055 mg_spin(1);
6056}
6057 
6058MG_IRAM static bool flash_erase(struct mg_flexspi_nor_config *config,
6059 void *addr) {
6060 if (flash_page_start(addr) == false) {
6061 MG_ERROR(("%p is not on a sector boundary", addr));
6062 return false;
6063 }
6064 
6065 void *dst = (void *) ((char *) addr - (char *) s_mg_flash_imxrt.start);
6066 
6067 bool ok = (flexspi_nor->erase(FLEXSPI_NOR_INSTANCE, config, (uint32_t) dst,
6068 s_mg_flash_imxrt.secsz) == 0);
6069 MG_DEBUG(("Sector starting at %p erasure: %s", addr, ok ? "ok" : "fail"));
6070 return ok;
6071}
6072 
6073#if 0
6074// standalone erase call
6075MG_IRAM static bool mg_imxrt_erase(void *addr) {
6076 struct mg_flexspi_nor_config config, *config_ptr = &config;
6077 bool ret;
6078 // Interrupts must be disabled before calls to ROM API in RT1020 and 1060
6079 MG_ARM_DISABLE_IRQ();
6080 ret = (flexspi_nor_get_config(&config_ptr) == 0);
6081 if (ret) ret = flash_erase(config_ptr, addr);
6082 MG_ARM_ENABLE_IRQ();
6083 return ret;
6084}
6085#endif
6086 
6087MG_IRAM bool mg_imxrt_swap(void) {
6088 return true;
6089}
6090 
6091MG_IRAM static bool mg_imxrt_write(void *addr, const void *buf, size_t len) {
6092 struct mg_flexspi_nor_config config, *config_ptr = &config;
6093 bool ok = false;
6094 // Interrupts must be disabled before calls to ROM API in RT1020 and 1060
6095 MG_ARM_DISABLE_IRQ();
6096 if (flexspi_nor_get_config(&config_ptr) != 0) goto fwxit;
6097 if ((len % s_mg_flash_imxrt.align) != 0) {
6098 MG_ERROR(("%lu is not aligned to %lu", len, s_mg_flash_imxrt.align));
6099 goto fwxit;
6100 }
6101 if ((char *) addr < (char *) s_mg_flash_imxrt.start) {
6102 MG_ERROR(("Invalid flash write address: %p", addr));
6103 goto fwxit;
6104 }
6105 
6106 uint32_t *dst = (uint32_t *) addr;
6107 uint32_t *src = (uint32_t *) buf;
6108 uint32_t *end = (uint32_t *) ((char *) buf + len);
6109 ok = true;
6110 
6111 while (ok && src < end) {
6112 if (flash_page_start(dst) && flash_erase(config_ptr, dst) == false) {
6113 ok = false;
6114 break;
6115 }
6116 uint32_t status;
6117 uint32_t dst_ofs = (uint32_t) dst - (uint32_t) s_mg_flash_imxrt.start;
6118 if ((char *) buf >= (char *) s_mg_flash_imxrt.start) {
6119 // If we copy from FLASH to FLASH, then we first need to copy the source
6120 // to RAM
6121 size_t tmp_buf_size = s_mg_flash_imxrt.align / sizeof(uint32_t);
6122 uint32_t tmp[tmp_buf_size];
6123 
6124 for (size_t i = 0; i < tmp_buf_size; i++) {
6125 flash_wait();
6126 tmp[i] = src[i];
6127 }
6128 status = flexspi_nor->program(FLEXSPI_NOR_INSTANCE, config_ptr,
6129 (uint32_t) dst_ofs, tmp);
6130 } else {
6131 status = flexspi_nor->program(FLEXSPI_NOR_INSTANCE, config_ptr,
6132 (uint32_t) dst_ofs, src);
6133 }
6134 src = (uint32_t *) ((char *) src + s_mg_flash_imxrt.align);
6135 dst = (uint32_t *) ((char *) dst + s_mg_flash_imxrt.align);
6136 if (status != 0) {
6137 ok = false;
6138 }
6139 }
6140 MG_DEBUG(("Flash write %lu bytes @ %p: %s.", len, dst, ok ? "ok" : "fail"));
6141fwxit:
6142 if (!s_flash_irq_disabled) MG_ARM_ENABLE_IRQ();
6143 return ok;
6144}
6145 
6146// just overwrite instead of swap
6147MG_IRAM static void single_bank_swap(char *p1, char *p2, size_t s, size_t ss) {
6148 // no stdlib calls here
6149 for (size_t ofs = 0; ofs < s; ofs += ss) {
6150 mg_imxrt_write(p1 + ofs, p2 + ofs, ss);
6151 }
6152 *(volatile unsigned long *) 0xe000ed0c = 0x5fa0004;
6153}
6154 
6155bool mg_ota_begin(size_t new_firmware_size) {
6156 return mg_ota_flash_begin(new_firmware_size, &s_mg_flash_imxrt);
6157}
6158 
6159bool mg_ota_write(const void *buf, size_t len) {
6160 return mg_ota_flash_write(buf, len, &s_mg_flash_imxrt);
6161}
6162 
6163bool mg_ota_end(void) {
6164 if (mg_ota_flash_end(&s_mg_flash_imxrt)) {
6165 if (0) { // is_dualbank()
6166 // TODO(): no devices so far
6167 *(volatile unsigned long *) 0xe000ed0c = 0x5fa0004;
6168 } else {
6169 // Swap partitions. Pray power does not go away
6170 MG_INFO(("Swapping partitions, size %u (%u sectors)",
6171 s_mg_flash_imxrt.size,
6172 s_mg_flash_imxrt.size / s_mg_flash_imxrt.secsz));
6173 MG_INFO(("Do NOT power off..."));
6174 mg_log_level = MG_LL_NONE;
6175 s_flash_irq_disabled = true;
6176 // Runs in RAM, will reset when finished
6177 single_bank_swap(
6178 (char *) s_mg_flash_imxrt.start,
6179 (char *) s_mg_flash_imxrt.start + s_mg_flash_imxrt.size / 2,
6180 s_mg_flash_imxrt.size / 2, s_mg_flash_imxrt.secsz);
6181 }
6182 }
6183 return false;
6184}
6185 
6186#endif
6187 
6188#ifdef MG_ENABLE_LINES
6189#line 1 "src/ota_mcxn.c"
6190#endif
6191 
6192 
6193 
6194 
6195#if MG_OTA == MG_OTA_MCXN
6196 
6197// - Flash phrase: 16 bytes; smallest portion programmed in one operation.
6198// - Flash page: 128 bytes; largest portion programmed in one operation.
6199// - Flash sector: 8 KB; smallest portion that can be erased in one operation.
6200// - Flash API mg_flash_driver->program: "start" and "len" must be page-size
6201// aligned; to use 'phrase', FMU register access is needed. Using ROM
6202 
6203static bool mg_mcxn_write(void *, const void *, size_t);
6204static bool mg_mcxn_swap(void);
6205 
6206static struct mg_flash s_mg_flash_mcxn = {
6207 (void *) 0, // Start, filled at init
6208 0, // Size, filled at init
6209 0, // Sector size, filled at init
6210 0, // Align, filled at init
6211 mg_mcxn_write,
6212 mg_mcxn_swap,
6213};
6214 
6215struct mg_flash_config {
6216 uint32_t addr;
6217 uint32_t size;
6218 uint32_t blocks;
6219 uint32_t page_size;
6220 uint32_t sector_size;
6221 uint32_t ffr[6];
6222 uint32_t reserved0[5];
6223 uint32_t *bootctx;
6224 bool useahb;
6225};
6226 
6227struct mg_flash_driver_interface {
6228 uint32_t version;
6229 uint32_t (*init)(struct mg_flash_config *);
6230 uint32_t (*erase)(struct mg_flash_config *, uint32_t start, uint32_t len,
6231 uint32_t key);
6232 uint32_t (*program)(struct mg_flash_config *, uint32_t start, uint8_t *src,
6233 uint32_t len);
6234 uint32_t (*verify_erase)(struct mg_flash_config *, uint32_t start,
6235 uint32_t len);
6236 uint32_t (*verify_program)(struct mg_flash_config *, uint32_t start,
6237 uint32_t len, const uint8_t *expected,
6238 uint32_t *addr, uint32_t *failed);
6239 uint32_t reserved1[12];
6240 uint32_t (*read)(struct mg_flash_config *, uint32_t start, uint8_t *dest,
6241 uint32_t len);
6242 uint32_t reserved2[4];
6243 uint32_t (*deinit)(struct mg_flash_config *);
6244};
6245#define mg_flash_driver \
6246 ((struct mg_flash_driver_interface *) (*((uint32_t *) 0x1303fc00 + 4)))
6247#define MG_MCXN_FLASK_KEY (('k' << 24) | ('e' << 16) | ('f' << 8) | 'l')
6248 
6249MG_IRAM static bool flash_sector_start(volatile uint32_t *dst) {
6250 char *base = (char *) s_mg_flash_mcxn.start,
6251 *end = base + s_mg_flash_mcxn.size;
6252 volatile char *p = (char *) dst;
6253 return p >= base && p < end && ((p - base) % s_mg_flash_mcxn.secsz) == 0;
6254}
6255 
6256MG_IRAM static bool flash_erase(struct mg_flash_config *config, void *addr) {
6257 if (flash_sector_start(addr) == false) {
6258 MG_ERROR(("%p is not on a sector boundary", addr));
6259 return false;
6260 }
6261 uint32_t dst =
6262 (uint32_t) addr - (uint32_t) s_mg_flash_mcxn.start; // future-proof
6263 uint32_t status = mg_flash_driver->erase(config, dst, s_mg_flash_mcxn.secsz,
6264 MG_MCXN_FLASK_KEY);
6265 bool ok = (status == 0);
6266 if (!ok) MG_ERROR(("Flash write error: %lu", status));
6267 MG_DEBUG(("Sector starting at %p erasure: %s", addr, ok ? "ok" : "fail"));
6268 return ok;
6269}
6270 
6271#if 0
6272// read-while-write, no need to disable IRQs for standalone usage
6273MG_IRAM static bool mg_mcxn_erase(void *addr) {
6274 uint32_t status;
6275 struct mg_flash_config config;
6276 if ((status = mg_flash_driver->init(&config)) != 0) {
6277 MG_ERROR(("Flash driver init error: %lu", status));
6278 return false;
6279 }
6280 bool ok = flash_erase(&config, addr);
6281 mg_flash_driver->deinit(&config);
6282 return ok;
6283}
6284#endif
6285 
6286MG_IRAM static bool mg_mcxn_swap(void) {
6287 // TODO(): no devices so far
6288 return true;
6289}
6290 
6291static bool s_flash_irq_disabled;
6292 
6293MG_IRAM static bool mg_mcxn_write(void *addr, const void *buf, size_t len) {
6294 bool ok = false;
6295 uint32_t status;
6296 struct mg_flash_config config;
6297 if ((status = mg_flash_driver->init(&config)) != 0) {
6298 MG_ERROR(("Flash driver init error: %lu", status));
6299 return false;
6300 }
6301 if ((len % s_mg_flash_mcxn.align) != 0) {
6302 MG_ERROR(("%lu is not aligned to %lu", len, s_mg_flash_mcxn.align));
6303 goto fwxit;
6304 }
6305 if ((((size_t) addr - (size_t) s_mg_flash_mcxn.start) %
6306 s_mg_flash_mcxn.align) != 0) {
6307 MG_ERROR(("%p is not on a page boundary", addr));
6308 goto fwxit;
6309 }
6310 
6311 uint32_t *dst = (uint32_t *) addr;
6312 uint32_t *src = (uint32_t *) buf;
6313 uint32_t *end = (uint32_t *) ((char *) buf + len);
6314 ok = true;
6315 
6316 MG_ARM_DISABLE_IRQ();
6317 while (ok && src < end) {
6318 if (flash_sector_start(dst) && flash_erase(&config, dst) == false) {
6319 ok = false;
6320 break;
6321 }
6322 uint32_t dst_ofs = (uint32_t) dst - (uint32_t) s_mg_flash_mcxn.start;
6323 // assume source is in RAM or in a different bank or read-while-write
6324 status = mg_flash_driver->program(&config, dst_ofs, (uint8_t *) src,
6325 s_mg_flash_mcxn.align);
6326 src = (uint32_t *) ((char *) src + s_mg_flash_mcxn.align);
6327 dst = (uint32_t *) ((char *) dst + s_mg_flash_mcxn.align);
6328 if (status != 0) {
6329 MG_ERROR(("Flash write error: %lu", status));
6330 ok = false;
6331 }
6332 }
6333 if (!s_flash_irq_disabled) MG_ARM_ENABLE_IRQ();
6334 MG_DEBUG(("Flash write %lu bytes @ %p: %s.", len, dst, ok ? "ok" : "fail"));
6335 
6336fwxit:
6337 mg_flash_driver->deinit(&config);
6338 return ok;
6339}
6340 
6341// try to swap (honor dual image), otherwise just overwrite
6342MG_IRAM static void single_bank_swap(char *p1, char *p2, size_t s, size_t ss) {
6343 char *tmp = malloc(ss);
6344 // no stdlib calls here
6345 for (size_t ofs = 0; ofs < s; ofs += ss) {
6346 if (tmp != NULL)
6347 for (size_t i = 0; i < ss; i++) tmp[i] = p1[ofs + i];
6348 mg_mcxn_write(p1 + ofs, p2 + ofs, ss);
6349 if (tmp != NULL) mg_mcxn_write(p2 + ofs, tmp, ss);
6350 }
6351 *(volatile unsigned long *) 0xe000ed0c = 0x5fa0004;
6352}
6353 
6354bool mg_ota_begin(size_t new_firmware_size) {
6355 uint32_t status;
6356 struct mg_flash_config config;
6357 if ((status = mg_flash_driver->init(&config)) != 0) {
6358 MG_ERROR(("Flash driver init error: %lu", status));
6359 return false;
6360 }
6361 s_mg_flash_mcxn.start = (void *) config.addr;
6362 s_mg_flash_mcxn.size = config.size;
6363 s_mg_flash_mcxn.secsz = config.sector_size;
6364 s_mg_flash_mcxn.align = config.page_size;
6365 mg_flash_driver->deinit(&config);
6366 MG_DEBUG(
6367 ("%lu-byte flash @%p, using %lu-byte sectors with %lu-byte-aligned pages",
6368 s_mg_flash_mcxn.size, s_mg_flash_mcxn.start, s_mg_flash_mcxn.secsz,
6369 s_mg_flash_mcxn.align));
6370 return mg_ota_flash_begin(new_firmware_size, &s_mg_flash_mcxn);
6371}
6372 
6373bool mg_ota_write(const void *buf, size_t len) {
6374 return mg_ota_flash_write(buf, len, &s_mg_flash_mcxn);
6375}
6376 
6377bool mg_ota_end(void) {
6378 if (mg_ota_flash_end(&s_mg_flash_mcxn)) {
6379 if (0) { // is_dualbank()
6380 // TODO(): no devices so far
6381 *(volatile unsigned long *) 0xe000ed0c = 0x5fa0004;
6382 } else {
6383 // Swap partitions. Pray power does not go away
6384 MG_INFO(("Swapping partitions, size %u (%u sectors)",
6385 s_mg_flash_mcxn.size,
6386 s_mg_flash_mcxn.size / s_mg_flash_mcxn.secsz));
6387 MG_INFO(("Do NOT power off..."));
6388 mg_log_level = MG_LL_NONE;
6389 s_flash_irq_disabled = true;
6390 // Runs in RAM, will reset when finished
6391 single_bank_swap(
6392 (char *) s_mg_flash_mcxn.start,
6393 (char *) s_mg_flash_mcxn.start + s_mg_flash_mcxn.size / 2,
6394 s_mg_flash_mcxn.size / 2, s_mg_flash_mcxn.secsz);
6395 }
6396 }
6397 return false;
6398}
6399#endif
6400 
6401#ifdef MG_ENABLE_LINES
6402#line 1 "src/ota_picosdk.c"
6403#endif
6404 
6405 
6406 
6407 
6408#if MG_OTA == MG_OTA_PICOSDK
6409 
6410// Both RP2040 and RP2350 have no flash, low-level flash access support in
6411// bootrom, and high-level support in Pico-SDK (2.0+ for the RP2350)
6412// - The RP2350 in RISC-V mode is not tested
6413// NOTE(): See OTA design notes
6414 
6415static bool mg_picosdk_write(void *, const void *, size_t);
6416static bool mg_picosdk_swap(void);
6417 
6418static struct mg_flash s_mg_flash_picosdk = {
6419 (void *) 0x10000000, // Start; functions handle offset
6420#ifdef PICO_FLASH_SIZE_BYTES
6421 PICO_FLASH_SIZE_BYTES, // Size, from board definitions
6422#else
6423 0x200000, // Size, guess... is 2M enough ?
6424#endif
6425 FLASH_SECTOR_SIZE, // Sector size, from hardware_flash
6426 FLASH_PAGE_SIZE, // Align, from hardware_flash
6427 mg_picosdk_write, mg_picosdk_swap,
6428};
6429 
6430#define MG_MODULO2(x, m) ((x) & ((m) -1))
6431 
6432static bool __no_inline_not_in_flash_func(flash_sector_start)(
6433 volatile uint32_t *dst) {
6434 char *base = (char *) s_mg_flash_picosdk.start,
6435 *end = base + s_mg_flash_picosdk.size;
6436 volatile char *p = (char *) dst;
6437 return p >= base && p < end &&
6438 MG_MODULO2(p - base, s_mg_flash_picosdk.secsz) == 0;
6439}
6440 
6441static bool __no_inline_not_in_flash_func(flash_erase)(void *addr) {
6442 if (flash_sector_start(addr) == false) {
6443 MG_ERROR(("%p is not on a sector boundary", addr));
6444 return false;
6445 }
6446 void *dst = (void *) ((char *) addr - (char *) s_mg_flash_picosdk.start);
6447 flash_range_erase((uint32_t) dst, s_mg_flash_picosdk.secsz);
6448 MG_DEBUG(("Sector starting at %p erasure", addr));
6449 return true;
6450}
6451 
6452static bool __no_inline_not_in_flash_func(mg_picosdk_swap)(void) {
6453 // TODO(): RP2350 might have some A/B functionality (DS 5.1)
6454 return true;
6455}
6456 
6457static bool s_flash_irq_disabled;
6458 
6459static bool __no_inline_not_in_flash_func(mg_picosdk_write)(void *addr,
6460 const void *buf,
6461 size_t len) {
6462 if ((len % s_mg_flash_picosdk.align) != 0) {
6463 MG_ERROR(("%lu is not aligned to %lu", len, s_mg_flash_picosdk.align));
6464 return false;
6465 }
6466 if ((((size_t) addr - (size_t) s_mg_flash_picosdk.start) %
6467 s_mg_flash_picosdk.align) != 0) {
6468 MG_ERROR(("%p is not on a page boundary", addr));
6469 return false;
6470 }
6471 
6472 uint32_t *dst = (uint32_t *) addr;
6473 uint32_t *src = (uint32_t *) buf;
6474 uint32_t *end = (uint32_t *) ((char *) buf + len);
6475 
6476#ifndef __riscv
6477 MG_ARM_DISABLE_IRQ();
6478#else
6479 asm volatile("csrrc zero, mstatus, %0" : : "i"(1 << 3) : "memory");
6480#endif
6481 while (src < end) {
6482 uint32_t dst_ofs = (uint32_t) dst - (uint32_t) s_mg_flash_picosdk.start;
6483 if (flash_sector_start(dst) && flash_erase(dst) == false) break;
6484 // flash_range_program() runs in RAM and handles writing up to
6485 // FLASH_PAGE_SIZE bytes. Source must not be in flash
6486 flash_range_program((uint32_t) dst_ofs, (uint8_t *) src,
6487 s_mg_flash_picosdk.align);
6488 src = (uint32_t *) ((char *) src + s_mg_flash_picosdk.align);
6489 dst = (uint32_t *) ((char *) dst + s_mg_flash_picosdk.align);
6490 }
6491 if (!s_flash_irq_disabled) {
6492#ifndef __riscv
6493 MG_ARM_ENABLE_IRQ();
6494#else
6495 asm volatile("csrrs mstatus, %0" : : "i"(1 << 3) : "memory");
6496#endif
6497 }
6498 MG_DEBUG(("Flash write %lu bytes @ %p.", len, dst));
6499 return true;
6500}
6501 
6502// just overwrite instead of swap
6503static void __no_inline_not_in_flash_func(single_bank_swap)(char *p1, char *p2,
6504 size_t s,
6505 size_t ss) {
6506 char *tmp = malloc(ss);
6507 if (tmp == NULL) return;
6508#if PICO_RP2040
6509 uint32_t xip[256 / sizeof(uint32_t)];
6510 void *dst = (void *) ((char *) p1 - (char *) s_mg_flash_picosdk.start);
6511 size_t count = MG_ROUND_UP(s, ss);
6512 // use SDK function calls to get BootROM function pointers
6513 rom_connect_internal_flash_fn connect = (rom_connect_internal_flash_fn) rom_func_lookup(ROM_FUNC_CONNECT_INTERNAL_FLASH);
6514 rom_flash_exit_xip_fn xit = (rom_flash_exit_xip_fn) rom_func_lookup(ROM_FUNC_FLASH_EXIT_XIP);
6515 rom_flash_range_program_fn program = (rom_flash_range_program_fn) rom_func_lookup(ROM_FUNC_FLASH_RANGE_PROGRAM);
6516 rom_flash_flush_cache_fn flush = (rom_flash_flush_cache_fn) rom_func_lookup(ROM_FUNC_FLASH_FLUSH_CACHE);
6517 // no stdlib calls here.
6518 MG_ARM_DISABLE_IRQ();
6519 // 2nd bootloader (XIP) is in flash, SDK functions copy it to RAM on entry
6520 for (size_t i = 0; i < 256 / sizeof(uint32_t); i++)
6521 xip[i] = ((uint32_t *) (s_mg_flash_picosdk.start))[i];
6522 flash_range_erase((uint32_t) dst, count);
6523 // flash has been erased, no XIP to copy. Only BootROM calls possible
6524 for (uint32_t ofs = 0; ofs < s; ofs += ss) {
6525 for (size_t i = 0; i < ss; i++) tmp[i] = p2[ofs + i];
6526 __compiler_memory_barrier();
6527 connect();
6528 xit();
6529 program((uint32_t) dst + ofs, tmp, ss);
6530 flush();
6531 ((void (*)(void))((intptr_t) xip + 1))(); // enter XIP again
6532 }
6533 *(volatile unsigned long *) 0xe000ed0c = 0x5fa0004; // AIRCR = SYSRESETREQ
6534#else
6535 // RP2350 has BootRAM and copies second bootloader there, SDK uses that copy,
6536 // It might also be able to take advantage of partition swapping
6537 rom_reboot_fn reboot = (rom_reboot_fn) rom_func_lookup(ROM_FUNC_REBOOT);
6538 for (size_t ofs = 0; ofs < s; ofs += ss) {
6539 for (size_t i = 0; i < ss; i++) tmp[i] = p2[ofs + i];
6540 mg_picosdk_write(p1 + ofs, tmp, ss);
6541 }
6542 reboot(BOOT_TYPE_NORMAL | 0x100, 1, 0, 0); // 0x100: NO_RETURN_ON_SUCCESS
6543#endif
6544}
6545 
6546bool mg_ota_begin(size_t new_firmware_size) {
6547 return mg_ota_flash_begin(new_firmware_size, &s_mg_flash_picosdk);
6548}
6549 
6550bool mg_ota_write(const void *buf, size_t len) {
6551 return mg_ota_flash_write(buf, len, &s_mg_flash_picosdk);
6552}
6553 
6554bool mg_ota_end(void) {
6555 if (mg_ota_flash_end(&s_mg_flash_picosdk)) {
6556 // Swap partitions. Pray power does not go away
6557 MG_INFO(("Swapping partitions, size %u (%u sectors)",
6558 s_mg_flash_picosdk.size,
6559 s_mg_flash_picosdk.size / s_mg_flash_picosdk.secsz));
6560 MG_INFO(("Do NOT power off..."));
6561 mg_log_level = MG_LL_NONE;
6562 s_flash_irq_disabled = true;
6563 // Runs in RAM, will reset when finished or return on failure
6564 single_bank_swap(
6565 (char *) s_mg_flash_picosdk.start,
6566 (char *) s_mg_flash_picosdk.start + s_mg_flash_picosdk.size / 2,
6567 s_mg_flash_picosdk.size / 2, s_mg_flash_picosdk.secsz);
6568 }
6569 return false;
6570}
6571#endif
6572 
6573#ifdef MG_ENABLE_LINES
6574#line 1 "src/ota_stm32f.c"
6575#endif
6576 
6577 
6578 
6579 
6580#if MG_OTA == MG_OTA_STM32F
6581 
6582static bool mg_stm32f_write(void *, const void *, size_t);
6583static bool mg_stm32f_swap(void);
6584 
6585static struct mg_flash s_mg_flash_stm32f = {
6586 (void *) 0x08000000, // Start
6587 0, // Size, FLASH_SIZE_REG
6588 0, // Irregular sector size
6589 32, // Align, 256 bit
6590 mg_stm32f_write,
6591 mg_stm32f_swap,
6592};
6593 
6594#define MG_FLASH_BASE 0x40023c00
6595#define MG_FLASH_KEYR 0x04
6596#define MG_FLASH_SR 0x0c
6597#define MG_FLASH_CR 0x10
6598#define MG_FLASH_OPTCR 0x14
6599#define MG_FLASH_SIZE_REG_F7 0x1FF0F442
6600#define MG_FLASH_SIZE_REG_F4 0x1FFF7A22
6601 
6602#define STM_DBGMCU_IDCODE 0xE0042000
6603#define STM_DEV_ID (MG_REG(STM_DBGMCU_IDCODE) & (MG_BIT(12) - 1))
6604#define SYSCFG_MEMRMP 0x40013800
6605 
6606#define MG_FLASH_SIZE_REG_LOCATION \
6607 ((STM_DEV_ID >= 0x449) ? MG_FLASH_SIZE_REG_F7 : MG_FLASH_SIZE_REG_F4)
6608 
6609static size_t flash_size(void) {
6610 return (MG_REG(MG_FLASH_SIZE_REG_LOCATION) & 0xFFFF) * 1024;
6611}
6612 
6613MG_IRAM static int is_dualbank(void) {
6614 // only F42x/F43x series (0x419) support dual bank
6615 return STM_DEV_ID == 0x419;
6616}
6617 
6618MG_IRAM static void flash_unlock(void) {
6619 static bool unlocked = false;
6620 if (unlocked == false) {
6621 MG_REG(MG_FLASH_BASE + MG_FLASH_KEYR) = 0x45670123;
6622 MG_REG(MG_FLASH_BASE + MG_FLASH_KEYR) = 0xcdef89ab;
6623 unlocked = true;
6624 }
6625}
6626 
6627#define MG_FLASH_CONFIG_16_64_128 1 // used by STM32F7
6628#define MG_FLASH_CONFIG_32_128_256 2 // used by STM32F4 and F2
6629 
6630MG_IRAM static bool flash_page_start(volatile uint32_t *dst) {
6631 char *base = (char *) s_mg_flash_stm32f.start;
6632 char *end = base + s_mg_flash_stm32f.size;
6633 
6634 if (is_dualbank() && dst >= (uint32_t *) (base + (end - base) / 2)) {
6635 dst = (uint32_t *) ((uint32_t) dst - (end - base) / 2);
6636 }
6637 
6638 uint32_t flash_config = MG_FLASH_CONFIG_16_64_128;
6639 if (STM_DEV_ID >= 0x449) {
6640 flash_config = MG_FLASH_CONFIG_32_128_256;
6641 }
6642 
6643 volatile char *p = (char *) dst;
6644 if (p >= base && p < end) {
6645 if (p < base + 16 * 1024 * 4 * flash_config) {
6646 if ((p - base) % (16 * 1024 * flash_config) == 0) return true;
6647 } else if (p == base + 16 * 1024 * 4 * flash_config) {
6648 return true;
6649 } else if ((p - base) % (128 * 1024 * flash_config) == 0) {
6650 return true;
6651 }
6652 }
6653 return false;
6654}
6655 
6656MG_IRAM static int flash_sector(volatile uint32_t *addr) {
6657 char *base = (char *) s_mg_flash_stm32f.start;
6658 char *end = base + s_mg_flash_stm32f.size;
6659 bool addr_in_bank_2 = false;
6660 if (is_dualbank() && addr >= (uint32_t *) (base + (end - base) / 2)) {
6661 addr = (uint32_t *) ((uint32_t) addr - (end - base) / 2);
6662 addr_in_bank_2 = true;
6663 }
6664 volatile char *p = (char *) addr;
6665 uint32_t flash_config = MG_FLASH_CONFIG_16_64_128;
6666 if (STM_DEV_ID >= 0x449) {
6667 flash_config = MG_FLASH_CONFIG_32_128_256;
6668 }
6669 int sector = -1;
6670 if (p >= base && p < end) {
6671 if (p < base + 16 * 1024 * 4 * flash_config) {
6672 sector = (p - base) / (16 * 1024 * flash_config);
6673 } else if (p >= base + 64 * 1024 * flash_config &&
6674 p < base + 128 * 1024 * flash_config) {
6675 sector = 4;
6676 } else {
6677 sector = (p - base) / (128 * 1024 * flash_config) + 4;
6678 }
6679 }
6680 if (sector == -1) return -1;
6681 if (addr_in_bank_2) sector += 12; // a bank has 12 sectors
6682 return sector;
6683}
6684 
6685MG_IRAM static bool flash_is_err(void) {
6686 return MG_REG(MG_FLASH_BASE + MG_FLASH_SR) & ((MG_BIT(7) - 1) << 1);
6687}
6688 
6689MG_IRAM static void flash_wait(void) {
6690 while (MG_REG(MG_FLASH_BASE + MG_FLASH_SR) & (MG_BIT(16))) (void) 0;
6691}
6692 
6693MG_IRAM static void flash_clear_err(void) {
6694 flash_wait(); // Wait until ready
6695 MG_REG(MG_FLASH_BASE + MG_FLASH_SR) = 0xf2; // Clear all errors
6696}
6697 
6698MG_IRAM static bool mg_stm32f_erase(void *addr) {
6699 bool ok = false;
6700 if (flash_page_start(addr) == false) {
6701 MG_ERROR(("%p is not on a sector boundary", addr));
6702 } else {
6703 int sector = flash_sector(addr);
6704 if (sector < 0) return false;
6705 uint32_t sector_reg = sector;
6706 if (is_dualbank() && sector >= 12) {
6707 // 3.9.8 Flash control register (FLASH_CR) for F42xxx and F43xxx
6708 // BITS[7:3]
6709 sector_reg -= 12;
6710 sector_reg |= MG_BIT(4);
6711 }
6712 flash_unlock();
6713 flash_wait();
6714 uint32_t cr = MG_BIT(1); // SER
6715 cr |= MG_BIT(16); // STRT
6716 cr |= (sector_reg & 31) << 3; // sector
6717 MG_REG(MG_FLASH_BASE + MG_FLASH_CR) = cr;
6718 ok = !flash_is_err();
6719 MG_DEBUG(("Erase sector %lu @ %p %s. CR %#lx SR %#lx", sector, addr,
6720 ok ? "ok" : "fail", MG_REG(MG_FLASH_BASE + MG_FLASH_CR),
6721 MG_REG(MG_FLASH_BASE + MG_FLASH_SR)));
6722 // After we have erased the sector, set CR flags for programming
6723 // 2 << 8 is word write parallelism, bit(0) is PG. RM0385, section 3.7.5
6724 MG_REG(MG_FLASH_BASE + MG_FLASH_CR) = MG_BIT(0) | (2 << 8);
6725 flash_clear_err();
6726 }
6727 return ok;
6728}
6729 
6730MG_IRAM static bool mg_stm32f_swap(void) {
6731 // STM32 F42x/F43x support dual bank, however, the memory mapping
6732 // change will not be carried through a hard reset. Therefore, we will use
6733 // the single bank approach for this family as well.
6734 return true;
6735}
6736 
6737static bool s_flash_irq_disabled;
6738 
6739MG_IRAM static bool mg_stm32f_write(void *addr, const void *buf, size_t len) {
6740 if ((len % s_mg_flash_stm32f.align) != 0) {
6741 MG_ERROR(("%lu is not aligned to %lu", len, s_mg_flash_stm32f.align));
6742 return false;
6743 }
6744 uint32_t *dst = (uint32_t *) addr;
6745 uint32_t *src = (uint32_t *) buf;
6746 uint32_t *end = (uint32_t *) ((char *) buf + len);
6747 bool ok = true;
6748 MG_ARM_DISABLE_IRQ();
6749 flash_unlock();
6750 flash_clear_err();
6751 MG_REG(MG_FLASH_BASE + MG_FLASH_CR) = MG_BIT(0) | MG_BIT(9); // PG, 32-bit
6752 flash_wait();
6753 MG_DEBUG(("Writing flash @ %p, %lu bytes", addr, len));
6754 while (ok && src < end) {
6755 if (flash_page_start(dst) && mg_stm32f_erase(dst) == false) break;
6756 *(volatile uint32_t *) dst++ = *src++;
6757 MG_DSB(); // ensure flash is written with no errors
6758 flash_wait();
6759 if (flash_is_err()) ok = false;
6760 }
6761 if (!s_flash_irq_disabled) MG_ARM_ENABLE_IRQ();
6762 MG_DEBUG(("Flash write %lu bytes @ %p: %s. CR %#lx SR %#lx", len, dst,
6763 ok ? "ok" : "fail", MG_REG(MG_FLASH_BASE + MG_FLASH_CR),
6764 MG_REG(MG_FLASH_BASE + MG_FLASH_SR)));
6765 MG_REG(MG_FLASH_BASE + MG_FLASH_CR) &= ~MG_BIT(0); // Clear programming flag
6766 return ok;
6767}
6768 
6769// just overwrite instead of swap
6770MG_IRAM void single_bank_swap(char *p1, char *p2, size_t size) {
6771 // no stdlib calls here
6772 mg_stm32f_write(p1, p2, size);
6773 *(volatile unsigned long *) 0xe000ed0c = 0x5fa0004;
6774}
6775 
6776bool mg_ota_begin(size_t new_firmware_size) {
6777 s_mg_flash_stm32f.size = flash_size();
6778 return mg_ota_flash_begin(new_firmware_size, &s_mg_flash_stm32f);
6779}
6780 
6781bool mg_ota_write(const void *buf, size_t len) {
6782 return mg_ota_flash_write(buf, len, &s_mg_flash_stm32f);
6783}
6784 
6785bool mg_ota_end(void) {
6786 if (mg_ota_flash_end(&s_mg_flash_stm32f)) {
6787 // Swap partitions. Pray power does not go away
6788 MG_INFO(("Swapping partitions, size %u (%u sectors)",
6789 s_mg_flash_stm32f.size, STM_DEV_ID == 0x449 ? 8 : 12));
6790 MG_INFO(("Do NOT power off..."));
6791 mg_log_level = MG_LL_NONE;
6792 s_flash_irq_disabled = true;
6793 char *p1 = (char *) s_mg_flash_stm32f.start;
6794 char *p2 = p1 + s_mg_flash_stm32f.size / 2;
6795 size_t size = s_mg_flash_stm32f.size / 2;
6796 // Runs in RAM, will reset when finished
6797 single_bank_swap(p1, p2, size);
6798 }
6799 return false;
6800}
6801#endif
6802 
6803#ifdef MG_ENABLE_LINES
6804#line 1 "src/ota_stm32h5.c"
6805#endif
6806 
6807 
6808 
6809 
6810#if MG_OTA == MG_OTA_STM32H5
6811 
6812static bool mg_stm32h5_write(void *, const void *, size_t);
6813static bool mg_stm32h5_swap(void);
6814 
6815static struct mg_flash s_mg_flash_stm32h5 = {
6816 (void *) 0x08000000, // Start
6817 2 * 1024 * 1024, // Size, 2Mb
6818 8 * 1024, // Sector size, 8k
6819 16, // Align, 128 bit
6820 mg_stm32h5_write,
6821 mg_stm32h5_swap,
6822};
6823 
6824#define MG_FLASH_BASE 0x40022000 // Base address of the flash controller
6825#define FLASH_KEYR (MG_FLASH_BASE + 0x4) // See RM0481 7.11
6826#define FLASH_OPTKEYR (MG_FLASH_BASE + 0xc)
6827#define FLASH_OPTCR (MG_FLASH_BASE + 0x1c)
6828#define FLASH_NSSR (MG_FLASH_BASE + 0x20)
6829#define FLASH_NSCR (MG_FLASH_BASE + 0x28)
6830#define FLASH_NSCCR (MG_FLASH_BASE + 0x30)
6831#define FLASH_OPTSR_CUR (MG_FLASH_BASE + 0x50)
6832#define FLASH_OPTSR_PRG (MG_FLASH_BASE + 0x54)
6833 
6834static void flash_unlock(void) {
6835 static bool unlocked = false;
6836 if (unlocked == false) {
6837 MG_REG(FLASH_KEYR) = 0x45670123;
6838 MG_REG(FLASH_KEYR) = 0Xcdef89ab;
6839 MG_REG(FLASH_OPTKEYR) = 0x08192a3b;
6840 MG_REG(FLASH_OPTKEYR) = 0x4c5d6e7f;
6841 unlocked = true;
6842 }
6843}
6844 
6845static int flash_page_start(volatile uint32_t *dst) {
6846 char *base = (char *) s_mg_flash_stm32h5.start,
6847 *end = base + s_mg_flash_stm32h5.size;
6848 volatile char *p = (char *) dst;
6849 return p >= base && p < end && ((p - base) % s_mg_flash_stm32h5.secsz) == 0;
6850}
6851 
6852static bool flash_is_err(void) {
6853 return MG_REG(FLASH_NSSR) & ((MG_BIT(8) - 1) << 17); // RM0481 7.11.9
6854}
6855 
6856static void flash_wait(void) {
6857 while ((MG_REG(FLASH_NSSR) & MG_BIT(0)) &&
6858 (MG_REG(FLASH_NSSR) & MG_BIT(16)) == 0) {
6859 (void) 0;
6860 }
6861}
6862 
6863static void flash_clear_err(void) {
6864 flash_wait(); // Wait until ready
6865 MG_REG(FLASH_NSCCR) = ((MG_BIT(9) - 1) << 16U); // Clear all errors
6866}
6867 
6868static bool flash_bank_is_swapped(void) {
6869 return MG_REG(FLASH_OPTCR) & MG_BIT(31); // RM0481 7.11.8
6870}
6871 
6872static bool mg_stm32h5_erase(void *location) {
6873 bool ok = false;
6874 if (flash_page_start(location) == false) {
6875 MG_ERROR(("%p is not on a sector boundary"));
6876 } else {
6877 uintptr_t diff = (char *) location - (char *) s_mg_flash_stm32h5.start;
6878 uint32_t sector = diff / s_mg_flash_stm32h5.secsz;
6879 uint32_t saved_cr = MG_REG(FLASH_NSCR); // Save CR value
6880 flash_unlock();
6881 flash_clear_err();
6882 MG_REG(FLASH_NSCR) = 0;
6883 if ((sector < 128 && flash_bank_is_swapped()) ||
6884 (sector > 127 && !flash_bank_is_swapped())) {
6885 MG_REG(FLASH_NSCR) |= MG_BIT(31); // Set FLASH_CR_BKSEL
6886 }
6887 if (sector > 127) sector -= 128;
6888 MG_REG(FLASH_NSCR) |= MG_BIT(2) | (sector << 6); // Erase | sector_num
6889 MG_REG(FLASH_NSCR) |= MG_BIT(5); // Start erasing
6890 flash_wait();
6891 ok = !flash_is_err();
6892 MG_DEBUG(("Erase sector %lu @ %p: %s. CR %#lx SR %#lx", sector, location,
6893 ok ? "ok" : "fail", MG_REG(FLASH_NSCR), MG_REG(FLASH_NSSR)));
6894 // mg_hexdump(location, 32);
6895 MG_REG(FLASH_NSCR) = saved_cr; // Restore saved CR
6896 }
6897 return ok;
6898}
6899 
6900static bool mg_stm32h5_swap(void) {
6901 uint32_t desired = flash_bank_is_swapped() ? 0 : MG_BIT(31);
6902 flash_unlock();
6903 flash_clear_err();
6904 // printf("OPTSR_PRG 1 %#lx\n", FLASH->OPTSR_PRG);
6905 MG_SET_BITS(MG_REG(FLASH_OPTSR_PRG), MG_BIT(31), desired);
6906 // printf("OPTSR_PRG 2 %#lx\n", FLASH->OPTSR_PRG);
6907 MG_REG(FLASH_OPTCR) |= MG_BIT(1); // OPTSTART
6908 while ((MG_REG(FLASH_OPTSR_CUR) & MG_BIT(31)) != desired) (void) 0;
6909 return true;
6910}
6911 
6912static bool mg_stm32h5_write(void *addr, const void *buf, size_t len) {
6913 if ((len % s_mg_flash_stm32h5.align) != 0) {
6914 MG_ERROR(("%lu is not aligned to %lu", len, s_mg_flash_stm32h5.align));
6915 return false;
6916 }
6917 uint32_t *dst = (uint32_t *) addr;
6918 uint32_t *src = (uint32_t *) buf;
6919 uint32_t *end = (uint32_t *) ((char *) buf + len);
6920 bool ok = true;
6921 MG_ARM_DISABLE_IRQ();
6922 flash_unlock();
6923 flash_clear_err();
6924 MG_REG(FLASH_NSCR) = MG_BIT(1); // Set programming flag
6925 while (ok && src < end) {
6926 if (flash_page_start(dst) && mg_stm32h5_erase(dst) == false) {
6927 ok = false;
6928 break;
6929 }
6930 *(volatile uint32_t *) dst++ = *src++;
6931 flash_wait();
6932 if (flash_is_err()) ok = false;
6933 }
6934 MG_ARM_ENABLE_IRQ();
6935 MG_DEBUG(("Flash write %lu bytes @ %p: %s. CR %#lx SR %#lx", len, dst,
6936 flash_is_err() ? "fail" : "ok", MG_REG(FLASH_NSCR),
6937 MG_REG(FLASH_NSSR)));
6938 MG_REG(FLASH_NSCR) = 0; // Clear flags
6939 return ok;
6940}
6941 
6942bool mg_ota_begin(size_t new_firmware_size) {
6943 return mg_ota_flash_begin(new_firmware_size, &s_mg_flash_stm32h5);
6944}
6945 
6946bool mg_ota_write(const void *buf, size_t len) {
6947 return mg_ota_flash_write(buf, len, &s_mg_flash_stm32h5);
6948}
6949 
6950// Actual bank swap is deferred until reset, it is safe to execute in flash
6951bool mg_ota_end(void) {
6952 if(!mg_ota_flash_end(&s_mg_flash_stm32h5)) return false;
6953 *(volatile unsigned long *) 0xe000ed0c = 0x5fa0004;
6954 return true;
6955}
6956#endif
6957 
6958#ifdef MG_ENABLE_LINES
6959#line 1 "src/ota_stm32h7.c"
6960#endif
6961 
6962 
6963 
6964 
6965#if MG_OTA == MG_OTA_STM32H7 || MG_OTA == MG_OTA_STM32H7_DUAL_CORE
6966 
6967// - H723/735 RM 4.3.3: Note: The application can simultaneously request a read
6968// and a write operation through the AXI interface.
6969// - We only need IRAM for partition swapping in the H723, however, all
6970// related functions must reside in IRAM for this to be possible.
6971// - Linker files for other devices won't define a .iram section so there's no
6972// associated penalty
6973 
6974static bool mg_stm32h7_write(void *, const void *, size_t);
6975static bool mg_stm32h7_swap(void);
6976 
6977static struct mg_flash s_mg_flash_stm32h7 = {
6978 (void *) 0x08000000, // Start
6979 0, // Size, FLASH_SIZE_REG
6980 128 * 1024, // Sector size, 128k
6981 32, // Align, 256 bit
6982 mg_stm32h7_write,
6983 mg_stm32h7_swap,
6984};
6985 
6986#define FLASH_BASE1 0x52002000 // Base address for bank1
6987#define FLASH_BASE2 0x52002100 // Base address for bank2
6988#define FLASH_KEYR 0x04 // See RM0433 4.9.2
6989#define FLASH_OPTKEYR 0x08
6990#define FLASH_OPTCR 0x18
6991#define FLASH_SR 0x10
6992#define FLASH_CR 0x0c
6993#define FLASH_CCR 0x14
6994#define FLASH_OPTSR_CUR 0x1c
6995#define FLASH_OPTSR_PRG 0x20
6996#define FLASH_SIZE_REG 0x1ff1e880
6997 
6998#define IS_DUALCORE() (MG_OTA == MG_OTA_STM32H7_DUAL_CORE)
6999 
7000MG_IRAM static bool is_dualbank(void) {
7001 if (IS_DUALCORE()) {
7002 // H745/H755 and H747/H757 are running on dual core.
7003 // Using only the 1st bank (mapped to CM7), in order not to interfere
7004 // with the 2nd bank (CM4), possibly causing CM4 to boot unexpectedly.
7005 return false;
7006 }
7007 return (s_mg_flash_stm32h7.size < 2 * 1024 * 1024) ? false : true;
7008}
7009 
7010MG_IRAM static void flash_unlock(void) {
7011 static bool unlocked = false;
7012 if (unlocked == false) {
7013 MG_REG(FLASH_BASE1 + FLASH_KEYR) = 0x45670123;
7014 MG_REG(FLASH_BASE1 + FLASH_KEYR) = 0xcdef89ab;
7015 if (is_dualbank()) {
7016 MG_REG(FLASH_BASE2 + FLASH_KEYR) = 0x45670123;
7017 MG_REG(FLASH_BASE2 + FLASH_KEYR) = 0xcdef89ab;
7018 }
7019 MG_REG(FLASH_BASE1 + FLASH_OPTKEYR) = 0x08192a3b; // opt reg is "shared"
7020 MG_REG(FLASH_BASE1 + FLASH_OPTKEYR) = 0x4c5d6e7f; // thus unlock once
7021 unlocked = true;
7022 }
7023}
7024 
7025MG_IRAM static bool flash_page_start(volatile uint32_t *dst) {
7026 char *base = (char *) s_mg_flash_stm32h7.start,
7027 *end = base + s_mg_flash_stm32h7.size;
7028 volatile char *p = (char *) dst;
7029 return p >= base && p < end && ((p - base) % s_mg_flash_stm32h7.secsz) == 0;
7030}
7031 
7032MG_IRAM static bool flash_is_err(uint32_t bank) {
7033 return MG_REG(bank + FLASH_SR) & ((MG_BIT(11) - 1) << 17); // RM0433 4.9.5
7034}
7035 
7036MG_IRAM static void flash_wait(uint32_t bank) {
7037 while (MG_REG(bank + FLASH_SR) & (MG_BIT(0) | MG_BIT(2))) (void) 0;
7038}
7039 
7040MG_IRAM static void flash_clear_err(uint32_t bank) {
7041 flash_wait(bank); // Wait until ready
7042 MG_REG(bank + FLASH_CCR) = ((MG_BIT(11) - 1) << 16U); // Clear all errors
7043}
7044 
7045MG_IRAM static bool flash_bank_is_swapped(uint32_t bank) {
7046 return MG_REG(bank + FLASH_OPTCR) & MG_BIT(31); // RM0433 4.9.7
7047}
7048 
7049// Figure out flash bank based on the address
7050MG_IRAM static uint32_t flash_bank(void *addr) {
7051 size_t ofs = (char *) addr - (char *) s_mg_flash_stm32h7.start;
7052 if (!is_dualbank()) return FLASH_BASE1;
7053 return ofs < s_mg_flash_stm32h7.size / 2 ? FLASH_BASE1 : FLASH_BASE2;
7054}
7055 
7056// read-while-write, no need to disable IRQs for standalone usage
7057MG_IRAM static bool mg_stm32h7_erase(void *addr) {
7058 bool ok = false;
7059 if (flash_page_start(addr) == false) {
7060 MG_ERROR(("%p is not on a sector boundary", addr));
7061 } else {
7062 uintptr_t diff = (char *) addr - (char *) s_mg_flash_stm32h7.start;
7063 uint32_t sector = diff / s_mg_flash_stm32h7.secsz;
7064 uint32_t bank = flash_bank(addr);
7065 uint32_t saved_cr = MG_REG(bank + FLASH_CR); // Save CR value
7066 
7067 flash_unlock();
7068 if (sector > 7) sector -= 8;
7069 
7070 flash_clear_err(bank);
7071 MG_REG(bank + FLASH_CR) = MG_BIT(5); // 32-bit write parallelism
7072 MG_REG(bank + FLASH_CR) |= (sector & 7U) << 8U; // Sector to erase
7073 MG_REG(bank + FLASH_CR) |= MG_BIT(2); // Sector erase bit
7074 MG_REG(bank + FLASH_CR) |= MG_BIT(7); // Start erasing
7075 ok = !flash_is_err(bank);
7076 MG_DEBUG(("Erase sector %lu @ %p %s. CR %#lx SR %#lx", sector, addr,
7077 ok ? "ok" : "fail", MG_REG(bank + FLASH_CR),
7078 MG_REG(bank + FLASH_SR)));
7079 MG_REG(bank + FLASH_CR) = saved_cr; // Restore CR
7080 }
7081 return ok;
7082}
7083 
7084MG_IRAM static bool mg_stm32h7_swap(void) {
7085 if (!is_dualbank()) return true;
7086 uint32_t bank = FLASH_BASE1;
7087 uint32_t desired = flash_bank_is_swapped(bank) ? 0 : MG_BIT(31);
7088 flash_unlock();
7089 flash_clear_err(bank);
7090 // printf("OPTSR_PRG 1 %#lx\n", FLASH->OPTSR_PRG);
7091 MG_SET_BITS(MG_REG(bank + FLASH_OPTSR_PRG), MG_BIT(31), desired);
7092 // printf("OPTSR_PRG 2 %#lx\n", FLASH->OPTSR_PRG);
7093 MG_REG(bank + FLASH_OPTCR) |= MG_BIT(1); // OPTSTART
7094 while ((MG_REG(bank + FLASH_OPTSR_CUR) & MG_BIT(31)) != desired) (void) 0;
7095 return true;
7096}
7097 
7098static bool s_flash_irq_disabled;
7099 
7100MG_IRAM static bool mg_stm32h7_write(void *addr, const void *buf, size_t len) {
7101 if ((len % s_mg_flash_stm32h7.align) != 0) {
7102 MG_ERROR(("%lu is not aligned to %lu", len, s_mg_flash_stm32h7.align));
7103 return false;
7104 }
7105 uint32_t bank = flash_bank(addr);
7106 uint32_t *dst = (uint32_t *) addr;
7107 uint32_t *src = (uint32_t *) buf;
7108 uint32_t *end = (uint32_t *) ((char *) buf + len);
7109 bool ok = true;
7110 MG_ARM_DISABLE_IRQ();
7111 flash_unlock();
7112 flash_clear_err(bank);
7113 MG_REG(bank + FLASH_CR) = MG_BIT(1); // Set programming flag
7114 MG_REG(bank + FLASH_CR) |= MG_BIT(5); // 32-bit write parallelism
7115 while (ok && src < end) {
7116 if (flash_page_start(dst) && mg_stm32h7_erase(dst) == false) {
7117 ok = false;
7118 break;
7119 }
7120 *(volatile uint32_t *) dst++ = *src++;
7121 flash_wait(bank);
7122 if (flash_is_err(bank)) ok = false;
7123 }
7124 if (!s_flash_irq_disabled) MG_ARM_ENABLE_IRQ();
7125 MG_DEBUG(("Flash write %lu bytes @ %p: %s. CR %#lx SR %#lx", len, dst,
7126 ok ? "ok" : "fail", MG_REG(bank + FLASH_CR),
7127 MG_REG(bank + FLASH_SR)));
7128 MG_REG(bank + FLASH_CR) &= ~MG_BIT(1); // Clear programming flag
7129 return ok;
7130}
7131 
7132// just overwrite instead of swap
7133MG_IRAM static void single_bank_swap(char *p1, char *p2, size_t s, size_t ss) {
7134 // no stdlib calls here
7135 for (size_t ofs = 0; ofs < s; ofs += ss) {
7136 mg_stm32h7_write(p1 + ofs, p2 + ofs, ss);
7137 }
7138 *(volatile unsigned long *) 0xe000ed0c = 0x5fa0004;
7139}
7140 
7141bool mg_ota_begin(size_t new_firmware_size) {
7142 s_mg_flash_stm32h7.size = MG_REG(FLASH_SIZE_REG) * 1024;
7143 if (IS_DUALCORE()) {
7144 // Using only the 1st bank (mapped to CM7)
7145 s_mg_flash_stm32h7.size /= 2;
7146 }
7147 return mg_ota_flash_begin(new_firmware_size, &s_mg_flash_stm32h7);
7148}
7149 
7150bool mg_ota_write(const void *buf, size_t len) {
7151 return mg_ota_flash_write(buf, len, &s_mg_flash_stm32h7);
7152}
7153 
7154bool mg_ota_end(void) {
7155 if (mg_ota_flash_end(&s_mg_flash_stm32h7)) {
7156 if (is_dualbank()) {
7157 // Bank swap is deferred until reset, been executing in flash, reset
7158 *(volatile unsigned long *) 0xe000ed0c = 0x5fa0004;
7159 } else {
7160 // Swap partitions. Pray power does not go away
7161 MG_INFO(("Swapping partitions, size %u (%u sectors)",
7162 s_mg_flash_stm32h7.size,
7163 s_mg_flash_stm32h7.size / s_mg_flash_stm32h7.secsz));
7164 MG_INFO(("Do NOT power off..."));
7165 mg_log_level = MG_LL_NONE;
7166 s_flash_irq_disabled = true;
7167 // Runs in RAM, will reset when finished
7168 single_bank_swap(
7169 (char *) s_mg_flash_stm32h7.start,
7170 (char *) s_mg_flash_stm32h7.start + s_mg_flash_stm32h7.size / 2,
7171 s_mg_flash_stm32h7.size / 2, s_mg_flash_stm32h7.secsz);
7172 }
7173 }
7174 return false;
7175}
7176#endif
7177 
7178#ifdef MG_ENABLE_LINES
7179#line 1 "src/printf.c"
7180#endif
7181 
7182 
7183 
7184 
7185size_t mg_queue_vprintf(struct mg_queue *q, const char *fmt, va_list *ap) {
7186 size_t len = mg_snprintf(NULL, 0, fmt, ap);
7187 char *buf;
7188 if (len == 0 || mg_queue_book(q, &buf, len + 1) < len + 1) {
7189 len = 0; // Nah. Not enough space
7190 } else {
7191 len = mg_vsnprintf((char *) buf, len + 1, fmt, ap);
7192 mg_queue_add(q, len);
7193 }
7194 return len;
7195}
7196 
7197size_t mg_queue_printf(struct mg_queue *q, const char *fmt, ...) {
7198 va_list ap;
7199 size_t len;
7200 va_start(ap, fmt);
7201 len = mg_queue_vprintf(q, fmt, &ap);
7202 va_end(ap);
7203 return len;
7204}
7205 
7206static void mg_pfn_iobuf_private(char ch, void *param, bool expand) {
7207 struct mg_iobuf *io = (struct mg_iobuf *) param;
7208 if (expand && io->len + 2 > io->size) mg_iobuf_resize(io, io->len + 2);
7209 if (io->len + 2 <= io->size) {
7210 io->buf[io->len++] = (uint8_t) ch;
7211 io->buf[io->len] = 0;
7212 } else if (io->len < io->size) {
7213 io->buf[io->len++] = 0; // Guarantee to 0-terminate
7214 }
7215}
7216 
7217static void mg_putchar_iobuf_static(char ch, void *param) {
7218 mg_pfn_iobuf_private(ch, param, false);
7219}
7220 
7221void mg_pfn_iobuf(char ch, void *param) {
7222 mg_pfn_iobuf_private(ch, param, true);
7223}
7224 
7225size_t mg_vsnprintf(char *buf, size_t len, const char *fmt, va_list *ap) {
7226 struct mg_iobuf io = {(uint8_t *) buf, len, 0, 0};
7227 size_t n = mg_vxprintf(mg_putchar_iobuf_static, &io, fmt, ap);
7228 if (n < len) buf[n] = '\0';
7229 return n;
7230}
7231 
7232size_t mg_snprintf(char *buf, size_t len, const char *fmt, ...) {
7233 va_list ap;
7234 size_t n;
7235 va_start(ap, fmt);
7236 n = mg_vsnprintf(buf, len, fmt, &ap);
7237 va_end(ap);
7238 return n;
7239}
7240 
7241char *mg_vmprintf(const char *fmt, va_list *ap) {
7242 struct mg_iobuf io = {0, 0, 0, 256};
7243 mg_vxprintf(mg_pfn_iobuf, &io, fmt, ap);
7244 return (char *) io.buf;
7245}
7246 
7247char *mg_mprintf(const char *fmt, ...) {
7248 char *s;
7249 va_list ap;
7250 va_start(ap, fmt);
7251 s = mg_vmprintf(fmt, &ap);
7252 va_end(ap);
7253 return s;
7254}
7255 
7256void mg_pfn_stdout(char c, void *param) {
7257 putchar(c);
7258 (void) param;
7259}
7260 
7261static size_t print_ip4(void (*out)(char, void *), void *arg, uint8_t *p) {
7262 return mg_xprintf(out, arg, "%d.%d.%d.%d", p[0], p[1], p[2], p[3]);
7263}
7264 
7265static size_t print_ip6(void (*out)(char, void *), void *arg, uint16_t *p) {
7266 return mg_xprintf(out, arg, "[%x:%x:%x:%x:%x:%x:%x:%x]", mg_ntohs(p[0]),
7267 mg_ntohs(p[1]), mg_ntohs(p[2]), mg_ntohs(p[3]),
7268 mg_ntohs(p[4]), mg_ntohs(p[5]), mg_ntohs(p[6]),
7269 mg_ntohs(p[7]));
7270}
7271 
7272size_t mg_print_ip4(void (*out)(char, void *), void *arg, va_list *ap) {
7273 uint8_t *p = va_arg(*ap, uint8_t *);
7274 return print_ip4(out, arg, p);
7275}
7276 
7277size_t mg_print_ip6(void (*out)(char, void *), void *arg, va_list *ap) {
7278 uint16_t *p = va_arg(*ap, uint16_t *);
7279 return print_ip6(out, arg, p);
7280}
7281 
7282size_t mg_print_ip(void (*out)(char, void *), void *arg, va_list *ap) {
7283 struct mg_addr *addr = va_arg(*ap, struct mg_addr *);
7284 if (addr->is_ip6) return print_ip6(out, arg, (uint16_t *) addr->ip);
7285 return print_ip4(out, arg, (uint8_t *) &addr->ip);
7286}
7287 
7288size_t mg_print_ip_port(void (*out)(char, void *), void *arg, va_list *ap) {
7289 struct mg_addr *a = va_arg(*ap, struct mg_addr *);
7290 return mg_xprintf(out, arg, "%M:%hu", mg_print_ip, a, mg_ntohs(a->port));
7291}
7292 
7293size_t mg_print_mac(void (*out)(char, void *), void *arg, va_list *ap) {
7294 uint8_t *p = va_arg(*ap, uint8_t *);
7295 return mg_xprintf(out, arg, "%02x:%02x:%02x:%02x:%02x:%02x", p[0], p[1], p[2],
7296 p[3], p[4], p[5]);
7297}
7298 
7299static char mg_esc(int c, bool esc) {
7300 const char *p, *esc1 = "\b\f\n\r\t\\\"", *esc2 = "bfnrt\\\"";
7301 for (p = esc ? esc1 : esc2; *p != '\0'; p++) {
7302 if (*p == c) return esc ? esc2[p - esc1] : esc1[p - esc2];
7303 }
7304 return 0;
7305}
7306 
7307static char mg_escape(int c) {
7308 return mg_esc(c, true);
7309}
7310 
7311static size_t qcpy(void (*out)(char, void *), void *ptr, char *buf,
7312 size_t len) {
7313 size_t i = 0, extra = 0;
7314 for (i = 0; i < len && buf[i] != '\0'; i++) {
7315 char c = mg_escape(buf[i]);
7316 if (c) {
7317 out('\\', ptr), out(c, ptr), extra++;
7318 } else {
7319 out(buf[i], ptr);
7320 }
7321 }
7322 return i + extra;
7323}
7324 
7325static size_t bcpy(void (*out)(char, void *), void *arg, uint8_t *buf,
7326 size_t len) {
7327 size_t i, j, n = 0;
7328 const char *t =
7329 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
7330 for (i = 0; i < len; i += 3) {
7331 uint8_t c1 = buf[i], c2 = i + 1 < len ? buf[i + 1] : 0,
7332 c3 = i + 2 < len ? buf[i + 2] : 0;
7333 char tmp[4] = {t[c1 >> 2], t[(c1 & 3) << 4 | (c2 >> 4)], '=', '='};
7334 if (i + 1 < len) tmp[2] = t[(c2 & 15) << 2 | (c3 >> 6)];
7335 if (i + 2 < len) tmp[3] = t[c3 & 63];
7336 for (j = 0; j < sizeof(tmp) && tmp[j] != '\0'; j++) out(tmp[j], arg);
7337 n += j;
7338 }
7339 return n;
7340}
7341 
7342size_t mg_print_hex(void (*out)(char, void *), void *arg, va_list *ap) {
7343 size_t bl = (size_t) va_arg(*ap, int);
7344 uint8_t *p = va_arg(*ap, uint8_t *);
7345 const char *hex = "0123456789abcdef";
7346 size_t j;
7347 for (j = 0; j < bl; j++) {
7348 out(hex[(p[j] >> 4) & 0x0F], arg);
7349 out(hex[p[j] & 0x0F], arg);
7350 }
7351 return 2 * bl;
7352}
7353size_t mg_print_base64(void (*out)(char, void *), void *arg, va_list *ap) {
7354 size_t len = (size_t) va_arg(*ap, int);
7355 uint8_t *buf = va_arg(*ap, uint8_t *);
7356 return bcpy(out, arg, buf, len);
7357}
7358 
7359size_t mg_print_esc(void (*out)(char, void *), void *arg, va_list *ap) {
7360 size_t len = (size_t) va_arg(*ap, int);
7361 char *p = va_arg(*ap, char *);
7362 if (len == 0) len = p == NULL ? 0 : strlen(p);
7363 return qcpy(out, arg, p, len);
7364}
7365 
7366#ifdef MG_ENABLE_LINES
7367#line 1 "src/queue.c"
7368#endif
7369 
7370 
7371 
7372#if (defined(__GNUC__) && (__GNUC__ > 4) || \
7373 (defined(__GNUC_MINOR__) && __GNUC__ == 4 && __GNUC_MINOR__ >= 1)) || \
7374 defined(__clang__)
7375#define MG_MEMORY_BARRIER() __sync_synchronize()
7376#elif defined(_MSC_VER) && _MSC_VER >= 1700
7377#define MG_MEMORY_BARRIER() MemoryBarrier()
7378#elif !defined(MG_MEMORY_BARRIER)
7379#define MG_MEMORY_BARRIER()
7380#endif
7381 
7382// Every message in a queue is prepended by a 32-bit message length (ML).
7383// If ML is 0, then it is the end, and reader must wrap to the beginning.
7384//
7385// Queue when q->tail <= q->head:
7386// |----- free -----| ML | message1 | ML | message2 | ----- free ------|
7387// ^ ^ ^ ^
7388// buf tail head len
7389//
7390// Queue when q->tail > q->head:
7391// | ML | message2 |----- free ------| ML | message1 | 0 |---- free ----|
7392// ^ ^ ^ ^
7393// buf head tail len
7394 
7395void mg_queue_init(struct mg_queue *q, char *buf, size_t size) {
7396 q->size = size;
7397 q->buf = buf;
7398 q->head = q->tail = 0;
7399}
7400 
7401static size_t mg_queue_read_len(struct mg_queue *q) {
7402 uint32_t n = 0;
7403 MG_MEMORY_BARRIER();
7404 memcpy(&n, q->buf + q->tail, sizeof(n));
7405 assert(q->tail + n + sizeof(n) <= q->size);
7406 return n;
7407}
7408 
7409static void mg_queue_write_len(struct mg_queue *q, size_t len) {
7410 uint32_t n = (uint32_t) len;
7411 memcpy(q->buf + q->head, &n, sizeof(n));
7412 MG_MEMORY_BARRIER();
7413}
7414 
7415size_t mg_queue_book(struct mg_queue *q, char **buf, size_t len) {
7416 size_t space = 0, hs = sizeof(uint32_t) * 2; // *2 is for the 0 marker
7417 if (q->head >= q->tail && q->head + len + hs <= q->size) {
7418 space = q->size - q->head - hs; // There is enough space
7419 } else if (q->head >= q->tail && q->tail > hs) {
7420 mg_queue_write_len(q, 0); // Not enough space ahead
7421 q->head = 0; // Wrap head to the beginning
7422 }
7423 if (q->head + hs + len < q->tail) space = q->tail - q->head - hs;
7424 if (buf != NULL) *buf = q->buf + q->head + sizeof(uint32_t);
7425 return space;
7426}
7427 
7428size_t mg_queue_next(struct mg_queue *q, char **buf) {
7429 size_t len = 0;
7430 if (q->tail != q->head) {
7431 len = mg_queue_read_len(q);
7432 if (len == 0) { // Zero (head wrapped) ?
7433 q->tail = 0; // Reset tail to the start
7434 if (q->head > q->tail) len = mg_queue_read_len(q); // Read again
7435 }
7436 }
7437 if (buf != NULL) *buf = q->buf + q->tail + sizeof(uint32_t);
7438 assert(q->tail + len <= q->size);
7439 return len;
7440}
7441 
7442void mg_queue_add(struct mg_queue *q, size_t len) {
7443 assert(len > 0);
7444 mg_queue_write_len(q, len);
7445 assert(q->head + sizeof(uint32_t) * 2 + len <= q->size);
7446 q->head += len + sizeof(uint32_t);
7447}
7448 
7449void mg_queue_del(struct mg_queue *q, size_t len) {
7450 q->tail += len + sizeof(uint32_t);
7451 assert(q->tail + sizeof(uint32_t) <= q->size);
7452}
7453 
7454#ifdef MG_ENABLE_LINES
7455#line 1 "src/rpc.c"
7456#endif
7457 
7458 
7459 
7460void mg_rpc_add(struct mg_rpc **head, struct mg_str method,
7461 void (*fn)(struct mg_rpc_req *), void *fn_data) {
7462 struct mg_rpc *rpc = (struct mg_rpc *) calloc(1, sizeof(*rpc));
7463 if (rpc != NULL) {
7464 rpc->method = mg_strdup(method);
7465 rpc->fn = fn;
7466 rpc->fn_data = fn_data;
7467 rpc->next = *head, *head = rpc;
7468 }
7469}
7470 
7471void mg_rpc_del(struct mg_rpc **head, void (*fn)(struct mg_rpc_req *)) {
7472 struct mg_rpc *r;
7473 while ((r = *head) != NULL) {
7474 if (r->fn == fn || fn == NULL) {
7475 *head = r->next;
7476 free((void *) r->method.buf);
7477 free(r);
7478 } else {
7479 head = &(*head)->next;
7480 }
7481 }
7482}
7483 
7484static void mg_rpc_call(struct mg_rpc_req *r, struct mg_str method) {
7485 struct mg_rpc *h = r->head == NULL ? NULL : *r->head;
7486 while (h != NULL && !mg_match(method, h->method, NULL)) h = h->next;
7487 if (h != NULL) {
7488 r->rpc = h;
7489 h->fn(r);
7490 } else {
7491 mg_rpc_err(r, -32601, "\"%.*s not found\"", (int) method.len, method.buf);
7492 }
7493}
7494 
7495void mg_rpc_process(struct mg_rpc_req *r) {
7496 int len, off = mg_json_get(r->frame, "$.method", &len);
7497 if (off > 0 && r->frame.buf[off] == '"') {
7498 struct mg_str method = mg_str_n(&r->frame.buf[off + 1], (size_t) len - 2);
7499 mg_rpc_call(r, method);
7500 } else if ((off = mg_json_get(r->frame, "$.result", &len)) > 0 ||
7501 (off = mg_json_get(r->frame, "$.error", &len)) > 0) {
7502 mg_rpc_call(r, mg_str("")); // JSON response! call "" method handler
7503 } else {
7504 mg_rpc_err(r, -32700, "%m", mg_print_esc, (int) r->frame.len,
7505 r->frame.buf); // Invalid
7506 }
7507}
7508 
7509void mg_rpc_vok(struct mg_rpc_req *r, const char *fmt, va_list *ap) {
7510 int len, off = mg_json_get(r->frame, "$.id", &len);
7511 if (off > 0) {
7512 mg_xprintf(r->pfn, r->pfn_data, "{%m:%.*s,%m:", mg_print_esc, 0, "id", len,
7513 &r->frame.buf[off], mg_print_esc, 0, "result");
7514 mg_vxprintf(r->pfn, r->pfn_data, fmt == NULL ? "null" : fmt, ap);
7515 mg_xprintf(r->pfn, r->pfn_data, "}");
7516 }
7517}
7518 
7519void mg_rpc_ok(struct mg_rpc_req *r, const char *fmt, ...) {
7520 va_list ap;
7521 va_start(ap, fmt);
7522 mg_rpc_vok(r, fmt, &ap);
7523 va_end(ap);
7524}
7525 
7526void mg_rpc_verr(struct mg_rpc_req *r, int code, const char *fmt, va_list *ap) {
7527 int len, off = mg_json_get(r->frame, "$.id", &len);
7528 mg_xprintf(r->pfn, r->pfn_data, "{");
7529 if (off > 0) {
7530 mg_xprintf(r->pfn, r->pfn_data, "%m:%.*s,", mg_print_esc, 0, "id", len,
7531 &r->frame.buf[off]);
7532 }
7533 mg_xprintf(r->pfn, r->pfn_data, "%m:{%m:%d,%m:", mg_print_esc, 0, "error",
7534 mg_print_esc, 0, "code", code, mg_print_esc, 0, "message");
7535 mg_vxprintf(r->pfn, r->pfn_data, fmt == NULL ? "null" : fmt, ap);
7536 mg_xprintf(r->pfn, r->pfn_data, "}}");
7537}
7538 
7539void mg_rpc_err(struct mg_rpc_req *r, int code, const char *fmt, ...) {
7540 va_list ap;
7541 va_start(ap, fmt);
7542 mg_rpc_verr(r, code, fmt, &ap);
7543 va_end(ap);
7544}
7545 
7546static size_t print_methods(mg_pfn_t pfn, void *pfn_data, va_list *ap) {
7547 struct mg_rpc *h, **head = (struct mg_rpc **) va_arg(*ap, void **);
7548 size_t len = 0;
7549 for (h = *head; h != NULL; h = h->next) {
7550 if (h->method.len == 0) continue; // Ignore response handler
7551 len += mg_xprintf(pfn, pfn_data, "%s%m", h == *head ? "" : ",",
7552 mg_print_esc, (int) h->method.len, h->method.buf);
7553 }
7554 return len;
7555}
7556 
7557void mg_rpc_list(struct mg_rpc_req *r) {
7558 mg_rpc_ok(r, "[%M]", print_methods, r->head);
7559}
7560 
7561#ifdef MG_ENABLE_LINES
7562#line 1 "src/sha1.c"
7563#endif
7564/* Copyright(c) By Steve Reid <steve@edmweb.com> */
7565/* 100% Public Domain */
7566 
7567 
7568 
7569union char64long16 {
7570 unsigned char c[64];
7571 uint32_t l[16];
7572};
7573 
7574#define rol(value, bits) (((value) << (bits)) | ((value) >> (32 - (bits))))
7575 
7576static uint32_t blk0(union char64long16 *block, int i) {
7577 if (MG_BIG_ENDIAN) {
7578 } else {
7579 block->l[i] = (rol(block->l[i], 24) & 0xFF00FF00) |
7580 (rol(block->l[i], 8) & 0x00FF00FF);
7581 }
7582 return block->l[i];
7583}
7584 
7585/* Avoid redefine warning (ARM /usr/include/sys/ucontext.h define R0~R4) */
7586#undef blk
7587#undef R0
7588#undef R1
7589#undef R2
7590#undef R3
7591#undef R4
7592 
7593#define blk(i) \
7594 (block->l[i & 15] = rol(block->l[(i + 13) & 15] ^ block->l[(i + 8) & 15] ^ \
7595 block->l[(i + 2) & 15] ^ block->l[i & 15], \
7596 1))
7597#define R0(v, w, x, y, z, i) \
7598 z += ((w & (x ^ y)) ^ y) + blk0(block, i) + 0x5A827999 + rol(v, 5); \
7599 w = rol(w, 30);
7600#define R1(v, w, x, y, z, i) \
7601 z += ((w & (x ^ y)) ^ y) + blk(i) + 0x5A827999 + rol(v, 5); \
7602 w = rol(w, 30);
7603#define R2(v, w, x, y, z, i) \
7604 z += (w ^ x ^ y) + blk(i) + 0x6ED9EBA1 + rol(v, 5); \
7605 w = rol(w, 30);
7606#define R3(v, w, x, y, z, i) \
7607 z += (((w | x) & y) | (w & x)) + blk(i) + 0x8F1BBCDC + rol(v, 5); \
7608 w = rol(w, 30);
7609#define R4(v, w, x, y, z, i) \
7610 z += (w ^ x ^ y) + blk(i) + 0xCA62C1D6 + rol(v, 5); \
7611 w = rol(w, 30);
7612 
7613static void mg_sha1_transform(uint32_t state[5],
7614 const unsigned char *buffer) {
7615 uint32_t a, b, c, d, e;
7616 union char64long16 block[1];
7617 
7618 memcpy(block, buffer, 64);
7619 a = state[0];
7620 b = state[1];
7621 c = state[2];
7622 d = state[3];
7623 e = state[4];
7624 R0(a, b, c, d, e, 0);
7625 R0(e, a, b, c, d, 1);
7626 R0(d, e, a, b, c, 2);
7627 R0(c, d, e, a, b, 3);
7628 R0(b, c, d, e, a, 4);
7629 R0(a, b, c, d, e, 5);
7630 R0(e, a, b, c, d, 6);
7631 R0(d, e, a, b, c, 7);
7632 R0(c, d, e, a, b, 8);
7633 R0(b, c, d, e, a, 9);
7634 R0(a, b, c, d, e, 10);
7635 R0(e, a, b, c, d, 11);
7636 R0(d, e, a, b, c, 12);
7637 R0(c, d, e, a, b, 13);
7638 R0(b, c, d, e, a, 14);
7639 R0(a, b, c, d, e, 15);
7640 R1(e, a, b, c, d, 16);
7641 R1(d, e, a, b, c, 17);
7642 R1(c, d, e, a, b, 18);
7643 R1(b, c, d, e, a, 19);
7644 R2(a, b, c, d, e, 20);
7645 R2(e, a, b, c, d, 21);
7646 R2(d, e, a, b, c, 22);
7647 R2(c, d, e, a, b, 23);
7648 R2(b, c, d, e, a, 24);
7649 R2(a, b, c, d, e, 25);
7650 R2(e, a, b, c, d, 26);
7651 R2(d, e, a, b, c, 27);
7652 R2(c, d, e, a, b, 28);
7653 R2(b, c, d, e, a, 29);
7654 R2(a, b, c, d, e, 30);
7655 R2(e, a, b, c, d, 31);
7656 R2(d, e, a, b, c, 32);
7657 R2(c, d, e, a, b, 33);
7658 R2(b, c, d, e, a, 34);
7659 R2(a, b, c, d, e, 35);
7660 R2(e, a, b, c, d, 36);
7661 R2(d, e, a, b, c, 37);
7662 R2(c, d, e, a, b, 38);
7663 R2(b, c, d, e, a, 39);
7664 R3(a, b, c, d, e, 40);
7665 R3(e, a, b, c, d, 41);
7666 R3(d, e, a, b, c, 42);
7667 R3(c, d, e, a, b, 43);
7668 R3(b, c, d, e, a, 44);
7669 R3(a, b, c, d, e, 45);
7670 R3(e, a, b, c, d, 46);
7671 R3(d, e, a, b, c, 47);
7672 R3(c, d, e, a, b, 48);
7673 R3(b, c, d, e, a, 49);
7674 R3(a, b, c, d, e, 50);
7675 R3(e, a, b, c, d, 51);
7676 R3(d, e, a, b, c, 52);
7677 R3(c, d, e, a, b, 53);
7678 R3(b, c, d, e, a, 54);
7679 R3(a, b, c, d, e, 55);
7680 R3(e, a, b, c, d, 56);
7681 R3(d, e, a, b, c, 57);
7682 R3(c, d, e, a, b, 58);
7683 R3(b, c, d, e, a, 59);
7684 R4(a, b, c, d, e, 60);
7685 R4(e, a, b, c, d, 61);
7686 R4(d, e, a, b, c, 62);
7687 R4(c, d, e, a, b, 63);
7688 R4(b, c, d, e, a, 64);
7689 R4(a, b, c, d, e, 65);
7690 R4(e, a, b, c, d, 66);
7691 R4(d, e, a, b, c, 67);
7692 R4(c, d, e, a, b, 68);
7693 R4(b, c, d, e, a, 69);
7694 R4(a, b, c, d, e, 70);
7695 R4(e, a, b, c, d, 71);
7696 R4(d, e, a, b, c, 72);
7697 R4(c, d, e, a, b, 73);
7698 R4(b, c, d, e, a, 74);
7699 R4(a, b, c, d, e, 75);
7700 R4(e, a, b, c, d, 76);
7701 R4(d, e, a, b, c, 77);
7702 R4(c, d, e, a, b, 78);
7703 R4(b, c, d, e, a, 79);
7704 state[0] += a;
7705 state[1] += b;
7706 state[2] += c;
7707 state[3] += d;
7708 state[4] += e;
7709 /* Erase working structures. The order of operations is important,
7710 * used to ensure that compiler doesn't optimize those out. */
7711 memset(block, 0, sizeof(block));
7712 a = b = c = d = e = 0;
7713 (void) a;
7714 (void) b;
7715 (void) c;
7716 (void) d;
7717 (void) e;
7718}
7719 
7720void mg_sha1_init(mg_sha1_ctx *context) {
7721 context->state[0] = 0x67452301;
7722 context->state[1] = 0xEFCDAB89;
7723 context->state[2] = 0x98BADCFE;
7724 context->state[3] = 0x10325476;
7725 context->state[4] = 0xC3D2E1F0;
7726 context->count[0] = context->count[1] = 0;
7727}
7728 
7729void mg_sha1_update(mg_sha1_ctx *context, const unsigned char *data,
7730 size_t len) {
7731 size_t i, j;
7732 
7733 j = context->count[0];
7734 if ((context->count[0] += (uint32_t) len << 3) < j) context->count[1]++;
7735 context->count[1] += (uint32_t) (len >> 29);
7736 j = (j >> 3) & 63;
7737 if ((j + len) > 63) {
7738 memcpy(&context->buffer[j], data, (i = 64 - j));
7739 mg_sha1_transform(context->state, context->buffer);
7740 for (; i + 63 < len; i += 64) {
7741 mg_sha1_transform(context->state, &data[i]);
7742 }
7743 j = 0;
7744 } else
7745 i = 0;
7746 memcpy(&context->buffer[j], &data[i], len - i);
7747}
7748 
7749void mg_sha1_final(unsigned char digest[20], mg_sha1_ctx *context) {
7750 unsigned i;
7751 unsigned char finalcount[8], c;
7752 
7753 for (i = 0; i < 8; i++) {
7754 finalcount[i] = (unsigned char) ((context->count[(i >= 4 ? 0 : 1)] >>
7755 ((3 - (i & 3)) * 8)) &
7756 255);
7757 }
7758 c = 0200;
7759 mg_sha1_update(context, &c, 1);
7760 while ((context->count[0] & 504) != 448) {
7761 c = 0000;
7762 mg_sha1_update(context, &c, 1);
7763 }
7764 mg_sha1_update(context, finalcount, 8);
7765 for (i = 0; i < 20; i++) {
7766 digest[i] =
7767 (unsigned char) ((context->state[i >> 2] >> ((3 - (i & 3)) * 8)) & 255);
7768 }
7769 memset(context, '\0', sizeof(*context));
7770 memset(&finalcount, '\0', sizeof(finalcount));
7771}
7772 
7773#ifdef MG_ENABLE_LINES
7774#line 1 "src/sha256.c"
7775#endif
7776// https://github.com/B-Con/crypto-algorithms
7777// Author: Brad Conte (brad AT bradconte.com)
7778// Disclaimer: This code is presented "as is" without any guarantees.
7779// Details: Defines the API for the corresponding SHA1 implementation.
7780// Copyright: public domain
7781 
7782 
7783 
7784#define ror(x, n) (((x) >> (n)) | ((x) << (32 - (n))))
7785#define ch(x, y, z) (((x) & (y)) ^ (~(x) & (z)))
7786#define maj(x, y, z) (((x) & (y)) ^ ((x) & (z)) ^ ((y) & (z)))
7787#define ep0(x) (ror(x, 2) ^ ror(x, 13) ^ ror(x, 22))
7788#define ep1(x) (ror(x, 6) ^ ror(x, 11) ^ ror(x, 25))
7789#define sig0(x) (ror(x, 7) ^ ror(x, 18) ^ ((x) >> 3))
7790#define sig1(x) (ror(x, 17) ^ ror(x, 19) ^ ((x) >> 10))
7791 
7792static const uint32_t mg_sha256_k[64] = {
7793 0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5, 0x3956c25b, 0x59f111f1,
7794 0x923f82a4, 0xab1c5ed5, 0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3,
7795 0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174, 0xe49b69c1, 0xefbe4786,
7796 0x0fc19dc6, 0x240ca1cc, 0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da,
7797 0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7, 0xc6e00bf3, 0xd5a79147,
7798 0x06ca6351, 0x14292967, 0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13,
7799 0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85, 0xa2bfe8a1, 0xa81a664b,
7800 0xc24b8b70, 0xc76c51a3, 0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070,
7801 0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5, 0x391c0cb3, 0x4ed8aa4a,
7802 0x5b9cca4f, 0x682e6ff3, 0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208,
7803 0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2};
7804 
7805void mg_sha256_init(mg_sha256_ctx *ctx) {
7806 ctx->len = 0;
7807 ctx->bits = 0;
7808 ctx->state[0] = 0x6a09e667;
7809 ctx->state[1] = 0xbb67ae85;
7810 ctx->state[2] = 0x3c6ef372;
7811 ctx->state[3] = 0xa54ff53a;
7812 ctx->state[4] = 0x510e527f;
7813 ctx->state[5] = 0x9b05688c;
7814 ctx->state[6] = 0x1f83d9ab;
7815 ctx->state[7] = 0x5be0cd19;
7816}
7817 
7818static void mg_sha256_chunk(mg_sha256_ctx *ctx) {
7819 int i, j;
7820 uint32_t a, b, c, d, e, f, g, h;
7821 uint32_t m[64];
7822 for (i = 0, j = 0; i < 16; ++i, j += 4)
7823 m[i] = (uint32_t) (((uint32_t) ctx->buffer[j] << 24) |
7824 ((uint32_t) ctx->buffer[j + 1] << 16) |
7825 ((uint32_t) ctx->buffer[j + 2] << 8) |
7826 ((uint32_t) ctx->buffer[j + 3]));
7827 for (; i < 64; ++i)
7828 m[i] = sig1(m[i - 2]) + m[i - 7] + sig0(m[i - 15]) + m[i - 16];
7829 
7830 a = ctx->state[0];
7831 b = ctx->state[1];
7832 c = ctx->state[2];
7833 d = ctx->state[3];
7834 e = ctx->state[4];
7835 f = ctx->state[5];
7836 g = ctx->state[6];
7837 h = ctx->state[7];
7838 
7839 for (i = 0; i < 64; ++i) {
7840 uint32_t t1 = h + ep1(e) + ch(e, f, g) + mg_sha256_k[i] + m[i];
7841 uint32_t t2 = ep0(a) + maj(a, b, c);
7842 h = g;
7843 g = f;
7844 f = e;
7845 e = d + t1;
7846 d = c;
7847 c = b;
7848 b = a;
7849 a = t1 + t2;
7850 }
7851 
7852 ctx->state[0] += a;
7853 ctx->state[1] += b;
7854 ctx->state[2] += c;
7855 ctx->state[3] += d;
7856 ctx->state[4] += e;
7857 ctx->state[5] += f;
7858 ctx->state[6] += g;
7859 ctx->state[7] += h;
7860}
7861 
7862void mg_sha256_update(mg_sha256_ctx *ctx, const unsigned char *data,
7863 size_t len) {
7864 size_t i;
7865 for (i = 0; i < len; i++) {
7866 ctx->buffer[ctx->len] = data[i];
7867 if ((++ctx->len) == 64) {
7868 mg_sha256_chunk(ctx);
7869 ctx->bits += 512;
7870 ctx->len = 0;
7871 }
7872 }
7873}
7874 
7875// TODO: make final reusable (remove side effects)
7876void mg_sha256_final(unsigned char digest[32], mg_sha256_ctx *ctx) {
7877 uint32_t i = ctx->len;
7878 if (i < 56) {
7879 ctx->buffer[i++] = 0x80;
7880 while (i < 56) {
7881 ctx->buffer[i++] = 0x00;
7882 }
7883 } else {
7884 ctx->buffer[i++] = 0x80;
7885 while (i < 64) {
7886 ctx->buffer[i++] = 0x00;
7887 }
7888 mg_sha256_chunk(ctx);
7889 memset(ctx->buffer, 0, 56);
7890 }
7891 
7892 ctx->bits += ctx->len * 8;
7893 ctx->buffer[63] = (uint8_t) ((ctx->bits) & 0xff);
7894 ctx->buffer[62] = (uint8_t) ((ctx->bits >> 8) & 0xff);
7895 ctx->buffer[61] = (uint8_t) ((ctx->bits >> 16) & 0xff);
7896 ctx->buffer[60] = (uint8_t) ((ctx->bits >> 24) & 0xff);
7897 ctx->buffer[59] = (uint8_t) ((ctx->bits >> 32) & 0xff);
7898 ctx->buffer[58] = (uint8_t) ((ctx->bits >> 40) & 0xff);
7899 ctx->buffer[57] = (uint8_t) ((ctx->bits >> 48) & 0xff);
7900 ctx->buffer[56] = (uint8_t) ((ctx->bits >> 56) & 0xff);
7901 mg_sha256_chunk(ctx);
7902 
7903 for (i = 0; i < 4; ++i) {
7904 digest[i] = (uint8_t) ((ctx->state[0] >> (24 - i * 8)) & 0xff);
7905 digest[i + 4] = (uint8_t) ((ctx->state[1] >> (24 - i * 8)) & 0xff);
7906 digest[i + 8] = (uint8_t) ((ctx->state[2] >> (24 - i * 8)) & 0xff);
7907 digest[i + 12] = (uint8_t) ((ctx->state[3] >> (24 - i * 8)) & 0xff);
7908 digest[i + 16] = (uint8_t) ((ctx->state[4] >> (24 - i * 8)) & 0xff);
7909 digest[i + 20] = (uint8_t) ((ctx->state[5] >> (24 - i * 8)) & 0xff);
7910 digest[i + 24] = (uint8_t) ((ctx->state[6] >> (24 - i * 8)) & 0xff);
7911 digest[i + 28] = (uint8_t) ((ctx->state[7] >> (24 - i * 8)) & 0xff);
7912 }
7913}
7914 
7915void mg_sha256(uint8_t dst[32], uint8_t *data, size_t datasz) {
7916 mg_sha256_ctx ctx;
7917 mg_sha256_init(&ctx);
7918 mg_sha256_update(&ctx, data, datasz);
7919 mg_sha256_final(dst, &ctx);
7920}
7921 
7922void mg_hmac_sha256(uint8_t dst[32], uint8_t *key, size_t keysz, uint8_t *data,
7923 size_t datasz) {
7924 mg_sha256_ctx ctx;
7925 uint8_t k[64] = {0};
7926 uint8_t o_pad[64], i_pad[64];
7927 unsigned int i;
7928 memset(i_pad, 0x36, sizeof(i_pad));
7929 memset(o_pad, 0x5c, sizeof(o_pad));
7930 if (keysz < 64) {
7931 if (keysz > 0) memmove(k, key, keysz);
7932 } else {
7933 mg_sha256_init(&ctx);
7934 mg_sha256_update(&ctx, key, keysz);
7935 mg_sha256_final(k, &ctx);
7936 }
7937 for (i = 0; i < sizeof(k); i++) {
7938 i_pad[i] ^= k[i];
7939 o_pad[i] ^= k[i];
7940 }
7941 mg_sha256_init(&ctx);
7942 mg_sha256_update(&ctx, i_pad, sizeof(i_pad));
7943 mg_sha256_update(&ctx, data, datasz);
7944 mg_sha256_final(dst, &ctx);
7945 mg_sha256_init(&ctx);
7946 mg_sha256_update(&ctx, o_pad, sizeof(o_pad));
7947 mg_sha256_update(&ctx, dst, 32);
7948 mg_sha256_final(dst, &ctx);
7949}
7950 
7951#define rotr64(x, n) (((x) >> (n)) | ((x) << (64 - (n))))
7952#define ep064(x) (rotr64(x, 28) ^ rotr64(x, 34) ^ rotr64(x, 39))
7953#define ep164(x) (rotr64(x, 14) ^ rotr64(x, 18) ^ rotr64(x, 41))
7954#define sig064(x) (rotr64(x, 1) ^ rotr64(x, 8) ^ ((x) >> 7))
7955#define sig164(x) (rotr64(x, 19) ^ rotr64(x, 61) ^ ((x) >> 6))
7956 
7957static const uint64_t mg_sha256_k2[80] = {
7958 0x428a2f98d728ae22, 0x7137449123ef65cd, 0xb5c0fbcfec4d3b2f,
7959 0xe9b5dba58189dbbc, 0x3956c25bf348b538, 0x59f111f1b605d019,
7960 0x923f82a4af194f9b, 0xab1c5ed5da6d8118, 0xd807aa98a3030242,
7961 0x12835b0145706fbe, 0x243185be4ee4b28c, 0x550c7dc3d5ffb4e2,
7962 0x72be5d74f27b896f, 0x80deb1fe3b1696b1, 0x9bdc06a725c71235,
7963 0xc19bf174cf692694, 0xe49b69c19ef14ad2, 0xefbe4786384f25e3,
7964 0x0fc19dc68b8cd5b5, 0x240ca1cc77ac9c65, 0x2de92c6f592b0275,
7965 0x4a7484aa6ea6e483, 0x5cb0a9dcbd41fbd4, 0x76f988da831153b5,
7966 0x983e5152ee66dfab, 0xa831c66d2db43210, 0xb00327c898fb213f,
7967 0xbf597fc7beef0ee4, 0xc6e00bf33da88fc2, 0xd5a79147930aa725,
7968 0x06ca6351e003826f, 0x142929670a0e6e70, 0x27b70a8546d22ffc,
7969 0x2e1b21385c26c926, 0x4d2c6dfc5ac42aed, 0x53380d139d95b3df,
7970 0x650a73548baf63de, 0x766a0abb3c77b2a8, 0x81c2c92e47edaee6,
7971 0x92722c851482353b, 0xa2bfe8a14cf10364, 0xa81a664bbc423001,
7972 0xc24b8b70d0f89791, 0xc76c51a30654be30, 0xd192e819d6ef5218,
7973 0xd69906245565a910, 0xf40e35855771202a, 0x106aa07032bbd1b8,
7974 0x19a4c116b8d2d0c8, 0x1e376c085141ab53, 0x2748774cdf8eeb99,
7975 0x34b0bcb5e19b48a8, 0x391c0cb3c5c95a63, 0x4ed8aa4ae3418acb,
7976 0x5b9cca4f7763e373, 0x682e6ff3d6b2b8a3, 0x748f82ee5defb2fc,
7977 0x78a5636f43172f60, 0x84c87814a1f0ab72, 0x8cc702081a6439ec,
7978 0x90befffa23631e28, 0xa4506cebde82bde9, 0xbef9a3f7b2c67915,
7979 0xc67178f2e372532b, 0xca273eceea26619c, 0xd186b8c721c0c207,
7980 0xeada7dd6cde0eb1e, 0xf57d4f7fee6ed178, 0x06f067aa72176fba,
7981 0x0a637dc5a2c898a6, 0x113f9804bef90dae, 0x1b710b35131c471b,
7982 0x28db77f523047d84, 0x32caab7b40c72493, 0x3c9ebe0a15c9bebc,
7983 0x431d67c49c100d4c, 0x4cc5d4becb3e42b6, 0x597f299cfc657e2a,
7984 0x5fcb6fab3ad6faec, 0x6c44198c4a475817};
7985 
7986static void mg_sha384_transform(mg_sha384_ctx *ctx, const uint8_t data[]) {
7987 uint64_t m[80];
7988 uint64_t a, b, c, d, e, f, g, h;
7989 int i, j;
7990 
7991 for (i = 0, j = 0; i < 16; ++i, j += 8)
7992 m[i] = ((uint64_t) data[j] << 56) | ((uint64_t) data[j + 1] << 48) |
7993 ((uint64_t) data[j + 2] << 40) | ((uint64_t) data[j + 3] << 32) |
7994 ((uint64_t) data[j + 4] << 24) | ((uint64_t) data[j + 5] << 16) |
7995 ((uint64_t) data[j + 6] << 8) | ((uint64_t) data[j + 7]);
7996 for (; i < 80; ++i)
7997 m[i] = sig164(m[i - 2]) + m[i - 7] + sig064(m[i - 15]) + m[i - 16];
7998 
7999 a = ctx->state[0];
8000 b = ctx->state[1];
8001 c = ctx->state[2];
8002 d = ctx->state[3];
8003 e = ctx->state[4];
8004 f = ctx->state[5];
8005 g = ctx->state[6];
8006 h = ctx->state[7];
8007 
8008 for (i = 0; i < 80; ++i) {
8009 uint64_t t1 = h + ep164(e) + ch(e, f, g) + mg_sha256_k2[i] + m[i];
8010 uint64_t t2 = ep064(a) + maj(a, b, c);
8011 h = g;
8012 g = f;
8013 f = e;
8014 e = d + t1;
8015 d = c;
8016 c = b;
8017 b = a;
8018 a = t1 + t2;
8019 }
8020 
8021 ctx->state[0] += a;
8022 ctx->state[1] += b;
8023 ctx->state[2] += c;
8024 ctx->state[3] += d;
8025 ctx->state[4] += e;
8026 ctx->state[5] += f;
8027 ctx->state[6] += g;
8028 ctx->state[7] += h;
8029}
8030 
8031void mg_sha384_init(mg_sha384_ctx *ctx) {
8032 ctx->datalen = 0;
8033 ctx->bitlen[0] = 0;
8034 ctx->bitlen[1] = 0;
8035 ctx->state[0] = 0xcbbb9d5dc1059ed8;
8036 ctx->state[1] = 0x629a292a367cd507;
8037 ctx->state[2] = 0x9159015a3070dd17;
8038 ctx->state[3] = 0x152fecd8f70e5939;
8039 ctx->state[4] = 0x67332667ffc00b31;
8040 ctx->state[5] = 0x8eb44a8768581511;
8041 ctx->state[6] = 0xdb0c2e0d64f98fa7;
8042 ctx->state[7] = 0x47b5481dbefa4fa4;
8043}
8044 
8045void mg_sha384_update(mg_sha384_ctx *ctx, const uint8_t *data, size_t len) {
8046 size_t i;
8047 for (i = 0; i < len; ++i) {
8048 ctx->buffer[ctx->datalen] = data[i];
8049 ctx->datalen++;
8050 if (ctx->datalen == 128) {
8051 mg_sha384_transform(ctx, ctx->buffer);
8052 ctx->bitlen[1] += 1024;
8053 if (ctx->bitlen[1] < 1024) ctx->bitlen[0]++;
8054 ctx->datalen = 0;
8055 }
8056 }
8057}
8058 
8059void mg_sha384_final(uint8_t hash[48], mg_sha384_ctx *ctx) {
8060 size_t i = ctx->datalen;
8061 
8062 if (ctx->datalen < 112) {
8063 ctx->buffer[i++] = 0x80;
8064 while (i < 112) ctx->buffer[i++] = 0x00;
8065 } else {
8066 ctx->buffer[i++] = 0x80;
8067 while (i < 128) ctx->buffer[i++] = 0x00;
8068 mg_sha384_transform(ctx, ctx->buffer);
8069 memset(ctx->buffer, 0, 112);
8070 }
8071 
8072 ctx->bitlen[1] += ctx->datalen * 8;
8073 if (ctx->bitlen[1] < ctx->datalen * 8) ctx->bitlen[0]++;
8074 ctx->buffer[127] = (uint8_t) (ctx->bitlen[1]);
8075 ctx->buffer[126] = (uint8_t) (ctx->bitlen[1] >> 8);
8076 ctx->buffer[125] = (uint8_t) (ctx->bitlen[1] >> 16);
8077 ctx->buffer[124] = (uint8_t) (ctx->bitlen[1] >> 24);
8078 ctx->buffer[123] = (uint8_t) (ctx->bitlen[1] >> 32);
8079 ctx->buffer[122] = (uint8_t) (ctx->bitlen[1] >> 40);
8080 ctx->buffer[121] = (uint8_t) (ctx->bitlen[1] >> 48);
8081 ctx->buffer[120] = (uint8_t) (ctx->bitlen[1] >> 56);
8082 ctx->buffer[119] = (uint8_t) (ctx->bitlen[0]);
8083 ctx->buffer[118] = (uint8_t) (ctx->bitlen[0] >> 8);
8084 ctx->buffer[117] = (uint8_t) (ctx->bitlen[0] >> 16);
8085 ctx->buffer[116] = (uint8_t) (ctx->bitlen[0] >> 24);
8086 ctx->buffer[115] = (uint8_t) (ctx->bitlen[0] >> 32);
8087 ctx->buffer[114] = (uint8_t) (ctx->bitlen[0] >> 40);
8088 ctx->buffer[113] = (uint8_t) (ctx->bitlen[0] >> 48);
8089 ctx->buffer[112] = (uint8_t) (ctx->bitlen[0] >> 56);
8090 mg_sha384_transform(ctx, ctx->buffer);
8091 
8092 for (i = 0; i < 6; ++i) {
8093 hash[i * 8] = (uint8_t) ((ctx->state[i] >> 56) & 0xff);
8094 hash[i * 8 + 1] = (uint8_t) ((ctx->state[i] >> 48) & 0xff);
8095 hash[i * 8 + 2] = (uint8_t) ((ctx->state[i] >> 40) & 0xff);
8096 hash[i * 8 + 3] = (uint8_t) ((ctx->state[i] >> 32) & 0xff);
8097 hash[i * 8 + 4] = (uint8_t) ((ctx->state[i] >> 24) & 0xff);
8098 hash[i * 8 + 5] = (uint8_t) ((ctx->state[i] >> 16) & 0xff);
8099 hash[i * 8 + 6] = (uint8_t) ((ctx->state[i] >> 8) & 0xff);
8100 hash[i * 8 + 7] = (uint8_t) (ctx->state[i] & 0xff);
8101 }
8102}
8103 
8104void mg_sha384(uint8_t dst[48], uint8_t *data, size_t datasz) {
8105 mg_sha384_ctx ctx;
8106 mg_sha384_init(&ctx);
8107 mg_sha384_update(&ctx, data, datasz);
8108 mg_sha384_final(dst, &ctx);
8109}
8110 
8111#ifdef MG_ENABLE_LINES
8112#line 1 "src/sntp.c"
8113#endif
8114 
8115 
8116 
8117 
8118 
8119 
8120#define SNTP_TIME_OFFSET 2208988800U // (1970 - 1900) in seconds
8121#define SNTP_MAX_FRAC 4294967295.0 // 2 ** 32 - 1
8122 
8123static uint64_t s_boot_timestamp = 0; // Updated by SNTP
8124 
8125uint64_t mg_now(void) {
8126 return mg_millis() + s_boot_timestamp;
8127}
8128 
8129static int64_t gettimestamp(const uint32_t *data) {
8130 uint32_t sec = mg_ntohl(data[0]), frac = mg_ntohl(data[1]);
8131 if (sec) sec -= SNTP_TIME_OFFSET;
8132 return ((int64_t) sec) * 1000 + (int64_t) (frac / SNTP_MAX_FRAC * 1000.0);
8133}
8134 
8135int64_t mg_sntp_parse(const unsigned char *buf, size_t len) {
8136 int64_t epoch_milliseconds = -1;
8137 int mode = len > 0 ? buf[0] & 7 : 0;
8138 int version = len > 0 ? (buf[0] >> 3) & 7 : 0;
8139 if (len < 48) {
8140 MG_ERROR(("%s", "corrupt packet"));
8141 } else if (mode != 4 && mode != 5) {
8142 MG_ERROR(("%s", "not a server reply"));
8143 } else if (buf[1] == 0) {
8144 MG_ERROR(("%s", "server sent a kiss of death"));
8145 } else if (version == 4 || version == 3) {
8146 // int64_t ref = gettimestamp((uint32_t *) &buf[16]);
8147 int64_t origin_time = gettimestamp((uint32_t *) &buf[24]);
8148 int64_t receive_time = gettimestamp((uint32_t *) &buf[32]);
8149 int64_t transmit_time = gettimestamp((uint32_t *) &buf[40]);
8150 int64_t now = (int64_t) mg_millis();
8151 int64_t latency = (now - origin_time) - (transmit_time - receive_time);
8152 epoch_milliseconds = transmit_time + latency / 2;
8153 s_boot_timestamp = (uint64_t) (epoch_milliseconds - now);
8154 } else {
8155 MG_ERROR(("unexpected version: %d", version));
8156 }
8157 return epoch_milliseconds;
8158}
8159 
8160static void sntp_cb(struct mg_connection *c, int ev, void *ev_data) {
8161 uint64_t *expiration_time = (uint64_t *) c->data;
8162 if (ev == MG_EV_OPEN) {
8163 *expiration_time = mg_millis() + 3000; // Store expiration time in 3s
8164 } else if (ev == MG_EV_CONNECT) {
8165 mg_sntp_request(c);
8166 } else if (ev == MG_EV_READ) {
8167 int64_t milliseconds = mg_sntp_parse(c->recv.buf, c->recv.len);
8168 if (milliseconds > 0) {
8169 s_boot_timestamp = (uint64_t) milliseconds - mg_millis();
8170 mg_call(c, MG_EV_SNTP_TIME, (uint64_t *) &milliseconds);
8171 MG_DEBUG(("%lu got time: %lld ms from epoch", c->id, milliseconds));
8172 }
8173 // mg_iobuf_del(&c->recv, 0, c->recv.len); // Free receive buffer
8174 c->is_closing = 1;
8175 } else if (ev == MG_EV_POLL) {
8176 if (mg_millis() > *expiration_time) c->is_closing = 1;
8177 } else if (ev == MG_EV_CLOSE) {
8178 }
8179 (void) ev_data;
8180}
8181 
8182void mg_sntp_request(struct mg_connection *c) {
8183 if (c->is_resolving) {
8184 MG_ERROR(("%lu wait until resolved", c->id));
8185 } else {
8186 int64_t now = (int64_t) mg_millis(); // Use int64_t, for vc98
8187 uint8_t buf[48] = {0};
8188 uint32_t *t = (uint32_t *) &buf[40];
8189 double frac = ((double) (now % 1000)) / 1000.0 * SNTP_MAX_FRAC;
8190 buf[0] = (0 << 6) | (4 << 3) | 3;
8191 t[0] = mg_htonl((uint32_t) (now / 1000) + SNTP_TIME_OFFSET);
8192 t[1] = mg_htonl((uint32_t) frac);
8193 mg_send(c, buf, sizeof(buf));
8194 }
8195}
8196 
8197struct mg_connection *mg_sntp_connect(struct mg_mgr *mgr, const char *url,
8198 mg_event_handler_t fn, void *fnd) {
8199 struct mg_connection *c = NULL;
8200 if (url == NULL) url = "udp://time.google.com:123";
8201 if ((c = mg_connect(mgr, url, fn, fnd)) != NULL) {
8202 c->pfn = sntp_cb;
8203 sntp_cb(c, MG_EV_OPEN, (void *) url);
8204 }
8205 return c;
8206}
8207 
8208#ifdef MG_ENABLE_LINES
8209#line 1 "src/sock.c"
8210#endif
8211 
8212 
8213 
8214 
8215 
8216 
8217 
8218 
8219 
8220 
8221 
8222#if MG_ENABLE_SOCKET
8223 
8224#ifndef closesocket
8225#define closesocket(x) close(x)
8226#endif
8227 
8228#define FD(c_) ((MG_SOCKET_TYPE) (size_t) (c_)->fd)
8229#define S2PTR(s_) ((void *) (size_t) (s_))
8230 
8231#ifndef MSG_NONBLOCKING
8232#define MSG_NONBLOCKING 0
8233#endif
8234 
8235#ifndef AF_INET6
8236#define AF_INET6 10
8237#endif
8238 
8239#ifndef MG_SOCK_ERR
8240#define MG_SOCK_ERR(errcode) ((errcode) < 0 ? errno : 0)
8241#endif
8242 
8243#ifndef MG_SOCK_INTR
8244#define MG_SOCK_INTR(fd) (fd == MG_INVALID_SOCKET && MG_SOCK_ERR(-1) == EINTR)
8245#endif
8246 
8247#ifndef MG_SOCK_PENDING
8248#define MG_SOCK_PENDING(errcode) \
8249 (((errcode) < 0) && (errno == EINPROGRESS || errno == EWOULDBLOCK))
8250#endif
8251 
8252#ifndef MG_SOCK_RESET
8253#define MG_SOCK_RESET(errcode) \
8254 (((errcode) < 0) && (errno == EPIPE || errno == ECONNRESET))
8255#endif
8256 
8257union usa {
8258 struct sockaddr sa;
8259 struct sockaddr_in sin;
8260#if MG_ENABLE_IPV6
8261 struct sockaddr_in6 sin6;
8262#endif
8263};
8264 
8265static socklen_t tousa(struct mg_addr *a, union usa *usa) {
8266 socklen_t len = sizeof(usa->sin);
8267 memset(usa, 0, sizeof(*usa));
8268 usa->sin.sin_family = AF_INET;
8269 usa->sin.sin_port = a->port;
8270 memcpy(&usa->sin.sin_addr, a->ip, sizeof(uint32_t));
8271#if MG_ENABLE_IPV6
8272 if (a->is_ip6) {
8273 usa->sin.sin_family = AF_INET6;
8274 usa->sin6.sin6_port = a->port;
8275 usa->sin6.sin6_scope_id = a->scope_id;
8276 memcpy(&usa->sin6.sin6_addr, a->ip, sizeof(a->ip));
8277 len = sizeof(usa->sin6);
8278 }
8279#endif
8280 return len;
8281}
8282 
8283static void tomgaddr(union usa *usa, struct mg_addr *a, bool is_ip6) {
8284 a->is_ip6 = is_ip6;
8285 a->port = usa->sin.sin_port;
8286 memcpy(&a->ip, &usa->sin.sin_addr, sizeof(uint32_t));
8287#if MG_ENABLE_IPV6
8288 if (is_ip6) {
8289 memcpy(a->ip, &usa->sin6.sin6_addr, sizeof(a->ip));
8290 a->port = usa->sin6.sin6_port;
8291 a->scope_id = (uint8_t) usa->sin6.sin6_scope_id;
8292 }
8293#endif
8294}
8295 
8296static void setlocaddr(MG_SOCKET_TYPE fd, struct mg_addr *addr) {
8297 union usa usa;
8298 socklen_t n = sizeof(usa);
8299 if (getsockname(fd, &usa.sa, &n) == 0) {
8300 tomgaddr(&usa, addr, n != sizeof(usa.sin));
8301 }
8302}
8303 
8304static void iolog(struct mg_connection *c, char *buf, long n, bool r) {
8305 if (n == MG_IO_WAIT) {
8306 // Do nothing
8307 } else if (n <= 0) {
8308 c->is_closing = 1; // Termination. Don't call mg_error(): #1529
8309 } else if (n > 0) {
8310 if (c->is_hexdumping) {
8311 MG_INFO(("\n-- %lu %M %s %M %ld", c->id, mg_print_ip_port, &c->loc,
8312 r ? "<-" : "->", mg_print_ip_port, &c->rem, n));
8313 mg_hexdump(buf, (size_t) n);
8314 }
8315 if (r) {
8316 c->recv.len += (size_t) n;
8317 mg_call(c, MG_EV_READ, &n);
8318 } else {
8319 mg_iobuf_del(&c->send, 0, (size_t) n);
8320 // if (c->send.len == 0) mg_iobuf_resize(&c->send, 0);
8321 if (c->send.len == 0) {
8322 MG_EPOLL_MOD(c, 0);
8323 }
8324 mg_call(c, MG_EV_WRITE, &n);
8325 }
8326 }
8327}
8328 
8329long mg_io_send(struct mg_connection *c, const void *buf, size_t len) {
8330 long n;
8331 if (c->is_udp) {
8332 union usa usa;
8333 socklen_t slen = tousa(&c->rem, &usa);
8334 n = sendto(FD(c), (char *) buf, len, 0, &usa.sa, slen);
8335 if (n > 0) setlocaddr(FD(c), &c->loc);
8336 } else {
8337 n = send(FD(c), (char *) buf, len, MSG_NONBLOCKING);
8338 }
8339 MG_VERBOSE(("%lu %ld %d", c->id, n, MG_SOCK_ERR(n)));
8340 if (MG_SOCK_PENDING(n)) return MG_IO_WAIT;
8341 if (MG_SOCK_RESET(n)) return MG_IO_RESET; // MbedTLS, see #1507
8342 if (n <= 0) return MG_IO_ERR;
8343 return n;
8344}
8345 
8346bool mg_send(struct mg_connection *c, const void *buf, size_t len) {
8347 if (c->is_udp) {
8348 long n = mg_io_send(c, buf, len);
8349 MG_DEBUG(("%lu %ld %lu:%lu:%lu %ld err %d", c->id, c->fd, c->send.len,
8350 c->recv.len, c->rtls.len, n, MG_SOCK_ERR(n)));
8351 iolog(c, (char *) buf, n, false);
8352 return n > 0;
8353 } else {
8354 return mg_iobuf_add(&c->send, c->send.len, buf, len);
8355 }
8356}
8357 
8358static void mg_set_non_blocking_mode(MG_SOCKET_TYPE fd) {
8359#if defined(MG_CUSTOM_NONBLOCK)
8360 MG_CUSTOM_NONBLOCK(fd);
8361#elif MG_ARCH == MG_ARCH_WIN32 && MG_ENABLE_WINSOCK
8362 unsigned long on = 1;
8363 ioctlsocket(fd, FIONBIO, &on);
8364#elif MG_ENABLE_RL
8365 unsigned long on = 1;
8366 ioctlsocket(fd, FIONBIO, &on);
8367#elif MG_ENABLE_FREERTOS_TCP
8368 const BaseType_t off = 0;
8369 if (setsockopt(fd, 0, FREERTOS_SO_RCVTIMEO, &off, sizeof(off)) != 0) (void) 0;
8370 if (setsockopt(fd, 0, FREERTOS_SO_SNDTIMEO, &off, sizeof(off)) != 0) (void) 0;
8371#elif MG_ENABLE_LWIP
8372 lwip_fcntl(fd, F_SETFL, O_NONBLOCK);
8373#elif MG_ARCH == MG_ARCH_AZURERTOS
8374 fcntl(fd, F_SETFL, O_NONBLOCK);
8375#elif MG_ARCH == MG_ARCH_TIRTOS
8376 int val = 0;
8377 setsockopt(fd, SOL_SOCKET, SO_BLOCKING, &val, sizeof(val));
8378 // SPRU524J section 3.3.3 page 63, SO_SNDLOWAT
8379 int sz = sizeof(val);
8380 getsockopt(fd, SOL_SOCKET, SO_SNDBUF, &val, &sz);
8381 val /= 2; // set send low-water mark at half send buffer size
8382 setsockopt(fd, SOL_SOCKET, SO_SNDLOWAT, &val, sizeof(val));
8383#else
8384 fcntl(fd, F_SETFL, fcntl(fd, F_GETFL, 0) | O_NONBLOCK); // Non-blocking mode
8385 fcntl(fd, F_SETFD, FD_CLOEXEC); // Set close-on-exec
8386#endif
8387}
8388 
8389void mg_multicast_add(struct mg_connection *c, char *ip);
8390void mg_multicast_add(struct mg_connection *c, char *ip) {
8391#if MG_ENABLE_RL
8392#error UNSUPPORTED
8393#elif MG_ENABLE_FREERTOS_TCP
8394 // TODO(): prvAllowIPPacketIPv4()
8395#else
8396 // lwIP, Unix, Windows, Zephyr(, AzureRTOS ?)
8397 struct ip_mreq mreq;
8398 mreq.imr_multiaddr.s_addr = inet_addr(ip);
8399 mreq.imr_interface.s_addr = mg_htonl(INADDR_ANY);
8400 setsockopt(FD(c), IPPROTO_IP, IP_ADD_MEMBERSHIP, (char *) &mreq, sizeof(mreq));
8401#endif
8402}
8403 
8404bool mg_open_listener(struct mg_connection *c, const char *url) {
8405 MG_SOCKET_TYPE fd = MG_INVALID_SOCKET;
8406 bool success = false;
8407 c->loc.port = mg_htons(mg_url_port(url));
8408 if (!mg_aton(mg_url_host(url), &c->loc)) {
8409 MG_ERROR(("invalid listening URL: %s", url));
8410 } else {
8411 union usa usa;
8412 socklen_t slen = tousa(&c->loc, &usa);
8413 int rc, on = 1, af = c->loc.is_ip6 ? AF_INET6 : AF_INET;
8414 int type = strncmp(url, "udp:", 4) == 0 ? SOCK_DGRAM : SOCK_STREAM;
8415 int proto = type == SOCK_DGRAM ? IPPROTO_UDP : IPPROTO_TCP;
8416 (void) on;
8417 
8418 if ((fd = socket(af, type, proto)) == MG_INVALID_SOCKET) {
8419 MG_ERROR(("socket: %d", MG_SOCK_ERR(-1)));
8420#if defined(SO_EXCLUSIVEADDRUSE)
8421 } else if ((rc = setsockopt(fd, SOL_SOCKET, SO_EXCLUSIVEADDRUSE,
8422 (char *) &on, sizeof(on))) != 0) {
8423 // "Using SO_REUSEADDR and SO_EXCLUSIVEADDRUSE"
8424 MG_ERROR(("setsockopt(SO_EXCLUSIVEADDRUSE): %d %d", on, MG_SOCK_ERR(rc)));
8425#elif defined(SO_REUSEADDR) && (!defined(LWIP_SOCKET) || SO_REUSE)
8426 } else if ((rc = setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (char *) &on,
8427 sizeof(on))) != 0) {
8428 // 1. SO_REUSEADDR semantics on UNIX and Windows is different. On
8429 // Windows, SO_REUSEADDR allows to bind a socket to a port without error
8430 // even if the port is already open by another program. This is not the
8431 // behavior SO_REUSEADDR was designed for, and leads to hard-to-track
8432 // failure scenarios.
8433 //
8434 // 2. For LWIP, SO_REUSEADDR should be explicitly enabled by defining
8435 // SO_REUSE = 1 in lwipopts.h, otherwise the code below will compile but
8436 // won't work! (setsockopt will return EINVAL)
8437 MG_ERROR(("setsockopt(SO_REUSEADDR): %d", MG_SOCK_ERR(rc)));
8438#endif
8439#if MG_IPV6_V6ONLY
8440 // Bind only to the V6 address, not V4 address on this port
8441 } else if (c->loc.is_ip6 &&
8442 (rc = setsockopt(fd, IPPROTO_IPV6, IPV6_V6ONLY, (char *) &on,
8443 sizeof(on))) != 0) {
8444 // See #2089. Allow to bind v4 and v6 sockets on the same port
8445 MG_ERROR(("setsockopt(IPV6_V6ONLY): %d", MG_SOCK_ERR(rc)));
8446#endif
8447 } else if ((rc = bind(fd, &usa.sa, slen)) != 0) {
8448 MG_ERROR(("bind: %d", MG_SOCK_ERR(rc)));
8449 } else if ((type == SOCK_STREAM &&
8450 (rc = listen(fd, MG_SOCK_LISTEN_BACKLOG_SIZE)) != 0)) {
8451 // NOTE(lsm): FreeRTOS uses backlog value as a connection limit
8452 // In case port was set to 0, get the real port number
8453 MG_ERROR(("listen: %d", MG_SOCK_ERR(rc)));
8454 } else {
8455 setlocaddr(fd, &c->loc);
8456 mg_set_non_blocking_mode(fd);
8457 c->fd = S2PTR(fd);
8458 MG_EPOLL_ADD(c);
8459 success = true;
8460 }
8461 }
8462 if (success == false && fd != MG_INVALID_SOCKET) closesocket(fd);
8463 return success;
8464}
8465 
8466static long recv_raw(struct mg_connection *c, void *buf, size_t len) {
8467 long n = 0;
8468 if (c->is_udp) {
8469 union usa usa;
8470 socklen_t slen = tousa(&c->rem, &usa);
8471 n = recvfrom(FD(c), (char *) buf, len, 0, &usa.sa, &slen);
8472 if (n > 0) tomgaddr(&usa, &c->rem, slen != sizeof(usa.sin));
8473 } else {
8474 n = recv(FD(c), (char *) buf, len, MSG_NONBLOCKING);
8475 }
8476 MG_VERBOSE(("%lu %ld %d", c->id, n, MG_SOCK_ERR(n)));
8477 if (MG_SOCK_PENDING(n)) return MG_IO_WAIT;
8478 if (MG_SOCK_RESET(n)) return MG_IO_RESET; // MbedTLS, see #1507
8479 if (n <= 0) return MG_IO_ERR;
8480 return n;
8481}
8482 
8483static bool ioalloc(struct mg_connection *c, struct mg_iobuf *io) {
8484 bool res = false;
8485 if (io->len >= MG_MAX_RECV_SIZE) {
8486 mg_error(c, "MG_MAX_RECV_SIZE");
8487 } else if (io->size <= io->len &&
8488 !mg_iobuf_resize(io, io->size + MG_IO_SIZE)) {
8489 mg_error(c, "OOM");
8490 } else {
8491 res = true;
8492 }
8493 return res;
8494}
8495 
8496// NOTE(lsm): do only one iteration of reads, cause some systems
8497// (e.g. FreeRTOS stack) return 0 instead of -1/EWOULDBLOCK when no data
8498static void read_conn(struct mg_connection *c) {
8499 if (ioalloc(c, &c->recv)) {
8500 char *buf = (char *) &c->recv.buf[c->recv.len];
8501 size_t len = c->recv.size - c->recv.len;
8502 long n = -1;
8503 if (c->is_tls) {
8504 // Do not read to the raw TLS buffer if it already has enough.
8505 // This is to prevent overflowing c->rtls if our reads are slow
8506 long m;
8507 if (c->rtls.len < 16 * 1024 + 40) { // TLS record, header, MAC, padding
8508 if (!ioalloc(c, &c->rtls)) return;
8509 n = recv_raw(c, (char *) &c->rtls.buf[c->rtls.len],
8510 c->rtls.size - c->rtls.len);
8511 if (n > 0) c->rtls.len += (size_t) n;
8512 }
8513 // there can still be > 16K from last iteration, always mg_tls_recv()
8514 m = c->is_tls_hs ? (long) MG_IO_WAIT : mg_tls_recv(c, buf, len);
8515 if (n == MG_IO_ERR || n == MG_IO_RESET) { // Windows, see #3031
8516 if (c->rtls.len == 0 || m < 0) {
8517 // Close only when we have fully drained both rtls and TLS buffers
8518 c->is_closing = 1; // or there's nothing we can do about it.
8519 if (m < 0) m = MG_IO_ERR; // but return last record data, see #3104
8520 } else { // see #2885
8521 // TLS buffer is capped to max record size, even though, there can
8522 // be more than one record, give TLS a chance to process them.
8523 }
8524 } else if (c->is_tls_hs) {
8525 mg_tls_handshake(c);
8526 }
8527 n = m;
8528 } else {
8529 n = recv_raw(c, buf, len);
8530 }
8531 MG_DEBUG(("%lu %ld %lu:%lu:%lu %ld err %d", c->id, c->fd, c->send.len,
8532 c->recv.len, c->rtls.len, n, MG_SOCK_ERR(n)));
8533 iolog(c, buf, n, true);
8534 }
8535}
8536 
8537static void write_conn(struct mg_connection *c) {
8538 char *buf = (char *) c->send.buf;
8539 size_t len = c->send.len;
8540 long n = c->is_tls ? mg_tls_send(c, buf, len) : mg_io_send(c, buf, len);
8541 MG_DEBUG(("%lu %ld snd %ld/%ld rcv %ld/%ld n=%ld err=%d", c->id, c->fd,
8542 (long) c->send.len, (long) c->send.size, (long) c->recv.len,
8543 (long) c->recv.size, n, MG_SOCK_ERR(n)));
8544 iolog(c, buf, n, false);
8545}
8546 
8547static void close_conn(struct mg_connection *c) {
8548 if (FD(c) != MG_INVALID_SOCKET) {
8549#if MG_ENABLE_EPOLL
8550 epoll_ctl(c->mgr->epoll_fd, EPOLL_CTL_DEL, FD(c), NULL);
8551#endif
8552 closesocket(FD(c));
8553#if MG_ENABLE_FREERTOS_TCP
8554 FreeRTOS_FD_CLR(c->fd, c->mgr->ss, eSELECT_ALL);
8555#endif
8556 }
8557 mg_close_conn(c);
8558}
8559 
8560static void connect_conn(struct mg_connection *c) {
8561 union usa usa;
8562 socklen_t n = sizeof(usa);
8563 // Use getpeername() to test whether we have connected
8564 if (getpeername(FD(c), &usa.sa, &n) == 0) {
8565 c->is_connecting = 0;
8566 setlocaddr(FD(c), &c->loc);
8567 mg_call(c, MG_EV_CONNECT, NULL);
8568 MG_EPOLL_MOD(c, 0);
8569 if (c->is_tls_hs) mg_tls_handshake(c);
8570 } else {
8571 mg_error(c, "socket error");
8572 }
8573}
8574 
8575static void setsockopts(struct mg_connection *c) {
8576#if MG_ENABLE_FREERTOS_TCP || MG_ARCH == MG_ARCH_AZURERTOS || \
8577 MG_ARCH == MG_ARCH_TIRTOS
8578 (void) c;
8579#else
8580 int on = 1;
8581#if !defined(SOL_TCP)
8582#define SOL_TCP IPPROTO_TCP
8583#endif
8584 if (setsockopt(FD(c), SOL_TCP, TCP_NODELAY, (char *) &on, sizeof(on)) != 0)
8585 (void) 0;
8586 if (setsockopt(FD(c), SOL_SOCKET, SO_KEEPALIVE, (char *) &on, sizeof(on)) !=
8587 0)
8588 (void) 0;
8589#endif
8590}
8591 
8592void mg_connect_resolved(struct mg_connection *c) {
8593 int type = c->is_udp ? SOCK_DGRAM : SOCK_STREAM;
8594 int proto = type == SOCK_DGRAM ? IPPROTO_UDP : IPPROTO_TCP;
8595 int rc, af = c->rem.is_ip6 ? AF_INET6 : AF_INET; // c->rem has resolved IP
8596 c->fd = S2PTR(socket(af, type, proto)); // Create outbound socket
8597 c->is_resolving = 0; // Clear resolving flag
8598 if (FD(c) == MG_INVALID_SOCKET) {
8599 mg_error(c, "socket(): %d", MG_SOCK_ERR(-1));
8600 } else if (c->is_udp) {
8601 MG_EPOLL_ADD(c);
8602#if MG_ARCH == MG_ARCH_TIRTOS
8603 union usa usa; // TI-RTOS NDK requires binding to receive on UDP sockets
8604 socklen_t slen = tousa(&c->loc, &usa);
8605 if ((rc = bind(c->fd, &usa.sa, slen)) != 0)
8606 MG_ERROR(("bind: %d", MG_SOCK_ERR(rc)));
8607#endif
8608 setlocaddr(FD(c), &c->loc);
8609 mg_call(c, MG_EV_RESOLVE, NULL);
8610 mg_call(c, MG_EV_CONNECT, NULL);
8611 } else {
8612 union usa usa;
8613 socklen_t slen = tousa(&c->rem, &usa);
8614 mg_set_non_blocking_mode(FD(c));
8615 setsockopts(c);
8616 MG_EPOLL_ADD(c);
8617 mg_call(c, MG_EV_RESOLVE, NULL);
8618 rc = connect(FD(c), &usa.sa, slen); // Attempt to connect
8619 if (rc == 0) { // Success
8620 setlocaddr(FD(c), &c->loc);
8621 mg_call(c, MG_EV_CONNECT, NULL); // Send MG_EV_CONNECT to the user
8622 } else if (MG_SOCK_PENDING(rc)) { // Need to wait for TCP handshake
8623 MG_DEBUG(("%lu %ld -> %M pend", c->id, c->fd, mg_print_ip_port, &c->rem));
8624 c->is_connecting = 1;
8625 } else {
8626 mg_error(c, "connect: %d", MG_SOCK_ERR(rc));
8627 }
8628 }
8629}
8630 
8631static MG_SOCKET_TYPE raccept(MG_SOCKET_TYPE sock, union usa *usa,
8632 socklen_t *len) {
8633 MG_SOCKET_TYPE fd = MG_INVALID_SOCKET;
8634 do {
8635 memset(usa, 0, sizeof(*usa));
8636 fd = accept(sock, &usa->sa, len);
8637 } while (MG_SOCK_INTR(fd));
8638 return fd;
8639}
8640 
8641static void accept_conn(struct mg_mgr *mgr, struct mg_connection *lsn) {
8642 struct mg_connection *c = NULL;
8643 union usa usa;
8644 socklen_t sa_len = sizeof(usa);
8645 MG_SOCKET_TYPE fd = raccept(FD(lsn), &usa, &sa_len);
8646 if (fd == MG_INVALID_SOCKET) {
8647#if MG_ARCH == MG_ARCH_AZURERTOS || defined(__ECOS)
8648 // AzureRTOS, in non-block socket mode can mark listening socket readable
8649 // even it is not. See comment for 'select' func implementation in
8650 // nx_bsd.c That's not an error, just should try later
8651 if (errno != EAGAIN)
8652#endif
8653 MG_ERROR(("%lu accept failed, errno %d", lsn->id, MG_SOCK_ERR(-1)));
8654#if (MG_ARCH != MG_ARCH_WIN32) && !MG_ENABLE_FREERTOS_TCP && \
8655 (MG_ARCH != MG_ARCH_TIRTOS) && !MG_ENABLE_POLL && !MG_ENABLE_EPOLL
8656 } else if ((long) fd >= FD_SETSIZE) {
8657 MG_ERROR(("%ld > %ld", (long) fd, (long) FD_SETSIZE));
8658 closesocket(fd);
8659#endif
8660 } else if ((c = mg_alloc_conn(mgr)) == NULL) {
8661 MG_ERROR(("%lu OOM", lsn->id));
8662 closesocket(fd);
8663 } else {
8664 tomgaddr(&usa, &c->rem, sa_len != sizeof(usa.sin));
8665 LIST_ADD_HEAD(struct mg_connection, &mgr->conns, c);
8666 c->fd = S2PTR(fd);
8667 MG_EPOLL_ADD(c);
8668 mg_set_non_blocking_mode(FD(c));
8669 setsockopts(c);
8670 c->is_accepted = 1;
8671 c->is_hexdumping = lsn->is_hexdumping;
8672 c->loc = lsn->loc;
8673 c->pfn = lsn->pfn;
8674 c->pfn_data = lsn->pfn_data;
8675 c->fn = lsn->fn;
8676 c->fn_data = lsn->fn_data;
8677 MG_DEBUG(("%lu %ld accepted %M -> %M", c->id, c->fd, mg_print_ip_port,
8678 &c->rem, mg_print_ip_port, &c->loc));
8679 mg_call(c, MG_EV_OPEN, NULL);
8680 mg_call(c, MG_EV_ACCEPT, NULL);
8681 }
8682}
8683 
8684static bool can_read(const struct mg_connection *c) {
8685 return c->is_full == false;
8686}
8687 
8688static bool can_write(const struct mg_connection *c) {
8689 return c->is_connecting || (c->send.len > 0 && c->is_tls_hs == 0);
8690}
8691 
8692static bool skip_iotest(const struct mg_connection *c) {
8693 return (c->is_closing || c->is_resolving || FD(c) == MG_INVALID_SOCKET) ||
8694 (can_read(c) == false && can_write(c) == false);
8695}
8696 
8697static void mg_iotest(struct mg_mgr *mgr, int ms) {
8698#if MG_ENABLE_FREERTOS_TCP
8699 struct mg_connection *c;
8700 for (c = mgr->conns; c != NULL; c = c->next) {
8701 c->is_readable = c->is_writable = 0;
8702 if (skip_iotest(c)) continue;
8703 if (can_read(c))
8704 FreeRTOS_FD_SET(c->fd, mgr->ss, eSELECT_READ | eSELECT_EXCEPT);
8705 if (can_write(c)) FreeRTOS_FD_SET(c->fd, mgr->ss, eSELECT_WRITE);
8706 if (c->is_closing) ms = 1;
8707 }
8708 FreeRTOS_select(mgr->ss, pdMS_TO_TICKS(ms));
8709 for (c = mgr->conns; c != NULL; c = c->next) {
8710 EventBits_t bits = FreeRTOS_FD_ISSET(c->fd, mgr->ss);
8711 c->is_readable = bits & (eSELECT_READ | eSELECT_EXCEPT) ? 1U : 0;
8712 c->is_writable = bits & eSELECT_WRITE ? 1U : 0;
8713 if (c->fd != MG_INVALID_SOCKET)
8714 FreeRTOS_FD_CLR(c->fd, mgr->ss,
8715 eSELECT_READ | eSELECT_EXCEPT | eSELECT_WRITE);
8716 }
8717#elif MG_ENABLE_EPOLL
8718 size_t max = 1;
8719 for (struct mg_connection *c = mgr->conns; c != NULL; c = c->next) {
8720 c->is_readable = c->is_writable = 0;
8721 if (c->rtls.len > 0 || mg_tls_pending(c) > 0) ms = 1, c->is_readable = 1;
8722 if (can_write(c)) MG_EPOLL_MOD(c, 1);
8723 if (c->is_closing) ms = 1;
8724 max++;
8725 }
8726 struct epoll_event *evs = (struct epoll_event *) alloca(max * sizeof(evs[0]));
8727 int n = epoll_wait(mgr->epoll_fd, evs, (int) max, ms);
8728 for (int i = 0; i < n; i++) {
8729 struct mg_connection *c = (struct mg_connection *) evs[i].data.ptr;
8730 if (evs[i].events & EPOLLERR) {
8731 mg_error(c, "socket error");
8732 } else if (c->is_readable == 0) {
8733 bool rd = evs[i].events & (EPOLLIN | EPOLLHUP);
8734 bool wr = evs[i].events & EPOLLOUT;
8735 c->is_readable = can_read(c) && rd ? 1U : 0;
8736 c->is_writable = can_write(c) && wr ? 1U : 0;
8737 if (c->rtls.len > 0 || mg_tls_pending(c) > 0) c->is_readable = 1;
8738 }
8739 }
8740 (void) skip_iotest;
8741#elif MG_ENABLE_POLL
8742 nfds_t n = 0;
8743 for (struct mg_connection *c = mgr->conns; c != NULL; c = c->next) n++;
8744 struct pollfd *fds = (struct pollfd *) alloca(n * sizeof(fds[0]));
8745 memset(fds, 0, n * sizeof(fds[0]));
8746 n = 0;
8747 for (struct mg_connection *c = mgr->conns; c != NULL; c = c->next) {
8748 c->is_readable = c->is_writable = 0;
8749 if (c->is_closing) ms = 1;
8750 if (skip_iotest(c)) {
8751 // Socket not valid, ignore
8752 } else {
8753 // Don't wait if TLS is ready
8754 if (c->rtls.len > 0 || mg_tls_pending(c) > 0) ms = 1;
8755 fds[n].fd = FD(c);
8756 if (can_read(c)) fds[n].events |= POLLIN;
8757 if (can_write(c)) fds[n].events |= POLLOUT;
8758 n++;
8759 }
8760 }
8761 
8762 // MG_INFO(("poll n=%d ms=%d", (int) n, ms));
8763 if (poll(fds, n, ms) < 0) {
8764#if MG_ARCH == MG_ARCH_WIN32
8765 if (n == 0) Sleep(ms); // On Windows, poll fails if no sockets
8766#endif
8767 memset(fds, 0, n * sizeof(fds[0]));
8768 }
8769 n = 0;
8770 for (struct mg_connection *c = mgr->conns; c != NULL; c = c->next) {
8771 if (skip_iotest(c)) {
8772 // Socket not valid, ignore
8773 } else {
8774 if (fds[n].revents & POLLERR) {
8775 mg_error(c, "socket error");
8776 } else {
8777 c->is_readable =
8778 (unsigned) (fds[n].revents & (POLLIN | POLLHUP) ? 1 : 0);
8779 c->is_writable = (unsigned) (fds[n].revents & POLLOUT ? 1 : 0);
8780 if (c->rtls.len > 0 || mg_tls_pending(c) > 0) c->is_readable = 1;
8781 }
8782 n++;
8783 }
8784 }
8785#else
8786 struct timeval tv = {ms / 1000, (ms % 1000) * 1000}, tv_zero = {0, 0}, *tvp;
8787 struct mg_connection *c;
8788 fd_set rset, wset, eset;
8789 MG_SOCKET_TYPE maxfd = 0;
8790 int rc;
8791 
8792 FD_ZERO(&rset);
8793 FD_ZERO(&wset);
8794 FD_ZERO(&eset);
8795 tvp = ms < 0 ? NULL : &tv;
8796 for (c = mgr->conns; c != NULL; c = c->next) {
8797 c->is_readable = c->is_writable = 0;
8798 if (skip_iotest(c)) continue;
8799 FD_SET(FD(c), &eset);
8800 if (can_read(c)) FD_SET(FD(c), &rset);
8801 if (can_write(c)) FD_SET(FD(c), &wset);
8802 if (c->rtls.len > 0 || mg_tls_pending(c) > 0) tvp = &tv_zero;
8803 if (FD(c) > maxfd) maxfd = FD(c);
8804 if (c->is_closing) tvp = &tv_zero;
8805 }
8806 
8807 if ((rc = select((int) maxfd + 1, &rset, &wset, &eset, tvp)) < 0) {
8808#if MG_ARCH == MG_ARCH_WIN32
8809 if (maxfd == 0) Sleep(ms); // On Windows, select fails if no sockets
8810#else
8811 MG_ERROR(("select: %d %d", rc, MG_SOCK_ERR(rc)));
8812#endif
8813 FD_ZERO(&rset);
8814 FD_ZERO(&wset);
8815 FD_ZERO(&eset);
8816 }
8817 
8818 for (c = mgr->conns; c != NULL; c = c->next) {
8819 if (FD(c) != MG_INVALID_SOCKET && FD_ISSET(FD(c), &eset)) {
8820 mg_error(c, "socket error");
8821 } else {
8822 c->is_readable = FD(c) != MG_INVALID_SOCKET && FD_ISSET(FD(c), &rset);
8823 c->is_writable = FD(c) != MG_INVALID_SOCKET && FD_ISSET(FD(c), &wset);
8824 if (c->rtls.len > 0 || mg_tls_pending(c) > 0) c->is_readable = 1;
8825 }
8826 }
8827#endif
8828}
8829 
8830static bool mg_socketpair(MG_SOCKET_TYPE sp[2], union usa usa[2]) {
8831 socklen_t n = sizeof(usa[0].sin);
8832 bool success = false;
8833 
8834 sp[0] = sp[1] = MG_INVALID_SOCKET;
8835 (void) memset(&usa[0], 0, sizeof(usa[0]));
8836 usa[0].sin.sin_family = AF_INET;
8837 *(uint32_t *) &usa->sin.sin_addr = mg_htonl(0x7f000001U); // 127.0.0.1
8838 usa[1] = usa[0];
8839 
8840 if ((sp[0] = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) != MG_INVALID_SOCKET &&
8841 (sp[1] = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) != MG_INVALID_SOCKET &&
8842 bind(sp[0], &usa[0].sa, n) == 0 && //
8843 bind(sp[1], &usa[1].sa, n) == 0 && //
8844 getsockname(sp[0], &usa[0].sa, &n) == 0 && //
8845 getsockname(sp[1], &usa[1].sa, &n) == 0 && //
8846 connect(sp[0], &usa[1].sa, n) == 0 && //
8847 connect(sp[1], &usa[0].sa, n) == 0) { //
8848 success = true;
8849 }
8850 if (!success) {
8851 if (sp[0] != MG_INVALID_SOCKET) closesocket(sp[0]);
8852 if (sp[1] != MG_INVALID_SOCKET) closesocket(sp[1]);
8853 sp[0] = sp[1] = MG_INVALID_SOCKET;
8854 }
8855 return success;
8856}
8857 
8858// mg_wakeup() event handler
8859static void wufn(struct mg_connection *c, int ev, void *ev_data) {
8860 if (ev == MG_EV_READ) {
8861 unsigned long *id = (unsigned long *) c->recv.buf;
8862 // MG_INFO(("Got data"));
8863 // mg_hexdump(c->recv.buf, c->recv.len);
8864 if (c->recv.len >= sizeof(*id)) {
8865 struct mg_connection *t;
8866 for (t = c->mgr->conns; t != NULL; t = t->next) {
8867 if (t->id == *id) {
8868 struct mg_str data = mg_str_n((char *) c->recv.buf + sizeof(*id),
8869 c->recv.len - sizeof(*id));
8870 mg_call(t, MG_EV_WAKEUP, &data);
8871 }
8872 }
8873 }
8874 c->recv.len = 0; // Consume received data
8875 } else if (ev == MG_EV_CLOSE) {
8876 closesocket(c->mgr->pipe); // When we're closing, close the other
8877 c->mgr->pipe = MG_INVALID_SOCKET; // side of the socketpair, too
8878 }
8879 (void) ev_data;
8880}
8881 
8882bool mg_wakeup_init(struct mg_mgr *mgr) {
8883 bool ok = false;
8884 if (mgr->pipe == MG_INVALID_SOCKET) {
8885 union usa usa[2];
8886 MG_SOCKET_TYPE sp[2] = {MG_INVALID_SOCKET, MG_INVALID_SOCKET};
8887 struct mg_connection *c = NULL;
8888 if (!mg_socketpair(sp, usa)) {
8889 MG_ERROR(("Cannot create socket pair"));
8890 } else if ((c = mg_wrapfd(mgr, (int) sp[1], wufn, NULL)) == NULL) {
8891 closesocket(sp[0]);
8892 closesocket(sp[1]);
8893 sp[0] = sp[1] = MG_INVALID_SOCKET;
8894 } else {
8895 tomgaddr(&usa[0], &c->rem, false);
8896 MG_DEBUG(("%lu %p pipe %lu", c->id, c->fd, (unsigned long) sp[0]));
8897 mgr->pipe = sp[0];
8898 ok = true;
8899 }
8900 }
8901 return ok;
8902}
8903 
8904bool mg_wakeup(struct mg_mgr *mgr, unsigned long conn_id, const void *buf,
8905 size_t len) {
8906 if (mgr->pipe != MG_INVALID_SOCKET && conn_id > 0) {
8907 char *extended_buf = (char *) alloca(len + sizeof(conn_id));
8908 memcpy(extended_buf, &conn_id, sizeof(conn_id));
8909 memcpy(extended_buf + sizeof(conn_id), buf, len);
8910 send(mgr->pipe, extended_buf, len + sizeof(conn_id), MSG_NONBLOCKING);
8911 return true;
8912 }
8913 return false;
8914}
8915 
8916void mg_mgr_poll(struct mg_mgr *mgr, int ms) {
8917 struct mg_connection *c, *tmp;
8918 uint64_t now;
8919 
8920 mg_iotest(mgr, ms);
8921 now = mg_millis();
8922 mg_timer_poll(&mgr->timers, now);
8923 
8924 for (c = mgr->conns; c != NULL; c = tmp) {
8925 bool is_resp = c->is_resp;
8926 tmp = c->next;
8927 mg_call(c, MG_EV_POLL, &now);
8928 if (is_resp && !c->is_resp) {
8929 long n = 0;
8930 mg_call(c, MG_EV_READ, &n);
8931 }
8932 MG_VERBOSE(("%lu %c%c %c%c%c%c%c %lu %lu", c->id,
8933 c->is_readable ? 'r' : '-', c->is_writable ? 'w' : '-',
8934 c->is_tls ? 'T' : 't', c->is_connecting ? 'C' : 'c',
8935 c->is_tls_hs ? 'H' : 'h', c->is_resolving ? 'R' : 'r',
8936 c->is_closing ? 'C' : 'c', mg_tls_pending(c), c->rtls.len));
8937 if (c->is_resolving || c->is_closing) {
8938 // Do nothing
8939 } else if (c->is_listening && c->is_udp == 0) {
8940 if (c->is_readable) accept_conn(mgr, c);
8941 } else if (c->is_connecting) {
8942 if (c->is_readable || c->is_writable) connect_conn(c);
8943 //} else if (c->is_tls_hs) {
8944 // if ((c->is_readable || c->is_writable)) mg_tls_handshake(c);
8945 } else {
8946 if (c->is_readable) read_conn(c);
8947 if (c->is_writable) write_conn(c);
8948 }
8949 
8950 if (c->is_draining && c->send.len == 0) c->is_closing = 1;
8951 if (c->is_closing) close_conn(c);
8952 }
8953}
8954#endif
8955 
8956#ifdef MG_ENABLE_LINES
8957#line 1 "src/ssi.c"
8958#endif
8959 
8960 
8961 
8962 
8963#ifndef MG_MAX_SSI_DEPTH
8964#define MG_MAX_SSI_DEPTH 5
8965#endif
8966 
8967#ifndef MG_SSI_BUFSIZ
8968#define MG_SSI_BUFSIZ 1024
8969#endif
8970 
8971#if MG_ENABLE_SSI
8972static char *mg_ssi(const char *path, const char *root, int depth) {
8973 struct mg_iobuf b = {NULL, 0, 0, MG_IO_SIZE};
8974 FILE *fp = fopen(path, "rb");
8975 if (fp != NULL) {
8976 char buf[MG_SSI_BUFSIZ], arg[sizeof(buf)];
8977 int ch, intag = 0;
8978 size_t len = 0;
8979 buf[0] = arg[0] = '\0';
8980 while ((ch = fgetc(fp)) != EOF) {
8981 if (intag && ch == '>' && buf[len - 1] == '-' && buf[len - 2] == '-') {
8982 buf[len++] = (char) (ch & 0xff);
8983 buf[len] = '\0';
8984 if (sscanf(buf, "<!--#include file=\"%[^\"]", arg) > 0) {
8985 char tmp[MG_PATH_MAX + MG_SSI_BUFSIZ + 10],
8986 *p = (char *) path + strlen(path), *data;
8987 while (p > path && p[-1] != MG_DIRSEP && p[-1] != '/') p--;
8988 mg_snprintf(tmp, sizeof(tmp), "%.*s%s", (int) (p - path), path, arg);
8989 if (depth < MG_MAX_SSI_DEPTH &&
8990 (data = mg_ssi(tmp, root, depth + 1)) != NULL) {
8991 mg_iobuf_add(&b, b.len, data, strlen(data));
8992 free(data);
8993 } else {
8994 MG_ERROR(("%s: file=%s error or too deep", path, arg));
8995 }
8996 } else if (sscanf(buf, "<!--#include virtual=\"%[^\"]", arg) > 0) {
8997 char tmp[MG_PATH_MAX + MG_SSI_BUFSIZ + 10], *data;
8998 mg_snprintf(tmp, sizeof(tmp), "%s%s", root, arg);
8999 if (depth < MG_MAX_SSI_DEPTH &&
9000 (data = mg_ssi(tmp, root, depth + 1)) != NULL) {
9001 mg_iobuf_add(&b, b.len, data, strlen(data));
9002 free(data);
9003 } else {
9004 MG_ERROR(("%s: virtual=%s error or too deep", path, arg));
9005 }
9006 } else {
9007 // Unknown SSI tag
9008 MG_ERROR(("Unknown SSI tag: %.*s", (int) len, buf));
9009 mg_iobuf_add(&b, b.len, buf, len);
9010 }
9011 intag = 0;
9012 len = 0;
9013 } else if (ch == '<') {
9014 intag = 1;
9015 if (len > 0) mg_iobuf_add(&b, b.len, buf, len);
9016 len = 0;
9017 buf[len++] = (char) (ch & 0xff);
9018 } else if (intag) {
9019 if (len == 5 && strncmp(buf, "<!--#", 5) != 0) {
9020 intag = 0;
9021 } else if (len >= sizeof(buf) - 2) {
9022 MG_ERROR(("%s: SSI tag is too large", path));
9023 len = 0;
9024 }
9025 buf[len++] = (char) (ch & 0xff);
9026 } else {
9027 buf[len++] = (char) (ch & 0xff);
9028 if (len >= sizeof(buf)) {
9029 mg_iobuf_add(&b, b.len, buf, len);
9030 len = 0;
9031 }
9032 }
9033 }
9034 if (len > 0) mg_iobuf_add(&b, b.len, buf, len);
9035 if (b.len > 0) mg_iobuf_add(&b, b.len, "", 1); // nul-terminate
9036 fclose(fp);
9037 }
9038 (void) depth;
9039 (void) root;
9040 return (char *) b.buf;
9041}
9042 
9043void mg_http_serve_ssi(struct mg_connection *c, const char *root,
9044 const char *fullpath) {
9045 const char *headers = "Content-Type: text/html; charset=utf-8\r\n";
9046 char *data = mg_ssi(fullpath, root, 0);
9047 mg_http_reply(c, 200, headers, "%s", data == NULL ? "" : data);
9048 free(data);
9049}
9050#else
9051void mg_http_serve_ssi(struct mg_connection *c, const char *root,
9052 const char *fullpath) {
9053 mg_http_reply(c, 501, NULL, "SSI not enabled");
9054 (void) root, (void) fullpath;
9055}
9056#endif
9057 
9058#ifdef MG_ENABLE_LINES
9059#line 1 "src/str.c"
9060#endif
9061 
9062 
9063struct mg_str mg_str_s(const char *s) {
9064 struct mg_str str = {(char *) s, s == NULL ? 0 : strlen(s)};
9065 return str;
9066}
9067 
9068struct mg_str mg_str_n(const char *s, size_t n) {
9069 struct mg_str str = {(char *) s, n};
9070 return str;
9071}
9072 
9073static int mg_tolc(char c) {
9074 return (c >= 'A' && c <= 'Z') ? c + 'a' - 'A' : c;
9075}
9076 
9077int mg_casecmp(const char *s1, const char *s2) {
9078 int diff = 0;
9079 do {
9080 int c = mg_tolc(*s1++), d = mg_tolc(*s2++);
9081 diff = c - d;
9082 } while (diff == 0 && s1[-1] != '\0');
9083 return diff;
9084}
9085 
9086struct mg_str mg_strdup(const struct mg_str s) {
9087 struct mg_str r = {NULL, 0};
9088 if (s.len > 0 && s.buf != NULL) {
9089 char *sc = (char *) calloc(1, s.len + 1);
9090 if (sc != NULL) {
9091 memcpy(sc, s.buf, s.len);
9092 sc[s.len] = '\0';
9093 r.buf = sc;
9094 r.len = s.len;
9095 }
9096 }
9097 return r;
9098}
9099 
9100int mg_strcmp(const struct mg_str str1, const struct mg_str str2) {
9101 size_t i = 0;
9102 while (i < str1.len && i < str2.len) {
9103 int c1 = str1.buf[i];
9104 int c2 = str2.buf[i];
9105 if (c1 < c2) return -1;
9106 if (c1 > c2) return 1;
9107 i++;
9108 }
9109 if (i < str1.len) return 1;
9110 if (i < str2.len) return -1;
9111 return 0;
9112}
9113 
9114int mg_strcasecmp(const struct mg_str str1, const struct mg_str str2) {
9115 size_t i = 0;
9116 while (i < str1.len && i < str2.len) {
9117 int c1 = mg_tolc(str1.buf[i]);
9118 int c2 = mg_tolc(str2.buf[i]);
9119 if (c1 < c2) return -1;
9120 if (c1 > c2) return 1;
9121 i++;
9122 }
9123 if (i < str1.len) return 1;
9124 if (i < str2.len) return -1;
9125 return 0;
9126}
9127 
9128bool mg_match(struct mg_str s, struct mg_str p, struct mg_str *caps) {
9129 size_t i = 0, j = 0, ni = 0, nj = 0;
9130 if (caps) caps->buf = NULL, caps->len = 0;
9131 while (i < p.len || j < s.len) {
9132 if (i < p.len && j < s.len &&
9133 (p.buf[i] == '?' ||
9134 (p.buf[i] != '*' && p.buf[i] != '#' && s.buf[j] == p.buf[i]))) {
9135 if (caps == NULL) {
9136 } else if (p.buf[i] == '?') {
9137 caps->buf = &s.buf[j], caps->len = 1; // Finalize `?` cap
9138 caps++, caps->buf = NULL, caps->len = 0; // Init next cap
9139 } else if (caps->buf != NULL && caps->len == 0) {
9140 caps->len = (size_t) (&s.buf[j] - caps->buf); // Finalize current cap
9141 caps++, caps->len = 0, caps->buf = NULL; // Init next cap
9142 }
9143 i++, j++;
9144 } else if (i < p.len && (p.buf[i] == '*' || p.buf[i] == '#')) {
9145 if (caps && !caps->buf) caps->len = 0, caps->buf = &s.buf[j]; // Init cap
9146 ni = i++, nj = j + 1;
9147 } else if (nj > 0 && nj <= s.len && (p.buf[ni] == '#' || s.buf[j] != '/')) {
9148 i = ni, j = nj;
9149 if (caps && caps->buf == NULL && caps->len == 0) {
9150 caps--, caps->len = 0; // Restart previous cap
9151 }
9152 } else {
9153 return false;
9154 }
9155 }
9156 if (caps && caps->buf && caps->len == 0) {
9157 caps->len = (size_t) (&s.buf[j] - caps->buf);
9158 }
9159 return true;
9160}
9161 
9162bool mg_span(struct mg_str s, struct mg_str *a, struct mg_str *b, char sep) {
9163 if (s.len == 0 || s.buf == NULL) {
9164 return false; // Empty string, nothing to span - fail
9165 } else {
9166 size_t len = 0;
9167 while (len < s.len && s.buf[len] != sep) len++; // Find separator
9168 if (a) *a = mg_str_n(s.buf, len); // Init a
9169 if (b) *b = mg_str_n(s.buf + len, s.len - len); // Init b
9170 if (b && len < s.len) b->buf++, b->len--; // Skip separator
9171 return true;
9172 }
9173}
9174 
9175bool mg_str_to_num(struct mg_str str, int base, void *val, size_t val_len) {
9176 size_t i = 0, ndigits = 0;
9177 uint64_t max = val_len == sizeof(uint8_t) ? 0xFF
9178 : val_len == sizeof(uint16_t) ? 0xFFFF
9179 : val_len == sizeof(uint32_t) ? 0xFFFFFFFF
9180 : (uint64_t) ~0;
9181 uint64_t result = 0;
9182 if (max == (uint64_t) ~0 && val_len != sizeof(uint64_t)) return false;
9183 if (base == 0 && str.len >= 2) {
9184 if (str.buf[i] == '0') {
9185 i++;
9186 base = str.buf[i] == 'b' ? 2 : str.buf[i] == 'x' ? 16 : 10;
9187 if (base != 10) ++i;
9188 } else {
9189 base = 10;
9190 }
9191 }
9192 switch (base) {
9193 case 2:
9194 while (i < str.len && (str.buf[i] == '0' || str.buf[i] == '1')) {
9195 uint64_t digit = (uint64_t) (str.buf[i] - '0');
9196 if (result > max / 2) return false; // Overflow
9197 result *= 2;
9198 if (result > max - digit) return false; // Overflow
9199 result += digit;
9200 i++, ndigits++;
9201 }
9202 break;
9203 case 10:
9204 while (i < str.len && str.buf[i] >= '0' && str.buf[i] <= '9') {
9205 uint64_t digit = (uint64_t) (str.buf[i] - '0');
9206 if (result > max / 10) return false; // Overflow
9207 result *= 10;
9208 if (result > max - digit) return false; // Overflow
9209 result += digit;
9210 i++, ndigits++;
9211 }
9212 break;
9213 case 16:
9214 while (i < str.len) {
9215 char c = str.buf[i];
9216 uint64_t digit = (c >= '0' && c <= '9') ? (uint64_t) (c - '0')
9217 : (c >= 'A' && c <= 'F') ? (uint64_t) (c - '7')
9218 : (c >= 'a' && c <= 'f') ? (uint64_t) (c - 'W')
9219 : (uint64_t) ~0;
9220 if (digit == (uint64_t) ~0) break;
9221 if (result > max / 16) return false; // Overflow
9222 result *= 16;
9223 if (result > max - digit) return false; // Overflow
9224 result += digit;
9225 i++, ndigits++;
9226 }
9227 break;
9228 default:
9229 return false;
9230 }
9231 if (ndigits == 0) return false;
9232 if (i != str.len) return false;
9233 if (val_len == 1) {
9234 *((uint8_t *) val) = (uint8_t) result;
9235 } else if (val_len == 2) {
9236 *((uint16_t *) val) = (uint16_t) result;
9237 } else if (val_len == 4) {
9238 *((uint32_t *) val) = (uint32_t) result;
9239 } else {
9240 *((uint64_t *) val) = (uint64_t) result;
9241 }
9242 return true;
9243}
9244 
9245#ifdef MG_ENABLE_LINES
9246#line 1 "src/timer.c"
9247#endif
9248 
9249 
9250 
9251void mg_timer_init(struct mg_timer **head, struct mg_timer *t, uint64_t ms,
9252 unsigned flags, void (*fn)(void *), void *arg) {
9253 t->period_ms = ms, t->expire = 0;
9254 t->flags = flags, t->fn = fn, t->arg = arg, t->next = *head;
9255 *head = t;
9256}
9257 
9258void mg_timer_free(struct mg_timer **head, struct mg_timer *t) {
9259 while (*head && *head != t) head = &(*head)->next;
9260 if (*head) *head = t->next;
9261}
9262 
9263// t: expiration time, prd: period, now: current time. Return true if expired
9264bool mg_timer_expired(uint64_t *t, uint64_t prd, uint64_t now) {
9265 if (now + prd < *t) *t = 0; // Time wrapped? Reset timer
9266 if (*t == 0) *t = now + prd; // Firt poll? Set expiration
9267 if (*t > now) return false; // Not expired yet, return
9268 *t = (now - *t) > prd ? now + prd : *t + prd; // Next expiration time
9269 return true; // Expired, return true
9270}
9271 
9272void mg_timer_poll(struct mg_timer **head, uint64_t now_ms) {
9273 struct mg_timer *t, *tmp;
9274 for (t = *head; t != NULL; t = tmp) {
9275 bool once = t->expire == 0 && (t->flags & MG_TIMER_RUN_NOW) &&
9276 !(t->flags & MG_TIMER_CALLED); // Handle MG_TIMER_NOW only once
9277 bool expired = mg_timer_expired(&t->expire, t->period_ms, now_ms);
9278 tmp = t->next;
9279 if (!once && !expired) continue;
9280 if ((t->flags & MG_TIMER_REPEAT) || !(t->flags & MG_TIMER_CALLED)) {
9281 t->fn(t->arg);
9282 }
9283 t->flags |= MG_TIMER_CALLED;
9284 
9285 // If this timer is not repeating and marked AUTODELETE, remove it
9286 if (!(t->flags & MG_TIMER_REPEAT) && (t->flags & MG_TIMER_AUTODELETE)) {
9287 mg_timer_free(head, t);
9288 free(t);
9289 }
9290 }
9291}
9292 
9293#ifdef MG_ENABLE_LINES
9294#line 1 "src/tls_aes128.c"
9295#endif
9296/******************************************************************************
9297 *
9298 * THIS SOURCE CODE IS HEREBY PLACED INTO THE PUBLIC DOMAIN FOR THE GOOD OF ALL
9299 *
9300 * This is a simple and straightforward implementation of the AES Rijndael
9301 * 128-bit block cipher designed by Vincent Rijmen and Joan Daemen. The focus
9302 * of this work was correctness & accuracy. It is written in 'C' without any
9303 * particular focus upon optimization or speed. It should be endian (memory
9304 * byte order) neutral since the few places that care are handled explicitly.
9305 *
9306 * This implementation of Rijndael was created by Steven M. Gibson of GRC.com.
9307 *
9308 * It is intended for general purpose use, but was written in support of GRC's
9309 * reference implementation of the SQRL (Secure Quick Reliable Login) client.
9310 *
9311 * See: http://csrc.nist.gov/archive/aes/rijndael/wsdindex.html
9312 *
9313 * NO COPYRIGHT IS CLAIMED IN THIS WORK, HOWEVER, NEITHER IS ANY WARRANTY MADE
9314 * REGARDING ITS FITNESS FOR ANY PARTICULAR PURPOSE. USE IT AT YOUR OWN RISK.
9315 *
9316 *******************************************************************************/
9317 
9318/******************************************************************************/
9319#define AES_DECRYPTION 1 // whether AES decryption is supported
9320/******************************************************************************/
9321 
9322#define MG_ENCRYPT 1 // specify whether we're encrypting
9323#define MG_DECRYPT 0 // or decrypting
9324 
9325 
9326 
9327 
9328 
9329#if MG_TLS == MG_TLS_BUILTIN
9330/******************************************************************************
9331 * AES_INIT_KEYGEN_TABLES : MUST be called once before any AES use
9332 ******************************************************************************/
9333static void aes_init_keygen_tables(void);
9334 
9335/******************************************************************************
9336 * AES_SETKEY : called to expand the key for encryption or decryption
9337 ******************************************************************************/
9338static int aes_setkey(aes_context *ctx, // pointer to context
9339 int mode, // 1 or 0 for Encrypt/Decrypt
9340 const unsigned char *key, // AES input key
9341 unsigned int keysize); // size in bytes (must be 16, 24, 32 for
9342 // 128, 192 or 256-bit keys respectively)
9343 // returns 0 for success
9344 
9345/******************************************************************************
9346 * AES_CIPHER : called to encrypt or decrypt ONE 128-bit block of data
9347 ******************************************************************************/
9348static int aes_cipher(aes_context *ctx, // pointer to context
9349 const unsigned char input[16], // 128-bit block to en/decipher
9350 unsigned char output[16]); // 128-bit output result block
9351 // returns 0 for success
9352 
9353/******************************************************************************
9354 * GCM_CONTEXT : GCM context / holds keytables, instance data, and AES ctx
9355 ******************************************************************************/
9356typedef struct {
9357 int mode; // cipher direction: encrypt/decrypt
9358 uint64_t len; // cipher data length processed so far
9359 uint64_t add_len; // total add data length
9360 uint64_t HL[16]; // precalculated lo-half HTable
9361 uint64_t HH[16]; // precalculated hi-half HTable
9362 unsigned char base_ectr[16]; // first counter-mode cipher output for tag
9363 unsigned char y[16]; // the current cipher-input IV|Counter value
9364 unsigned char buf[16]; // buf working value
9365 aes_context aes_ctx; // cipher context used
9366} gcm_context;
9367 
9368/******************************************************************************
9369 * GCM_SETKEY : sets the GCM (and AES) keying material for use
9370 ******************************************************************************/
9371static int gcm_setkey(
9372 gcm_context *ctx, // caller-provided context ptr
9373 const unsigned char *key, // pointer to cipher key
9374 const unsigned int keysize // size in bytes (must be 16, 24, 32 for
9375 // 128, 192 or 256-bit keys respectively)
9376); // returns 0 for success
9377 
9378/******************************************************************************
9379 *
9380 * GCM_CRYPT_AND_TAG
9381 *
9382 * This either encrypts or decrypts the user-provided data and, either
9383 * way, generates an authentication tag of the requested length. It must be
9384 * called with a GCM context whose key has already been set with GCM_SETKEY.
9385 *
9386 * The user would typically call this explicitly to ENCRYPT a buffer of data
9387 * and optional associated data, and produce its an authentication tag.
9388 *
9389 * To reverse the process the user would typically call the companion
9390 * GCM_AUTH_DECRYPT function to decrypt data and verify a user-provided
9391 * authentication tag. The GCM_AUTH_DECRYPT function calls this function
9392 * to perform its decryption and tag generation, which it then compares.
9393 *
9394 ******************************************************************************/
9395static int gcm_crypt_and_tag(
9396 gcm_context *ctx, // gcm context with key already setup
9397 int mode, // cipher direction: MG_ENCRYPT (1) or MG_DECRYPT (0)
9398 const unsigned char *iv, // pointer to the 12-byte initialization vector
9399 size_t iv_len, // byte length if the IV. should always be 12
9400 const unsigned char *add, // pointer to the non-ciphered additional data
9401 size_t add_len, // byte length of the additional AEAD data
9402 const unsigned char *input, // pointer to the cipher data source
9403 unsigned char *output, // pointer to the cipher data destination
9404 size_t length, // byte length of the cipher data
9405 unsigned char *tag, // pointer to the tag to be generated
9406 size_t tag_len); // byte length of the tag to be generated
9407 
9408/******************************************************************************
9409 *
9410 * GCM_START
9411 *
9412 * Given a user-provided GCM context, this initializes it, sets the encryption
9413 * mode, and preprocesses the initialization vector and additional AEAD data.
9414 *
9415 ******************************************************************************/
9416static int gcm_start(
9417 gcm_context *ctx, // pointer to user-provided GCM context
9418 int mode, // MG_ENCRYPT (1) or MG_DECRYPT (0)
9419 const unsigned char *iv, // pointer to initialization vector
9420 size_t iv_len, // IV length in bytes (should == 12)
9421 const unsigned char *add, // pointer to additional AEAD data (NULL if none)
9422 size_t add_len); // length of additional AEAD data (bytes)
9423 
9424/******************************************************************************
9425 *
9426 * GCM_UPDATE
9427 *
9428 * This is called once or more to process bulk plaintext or ciphertext data.
9429 * We give this some number of bytes of input and it returns the same number
9430 * of output bytes. If called multiple times (which is fine) all but the final
9431 * invocation MUST be called with length mod 16 == 0. (Only the final call can
9432 * have a partial block length of < 128 bits.)
9433 *
9434 ******************************************************************************/
9435static int gcm_update(gcm_context *ctx, // pointer to user-provided GCM context
9436 size_t length, // length, in bytes, of data to process
9437 const unsigned char *input, // pointer to source data
9438 unsigned char *output); // pointer to destination data
9439 
9440/******************************************************************************
9441 *
9442 * GCM_FINISH
9443 *
9444 * This is called once after all calls to GCM_UPDATE to finalize the GCM.
9445 * It performs the final GHASH to produce the resulting authentication TAG.
9446 *
9447 ******************************************************************************/
9448static int gcm_finish(
9449 gcm_context *ctx, // pointer to user-provided GCM context
9450 unsigned char *tag, // ptr to tag buffer - NULL if tag_len = 0
9451 size_t tag_len); // length, in bytes, of the tag-receiving buf
9452 
9453/******************************************************************************
9454 *
9455 * GCM_ZERO_CTX
9456 *
9457 * The GCM context contains both the GCM context and the AES context.
9458 * This includes keying and key-related material which is security-
9459 * sensitive, so it MUST be zeroed after use. This function does that.
9460 *
9461 ******************************************************************************/
9462static void gcm_zero_ctx(gcm_context *ctx);
9463 
9464/******************************************************************************
9465 *
9466 * THIS SOURCE CODE IS HEREBY PLACED INTO THE PUBLIC DOMAIN FOR THE GOOD OF ALL
9467 *
9468 * This is a simple and straightforward implementation of the AES Rijndael
9469 * 128-bit block cipher designed by Vincent Rijmen and Joan Daemen. The focus
9470 * of this work was correctness & accuracy. It is written in 'C' without any
9471 * particular focus upon optimization or speed. It should be endian (memory
9472 * byte order) neutral since the few places that care are handled explicitly.
9473 *
9474 * This implementation of Rijndael was created by Steven M. Gibson of GRC.com.
9475 *
9476 * It is intended for general purpose use, but was written in support of GRC's
9477 * reference implementation of the SQRL (Secure Quick Reliable Login) client.
9478 *
9479 * See: http://csrc.nist.gov/archive/aes/rijndael/wsdindex.html
9480 *
9481 * NO COPYRIGHT IS CLAIMED IN THIS WORK, HOWEVER, NEITHER IS ANY WARRANTY MADE
9482 * REGARDING ITS FITNESS FOR ANY PARTICULAR PURPOSE. USE IT AT YOUR OWN RISK.
9483 *
9484 *******************************************************************************/
9485 
9486static int aes_tables_inited = 0; // run-once flag for performing key
9487 // expasion table generation (see below)
9488/*
9489 * The following static local tables must be filled-in before the first use of
9490 * the GCM or AES ciphers. They are used for the AES key expansion/scheduling
9491 * and once built are read-only and thread safe. The "gcm_initialize" function
9492 * must be called once during system initialization to populate these arrays
9493 * for subsequent use by the AES key scheduler. If they have not been built
9494 * before attempted use, an error will be returned to the caller.
9495 *
9496 * NOTE: GCM Encryption/Decryption does NOT REQUIRE AES decryption. Since
9497 * GCM uses AES in counter-mode, where the AES cipher output is XORed with
9498 * the GCM input, we ONLY NEED AES encryption. Thus, to save space AES
9499 * decryption is typically disabled by setting AES_DECRYPTION to 0 in aes.h.
9500 */
9501// We always need our forward tables
9502static unsigned char FSb[256]; // Forward substitution box (FSb)
9503static uint32_t FT0[256]; // Forward key schedule assembly tables
9504static uint32_t FT1[256];
9505static uint32_t FT2[256];
9506static uint32_t FT3[256];
9507 
9508#if AES_DECRYPTION // We ONLY need reverse for decryption
9509static unsigned char RSb[256]; // Reverse substitution box (RSb)
9510static uint32_t RT0[256]; // Reverse key schedule assembly tables
9511static uint32_t RT1[256];
9512static uint32_t RT2[256];
9513static uint32_t RT3[256];
9514#endif /* AES_DECRYPTION */
9515 
9516static uint32_t RCON[10]; // AES round constants
9517 
9518/*
9519 * Platform Endianness Neutralizing Load and Store Macro definitions
9520 * AES wants platform-neutral Little Endian (LE) byte ordering
9521 */
9522#define GET_UINT32_LE(n, b, i) \
9523 { \
9524 (n) = ((uint32_t) (b)[(i)]) | ((uint32_t) (b)[(i) + 1] << 8) | \
9525 ((uint32_t) (b)[(i) + 2] << 16) | ((uint32_t) (b)[(i) + 3] << 24); \
9526 }
9527 
9528#define PUT_UINT32_LE(n, b, i) \
9529 { \
9530 (b)[(i)] = (unsigned char) ((n)); \
9531 (b)[(i) + 1] = (unsigned char) ((n) >> 8); \
9532 (b)[(i) + 2] = (unsigned char) ((n) >> 16); \
9533 (b)[(i) + 3] = (unsigned char) ((n) >> 24); \
9534 }
9535 
9536/*
9537 * AES forward and reverse encryption round processing macros
9538 */
9539#define AES_FROUND(X0, X1, X2, X3, Y0, Y1, Y2, Y3) \
9540 { \
9541 X0 = *RK++ ^ FT0[(Y0) & 0xFF] ^ FT1[(Y1 >> 8) & 0xFF] ^ \
9542 FT2[(Y2 >> 16) & 0xFF] ^ FT3[(Y3 >> 24) & 0xFF]; \
9543 \
9544 X1 = *RK++ ^ FT0[(Y1) & 0xFF] ^ FT1[(Y2 >> 8) & 0xFF] ^ \
9545 FT2[(Y3 >> 16) & 0xFF] ^ FT3[(Y0 >> 24) & 0xFF]; \
9546 \
9547 X2 = *RK++ ^ FT0[(Y2) & 0xFF] ^ FT1[(Y3 >> 8) & 0xFF] ^ \
9548 FT2[(Y0 >> 16) & 0xFF] ^ FT3[(Y1 >> 24) & 0xFF]; \
9549 \
9550 X3 = *RK++ ^ FT0[(Y3) & 0xFF] ^ FT1[(Y0 >> 8) & 0xFF] ^ \
9551 FT2[(Y1 >> 16) & 0xFF] ^ FT3[(Y2 >> 24) & 0xFF]; \
9552 }
9553 
9554#define AES_RROUND(X0, X1, X2, X3, Y0, Y1, Y2, Y3) \
9555 { \
9556 X0 = *RK++ ^ RT0[(Y0) & 0xFF] ^ RT1[(Y3 >> 8) & 0xFF] ^ \
9557 RT2[(Y2 >> 16) & 0xFF] ^ RT3[(Y1 >> 24) & 0xFF]; \
9558 \
9559 X1 = *RK++ ^ RT0[(Y1) & 0xFF] ^ RT1[(Y0 >> 8) & 0xFF] ^ \
9560 RT2[(Y3 >> 16) & 0xFF] ^ RT3[(Y2 >> 24) & 0xFF]; \
9561 \
9562 X2 = *RK++ ^ RT0[(Y2) & 0xFF] ^ RT1[(Y1 >> 8) & 0xFF] ^ \
9563 RT2[(Y0 >> 16) & 0xFF] ^ RT3[(Y3 >> 24) & 0xFF]; \
9564 \
9565 X3 = *RK++ ^ RT0[(Y3) & 0xFF] ^ RT1[(Y2 >> 8) & 0xFF] ^ \
9566 RT2[(Y1 >> 16) & 0xFF] ^ RT3[(Y0 >> 24) & 0xFF]; \
9567 }
9568 
9569/*
9570 * These macros improve the readability of the key
9571 * generation initialization code by collapsing
9572 * repetitive common operations into logical pieces.
9573 */
9574#define ROTL8(x) ((x << 8) & 0xFFFFFFFF) | (x >> 24)
9575#define XTIME(x) ((x << 1) ^ ((x & 0x80) ? 0x1B : 0x00))
9576#define MUL(x, y) ((x && y) ? pow[(log[x] + log[y]) % 255] : 0)
9577#define MIX(x, y) \
9578 { \
9579 y = ((y << 1) | (y >> 7)) & 0xFF; \
9580 x ^= y; \
9581 }
9582#define CPY128 \
9583 { \
9584 *RK++ = *SK++; \
9585 *RK++ = *SK++; \
9586 *RK++ = *SK++; \
9587 *RK++ = *SK++; \
9588 }
9589 
9590/******************************************************************************
9591 *
9592 * AES_INIT_KEYGEN_TABLES
9593 *
9594 * Fills the AES key expansion tables allocated above with their static
9595 * data. This is not "per key" data, but static system-wide read-only
9596 * table data. THIS FUNCTION IS NOT THREAD SAFE. It must be called once
9597 * at system initialization to setup the tables for all subsequent use.
9598 *
9599 ******************************************************************************/
9600void aes_init_keygen_tables(void) {
9601 int i, x, y, z; // general purpose iteration and computation locals
9602 int pow[256];
9603 int log[256];
9604 
9605 if (aes_tables_inited) return;
9606 
9607 // fill the 'pow' and 'log' tables over GF(2^8)
9608 for (i = 0, x = 1; i < 256; i++) {
9609 pow[i] = x;
9610 log[x] = i;
9611 x = (x ^ XTIME(x)) & 0xFF;
9612 }
9613 // compute the round constants
9614 for (i = 0, x = 1; i < 10; i++) {
9615 RCON[i] = (uint32_t) x;
9616 x = XTIME(x) & 0xFF;
9617 }
9618 // fill the forward and reverse substitution boxes
9619 FSb[0x00] = 0x63;
9620#if AES_DECRYPTION // whether AES decryption is supported
9621 RSb[0x63] = 0x00;
9622#endif /* AES_DECRYPTION */
9623 
9624 for (i = 1; i < 256; i++) {
9625 x = y = pow[255 - log[i]];
9626 MIX(x, y);
9627 MIX(x, y);
9628 MIX(x, y);
9629 MIX(x, y);
9630 FSb[i] = (unsigned char) (x ^= 0x63);
9631#if AES_DECRYPTION // whether AES decryption is supported
9632 RSb[x] = (unsigned char) i;
9633#endif /* AES_DECRYPTION */
9634 }
9635 // generate the forward and reverse key expansion tables
9636 for (i = 0; i < 256; i++) {
9637 x = FSb[i];
9638 y = XTIME(x) & 0xFF;
9639 z = (y ^ x) & 0xFF;
9640 
9641 FT0[i] = ((uint32_t) y) ^ ((uint32_t) x << 8) ^ ((uint32_t) x << 16) ^
9642 ((uint32_t) z << 24);
9643 
9644 FT1[i] = ROTL8(FT0[i]);
9645 FT2[i] = ROTL8(FT1[i]);
9646 FT3[i] = ROTL8(FT2[i]);
9647 
9648#if AES_DECRYPTION // whether AES decryption is supported
9649 x = RSb[i];
9650 
9651 RT0[i] = ((uint32_t) MUL(0x0E, x)) ^ ((uint32_t) MUL(0x09, x) << 8) ^
9652 ((uint32_t) MUL(0x0D, x) << 16) ^ ((uint32_t) MUL(0x0B, x) << 24);
9653 
9654 RT1[i] = ROTL8(RT0[i]);
9655 RT2[i] = ROTL8(RT1[i]);
9656 RT3[i] = ROTL8(RT2[i]);
9657#endif /* AES_DECRYPTION */
9658 }
9659 aes_tables_inited = 1; // flag that the tables have been generated
9660} // to permit subsequent use of the AES cipher
9661 
9662/******************************************************************************
9663 *
9664 * AES_SET_ENCRYPTION_KEY
9665 *
9666 * This is called by 'aes_setkey' when we're establishing a key for
9667 * subsequent encryption. We give it a pointer to the encryption
9668 * context, a pointer to the key, and the key's length in bytes.
9669 * Valid lengths are: 16, 24 or 32 bytes (128, 192, 256 bits).
9670 *
9671 ******************************************************************************/
9672static int aes_set_encryption_key(aes_context *ctx, const unsigned char *key,
9673 unsigned int keysize) {
9674 unsigned int i; // general purpose iteration local
9675 uint32_t *RK = ctx->rk; // initialize our RoundKey buffer pointer
9676 
9677 for (i = 0; i < (keysize >> 2); i++) {
9678 GET_UINT32_LE(RK[i], key, i << 2);
9679 }
9680 
9681 switch (ctx->rounds) {
9682 case 10:
9683 for (i = 0; i < 10; i++, RK += 4) {
9684 RK[4] = RK[0] ^ RCON[i] ^ ((uint32_t) FSb[(RK[3] >> 8) & 0xFF]) ^
9685 ((uint32_t) FSb[(RK[3] >> 16) & 0xFF] << 8) ^
9686 ((uint32_t) FSb[(RK[3] >> 24) & 0xFF] << 16) ^
9687 ((uint32_t) FSb[(RK[3]) & 0xFF] << 24);
9688 
9689 RK[5] = RK[1] ^ RK[4];
9690 RK[6] = RK[2] ^ RK[5];
9691 RK[7] = RK[3] ^ RK[6];
9692 }
9693 break;
9694 
9695 case 12:
9696 for (i = 0; i < 8; i++, RK += 6) {
9697 RK[6] = RK[0] ^ RCON[i] ^ ((uint32_t) FSb[(RK[5] >> 8) & 0xFF]) ^
9698 ((uint32_t) FSb[(RK[5] >> 16) & 0xFF] << 8) ^
9699 ((uint32_t) FSb[(RK[5] >> 24) & 0xFF] << 16) ^
9700 ((uint32_t) FSb[(RK[5]) & 0xFF] << 24);
9701 
9702 RK[7] = RK[1] ^ RK[6];
9703 RK[8] = RK[2] ^ RK[7];
9704 RK[9] = RK[3] ^ RK[8];
9705 RK[10] = RK[4] ^ RK[9];
9706 RK[11] = RK[5] ^ RK[10];
9707 }
9708 break;
9709 
9710 case 14:
9711 for (i = 0; i < 7; i++, RK += 8) {
9712 RK[8] = RK[0] ^ RCON[i] ^ ((uint32_t) FSb[(RK[7] >> 8) & 0xFF]) ^
9713 ((uint32_t) FSb[(RK[7] >> 16) & 0xFF] << 8) ^
9714 ((uint32_t) FSb[(RK[7] >> 24) & 0xFF] << 16) ^
9715 ((uint32_t) FSb[(RK[7]) & 0xFF] << 24);
9716 
9717 RK[9] = RK[1] ^ RK[8];
9718 RK[10] = RK[2] ^ RK[9];
9719 RK[11] = RK[3] ^ RK[10];
9720 
9721 RK[12] = RK[4] ^ ((uint32_t) FSb[(RK[11]) & 0xFF]) ^
9722 ((uint32_t) FSb[(RK[11] >> 8) & 0xFF] << 8) ^
9723 ((uint32_t) FSb[(RK[11] >> 16) & 0xFF] << 16) ^
9724 ((uint32_t) FSb[(RK[11] >> 24) & 0xFF] << 24);
9725 
9726 RK[13] = RK[5] ^ RK[12];
9727 RK[14] = RK[6] ^ RK[13];
9728 RK[15] = RK[7] ^ RK[14];
9729 }
9730 break;
9731 
9732 default:
9733 return -1;
9734 }
9735 return (0);
9736}
9737 
9738#if AES_DECRYPTION // whether AES decryption is supported
9739 
9740/******************************************************************************
9741 *
9742 * AES_SET_DECRYPTION_KEY
9743 *
9744 * This is called by 'aes_setkey' when we're establishing a
9745 * key for subsequent decryption. We give it a pointer to
9746 * the encryption context, a pointer to the key, and the key's
9747 * length in bits. Valid lengths are: 128, 192, or 256 bits.
9748 *
9749 ******************************************************************************/
9750static int aes_set_decryption_key(aes_context *ctx, const unsigned char *key,
9751 unsigned int keysize) {
9752 int i, j;
9753 aes_context cty; // a calling aes context for set_encryption_key
9754 uint32_t *RK = ctx->rk; // initialize our RoundKey buffer pointer
9755 uint32_t *SK;
9756 int ret;
9757 
9758 cty.rounds = ctx->rounds; // initialize our local aes context
9759 cty.rk = cty.buf; // round count and key buf pointer
9760 
9761 if ((ret = aes_set_encryption_key(&cty, key, keysize)) != 0) return (ret);
9762 
9763 SK = cty.rk + cty.rounds * 4;
9764 
9765 CPY128 // copy a 128-bit block from *SK to *RK
9766 
9767 for (i = ctx->rounds - 1, SK -= 8; i > 0; i--, SK -= 8) {
9768 for (j = 0; j < 4; j++, SK++) {
9769 *RK++ = RT0[FSb[(*SK) & 0xFF]] ^ RT1[FSb[(*SK >> 8) & 0xFF]] ^
9770 RT2[FSb[(*SK >> 16) & 0xFF]] ^ RT3[FSb[(*SK >> 24) & 0xFF]];
9771 }
9772 }
9773 CPY128 // copy a 128-bit block from *SK to *RK
9774 memset(&cty, 0, sizeof(aes_context)); // clear local aes context
9775 return (0);
9776}
9777 
9778#endif /* AES_DECRYPTION */
9779 
9780/******************************************************************************
9781 *
9782 * AES_SETKEY
9783 *
9784 * Invoked to establish the key schedule for subsequent encryption/decryption
9785 *
9786 ******************************************************************************/
9787static int aes_setkey(aes_context *ctx, // AES context provided by our caller
9788 int mode, // ENCRYPT or DECRYPT flag
9789 const unsigned char *key, // pointer to the key
9790 unsigned int keysize) // key length in bytes
9791{
9792 // since table initialization is not thread safe, we could either add
9793 // system-specific mutexes and init the AES key generation tables on
9794 // demand, or ask the developer to simply call "gcm_initialize" once during
9795 // application startup before threading begins. That's what we choose.
9796 if (!aes_tables_inited) return (-1); // fail the call when not inited.
9797 
9798 ctx->mode = mode; // capture the key type we're creating
9799 ctx->rk = ctx->buf; // initialize our round key pointer
9800 
9801 switch (keysize) // set the rounds count based upon the keysize
9802 {
9803 case 16:
9804 ctx->rounds = 10;
9805 break; // 16-byte, 128-bit key
9806 case 24:
9807 ctx->rounds = 12;
9808 break; // 24-byte, 192-bit key
9809 case 32:
9810 ctx->rounds = 14;
9811 break; // 32-byte, 256-bit key
9812 default:
9813 return (-1);
9814 }
9815 
9816#if AES_DECRYPTION
9817 if (mode == MG_DECRYPT) // expand our key for encryption or decryption
9818 return (aes_set_decryption_key(ctx, key, keysize));
9819 else /* MG_ENCRYPT */
9820#endif /* AES_DECRYPTION */
9821 return (aes_set_encryption_key(ctx, key, keysize));
9822}
9823 
9824/******************************************************************************
9825 *
9826 * AES_CIPHER
9827 *
9828 * Perform AES encryption and decryption.
9829 * The AES context will have been setup with the encryption mode
9830 * and all keying information appropriate for the task.
9831 *
9832 ******************************************************************************/
9833static int aes_cipher(aes_context *ctx, const unsigned char input[16],
9834 unsigned char output[16]) {
9835 int i;
9836 uint32_t *RK, X0, X1, X2, X3, Y0, Y1, Y2, Y3; // general purpose locals
9837 
9838 RK = ctx->rk;
9839 
9840 GET_UINT32_LE(X0, input, 0);
9841 X0 ^= *RK++; // load our 128-bit
9842 GET_UINT32_LE(X1, input, 4);
9843 X1 ^= *RK++; // input buffer in a storage
9844 GET_UINT32_LE(X2, input, 8);
9845 X2 ^= *RK++; // memory endian-neutral way
9846 GET_UINT32_LE(X3, input, 12);
9847 X3 ^= *RK++;
9848 
9849#if AES_DECRYPTION // whether AES decryption is supported
9850 
9851 if (ctx->mode == MG_DECRYPT) {
9852 for (i = (ctx->rounds >> 1) - 1; i > 0; i--) {
9853 AES_RROUND(Y0, Y1, Y2, Y3, X0, X1, X2, X3);
9854 AES_RROUND(X0, X1, X2, X3, Y0, Y1, Y2, Y3);
9855 }
9856 
9857 AES_RROUND(Y0, Y1, Y2, Y3, X0, X1, X2, X3);
9858 
9859 X0 = *RK++ ^ ((uint32_t) RSb[(Y0) & 0xFF]) ^
9860 ((uint32_t) RSb[(Y3 >> 8) & 0xFF] << 8) ^
9861 ((uint32_t) RSb[(Y2 >> 16) & 0xFF] << 16) ^
9862 ((uint32_t) RSb[(Y1 >> 24) & 0xFF] << 24);
9863 
9864 X1 = *RK++ ^ ((uint32_t) RSb[(Y1) & 0xFF]) ^
9865 ((uint32_t) RSb[(Y0 >> 8) & 0xFF] << 8) ^
9866 ((uint32_t) RSb[(Y3 >> 16) & 0xFF] << 16) ^
9867 ((uint32_t) RSb[(Y2 >> 24) & 0xFF] << 24);
9868 
9869 X2 = *RK++ ^ ((uint32_t) RSb[(Y2) & 0xFF]) ^
9870 ((uint32_t) RSb[(Y1 >> 8) & 0xFF] << 8) ^
9871 ((uint32_t) RSb[(Y0 >> 16) & 0xFF] << 16) ^
9872 ((uint32_t) RSb[(Y3 >> 24) & 0xFF] << 24);
9873 
9874 X3 = *RK++ ^ ((uint32_t) RSb[(Y3) & 0xFF]) ^
9875 ((uint32_t) RSb[(Y2 >> 8) & 0xFF] << 8) ^
9876 ((uint32_t) RSb[(Y1 >> 16) & 0xFF] << 16) ^
9877 ((uint32_t) RSb[(Y0 >> 24) & 0xFF] << 24);
9878 } else /* MG_ENCRYPT */
9879 {
9880#endif /* AES_DECRYPTION */
9881 
9882 for (i = (ctx->rounds >> 1) - 1; i > 0; i--) {
9883 AES_FROUND(Y0, Y1, Y2, Y3, X0, X1, X2, X3);
9884 AES_FROUND(X0, X1, X2, X3, Y0, Y1, Y2, Y3);
9885 }
9886 
9887 AES_FROUND(Y0, Y1, Y2, Y3, X0, X1, X2, X3);
9888 
9889 X0 = *RK++ ^ ((uint32_t) FSb[(Y0) & 0xFF]) ^
9890 ((uint32_t) FSb[(Y1 >> 8) & 0xFF] << 8) ^
9891 ((uint32_t) FSb[(Y2 >> 16) & 0xFF] << 16) ^
9892 ((uint32_t) FSb[(Y3 >> 24) & 0xFF] << 24);
9893 
9894 X1 = *RK++ ^ ((uint32_t) FSb[(Y1) & 0xFF]) ^
9895 ((uint32_t) FSb[(Y2 >> 8) & 0xFF] << 8) ^
9896 ((uint32_t) FSb[(Y3 >> 16) & 0xFF] << 16) ^
9897 ((uint32_t) FSb[(Y0 >> 24) & 0xFF] << 24);
9898 
9899 X2 = *RK++ ^ ((uint32_t) FSb[(Y2) & 0xFF]) ^
9900 ((uint32_t) FSb[(Y3 >> 8) & 0xFF] << 8) ^
9901 ((uint32_t) FSb[(Y0 >> 16) & 0xFF] << 16) ^
9902 ((uint32_t) FSb[(Y1 >> 24) & 0xFF] << 24);
9903 
9904 X3 = *RK++ ^ ((uint32_t) FSb[(Y3) & 0xFF]) ^
9905 ((uint32_t) FSb[(Y0 >> 8) & 0xFF] << 8) ^
9906 ((uint32_t) FSb[(Y1 >> 16) & 0xFF] << 16) ^
9907 ((uint32_t) FSb[(Y2 >> 24) & 0xFF] << 24);
9908 
9909#if AES_DECRYPTION // whether AES decryption is supported
9910 }
9911#endif /* AES_DECRYPTION */
9912 
9913 PUT_UINT32_LE(X0, output, 0);
9914 PUT_UINT32_LE(X1, output, 4);
9915 PUT_UINT32_LE(X2, output, 8);
9916 PUT_UINT32_LE(X3, output, 12);
9917 
9918 return (0);
9919}
9920/* end of aes.c */
9921/******************************************************************************
9922 *
9923 * THIS SOURCE CODE IS HEREBY PLACED INTO THE PUBLIC DOMAIN FOR THE GOOD OF ALL
9924 *
9925 * This is a simple and straightforward implementation of AES-GCM authenticated
9926 * encryption. The focus of this work was correctness & accuracy. It is written
9927 * in straight 'C' without any particular focus upon optimization or speed. It
9928 * should be endian (memory byte order) neutral since the few places that care
9929 * are handled explicitly.
9930 *
9931 * This implementation of AES-GCM was created by Steven M. Gibson of GRC.com.
9932 *
9933 * It is intended for general purpose use, but was written in support of GRC's
9934 * reference implementation of the SQRL (Secure Quick Reliable Login) client.
9935 *
9936 * See: http://csrc.nist.gov/publications/nistpubs/800-38D/SP-800-38D.pdf
9937 * http://csrc.nist.gov/groups/ST/toolkit/BCM/documents/proposedmodes/
9938 * gcm/gcm-revised-spec.pdf
9939 *
9940 * NO COPYRIGHT IS CLAIMED IN THIS WORK, HOWEVER, NEITHER IS ANY WARRANTY MADE
9941 * REGARDING ITS FITNESS FOR ANY PARTICULAR PURPOSE. USE IT AT YOUR OWN RISK.
9942 *
9943 *******************************************************************************/
9944 
9945/******************************************************************************
9946 * ==== IMPLEMENTATION WARNING ====
9947 *
9948 * This code was developed for use within SQRL's fixed environmnent. Thus, it
9949 * is somewhat less "general purpose" than it would be if it were designed as
9950 * a general purpose AES-GCM library. Specifically, it bothers with almost NO
9951 * error checking on parameter limits, buffer bounds, etc. It assumes that it
9952 * is being invoked by its author or by someone who understands the values it
9953 * expects to receive. Its behavior will be undefined otherwise.
9954 *
9955 * All functions that might fail are defined to return 'ints' to indicate a
9956 * problem. Most do not do so now. But this allows for error propagation out
9957 * of internal functions if robust error checking should ever be desired.
9958 *
9959 ******************************************************************************/
9960 
9961/* Calculating the "GHASH"
9962 *
9963 * There are many ways of calculating the so-called GHASH in software, each with
9964 * a traditional size vs performance tradeoff. The GHASH (Galois field hash) is
9965 * an intriguing construction which takes two 128-bit strings (also the cipher's
9966 * block size and the fundamental operation size for the system) and hashes them
9967 * into a third 128-bit result.
9968 *
9969 * Many implementation solutions have been worked out that use large precomputed
9970 * table lookups in place of more time consuming bit fiddling, and this approach
9971 * can be scaled easily upward or downward as needed to change the time/space
9972 * tradeoff. It's been studied extensively and there's a solid body of theory
9973 * and practice. For example, without using any lookup tables an implementation
9974 * might obtain 119 cycles per byte throughput, whereas using a simple, though
9975 * large, key-specific 64 kbyte 8-bit lookup table the performance jumps to 13
9976 * cycles per byte.
9977 *
9978 * And Intel's processors have, since 2010, included an instruction which does
9979 * the entire 128x128->128 bit job in just several 64x64->128 bit pieces.
9980 *
9981 * Since SQRL is interactive, and only processing a few 128-bit blocks, I've
9982 * settled upon a relatively slower but appealing small-table compromise which
9983 * folds a bunch of not only time consuming but also bit twiddling into a simple
9984 * 16-entry table which is attributed to Victor Shoup's 1996 work while at
9985 * Bellcore: "On Fast and Provably Secure MessageAuthentication Based on
9986 * Universal Hashing." See: http://www.shoup.net/papers/macs.pdf
9987 * See, also section 4.1 of the "gcm-revised-spec" cited above.
9988 */
9989 
9990/*
9991 * This 16-entry table of pre-computed constants is used by the
9992 * GHASH multiplier to improve over a strictly table-free but
9993 * significantly slower 128x128 bit multiple within GF(2^128).
9994 */
9995static const uint64_t last4[16] = {
9996 0x0000, 0x1c20, 0x3840, 0x2460, 0x7080, 0x6ca0, 0x48c0, 0x54e0,
9997 0xe100, 0xfd20, 0xd940, 0xc560, 0x9180, 0x8da0, 0xa9c0, 0xb5e0};
9998 
9999/*
10000 * Platform Endianness Neutralizing Load and Store Macro definitions
10001 * GCM wants platform-neutral Big Endian (BE) byte ordering
10002 */
10003#define GET_UINT32_BE(n, b, i) \
10004 { \
10005 (n) = ((uint32_t) (b)[(i)] << 24) | ((uint32_t) (b)[(i) + 1] << 16) | \
10006 ((uint32_t) (b)[(i) + 2] << 8) | ((uint32_t) (b)[(i) + 3]); \
10007 }
10008 
10009#define PUT_UINT32_BE(n, b, i) \
10010 { \
10011 (b)[(i)] = (unsigned char) ((n) >> 24); \
10012 (b)[(i) + 1] = (unsigned char) ((n) >> 16); \
10013 (b)[(i) + 2] = (unsigned char) ((n) >> 8); \
10014 (b)[(i) + 3] = (unsigned char) ((n)); \
10015 }
10016 
10017/******************************************************************************
10018 *
10019 * GCM_INITIALIZE
10020 *
10021 * Must be called once to initialize the GCM library.
10022 *
10023 * At present, this only calls the AES keygen table generator, which expands
10024 * the AES keying tables for use. This is NOT A THREAD-SAFE function, so it
10025 * MUST be called during system initialization before a multi-threading
10026 * environment is running.
10027 *
10028 ******************************************************************************/
10029int mg_gcm_initialize(void) {
10030 aes_init_keygen_tables();
10031 return (0);
10032}
10033 
10034/******************************************************************************
10035 *
10036 * GCM_MULT
10037 *
10038 * Performs a GHASH operation on the 128-bit input vector 'x', setting
10039 * the 128-bit output vector to 'x' times H using our precomputed tables.
10040 * 'x' and 'output' are seen as elements of GCM's GF(2^128) Galois field.
10041 *
10042 ******************************************************************************/
10043static void gcm_mult(gcm_context *ctx, // pointer to established context
10044 const unsigned char x[16], // pointer to 128-bit input vector
10045 unsigned char output[16]) // pointer to 128-bit output vector
10046{
10047 int i;
10048 unsigned char lo, hi, rem;
10049 uint64_t zh, zl;
10050 
10051 lo = (unsigned char) (x[15] & 0x0f);
10052 hi = (unsigned char) (x[15] >> 4);
10053 zh = ctx->HH[lo];
10054 zl = ctx->HL[lo];
10055 
10056 for (i = 15; i >= 0; i--) {
10057 lo = (unsigned char) (x[i] & 0x0f);
10058 hi = (unsigned char) (x[i] >> 4);
10059 
10060 if (i != 15) {
10061 rem = (unsigned char) (zl & 0x0f);
10062 zl = (zh << 60) | (zl >> 4);
10063 zh = (zh >> 4);
10064 zh ^= (uint64_t) last4[rem] << 48;
10065 zh ^= ctx->HH[lo];
10066 zl ^= ctx->HL[lo];
10067 }
10068 rem = (unsigned char) (zl & 0x0f);
10069 zl = (zh << 60) | (zl >> 4);
10070 zh = (zh >> 4);
10071 zh ^= (uint64_t) last4[rem] << 48;
10072 zh ^= ctx->HH[hi];
10073 zl ^= ctx->HL[hi];
10074 }
10075 PUT_UINT32_BE(zh >> 32, output, 0);
10076 PUT_UINT32_BE(zh, output, 4);
10077 PUT_UINT32_BE(zl >> 32, output, 8);
10078 PUT_UINT32_BE(zl, output, 12);
10079}
10080 
10081/******************************************************************************
10082 *
10083 * GCM_SETKEY
10084 *
10085 * This is called to set the AES-GCM key. It initializes the AES key
10086 * and populates the gcm context's pre-calculated HTables.
10087 *
10088 ******************************************************************************/
10089static int gcm_setkey(
10090 gcm_context *ctx, // pointer to caller-provided gcm context
10091 const unsigned char *key, // pointer to the AES encryption key
10092 const unsigned int keysize) // size in bytes (must be 16, 24, 32 for
10093 // 128, 192 or 256-bit keys respectively)
10094{
10095 int ret, i, j;
10096 uint64_t hi, lo;
10097 uint64_t vl, vh;
10098 unsigned char h[16];
10099 
10100 memset(ctx, 0, sizeof(gcm_context)); // zero caller-provided GCM context
10101 memset(h, 0, 16); // initialize the block to encrypt
10102 
10103 // encrypt the null 128-bit block to generate a key-based value
10104 // which is then used to initialize our GHASH lookup tables
10105 if ((ret = aes_setkey(&ctx->aes_ctx, MG_ENCRYPT, key, keysize)) != 0)
10106 return (ret);
10107 if ((ret = aes_cipher(&ctx->aes_ctx, h, h)) != 0) return (ret);
10108 
10109 GET_UINT32_BE(hi, h, 0); // pack h as two 64-bit ints, big-endian
10110 GET_UINT32_BE(lo, h, 4);
10111 vh = (uint64_t) hi << 32 | lo;
10112 
10113 GET_UINT32_BE(hi, h, 8);
10114 GET_UINT32_BE(lo, h, 12);
10115 vl = (uint64_t) hi << 32 | lo;
10116 
10117 ctx->HL[8] = vl; // 8 = 1000 corresponds to 1 in GF(2^128)
10118 ctx->HH[8] = vh;
10119 ctx->HH[0] = 0; // 0 corresponds to 0 in GF(2^128)
10120 ctx->HL[0] = 0;
10121 
10122 for (i = 4; i > 0; i >>= 1) {
10123 uint32_t T = (uint32_t) (vl & 1) * 0xe1000000U;
10124 vl = (vh << 63) | (vl >> 1);
10125 vh = (vh >> 1) ^ ((uint64_t) T << 32);
10126 ctx->HL[i] = vl;
10127 ctx->HH[i] = vh;
10128 }
10129 for (i = 2; i < 16; i <<= 1) {
10130 uint64_t *HiL = ctx->HL + i, *HiH = ctx->HH + i;
10131 vh = *HiH;
10132 vl = *HiL;
10133 for (j = 1; j < i; j++) {
10134 HiH[j] = vh ^ ctx->HH[j];
10135 HiL[j] = vl ^ ctx->HL[j];
10136 }
10137 }
10138 return (0);
10139}
10140 
10141/******************************************************************************
10142 *
10143 * GCM processing occurs four phases: SETKEY, START, UPDATE and FINISH.
10144 *
10145 * SETKEY:
10146 *
10147 * START: Sets the Encryption/Decryption mode.
10148 * Accepts the initialization vector and additional data.
10149 *
10150 * UPDATE: Encrypts or decrypts the plaintext or ciphertext.
10151 *
10152 * FINISH: Performs a final GHASH to generate the authentication tag.
10153 *
10154 ******************************************************************************
10155 *
10156 * GCM_START
10157 *
10158 * Given a user-provided GCM context, this initializes it, sets the encryption
10159 * mode, and preprocesses the initialization vector and additional AEAD data.
10160 *
10161 ******************************************************************************/
10162int gcm_start(gcm_context *ctx, // pointer to user-provided GCM context
10163 int mode, // GCM_ENCRYPT or GCM_DECRYPT
10164 const unsigned char *iv, // pointer to initialization vector
10165 size_t iv_len, // IV length in bytes (should == 12)
10166 const unsigned char *add, // ptr to additional AEAD data (NULL if none)
10167 size_t add_len) // length of additional AEAD data (bytes)
10168{
10169 int ret; // our error return if the AES encrypt fails
10170 unsigned char work_buf[16]; // XOR source built from provided IV if len != 16
10171 const unsigned char *p; // general purpose array pointer
10172 size_t use_len; // byte count to process, up to 16 bytes
10173 size_t i; // local loop iterator
10174 
10175 // since the context might be reused under the same key
10176 // we zero the working buffers for this next new process
10177 memset(ctx->y, 0x00, sizeof(ctx->y));
10178 memset(ctx->buf, 0x00, sizeof(ctx->buf));
10179 ctx->len = 0;
10180 ctx->add_len = 0;
10181 
10182 ctx->mode = mode; // set the GCM encryption/decryption mode
10183 ctx->aes_ctx.mode = MG_ENCRYPT; // GCM *always* runs AES in ENCRYPTION mode
10184 
10185 if (iv_len == 12) { // GCM natively uses a 12-byte, 96-bit IV
10186 memcpy(ctx->y, iv, iv_len); // copy the IV to the top of the 'y' buff
10187 ctx->y[15] = 1; // start "counting" from 1 (not 0)
10188 } else // if we don't have a 12-byte IV, we GHASH whatever we've been given
10189 {
10190 memset(work_buf, 0x00, 16); // clear the working buffer
10191 PUT_UINT32_BE(iv_len * 8, work_buf, 12); // place the IV into buffer
10192 
10193 p = iv;
10194 while (iv_len > 0) {
10195 use_len = (iv_len < 16) ? iv_len : 16;
10196 for (i = 0; i < use_len; i++) ctx->y[i] ^= p[i];
10197 gcm_mult(ctx, ctx->y, ctx->y);
10198 iv_len -= use_len;
10199 p += use_len;
10200 }
10201 for (i = 0; i < 16; i++) ctx->y[i] ^= work_buf[i];
10202 gcm_mult(ctx, ctx->y, ctx->y);
10203 }
10204 if ((ret = aes_cipher(&ctx->aes_ctx, ctx->y, ctx->base_ectr)) != 0)
10205 return (ret);
10206 
10207 ctx->add_len = add_len;
10208 p = add;
10209 while (add_len > 0) {
10210 use_len = (add_len < 16) ? add_len : 16;
10211 for (i = 0; i < use_len; i++) ctx->buf[i] ^= p[i];
10212 gcm_mult(ctx, ctx->buf, ctx->buf);
10213 add_len -= use_len;
10214 p += use_len;
10215 }
10216 return (0);
10217}
10218 
10219/******************************************************************************
10220 *
10221 * GCM_UPDATE
10222 *
10223 * This is called once or more to process bulk plaintext or ciphertext data.
10224 * We give this some number of bytes of input and it returns the same number
10225 * of output bytes. If called multiple times (which is fine) all but the final
10226 * invocation MUST be called with length mod 16 == 0. (Only the final call can
10227 * have a partial block length of < 128 bits.)
10228 *
10229 ******************************************************************************/
10230int gcm_update(gcm_context *ctx, // pointer to user-provided GCM context
10231 size_t length, // length, in bytes, of data to process
10232 const unsigned char *input, // pointer to source data
10233 unsigned char *output) // pointer to destination data
10234{
10235 int ret; // our error return if the AES encrypt fails
10236 unsigned char ectr[16]; // counter-mode cipher output for XORing
10237 size_t use_len; // byte count to process, up to 16 bytes
10238 size_t i; // local loop iterator
10239 
10240 ctx->len += length; // bump the GCM context's running length count
10241 
10242 while (length > 0) {
10243 // clamp the length to process at 16 bytes
10244 use_len = (length < 16) ? length : 16;
10245 
10246 // increment the context's 128-bit IV||Counter 'y' vector
10247 for (i = 16; i > 12; i--)
10248 if (++ctx->y[i - 1] != 0) break;
10249 
10250 // encrypt the context's 'y' vector under the established key
10251 if ((ret = aes_cipher(&ctx->aes_ctx, ctx->y, ectr)) != 0) return (ret);
10252 
10253 // encrypt or decrypt the input to the output
10254 if (ctx->mode == MG_ENCRYPT) {
10255 for (i = 0; i < use_len; i++) {
10256 // XOR the cipher's ouptut vector (ectr) with our input
10257 output[i] = (unsigned char) (ectr[i] ^ input[i]);
10258 // now we mix in our data into the authentication hash.
10259 // if we're ENcrypting we XOR in the post-XOR (output)
10260 // results, but if we're DEcrypting we XOR in the input
10261 // data
10262 ctx->buf[i] ^= output[i];
10263 }
10264 } else {
10265 for (i = 0; i < use_len; i++) {
10266 // but if we're DEcrypting we XOR in the input data first,
10267 // i.e. before saving to ouput data, otherwise if the input
10268 // and output buffer are the same (inplace decryption) we
10269 // would not get the correct auth tag
10270 
10271 ctx->buf[i] ^= input[i];
10272 
10273 // XOR the cipher's ouptut vector (ectr) with our input
10274 output[i] = (unsigned char) (ectr[i] ^ input[i]);
10275 }
10276 }
10277 gcm_mult(ctx, ctx->buf, ctx->buf); // perform a GHASH operation
10278 
10279 length -= use_len; // drop the remaining byte count to process
10280 input += use_len; // bump our input pointer forward
10281 output += use_len; // bump our output pointer forward
10282 }
10283 return (0);
10284}
10285 
10286/******************************************************************************
10287 *
10288 * GCM_FINISH
10289 *
10290 * This is called once after all calls to GCM_UPDATE to finalize the GCM.
10291 * It performs the final GHASH to produce the resulting authentication TAG.
10292 *
10293 ******************************************************************************/
10294int gcm_finish(gcm_context *ctx, // pointer to user-provided GCM context
10295 unsigned char *tag, // pointer to buffer which receives the tag
10296 size_t tag_len) // length, in bytes, of the tag-receiving buf
10297{
10298 unsigned char work_buf[16];
10299 uint64_t orig_len = ctx->len * 8;
10300 uint64_t orig_add_len = ctx->add_len * 8;
10301 size_t i;
10302 
10303 if (tag_len != 0) memcpy(tag, ctx->base_ectr, tag_len);
10304 
10305 if (orig_len || orig_add_len) {
10306 memset(work_buf, 0x00, 16);
10307 
10308 PUT_UINT32_BE((orig_add_len >> 32), work_buf, 0);
10309 PUT_UINT32_BE((orig_add_len), work_buf, 4);
10310 PUT_UINT32_BE((orig_len >> 32), work_buf, 8);
10311 PUT_UINT32_BE((orig_len), work_buf, 12);
10312 
10313 for (i = 0; i < 16; i++) ctx->buf[i] ^= work_buf[i];
10314 gcm_mult(ctx, ctx->buf, ctx->buf);
10315 for (i = 0; i < tag_len; i++) tag[i] ^= ctx->buf[i];
10316 }
10317 return (0);
10318}
10319 
10320/******************************************************************************
10321 *
10322 * GCM_CRYPT_AND_TAG
10323 *
10324 * This either encrypts or decrypts the user-provided data and, either
10325 * way, generates an authentication tag of the requested length. It must be
10326 * called with a GCM context whose key has already been set with GCM_SETKEY.
10327 *
10328 * The user would typically call this explicitly to ENCRYPT a buffer of data
10329 * and optional associated data, and produce its an authentication tag.
10330 *
10331 * To reverse the process the user would typically call the companion
10332 * GCM_AUTH_DECRYPT function to decrypt data and verify a user-provided
10333 * authentication tag. The GCM_AUTH_DECRYPT function calls this function
10334 * to perform its decryption and tag generation, which it then compares.
10335 *
10336 ******************************************************************************/
10337int gcm_crypt_and_tag(
10338 gcm_context *ctx, // gcm context with key already setup
10339 int mode, // cipher direction: GCM_ENCRYPT or GCM_DECRYPT
10340 const unsigned char *iv, // pointer to the 12-byte initialization vector
10341 size_t iv_len, // byte length if the IV. should always be 12
10342 const unsigned char *add, // pointer to the non-ciphered additional data
10343 size_t add_len, // byte length of the additional AEAD data
10344 const unsigned char *input, // pointer to the cipher data source
10345 unsigned char *output, // pointer to the cipher data destination
10346 size_t length, // byte length of the cipher data
10347 unsigned char *tag, // pointer to the tag to be generated
10348 size_t tag_len) // byte length of the tag to be generated
10349{ /*
10350 assuming that the caller has already invoked gcm_setkey to
10351 prepare the gcm context with the keying material, we simply
10352 invoke each of the three GCM sub-functions in turn...
10353 */
10354 gcm_start(ctx, mode, iv, iv_len, add, add_len);
10355 gcm_update(ctx, length, input, output);
10356 gcm_finish(ctx, tag, tag_len);
10357 return (0);
10358}
10359 
10360/******************************************************************************
10361 *
10362 * GCM_ZERO_CTX
10363 *
10364 * The GCM context contains both the GCM context and the AES context.
10365 * This includes keying and key-related material which is security-
10366 * sensitive, so it MUST be zeroed after use. This function does that.
10367 *
10368 ******************************************************************************/
10369void gcm_zero_ctx(gcm_context *ctx) {
10370 // zero the context originally provided to us
10371 memset(ctx, 0, sizeof(gcm_context));
10372}
10373//
10374// aes-gcm.c
10375// Pods
10376//
10377// Created by Markus Kosmal on 20/11/14.
10378//
10379//
10380 
10381int mg_aes_gcm_encrypt(unsigned char *output, //
10382 const unsigned char *input, size_t input_length,
10383 const unsigned char *key, const size_t key_len,
10384 const unsigned char *iv, const size_t iv_len,
10385 unsigned char *aead, size_t aead_len, unsigned char *tag,
10386 const size_t tag_len) {
10387 int ret = 0; // our return value
10388 gcm_context ctx; // includes the AES context structure
10389 
10390 gcm_setkey(&ctx, key, (unsigned int) key_len);
10391 
10392 ret = gcm_crypt_and_tag(&ctx, MG_ENCRYPT, iv, iv_len, aead, aead_len, input,
10393 output, input_length, tag, tag_len);
10394 
10395 gcm_zero_ctx(&ctx);
10396 
10397 return (ret);
10398}
10399 
10400int mg_aes_gcm_decrypt(unsigned char *output, const unsigned char *input,
10401 size_t input_length, const unsigned char *key,
10402 const size_t key_len, const unsigned char *iv,
10403 const size_t iv_len) {
10404 int ret = 0; // our return value
10405 gcm_context ctx; // includes the AES context structure
10406 
10407 size_t tag_len = 0;
10408 unsigned char *tag_buf = NULL;
10409 
10410 gcm_setkey(&ctx, key, (unsigned int) key_len);
10411 
10412 ret = gcm_crypt_and_tag(&ctx, MG_DECRYPT, iv, iv_len, NULL, 0, input, output,
10413 input_length, tag_buf, tag_len);
10414 
10415 gcm_zero_ctx(&ctx);
10416 
10417 return (ret);
10418}
10419#endif
10420// End of aes128 PD
10421 
10422#ifdef MG_ENABLE_LINES
10423#line 1 "src/tls_builtin.c"
10424#endif
10425 
10426 
10427 
10428 
10429 
10430 
10431 
10432 
10433 
10434 
10435 
10436 
10437#if MG_TLS == MG_TLS_BUILTIN
10438 
10439#define CHACHA20 1
10440 
10441/* TLS 1.3 Record Content Type (RFC8446 B.1) */
10442#define MG_TLS_CHANGE_CIPHER 20
10443#define MG_TLS_ALERT 21
10444#define MG_TLS_HANDSHAKE 22
10445#define MG_TLS_APP_DATA 23
10446#define MG_TLS_HEARTBEAT 24
10447 
10448/* TLS 1.3 Handshake Message Type (RFC8446 B.3) */
10449#define MG_TLS_CLIENT_HELLO 1
10450#define MG_TLS_SERVER_HELLO 2
10451#define MG_TLS_ENCRYPTED_EXTENSIONS 8
10452#define MG_TLS_CERTIFICATE 11
10453#define MG_TLS_CERTIFICATE_REQUEST 13
10454#define MG_TLS_CERTIFICATE_VERIFY 15
10455#define MG_TLS_FINISHED 20
10456 
10457// handshake is re-entrant, so we need to keep track of its state state names
10458// refer to RFC8446#A.1
10459enum mg_tls_hs_state {
10460 // Client state machine:
10461 MG_TLS_STATE_CLIENT_START, // Send ClientHello
10462 MG_TLS_STATE_CLIENT_WAIT_SH, // Wait for ServerHello
10463 MG_TLS_STATE_CLIENT_WAIT_EE, // Wait for EncryptedExtensions
10464 MG_TLS_STATE_CLIENT_WAIT_CERT, // Wait for Certificate
10465 MG_TLS_STATE_CLIENT_WAIT_CV, // Wait for CertificateVerify
10466 MG_TLS_STATE_CLIENT_WAIT_FINISHED, // Wait for Finished
10467 MG_TLS_STATE_CLIENT_CONNECTED, // Done
10468 
10469 // Server state machine:
10470 MG_TLS_STATE_SERVER_START, // Wait for ClientHello
10471 MG_TLS_STATE_SERVER_NEGOTIATED, // Wait for Finished
10472 MG_TLS_STATE_SERVER_CONNECTED // Done
10473};
10474 
10475// encryption keys for a TLS connection
10476struct tls_enc {
10477 uint32_t sseq; // server sequence number, used in encryption
10478 uint32_t cseq; // client sequence number, used in decryption
10479 // keys for AES encryption or ChaCha20
10480 uint8_t handshake_secret[32];
10481 uint8_t server_write_key[32];
10482 uint8_t server_write_iv[12];
10483 uint8_t server_finished_key[32];
10484 uint8_t client_write_key[32];
10485 uint8_t client_write_iv[12];
10486 uint8_t client_finished_key[32];
10487};
10488 
10489// per-connection TLS data
10490struct tls_data {
10491 enum mg_tls_hs_state state; // keep track of connection handshake progress
10492 
10493 struct mg_iobuf send; // For the receive path, we're reusing c->rtls
10494 size_t recv_offset; // While c->rtls contains full records, reuse that
10495 size_t recv_len; // buffer but point at individual decrypted messages
10496 
10497 uint8_t content_type; // Last received record content type
10498 
10499 mg_sha256_ctx sha256; // incremental SHA-256 hash for TLS handshake
10500 
10501 uint8_t random[32]; // client random from ClientHello
10502 uint8_t session_id[32]; // client session ID between the handshake states
10503 uint8_t x25519_cli[32]; // client X25519 key between the handshake states
10504 uint8_t x25519_sec[32]; // x25519 secret between the handshake states
10505 
10506 int skip_verification; // perform checks on server certificate?
10507 int cert_requested; // client received a CertificateRequest?
10508 struct mg_str cert_der; // certificate in DER format
10509 struct mg_str ca_der; // CA certificate
10510 uint8_t ec_key[32]; // EC private key
10511 char hostname[254]; // server hostname (client extension)
10512 
10513 int is_ec_pubkey; // EC or RSA?
10514 uint8_t pubkey[512 + 16]; // server EC (64) or RSA (512+exp) public key to
10515 // verify cert
10516 size_t pubkeysz; // size of the server public key
10517 uint8_t sighash[32]; // calculated signature verification hash
10518 
10519 struct tls_enc enc;
10520};
10521 
10522#define TLS_RECHDR_SIZE 5 // 1 byte type, 2 bytes version, 2 bytes length
10523#define TLS_MSGHDR_SIZE 4 // 1 byte type, 3 bytes length
10524 
10525#ifdef MG_TLS_SSLKEYLOGFILE
10526#include <stdio.h>
10527static void mg_ssl_key_log(const char *label, uint8_t client_random[32],
10528 uint8_t *secret, size_t secretsz) {
10529 char *keylogfile = getenv("SSLKEYLOGFILE");
10530 size_t i;
10531 if (keylogfile != NULL) {
10532 MG_DEBUG(("Dumping key log into %s", keylogfile));
10533 FILE *f = fopen(keylogfile, "a");
10534 if (f != NULL) {
10535 fprintf(f, "%s ", label);
10536 for (i = 0; i < 32; i++) {
10537 fprintf(f, "%02x", client_random[i]);
10538 }
10539 fprintf(f, " ");
10540 for (i = 0; i < secretsz; i++) {
10541 fprintf(f, "%02x", secret[i]);
10542 }
10543 fprintf(f, "\n");
10544 fclose(f);
10545 } else {
10546 MG_ERROR(("Cannot open %s", keylogfile));
10547 }
10548 }
10549}
10550#endif
10551 
10552// for derived tls keys we need SHA256([0]*32)
10553static uint8_t zeros[32] = {0};
10554static uint8_t zeros_sha256_digest[32] = {
10555 0xe3, 0xb0, 0xc4, 0x42, 0x98, 0xfc, 0x1c, 0x14, 0x9a, 0xfb, 0xf4,
10556 0xc8, 0x99, 0x6f, 0xb9, 0x24, 0x27, 0xae, 0x41, 0xe4, 0x64, 0x9b,
10557 0x93, 0x4c, 0xa4, 0x95, 0x99, 0x1b, 0x78, 0x52, 0xb8, 0x55};
10558 
10559// helper to hexdump buffers inline
10560static void mg_tls_hexdump(const char *msg, uint8_t *buf, size_t bufsz) {
10561 MG_VERBOSE(("%s: %M", msg, mg_print_hex, bufsz, buf));
10562}
10563 
10564// helper utilities to parse ASN.1 DER
10565struct mg_der_tlv {
10566 uint8_t type;
10567 uint32_t len;
10568 uint8_t *value;
10569};
10570 
10571static int mg_der_parse(uint8_t *der, size_t dersz, struct mg_der_tlv *tlv) {
10572 size_t header_len = 2;
10573 uint32_t len = dersz < 2 ? 0 : der[1];
10574 if (dersz < 2) return -1; // Invalid DER
10575 tlv->type = der[0];
10576 if (len > 0x7F) { // long-form length
10577 uint8_t len_bytes = len & 0x7F;
10578 if (dersz < (size_t) (2 + len_bytes)) return -1;
10579 len = 0;
10580 for (uint8_t i = 0; i < len_bytes; i++) {
10581 len = (len << 8) | der[2 + i];
10582 }
10583 header_len += len_bytes;
10584 }
10585 if (dersz < header_len + len) return -1;
10586 tlv->len = len;
10587 tlv->value = der + header_len;
10588 return (int) (header_len + len);
10589}
10590 
10591static int mg_der_next(struct mg_der_tlv *parent, struct mg_der_tlv *child) {
10592 if (parent->len == 0) return 0;
10593 int consumed = mg_der_parse(parent->value, parent->len, child);
10594 if (consumed < 0) return -1;
10595 parent->value += consumed;
10596 parent->len -= (uint32_t) consumed;
10597 return 1;
10598}
10599 
10600static int mg_der_find_oid(struct mg_der_tlv *tlv, const uint8_t *oid,
10601 size_t oid_len, struct mg_der_tlv *found) {
10602 struct mg_der_tlv parent, child;
10603 parent = *tlv;
10604 while (mg_der_next(&parent, &child) > 0) {
10605 if (child.type == 0x06 && child.len == oid_len &&
10606 memcmp(child.value, oid, oid_len) == 0) {
10607 return mg_der_next(&parent, found);
10608 } else if (child.type & 0x20) {
10609 struct mg_der_tlv sub_parent = child;
10610 if (mg_der_find_oid(&sub_parent, oid, oid_len, found)) return 1;
10611 }
10612 }
10613 return 0;
10614}
10615 
10616#if 0
10617static void mg_der_debug(struct mg_der_tlv *tlv, int depth) {
10618 MG_DEBUG(("> %.*sd=%d Type: 0x%02X, Length: %u\n", depth * 4, " ", depth,
10619 tlv->type, tlv->len));
10620 
10621 if (tlv->type & 0x20) { // Constructed: recurse into children
10622 struct mg_der_tlv child;
10623 struct mg_der_tlv parent = *tlv;
10624 while (mg_der_next(&parent, &child) > 0) {
10625 mg_der_debug(&child, depth + 1);
10626 }
10627 }
10628}
10629#endif
10630 
10631// parse DER into a TLV record
10632static int mg_der_to_tlv(uint8_t *der, size_t dersz, struct mg_der_tlv *tlv) {
10633 if (dersz < 2) {
10634 return -1;
10635 }
10636 tlv->type = der[0];
10637 tlv->len = der[1];
10638 tlv->value = der + 2;
10639 if (tlv->len > 0x7f) {
10640 uint32_t i, n = tlv->len - 0x80;
10641 tlv->len = 0;
10642 for (i = 0; i < n; i++) {
10643 tlv->len = (tlv->len << 8) | (der[2 + i]);
10644 }
10645 tlv->value = der + 2 + n;
10646 }
10647 if (der + dersz < tlv->value + tlv->len) {
10648 return -1;
10649 }
10650 return 0;
10651}
10652 
10653// Did we receive a full TLS record in the c->rtls buffer?
10654static bool mg_tls_got_record(struct mg_connection *c) {
10655 return c->rtls.len >= (size_t) TLS_RECHDR_SIZE &&
10656 c->rtls.len >=
10657 (size_t) (TLS_RECHDR_SIZE + MG_LOAD_BE16(c->rtls.buf + 3));
10658}
10659 
10660// Remove a single TLS record from the recv buffer
10661static void mg_tls_drop_record(struct mg_connection *c) {
10662 struct mg_iobuf *rio = &c->rtls;
10663 uint16_t n = MG_LOAD_BE16(rio->buf + 3) + TLS_RECHDR_SIZE;
10664 mg_iobuf_del(rio, 0, n);
10665}
10666 
10667// Remove a single TLS message from decrypted buffer, remove the wrapping
10668// record if it was the last message within a record
10669static void mg_tls_drop_message(struct mg_connection *c) {
10670 uint32_t len;
10671 struct tls_data *tls = (struct tls_data *) c->tls;
10672 unsigned char *recv_buf = &c->rtls.buf[tls->recv_offset];
10673 if (tls->recv_len == 0) return;
10674 len = MG_LOAD_BE24(recv_buf + 1) + TLS_MSGHDR_SIZE;
10675 if (tls->recv_len < len) {
10676 mg_error(c, "wrong size");
10677 return;
10678 }
10679 mg_sha256_update(&tls->sha256, recv_buf, len);
10680 tls->recv_offset += len;
10681 tls->recv_len -= len;
10682 if (tls->recv_len == 0) {
10683 mg_tls_drop_record(c);
10684 }
10685}
10686 
10687// TLS1.3 secret derivation based on the key label
10688static void mg_tls_derive_secret(const char *label, uint8_t *key, size_t keysz,
10689 uint8_t *data, size_t datasz, uint8_t *hash,
10690 size_t hashsz) {
10691 size_t labelsz = strlen(label);
10692 uint8_t secret[32];
10693 uint8_t packed[256] = {0, (uint8_t) hashsz, (uint8_t) labelsz};
10694 // TODO: assert lengths of label, key, data and hash
10695 if (labelsz > 0) memmove(packed + 3, label, labelsz);
10696 packed[3 + labelsz] = (uint8_t) datasz;
10697 if (datasz > 0) memmove(packed + labelsz + 4, data, datasz);
10698 packed[4 + labelsz + datasz] = 1;
10699 
10700 mg_hmac_sha256(secret, key, keysz, packed, 5 + labelsz + datasz);
10701 memmove(hash, secret, hashsz);
10702}
10703 
10704// at this point we have x25519 shared secret, we can generate a set of derived
10705// handshake encryption keys
10706static void mg_tls_generate_handshake_keys(struct mg_connection *c) {
10707 struct tls_data *tls = (struct tls_data *) c->tls;
10708 
10709 mg_sha256_ctx sha256;
10710 uint8_t early_secret[32];
10711 uint8_t pre_extract_secret[32];
10712 uint8_t hello_hash[32];
10713 uint8_t server_hs_secret[32];
10714 uint8_t client_hs_secret[32];
10715#if CHACHA20
10716 const size_t keysz = 32;
10717#else
10718 const size_t keysz = 16;
10719#endif
10720 
10721 mg_hmac_sha256(early_secret, NULL, 0, zeros, sizeof(zeros));
10722 mg_tls_derive_secret("tls13 derived", early_secret, 32, zeros_sha256_digest,
10723 32, pre_extract_secret, 32);
10724 mg_hmac_sha256(tls->enc.handshake_secret, pre_extract_secret,
10725 sizeof(pre_extract_secret), tls->x25519_sec,
10726 sizeof(tls->x25519_sec));
10727 mg_tls_hexdump("hs secret", tls->enc.handshake_secret, 32);
10728 
10729 // mg_sha256_final is not idempotent, need to copy sha256 context to calculate
10730 // the digest
10731 memmove(&sha256, &tls->sha256, sizeof(mg_sha256_ctx));
10732 mg_sha256_final(hello_hash, &sha256);
10733 
10734 mg_tls_hexdump("hello hash", hello_hash, 32);
10735 // derive keys needed for the rest of the handshake
10736 mg_tls_derive_secret("tls13 s hs traffic", tls->enc.handshake_secret, 32,
10737 hello_hash, 32, server_hs_secret, 32);
10738 mg_tls_derive_secret("tls13 c hs traffic", tls->enc.handshake_secret, 32,
10739 hello_hash, 32, client_hs_secret, 32);
10740 
10741 mg_tls_derive_secret("tls13 key", server_hs_secret, 32, NULL, 0,
10742 tls->enc.server_write_key, keysz);
10743 mg_tls_derive_secret("tls13 iv", server_hs_secret, 32, NULL, 0,
10744 tls->enc.server_write_iv, 12);
10745 mg_tls_derive_secret("tls13 finished", server_hs_secret, 32, NULL, 0,
10746 tls->enc.server_finished_key, 32);
10747 
10748 mg_tls_derive_secret("tls13 key", client_hs_secret, 32, NULL, 0,
10749 tls->enc.client_write_key, keysz);
10750 mg_tls_derive_secret("tls13 iv", client_hs_secret, 32, NULL, 0,
10751 tls->enc.client_write_iv, 12);
10752 mg_tls_derive_secret("tls13 finished", client_hs_secret, 32, NULL, 0,
10753 tls->enc.client_finished_key, 32);
10754 
10755 mg_tls_hexdump("s hs traffic", server_hs_secret, 32);
10756 mg_tls_hexdump("s key", tls->enc.server_write_key, keysz);
10757 mg_tls_hexdump("s iv", tls->enc.server_write_iv, 12);
10758 mg_tls_hexdump("s finished", tls->enc.server_finished_key, 32);
10759 mg_tls_hexdump("c hs traffic", client_hs_secret, 32);
10760 mg_tls_hexdump("c key", tls->enc.client_write_key, keysz);
10761 mg_tls_hexdump("c iv", tls->enc.client_write_iv, 12);
10762 mg_tls_hexdump("c finished", tls->enc.client_finished_key, 32);
10763 
10764#ifdef MG_TLS_SSLKEYLOGFILE
10765 mg_ssl_key_log("SERVER_HANDSHAKE_TRAFFIC_SECRET", tls->random,
10766 server_hs_secret, 32);
10767 mg_ssl_key_log("CLIENT_HANDSHAKE_TRAFFIC_SECRET", tls->random,
10768 client_hs_secret, 32);
10769#endif
10770}
10771 
10772static void mg_tls_generate_application_keys(struct mg_connection *c) {
10773 struct tls_data *tls = (struct tls_data *) c->tls;
10774 uint8_t hash[32];
10775 uint8_t premaster_secret[32];
10776 uint8_t master_secret[32];
10777 uint8_t server_secret[32];
10778 uint8_t client_secret[32];
10779#if CHACHA20
10780 const size_t keysz = 32;
10781#else
10782 const size_t keysz = 16;
10783#endif
10784 
10785 mg_sha256_ctx sha256;
10786 memmove(&sha256, &tls->sha256, sizeof(mg_sha256_ctx));
10787 mg_sha256_final(hash, &sha256);
10788 
10789 mg_tls_derive_secret("tls13 derived", tls->enc.handshake_secret, 32,
10790 zeros_sha256_digest, 32, premaster_secret, 32);
10791 mg_hmac_sha256(master_secret, premaster_secret, 32, zeros, 32);
10792 
10793 mg_tls_derive_secret("tls13 s ap traffic", master_secret, 32, hash, 32,
10794 server_secret, 32);
10795 mg_tls_derive_secret("tls13 key", server_secret, 32, NULL, 0,
10796 tls->enc.server_write_key, keysz);
10797 mg_tls_derive_secret("tls13 iv", server_secret, 32, NULL, 0,
10798 tls->enc.server_write_iv, 12);
10799 mg_tls_derive_secret("tls13 c ap traffic", master_secret, 32, hash, 32,
10800 client_secret, 32);
10801 mg_tls_derive_secret("tls13 key", client_secret, 32, NULL, 0,
10802 tls->enc.client_write_key, keysz);
10803 mg_tls_derive_secret("tls13 iv", client_secret, 32, NULL, 0,
10804 tls->enc.client_write_iv, 12);
10805 
10806 mg_tls_hexdump("s ap traffic", server_secret, 32);
10807 mg_tls_hexdump("s key", tls->enc.server_write_key, keysz);
10808 mg_tls_hexdump("s iv", tls->enc.server_write_iv, 12);
10809 mg_tls_hexdump("s finished", tls->enc.server_finished_key, 32);
10810 mg_tls_hexdump("c ap traffic", client_secret, 32);
10811 mg_tls_hexdump("c key", tls->enc.client_write_key, keysz);
10812 mg_tls_hexdump("c iv", tls->enc.client_write_iv, 12);
10813 mg_tls_hexdump("c finished", tls->enc.client_finished_key, 32);
10814 tls->enc.sseq = tls->enc.cseq = 0;
10815 
10816#ifdef MG_TLS_SSLKEYLOGFILE
10817 mg_ssl_key_log("SERVER_TRAFFIC_SECRET_0", tls->random, server_secret, 32);
10818 mg_ssl_key_log("CLIENT_TRAFFIC_SECRET_0", tls->random, client_secret, 32);
10819#endif
10820}
10821 
10822// AES GCM encryption of the message + put encoded data into the write buffer
10823static void mg_tls_encrypt(struct mg_connection *c, const uint8_t *msg,
10824 size_t msgsz, uint8_t msgtype) {
10825 struct tls_data *tls = (struct tls_data *) c->tls;
10826 struct mg_iobuf *wio = &tls->send;
10827 uint8_t *outmsg;
10828 uint8_t *tag;
10829 size_t encsz = msgsz + 16 + 1;
10830 uint8_t hdr[5] = {MG_TLS_APP_DATA, 0x03, 0x03,
10831 (uint8_t) ((encsz >> 8) & 0xff), (uint8_t) (encsz & 0xff)};
10832 uint8_t associated_data[5] = {MG_TLS_APP_DATA, 0x03, 0x03,
10833 (uint8_t) ((encsz >> 8) & 0xff),
10834 (uint8_t) (encsz & 0xff)};
10835 uint8_t nonce[12];
10836 
10837 uint32_t seq = c->is_client ? tls->enc.cseq : tls->enc.sseq;
10838 uint8_t *key =
10839 c->is_client ? tls->enc.client_write_key : tls->enc.server_write_key;
10840 uint8_t *iv =
10841 c->is_client ? tls->enc.client_write_iv : tls->enc.server_write_iv;
10842 
10843#if !CHACHA20
10844 mg_gcm_initialize();
10845#endif
10846 
10847 memmove(nonce, iv, sizeof(nonce));
10848 nonce[8] ^= (uint8_t) ((seq >> 24) & 255U);
10849 nonce[9] ^= (uint8_t) ((seq >> 16) & 255U);
10850 nonce[10] ^= (uint8_t) ((seq >> 8) & 255U);
10851 nonce[11] ^= (uint8_t) ((seq) &255U);
10852 
10853 mg_iobuf_add(wio, wio->len, hdr, sizeof(hdr));
10854 mg_iobuf_resize(wio, wio->len + encsz);
10855 outmsg = wio->buf + wio->len;
10856 tag = wio->buf + wio->len + msgsz + 1;
10857 memmove(outmsg, msg, msgsz);
10858 outmsg[msgsz] = msgtype;
10859#if CHACHA20
10860 (void) tag; // tag is only used in aes gcm
10861 {
10862 size_t maxlen = MG_IO_SIZE > 16384 ? 16384 : MG_IO_SIZE;
10863 uint8_t *enc = (uint8_t *) calloc(1, maxlen + 256 + 1);
10864 if (enc == NULL) {
10865 mg_error(c, "TLS OOM");
10866 return;
10867 } else {
10868 size_t n = mg_chacha20_poly1305_encrypt(enc, key, nonce, associated_data,
10869 sizeof(associated_data), outmsg,
10870 msgsz + 1);
10871 memmove(outmsg, enc, n);
10872 free(enc);
10873 }
10874 }
10875#else
10876 mg_aes_gcm_encrypt(outmsg, outmsg, msgsz + 1, key, 16, nonce, sizeof(nonce),
10877 associated_data, sizeof(associated_data), tag, 16);
10878#endif
10879 c->is_client ? tls->enc.cseq++ : tls->enc.sseq++;
10880 wio->len += encsz;
10881}
10882 
10883// read an encrypted record, decrypt it in place
10884static int mg_tls_recv_record(struct mg_connection *c) {
10885 struct tls_data *tls = (struct tls_data *) c->tls;
10886 struct mg_iobuf *rio = &c->rtls;
10887 uint16_t msgsz;
10888 uint8_t *msg;
10889 uint8_t nonce[12];
10890 int r;
10891 
10892 uint32_t seq = c->is_client ? tls->enc.sseq : tls->enc.cseq;
10893 uint8_t *key =
10894 c->is_client ? tls->enc.server_write_key : tls->enc.client_write_key;
10895 uint8_t *iv =
10896 c->is_client ? tls->enc.server_write_iv : tls->enc.client_write_iv;
10897 
10898 if (tls->recv_len > 0) {
10899 return 0; /* some data from previous record is still present */
10900 }
10901 for (;;) {
10902 if (!mg_tls_got_record(c)) {
10903 return MG_IO_WAIT;
10904 }
10905 if (rio->buf[0] == MG_TLS_APP_DATA) {
10906 break;
10907 } else if (rio->buf[0] ==
10908 MG_TLS_CHANGE_CIPHER) { // Skip ChangeCipher messages
10909 mg_tls_drop_record(c);
10910 } else if (rio->buf[0] == MG_TLS_ALERT) { // Skip Alerts
10911 MG_INFO(("TLS ALERT packet received"));
10912 mg_tls_drop_record(c);
10913 } else {
10914 mg_error(c, "unexpected packet");
10915 return -1;
10916 }
10917 }
10918 
10919 msgsz = MG_LOAD_BE16(rio->buf + 3);
10920 msg = rio->buf + 5;
10921 if (msgsz < 16) {
10922 mg_error(c, "wrong size");
10923 return -1;
10924 }
10925 
10926 memmove(nonce, iv, sizeof(nonce));
10927 nonce[8] ^= (uint8_t) ((seq >> 24) & 255U);
10928 nonce[9] ^= (uint8_t) ((seq >> 16) & 255U);
10929 nonce[10] ^= (uint8_t) ((seq >> 8) & 255U);
10930 nonce[11] ^= (uint8_t) ((seq) &255U);
10931#if CHACHA20
10932 {
10933 uint8_t *dec = (uint8_t *) calloc(1, msgsz);
10934 size_t n;
10935 if (dec == NULL) {
10936 mg_error(c, "TLS OOM");
10937 return -1;
10938 }
10939 n = mg_chacha20_poly1305_decrypt(dec, key, nonce, msg, msgsz);
10940 memmove(msg, dec, n);
10941 free(dec);
10942 }
10943#else
10944 mg_gcm_initialize();
10945 mg_aes_gcm_decrypt(msg, msg, msgsz - 16, key, 16, nonce, sizeof(nonce));
10946#endif
10947 
10948 r = msgsz - 16 - 1;
10949 tls->content_type = msg[msgsz - 16 - 1];
10950 tls->recv_offset = (size_t) msg - (size_t) rio->buf;
10951 tls->recv_len = (size_t) msgsz - 16 - 1;
10952 c->is_client ? tls->enc.sseq++ : tls->enc.cseq++;
10953 return r;
10954}
10955 
10956static void mg_tls_calc_cert_verify_hash(struct mg_connection *c,
10957 uint8_t hash[32], int is_client) {
10958 struct tls_data *tls = (struct tls_data *) c->tls;
10959 uint8_t server_context[34] = "TLS 1.3, server CertificateVerify";
10960 uint8_t client_context[34] = "TLS 1.3, client CertificateVerify";
10961 uint8_t sig_content[130];
10962 mg_sha256_ctx sha256;
10963 
10964 memset(sig_content, 0x20, 64);
10965 if (is_client) {
10966 memmove(sig_content + 64, client_context, sizeof(client_context));
10967 } else {
10968 memmove(sig_content + 64, server_context, sizeof(server_context));
10969 }
10970 
10971 memmove(&sha256, &tls->sha256, sizeof(mg_sha256_ctx));
10972 mg_sha256_final(sig_content + 98, &sha256);
10973 
10974 mg_sha256_init(&sha256);
10975 mg_sha256_update(&sha256, sig_content, sizeof(sig_content));
10976 mg_sha256_final(hash, &sha256);
10977}
10978 
10979// read and parse ClientHello record
10980static int mg_tls_server_recv_hello(struct mg_connection *c) {
10981 struct tls_data *tls = (struct tls_data *) c->tls;
10982 struct mg_iobuf *rio = &c->rtls;
10983 uint8_t session_id_len;
10984 uint16_t j;
10985 uint16_t cipher_suites_len;
10986 uint16_t ext_len;
10987 uint8_t *ext;
10988 uint16_t msgsz;
10989 
10990 if (!mg_tls_got_record(c)) {
10991 return MG_IO_WAIT;
10992 }
10993 if (rio->buf[0] != MG_TLS_HANDSHAKE || rio->buf[5] != MG_TLS_CLIENT_HELLO) {
10994 mg_error(c, "not a client hello packet");
10995 return -1;
10996 }
10997 msgsz = MG_LOAD_BE16(rio->buf + 3);
10998 mg_sha256_update(&tls->sha256, rio->buf + 5, msgsz);
10999 // store client random
11000 memmove(tls->random, rio->buf + 11, sizeof(tls->random));
11001 // store session_id
11002 session_id_len = rio->buf[43];
11003 if (session_id_len == sizeof(tls->session_id)) {
11004 memmove(tls->session_id, rio->buf + 44, session_id_len);
11005 } else if (session_id_len != 0) {
11006 MG_INFO(("bad session id len"));
11007 }
11008 cipher_suites_len = MG_LOAD_BE16(rio->buf + 44 + session_id_len);
11009 if (cipher_suites_len > (rio->len - 46 - session_id_len)) goto fail;
11010 ext_len = MG_LOAD_BE16(rio->buf + 48 + session_id_len + cipher_suites_len);
11011 ext = rio->buf + 50 + session_id_len + cipher_suites_len;
11012 if (ext_len > (rio->len - 50 - session_id_len - cipher_suites_len)) goto fail;
11013 for (j = 0; j < ext_len;) {
11014 uint16_t k;
11015 uint16_t key_exchange_len;
11016 uint8_t *key_exchange;
11017 uint16_t n = MG_LOAD_BE16(ext + j + 2);
11018 if (MG_LOAD_BE16(ext + j) != 0x0033) { // not a key share extension, ignore
11019 j += (uint16_t) (n + 4);
11020 continue;
11021 }
11022 key_exchange_len = MG_LOAD_BE16(ext + j + 4);
11023 key_exchange = ext + j + 6;
11024 if (key_exchange_len >
11025 rio->len - (uint16_t) ((size_t) key_exchange - (size_t) rio->buf))
11026 goto fail;
11027 for (k = 0; k < key_exchange_len;) {
11028 uint16_t m = MG_LOAD_BE16(key_exchange + k + 2);
11029 if (m > (key_exchange_len - k - 4)) goto fail;
11030 if (m == 32 && key_exchange[k] == 0x00 && key_exchange[k + 1] == 0x1d) {
11031 memmove(tls->x25519_cli, key_exchange + k + 4, m);
11032 mg_tls_drop_record(c);
11033 return 0;
11034 }
11035 k += (uint16_t) (m + 4);
11036 }
11037 j += (uint16_t) (n + 4);
11038 }
11039fail:
11040 mg_error(c, "bad client hello");
11041 return -1;
11042}
11043 
11044#define PLACEHOLDER_8B 'X', 'X', 'X', 'X', 'X', 'X', 'X', 'X'
11045#define PLACEHOLDER_16B PLACEHOLDER_8B, PLACEHOLDER_8B
11046#define PLACEHOLDER_32B PLACEHOLDER_16B, PLACEHOLDER_16B
11047 
11048// put ServerHello record into wio buffer
11049static void mg_tls_server_send_hello(struct mg_connection *c) {
11050 struct tls_data *tls = (struct tls_data *) c->tls;
11051 struct mg_iobuf *wio = &tls->send;
11052 
11053 // clang-format off
11054 uint8_t msg_server_hello[122] = {
11055 // server hello, tls 1.2
11056 0x02, 0x00, 0x00, 0x76, 0x03, 0x03,
11057 // random (32 bytes)
11058 PLACEHOLDER_32B,
11059 // session ID length + session ID (32 bytes)
11060 0x20, PLACEHOLDER_32B,
11061#if defined(CHACHA20) && CHACHA20
11062 // TLS_CHACHA20_POLY1305_SHA256 + no compression
11063 0x13, 0x03, 0x00,
11064#else
11065 // TLS_AES_128_GCM_SHA256 + no compression
11066 0x13, 0x01, 0x00,
11067#endif
11068 // extensions + keyshare
11069 0x00, 0x2e, 0x00, 0x33, 0x00, 0x24, 0x00, 0x1d, 0x00, 0x20,
11070 // x25519 keyshare
11071 PLACEHOLDER_32B,
11072 // supported versions (tls1.3 == 0x304)
11073 0x00, 0x2b, 0x00, 0x02, 0x03, 0x04};
11074 // clang-format on
11075 
11076 // calculate keyshare
11077 uint8_t x25519_pub[X25519_BYTES];
11078 uint8_t x25519_prv[X25519_BYTES];
11079 if (!mg_random(x25519_prv, sizeof(x25519_prv))) mg_error(c, "RNG");
11080 mg_tls_x25519(x25519_pub, x25519_prv, X25519_BASE_POINT, 1);
11081 mg_tls_x25519(tls->x25519_sec, x25519_prv, tls->x25519_cli, 1);
11082 mg_tls_hexdump("s x25519 sec", tls->x25519_sec, sizeof(tls->x25519_sec));
11083 
11084 // fill in the gaps: random + session ID + keyshare
11085 memmove(msg_server_hello + 6, tls->random, sizeof(tls->random));
11086 memmove(msg_server_hello + 39, tls->session_id, sizeof(tls->session_id));
11087 memmove(msg_server_hello + 84, x25519_pub, sizeof(x25519_pub));
11088 
11089 // server hello message
11090 mg_iobuf_add(wio, wio->len, "\x16\x03\x03\x00\x7a", 5);
11091 mg_iobuf_add(wio, wio->len, msg_server_hello, sizeof(msg_server_hello));
11092 mg_sha256_update(&tls->sha256, msg_server_hello, sizeof(msg_server_hello));
11093 
11094 // change cipher message
11095 mg_iobuf_add(wio, wio->len, "\x14\x03\x03\x00\x01\x01", 6);
11096}
11097 
11098static void mg_tls_server_send_ext(struct mg_connection *c) {
11099 struct tls_data *tls = (struct tls_data *) c->tls;
11100 // server extensions
11101 uint8_t ext[6] = {0x08, 0, 0, 2, 0, 0};
11102 mg_sha256_update(&tls->sha256, ext, sizeof(ext));
11103 mg_tls_encrypt(c, ext, sizeof(ext), MG_TLS_HANDSHAKE);
11104}
11105 
11106static void mg_tls_server_send_cert(struct mg_connection *c) {
11107 struct tls_data *tls = (struct tls_data *) c->tls;
11108 int send_ca = !c->is_client && tls->ca_der.len > 0;
11109 // server DER certificate + CA (optional)
11110 size_t n = tls->cert_der.len + (send_ca ? tls->ca_der.len + 5 : 0);
11111 uint8_t *cert = (uint8_t *) calloc(1, 13 + n);
11112 if (cert == NULL) {
11113 mg_error(c, "tls cert oom");
11114 return;
11115 }
11116 cert[0] = 0x0b; // handshake header
11117 MG_STORE_BE24(cert + 1, n + 9);
11118 cert[4] = 0; // request context
11119 MG_STORE_BE24(cert + 5, n + 5); // 3 bytes: cert (s) length
11120 MG_STORE_BE24(cert + 8, tls->cert_der.len); // 3 bytes: first cert len
11121 // bytes 11+ are certificate in DER format
11122 memmove(cert + 11, tls->cert_der.buf, tls->cert_der.len);
11123 MG_STORE_BE16(cert + 11 + tls->cert_der.len,
11124 0); // certificate extensions (none)
11125 if (send_ca) {
11126 size_t offset = 13 + tls->cert_der.len;
11127 MG_STORE_BE24(cert + offset, tls->ca_der.len); // 3 bytes: CA cert length
11128 memmove(cert + offset + 3, tls->ca_der.buf,
11129 tls->ca_der.len); // CA cert data
11130 MG_STORE_BE16(cert + 11 + n, 0); // certificate extensions (none)
11131 }
11132 mg_sha256_update(&tls->sha256, cert, 13 + n);
11133 mg_tls_encrypt(c, cert, 13 + n, MG_TLS_HANDSHAKE);
11134 free(cert);
11135}
11136 
11137// type adapter between uECC hash context and our sha256 implementation
11138typedef struct SHA256_HashContext {
11139 MG_UECC_HashContext uECC;
11140 mg_sha256_ctx ctx;
11141} SHA256_HashContext;
11142 
11143static void init_SHA256(const MG_UECC_HashContext *base) {
11144 SHA256_HashContext *c = (SHA256_HashContext *) base;
11145 mg_sha256_init(&c->ctx);
11146}
11147 
11148static void update_SHA256(const MG_UECC_HashContext *base,
11149 const uint8_t *message, unsigned message_size) {
11150 SHA256_HashContext *c = (SHA256_HashContext *) base;
11151 mg_sha256_update(&c->ctx, message, message_size);
11152}
11153static void finish_SHA256(const MG_UECC_HashContext *base,
11154 uint8_t *hash_result) {
11155 SHA256_HashContext *c = (SHA256_HashContext *) base;
11156 mg_sha256_final(hash_result, &c->ctx);
11157}
11158 
11159static void mg_tls_send_cert_verify(struct mg_connection *c, int is_client) {
11160 struct tls_data *tls = (struct tls_data *) c->tls;
11161 // server certificate verify packet
11162 uint8_t verify[82] = {0x0f, 0x00, 0x00, 0x00, 0x04, 0x03, 0x00, 0x00};
11163 size_t sigsz, verifysz = 0;
11164 uint8_t hash[32] = {0}, tmp[2 * 32 + 64] = {0};
11165 struct SHA256_HashContext ctx = {
11166 {&init_SHA256, &update_SHA256, &finish_SHA256, 64, 32, tmp},
11167 {{0}, 0, 0, {0}}};
11168 int neg1, neg2;
11169 uint8_t sig[64] = {0};
11170 
11171 mg_tls_calc_cert_verify_hash(c, (uint8_t *) hash, is_client);
11172 
11173 mg_uecc_sign_deterministic(tls->ec_key, hash, sizeof(hash), &ctx.uECC, sig,
11174 mg_uecc_secp256r1());
11175 
11176 neg1 = !!(sig[0] & 0x80);
11177 neg2 = !!(sig[32] & 0x80);
11178 verify[8] = 0x30; // ASN.1 SEQUENCE
11179 verify[9] = (uint8_t) (68 + neg1 + neg2);
11180 verify[10] = 0x02; // ASN.1 INTEGER
11181 verify[11] = (uint8_t) (32 + neg1);
11182 memmove(verify + 12 + neg1, sig, 32);
11183 verify[12 + 32 + neg1] = 0x02; // ASN.1 INTEGER
11184 verify[13 + 32 + neg1] = (uint8_t) (32 + neg2);
11185 memmove(verify + 14 + 32 + neg1 + neg2, sig + 32, 32);
11186 
11187 sigsz = (size_t) (70 + neg1 + neg2);
11188 verifysz = 8U + sigsz;
11189 verify[3] = (uint8_t) (sigsz + 4);
11190 verify[7] = (uint8_t) sigsz;
11191 
11192 mg_sha256_update(&tls->sha256, verify, verifysz);
11193 mg_tls_encrypt(c, verify, verifysz, MG_TLS_HANDSHAKE);
11194}
11195 
11196static void mg_tls_server_send_finish(struct mg_connection *c) {
11197 struct tls_data *tls = (struct tls_data *) c->tls;
11198 struct mg_iobuf *wio = &tls->send;
11199 mg_sha256_ctx sha256;
11200 uint8_t hash[32];
11201 uint8_t finish[36] = {0x14, 0, 0, 32};
11202 memmove(&sha256, &tls->sha256, sizeof(mg_sha256_ctx));
11203 mg_sha256_final(hash, &sha256);
11204 mg_hmac_sha256(finish + 4, tls->enc.server_finished_key, 32, hash, 32);
11205 mg_tls_encrypt(c, finish, sizeof(finish), MG_TLS_HANDSHAKE);
11206 mg_io_send(c, wio->buf, wio->len);
11207 wio->len = 0;
11208 
11209 mg_sha256_update(&tls->sha256, finish, sizeof(finish));
11210}
11211 
11212static int mg_tls_server_recv_finish(struct mg_connection *c) {
11213 struct tls_data *tls = (struct tls_data *) c->tls;
11214 unsigned char *recv_buf;
11215 // we have to backup sha256 value to restore it later, since Finished record
11216 // is exceptional and is not supposed to be added to the rolling hash
11217 // calculation.
11218 mg_sha256_ctx sha256 = tls->sha256;
11219 if (mg_tls_recv_record(c) < 0) {
11220 return -1;
11221 }
11222 recv_buf = &c->rtls.buf[tls->recv_offset];
11223 if (recv_buf[0] != MG_TLS_FINISHED) {
11224 mg_error(c, "expected Finish but got msg 0x%02x", recv_buf[0]);
11225 return -1;
11226 }
11227 mg_tls_drop_message(c);
11228 
11229 // restore hash
11230 tls->sha256 = sha256;
11231 return 0;
11232}
11233 
11234static void mg_tls_client_send_hello(struct mg_connection *c) {
11235 struct tls_data *tls = (struct tls_data *) c->tls;
11236 struct mg_iobuf *wio = &tls->send;
11237 
11238 uint8_t x25519_pub[X25519_BYTES];
11239 
11240 // signature algorithms we actually support:
11241 // rsa_pkcs1_sha256, rsa_pss_rsae_sha256 and ecdsa_secp256r1_sha256
11242 uint8_t secp256r1_sig_algs[12] = {
11243 0x00, 0x0d, 0x00, 0x08, 0x00, 0x06, 0x04, 0x03, 0x08, 0x04, 0x04, 0x01,
11244 };
11245 // all popular signature algorithms (if we don't care about verification)
11246 uint8_t all_sig_algs[34] = {
11247 0x00, 0x0d, 0x00, 0x1e, 0x00, 0x1c, 0x04, 0x03, 0x05, 0x03, 0x06, 0x03,
11248 0x08, 0x07, 0x08, 0x08, 0x08, 0x09, 0x08, 0x0a, 0x08, 0x0b, 0x08, 0x04,
11249 0x08, 0x05, 0x08, 0x06, 0x04, 0x01, 0x05, 0x01, 0x06, 0x01};
11250 uint8_t server_name_ext[9] = {0x00, 0x00, 0x00, 0xfe, 0x00,
11251 0xfe, 0x00, 0x00, 0xfe};
11252 
11253 // clang-format off
11254 uint8_t msg_client_hello[145] = {
11255 // TLS Client Hello header reported as TLS1.2 (5)
11256 0x16, 0x03, 0x03, 0x00, 0xfe,
11257 // client hello, tls 1.2 (6)
11258 0x01, 0x00, 0x00, 0x8c, 0x03, 0x03,
11259 // random (32 bytes)
11260 PLACEHOLDER_32B,
11261 // session ID length + session ID (32 bytes)
11262 0x20, PLACEHOLDER_32B, 0x00,
11263 0x02, // size = 2 bytes
11264#if defined(CHACHA20) && CHACHA20
11265 // TLS_CHACHA20_POLY1305_SHA256
11266 0x13, 0x03,
11267#else
11268 // TLS_AES_128_GCM_SHA256
11269 0x13, 0x01,
11270#endif
11271 // no compression
11272 0x01, 0x00,
11273 // extensions + keyshare
11274 0x00, 0xfe,
11275 // x25519 keyshare
11276 0x00, 0x33, 0x00, 0x26, 0x00, 0x24, 0x00, 0x1d, 0x00, 0x20,
11277 PLACEHOLDER_32B,
11278 // supported groups (x25519)
11279 0x00, 0x0a, 0x00, 0x04, 0x00, 0x02, 0x00, 0x1d,
11280 // supported versions (tls1.3 == 0x304)
11281 0x00, 0x2b, 0x00, 0x03, 0x02, 0x03, 0x04,
11282 // session ticket (none)
11283 0x00, 0x23, 0x00, 0x00, // 144 bytes till here
11284 };
11285 // clang-format on
11286 const char *hostname = tls->hostname;
11287 size_t hostnamesz = strlen(tls->hostname);
11288 size_t hostname_extsz = hostnamesz ? hostnamesz + 9 : 0;
11289 uint8_t *sig_alg = tls->skip_verification ? all_sig_algs : secp256r1_sig_algs;
11290 size_t sig_alg_sz = tls->skip_verification ? sizeof(all_sig_algs)
11291 : sizeof(secp256r1_sig_algs);
11292 
11293 // patch ClientHello with correct hostname ext length (if any)
11294 MG_STORE_BE16(msg_client_hello + 3,
11295 hostname_extsz + 183 - 9 - 34 + sig_alg_sz);
11296 MG_STORE_BE16(msg_client_hello + 7,
11297 hostname_extsz + 179 - 9 - 34 + sig_alg_sz);
11298 MG_STORE_BE16(msg_client_hello + 82,
11299 hostname_extsz + 104 - 9 - 34 + sig_alg_sz);
11300 
11301 if (hostnamesz > 0) {
11302 MG_STORE_BE16(server_name_ext + 2, hostnamesz + 5);
11303 MG_STORE_BE16(server_name_ext + 4, hostnamesz + 3);
11304 MG_STORE_BE16(server_name_ext + 7, hostnamesz);
11305 }
11306 
11307 // calculate keyshare
11308 if (!mg_random(tls->x25519_cli, sizeof(tls->x25519_cli))) mg_error(c, "RNG");
11309 mg_tls_x25519(x25519_pub, tls->x25519_cli, X25519_BASE_POINT, 1);
11310 
11311 // fill in the gaps: random + session ID + keyshare
11312 if (!mg_random(tls->session_id, sizeof(tls->session_id))) mg_error(c, "RNG");
11313 if (!mg_random(tls->random, sizeof(tls->random))) mg_error(c, "RNG");
11314 memmove(msg_client_hello + 11, tls->random, sizeof(tls->random));
11315 memmove(msg_client_hello + 44, tls->session_id, sizeof(tls->session_id));
11316 memmove(msg_client_hello + 94, x25519_pub, sizeof(x25519_pub));
11317 
11318 // client hello message
11319 mg_iobuf_add(wio, wio->len, msg_client_hello, sizeof(msg_client_hello));
11320 mg_sha256_update(&tls->sha256, msg_client_hello + 5,
11321 sizeof(msg_client_hello) - 5);
11322 mg_iobuf_add(wio, wio->len, sig_alg, sig_alg_sz);
11323 mg_sha256_update(&tls->sha256, sig_alg, sig_alg_sz);
11324 if (hostnamesz > 0) {
11325 mg_iobuf_add(wio, wio->len, server_name_ext, sizeof(server_name_ext));
11326 mg_iobuf_add(wio, wio->len, hostname, hostnamesz);
11327 mg_sha256_update(&tls->sha256, server_name_ext, sizeof(server_name_ext));
11328 mg_sha256_update(&tls->sha256, (uint8_t *) hostname, hostnamesz);
11329 }
11330 
11331 // change cipher message
11332 mg_iobuf_add(wio, wio->len, (const char *) "\x14\x03\x03\x00\x01\x01", 6);
11333 mg_io_send(c, wio->buf, wio->len);
11334 wio->len = 0;
11335}
11336 
11337static int mg_tls_client_recv_hello(struct mg_connection *c) {
11338 struct tls_data *tls = (struct tls_data *) c->tls;
11339 struct mg_iobuf *rio = &c->rtls;
11340 uint16_t msgsz;
11341 uint8_t *ext;
11342 uint16_t ext_len;
11343 int j;
11344 
11345 if (!mg_tls_got_record(c)) {
11346 return MG_IO_WAIT;
11347 }
11348 if (rio->buf[0] != MG_TLS_HANDSHAKE || rio->buf[5] != MG_TLS_SERVER_HELLO) {
11349 if (rio->buf[0] == MG_TLS_ALERT && rio->len >= 7) {
11350 mg_error(c, "tls alert %d", rio->buf[6]);
11351 return -1;
11352 }
11353 MG_INFO(("got packet type 0x%02x/0x%02x", rio->buf[0], rio->buf[5]));
11354 mg_error(c, "not a server hello packet");
11355 return -1;
11356 }
11357 
11358 msgsz = MG_LOAD_BE16(rio->buf + 3);
11359 mg_sha256_update(&tls->sha256, rio->buf + 5, msgsz);
11360 
11361 ext_len = MG_LOAD_BE16(rio->buf + 5 + 39 + 32 + 3);
11362 ext = rio->buf + 5 + 39 + 32 + 3 + 2;
11363 if (ext_len > (rio->len - (5 + 39 + 32 + 3 + 2))) goto fail;
11364 
11365 for (j = 0; j < ext_len;) {
11366 uint16_t ext_type = MG_LOAD_BE16(ext + j);
11367 uint16_t ext_len2 = MG_LOAD_BE16(ext + j + 2);
11368 uint16_t group;
11369 uint8_t *key_exchange;
11370 uint16_t key_exchange_len;
11371 if (ext_len2 > (ext_len - j - 4)) goto fail;
11372 if (ext_type != 0x0033) { // not a key share extension, ignore
11373 j += (uint16_t) (ext_len2 + 4);
11374 continue;
11375 }
11376 group = MG_LOAD_BE16(ext + j + 4);
11377 if (group != 0x001d) {
11378 mg_error(c, "bad key exchange group");
11379 return -1;
11380 }
11381 key_exchange_len = MG_LOAD_BE16(ext + j + 6);
11382 key_exchange = ext + j + 8;
11383 if (key_exchange_len != 32) {
11384 mg_error(c, "bad key exchange length");
11385 return -1;
11386 }
11387 mg_tls_x25519(tls->x25519_sec, tls->x25519_cli, key_exchange, 1);
11388 mg_tls_hexdump("c x25519 sec", tls->x25519_sec, 32);
11389 mg_tls_drop_record(c);
11390 /* generate handshake keys */
11391 mg_tls_generate_handshake_keys(c);
11392 return 0;
11393 }
11394fail:
11395 mg_error(c, "bad server hello");
11396 return -1;
11397}
11398 
11399static int mg_tls_client_recv_ext(struct mg_connection *c) {
11400 struct tls_data *tls = (struct tls_data *) c->tls;
11401 unsigned char *recv_buf;
11402 if (mg_tls_recv_record(c) < 0) {
11403 return -1;
11404 }
11405 recv_buf = &c->rtls.buf[tls->recv_offset];
11406 if (recv_buf[0] != MG_TLS_ENCRYPTED_EXTENSIONS) {
11407 mg_error(c, "expected server extensions but got msg 0x%02x", recv_buf[0]);
11408 return -1;
11409 }
11410 mg_tls_drop_message(c);
11411 return 0;
11412}
11413 
11414struct mg_tls_cert {
11415 int is_ec_pubkey;
11416 struct mg_str sn;
11417 struct mg_str pubkey;
11418 struct mg_str sig; // signature
11419 uint8_t tbshash[48]; // 32b for sha256/secp256, 48b for sha384/secp384
11420 size_t tbshashsz; // actual TBS hash size
11421};
11422 
11423static void mg_der_debug_cert_name(const char *name, struct mg_der_tlv *tlv) {
11424 struct mg_der_tlv v;
11425 struct mg_str cn, c, o, ou;
11426 cn = c = o = ou = mg_str("");
11427 if (mg_der_find_oid(tlv, (uint8_t *) "\x55\x04\x03", 3, &v))
11428 cn = mg_str_n((const char *) v.value, v.len);
11429 if (mg_der_find_oid(tlv, (uint8_t *) "\x55\x04\x06", 3, &v))
11430 c = mg_str_n((const char *) v.value, v.len);
11431 if (mg_der_find_oid(tlv, (uint8_t *) "\x55\x04\x0a", 3, &v))
11432 o = mg_str_n((const char *) v.value, v.len);
11433 if (mg_der_find_oid(tlv, (uint8_t *) "\x55\x04\x0b", 3, &v))
11434 ou = mg_str_n((const char *) v.value, v.len);
11435 MG_VERBOSE(("%s: CN=%.*s, C=%.*s, O=%.*s, OU=%.*s", name, cn.len, cn.buf,
11436 c.len, c.buf, o.len, o.buf, ou.len, ou.buf));
11437}
11438 
11439static int mg_tls_parse_cert_der(void *buf, size_t dersz,
11440 struct mg_tls_cert *cert) {
11441 uint8_t *tbs, *der = (uint8_t *) buf;
11442 size_t tbssz;
11443 struct mg_der_tlv root, tbs_cert, field, algo; // pubkey, signature;
11444 struct mg_der_tlv pki, pki_algo, pki_key, pki_curve, raw_sig;
11445 
11446 // Parse outermost SEQUENCE
11447 if (mg_der_parse(der, dersz, &root) <= 0 || root.type != 0x30) return -1;
11448 
11449 // Parse TBSCertificate SEQUENCE
11450 tbs = root.value;
11451 if (mg_der_next(&root, &tbs_cert) <= 0 || tbs_cert.type != 0x30) return -1;
11452 tbssz = (size_t) (tbs_cert.value + tbs_cert.len - tbs);
11453 
11454 // Parse Version (optional field)
11455 if (mg_der_next(&tbs_cert, &field) <= 0) return -1;
11456 if (field.type == 0xa0) { // v3
11457 if (mg_der_parse(field.value, field.len, &field) <= 0 || field.len != 1 ||
11458 field.value[0] != 2)
11459 return -1;
11460 if (mg_der_next(&tbs_cert, &field) <= 0) return -1;
11461 }
11462 
11463 // Parse Serial Number
11464 if (field.type != 2) return -1;
11465 cert->sn = mg_str_n((char *) field.value, field.len);
11466 MG_VERBOSE(("cert s/n: %M", mg_print_hex, cert->sn.len, cert->sn.buf));
11467 
11468 // Parse signature algorithm (first occurrence)
11469 if (mg_der_next(&tbs_cert, &field) <= 0 || field.type != 0x30) return -1;
11470 if (mg_der_next(&field, &algo) <= 0 || algo.type != 0x06) return -1;
11471 
11472 MG_VERBOSE(("sig algo (oid): %M", mg_print_hex, algo.len, algo.value));
11473 // Signature algorithm OID mapping
11474 if (memcmp(algo.value, "\x2A\x86\x48\xCE\x3D\x04\x03\x02", algo.len) == 0) {
11475 MG_VERBOSE(("sig algo: ECDSA with SHA256"));
11476 mg_sha256(cert->tbshash, tbs, tbssz);
11477 cert->tbshashsz = 32;
11478 } else if (memcmp(algo.value, "\x2A\x86\x48\x86\xF7\x0D\x01\x01\x0B",
11479 algo.len) == 0) {
11480 MG_VERBOSE(("sig algo: RSA with SHA256"));
11481 mg_sha256(cert->tbshash, tbs, tbssz);
11482 cert->tbshashsz = 32;
11483 } else if (memcmp(algo.value, "\x2A\x86\x48\xCE\x3D\x04\x03\x03", algo.len) ==
11484 0) {
11485 MG_VERBOSE(("sig algo: ECDSA with SHA384"));
11486 mg_sha384(cert->tbshash, tbs, tbssz);
11487 cert->tbshashsz = 48;
11488 } else if (memcmp(algo.value, "\x2A\x86\x48\x86\xF7\x0D\x01\x01\x0C",
11489 algo.len) == 0) {
11490 MG_VERBOSE(("sig algo: RSA with SHA384"));
11491 mg_sha384(cert->tbshash, tbs, tbssz);
11492 cert->tbshashsz = 48;
11493 } else {
11494 MG_ERROR(
11495 ("sig algo: unsupported OID: %M", mg_print_hex, algo.len, algo.value));
11496 return -1;
11497 }
11498 MG_VERBOSE(("tbs hash: %M", mg_print_hex, cert->tbshashsz, cert->tbshash));
11499 
11500 // issuer
11501 if (mg_der_next(&tbs_cert, &field) <= 0 || field.type != 0x30) return -1;
11502 mg_der_debug_cert_name("issuer", &field);
11503 
11504 // validity dates (before/after)
11505 if (mg_der_next(&tbs_cert, &field) <= 0 || field.type != 0x30) return -1;
11506 if (1) {
11507 struct mg_der_tlv before, after;
11508 mg_der_next(&field, &before);
11509 mg_der_next(&field, &after);
11510 if (memcmp(after.value, "250101000000Z", after.len) < 0) {
11511 MG_ERROR(("invalid validity dates: before=%M after=%M", mg_print_hex,
11512 before.len, before.value, mg_print_hex, after.len,
11513 after.value));
11514 return -1;
11515 }
11516 }
11517 
11518 // subject
11519 if (mg_der_next(&tbs_cert, &field) <= 0 || field.type != 0x30) return -1;
11520 mg_der_debug_cert_name("subject", &field);
11521 
11522 // subject public key info
11523 if (mg_der_next(&tbs_cert, &field) <= 0 || field.type != 0x30) return -1;
11524 
11525 if (mg_der_next(&field, &pki) <= 0 || pki.type != 0x30) return -1;
11526 if (mg_der_next(&pki, &pki_algo) <= 0 || pki_algo.type != 0x06) return -1;
11527 
11528 // public key algorithm
11529 MG_VERBOSE(("pk algo (oid): %M", mg_print_hex, pki_algo.len, pki_algo.value));
11530 if (memcmp(pki_algo.value, "\x2A\x86\x48\xCE\x3D\x03\x01\x07",
11531 pki_algo.len) == 0) {
11532 cert->is_ec_pubkey = 1;
11533 MG_VERBOSE(("pk algo: ECDSA secp256r1"));
11534 } else if (memcmp(pki_algo.value, "\x2A\x86\x48\xCE\x3D\x03\x01\x08",
11535 pki_algo.len) == 0) {
11536 cert->is_ec_pubkey = 1;
11537 MG_VERBOSE(("pk algo: ECDSA secp384r1"));
11538 } else if (memcmp(pki_algo.value, "\x2A\x86\x48\xCE\x3D\x02\x01",
11539 pki_algo.len) == 0) {
11540 cert->is_ec_pubkey = 1;
11541 MG_VERBOSE(("pk algo: EC public key"));
11542 } else if (memcmp(pki_algo.value, "\x2A\x86\x48\x86\xF7\x0D\x01\x01\x01",
11543 pki_algo.len) == 0) {
11544 cert->is_ec_pubkey = 0;
11545 MG_VERBOSE(("pk algo: RSA"));
11546 } else {
11547 MG_ERROR(("unsupported pk algo: %M", mg_print_hex, pki_algo.len,
11548 pki_algo.value));
11549 return -1;
11550 }
11551 
11552 // Parse public key
11553 if (cert->is_ec_pubkey) {
11554 if (mg_der_next(&pki, &pki_curve) <= 0 || pki_curve.type != 0x06) return -1;
11555 }
11556 if (mg_der_next(&field, &pki_key) <= 0 || pki_key.type != 0x03) return -1;
11557 
11558 if (cert->is_ec_pubkey) { // Skip leading 0x00 and 0x04 (=uncompressed)
11559 cert->pubkey = mg_str_n((char *) pki_key.value + 2, pki_key.len - 2);
11560 } else { // Skip leading 0x00 byte
11561 cert->pubkey = mg_str_n((char *) pki_key.value + 1, pki_key.len - 1);
11562 }
11563 
11564 // Parse signature
11565 if (mg_der_next(&root, &field) <= 0 || field.type != 0x30) return -1;
11566 if (mg_der_next(&root, &raw_sig) <= 0 || raw_sig.type != 0x03) return -1;
11567 if (raw_sig.len < 1 || raw_sig.value[0] != 0x00) return -1;
11568 
11569 cert->sig = mg_str_n((char *) raw_sig.value + 1, raw_sig.len - 1);
11570 MG_VERBOSE(("sig: %M", mg_print_hex, cert->sig.len, cert->sig.buf));
11571 
11572 return 0;
11573}
11574 
11575static int mg_tls_verify_cert_san(const uint8_t *der, size_t dersz,
11576 const char *server_name) {
11577 struct mg_der_tlv root, field, name;
11578 if (mg_der_parse((uint8_t *) der, dersz, &root) < 0 ||
11579 mg_der_find_oid(&root, (uint8_t *) "\x55\x1d\x11", 3, &field) < 0) {
11580 MG_ERROR(("failed to parse certificate to extract SAN"));
11581 return -1;
11582 }
11583 if (mg_der_parse(field.value, field.len, &field) < 0) {
11584 MG_ERROR(
11585 ("certificate subject alternative names is not a constructed object"));
11586 return -1;
11587 }
11588 while (mg_der_next(&field, &name) > 0) {
11589 if (mg_match(mg_str(server_name),
11590 mg_str_n((const char *) name.value, name.len), NULL)) {
11591 // Found SAN that matches the host name
11592 return 1;
11593 }
11594 }
11595 return -1;
11596}
11597 
11598static int mg_tls_verify_cert_signature(const struct mg_tls_cert *cert,
11599 const struct mg_tls_cert *issuer) {
11600 if (issuer->is_ec_pubkey) {
11601 uint8_t sig[128];
11602 struct mg_der_tlv seq = {0, 0, 0}, a = {0, 0, 0}, b = {0, 0, 0};
11603 mg_der_parse((uint8_t *) cert->sig.buf, cert->sig.len, &seq);
11604 mg_der_next(&seq, &a);
11605 mg_der_next(&seq, &b);
11606 if (a.len == 0 || b.len == 0) {
11607 MG_ERROR(("cert verification error"));
11608 return 0;
11609 }
11610 if (issuer->pubkey.len == 64) {
11611 const uint32_t N = 32;
11612 if (a.len > N) a.value += (a.len - N), a.len = N;
11613 if (b.len > N) b.value += (b.len - N), b.len = N;
11614 memmove(sig, a.value, N);
11615 memmove(sig + N, b.value, N);
11616 return mg_uecc_verify((uint8_t *) issuer->pubkey.buf, cert->tbshash,
11617 (unsigned) cert->tbshashsz, sig,
11618 mg_uecc_secp256r1());
11619 } else if (issuer->pubkey.len == 96) {
11620 MG_DEBUG(("ignore secp386 for now"));
11621 return 1;
11622 } else {
11623 MG_ERROR(("unsupported public key length: %d", issuer->pubkey.len));
11624 return 0;
11625 }
11626 } else {
11627 int r;
11628 uint8_t sig2[256]; // 2048 bits
11629 struct mg_der_tlv seq, modulus, exponent;
11630 if (mg_der_parse((uint8_t *) issuer->pubkey.buf, issuer->pubkey.len,
11631 &seq) <= 0 ||
11632 mg_der_next(&seq, &modulus) <= 0 || modulus.type != 2 ||
11633 mg_der_next(&seq, &exponent) <= 0 || exponent.type != 2) {
11634 return -1;
11635 }
11636 mg_rsa_mod_pow(modulus.value, modulus.len, exponent.value, exponent.len,
11637 (uint8_t *) cert->sig.buf, cert->sig.len, sig2,
11638 sizeof(sig2));
11639 
11640 r = memcmp(sig2 + sizeof(sig2) - cert->tbshashsz, cert->tbshash,
11641 cert->tbshashsz);
11642 return r == 0;
11643 }
11644}
11645 
11646static int mg_tls_client_recv_cert(struct mg_connection *c) {
11647 int subj_match = 0;
11648 struct tls_data *tls = (struct tls_data *) c->tls;
11649 unsigned char *recv_buf;
11650 (void) subj_match;
11651 
11652 if (mg_tls_recv_record(c) < 0) {
11653 return -1;
11654 }
11655 
11656 recv_buf = &c->rtls.buf[tls->recv_offset];
11657 
11658 if (recv_buf[0] == MG_TLS_CERTIFICATE_REQUEST) {
11659 MG_VERBOSE(("got certificate request"));
11660 mg_tls_drop_message(c);
11661 tls->cert_requested = 1;
11662 return -1;
11663 }
11664 
11665 if (recv_buf[0] != MG_TLS_CERTIFICATE) {
11666 mg_error(c, "expected server certificate but got msg 0x%02x", recv_buf[0]);
11667 return -1;
11668 }
11669 
11670 if (tls->recv_len < 11) {
11671 mg_error(c, "certificate list too short");
11672 return -1;
11673 }
11674 
11675 uint32_t full_cert_chain_len = MG_LOAD_BE24(recv_buf + 1);
11676 uint32_t cert_chain_len = MG_LOAD_BE24(recv_buf + 5);
11677 if (cert_chain_len != full_cert_chain_len - 4) {
11678 MG_ERROR(("full chain length: %d, chain length: %d", full_cert_chain_len,
11679 cert_chain_len));
11680 mg_error(c, "certificate chain length mismatch");
11681 return -1;
11682 }
11683 
11684 // Normally, there are 2-3 certs in a chain
11685 struct mg_tls_cert certs[8];
11686 int certnum = 0;
11687 uint8_t *p = recv_buf + 8;
11688 // uint8_t *endp = recv_buf + tls->recv_len;
11689 uint8_t *endp = recv_buf + cert_chain_len;
11690 
11691 int found_ca = 0;
11692 struct mg_tls_cert ca;
11693 
11694 memset(certs, 0, sizeof(certs));
11695 memset(&ca, 0, sizeof(ca));
11696 
11697 if (tls->ca_der.len > 0) {
11698 if (mg_tls_parse_cert_der(tls->ca_der.buf, tls->ca_der.len, &ca) < 0) {
11699 mg_error(c, "failed to parse CA certificate");
11700 return -1;
11701 }
11702 MG_VERBOSE(("CA serial: %M", mg_print_hex, ca.sn.len, ca.sn.buf));
11703 }
11704 
11705 while (p < endp) {
11706 struct mg_tls_cert *ci = &certs[certnum++];
11707 uint32_t certsz = MG_LOAD_BE24(p);
11708 uint8_t *cert = p + 3;
11709 uint16_t certext = MG_LOAD_BE16(cert + certsz);
11710 if (certext != 0) {
11711 mg_error(c, "certificate extensions are not supported");
11712 return -1;
11713 }
11714 p = cert + certsz + 2;
11715 
11716 if (mg_tls_parse_cert_der(cert, certsz, ci) < 0) {
11717 mg_error(c, "failed to parse certificate");
11718 return -1;
11719 }
11720 
11721 if (ci == certs) {
11722 // First certificate in the chain is peer cert, check SAN and store
11723 // public key for further CertVerify step
11724 if (mg_tls_verify_cert_san(cert, certsz, tls->hostname) <= 0) {
11725 mg_error(c, "failed to verify hostname");
11726 return -1;
11727 }
11728 memmove(tls->pubkey, ci->pubkey.buf, ci->pubkey.len);
11729 tls->pubkeysz = ci->pubkey.len;
11730 } else {
11731 if (!mg_tls_verify_cert_signature(ci - 1, ci)) {
11732 mg_error(c, "failed to verify certificate chain");
11733 return -1;
11734 }
11735 }
11736 
11737 if (ca.pubkey.len == ci->pubkey.len &&
11738 memcmp(ca.pubkey.buf, ci->pubkey.buf, ca.pubkey.len) == 0) {
11739 found_ca = 1;
11740 break;
11741 }
11742 
11743 if (certnum == sizeof(certs) / sizeof(certs[0]) - 1) {
11744 mg_error(c, "too many certificates in the chain");
11745 return -1;
11746 }
11747 }
11748 
11749 if (!found_ca && tls->ca_der.len > 0) {
11750 if (certnum < 1 ||
11751 !mg_tls_verify_cert_signature(&certs[certnum - 1], &ca)) {
11752 mg_error(c, "failed to verify CA");
11753 return -1;
11754 } else {
11755 MG_VERBOSE(
11756 ("CA was not in the chain, but verification with builtin CA passed"));
11757 }
11758 }
11759 
11760 mg_tls_drop_message(c);
11761 mg_tls_calc_cert_verify_hash(c, tls->sighash, 0);
11762 return 0;
11763}
11764 
11765static int mg_tls_client_recv_cert_verify(struct mg_connection *c) {
11766 struct tls_data *tls = (struct tls_data *) c->tls;
11767 unsigned char *recv_buf;
11768 if (mg_tls_recv_record(c) < 0) {
11769 return -1;
11770 }
11771 recv_buf = &c->rtls.buf[tls->recv_offset];
11772 if (recv_buf[0] != MG_TLS_CERTIFICATE_VERIFY) {
11773 mg_error(c, "expected server certificate verify but got msg 0x%02x",
11774 recv_buf[0]);
11775 return -1;
11776 }
11777 if (tls->recv_len < 8) {
11778 mg_error(c, "server certificate verify is too short: %d bytes",
11779 tls->recv_len);
11780 return -1;
11781 }
11782 
11783 // Ignore CertificateVerify is strict checks are not required
11784 if (tls->skip_verification) {
11785 mg_tls_drop_message(c);
11786 return 0;
11787 }
11788 
11789 uint16_t sigalg = MG_LOAD_BE16(recv_buf + 4);
11790 uint16_t siglen = MG_LOAD_BE16(recv_buf + 6);
11791 uint8_t *sigbuf = recv_buf + 8;
11792 if (siglen > tls->recv_len - 8) {
11793 mg_error(c, "invalid certverify signature length: %d, expected %d", siglen,
11794 tls->recv_len - 8);
11795 return -1;
11796 }
11797 MG_VERBOSE(
11798 ("certificate verification, algo=%04x, siglen=%d", sigalg, siglen));
11799 
11800 if (sigalg == 0x0804) { // rsa_pss_rsae_sha256
11801 uint8_t sig2[512]; // 2048 or 4096 bits
11802 struct mg_der_tlv seq, modulus, exponent;
11803 
11804 if (mg_der_parse(tls->pubkey, tls->pubkeysz, &seq) <= 0 ||
11805 mg_der_next(&seq, &modulus) <= 0 || modulus.type != 2 ||
11806 mg_der_next(&seq, &exponent) <= 0 || exponent.type != 2) {
11807 mg_error(c, "invalid public key");
11808 return -1;
11809 }
11810 
11811 mg_rsa_mod_pow(modulus.value, modulus.len, exponent.value, exponent.len,
11812 sigbuf, siglen, sig2, sizeof(sig2));
11813 
11814 if (sig2[sizeof(sig2) - 1] != 0xbc) {
11815 mg_error(c, "failed to verify RSA certificate (certverify)");
11816 return -1;
11817 }
11818 MG_DEBUG(("certificate verification successful (RSA)"));
11819 } else if (sigalg == 0x0403) { // ecdsa_secp256r1_sha256
11820 // Extract certificate signature and verify it using pubkey and sighash
11821 uint8_t sig[64];
11822 struct mg_der_tlv seq, r, s;
11823 if (mg_der_to_tlv(sigbuf, siglen, &seq) < 0) {
11824 mg_error(c, "verification message is not an ASN.1 DER sequence");
11825 return -1;
11826 }
11827 if (mg_der_to_tlv(seq.value, seq.len, &r) < 0) {
11828 mg_error(c, "missing first part of the signature");
11829 return -1;
11830 }
11831 if (mg_der_to_tlv(r.value + r.len, seq.len - r.len, &s) < 0) {
11832 mg_error(c, "missing second part of the signature");
11833 return -1;
11834 }
11835 // Integers may be padded with zeroes
11836 if (r.len > 32) r.value = r.value + (r.len - 32), r.len = 32;
11837 if (s.len > 32) s.value = s.value + (s.len - 32), s.len = 32;
11838 
11839 memmove(sig, r.value, r.len);
11840 memmove(sig + 32, s.value, s.len);
11841 
11842 if (mg_uecc_verify(tls->pubkey, tls->sighash, sizeof(tls->sighash), sig,
11843 mg_uecc_secp256r1()) != 1) {
11844 mg_error(c, "failed to verify EC certificate (certverify)");
11845 return -1;
11846 }
11847 MG_DEBUG(("certificate verification successful (EC)"));
11848 } else {
11849 // From
11850 // https://www.iana.org/assignments/tls-parameters/tls-parameters.xhtml:
11851 // 0805 = rsa_pss_rsae_sha384
11852 // 0806 = rsa_pss_rsae_sha512
11853 // 0807 = ed25519
11854 // 0808 = ed448
11855 // 0809 = rsa_pss_pss_sha256
11856 // 080A = rsa_pss_pss_sha384
11857 // 080B = rsa_pss_pss_sha512
11858 MG_ERROR(("unsupported certverify signature scheme: %x of %d bytes", sigalg,
11859 siglen));
11860 return -1;
11861 }
11862 mg_tls_drop_message(c);
11863 return 0;
11864}
11865 
11866static int mg_tls_client_recv_finish(struct mg_connection *c) {
11867 struct tls_data *tls = (struct tls_data *) c->tls;
11868 unsigned char *recv_buf;
11869 if (mg_tls_recv_record(c) < 0) {
11870 return -1;
11871 }
11872 recv_buf = &c->rtls.buf[tls->recv_offset];
11873 if (recv_buf[0] != MG_TLS_FINISHED) {
11874 mg_error(c, "expected server finished but got msg 0x%02x", recv_buf[0]);
11875 return -1;
11876 }
11877 mg_tls_drop_message(c);
11878 return 0;
11879}
11880 
11881static void mg_tls_client_send_finish(struct mg_connection *c) {
11882 struct tls_data *tls = (struct tls_data *) c->tls;
11883 struct mg_iobuf *wio = &tls->send;
11884 mg_sha256_ctx sha256;
11885 uint8_t hash[32];
11886 uint8_t finish[36] = {0x14, 0, 0, 32};
11887 memmove(&sha256, &tls->sha256, sizeof(mg_sha256_ctx));
11888 mg_sha256_final(hash, &sha256);
11889 mg_hmac_sha256(finish + 4, tls->enc.client_finished_key, 32, hash, 32);
11890 mg_tls_encrypt(c, finish, sizeof(finish), MG_TLS_HANDSHAKE);
11891 mg_io_send(c, wio->buf, wio->len);
11892 wio->len = 0;
11893}
11894 
11895static void mg_tls_client_handshake(struct mg_connection *c) {
11896 struct tls_data *tls = (struct tls_data *) c->tls;
11897 switch (tls->state) {
11898 case MG_TLS_STATE_CLIENT_START:
11899 mg_tls_client_send_hello(c);
11900 tls->state = MG_TLS_STATE_CLIENT_WAIT_SH;
11901 // Fallthrough
11902 case MG_TLS_STATE_CLIENT_WAIT_SH:
11903 if (mg_tls_client_recv_hello(c) < 0) {
11904 break;
11905 }
11906 tls->state = MG_TLS_STATE_CLIENT_WAIT_EE;
11907 // Fallthrough
11908 case MG_TLS_STATE_CLIENT_WAIT_EE:
11909 if (mg_tls_client_recv_ext(c) < 0) {
11910 break;
11911 }
11912 tls->state = MG_TLS_STATE_CLIENT_WAIT_CERT;
11913 // Fallthrough
11914 case MG_TLS_STATE_CLIENT_WAIT_CERT:
11915 if (mg_tls_client_recv_cert(c) < 0) {
11916 break;
11917 }
11918 tls->state = MG_TLS_STATE_CLIENT_WAIT_CV;
11919 // Fallthrough
11920 case MG_TLS_STATE_CLIENT_WAIT_CV:
11921 if (mg_tls_client_recv_cert_verify(c) < 0) {
11922 break;
11923 }
11924 tls->state = MG_TLS_STATE_CLIENT_WAIT_FINISHED;
11925 // Fallthrough
11926 case MG_TLS_STATE_CLIENT_WAIT_FINISHED:
11927 if (mg_tls_client_recv_finish(c) < 0) {
11928 break;
11929 }
11930 if (tls->cert_requested) {
11931 /* for mTLS we should generate application keys at this point
11932 * but then restore handshake keys and continue with
11933 * the rest of the handshake */
11934 struct tls_enc app_keys;
11935 struct tls_enc hs_keys = tls->enc;
11936 mg_tls_generate_application_keys(c);
11937 app_keys = tls->enc;
11938 tls->enc = hs_keys;
11939 mg_tls_server_send_cert(c);
11940 mg_tls_send_cert_verify(c, 1);
11941 mg_tls_client_send_finish(c);
11942 tls->enc = app_keys;
11943 } else {
11944 mg_tls_client_send_finish(c);
11945 mg_tls_generate_application_keys(c);
11946 }
11947 tls->state = MG_TLS_STATE_CLIENT_CONNECTED;
11948 c->is_tls_hs = 0;
11949 mg_call(c, MG_EV_TLS_HS, NULL);
11950 break;
11951 default:
11952 mg_error(c, "unexpected client state: %d", tls->state);
11953 break;
11954 }
11955}
11956 
11957static void mg_tls_server_handshake(struct mg_connection *c) {
11958 struct tls_data *tls = (struct tls_data *) c->tls;
11959 switch (tls->state) {
11960 case MG_TLS_STATE_SERVER_START:
11961 if (mg_tls_server_recv_hello(c) < 0) {
11962 return;
11963 }
11964 mg_tls_server_send_hello(c);
11965 mg_tls_generate_handshake_keys(c);
11966 mg_tls_server_send_ext(c);
11967 mg_tls_server_send_cert(c);
11968 mg_tls_send_cert_verify(c, 0);
11969 mg_tls_server_send_finish(c);
11970 tls->state = MG_TLS_STATE_SERVER_NEGOTIATED;
11971 // fallthrough
11972 case MG_TLS_STATE_SERVER_NEGOTIATED:
11973 if (mg_tls_server_recv_finish(c) < 0) {
11974 return;
11975 }
11976 mg_tls_generate_application_keys(c);
11977 tls->state = MG_TLS_STATE_SERVER_CONNECTED;
11978 c->is_tls_hs = 0;
11979 return;
11980 default:
11981 mg_error(c, "unexpected server state: %d", tls->state);
11982 break;
11983 }
11984}
11985 
11986void mg_tls_handshake(struct mg_connection *c) {
11987 if (c->is_client) {
11988 mg_tls_client_handshake(c);
11989 } else {
11990 mg_tls_server_handshake(c);
11991 }
11992}
11993 
11994static int mg_parse_pem(const struct mg_str pem, const struct mg_str label,
11995 struct mg_str *der) {
11996 size_t n = 0, m = 0;
11997 char *s;
11998 const char *c;
11999 struct mg_str caps[6]; // number of wildcards + 1
12000 if (!mg_match(pem, mg_str("#-----BEGIN #-----#-----END #-----#"), caps)) {
12001 *der = mg_strdup(pem);
12002 return 0;
12003 }
12004 if (mg_strcmp(caps[1], label) != 0 || mg_strcmp(caps[3], label) != 0) {
12005 return -1; // bad label
12006 }
12007 if ((s = (char *) calloc(1, caps[2].len)) == NULL) {
12008 return -1;
12009 }
12010 
12011 for (c = caps[2].buf; c < caps[2].buf + caps[2].len; c++) {
12012 if (*c == ' ' || *c == '\n' || *c == '\r' || *c == '\t') {
12013 continue;
12014 }
12015 s[n++] = *c;
12016 }
12017 m = mg_base64_decode(s, n, s, n);
12018 if (m == 0) {
12019 free(s);
12020 return -1;
12021 }
12022 der->buf = s;
12023 der->len = m;
12024 return 0;
12025}
12026 
12027void mg_tls_init(struct mg_connection *c, const struct mg_tls_opts *opts) {
12028 struct mg_str key;
12029 struct tls_data *tls = (struct tls_data *) calloc(1, sizeof(struct tls_data));
12030 if (tls == NULL) {
12031 mg_error(c, "tls oom");
12032 return;
12033 }
12034 
12035 tls->state =
12036 c->is_client ? MG_TLS_STATE_CLIENT_START : MG_TLS_STATE_SERVER_START;
12037 
12038 tls->skip_verification = opts->skip_verification;
12039 // tls->send.align = MG_IO_SIZE;
12040 
12041 c->tls = tls;
12042 c->is_tls = c->is_tls_hs = 1;
12043 mg_sha256_init(&tls->sha256);
12044 
12045 // save hostname (client extension)
12046 if (opts->name.len > 0) {
12047 if (opts->name.len >= sizeof(tls->hostname) - 1) {
12048 mg_error(c, "hostname too long");
12049 return;
12050 }
12051 strncpy((char *) tls->hostname, opts->name.buf, sizeof(tls->hostname) - 1);
12052 tls->hostname[opts->name.len] = 0;
12053 }
12054 // server CA certificate, store serial number
12055 if (opts->ca.len > 0) {
12056 if (mg_parse_pem(opts->ca, mg_str_s("CERTIFICATE"), &tls->ca_der) < 0) {
12057 MG_ERROR(("Failed to load certificate"));
12058 return;
12059 }
12060 }
12061 
12062 if (opts->cert.buf == NULL) {
12063 MG_VERBOSE(("No certificate provided"));
12064 return;
12065 }
12066 
12067 // parse PEM or DER certificate
12068 if (mg_parse_pem(opts->cert, mg_str_s("CERTIFICATE"), &tls->cert_der) < 0) {
12069 MG_ERROR(("Failed to load certificate"));
12070 return;
12071 }
12072 
12073 // parse PEM or DER EC key
12074 if (opts->key.buf == NULL) {
12075 mg_error(c, "Certificate provided without a private key");
12076 return;
12077 }
12078 
12079 if (mg_parse_pem(opts->key, mg_str_s("EC PRIVATE KEY"), &key) == 0) {
12080 if (key.len < 39) {
12081 MG_ERROR(("EC private key too short"));
12082 return;
12083 }
12084 // expect ASN.1 SEQUENCE=[INTEGER=1, BITSTRING of 32 bytes, ...]
12085 // 30 nn 02 01 01 04 20 [key] ...
12086 if (key.buf[0] != 0x30 || (key.buf[1] & 0x80) != 0) {
12087 MG_ERROR(("EC private key: ASN.1 bad sequence"));
12088 return;
12089 }
12090 if (memcmp(key.buf + 2, "\x02\x01\x01\x04\x20", 5) != 0) {
12091 MG_ERROR(("EC private key: ASN.1 bad data"));
12092 }
12093 memmove(tls->ec_key, key.buf + 7, 32);
12094 free((void *) key.buf);
12095 } else if (mg_parse_pem(opts->key, mg_str_s("PRIVATE KEY"), &key) == 0) {
12096 mg_error(c, "PKCS8 private key format is not supported");
12097 } else {
12098 mg_error(c, "Expected EC PRIVATE KEY or PRIVATE KEY");
12099 }
12100}
12101 
12102void mg_tls_free(struct mg_connection *c) {
12103 struct tls_data *tls = (struct tls_data *) c->tls;
12104 if (tls != NULL) {
12105 mg_iobuf_free(&tls->send);
12106 free((void *) tls->cert_der.buf);
12107 free((void *) tls->ca_der.buf);
12108 }
12109 free(c->tls);
12110 c->tls = NULL;
12111}
12112 
12113long mg_tls_send(struct mg_connection *c, const void *buf, size_t len) {
12114 struct tls_data *tls = (struct tls_data *) c->tls;
12115 long n = MG_IO_WAIT;
12116 bool was_throttled = c->is_tls_throttled; // see #3074
12117 if (!was_throttled) { // encrypt new data
12118 if (len > MG_IO_SIZE) len = MG_IO_SIZE;
12119 if (len > 16384) len = 16384;
12120 mg_tls_encrypt(c, (const uint8_t *) buf, len, MG_TLS_APP_DATA);
12121 } // else, resend outstanding encrypted data in tls->send
12122 while (tls->send.len > 0 &&
12123 (n = mg_io_send(c, tls->send.buf, tls->send.len)) > 0) {
12124 mg_iobuf_del(&tls->send, 0, (size_t) n);
12125 }
12126 c->is_tls_throttled = (tls->send.len > 0 && n == MG_IO_WAIT);
12127 MG_VERBOSE(("%lu %ld %ld %ld %c %c", c->id, (long) len, (long) tls->send.len,
12128 n, was_throttled ? 'T' : 't', c->is_tls_throttled ? 'T' : 't'));
12129 if (n == MG_IO_ERR) return MG_IO_ERR;
12130 if (was_throttled) return MG_IO_WAIT; // sent throttled data instead
12131 return (long) len; // return len even when throttled, already encripted that
12132}
12133 
12134long mg_tls_recv(struct mg_connection *c, void *buf, size_t len) {
12135 int r = 0;
12136 struct tls_data *tls = (struct tls_data *) c->tls;
12137 unsigned char *recv_buf;
12138 size_t minlen;
12139 
12140 r = mg_tls_recv_record(c);
12141 if (r < 0) {
12142 return r;
12143 }
12144 recv_buf = &c->rtls.buf[tls->recv_offset];
12145 
12146 if (tls->content_type != MG_TLS_APP_DATA) {
12147 tls->recv_len = 0;
12148 mg_tls_drop_record(c);
12149 return MG_IO_WAIT;
12150 }
12151 if (buf == NULL || len == 0) return 0L;
12152 minlen = len < tls->recv_len ? len : tls->recv_len;
12153 memmove(buf, recv_buf, minlen);
12154 tls->recv_offset += minlen;
12155 tls->recv_len -= minlen;
12156 if (tls->recv_len == 0) {
12157 mg_tls_drop_record(c);
12158 }
12159 return (long) minlen;
12160}
12161 
12162size_t mg_tls_pending(struct mg_connection *c) {
12163 struct tls_data *tls = (struct tls_data *) c->tls;
12164 return tls != NULL ? tls->recv_len : 0;
12165}
12166 
12167void mg_tls_ctx_init(struct mg_mgr *mgr) {
12168 (void) mgr;
12169}
12170 
12171void mg_tls_ctx_free(struct mg_mgr *mgr) {
12172 (void) mgr;
12173}
12174#endif
12175 
12176#ifdef MG_ENABLE_LINES
12177#line 1 "src/tls_chacha20.c"
12178#endif
12179// portable8439 v1.0.1
12180// Source: https://github.com/DavyLandman/portable8439
12181// Licensed under CC0-1.0
12182// Contains poly1305-donna e6ad6e091d30d7f4ec2d4f978be1fcfcbce72781 (Public
12183// Domain)
12184 
12185 
12186 
12187 
12188#if MG_TLS == MG_TLS_BUILTIN
12189// ******* BEGIN: chacha-portable/chacha-portable.h ********
12190 
12191#if !defined(__cplusplus) && !defined(_MSC_VER) && \
12192 (!defined(__STDC_VERSION__) || __STDC_VERSION__ < 199901L)
12193#error "C99 or newer required"
12194#endif
12195 
12196#define CHACHA20_KEY_SIZE (32)
12197#define CHACHA20_NONCE_SIZE (12)
12198 
12199#if defined(_MSC_VER) || defined(__cplusplus)
12200// add restrict support
12201#if (defined(_MSC_VER) && _MSC_VER >= 1900) || defined(__clang__) || \
12202 defined(__GNUC__)
12203#define restrict __restrict
12204#else
12205#define restrict
12206#endif
12207#endif
12208 
12209// xor data with a ChaCha20 keystream as per RFC8439
12210static PORTABLE_8439_DECL void chacha20_xor_stream(
12211 uint8_t *restrict dest, const uint8_t *restrict source, size_t length,
12212 const uint8_t key[CHACHA20_KEY_SIZE],
12213 const uint8_t nonce[CHACHA20_NONCE_SIZE], uint32_t counter);
12214 
12215static PORTABLE_8439_DECL void rfc8439_keygen(
12216 uint8_t poly_key[32], const uint8_t key[CHACHA20_KEY_SIZE],
12217 const uint8_t nonce[CHACHA20_NONCE_SIZE]);
12218 
12219// ******* END: chacha-portable/chacha-portable.h ********
12220// ******* BEGIN: poly1305-donna/poly1305-donna.h ********
12221 
12222#include <stddef.h>
12223 
12224typedef struct poly1305_context {
12225 size_t aligner;
12226 unsigned char opaque[136];
12227} poly1305_context;
12228 
12229static PORTABLE_8439_DECL void poly1305_init(poly1305_context *ctx,
12230 const unsigned char key[32]);
12231static PORTABLE_8439_DECL void poly1305_update(poly1305_context *ctx,
12232 const unsigned char *m,
12233 size_t bytes);
12234static PORTABLE_8439_DECL void poly1305_finish(poly1305_context *ctx,
12235 unsigned char mac[16]);
12236 
12237// ******* END: poly1305-donna/poly1305-donna.h ********
12238// ******* BEGIN: chacha-portable.c ********
12239 
12240#include <assert.h>
12241#include <string.h>
12242 
12243// this is a fresh implementation of chacha20, based on the description in
12244// rfc8349 it's such a nice compact algorithm that it is easy to do. In
12245// relationship to other c implementation this implementation:
12246// - pure c99
12247// - big & little endian support
12248// - safe for architectures that don't support unaligned reads
12249//
12250// Next to this, we try to be fast as possible without resorting inline
12251// assembly.
12252 
12253// based on https://sourceforge.net/p/predef/wiki/Endianness/
12254#if defined(__BYTE_ORDER__) && defined(__ORDER_LITTLE_ENDIAN__) && \
12255 __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
12256#define __HAVE_LITTLE_ENDIAN 1
12257#elif defined(__LITTLE_ENDIAN__) || defined(__ARMEL__) || \
12258 defined(__THUMBEL__) || defined(__AARCH64EL__) || defined(_MIPSEL) || \
12259 defined(__MIPSEL) || defined(__MIPSEL__) || defined(__XTENSA_EL__) || \
12260 defined(__AVR__) || defined(LITTLE_ENDIAN)
12261#define __HAVE_LITTLE_ENDIAN 1
12262#endif
12263 
12264#ifndef TEST_SLOW_PATH
12265#if defined(__HAVE_LITTLE_ENDIAN)
12266#define FAST_PATH
12267#endif
12268#endif
12269 
12270#define CHACHA20_STATE_WORDS (16)
12271#define CHACHA20_BLOCK_SIZE (CHACHA20_STATE_WORDS * sizeof(uint32_t))
12272 
12273#ifdef FAST_PATH
12274#define store_32_le(target, source) memcpy(&(target), source, sizeof(uint32_t))
12275#else
12276#define store_32_le(target, source) \
12277 target = (uint32_t) (source)[0] | ((uint32_t) (source)[1]) << 8 | \
12278 ((uint32_t) (source)[2]) << 16 | ((uint32_t) (source)[3]) << 24
12279#endif
12280 
12281static void initialize_state(uint32_t state[CHACHA20_STATE_WORDS],
12282 const uint8_t key[CHACHA20_KEY_SIZE],
12283 const uint8_t nonce[CHACHA20_NONCE_SIZE],
12284 uint32_t counter) {
12285#if 0
12286#ifdef static_assert
12287 static_assert(sizeof(uint32_t) == 4,
12288 "We don't support systems that do not conform to standard of "
12289 "uint32_t being exact 32bit wide");
12290#endif
12291#endif
12292 state[0] = 0x61707865;
12293 state[1] = 0x3320646e;
12294 state[2] = 0x79622d32;
12295 state[3] = 0x6b206574;
12296 store_32_le(state[4], key);
12297 store_32_le(state[5], key + 4);
12298 store_32_le(state[6], key + 8);
12299 store_32_le(state[7], key + 12);
12300 store_32_le(state[8], key + 16);
12301 store_32_le(state[9], key + 20);
12302 store_32_le(state[10], key + 24);
12303 store_32_le(state[11], key + 28);
12304 state[12] = counter;
12305 store_32_le(state[13], nonce);
12306 store_32_le(state[14], nonce + 4);
12307 store_32_le(state[15], nonce + 8);
12308}
12309 
12310#define increment_counter(state) (state)[12]++
12311 
12312// source: http://blog.regehr.org/archives/1063
12313#define rotl32a(x, n) ((x) << (n)) | ((x) >> (32 - (n)))
12314 
12315#define Qround(a, b, c, d) \
12316 a += b; \
12317 d ^= a; \
12318 d = rotl32a(d, 16); \
12319 c += d; \
12320 b ^= c; \
12321 b = rotl32a(b, 12); \
12322 a += b; \
12323 d ^= a; \
12324 d = rotl32a(d, 8); \
12325 c += d; \
12326 b ^= c; \
12327 b = rotl32a(b, 7);
12328 
12329#define TIMES16(x) \
12330 x(0) x(1) x(2) x(3) x(4) x(5) x(6) x(7) x(8) x(9) x(10) x(11) x(12) x(13) \
12331 x(14) x(15)
12332 
12333static void core_block(const uint32_t *restrict start,
12334 uint32_t *restrict output) {
12335 int i;
12336// instead of working on the output array,
12337// we let the compiler allocate 16 local variables on the stack
12338#define __LV(i) uint32_t __t##i = start[i];
12339 TIMES16(__LV)
12340 
12341#define __Q(a, b, c, d) Qround(__t##a, __t##b, __t##c, __t##d)
12342 
12343 for (i = 0; i < 10; i++) {
12344 __Q(0, 4, 8, 12);
12345 __Q(1, 5, 9, 13);
12346 __Q(2, 6, 10, 14);
12347 __Q(3, 7, 11, 15);
12348 __Q(0, 5, 10, 15);
12349 __Q(1, 6, 11, 12);
12350 __Q(2, 7, 8, 13);
12351 __Q(3, 4, 9, 14);
12352 }
12353 
12354#define __FIN(i) output[i] = start[i] + __t##i;
12355 TIMES16(__FIN)
12356}
12357 
12358#define U8(x) ((uint8_t) ((x) &0xFF))
12359 
12360#ifdef FAST_PATH
12361#define xor32_le(dst, src, pad) \
12362 uint32_t __value; \
12363 memcpy(&__value, src, sizeof(uint32_t)); \
12364 __value ^= *(pad); \
12365 memcpy(dst, &__value, sizeof(uint32_t));
12366#else
12367#define xor32_le(dst, src, pad) \
12368 (dst)[0] = (src)[0] ^ U8(*(pad)); \
12369 (dst)[1] = (src)[1] ^ U8(*(pad) >> 8); \
12370 (dst)[2] = (src)[2] ^ U8(*(pad) >> 16); \
12371 (dst)[3] = (src)[3] ^ U8(*(pad) >> 24);
12372#endif
12373 
12374#define index8_32(a, ix) ((a) + ((ix) * sizeof(uint32_t)))
12375 
12376#define xor32_blocks(dest, source, pad, words) \
12377 for (i = 0; i < words; i++) { \
12378 xor32_le(index8_32(dest, i), index8_32(source, i), (pad) + i) \
12379 }
12380 
12381static void xor_block(uint8_t *restrict dest, const uint8_t *restrict source,
12382 const uint32_t *restrict pad, unsigned int chunk_size) {
12383 unsigned int i, full_blocks = chunk_size / (unsigned int) sizeof(uint32_t);
12384 // have to be carefull, we are going back from uint32 to uint8, so endianness
12385 // matters again
12386 xor32_blocks(dest, source, pad, full_blocks)
12387 
12388 dest += full_blocks * sizeof(uint32_t);
12389 source += full_blocks * sizeof(uint32_t);
12390 pad += full_blocks;
12391 
12392 switch (chunk_size % sizeof(uint32_t)) {
12393 case 1:
12394 dest[0] = source[0] ^ U8(*pad);
12395 break;
12396 case 2:
12397 dest[0] = source[0] ^ U8(*pad);
12398 dest[1] = source[1] ^ U8(*pad >> 8);
12399 break;
12400 case 3:
12401 dest[0] = source[0] ^ U8(*pad);
12402 dest[1] = source[1] ^ U8(*pad >> 8);
12403 dest[2] = source[2] ^ U8(*pad >> 16);
12404 break;
12405 }
12406}
12407 
12408static void chacha20_xor_stream(uint8_t *restrict dest,
12409 const uint8_t *restrict source, size_t length,
12410 const uint8_t key[CHACHA20_KEY_SIZE],
12411 const uint8_t nonce[CHACHA20_NONCE_SIZE],
12412 uint32_t counter) {
12413 uint32_t state[CHACHA20_STATE_WORDS];
12414 uint32_t pad[CHACHA20_STATE_WORDS];
12415 size_t i, b, last_block, full_blocks = length / CHACHA20_BLOCK_SIZE;
12416 initialize_state(state, key, nonce, counter);
12417 for (b = 0; b < full_blocks; b++) {
12418 core_block(state, pad);
12419 increment_counter(state);
12420 xor32_blocks(dest, source, pad, CHACHA20_STATE_WORDS) dest +=
12421 CHACHA20_BLOCK_SIZE;
12422 source += CHACHA20_BLOCK_SIZE;
12423 }
12424 last_block = length % CHACHA20_BLOCK_SIZE;
12425 if (last_block > 0) {
12426 core_block(state, pad);
12427 xor_block(dest, source, pad, (unsigned int) last_block);
12428 }
12429}
12430 
12431#ifdef FAST_PATH
12432#define serialize(poly_key, result) memcpy(poly_key, result, 32)
12433#else
12434#define store32_le(target, source) \
12435 (target)[0] = U8(*(source)); \
12436 (target)[1] = U8(*(source) >> 8); \
12437 (target)[2] = U8(*(source) >> 16); \
12438 (target)[3] = U8(*(source) >> 24);
12439 
12440#define serialize(poly_key, result) \
12441 for (i = 0; i < 32 / sizeof(uint32_t); i++) { \
12442 store32_le(index8_32(poly_key, i), result + i); \
12443 }
12444#endif
12445 
12446static void rfc8439_keygen(uint8_t poly_key[32],
12447 const uint8_t key[CHACHA20_KEY_SIZE],
12448 const uint8_t nonce[CHACHA20_NONCE_SIZE]) {
12449 uint32_t state[CHACHA20_STATE_WORDS];
12450 uint32_t result[CHACHA20_STATE_WORDS];
12451 size_t i;
12452 initialize_state(state, key, nonce, 0);
12453 core_block(state, result);
12454 serialize(poly_key, result);
12455 (void) i;
12456}
12457// ******* END: chacha-portable.c ********
12458// ******* BEGIN: poly1305-donna.c ********
12459 
12460/* auto detect between 32bit / 64bit */
12461#if /* uint128 available on 64bit system*/ \
12462 (defined(__SIZEOF_INT128__) && \
12463 defined(__LP64__)) /* MSVC 64bit compiler */ \
12464 || (defined(_MSC_VER) && defined(_M_X64)) /* gcc >= 4.4 64bit */ \
12465 || (defined(__GNUC__) && defined(__LP64__) && \
12466 ((__GNUC__ > 4) || ((__GNUC__ == 4) && (__GNUC_MINOR__ >= 4))))
12467#define __GUESS64
12468#else
12469#define __GUESS32
12470#endif
12471 
12472#if defined(POLY1305_8BIT)
12473/*
12474 poly1305 implementation using 8 bit * 8 bit = 16 bit multiplication and
1247532 bit addition
12476 
12477 based on the public domain reference version in supercop by djb
12478static */
12479 
12480#if defined(_MSC_VER) && _MSC_VER < 1700
12481#define POLY1305_NOINLINE
12482#elif defined(_MSC_VER)
12483#define POLY1305_NOINLINE __declspec(noinline)
12484#elif defined(__GNUC__)
12485#define POLY1305_NOINLINE __attribute__((noinline))
12486#else
12487#define POLY1305_NOINLINE
12488#endif
12489 
12490#define poly1305_block_size 16
12491 
12492/* 17 + sizeof(size_t) + 51*sizeof(unsigned char) */
12493typedef struct poly1305_state_internal_t {
12494 unsigned char buffer[poly1305_block_size];
12495 size_t leftover;
12496 unsigned char h[17];
12497 unsigned char r[17];
12498 unsigned char pad[17];
12499 unsigned char final;
12500} poly1305_state_internal_t;
12501 
12502static void poly1305_init(poly1305_context *ctx, const unsigned char key[32]) {
12503 poly1305_state_internal_t *st = (poly1305_state_internal_t *) ctx;
12504 size_t i;
12505 
12506 st->leftover = 0;
12507 
12508 /* h = 0 */
12509 for (i = 0; i < 17; i++) st->h[i] = 0;
12510 
12511 /* r &= 0xffffffc0ffffffc0ffffffc0fffffff */
12512 st->r[0] = key[0] & 0xff;
12513 st->r[1] = key[1] & 0xff;
12514 st->r[2] = key[2] & 0xff;
12515 st->r[3] = key[3] & 0x0f;
12516 st->r[4] = key[4] & 0xfc;
12517 st->r[5] = key[5] & 0xff;
12518 st->r[6] = key[6] & 0xff;
12519 st->r[7] = key[7] & 0x0f;
12520 st->r[8] = key[8] & 0xfc;
12521 st->r[9] = key[9] & 0xff;
12522 st->r[10] = key[10] & 0xff;
12523 st->r[11] = key[11] & 0x0f;
12524 st->r[12] = key[12] & 0xfc;
12525 st->r[13] = key[13] & 0xff;
12526 st->r[14] = key[14] & 0xff;
12527 st->r[15] = key[15] & 0x0f;
12528 st->r[16] = 0;
12529 
12530 /* save pad for later */
12531 for (i = 0; i < 16; i++) st->pad[i] = key[i + 16];
12532 st->pad[16] = 0;
12533 
12534 st->final = 0;
12535}
12536 
12537static void poly1305_add(unsigned char h[17], const unsigned char c[17]) {
12538 unsigned short u;
12539 unsigned int i;
12540 for (u = 0, i = 0; i < 17; i++) {
12541 u += (unsigned short) h[i] + (unsigned short) c[i];
12542 h[i] = (unsigned char) u & 0xff;
12543 u >>= 8;
12544 }
12545}
12546 
12547static void poly1305_squeeze(unsigned char h[17], unsigned long hr[17]) {
12548 unsigned long u;
12549 unsigned int i;
12550 u = 0;
12551 for (i = 0; i < 16; i++) {
12552 u += hr[i];
12553 h[i] = (unsigned char) u & 0xff;
12554 u >>= 8;
12555 }
12556 u += hr[16];
12557 h[16] = (unsigned char) u & 0x03;
12558 u >>= 2;
12559 u += (u << 2); /* u *= 5; */
12560 for (i = 0; i < 16; i++) {
12561 u += h[i];
12562 h[i] = (unsigned char) u & 0xff;
12563 u >>= 8;
12564 }
12565 h[16] += (unsigned char) u;
12566}
12567 
12568static void poly1305_freeze(unsigned char h[17]) {
12569 const unsigned char minusp[17] = {0x05, 0x00, 0x00, 0x00, 0x00, 0x00,
12570 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
12571 0x00, 0x00, 0x00, 0x00, 0xfc};
12572 unsigned char horig[17], negative;
12573 unsigned int i;
12574 
12575 /* compute h + -p */
12576 for (i = 0; i < 17; i++) horig[i] = h[i];
12577 poly1305_add(h, minusp);
12578 
12579 /* select h if h < p, or h + -p if h >= p */
12580 negative = -(h[16] >> 7);
12581 for (i = 0; i < 17; i++) h[i] ^= negative & (horig[i] ^ h[i]);
12582}
12583 
12584static void poly1305_blocks(poly1305_state_internal_t *st,
12585 const unsigned char *m, size_t bytes) {
12586 const unsigned char hibit = st->final ^ 1; /* 1 << 128 */
12587 
12588 while (bytes >= poly1305_block_size) {
12589 unsigned long hr[17], u;
12590 unsigned char c[17];
12591 unsigned int i, j;
12592 
12593 /* h += m */
12594 for (i = 0; i < 16; i++) c[i] = m[i];
12595 c[16] = hibit;
12596 poly1305_add(st->h, c);
12597 
12598 /* h *= r */
12599 for (i = 0; i < 17; i++) {
12600 u = 0;
12601 for (j = 0; j <= i; j++) {
12602 u += (unsigned short) st->h[j] * st->r[i - j];
12603 }
12604 for (j = i + 1; j < 17; j++) {
12605 unsigned long v = (unsigned short) st->h[j] * st->r[i + 17 - j];
12606 v = ((v << 8) + (v << 6)); /* v *= (5 << 6); */
12607 u += v;
12608 }
12609 hr[i] = u;
12610 }
12611 
12612 /* (partial) h %= p */
12613 poly1305_squeeze(st->h, hr);
12614 
12615 m += poly1305_block_size;
12616 bytes -= poly1305_block_size;
12617 }
12618}
12619 
12620static POLY1305_NOINLINE void poly1305_finish(poly1305_context *ctx,
12621 unsigned char mac[16]) {
12622 poly1305_state_internal_t *st = (poly1305_state_internal_t *) ctx;
12623 size_t i;
12624 
12625 /* process the remaining block */
12626 if (st->leftover) {
12627 size_t i = st->leftover;
12628 st->buffer[i++] = 1;
12629 for (; i < poly1305_block_size; i++) st->buffer[i] = 0;
12630 st->final = 1;
12631 poly1305_blocks(st, st->buffer, poly1305_block_size);
12632 }
12633 
12634 /* fully reduce h */
12635 poly1305_freeze(st->h);
12636 
12637 /* h = (h + pad) % (1 << 128) */
12638 poly1305_add(st->h, st->pad);
12639 for (i = 0; i < 16; i++) mac[i] = st->h[i];
12640 
12641 /* zero out the state */
12642 for (i = 0; i < 17; i++) st->h[i] = 0;
12643 for (i = 0; i < 17; i++) st->r[i] = 0;
12644 for (i = 0; i < 17; i++) st->pad[i] = 0;
12645}
12646#elif defined(POLY1305_16BIT)
12647/*
12648 poly1305 implementation using 16 bit * 16 bit = 32 bit multiplication
12649and 32 bit addition static */
12650 
12651#if defined(_MSC_VER) && _MSC_VER < 1700
12652#define POLY1305_NOINLINE
12653#elif defined(_MSC_VER)
12654#define POLY1305_NOINLINE __declspec(noinline)
12655#elif defined(__GNUC__)
12656#define POLY1305_NOINLINE __attribute__((noinline))
12657#else
12658#define POLY1305_NOINLINE
12659#endif
12660 
12661#define poly1305_block_size 16
12662 
12663/* 17 + sizeof(size_t) + 18*sizeof(unsigned short) */
12664typedef struct poly1305_state_internal_t {
12665 unsigned char buffer[poly1305_block_size];
12666 size_t leftover;
12667 unsigned short r[10];
12668 unsigned short h[10];
12669 unsigned short pad[8];
12670 unsigned char final;
12671} poly1305_state_internal_t;
12672 
12673/* interpret two 8 bit unsigned integers as a 16 bit unsigned integer in little
12674 * endian */
12675static unsigned short U8TO16(const unsigned char *p) {
12676 return (((unsigned short) (p[0] & 0xff)) |
12677 ((unsigned short) (p[1] & 0xff) << 8));
12678}
12679 
12680/* store a 16 bit unsigned integer as two 8 bit unsigned integers in little
12681 * endian */
12682static void U16TO8(unsigned char *p, unsigned short v) {
12683 p[0] = (v) &0xff;
12684 p[1] = (v >> 8) & 0xff;
12685}
12686 
12687static void poly1305_init(poly1305_context *ctx, const unsigned char key[32]) {
12688 poly1305_state_internal_t *st = (poly1305_state_internal_t *) ctx;
12689 unsigned short t0, t1, t2, t3, t4, t5, t6, t7;
12690 size_t i;
12691 
12692 /* r &= 0xffffffc0ffffffc0ffffffc0fffffff */
12693 t0 = U8TO16(&key[0]);
12694 st->r[0] = (t0) &0x1fff;
12695 t1 = U8TO16(&key[2]);
12696 st->r[1] = ((t0 >> 13) | (t1 << 3)) & 0x1fff;
12697 t2 = U8TO16(&key[4]);
12698 st->r[2] = ((t1 >> 10) | (t2 << 6)) & 0x1f03;
12699 t3 = U8TO16(&key[6]);
12700 st->r[3] = ((t2 >> 7) | (t3 << 9)) & 0x1fff;
12701 t4 = U8TO16(&key[8]);
12702 st->r[4] = ((t3 >> 4) | (t4 << 12)) & 0x00ff;
12703 st->r[5] = ((t4 >> 1)) & 0x1ffe;
12704 t5 = U8TO16(&key[10]);
12705 st->r[6] = ((t4 >> 14) | (t5 << 2)) & 0x1fff;
12706 t6 = U8TO16(&key[12]);
12707 st->r[7] = ((t5 >> 11) | (t6 << 5)) & 0x1f81;
12708 t7 = U8TO16(&key[14]);
12709 st->r[8] = ((t6 >> 8) | (t7 << 8)) & 0x1fff;
12710 st->r[9] = ((t7 >> 5)) & 0x007f;
12711 
12712 /* h = 0 */
12713 for (i = 0; i < 10; i++) st->h[i] = 0;
12714 
12715 /* save pad for later */
12716 for (i = 0; i < 8; i++) st->pad[i] = U8TO16(&key[16 + (2 * i)]);
12717 
12718 st->leftover = 0;
12719 st->final = 0;
12720}
12721 
12722static void poly1305_blocks(poly1305_state_internal_t *st,
12723 const unsigned char *m, size_t bytes) {
12724 const unsigned short hibit = (st->final) ? 0 : (1 << 11); /* 1 << 128 */
12725 unsigned short t0, t1, t2, t3, t4, t5, t6, t7;
12726 unsigned long d[10];
12727 unsigned long c;
12728 
12729 while (bytes >= poly1305_block_size) {
12730 size_t i, j;
12731 
12732 /* h += m[i] */
12733 t0 = U8TO16(&m[0]);
12734 st->h[0] += (t0) &0x1fff;
12735 t1 = U8TO16(&m[2]);
12736 st->h[1] += ((t0 >> 13) | (t1 << 3)) & 0x1fff;
12737 t2 = U8TO16(&m[4]);
12738 st->h[2] += ((t1 >> 10) | (t2 << 6)) & 0x1fff;
12739 t3 = U8TO16(&m[6]);
12740 st->h[3] += ((t2 >> 7) | (t3 << 9)) & 0x1fff;
12741 t4 = U8TO16(&m[8]);
12742 st->h[4] += ((t3 >> 4) | (t4 << 12)) & 0x1fff;
12743 st->h[5] += ((t4 >> 1)) & 0x1fff;
12744 t5 = U8TO16(&m[10]);
12745 st->h[6] += ((t4 >> 14) | (t5 << 2)) & 0x1fff;
12746 t6 = U8TO16(&m[12]);
12747 st->h[7] += ((t5 >> 11) | (t6 << 5)) & 0x1fff;
12748 t7 = U8TO16(&m[14]);
12749 st->h[8] += ((t6 >> 8) | (t7 << 8)) & 0x1fff;
12750 st->h[9] += ((t7 >> 5)) | hibit;
12751 
12752 /* h *= r, (partial) h %= p */
12753 for (i = 0, c = 0; i < 10; i++) {
12754 d[i] = c;
12755 for (j = 0; j < 10; j++) {
12756 d[i] += (unsigned long) st->h[j] *
12757 ((j <= i) ? st->r[i - j] : (5 * st->r[i + 10 - j]));
12758 /* Sum(h[i] * r[i] * 5) will overflow slightly above 6 products with an
12759 * unclamped r, so carry at 5 */
12760 if (j == 4) {
12761 c = (d[i] >> 13);
12762 d[i] &= 0x1fff;
12763 }
12764 }
12765 c += (d[i] >> 13);
12766 d[i] &= 0x1fff;
12767 }
12768 c = ((c << 2) + c); /* c *= 5 */
12769 c += d[0];
12770 d[0] = ((unsigned short) c & 0x1fff);
12771 c = (c >> 13);
12772 d[1] += c;
12773 
12774 for (i = 0; i < 10; i++) st->h[i] = (unsigned short) d[i];
12775 
12776 m += poly1305_block_size;
12777 bytes -= poly1305_block_size;
12778 }
12779}
12780 
12781static POLY1305_NOINLINE void poly1305_finish(poly1305_context *ctx,
12782 unsigned char mac[16]) {
12783 poly1305_state_internal_t *st = (poly1305_state_internal_t *) ctx;
12784 unsigned short c;
12785 unsigned short g[10];
12786 unsigned short mask;
12787 unsigned long f;
12788 size_t i;
12789 
12790 /* process the remaining block */
12791 if (st->leftover) {
12792 size_t i = st->leftover;
12793 st->buffer[i++] = 1;
12794 for (; i < poly1305_block_size; i++) st->buffer[i] = 0;
12795 st->final = 1;
12796 poly1305_blocks(st, st->buffer, poly1305_block_size);
12797 }
12798 
12799 /* fully carry h */
12800 c = st->h[1] >> 13;
12801 st->h[1] &= 0x1fff;
12802 for (i = 2; i < 10; i++) {
12803 st->h[i] += c;
12804 c = st->h[i] >> 13;
12805 st->h[i] &= 0x1fff;
12806 }
12807 st->h[0] += (c * 5);
12808 c = st->h[0] >> 13;
12809 st->h[0] &= 0x1fff;
12810 st->h[1] += c;
12811 c = st->h[1] >> 13;
12812 st->h[1] &= 0x1fff;
12813 st->h[2] += c;
12814 
12815 /* compute h + -p */
12816 g[0] = st->h[0] + 5;
12817 c = g[0] >> 13;
12818 g[0] &= 0x1fff;
12819 for (i = 1; i < 10; i++) {
12820 g[i] = st->h[i] + c;
12821 c = g[i] >> 13;
12822 g[i] &= 0x1fff;
12823 }
12824 
12825 /* select h if h < p, or h + -p if h >= p */
12826 mask = (c ^ 1) - 1;
12827 for (i = 0; i < 10; i++) g[i] &= mask;
12828 mask = ~mask;
12829 for (i = 0; i < 10; i++) st->h[i] = (st->h[i] & mask) | g[i];
12830 
12831 /* h = h % (2^128) */
12832 st->h[0] = ((st->h[0]) | (st->h[1] << 13)) & 0xffff;
12833 st->h[1] = ((st->h[1] >> 3) | (st->h[2] << 10)) & 0xffff;
12834 st->h[2] = ((st->h[2] >> 6) | (st->h[3] << 7)) & 0xffff;
12835 st->h[3] = ((st->h[3] >> 9) | (st->h[4] << 4)) & 0xffff;
12836 st->h[4] = ((st->h[4] >> 12) | (st->h[5] << 1) | (st->h[6] << 14)) & 0xffff;
12837 st->h[5] = ((st->h[6] >> 2) | (st->h[7] << 11)) & 0xffff;
12838 st->h[6] = ((st->h[7] >> 5) | (st->h[8] << 8)) & 0xffff;
12839 st->h[7] = ((st->h[8] >> 8) | (st->h[9] << 5)) & 0xffff;
12840 
12841 /* mac = (h + pad) % (2^128) */
12842 f = (unsigned long) st->h[0] + st->pad[0];
12843 st->h[0] = (unsigned short) f;
12844 for (i = 1; i < 8; i++) {
12845 f = (unsigned long) st->h[i] + st->pad[i] + (f >> 16);
12846 st->h[i] = (unsigned short) f;
12847 }
12848 
12849 for (i = 0; i < 8; i++) U16TO8(mac + (i * 2), st->h[i]);
12850 
12851 /* zero out the state */
12852 for (i = 0; i < 10; i++) st->h[i] = 0;
12853 for (i = 0; i < 10; i++) st->r[i] = 0;
12854 for (i = 0; i < 8; i++) st->pad[i] = 0;
12855}
12856#elif defined(POLY1305_32BIT) || \
12857 (!defined(POLY1305_64BIT) && defined(__GUESS32))
12858/*
12859 poly1305 implementation using 32 bit * 32 bit = 64 bit multiplication
12860and 64 bit addition static */
12861 
12862#if defined(_MSC_VER) && _MSC_VER < 1700
12863#define POLY1305_NOINLINE
12864#elif defined(_MSC_VER)
12865#define POLY1305_NOINLINE __declspec(noinline)
12866#elif defined(__GNUC__)
12867#define POLY1305_NOINLINE __attribute__((noinline))
12868#else
12869#define POLY1305_NOINLINE
12870#endif
12871 
12872#define poly1305_block_size 16
12873 
12874/* 17 + sizeof(size_t) + 14*sizeof(unsigned long) */
12875typedef struct poly1305_state_internal_t {
12876 unsigned long r[5];
12877 unsigned long h[5];
12878 unsigned long pad[4];
12879 size_t leftover;
12880 unsigned char buffer[poly1305_block_size];
12881 unsigned char final;
12882} poly1305_state_internal_t;
12883 
12884/* interpret four 8 bit unsigned integers as a 32 bit unsigned integer in little
12885 * endian */
12886static unsigned long U8TO32(const unsigned char *p) {
12887 return (((unsigned long) (p[0] & 0xff)) |
12888 ((unsigned long) (p[1] & 0xff) << 8) |
12889 ((unsigned long) (p[2] & 0xff) << 16) |
12890 ((unsigned long) (p[3] & 0xff) << 24));
12891}
12892 
12893/* store a 32 bit unsigned integer as four 8 bit unsigned integers in little
12894 * endian */
12895static void U32TO8(unsigned char *p, unsigned long v) {
12896 p[0] = (unsigned char) ((v) &0xff);
12897 p[1] = (unsigned char) ((v >> 8) & 0xff);
12898 p[2] = (unsigned char) ((v >> 16) & 0xff);
12899 p[3] = (unsigned char) ((v >> 24) & 0xff);
12900}
12901 
12902static void poly1305_init(poly1305_context *ctx, const unsigned char key[32]) {
12903 poly1305_state_internal_t *st = (poly1305_state_internal_t *) ctx;
12904 
12905 /* r &= 0xffffffc0ffffffc0ffffffc0fffffff */
12906 st->r[0] = (U8TO32(&key[0])) & 0x3ffffff;
12907 st->r[1] = (U8TO32(&key[3]) >> 2) & 0x3ffff03;
12908 st->r[2] = (U8TO32(&key[6]) >> 4) & 0x3ffc0ff;
12909 st->r[3] = (U8TO32(&key[9]) >> 6) & 0x3f03fff;
12910 st->r[4] = (U8TO32(&key[12]) >> 8) & 0x00fffff;
12911 
12912 /* h = 0 */
12913 st->h[0] = 0;
12914 st->h[1] = 0;
12915 st->h[2] = 0;
12916 st->h[3] = 0;
12917 st->h[4] = 0;
12918 
12919 /* save pad for later */
12920 st->pad[0] = U8TO32(&key[16]);
12921 st->pad[1] = U8TO32(&key[20]);
12922 st->pad[2] = U8TO32(&key[24]);
12923 st->pad[3] = U8TO32(&key[28]);
12924 
12925 st->leftover = 0;
12926 st->final = 0;
12927}
12928 
12929static void poly1305_blocks(poly1305_state_internal_t *st,
12930 const unsigned char *m, size_t bytes) {
12931 const unsigned long hibit = (st->final) ? 0 : (1UL << 24); /* 1 << 128 */
12932 unsigned long r0, r1, r2, r3, r4;
12933 unsigned long s1, s2, s3, s4;
12934 unsigned long h0, h1, h2, h3, h4;
12935 uint64_t d0, d1, d2, d3, d4;
12936 unsigned long c;
12937 
12938 r0 = st->r[0];
12939 r1 = st->r[1];
12940 r2 = st->r[2];
12941 r3 = st->r[3];
12942 r4 = st->r[4];
12943 
12944 s1 = r1 * 5;
12945 s2 = r2 * 5;
12946 s3 = r3 * 5;
12947 s4 = r4 * 5;
12948 
12949 h0 = st->h[0];
12950 h1 = st->h[1];
12951 h2 = st->h[2];
12952 h3 = st->h[3];
12953 h4 = st->h[4];
12954 
12955 while (bytes >= poly1305_block_size) {
12956 /* h += m[i] */
12957 h0 += (U8TO32(m + 0)) & 0x3ffffff;
12958 h1 += (U8TO32(m + 3) >> 2) & 0x3ffffff;
12959 h2 += (U8TO32(m + 6) >> 4) & 0x3ffffff;
12960 h3 += (U8TO32(m + 9) >> 6) & 0x3ffffff;
12961 h4 += (U8TO32(m + 12) >> 8) | hibit;
12962 
12963 /* h *= r */
12964 d0 = ((uint64_t) h0 * r0) + ((uint64_t) h1 * s4) + ((uint64_t) h2 * s3) +
12965 ((uint64_t) h3 * s2) + ((uint64_t) h4 * s1);
12966 d1 = ((uint64_t) h0 * r1) + ((uint64_t) h1 * r0) + ((uint64_t) h2 * s4) +
12967 ((uint64_t) h3 * s3) + ((uint64_t) h4 * s2);
12968 d2 = ((uint64_t) h0 * r2) + ((uint64_t) h1 * r1) + ((uint64_t) h2 * r0) +
12969 ((uint64_t) h3 * s4) + ((uint64_t) h4 * s3);
12970 d3 = ((uint64_t) h0 * r3) + ((uint64_t) h1 * r2) + ((uint64_t) h2 * r1) +
12971 ((uint64_t) h3 * r0) + ((uint64_t) h4 * s4);
12972 d4 = ((uint64_t) h0 * r4) + ((uint64_t) h1 * r3) + ((uint64_t) h2 * r2) +
12973 ((uint64_t) h3 * r1) + ((uint64_t) h4 * r0);
12974 
12975 /* (partial) h %= p */
12976 c = (unsigned long) (d0 >> 26);
12977 h0 = (unsigned long) d0 & 0x3ffffff;
12978 d1 += c;
12979 c = (unsigned long) (d1 >> 26);
12980 h1 = (unsigned long) d1 & 0x3ffffff;
12981 d2 += c;
12982 c = (unsigned long) (d2 >> 26);
12983 h2 = (unsigned long) d2 & 0x3ffffff;
12984 d3 += c;
12985 c = (unsigned long) (d3 >> 26);
12986 h3 = (unsigned long) d3 & 0x3ffffff;
12987 d4 += c;
12988 c = (unsigned long) (d4 >> 26);
12989 h4 = (unsigned long) d4 & 0x3ffffff;
12990 h0 += c * 5;
12991 c = (h0 >> 26);
12992 h0 = h0 & 0x3ffffff;
12993 h1 += c;
12994 
12995 m += poly1305_block_size;
12996 bytes -= poly1305_block_size;
12997 }
12998 
12999 st->h[0] = h0;
13000 st->h[1] = h1;
13001 st->h[2] = h2;
13002 st->h[3] = h3;
13003 st->h[4] = h4;
13004}
13005 
13006static POLY1305_NOINLINE void poly1305_finish(poly1305_context *ctx,
13007 unsigned char mac[16]) {
13008 poly1305_state_internal_t *st = (poly1305_state_internal_t *) ctx;
13009 unsigned long h0, h1, h2, h3, h4, c;
13010 unsigned long g0, g1, g2, g3, g4;
13011 uint64_t f;
13012 unsigned long mask;
13013 
13014 /* process the remaining block */
13015 if (st->leftover) {
13016 size_t i = st->leftover;
13017 st->buffer[i++] = 1;
13018 for (; i < poly1305_block_size; i++) st->buffer[i] = 0;
13019 st->final = 1;
13020 poly1305_blocks(st, st->buffer, poly1305_block_size);
13021 }
13022 
13023 /* fully carry h */
13024 h0 = st->h[0];
13025 h1 = st->h[1];
13026 h2 = st->h[2];
13027 h3 = st->h[3];
13028 h4 = st->h[4];
13029 
13030 c = h1 >> 26;
13031 h1 = h1 & 0x3ffffff;
13032 h2 += c;
13033 c = h2 >> 26;
13034 h2 = h2 & 0x3ffffff;
13035 h3 += c;
13036 c = h3 >> 26;
13037 h3 = h3 & 0x3ffffff;
13038 h4 += c;
13039 c = h4 >> 26;
13040 h4 = h4 & 0x3ffffff;
13041 h0 += c * 5;
13042 c = h0 >> 26;
13043 h0 = h0 & 0x3ffffff;
13044 h1 += c;
13045 
13046 /* compute h + -p */
13047 g0 = h0 + 5;
13048 c = g0 >> 26;
13049 g0 &= 0x3ffffff;
13050 g1 = h1 + c;
13051 c = g1 >> 26;
13052 g1 &= 0x3ffffff;
13053 g2 = h2 + c;
13054 c = g2 >> 26;
13055 g2 &= 0x3ffffff;
13056 g3 = h3 + c;
13057 c = g3 >> 26;
13058 g3 &= 0x3ffffff;
13059 g4 = h4 + c - (1UL << 26);
13060 
13061 /* select h if h < p, or h + -p if h >= p */
13062 mask = (g4 >> ((sizeof(unsigned long) * 8) - 1)) - 1;
13063 g0 &= mask;
13064 g1 &= mask;
13065 g2 &= mask;
13066 g3 &= mask;
13067 g4 &= mask;
13068 mask = ~mask;
13069 h0 = (h0 & mask) | g0;
13070 h1 = (h1 & mask) | g1;
13071 h2 = (h2 & mask) | g2;
13072 h3 = (h3 & mask) | g3;
13073 h4 = (h4 & mask) | g4;
13074 
13075 /* h = h % (2^128) */
13076 h0 = ((h0) | (h1 << 26)) & 0xffffffff;
13077 h1 = ((h1 >> 6) | (h2 << 20)) & 0xffffffff;
13078 h2 = ((h2 >> 12) | (h3 << 14)) & 0xffffffff;
13079 h3 = ((h3 >> 18) | (h4 << 8)) & 0xffffffff;
13080 
13081 /* mac = (h + pad) % (2^128) */
13082 f = (uint64_t) h0 + st->pad[0];
13083 h0 = (unsigned long) f;
13084 f = (uint64_t) h1 + st->pad[1] + (f >> 32);
13085 h1 = (unsigned long) f;
13086 f = (uint64_t) h2 + st->pad[2] + (f >> 32);
13087 h2 = (unsigned long) f;
13088 f = (uint64_t) h3 + st->pad[3] + (f >> 32);
13089 h3 = (unsigned long) f;
13090 
13091 U32TO8(mac + 0, h0);
13092 U32TO8(mac + 4, h1);
13093 U32TO8(mac + 8, h2);
13094 U32TO8(mac + 12, h3);
13095 
13096 /* zero out the state */
13097 st->h[0] = 0;
13098 st->h[1] = 0;
13099 st->h[2] = 0;
13100 st->h[3] = 0;
13101 st->h[4] = 0;
13102 st->r[0] = 0;
13103 st->r[1] = 0;
13104 st->r[2] = 0;
13105 st->r[3] = 0;
13106 st->r[4] = 0;
13107 st->pad[0] = 0;
13108 st->pad[1] = 0;
13109 st->pad[2] = 0;
13110 st->pad[3] = 0;
13111}
13112 
13113#else
13114/*
13115 poly1305 implementation using 64 bit * 64 bit = 128 bit multiplication
13116and 128 bit addition static */
13117 
13118#if defined(_MSC_VER)
13119 
13120typedef struct uint128_t {
13121 uint64_t lo;
13122 uint64_t hi;
13123} uint128_t;
13124 
13125#define MUL128(out, x, y) out.lo = _umul128((x), (y), &out.hi)
13126#define ADD(out, in) \
13127 { \
13128 uint64_t t = out.lo; \
13129 out.lo += in.lo; \
13130 out.hi += (out.lo < t) + in.hi; \
13131 }
13132#define ADDLO(out, in) \
13133 { \
13134 uint64_t t = out.lo; \
13135 out.lo += in; \
13136 out.hi += (out.lo < t); \
13137 }
13138#define SHR(in, shift) (__shiftright128(in.lo, in.hi, (shift)))
13139#define LO(in) (in.lo)
13140 
13141#if defined(_MSC_VER) && _MSC_VER < 1700
13142#define POLY1305_NOINLINE
13143#else
13144#define POLY1305_NOINLINE __declspec(noinline)
13145#endif
13146#elif defined(__GNUC__)
13147#if defined(__SIZEOF_INT128__)
13148// Get rid of GCC warning "ISO C does not support '__int128' types"
13149#pragma GCC diagnostic push
13150#pragma GCC diagnostic ignored "-Wpedantic"
13151typedef unsigned __int128 uint128_t;
13152#pragma GCC diagnostic pop
13153#else
13154typedef unsigned uint128_t __attribute__((mode(TI)));
13155#endif
13156 
13157#define MUL128(out, x, y) out = ((uint128_t) x * y)
13158#define ADD(out, in) out += in
13159#define ADDLO(out, in) out += in
13160#define SHR(in, shift) (uint64_t)(in >> (shift))
13161#define LO(in) (uint64_t)(in)
13162 
13163#define POLY1305_NOINLINE __attribute__((noinline))
13164#endif
13165 
13166#define poly1305_block_size 16
13167 
13168/* 17 + sizeof(size_t) + 8*sizeof(uint64_t) */
13169typedef struct poly1305_state_internal_t {
13170 uint64_t r[3];
13171 uint64_t h[3];
13172 uint64_t pad[2];
13173 size_t leftover;
13174 unsigned char buffer[poly1305_block_size];
13175 unsigned char final;
13176} poly1305_state_internal_t;
13177 
13178/* interpret eight 8 bit unsigned integers as a 64 bit unsigned integer in
13179 * little endian */
13180static uint64_t U8TO64(const unsigned char *p) {
13181 return (((uint64_t) (p[0] & 0xff)) | ((uint64_t) (p[1] & 0xff) << 8) |
13182 ((uint64_t) (p[2] & 0xff) << 16) | ((uint64_t) (p[3] & 0xff) << 24) |
13183 ((uint64_t) (p[4] & 0xff) << 32) | ((uint64_t) (p[5] & 0xff) << 40) |
13184 ((uint64_t) (p[6] & 0xff) << 48) | ((uint64_t) (p[7] & 0xff) << 56));
13185}
13186 
13187/* store a 64 bit unsigned integer as eight 8 bit unsigned integers in little
13188 * endian */
13189static void U64TO8(unsigned char *p, uint64_t v) {
13190 p[0] = (unsigned char) ((v) &0xff);
13191 p[1] = (unsigned char) ((v >> 8) & 0xff);
13192 p[2] = (unsigned char) ((v >> 16) & 0xff);
13193 p[3] = (unsigned char) ((v >> 24) & 0xff);
13194 p[4] = (unsigned char) ((v >> 32) & 0xff);
13195 p[5] = (unsigned char) ((v >> 40) & 0xff);
13196 p[6] = (unsigned char) ((v >> 48) & 0xff);
13197 p[7] = (unsigned char) ((v >> 56) & 0xff);
13198}
13199 
13200static void poly1305_init(poly1305_context *ctx, const unsigned char key[32]) {
13201 poly1305_state_internal_t *st = (poly1305_state_internal_t *) ctx;
13202 uint64_t t0, t1;
13203 
13204 /* r &= 0xffffffc0ffffffc0ffffffc0fffffff */
13205 t0 = U8TO64(&key[0]);
13206 t1 = U8TO64(&key[8]);
13207 
13208 st->r[0] = (t0) &0xffc0fffffff;
13209 st->r[1] = ((t0 >> 44) | (t1 << 20)) & 0xfffffc0ffff;
13210 st->r[2] = ((t1 >> 24)) & 0x00ffffffc0f;
13211 
13212 /* h = 0 */
13213 st->h[0] = 0;
13214 st->h[1] = 0;
13215 st->h[2] = 0;
13216 
13217 /* save pad for later */
13218 st->pad[0] = U8TO64(&key[16]);
13219 st->pad[1] = U8TO64(&key[24]);
13220 
13221 st->leftover = 0;
13222 st->final = 0;
13223}
13224 
13225static void poly1305_blocks(poly1305_state_internal_t *st,
13226 const unsigned char *m, size_t bytes) {
13227 const uint64_t hibit = (st->final) ? 0 : ((uint64_t) 1 << 40); /* 1 << 128 */
13228 uint64_t r0, r1, r2;
13229 uint64_t s1, s2;
13230 uint64_t h0, h1, h2;
13231 uint64_t c;
13232 uint128_t d0, d1, d2, d;
13233 
13234 r0 = st->r[0];
13235 r1 = st->r[1];
13236 r2 = st->r[2];
13237 
13238 h0 = st->h[0];
13239 h1 = st->h[1];
13240 h2 = st->h[2];
13241 
13242 s1 = r1 * (5 << 2);
13243 s2 = r2 * (5 << 2);
13244 
13245 while (bytes >= poly1305_block_size) {
13246 uint64_t t0, t1;
13247 
13248 /* h += m[i] */
13249 t0 = U8TO64(&m[0]);
13250 t1 = U8TO64(&m[8]);
13251 
13252 h0 += ((t0) &0xfffffffffff);
13253 h1 += (((t0 >> 44) | (t1 << 20)) & 0xfffffffffff);
13254 h2 += (((t1 >> 24)) & 0x3ffffffffff) | hibit;
13255 
13256 /* h *= r */
13257 MUL128(d0, h0, r0);
13258 MUL128(d, h1, s2);
13259 ADD(d0, d);
13260 MUL128(d, h2, s1);
13261 ADD(d0, d);
13262 MUL128(d1, h0, r1);
13263 MUL128(d, h1, r0);
13264 ADD(d1, d);
13265 MUL128(d, h2, s2);
13266 ADD(d1, d);
13267 MUL128(d2, h0, r2);
13268 MUL128(d, h1, r1);
13269 ADD(d2, d);
13270 MUL128(d, h2, r0);
13271 ADD(d2, d);
13272 
13273 /* (partial) h %= p */
13274 c = SHR(d0, 44);
13275 h0 = LO(d0) & 0xfffffffffff;
13276 ADDLO(d1, c);
13277 c = SHR(d1, 44);
13278 h1 = LO(d1) & 0xfffffffffff;
13279 ADDLO(d2, c);
13280 c = SHR(d2, 42);
13281 h2 = LO(d2) & 0x3ffffffffff;
13282 h0 += c * 5;
13283 c = (h0 >> 44);
13284 h0 = h0 & 0xfffffffffff;
13285 h1 += c;
13286 
13287 m += poly1305_block_size;
13288 bytes -= poly1305_block_size;
13289 }
13290 
13291 st->h[0] = h0;
13292 st->h[1] = h1;
13293 st->h[2] = h2;
13294}
13295 
13296static POLY1305_NOINLINE void poly1305_finish(poly1305_context *ctx,
13297 unsigned char mac[16]) {
13298 poly1305_state_internal_t *st = (poly1305_state_internal_t *) ctx;
13299 uint64_t h0, h1, h2, c;
13300 uint64_t g0, g1, g2;
13301 uint64_t t0, t1;
13302 
13303 /* process the remaining block */
13304 if (st->leftover) {
13305 size_t i = st->leftover;
13306 st->buffer[i] = 1;
13307 for (i = i + 1; i < poly1305_block_size; i++) st->buffer[i] = 0;
13308 st->final = 1;
13309 poly1305_blocks(st, st->buffer, poly1305_block_size);
13310 }
13311 
13312 /* fully carry h */
13313 h0 = st->h[0];
13314 h1 = st->h[1];
13315 h2 = st->h[2];
13316 
13317 c = (h1 >> 44);
13318 h1 &= 0xfffffffffff;
13319 h2 += c;
13320 c = (h2 >> 42);
13321 h2 &= 0x3ffffffffff;
13322 h0 += c * 5;
13323 c = (h0 >> 44);
13324 h0 &= 0xfffffffffff;
13325 h1 += c;
13326 c = (h1 >> 44);
13327 h1 &= 0xfffffffffff;
13328 h2 += c;
13329 c = (h2 >> 42);
13330 h2 &= 0x3ffffffffff;
13331 h0 += c * 5;
13332 c = (h0 >> 44);
13333 h0 &= 0xfffffffffff;
13334 h1 += c;
13335 
13336 /* compute h + -p */
13337 g0 = h0 + 5;
13338 c = (g0 >> 44);
13339 g0 &= 0xfffffffffff;
13340 g1 = h1 + c;
13341 c = (g1 >> 44);
13342 g1 &= 0xfffffffffff;
13343 g2 = h2 + c - ((uint64_t) 1 << 42);
13344 
13345 /* select h if h < p, or h + -p if h >= p */
13346 c = (g2 >> ((sizeof(uint64_t) * 8) - 1)) - 1;
13347 g0 &= c;
13348 g1 &= c;
13349 g2 &= c;
13350 c = ~c;
13351 h0 = (h0 & c) | g0;
13352 h1 = (h1 & c) | g1;
13353 h2 = (h2 & c) | g2;
13354 
13355 /* h = (h + pad) */
13356 t0 = st->pad[0];
13357 t1 = st->pad[1];
13358 
13359 h0 += ((t0) &0xfffffffffff);
13360 c = (h0 >> 44);
13361 h0 &= 0xfffffffffff;
13362 h1 += (((t0 >> 44) | (t1 << 20)) & 0xfffffffffff) + c;
13363 c = (h1 >> 44);
13364 h1 &= 0xfffffffffff;
13365 h2 += (((t1 >> 24)) & 0x3ffffffffff) + c;
13366 h2 &= 0x3ffffffffff;
13367 
13368 /* mac = h % (2^128) */
13369 h0 = ((h0) | (h1 << 44));
13370 h1 = ((h1 >> 20) | (h2 << 24));
13371 
13372 U64TO8(&mac[0], h0);
13373 U64TO8(&mac[8], h1);
13374 
13375 /* zero out the state */
13376 st->h[0] = 0;
13377 st->h[1] = 0;
13378 st->h[2] = 0;
13379 st->r[0] = 0;
13380 st->r[1] = 0;
13381 st->r[2] = 0;
13382 st->pad[0] = 0;
13383 st->pad[1] = 0;
13384}
13385 
13386#endif
13387 
13388static void poly1305_update(poly1305_context *ctx, const unsigned char *m,
13389 size_t bytes) {
13390 poly1305_state_internal_t *st = (poly1305_state_internal_t *) ctx;
13391 size_t i;
13392 
13393 /* handle leftover */
13394 if (st->leftover) {
13395 size_t want = (poly1305_block_size - st->leftover);
13396 if (want > bytes) want = bytes;
13397 for (i = 0; i < want; i++) st->buffer[st->leftover + i] = m[i];
13398 bytes -= want;
13399 m += want;
13400 st->leftover += want;
13401 if (st->leftover < poly1305_block_size) return;
13402 poly1305_blocks(st, st->buffer, poly1305_block_size);
13403 st->leftover = 0;
13404 }
13405 
13406 /* process full blocks */
13407 if (bytes >= poly1305_block_size) {
13408 size_t want = (bytes & (size_t) ~(poly1305_block_size - 1));
13409 poly1305_blocks(st, m, want);
13410 m += want;
13411 bytes -= want;
13412 }
13413 
13414 /* store leftover */
13415 if (bytes) {
13416 for (i = 0; i < bytes; i++) st->buffer[st->leftover + i] = m[i];
13417 st->leftover += bytes;
13418 }
13419}
13420 
13421// ******* END: poly1305-donna.c ********
13422// ******* BEGIN: portable8439.c ********
13423 
13424#define __CHACHA20_BLOCK_SIZE (64)
13425#define __POLY1305_KEY_SIZE (32)
13426 
13427static PORTABLE_8439_DECL uint8_t __ZEROES[16] = {0};
13428static PORTABLE_8439_DECL void pad_if_needed(poly1305_context *ctx,
13429 size_t size) {
13430 size_t padding = size % 16;
13431 if (padding != 0) {
13432 poly1305_update(ctx, __ZEROES, 16 - padding);
13433 }
13434}
13435 
13436#define __u8(v) ((uint8_t) ((v) &0xFF))
13437 
13438// TODO: make this depending on the unaligned/native read size possible
13439static PORTABLE_8439_DECL void write_64bit_int(poly1305_context *ctx,
13440 uint64_t value) {
13441 uint8_t result[8];
13442 result[0] = __u8(value);
13443 result[1] = __u8(value >> 8);
13444 result[2] = __u8(value >> 16);
13445 result[3] = __u8(value >> 24);
13446 result[4] = __u8(value >> 32);
13447 result[5] = __u8(value >> 40);
13448 result[6] = __u8(value >> 48);
13449 result[7] = __u8(value >> 56);
13450 poly1305_update(ctx, result, 8);
13451}
13452 
13453static PORTABLE_8439_DECL void poly1305_calculate_mac(
13454 uint8_t *mac, const uint8_t *cipher_text, size_t cipher_text_size,
13455 const uint8_t key[RFC_8439_KEY_SIZE],
13456 const uint8_t nonce[RFC_8439_NONCE_SIZE], const uint8_t *ad,
13457 size_t ad_size) {
13458 // init poly key (section 2.6)
13459 uint8_t poly_key[__POLY1305_KEY_SIZE] = {0};
13460 poly1305_context poly_ctx;
13461 rfc8439_keygen(poly_key, key, nonce);
13462 // start poly1305 mac
13463 poly1305_init(&poly_ctx, poly_key);
13464 
13465 if (ad != NULL && ad_size > 0) {
13466 // write AD if present
13467 poly1305_update(&poly_ctx, ad, ad_size);
13468 pad_if_needed(&poly_ctx, ad_size);
13469 }
13470 
13471 // now write the cipher text
13472 poly1305_update(&poly_ctx, cipher_text, cipher_text_size);
13473 pad_if_needed(&poly_ctx, cipher_text_size);
13474 
13475 // write sizes
13476 write_64bit_int(&poly_ctx, ad_size);
13477 write_64bit_int(&poly_ctx, cipher_text_size);
13478 
13479 // calculate MAC
13480 poly1305_finish(&poly_ctx, mac);
13481}
13482 
13483#define MG_PM(p) ((size_t) (p))
13484 
13485// pointers overlap if the smaller either ahead of the end,
13486// or its end is before the start of the other
13487//
13488// s_size should be smaller or equal to b_size
13489#define MG_OVERLAPPING(s, s_size, b, b_size) \
13490 (MG_PM(s) < MG_PM((b) + (b_size))) && (MG_PM(b) < MG_PM((s) + (s_size)))
13491 
13492PORTABLE_8439_DECL size_t mg_chacha20_poly1305_encrypt(
13493 uint8_t *restrict cipher_text, const uint8_t key[RFC_8439_KEY_SIZE],
13494 const uint8_t nonce[RFC_8439_NONCE_SIZE], const uint8_t *restrict ad,
13495 size_t ad_size, const uint8_t *restrict plain_text,
13496 size_t plain_text_size) {
13497 size_t new_size = plain_text_size + RFC_8439_TAG_SIZE;
13498 if (MG_OVERLAPPING(plain_text, plain_text_size, cipher_text, new_size)) {
13499 return (size_t) -1;
13500 }
13501 chacha20_xor_stream(cipher_text, plain_text, plain_text_size, key, nonce, 1);
13502 poly1305_calculate_mac(cipher_text + plain_text_size, cipher_text,
13503 plain_text_size, key, nonce, ad, ad_size);
13504 return new_size;
13505}
13506 
13507PORTABLE_8439_DECL size_t mg_chacha20_poly1305_decrypt(
13508 uint8_t *restrict plain_text, const uint8_t key[RFC_8439_KEY_SIZE],
13509 const uint8_t nonce[RFC_8439_NONCE_SIZE],
13510 const uint8_t *restrict cipher_text, size_t cipher_text_size) {
13511 // first we calculate the mac and see if it lines up, only then do we decrypt
13512 size_t actual_size = cipher_text_size - RFC_8439_TAG_SIZE;
13513 if (MG_OVERLAPPING(plain_text, actual_size, cipher_text, cipher_text_size)) {
13514 return (size_t) -1;
13515 }
13516 
13517 chacha20_xor_stream(plain_text, cipher_text, actual_size, key, nonce, 1);
13518 return actual_size;
13519}
13520// ******* END: portable8439.c ********
13521#endif // MG_TLS == MG_TLS_BUILTIN
13522 
13523#ifdef MG_ENABLE_LINES
13524#line 1 "src/tls_dummy.c"
13525#endif
13526 
13527 
13528#if MG_TLS == MG_TLS_NONE
13529void mg_tls_init(struct mg_connection *c, const struct mg_tls_opts *opts) {
13530 (void) opts;
13531 mg_error(c, "TLS is not enabled");
13532}
13533void mg_tls_handshake(struct mg_connection *c) {
13534 (void) c;
13535}
13536void mg_tls_free(struct mg_connection *c) {
13537 (void) c;
13538}
13539long mg_tls_recv(struct mg_connection *c, void *buf, size_t len) {
13540 return c == NULL || buf == NULL || len == 0 ? 0 : -1;
13541}
13542long mg_tls_send(struct mg_connection *c, const void *buf, size_t len) {
13543 return c == NULL || buf == NULL || len == 0 ? 0 : -1;
13544}
13545size_t mg_tls_pending(struct mg_connection *c) {
13546 (void) c;
13547 return 0;
13548}
13549void mg_tls_ctx_init(struct mg_mgr *mgr) {
13550 (void) mgr;
13551}
13552void mg_tls_ctx_free(struct mg_mgr *mgr) {
13553 (void) mgr;
13554}
13555#endif
13556 
13557#ifdef MG_ENABLE_LINES
13558#line 1 "src/tls_mbed.c"
13559#endif
13560 
13561 
13562 
13563#if MG_TLS == MG_TLS_MBED
13564 
13565#if defined(MBEDTLS_VERSION_NUMBER) && MBEDTLS_VERSION_NUMBER >= 0x03000000
13566#define MG_MBEDTLS_RNG_GET , mg_mbed_rng, NULL
13567#else
13568#define MG_MBEDTLS_RNG_GET
13569#endif
13570 
13571static int mg_mbed_rng(void *ctx, unsigned char *buf, size_t len) {
13572 mg_random(buf, len);
13573 (void) ctx;
13574 return 0;
13575}
13576 
13577static bool mg_load_cert(struct mg_str str, mbedtls_x509_crt *p) {
13578 int rc;
13579 if (str.buf == NULL || str.buf[0] == '\0' || str.buf[0] == '*') return true;
13580 if (str.buf[0] == '-') str.len++; // PEM, include trailing NUL
13581 if ((rc = mbedtls_x509_crt_parse(p, (uint8_t *) str.buf, str.len)) != 0) {
13582 MG_ERROR(("cert err %#x", -rc));
13583 return false;
13584 }
13585 return true;
13586}
13587 
13588static bool mg_load_key(struct mg_str str, mbedtls_pk_context *p) {
13589 int rc;
13590 if (str.buf == NULL || str.buf[0] == '\0' || str.buf[0] == '*') return true;
13591 if (str.buf[0] == '-') str.len++; // PEM, include trailing NUL
13592 if ((rc = mbedtls_pk_parse_key(p, (uint8_t *) str.buf, str.len, NULL,
13593 0 MG_MBEDTLS_RNG_GET)) != 0) {
13594 MG_ERROR(("key err %#x", -rc));
13595 return false;
13596 }
13597 return true;
13598}
13599 
13600void mg_tls_free(struct mg_connection *c) {
13601 struct mg_tls *tls = (struct mg_tls *) c->tls;
13602 if (tls != NULL) {
13603 mbedtls_ssl_free(&tls->ssl);
13604 mbedtls_pk_free(&tls->pk);
13605 mbedtls_x509_crt_free(&tls->ca);
13606 mbedtls_x509_crt_free(&tls->cert);
13607 mbedtls_ssl_config_free(&tls->conf);
13608#ifdef MBEDTLS_SSL_SESSION_TICKETS
13609 mbedtls_ssl_ticket_free(&tls->ticket);
13610#endif
13611 free(tls);
13612 c->tls = NULL;
13613 }
13614}
13615 
13616static int mg_net_send(void *ctx, const unsigned char *buf, size_t len) {
13617 long n = mg_io_send((struct mg_connection *) ctx, buf, len);
13618 MG_VERBOSE(("%lu n=%ld e=%d", ((struct mg_connection *) ctx)->id, n, errno));
13619 if (n == MG_IO_WAIT) return MBEDTLS_ERR_SSL_WANT_WRITE;
13620 if (n == MG_IO_RESET) return MBEDTLS_ERR_NET_CONN_RESET;
13621 if (n == MG_IO_ERR) return MBEDTLS_ERR_NET_SEND_FAILED;
13622 return (int) n;
13623}
13624 
13625static int mg_net_recv(void *ctx, unsigned char *buf, size_t len) {
13626 long n = mg_io_recv((struct mg_connection *) ctx, buf, len);
13627 MG_VERBOSE(("%lu n=%ld", ((struct mg_connection *) ctx)->id, n));
13628 if (n == MG_IO_WAIT) return MBEDTLS_ERR_SSL_WANT_WRITE;
13629 if (n == MG_IO_RESET) return MBEDTLS_ERR_NET_CONN_RESET;
13630 if (n == MG_IO_ERR) return MBEDTLS_ERR_NET_RECV_FAILED;
13631 return (int) n;
13632}
13633 
13634void mg_tls_handshake(struct mg_connection *c) {
13635 struct mg_tls *tls = (struct mg_tls *) c->tls;
13636 int rc = mbedtls_ssl_handshake(&tls->ssl);
13637 if (rc == 0) { // Success
13638 MG_DEBUG(("%lu success", c->id));
13639 c->is_tls_hs = 0;
13640 mg_call(c, MG_EV_TLS_HS, NULL);
13641 } else if (rc == MBEDTLS_ERR_SSL_WANT_READ ||
13642 rc == MBEDTLS_ERR_SSL_WANT_WRITE) { // Still pending
13643 MG_VERBOSE(("%lu pending, %d%d %d (-%#x)", c->id, c->is_connecting,
13644 c->is_tls_hs, rc, -rc));
13645 } else {
13646 mg_error(c, "TLS handshake: -%#x", -rc); // Error
13647 }
13648}
13649 
13650static void debug_cb(void *c, int lev, const char *s, int n, const char *s2) {
13651 n = (int) strlen(s2) - 1;
13652 MG_INFO(("%lu %d %.*s", ((struct mg_connection *) c)->id, lev, n, s2));
13653 (void) s;
13654}
13655 
13656void mg_tls_init(struct mg_connection *c, const struct mg_tls_opts *opts) {
13657 struct mg_tls *tls = (struct mg_tls *) calloc(1, sizeof(*tls));
13658 int rc = 0;
13659 c->tls = tls;
13660 if (c->tls == NULL) {
13661 mg_error(c, "TLS OOM");
13662 goto fail;
13663 }
13664 if (c->is_listening) goto fail;
13665 MG_DEBUG(("%lu Setting TLS", c->id));
13666 MG_PROF_ADD(c, "mbedtls_init_start");
13667#if defined(MBEDTLS_VERSION_NUMBER) && MBEDTLS_VERSION_NUMBER >= 0x03000000 && \
13668 defined(MBEDTLS_PSA_CRYPTO_C)
13669 psa_crypto_init(); // https://github.com/Mbed-TLS/mbedtls/issues/9072#issuecomment-2084845711
13670#endif
13671 mbedtls_ssl_init(&tls->ssl);
13672 mbedtls_ssl_config_init(&tls->conf);
13673 mbedtls_x509_crt_init(&tls->ca);
13674 mbedtls_x509_crt_init(&tls->cert);
13675 mbedtls_pk_init(&tls->pk);
13676 mbedtls_ssl_conf_dbg(&tls->conf, debug_cb, c);
13677#if defined(MG_MBEDTLS_DEBUG_LEVEL)
13678 mbedtls_debug_set_threshold(MG_MBEDTLS_DEBUG_LEVEL);
13679#endif
13680 if ((rc = mbedtls_ssl_config_defaults(
13681 &tls->conf,
13682 c->is_client ? MBEDTLS_SSL_IS_CLIENT : MBEDTLS_SSL_IS_SERVER,
13683 MBEDTLS_SSL_TRANSPORT_STREAM, MBEDTLS_SSL_PRESET_DEFAULT)) != 0) {
13684 mg_error(c, "tls defaults %#x", -rc);
13685 goto fail;
13686 }
13687 mbedtls_ssl_conf_rng(&tls->conf, mg_mbed_rng, c);
13688 
13689 if (opts->ca.len == 0 || mg_strcmp(opts->ca, mg_str("*")) == 0) {
13690 // NOTE: MBEDTLS_SSL_VERIFY_NONE is not supported for TLS1.3 on client side
13691 // See https://github.com/Mbed-TLS/mbedtls/issues/7075
13692 mbedtls_ssl_conf_authmode(&tls->conf, MBEDTLS_SSL_VERIFY_NONE);
13693 } else {
13694 if (mg_load_cert(opts->ca, &tls->ca) == false) goto fail;
13695 mbedtls_ssl_conf_ca_chain(&tls->conf, &tls->ca, NULL);
13696 if (c->is_client && opts->name.buf != NULL && opts->name.buf[0] != '\0') {
13697 char *host = mg_mprintf("%.*s", opts->name.len, opts->name.buf);
13698 mbedtls_ssl_set_hostname(&tls->ssl, host);
13699 MG_DEBUG(("%lu hostname verification: %s", c->id, host));
13700 free(host);
13701 }
13702 mbedtls_ssl_conf_authmode(&tls->conf, MBEDTLS_SSL_VERIFY_REQUIRED);
13703 }
13704 if (!mg_load_cert(opts->cert, &tls->cert)) goto fail;
13705 if (!mg_load_key(opts->key, &tls->pk)) goto fail;
13706 if (tls->cert.version &&
13707 (rc = mbedtls_ssl_conf_own_cert(&tls->conf, &tls->cert, &tls->pk)) != 0) {
13708 mg_error(c, "own cert %#x", -rc);
13709 goto fail;
13710 }
13711 
13712#ifdef MBEDTLS_SSL_SESSION_TICKETS
13713 mbedtls_ssl_conf_session_tickets_cb(
13714 &tls->conf, mbedtls_ssl_ticket_write, mbedtls_ssl_ticket_parse,
13715 &((struct mg_tls_ctx *) c->mgr->tls_ctx)->tickets);
13716#endif
13717 
13718 if ((rc = mbedtls_ssl_setup(&tls->ssl, &tls->conf)) != 0) {
13719 mg_error(c, "setup err %#x", -rc);
13720 goto fail;
13721 }
13722 c->is_tls = 1;
13723 c->is_tls_hs = 1;
13724 mbedtls_ssl_set_bio(&tls->ssl, c, mg_net_send, mg_net_recv, 0);
13725 MG_PROF_ADD(c, "mbedtls_init_end");
13726 return;
13727fail:
13728 mg_tls_free(c);
13729}
13730 
13731size_t mg_tls_pending(struct mg_connection *c) {
13732 struct mg_tls *tls = (struct mg_tls *) c->tls;
13733 return tls == NULL ? 0 : mbedtls_ssl_get_bytes_avail(&tls->ssl);
13734}
13735 
13736long mg_tls_recv(struct mg_connection *c, void *buf, size_t len) {
13737 struct mg_tls *tls = (struct mg_tls *) c->tls;
13738 long n = mbedtls_ssl_read(&tls->ssl, (unsigned char *) buf, len);
13739 if (!c->is_tls_hs && buf == NULL && n == 0) return 0; // TODO(): MIP
13740 if (n == MBEDTLS_ERR_SSL_WANT_READ || n == MBEDTLS_ERR_SSL_WANT_WRITE)
13741 return MG_IO_WAIT;
13742#if defined(MBEDTLS_ERR_SSL_RECEIVED_NEW_SESSION_TICKET)
13743 if (n == MBEDTLS_ERR_SSL_RECEIVED_NEW_SESSION_TICKET) {
13744 return MG_IO_WAIT;
13745 }
13746#endif
13747 if (n <= 0) return MG_IO_ERR;
13748 return n;
13749}
13750 
13751long mg_tls_send(struct mg_connection *c, const void *buf, size_t len) {
13752 struct mg_tls *tls = (struct mg_tls *) c->tls;
13753 long n;
13754 bool was_throttled = c->is_tls_throttled; // see #3074
13755 n = was_throttled ? mbedtls_ssl_write(&tls->ssl, tls->throttled_buf,
13756 tls->throttled_len) /* flush old data */
13757 : mbedtls_ssl_write(&tls->ssl, (unsigned char *) buf,
13758 len); // encrypt current data
13759 c->is_tls_throttled =
13760 (n == MBEDTLS_ERR_SSL_WANT_READ || n == MBEDTLS_ERR_SSL_WANT_WRITE);
13761 if (was_throttled) return MG_IO_WAIT; // flushed throttled data instead
13762 if (c->is_tls_throttled) {
13763 tls->throttled_buf = (unsigned char *)buf; // MbedTLS code actually ignores
13764 tls->throttled_len = len; // these, but let's play API rules
13765 return (long) len; // already encripted that when throttled
13766 }
13767 if (n <= 0) return MG_IO_ERR;
13768 return n;
13769}
13770 
13771void mg_tls_ctx_init(struct mg_mgr *mgr) {
13772 struct mg_tls_ctx *ctx = (struct mg_tls_ctx *) calloc(1, sizeof(*ctx));
13773 if (ctx == NULL) {
13774 MG_ERROR(("TLS context init OOM"));
13775 } else {
13776#ifdef MBEDTLS_SSL_SESSION_TICKETS
13777 int rc;
13778 mbedtls_ssl_ticket_init(&ctx->tickets);
13779 if ((rc = mbedtls_ssl_ticket_setup(&ctx->tickets, mg_mbed_rng, NULL,
13780 MBEDTLS_CIPHER_AES_128_GCM, 86400)) !=
13781 0) {
13782 MG_ERROR((" mbedtls_ssl_ticket_setup %#x", -rc));
13783 }
13784#endif
13785 mgr->tls_ctx = ctx;
13786 }
13787}
13788 
13789void mg_tls_ctx_free(struct mg_mgr *mgr) {
13790 struct mg_tls_ctx *ctx = (struct mg_tls_ctx *) mgr->tls_ctx;
13791 if (ctx != NULL) {
13792#ifdef MBEDTLS_SSL_SESSION_TICKETS
13793 mbedtls_ssl_ticket_free(&ctx->tickets);
13794#endif
13795 free(ctx);
13796 mgr->tls_ctx = NULL;
13797 }
13798}
13799#endif
13800 
13801#ifdef MG_ENABLE_LINES
13802#line 1 "src/tls_openssl.c"
13803#endif
13804 
13805 
13806 
13807#if MG_TLS == MG_TLS_OPENSSL || MG_TLS == MG_TLS_WOLFSSL
13808 
13809static int tls_err_cb(const char *s, size_t len, void *c) {
13810 int n = (int) len - 1;
13811 MG_ERROR(("%lu %.*s", ((struct mg_connection *) c)->id, n, s));
13812 return 0; // undocumented
13813}
13814 
13815static int mg_tls_err(struct mg_connection *c, struct mg_tls *tls, int res) {
13816 int err = SSL_get_error(tls->ssl, res);
13817 // We've just fetched the last error from the queue.
13818 // Now we need to clear the error queue. If we do not, then the following
13819 // can happen (actually reported):
13820 // - A new connection is accept()-ed with cert error (e.g. self-signed cert)
13821 // - Since all accept()-ed connections share listener's context,
13822 // - *ALL* SSL accepted connection report read error on the next poll cycle.
13823 // Thus a single errored connection can close all the rest, unrelated ones.
13824 // Clearing the error keeps the shared SSL_CTX in an OK state.
13825 
13826 if (err != 0) ERR_print_errors_cb(tls_err_cb, c);
13827 ERR_clear_error();
13828 if (err == SSL_ERROR_WANT_READ) return 0;
13829 if (err == SSL_ERROR_WANT_WRITE) return 0;
13830 return err;
13831}
13832 
13833static STACK_OF(X509_INFO) * load_ca_certs(struct mg_str ca) {
13834 BIO *bio = BIO_new_mem_buf(ca.buf, (int) ca.len);
13835 STACK_OF(X509_INFO) *certs =
13836 bio ? PEM_X509_INFO_read_bio(bio, NULL, NULL, NULL) : NULL;
13837 if (bio) BIO_free(bio);
13838 return certs;
13839}
13840 
13841static bool add_ca_certs(SSL_CTX *ctx, STACK_OF(X509_INFO) * certs) {
13842 int i;
13843 X509_STORE *cert_store = SSL_CTX_get_cert_store(ctx);
13844 for (i = 0; i < sk_X509_INFO_num(certs); i++) {
13845 X509_INFO *cert_info = sk_X509_INFO_value(certs, i);
13846 if (cert_info->x509 && !X509_STORE_add_cert(cert_store, cert_info->x509))
13847 return false;
13848 }
13849 return true;
13850}
13851 
13852static EVP_PKEY *load_key(struct mg_str s) {
13853 BIO *bio = BIO_new_mem_buf(s.buf, (int) (long) s.len);
13854 EVP_PKEY *key = bio ? PEM_read_bio_PrivateKey(bio, NULL, 0, NULL) : NULL;
13855 if (bio) BIO_free(bio);
13856 return key;
13857}
13858 
13859static X509 *load_cert(struct mg_str s) {
13860 BIO *bio = BIO_new_mem_buf(s.buf, (int) (long) s.len);
13861 X509 *cert = bio == NULL ? NULL
13862 : s.buf[0] == '-'
13863 ? PEM_read_bio_X509(bio, NULL, NULL, NULL) // PEM
13864 : d2i_X509_bio(bio, NULL); // DER
13865 if (bio) BIO_free(bio);
13866 return cert;
13867}
13868 
13869static long mg_bio_ctrl(BIO *b, int cmd, long larg, void *pargs) {
13870 long ret = 0;
13871 if (cmd == BIO_CTRL_PUSH) ret = 1;
13872 if (cmd == BIO_CTRL_POP) ret = 1;
13873 if (cmd == BIO_CTRL_FLUSH) ret = 1;
13874#if MG_TLS == MG_TLS_OPENSSL
13875 if (cmd == BIO_C_SET_NBIO) ret = 1;
13876#endif
13877 // MG_DEBUG(("%d -> %ld", cmd, ret));
13878 (void) b, (void) cmd, (void) larg, (void) pargs;
13879 return ret;
13880}
13881 
13882static int mg_bio_read(BIO *bio, char *buf, int len) {
13883 struct mg_connection *c = (struct mg_connection *) BIO_get_data(bio);
13884 long res = mg_io_recv(c, buf, (size_t) len);
13885 // MG_DEBUG(("%p %d %ld", buf, len, res));
13886 len = res > 0 ? (int) res : -1;
13887 if (res == MG_IO_WAIT) BIO_set_retry_read(bio);
13888 return len;
13889}
13890 
13891static int mg_bio_write(BIO *bio, const char *buf, int len) {
13892 struct mg_connection *c = (struct mg_connection *) BIO_get_data(bio);
13893 long res = mg_io_send(c, buf, (size_t) len);
13894 // MG_DEBUG(("%p %d %ld", buf, len, res));
13895 len = res > 0 ? (int) res : -1;
13896 if (res == MG_IO_WAIT) BIO_set_retry_write(bio);
13897 return len;
13898}
13899 
13900#ifdef MG_TLS_SSLKEYLOGFILE
13901static void ssl_keylog_cb(const SSL *ssl, const char *line) {
13902 char *keylogfile = getenv("SSLKEYLOGFILE");
13903 if (keylogfile == NULL) {
13904 return;
13905 }
13906 FILE *f = fopen(keylogfile, "a");
13907 fprintf(f, "%s\n", line);
13908 fflush(f);
13909 fclose(f);
13910}
13911#endif
13912 
13913void mg_tls_free(struct mg_connection *c) {
13914 struct mg_tls *tls = (struct mg_tls *) c->tls;
13915 if (tls == NULL) return;
13916 SSL_free(tls->ssl);
13917 SSL_CTX_free(tls->ctx);
13918 BIO_meth_free(tls->bm);
13919 free(tls);
13920 c->tls = NULL;
13921}
13922 
13923void mg_tls_init(struct mg_connection *c, const struct mg_tls_opts *opts) {
13924 struct mg_tls *tls = (struct mg_tls *) calloc(1, sizeof(*tls));
13925 const char *id = "mongoose";
13926 static unsigned char s_initialised = 0;
13927 BIO *bio = NULL;
13928 int rc;
13929 c->tls = tls;
13930 if (tls == NULL) {
13931 mg_error(c, "TLS OOM");
13932 goto fail;
13933 }
13934 
13935 if (!s_initialised) {
13936 SSL_library_init();
13937 s_initialised++;
13938 }
13939 MG_DEBUG(("%lu Setting TLS", c->id));
13940 tls->ctx = c->is_client ? SSL_CTX_new(TLS_client_method())
13941 : SSL_CTX_new(TLS_server_method());
13942 if (tls->ctx == NULL) {
13943 mg_error(c, "SSL_CTX_new");
13944 goto fail;
13945 }
13946#ifdef MG_TLS_SSLKEYLOGFILE
13947 SSL_CTX_set_keylog_callback(tls->ctx, ssl_keylog_cb);
13948#endif
13949 if ((tls->ssl = SSL_new(tls->ctx)) == NULL) {
13950 mg_error(c, "SSL_new");
13951 goto fail;
13952 }
13953 SSL_set_session_id_context(tls->ssl, (const uint8_t *) id,
13954 (unsigned) strlen(id));
13955 // Disable deprecated protocols
13956 SSL_set_options(tls->ssl, SSL_OP_NO_SSLv2);
13957 SSL_set_options(tls->ssl, SSL_OP_NO_SSLv3);
13958 SSL_set_options(tls->ssl, SSL_OP_NO_TLSv1);
13959 SSL_set_options(tls->ssl, SSL_OP_NO_TLSv1_1);
13960#ifdef MG_ENABLE_OPENSSL_NO_COMPRESSION
13961 SSL_set_options(tls->ssl, SSL_OP_NO_COMPRESSION);
13962#endif
13963#ifdef MG_ENABLE_OPENSSL_CIPHER_SERVER_PREFERENCE
13964 SSL_set_options(tls->ssl, SSL_OP_CIPHER_SERVER_PREFERENCE);
13965#endif
13966 
13967#if MG_TLS == MG_TLS_WOLFSSL && !defined(OPENSSL_COMPATIBLE_DEFAULTS)
13968 if (opts->ca.len == 0 || mg_strcmp(opts->ca, mg_str("*")) == 0) {
13969 // Older versions require that either the CA is loaded or SSL_VERIFY_NONE
13970 // explicitly set
13971 SSL_set_verify(tls->ssl, SSL_VERIFY_NONE, NULL);
13972 }
13973#endif
13974 if (opts->ca.buf != NULL && opts->ca.buf[0] != '\0') {
13975 SSL_set_verify(tls->ssl, SSL_VERIFY_PEER | SSL_VERIFY_FAIL_IF_NO_PEER_CERT,
13976 NULL);
13977 STACK_OF(X509_INFO) *certs = load_ca_certs(opts->ca);
13978 rc = add_ca_certs(tls->ctx, certs);
13979 sk_X509_INFO_pop_free(certs, X509_INFO_free);
13980 if (!rc) {
13981 mg_error(c, "CA err");
13982 goto fail;
13983 }
13984 }
13985 if (opts->cert.buf != NULL && opts->cert.buf[0] != '\0') {
13986 X509 *cert = load_cert(opts->cert);
13987 rc = cert == NULL ? 0 : SSL_use_certificate(tls->ssl, cert);
13988 X509_free(cert);
13989 if (cert == NULL || rc != 1) {
13990 mg_error(c, "CERT err %d", mg_tls_err(c, tls, rc));
13991 goto fail;
13992 }
13993 }
13994 if (opts->key.buf != NULL && opts->key.buf[0] != '\0') {
13995 EVP_PKEY *key = load_key(opts->key);
13996 rc = key == NULL ? 0 : SSL_use_PrivateKey(tls->ssl, key);
13997 EVP_PKEY_free(key);
13998 if (key == NULL || rc != 1) {
13999 mg_error(c, "KEY err %d", mg_tls_err(c, tls, rc));
14000 goto fail;
14001 }
14002 }
14003 
14004 SSL_set_mode(tls->ssl, SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER);
14005#if MG_TLS == MG_TLS_OPENSSL && OPENSSL_VERSION_NUMBER > 0x10002000L
14006 (void) SSL_set_ecdh_auto(tls->ssl, 1);
14007#endif
14008#if OPENSSL_VERSION_NUMBER >= 0x10100000L
14009 if (opts->name.len > 0) {
14010 char *s = mg_mprintf("%.*s", (int) opts->name.len, opts->name.buf);
14011#if MG_TLS != MG_TLS_WOLFSSL || LIBWOLFSSL_VERSION_HEX >= 0x05005002
14012 SSL_set1_host(tls->ssl, s);
14013#else
14014 X509_VERIFY_PARAM_set1_host(SSL_get0_param(tls->ssl), s, 0);
14015#endif
14016 SSL_set_tlsext_host_name(tls->ssl, s);
14017 free(s);
14018 }
14019#endif
14020#if MG_TLS == MG_TLS_WOLFSSL
14021 tls->bm = BIO_meth_new(0, "bio_mg");
14022#else
14023 tls->bm = BIO_meth_new(BIO_get_new_index() | BIO_TYPE_SOURCE_SINK, "bio_mg");
14024#endif
14025 BIO_meth_set_write(tls->bm, mg_bio_write);
14026 BIO_meth_set_read(tls->bm, mg_bio_read);
14027 BIO_meth_set_ctrl(tls->bm, mg_bio_ctrl);
14028 
14029 bio = BIO_new(tls->bm);
14030 BIO_set_data(bio, c);
14031 SSL_set_bio(tls->ssl, bio, bio);
14032 
14033 c->is_tls = 1;
14034 c->is_tls_hs = 1;
14035 MG_DEBUG(("%lu SSL %s OK", c->id, c->is_accepted ? "accept" : "client"));
14036 return;
14037fail:
14038 mg_tls_free(c);
14039}
14040 
14041void mg_tls_handshake(struct mg_connection *c) {
14042 struct mg_tls *tls = (struct mg_tls *) c->tls;
14043 int rc = c->is_client ? SSL_connect(tls->ssl) : SSL_accept(tls->ssl);
14044 if (rc == 1) {
14045 MG_DEBUG(("%lu success", c->id));
14046 c->is_tls_hs = 0;
14047 mg_call(c, MG_EV_TLS_HS, NULL);
14048 } else {
14049 int code = mg_tls_err(c, tls, rc);
14050 if (code != 0) mg_error(c, "tls hs: rc %d, err %d", rc, code);
14051 }
14052}
14053 
14054size_t mg_tls_pending(struct mg_connection *c) {
14055 struct mg_tls *tls = (struct mg_tls *) c->tls;
14056 return tls == NULL ? 0 : (size_t) SSL_pending(tls->ssl);
14057}
14058 
14059long mg_tls_recv(struct mg_connection *c, void *buf, size_t len) {
14060 struct mg_tls *tls = (struct mg_tls *) c->tls;
14061 int n = SSL_read(tls->ssl, buf, (int) len);
14062 if (!c->is_tls_hs && buf == NULL && n == 0) return 0; // TODO(): MIP
14063 if (n < 0 && mg_tls_err(c, tls, n) == 0) return MG_IO_WAIT;
14064 if (n <= 0) return MG_IO_ERR;
14065 return n;
14066}
14067 
14068long mg_tls_send(struct mg_connection *c, const void *buf, size_t len) {
14069 struct mg_tls *tls = (struct mg_tls *) c->tls;
14070 int n = SSL_write(tls->ssl, buf, (int) len);
14071 if (n < 0 && mg_tls_err(c, tls, n) == 0) return MG_IO_WAIT;
14072 if (n <= 0) return MG_IO_ERR;
14073 return n;
14074}
14075 
14076void mg_tls_ctx_init(struct mg_mgr *mgr) {
14077 (void) mgr;
14078}
14079 
14080void mg_tls_ctx_free(struct mg_mgr *mgr) {
14081 (void) mgr;
14082}
14083#endif
14084 
14085#ifdef MG_ENABLE_LINES
14086#line 1 "src/tls_rsa.c"
14087#endif
14088 
14089 
14090 
14091#if MG_TLS == MG_TLS_BUILTIN
14092 
14093#define NS_INTERNAL static
14094typedef struct _bigint bigint; /**< An alias for _bigint */
14095 
14096/*
14097 * Copyright (c) 2007, Cameron Rich
14098 *
14099 * All rights reserved.
14100 *
14101 * Redistribution and use in source and binary forms, with or without
14102 * modification, are permitted provided that the following conditions are met:
14103 *
14104 * * Redistributions of source code must retain the above copyright notice,
14105 * this list of conditions and the following disclaimer.
14106 * * Redistributions in binary form must reproduce the above copyright notice,
14107 * this list of conditions and the following disclaimer in the documentation
14108 * and/or other materials provided with the distribution.
14109 * * Neither the name of the axTLS project nor the names of its contributors
14110 * may be used to endorse or promote products derived from this software
14111 * without specific prior written permission.
14112 *
14113 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
14114 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
14115 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
14116 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
14117 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
14118 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
14119 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
14120 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
14121 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
14122 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
14123 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
14124 */
14125 
14126/* Maintain a number of precomputed variables when doing reduction */
14127#define BIGINT_M_OFFSET 0 /**< Normal modulo offset. */
14128#define BIGINT_P_OFFSET 1 /**< p modulo offset. */
14129#define BIGINT_Q_OFFSET 2 /**< q module offset. */
14130#define BIGINT_NUM_MODS 3 /**< The number of modulus constants used. */
14131 
14132/* Architecture specific functions for big ints */
14133#if defined(CONFIG_INTEGER_8BIT)
14134#define COMP_RADIX 256U /**< Max component + 1 */
14135#define COMP_MAX 0xFFFFU /**< (Max dbl comp -1) */
14136#define COMP_BIT_SIZE 8 /**< Number of bits in a component. */
14137#define COMP_BYTE_SIZE 1 /**< Number of bytes in a component. */
14138#define COMP_NUM_NIBBLES 2 /**< Used For diagnostics only. */
14139typedef uint8_t comp; /**< A single precision component. */
14140typedef uint16_t long_comp; /**< A double precision component. */
14141typedef int16_t slong_comp; /**< A signed double precision component. */
14142#elif defined(CONFIG_INTEGER_16BIT)
14143#define COMP_RADIX 65536U /**< Max component + 1 */
14144#define COMP_MAX 0xFFFFFFFFU /**< (Max dbl comp -1) */
14145#define COMP_BIT_SIZE 16 /**< Number of bits in a component. */
14146#define COMP_BYTE_SIZE 2 /**< Number of bytes in a component. */
14147#define COMP_NUM_NIBBLES 4 /**< Used For diagnostics only. */
14148typedef uint16_t comp; /**< A single precision component. */
14149typedef uint32_t long_comp; /**< A double precision component. */
14150typedef int32_t slong_comp; /**< A signed double precision component. */
14151#else /* regular 32 bit */
14152#ifdef WIN32
14153#define COMP_RADIX 4294967296i64
14154#define COMP_MAX 0xFFFFFFFFFFFFFFFFui64
14155#else
14156#define COMP_RADIX 4294967296 /**< Max component + 1 */
14157#define COMP_MAX 0xFFFFFFFFFFFFFFFF /**< (Max dbl comp -1) */
14158#endif
14159#define COMP_BIT_SIZE 32 /**< Number of bits in a component. */
14160#define COMP_BYTE_SIZE 4 /**< Number of bytes in a component. */
14161#define COMP_NUM_NIBBLES 8 /**< Used For diagnostics only. */
14162typedef uint32_t comp; /**< A single precision component. */
14163typedef uint64_t long_comp; /**< A double precision component. */
14164typedef int64_t slong_comp; /**< A signed double precision component. */
14165#endif
14166 
14167/**
14168 * @struct _bigint
14169 * @brief A big integer basic object
14170 */
14171struct _bigint {
14172 struct _bigint *next; /**< The next bigint in the cache. */
14173 short size; /**< The number of components in this bigint. */
14174 short max_comps; /**< The heapsize allocated for this bigint */
14175 int refs; /**< An internal reference count. */
14176 comp *comps; /**< A ptr to the actual component data */
14177};
14178 
14179/**
14180 * Maintains the state of the cache, and a number of variables used in
14181 * reduction.
14182 */
14183struct _BI_CTX /**< A big integer "session" context. */
14184 {
14185 bigint *active_list; /**< Bigints currently used. */
14186 bigint *free_list; /**< Bigints not used. */
14187 bigint *bi_radix; /**< The radix used. */
14188 bigint *bi_mod[BIGINT_NUM_MODS]; /**< modulus */
14189 
14190#if defined(CONFIG_BIGINT_MONTGOMERY)
14191 bigint *bi_RR_mod_m[BIGINT_NUM_MODS]; /**< R^2 mod m */
14192 bigint *bi_R_mod_m[BIGINT_NUM_MODS]; /**< R mod m */
14193 comp N0_dash[BIGINT_NUM_MODS];
14194#elif defined(CONFIG_BIGINT_BARRETT)
14195 bigint *bi_mu[BIGINT_NUM_MODS]; /**< Storage for mu */
14196#endif
14197 bigint *bi_normalised_mod[BIGINT_NUM_MODS]; /**< Normalised mod storage. */
14198 bigint **g; /**< Used by sliding-window. */
14199 int window; /**< The size of the sliding window */
14200 int active_count; /**< Number of active bigints. */
14201 int free_count; /**< Number of free bigints. */
14202 
14203#ifdef CONFIG_BIGINT_MONTGOMERY
14204 uint8_t use_classical; /**< Use classical reduction. */
14205#endif
14206 uint8_t mod_offset; /**< The mod offset we are using */
14207};
14208typedef struct _BI_CTX BI_CTX;
14209 
14210#if !defined(MAX)
14211#define MAX(a, b) ((a) > (b) ? (a) : (b))
14212#define MIN(a, b) ((a) < (b) ? (a) : (b))
14213#endif
14214 
14215#define PERMANENT 0x7FFF55AA /**< A magic number for permanents. */
14216 
14217/*
14218 * Copyright (c) 2007, Cameron Rich
14219 *
14220 * All rights reserved.
14221 *
14222 * Redistribution and use in source and binary forms, with or without
14223 * modification, are permitted provided that the following conditions are met:
14224 *
14225 * * Redistributions of source code must retain the above copyright notice,
14226 * this list of conditions and the following disclaimer.
14227 * * Redistributions in binary form must reproduce the above copyright notice,
14228 * this list of conditions and the following disclaimer in the documentation
14229 * and/or other materials provided with the distribution.
14230 * * Neither the name of the axTLS project nor the names of its contributors
14231 * may be used to endorse or promote products derived from this software
14232 * without specific prior written permission.
14233 *
14234 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
14235 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
14236 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
14237 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
14238 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
14239 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
14240 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
14241 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
14242 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
14243 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
14244 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
14245 */
14246 
14247NS_INTERNAL BI_CTX *bi_initialize(void);
14248//NS_INTERNAL void bi_terminate(BI_CTX *ctx);
14249NS_INTERNAL void bi_permanent(bigint *bi);
14250NS_INTERNAL void bi_depermanent(bigint *bi);
14251//NS_INTERNAL void bi_clear_cache(BI_CTX *ctx);
14252NS_INTERNAL void bi_free(BI_CTX *ctx, bigint *bi);
14253NS_INTERNAL bigint *bi_copy(bigint *bi);
14254NS_INTERNAL bigint *bi_clone(BI_CTX *ctx, const bigint *bi);
14255NS_INTERNAL void bi_export(BI_CTX *ctx, bigint *bi, uint8_t *data, int size);
14256NS_INTERNAL bigint *bi_import(BI_CTX *ctx, const uint8_t *data, int len);
14257NS_INTERNAL bigint *int_to_bi(BI_CTX *ctx, comp i);
14258 
14259/* the functions that actually do something interesting */
14260NS_INTERNAL bigint *bi_add(BI_CTX *ctx, bigint *bia, bigint *bib);
14261NS_INTERNAL bigint *bi_subtract(BI_CTX *ctx, bigint *bia, bigint *bib,
14262 int *is_negative);
14263NS_INTERNAL bigint *bi_divide(BI_CTX *ctx, bigint *bia, bigint *bim,
14264 int is_mod);
14265NS_INTERNAL bigint *bi_multiply(BI_CTX *ctx, bigint *bia, bigint *bib);
14266NS_INTERNAL bigint *bi_mod_power(BI_CTX *ctx, bigint *bi, bigint *biexp);
14267#if 0
14268NS_INTERNAL bigint *bi_mod_power2(BI_CTX *ctx, bigint *bi,
14269 bigint *bim, bigint *biexp);
14270#endif
14271NS_INTERNAL int bi_compare(bigint *bia, bigint *bib);
14272NS_INTERNAL void bi_set_mod(BI_CTX *ctx, bigint *bim, int mod_offset);
14273//NS_INTERNAL void bi_free_mod(BI_CTX *ctx, int mod_offset);
14274 
14275#ifdef CONFIG_SSL_FULL_MODE
14276NS_INTERNAL void bi_print(const char *label, bigint *bi);
14277NS_INTERNAL bigint *bi_str_import(BI_CTX *ctx, const char *data);
14278#endif
14279 
14280/**
14281 * @def bi_mod
14282 * Find the residue of B. bi_set_mod() must be called before hand.
14283 */
14284#define bi_mod(A, B) bi_divide(A, B, ctx->bi_mod[ctx->mod_offset], 1)
14285 
14286/**
14287 * bi_residue() is technically the same as bi_mod(), but it uses the
14288 * appropriate reduction technique (which is bi_mod() when doing classical
14289 * reduction).
14290 */
14291#if defined(CONFIG_BIGINT_MONTGOMERY)
14292#define bi_residue(A, B) bi_mont(A, B)
14293NS_INTERNAL bigint *bi_mont(BI_CTX *ctx, bigint *bixy);
14294#elif defined(CONFIG_BIGINT_BARRETT)
14295#define bi_residue(A, B) bi_barrett(A, B)
14296NS_INTERNAL bigint *bi_barrett(BI_CTX *ctx, bigint *bi);
14297#else /* if defined(CONFIG_BIGINT_CLASSICAL) */
14298#define bi_residue(A, B) bi_mod(A, B)
14299#endif
14300 
14301#ifdef CONFIG_BIGINT_SQUARE
14302NS_INTERNAL bigint *bi_square(BI_CTX *ctx, bigint *bi);
14303#else
14304#define bi_square(A, B) bi_multiply(A, bi_copy(B), B)
14305#endif
14306 
14307//NS_INTERNAL bigint *bi_crt(BI_CTX *ctx, bigint *bi, bigint *dP, bigint *dQ,
14308// bigint *p, bigint *q, bigint *qInv);
14309 
14310/*
14311 * Copyright (c) 2007, Cameron Rich
14312 *
14313 * All rights reserved.
14314 *
14315 * Redistribution and use in source and binary forms, with or without
14316 * modification, are permitted provided that the following conditions are met:
14317 *
14318 * * Redistributions of source code must retain the above copyright notice,
14319 * this list of conditions and the following disclaimer.
14320 * * Redistributions in binary form must reproduce the above copyright notice,
14321 * this list of conditions and the following disclaimer in the documentation
14322 * and/or other materials provided with the distribution.
14323 * * Neither the name of the axTLS project nor the names of its contributors
14324 * may be used to endorse or promote products derived from this software
14325 * without specific prior written permission.
14326 *
14327 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
14328 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
14329 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
14330 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
14331 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
14332 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
14333 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
14334 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
14335 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
14336 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
14337 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
14338 */
14339 
14340/**
14341 * @defgroup bigint_api Big Integer API
14342 * @brief The bigint implementation as used by the axTLS project.
14343 *
14344 * The bigint library is for RSA encryption/decryption as well as signing.
14345 * This code tries to minimise use of malloc/free by maintaining a small
14346 * cache. A bigint context may maintain state by being made "permanent".
14347 * It be be later released with a bi_depermanent() and bi_free() call.
14348 *
14349 * It supports the following reduction techniques:
14350 * - Classical
14351 * - Barrett
14352 * - Montgomery
14353 *
14354 * It also implements the following:
14355 * - Karatsuba multiplication
14356 * - Squaring
14357 * - Sliding window exponentiation
14358 * - Chinese Remainder Theorem (implemented in rsa.c).
14359 *
14360 * All the algorithms used are pretty standard, and designed for different
14361 * data bus sizes. Negative numbers are not dealt with at all, so a subtraction
14362 * may need to be tested for negativity.
14363 *
14364 * This library steals some ideas from Jef Poskanzer
14365 * <http://cs.marlboro.edu/term/cs-fall02/algorithms/crypto/RSA/bigint>
14366 * and GMP <http://www.swox.com/gmp>. It gets most of its implementation
14367 * detail from "The Handbook of Applied Cryptography"
14368 * <http://www.cacr.math.uwaterloo.ca/hac/about/chap14.pdf>
14369 * @{
14370 */
14371 
14372#define V1 v->comps[v->size - 1] /**< v1 for division */
14373#define V2 v->comps[v->size - 2] /**< v2 for division */
14374#define U(j) tmp_u->comps[tmp_u->size - j - 1] /**< uj for division */
14375#define Q(j) quotient->comps[quotient->size - j - 1] /**< qj for division */
14376 
14377static bigint *bi_int_multiply(BI_CTX *ctx, bigint *bi, comp i);
14378static bigint *bi_int_divide(BI_CTX *ctx, bigint *biR, comp denom);
14379static bigint *alloc(BI_CTX *ctx, int size);
14380static bigint *trim(bigint *bi);
14381static void more_comps(bigint *bi, int n);
14382#if defined(CONFIG_BIGINT_KARATSUBA) || defined(CONFIG_BIGINT_BARRETT) || \
14383 defined(CONFIG_BIGINT_MONTGOMERY)
14384static bigint *comp_right_shift(bigint *biR, int num_shifts);
14385static bigint *comp_left_shift(bigint *biR, int num_shifts);
14386#endif
14387 
14388#ifdef CONFIG_BIGINT_CHECK_ON
14389static void check(const bigint *bi);
14390#else
14391#define check(A) /**< disappears in normal production mode */
14392#endif
14393 
14394/**
14395 * @brief Start a new bigint context.
14396 * @return A bigint context.
14397 */
14398NS_INTERNAL BI_CTX *bi_initialize(void) {
14399 /* calloc() sets everything to zero */
14400 BI_CTX *ctx = (BI_CTX *) calloc(1, sizeof(BI_CTX));
14401 
14402 /* the radix */
14403 ctx->bi_radix = alloc(ctx, 2);
14404 ctx->bi_radix->comps[0] = 0;
14405 ctx->bi_radix->comps[1] = 1;
14406 bi_permanent(ctx->bi_radix);
14407 return ctx;
14408}
14409 
14410#if 0
14411/**
14412 * @brief Close the bigint context and free any resources.
14413 *
14414 * Free up any used memory - a check is done if all objects were not
14415 * properly freed.
14416 * @param ctx [in] The bigint session context.
14417 */
14418NS_INTERNAL void bi_terminate(BI_CTX *ctx) {
14419 bi_depermanent(ctx->bi_radix);
14420 bi_free(ctx, ctx->bi_radix);
14421 
14422 if (ctx->active_count != 0) {
14423#ifdef CONFIG_SSL_FULL_MODE
14424 printf("bi_terminate: there were %d un-freed bigints\n", ctx->active_count);
14425#endif
14426 abort();
14427 }
14428 
14429 bi_clear_cache(ctx);
14430 free(ctx);
14431}
14432 
14433/**
14434 *@brief Clear the memory cache.
14435 */
14436NS_INTERNAL void bi_clear_cache(BI_CTX *ctx) {
14437 bigint *p, *pn;
14438 
14439 if (ctx->free_list == NULL) return;
14440 
14441 for (p = ctx->free_list; p != NULL; p = pn) {
14442 pn = p->next;
14443 free(p->comps);
14444 free(p);
14445 }
14446 
14447 ctx->free_count = 0;
14448 ctx->free_list = NULL;
14449}
14450#endif
14451 
14452/**
14453 * @brief Increment the number of references to this object.
14454 * It does not do a full copy.
14455 * @param bi [in] The bigint to copy.
14456 * @return A reference to the same bigint.
14457 */
14458NS_INTERNAL bigint *bi_copy(bigint *bi) {
14459 check(bi);
14460 if (bi->refs != PERMANENT) bi->refs++;
14461 return bi;
14462}
14463 
14464/**
14465 * @brief Simply make a bigint object "unfreeable" if bi_free() is called on it.
14466 *
14467 * For this object to be freed, bi_depermanent() must be called.
14468 * @param bi [in] The bigint to be made permanent.
14469 */
14470NS_INTERNAL void bi_permanent(bigint *bi) {
14471 check(bi);
14472 if (bi->refs != 1) {
14473#ifdef CONFIG_SSL_FULL_MODE
14474 printf("bi_permanent: refs was not 1\n");
14475#endif
14476 abort();
14477 }
14478 
14479 bi->refs = PERMANENT;
14480}
14481 
14482/**
14483 * @brief Take a permanent object and make it eligible for freedom.
14484 * @param bi [in] The bigint to be made back to temporary.
14485 */
14486NS_INTERNAL void bi_depermanent(bigint *bi) {
14487 check(bi);
14488 if (bi->refs != PERMANENT) {
14489#ifdef CONFIG_SSL_FULL_MODE
14490 printf("bi_depermanent: bigint was not permanent\n");
14491#endif
14492 abort();
14493 }
14494 
14495 bi->refs = 1;
14496}
14497 
14498/**
14499 * @brief Free a bigint object so it can be used again.
14500 *
14501 * The memory itself it not actually freed, just tagged as being available
14502 * @param ctx [in] The bigint session context.
14503 * @param bi [in] The bigint to be freed.
14504 */
14505NS_INTERNAL void bi_free(BI_CTX *ctx, bigint *bi) {
14506 check(bi);
14507 if (bi->refs == PERMANENT) {
14508 return;
14509 }
14510 
14511 if (--bi->refs > 0) {
14512 return;
14513 }
14514 
14515 bi->next = ctx->free_list;
14516 ctx->free_list = bi;
14517 ctx->free_count++;
14518 
14519 if (--ctx->active_count < 0) {
14520#ifdef CONFIG_SSL_FULL_MODE
14521 printf(
14522 "bi_free: active_count went negative "
14523 "- double-freed bigint?\n");
14524#endif
14525 abort();
14526 }
14527}
14528 
14529/**
14530 * @brief Convert an (unsigned) integer into a bigint.
14531 * @param ctx [in] The bigint session context.
14532 * @param i [in] The (unsigned) integer to be converted.
14533 *
14534 */
14535NS_INTERNAL bigint *int_to_bi(BI_CTX *ctx, comp i) {
14536 bigint *biR = alloc(ctx, 1);
14537 biR->comps[0] = i;
14538 return biR;
14539}
14540 
14541/**
14542 * @brief Do a full copy of the bigint object.
14543 * @param ctx [in] The bigint session context.
14544 * @param bi [in] The bigint object to be copied.
14545 */
14546NS_INTERNAL bigint *bi_clone(BI_CTX *ctx, const bigint *bi) {
14547 bigint *biR = alloc(ctx, bi->size);
14548 check(bi);
14549 memcpy(biR->comps, bi->comps, (size_t) bi->size * COMP_BYTE_SIZE);
14550 return biR;
14551}
14552 
14553/**
14554 * @brief Perform an addition operation between two bigints.
14555 * @param ctx [in] The bigint session context.
14556 * @param bia [in] A bigint.
14557 * @param bib [in] Another bigint.
14558 * @return The result of the addition.
14559 */
14560NS_INTERNAL bigint *bi_add(BI_CTX *ctx, bigint *bia, bigint *bib) {
14561 int n;
14562 comp carry = 0;
14563 comp *pa, *pb;
14564 
14565 check(bia);
14566 check(bib);
14567 
14568 n = MAX(bia->size, bib->size);
14569 more_comps(bia, n + 1);
14570 more_comps(bib, n);
14571 pa = bia->comps;
14572 pb = bib->comps;
14573 
14574 do {
14575 comp sl, rl, cy1;
14576 sl = *pa + *pb++;
14577 rl = sl + carry;
14578 cy1 = sl < *pa;
14579 carry = cy1 | (rl < sl);
14580 *pa++ = rl;
14581 } while (--n != 0);
14582 
14583 *pa = carry; /* do overflow */
14584 bi_free(ctx, bib);
14585 return trim(bia);
14586}
14587 
14588/**
14589 * @brief Perform a subtraction operation between two bigints.
14590 * @param ctx [in] The bigint session context.
14591 * @param bia [in] A bigint.
14592 * @param bib [in] Another bigint.
14593 * @param is_negative [out] If defined, indicates that the result was negative.
14594 * is_negative may be null.
14595 * @return The result of the subtraction. The result is always positive.
14596 */
14597NS_INTERNAL bigint *bi_subtract(BI_CTX *ctx, bigint *bia, bigint *bib,
14598 int *is_negative) {
14599 int n = bia->size;
14600 comp *pa, *pb, carry = 0;
14601 
14602 check(bia);
14603 check(bib);
14604 
14605 more_comps(bib, n);
14606 pa = bia->comps;
14607 pb = bib->comps;
14608 
14609 do {
14610 comp sl, rl, cy1;
14611 sl = *pa - *pb++;
14612 rl = sl - carry;
14613 cy1 = sl > *pa;
14614 carry = cy1 | (rl > sl);
14615 *pa++ = rl;
14616 } while (--n != 0);
14617 
14618 if (is_negative) /* indicate a negative result */
14619 {
14620 *is_negative = (int) carry;
14621 }
14622 
14623 bi_free(ctx, trim(bib)); /* put bib back to the way it was */
14624 return trim(bia);
14625}
14626 
14627/**
14628 * Perform a multiply between a bigint an an (unsigned) integer
14629 */
14630static bigint *bi_int_multiply(BI_CTX *ctx, bigint *bia, comp b) {
14631 int j = 0, n = bia->size;
14632 bigint *biR = alloc(ctx, n + 1);
14633 comp carry = 0;
14634 comp *r = biR->comps;
14635 comp *a = bia->comps;
14636 
14637 check(bia);
14638 
14639 /* clear things to start with */
14640 memset(r, 0, (size_t) ((n + 1) * COMP_BYTE_SIZE));
14641 
14642 do {
14643 long_comp tmp = *r + (long_comp) a[j] * b + carry;
14644 *r++ = (comp) tmp; /* downsize */
14645 carry = (comp)(tmp >> COMP_BIT_SIZE);
14646 } while (++j < n);
14647 
14648 *r = carry;
14649 bi_free(ctx, bia);
14650 return trim(biR);
14651}
14652 
14653/**
14654 * @brief Does both division and modulo calculations.
14655 *
14656 * Used extensively when doing classical reduction.
14657 * @param ctx [in] The bigint session context.
14658 * @param u [in] A bigint which is the numerator.
14659 * @param v [in] Either the denominator or the modulus depending on the mode.
14660 * @param is_mod [n] Determines if this is a normal division (0) or a reduction
14661 * (1).
14662 * @return The result of the division/reduction.
14663 */
14664NS_INTERNAL bigint *bi_divide(BI_CTX *ctx, bigint *u, bigint *v, int is_mod) {
14665 int n = v->size, m = u->size - n;
14666 int j = 0, orig_u_size = u->size;
14667 uint8_t mod_offset = ctx->mod_offset;
14668 comp d;
14669 bigint *quotient, *tmp_u;
14670 comp q_dash;
14671 
14672 check(u);
14673 check(v);
14674 
14675 /* if doing reduction and we are < mod, then return mod */
14676 if (is_mod && bi_compare(v, u) > 0) {
14677 bi_free(ctx, v);
14678 return u;
14679 }
14680 
14681 quotient = alloc(ctx, m + 1);
14682 tmp_u = alloc(ctx, n + 1);
14683 v = trim(v); /* make sure we have no leading 0's */
14684 d = (comp)((long_comp) COMP_RADIX / (V1 + 1));
14685 
14686 /* clear things to start with */
14687 memset(quotient->comps, 0, (size_t) ((quotient->size) * COMP_BYTE_SIZE));
14688 
14689 /* normalise */
14690 if (d > 1) {
14691 u = bi_int_multiply(ctx, u, d);
14692 
14693 if (is_mod) {
14694 v = ctx->bi_normalised_mod[mod_offset];
14695 } else {
14696 v = bi_int_multiply(ctx, v, d);
14697 }
14698 }
14699 
14700 if (orig_u_size == u->size) /* new digit position u0 */
14701 {
14702 more_comps(u, orig_u_size + 1);
14703 }
14704 
14705 do {
14706 /* get a temporary short version of u */
14707 memcpy(tmp_u->comps, &u->comps[u->size - n - 1 - j],
14708 (size_t) (n + 1) * COMP_BYTE_SIZE);
14709 
14710 /* calculate q' */
14711 if (U(0) == V1) {
14712 q_dash = COMP_RADIX - 1;
14713 } else {
14714 q_dash = (comp)(((long_comp) U(0) * COMP_RADIX + U(1)) / V1);
14715 
14716 if (v->size > 1 && V2) {
14717 /* we are implementing the following:
14718 if (V2*q_dash > (((U(0)*COMP_RADIX + U(1) -
14719 q_dash*V1)*COMP_RADIX) + U(2))) ... */
14720 comp inner = (comp)((long_comp) COMP_RADIX * U(0) + U(1) -
14721 (long_comp) q_dash * V1);
14722 if ((long_comp) V2 * q_dash > (long_comp) inner * COMP_RADIX + U(2)) {
14723 q_dash--;
14724 }
14725 }
14726 }
14727 
14728 /* multiply and subtract */
14729 if (q_dash) {
14730 int is_negative;
14731 tmp_u = bi_subtract(ctx, tmp_u, bi_int_multiply(ctx, bi_copy(v), q_dash),
14732 &is_negative);
14733 more_comps(tmp_u, n + 1);
14734 
14735 Q(j) = q_dash;
14736 
14737 /* add back */
14738 if (is_negative) {
14739 Q(j)--;
14740 tmp_u = bi_add(ctx, tmp_u, bi_copy(v));
14741 
14742 /* lop off the carry */
14743 tmp_u->size--;
14744 v->size--;
14745 }
14746 } else {
14747 Q(j) = 0;
14748 }
14749 
14750 /* copy back to u */
14751 memcpy(&u->comps[u->size - n - 1 - j], tmp_u->comps,
14752 (size_t) (n + 1) * COMP_BYTE_SIZE);
14753 } while (++j <= m);
14754 
14755 bi_free(ctx, tmp_u);
14756 bi_free(ctx, v);
14757 
14758 if (is_mod) /* get the remainder */
14759 {
14760 bi_free(ctx, quotient);
14761 return bi_int_divide(ctx, trim(u), d);
14762 } else /* get the quotient */
14763 {
14764 bi_free(ctx, u);
14765 return trim(quotient);
14766 }
14767}
14768 
14769/*
14770 * Perform an integer divide on a bigint.
14771 */
14772static bigint *bi_int_divide(BI_CTX *ctx, bigint *biR, comp denom) {
14773 int i = biR->size - 1;
14774 long_comp r = 0;
14775 
14776 (void) ctx;
14777 check(biR);
14778 
14779 do {
14780 r = (r << COMP_BIT_SIZE) + biR->comps[i];
14781 biR->comps[i] = (comp)(r / denom);
14782 r %= denom;
14783 } while (--i >= 0);
14784 
14785 return trim(biR);
14786}
14787 
14788#ifdef CONFIG_BIGINT_MONTGOMERY
14789/**
14790 * There is a need for the value of integer N' such that B^-1(B-1)-N^-1N'=1,
14791 * where B^-1(B-1) mod N=1. Actually, only the least significant part of
14792 * N' is needed, hence the definition N0'=N' mod b. We reproduce below the
14793 * simple algorithm from an article by Dusse and Kaliski to efficiently
14794 * find N0' from N0 and b */
14795static comp modular_inverse(bigint *bim) {
14796 int i;
14797 comp t = 1;
14798 comp two_2_i_minus_1 = 2; /* 2^(i-1) */
14799 long_comp two_2_i = 4; /* 2^i */
14800 comp N = bim->comps[0];
14801 
14802 for (i = 2; i <= COMP_BIT_SIZE; i++) {
14803 if ((long_comp) N * t % two_2_i >= two_2_i_minus_1) {
14804 t += two_2_i_minus_1;
14805 }
14806 
14807 two_2_i_minus_1 <<= 1;
14808 two_2_i <<= 1;
14809 }
14810 
14811 return (comp)(COMP_RADIX - t);
14812}
14813#endif
14814 
14815#if defined(CONFIG_BIGINT_KARATSUBA) || defined(CONFIG_BIGINT_BARRETT) || \
14816 defined(CONFIG_BIGINT_MONTGOMERY)
14817/**
14818 * Take each component and shift down (in terms of components)
14819 */
14820static bigint *comp_right_shift(bigint *biR, int num_shifts) {
14821 int i = biR->size - num_shifts;
14822 comp *x = biR->comps;
14823 comp *y = &biR->comps[num_shifts];
14824 
14825 check(biR);
14826 
14827 if (i <= 0) /* have we completely right shifted? */
14828 {
14829 biR->comps[0] = 0; /* return 0 */
14830 biR->size = 1;
14831 return biR;
14832 }
14833 
14834 do {
14835 *x++ = *y++;
14836 } while (--i > 0);
14837 
14838 biR->size -= num_shifts;
14839 return biR;
14840}
14841 
14842/**
14843 * Take each component and shift it up (in terms of components)
14844 */
14845static bigint *comp_left_shift(bigint *biR, int num_shifts) {
14846 int i = biR->size - 1;
14847 comp *x, *y;
14848 
14849 check(biR);
14850 
14851 if (num_shifts <= 0) {
14852 return biR;
14853 }
14854 
14855 more_comps(biR, biR->size + num_shifts);
14856 
14857 x = &biR->comps[i + num_shifts];
14858 y = &biR->comps[i];
14859 
14860 do {
14861 *x-- = *y--;
14862 } while (i--);
14863 
14864 memset(biR->comps, 0, (size_t) (num_shifts * COMP_BYTE_SIZE)); /* zero LS comps */
14865 return biR;
14866}
14867#endif
14868 
14869/**
14870 * @brief Allow a binary sequence to be imported as a bigint.
14871 * @param ctx [in] The bigint session context.
14872 * @param data [in] The data to be converted.
14873 * @param size [in] The number of bytes of data.
14874 * @return A bigint representing this data.
14875 */
14876NS_INTERNAL bigint *bi_import(BI_CTX *ctx, const uint8_t *data, int size) {
14877 bigint *biR = alloc(ctx, (size + COMP_BYTE_SIZE - 1) / COMP_BYTE_SIZE);
14878 int i, j = 0, offset = 0;
14879 
14880 memset(biR->comps, 0, (size_t) (biR->size * COMP_BYTE_SIZE));
14881 
14882 for (i = size - 1; i >= 0; i--) {
14883 biR->comps[offset] += (comp) data[i] << (j * 8);
14884 
14885 if (++j == COMP_BYTE_SIZE) {
14886 j = 0;
14887 offset++;
14888 }
14889 }
14890 
14891 return trim(biR);
14892}
14893 
14894#ifdef CONFIG_SSL_FULL_MODE
14895/**
14896 * @brief The testharness uses this code to import text hex-streams and
14897 * convert them into bigints.
14898 * @param ctx [in] The bigint session context.
14899 * @param data [in] A string consisting of hex characters. The characters must
14900 * be in upper case.
14901 * @return A bigint representing this data.
14902 */
14903NS_INTERNAL bigint *bi_str_import(BI_CTX *ctx, const char *data) {
14904 int size = strlen(data);
14905 bigint *biR = alloc(ctx, (size + COMP_NUM_NIBBLES - 1) / COMP_NUM_NIBBLES);
14906 int i, j = 0, offset = 0;
14907 memset(biR->comps, 0, (size_t) (biR->size * COMP_BYTE_SIZE));
14908 
14909 for (i = size - 1; i >= 0; i--) {
14910 int num = (data[i] <= '9') ? (data[i] - '0') : (data[i] - 'A' + 10);
14911 biR->comps[offset] += num << (j * 4);
14912 
14913 if (++j == COMP_NUM_NIBBLES) {
14914 j = 0;
14915 offset++;
14916 }
14917 }
14918 
14919 return biR;
14920}
14921 
14922NS_INTERNAL void bi_print(const char *label, bigint *x) {
14923 int i, j;
14924 
14925 if (x == NULL) {
14926 printf("%s: (null)\n", label);
14927 return;
14928 }
14929 
14930 printf("%s: (size %d)\n", label, x->size);
14931 for (i = x->size - 1; i >= 0; i--) {
14932 for (j = COMP_NUM_NIBBLES - 1; j >= 0; j--) {
14933 comp mask = 0x0f << (j * 4);
14934 comp num = (x->comps[i] & mask) >> (j * 4);
14935 putc((num <= 9) ? (num + '0') : (num + 'A' - 10), stdout);
14936 }
14937 }
14938 
14939 printf("\n");
14940}
14941#endif
14942 
14943/**
14944 * @brief Take a bigint and convert it into a byte sequence.
14945 *
14946 * This is useful after a decrypt operation.
14947 * @param ctx [in] The bigint session context.
14948 * @param x [in] The bigint to be converted.
14949 * @param data [out] The converted data as a byte stream.
14950 * @param size [in] The maximum size of the byte stream. Unused bytes will be
14951 * zeroed.
14952 */
14953NS_INTERNAL void bi_export(BI_CTX *ctx, bigint *x, uint8_t *data, int size) {
14954 int i, j, k = size - 1;
14955 
14956 check(x);
14957 memset(data, 0, (size_t) size); /* ensure all leading 0's are cleared */
14958 
14959 for (i = 0; i < x->size; i++) {
14960 for (j = 0; j < COMP_BYTE_SIZE; j++) {
14961 comp mask = (comp) 0xff << (j * 8);
14962 int num = (int) (x->comps[i] & mask) >> (j * 8);
14963 data[k--] = (uint8_t) num;
14964 
14965 if (k < 0) {
14966 goto buf_done;
14967 }
14968 }
14969 }
14970buf_done:
14971 
14972 bi_free(ctx, x);
14973}
14974 
14975/**
14976 * @brief Pre-calculate some of the expensive steps in reduction.
14977 *
14978 * This function should only be called once (normally when a session starts).
14979 * When the session is over, bi_free_mod() should be called. bi_mod_power()
14980 * relies on this function being called.
14981 * @param ctx [in] The bigint session context.
14982 * @param bim [in] The bigint modulus that will be used.
14983 * @param mod_offset [in] There are three moduluii that can be stored - the
14984 * standard modulus, and its two primes p and q. This offset refers to which
14985 * modulus we are referring to.
14986 * @see bi_free_mod(), bi_mod_power().
14987 */
14988NS_INTERNAL void bi_set_mod(BI_CTX *ctx, bigint *bim, int mod_offset) {
14989 int k = bim->size;
14990 comp d = (comp)((long_comp) COMP_RADIX / (bim->comps[k - 1] + 1));
14991#ifdef CONFIG_BIGINT_MONTGOMERY
14992 bigint *R, *R2;
14993#endif
14994 
14995 ctx->bi_mod[mod_offset] = bim;
14996 bi_permanent(ctx->bi_mod[mod_offset]);
14997 ctx->bi_normalised_mod[mod_offset] = bi_int_multiply(ctx, bim, d);
14998 bi_permanent(ctx->bi_normalised_mod[mod_offset]);
14999 
15000#if defined(CONFIG_BIGINT_MONTGOMERY)
15001 /* set montgomery variables */
15002 R = comp_left_shift(bi_clone(ctx, ctx->bi_radix), k - 1); /* R */
15003 R2 = comp_left_shift(bi_clone(ctx, ctx->bi_radix), k * 2 - 1); /* R^2 */
15004 ctx->bi_RR_mod_m[mod_offset] = bi_mod(ctx, R2); /* R^2 mod m */
15005 ctx->bi_R_mod_m[mod_offset] = bi_mod(ctx, R); /* R mod m */
15006 
15007 bi_permanent(ctx->bi_RR_mod_m[mod_offset]);
15008 bi_permanent(ctx->bi_R_mod_m[mod_offset]);
15009 
15010 ctx->N0_dash[mod_offset] = modular_inverse(ctx->bi_mod[mod_offset]);
15011 
15012#elif defined(CONFIG_BIGINT_BARRETT)
15013 ctx->bi_mu[mod_offset] =
15014 bi_divide(ctx, comp_left_shift(bi_clone(ctx, ctx->bi_radix), k * 2 - 1),
15015 ctx->bi_mod[mod_offset], 0);
15016 bi_permanent(ctx->bi_mu[mod_offset]);
15017#endif
15018}
15019 
15020#if 0
15021/**
15022 * @brief Used when cleaning various bigints at the end of a session.
15023 * @param ctx [in] The bigint session context.
15024 * @param mod_offset [in] The offset to use.
15025 * @see bi_set_mod().
15026 */
15027void bi_free_mod(BI_CTX *ctx, int mod_offset) {
15028 bi_depermanent(ctx->bi_mod[mod_offset]);
15029 bi_free(ctx, ctx->bi_mod[mod_offset]);
15030#if defined(CONFIG_BIGINT_MONTGOMERY)
15031 bi_depermanent(ctx->bi_RR_mod_m[mod_offset]);
15032 bi_depermanent(ctx->bi_R_mod_m[mod_offset]);
15033 bi_free(ctx, ctx->bi_RR_mod_m[mod_offset]);
15034 bi_free(ctx, ctx->bi_R_mod_m[mod_offset]);
15035#elif defined(CONFIG_BIGINT_BARRETT)
15036 bi_depermanent(ctx->bi_mu[mod_offset]);
15037 bi_free(ctx, ctx->bi_mu[mod_offset]);
15038#endif
15039 bi_depermanent(ctx->bi_normalised_mod[mod_offset]);
15040 bi_free(ctx, ctx->bi_normalised_mod[mod_offset]);
15041}
15042#endif
15043 
15044/**
15045 * Perform a standard multiplication between two bigints.
15046 *
15047 * Barrett reduction has no need for some parts of the product, so ignore bits
15048 * of the multiply. This routine gives Barrett its big performance
15049 * improvements over Classical/Montgomery reduction methods.
15050 */
15051static bigint *regular_multiply(BI_CTX *ctx, bigint *bia, bigint *bib,
15052 int inner_partial, int outer_partial) {
15053 int i = 0, j;
15054 int n = bia->size;
15055 int t = bib->size;
15056 bigint *biR = alloc(ctx, n + t);
15057 comp *sr = biR->comps;
15058 comp *sa = bia->comps;
15059 comp *sb = bib->comps;
15060 
15061 check(bia);
15062 check(bib);
15063 
15064 /* clear things to start with */
15065 memset(biR->comps, 0, (size_t) ((n + t) * COMP_BYTE_SIZE));
15066 
15067 do {
15068 long_comp tmp;
15069 comp carry = 0;
15070 int r_index = i;
15071 j = 0;
15072 
15073 if (outer_partial && outer_partial - i > 0 && outer_partial < n) {
15074 r_index = outer_partial - 1;
15075 j = outer_partial - i - 1;
15076 }
15077 
15078 do {
15079 if (inner_partial && r_index >= inner_partial) {
15080 break;
15081 }
15082 
15083 tmp = sr[r_index] + ((long_comp) sa[j]) * sb[i] + carry;
15084 sr[r_index++] = (comp) tmp; /* downsize */
15085 carry = (comp) (tmp >> COMP_BIT_SIZE);
15086 } while (++j < n);
15087 
15088 sr[r_index] = carry;
15089 } while (++i < t);
15090 
15091 bi_free(ctx, bia);
15092 bi_free(ctx, bib);
15093 return trim(biR);
15094}
15095 
15096#ifdef CONFIG_BIGINT_KARATSUBA
15097/*
15098 * Karatsuba improves on regular multiplication due to only 3 multiplications
15099 * being done instead of 4. The additional additions/subtractions are O(N)
15100 * rather than O(N^2) and so for big numbers it saves on a few operations
15101 */
15102static bigint *karatsuba(BI_CTX *ctx, bigint *bia, bigint *bib, int is_square) {
15103 bigint *x0, *x1;
15104 bigint *p0, *p1, *p2;
15105 int m;
15106 
15107 if (is_square) {
15108 m = (bia->size + 1) / 2;
15109 } else {
15110 m = (MAX(bia->size, bib->size) + 1) / 2;
15111 }
15112 
15113 x0 = bi_clone(ctx, bia);
15114 x0->size = m;
15115 x1 = bi_clone(ctx, bia);
15116 comp_right_shift(x1, m);
15117 bi_free(ctx, bia);
15118 
15119 /* work out the 3 partial products */
15120 if (is_square) {
15121 p0 = bi_square(ctx, bi_copy(x0));
15122 p2 = bi_square(ctx, bi_copy(x1));
15123 p1 = bi_square(ctx, bi_add(ctx, x0, x1));
15124 } else /* normal multiply */
15125 {
15126 bigint *y0, *y1;
15127 y0 = bi_clone(ctx, bib);
15128 y0->size = m;
15129 y1 = bi_clone(ctx, bib);
15130 comp_right_shift(y1, m);
15131 bi_free(ctx, bib);
15132 
15133 p0 = bi_multiply(ctx, bi_copy(x0), bi_copy(y0));
15134 p2 = bi_multiply(ctx, bi_copy(x1), bi_copy(y1));
15135 p1 = bi_multiply(ctx, bi_add(ctx, x0, x1), bi_add(ctx, y0, y1));
15136 }
15137 
15138 p1 = bi_subtract(ctx, bi_subtract(ctx, p1, bi_copy(p2), NULL), bi_copy(p0),
15139 NULL);
15140 
15141 comp_left_shift(p1, m);
15142 comp_left_shift(p2, 2 * m);
15143 return bi_add(ctx, p1, bi_add(ctx, p0, p2));
15144}
15145#endif
15146 
15147/**
15148 * @brief Perform a multiplication operation between two bigints.
15149 * @param ctx [in] The bigint session context.
15150 * @param bia [in] A bigint.
15151 * @param bib [in] Another bigint.
15152 * @return The result of the multiplication.
15153 */
15154NS_INTERNAL bigint *bi_multiply(BI_CTX *ctx, bigint *bia, bigint *bib) {
15155 check(bia);
15156 check(bib);
15157 
15158#ifdef CONFIG_BIGINT_KARATSUBA
15159 if (MIN(bia->size, bib->size) < MUL_KARATSUBA_THRESH) {
15160 return regular_multiply(ctx, bia, bib, 0, 0);
15161 }
15162 
15163 return karatsuba(ctx, bia, bib, 0);
15164#else
15165 return regular_multiply(ctx, bia, bib, 0, 0);
15166#endif
15167}
15168 
15169#ifdef CONFIG_BIGINT_SQUARE
15170/*
15171 * Perform the actual square operion. It takes into account overflow.
15172 */
15173static bigint *regular_square(BI_CTX *ctx, bigint *bi) {
15174 int t = bi->size;
15175 int i = 0, j;
15176 bigint *biR = alloc(ctx, t * 2 + 1);
15177 comp *w = biR->comps;
15178 comp *x = bi->comps;
15179 long_comp carry;
15180 memset(w, 0, biR->size * COMP_BYTE_SIZE);
15181 
15182 do {
15183 long_comp tmp = w[2 * i] + (long_comp) x[i] * x[i];
15184 w[2 * i] = (comp) tmp;
15185 carry = tmp >> COMP_BIT_SIZE;
15186 
15187 for (j = i + 1; j < t; j++) {
15188 uint8_t c = 0;
15189 long_comp xx = (long_comp) x[i] * x[j];
15190 if ((COMP_MAX - xx) < xx) c = 1;
15191 
15192 tmp = (xx << 1);
15193 
15194 if ((COMP_MAX - tmp) < w[i + j]) c = 1;
15195 
15196 tmp += w[i + j];
15197 
15198 if ((COMP_MAX - tmp) < carry) c = 1;
15199 
15200 tmp += carry;
15201 w[i + j] = (comp) tmp;
15202 carry = tmp >> COMP_BIT_SIZE;
15203 
15204 if (c) carry += COMP_RADIX;
15205 }
15206 
15207 tmp = w[i + t] + carry;
15208 w[i + t] = (comp) tmp;
15209 w[i + t + 1] = tmp >> COMP_BIT_SIZE;
15210 } while (++i < t);
15211 
15212 bi_free(ctx, bi);
15213 return trim(biR);
15214}
15215 
15216/**
15217 * @brief Perform a square operation on a bigint.
15218 * @param ctx [in] The bigint session context.
15219 * @param bia [in] A bigint.
15220 * @return The result of the multiplication.
15221 */
15222NS_INTERNAL bigint *bi_square(BI_CTX *ctx, bigint *bia) {
15223 check(bia);
15224 
15225#ifdef CONFIG_BIGINT_KARATSUBA
15226 if (bia->size < SQU_KARATSUBA_THRESH) {
15227 return regular_square(ctx, bia);
15228 }
15229 
15230 return karatsuba(ctx, bia, NULL, 1);
15231#else
15232 return regular_square(ctx, bia);
15233#endif
15234}
15235#endif
15236 
15237/**
15238 * @brief Compare two bigints.
15239 * @param bia [in] A bigint.
15240 * @param bib [in] Another bigint.
15241 * @return -1 if smaller, 1 if larger and 0 if equal.
15242 */
15243NS_INTERNAL int bi_compare(bigint *bia, bigint *bib) {
15244 int r, i;
15245 
15246 check(bia);
15247 check(bib);
15248 
15249 if (bia->size > bib->size)
15250 r = 1;
15251 else if (bia->size < bib->size)
15252 r = -1;
15253 else {
15254 comp *a = bia->comps;
15255 comp *b = bib->comps;
15256 
15257 /* Same number of components. Compare starting from the high end
15258 * and working down. */
15259 r = 0;
15260 i = bia->size - 1;
15261 
15262 do {
15263 if (a[i] > b[i]) {
15264 r = 1;
15265 break;
15266 } else if (a[i] < b[i]) {
15267 r = -1;
15268 break;
15269 }
15270 } while (--i >= 0);
15271 }
15272 
15273 return r;
15274}
15275 
15276/*
15277 * Allocate and zero more components. Does not consume bi.
15278 */
15279static void more_comps(bigint *bi, int n) {
15280 if (n > bi->max_comps) {
15281 int max = MAX(bi->max_comps * 2, n);
15282 void *p = calloc(1, (size_t) max * COMP_BYTE_SIZE);
15283 if (p != NULL && bi->size > 0) memcpy(p, bi->comps, (size_t) bi->max_comps * COMP_BYTE_SIZE);
15284 free(bi->comps);
15285 bi->max_comps = (short) max;
15286 bi->comps = (comp *) p;
15287 }
15288 
15289 if (n > bi->size) {
15290 memset(&bi->comps[bi->size], 0, (size_t) (n - bi->size) * COMP_BYTE_SIZE);
15291 }
15292 
15293 bi->size = (short) n;
15294}
15295 
15296/*
15297 * Make a new empty bigint. It may just use an old one if one is available.
15298 * Otherwise get one off the heap.
15299 */
15300static bigint *alloc(BI_CTX *ctx, int size) {
15301 bigint *biR;
15302 
15303 /* Can we recycle an old bigint? */
15304 if (ctx->free_list != NULL) {
15305 biR = ctx->free_list;
15306 ctx->free_list = biR->next;
15307 ctx->free_count--;
15308 
15309 if (biR->refs != 0) {
15310#ifdef CONFIG_SSL_FULL_MODE
15311 printf("alloc: refs was not 0\n");
15312#endif
15313 abort(); /* create a stack trace from a core dump */
15314 }
15315 
15316 more_comps(biR, size);
15317 } else {
15318 /* No free bigints available - create a new one. */
15319 biR = (bigint *) calloc(1, sizeof(bigint));
15320 biR->comps = (comp *) calloc(1, (size_t) size * COMP_BYTE_SIZE);
15321 biR->max_comps = (short) size; /* give some space to spare */
15322 }
15323 
15324 biR->size = (short) size;
15325 biR->refs = 1;
15326 biR->next = NULL;
15327 ctx->active_count++;
15328 return biR;
15329}
15330 
15331/*
15332 * Work out the highest '1' bit in an exponent. Used when doing sliding-window
15333 * exponentiation.
15334 */
15335static int find_max_exp_index(bigint *biexp) {
15336 int i = COMP_BIT_SIZE - 1;
15337 comp shift = COMP_RADIX / 2;
15338 comp test = biexp->comps[biexp->size - 1]; /* assume no leading zeroes */
15339 
15340 check(biexp);
15341 
15342 do {
15343 if (test & shift) {
15344 return i + (biexp->size - 1) * COMP_BIT_SIZE;
15345 }
15346 
15347 shift >>= 1;
15348 } while (i-- != 0);
15349 
15350 return -1; /* error - must have been a leading 0 */
15351}
15352 
15353/*
15354 * Is a particular bit is an exponent 1 or 0? Used when doing sliding-window
15355 * exponentiation.
15356 */
15357static int exp_bit_is_one(bigint *biexp, int offset) {
15358 comp test = biexp->comps[offset / COMP_BIT_SIZE];
15359 int num_shifts = offset % COMP_BIT_SIZE;
15360 comp shift = 1;
15361 int i;
15362 
15363 check(biexp);
15364 
15365 for (i = 0; i < num_shifts; i++) {
15366 shift <<= 1;
15367 }
15368 
15369 return (test & shift) != 0;
15370}
15371 
15372#ifdef CONFIG_BIGINT_CHECK_ON
15373/*
15374 * Perform a sanity check on bi.
15375 */
15376static void check(const bigint *bi) {
15377 if (bi->refs <= 0) {
15378 printf("check: zero or negative refs in bigint\n");
15379 abort();
15380 }
15381 
15382 if (bi->next != NULL) {
15383 printf(
15384 "check: attempt to use a bigint from "
15385 "the free list\n");
15386 abort();
15387 }
15388}
15389#endif
15390 
15391/*
15392 * Delete any leading 0's (and allow for 0).
15393 */
15394static bigint *trim(bigint *bi) {
15395 check(bi);
15396 
15397 while (bi->comps[bi->size - 1] == 0 && bi->size > 1) {
15398 bi->size--;
15399 }
15400 
15401 return bi;
15402}
15403 
15404#if defined(CONFIG_BIGINT_MONTGOMERY)
15405/**
15406 * @brief Perform a single montgomery reduction.
15407 * @param ctx [in] The bigint session context.
15408 * @param bixy [in] A bigint.
15409 * @return The result of the montgomery reduction.
15410 */
15411NS_INTERNAL bigint *bi_mont(BI_CTX *ctx, bigint *bixy) {
15412 int i = 0, n;
15413 uint8_t mod_offset = ctx->mod_offset;
15414 bigint *bim = ctx->bi_mod[mod_offset];
15415 comp mod_inv = ctx->N0_dash[mod_offset];
15416 
15417 check(bixy);
15418 
15419 if (ctx->use_classical) /* just use classical instead */
15420 {
15421 return bi_mod(ctx, bixy);
15422 }
15423 
15424 n = bim->size;
15425 
15426 do {
15427 bixy = bi_add(ctx, bixy,
15428 comp_left_shift(
15429 bi_int_multiply(ctx, bim, bixy->comps[i] * mod_inv), i));
15430 } while (++i < n);
15431 
15432 comp_right_shift(bixy, n);
15433 
15434 if (bi_compare(bixy, bim) >= 0) {
15435 bixy = bi_subtract(ctx, bixy, bim, NULL);
15436 }
15437 
15438 return bixy;
15439}
15440 
15441#elif defined(CONFIG_BIGINT_BARRETT)
15442/*
15443 * Stomp on the most significant components to give the illusion of a "mod base
15444 * radix" operation
15445 */
15446static bigint *comp_mod(bigint *bi, int mod) {
15447 check(bi);
15448 
15449 if (bi->size > mod) {
15450 bi->size = mod;
15451 }
15452 
15453 return bi;
15454}
15455 
15456/**
15457 * @brief Perform a single Barrett reduction.
15458 * @param ctx [in] The bigint session context.
15459 * @param bi [in] A bigint.
15460 * @return The result of the Barrett reduction.
15461 */
15462NS_INTERNAL bigint *bi_barrett(BI_CTX *ctx, bigint *bi) {
15463 bigint *q1, *q2, *q3, *r1, *r2, *r;
15464 uint8_t mod_offset = ctx->mod_offset;
15465 bigint *bim = ctx->bi_mod[mod_offset];
15466 int k = bim->size;
15467 
15468 check(bi);
15469 check(bim);
15470 
15471 /* use Classical method instead - Barrett cannot help here */
15472 if (bi->size > k * 2) {
15473 return bi_mod(ctx, bi);
15474 }
15475 
15476 q1 = comp_right_shift(bi_clone(ctx, bi), k - 1);
15477 
15478 /* do outer partial multiply */
15479 q2 = regular_multiply(ctx, q1, ctx->bi_mu[mod_offset], 0, k - 1);
15480 q3 = comp_right_shift(q2, k + 1);
15481 r1 = comp_mod(bi, k + 1);
15482 
15483 /* do inner partial multiply */
15484 r2 = comp_mod(regular_multiply(ctx, q3, bim, k + 1, 0), k + 1);
15485 r = bi_subtract(ctx, r1, r2, NULL);
15486 
15487 /* if (r >= m) r = r - m; */
15488 if (bi_compare(r, bim) >= 0) {
15489 r = bi_subtract(ctx, r, bim, NULL);
15490 }
15491 
15492 return r;
15493}
15494#endif /* CONFIG_BIGINT_BARRETT */
15495 
15496#ifdef CONFIG_BIGINT_SLIDING_WINDOW
15497/*
15498 * Work out g1, g3, g5, g7... etc for the sliding-window algorithm
15499 */
15500static void precompute_slide_window(BI_CTX *ctx, int window, bigint *g1) {
15501 int k = 1, i;
15502 bigint *g2;
15503 
15504 for (i = 0; i < window - 1; i++) /* compute 2^(window-1) */
15505 {
15506 k <<= 1;
15507 }
15508 
15509 ctx->g = (bigint **) calloc(1, k * sizeof(bigint *));
15510 ctx->g[0] = bi_clone(ctx, g1);
15511 bi_permanent(ctx->g[0]);
15512 g2 = bi_residue(ctx, bi_square(ctx, ctx->g[0])); /* g^2 */
15513 
15514 for (i = 1; i < k; i++) {
15515 ctx->g[i] = bi_residue(ctx, bi_multiply(ctx, ctx->g[i - 1], bi_copy(g2)));
15516 bi_permanent(ctx->g[i]);
15517 }
15518 
15519 bi_free(ctx, g2);
15520 ctx->window = k;
15521}
15522#endif
15523 
15524/**
15525 * @brief Perform a modular exponentiation.
15526 *
15527 * This function requires bi_set_mod() to have been called previously. This is
15528 * one of the optimisations used for performance.
15529 * @param ctx [in] The bigint session context.
15530 * @param bi [in] The bigint on which to perform the mod power operation.
15531 * @param biexp [in] The bigint exponent.
15532 * @return The result of the mod exponentiation operation
15533 * @see bi_set_mod().
15534 */
15535NS_INTERNAL bigint *bi_mod_power(BI_CTX *ctx, bigint *bi, bigint *biexp) {
15536 int i = find_max_exp_index(biexp), j, window_size = 1;
15537 bigint *biR = int_to_bi(ctx, 1);
15538 
15539#if defined(CONFIG_BIGINT_MONTGOMERY)
15540 uint8_t mod_offset = ctx->mod_offset;
15541 if (!ctx->use_classical) {
15542 /* preconvert */
15543 bi = bi_mont(ctx,
15544 bi_multiply(ctx, bi, ctx->bi_RR_mod_m[mod_offset])); /* x' */
15545 bi_free(ctx, biR);
15546 biR = ctx->bi_R_mod_m[mod_offset]; /* A */
15547 }
15548#endif
15549 
15550 check(bi);
15551 check(biexp);
15552 
15553#ifdef CONFIG_BIGINT_SLIDING_WINDOW
15554 for (j = i; j > 32; j /= 5) /* work out an optimum size */
15555 window_size++;
15556 
15557 /* work out the slide constants */
15558 precompute_slide_window(ctx, window_size, bi);
15559#else /* just one constant */
15560 ctx->g = (bigint **) calloc(1, sizeof(bigint *));
15561 ctx->g[0] = bi_clone(ctx, bi);
15562 ctx->window = 1;
15563 bi_permanent(ctx->g[0]);
15564#endif
15565 
15566 /* if sliding-window is off, then only one bit will be done at a time and
15567 * will reduce to standard left-to-right exponentiation */
15568 do {
15569 if (exp_bit_is_one(biexp, i)) {
15570 int l = i - window_size + 1;
15571 int part_exp = 0;
15572 
15573 if (l < 0) /* LSB of exponent will always be 1 */
15574 l = 0;
15575 else {
15576 while (exp_bit_is_one(biexp, l) == 0) l++; /* go back up */
15577 }
15578 
15579 /* build up the section of the exponent */
15580 for (j = i; j >= l; j--) {
15581 biR = bi_residue(ctx, bi_square(ctx, biR));
15582 if (exp_bit_is_one(biexp, j)) part_exp++;
15583 
15584 if (j != l) part_exp <<= 1;
15585 }
15586 
15587 part_exp = (part_exp - 1) / 2; /* adjust for array */
15588 biR = bi_residue(ctx, bi_multiply(ctx, biR, ctx->g[part_exp]));
15589 i = l - 1;
15590 } else /* square it */
15591 {
15592 biR = bi_residue(ctx, bi_square(ctx, biR));
15593 i--;
15594 }
15595 } while (i >= 0);
15596 
15597 /* cleanup */
15598 for (i = 0; i < ctx->window; i++) {
15599 bi_depermanent(ctx->g[i]);
15600 bi_free(ctx, ctx->g[i]);
15601 }
15602 
15603 free(ctx->g);
15604 bi_free(ctx, bi);
15605 bi_free(ctx, biexp);
15606#if defined CONFIG_BIGINT_MONTGOMERY
15607 return ctx->use_classical ? biR : bi_mont(ctx, biR); /* convert back */
15608#else /* CONFIG_BIGINT_CLASSICAL or CONFIG_BIGINT_BARRETT */
15609 return biR;
15610#endif
15611}
15612 
15613#if 0
15614/**
15615 * @brief Use the Chinese Remainder Theorem to quickly perform RSA decrypts.
15616 *
15617 * @param ctx [in] The bigint session context.
15618 * @param bi [in] The bigint to perform the exp/mod.
15619 * @param dP [in] CRT's dP bigint
15620 * @param dQ [in] CRT's dQ bigint
15621 * @param p [in] CRT's p bigint
15622 * @param q [in] CRT's q bigint
15623 * @param qInv [in] CRT's qInv bigint
15624 * @return The result of the CRT operation
15625 */
15626NS_INTERNAL bigint *bi_crt(BI_CTX *ctx, bigint *bi, bigint *dP, bigint *dQ,
15627 bigint *p, bigint *q, bigint *qInv) {
15628 bigint *m1, *m2, *h;
15629 
15630/* Montgomery has a condition the 0 < x, y < m and these products violate
15631 * that condition. So disable Montgomery when using CRT */
15632#if defined(CONFIG_BIGINT_MONTGOMERY)
15633 ctx->use_classical = 1;
15634#endif
15635 ctx->mod_offset = BIGINT_P_OFFSET;
15636 m1 = bi_mod_power(ctx, bi_copy(bi), dP);
15637 
15638 ctx->mod_offset = BIGINT_Q_OFFSET;
15639 m2 = bi_mod_power(ctx, bi, dQ);
15640 
15641 h = bi_subtract(ctx, bi_add(ctx, m1, p), bi_copy(m2), NULL);
15642 h = bi_multiply(ctx, h, qInv);
15643 ctx->mod_offset = BIGINT_P_OFFSET;
15644 h = bi_residue(ctx, h);
15645#if defined(CONFIG_BIGINT_MONTGOMERY)
15646 ctx->use_classical = 0; /* reset for any further operation */
15647#endif
15648 return bi_add(ctx, m2, bi_multiply(ctx, q, h));
15649}
15650#endif
15651 
15652int mg_rsa_mod_pow(const uint8_t *mod, size_t modsz, const uint8_t *exp, size_t expsz, const uint8_t *msg, size_t msgsz, uint8_t *out, size_t outsz) {
15653 BI_CTX *bi_ctx = bi_initialize();
15654 bigint *n = bi_import(bi_ctx, mod, (int) modsz);
15655 bigint *e = bi_import(bi_ctx, exp, (int) expsz);
15656 bigint *h = bi_import(bi_ctx, msg, (int) msgsz);
15657 bi_set_mod(bi_ctx, n, 0);
15658 bigint *m1 = bi_mod_power(bi_ctx, h, e);
15659 bi_export(bi_ctx, m1, out, (int) outsz);
15660 bi_free(bi_ctx, n);
15661 bi_free(bi_ctx, e);
15662 bi_free(bi_ctx, h);
15663 bi_free(bi_ctx, m1);
15664 return 0;
15665}
15666 
15667#endif /* MG_TLS == MG_TLS_BUILTIN */
15668 
15669#ifdef MG_ENABLE_LINES
15670#line 1 "src/tls_uecc.c"
15671#endif
15672/* Copyright 2014, Kenneth MacKay. Licensed under the BSD 2-clause license. */
15673 
15674 
15675 
15676 
15677#if MG_TLS == MG_TLS_BUILTIN
15678 
15679#ifndef MG_UECC_RNG_MAX_TRIES
15680#define MG_UECC_RNG_MAX_TRIES 64
15681#endif
15682 
15683#if MG_UECC_ENABLE_VLI_API
15684#define MG_UECC_VLI_API
15685#else
15686#define MG_UECC_VLI_API static
15687#endif
15688 
15689#if (MG_UECC_PLATFORM == mg_uecc_avr) || (MG_UECC_PLATFORM == mg_uecc_arm) || \
15690 (MG_UECC_PLATFORM == mg_uecc_arm_thumb) || \
15691 (MG_UECC_PLATFORM == mg_uecc_arm_thumb2)
15692#define MG_UECC_CONCATX(a, ...) a##__VA_ARGS__
15693#define MG_UECC_CONCAT(a, ...) MG_UECC_CONCATX(a, __VA_ARGS__)
15694 
15695#define STRX(a) #a
15696#define STR(a) STRX(a)
15697 
15698#define EVAL(...) EVAL1(EVAL1(EVAL1(EVAL1(__VA_ARGS__))))
15699#define EVAL1(...) EVAL2(EVAL2(EVAL2(EVAL2(__VA_ARGS__))))
15700#define EVAL2(...) EVAL3(EVAL3(EVAL3(EVAL3(__VA_ARGS__))))
15701#define EVAL3(...) EVAL4(EVAL4(EVAL4(EVAL4(__VA_ARGS__))))
15702#define EVAL4(...) __VA_ARGS__
15703 
15704#define DEC_1 0
15705#define DEC_2 1
15706#define DEC_3 2
15707#define DEC_4 3
15708#define DEC_5 4
15709#define DEC_6 5
15710#define DEC_7 6
15711#define DEC_8 7
15712#define DEC_9 8
15713#define DEC_10 9
15714#define DEC_11 10
15715#define DEC_12 11
15716#define DEC_13 12
15717#define DEC_14 13
15718#define DEC_15 14
15719#define DEC_16 15
15720#define DEC_17 16
15721#define DEC_18 17
15722#define DEC_19 18
15723#define DEC_20 19
15724#define DEC_21 20
15725#define DEC_22 21
15726#define DEC_23 22
15727#define DEC_24 23
15728#define DEC_25 24
15729#define DEC_26 25
15730#define DEC_27 26
15731#define DEC_28 27
15732#define DEC_29 28
15733#define DEC_30 29
15734#define DEC_31 30
15735#define DEC_32 31
15736 
15737#define DEC_(N) MG_UECC_CONCAT(DEC_, N)
15738 
15739#define SECOND_ARG(_, val, ...) val
15740#define SOME_CHECK_0 ~, 0
15741#define GET_SECOND_ARG(...) SECOND_ARG(__VA_ARGS__, SOME, )
15742#define SOME_OR_0(N) GET_SECOND_ARG(MG_UECC_CONCAT(SOME_CHECK_, N))
15743 
15744#define MG_UECC_EMPTY(...)
15745#define DEFER(...) __VA_ARGS__ MG_UECC_EMPTY()
15746 
15747#define REPEAT_NAME_0() REPEAT_0
15748#define REPEAT_NAME_SOME() REPEAT_SOME
15749#define REPEAT_0(...)
15750#define REPEAT_SOME(N, stuff) \
15751 DEFER(MG_UECC_CONCAT(REPEAT_NAME_, SOME_OR_0(DEC_(N))))()(DEC_(N), stuff) stuff
15752#define REPEAT(N, stuff) EVAL(REPEAT_SOME(N, stuff))
15753 
15754#define REPEATM_NAME_0() REPEATM_0
15755#define REPEATM_NAME_SOME() REPEATM_SOME
15756#define REPEATM_0(...)
15757#define REPEATM_SOME(N, macro) \
15758 macro(N) DEFER(MG_UECC_CONCAT(REPEATM_NAME_, SOME_OR_0(DEC_(N))))()(DEC_(N), macro)
15759#define REPEATM(N, macro) EVAL(REPEATM_SOME(N, macro))
15760#endif
15761 
15762//
15763 
15764#if (MG_UECC_WORD_SIZE == 1)
15765#if MG_UECC_SUPPORTS_secp160r1
15766#define MG_UECC_MAX_WORDS 21 /* Due to the size of curve_n. */
15767#endif
15768#if MG_UECC_SUPPORTS_secp192r1
15769#undef MG_UECC_MAX_WORDS
15770#define MG_UECC_MAX_WORDS 24
15771#endif
15772#if MG_UECC_SUPPORTS_secp224r1
15773#undef MG_UECC_MAX_WORDS
15774#define MG_UECC_MAX_WORDS 28
15775#endif
15776#if (MG_UECC_SUPPORTS_secp256r1 || MG_UECC_SUPPORTS_secp256k1)
15777#undef MG_UECC_MAX_WORDS
15778#define MG_UECC_MAX_WORDS 32
15779#endif
15780#elif (MG_UECC_WORD_SIZE == 4)
15781#if MG_UECC_SUPPORTS_secp160r1
15782#define MG_UECC_MAX_WORDS 6 /* Due to the size of curve_n. */
15783#endif
15784#if MG_UECC_SUPPORTS_secp192r1
15785#undef MG_UECC_MAX_WORDS
15786#define MG_UECC_MAX_WORDS 6
15787#endif
15788#if MG_UECC_SUPPORTS_secp224r1
15789#undef MG_UECC_MAX_WORDS
15790#define MG_UECC_MAX_WORDS 7
15791#endif
15792#if (MG_UECC_SUPPORTS_secp256r1 || MG_UECC_SUPPORTS_secp256k1)
15793#undef MG_UECC_MAX_WORDS
15794#define MG_UECC_MAX_WORDS 8
15795#endif
15796#elif (MG_UECC_WORD_SIZE == 8)
15797#if MG_UECC_SUPPORTS_secp160r1
15798#define MG_UECC_MAX_WORDS 3
15799#endif
15800#if MG_UECC_SUPPORTS_secp192r1
15801#undef MG_UECC_MAX_WORDS
15802#define MG_UECC_MAX_WORDS 3
15803#endif
15804#if MG_UECC_SUPPORTS_secp224r1
15805#undef MG_UECC_MAX_WORDS
15806#define MG_UECC_MAX_WORDS 4
15807#endif
15808#if (MG_UECC_SUPPORTS_secp256r1 || MG_UECC_SUPPORTS_secp256k1)
15809#undef MG_UECC_MAX_WORDS
15810#define MG_UECC_MAX_WORDS 4
15811#endif
15812#endif /* MG_UECC_WORD_SIZE */
15813 
15814#define BITS_TO_WORDS(num_bits) \
15815 ((wordcount_t) ((num_bits + ((MG_UECC_WORD_SIZE * 8) - 1)) / \
15816 (MG_UECC_WORD_SIZE * 8)))
15817#define BITS_TO_BYTES(num_bits) ((num_bits + 7) / 8)
15818 
15819struct MG_UECC_Curve_t {
15820 wordcount_t num_words;
15821 wordcount_t num_bytes;
15822 bitcount_t num_n_bits;
15823 mg_uecc_word_t p[MG_UECC_MAX_WORDS];
15824 mg_uecc_word_t n[MG_UECC_MAX_WORDS];
15825 mg_uecc_word_t G[MG_UECC_MAX_WORDS * 2];
15826 mg_uecc_word_t b[MG_UECC_MAX_WORDS];
15827 void (*double_jacobian)(mg_uecc_word_t *X1, mg_uecc_word_t *Y1,
15828 mg_uecc_word_t *Z1, MG_UECC_Curve curve);
15829#if MG_UECC_SUPPORT_COMPRESSED_POINT
15830 void (*mod_sqrt)(mg_uecc_word_t *a, MG_UECC_Curve curve);
15831#endif
15832 void (*x_side)(mg_uecc_word_t *result, const mg_uecc_word_t *x,
15833 MG_UECC_Curve curve);
15834#if (MG_UECC_OPTIMIZATION_LEVEL > 0)
15835 void (*mmod_fast)(mg_uecc_word_t *result, mg_uecc_word_t *product);
15836#endif
15837};
15838 
15839#if MG_UECC_VLI_NATIVE_LITTLE_ENDIAN
15840static void bcopy(uint8_t *dst, const uint8_t *src, unsigned num_bytes) {
15841 while (0 != num_bytes) {
15842 num_bytes--;
15843 dst[num_bytes] = src[num_bytes];
15844 }
15845}
15846#endif
15847 
15848static cmpresult_t mg_uecc_vli_cmp_unsafe(const mg_uecc_word_t *left,
15849 const mg_uecc_word_t *right,
15850 wordcount_t num_words);
15851 
15852#if (MG_UECC_PLATFORM == mg_uecc_arm || \
15853 MG_UECC_PLATFORM == mg_uecc_arm_thumb || \
15854 MG_UECC_PLATFORM == mg_uecc_arm_thumb2)
15855 
15856#endif
15857 
15858#if (MG_UECC_PLATFORM == mg_uecc_avr)
15859 
15860#endif
15861 
15862#ifndef asm_clear
15863#define asm_clear 0
15864#endif
15865#ifndef asm_set
15866#define asm_set 0
15867#endif
15868#ifndef asm_add
15869#define asm_add 0
15870#endif
15871#ifndef asm_sub
15872#define asm_sub 0
15873#endif
15874#ifndef asm_mult
15875#define asm_mult 0
15876#endif
15877#ifndef asm_rshift1
15878#define asm_rshift1 0
15879#endif
15880#ifndef asm_mmod_fast_secp256r1
15881#define asm_mmod_fast_secp256r1 0
15882#endif
15883 
15884#if defined(default_RNG_defined) && default_RNG_defined
15885static MG_UECC_RNG_Function g_rng_function = &default_RNG;
15886#else
15887static MG_UECC_RNG_Function g_rng_function = 0;
15888#endif
15889 
15890void mg_uecc_set_rng(MG_UECC_RNG_Function rng_function) {
15891 g_rng_function = rng_function;
15892}
15893 
15894MG_UECC_RNG_Function mg_uecc_get_rng(void) {
15895 return g_rng_function;
15896}
15897 
15898int mg_uecc_curve_private_key_size(MG_UECC_Curve curve) {
15899 return BITS_TO_BYTES(curve->num_n_bits);
15900}
15901 
15902int mg_uecc_curve_public_key_size(MG_UECC_Curve curve) {
15903 return 2 * curve->num_bytes;
15904}
15905 
15906#if !asm_clear
15907MG_UECC_VLI_API void mg_uecc_vli_clear(mg_uecc_word_t *vli,
15908 wordcount_t num_words) {
15909 wordcount_t i;
15910 for (i = 0; i < num_words; ++i) {
15911 vli[i] = 0;
15912 }
15913}
15914#endif /* !asm_clear */
15915 
15916/* Constant-time comparison to zero - secure way to compare long integers */
15917/* Returns 1 if vli == 0, 0 otherwise. */
15918MG_UECC_VLI_API mg_uecc_word_t mg_uecc_vli_isZero(const mg_uecc_word_t *vli,
15919 wordcount_t num_words) {
15920 mg_uecc_word_t bits = 0;
15921 wordcount_t i;
15922 for (i = 0; i < num_words; ++i) {
15923 bits |= vli[i];
15924 }
15925 return (bits == 0);
15926}
15927 
15928/* Returns nonzero if bit 'bit' of vli is set. */
15929MG_UECC_VLI_API mg_uecc_word_t mg_uecc_vli_testBit(const mg_uecc_word_t *vli,
15930 bitcount_t bit) {
15931 return (vli[bit >> MG_UECC_WORD_BITS_SHIFT] &
15932 ((mg_uecc_word_t) 1 << (bit & MG_UECC_WORD_BITS_MASK)));
15933}
15934 
15935/* Counts the number of words in vli. */
15936static wordcount_t vli_numDigits(const mg_uecc_word_t *vli,
15937 const wordcount_t max_words) {
15938 wordcount_t i;
15939 /* Search from the end until we find a non-zero digit.
15940 We do it in reverse because we expect that most digits will be nonzero. */
15941 for (i = max_words - 1; i >= 0 && vli[i] == 0; --i) {
15942 }
15943 
15944 return (i + 1);
15945}
15946 
15947/* Counts the number of bits required to represent vli. */
15948MG_UECC_VLI_API bitcount_t mg_uecc_vli_numBits(const mg_uecc_word_t *vli,
15949 const wordcount_t max_words) {
15950 mg_uecc_word_t i;
15951 mg_uecc_word_t digit;
15952 
15953 wordcount_t num_digits = vli_numDigits(vli, max_words);
15954 if (num_digits == 0) {
15955 return 0;
15956 }
15957 
15958 digit = vli[num_digits - 1];
15959 for (i = 0; digit; ++i) {
15960 digit >>= 1;
15961 }
15962 
15963 return (((bitcount_t) ((num_digits - 1) << MG_UECC_WORD_BITS_SHIFT)) +
15964 (bitcount_t) i);
15965}
15966 
15967/* Sets dest = src. */
15968#if !asm_set
15969MG_UECC_VLI_API void mg_uecc_vli_set(mg_uecc_word_t *dest,
15970 const mg_uecc_word_t *src,
15971 wordcount_t num_words) {
15972 wordcount_t i;
15973 for (i = 0; i < num_words; ++i) {
15974 dest[i] = src[i];
15975 }
15976}
15977#endif /* !asm_set */
15978 
15979/* Returns sign of left - right. */
15980static cmpresult_t mg_uecc_vli_cmp_unsafe(const mg_uecc_word_t *left,
15981 const mg_uecc_word_t *right,
15982 wordcount_t num_words) {
15983 wordcount_t i;
15984 for (i = num_words - 1; i >= 0; --i) {
15985 if (left[i] > right[i]) {
15986 return 1;
15987 } else if (left[i] < right[i]) {
15988 return -1;
15989 }
15990 }
15991 return 0;
15992}
15993 
15994/* Constant-time comparison function - secure way to compare long integers */
15995/* Returns one if left == right, zero otherwise. */
15996MG_UECC_VLI_API mg_uecc_word_t mg_uecc_vli_equal(const mg_uecc_word_t *left,
15997 const mg_uecc_word_t *right,
15998 wordcount_t num_words) {
15999 mg_uecc_word_t diff = 0;
16000 wordcount_t i;
16001 for (i = num_words - 1; i >= 0; --i) {
16002 diff |= (left[i] ^ right[i]);
16003 }
16004 return (diff == 0);
16005}
16006 
16007MG_UECC_VLI_API mg_uecc_word_t mg_uecc_vli_sub(mg_uecc_word_t *result,
16008 const mg_uecc_word_t *left,
16009 const mg_uecc_word_t *right,
16010 wordcount_t num_words);
16011 
16012/* Returns sign of left - right, in constant time. */
16013MG_UECC_VLI_API cmpresult_t mg_uecc_vli_cmp(const mg_uecc_word_t *left,
16014 const mg_uecc_word_t *right,
16015 wordcount_t num_words) {
16016 mg_uecc_word_t tmp[MG_UECC_MAX_WORDS];
16017 mg_uecc_word_t neg = !!mg_uecc_vli_sub(tmp, left, right, num_words);
16018 mg_uecc_word_t equal = mg_uecc_vli_isZero(tmp, num_words);
16019 return (cmpresult_t) (!equal - 2 * neg);
16020}
16021 
16022/* Computes vli = vli >> 1. */
16023#if !asm_rshift1
16024MG_UECC_VLI_API void mg_uecc_vli_rshift1(mg_uecc_word_t *vli,
16025 wordcount_t num_words) {
16026 mg_uecc_word_t *end = vli;
16027 mg_uecc_word_t carry = 0;
16028 
16029 vli += num_words;
16030 while (vli-- > end) {
16031 mg_uecc_word_t temp = *vli;
16032 *vli = (temp >> 1) | carry;
16033 carry = temp << (MG_UECC_WORD_BITS - 1);
16034 }
16035}
16036#endif /* !asm_rshift1 */
16037 
16038/* Computes result = left + right, returning carry. Can modify in place. */
16039#if !asm_add
16040MG_UECC_VLI_API mg_uecc_word_t mg_uecc_vli_add(mg_uecc_word_t *result,
16041 const mg_uecc_word_t *left,
16042 const mg_uecc_word_t *right,
16043 wordcount_t num_words) {
16044 mg_uecc_word_t carry = 0;
16045 wordcount_t i;
16046 for (i = 0; i < num_words; ++i) {
16047 mg_uecc_word_t sum = left[i] + right[i] + carry;
16048 if (sum != left[i]) {
16049 carry = (sum < left[i]);
16050 }
16051 result[i] = sum;
16052 }
16053 return carry;
16054}
16055#endif /* !asm_add */
16056 
16057/* Computes result = left - right, returning borrow. Can modify in place. */
16058#if !asm_sub
16059MG_UECC_VLI_API mg_uecc_word_t mg_uecc_vli_sub(mg_uecc_word_t *result,
16060 const mg_uecc_word_t *left,
16061 const mg_uecc_word_t *right,
16062 wordcount_t num_words) {
16063 mg_uecc_word_t borrow = 0;
16064 wordcount_t i;
16065 for (i = 0; i < num_words; ++i) {
16066 mg_uecc_word_t diff = left[i] - right[i] - borrow;
16067 if (diff != left[i]) {
16068 borrow = (diff > left[i]);
16069 }
16070 result[i] = diff;
16071 }
16072 return borrow;
16073}
16074#endif /* !asm_sub */
16075 
16076#if !asm_mult || (MG_UECC_SQUARE_FUNC && !asm_square) || \
16077 (MG_UECC_SUPPORTS_secp256k1 && (MG_UECC_OPTIMIZATION_LEVEL > 0) && \
16078 ((MG_UECC_WORD_SIZE == 1) || (MG_UECC_WORD_SIZE == 8)))
16079static void muladd(mg_uecc_word_t a, mg_uecc_word_t b, mg_uecc_word_t *r0,
16080 mg_uecc_word_t *r1, mg_uecc_word_t *r2) {
16081#if MG_UECC_WORD_SIZE == 8
16082 uint64_t a0 = a & 0xffffffff;
16083 uint64_t a1 = a >> 32;
16084 uint64_t b0 = b & 0xffffffff;
16085 uint64_t b1 = b >> 32;
16086 
16087 uint64_t i0 = a0 * b0;
16088 uint64_t i1 = a0 * b1;
16089 uint64_t i2 = a1 * b0;
16090 uint64_t i3 = a1 * b1;
16091 
16092 uint64_t p0, p1;
16093 
16094 i2 += (i0 >> 32);
16095 i2 += i1;
16096 if (i2 < i1) { /* overflow */
16097 i3 += 0x100000000;
16098 }
16099 
16100 p0 = (i0 & 0xffffffff) | (i2 << 32);
16101 p1 = i3 + (i2 >> 32);
16102 
16103 *r0 += p0;
16104 *r1 += (p1 + (*r0 < p0));
16105 *r2 += ((*r1 < p1) || (*r1 == p1 && *r0 < p0));
16106#else
16107 mg_uecc_dword_t p = (mg_uecc_dword_t) a * b;
16108 mg_uecc_dword_t r01 = ((mg_uecc_dword_t) (*r1) << MG_UECC_WORD_BITS) | *r0;
16109 r01 += p;
16110 *r2 += (r01 < p);
16111 *r1 = (mg_uecc_word_t) (r01 >> MG_UECC_WORD_BITS);
16112 *r0 = (mg_uecc_word_t) r01;
16113#endif
16114}
16115#endif /* muladd needed */
16116 
16117#if !asm_mult
16118MG_UECC_VLI_API void mg_uecc_vli_mult(mg_uecc_word_t *result,
16119 const mg_uecc_word_t *left,
16120 const mg_uecc_word_t *right,
16121 wordcount_t num_words) {
16122 mg_uecc_word_t r0 = 0;
16123 mg_uecc_word_t r1 = 0;
16124 mg_uecc_word_t r2 = 0;
16125 wordcount_t i, k;
16126 
16127 /* Compute each digit of result in sequence, maintaining the carries. */
16128 for (k = 0; k < num_words; ++k) {
16129 for (i = 0; i <= k; ++i) {
16130 muladd(left[i], right[k - i], &r0, &r1, &r2);
16131 }
16132 result[k] = r0;
16133 r0 = r1;
16134 r1 = r2;
16135 r2 = 0;
16136 }
16137 for (k = num_words; k < num_words * 2 - 1; ++k) {
16138 for (i = (wordcount_t) ((k + 1) - num_words); i < num_words; ++i) {
16139 muladd(left[i], right[k - i], &r0, &r1, &r2);
16140 }
16141 result[k] = r0;
16142 r0 = r1;
16143 r1 = r2;
16144 r2 = 0;
16145 }
16146 result[num_words * 2 - 1] = r0;
16147}
16148#endif /* !asm_mult */
16149 
16150#if MG_UECC_SQUARE_FUNC
16151 
16152#if !asm_square
16153static void mul2add(mg_uecc_word_t a, mg_uecc_word_t b, mg_uecc_word_t *r0,
16154 mg_uecc_word_t *r1, mg_uecc_word_t *r2) {
16155#if MG_UECC_WORD_SIZE == 8
16156 uint64_t a0 = a & 0xffffffffull;
16157 uint64_t a1 = a >> 32;
16158 uint64_t b0 = b & 0xffffffffull;
16159 uint64_t b1 = b >> 32;
16160 
16161 uint64_t i0 = a0 * b0;
16162 uint64_t i1 = a0 * b1;
16163 uint64_t i2 = a1 * b0;
16164 uint64_t i3 = a1 * b1;
16165 
16166 uint64_t p0, p1;
16167 
16168 i2 += (i0 >> 32);
16169 i2 += i1;
16170 if (i2 < i1) { /* overflow */
16171 i3 += 0x100000000ull;
16172 }
16173 
16174 p0 = (i0 & 0xffffffffull) | (i2 << 32);
16175 p1 = i3 + (i2 >> 32);
16176 
16177 *r2 += (p1 >> 63);
16178 p1 = (p1 << 1) | (p0 >> 63);
16179 p0 <<= 1;
16180 
16181 *r0 += p0;
16182 *r1 += (p1 + (*r0 < p0));
16183 *r2 += ((*r1 < p1) || (*r1 == p1 && *r0 < p0));
16184#else
16185 mg_uecc_dword_t p = (mg_uecc_dword_t) a * b;
16186 mg_uecc_dword_t r01 = ((mg_uecc_dword_t) (*r1) << MG_UECC_WORD_BITS) | *r0;
16187 *r2 += (p >> (MG_UECC_WORD_BITS * 2 - 1));
16188 p *= 2;
16189 r01 += p;
16190 *r2 += (r01 < p);
16191 *r1 = r01 >> MG_UECC_WORD_BITS;
16192 *r0 = (mg_uecc_word_t) r01;
16193#endif
16194}
16195 
16196MG_UECC_VLI_API void mg_uecc_vli_square(mg_uecc_word_t *result,
16197 const mg_uecc_word_t *left,
16198 wordcount_t num_words) {
16199 mg_uecc_word_t r0 = 0;
16200 mg_uecc_word_t r1 = 0;
16201 mg_uecc_word_t r2 = 0;
16202 
16203 wordcount_t i, k;
16204 
16205 for (k = 0; k < num_words * 2 - 1; ++k) {
16206 mg_uecc_word_t min = (k < num_words ? 0 : (k + 1) - num_words);
16207 for (i = min; i <= k && i <= k - i; ++i) {
16208 if (i < k - i) {
16209 mul2add(left[i], left[k - i], &r0, &r1, &r2);
16210 } else {
16211 muladd(left[i], left[k - i], &r0, &r1, &r2);
16212 }
16213 }
16214 result[k] = r0;
16215 r0 = r1;
16216 r1 = r2;
16217 r2 = 0;
16218 }
16219 
16220 result[num_words * 2 - 1] = r0;
16221}
16222#endif /* !asm_square */
16223 
16224#else /* MG_UECC_SQUARE_FUNC */
16225 
16226#if MG_UECC_ENABLE_VLI_API
16227MG_UECC_VLI_API void mg_uecc_vli_square(mg_uecc_word_t *result,
16228 const mg_uecc_word_t *left,
16229 wordcount_t num_words) {
16230 mg_uecc_vli_mult(result, left, left, num_words);
16231}
16232#endif /* MG_UECC_ENABLE_VLI_API */
16233 
16234#endif /* MG_UECC_SQUARE_FUNC */
16235 
16236/* Computes result = (left + right) % mod.
16237 Assumes that left < mod and right < mod, and that result does not overlap
16238 mod. */
16239MG_UECC_VLI_API void mg_uecc_vli_modAdd(mg_uecc_word_t *result,
16240 const mg_uecc_word_t *left,
16241 const mg_uecc_word_t *right,
16242 const mg_uecc_word_t *mod,
16243 wordcount_t num_words) {
16244 mg_uecc_word_t carry = mg_uecc_vli_add(result, left, right, num_words);
16245 if (carry || mg_uecc_vli_cmp_unsafe(mod, result, num_words) != 1) {
16246 /* result > mod (result = mod + remainder), so subtract mod to get
16247 * remainder. */
16248 mg_uecc_vli_sub(result, result, mod, num_words);
16249 }
16250}
16251 
16252/* Computes result = (left - right) % mod.
16253 Assumes that left < mod and right < mod, and that result does not overlap
16254 mod. */
16255MG_UECC_VLI_API void mg_uecc_vli_modSub(mg_uecc_word_t *result,
16256 const mg_uecc_word_t *left,
16257 const mg_uecc_word_t *right,
16258 const mg_uecc_word_t *mod,
16259 wordcount_t num_words) {
16260 mg_uecc_word_t l_borrow = mg_uecc_vli_sub(result, left, right, num_words);
16261 if (l_borrow) {
16262 /* In this case, result == -diff == (max int) - diff. Since -x % d == d - x,
16263 we can get the correct result from result + mod (with overflow). */
16264 mg_uecc_vli_add(result, result, mod, num_words);
16265 }
16266}
16267 
16268/* Computes result = product % mod, where product is 2N words long. */
16269/* Currently only designed to work for curve_p or curve_n. */
16270MG_UECC_VLI_API void mg_uecc_vli_mmod(mg_uecc_word_t *result,
16271 mg_uecc_word_t *product,
16272 const mg_uecc_word_t *mod,
16273 wordcount_t num_words) {
16274 mg_uecc_word_t mod_multiple[2 * MG_UECC_MAX_WORDS];
16275 mg_uecc_word_t tmp[2 * MG_UECC_MAX_WORDS];
16276 mg_uecc_word_t *v[2] = {tmp, product};
16277 mg_uecc_word_t index;
16278 
16279 /* Shift mod so its highest set bit is at the maximum position. */
16280 bitcount_t shift = (bitcount_t) ((num_words * 2 * MG_UECC_WORD_BITS) -
16281 mg_uecc_vli_numBits(mod, num_words));
16282 wordcount_t word_shift = (wordcount_t) (shift / MG_UECC_WORD_BITS);
16283 wordcount_t bit_shift = (wordcount_t) (shift % MG_UECC_WORD_BITS);
16284 mg_uecc_word_t carry = 0;
16285 mg_uecc_vli_clear(mod_multiple, word_shift);
16286 if (bit_shift > 0) {
16287 for (index = 0; index < (mg_uecc_word_t) num_words; ++index) {
16288 mod_multiple[(mg_uecc_word_t) word_shift + index] =
16289 (mg_uecc_word_t) (mod[index] << bit_shift) | carry;
16290 carry = mod[index] >> (MG_UECC_WORD_BITS - bit_shift);
16291 }
16292 } else {
16293 mg_uecc_vli_set(mod_multiple + word_shift, mod, num_words);
16294 }
16295 
16296 for (index = 1; shift >= 0; --shift) {
16297 mg_uecc_word_t borrow = 0;
16298 wordcount_t i;
16299 for (i = 0; i < num_words * 2; ++i) {
16300 mg_uecc_word_t diff = v[index][i] - mod_multiple[i] - borrow;
16301 if (diff != v[index][i]) {
16302 borrow = (diff > v[index][i]);
16303 }
16304 v[1 - index][i] = diff;
16305 }
16306 index = !(index ^ borrow); /* Swap the index if there was no borrow */
16307 mg_uecc_vli_rshift1(mod_multiple, num_words);
16308 mod_multiple[num_words - 1] |= mod_multiple[num_words]
16309 << (MG_UECC_WORD_BITS - 1);
16310 mg_uecc_vli_rshift1(mod_multiple + num_words, num_words);
16311 }
16312 mg_uecc_vli_set(result, v[index], num_words);
16313}
16314 
16315/* Computes result = (left * right) % mod. */
16316MG_UECC_VLI_API void mg_uecc_vli_modMult(mg_uecc_word_t *result,
16317 const mg_uecc_word_t *left,
16318 const mg_uecc_word_t *right,
16319 const mg_uecc_word_t *mod,
16320 wordcount_t num_words) {
16321 mg_uecc_word_t product[2 * MG_UECC_MAX_WORDS];
16322 mg_uecc_vli_mult(product, left, right, num_words);
16323 mg_uecc_vli_mmod(result, product, mod, num_words);
16324}
16325 
16326MG_UECC_VLI_API void mg_uecc_vli_modMult_fast(mg_uecc_word_t *result,
16327 const mg_uecc_word_t *left,
16328 const mg_uecc_word_t *right,
16329 MG_UECC_Curve curve) {
16330 mg_uecc_word_t product[2 * MG_UECC_MAX_WORDS];
16331 mg_uecc_vli_mult(product, left, right, curve->num_words);
16332#if (MG_UECC_OPTIMIZATION_LEVEL > 0)
16333 curve->mmod_fast(result, product);
16334#else
16335 mg_uecc_vli_mmod(result, product, curve->p, curve->num_words);
16336#endif
16337}
16338 
16339#if MG_UECC_SQUARE_FUNC
16340 
16341#if MG_UECC_ENABLE_VLI_API
16342/* Computes result = left^2 % mod. */
16343MG_UECC_VLI_API void mg_uecc_vli_modSquare(mg_uecc_word_t *result,
16344 const mg_uecc_word_t *left,
16345 const mg_uecc_word_t *mod,
16346 wordcount_t num_words) {
16347 mg_uecc_word_t product[2 * MG_UECC_MAX_WORDS];
16348 mg_uecc_vli_square(product, left, num_words);
16349 mg_uecc_vli_mmod(result, product, mod, num_words);
16350}
16351#endif /* MG_UECC_ENABLE_VLI_API */
16352 
16353MG_UECC_VLI_API void mg_uecc_vli_modSquare_fast(mg_uecc_word_t *result,
16354 const mg_uecc_word_t *left,
16355 MG_UECC_Curve curve) {
16356 mg_uecc_word_t product[2 * MG_UECC_MAX_WORDS];
16357 mg_uecc_vli_square(product, left, curve->num_words);
16358#if (MG_UECC_OPTIMIZATION_LEVEL > 0)
16359 curve->mmod_fast(result, product);
16360#else
16361 mg_uecc_vli_mmod(result, product, curve->p, curve->num_words);
16362#endif
16363}
16364 
16365#else /* MG_UECC_SQUARE_FUNC */
16366 
16367#if MG_UECC_ENABLE_VLI_API
16368MG_UECC_VLI_API void mg_uecc_vli_modSquare(mg_uecc_word_t *result,
16369 const mg_uecc_word_t *left,
16370 const mg_uecc_word_t *mod,
16371 wordcount_t num_words) {
16372 mg_uecc_vli_modMult(result, left, left, mod, num_words);
16373}
16374#endif /* MG_UECC_ENABLE_VLI_API */
16375 
16376MG_UECC_VLI_API void mg_uecc_vli_modSquare_fast(mg_uecc_word_t *result,
16377 const mg_uecc_word_t *left,
16378 MG_UECC_Curve curve) {
16379 mg_uecc_vli_modMult_fast(result, left, left, curve);
16380}
16381 
16382#endif /* MG_UECC_SQUARE_FUNC */
16383 
16384#define EVEN(vli) (!(vli[0] & 1))
16385static void vli_modInv_update(mg_uecc_word_t *uv, const mg_uecc_word_t *mod,
16386 wordcount_t num_words) {
16387 mg_uecc_word_t carry = 0;
16388 if (!EVEN(uv)) {
16389 carry = mg_uecc_vli_add(uv, uv, mod, num_words);
16390 }
16391 mg_uecc_vli_rshift1(uv, num_words);
16392 if (carry) {
16393 uv[num_words - 1] |= HIGH_BIT_SET;
16394 }
16395}
16396 
16397/* Computes result = (1 / input) % mod. All VLIs are the same size.
16398 See "From Euclid's GCD to Montgomery Multiplication to the Great Divide" */
16399MG_UECC_VLI_API void mg_uecc_vli_modInv(mg_uecc_word_t *result,
16400 const mg_uecc_word_t *input,
16401 const mg_uecc_word_t *mod,
16402 wordcount_t num_words) {
16403 mg_uecc_word_t a[MG_UECC_MAX_WORDS], b[MG_UECC_MAX_WORDS],
16404 u[MG_UECC_MAX_WORDS], v[MG_UECC_MAX_WORDS];
16405 cmpresult_t cmpResult;
16406 
16407 if (mg_uecc_vli_isZero(input, num_words)) {
16408 mg_uecc_vli_clear(result, num_words);
16409 return;
16410 }
16411 
16412 mg_uecc_vli_set(a, input, num_words);
16413 mg_uecc_vli_set(b, mod, num_words);
16414 mg_uecc_vli_clear(u, num_words);
16415 u[0] = 1;
16416 mg_uecc_vli_clear(v, num_words);
16417 while ((cmpResult = mg_uecc_vli_cmp_unsafe(a, b, num_words)) != 0) {
16418 if (EVEN(a)) {
16419 mg_uecc_vli_rshift1(a, num_words);
16420 vli_modInv_update(u, mod, num_words);
16421 } else if (EVEN(b)) {
16422 mg_uecc_vli_rshift1(b, num_words);
16423 vli_modInv_update(v, mod, num_words);
16424 } else if (cmpResult > 0) {
16425 mg_uecc_vli_sub(a, a, b, num_words);
16426 mg_uecc_vli_rshift1(a, num_words);
16427 if (mg_uecc_vli_cmp_unsafe(u, v, num_words) < 0) {
16428 mg_uecc_vli_add(u, u, mod, num_words);
16429 }
16430 mg_uecc_vli_sub(u, u, v, num_words);
16431 vli_modInv_update(u, mod, num_words);
16432 } else {
16433 mg_uecc_vli_sub(b, b, a, num_words);
16434 mg_uecc_vli_rshift1(b, num_words);
16435 if (mg_uecc_vli_cmp_unsafe(v, u, num_words) < 0) {
16436 mg_uecc_vli_add(v, v, mod, num_words);
16437 }
16438 mg_uecc_vli_sub(v, v, u, num_words);
16439 vli_modInv_update(v, mod, num_words);
16440 }
16441 }
16442 mg_uecc_vli_set(result, u, num_words);
16443}
16444 
16445/* ------ Point operations ------ */
16446 
16447/* Copyright 2015, Kenneth MacKay. Licensed under the BSD 2-clause license. */
16448 
16449#ifndef _UECC_CURVE_SPECIFIC_H_
16450#define _UECC_CURVE_SPECIFIC_H_
16451 
16452#define num_bytes_secp160r1 20
16453#define num_bytes_secp192r1 24
16454#define num_bytes_secp224r1 28
16455#define num_bytes_secp256r1 32
16456#define num_bytes_secp256k1 32
16457 
16458#if (MG_UECC_WORD_SIZE == 1)
16459 
16460#define num_words_secp160r1 20
16461#define num_words_secp192r1 24
16462#define num_words_secp224r1 28
16463#define num_words_secp256r1 32
16464#define num_words_secp256k1 32
16465 
16466#define BYTES_TO_WORDS_8(a, b, c, d, e, f, g, h) \
16467 0x##a, 0x##b, 0x##c, 0x##d, 0x##e, 0x##f, 0x##g, 0x##h
16468#define BYTES_TO_WORDS_4(a, b, c, d) 0x##a, 0x##b, 0x##c, 0x##d
16469 
16470#elif (MG_UECC_WORD_SIZE == 4)
16471 
16472#define num_words_secp160r1 5
16473#define num_words_secp192r1 6
16474#define num_words_secp224r1 7
16475#define num_words_secp256r1 8
16476#define num_words_secp256k1 8
16477 
16478#define BYTES_TO_WORDS_8(a, b, c, d, e, f, g, h) 0x##d##c##b##a, 0x##h##g##f##e
16479#define BYTES_TO_WORDS_4(a, b, c, d) 0x##d##c##b##a
16480 
16481#elif (MG_UECC_WORD_SIZE == 8)
16482 
16483#define num_words_secp160r1 3
16484#define num_words_secp192r1 3
16485#define num_words_secp224r1 4
16486#define num_words_secp256r1 4
16487#define num_words_secp256k1 4
16488 
16489#define BYTES_TO_WORDS_8(a, b, c, d, e, f, g, h) 0x##h##g##f##e##d##c##b##a##U
16490#define BYTES_TO_WORDS_4(a, b, c, d) 0x##d##c##b##a##U
16491 
16492#endif /* MG_UECC_WORD_SIZE */
16493 
16494#if MG_UECC_SUPPORTS_secp160r1 || MG_UECC_SUPPORTS_secp192r1 || \
16495 MG_UECC_SUPPORTS_secp224r1 || MG_UECC_SUPPORTS_secp256r1
16496static void double_jacobian_default(mg_uecc_word_t *X1, mg_uecc_word_t *Y1,
16497 mg_uecc_word_t *Z1, MG_UECC_Curve curve) {
16498 /* t1 = X, t2 = Y, t3 = Z */
16499 mg_uecc_word_t t4[MG_UECC_MAX_WORDS];
16500 mg_uecc_word_t t5[MG_UECC_MAX_WORDS];
16501 wordcount_t num_words = curve->num_words;
16502 
16503 if (mg_uecc_vli_isZero(Z1, num_words)) {
16504 return;
16505 }
16506 
16507 mg_uecc_vli_modSquare_fast(t4, Y1, curve); /* t4 = y1^2 */
16508 mg_uecc_vli_modMult_fast(t5, X1, t4, curve); /* t5 = x1*y1^2 = A */
16509 mg_uecc_vli_modSquare_fast(t4, t4, curve); /* t4 = y1^4 */
16510 mg_uecc_vli_modMult_fast(Y1, Y1, Z1, curve); /* t2 = y1*z1 = z3 */
16511 mg_uecc_vli_modSquare_fast(Z1, Z1, curve); /* t3 = z1^2 */
16512 
16513 mg_uecc_vli_modAdd(X1, X1, Z1, curve->p, num_words); /* t1 = x1 + z1^2 */
16514 mg_uecc_vli_modAdd(Z1, Z1, Z1, curve->p, num_words); /* t3 = 2*z1^2 */
16515 mg_uecc_vli_modSub(Z1, X1, Z1, curve->p, num_words); /* t3 = x1 - z1^2 */
16516 mg_uecc_vli_modMult_fast(X1, X1, Z1, curve); /* t1 = x1^2 - z1^4 */
16517 
16518 mg_uecc_vli_modAdd(Z1, X1, X1, curve->p,
16519 num_words); /* t3 = 2*(x1^2 - z1^4) */
16520 mg_uecc_vli_modAdd(X1, X1, Z1, curve->p,
16521 num_words); /* t1 = 3*(x1^2 - z1^4) */
16522 if (mg_uecc_vli_testBit(X1, 0)) {
16523 mg_uecc_word_t l_carry = mg_uecc_vli_add(X1, X1, curve->p, num_words);
16524 mg_uecc_vli_rshift1(X1, num_words);
16525 X1[num_words - 1] |= l_carry << (MG_UECC_WORD_BITS - 1);
16526 } else {
16527 mg_uecc_vli_rshift1(X1, num_words);
16528 }
16529 /* t1 = 3/2*(x1^2 - z1^4) = B */
16530 
16531 mg_uecc_vli_modSquare_fast(Z1, X1, curve); /* t3 = B^2 */
16532 mg_uecc_vli_modSub(Z1, Z1, t5, curve->p, num_words); /* t3 = B^2 - A */
16533 mg_uecc_vli_modSub(Z1, Z1, t5, curve->p, num_words); /* t3 = B^2 - 2A = x3 */
16534 mg_uecc_vli_modSub(t5, t5, Z1, curve->p, num_words); /* t5 = A - x3 */
16535 mg_uecc_vli_modMult_fast(X1, X1, t5, curve); /* t1 = B * (A - x3) */
16536 mg_uecc_vli_modSub(t4, X1, t4, curve->p,
16537 num_words); /* t4 = B * (A - x3) - y1^4 = y3 */
16538 
16539 mg_uecc_vli_set(X1, Z1, num_words);
16540 mg_uecc_vli_set(Z1, Y1, num_words);
16541 mg_uecc_vli_set(Y1, t4, num_words);
16542}
16543 
16544/* Computes result = x^3 + ax + b. result must not overlap x. */
16545static void x_side_default(mg_uecc_word_t *result, const mg_uecc_word_t *x,
16546 MG_UECC_Curve curve) {
16547 mg_uecc_word_t _3[MG_UECC_MAX_WORDS] = {3}; /* -a = 3 */
16548 wordcount_t num_words = curve->num_words;
16549 
16550 mg_uecc_vli_modSquare_fast(result, x, curve); /* r = x^2 */
16551 mg_uecc_vli_modSub(result, result, _3, curve->p, num_words); /* r = x^2 - 3 */
16552 mg_uecc_vli_modMult_fast(result, result, x, curve); /* r = x^3 - 3x */
16553 mg_uecc_vli_modAdd(result, result, curve->b, curve->p,
16554 num_words); /* r = x^3 - 3x + b */
16555}
16556#endif /* MG_UECC_SUPPORTS_secp... */
16557 
16558#if MG_UECC_SUPPORT_COMPRESSED_POINT
16559#if MG_UECC_SUPPORTS_secp160r1 || MG_UECC_SUPPORTS_secp192r1 || \
16560 MG_UECC_SUPPORTS_secp256r1 || MG_UECC_SUPPORTS_secp256k1
16561/* Compute a = sqrt(a) (mod curve_p). */
16562static void mod_sqrt_default(mg_uecc_word_t *a, MG_UECC_Curve curve) {
16563 bitcount_t i;
16564 mg_uecc_word_t p1[MG_UECC_MAX_WORDS] = {1};
16565 mg_uecc_word_t l_result[MG_UECC_MAX_WORDS] = {1};
16566 wordcount_t num_words = curve->num_words;
16567 
16568 /* When curve->p == 3 (mod 4), we can compute
16569 sqrt(a) = a^((curve->p + 1) / 4) (mod curve->p). */
16570 mg_uecc_vli_add(p1, curve->p, p1, num_words); /* p1 = curve_p + 1 */
16571 for (i = mg_uecc_vli_numBits(p1, num_words) - 1; i > 1; --i) {
16572 mg_uecc_vli_modSquare_fast(l_result, l_result, curve);
16573 if (mg_uecc_vli_testBit(p1, i)) {
16574 mg_uecc_vli_modMult_fast(l_result, l_result, a, curve);
16575 }
16576 }
16577 mg_uecc_vli_set(a, l_result, num_words);
16578}
16579#endif /* MG_UECC_SUPPORTS_secp... */
16580#endif /* MG_UECC_SUPPORT_COMPRESSED_POINT */
16581 
16582#if MG_UECC_SUPPORTS_secp160r1
16583 
16584#if (MG_UECC_OPTIMIZATION_LEVEL > 0)
16585static void vli_mmod_fast_secp160r1(mg_uecc_word_t *result,
16586 mg_uecc_word_t *product);
16587#endif
16588 
16589static const struct MG_UECC_Curve_t curve_secp160r1 = {
16590 num_words_secp160r1,
16591 num_bytes_secp160r1,
16592 161, /* num_n_bits */
16593 {BYTES_TO_WORDS_8(FF, FF, FF, 7F, FF, FF, FF, FF),
16594 BYTES_TO_WORDS_8(FF, FF, FF, FF, FF, FF, FF, FF),
16595 BYTES_TO_WORDS_4(FF, FF, FF, FF)},
16596 {BYTES_TO_WORDS_8(57, 22, 75, CA, D3, AE, 27, F9),
16597 BYTES_TO_WORDS_8(C8, F4, 01, 00, 00, 00, 00, 00),
16598 BYTES_TO_WORDS_8(00, 00, 00, 00, 01, 00, 00, 00)},
16599 {BYTES_TO_WORDS_8(82, FC, CB, 13, B9, 8B, C3, 68),
16600 BYTES_TO_WORDS_8(89, 69, 64, 46, 28, 73, F5, 8E),
16601 BYTES_TO_WORDS_4(68, B5, 96, 4A),
16602 
16603 BYTES_TO_WORDS_8(32, FB, C5, 7A, 37, 51, 23, 04),
16604 BYTES_TO_WORDS_8(12, C9, DC, 59, 7D, 94, 68, 31),
16605 BYTES_TO_WORDS_4(55, 28, A6, 23)},
16606 {BYTES_TO_WORDS_8(45, FA, 65, C5, AD, D4, D4, 81),
16607 BYTES_TO_WORDS_8(9F, F8, AC, 65, 8B, 7A, BD, 54),
16608 BYTES_TO_WORDS_4(FC, BE, 97, 1C)},
16609 &double_jacobian_default,
16610#if MG_UECC_SUPPORT_COMPRESSED_POINT
16611 &mod_sqrt_default,
16612#endif
16613 &x_side_default,
16614#if (MG_UECC_OPTIMIZATION_LEVEL > 0)
16615 &vli_mmod_fast_secp160r1
16616#endif
16617};
16618 
16619MG_UECC_Curve mg_uecc_secp160r1(void) {
16620 return &curve_secp160r1;
16621}
16622 
16623#if (MG_UECC_OPTIMIZATION_LEVEL > 0 && !asm_mmod_fast_secp160r1)
16624/* Computes result = product % curve_p
16625 see http://www.isys.uni-klu.ac.at/PDF/2001-0126-MT.pdf page 354
16626 
16627 Note that this only works if log2(omega) < log2(p) / 2 */
16628static void omega_mult_secp160r1(mg_uecc_word_t *result,
16629 const mg_uecc_word_t *right);
16630#if MG_UECC_WORD_SIZE == 8
16631static void vli_mmod_fast_secp160r1(mg_uecc_word_t *result,
16632 mg_uecc_word_t *product) {
16633 mg_uecc_word_t tmp[2 * num_words_secp160r1];
16634 mg_uecc_word_t copy;
16635 
16636 mg_uecc_vli_clear(tmp, num_words_secp160r1);
16637 mg_uecc_vli_clear(tmp + num_words_secp160r1, num_words_secp160r1);
16638 
16639 omega_mult_secp160r1(tmp,
16640 product + num_words_secp160r1 - 1); /* (Rq, q) = q * c */
16641 
16642 product[num_words_secp160r1 - 1] &= 0xffffffff;
16643 copy = tmp[num_words_secp160r1 - 1];
16644 tmp[num_words_secp160r1 - 1] &= 0xffffffff;
16645 mg_uecc_vli_add(result, product, tmp,
16646 num_words_secp160r1); /* (C, r) = r + q */
16647 mg_uecc_vli_clear(product, num_words_secp160r1);
16648 tmp[num_words_secp160r1 - 1] = copy;
16649 omega_mult_secp160r1(product, tmp + num_words_secp160r1 - 1); /* Rq*c */
16650 mg_uecc_vli_add(result, result, product,
16651 num_words_secp160r1); /* (C1, r) = r + Rq*c */
16652 
16653 while (mg_uecc_vli_cmp_unsafe(result, curve_secp160r1.p,
16654 num_words_secp160r1) > 0) {
16655 mg_uecc_vli_sub(result, result, curve_secp160r1.p, num_words_secp160r1);
16656 }
16657}
16658 
16659static void omega_mult_secp160r1(uint64_t *result, const uint64_t *right) {
16660 uint32_t carry;
16661 unsigned i;
16662 
16663 /* Multiply by (2^31 + 1). */
16664 carry = 0;
16665 for (i = 0; i < num_words_secp160r1; ++i) {
16666 uint64_t tmp = (right[i] >> 32) | (right[i + 1] << 32);
16667 result[i] = (tmp << 31) + tmp + carry;
16668 carry = (tmp >> 33) + (result[i] < tmp || (carry && result[i] == tmp));
16669 }
16670 result[i] = carry;
16671}
16672#else
16673static void vli_mmod_fast_secp160r1(mg_uecc_word_t *result,
16674 mg_uecc_word_t *product) {
16675 mg_uecc_word_t tmp[2 * num_words_secp160r1];
16676 mg_uecc_word_t carry;
16677 
16678 mg_uecc_vli_clear(tmp, num_words_secp160r1);
16679 mg_uecc_vli_clear(tmp + num_words_secp160r1, num_words_secp160r1);
16680 
16681 omega_mult_secp160r1(tmp,
16682 product + num_words_secp160r1); /* (Rq, q) = q * c */
16683 
16684 carry = mg_uecc_vli_add(result, product, tmp,
16685 num_words_secp160r1); /* (C, r) = r + q */
16686 mg_uecc_vli_clear(product, num_words_secp160r1);
16687 omega_mult_secp160r1(product, tmp + num_words_secp160r1); /* Rq*c */
16688 carry += mg_uecc_vli_add(result, result, product,
16689 num_words_secp160r1); /* (C1, r) = r + Rq*c */
16690 
16691 while (carry > 0) {
16692 --carry;
16693 mg_uecc_vli_sub(result, result, curve_secp160r1.p, num_words_secp160r1);
16694 }
16695 if (mg_uecc_vli_cmp_unsafe(result, curve_secp160r1.p, num_words_secp160r1) >
16696 0) {
16697 mg_uecc_vli_sub(result, result, curve_secp160r1.p, num_words_secp160r1);
16698 }
16699}
16700#endif
16701 
16702#if MG_UECC_WORD_SIZE == 1
16703static void omega_mult_secp160r1(uint8_t *result, const uint8_t *right) {
16704 uint8_t carry;
16705 uint8_t i;
16706 
16707 /* Multiply by (2^31 + 1). */
16708 mg_uecc_vli_set(result + 4, right, num_words_secp160r1); /* 2^32 */
16709 mg_uecc_vli_rshift1(result + 4, num_words_secp160r1); /* 2^31 */
16710 result[3] = right[0] << 7; /* get last bit from shift */
16711 
16712 carry = mg_uecc_vli_add(result, result, right,
16713 num_words_secp160r1); /* 2^31 + 1 */
16714 for (i = num_words_secp160r1; carry; ++i) {
16715 uint16_t sum = (uint16_t) result[i] + carry;
16716 result[i] = (uint8_t) sum;
16717 carry = sum >> 8;
16718 }
16719}
16720#elif MG_UECC_WORD_SIZE == 4
16721static void omega_mult_secp160r1(uint32_t *result, const uint32_t *right) {
16722 uint32_t carry;
16723 unsigned i;
16724 
16725 /* Multiply by (2^31 + 1). */
16726 mg_uecc_vli_set(result + 1, right, num_words_secp160r1); /* 2^32 */
16727 mg_uecc_vli_rshift1(result + 1, num_words_secp160r1); /* 2^31 */
16728 result[0] = right[0] << 31; /* get last bit from shift */
16729 
16730 carry = mg_uecc_vli_add(result, result, right,
16731 num_words_secp160r1); /* 2^31 + 1 */
16732 for (i = num_words_secp160r1; carry; ++i) {
16733 uint64_t sum = (uint64_t) result[i] + carry;
16734 result[i] = (uint32_t) sum;
16735 carry = sum >> 32;
16736 }
16737}
16738#endif /* MG_UECC_WORD_SIZE */
16739#endif /* (MG_UECC_OPTIMIZATION_LEVEL > 0 && !asm_mmod_fast_secp160r1) */
16740 
16741#endif /* MG_UECC_SUPPORTS_secp160r1 */
16742 
16743#if MG_UECC_SUPPORTS_secp192r1
16744 
16745#if (MG_UECC_OPTIMIZATION_LEVEL > 0)
16746static void vli_mmod_fast_secp192r1(mg_uecc_word_t *result,
16747 mg_uecc_word_t *product);
16748#endif
16749 
16750static const struct MG_UECC_Curve_t curve_secp192r1 = {
16751 num_words_secp192r1,
16752 num_bytes_secp192r1,
16753 192, /* num_n_bits */
16754 {BYTES_TO_WORDS_8(FF, FF, FF, FF, FF, FF, FF, FF),
16755 BYTES_TO_WORDS_8(FE, FF, FF, FF, FF, FF, FF, FF),
16756 BYTES_TO_WORDS_8(FF, FF, FF, FF, FF, FF, FF, FF)},
16757 {BYTES_TO_WORDS_8(31, 28, D2, B4, B1, C9, 6B, 14),
16758 BYTES_TO_WORDS_8(36, F8, DE, 99, FF, FF, FF, FF),
16759 BYTES_TO_WORDS_8(FF, FF, FF, FF, FF, FF, FF, FF)},
16760 {BYTES_TO_WORDS_8(12, 10, FF, 82, FD, 0A, FF, F4),
16761 BYTES_TO_WORDS_8(00, 88, A1, 43, EB, 20, BF, 7C),
16762 BYTES_TO_WORDS_8(F6, 90, 30, B0, 0E, A8, 8D, 18),
16763 
16764 BYTES_TO_WORDS_8(11, 48, 79, 1E, A1, 77, F9, 73),
16765 BYTES_TO_WORDS_8(D5, CD, 24, 6B, ED, 11, 10, 63),
16766 BYTES_TO_WORDS_8(78, DA, C8, FF, 95, 2B, 19, 07)},
16767 {BYTES_TO_WORDS_8(B1, B9, 46, C1, EC, DE, B8, FE),
16768 BYTES_TO_WORDS_8(49, 30, 24, 72, AB, E9, A7, 0F),
16769 BYTES_TO_WORDS_8(E7, 80, 9C, E5, 19, 05, 21, 64)},
16770 &double_jacobian_default,
16771#if MG_UECC_SUPPORT_COMPRESSED_POINT
16772 &mod_sqrt_default,
16773#endif
16774 &x_side_default,
16775#if (MG_UECC_OPTIMIZATION_LEVEL > 0)
16776 &vli_mmod_fast_secp192r1
16777#endif
16778};
16779 
16780MG_UECC_Curve mg_uecc_secp192r1(void) {
16781 return &curve_secp192r1;
16782}
16783 
16784#if (MG_UECC_OPTIMIZATION_LEVEL > 0)
16785/* Computes result = product % curve_p.
16786 See algorithm 5 and 6 from http://www.isys.uni-klu.ac.at/PDF/2001-0126-MT.pdf
16787 */
16788#if MG_UECC_WORD_SIZE == 1
16789static void vli_mmod_fast_secp192r1(uint8_t *result, uint8_t *product) {
16790 uint8_t tmp[num_words_secp192r1];
16791 uint8_t carry;
16792 
16793 mg_uecc_vli_set(result, product, num_words_secp192r1);
16794 
16795 mg_uecc_vli_set(tmp, &product[24], num_words_secp192r1);
16796 carry = mg_uecc_vli_add(result, result, tmp, num_words_secp192r1);
16797 
16798 tmp[0] = tmp[1] = tmp[2] = tmp[3] = tmp[4] = tmp[5] = tmp[6] = tmp[7] = 0;
16799 tmp[8] = product[24];
16800 tmp[9] = product[25];
16801 tmp[10] = product[26];
16802 tmp[11] = product[27];
16803 tmp[12] = product[28];
16804 tmp[13] = product[29];
16805 tmp[14] = product[30];
16806 tmp[15] = product[31];
16807 tmp[16] = product[32];
16808 tmp[17] = product[33];
16809 tmp[18] = product[34];
16810 tmp[19] = product[35];
16811 tmp[20] = product[36];
16812 tmp[21] = product[37];
16813 tmp[22] = product[38];
16814 tmp[23] = product[39];
16815 carry += mg_uecc_vli_add(result, result, tmp, num_words_secp192r1);
16816 
16817 tmp[0] = tmp[8] = product[40];
16818 tmp[1] = tmp[9] = product[41];
16819 tmp[2] = tmp[10] = product[42];
16820 tmp[3] = tmp[11] = product[43];
16821 tmp[4] = tmp[12] = product[44];
16822 tmp[5] = tmp[13] = product[45];
16823 tmp[6] = tmp[14] = product[46];
16824 tmp[7] = tmp[15] = product[47];
16825 tmp[16] = tmp[17] = tmp[18] = tmp[19] = tmp[20] = tmp[21] = tmp[22] =
16826 tmp[23] = 0;
16827 carry += mg_uecc_vli_add(result, result, tmp, num_words_secp192r1);
16828 
16829 while (carry || mg_uecc_vli_cmp_unsafe(curve_secp192r1.p, result,
16830 num_words_secp192r1) != 1) {
16831 carry -=
16832 mg_uecc_vli_sub(result, result, curve_secp192r1.p, num_words_secp192r1);
16833 }
16834}
16835#elif MG_UECC_WORD_SIZE == 4
16836static void vli_mmod_fast_secp192r1(uint32_t *result, uint32_t *product) {
16837 uint32_t tmp[num_words_secp192r1];
16838 int carry;
16839 
16840 mg_uecc_vli_set(result, product, num_words_secp192r1);
16841 
16842 mg_uecc_vli_set(tmp, &product[6], num_words_secp192r1);
16843 carry = mg_uecc_vli_add(result, result, tmp, num_words_secp192r1);
16844 
16845 tmp[0] = tmp[1] = 0;
16846 tmp[2] = product[6];
16847 tmp[3] = product[7];
16848 tmp[4] = product[8];
16849 tmp[5] = product[9];
16850 carry += mg_uecc_vli_add(result, result, tmp, num_words_secp192r1);
16851 
16852 tmp[0] = tmp[2] = product[10];
16853 tmp[1] = tmp[3] = product[11];
16854 tmp[4] = tmp[5] = 0;
16855 carry += mg_uecc_vli_add(result, result, tmp, num_words_secp192r1);
16856 
16857 while (carry || mg_uecc_vli_cmp_unsafe(curve_secp192r1.p, result,
16858 num_words_secp192r1) != 1) {
16859 carry -=
16860 mg_uecc_vli_sub(result, result, curve_secp192r1.p, num_words_secp192r1);
16861 }
16862}
16863#else
16864static void vli_mmod_fast_secp192r1(uint64_t *result, uint64_t *product) {
16865 uint64_t tmp[num_words_secp192r1];
16866 int carry;
16867 
16868 mg_uecc_vli_set(result, product, num_words_secp192r1);
16869 
16870 mg_uecc_vli_set(tmp, &product[3], num_words_secp192r1);
16871 carry = (int) mg_uecc_vli_add(result, result, tmp, num_words_secp192r1);
16872 
16873 tmp[0] = 0;
16874 tmp[1] = product[3];
16875 tmp[2] = product[4];
16876 carry += mg_uecc_vli_add(result, result, tmp, num_words_secp192r1);
16877 
16878 tmp[0] = tmp[1] = product[5];
16879 tmp[2] = 0;
16880 carry += mg_uecc_vli_add(result, result, tmp, num_words_secp192r1);
16881 
16882 while (carry || mg_uecc_vli_cmp_unsafe(curve_secp192r1.p, result,
16883 num_words_secp192r1) != 1) {
16884 carry -=
16885 mg_uecc_vli_sub(result, result, curve_secp192r1.p, num_words_secp192r1);
16886 }
16887}
16888#endif /* MG_UECC_WORD_SIZE */
16889#endif /* (MG_UECC_OPTIMIZATION_LEVEL > 0) */
16890 
16891#endif /* MG_UECC_SUPPORTS_secp192r1 */
16892 
16893#if MG_UECC_SUPPORTS_secp224r1
16894 
16895#if MG_UECC_SUPPORT_COMPRESSED_POINT
16896static void mod_sqrt_secp224r1(mg_uecc_word_t *a, MG_UECC_Curve curve);
16897#endif
16898#if (MG_UECC_OPTIMIZATION_LEVEL > 0)
16899static void vli_mmod_fast_secp224r1(mg_uecc_word_t *result,
16900 mg_uecc_word_t *product);
16901#endif
16902 
16903static const struct MG_UECC_Curve_t curve_secp224r1 = {
16904 num_words_secp224r1,
16905 num_bytes_secp224r1,
16906 224, /* num_n_bits */
16907 {BYTES_TO_WORDS_8(01, 00, 00, 00, 00, 00, 00, 00),
16908 BYTES_TO_WORDS_8(00, 00, 00, 00, FF, FF, FF, FF),
16909 BYTES_TO_WORDS_8(FF, FF, FF, FF, FF, FF, FF, FF),
16910 BYTES_TO_WORDS_4(FF, FF, FF, FF)},
16911 {BYTES_TO_WORDS_8(3D, 2A, 5C, 5C, 45, 29, DD, 13),
16912 BYTES_TO_WORDS_8(3E, F0, B8, E0, A2, 16, FF, FF),
16913 BYTES_TO_WORDS_8(FF, FF, FF, FF, FF, FF, FF, FF),
16914 BYTES_TO_WORDS_4(FF, FF, FF, FF)},
16915 {BYTES_TO_WORDS_8(21, 1D, 5C, 11, D6, 80, 32, 34),
16916 BYTES_TO_WORDS_8(22, 11, C2, 56, D3, C1, 03, 4A),
16917 BYTES_TO_WORDS_8(B9, 90, 13, 32, 7F, BF, B4, 6B),
16918 BYTES_TO_WORDS_4(BD, 0C, 0E, B7),
16919 
16920 BYTES_TO_WORDS_8(34, 7E, 00, 85, 99, 81, D5, 44),
16921 BYTES_TO_WORDS_8(64, 47, 07, 5A, A0, 75, 43, CD),
16922 BYTES_TO_WORDS_8(E6, DF, 22, 4C, FB, 23, F7, B5),
16923 BYTES_TO_WORDS_4(88, 63, 37, BD)},
16924 {BYTES_TO_WORDS_8(B4, FF, 55, 23, 43, 39, 0B, 27),
16925 BYTES_TO_WORDS_8(BA, D8, BF, D7, B7, B0, 44, 50),
16926 BYTES_TO_WORDS_8(56, 32, 41, F5, AB, B3, 04, 0C),
16927 BYTES_TO_WORDS_4(85, 0A, 05, B4)},
16928 &double_jacobian_default,
16929#if MG_UECC_SUPPORT_COMPRESSED_POINT
16930 &mod_sqrt_secp224r1,
16931#endif
16932 &x_side_default,
16933#if (MG_UECC_OPTIMIZATION_LEVEL > 0)
16934 &vli_mmod_fast_secp224r1
16935#endif
16936};
16937 
16938MG_UECC_Curve mg_uecc_secp224r1(void) {
16939 return &curve_secp224r1;
16940}
16941 
16942#if MG_UECC_SUPPORT_COMPRESSED_POINT
16943/* Routine 3.2.4 RS; from http://www.nsa.gov/ia/_files/nist-routines.pdf */
16944static void mod_sqrt_secp224r1_rs(mg_uecc_word_t *d1, mg_uecc_word_t *e1,
16945 mg_uecc_word_t *f1, const mg_uecc_word_t *d0,
16946 const mg_uecc_word_t *e0,
16947 const mg_uecc_word_t *f0) {
16948 mg_uecc_word_t t[num_words_secp224r1];
16949 
16950 mg_uecc_vli_modSquare_fast(t, d0, &curve_secp224r1); /* t <-- d0 ^ 2 */
16951 mg_uecc_vli_modMult_fast(e1, d0, e0, &curve_secp224r1); /* e1 <-- d0 * e0 */
16952 mg_uecc_vli_modAdd(d1, t, f0, curve_secp224r1.p,
16953 num_words_secp224r1); /* d1 <-- t + f0 */
16954 mg_uecc_vli_modAdd(e1, e1, e1, curve_secp224r1.p,
16955 num_words_secp224r1); /* e1 <-- e1 + e1 */
16956 mg_uecc_vli_modMult_fast(f1, t, f0, &curve_secp224r1); /* f1 <-- t * f0 */
16957 mg_uecc_vli_modAdd(f1, f1, f1, curve_secp224r1.p,
16958 num_words_secp224r1); /* f1 <-- f1 + f1 */
16959 mg_uecc_vli_modAdd(f1, f1, f1, curve_secp224r1.p,
16960 num_words_secp224r1); /* f1 <-- f1 + f1 */
16961}
16962 
16963/* Routine 3.2.5 RSS; from http://www.nsa.gov/ia/_files/nist-routines.pdf */
16964static void mod_sqrt_secp224r1_rss(mg_uecc_word_t *d1, mg_uecc_word_t *e1,
16965 mg_uecc_word_t *f1, const mg_uecc_word_t *d0,
16966 const mg_uecc_word_t *e0,
16967 const mg_uecc_word_t *f0,
16968 const bitcount_t j) {
16969 bitcount_t i;
16970 
16971 mg_uecc_vli_set(d1, d0, num_words_secp224r1); /* d1 <-- d0 */
16972 mg_uecc_vli_set(e1, e0, num_words_secp224r1); /* e1 <-- e0 */
16973 mg_uecc_vli_set(f1, f0, num_words_secp224r1); /* f1 <-- f0 */
16974 for (i = 1; i <= j; i++) {
16975 mod_sqrt_secp224r1_rs(d1, e1, f1, d1, e1, f1); /* RS (d1,e1,f1,d1,e1,f1) */
16976 }
16977}
16978 
16979/* Routine 3.2.6 RM; from http://www.nsa.gov/ia/_files/nist-routines.pdf */
16980static void mod_sqrt_secp224r1_rm(mg_uecc_word_t *d2, mg_uecc_word_t *e2,
16981 mg_uecc_word_t *f2, const mg_uecc_word_t *c,
16982 const mg_uecc_word_t *d0,
16983 const mg_uecc_word_t *e0,
16984 const mg_uecc_word_t *d1,
16985 const mg_uecc_word_t *e1) {
16986 mg_uecc_word_t t1[num_words_secp224r1];
16987 mg_uecc_word_t t2[num_words_secp224r1];
16988 
16989 mg_uecc_vli_modMult_fast(t1, e0, e1, &curve_secp224r1); /* t1 <-- e0 * e1 */
16990 mg_uecc_vli_modMult_fast(t1, t1, c, &curve_secp224r1); /* t1 <-- t1 * c */
16991 /* t1 <-- p - t1 */
16992 mg_uecc_vli_modSub(t1, curve_secp224r1.p, t1, curve_secp224r1.p,
16993 num_words_secp224r1);
16994 mg_uecc_vli_modMult_fast(t2, d0, d1, &curve_secp224r1); /* t2 <-- d0 * d1 */
16995 mg_uecc_vli_modAdd(t2, t2, t1, curve_secp224r1.p,
16996 num_words_secp224r1); /* t2 <-- t2 + t1 */
16997 mg_uecc_vli_modMult_fast(t1, d0, e1, &curve_secp224r1); /* t1 <-- d0 * e1 */
16998 mg_uecc_vli_modMult_fast(e2, d1, e0, &curve_secp224r1); /* e2 <-- d1 * e0 */
16999 mg_uecc_vli_modAdd(e2, e2, t1, curve_secp224r1.p,
17000 num_words_secp224r1); /* e2 <-- e2 + t1 */
17001 mg_uecc_vli_modSquare_fast(f2, e2, &curve_secp224r1); /* f2 <-- e2^2 */
17002 mg_uecc_vli_modMult_fast(f2, f2, c, &curve_secp224r1); /* f2 <-- f2 * c */
17003 /* f2 <-- p - f2 */
17004 mg_uecc_vli_modSub(f2, curve_secp224r1.p, f2, curve_secp224r1.p,
17005 num_words_secp224r1);
17006 mg_uecc_vli_set(d2, t2, num_words_secp224r1); /* d2 <-- t2 */
17007}
17008 
17009/* Routine 3.2.7 RP; from http://www.nsa.gov/ia/_files/nist-routines.pdf */
17010static void mod_sqrt_secp224r1_rp(mg_uecc_word_t *d1, mg_uecc_word_t *e1,
17011 mg_uecc_word_t *f1, const mg_uecc_word_t *c,
17012 const mg_uecc_word_t *r) {
17013 wordcount_t i;
17014 wordcount_t pow2i = 1;
17015 mg_uecc_word_t d0[num_words_secp224r1];
17016 mg_uecc_word_t e0[num_words_secp224r1] = {1}; /* e0 <-- 1 */
17017 mg_uecc_word_t f0[num_words_secp224r1];
17018 
17019 mg_uecc_vli_set(d0, r, num_words_secp224r1); /* d0 <-- r */
17020 /* f0 <-- p - c */
17021 mg_uecc_vli_modSub(f0, curve_secp224r1.p, c, curve_secp224r1.p,
17022 num_words_secp224r1);
17023 for (i = 0; i <= 6; i++) {
17024 mod_sqrt_secp224r1_rss(d1, e1, f1, d0, e0, f0,
17025 pow2i); /* RSS (d1,e1,f1,d0,e0,f0,2^i) */
17026 mod_sqrt_secp224r1_rm(d1, e1, f1, c, d1, e1, d0,
17027 e0); /* RM (d1,e1,f1,c,d1,e1,d0,e0) */
17028 mg_uecc_vli_set(d0, d1, num_words_secp224r1); /* d0 <-- d1 */
17029 mg_uecc_vli_set(e0, e1, num_words_secp224r1); /* e0 <-- e1 */
17030 mg_uecc_vli_set(f0, f1, num_words_secp224r1); /* f0 <-- f1 */
17031 pow2i *= 2;
17032 }
17033}
17034 
17035/* Compute a = sqrt(a) (mod curve_p). */
17036/* Routine 3.2.8 mp_mod_sqrt_224; from
17037 * http://www.nsa.gov/ia/_files/nist-routines.pdf */
17038static void mod_sqrt_secp224r1(mg_uecc_word_t *a, MG_UECC_Curve curve) {
17039 (void) curve;
17040 bitcount_t i;
17041 mg_uecc_word_t e1[num_words_secp224r1];
17042 mg_uecc_word_t f1[num_words_secp224r1];
17043 mg_uecc_word_t d0[num_words_secp224r1];
17044 mg_uecc_word_t e0[num_words_secp224r1];
17045 mg_uecc_word_t f0[num_words_secp224r1];
17046 mg_uecc_word_t d1[num_words_secp224r1];
17047 
17048 /* s = a; using constant instead of random value */
17049 mod_sqrt_secp224r1_rp(d0, e0, f0, a, a); /* RP (d0, e0, f0, c, s) */
17050 mod_sqrt_secp224r1_rs(d1, e1, f1, d0, e0,
17051 f0); /* RS (d1, e1, f1, d0, e0, f0) */
17052 for (i = 1; i <= 95; i++) {
17053 mg_uecc_vli_set(d0, d1, num_words_secp224r1); /* d0 <-- d1 */
17054 mg_uecc_vli_set(e0, e1, num_words_secp224r1); /* e0 <-- e1 */
17055 mg_uecc_vli_set(f0, f1, num_words_secp224r1); /* f0 <-- f1 */
17056 mod_sqrt_secp224r1_rs(d1, e1, f1, d0, e0,
17057 f0); /* RS (d1, e1, f1, d0, e0, f0) */
17058 if (mg_uecc_vli_isZero(d1, num_words_secp224r1)) { /* if d1 == 0 */
17059 break;
17060 }
17061 }
17062 mg_uecc_vli_modInv(f1, e0, curve_secp224r1.p,
17063 num_words_secp224r1); /* f1 <-- 1 / e0 */
17064 mg_uecc_vli_modMult_fast(a, d0, f1, &curve_secp224r1); /* a <-- d0 / e0 */
17065}
17066#endif /* MG_UECC_SUPPORT_COMPRESSED_POINT */
17067 
17068#if (MG_UECC_OPTIMIZATION_LEVEL > 0)
17069/* Computes result = product % curve_p
17070 from http://www.nsa.gov/ia/_files/nist-routines.pdf */
17071#if MG_UECC_WORD_SIZE == 1
17072static void vli_mmod_fast_secp224r1(uint8_t *result, uint8_t *product) {
17073 uint8_t tmp[num_words_secp224r1];
17074 int8_t carry;
17075 
17076 /* t */
17077 mg_uecc_vli_set(result, product, num_words_secp224r1);
17078 
17079 /* s1 */
17080 tmp[0] = tmp[1] = tmp[2] = tmp[3] = 0;
17081 tmp[4] = tmp[5] = tmp[6] = tmp[7] = 0;
17082 tmp[8] = tmp[9] = tmp[10] = tmp[11] = 0;
17083 tmp[12] = product[28];
17084 tmp[13] = product[29];
17085 tmp[14] = product[30];
17086 tmp[15] = product[31];
17087 tmp[16] = product[32];
17088 tmp[17] = product[33];
17089 tmp[18] = product[34];
17090 tmp[19] = product[35];
17091 tmp[20] = product[36];
17092 tmp[21] = product[37];
17093 tmp[22] = product[38];
17094 tmp[23] = product[39];
17095 tmp[24] = product[40];
17096 tmp[25] = product[41];
17097 tmp[26] = product[42];
17098 tmp[27] = product[43];
17099 carry = mg_uecc_vli_add(result, result, tmp, num_words_secp224r1);
17100 
17101 /* s2 */
17102 tmp[12] = product[44];
17103 tmp[13] = product[45];
17104 tmp[14] = product[46];
17105 tmp[15] = product[47];
17106 tmp[16] = product[48];
17107 tmp[17] = product[49];
17108 tmp[18] = product[50];
17109 tmp[19] = product[51];
17110 tmp[20] = product[52];
17111 tmp[21] = product[53];
17112 tmp[22] = product[54];
17113 tmp[23] = product[55];
17114 tmp[24] = tmp[25] = tmp[26] = tmp[27] = 0;
17115 carry += mg_uecc_vli_add(result, result, tmp, num_words_secp224r1);
17116 
17117 /* d1 */
17118 tmp[0] = product[28];
17119 tmp[1] = product[29];
17120 tmp[2] = product[30];
17121 tmp[3] = product[31];
17122 tmp[4] = product[32];
17123 tmp[5] = product[33];
17124 tmp[6] = product[34];
17125 tmp[7] = product[35];
17126 tmp[8] = product[36];
17127 tmp[9] = product[37];
17128 tmp[10] = product[38];
17129 tmp[11] = product[39];
17130 tmp[12] = product[40];
17131 tmp[13] = product[41];
17132 tmp[14] = product[42];
17133 tmp[15] = product[43];
17134 tmp[16] = product[44];
17135 tmp[17] = product[45];
17136 tmp[18] = product[46];
17137 tmp[19] = product[47];
17138 tmp[20] = product[48];
17139 tmp[21] = product[49];
17140 tmp[22] = product[50];
17141 tmp[23] = product[51];
17142 tmp[24] = product[52];
17143 tmp[25] = product[53];
17144 tmp[26] = product[54];
17145 tmp[27] = product[55];
17146 carry -= mg_uecc_vli_sub(result, result, tmp, num_words_secp224r1);
17147 
17148 /* d2 */
17149 tmp[0] = product[44];
17150 tmp[1] = product[45];
17151 tmp[2] = product[46];
17152 tmp[3] = product[47];
17153 tmp[4] = product[48];
17154 tmp[5] = product[49];
17155 tmp[6] = product[50];
17156 tmp[7] = product[51];
17157 tmp[8] = product[52];
17158 tmp[9] = product[53];
17159 tmp[10] = product[54];
17160 tmp[11] = product[55];
17161 tmp[12] = tmp[13] = tmp[14] = tmp[15] = 0;
17162 tmp[16] = tmp[17] = tmp[18] = tmp[19] = 0;
17163 tmp[20] = tmp[21] = tmp[22] = tmp[23] = 0;
17164 tmp[24] = tmp[25] = tmp[26] = tmp[27] = 0;
17165 carry -= mg_uecc_vli_sub(result, result, tmp, num_words_secp224r1);
17166 
17167 if (carry < 0) {
17168 do {
17169 carry += mg_uecc_vli_add(result, result, curve_secp224r1.p,
17170 num_words_secp224r1);
17171 } while (carry < 0);
17172 } else {
17173 while (carry || mg_uecc_vli_cmp_unsafe(curve_secp224r1.p, result,
17174 num_words_secp224r1) != 1) {
17175 carry -= mg_uecc_vli_sub(result, result, curve_secp224r1.p,
17176 num_words_secp224r1);
17177 }
17178 }
17179}
17180#elif MG_UECC_WORD_SIZE == 4
17181static void vli_mmod_fast_secp224r1(uint32_t *result, uint32_t *product) {
17182 uint32_t tmp[num_words_secp224r1];
17183 int carry;
17184 
17185 /* t */
17186 mg_uecc_vli_set(result, product, num_words_secp224r1);
17187 
17188 /* s1 */
17189 tmp[0] = tmp[1] = tmp[2] = 0;
17190 tmp[3] = product[7];
17191 tmp[4] = product[8];
17192 tmp[5] = product[9];
17193 tmp[6] = product[10];
17194 carry = mg_uecc_vli_add(result, result, tmp, num_words_secp224r1);
17195 
17196 /* s2 */
17197 tmp[3] = product[11];
17198 tmp[4] = product[12];
17199 tmp[5] = product[13];
17200 tmp[6] = 0;
17201 carry += mg_uecc_vli_add(result, result, tmp, num_words_secp224r1);
17202 
17203 /* d1 */
17204 tmp[0] = product[7];
17205 tmp[1] = product[8];
17206 tmp[2] = product[9];
17207 tmp[3] = product[10];
17208 tmp[4] = product[11];
17209 tmp[5] = product[12];
17210 tmp[6] = product[13];
17211 carry -= mg_uecc_vli_sub(result, result, tmp, num_words_secp224r1);
17212 
17213 /* d2 */
17214 tmp[0] = product[11];
17215 tmp[1] = product[12];
17216 tmp[2] = product[13];
17217 tmp[3] = tmp[4] = tmp[5] = tmp[6] = 0;
17218 carry -= mg_uecc_vli_sub(result, result, tmp, num_words_secp224r1);
17219 
17220 if (carry < 0) {
17221 do {
17222 carry += mg_uecc_vli_add(result, result, curve_secp224r1.p,
17223 num_words_secp224r1);
17224 } while (carry < 0);
17225 } else {
17226 while (carry || mg_uecc_vli_cmp_unsafe(curve_secp224r1.p, result,
17227 num_words_secp224r1) != 1) {
17228 carry -= mg_uecc_vli_sub(result, result, curve_secp224r1.p,
17229 num_words_secp224r1);
17230 }
17231 }
17232}
17233#else
17234static void vli_mmod_fast_secp224r1(uint64_t *result, uint64_t *product) {
17235 uint64_t tmp[num_words_secp224r1];
17236 int carry = 0;
17237 
17238 /* t */
17239 mg_uecc_vli_set(result, product, num_words_secp224r1);
17240 result[num_words_secp224r1 - 1] &= 0xffffffff;
17241 
17242 /* s1 */
17243 tmp[0] = 0;
17244 tmp[1] = product[3] & 0xffffffff00000000ull;
17245 tmp[2] = product[4];
17246 tmp[3] = product[5] & 0xffffffff;
17247 mg_uecc_vli_add(result, result, tmp, num_words_secp224r1);
17248 
17249 /* s2 */
17250 tmp[1] = product[5] & 0xffffffff00000000ull;
17251 tmp[2] = product[6];
17252 tmp[3] = 0;
17253 mg_uecc_vli_add(result, result, tmp, num_words_secp224r1);
17254 
17255 /* d1 */
17256 tmp[0] = (product[3] >> 32) | (product[4] << 32);
17257 tmp[1] = (product[4] >> 32) | (product[5] << 32);
17258 tmp[2] = (product[5] >> 32) | (product[6] << 32);
17259 tmp[3] = product[6] >> 32;
17260 carry -= mg_uecc_vli_sub(result, result, tmp, num_words_secp224r1);
17261 
17262 /* d2 */
17263 tmp[0] = (product[5] >> 32) | (product[6] << 32);
17264 tmp[1] = product[6] >> 32;
17265 tmp[2] = tmp[3] = 0;
17266 carry -= mg_uecc_vli_sub(result, result, tmp, num_words_secp224r1);
17267 
17268 if (carry < 0) {
17269 do {
17270 carry += mg_uecc_vli_add(result, result, curve_secp224r1.p,
17271 num_words_secp224r1);
17272 } while (carry < 0);
17273 } else {
17274 while (mg_uecc_vli_cmp_unsafe(curve_secp224r1.p, result,
17275 num_words_secp224r1) != 1) {
17276 mg_uecc_vli_sub(result, result, curve_secp224r1.p, num_words_secp224r1);
17277 }
17278 }
17279}
17280#endif /* MG_UECC_WORD_SIZE */
17281#endif /* (MG_UECC_OPTIMIZATION_LEVEL > 0) */
17282 
17283#endif /* MG_UECC_SUPPORTS_secp224r1 */
17284 
17285#if MG_UECC_SUPPORTS_secp256r1
17286 
17287#if (MG_UECC_OPTIMIZATION_LEVEL > 0)
17288static void vli_mmod_fast_secp256r1(mg_uecc_word_t *result,
17289 mg_uecc_word_t *product);
17290#endif
17291 
17292static const struct MG_UECC_Curve_t curve_secp256r1 = {
17293 num_words_secp256r1,
17294 num_bytes_secp256r1,
17295 256, /* num_n_bits */
17296 {BYTES_TO_WORDS_8(FF, FF, FF, FF, FF, FF, FF, FF),
17297 BYTES_TO_WORDS_8(FF, FF, FF, FF, 00, 00, 00, 00),
17298 BYTES_TO_WORDS_8(00, 00, 00, 00, 00, 00, 00, 00),
17299 BYTES_TO_WORDS_8(01, 00, 00, 00, FF, FF, FF, FF)},
17300 {BYTES_TO_WORDS_8(51, 25, 63, FC, C2, CA, B9, F3),
17301 BYTES_TO_WORDS_8(84, 9E, 17, A7, AD, FA, E6, BC),
17302 BYTES_TO_WORDS_8(FF, FF, FF, FF, FF, FF, FF, FF),
17303 BYTES_TO_WORDS_8(00, 00, 00, 00, FF, FF, FF, FF)},
17304 {BYTES_TO_WORDS_8(96, C2, 98, D8, 45, 39, A1, F4),
17305 BYTES_TO_WORDS_8(A0, 33, EB, 2D, 81, 7D, 03, 77),
17306 BYTES_TO_WORDS_8(F2, 40, A4, 63, E5, E6, BC, F8),
17307 BYTES_TO_WORDS_8(47, 42, 2C, E1, F2, D1, 17, 6B),
17308 
17309 BYTES_TO_WORDS_8(F5, 51, BF, 37, 68, 40, B6, CB),
17310 BYTES_TO_WORDS_8(CE, 5E, 31, 6B, 57, 33, CE, 2B),
17311 BYTES_TO_WORDS_8(16, 9E, 0F, 7C, 4A, EB, E7, 8E),
17312 BYTES_TO_WORDS_8(9B, 7F, 1A, FE, E2, 42, E3, 4F)},
17313 {BYTES_TO_WORDS_8(4B, 60, D2, 27, 3E, 3C, CE, 3B),
17314 BYTES_TO_WORDS_8(F6, B0, 53, CC, B0, 06, 1D, 65),
17315 BYTES_TO_WORDS_8(BC, 86, 98, 76, 55, BD, EB, B3),
17316 BYTES_TO_WORDS_8(E7, 93, 3A, AA, D8, 35, C6, 5A)},
17317 &double_jacobian_default,
17318#if MG_UECC_SUPPORT_COMPRESSED_POINT
17319 &mod_sqrt_default,
17320#endif
17321 &x_side_default,
17322#if (MG_UECC_OPTIMIZATION_LEVEL > 0)
17323 &vli_mmod_fast_secp256r1
17324#endif
17325};
17326 
17327MG_UECC_Curve mg_uecc_secp256r1(void) {
17328 return &curve_secp256r1;
17329}
17330 
17331#if (MG_UECC_OPTIMIZATION_LEVEL > 0 && !asm_mmod_fast_secp256r1)
17332/* Computes result = product % curve_p
17333 from http://www.nsa.gov/ia/_files/nist-routines.pdf */
17334#if MG_UECC_WORD_SIZE == 1
17335static void vli_mmod_fast_secp256r1(uint8_t *result, uint8_t *product) {
17336 uint8_t tmp[num_words_secp256r1];
17337 int8_t carry;
17338 
17339 /* t */
17340 mg_uecc_vli_set(result, product, num_words_secp256r1);
17341 
17342 /* s1 */
17343 tmp[0] = tmp[1] = tmp[2] = tmp[3] = 0;
17344 tmp[4] = tmp[5] = tmp[6] = tmp[7] = 0;
17345 tmp[8] = tmp[9] = tmp[10] = tmp[11] = 0;
17346 tmp[12] = product[44];
17347 tmp[13] = product[45];
17348 tmp[14] = product[46];
17349 tmp[15] = product[47];
17350 tmp[16] = product[48];
17351 tmp[17] = product[49];
17352 tmp[18] = product[50];
17353 tmp[19] = product[51];
17354 tmp[20] = product[52];
17355 tmp[21] = product[53];
17356 tmp[22] = product[54];
17357 tmp[23] = product[55];
17358 tmp[24] = product[56];
17359 tmp[25] = product[57];
17360 tmp[26] = product[58];
17361 tmp[27] = product[59];
17362 tmp[28] = product[60];
17363 tmp[29] = product[61];
17364 tmp[30] = product[62];
17365 tmp[31] = product[63];
17366 carry = mg_uecc_vli_add(tmp, tmp, tmp, num_words_secp256r1);
17367 carry += mg_uecc_vli_add(result, result, tmp, num_words_secp256r1);
17368 
17369 /* s2 */
17370 tmp[12] = product[48];
17371 tmp[13] = product[49];
17372 tmp[14] = product[50];
17373 tmp[15] = product[51];
17374 tmp[16] = product[52];
17375 tmp[17] = product[53];
17376 tmp[18] = product[54];
17377 tmp[19] = product[55];
17378 tmp[20] = product[56];
17379 tmp[21] = product[57];
17380 tmp[22] = product[58];
17381 tmp[23] = product[59];
17382 tmp[24] = product[60];
17383 tmp[25] = product[61];
17384 tmp[26] = product[62];
17385 tmp[27] = product[63];
17386 tmp[28] = tmp[29] = tmp[30] = tmp[31] = 0;
17387 carry += mg_uecc_vli_add(tmp, tmp, tmp, num_words_secp256r1);
17388 carry += mg_uecc_vli_add(result, result, tmp, num_words_secp256r1);
17389 
17390 /* s3 */
17391 tmp[0] = product[32];
17392 tmp[1] = product[33];
17393 tmp[2] = product[34];
17394 tmp[3] = product[35];
17395 tmp[4] = product[36];
17396 tmp[5] = product[37];
17397 tmp[6] = product[38];
17398 tmp[7] = product[39];
17399 tmp[8] = product[40];
17400 tmp[9] = product[41];
17401 tmp[10] = product[42];
17402 tmp[11] = product[43];
17403 tmp[12] = tmp[13] = tmp[14] = tmp[15] = 0;
17404 tmp[16] = tmp[17] = tmp[18] = tmp[19] = 0;
17405 tmp[20] = tmp[21] = tmp[22] = tmp[23] = 0;
17406 tmp[24] = product[56];
17407 tmp[25] = product[57];
17408 tmp[26] = product[58];
17409 tmp[27] = product[59];
17410 tmp[28] = product[60];
17411 tmp[29] = product[61];
17412 tmp[30] = product[62];
17413 tmp[31] = product[63];
17414 carry += mg_uecc_vli_add(result, result, tmp, num_words_secp256r1);
17415 
17416 /* s4 */
17417 tmp[0] = product[36];
17418 tmp[1] = product[37];
17419 tmp[2] = product[38];
17420 tmp[3] = product[39];
17421 tmp[4] = product[40];
17422 tmp[5] = product[41];
17423 tmp[6] = product[42];
17424 tmp[7] = product[43];
17425 tmp[8] = product[44];
17426 tmp[9] = product[45];
17427 tmp[10] = product[46];
17428 tmp[11] = product[47];
17429 tmp[12] = product[52];
17430 tmp[13] = product[53];
17431 tmp[14] = product[54];
17432 tmp[15] = product[55];
17433 tmp[16] = product[56];
17434 tmp[17] = product[57];
17435 tmp[18] = product[58];
17436 tmp[19] = product[59];
17437 tmp[20] = product[60];
17438 tmp[21] = product[61];
17439 tmp[22] = product[62];
17440 tmp[23] = product[63];
17441 tmp[24] = product[52];
17442 tmp[25] = product[53];
17443 tmp[26] = product[54];
17444 tmp[27] = product[55];
17445 tmp[28] = product[32];
17446 tmp[29] = product[33];
17447 tmp[30] = product[34];
17448 tmp[31] = product[35];
17449 carry += mg_uecc_vli_add(result, result, tmp, num_words_secp256r1);
17450 
17451 /* d1 */
17452 tmp[0] = product[44];
17453 tmp[1] = product[45];
17454 tmp[2] = product[46];
17455 tmp[3] = product[47];
17456 tmp[4] = product[48];
17457 tmp[5] = product[49];
17458 tmp[6] = product[50];
17459 tmp[7] = product[51];
17460 tmp[8] = product[52];
17461 tmp[9] = product[53];
17462 tmp[10] = product[54];
17463 tmp[11] = product[55];
17464 tmp[12] = tmp[13] = tmp[14] = tmp[15] = 0;
17465 tmp[16] = tmp[17] = tmp[18] = tmp[19] = 0;
17466 tmp[20] = tmp[21] = tmp[22] = tmp[23] = 0;
17467 tmp[24] = product[32];
17468 tmp[25] = product[33];
17469 tmp[26] = product[34];
17470 tmp[27] = product[35];
17471 tmp[28] = product[40];
17472 tmp[29] = product[41];
17473 tmp[30] = product[42];
17474 tmp[31] = product[43];
17475 carry -= mg_uecc_vli_sub(result, result, tmp, num_words_secp256r1);
17476 
17477 /* d2 */
17478 tmp[0] = product[48];
17479 tmp[1] = product[49];
17480 tmp[2] = product[50];
17481 tmp[3] = product[51];
17482 tmp[4] = product[52];
17483 tmp[5] = product[53];
17484 tmp[6] = product[54];
17485 tmp[7] = product[55];
17486 tmp[8] = product[56];
17487 tmp[9] = product[57];
17488 tmp[10] = product[58];
17489 tmp[11] = product[59];
17490 tmp[12] = product[60];
17491 tmp[13] = product[61];
17492 tmp[14] = product[62];
17493 tmp[15] = product[63];
17494 tmp[16] = tmp[17] = tmp[18] = tmp[19] = 0;
17495 tmp[20] = tmp[21] = tmp[22] = tmp[23] = 0;
17496 tmp[24] = product[36];
17497 tmp[25] = product[37];
17498 tmp[26] = product[38];
17499 tmp[27] = product[39];
17500 tmp[28] = product[44];
17501 tmp[29] = product[45];
17502 tmp[30] = product[46];
17503 tmp[31] = product[47];
17504 carry -= mg_uecc_vli_sub(result, result, tmp, num_words_secp256r1);
17505 
17506 /* d3 */
17507 tmp[0] = product[52];
17508 tmp[1] = product[53];
17509 tmp[2] = product[54];
17510 tmp[3] = product[55];
17511 tmp[4] = product[56];
17512 tmp[5] = product[57];
17513 tmp[6] = product[58];
17514 tmp[7] = product[59];
17515 tmp[8] = product[60];
17516 tmp[9] = product[61];
17517 tmp[10] = product[62];
17518 tmp[11] = product[63];
17519 tmp[12] = product[32];
17520 tmp[13] = product[33];
17521 tmp[14] = product[34];
17522 tmp[15] = product[35];
17523 tmp[16] = product[36];
17524 tmp[17] = product[37];
17525 tmp[18] = product[38];
17526 tmp[19] = product[39];
17527 tmp[20] = product[40];
17528 tmp[21] = product[41];
17529 tmp[22] = product[42];
17530 tmp[23] = product[43];
17531 tmp[24] = tmp[25] = tmp[26] = tmp[27] = 0;
17532 tmp[28] = product[48];
17533 tmp[29] = product[49];
17534 tmp[30] = product[50];
17535 tmp[31] = product[51];
17536 carry -= mg_uecc_vli_sub(result, result, tmp, num_words_secp256r1);
17537 
17538 /* d4 */
17539 tmp[0] = product[56];
17540 tmp[1] = product[57];
17541 tmp[2] = product[58];
17542 tmp[3] = product[59];
17543 tmp[4] = product[60];
17544 tmp[5] = product[61];
17545 tmp[6] = product[62];
17546 tmp[7] = product[63];
17547 tmp[8] = tmp[9] = tmp[10] = tmp[11] = 0;
17548 tmp[12] = product[36];
17549 tmp[13] = product[37];
17550 tmp[14] = product[38];
17551 tmp[15] = product[39];
17552 tmp[16] = product[40];
17553 tmp[17] = product[41];
17554 tmp[18] = product[42];
17555 tmp[19] = product[43];
17556 tmp[20] = product[44];
17557 tmp[21] = product[45];
17558 tmp[22] = product[46];
17559 tmp[23] = product[47];
17560 tmp[24] = tmp[25] = tmp[26] = tmp[27] = 0;
17561 tmp[28] = product[52];
17562 tmp[29] = product[53];
17563 tmp[30] = product[54];
17564 tmp[31] = product[55];
17565 carry -= mg_uecc_vli_sub(result, result, tmp, num_words_secp256r1);
17566 
17567 if (carry < 0) {
17568 do {
17569 carry += mg_uecc_vli_add(result, result, curve_secp256r1.p,
17570 num_words_secp256r1);
17571 } while (carry < 0);
17572 } else {
17573 while (carry || mg_uecc_vli_cmp_unsafe(curve_secp256r1.p, result,
17574 num_words_secp256r1) != 1) {
17575 carry -= mg_uecc_vli_sub(result, result, curve_secp256r1.p,
17576 num_words_secp256r1);
17577 }
17578 }
17579}
17580#elif MG_UECC_WORD_SIZE == 4
17581static void vli_mmod_fast_secp256r1(uint32_t *result, uint32_t *product) {
17582 uint32_t tmp[num_words_secp256r1];
17583 int carry;
17584 
17585 /* t */
17586 mg_uecc_vli_set(result, product, num_words_secp256r1);
17587 
17588 /* s1 */
17589 tmp[0] = tmp[1] = tmp[2] = 0;
17590 tmp[3] = product[11];
17591 tmp[4] = product[12];
17592 tmp[5] = product[13];
17593 tmp[6] = product[14];
17594 tmp[7] = product[15];
17595 carry = (int) mg_uecc_vli_add(tmp, tmp, tmp, num_words_secp256r1);
17596 carry += (int) mg_uecc_vli_add(result, result, tmp, num_words_secp256r1);
17597 
17598 /* s2 */
17599 tmp[3] = product[12];
17600 tmp[4] = product[13];
17601 tmp[5] = product[14];
17602 tmp[6] = product[15];
17603 tmp[7] = 0;
17604 carry += (int) mg_uecc_vli_add(tmp, tmp, tmp, num_words_secp256r1);
17605 carry += (int) mg_uecc_vli_add(result, result, tmp, num_words_secp256r1);
17606 
17607 /* s3 */
17608 tmp[0] = product[8];
17609 tmp[1] = product[9];
17610 tmp[2] = product[10];
17611 tmp[3] = tmp[4] = tmp[5] = 0;
17612 tmp[6] = product[14];
17613 tmp[7] = product[15];
17614 carry += (int) mg_uecc_vli_add(result, result, tmp, num_words_secp256r1);
17615 
17616 /* s4 */
17617 tmp[0] = product[9];
17618 tmp[1] = product[10];
17619 tmp[2] = product[11];
17620 tmp[3] = product[13];
17621 tmp[4] = product[14];
17622 tmp[5] = product[15];
17623 tmp[6] = product[13];
17624 tmp[7] = product[8];
17625 carry += (int) mg_uecc_vli_add(result, result, tmp, num_words_secp256r1);
17626 
17627 /* d1 */
17628 tmp[0] = product[11];
17629 tmp[1] = product[12];
17630 tmp[2] = product[13];
17631 tmp[3] = tmp[4] = tmp[5] = 0;
17632 tmp[6] = product[8];
17633 tmp[7] = product[10];
17634 carry -= (int) mg_uecc_vli_sub(result, result, tmp, num_words_secp256r1);
17635 
17636 /* d2 */
17637 tmp[0] = product[12];
17638 tmp[1] = product[13];
17639 tmp[2] = product[14];
17640 tmp[3] = product[15];
17641 tmp[4] = tmp[5] = 0;
17642 tmp[6] = product[9];
17643 tmp[7] = product[11];
17644 carry -= (int) mg_uecc_vli_sub(result, result, tmp, num_words_secp256r1);
17645 
17646 /* d3 */
17647 tmp[0] = product[13];
17648 tmp[1] = product[14];
17649 tmp[2] = product[15];
17650 tmp[3] = product[8];
17651 tmp[4] = product[9];
17652 tmp[5] = product[10];
17653 tmp[6] = 0;
17654 tmp[7] = product[12];
17655 carry -= (int) mg_uecc_vli_sub(result, result, tmp, num_words_secp256r1);
17656 
17657 /* d4 */
17658 tmp[0] = product[14];
17659 tmp[1] = product[15];
17660 tmp[2] = 0;
17661 tmp[3] = product[9];
17662 tmp[4] = product[10];
17663 tmp[5] = product[11];
17664 tmp[6] = 0;
17665 tmp[7] = product[13];
17666 carry -= (int) mg_uecc_vli_sub(result, result, tmp, num_words_secp256r1);
17667 
17668 if (carry < 0) {
17669 do {
17670 carry += (int) mg_uecc_vli_add(result, result, curve_secp256r1.p,
17671 num_words_secp256r1);
17672 } while (carry < 0);
17673 } else {
17674 while (carry || mg_uecc_vli_cmp_unsafe(curve_secp256r1.p, result,
17675 num_words_secp256r1) != 1) {
17676 carry -= (int) mg_uecc_vli_sub(result, result, curve_secp256r1.p,
17677 num_words_secp256r1);
17678 }
17679 }
17680}
17681#else
17682static void vli_mmod_fast_secp256r1(uint64_t *result, uint64_t *product) {
17683 uint64_t tmp[num_words_secp256r1];
17684 int carry;
17685 
17686 /* t */
17687 mg_uecc_vli_set(result, product, num_words_secp256r1);
17688 
17689 /* s1 */
17690 tmp[0] = 0;
17691 tmp[1] = product[5] & 0xffffffff00000000U;
17692 tmp[2] = product[6];
17693 tmp[3] = product[7];
17694 carry = (int) mg_uecc_vli_add(tmp, tmp, tmp, num_words_secp256r1);
17695 carry += (int) mg_uecc_vli_add(result, result, tmp, num_words_secp256r1);
17696 
17697 /* s2 */
17698 tmp[1] = product[6] << 32;
17699 tmp[2] = (product[6] >> 32) | (product[7] << 32);
17700 tmp[3] = product[7] >> 32;
17701 carry += (int) mg_uecc_vli_add(tmp, tmp, tmp, num_words_secp256r1);
17702 carry += (int) mg_uecc_vli_add(result, result, tmp, num_words_secp256r1);
17703 
17704 /* s3 */
17705 tmp[0] = product[4];
17706 tmp[1] = product[5] & 0xffffffff;
17707 tmp[2] = 0;
17708 tmp[3] = product[7];
17709 carry += (int) mg_uecc_vli_add(result, result, tmp, num_words_secp256r1);
17710 
17711 /* s4 */
17712 tmp[0] = (product[4] >> 32) | (product[5] << 32);
17713 tmp[1] = (product[5] >> 32) | (product[6] & 0xffffffff00000000U);
17714 tmp[2] = product[7];
17715 tmp[3] = (product[6] >> 32) | (product[4] << 32);
17716 carry += (int) mg_uecc_vli_add(result, result, tmp, num_words_secp256r1);
17717 
17718 /* d1 */
17719 tmp[0] = (product[5] >> 32) | (product[6] << 32);
17720 tmp[1] = (product[6] >> 32);
17721 tmp[2] = 0;
17722 tmp[3] = (product[4] & 0xffffffff) | (product[5] << 32);
17723 carry -= (int) mg_uecc_vli_sub(result, result, tmp, num_words_secp256r1);
17724 
17725 /* d2 */
17726 tmp[0] = product[6];
17727 tmp[1] = product[7];
17728 tmp[2] = 0;
17729 tmp[3] = (product[4] >> 32) | (product[5] & 0xffffffff00000000);
17730 carry -= (int) mg_uecc_vli_sub(result, result, tmp, num_words_secp256r1);
17731 
17732 /* d3 */
17733 tmp[0] = (product[6] >> 32) | (product[7] << 32);
17734 tmp[1] = (product[7] >> 32) | (product[4] << 32);
17735 tmp[2] = (product[4] >> 32) | (product[5] << 32);
17736 tmp[3] = (product[6] << 32);
17737 carry -= (int) mg_uecc_vli_sub(result, result, tmp, num_words_secp256r1);
17738 
17739 /* d4 */
17740 tmp[0] = product[7];
17741 tmp[1] = product[4] & 0xffffffff00000000U;
17742 tmp[2] = product[5];
17743 tmp[3] = product[6] & 0xffffffff00000000U;
17744 carry -= (int) mg_uecc_vli_sub(result, result, tmp, num_words_secp256r1);
17745 
17746 if (carry < 0) {
17747 do {
17748 carry += (int) mg_uecc_vli_add(result, result, curve_secp256r1.p,
17749 num_words_secp256r1);
17750 } while (carry < 0);
17751 } else {
17752 while (carry || mg_uecc_vli_cmp_unsafe(curve_secp256r1.p, result,
17753 num_words_secp256r1) != 1) {
17754 carry -= (int) mg_uecc_vli_sub(result, result, curve_secp256r1.p,
17755 num_words_secp256r1);
17756 }
17757 }
17758}
17759#endif /* MG_UECC_WORD_SIZE */
17760#endif /* (MG_UECC_OPTIMIZATION_LEVEL > 0 && !asm_mmod_fast_secp256r1) */
17761 
17762#endif /* MG_UECC_SUPPORTS_secp256r1 */
17763 
17764#if MG_UECC_SUPPORTS_secp256k1
17765 
17766static void double_jacobian_secp256k1(mg_uecc_word_t *X1, mg_uecc_word_t *Y1,
17767 mg_uecc_word_t *Z1, MG_UECC_Curve curve);
17768static void x_side_secp256k1(mg_uecc_word_t *result, const mg_uecc_word_t *x,
17769 MG_UECC_Curve curve);
17770#if (MG_UECC_OPTIMIZATION_LEVEL > 0)
17771static void vli_mmod_fast_secp256k1(mg_uecc_word_t *result,
17772 mg_uecc_word_t *product);
17773#endif
17774 
17775static const struct MG_UECC_Curve_t curve_secp256k1 = {
17776 num_words_secp256k1,
17777 num_bytes_secp256k1,
17778 256, /* num_n_bits */
17779 {BYTES_TO_WORDS_8(2F, FC, FF, FF, FE, FF, FF, FF),
17780 BYTES_TO_WORDS_8(FF, FF, FF, FF, FF, FF, FF, FF),
17781 BYTES_TO_WORDS_8(FF, FF, FF, FF, FF, FF, FF, FF),
17782 BYTES_TO_WORDS_8(FF, FF, FF, FF, FF, FF, FF, FF)},
17783 {BYTES_TO_WORDS_8(41, 41, 36, D0, 8C, 5E, D2, BF),
17784 BYTES_TO_WORDS_8(3B, A0, 48, AF, E6, DC, AE, BA),
17785 BYTES_TO_WORDS_8(FE, FF, FF, FF, FF, FF, FF, FF),
17786 BYTES_TO_WORDS_8(FF, FF, FF, FF, FF, FF, FF, FF)},
17787 {BYTES_TO_WORDS_8(98, 17, F8, 16, 5B, 81, F2, 59),
17788 BYTES_TO_WORDS_8(D9, 28, CE, 2D, DB, FC, 9B, 02),
17789 BYTES_TO_WORDS_8(07, 0B, 87, CE, 95, 62, A0, 55),
17790 BYTES_TO_WORDS_8(AC, BB, DC, F9, 7E, 66, BE, 79),
17791 
17792 BYTES_TO_WORDS_8(B8, D4, 10, FB, 8F, D0, 47, 9C),
17793 BYTES_TO_WORDS_8(19, 54, 85, A6, 48, B4, 17, FD),
17794 BYTES_TO_WORDS_8(A8, 08, 11, 0E, FC, FB, A4, 5D),
17795 BYTES_TO_WORDS_8(65, C4, A3, 26, 77, DA, 3A, 48)},
17796 {BYTES_TO_WORDS_8(07, 00, 00, 00, 00, 00, 00, 00),
17797 BYTES_TO_WORDS_8(00, 00, 00, 00, 00, 00, 00, 00),
17798 BYTES_TO_WORDS_8(00, 00, 00, 00, 00, 00, 00, 00),
17799 BYTES_TO_WORDS_8(00, 00, 00, 00, 00, 00, 00, 00)},
17800 &double_jacobian_secp256k1,
17801#if MG_UECC_SUPPORT_COMPRESSED_POINT
17802 &mod_sqrt_default,
17803#endif
17804 &x_side_secp256k1,
17805#if (MG_UECC_OPTIMIZATION_LEVEL > 0)
17806 &vli_mmod_fast_secp256k1
17807#endif
17808};
17809 
17810MG_UECC_Curve mg_uecc_secp256k1(void) {
17811 return &curve_secp256k1;
17812}
17813 
17814/* Double in place */
17815static void double_jacobian_secp256k1(mg_uecc_word_t *X1, mg_uecc_word_t *Y1,
17816 mg_uecc_word_t *Z1, MG_UECC_Curve curve) {
17817 /* t1 = X, t2 = Y, t3 = Z */
17818 mg_uecc_word_t t4[num_words_secp256k1];
17819 mg_uecc_word_t t5[num_words_secp256k1];
17820 
17821 if (mg_uecc_vli_isZero(Z1, num_words_secp256k1)) {
17822 return;
17823 }
17824 
17825 mg_uecc_vli_modSquare_fast(t5, Y1, curve); /* t5 = y1^2 */
17826 mg_uecc_vli_modMult_fast(t4, X1, t5, curve); /* t4 = x1*y1^2 = A */
17827 mg_uecc_vli_modSquare_fast(X1, X1, curve); /* t1 = x1^2 */
17828 mg_uecc_vli_modSquare_fast(t5, t5, curve); /* t5 = y1^4 */
17829 mg_uecc_vli_modMult_fast(Z1, Y1, Z1, curve); /* t3 = y1*z1 = z3 */
17830 
17831 mg_uecc_vli_modAdd(Y1, X1, X1, curve->p,
17832 num_words_secp256k1); /* t2 = 2*x1^2 */
17833 mg_uecc_vli_modAdd(Y1, Y1, X1, curve->p,
17834 num_words_secp256k1); /* t2 = 3*x1^2 */
17835 if (mg_uecc_vli_testBit(Y1, 0)) {
17836 mg_uecc_word_t carry =
17837 mg_uecc_vli_add(Y1, Y1, curve->p, num_words_secp256k1);
17838 mg_uecc_vli_rshift1(Y1, num_words_secp256k1);
17839 Y1[num_words_secp256k1 - 1] |= carry << (MG_UECC_WORD_BITS - 1);
17840 } else {
17841 mg_uecc_vli_rshift1(Y1, num_words_secp256k1);
17842 }
17843 /* t2 = 3/2*(x1^2) = B */
17844 
17845 mg_uecc_vli_modSquare_fast(X1, Y1, curve); /* t1 = B^2 */
17846 mg_uecc_vli_modSub(X1, X1, t4, curve->p,
17847 num_words_secp256k1); /* t1 = B^2 - A */
17848 mg_uecc_vli_modSub(X1, X1, t4, curve->p,
17849 num_words_secp256k1); /* t1 = B^2 - 2A = x3 */
17850 
17851 mg_uecc_vli_modSub(t4, t4, X1, curve->p,
17852 num_words_secp256k1); /* t4 = A - x3 */
17853 mg_uecc_vli_modMult_fast(Y1, Y1, t4, curve); /* t2 = B * (A - x3) */
17854 mg_uecc_vli_modSub(Y1, Y1, t5, curve->p,
17855 num_words_secp256k1); /* t2 = B * (A - x3) - y1^4 = y3 */
17856}
17857 
17858/* Computes result = x^3 + b. result must not overlap x. */
17859static void x_side_secp256k1(mg_uecc_word_t *result, const mg_uecc_word_t *x,
17860 MG_UECC_Curve curve) {
17861 mg_uecc_vli_modSquare_fast(result, x, curve); /* r = x^2 */
17862 mg_uecc_vli_modMult_fast(result, result, x, curve); /* r = x^3 */
17863 mg_uecc_vli_modAdd(result, result, curve->b, curve->p,
17864 num_words_secp256k1); /* r = x^3 + b */
17865}
17866 
17867#if (MG_UECC_OPTIMIZATION_LEVEL > 0 && !asm_mmod_fast_secp256k1)
17868static void omega_mult_secp256k1(mg_uecc_word_t *result,
17869 const mg_uecc_word_t *right);
17870static void vli_mmod_fast_secp256k1(mg_uecc_word_t *result,
17871 mg_uecc_word_t *product) {
17872 mg_uecc_word_t tmp[2 * num_words_secp256k1];
17873 mg_uecc_word_t carry;
17874 
17875 mg_uecc_vli_clear(tmp, num_words_secp256k1);
17876 mg_uecc_vli_clear(tmp + num_words_secp256k1, num_words_secp256k1);
17877 
17878 omega_mult_secp256k1(tmp,
17879 product + num_words_secp256k1); /* (Rq, q) = q * c */
17880 
17881 carry = mg_uecc_vli_add(result, product, tmp,
17882 num_words_secp256k1); /* (C, r) = r + q */
17883 mg_uecc_vli_clear(product, num_words_secp256k1);
17884 omega_mult_secp256k1(product, tmp + num_words_secp256k1); /* Rq*c */
17885 carry += mg_uecc_vli_add(result, result, product,
17886 num_words_secp256k1); /* (C1, r) = r + Rq*c */
17887 
17888 while (carry > 0) {
17889 --carry;
17890 mg_uecc_vli_sub(result, result, curve_secp256k1.p, num_words_secp256k1);
17891 }
17892 if (mg_uecc_vli_cmp_unsafe(result, curve_secp256k1.p, num_words_secp256k1) >
17893 0) {
17894 mg_uecc_vli_sub(result, result, curve_secp256k1.p, num_words_secp256k1);
17895 }
17896}
17897 
17898#if MG_UECC_WORD_SIZE == 1
17899static void omega_mult_secp256k1(uint8_t *result, const uint8_t *right) {
17900 /* Multiply by (2^32 + 2^9 + 2^8 + 2^7 + 2^6 + 2^4 + 1). */
17901 mg_uecc_word_t r0 = 0;
17902 mg_uecc_word_t r1 = 0;
17903 mg_uecc_word_t r2 = 0;
17904 wordcount_t k;
17905 
17906 /* Multiply by (2^9 + 2^8 + 2^7 + 2^6 + 2^4 + 1). */
17907 muladd(0xD1, right[0], &r0, &r1, &r2);
17908 result[0] = r0;
17909 r0 = r1;
17910 r1 = r2;
17911 /* r2 is still 0 */
17912 
17913 for (k = 1; k < num_words_secp256k1; ++k) {
17914 muladd(0x03, right[k - 1], &r0, &r1, &r2);
17915 muladd(0xD1, right[k], &r0, &r1, &r2);
17916 result[k] = r0;
17917 r0 = r1;
17918 r1 = r2;
17919 r2 = 0;
17920 }
17921 muladd(0x03, right[num_words_secp256k1 - 1], &r0, &r1, &r2);
17922 result[num_words_secp256k1] = r0;
17923 result[num_words_secp256k1 + 1] = r1;
17924 /* add the 2^32 multiple */
17925 result[4 + num_words_secp256k1] =
17926 mg_uecc_vli_add(result + 4, result + 4, right, num_words_secp256k1);
17927}
17928#elif MG_UECC_WORD_SIZE == 4
17929static void omega_mult_secp256k1(uint32_t *result, const uint32_t *right) {
17930 /* Multiply by (2^9 + 2^8 + 2^7 + 2^6 + 2^4 + 1). */
17931 uint32_t carry = 0;
17932 wordcount_t k;
17933 
17934 for (k = 0; k < num_words_secp256k1; ++k) {
17935 uint64_t p = (uint64_t) 0x3D1 * right[k] + carry;
17936 result[k] = (uint32_t) p;
17937 carry = p >> 32;
17938 }
17939 result[num_words_secp256k1] = carry;
17940 /* add the 2^32 multiple */
17941 result[1 + num_words_secp256k1] =
17942 mg_uecc_vli_add(result + 1, result + 1, right, num_words_secp256k1);
17943}
17944#else
17945static void omega_mult_secp256k1(uint64_t *result, const uint64_t *right) {
17946 mg_uecc_word_t r0 = 0;
17947 mg_uecc_word_t r1 = 0;
17948 mg_uecc_word_t r2 = 0;
17949 wordcount_t k;
17950 
17951 /* Multiply by (2^32 + 2^9 + 2^8 + 2^7 + 2^6 + 2^4 + 1). */
17952 for (k = 0; k < num_words_secp256k1; ++k) {
17953 muladd(0x1000003D1ull, right[k], &r0, &r1, &r2);
17954 result[k] = r0;
17955 r0 = r1;
17956 r1 = r2;
17957 r2 = 0;
17958 }
17959 result[num_words_secp256k1] = r0;
17960}
17961#endif /* MG_UECC_WORD_SIZE */
17962#endif /* (MG_UECC_OPTIMIZATION_LEVEL > 0 && && !asm_mmod_fast_secp256k1) */
17963 
17964#endif /* MG_UECC_SUPPORTS_secp256k1 */
17965 
17966#endif /* _UECC_CURVE_SPECIFIC_H_ */
17967 
17968/* Returns 1 if 'point' is the point at infinity, 0 otherwise. */
17969#define EccPoint_isZero(point, curve) \
17970 mg_uecc_vli_isZero((point), (wordcount_t) ((curve)->num_words * 2))
17971 
17972/* Point multiplication algorithm using Montgomery's ladder with co-Z
17973coordinates. From http://eprint.iacr.org/2011/338.pdf
17974*/
17975 
17976/* Modify (x1, y1) => (x1 * z^2, y1 * z^3) */
17977static void apply_z(mg_uecc_word_t *X1, mg_uecc_word_t *Y1,
17978 const mg_uecc_word_t *const Z, MG_UECC_Curve curve) {
17979 mg_uecc_word_t t1[MG_UECC_MAX_WORDS];
17980 
17981 mg_uecc_vli_modSquare_fast(t1, Z, curve); /* z^2 */
17982 mg_uecc_vli_modMult_fast(X1, X1, t1, curve); /* x1 * z^2 */
17983 mg_uecc_vli_modMult_fast(t1, t1, Z, curve); /* z^3 */
17984 mg_uecc_vli_modMult_fast(Y1, Y1, t1, curve); /* y1 * z^3 */
17985}
17986 
17987/* P = (x1, y1) => 2P, (x2, y2) => P' */
17988static void XYcZ_initial_double(mg_uecc_word_t *X1, mg_uecc_word_t *Y1,
17989 mg_uecc_word_t *X2, mg_uecc_word_t *Y2,
17990 const mg_uecc_word_t *const initial_Z,
17991 MG_UECC_Curve curve) {
17992 mg_uecc_word_t z[MG_UECC_MAX_WORDS];
17993 wordcount_t num_words = curve->num_words;
17994 if (initial_Z) {
17995 mg_uecc_vli_set(z, initial_Z, num_words);
17996 } else {
17997 mg_uecc_vli_clear(z, num_words);
17998 z[0] = 1;
17999 }
18000 
18001 mg_uecc_vli_set(X2, X1, num_words);
18002 mg_uecc_vli_set(Y2, Y1, num_words);
18003 
18004 apply_z(X1, Y1, z, curve);
18005 curve->double_jacobian(X1, Y1, z, curve);
18006 apply_z(X2, Y2, z, curve);
18007}
18008 
18009/* Input P = (x1, y1, Z), Q = (x2, y2, Z)
18010 Output P' = (x1', y1', Z3), P + Q = (x3, y3, Z3)
18011 or P => P', Q => P + Q
18012*/
18013static void XYcZ_add(mg_uecc_word_t *X1, mg_uecc_word_t *Y1, mg_uecc_word_t *X2,
18014 mg_uecc_word_t *Y2, MG_UECC_Curve curve) {
18015 /* t1 = X1, t2 = Y1, t3 = X2, t4 = Y2 */
18016 mg_uecc_word_t t5[MG_UECC_MAX_WORDS] = {0};
18017 wordcount_t num_words = curve->num_words;
18018 
18019 mg_uecc_vli_modSub(t5, X2, X1, curve->p, num_words); /* t5 = x2 - x1 */
18020 mg_uecc_vli_modSquare_fast(t5, t5, curve); /* t5 = (x2 - x1)^2 = A */
18021 mg_uecc_vli_modMult_fast(X1, X1, t5, curve); /* t1 = x1*A = B */
18022 mg_uecc_vli_modMult_fast(X2, X2, t5, curve); /* t3 = x2*A = C */
18023 mg_uecc_vli_modSub(Y2, Y2, Y1, curve->p, num_words); /* t4 = y2 - y1 */
18024 mg_uecc_vli_modSquare_fast(t5, Y2, curve); /* t5 = (y2 - y1)^2 = D */
18025 
18026 mg_uecc_vli_modSub(t5, t5, X1, curve->p, num_words); /* t5 = D - B */
18027 mg_uecc_vli_modSub(t5, t5, X2, curve->p, num_words); /* t5 = D - B - C = x3 */
18028 mg_uecc_vli_modSub(X2, X2, X1, curve->p, num_words); /* t3 = C - B */
18029 mg_uecc_vli_modMult_fast(Y1, Y1, X2, curve); /* t2 = y1*(C - B) */
18030 mg_uecc_vli_modSub(X2, X1, t5, curve->p, num_words); /* t3 = B - x3 */
18031 mg_uecc_vli_modMult_fast(Y2, Y2, X2, curve); /* t4 = (y2 - y1)*(B - x3) */
18032 mg_uecc_vli_modSub(Y2, Y2, Y1, curve->p, num_words); /* t4 = y3 */
18033 
18034 mg_uecc_vli_set(X2, t5, num_words);
18035}
18036 
18037/* Input P = (x1, y1, Z), Q = (x2, y2, Z)
18038 Output P + Q = (x3, y3, Z3), P - Q = (x3', y3', Z3)
18039 or P => P - Q, Q => P + Q
18040*/
18041static void XYcZ_addC(mg_uecc_word_t *X1, mg_uecc_word_t *Y1,
18042 mg_uecc_word_t *X2, mg_uecc_word_t *Y2,
18043 MG_UECC_Curve curve) {
18044 /* t1 = X1, t2 = Y1, t3 = X2, t4 = Y2 */
18045 mg_uecc_word_t t5[MG_UECC_MAX_WORDS] = {0};
18046 mg_uecc_word_t t6[MG_UECC_MAX_WORDS];
18047 mg_uecc_word_t t7[MG_UECC_MAX_WORDS];
18048 wordcount_t num_words = curve->num_words;
18049 
18050 mg_uecc_vli_modSub(t5, X2, X1, curve->p, num_words); /* t5 = x2 - x1 */
18051 mg_uecc_vli_modSquare_fast(t5, t5, curve); /* t5 = (x2 - x1)^2 = A */
18052 mg_uecc_vli_modMult_fast(X1, X1, t5, curve); /* t1 = x1*A = B */
18053 mg_uecc_vli_modMult_fast(X2, X2, t5, curve); /* t3 = x2*A = C */
18054 mg_uecc_vli_modAdd(t5, Y2, Y1, curve->p, num_words); /* t5 = y2 + y1 */
18055 mg_uecc_vli_modSub(Y2, Y2, Y1, curve->p, num_words); /* t4 = y2 - y1 */
18056 
18057 mg_uecc_vli_modSub(t6, X2, X1, curve->p, num_words); /* t6 = C - B */
18058 mg_uecc_vli_modMult_fast(Y1, Y1, t6, curve); /* t2 = y1 * (C - B) = E */
18059 mg_uecc_vli_modAdd(t6, X1, X2, curve->p, num_words); /* t6 = B + C */
18060 mg_uecc_vli_modSquare_fast(X2, Y2, curve); /* t3 = (y2 - y1)^2 = D */
18061 mg_uecc_vli_modSub(X2, X2, t6, curve->p,
18062 num_words); /* t3 = D - (B + C) = x3 */
18063 
18064 mg_uecc_vli_modSub(t7, X1, X2, curve->p, num_words); /* t7 = B - x3 */
18065 mg_uecc_vli_modMult_fast(Y2, Y2, t7, curve); /* t4 = (y2 - y1)*(B - x3) */
18066 mg_uecc_vli_modSub(Y2, Y2, Y1, curve->p,
18067 num_words); /* t4 = (y2 - y1)*(B - x3) - E = y3 */
18068 
18069 mg_uecc_vli_modSquare_fast(t7, t5, curve); /* t7 = (y2 + y1)^2 = F */
18070 mg_uecc_vli_modSub(t7, t7, t6, curve->p,
18071 num_words); /* t7 = F - (B + C) = x3' */
18072 mg_uecc_vli_modSub(t6, t7, X1, curve->p, num_words); /* t6 = x3' - B */
18073 mg_uecc_vli_modMult_fast(t6, t6, t5, curve); /* t6 = (y2+y1)*(x3' - B) */
18074 mg_uecc_vli_modSub(Y1, t6, Y1, curve->p,
18075 num_words); /* t2 = (y2+y1)*(x3' - B) - E = y3' */
18076 
18077 mg_uecc_vli_set(X1, t7, num_words);
18078}
18079 
18080/* result may overlap point. */
18081static void EccPoint_mult(mg_uecc_word_t *result, const mg_uecc_word_t *point,
18082 const mg_uecc_word_t *scalar,
18083 const mg_uecc_word_t *initial_Z, bitcount_t num_bits,
18084 MG_UECC_Curve curve) {
18085 /* R0 and R1 */
18086 mg_uecc_word_t Rx[2][MG_UECC_MAX_WORDS];
18087 mg_uecc_word_t Ry[2][MG_UECC_MAX_WORDS];
18088 mg_uecc_word_t z[MG_UECC_MAX_WORDS];
18089 bitcount_t i;
18090 mg_uecc_word_t nb;
18091 wordcount_t num_words = curve->num_words;
18092 
18093 mg_uecc_vli_set(Rx[1], point, num_words);
18094 mg_uecc_vli_set(Ry[1], point + num_words, num_words);
18095 
18096 XYcZ_initial_double(Rx[1], Ry[1], Rx[0], Ry[0], initial_Z, curve);
18097 
18098 for (i = num_bits - 2; i > 0; --i) {
18099 nb = !mg_uecc_vli_testBit(scalar, i);
18100 XYcZ_addC(Rx[1 - nb], Ry[1 - nb], Rx[nb], Ry[nb], curve);
18101 XYcZ_add(Rx[nb], Ry[nb], Rx[1 - nb], Ry[1 - nb], curve);
18102 }
18103 
18104 nb = !mg_uecc_vli_testBit(scalar, 0);
18105 XYcZ_addC(Rx[1 - nb], Ry[1 - nb], Rx[nb], Ry[nb], curve);
18106 
18107 /* Find final 1/Z value. */
18108 mg_uecc_vli_modSub(z, Rx[1], Rx[0], curve->p, num_words); /* X1 - X0 */
18109 mg_uecc_vli_modMult_fast(z, z, Ry[1 - nb], curve); /* Yb * (X1 - X0) */
18110 mg_uecc_vli_modMult_fast(z, z, point, curve); /* xP * Yb * (X1 - X0) */
18111 mg_uecc_vli_modInv(z, z, curve->p, num_words); /* 1 / (xP * Yb * (X1 - X0)) */
18112 /* yP / (xP * Yb * (X1 - X0)) */
18113 mg_uecc_vli_modMult_fast(z, z, point + num_words, curve);
18114 mg_uecc_vli_modMult_fast(z, z, Rx[1 - nb],
18115 curve); /* Xb * yP / (xP * Yb * (X1 - X0)) */
18116 /* End 1/Z calculation */
18117 
18118 XYcZ_add(Rx[nb], Ry[nb], Rx[1 - nb], Ry[1 - nb], curve);
18119 apply_z(Rx[0], Ry[0], z, curve);
18120 
18121 mg_uecc_vli_set(result, Rx[0], num_words);
18122 mg_uecc_vli_set(result + num_words, Ry[0], num_words);
18123}
18124 
18125static mg_uecc_word_t regularize_k(const mg_uecc_word_t *const k,
18126 mg_uecc_word_t *k0, mg_uecc_word_t *k1,
18127 MG_UECC_Curve curve) {
18128 wordcount_t num_n_words = BITS_TO_WORDS(curve->num_n_bits);
18129 bitcount_t num_n_bits = curve->num_n_bits;
18130 mg_uecc_word_t carry =
18131 mg_uecc_vli_add(k0, k, curve->n, num_n_words) ||
18132 (num_n_bits < ((bitcount_t) num_n_words * MG_UECC_WORD_SIZE * 8) &&
18133 mg_uecc_vli_testBit(k0, num_n_bits));
18134 mg_uecc_vli_add(k1, k0, curve->n, num_n_words);
18135 return carry;
18136}
18137 
18138/* Generates a random integer in the range 0 < random < top.
18139 Both random and top have num_words words. */
18140MG_UECC_VLI_API int mg_uecc_generate_random_int(mg_uecc_word_t *random,
18141 const mg_uecc_word_t *top,
18142 wordcount_t num_words) {
18143 mg_uecc_word_t mask = (mg_uecc_word_t) -1;
18144 mg_uecc_word_t tries;
18145 bitcount_t num_bits = mg_uecc_vli_numBits(top, num_words);
18146 
18147 if (!g_rng_function) {
18148 return 0;
18149 }
18150 
18151 for (tries = 0; tries < MG_UECC_RNG_MAX_TRIES; ++tries) {
18152 if (!g_rng_function((uint8_t *) random,
18153 (unsigned int) (num_words * MG_UECC_WORD_SIZE))) {
18154 return 0;
18155 }
18156 random[num_words - 1] &=
18157 mask >> ((bitcount_t) (num_words * MG_UECC_WORD_SIZE * 8 - num_bits));
18158 if (!mg_uecc_vli_isZero(random, num_words) &&
18159 mg_uecc_vli_cmp(top, random, num_words) == 1) {
18160 return 1;
18161 }
18162 }
18163 return 0;
18164}
18165 
18166static mg_uecc_word_t EccPoint_compute_public_key(mg_uecc_word_t *result,
18167 mg_uecc_word_t *private_key,
18168 MG_UECC_Curve curve) {
18169 mg_uecc_word_t tmp1[MG_UECC_MAX_WORDS];
18170 mg_uecc_word_t tmp2[MG_UECC_MAX_WORDS];
18171 mg_uecc_word_t *p2[2] = {tmp1, tmp2};
18172 mg_uecc_word_t *initial_Z = 0;
18173 mg_uecc_word_t carry;
18174 
18175 /* Regularize the bitcount for the private key so that attackers cannot use a
18176 side channel attack to learn the number of leading zeros. */
18177 carry = regularize_k(private_key, tmp1, tmp2, curve);
18178 
18179 /* If an RNG function was specified, try to get a random initial Z value to
18180 improve protection against side-channel attacks. */
18181 if (g_rng_function) {
18182 if (!mg_uecc_generate_random_int(p2[carry], curve->p, curve->num_words)) {
18183 return 0;
18184 }
18185 initial_Z = p2[carry];
18186 }
18187 EccPoint_mult(result, curve->G, p2[!carry], initial_Z,
18188 (bitcount_t) (curve->num_n_bits + 1), curve);
18189 
18190 if (EccPoint_isZero(result, curve)) {
18191 return 0;
18192 }
18193 return 1;
18194}
18195 
18196#if MG_UECC_WORD_SIZE == 1
18197 
18198MG_UECC_VLI_API void mg_uecc_vli_nativeToBytes(uint8_t *bytes, int num_bytes,
18199 const uint8_t *native) {
18200 wordcount_t i;
18201 for (i = 0; i < num_bytes; ++i) {
18202 bytes[i] = native[(num_bytes - 1) - i];
18203 }
18204}
18205 
18206MG_UECC_VLI_API void mg_uecc_vli_bytesToNative(uint8_t *native,
18207 const uint8_t *bytes,
18208 int num_bytes) {
18209 mg_uecc_vli_nativeToBytes(native, num_bytes, bytes);
18210}
18211 
18212#else
18213 
18214MG_UECC_VLI_API void mg_uecc_vli_nativeToBytes(uint8_t *bytes, int num_bytes,
18215 const mg_uecc_word_t *native) {
18216 int i;
18217 for (i = 0; i < num_bytes; ++i) {
18218 unsigned b = (unsigned) (num_bytes - 1 - i);
18219 bytes[i] = (uint8_t) (native[b / MG_UECC_WORD_SIZE] >>
18220 (8 * (b % MG_UECC_WORD_SIZE)));
18221 }
18222}
18223 
18224MG_UECC_VLI_API void mg_uecc_vli_bytesToNative(mg_uecc_word_t *native,
18225 const uint8_t *bytes,
18226 int num_bytes) {
18227 int i;
18228 mg_uecc_vli_clear(native,
18229 (wordcount_t) ((num_bytes + (MG_UECC_WORD_SIZE - 1)) /
18230 MG_UECC_WORD_SIZE));
18231 for (i = 0; i < num_bytes; ++i) {
18232 unsigned b = (unsigned) (num_bytes - 1 - i);
18233 native[b / MG_UECC_WORD_SIZE] |= (mg_uecc_word_t) bytes[i]
18234 << (8 * (b % MG_UECC_WORD_SIZE));
18235 }
18236}
18237 
18238#endif /* MG_UECC_WORD_SIZE */
18239 
18240int mg_uecc_make_key(uint8_t *public_key, uint8_t *private_key,
18241 MG_UECC_Curve curve) {
18242#if MG_UECC_VLI_NATIVE_LITTLE_ENDIAN
18243 mg_uecc_word_t *_private = (mg_uecc_word_t *) private_key;
18244 mg_uecc_word_t *_public = (mg_uecc_word_t *) public_key;
18245#else
18246 mg_uecc_word_t _private[MG_UECC_MAX_WORDS];
18247 mg_uecc_word_t _public[MG_UECC_MAX_WORDS * 2];
18248#endif
18249 mg_uecc_word_t tries;
18250 
18251 for (tries = 0; tries < MG_UECC_RNG_MAX_TRIES; ++tries) {
18252 if (!mg_uecc_generate_random_int(_private, curve->n,
18253 BITS_TO_WORDS(curve->num_n_bits))) {
18254 return 0;
18255 }
18256 
18257 if (EccPoint_compute_public_key(_public, _private, curve)) {
18258#if MG_UECC_VLI_NATIVE_LITTLE_ENDIAN == 0
18259 mg_uecc_vli_nativeToBytes(private_key, BITS_TO_BYTES(curve->num_n_bits),
18260 _private);
18261 mg_uecc_vli_nativeToBytes(public_key, curve->num_bytes, _public);
18262 mg_uecc_vli_nativeToBytes(public_key + curve->num_bytes, curve->num_bytes,
18263 _public + curve->num_words);
18264#endif
18265 return 1;
18266 }
18267 }
18268 return 0;
18269}
18270 
18271int mg_uecc_shared_secret(const uint8_t *public_key, const uint8_t *private_key,
18272 uint8_t *secret, MG_UECC_Curve curve) {
18273 mg_uecc_word_t _public[MG_UECC_MAX_WORDS * 2];
18274 mg_uecc_word_t _private[MG_UECC_MAX_WORDS];
18275 
18276 mg_uecc_word_t tmp[MG_UECC_MAX_WORDS];
18277 mg_uecc_word_t *p2[2] = {_private, tmp};
18278 mg_uecc_word_t *initial_Z = 0;
18279 mg_uecc_word_t carry;
18280 wordcount_t num_words = curve->num_words;
18281 wordcount_t num_bytes = curve->num_bytes;
18282 
18283#if MG_UECC_VLI_NATIVE_LITTLE_ENDIAN
18284 bcopy((uint8_t *) _private, private_key, num_bytes);
18285 bcopy((uint8_t *) _public, public_key, num_bytes * 2);
18286#else
18287 mg_uecc_vli_bytesToNative(_private, private_key,
18288 BITS_TO_BYTES(curve->num_n_bits));
18289 mg_uecc_vli_bytesToNative(_public, public_key, num_bytes);
18290 mg_uecc_vli_bytesToNative(_public + num_words, public_key + num_bytes,
18291 num_bytes);
18292#endif
18293 
18294 /* Regularize the bitcount for the private key so that attackers cannot use a
18295 side channel attack to learn the number of leading zeros. */
18296 carry = regularize_k(_private, _private, tmp, curve);
18297 
18298 /* If an RNG function was specified, try to get a random initial Z value to
18299 improve protection against side-channel attacks. */
18300 if (g_rng_function) {
18301 if (!mg_uecc_generate_random_int(p2[carry], curve->p, num_words)) {
18302 return 0;
18303 }
18304 initial_Z = p2[carry];
18305 }
18306 
18307 EccPoint_mult(_public, _public, p2[!carry], initial_Z,
18308 (bitcount_t) (curve->num_n_bits + 1), curve);
18309#if MG_UECC_VLI_NATIVE_LITTLE_ENDIAN
18310 bcopy((uint8_t *) secret, (uint8_t *) _public, num_bytes);
18311#else
18312 mg_uecc_vli_nativeToBytes(secret, num_bytes, _public);
18313#endif
18314 return !EccPoint_isZero(_public, curve);
18315}
18316 
18317#if MG_UECC_SUPPORT_COMPRESSED_POINT
18318void mg_uecc_compress(const uint8_t *public_key, uint8_t *compressed,
18319 MG_UECC_Curve curve) {
18320 wordcount_t i;
18321 for (i = 0; i < curve->num_bytes; ++i) {
18322 compressed[i + 1] = public_key[i];
18323 }
18324#if MG_UECC_VLI_NATIVE_LITTLE_ENDIAN
18325 compressed[0] = 2 + (public_key[curve->num_bytes] & 0x01);
18326#else
18327 compressed[0] = 2 + (public_key[curve->num_bytes * 2 - 1] & 0x01);
18328#endif
18329}
18330 
18331void mg_uecc_decompress(const uint8_t *compressed, uint8_t *public_key,
18332 MG_UECC_Curve curve) {
18333#if MG_UECC_VLI_NATIVE_LITTLE_ENDIAN
18334 mg_uecc_word_t *point = (mg_uecc_word_t *) public_key;
18335#else
18336 mg_uecc_word_t point[MG_UECC_MAX_WORDS * 2];
18337#endif
18338 mg_uecc_word_t *y = point + curve->num_words;
18339#if MG_UECC_VLI_NATIVE_LITTLE_ENDIAN
18340 bcopy(public_key, compressed + 1, curve->num_bytes);
18341#else
18342 mg_uecc_vli_bytesToNative(point, compressed + 1, curve->num_bytes);
18343#endif
18344 curve->x_side(y, point, curve);
18345 curve->mod_sqrt(y, curve);
18346 
18347 if ((uint8_t) (y[0] & 0x01) != (compressed[0] & 0x01)) {
18348 mg_uecc_vli_sub(y, curve->p, y, curve->num_words);
18349 }
18350 
18351#if MG_UECC_VLI_NATIVE_LITTLE_ENDIAN == 0
18352 mg_uecc_vli_nativeToBytes(public_key, curve->num_bytes, point);
18353 mg_uecc_vli_nativeToBytes(public_key + curve->num_bytes, curve->num_bytes, y);
18354#endif
18355}
18356#endif /* MG_UECC_SUPPORT_COMPRESSED_POINT */
18357 
18358MG_UECC_VLI_API int mg_uecc_valid_point(const mg_uecc_word_t *point,
18359 MG_UECC_Curve curve) {
18360 mg_uecc_word_t tmp1[MG_UECC_MAX_WORDS];
18361 mg_uecc_word_t tmp2[MG_UECC_MAX_WORDS];
18362 wordcount_t num_words = curve->num_words;
18363 
18364 /* The point at infinity is invalid. */
18365 if (EccPoint_isZero(point, curve)) {
18366 return 0;
18367 }
18368 
18369 /* x and y must be smaller than p. */
18370 if (mg_uecc_vli_cmp_unsafe(curve->p, point, num_words) != 1 ||
18371 mg_uecc_vli_cmp_unsafe(curve->p, point + num_words, num_words) != 1) {
18372 return 0;
18373 }
18374 
18375 mg_uecc_vli_modSquare_fast(tmp1, point + num_words, curve);
18376 curve->x_side(tmp2, point, curve); /* tmp2 = x^3 + ax + b */
18377 
18378 /* Make sure that y^2 == x^3 + ax + b */
18379 return (int) (mg_uecc_vli_equal(tmp1, tmp2, num_words));
18380}
18381 
18382int mg_uecc_valid_public_key(const uint8_t *public_key, MG_UECC_Curve curve) {
18383#if MG_UECC_VLI_NATIVE_LITTLE_ENDIAN
18384 mg_uecc_word_t *_public = (mg_uecc_word_t *) public_key;
18385#else
18386 mg_uecc_word_t _public[MG_UECC_MAX_WORDS * 2];
18387#endif
18388 
18389#if MG_UECC_VLI_NATIVE_LITTLE_ENDIAN == 0
18390 mg_uecc_vli_bytesToNative(_public, public_key, curve->num_bytes);
18391 mg_uecc_vli_bytesToNative(_public + curve->num_words,
18392 public_key + curve->num_bytes, curve->num_bytes);
18393#endif
18394 return mg_uecc_valid_point(_public, curve);
18395}
18396 
18397int mg_uecc_compute_public_key(const uint8_t *private_key, uint8_t *public_key,
18398 MG_UECC_Curve curve) {
18399#if MG_UECC_VLI_NATIVE_LITTLE_ENDIAN
18400 mg_uecc_word_t *_private = (mg_uecc_word_t *) private_key;
18401 mg_uecc_word_t *_public = (mg_uecc_word_t *) public_key;
18402#else
18403 mg_uecc_word_t _private[MG_UECC_MAX_WORDS];
18404 mg_uecc_word_t _public[MG_UECC_MAX_WORDS * 2];
18405#endif
18406 
18407#if MG_UECC_VLI_NATIVE_LITTLE_ENDIAN == 0
18408 mg_uecc_vli_bytesToNative(_private, private_key,
18409 BITS_TO_BYTES(curve->num_n_bits));
18410#endif
18411 
18412 /* Make sure the private key is in the range [1, n-1]. */
18413 if (mg_uecc_vli_isZero(_private, BITS_TO_WORDS(curve->num_n_bits))) {
18414 return 0;
18415 }
18416 
18417 if (mg_uecc_vli_cmp(curve->n, _private, BITS_TO_WORDS(curve->num_n_bits)) !=
18418 1) {
18419 return 0;
18420 }
18421 
18422 /* Compute public key. */
18423 if (!EccPoint_compute_public_key(_public, _private, curve)) {
18424 return 0;
18425 }
18426 
18427#if MG_UECC_VLI_NATIVE_LITTLE_ENDIAN == 0
18428 mg_uecc_vli_nativeToBytes(public_key, curve->num_bytes, _public);
18429 mg_uecc_vli_nativeToBytes(public_key + curve->num_bytes, curve->num_bytes,
18430 _public + curve->num_words);
18431#endif
18432 return 1;
18433}
18434 
18435/* -------- ECDSA code -------- */
18436 
18437static void bits2int(mg_uecc_word_t *native, const uint8_t *bits,
18438 unsigned bits_size, MG_UECC_Curve curve) {
18439 unsigned num_n_bytes = (unsigned) BITS_TO_BYTES(curve->num_n_bits);
18440 unsigned num_n_words = (unsigned) BITS_TO_WORDS(curve->num_n_bits);
18441 int shift;
18442 mg_uecc_word_t carry;
18443 mg_uecc_word_t *ptr;
18444 
18445 if (bits_size > num_n_bytes) {
18446 bits_size = num_n_bytes;
18447 }
18448 
18449 mg_uecc_vli_clear(native, (wordcount_t) num_n_words);
18450#if MG_UECC_VLI_NATIVE_LITTLE_ENDIAN
18451 bcopy((uint8_t *) native, bits, bits_size);
18452#else
18453 mg_uecc_vli_bytesToNative(native, bits, (int) bits_size);
18454#endif
18455 if (bits_size * 8 <= (unsigned) curve->num_n_bits) {
18456 return;
18457 }
18458 shift = (int) bits_size * 8 - curve->num_n_bits;
18459 carry = 0;
18460 ptr = native + num_n_words;
18461 while (ptr-- > native) {
18462 mg_uecc_word_t temp = *ptr;
18463 *ptr = (temp >> shift) | carry;
18464 carry = temp << (MG_UECC_WORD_BITS - shift);
18465 }
18466 
18467 /* Reduce mod curve_n */
18468 if (mg_uecc_vli_cmp_unsafe(curve->n, native, (wordcount_t) num_n_words) !=
18469 1) {
18470 mg_uecc_vli_sub(native, native, curve->n, (wordcount_t) num_n_words);
18471 }
18472}
18473 
18474static int mg_uecc_sign_with_k_internal(const uint8_t *private_key,
18475 const uint8_t *message_hash,
18476 unsigned hash_size, mg_uecc_word_t *k,
18477 uint8_t *signature,
18478 MG_UECC_Curve curve) {
18479 mg_uecc_word_t tmp[MG_UECC_MAX_WORDS];
18480 mg_uecc_word_t s[MG_UECC_MAX_WORDS];
18481 mg_uecc_word_t *k2[2] = {tmp, s};
18482 mg_uecc_word_t *initial_Z = 0;
18483#if MG_UECC_VLI_NATIVE_LITTLE_ENDIAN
18484 mg_uecc_word_t *p = (mg_uecc_word_t *) signature;
18485#else
18486 mg_uecc_word_t p[MG_UECC_MAX_WORDS * 2];
18487#endif
18488 mg_uecc_word_t carry;
18489 wordcount_t num_words = curve->num_words;
18490 wordcount_t num_n_words = BITS_TO_WORDS(curve->num_n_bits);
18491 bitcount_t num_n_bits = curve->num_n_bits;
18492 
18493 /* Make sure 0 < k < curve_n */
18494 if (mg_uecc_vli_isZero(k, num_words) ||
18495 mg_uecc_vli_cmp(curve->n, k, num_n_words) != 1) {
18496 return 0;
18497 }
18498 
18499 carry = regularize_k(k, tmp, s, curve);
18500 /* If an RNG function was specified, try to get a random initial Z value to
18501 improve protection against side-channel attacks. */
18502 if (g_rng_function) {
18503 if (!mg_uecc_generate_random_int(k2[carry], curve->p, num_words)) {
18504 return 0;
18505 }
18506 initial_Z = k2[carry];
18507 }
18508 EccPoint_mult(p, curve->G, k2[!carry], initial_Z,
18509 (bitcount_t) (num_n_bits + 1), curve);
18510 if (mg_uecc_vli_isZero(p, num_words)) {
18511 return 0;
18512 }
18513 
18514 /* If an RNG function was specified, get a random number
18515 to prevent side channel analysis of k. */
18516 if (!g_rng_function) {
18517 mg_uecc_vli_clear(tmp, num_n_words);
18518 tmp[0] = 1;
18519 } else if (!mg_uecc_generate_random_int(tmp, curve->n, num_n_words)) {
18520 return 0;
18521 }
18522 
18523 /* Prevent side channel analysis of mg_uecc_vli_modInv() to determine
18524 bits of k / the private key by premultiplying by a random number */
18525 mg_uecc_vli_modMult(k, k, tmp, curve->n, num_n_words); /* k' = rand * k */
18526 mg_uecc_vli_modInv(k, k, curve->n, num_n_words); /* k = 1 / k' */
18527 mg_uecc_vli_modMult(k, k, tmp, curve->n, num_n_words); /* k = 1 / k */
18528 
18529#if MG_UECC_VLI_NATIVE_LITTLE_ENDIAN == 0
18530 mg_uecc_vli_nativeToBytes(signature, curve->num_bytes, p); /* store r */
18531#endif
18532 
18533#if MG_UECC_VLI_NATIVE_LITTLE_ENDIAN
18534 bcopy((uint8_t *) tmp, private_key, BITS_TO_BYTES(curve->num_n_bits));
18535#else
18536 mg_uecc_vli_bytesToNative(tmp, private_key,
18537 BITS_TO_BYTES(curve->num_n_bits)); /* tmp = d */
18538#endif
18539 
18540 s[num_n_words - 1] = 0;
18541 mg_uecc_vli_set(s, p, num_words);
18542 mg_uecc_vli_modMult(s, tmp, s, curve->n, num_n_words); /* s = r*d */
18543 
18544 bits2int(tmp, message_hash, hash_size, curve);
18545 mg_uecc_vli_modAdd(s, tmp, s, curve->n, num_n_words); /* s = e + r*d */
18546 mg_uecc_vli_modMult(s, s, k, curve->n, num_n_words); /* s = (e + r*d) / k */
18547 if (mg_uecc_vli_numBits(s, num_n_words) > (bitcount_t) curve->num_bytes * 8) {
18548 return 0;
18549 }
18550#if MG_UECC_VLI_NATIVE_LITTLE_ENDIAN
18551 bcopy((uint8_t *) signature + curve->num_bytes, (uint8_t *) s,
18552 curve->num_bytes);
18553#else
18554 mg_uecc_vli_nativeToBytes(signature + curve->num_bytes, curve->num_bytes, s);
18555#endif
18556 return 1;
18557}
18558 
18559#if 0
18560/* For testing - sign with an explicitly specified k value */
18561int mg_uecc_sign_with_k(const uint8_t *private_key, const uint8_t *message_hash,
18562 unsigned hash_size, const uint8_t *k, uint8_t *signature,
18563 MG_UECC_Curve curve) {
18564 mg_uecc_word_t k2[MG_UECC_MAX_WORDS];
18565 bits2int(k2, k, (unsigned) BITS_TO_BYTES(curve->num_n_bits), curve);
18566 return mg_uecc_sign_with_k_internal(private_key, message_hash, hash_size, k2,
18567 signature, curve);
18568}
18569#endif
18570 
18571int mg_uecc_sign(const uint8_t *private_key, const uint8_t *message_hash,
18572 unsigned hash_size, uint8_t *signature, MG_UECC_Curve curve) {
18573 mg_uecc_word_t k[MG_UECC_MAX_WORDS];
18574 mg_uecc_word_t tries;
18575 
18576 for (tries = 0; tries < MG_UECC_RNG_MAX_TRIES; ++tries) {
18577 if (!mg_uecc_generate_random_int(k, curve->n,
18578 BITS_TO_WORDS(curve->num_n_bits))) {
18579 return 0;
18580 }
18581 
18582 if (mg_uecc_sign_with_k_internal(private_key, message_hash, hash_size, k,
18583 signature, curve)) {
18584 return 1;
18585 }
18586 }
18587 return 0;
18588}
18589 
18590/* Compute an HMAC using K as a key (as in RFC 6979). Note that K is always
18591 the same size as the hash result size. */
18592static void HMAC_init(const MG_UECC_HashContext *hash_context,
18593 const uint8_t *K) {
18594 uint8_t *pad = hash_context->tmp + 2 * hash_context->result_size;
18595 unsigned i;
18596 for (i = 0; i < hash_context->result_size; ++i) pad[i] = K[i] ^ 0x36;
18597 for (; i < hash_context->block_size; ++i) pad[i] = 0x36;
18598 
18599 hash_context->init_hash(hash_context);
18600 hash_context->update_hash(hash_context, pad, hash_context->block_size);
18601}
18602 
18603static void HMAC_update(const MG_UECC_HashContext *hash_context,
18604 const uint8_t *message, unsigned message_size) {
18605 hash_context->update_hash(hash_context, message, message_size);
18606}
18607 
18608static void HMAC_finish(const MG_UECC_HashContext *hash_context,
18609 const uint8_t *K, uint8_t *result) {
18610 uint8_t *pad = hash_context->tmp + 2 * hash_context->result_size;
18611 unsigned i;
18612 for (i = 0; i < hash_context->result_size; ++i) pad[i] = K[i] ^ 0x5c;
18613 for (; i < hash_context->block_size; ++i) pad[i] = 0x5c;
18614 
18615 hash_context->finish_hash(hash_context, result);
18616 
18617 hash_context->init_hash(hash_context);
18618 hash_context->update_hash(hash_context, pad, hash_context->block_size);
18619 hash_context->update_hash(hash_context, result, hash_context->result_size);
18620 hash_context->finish_hash(hash_context, result);
18621}
18622 
18623/* V = HMAC_K(V) */
18624static void update_V(const MG_UECC_HashContext *hash_context, uint8_t *K,
18625 uint8_t *V) {
18626 HMAC_init(hash_context, K);
18627 HMAC_update(hash_context, V, hash_context->result_size);
18628 HMAC_finish(hash_context, K, V);
18629}
18630 
18631/* Deterministic signing, similar to RFC 6979. Differences are:
18632 * We just use H(m) directly rather than bits2octets(H(m))
18633 (it is not reduced modulo curve_n).
18634 * We generate a value for k (aka T) directly rather than converting
18635 endianness.
18636 
18637 Layout of hash_context->tmp: <K> | <V> | (1 byte overlapped 0x00 or 0x01) /
18638 <HMAC pad> */
18639int mg_uecc_sign_deterministic(const uint8_t *private_key,
18640 const uint8_t *message_hash, unsigned hash_size,
18641 const MG_UECC_HashContext *hash_context,
18642 uint8_t *signature, MG_UECC_Curve curve) {
18643 uint8_t *K = hash_context->tmp;
18644 uint8_t *V = K + hash_context->result_size;
18645 wordcount_t num_bytes = curve->num_bytes;
18646 wordcount_t num_n_words = BITS_TO_WORDS(curve->num_n_bits);
18647 bitcount_t num_n_bits = curve->num_n_bits;
18648 mg_uecc_word_t tries;
18649 unsigned i;
18650 for (i = 0; i < hash_context->result_size; ++i) {
18651 V[i] = 0x01;
18652 K[i] = 0;
18653 }
18654 
18655 /* K = HMAC_K(V || 0x00 || int2octets(x) || h(m)) */
18656 HMAC_init(hash_context, K);
18657 V[hash_context->result_size] = 0x00;
18658 HMAC_update(hash_context, V, hash_context->result_size + 1);
18659 HMAC_update(hash_context, private_key, (unsigned int) num_bytes);
18660 HMAC_update(hash_context, message_hash, hash_size);
18661 HMAC_finish(hash_context, K, K);
18662 
18663 update_V(hash_context, K, V);
18664 
18665 /* K = HMAC_K(V || 0x01 || int2octets(x) || h(m)) */
18666 HMAC_init(hash_context, K);
18667 V[hash_context->result_size] = 0x01;
18668 HMAC_update(hash_context, V, hash_context->result_size + 1);
18669 HMAC_update(hash_context, private_key, (unsigned int) num_bytes);
18670 HMAC_update(hash_context, message_hash, hash_size);
18671 HMAC_finish(hash_context, K, K);
18672 
18673 update_V(hash_context, K, V);
18674 
18675 for (tries = 0; tries < MG_UECC_RNG_MAX_TRIES; ++tries) {
18676 mg_uecc_word_t T[MG_UECC_MAX_WORDS];
18677 uint8_t *T_ptr = (uint8_t *) T;
18678 wordcount_t T_bytes = 0;
18679 for (;;) {
18680 update_V(hash_context, K, V);
18681 for (i = 0; i < hash_context->result_size; ++i) {
18682 T_ptr[T_bytes++] = V[i];
18683 if (T_bytes >= num_n_words * MG_UECC_WORD_SIZE) {
18684 goto filled;
18685 }
18686 }
18687 }
18688 filled:
18689 if ((bitcount_t) num_n_words * MG_UECC_WORD_SIZE * 8 > num_n_bits) {
18690 mg_uecc_word_t mask = (mg_uecc_word_t) -1;
18691 T[num_n_words - 1] &=
18692 mask >>
18693 ((bitcount_t) (num_n_words * MG_UECC_WORD_SIZE * 8 - num_n_bits));
18694 }
18695 
18696 if (mg_uecc_sign_with_k_internal(private_key, message_hash, hash_size, T,
18697 signature, curve)) {
18698 return 1;
18699 }
18700 
18701 /* K = HMAC_K(V || 0x00) */
18702 HMAC_init(hash_context, K);
18703 V[hash_context->result_size] = 0x00;
18704 HMAC_update(hash_context, V, hash_context->result_size + 1);
18705 HMAC_finish(hash_context, K, K);
18706 
18707 update_V(hash_context, K, V);
18708 }
18709 return 0;
18710}
18711 
18712static bitcount_t smax(bitcount_t a, bitcount_t b) {
18713 return (a > b ? a : b);
18714}
18715 
18716int mg_uecc_verify(const uint8_t *public_key, const uint8_t *message_hash,
18717 unsigned hash_size, const uint8_t *signature,
18718 MG_UECC_Curve curve) {
18719 mg_uecc_word_t u1[MG_UECC_MAX_WORDS], u2[MG_UECC_MAX_WORDS];
18720 mg_uecc_word_t z[MG_UECC_MAX_WORDS];
18721 mg_uecc_word_t sum[MG_UECC_MAX_WORDS * 2];
18722 mg_uecc_word_t rx[MG_UECC_MAX_WORDS];
18723 mg_uecc_word_t ry[MG_UECC_MAX_WORDS];
18724 mg_uecc_word_t tx[MG_UECC_MAX_WORDS];
18725 mg_uecc_word_t ty[MG_UECC_MAX_WORDS];
18726 mg_uecc_word_t tz[MG_UECC_MAX_WORDS];
18727 const mg_uecc_word_t *points[4];
18728 const mg_uecc_word_t *point;
18729 bitcount_t num_bits;
18730 bitcount_t i;
18731#if MG_UECC_VLI_NATIVE_LITTLE_ENDIAN
18732 mg_uecc_word_t *_public = (mg_uecc_word_t *) public_key;
18733#else
18734 mg_uecc_word_t _public[MG_UECC_MAX_WORDS * 2];
18735#endif
18736 mg_uecc_word_t r[MG_UECC_MAX_WORDS], s[MG_UECC_MAX_WORDS];
18737 wordcount_t num_words = curve->num_words;
18738 wordcount_t num_n_words = BITS_TO_WORDS(curve->num_n_bits);
18739 
18740 rx[num_n_words - 1] = 0;
18741 r[num_n_words - 1] = 0;
18742 s[num_n_words - 1] = 0;
18743 
18744#if MG_UECC_VLI_NATIVE_LITTLE_ENDIAN
18745 bcopy((uint8_t *) r, signature, curve->num_bytes);
18746 bcopy((uint8_t *) s, signature + curve->num_bytes, curve->num_bytes);
18747#else
18748 mg_uecc_vli_bytesToNative(_public, public_key, curve->num_bytes);
18749 mg_uecc_vli_bytesToNative(_public + num_words, public_key + curve->num_bytes,
18750 curve->num_bytes);
18751 mg_uecc_vli_bytesToNative(r, signature, curve->num_bytes);
18752 mg_uecc_vli_bytesToNative(s, signature + curve->num_bytes, curve->num_bytes);
18753#endif
18754 
18755 /* r, s must not be 0. */
18756 if (mg_uecc_vli_isZero(r, num_words) || mg_uecc_vli_isZero(s, num_words)) {
18757 return 0;
18758 }
18759 
18760 /* r, s must be < n. */
18761 if (mg_uecc_vli_cmp_unsafe(curve->n, r, num_n_words) != 1 ||
18762 mg_uecc_vli_cmp_unsafe(curve->n, s, num_n_words) != 1) {
18763 return 0;
18764 }
18765 
18766 /* Calculate u1 and u2. */
18767 mg_uecc_vli_modInv(z, s, curve->n, num_n_words); /* z = 1/s */
18768 u1[num_n_words - 1] = 0;
18769 bits2int(u1, message_hash, hash_size, curve);
18770 mg_uecc_vli_modMult(u1, u1, z, curve->n, num_n_words); /* u1 = e/s */
18771 mg_uecc_vli_modMult(u2, r, z, curve->n, num_n_words); /* u2 = r/s */
18772 
18773 /* Calculate sum = G + Q. */
18774 mg_uecc_vli_set(sum, _public, num_words);
18775 mg_uecc_vli_set(sum + num_words, _public + num_words, num_words);
18776 mg_uecc_vli_set(tx, curve->G, num_words);
18777 mg_uecc_vli_set(ty, curve->G + num_words, num_words);
18778 mg_uecc_vli_modSub(z, sum, tx, curve->p, num_words); /* z = x2 - x1 */
18779 XYcZ_add(tx, ty, sum, sum + num_words, curve);
18780 mg_uecc_vli_modInv(z, z, curve->p, num_words); /* z = 1/z */
18781 apply_z(sum, sum + num_words, z, curve);
18782 
18783 /* Use Shamir's trick to calculate u1*G + u2*Q */
18784 points[0] = 0;
18785 points[1] = curve->G;
18786 points[2] = _public;
18787 points[3] = sum;
18788 num_bits = smax(mg_uecc_vli_numBits(u1, num_n_words),
18789 mg_uecc_vli_numBits(u2, num_n_words));
18790 point =
18791 points[(!!mg_uecc_vli_testBit(u1, (bitcount_t) (num_bits - 1))) |
18792 ((!!mg_uecc_vli_testBit(u2, (bitcount_t) (num_bits - 1))) << 1)];
18793 mg_uecc_vli_set(rx, point, num_words);
18794 mg_uecc_vli_set(ry, point + num_words, num_words);
18795 mg_uecc_vli_clear(z, num_words);
18796 z[0] = 1;
18797 
18798 for (i = num_bits - 2; i >= 0; --i) {
18799 mg_uecc_word_t index;
18800 curve->double_jacobian(rx, ry, z, curve);
18801 
18802 index = (!!mg_uecc_vli_testBit(u1, i)) |
18803 (mg_uecc_word_t) ((!!mg_uecc_vli_testBit(u2, i)) << 1);
18804 point = points[index];
18805 if (point) {
18806 mg_uecc_vli_set(tx, point, num_words);
18807 mg_uecc_vli_set(ty, point + num_words, num_words);
18808 apply_z(tx, ty, z, curve);
18809 mg_uecc_vli_modSub(tz, rx, tx, curve->p, num_words); /* Z = x2 - x1 */
18810 XYcZ_add(tx, ty, rx, ry, curve);
18811 mg_uecc_vli_modMult_fast(z, z, tz, curve);
18812 }
18813 }
18814 
18815 mg_uecc_vli_modInv(z, z, curve->p, num_words); /* Z = 1/Z */
18816 apply_z(rx, ry, z, curve);
18817 
18818 /* v = x1 (mod n) */
18819 if (mg_uecc_vli_cmp_unsafe(curve->n, rx, num_n_words) != 1) {
18820 mg_uecc_vli_sub(rx, rx, curve->n, num_n_words);
18821 }
18822 
18823 /* Accept only if v == r. */
18824 return (int) (mg_uecc_vli_equal(rx, r, num_words));
18825}
18826 
18827#if MG_UECC_ENABLE_VLI_API
18828 
18829unsigned mg_uecc_curve_num_words(MG_UECC_Curve curve) {
18830 return curve->num_words;
18831}
18832 
18833unsigned mg_uecc_curve_num_bytes(MG_UECC_Curve curve) {
18834 return curve->num_bytes;
18835}
18836 
18837unsigned mg_uecc_curve_num_bits(MG_UECC_Curve curve) {
18838 return curve->num_bytes * 8;
18839}
18840 
18841unsigned mg_uecc_curve_num_n_words(MG_UECC_Curve curve) {
18842 return BITS_TO_WORDS(curve->num_n_bits);
18843}
18844 
18845unsigned mg_uecc_curve_num_n_bytes(MG_UECC_Curve curve) {
18846 return BITS_TO_BYTES(curve->num_n_bits);
18847}
18848 
18849unsigned mg_uecc_curve_num_n_bits(MG_UECC_Curve curve) {
18850 return curve->num_n_bits;
18851}
18852 
18853const mg_uecc_word_t *mg_uecc_curve_p(MG_UECC_Curve curve) {
18854 return curve->p;
18855}
18856 
18857const mg_uecc_word_t *mg_uecc_curve_n(MG_UECC_Curve curve) {
18858 return curve->n;
18859}
18860 
18861const mg_uecc_word_t *mg_uecc_curve_G(MG_UECC_Curve curve) {
18862 return curve->G;
18863}
18864 
18865const mg_uecc_word_t *mg_uecc_curve_b(MG_UECC_Curve curve) {
18866 return curve->b;
18867}
18868 
18869#if MG_UECC_SUPPORT_COMPRESSED_POINT
18870void mg_uecc_vli_mod_sqrt(mg_uecc_word_t *a, MG_UECC_Curve curve) {
18871 curve->mod_sqrt(a, curve);
18872}
18873#endif
18874 
18875void mg_uecc_vli_mmod_fast(mg_uecc_word_t *result, mg_uecc_word_t *product,
18876 MG_UECC_Curve curve) {
18877#if (MG_UECC_OPTIMIZATION_LEVEL > 0)
18878 curve->mmod_fast(result, product);
18879#else
18880 mg_uecc_vli_mmod(result, product, curve->p, curve->num_words);
18881#endif
18882}
18883 
18884void mg_uecc_point_mult(mg_uecc_word_t *result, const mg_uecc_word_t *point,
18885 const mg_uecc_word_t *scalar, MG_UECC_Curve curve) {
18886 mg_uecc_word_t tmp1[MG_UECC_MAX_WORDS];
18887 mg_uecc_word_t tmp2[MG_UECC_MAX_WORDS];
18888 mg_uecc_word_t *p2[2] = {tmp1, tmp2};
18889 mg_uecc_word_t carry = regularize_k(scalar, tmp1, tmp2, curve);
18890 
18891 EccPoint_mult(result, point, p2[!carry], 0, curve->num_n_bits + 1, curve);
18892}
18893 
18894#endif /* MG_UECC_ENABLE_VLI_API */
18895#endif // MG_TLS_BUILTIN
18896// End of uecc BSD-2
18897 
18898#ifdef MG_ENABLE_LINES
18899#line 1 "src/tls_x25519.c"
18900#endif
18901/**
18902 * Adapted from STROBE: https://strobe.sourceforge.io/
18903 * Copyright (c) 2015-2016 Cryptography Research, Inc.
18904 * Author: Mike Hamburg
18905 * License: MIT License
18906 */
18907 
18908 
18909 
18910 
18911#if MG_TLS == MG_TLS_BUILTIN
18912 
18913const uint8_t X25519_BASE_POINT[X25519_BYTES] = {9};
18914 
18915#define X25519_WBITS 32
18916 
18917typedef uint32_t limb_t;
18918typedef uint64_t dlimb_t;
18919typedef int64_t sdlimb_t;
18920 
18921#define NLIMBS (256 / X25519_WBITS)
18922typedef limb_t mg_fe[NLIMBS];
18923 
18924static limb_t umaal(limb_t *carry, limb_t acc, limb_t mand, limb_t mier) {
18925 dlimb_t tmp = (dlimb_t) mand * mier + acc + *carry;
18926 *carry = (limb_t) (tmp >> X25519_WBITS);
18927 return (limb_t) tmp;
18928}
18929 
18930// These functions are implemented in terms of umaal on ARM
18931static limb_t adc(limb_t *carry, limb_t acc, limb_t mand) {
18932 dlimb_t total = (dlimb_t) *carry + acc + mand;
18933 *carry = (limb_t) (total >> X25519_WBITS);
18934 return (limb_t) total;
18935}
18936 
18937static limb_t adc0(limb_t *carry, limb_t acc) {
18938 dlimb_t total = (dlimb_t) *carry + acc;
18939 *carry = (limb_t) (total >> X25519_WBITS);
18940 return (limb_t) total;
18941}
18942 
18943// - Precondition: carry is small.
18944// - Invariant: result of propagate is < 2^255 + 1 word
18945// - In particular, always less than 2p.
18946// - Also, output x >= min(x,19)
18947static void propagate(mg_fe x, limb_t over) {
18948 unsigned i;
18949 limb_t carry;
18950 over = x[NLIMBS - 1] >> (X25519_WBITS - 1) | over << 1;
18951 x[NLIMBS - 1] &= ~((limb_t) 1 << (X25519_WBITS - 1));
18952 
18953 carry = over * 19;
18954 for (i = 0; i < NLIMBS; i++) {
18955 x[i] = adc0(&carry, x[i]);
18956 }
18957}
18958 
18959static void add(mg_fe out, const mg_fe a, const mg_fe b) {
18960 unsigned i;
18961 limb_t carry = 0;
18962 for (i = 0; i < NLIMBS; i++) {
18963 out[i] = adc(&carry, a[i], b[i]);
18964 }
18965 propagate(out, carry);
18966}
18967 
18968static void sub(mg_fe out, const mg_fe a, const mg_fe b) {
18969 unsigned i;
18970 sdlimb_t carry = -38;
18971 for (i = 0; i < NLIMBS; i++) {
18972 carry = carry + a[i] - b[i];
18973 out[i] = (limb_t) carry;
18974 carry >>= X25519_WBITS;
18975 }
18976 propagate(out, (limb_t) (1 + carry));
18977}
18978 
18979// `b` can contain less than 8 limbs, thus we use `limb_t *` instead of `mg_fe`
18980// to avoid build warnings
18981static void mul(mg_fe out, const mg_fe a, const limb_t *b, unsigned nb) {
18982 limb_t accum[2 * NLIMBS] = {0};
18983 unsigned i, j;
18984 
18985 limb_t carry2;
18986 for (i = 0; i < nb; i++) {
18987 limb_t mand = b[i];
18988 carry2 = 0;
18989 for (j = 0; j < NLIMBS; j++) {
18990 limb_t tmp; // "a" may be misaligned
18991 memcpy(&tmp, &a[j], sizeof(tmp)); // So make an aligned copy
18992 accum[i + j] = umaal(&carry2, accum[i + j], mand, tmp);
18993 }
18994 accum[i + j] = carry2;
18995 }
18996 
18997 carry2 = 0;
18998 for (j = 0; j < NLIMBS; j++) {
18999 out[j] = umaal(&carry2, accum[j], 38, accum[j + NLIMBS]);
19000 }
19001 propagate(out, carry2);
19002}
19003 
19004static void sqr(mg_fe out, const mg_fe a) {
19005 mul(out, a, a, NLIMBS);
19006}
19007static void mul1(mg_fe out, const mg_fe a) {
19008 mul(out, a, out, NLIMBS);
19009}
19010static void sqr1(mg_fe a) {
19011 mul1(a, a);
19012}
19013 
19014static void condswap(limb_t a[2 * NLIMBS], limb_t b[2 * NLIMBS],
19015 limb_t doswap) {
19016 unsigned i;
19017 for (i = 0; i < 2 * NLIMBS; i++) {
19018 limb_t xor_ab = (a[i] ^ b[i]) & doswap;
19019 a[i] ^= xor_ab;
19020 b[i] ^= xor_ab;
19021 }
19022}
19023 
19024// Canonicalize a field element x, reducing it to the least residue which is
19025// congruent to it mod 2^255-19
19026// - Precondition: x < 2^255 + 1 word
19027static limb_t canon(mg_fe x) {
19028 // First, add 19.
19029 unsigned i;
19030 limb_t carry0 = 19;
19031 limb_t res;
19032 sdlimb_t carry;
19033 for (i = 0; i < NLIMBS; i++) {
19034 x[i] = adc0(&carry0, x[i]);
19035 }
19036 propagate(x, carry0);
19037 
19038 // Here, 19 <= x2 < 2^255
19039 // - This is because we added 19, so before propagate it can't be less
19040 // than 19. After propagate, it still can't be less than 19, because if
19041 // propagate does anything it adds 19.
19042 // - We know that the high bit must be clear, because either the input was ~
19043 // 2^255 + one word + 19 (in which case it propagates to at most 2 words) or
19044 // it was < 2^255. So now, if we subtract 19, we will get back to something in
19045 // [0,2^255-19).
19046 carry = -19;
19047 res = 0;
19048 for (i = 0; i < NLIMBS; i++) {
19049 carry += x[i];
19050 res |= x[i] = (limb_t) carry;
19051 carry >>= X25519_WBITS;
19052 }
19053 return (limb_t) (((dlimb_t) res - 1) >> X25519_WBITS);
19054}
19055 
19056static const limb_t a24[1] = {121665};
19057 
19058static void ladder_part1(mg_fe xs[5]) {
19059 limb_t *x2 = xs[0], *z2 = xs[1], *x3 = xs[2], *z3 = xs[3], *t1 = xs[4];
19060 add(t1, x2, z2); // t1 = A
19061 sub(z2, x2, z2); // z2 = B
19062 add(x2, x3, z3); // x2 = C
19063 sub(z3, x3, z3); // z3 = D
19064 mul1(z3, t1); // z3 = DA
19065 mul1(x2, z2); // x3 = BC
19066 add(x3, z3, x2); // x3 = DA+CB
19067 sub(z3, z3, x2); // z3 = DA-CB
19068 sqr1(t1); // t1 = AA
19069 sqr1(z2); // z2 = BB
19070 sub(x2, t1, z2); // x2 = E = AA-BB
19071 mul(z2, x2, a24, sizeof(a24) / sizeof(a24[0])); // z2 = E*a24
19072 add(z2, z2, t1); // z2 = E*a24 + AA
19073}
19074 
19075static void ladder_part2(mg_fe xs[5], const mg_fe x1) {
19076 limb_t *x2 = xs[0], *z2 = xs[1], *x3 = xs[2], *z3 = xs[3], *t1 = xs[4];
19077 sqr1(z3); // z3 = (DA-CB)^2
19078 mul1(z3, x1); // z3 = x1 * (DA-CB)^2
19079 sqr1(x3); // x3 = (DA+CB)^2
19080 mul1(z2, x2); // z2 = AA*(E*a24+AA)
19081 sub(x2, t1, x2); // x2 = BB again
19082 mul1(x2, t1); // x2 = AA*BB
19083}
19084 
19085static void x25519_core(mg_fe xs[5], const uint8_t scalar[X25519_BYTES],
19086 const uint8_t *x1, int clamp) {
19087 int i;
19088 mg_fe x1_limbs;
19089 limb_t swap = 0;
19090 limb_t *x2 = xs[0], *x3 = xs[2], *z3 = xs[3];
19091 memset(xs, 0, 4 * sizeof(mg_fe));
19092 x2[0] = z3[0] = 1;
19093 for (i = 0; i < NLIMBS; i++) {
19094 x3[i] = x1_limbs[i] =
19095 MG_U32(x1[i * 4 + 3], x1[i * 4 + 2], x1[i * 4 + 1], x1[i * 4]);
19096 }
19097 
19098 for (i = 255; i >= 0; i--) {
19099 uint8_t bytei = scalar[i / 8];
19100 limb_t doswap;
19101 if (clamp) {
19102 if (i / 8 == 0) {
19103 bytei &= (uint8_t) ~7U;
19104 } else if (i / 8 == X25519_BYTES - 1) {
19105 bytei &= 0x7F;
19106 bytei |= 0x40;
19107 }
19108 }
19109 doswap = 0 - (limb_t) ((bytei >> (i % 8)) & 1);
19110 condswap(x2, x3, swap ^ doswap);
19111 swap = doswap;
19112 
19113 ladder_part1(xs);
19114 ladder_part2(xs, (const limb_t *) x1_limbs);
19115 }
19116 condswap(x2, x3, swap);
19117}
19118 
19119int mg_tls_x25519(uint8_t out[X25519_BYTES], const uint8_t scalar[X25519_BYTES],
19120 const uint8_t x1[X25519_BYTES], int clamp) {
19121 int i, ret;
19122 mg_fe xs[5], out_limbs;
19123 limb_t *x2, *z2, *z3, *prev;
19124 static const struct {
19125 uint8_t a, c, n;
19126 } steps[13] = {{2, 1, 1}, {2, 1, 1}, {4, 2, 3}, {2, 4, 6}, {3, 1, 1},
19127 {3, 2, 12}, {4, 3, 25}, {2, 3, 25}, {2, 4, 50}, {3, 2, 125},
19128 {3, 1, 2}, {3, 1, 2}, {3, 1, 1}};
19129 x25519_core(xs, scalar, x1, clamp);
19130 
19131 // Precomputed inversion chain
19132 x2 = xs[0];
19133 z2 = xs[1];
19134 z3 = xs[3];
19135 
19136 prev = z2;
19137 for (i = 0; i < 13; i++) {
19138 int j;
19139 limb_t *a = xs[steps[i].a];
19140 for (j = steps[i].n; j > 0; j--) {
19141 sqr(a, prev);
19142 prev = a;
19143 }
19144 mul1(a, xs[steps[i].c]);
19145 }
19146 
19147 // Here prev = z3
19148 // x2 /= z2
19149 mul(out_limbs, x2, z3, NLIMBS);
19150 ret = (int) canon(out_limbs);
19151 if (!clamp) ret = 0;
19152 for (i = 0; i < NLIMBS; i++) {
19153 uint32_t n = out_limbs[i];
19154 out[i * 4] = (uint8_t) (n & 0xff);
19155 out[i * 4 + 1] = (uint8_t) ((n >> 8) & 0xff);
19156 out[i * 4 + 2] = (uint8_t) ((n >> 16) & 0xff);
19157 out[i * 4 + 3] = (uint8_t) ((n >> 24) & 0xff);
19158 }
19159 return ret;
19160}
19161 
19162#endif
19163 
19164#ifdef MG_ENABLE_LINES
19165#line 1 "src/url.c"
19166#endif
19167 
19168 
19169struct url {
19170 size_t key, user, pass, host, port, uri, end;
19171};
19172 
19173int mg_url_is_ssl(const char *url) {
19174 return strncmp(url, "wss:", 4) == 0 || strncmp(url, "https:", 6) == 0 ||
19175 strncmp(url, "mqtts:", 6) == 0 || strncmp(url, "ssl:", 4) == 0 ||
19176 strncmp(url, "tls:", 4) == 0 || strncmp(url, "tcps:", 5) == 0;
19177}
19178 
19179static struct url urlparse(const char *url) {
19180 size_t i;
19181 struct url u;
19182 memset(&u, 0, sizeof(u));
19183 for (i = 0; url[i] != '\0'; i++) {
19184 if (url[i] == '/' && i > 0 && u.host == 0 && url[i - 1] == '/') {
19185 u.host = i + 1;
19186 u.port = 0;
19187 } else if (url[i] == ']') {
19188 u.port = 0; // IPv6 URLs, like http://[::1]/bar
19189 } else if (url[i] == ':' && u.port == 0 && u.uri == 0) {
19190 u.port = i + 1;
19191 } else if (url[i] == '@' && u.user == 0 && u.pass == 0 && u.uri == 0) {
19192 u.user = u.host;
19193 u.pass = u.port;
19194 u.host = i + 1;
19195 u.port = 0;
19196 } else if (url[i] == '/' && u.host && u.uri == 0) {
19197 u.uri = i;
19198 }
19199 }
19200 u.end = i;
19201#if 0
19202 printf("[%s] %d %d %d %d %d\n", url, u.user, u.pass, u.host, u.port, u.uri);
19203#endif
19204 return u;
19205}
19206 
19207struct mg_str mg_url_host(const char *url) {
19208 struct url u = urlparse(url);
19209 size_t n = u.port ? u.port - u.host - 1
19210 : u.uri ? u.uri - u.host
19211 : u.end - u.host;
19212 struct mg_str s = mg_str_n(url + u.host, n);
19213 return s;
19214}
19215 
19216const char *mg_url_uri(const char *url) {
19217 struct url u = urlparse(url);
19218 return u.uri ? url + u.uri : "/";
19219}
19220 
19221unsigned short mg_url_port(const char *url) {
19222 struct url u = urlparse(url);
19223 unsigned short port = 0;
19224 if (strncmp(url, "http:", 5) == 0 || strncmp(url, "ws:", 3) == 0) port = 80;
19225 if (strncmp(url, "wss:", 4) == 0 || strncmp(url, "https:", 6) == 0)
19226 port = 443;
19227 if (strncmp(url, "mqtt:", 5) == 0) port = 1883;
19228 if (strncmp(url, "mqtts:", 6) == 0) port = 8883;
19229 if (u.port) port = (unsigned short) atoi(url + u.port);
19230 return port;
19231}
19232 
19233struct mg_str mg_url_user(const char *url) {
19234 struct url u = urlparse(url);
19235 struct mg_str s = mg_str("");
19236 if (u.user && (u.pass || u.host)) {
19237 size_t n = u.pass ? u.pass - u.user - 1 : u.host - u.user - 1;
19238 s = mg_str_n(url + u.user, n);
19239 }
19240 return s;
19241}
19242 
19243struct mg_str mg_url_pass(const char *url) {
19244 struct url u = urlparse(url);
19245 struct mg_str s = mg_str_n("", 0UL);
19246 if (u.pass && u.host) {
19247 size_t n = u.host - u.pass - 1;
19248 s = mg_str_n(url + u.pass, n);
19249 }
19250 return s;
19251}
19252 
19253#ifdef MG_ENABLE_LINES
19254#line 1 "src/util.c"
19255#endif
19256 
19257 
19258 
19259// Not using memset for zeroing memory, cause it can be dropped by compiler
19260// See https://github.com/cesanta/mongoose/pull/1265
19261void mg_bzero(volatile unsigned char *buf, size_t len) {
19262 if (buf != NULL) {
19263 while (len--) *buf++ = 0;
19264 }
19265}
19266 
19267#if MG_ENABLE_CUSTOM_RANDOM
19268#else
19269bool mg_random(void *buf, size_t len) {
19270 bool success = false;
19271 unsigned char *p = (unsigned char *) buf;
19272#if MG_ARCH == MG_ARCH_ESP32
19273 while (len--) *p++ = (unsigned char) (esp_random() & 255);
19274 success = true;
19275#elif MG_ARCH == MG_ARCH_PICOSDK
19276 while (len--) *p++ = (unsigned char) (get_rand_32() & 255);
19277 success = true;
19278#elif MG_ARCH == MG_ARCH_WIN32
19279#if defined(_MSC_VER) && _MSC_VER < 1700
19280 static bool initialised = false;
19281 static HCRYPTPROV hProv;
19282 // CryptGenRandom() implementation earlier than 2008 is weak, see
19283 // https://en.wikipedia.org/wiki/CryptGenRandom
19284 if (!initialised) {
19285 initialised = CryptAcquireContext(&hProv, NULL, NULL, PROV_RSA_FULL,
19286 CRYPT_VERIFYCONTEXT);
19287 }
19288 if (initialised) success = CryptGenRandom(hProv, len, p);
19289#else
19290 size_t i;
19291 for (i = 0; i < len; i++) {
19292 unsigned int rand_v;
19293 if (rand_s(&rand_v) == 0) {
19294 p[i] = (unsigned char) (rand_v & 255);
19295 } else {
19296 break;
19297 }
19298 }
19299 success = (i == len);
19300#endif
19301 
19302#elif MG_ARCH == MG_ARCH_UNIX
19303 FILE *fp = fopen("/dev/urandom", "rb");
19304 if (fp != NULL) {
19305 if (fread(buf, 1, len, fp) == len) success = true;
19306 fclose(fp);
19307 }
19308#endif
19309 // If everything above did not work, fallback to a pseudo random generator
19310 if (success == false) {
19311 MG_ERROR(("Weak RNG: using rand()"));
19312 while (len--) *p++ = (unsigned char) (rand() & 255);
19313 }
19314 return success;
19315}
19316#endif
19317 
19318char *mg_random_str(char *buf, size_t len) {
19319 size_t i;
19320 mg_random(buf, len);
19321 for (i = 0; i < len; i++) {
19322 uint8_t c = ((uint8_t *) buf)[i] % 62U;
19323 buf[i] = i == len - 1 ? (char) '\0' // 0-terminate last byte
19324 : c < 26 ? (char) ('a' + c) // lowercase
19325 : c < 52 ? (char) ('A' + c - 26) // uppercase
19326 : (char) ('0' + c - 52); // numeric
19327 }
19328 return buf;
19329}
19330 
19331uint32_t mg_crc32(uint32_t crc, const char *buf, size_t len) {
19332 static const uint32_t crclut[16] = {
19333 // table for polynomial 0xEDB88320 (reflected)
19334 0x00000000, 0x1DB71064, 0x3B6E20C8, 0x26D930AC, 0x76DC4190, 0x6B6B51F4,
19335 0x4DB26158, 0x5005713C, 0xEDB88320, 0xF00F9344, 0xD6D6A3E8, 0xCB61B38C,
19336 0x9B64C2B0, 0x86D3D2D4, 0xA00AE278, 0xBDBDF21C};
19337 crc = ~crc;
19338 while (len--) {
19339 uint8_t b = *(uint8_t *) buf++;
19340 crc = crclut[(crc ^ b) & 0x0F] ^ (crc >> 4);
19341 crc = crclut[(crc ^ (b >> 4)) & 0x0F] ^ (crc >> 4);
19342 }
19343 return ~crc;
19344}
19345 
19346static int isbyte(int n) {
19347 return n >= 0 && n <= 255;
19348}
19349 
19350static int parse_net(const char *spec, uint32_t *net, uint32_t *mask) {
19351 int n, a, b, c, d, slash = 32, len = 0;
19352 if ((sscanf(spec, "%d.%d.%d.%d/%d%n", &a, &b, &c, &d, &slash, &n) == 5 ||
19353 sscanf(spec, "%d.%d.%d.%d%n", &a, &b, &c, &d, &n) == 4) &&
19354 isbyte(a) && isbyte(b) && isbyte(c) && isbyte(d) && slash >= 0 &&
19355 slash < 33) {
19356 len = n;
19357 *net = ((uint32_t) a << 24) | ((uint32_t) b << 16) | ((uint32_t) c << 8) |
19358 (uint32_t) d;
19359 *mask = slash ? (uint32_t) (0xffffffffU << (32 - slash)) : (uint32_t) 0;
19360 }
19361 return len;
19362}
19363 
19364int mg_check_ip_acl(struct mg_str acl, struct mg_addr *remote_ip) {
19365 struct mg_str entry;
19366 int allowed = acl.len == 0 ? '+' : '-'; // If any ACL is set, deny by default
19367 uint32_t remote_ip4;
19368 if (remote_ip->is_ip6) {
19369 return -1; // TODO(): handle IPv6 ACL and addresses
19370 } else { // IPv4
19371 memcpy((void *) &remote_ip4, remote_ip->ip, sizeof(remote_ip4));
19372 while (mg_span(acl, &entry, &acl, ',')) {
19373 uint32_t net, mask;
19374 if (entry.buf[0] != '+' && entry.buf[0] != '-') return -1;
19375 if (parse_net(&entry.buf[1], &net, &mask) == 0) return -2;
19376 if ((mg_ntohl(remote_ip4) & mask) == net) allowed = entry.buf[0];
19377 }
19378 }
19379 return allowed == '+';
19380}
19381 
19382bool mg_path_is_sane(const struct mg_str path) {
19383 const char *s = path.buf;
19384 size_t n = path.len;
19385 if (path.buf[0] == '.' && path.buf[1] == '.') return false; // Starts with ..
19386 for (; s[0] != '\0' && n > 0; s++, n--) {
19387 if ((s[0] == '/' || s[0] == '\\') && n >= 2) { // Subdir?
19388 if (s[1] == '.' && s[2] == '.') return false; // Starts with ..
19389 }
19390 }
19391 return true;
19392}
19393 
19394#if MG_ENABLE_CUSTOM_MILLIS
19395#else
19396uint64_t mg_millis(void) {
19397#if MG_ARCH == MG_ARCH_WIN32
19398 return GetTickCount();
19399#elif MG_ARCH == MG_ARCH_PICOSDK
19400 return time_us_64() / 1000;
19401#elif MG_ARCH == MG_ARCH_ESP8266 || MG_ARCH == MG_ARCH_ESP32 || \
19402 MG_ARCH == MG_ARCH_FREERTOS
19403 return xTaskGetTickCount() * portTICK_PERIOD_MS;
19404#elif MG_ARCH == MG_ARCH_AZURERTOS
19405 return tx_time_get() * (1000 /* MS per SEC */ / TX_TIMER_TICKS_PER_SECOND);
19406#elif MG_ARCH == MG_ARCH_TIRTOS
19407 return (uint64_t) Clock_getTicks();
19408#elif MG_ARCH == MG_ARCH_ZEPHYR
19409 return (uint64_t) k_uptime_get();
19410#elif MG_ARCH == MG_ARCH_CMSIS_RTOS1
19411 return (uint64_t) rt_time_get();
19412#elif MG_ARCH == MG_ARCH_CMSIS_RTOS2
19413 return (uint64_t) ((osKernelGetTickCount() * 1000) / osKernelGetTickFreq());
19414#elif MG_ARCH == MG_ARCH_RTTHREAD
19415 return (uint64_t) ((rt_tick_get() * 1000) / RT_TICK_PER_SECOND);
19416#elif MG_ARCH == MG_ARCH_UNIX && defined(__APPLE__)
19417 // Apple CLOCK_MONOTONIC_RAW is equivalent to CLOCK_BOOTTIME on linux
19418 // Apple CLOCK_UPTIME_RAW is equivalent to CLOCK_MONOTONIC_RAW on linux
19419 return clock_gettime_nsec_np(CLOCK_UPTIME_RAW) / 1000000;
19420#elif MG_ARCH == MG_ARCH_UNIX
19421 struct timespec ts = {0, 0};
19422 // See #1615 - prefer monotonic clock
19423#if defined(CLOCK_MONOTONIC_RAW)
19424 // Raw hardware-based time that is not subject to NTP adjustment
19425 clock_gettime(CLOCK_MONOTONIC_RAW, &ts);
19426#elif defined(CLOCK_MONOTONIC)
19427 // Affected by the incremental adjustments performed by adjtime and NTP
19428 clock_gettime(CLOCK_MONOTONIC, &ts);
19429#else
19430 // Affected by discontinuous jumps in the system time and by the incremental
19431 // adjustments performed by adjtime and NTP
19432 clock_gettime(CLOCK_REALTIME, &ts);
19433#endif
19434 return ((uint64_t) ts.tv_sec * 1000 + (uint64_t) ts.tv_nsec / 1000000);
19435#elif defined(ARDUINO)
19436 return (uint64_t) millis();
19437#else
19438 return (uint64_t) (time(NULL) * 1000);
19439#endif
19440}
19441#endif
19442 
19443// network format equates big endian order
19444uint16_t mg_ntohs(uint16_t net) {
19445 return MG_LOAD_BE16(&net);
19446}
19447 
19448uint32_t mg_ntohl(uint32_t net) {
19449 return MG_LOAD_BE32(&net);
19450}
19451 
19452void mg_delayms(unsigned int ms) {
19453 uint64_t to = mg_millis() + ms + 1;
19454 while (mg_millis() < to) (void) 0;
19455}
19456 
19457#ifdef MG_ENABLE_LINES
19458#line 1 "src/wifi_dummy.c"
19459#endif
19460 
19461 
19462#if (!defined(MG_ENABLE_DRIVER_PICO_W) || !MG_ENABLE_DRIVER_PICO_W) && \
19463 (!defined(MG_ENABLE_DRIVER_CYW) || !MG_ENABLE_DRIVER_CYW)
19464 
19465bool mg_wifi_scan(void) {
19466 MG_ERROR(("No Wi-Fi driver enabled"));
19467 return false;
19468}
19469 
19470bool mg_wifi_connect(char *ssid, char *pass) {
19471 (void) ssid;
19472 (void) pass;
19473 return mg_wifi_scan();
19474}
19475 
19476bool mg_wifi_disconnect(void) {
19477 return mg_wifi_scan();
19478}
19479 
19480bool mg_wifi_ap_start(char *ssid, char *pass, unsigned int channel) {
19481 (void) ssid;
19482 (void) pass;
19483 (void) channel;
19484 return mg_wifi_scan();
19485}
19486 
19487bool mg_wifi_ap_stop(void) {
19488 return mg_wifi_scan();
19489}
19490 
19491#endif
19492 
19493#ifdef MG_ENABLE_LINES
19494#line 1 "src/ws.c"
19495#endif
19496 
19497 
19498 
19499 
19500 
19501 
19502 
19503 
19504 
19505 
19506 
19507struct ws_msg {
19508 uint8_t flags;
19509 size_t header_len;
19510 size_t data_len;
19511};
19512 
19513size_t mg_ws_vprintf(struct mg_connection *c, int op, const char *fmt,
19514 va_list *ap) {
19515 size_t len = c->send.len;
19516 size_t n = mg_vxprintf(mg_pfn_iobuf, &c->send, fmt, ap);
19517 mg_ws_wrap(c, c->send.len - len, op);
19518 return n;
19519}
19520 
19521size_t mg_ws_printf(struct mg_connection *c, int op, const char *fmt, ...) {
19522 size_t len = 0;
19523 va_list ap;
19524 va_start(ap, fmt);
19525 len = mg_ws_vprintf(c, op, fmt, &ap);
19526 va_end(ap);
19527 return len;
19528}
19529 
19530static void ws_handshake(struct mg_connection *c, const struct mg_str *wskey,
19531 const struct mg_str *wsproto, const char *fmt,
19532 va_list *ap) {
19533 const char *magic = "258EAFA5-E914-47DA-95CA-C5AB0DC85B11";
19534 unsigned char sha[20], b64_sha[30];
19535 
19536 mg_sha1_ctx sha_ctx;
19537 mg_sha1_init(&sha_ctx);
19538 mg_sha1_update(&sha_ctx, (unsigned char *) wskey->buf, wskey->len);
19539 mg_sha1_update(&sha_ctx, (unsigned char *) magic, 36);
19540 mg_sha1_final(sha, &sha_ctx);
19541 mg_base64_encode(sha, sizeof(sha), (char *) b64_sha, sizeof(b64_sha));
19542 mg_xprintf(mg_pfn_iobuf, &c->send,
19543 "HTTP/1.1 101 Switching Protocols\r\n"
19544 "Upgrade: websocket\r\n"
19545 "Connection: Upgrade\r\n"
19546 "Sec-WebSocket-Accept: %s\r\n",
19547 b64_sha);
19548 if (fmt != NULL) mg_vxprintf(mg_pfn_iobuf, &c->send, fmt, ap);
19549 if (wsproto != NULL) {
19550 mg_printf(c, "Sec-WebSocket-Protocol: %.*s\r\n", (int) wsproto->len,
19551 wsproto->buf);
19552 }
19553 mg_send(c, "\r\n", 2);
19554}
19555 
19556static uint32_t be32(const uint8_t *p) {
19557 return (((uint32_t) p[3]) << 0) | (((uint32_t) p[2]) << 8) |
19558 (((uint32_t) p[1]) << 16) | (((uint32_t) p[0]) << 24);
19559}
19560 
19561static size_t ws_process(uint8_t *buf, size_t len, struct ws_msg *msg) {
19562 size_t i, n = 0, mask_len = 0;
19563 memset(msg, 0, sizeof(*msg));
19564 if (len >= 2) {
19565 n = buf[1] & 0x7f; // Frame length
19566 mask_len = buf[1] & 128 ? 4 : 0; // last bit is a mask bit
19567 msg->flags = buf[0];
19568 if (n < 126 && len >= mask_len) {
19569 msg->data_len = n;
19570 msg->header_len = 2 + mask_len;
19571 } else if (n == 126 && len >= 4 + mask_len) {
19572 msg->header_len = 4 + mask_len;
19573 msg->data_len = (((size_t) buf[2]) << 8) | buf[3];
19574 } else if (len >= 10 + mask_len) {
19575 msg->header_len = 10 + mask_len;
19576 msg->data_len =
19577 (size_t) (((uint64_t) be32(buf + 2) << 32) + be32(buf + 6));
19578 }
19579 }
19580 // Sanity check, and integer overflow protection for the boundary check below
19581 // data_len should not be larger than 1 Gb
19582 if (msg->data_len > 1024 * 1024 * 1024) return 0;
19583 if (msg->header_len + msg->data_len > len) return 0;
19584 if (mask_len > 0) {
19585 uint8_t *p = buf + msg->header_len, *m = p - mask_len;
19586 for (i = 0; i < msg->data_len; i++) p[i] ^= m[i & 3];
19587 }
19588 return msg->header_len + msg->data_len;
19589}
19590 
19591static size_t mkhdr(size_t len, int op, bool is_client, uint8_t *buf) {
19592 size_t n = 0;
19593 buf[0] = (uint8_t) (op | 128);
19594 if (len < 126) {
19595 buf[1] = (unsigned char) len;
19596 n = 2;
19597 } else if (len < 65536) {
19598 uint16_t tmp = mg_htons((uint16_t) len);
19599 buf[1] = 126;
19600 memcpy(&buf[2], &tmp, sizeof(tmp));
19601 n = 4;
19602 } else {
19603 uint32_t tmp;
19604 buf[1] = 127;
19605 tmp = mg_htonl((uint32_t) (((uint64_t) len) >> 32));
19606 memcpy(&buf[2], &tmp, sizeof(tmp));
19607 tmp = mg_htonl((uint32_t) (len & 0xffffffffU));
19608 memcpy(&buf[6], &tmp, sizeof(tmp));
19609 n = 10;
19610 }
19611 if (is_client) {
19612 buf[1] |= 1 << 7; // Set masking flag
19613 mg_random(&buf[n], 4);
19614 n += 4;
19615 }
19616 return n;
19617}
19618 
19619static void mg_ws_mask(struct mg_connection *c, size_t len) {
19620 if (c->is_client && c->send.buf != NULL) {
19621 size_t i;
19622 uint8_t *p = c->send.buf + c->send.len - len, *mask = p - 4;
19623 for (i = 0; i < len; i++) p[i] ^= mask[i & 3];
19624 }
19625}
19626 
19627size_t mg_ws_send(struct mg_connection *c, const void *buf, size_t len,
19628 int op) {
19629 uint8_t header[14];
19630 size_t header_len = mkhdr(len, op, c->is_client, header);
19631 if (!mg_send(c, header, header_len)) return 0;
19632 if (!mg_send(c, buf, len)) return header_len;
19633 MG_VERBOSE(("WS out: %d [%.*s]", (int) len, (int) len, buf));
19634 mg_ws_mask(c, len);
19635 return header_len + len;
19636}
19637 
19638static bool mg_ws_client_handshake(struct mg_connection *c) {
19639 int n = mg_http_get_request_len(c->recv.buf, c->recv.len);
19640 if (n < 0) {
19641 mg_error(c, "not http"); // Some just, not an HTTP request
19642 } else if (n > 0) {
19643 if (n < 15 || memcmp(c->recv.buf + 9, "101", 3) != 0) {
19644 mg_error(c, "ws handshake error");
19645 } else {
19646 struct mg_http_message hm;
19647 if (mg_http_parse((char *) c->recv.buf, c->recv.len, &hm)) {
19648 c->is_websocket = 1;
19649 mg_call(c, MG_EV_WS_OPEN, &hm);
19650 } else {
19651 mg_error(c, "ws handshake error");
19652 }
19653 }
19654 mg_iobuf_del(&c->recv, 0, (size_t) n);
19655 } else {
19656 return true; // Request is not yet received, quit event handler
19657 }
19658 return false; // Continue event handler
19659}
19660 
19661static void mg_ws_cb(struct mg_connection *c, int ev, void *ev_data) {
19662 struct ws_msg msg;
19663 size_t ofs = (size_t) c->pfn_data;
19664 
19665 // assert(ofs < c->recv.len);
19666 if (ev == MG_EV_READ) {
19667 if (c->is_client && !c->is_websocket && mg_ws_client_handshake(c)) return;
19668 
19669 while (ws_process(c->recv.buf + ofs, c->recv.len - ofs, &msg) > 0) {
19670 char *s = (char *) c->recv.buf + ofs + msg.header_len;
19671 struct mg_ws_message m = {{s, msg.data_len}, msg.flags};
19672 size_t len = msg.header_len + msg.data_len;
19673 uint8_t final = msg.flags & 128, op = msg.flags & 15;
19674 // MG_VERBOSE ("fin %d op %d len %d [%.*s]", final, op,
19675 // (int) m.data.len, (int) m.data.len, m.data.buf));
19676 switch (op) {
19677 case WEBSOCKET_OP_CONTINUE:
19678 mg_call(c, MG_EV_WS_CTL, &m);
19679 break;
19680 case WEBSOCKET_OP_PING:
19681 MG_DEBUG(("%s", "WS PONG"));
19682 mg_ws_send(c, s, msg.data_len, WEBSOCKET_OP_PONG);
19683 mg_call(c, MG_EV_WS_CTL, &m);
19684 break;
19685 case WEBSOCKET_OP_PONG:
19686 mg_call(c, MG_EV_WS_CTL, &m);
19687 break;
19688 case WEBSOCKET_OP_TEXT:
19689 case WEBSOCKET_OP_BINARY:
19690 if (final) mg_call(c, MG_EV_WS_MSG, &m);
19691 break;
19692 case WEBSOCKET_OP_CLOSE:
19693 MG_DEBUG(("%lu WS CLOSE", c->id));
19694 mg_call(c, MG_EV_WS_CTL, &m);
19695 // Echo the payload of the received CLOSE message back to the sender
19696 mg_ws_send(c, m.data.buf, m.data.len, WEBSOCKET_OP_CLOSE);
19697 c->is_draining = 1;
19698 break;
19699 default:
19700 // Per RFC6455, close conn when an unknown op is recvd
19701 mg_error(c, "unknown WS op %d", op);
19702 break;
19703 }
19704 
19705 // Handle fragmented frames: strip header, keep in c->recv
19706 if (final == 0 || op == 0) {
19707 if (op) ofs++, len--, msg.header_len--; // First frame
19708 mg_iobuf_del(&c->recv, ofs, msg.header_len); // Strip header
19709 len -= msg.header_len;
19710 ofs += len;
19711 c->pfn_data = (void *) ofs;
19712 // MG_INFO(("FRAG %d [%.*s]", (int) ofs, (int) ofs, c->recv.buf));
19713 }
19714 // Remove non-fragmented frame
19715 if (final && op) mg_iobuf_del(&c->recv, ofs, len);
19716 // Last chunk of the fragmented frame
19717 if (final && !op) {
19718 m.flags = c->recv.buf[0];
19719 m.data = mg_str_n((char *) &c->recv.buf[1], (size_t) (ofs - 1));
19720 mg_call(c, MG_EV_WS_MSG, &m);
19721 mg_iobuf_del(&c->recv, 0, ofs);
19722 ofs = 0;
19723 c->pfn_data = NULL;
19724 }
19725 }
19726 }
19727 (void) ev_data;
19728}
19729 
19730struct mg_connection *mg_ws_connect(struct mg_mgr *mgr, const char *url,
19731 mg_event_handler_t fn, void *fn_data,
19732 const char *fmt, ...) {
19733 struct mg_connection *c = mg_connect(mgr, url, fn, fn_data);
19734 if (c != NULL) {
19735 char nonce[16], key[30];
19736 struct mg_str host = mg_url_host(url);
19737 mg_random(nonce, sizeof(nonce));
19738 mg_base64_encode((unsigned char *) nonce, sizeof(nonce), key, sizeof(key));
19739 mg_xprintf(mg_pfn_iobuf, &c->send,
19740 "GET %s HTTP/1.1\r\n"
19741 "Upgrade: websocket\r\n"
19742 "Host: %.*s\r\n"
19743 "Connection: Upgrade\r\n"
19744 "Sec-WebSocket-Version: 13\r\n"
19745 "Sec-WebSocket-Key: %s\r\n",
19746 mg_url_uri(url), (int) host.len, host.buf, key);
19747 if (fmt != NULL) {
19748 va_list ap;
19749 va_start(ap, fmt);
19750 mg_vxprintf(mg_pfn_iobuf, &c->send, fmt, &ap);
19751 va_end(ap);
19752 }
19753 mg_xprintf(mg_pfn_iobuf, &c->send, "\r\n");
19754 c->pfn = mg_ws_cb;
19755 c->pfn_data = NULL;
19756 }
19757 return c;
19758}
19759 
19760void mg_ws_upgrade(struct mg_connection *c, struct mg_http_message *hm,
19761 const char *fmt, ...) {
19762 struct mg_str *wskey = mg_http_get_header(hm, "Sec-WebSocket-Key");
19763 c->pfn = mg_ws_cb;
19764 c->pfn_data = NULL;
19765 if (wskey == NULL) {
19766 mg_http_reply(c, 426, "", "WS upgrade expected\n");
19767 c->is_draining = 1;
19768 } else {
19769 struct mg_str *wsproto = mg_http_get_header(hm, "Sec-WebSocket-Protocol");
19770 va_list ap;
19771 va_start(ap, fmt);
19772 ws_handshake(c, wskey, wsproto, fmt, &ap);
19773 va_end(ap);
19774 c->is_websocket = 1;
19775 c->is_resp = 0;
19776 mg_call(c, MG_EV_WS_OPEN, hm);
19777 }
19778}
19779 
19780size_t mg_ws_wrap(struct mg_connection *c, size_t len, int op) {
19781 uint8_t header[14], *p;
19782 size_t header_len = mkhdr(len, op, c->is_client, header);
19783 
19784 // NOTE: order of operations is important!
19785 if (mg_iobuf_add(&c->send, c->send.len, NULL, header_len) != 0) {
19786 p = &c->send.buf[c->send.len - len]; // p points to data
19787 memmove(p, p - header_len, len); // Shift data
19788 memcpy(p - header_len, header, header_len); // Prepend header
19789 mg_ws_mask(c, len); // Mask data
19790 }
19791 return c->send.len;
19792}
19793 
19794#ifdef MG_ENABLE_LINES
19795#line 1 "src/drivers/cmsis.c"
19796#endif
19797// https://arm-software.github.io/CMSIS_5/Driver/html/index.html
19798 
19799#if MG_ENABLE_TCPIP && defined(MG_ENABLE_DRIVER_CMSIS) && MG_ENABLE_DRIVER_CMSIS
19800 
19801 
19802 
19803 
19804 
19805extern ARM_DRIVER_ETH_MAC Driver_ETH_MAC0;
19806extern ARM_DRIVER_ETH_PHY Driver_ETH_PHY0;
19807 
19808static struct mg_tcpip_if *s_ifp;
19809 
19810static void mac_cb(uint32_t);
19811static bool cmsis_init(struct mg_tcpip_if *);
19812static bool cmsis_poll(struct mg_tcpip_if *, bool);
19813static size_t cmsis_tx(const void *, size_t, struct mg_tcpip_if *);
19814static size_t cmsis_rx(void *, size_t, struct mg_tcpip_if *);
19815 
19816struct mg_tcpip_driver mg_tcpip_driver_cmsis = {cmsis_init, cmsis_tx, NULL,
19817 cmsis_poll};
19818 
19819static bool cmsis_init(struct mg_tcpip_if *ifp) {
19820 ARM_ETH_MAC_ADDR addr;
19821 s_ifp = ifp;
19822 
19823 ARM_DRIVER_ETH_MAC *mac = &Driver_ETH_MAC0;
19824 ARM_DRIVER_ETH_PHY *phy = &Driver_ETH_PHY0;
19825 ARM_ETH_MAC_CAPABILITIES cap = mac->GetCapabilities();
19826 if (mac->Initialize(mac_cb) != ARM_DRIVER_OK) return false;
19827 if (phy->Initialize(mac->PHY_Read, mac->PHY_Write) != ARM_DRIVER_OK)
19828 return false;
19829 if (cap.event_rx_frame == 0) // polled mode driver
19830 mg_tcpip_driver_cmsis.rx = cmsis_rx;
19831 mac->PowerControl(ARM_POWER_FULL);
19832 if (cap.mac_address) { // driver provides MAC address
19833 mac->GetMacAddress(&addr);
19834 memcpy(ifp->mac, &addr, sizeof(ifp->mac));
19835 } else { // we provide MAC address
19836 memcpy(&addr, ifp->mac, sizeof(addr));
19837 mac->SetMacAddress(&addr);
19838 }
19839 phy->PowerControl(ARM_POWER_FULL);
19840 phy->SetInterface(cap.media_interface);
19841 phy->SetMode(ARM_ETH_PHY_AUTO_NEGOTIATE);
19842 return true;
19843}
19844 
19845static size_t cmsis_tx(const void *buf, size_t len, struct mg_tcpip_if *ifp) {
19846 ARM_DRIVER_ETH_MAC *mac = &Driver_ETH_MAC0;
19847 if (mac->SendFrame(buf, (uint32_t) len, 0) != ARM_DRIVER_OK) {
19848 ifp->nerr++;
19849 return 0;
19850 }
19851 ifp->nsent++;
19852 return len;
19853}
19854 
19855static void cmsis_update_hash_table(struct mg_tcpip_if *ifp) {
19856 // TODO(): read database, rebuild hash table
19857 ARM_DRIVER_ETH_MAC *mac = &Driver_ETH_MAC0;
19858 ARM_ETH_MAC_ADDR addr;
19859 memcpy(&addr, mcast_addr, sizeof(addr));
19860 mac->SetAddressFilter(&addr, 1);
19861 (void) ifp;
19862}
19863 
19864static bool cmsis_poll(struct mg_tcpip_if *ifp, bool s1) {
19865 if (ifp->update_mac_hash_table) {
19866 cmsis_update_hash_table(ifp);
19867 ifp->update_mac_hash_table = false;
19868 }
19869 if (!s1) return false;
19870 ARM_DRIVER_ETH_PHY *phy = &Driver_ETH_PHY0;
19871 ARM_DRIVER_ETH_MAC *mac = &Driver_ETH_MAC0;
19872 bool up = (phy->GetLinkState() == ARM_ETH_LINK_UP) ? 1 : 0; // link state
19873 if ((ifp->state == MG_TCPIP_STATE_DOWN) && up) { // just went up
19874 ARM_ETH_LINK_INFO st = phy->GetLinkInfo();
19875 mac->Control(ARM_ETH_MAC_CONFIGURE,
19876 (st.speed << ARM_ETH_MAC_SPEED_Pos) |
19877 (st.duplex << ARM_ETH_MAC_DUPLEX_Pos) |
19878 ARM_ETH_MAC_ADDRESS_BROADCAST);
19879 MG_DEBUG(("Link is %uM %s-duplex",
19880 (st.speed == 2) ? 1000
19881 : st.speed ? 100
19882 : 10,
19883 st.duplex ? "full" : "half"));
19884 mac->Control(ARM_ETH_MAC_CONTROL_TX, 1);
19885 mac->Control(ARM_ETH_MAC_CONTROL_RX, 1);
19886 } else if ((ifp->state != MG_TCPIP_STATE_DOWN) && !up) { // just went down
19887 mac->Control(ARM_ETH_MAC_FLUSH,
19888 ARM_ETH_MAC_FLUSH_TX | ARM_ETH_MAC_FLUSH_RX);
19889 mac->Control(ARM_ETH_MAC_CONTROL_TX, 0);
19890 mac->Control(ARM_ETH_MAC_CONTROL_RX, 0);
19891 }
19892 return up;
19893}
19894 
19895static void mac_cb(uint32_t ev) {
19896 if ((ev & ARM_ETH_MAC_EVENT_RX_FRAME) == 0) return;
19897 ARM_DRIVER_ETH_MAC *mac = &Driver_ETH_MAC0;
19898 uint32_t len = mac->GetRxFrameSize(); // CRC already stripped
19899 if (len >= 60 && len <= 1518) { // proper frame
19900 char *p;
19901 if (mg_queue_book(&s_ifp->recv_queue, &p, len) >= len) { // have room
19902 if ((len = mac->ReadFrame((uint8_t *) p, len)) > 0) { // copy succeeds
19903 mg_queue_add(&s_ifp->recv_queue, len);
19904 s_ifp->nrecv++;
19905 }
19906 return;
19907 }
19908 s_ifp->ndrop++;
19909 }
19910 mac->ReadFrame(NULL, 0); // otherwise, discard
19911}
19912 
19913static size_t cmsis_rx(void *buf, size_t buflen, struct mg_tcpip_if *ifp) {
19914 ARM_DRIVER_ETH_MAC *mac = &Driver_ETH_MAC0;
19915 uint32_t len = mac->GetRxFrameSize(); // CRC already stripped
19916 if (len >= 60 && len <= 1518 &&
19917 ((len = mac->ReadFrame(buf, (uint32_t) buflen)) > 0))
19918 return len;
19919 if (len > 0) mac->ReadFrame(NULL, 0); // discard bad frames
19920 (void) ifp;
19921 return 0;
19922}
19923 
19924#endif
19925 
19926#ifdef MG_ENABLE_LINES
19927#line 1 "src/drivers/cyw.c"
19928#endif
19929 
19930 
19931 
19932#if MG_ENABLE_TCPIP && defined(MG_ENABLE_DRIVER_CYW) && MG_ENABLE_DRIVER_CYW
19933 
19934 
19935static struct mg_tcpip_if *s_ifp;
19936static bool s_link, s_auth, s_join;
19937 
19938static bool cyw_init(uint8_t *mac);
19939static void cyw_poll(void);
19940 
19941static bool mg_tcpip_driver_cyw_init(struct mg_tcpip_if *ifp) {
19942 struct mg_tcpip_driver_cyw_data *d =
19943 (struct mg_tcpip_driver_cyw_data *) ifp->driver_data;
19944 if (MG_BIG_ENDIAN) {
19945 MG_ERROR(("Big-endian host"));
19946 return false;
19947 }
19948 s_ifp = ifp;
19949 s_link = s_auth = s_join = false;
19950 if (!cyw_init(ifp->mac)) return false;
19951 
19952 if (d->apmode) {
19953 MG_DEBUG(("Starting AP '%s' (%u)", d->apssid, d->apchannel));
19954 return mg_wifi_ap_start(d->apssid, d->appass, d->apchannel);
19955 } else if (d->ssid != NULL && d->pass != NULL) {
19956 MG_DEBUG(("Connecting to '%s'", d->ssid));
19957 return mg_wifi_connect(d->ssid, d->pass);
19958 }
19959 return true;
19960}
19961 
19962static size_t mg_cyw_tx(unsigned int ifc, void *data, size_t len);
19963size_t mg_tcpip_driver_cyw_output(const void *buf, size_t len,
19964 struct mg_tcpip_if *ifp) {
19965 struct mg_tcpip_driver_cyw_data *d =
19966 (struct mg_tcpip_driver_cyw_data *) ifp->driver_data;
19967 return mg_cyw_tx(d->apmode ? 1 : 0, (void *) buf, len) >= len ? len : 0;
19968}
19969 
19970static bool mg_tcpip_driver_cyw_poll(struct mg_tcpip_if *ifp, bool s1) {
19971 cyw_poll();
19972 if (!s1) return false;
19973 struct mg_tcpip_driver_cyw_data *d =
19974 (struct mg_tcpip_driver_cyw_data *) ifp->driver_data;
19975 return d->apmode ? s_link : s_link && s_auth && s_join;
19976}
19977 
19978struct mg_tcpip_driver mg_tcpip_driver_cyw = {mg_tcpip_driver_cyw_init,
19979 mg_tcpip_driver_cyw_output, NULL,
19980 mg_tcpip_driver_cyw_poll};
19981 
19982// - DS:
19983// https://www.mouser.com/datasheet/2/196/Infineon_CYW43439_DataSheet_v03_00_EN-3074791.pdf
19984// - WHD: https://github.com/Infineon/wifi-host-driver
19985//
19986// | e <-- event data
19987// |-----
19988// net | vnd <-- network (TCP/IP) | vendor header (Broadcom (bcm))
19989// -----|-----
19990// IOCTL | ETH | ETH <-- IOCTL/IOVAR: chip control | ETH: Ethernet header
19991// -------|-----|-----
19992// CDC | BDC | BDC
19993// ------- ----- -----
19994// SDPCM <-- includes SDIO bus arbitration, not used in SPI
19995// -------------------
19996// SPI | SDIO <-- padded to 32-bit | 64-bytes
19997//
19998// - SDPCM has 3 channels (control, data, and asynchronous data)
19999// - SPI (and SDIO) has 4 "functions", F0 to F3, to access different
20000// blocks in the chip, like the SPI/SDIO controller, chip backplane, and 2 DMA
20001// I/Os; these are usually handled by SDPCM but we need to explicitly access
20002// the I/O controller and chip backplane during initialization
20003 
20004// Processor core firmware is loaded to TCM RAM, along with module-dependent
20005// (hardware design) NVRAM data, via the chip backplane access through the bus
20006// Once the chip has been initialized, information regarding regulatory
20007// constraints (CLM blob, “Country Locale Matrix”), is loaded as an IOVAR. This
20008// is tied to the module being certified, hence it is also module-dependent.
20009// - Result: chip firmware + module NVRAM data + module CLM blob
20010 
20011#pragma pack(push, 1)
20012// all little endian
20013 
20014struct cdc_hdr {
20015 uint32_t cmd; // ioctl command value
20016 uint16_t olen; // output buflen
20017 uint16_t ilen; // input buflen (excludes header)
20018 uint32_t flags;
20019 uint32_t status;
20020};
20021 
20022struct bdc_hdr {
20023 uint8_t flags; // Flags
20024 uint8_t priority; // 802.1d Priority (low 3 bits)
20025 uint8_t flags2;
20026 uint8_t data_offset; // Offset from end of BDC header to packet data, in
20027 // 4-uint8_t words. Leaves room for optional headers.
20028};
20029 
20030struct sdpcm_sw_hdr {
20031 uint8_t sequence; // Sequence number of pkt
20032 uint8_t channel_and_flags; // IOCTL/IOVAR or User Data or Event
20033 uint8_t next_length;
20034 uint8_t header_length; // Offset to BDC or CDC header
20035 uint8_t wireless_flow_control;
20036 uint8_t bus_data_credit; // Credit from WLAN Chip
20037 uint8_t _reserved[2];
20038};
20039 
20040struct sdpcm_hdr {
20041 uint16_t len;
20042 uint16_t _len; // ~len
20043 struct sdpcm_sw_hdr sw_hdr;
20044};
20045 
20046struct data_hdr {
20047 struct sdpcm_hdr sdpcm;
20048 uint8_t pad[2];
20049 struct bdc_hdr bdc;
20050};
20051 
20052// gSPI, DS 4.2.1 Fig.12, 2-bit field
20053#define CYW_SD_FUNC_BUS 0 // F0
20054#define CYW_SD_FUNC_CHIP 1 // F1
20055#define CYW_SD_FUNC_WLAN 2 // F2
20056 
20057#define CYW_SDPCM_CTRL_HDR 0
20058#define CYW_SDPCM_ASYNC_HDR 1
20059#define CYW_SDPCM_DATA_HDR 2
20060 
20061#pragma pack(pop)
20062 
20063static uint8_t s_tx_seqno;
20064static uint32_t txdata[2048 / 4], resp[2048 / 4];
20065 
20066static void cyw_handle_cdc(struct cdc_hdr *cdc, size_t len);
20067static void cyw_handle_bdc(struct bdc_hdr *bdc, size_t len);
20068static void cyw_handle_bdc_evnt(struct bdc_hdr *bdc, size_t len);
20069 
20070static size_t cyw_spi_poll(uint8_t *dest);
20071static void cyw_update_hash_table(void);
20072 
20073// High-level comm stuff
20074 
20075static void cyw_poll(void) {
20076 struct sdpcm_hdr *sdpcm = (struct sdpcm_hdr *) resp;
20077 unsigned int channel;
20078 if (s_ifp->update_mac_hash_table) {
20079 // first call to _poll() is after _init(), so this is safe
20080 cyw_update_hash_table();
20081 s_ifp->update_mac_hash_table = false;
20082 }
20083 if (cyw_spi_poll((uint8_t *) resp) == 0) return; // BUS DEPENDENCY
20084 if ((sdpcm->len ^ sdpcm->_len) != 0xffff || sdpcm->len < sizeof(*sdpcm) ||
20085 sdpcm->len > 2048 - sizeof(*sdpcm))
20086 return;
20087 channel = sdpcm->sw_hdr.channel_and_flags & 0x0F;
20088 if (channel == CYW_SDPCM_CTRL_HDR) {
20089 if (sdpcm->len >= sizeof(*sdpcm) + sizeof(struct cdc_hdr)) {
20090 struct cdc_hdr *cdc =
20091 (struct cdc_hdr *) ((size_t) sdpcm + sdpcm->sw_hdr.header_length);
20092 size_t len = sdpcm->len - sdpcm->sw_hdr.header_length;
20093 cyw_handle_cdc(cdc, len);
20094 }
20095 } else if (channel == CYW_SDPCM_DATA_HDR) {
20096 if (sdpcm->len >= sizeof(*sdpcm) + sizeof(struct bdc_hdr)) {
20097 struct bdc_hdr *bdc =
20098 (struct bdc_hdr *) ((size_t) sdpcm + sdpcm->sw_hdr.header_length);
20099 size_t len = sdpcm->len - sdpcm->sw_hdr.header_length;
20100 cyw_handle_bdc(bdc, len);
20101 }
20102 } else if (channel == CYW_SDPCM_ASYNC_HDR) {
20103 struct bdc_hdr *bdc =
20104 (struct bdc_hdr *) ((size_t) sdpcm + sdpcm->sw_hdr.header_length);
20105 size_t len_ = sdpcm->len - sdpcm->sw_hdr.header_length;
20106 cyw_handle_bdc_evnt(bdc, len_);
20107 } // else silently discard
20108}
20109 
20110// WLAN frame reception
20111static void cyw_handle_bdc(struct bdc_hdr *bdc, size_t len) {
20112 uint8_t *payload = (uint8_t *) &bdc[bdc->data_offset + 1];
20113 mg_tcpip_qwrite(payload, len - (payload - (uint8_t *) bdc), s_ifp);
20114}
20115 
20116static size_t cyw_bus_tx(uint32_t *data, uint16_t len);
20117 
20118// WLAN frame transmission
20119static size_t mg_cyw_tx(unsigned int ifc, void *data, size_t len) {
20120 struct data_hdr *hdr = (struct data_hdr *) txdata;
20121 uint16_t txlen = (uint16_t) (len + sizeof(*hdr));
20122 memset(txdata, 0, sizeof(*hdr));
20123 memcpy((uint8_t *) txdata + sizeof(*hdr), data, len);
20124 // TODO(): hdr->bdc.priority = map IP to TOS if supporting QoS/ToS
20125 hdr->bdc.flags = 2 << 4; // BDC version 2
20126 hdr->bdc.flags2 = ifc; // 0 -> STA, 1 -> AP
20127 // hdr->bdc.data_offset = 0; // actually zeroed above
20128 hdr->sdpcm.len = txlen;
20129 hdr->sdpcm._len = (uint16_t) ~txlen;
20130 hdr->sdpcm.sw_hdr.sequence = ++s_tx_seqno;
20131 hdr->sdpcm.sw_hdr.channel_and_flags = CYW_SDPCM_DATA_HDR,
20132 hdr->sdpcm.sw_hdr.header_length = offsetof(struct data_hdr, bdc);
20133 return cyw_bus_tx(txdata, txlen);
20134}
20135 
20136// WLAN event handling
20137#pragma pack(push, 1)
20138// all in network order
20139 
20140struct eth_hdr { // TODO(scaprile) reuse 'eth' in net_builtin.c
20141 uint8_t dest[6];
20142 uint8_t src[6];
20143 uint16_t type;
20144};
20145 
20146struct bcm_vendor_hdr {
20147 uint16_t subtype; // vendor specific: 0x8001
20148 uint16_t length; // bytes following this field
20149 uint8_t version; // 0
20150 uint8_t oui[3]; // vendor specific: 0x00 0x10 0x18
20151 uint16_t usr_subtype;
20152};
20153 
20154struct bcm_evnt_hdr {
20155 uint16_t version; // 1: fields up to ifname; 2: as shown
20156 uint16_t flags;
20157 uint32_t event_type;
20158 uint32_t status;
20159 uint32_t reason;
20160 uint32_t auth_type;
20161 uint32_t datalen;
20162 uint8_t addr[6]; // Station address (if applicable)
20163 char ifname[16];
20164 uint8_t ifidx;
20165 uint8_t bss_cfg_idx;
20166};
20167 
20168struct evnt_msg {
20169 struct eth_hdr eth;
20170 // struct vendor_hdr; but we only handle Broadcom (Wi-Fi processor) events
20171 struct bcm_vendor_hdr bcm;
20172 struct bcm_evnt_hdr event;
20173};
20174 
20175#pragma pack(pop)
20176 
20177struct scan_result;
20178static void cyw_handle_scan_result(uint32_t status, struct scan_result *data,
20179 size_t len);
20180 
20181static void cyw_handle_bdc_evnt(struct bdc_hdr *bdc, size_t len) {
20182 struct evnt_msg *msg = (struct evnt_msg *) &bdc[bdc->data_offset + 1];
20183 MG_VERBOSE(("%u bytes event", len));
20184 if (mg_log_level >= MG_LL_VERBOSE) mg_hexdump((void *) bdc, len);
20185 if (mg_ntohs(msg->eth.type) != 0x886C || msg->bcm.oui[0] != 0x00 ||
20186 msg->bcm.oui[1] != 0x10 || msg->bcm.oui[2] != 0x18)
20187 return; // discard if not Broadcom
20188 if (mg_ntohl(msg->event.datalen) <=
20189 len - ((uint8_t *) msg - (uint8_t *) bdc)) {
20190 uint32_t event_type = mg_ntohl(msg->event.event_type);
20191 uint32_t status = mg_ntohl(msg->event.status);
20192 uint32_t reason = mg_ntohl(msg->event.reason);
20193 uint16_t flags = mg_ntohs(msg->event.flags);
20194 MG_DEBUG(("BCM event %lu %lu %lu %p", event_type, status, reason, flags));
20195 if (event_type == 16 && status == 0) { // Link
20196 s_link = flags & 1;
20197 } else if (event_type == 46 && s_link) { // PSK sup with link up
20198 if (status == 6) { // Keyed
20199 } else if ((status == 4 || status == 8 || status == 10) &&
20200 reason == 15) { // Wait M1/M3/G1
20201 MG_ERROR(("AUTH TIMEOUT"));
20202 s_auth = false;
20203 } else {
20204 MG_ERROR(("AUTH FAILED"));
20205 s_auth = false;
20206 }
20207 } else if (event_type == 3 && status != 6) { // Auth (not unsolicited)
20208 if (status == 0) { // Success
20209 s_auth = true;
20210 } else {
20211 MG_ERROR(("AUTH TIMEOUT"));
20212 s_auth = false;
20213 }
20214 } else if (event_type == 1) { // Join
20215 if (status == 0) { // Success
20216 s_join = true;
20217 } else {
20218 MG_ERROR(("%s", status == 3 /* No networks */ ? "SSID NOT FOUND"
20219 : "JOIN FAILED"));
20220 s_join = false;
20221 mg_tcpip_call(s_ifp, MG_TCPIP_EV_WIFI_CONNECT_ERR, &status);
20222 }
20223 } else if (event_type == 12 || event_type == 5) { // Disassoc, Deauth
20224 s_auth = false;
20225 } else if (event_type == 69) { // Scan result
20226 struct scan_result *data = (struct scan_result *) (&msg->event + 1);
20227 size_t dlen = mg_ntohl(msg->event.datalen);
20228 if (dlen > len - ((uint8_t *) data - (uint8_t *) bdc)) return;
20229 cyw_handle_scan_result(status, data, dlen);
20230 }
20231 } // else silently discard
20232}
20233 
20234static bool cyw_ioctl_get_(unsigned int ifc, unsigned int cmd, void *data,
20235 size_t len);
20236static bool cyw_ioctl_set_(unsigned int ifc, unsigned int cmd, void *data,
20237 size_t len);
20238static bool cyw_ioctl_iovar_get_(unsigned int ifc, char *var, void *data,
20239 size_t len);
20240static bool cyw_ioctl_iovar_set_(unsigned int ifc, char *var, void *data,
20241 size_t len);
20242// clang-format off
20243// convenience: ioctl funcs on default ifc (0), as only AP needs ifc 1
20244static bool cyw_ioctl_get(unsigned int cmd, void *data, size_t len) { return cyw_ioctl_get_(0, cmd, data, len); }
20245static bool cyw_ioctl_set(unsigned int cmd, void *data, size_t len) { return cyw_ioctl_set_(0, cmd, data, len); }
20246static bool cyw_ioctl_iovar_get(char *var, void *data, size_t len) { return cyw_ioctl_iovar_get_(0, var, data, len); }
20247static bool cyw_ioctl_iovar_set(char *var, void *data, size_t len) { return cyw_ioctl_iovar_set_(0, var, data, len); }
20248// clang-format on
20249 
20250// Wi-Fi network stuff
20251 
20252// clang-format off
20253static bool cyw_wifi_connect(char *ssid, char *pass) {
20254 uint32_t sup_wpa[2] = {0, 1}; // bss index 0 = STA, not open
20255 static const uint32_t const eapver[2] = {0, (uint32_t) -1}, // accept AP version
20256 tmo[2] = {0, 2500};
20257 uint32_t data[64/4 + 1]; // max pass length: 64 for WPA, 128 for WPA3 SAE
20258 unsigned int len;
20259 uint32_t val;
20260 val = 4; // security type: 0 for none, 2 for WPA, 4 for WPA2/WPA3, 6 for mixed WPA/WPA2
20261 // sup_wpa[1] = 0 if not using security
20262 if (!(cyw_ioctl_set(134 /* SET_WSEC */, (uint8_t *)&val, sizeof(val))
20263 && cyw_ioctl_iovar_set("bsscfg:sup_wpa", (void *)sup_wpa, sizeof(sup_wpa))
20264 && cyw_ioctl_iovar_set("bsscfg:sup_wpa2_eapver", (void *)eapver, sizeof(eapver))
20265 && cyw_ioctl_iovar_set("bsscfg:sup_wpa_tmo", (void *)tmo, sizeof(tmo)))
20266 ) return false;
20267 mg_delayms(2); // allow radio firmware to be ready
20268 // skip if not using auth
20269 memset(data, 0, sizeof(data));
20270 len = strlen(pass);
20271 ((uint16_t *)data)[0] = (uint16_t) len;
20272 ((uint16_t *)data)[1] = 1; // indicates wireless security key, skip for WPA3 SAE
20273 memcpy((uint8_t *)data + 2 * sizeof(uint16_t), pass, len); // skip for WPA3 SAE
20274 if (!cyw_ioctl_set(268 /* SET_WSEC_PMK */, data, sizeof(data))) return false; // skip for WPA3 SAE, sizeof/2 if supporting SAE but using WPA
20275 // for WPA3 SAE: memcpy((uint8_t *)data + sizeof(uint16_t), pass, len); cyw_ioctl_iovar_set("sae_password", data, sizeof(data));
20276 // resume if not using auth
20277 val = 1; if (!cyw_ioctl_set(20 /* SET_INFRA */, (uint8_t *)&val, sizeof(val))) return false;
20278 val = 0; // auth type: 0 for open, 3 for SAE
20279 if (!cyw_ioctl_set(22 /* SET_AUTH */, (uint8_t *)&val, sizeof(val))) return false;
20280 val = 1; // MFP capable: 1 for yes, 0 for no; recommended to be set for WPA2+ (2 for 'required', WPA3)
20281 cyw_ioctl_iovar_set("mfp", (uint8_t *)&val, sizeof(val)); // Old chipsets do not support MFP
20282 val = 0x80; // auth type: 0 for none, 4 for WPA PSK, 0x80 for WPA2 PSK, 0x40000 for WPA3 SAE PSK
20283 if (!cyw_ioctl_set(165 /* SET_WPA_AUTH */, (uint8_t *)&val, sizeof(val))) return false;
20284 len = strlen(ssid);
20285 data[0] = (uint32_t) len;
20286 memcpy((uint8_t *)&data[1], ssid, len);
20287 if (!cyw_ioctl_set(26 /* SET_SSID */, data, len + sizeof(uint32_t))) return false;
20288 return true;
20289}
20290 
20291static bool cyw_wifi_disconnect(void) {
20292 return cyw_ioctl_set(52 /* DISASSOC */, NULL, 0);
20293}
20294 
20295// For AP functions, we use explicit ifc selection; both for clarity and maintenance, as some actions are performed on ifc 0, with or without a bss_index, and others are performed on ifc 1
20296 
20297static bool cyw_wifi_ap_start(char *ssid, char *pass, unsigned int channel) {
20298 uint32_t data[64/4 + 2]; // max pass length: 64 for WPA, 128 for WPA3 SAE
20299 unsigned int len;
20300 uint32_t val;
20301 // CHIP DEPENDENCY
20302 // RPi set the AMPDU parameter for AP (window size = 2) *****************
20303 // val = 2 ; cyw_ioctl_iovar_set_(0, "ampdu_ba_wsize", (uint8_t *)&val, sizeof(val));
20304 // some chips might require to turn APSTA off and issue a SET_AP IOCTL
20305 len = strlen(ssid);
20306 data[0] = 1; // bss index 1 = AP
20307 data[1] = (uint32_t) len;
20308 memcpy((uint8_t *)&data[2], ssid, len);
20309 // TODO(scaprile): this takes some time to process, or requires a delay before doing it
20310 if (!cyw_ioctl_iovar_set_(0, "bsscfg:ssid", (uint8_t *)&data, len + 2 * sizeof(uint32_t))) return false;
20311 // TODO(scaprile): but sometimes this one takes some time to process
20312 val = (uint32_t) channel; if (!cyw_ioctl_set_(0, 30 /* SET_CHANNEL */, (uint8_t *)&val, sizeof(val))) return false;
20313 data[0] = 1; // bss index 1 = AP
20314 data[1] = 0x00400004; // security type: 0 for none, 0x00200002 for WPA, 0x00400004 for WPA2, 0x01000004 for WPA3, 0x01400004 for mixed WPA2/WPA3, 0x00400006 for mixed WPA/WPA2
20315 // NOTE(): WHD writes & 0xFF if WPS is not enabled (?)
20316 if (!cyw_ioctl_iovar_set_(0, "bsscfg:wsec", (uint8_t *)&data, 2 * sizeof(uint32_t))) return false;
20317 val = 1; // MFP capable: 1 for yes, 0 for no; recommended to be set for WPA2+ (2 for 'required', WPA3)
20318 cyw_ioctl_iovar_set_(1, "mfp", (uint8_t *)&val, sizeof(val)); // Old chipsets do not support MFP
20319 mg_delayms(2); // allow radio firmware to be ready
20320 // skip if not using auth
20321 // WPA, WPA2, mixed WPA/WPA2, mixed WPA2/WPA3
20322 // NOTE(): WHD does not set SAE password for shared WPA2/WPA3, same do we
20323 memset(data, 0, sizeof(data));
20324 len = strlen(pass);
20325 ((uint16_t *)data)[0] = (uint16_t) len; // skip for WPA3 SAE
20326 ((uint16_t *)data)[1] = 1; // indicates wireless security key, skip for WPA3 SAE
20327 memcpy((uint8_t *)data + 2 * sizeof(uint16_t), pass, len); // skip for WPA3 SAE
20328 if (!cyw_ioctl_set_(1, 268 /* SET_WSEC_PMK */, data, sizeof(data))) return false; // skip for WPA3 SAE, sizeof/2 if supporting SAE but using WPA
20329 /* for WPA3 SAE:
20330 memcpy((uint8_t *)data + sizeof(uint16_t), pass, len);
20331 cyw_ioctl_iovar_set_(1, "sae_password", data, sizeof(data)); */
20332 /* for WPA3 or mixed WPA2/WPA3:
20333 val = 5 ; cyw_ioctl_iovar_set_(1, "sae_max_pwe_loop", (uint8_t *)&val, sizeof(val)); // Some chipsets do not support this */
20334 // resume if not using auth
20335 
20336 data[0] = 1; // bss index 1 = AP
20337 data[1] = 0x80; // auth type: 0 for none, 4 for WPA PSK, 0x80 for WPA2 PSK, 0x40000 for WPA3 SAE PSK; ored if mixed
20338 if (!cyw_ioctl_iovar_set_(0, "bsscfg:wpa_auth", (uint8_t *)&data, 2 * sizeof(uint32_t))) return false;
20339 
20340 val = 1 /* auto */; if (!cyw_ioctl_set_(1, 110 /* SET_GMODE */, (uint8_t *)&val, sizeof(val))) return false;
20341 // Set multicast tx rate to 11Mbps, may fail in some chipsets, we are enforcing it
20342 val = 11000000 / 500000; if (!cyw_ioctl_iovar_set_(1, "2g_mrate", (uint8_t *)&val, sizeof(val))) return false;
20343 val = 1; if (!cyw_ioctl_set_(1, 78 /* SET_DTIMPRD */, (uint8_t *)&val, sizeof(val))) return false;
20344 data[0] = 1; // bss index 1 = AP
20345 data[1] = 1; // UP
20346 // TODO(scaprile): this takes a long time to process
20347 if (!cyw_ioctl_iovar_set_(0, "bss", (uint8_t *)&data, 2 * sizeof(uint32_t))) return false;
20348 return true;
20349}
20350 
20351static bool cyw_wifi_ap_stop(void) {
20352 uint32_t data[2];
20353 data[0] = 1; // bss index 1 = AP
20354 data[1] = 0; // DOWN
20355 if (!cyw_ioctl_iovar_set_(0, "bss", (uint8_t *)&data, 2 * sizeof(uint32_t))) return false;
20356 // DO WE NEED TO CLEAR CHANNEL ???
20357 // CHIP DEPENDENCY
20358 //val = 8 ; cyw_ioctl_iovar_set_(0, "ampdu_ba_wsize", (uint8_t *)&val, sizeof(val));
20359 return true;
20360}
20361 
20362// WLAN scan handling
20363 
20364#pragma pack(push, 1)
20365// in little endian
20366 
20367struct wifi_scan_opt {
20368 uint32_t version;
20369 uint16_t action;
20370 uint16_t _;
20371 uint32_t ssid_len;
20372 uint8_t ssid[32];
20373 uint8_t bssid[6];
20374 int8_t bss_type;
20375 int8_t scan_type;
20376 int32_t nprobes;
20377 int32_t active_time;
20378 int32_t passive_time;
20379 int32_t home_time;
20380 int32_t channel_num;
20381 uint16_t channel_list[1];
20382};
20383#pragma pack(pop)
20384 
20385static bool cyw_wifi_scan(void) {
20386 struct wifi_scan_opt opts;
20387 memset(&opts, 0, sizeof(opts));
20388 opts.version = 1;
20389 opts.action = 1; // start
20390 opts._ = 0;
20391 memset(opts.bssid, 0xff, sizeof(opts.bssid));
20392 opts.bss_type = 2; // any
20393 opts.nprobes = -1;
20394 opts.active_time = -1;
20395 opts.passive_time = -1;
20396 opts.home_time = -1;
20397 opts.channel_num = 0;
20398 opts.channel_list[0] = 0;
20399 return cyw_ioctl_iovar_set("escan", (uint8_t *)&opts, sizeof(opts));
20400}
20401 
20402 
20403#pragma pack(push, 1)
20404// in little endian
20405 
20406struct scan_bss {
20407 uint32_t version; // version field
20408 uint32_t length; // byte length of data in this record, starting at version and including IEs
20409 uint8_t BSSID[6]; // Unique 6-byte MAC address
20410 uint16_t beacon_period; // Interval between two consecutive beacon frames. Units are Kusec
20411 uint16_t capability; // Capability information
20412 uint8_t SSID_len; // SSID length
20413 uint8_t SSID[32]; // Array to store SSID
20414 uint8_t reserved1[1]; // Reserved(padding)
20415 uint32_t rateset_count; // Count of rates in this set
20416 uint8_t rateset_rates[16]; // rates in 500kbps units, higher bit set if basic
20417 uint16_t chanspec; // Channel specification for basic service set
20418 uint16_t atim_window; // Announcement traffic indication message window size. Units are Kusec
20419 uint8_t dtim_period; // Delivery traffic indication message period
20420 uint8_t reserved2[1]; // Reserved(padding)
20421 int16_t RSSI; // receive signal strength (in dBm)
20422 int8_t phy_noise; // noise (in dBm)
20423 uint8_t n_cap; // BSS is 802.11n Capable
20424 uint8_t reserved3[2]; // Reserved(padding)
20425 uint32_t nbss_cap; // 802.11n BSS Capabilities (based on HT_CAP_*)
20426 uint8_t ctl_ch; // 802.11n BSS control channel number
20427 uint8_t reserved4[3]; // Reserved(padding)
20428 uint32_t reserved32[1]; // Reserved for expansion of BSS properties
20429 uint8_t flags; // flags
20430 uint8_t vht_cap; // BSS is vht capable
20431 uint8_t reserved5[2]; // Reserved(padding)
20432 uint8_t basic_mcs[16]; // 802.11N BSS required MCS set
20433 uint16_t ie_offset; // offset at which IEs start, from beginning
20434 uint16_t reserved16[1]; // Reserved(padding)
20435 uint32_t ie_length; // byte length of Information Elements
20436 int16_t SNR; // Average SNR during frame reception
20437};
20438 
20439struct scan_result {
20440 uint32_t buflen;
20441 uint32_t version;
20442 uint16_t sync_id;
20443 uint16_t bss_count;
20444 struct scan_bss bss[1];
20445};
20446 
20447#pragma pack(pop)
20448 
20449// CHIP DEPENDENCY
20450#define CYW_BSS_BANDMASK 0xc000
20451#define CYW_BSS_BAND2G 0
20452//
20453 
20454static void cyw_handle_scan_result(uint32_t status, struct scan_result *data, size_t len) {
20455 MG_VERBOSE(("scan event, status: %ld", status));
20456 if (status == 0) { // SUCCESS
20457 MG_VERBOSE(("scan complete"));
20458 mg_tcpip_call(s_ifp, MG_TCPIP_EV_WIFI_SCAN_END, NULL);
20459 } else if (status == 8) { // PARTIAL
20460 struct mg_wifi_scan_bss_data bss;
20461 struct scan_bss *sbss = data->bss;
20462 unsigned int band = sbss->chanspec & CYW_BSS_BANDMASK;
20463 if (data->version != 109 || data->bss_count != 1) {
20464 MG_ERROR(("Unsupported: %lu %u", data->version, data->bss_count));
20465 return;
20466 }
20467 if (sbss->length > len - offsetof(struct scan_result, bss) || sbss->SSID_len > sizeof(sbss->SSID) || sbss->ie_offset < sizeof(*sbss) || sbss->ie_offset > (sizeof(*sbss) + sbss->ie_length) || sbss->ie_offset + sbss->ie_length > sbss->length)
20468 return; // silently discard malformed data
20469 if (!(sbss->flags & MG_BIT(2))) return; // RSSI_ONCHANNEL, ignore off-channel results
20470 bss.SSID = mg_str_n(sbss->SSID, sbss->SSID_len);
20471 bss.BSSID = sbss->BSSID;
20472 bss.RSSI = (int8_t)sbss->RSSI;
20473 bss.has_n = sbss->n_cap != 0;
20474 bss.channel = bss.has_n ? sbss->ctl_ch : (uint8_t)(sbss->chanspec & 0xff); // n 40MHz vs a/b/g and 20MHz
20475 bss.band = band & CYW_BSS_BAND2G ? MG_WIFI_BAND_2G : MG_WIFI_BAND_5G;
20476 bss.security = (sbss->capability & MG_BIT(4) /* CAP_PRIVACY */) ? MG_WIFI_SECURITY_WEP : MG_WIFI_SECURITY_OPEN;
20477 { // travel IEs (Information Elements) in search of security definitions
20478 const uint8_t wot1[4] = {0x00, 0x50, 0xf2, 0x01}; // WPA_OUI_TYPE1
20479 uint8_t *ie = (uint8_t *)sbss + sbss->ie_offset;
20480 int bytes = (int) sbss->ie_length;
20481 while (bytes > 0 && ie[1] + 2 < bytes) { // ie[0] -> type, ie[1] -> bytes from ie[2]
20482 if (ie[0] == 48 /* IE_ID_RSN */) bss.security |= MG_WIFI_SECURITY_WPA2;
20483 if (ie[0] == 221 /* IE_ID_VENDOR_SPECIFIC */ && memcmp(&ie[2], wot1, 4) == 0)
20484 bss.security |= MG_WIFI_SECURITY_WPA;
20485 ie += ie[1] + 2;
20486 bytes -= ie[1] + 2;
20487 }
20488 }
20489 MG_VERBOSE(("BSS: %.*s (%u) (%M) %d dBm %u", bss.SSID.len, bss.SSID.buf, bss.channel, mg_print_mac, bss.BSSID, (int) bss.RSSI, bss.security));
20490 mg_tcpip_call(s_ifp, MG_TCPIP_EV_WIFI_SCAN_RESULT, &bss);
20491 } else {
20492 MG_ERROR(("scan error"));
20493 }
20494}
20495// clang-format on
20496 
20497// IOCTL stuff. All values read and written are in little endian format
20498 
20499static uint16_t s_ioctl_reqid;
20500 
20501// CDC handler for waiting loop
20502static uint8_t *s_ioctl_resp;
20503static bool s_ioctl_err;
20504 
20505static void cyw_handle_cdc(struct cdc_hdr *cdc, size_t len) {
20506 uint8_t *resp = (uint8_t *) cdc + sizeof(*cdc);
20507 MG_VERBOSE(("%u bytes CDC frame", len));
20508 if ((cdc->flags >> 16) != s_ioctl_reqid) return;
20509 if (cdc->flags & 1) {
20510 MG_ERROR(("IOCTL error: %ld", -cdc->status));
20511 s_ioctl_err = true;
20512 return;
20513 }
20514 if (mg_log_level >= MG_LL_VERBOSE) mg_hexdump((void *) cdc, len);
20515 MG_DEBUG(("IOCTL result: %02x %02x %02x %02x ...", resp[0], resp[1], resp[2],
20516 resp[3]));
20517 s_ioctl_resp = resp;
20518}
20519// NOTE(): alt no loop handler dispatching IOCTL response to current handler:
20520// static void *s_ioctl_hnd; *s_ioctl_hnd(ioctl, len);
20521// app is a state machine calling get/sets and advancing via these callbacks
20522 
20523#pragma pack(push, 1)
20524// all little endian
20525 
20526struct ctrl_hdr {
20527 struct sdpcm_hdr sdpcm;
20528 struct cdc_hdr cdc;
20529};
20530 
20531#pragma pack(pop)
20532 
20533// IOCTL command send
20534static void cyw_ioctl_send_cmd(unsigned int ifc, unsigned int cmd, bool set,
20535 size_t len) {
20536 struct ctrl_hdr *hdr = (struct ctrl_hdr *) txdata;
20537 uint16_t txlen = (uint16_t) (len + sizeof(*hdr));
20538 memset(txdata, 0, sizeof(*hdr));
20539 hdr->cdc.cmd = cmd;
20540 hdr->cdc.olen = (uint16_t) len;
20541 // hdr->cdc.ilen = 0; // actually zeroed above
20542 hdr->cdc.flags = ((uint32_t) ++s_ioctl_reqid << 16) | ((ifc & 0xf) << 12) |
20543 (set ? MG_BIT(1) : 0);
20544 hdr->sdpcm.len = txlen;
20545 hdr->sdpcm._len = (uint16_t) ~txlen;
20546 hdr->sdpcm.sw_hdr.sequence = ++s_tx_seqno;
20547 hdr->sdpcm.sw_hdr.channel_and_flags = CYW_SDPCM_CTRL_HDR;
20548 hdr->sdpcm.sw_hdr.header_length = offsetof(struct ctrl_hdr, cdc);
20549 cyw_bus_tx(txdata, txlen);
20550}
20551 
20552// just send respective commands, response handled via CDC handler
20553static void cyw_ioctl_send_get(unsigned int ifc, unsigned int cmd) {
20554 cyw_ioctl_send_cmd(ifc, cmd, false, 0);
20555}
20556 
20557static void cyw_ioctl_send_set(unsigned int ifc, unsigned int cmd, void *data,
20558 size_t len) {
20559 if (data != NULL && len > 0)
20560 memcpy((uint8_t *) txdata + sizeof(struct ctrl_hdr), data, len);
20561 cyw_ioctl_send_cmd(ifc, cmd, true, (uint16_t) len);
20562}
20563 
20564static void cyw_ioctl_send_iovar_get(unsigned int ifc, char *var, size_t len) {
20565 unsigned int namelen = strlen(var) + 1; // include '\0'
20566 // cmd = GET IOVAR, "set" the name...
20567 cyw_ioctl_send_set(ifc, 262, var, len > namelen ? len : namelen);
20568}
20569 
20570static void cyw_ioctl_send_iovar_set2(unsigned int ifc, char *var, void *data1,
20571 size_t len1, void *data2, size_t len2) {
20572 struct ctrl_hdr *hdr = (struct ctrl_hdr *) txdata;
20573 unsigned int namelen = strlen(var) + 1; // include '\0'
20574 uint16_t txlen, payload_len = (uint16_t) (namelen + len1 + len2);
20575 memcpy((uint8_t *) txdata + sizeof(*hdr), var, namelen);
20576 memcpy((uint8_t *) txdata + namelen + sizeof(*hdr), data1, len1);
20577 if (data2 != NULL)
20578 memcpy((uint8_t *) txdata + namelen + sizeof(*hdr) + len1, data2, len2);
20579 txlen = (uint16_t) (payload_len + sizeof(*hdr));
20580 cyw_ioctl_send_cmd(ifc, 263, true, txlen); // cmd = SET IOVAR
20581}
20582 
20583static void cyw_ioctl_send_iovar_set(unsigned int ifc, char *var, void *data,
20584 size_t len) {
20585 cyw_ioctl_send_iovar_set2(ifc, var, data, len, NULL, 0);
20586}
20587 
20588// wait for a response, meanwhile delivering received frames and events
20589static bool cyw_ioctl_wait(void) {
20590 unsigned int times = 6000;
20591 s_ioctl_resp = NULL;
20592 s_ioctl_err = false;
20593 while (s_ioctl_resp == NULL && !s_ioctl_err && times-- > 0)
20594 cyw_poll(); // TODO(scaprile): review wait/sleep strategy (this loop is executed only when initializing/acting on the chip)
20595 MG_DEBUG(("resp: %lp, err: %c, times: %d", s_ioctl_resp,
20596 s_ioctl_err ? '1' : '0', (int) times));
20597 return s_ioctl_resp != NULL;
20598}
20599 
20600static bool cyw_ioctl_waitdata(void *data, size_t len) {
20601 if (!cyw_ioctl_wait()) return false;
20602 memcpy(data, s_ioctl_resp, len);
20603 return true;
20604}
20605 
20606// send respective commands, wait for a response or timeout
20607static bool cyw_ioctl_get_(unsigned int ifc, unsigned int cmd, void *data,
20608 size_t len) {
20609 cyw_ioctl_send_get(ifc, cmd);
20610 return cyw_ioctl_waitdata(data, len);
20611}
20612static bool cyw_ioctl_set_(unsigned int ifc, unsigned int cmd, void *data,
20613 size_t len) {
20614 cyw_ioctl_send_set(ifc, cmd, data, len);
20615 return cyw_ioctl_wait();
20616}
20617 
20618static bool cyw_ioctl_iovar_get_(unsigned int ifc, char *var, void *data,
20619 size_t len) {
20620 cyw_ioctl_send_iovar_get(ifc, var, len);
20621 return cyw_ioctl_waitdata(data, len);
20622}
20623static bool cyw_ioctl_iovar_set2_(unsigned int ifc, char *var, void *data1,
20624 size_t len1, void *data2, size_t len2) {
20625 cyw_ioctl_send_iovar_set2(ifc, var, data1, len1, data2, len2);
20626 return cyw_ioctl_wait();
20627}
20628static bool cyw_ioctl_iovar_set_(unsigned int ifc, char *var, void *data,
20629 size_t len) {
20630 return cyw_ioctl_iovar_set2_(ifc, var, data, len, NULL, 0);
20631}
20632 
20633// CYW43 chipset specifics. All values read and written are in little endian
20634// format
20635 
20636#pragma pack(push, 1)
20637// all little endian
20638 
20639struct cyw_country {
20640 uint32_t a;
20641 int32_t rev;
20642 uint32_t c;
20643};
20644 
20645struct clm_hdr {
20646 uint16_t flag;
20647 uint16_t type;
20648 uint32_t len;
20649 uint32_t crc;
20650};
20651 
20652#pragma pack(pop)
20653 
20654// worlwide rev0, try rev 17 for 4343W
20655static const uint32_t country_code = 'X' + ('X' << 8) + (0 << 16);
20656 
20657static bool cyw_spi_init();
20658 
20659// clang-format off
20660static bool cyw_init(uint8_t *mac) {
20661 uint32_t val = 0;
20662 if (!cyw_spi_init()) return false; // BUS DEPENDENCY
20663 // BT-ENABLED DEPENDENCY
20664 // set Wi-Fi up
20665 val = 0 /* disable */; cyw_ioctl_iovar_set("bus:txglom", (uint8_t *)&val, sizeof(val));
20666 val = 1 /* on */; cyw_ioctl_iovar_set("apsta", (uint8_t *)&val, sizeof(val));
20667 // CHIP DEPENDENCY
20668 val = 8 ; cyw_ioctl_iovar_set("ampdu_ba_wsize", (uint8_t *)&val, sizeof(val));
20669 val = 4 ; cyw_ioctl_iovar_set("ampdu_mpdu", (uint8_t *)&val, sizeof(val));
20670 val = 0 /* 8K */; cyw_ioctl_iovar_set("ampdu_rx_factor", (uint8_t *)&val, sizeof(val));
20671 //
20672 {
20673 struct cyw_country c;
20674 unsigned int rev = (unsigned int) (country_code >> 16) & 0xffff;
20675 c.c = c.a = country_code & 0xffff;
20676 c.rev = rev == 0 ? -1 : (int32_t) rev; // if rev is 0, set it to -1, the chip will use any NVRAM/OTP configured aggregate or default to rev 0
20677 cyw_ioctl_iovar_set("country", (void *)&c, sizeof(c));
20678 } // this takes some time to process
20679 { // so do some retries while enabling events of interest
20680 // we care for SET_SSID(0), JOIN(1), AUTH(3), DEAUTH(5), DISASSOC_IND(12), LINK(16), PSK_SUP(46), SCAN_RESULT(69); all < 128
20681 uint32_t data[128/8/4 + 1];
20682 data[0] = 0; // bss index: 0 = STA
20683 memset(&data[1], 0, 128/8); // mark all as not desired
20684 data[1] = MG_BIT(0) | MG_BIT(1) | MG_BIT(3) | MG_BIT(5) | MG_BIT(12) | MG_BIT(16); // events 0 to 31
20685 data[2] = MG_BIT(46 - 32); // events 32 to 63
20686 data[3] = MG_BIT(69 - 64); // events 64 to 95
20687 unsigned int times = 100;
20688 while (times --)
20689 if (cyw_ioctl_iovar_set("bsscfg:event_msgs", (uint8_t *)data, sizeof(data))) break;
20690 if (times == ~0) return false;
20691 }
20692 val = 0; if (!cyw_ioctl_set(64 /* SET_ANTDIV */, (uint8_t *)&val, sizeof(val))) return false;
20693 if (!cyw_ioctl_set(2 /* UP, interface up */, NULL, 0)) return false;
20694 // use PM2 power saving for max throughput
20695 val = 200 /* ms */; if (!cyw_ioctl_iovar_set("pm2_sleep_ret", (uint8_t *)&val, sizeof(val))) return false;
20696 // set beacon intervals to reduce power consumption while associated to an AP but idle
20697 val = 1; if (!cyw_ioctl_iovar_set("bcn_li_bcn", (uint8_t *)&val, sizeof(val))) return false;
20698 val = 1; if (!cyw_ioctl_iovar_set("bcn_li_dtim", (uint8_t *)&val, sizeof(val))) return false;
20699 val = 10; if (!cyw_ioctl_iovar_set("assoc_listen", (uint8_t *)&val, sizeof(val))) return false;
20700 val = 1 /* auto */; if (!cyw_ioctl_set(110 /* SET_GMODE */, (uint8_t *)&val, sizeof(val))) return false;
20701 val = 0 /* any */; if (!cyw_ioctl_set(142 /* SET_BAND */, (uint8_t *)&val, sizeof(val))) return false;
20702 if (mg_log_level >= MG_LL_DEBUG) {
20703 char text[256]; // this is huge, but we're just starting up
20704 if (cyw_ioctl_iovar_get("ver", (uint8_t *)text, sizeof(text))) {
20705 unsigned int len = strnlen(text, sizeof(text));
20706 MG_DEBUG(("Firmware:\n%.*s", len, text));
20707 }
20708 text[0] = '\0';
20709 if (cyw_ioctl_iovar_get("clmver", (uint8_t *)text, sizeof(text)) && text[0] != '\0') {
20710 unsigned int len = strnlen(text, sizeof(text));
20711 MG_DEBUG(("CLM:\n%.*s", len, text));
20712 }
20713 }
20714 {
20715 if(cyw_ioctl_iovar_get("cur_etheraddr", mac, 6)) {
20716 MG_DEBUG(("MAC: %M", mg_print_mac, mac));
20717 } else {
20718 MG_ERROR(("read MAC failed"));
20719 }
20720 }
20721 return true;
20722}
20723// clang-format on
20724 
20725static bool cyw_load_fwll(void *fwdata, size_t fwlen, void *nvramdata,
20726 size_t nvramlen);
20727 
20728static bool cyw_load_firmware(struct mg_tcpip_driver_cyw_firmware *fw) {
20729 return cyw_load_fwll((void *) fw->code_addr, fw->code_len,
20730 (void *) fw->nvram_addr, fw->nvram_len);
20731}
20732 
20733// clang-format off
20734static bool cyw_load_clmll(void *data, size_t len) {
20735 unsigned int sent = 0, offset = 0;
20736 struct clm_hdr hdr = {
20737 .flag = 1 << 12 /* DLOAD_HANDLER_VER */ | MG_BIT(1) /* DL_BEGIN */,
20738 .type = 2,
20739 .crc = 0};
20740 while (sent < len) {
20741 unsigned int bytes = len - sent;
20742 if (bytes > 1024) bytes = 1024;
20743 if (sent + bytes >= len) hdr.flag |= MG_BIT(2); // DL_END;
20744 hdr.len = bytes;
20745 if (!cyw_ioctl_iovar_set2_(0, "clmload", (void *) &hdr, sizeof(hdr), (uint8_t *) data + offset, bytes))
20746 break;
20747 sent += bytes;
20748 offset += bytes;
20749 hdr.flag &= ~MG_BIT(1); // DL_BEGIN
20750 }
20751 return sent >= len;
20752}
20753// clang-format on
20754 
20755static bool cyw_load_clm(struct mg_tcpip_driver_cyw_firmware *fw) {
20756 return cyw_load_clmll((void *) fw->clm_addr, fw->clm_len);
20757}
20758 
20759static void cyw_update_hash_table(void) {
20760 // TODO(): read database, rebuild hash table
20761 uint32_t val = 0;
20762 val = 1; cyw_ioctl_iovar_set2_(0, "mcast_list", (uint8_t *)&val, sizeof(val), (uint8_t *)mcast_addr, sizeof(mcast_addr));
20763 mg_delayms(50);
20764}
20765 
20766// CYW43 chip backplane specifics. All values read and written are in little
20767// endian format
20768 
20769// Access to chip backplane is done windowed in 32KB banks
20770// - addr = area base address + register offset
20771// - set the window address to addr & ~ADDRMSK
20772// - access addr & ADDRMSK for non-32-bit quantities
20773// - if accesing 32-bit quantities, do it on (addr & ADDRMSK) | ACCSS4B
20774#define CYW_CHIP_CHIPCOMMON 0x18000000
20775#define CYW_CHIP_BCKPLN_WINSZ 0x8000
20776#define CYW_CHIP_BCKPLN_ADDRMSK 0x7fff
20777#define CYW_CHIP_BCKPLN_ACCSS4B MG_BIT(15)
20778#define CYW_CHIP_BCKPLN_WRAPPOFF 0x100000
20779#define CYW_CHIP_BCKPLN_SPIMAX 64
20780#define CYW_CHIP_BCKPLN_SDIOMAX 1536
20781 
20782// CHIP DEPENDENCY
20783#define CYW_CHIP_ARMCORE_BASE (CYW_CHIP_CHIPCOMMON + 0x3000)
20784#define CYW_CHIP_SOCSRAM_BASE (CYW_CHIP_CHIPCOMMON + 0x4000)
20785#define CYW_CHIP_ARMCORE (CYW_CHIP_ARMCORE_BASE + CYW_CHIP_BCKPLN_WRAPPOFF)
20786#define CYW_CHIP_SOCSRAM (CYW_CHIP_SOCSRAM_BASE + CYW_CHIP_BCKPLN_WRAPPOFF)
20787#define CYW_CHIP_ATCMRAM_BASE 0
20788#define CYW_CHIP_RAM_SIZE 0x80000
20789//
20790 
20791#define CYW_CHIP_ADDRLOW 0x1000a
20792#define CYW_CHIP_ADDRMID 0x1000b
20793#define CYW_CHIP_ADDRHIGH 0x1000c
20794#define CYW_CHIP_SPIFRCTRL 0x1000d
20795#define CYW_CHIP_CLOCKCSR 0x1000e
20796#define CYW_CHIP_PULLUP 0x1000f
20797#define CYW_CHIP_WAKEUPCTL 0x1001e
20798#define CYW_CHIP_SLEEPCSR 0x1001f
20799 
20800#define CYW_CHIP_SOCSRAM_BANKXIDX 0x010
20801#define CYW_CHIP_SOCSRAM_BANKXPDA 0x044
20802#define CYW_CHIP_AI_IOCTRL 0x408
20803#define CYW_CHIP_AI_RESETCTRL 0x800
20804 
20805static bool cyw_spi_write(unsigned int f, uint32_t addr, void *data,
20806 uint16_t len);
20807static void cyw_spi_read(unsigned int f, uint32_t addr, void *data,
20808 uint16_t len);
20809 
20810// clang-format off
20811// set backplane window to requested area.
20812static void cyw_set_backplane_window(uint32_t addr) {
20813 uint32_t val;
20814 addr &= ~CYW_CHIP_BCKPLN_ADDRMSK;
20815 val = (addr >> 24) & 0xff; cyw_spi_write(CYW_SD_FUNC_CHIP, CYW_CHIP_ADDRHIGH, &val, 1);
20816 val = (addr >> 16) & 0xff; cyw_spi_write(CYW_SD_FUNC_CHIP, CYW_CHIP_ADDRMID, &val, 1);
20817 val = (addr >> 8) & 0xff; cyw_spi_write(CYW_SD_FUNC_CHIP, CYW_CHIP_ADDRLOW, &val, 1);
20818}
20819 
20820static bool cyw_core_reset(uint32_t core_base, bool check) {
20821 uint32_t val = 0;
20822 // core disabled after chip reset
20823 cyw_set_backplane_window(core_base); // set backplane window for requested area; we do know offsets fall within that window
20824 // possible CHIP DEPENDENCY: AI_RESETSTATUS check and wait (instead of these cool reads) to ensure backplane operations end
20825 cyw_spi_read(CYW_SD_FUNC_CHIP, (core_base + CYW_CHIP_AI_IOCTRL) & CYW_CHIP_BCKPLN_ADDRMSK, &val, 1); // ensure backplane operations end
20826 val = MG_BIT(1) | MG_BIT(0) /* SICF_FGC | SICF_CLOCK_EN */; cyw_spi_write(CYW_SD_FUNC_CHIP, (core_base + CYW_CHIP_AI_IOCTRL) & CYW_CHIP_BCKPLN_ADDRMSK, &val, 1); // reset
20827 cyw_spi_read(CYW_SD_FUNC_CHIP, (core_base + CYW_CHIP_AI_IOCTRL) & CYW_CHIP_BCKPLN_ADDRMSK, &val, 1); // ensure backplane operations end
20828 val = 0x00; cyw_spi_write(CYW_SD_FUNC_CHIP, (core_base + CYW_CHIP_AI_RESETCTRL) & CYW_CHIP_BCKPLN_ADDRMSK, &val, 1); // release reset
20829 mg_delayms(1);
20830 val = MG_BIT(0) /* SICF_CLOCK_EN */; cyw_spi_write(CYW_SD_FUNC_CHIP, (core_base + CYW_CHIP_AI_IOCTRL) & CYW_CHIP_BCKPLN_ADDRMSK, &val, 1);
20831 cyw_spi_read(CYW_SD_FUNC_CHIP, (core_base + CYW_CHIP_AI_IOCTRL) & CYW_CHIP_BCKPLN_ADDRMSK, &val, 1); // ensure backplane operations end
20832 mg_delayms(1);
20833 
20834 if (check) {
20835 // Verify only clock is enabled
20836 cyw_spi_read(CYW_SD_FUNC_CHIP, (core_base + CYW_CHIP_AI_IOCTRL) & CYW_CHIP_BCKPLN_ADDRMSK, &val, 1);
20837 if ((val & (MG_BIT(1) | MG_BIT(0)) /* SICF_FGC | SICF_CLOCK_EN) */) != MG_BIT(0)) return false;
20838 // Verify it is not in reset state
20839 cyw_spi_read(CYW_SD_FUNC_CHIP, (core_base + CYW_CHIP_AI_RESETCTRL) & CYW_CHIP_BCKPLN_ADDRMSK, &val, 1);
20840 if (val & MG_BIT(0)) return false; // AIRC_RESET
20841 }
20842 return true;
20843}
20844 
20845static void cyw_socram_init(void) {
20846 uint32_t val;
20847 // CHIP DEPENDENCY: disable remap for SRAM_3
20848 cyw_set_backplane_window(CYW_CHIP_SOCSRAM_BASE); // set backplane window for requested area; we do know offsets fall within that window
20849 val = 0x03; cyw_spi_write(CYW_SD_FUNC_CHIP, ((CYW_CHIP_SOCSRAM_BASE + CYW_CHIP_SOCSRAM_BANKXIDX) & CYW_CHIP_BCKPLN_ADDRMSK) | CYW_CHIP_BCKPLN_ACCSS4B, &val, sizeof(val));
20850 val = 0x00; cyw_spi_write(CYW_SD_FUNC_CHIP, ((CYW_CHIP_SOCSRAM_BASE + CYW_CHIP_SOCSRAM_BANKXPDA) & CYW_CHIP_BCKPLN_ADDRMSK) | CYW_CHIP_BCKPLN_ACCSS4B, &val, sizeof(val));
20851}
20852 
20853// transfer is fractioned in bus-to-backplane-size units within backplane windows
20854static void cyw_load_data(uint32_t dest, void *data, size_t len) {
20855 size_t sent = 0, offset = 0;
20856 uint32_t last_addr = ~0;
20857 while (sent < len) {
20858 size_t bytes = len - sent, avail;
20859 uint32_t addr = dest + offset;
20860 if (addr - last_addr >= CYW_CHIP_BCKPLN_WINSZ || last_addr == ~0) {
20861 cyw_set_backplane_window(addr); // set backplane window for requested area
20862 last_addr = addr & ~CYW_CHIP_BCKPLN_ADDRMSK;
20863 }
20864 addr &= CYW_CHIP_BCKPLN_ADDRMSK;
20865 avail = CYW_CHIP_BCKPLN_WINSZ - (unsigned int) addr;
20866 if (bytes > avail) bytes = avail;
20867 // BUS DEPENDENCY: max bus to backplane transfer size
20868 if (bytes > CYW_CHIP_BCKPLN_SPIMAX) bytes = CYW_CHIP_BCKPLN_SPIMAX;
20869 cyw_spi_write(CYW_SD_FUNC_CHIP, addr | CYW_CHIP_BCKPLN_ACCSS4B, (uint8_t *)data + offset, bytes);
20870 sent += bytes;
20871 offset += bytes;
20872 }
20873}
20874 
20875// CHIP DEPENDENCY: no SOCSRAM base address; start address in fwdata image (Cortex-R4 chips)
20876static bool cyw_load_fwll(void *fwdata, size_t fwlen, void *nvramdata, size_t nvramlen) {
20877 uint32_t val = ((~(nvramlen / 4) & 0xffff) << 16) | (nvramlen / 4); // ~len len in 32-bit words
20878 cyw_core_reset(CYW_CHIP_SOCSRAM, false); // cores were disabled at chip reset
20879 cyw_socram_init();
20880 cyw_load_data(CYW_CHIP_ATCMRAM_BASE, fwdata, fwlen);
20881 mg_delayms(5); // ************ CHECK IF THIS IS ACTUALLY NEEDED
20882 // Load NVRAM and place 'length ~length' at the end; end of chip RAM
20883 {
20884 const uint32_t start = CYW_CHIP_RAM_SIZE - 4 - nvramlen;
20885 cyw_load_data(start, nvramdata, nvramlen); // nvramlen must be a multiple of 4
20886 // RAM_SIZE is a multiple of WINSZ, so the place for len ~len will be at the end of the window
20887 cyw_spi_write(CYW_SD_FUNC_CHIP, (CYW_CHIP_BCKPLN_WINSZ - 4) | CYW_CHIP_BCKPLN_ACCSS4B, &val, sizeof(val));
20888 }
20889 // Reset ARM core and check it starts
20890 if (!cyw_core_reset(CYW_CHIP_ARMCORE, true)) return false;
20891 return true;
20892}
20893// clang-format on
20894 
20895// CYW43 SPI bus specifics
20896 
20897#define CYW_BUS_SPI_BUSCTRL 0x00 // 4 regs, 0 to 3
20898#define CYW_BUS_SPI_INT 0x04 // 2 regs, 4 to 5
20899#define CYW_BUS_SPI_INTEN 0x06 // 16-bit register
20900#define CYW_BUS_SPI_STATUS 0x08 // 32-bit register
20901#define CYW_BUS_SPI_TEST 0x14 // 32-bit register
20902#define CYW_BUS_SPI_RESPDLY_F1 0x1d // 8-bit register, F1: chip
20903 
20904#define CYW_BUS_STS_LEN(x) ((x >> 9) & 0x7ff)
20905 
20906// clang-format off
20907static size_t cyw_spi_poll(uint8_t *response) {
20908 size_t len;
20909 uint32_t res;
20910 // SPI poll
20911 cyw_spi_read(CYW_SD_FUNC_BUS, CYW_BUS_SPI_STATUS, &res, sizeof(res));
20912 if (res == ~0 || !(res & MG_BIT(8) /* packet available */ )) return 0;
20913 len = CYW_BUS_STS_LEN(res);
20914 if (len == 0) { // just ack IRQ
20915 uint16_t val = 1;
20916 cyw_spi_write(CYW_SD_FUNC_CHIP, CYW_CHIP_SPIFRCTRL, &val, 1);
20917 cyw_spi_read(CYW_SD_FUNC_BUS, CYW_BUS_SPI_INT, &val, sizeof(val));
20918 cyw_spi_write(CYW_SD_FUNC_BUS, CYW_BUS_SPI_INT, &val, sizeof(val));
20919 return 0;
20920 }
20921 cyw_spi_read(CYW_SD_FUNC_WLAN, 0, response, len);
20922 return len;
20923}
20924 
20925// BUS DEPENDENCY: name is generic but function is bus dependent
20926static size_t cyw_bus_tx(uint32_t *data, uint16_t len) {
20927 while (len & 3) data[len++] = 0; // SPI 32-bit padding (SDIO->64-byte)
20928 return cyw_spi_write(CYW_SD_FUNC_WLAN, 0, data, len) ? len: 0;
20929}
20930 
20931// this can be integrated in lowest level SPI read/write _driver_ functions
20932// (those calling hal SPI transaction functions), though is only used at start
20933uint32_t sw16_2(uint32_t data) {
20934 return ((uint32_t)mg_htons((uint16_t)(data >> 16)) << 16) + mg_htons((uint16_t)data);
20935}
20936 
20937// DS 4.2.2 Table 6: signal we're working in 16-bit mode
20938#define CYW_SD_16bMODE MG_BIT(2) // arbitrary bit out of the FUNC space
20939 
20940static bool cyw_spi_init() {
20941 struct mg_tcpip_driver_cyw_data *d =
20942 (struct mg_tcpip_driver_cyw_data *) s_ifp->driver_data;
20943 uint32_t val = 0;
20944 // DS 4.2.3 Boot-Up Sequence; WHD: other chips might require more effort
20945 unsigned int times = 51;
20946 while (times--) {
20947 cyw_spi_read(CYW_SD_FUNC_BUS | CYW_SD_16bMODE, CYW_BUS_SPI_TEST, &val, sizeof(val));
20948 if (sw16_2(val) == 0xFEEDBEAD) break;
20949 mg_delayms(1);
20950 }
20951 if (times == ~0) return false;
20952 // DS 4.2.3 Table 6. Chip starts in 16-bit little-endian mode.
20953 // Configure SPI and switch to 32-bit big-endian mode:
20954 // - High-speed mode: d->hs true
20955 // - IRQ POLARITY high
20956 // - SPI RESPONSE DELAY 4 bytes time [not in DS] TODO(scaprile): logic ana
20957 // - Status not sent after command, IRQ with status
20958 val = sw16_2(0x000204a3 | (d->hs ? MG_BIT(4) : 0)); // 4 reg content
20959 cyw_spi_write(CYW_SD_FUNC_BUS | CYW_SD_16bMODE, CYW_BUS_SPI_BUSCTRL, &val, sizeof(val));
20960 mg_tcpip_call(s_ifp, MG_TCPIP_EV_DRIVER, NULL);
20961 cyw_spi_read(CYW_SD_FUNC_BUS, CYW_BUS_SPI_TEST, &val, sizeof(val));
20962 if (val != 0xFEEDBEAD) return false;
20963 val = 4; cyw_spi_write(CYW_SD_FUNC_BUS, CYW_BUS_SPI_RESPDLY_F1, &val, 1);
20964 val = 0x99; // clear error bits DATA_UNAVAILABLE, COMMAND_ERROR, DATA_ERROR, F1_OVERFLOW
20965 cyw_spi_write(CYW_SD_FUNC_BUS, CYW_BUS_SPI_INT, &val, 1);
20966 val = 0x00be; // Enable IRQs F2_F3_FIFO_RD_UNDERFLOW, F2_F3_FIFO_WR_OVERFLOW, COMMAND_ERROR, DATA_ERROR, F2_PACKET_AVAILABLE, F1_OVERFLOW
20967 // BT-ENABLED DEPENDENCY: add F1_INTR (bit 13)
20968 cyw_spi_write(CYW_SD_FUNC_BUS, CYW_BUS_SPI_INTEN, &val, sizeof(uint16_t));
20969 
20970 // chip backplane is ready, initialize it
20971 // request ALP (Active Low Power) clock
20972 val = MG_BIT(3) /* ALP_REQ */; cyw_spi_write(CYW_SD_FUNC_CHIP, CYW_CHIP_CLOCKCSR, &val, 1);
20973 // BT-ENABLED DEPENDENCY
20974 times = 10;
20975 while (times--) {
20976 cyw_spi_read(CYW_SD_FUNC_CHIP, CYW_CHIP_CLOCKCSR, &val, 1);
20977 if (val & MG_BIT(6)) break; // ALP_AVAIL
20978 mg_delayms(1);
20979 }
20980 if (times == ~0) return false;
20981 // clear request
20982 val = 0; cyw_spi_write(CYW_SD_FUNC_CHIP, CYW_CHIP_CLOCKCSR, &val, 1);
20983 cyw_set_backplane_window(CYW_CHIP_CHIPCOMMON); // set backplane window to start of CHIPCOMMON area
20984 cyw_spi_read(CYW_SD_FUNC_CHIP, (CYW_CHIP_CHIPCOMMON + 0x00) & CYW_CHIP_BCKPLN_ADDRMSK, &val, 2);
20985 MG_INFO(("WLAN chip is CYW%u", *((uint16_t *)&val)));
20986 
20987 // Load firmware (code and NVRAM)
20988 if (!cyw_load_firmware(d->fw)) return false;
20989 
20990 // Wait for High Throughput (HT) clock ready
20991 times = 50;
20992 while (times--) {
20993 cyw_spi_read(CYW_SD_FUNC_CHIP, CYW_CHIP_CLOCKCSR, &val, 1);
20994 if (val & MG_BIT(7)) break; // HT_AVAIL
20995 mg_delayms(1);
20996 }
20997 if (times == ~0) return false;
20998 // Wait for backplane ready
20999 times = 1000;
21000 while (times--) {
21001 cyw_spi_read(CYW_SD_FUNC_BUS, CYW_BUS_SPI_STATUS, &val, sizeof(val));
21002 if (val & MG_BIT(5)) break; // F2_RX_READY
21003 mg_delayms(1);
21004 }
21005 if (times == ~0) return false;
21006 
21007 // CHIP DEPENDENCY
21008 // Enable save / restore
21009 // Configure WakeupCtrl, set HT_AVAIL in CLOCK_CSR
21010 cyw_spi_read(CYW_SD_FUNC_CHIP, CYW_CHIP_WAKEUPCTL, &val, 1);
21011 val |= MG_BIT(1) /* WAKE_TILL_HT_AVAIL */; cyw_spi_write(CYW_SD_FUNC_CHIP, CYW_CHIP_WAKEUPCTL, &val, 1);
21012#if 0
21013 // Set BRCM_CARDCAP to CMD_NODEC. NOTE(): This is probably only necessary for SDIO, not SPI
21014 val = MG_BIT(3); cyw_spi_write(CYW_SD_FUNC_BUS, 0xf0 /* SDIOD_CCCR_BRCM_CARDCAP */, &val, 1);
21015#endif
21016 // Force HT request to chip backplane
21017 val = MG_BIT(1) /* FORCE_HT */; cyw_spi_write(CYW_SD_FUNC_CHIP, CYW_CHIP_CLOCKCSR, &val, 1);
21018 // Enable Keep SDIO On (KSO)
21019 cyw_spi_read(CYW_SD_FUNC_CHIP, CYW_CHIP_SLEEPCSR, &val, 1);
21020 if (!(val & MG_BIT(0))) {
21021 val |= MG_BIT(0); cyw_spi_write(CYW_SD_FUNC_CHIP, CYW_CHIP_SLEEPCSR, &val, 1);
21022 }
21023 // The SPI bus can be configured for sleep (KSO controls wlan block sleep)
21024 cyw_spi_read(CYW_SD_FUNC_BUS, CYW_BUS_SPI_BUSCTRL, &val, sizeof(val));
21025 val &= ~MG_BIT(7) /* WAKE_UP */; cyw_spi_write(CYW_SD_FUNC_BUS, CYW_BUS_SPI_BUSCTRL, &val, sizeof(val));
21026 // Set SPI bus sleep
21027 val = 0x0f; cyw_spi_write(CYW_SD_FUNC_CHIP, CYW_CHIP_PULLUP, &val, 1);
21028 
21029 // Clear pullups. NOTE(): ?
21030 val = 0x00; cyw_spi_write(CYW_SD_FUNC_CHIP, CYW_CHIP_PULLUP, &val, 1);
21031 cyw_spi_read(CYW_SD_FUNC_CHIP, CYW_CHIP_PULLUP, &val, 1);
21032 // Clear possible data unavailable error
21033 cyw_spi_read(CYW_SD_FUNC_BUS, CYW_BUS_SPI_INTEN, &val, sizeof(uint16_t));
21034 if (val & MG_BIT(0)) cyw_spi_write(CYW_SD_FUNC_BUS, CYW_BUS_SPI_INTEN, &val, sizeof(uint16_t));
21035 
21036 // Load CLM blob
21037 if (!cyw_load_clm(d->fw)) return false;
21038 
21039 return true;
21040}
21041// clang-format on
21042 
21043// gSPI, DS 4.2.1 Fig.12
21044#define CYW_SD_LEN(x) ((x) &0x7FF) // bits 0-10
21045#define CYW_SD_ADDR(x) (((x) &0x1FFFF) << 11) // bits 11-27,
21046#define CYW_SD_FUNC(x) (((x) &3) << 28) // bits 28-29
21047#define CYW_SD_INC MG_BIT(30)
21048#define CYW_SD_WR MG_BIT(31)
21049 
21050static bool cyw_spi_write(unsigned int f, uint32_t addr, void *data,
21051 uint16_t len) {
21052 struct mg_tcpip_driver_cyw_data *d =
21053 (struct mg_tcpip_driver_cyw_data *) s_ifp->driver_data;
21054 struct mg_tcpip_spi_ *s = (struct mg_tcpip_spi_ *) d->spi;
21055 uint32_t hdr = CYW_SD_WR | CYW_SD_INC | CYW_SD_FUNC(f) | CYW_SD_ADDR(addr) |
21056 CYW_SD_LEN(len); // gSPI header
21057 // TODO(scaprile): check spin in between and timeout values, return false
21058 if (f == CYW_SD_FUNC_WLAN) {
21059 uint32_t val = 0;
21060 while ((val & MG_BIT(5)) != MG_BIT(5)) // F2 rx ready (FIFO ready)
21061 cyw_spi_read(CYW_SD_FUNC_BUS, CYW_BUS_SPI_STATUS, &val, sizeof(val));
21062 }
21063 if (f & CYW_SD_16bMODE)
21064 hdr = sw16_2(hdr); // swap half-words in 16-bit little-endian mode
21065 
21066 s->begin(NULL);
21067 s->txn(NULL, (uint8_t *) &hdr, NULL, sizeof(hdr));
21068 if (len <= 4) {
21069 uint32_t pad = 0;
21070 memcpy(&pad, data, len);
21071 s->txn(NULL, (uint8_t *) &pad, NULL, sizeof(pad));
21072 } else {
21073 s->txn(NULL, (uint8_t *) data, NULL, len);
21074 }
21075 s->end(NULL);
21076 return true;
21077}
21078 
21079// will write 32-bit aligned quantities to data if f == CYW_SD_FUNC_WLAN
21080static void cyw_spi_read(unsigned int f, uint32_t addr, void *data,
21081 uint16_t len) {
21082 struct mg_tcpip_driver_cyw_data *d =
21083 (struct mg_tcpip_driver_cyw_data *) s_ifp->driver_data;
21084 struct mg_tcpip_spi_ *s = (struct mg_tcpip_spi_ *) d->spi;
21085 uint32_t padding =
21086 f == CYW_SD_FUNC_CHIP
21087 ? 4
21088 : 0; // add padding to chip backplane reads as a response delay
21089 uint32_t hdr = CYW_SD_INC | CYW_SD_FUNC(f) | CYW_SD_ADDR(addr) |
21090 CYW_SD_LEN(len + padding); // gSPI header
21091 if (f == CYW_SD_FUNC_WLAN && (len & 3))
21092 len = (len + 4) & ~3; // align WLAN transfers to 32-bit
21093 if (f & CYW_SD_16bMODE)
21094 hdr = sw16_2(hdr); // swap half-words in 16-bit little-endian mode
21095 
21096 s->begin(NULL);
21097 s->txn(NULL, (uint8_t *) &hdr, NULL, sizeof(hdr));
21098 if (f == CYW_SD_FUNC_CHIP) {
21099 uint32_t pad;
21100 s->txn(NULL, NULL, (uint8_t *) &pad, 4); // read padding back and discard
21101 }
21102 s->txn(NULL, NULL, (uint8_t *) data, len);
21103 s->end(NULL);
21104}
21105 
21106// Mongoose Wi-Fi API functions
21107 
21108bool mg_wifi_scan(void) {
21109 return cyw_wifi_scan();
21110}
21111 
21112bool mg_wifi_connect(char *ssid, char *pass) {
21113 return cyw_wifi_connect(ssid, pass);
21114}
21115 
21116bool mg_wifi_disconnect(void) {
21117 return cyw_wifi_disconnect();
21118}
21119 
21120bool mg_wifi_ap_start(char *ssid, char *pass, unsigned int channel) {
21121 return cyw_wifi_ap_start(ssid, pass, channel);
21122}
21123 
21124bool mg_wifi_ap_stop(void) {
21125 return cyw_wifi_ap_stop();
21126}
21127 
21128#endif
21129 
21130#ifdef MG_ENABLE_LINES
21131#line 1 "src/drivers/imxrt.c"
21132#endif
21133 
21134 
21135#if MG_ENABLE_TCPIP && defined(MG_ENABLE_DRIVER_IMXRT) && MG_ENABLE_DRIVER_IMXRT
21136struct imxrt_enet {
21137 volatile uint32_t RESERVED0, EIR, EIMR, RESERVED1, RDAR, TDAR, RESERVED2[3],
21138 ECR, RESERVED3[6], MMFR, MSCR, RESERVED4[7], MIBC, RESERVED5[7], RCR,
21139 RESERVED6[15], TCR, RESERVED7[7], PALR, PAUR, OPD, TXIC0, TXIC1, TXIC2,
21140 RESERVED8, RXIC0, RXIC1, RXIC2, RESERVED9[3], IAUR, IALR, GAUR, GALR,
21141 RESERVED10[7], TFWR, RESERVED11[14], RDSR, TDSR, MRBR[2], RSFL, RSEM,
21142 RAEM, RAFL, TSEM, TAEM, TAFL, TIPG, FTRL, RESERVED12[3], TACC, RACC,
21143 RESERVED13[15], RMON_T_PACKETS, RMON_T_BC_PKT, RMON_T_MC_PKT,
21144 RMON_T_CRC_ALIGN, RMON_T_UNDERSIZE, RMON_T_OVERSIZE, RMON_T_FRAG,
21145 RMON_T_JAB, RMON_T_COL, RMON_T_P64, RMON_T_P65TO127, RMON_T_P128TO255,
21146 RMON_T_P256TO511, RMON_T_P512TO1023, RMON_T_P1024TO2048, RMON_T_GTE2048,
21147 RMON_T_OCTETS, IEEE_T_DROP, IEEE_T_FRAME_OK, IEEE_T_1COL, IEEE_T_MCOL,
21148 IEEE_T_DEF, IEEE_T_LCOL, IEEE_T_EXCOL, IEEE_T_MACERR, IEEE_T_CSERR,
21149 IEEE_T_SQE, IEEE_T_FDXFC, IEEE_T_OCTETS_OK, RESERVED14[3], RMON_R_PACKETS,
21150 RMON_R_BC_PKT, RMON_R_MC_PKT, RMON_R_CRC_ALIGN, RMON_R_UNDERSIZE,
21151 RMON_R_OVERSIZE, RMON_R_FRAG, RMON_R_JAB, RESERVED15, RMON_R_P64,
21152 RMON_R_P65TO127, RMON_R_P128TO255, RMON_R_P256TO511, RMON_R_P512TO1023,
21153 RMON_R_P1024TO2047, RMON_R_GTE2048, RMON_R_OCTETS, IEEE_R_DROP,
21154 IEEE_R_FRAME_OK, IEEE_R_CRC, IEEE_R_ALIGN, IEEE_R_MACERR, IEEE_R_FDXFC,
21155 IEEE_R_OCTETS_OK, RESERVED16[71], ATCR, ATVR, ATOFF, ATPER, ATCOR, ATINC,
21156 ATSTMP, RESERVED17[122], TGSR, TCSR0, TCCR0, TCSR1, TCCR1, TCSR2, TCCR2,
21157 TCSR3;
21158};
21159 
21160#undef ENET
21161#if defined(MG_DRIVER_IMXRT_RT11) && MG_DRIVER_IMXRT_RT11
21162#define ENET ((struct imxrt_enet *) (uintptr_t) 0x40424000U)
21163#define ETH_DESC_CNT 5 // Descriptors count
21164#else
21165#define ENET ((struct imxrt_enet *) (uintptr_t) 0x402D8000U)
21166#define ETH_DESC_CNT 4 // Descriptors count
21167#endif
21168 
21169#define ETH_PKT_SIZE 1536 // Max frame size, 64-bit aligned
21170 
21171struct enet_desc {
21172 uint16_t length; // Data length
21173 uint16_t control; // Control and status
21174 uint32_t *buffer; // Data ptr
21175};
21176 
21177// TODO(): handle these in a portable compiler-independent CMSIS-friendly way
21178#define MG_64BYTE_ALIGNED __attribute__((aligned((64U))))
21179 
21180// Descriptors: in non-cached area (TODO(scaprile)), (37.5.1.22.2 37.5.1.23.2)
21181// Buffers: 64-byte aligned (37.3.14)
21182static volatile struct enet_desc s_rxdesc[ETH_DESC_CNT] MG_64BYTE_ALIGNED;
21183static volatile struct enet_desc s_txdesc[ETH_DESC_CNT] MG_64BYTE_ALIGNED;
21184static uint8_t s_rxbuf[ETH_DESC_CNT][ETH_PKT_SIZE] MG_64BYTE_ALIGNED;
21185static uint8_t s_txbuf[ETH_DESC_CNT][ETH_PKT_SIZE] MG_64BYTE_ALIGNED;
21186static struct mg_tcpip_if *s_ifp; // MIP interface
21187 
21188static uint16_t enet_read_phy(uint8_t addr, uint8_t reg) {
21189 ENET->EIR |= MG_BIT(23); // MII interrupt clear
21190 ENET->MMFR = (1 << 30) | (2 << 28) | (addr << 23) | (reg << 18) | (2 << 16);
21191 while ((ENET->EIR & MG_BIT(23)) == 0) (void) 0;
21192 return ENET->MMFR & 0xffff;
21193}
21194 
21195static void enet_write_phy(uint8_t addr, uint8_t reg, uint16_t val) {
21196 ENET->EIR |= MG_BIT(23); // MII interrupt clear
21197 ENET->MMFR =
21198 (1 << 30) | (1 << 28) | (addr << 23) | (reg << 18) | (2 << 16) | val;
21199 while ((ENET->EIR & MG_BIT(23)) == 0) (void) 0;
21200}
21201 
21202// MDC clock is generated from IPS Bus clock (ipg_clk); as per 802.3,
21203// it must not exceed 2.5MHz
21204// The PHY receives the PLL6-generated 50MHz clock
21205static bool mg_tcpip_driver_imxrt_init(struct mg_tcpip_if *ifp) {
21206 struct mg_tcpip_driver_imxrt_data *d =
21207 (struct mg_tcpip_driver_imxrt_data *) ifp->driver_data;
21208 s_ifp = ifp;
21209 
21210 // Init RX descriptors
21211 for (int i = 0; i < ETH_DESC_CNT; i++) {
21212 s_rxdesc[i].control = MG_BIT(15); // Own (E)
21213 s_rxdesc[i].buffer = (uint32_t *) s_rxbuf[i]; // Point to data buffer
21214 }
21215 s_rxdesc[ETH_DESC_CNT - 1].control |= MG_BIT(13); // Wrap last descriptor
21216 
21217 // Init TX descriptors
21218 for (int i = 0; i < ETH_DESC_CNT; i++) {
21219 // s_txdesc[i].control = MG_BIT(10); // Own (TC)
21220 s_txdesc[i].buffer = (uint32_t *) s_txbuf[i];
21221 }
21222 s_txdesc[ETH_DESC_CNT - 1].control |= MG_BIT(13); // Wrap last descriptor
21223 
21224 ENET->ECR = MG_BIT(0); // Software reset, disable
21225 while ((ENET->ECR & MG_BIT(0))) (void) 0; // Wait until done
21226 
21227 // Set MDC clock divider. If user told us the value, use it.
21228 // TODO(): Otherwise, guess (currently assuming max freq)
21229 int cr = (d == NULL || d->mdc_cr < 0) ? 24 : d->mdc_cr;
21230 ENET->MSCR = (1 << 8) | ((cr & 0x3f) << 1); // HOLDTIME 2 clks
21231 struct mg_phy phy = {enet_read_phy, enet_write_phy};
21232 mg_phy_init(&phy, d->phy_addr, MG_PHY_LEDS_ACTIVE_HIGH); // MAC clocks PHY
21233 // Select RMII mode, 100M, keep CRC, set max rx length, disable loop
21234 ENET->RCR = (1518 << 16) | MG_BIT(8) | MG_BIT(2);
21235 // ENET->RCR |= MG_BIT(3); // Receive all
21236 ENET->TCR = MG_BIT(2); // Full-duplex
21237 ENET->RDSR = (uint32_t) (uintptr_t) s_rxdesc;
21238 ENET->TDSR = (uint32_t) (uintptr_t) s_txdesc;
21239 ENET->MRBR[0] = ETH_PKT_SIZE; // Same size for RX/TX buffers
21240 // MAC address filtering (bytes in reversed order)
21241 ENET->PAUR = ((uint32_t) ifp->mac[4] << 24U) | (uint32_t) ifp->mac[5] << 16U;
21242 ENET->PALR = (uint32_t) (ifp->mac[0] << 24U) |
21243 ((uint32_t) ifp->mac[1] << 16U) |
21244 ((uint32_t) ifp->mac[2] << 8U) | ifp->mac[3];
21245 ENET->ECR = MG_BIT(8) | MG_BIT(1); // Little-endian CPU, Enable
21246 ENET->EIMR = MG_BIT(25); // Set interrupt mask
21247 ENET->RDAR = MG_BIT(24); // Receive Descriptors have changed
21248 ENET->TDAR = MG_BIT(24); // Transmit Descriptors have changed
21249 // ENET->OPD = 0x10014;
21250 ENET->IAUR = 0;
21251 ENET->IALR = 0;
21252 ENET->GAUR = 0;
21253 ENET->GALR = 0;
21254 return true;
21255}
21256 
21257 
21258// Transmit frame
21259static size_t mg_tcpip_driver_imxrt_tx(const void *buf, size_t len,
21260 struct mg_tcpip_if *ifp) {
21261 static int s_txno; // Current descriptor index
21262 if (len > sizeof(s_txbuf[ETH_DESC_CNT])) {
21263 MG_ERROR(("Frame too big, %ld", (long) len));
21264 len = (size_t) -1; // fail
21265 } else if ((s_txdesc[s_txno].control & MG_BIT(15))) {
21266 ifp->nerr++;
21267 MG_ERROR(("No descriptors available"));
21268 len = 0; // retry later
21269 } else {
21270 memcpy(s_txbuf[s_txno], buf, len); // Copy data
21271 s_txdesc[s_txno].length = (uint16_t) len; // Set data len
21272 // Table 37-34, R, L, TC (Ready, last, transmit CRC after frame
21273 s_txdesc[s_txno].control |=
21274 (uint16_t) (MG_BIT(15) | MG_BIT(11) | MG_BIT(10));
21275 ENET->TDAR = MG_BIT(24); // Descriptor ring updated
21276 if (++s_txno >= ETH_DESC_CNT) s_txno = 0;
21277 }
21278 (void) ifp;
21279 return len;
21280}
21281 
21282static void mg_tcpip_driver_imxrt_update_hash_table(struct mg_tcpip_if *ifp) {
21283 // TODO(): read database, rebuild hash table
21284 // RM 37.3.4.3.2
21285 uint32_t hash_table[2] = {0, 0};
21286 // uint8_t hash64 = ((~mg_crc32(0, mcast_addr, 6)) >> 26) & 0x3f;
21287 // hash_table[((uint8_t)hash64) >> 5] |= (1 << (hash64 & 0x1f));
21288 hash_table[1] = MG_BIT(1); // above reduces to this for mDNS addr
21289 ENET->GAUR = hash_table[1];
21290 ENET->GALR = hash_table[0];
21291 (void) ifp;
21292}
21293 
21294static bool mg_tcpip_driver_imxrt_poll(struct mg_tcpip_if *ifp, bool s1) {
21295 if (ifp->update_mac_hash_table) {
21296 mg_tcpip_driver_imxrt_update_hash_table(ifp);
21297 ifp->update_mac_hash_table = false;
21298 }
21299 if (!s1) return false;
21300 struct mg_tcpip_driver_imxrt_data *d =
21301 (struct mg_tcpip_driver_imxrt_data *) ifp->driver_data;
21302 uint8_t speed = MG_PHY_SPEED_10M;
21303 bool up = false, full_duplex = false;
21304 struct mg_phy phy = {enet_read_phy, enet_write_phy};
21305 up = mg_phy_up(&phy, d->phy_addr, &full_duplex, &speed);
21306 if ((ifp->state == MG_TCPIP_STATE_DOWN) && up) { // link state just went up
21307 // tmp = reg with flags set to the most likely situation: 100M full-duplex
21308 // if(link is slow or half) set flags otherwise
21309 // reg = tmp
21310 uint32_t tcr = ENET->TCR | MG_BIT(2); // Full-duplex
21311 uint32_t rcr = ENET->RCR & ~MG_BIT(9); // 100M
21312 if (speed == MG_PHY_SPEED_10M) rcr |= MG_BIT(9); // 10M
21313 if (full_duplex == false) tcr &= ~MG_BIT(2); // Half-duplex
21314 ENET->TCR = tcr; // IRQ handler does not fiddle with these registers
21315 ENET->RCR = rcr;
21316 MG_DEBUG(("Link is %uM %s-duplex", rcr & MG_BIT(9) ? 10 : 100,
21317 tcr & MG_BIT(2) ? "full" : "half"));
21318 }
21319 return up;
21320}
21321 
21322void ENET_IRQHandler(void);
21323static uint32_t s_rxno;
21324void ENET_IRQHandler(void) {
21325 ENET->EIR = MG_BIT(25); // Ack IRQ
21326 // Frame received, loop
21327 for (uint32_t i = 0; i < 10; i++) { // read as they arrive but not forever
21328 uint32_t r = s_rxdesc[s_rxno].control;
21329 if (r & MG_BIT(15)) break; // exit when done
21330 // skip partial/errored frames (Table 37-32)
21331 if ((r & MG_BIT(11)) &&
21332 !(r & (MG_BIT(5) | MG_BIT(4) | MG_BIT(2) | MG_BIT(1) | MG_BIT(0)))) {
21333 size_t len = s_rxdesc[s_rxno].length;
21334 mg_tcpip_qwrite(s_rxbuf[s_rxno], len > 4 ? len - 4 : len, s_ifp);
21335 }
21336 s_rxdesc[s_rxno].control |= MG_BIT(15);
21337 if (++s_rxno >= ETH_DESC_CNT) s_rxno = 0;
21338 }
21339 ENET->RDAR = MG_BIT(24); // Receive Descriptors have changed
21340 // If b24 == 0, descriptors were exhausted and probably frames were dropped
21341}
21342 
21343struct mg_tcpip_driver mg_tcpip_driver_imxrt = {mg_tcpip_driver_imxrt_init,
21344 mg_tcpip_driver_imxrt_tx, NULL,
21345 mg_tcpip_driver_imxrt_poll};
21346 
21347#endif
21348 
21349#ifdef MG_ENABLE_LINES
21350#line 1 "src/drivers/phy.c"
21351#endif
21352 
21353 
21354enum { // ID1 ID2
21355 MG_PHY_KSZ8x = 0x22, // 0022 1561 - KSZ8081RNB
21356 MG_PHY_DP83x = 0x2000,
21357 MG_PHY_DP83867 = 0xa231, // 2000 a231 - TI DP83867I
21358 MG_PHY_DP83825 = 0xa140, // 2000 a140 - TI DP83825I
21359 MG_PHY_DP83848 = 0x5ca2, // 2000 5ca2 - TI DP83848I
21360 MG_PHY_LAN87x = 0x7, // 0007 c0fx - LAN8720
21361 MG_PHY_RTL8201 = 0x1C // 001c c816 - RTL8201
21362};
21363 
21364enum {
21365 MG_PHY_REG_BCR = 0,
21366 MG_PHY_REG_BSR = 1,
21367 MG_PHY_REG_ID1 = 2,
21368 MG_PHY_REG_ID2 = 3,
21369 MG_PHY_DP83x_REG_PHYSTS = 16,
21370 MG_PHY_DP83867_REG_PHYSTS = 17,
21371 MG_PHY_DP83x_REG_RCSR = 23,
21372 MG_PHY_DP83x_REG_LEDCR = 24,
21373 MG_PHY_KSZ8x_REG_PC1R = 30,
21374 MG_PHY_KSZ8x_REG_PC2R = 31,
21375 MG_PHY_LAN87x_REG_SCSR = 31,
21376 MG_PHY_RTL8201_REG_RMSR = 16, // in page 7
21377 MG_PHY_RTL8201_REG_PAGESEL = 31
21378};
21379 
21380static const char *mg_phy_id_to_str(uint16_t id1, uint16_t id2) {
21381 switch (id1) {
21382 case MG_PHY_DP83x:
21383 switch (id2) {
21384 case MG_PHY_DP83867:
21385 return "DP83867";
21386 case MG_PHY_DP83848:
21387 return "DP83848";
21388 case MG_PHY_DP83825:
21389 return "DP83825";
21390 default:
21391 return "DP83x";
21392 }
21393 case MG_PHY_KSZ8x:
21394 return "KSZ8x";
21395 case MG_PHY_LAN87x:
21396 return "LAN87x";
21397 case MG_PHY_RTL8201:
21398 return "RTL8201";
21399 default:
21400 return "unknown";
21401 }
21402 (void) id2;
21403}
21404 
21405void mg_phy_init(struct mg_phy *phy, uint8_t phy_addr, uint8_t config) {
21406 uint16_t id1, id2;
21407 phy->write_reg(phy_addr, MG_PHY_REG_BCR, MG_BIT(15)); // Reset PHY
21408 while (phy->read_reg(phy_addr, MG_PHY_REG_BCR) & MG_BIT(15)) (void) 0;
21409 // MG_PHY_REG_BCR[12]: Autonegotiation is default unless hw says otherwise
21410 
21411 id1 = phy->read_reg(phy_addr, MG_PHY_REG_ID1);
21412 id2 = phy->read_reg(phy_addr, MG_PHY_REG_ID2);
21413 MG_INFO(("PHY ID: %#04x %#04x (%s)", id1, id2, mg_phy_id_to_str(id1, id2)));
21414 
21415 if (id1 == MG_PHY_DP83x && id2 == MG_PHY_DP83867) {
21416 phy->write_reg(phy_addr, 0x0d, 0x1f); // write 0x10d to IO_MUX_CFG (0x0170)
21417 phy->write_reg(phy_addr, 0x0e, 0x170);
21418 phy->write_reg(phy_addr, 0x0d, 0x401f);
21419 phy->write_reg(phy_addr, 0x0e, 0x10d);
21420 }
21421 
21422 if (config & MG_PHY_CLOCKS_MAC) {
21423 // Use PHY crystal oscillator (preserve defaults)
21424 // nothing to do
21425 } else { // MAC clocks PHY, PHY has no xtal
21426 // Enable 50 MHz external ref clock at XI (preserve defaults)
21427 if (id1 == MG_PHY_DP83x && id2 != MG_PHY_DP83867 && id2 != MG_PHY_DP83848) {
21428 phy->write_reg(phy_addr, MG_PHY_DP83x_REG_RCSR, MG_BIT(7) | MG_BIT(0));
21429 } else if (id1 == MG_PHY_KSZ8x) {
21430 // Disable isolation (override hw, it doesn't make sense at this point)
21431 phy->write_reg( // #2848, some NXP boards set ISO, even though
21432 phy_addr, MG_PHY_REG_BCR, // docs say they don't
21433 phy->read_reg(phy_addr, MG_PHY_REG_BCR) & (uint16_t) ~MG_BIT(10));
21434 phy->write_reg(phy_addr, MG_PHY_KSZ8x_REG_PC2R, // now do clock stuff
21435 MG_BIT(15) | MG_BIT(8) | MG_BIT(7));
21436 } else if (id1 == MG_PHY_LAN87x) {
21437 // nothing to do
21438 } else if (id1 == MG_PHY_RTL8201) {
21439 // assume PHY has been hardware strapped properly
21440#if 0
21441 phy->write_reg(phy_addr, MG_PHY_RTL8201_REG_PAGESEL, 7); // Select page 7
21442 phy->write_reg(phy_addr, MG_PHY_RTL8201_REG_RMSR, 0x1ffa);
21443 phy->write_reg(phy_addr, MG_PHY_RTL8201_REG_PAGESEL, 0); // Select page 0
21444#endif
21445 }
21446 }
21447 
21448 if (config & MG_PHY_LEDS_ACTIVE_HIGH && id1 == MG_PHY_DP83x) {
21449 phy->write_reg(phy_addr, MG_PHY_DP83x_REG_LEDCR,
21450 MG_BIT(9) | MG_BIT(7)); // LED status, active high
21451 } // Other PHYs do not support this feature
21452}
21453 
21454bool mg_phy_up(struct mg_phy *phy, uint8_t phy_addr, bool *full_duplex,
21455 uint8_t *speed) {
21456 bool up = false;
21457 uint16_t bsr = phy->read_reg(phy_addr, MG_PHY_REG_BSR);
21458 if ((bsr & MG_BIT(5)) && !(bsr & MG_BIT(2))) // some PHYs latch down events
21459 bsr = phy->read_reg(phy_addr, MG_PHY_REG_BSR); // read again
21460 up = bsr & MG_BIT(2);
21461 if (up && full_duplex != NULL && speed != NULL) {
21462 uint16_t id1 = phy->read_reg(phy_addr, MG_PHY_REG_ID1);
21463 if (id1 == MG_PHY_DP83x) {
21464 uint16_t id2 = phy->read_reg(phy_addr, MG_PHY_REG_ID2);
21465 if (id2 == MG_PHY_DP83867) {
21466 uint16_t physts = phy->read_reg(phy_addr, MG_PHY_DP83867_REG_PHYSTS);
21467 *full_duplex = physts & MG_BIT(13);
21468 *speed = (physts & MG_BIT(15)) ? MG_PHY_SPEED_1000M
21469 : (physts & MG_BIT(14)) ? MG_PHY_SPEED_100M
21470 : MG_PHY_SPEED_10M;
21471 } else {
21472 uint16_t physts = phy->read_reg(phy_addr, MG_PHY_DP83x_REG_PHYSTS);
21473 *full_duplex = physts & MG_BIT(2);
21474 *speed = (physts & MG_BIT(1)) ? MG_PHY_SPEED_10M : MG_PHY_SPEED_100M;
21475 }
21476 } else if (id1 == MG_PHY_KSZ8x) {
21477 uint16_t pc1r = phy->read_reg(phy_addr, MG_PHY_KSZ8x_REG_PC1R);
21478 *full_duplex = pc1r & MG_BIT(2);
21479 *speed = (pc1r & 3) == 1 ? MG_PHY_SPEED_10M : MG_PHY_SPEED_100M;
21480 } else if (id1 == MG_PHY_LAN87x) {
21481 uint16_t scsr = phy->read_reg(phy_addr, MG_PHY_LAN87x_REG_SCSR);
21482 *full_duplex = scsr & MG_BIT(4);
21483 *speed = (scsr & MG_BIT(3)) ? MG_PHY_SPEED_100M : MG_PHY_SPEED_10M;
21484 } else if (id1 == MG_PHY_RTL8201) {
21485 uint16_t bcr = phy->read_reg(phy_addr, MG_PHY_REG_BCR);
21486 *full_duplex = bcr & MG_BIT(8);
21487 *speed = (bcr & MG_BIT(13)) ? MG_PHY_SPEED_100M : MG_PHY_SPEED_10M;
21488 }
21489 }
21490 return up;
21491}
21492 
21493#ifdef MG_ENABLE_LINES
21494#line 1 "src/drivers/pico-w.c"
21495#endif
21496#if MG_ENABLE_TCPIP && MG_ARCH == MG_ARCH_PICOSDK && \
21497 defined(MG_ENABLE_DRIVER_PICO_W) && MG_ENABLE_DRIVER_PICO_W
21498 
21499 
21500 
21501 
21502 
21503static struct mg_tcpip_if *s_ifp;
21504 
21505static bool mg_tcpip_driver_pico_w_init(struct mg_tcpip_if *ifp) {
21506 struct mg_tcpip_driver_pico_w_data *d =
21507 (struct mg_tcpip_driver_pico_w_data *) ifp->driver_data;
21508 s_ifp = ifp;
21509 if (cyw43_arch_init() != 0)
21510 return false; // initialize async_context and WiFi chip
21511 if (d->apmode && d->apssid != NULL) {
21512 MG_DEBUG(("Starting AP '%s' (%u)", d->apssid, d->apchannel));
21513 if (!mg_wifi_ap_start(d->apssid, d->appass, d->apchannel)) return false;
21514 cyw43_wifi_get_mac(&cyw43_state, CYW43_ITF_STA, ifp->mac); // same MAC
21515 } else {
21516 cyw43_arch_enable_sta_mode();
21517 cyw43_wifi_get_mac(&cyw43_state, CYW43_ITF_STA, ifp->mac);
21518 if (d->ssid != NULL) {
21519 MG_DEBUG(("Connecting to '%s'", d->ssid));
21520 return mg_wifi_connect(d->ssid, d->pass);
21521 } else {
21522 cyw43_arch_disable_sta_mode();
21523 }
21524 }
21525 return true;
21526}
21527 
21528static size_t mg_tcpip_driver_pico_w_tx(const void *buf, size_t len,
21529 struct mg_tcpip_if *ifp) {
21530 struct mg_tcpip_driver_pico_w_data *d =
21531 (struct mg_tcpip_driver_pico_w_data *) ifp->driver_data;
21532 return cyw43_send_ethernet(&cyw43_state,
21533 d->apmode ? CYW43_ITF_AP : CYW43_ITF_STA, len, buf,
21534 false) == 0
21535 ? len
21536 : 0;
21537}
21538 
21539static bool s_aplink = false, s_scanning = false;
21540static bool s_stalink = false, s_connecting = false;
21541 
21542static bool mg_tcpip_driver_pico_w_poll(struct mg_tcpip_if *ifp, bool s1) {
21543 cyw43_arch_poll(); // not necessary, except when IRQs are disabled (OTA)
21544 if (s_scanning && !cyw43_wifi_scan_active(&cyw43_state)) {
21545 MG_VERBOSE(("scan complete"));
21546 s_scanning = 0;
21547 mg_tcpip_call(s_ifp, MG_TCPIP_EV_WIFI_SCAN_END, NULL);
21548 }
21549 if (ifp->update_mac_hash_table) {
21550 // first call to _poll() is after _init(), so this is safe
21551 cyw43_wifi_update_multicast_filter(&cyw43_state, (uint8_t *)mcast_addr, true);
21552 ifp->update_mac_hash_table = false;
21553 }
21554 if (!s1) return false;
21555 struct mg_tcpip_driver_pico_w_data *d =
21556 (struct mg_tcpip_driver_pico_w_data *) ifp->driver_data;
21557 if (d->apmode) return s_aplink;
21558 int sdkstate = cyw43_wifi_link_status(&cyw43_state, CYW43_ITF_STA);
21559 MG_VERBOSE(("conn: %c state: %d", s_connecting ? '1' : '0', sdkstate));
21560 if (sdkstate < 0 && s_connecting) {
21561 mg_tcpip_call(s_ifp, MG_TCPIP_EV_WIFI_CONNECT_ERR, &sdkstate);
21562 s_connecting = false;
21563 }
21564 return s_stalink;
21565}
21566 
21567struct mg_tcpip_driver mg_tcpip_driver_pico_w = {
21568 mg_tcpip_driver_pico_w_init,
21569 mg_tcpip_driver_pico_w_tx,
21570 NULL,
21571 mg_tcpip_driver_pico_w_poll,
21572};
21573 
21574// Called once per outstanding frame by async_context
21575void cyw43_cb_process_ethernet(void *cb_data, int itf, size_t len,
21576 const uint8_t *buf) {
21577 mg_tcpip_qwrite((void *) buf, len, s_ifp);
21578 (void) cb_data;
21579}
21580 
21581// Called by async_context
21582void cyw43_cb_tcpip_set_link_up(cyw43_t *self, int itf) {
21583 if (itf == CYW43_ITF_AP) {
21584 s_aplink = true;
21585 } else {
21586 s_stalink = true;
21587 s_connecting = false;
21588 }
21589}
21590void cyw43_cb_tcpip_set_link_down(cyw43_t *self, int itf) {
21591 if (itf == CYW43_ITF_AP) {
21592 s_aplink = false;
21593 } else {
21594 s_stalink = false;
21595 // SDK calls this before we check status, don't clear s_connecting here
21596 }
21597}
21598 
21599// there's life beyond lwIP
21600void pbuf_copy_partial(void) {
21601 (void) 0;
21602}
21603 
21604static int result_cb(void *arg, const cyw43_ev_scan_result_t *data) {
21605 struct mg_wifi_scan_bss_data bss;
21606 bss.SSID = mg_str_n(data->ssid, data->ssid_len);
21607 bss.BSSID = (char *) data->bssid;
21608 bss.RSSI = (int8_t) data->rssi;
21609 bss.has_n = 0; // SDK ignores this
21610 bss.channel = (uint8_t) data->channel;
21611 bss.band = MG_WIFI_BAND_2G;
21612 // SDK-internal dependency, 2.1.0
21613 bss.security = data->auth_mode & MG_BIT(0) ? MG_WIFI_SECURITY_WEP
21614 : MG_WIFI_SECURITY_OPEN;
21615 if (data->auth_mode & MG_BIT(1)) bss.security |= MG_WIFI_SECURITY_WPA;
21616 if (data->auth_mode & MG_BIT(2)) bss.security |= MG_WIFI_SECURITY_WPA2;
21617 MG_VERBOSE(("BSS: %.*s (%u) (%M) %d dBm %u", bss.SSID.len, bss.SSID.buf,
21618 bss.channel, mg_print_mac, bss.BSSID, (int) bss.RSSI,
21619 bss.security));
21620 mg_tcpip_call(s_ifp, MG_TCPIP_EV_WIFI_SCAN_RESULT, &bss);
21621 return 0;
21622}
21623 
21624bool mg_wifi_scan(void) {
21625 cyw43_wifi_scan_options_t opts;
21626 memset(&opts, 0, sizeof(opts));
21627 bool res = (cyw43_wifi_scan(&cyw43_state, &opts, NULL, result_cb) == 0);
21628 if (res) s_scanning = true;
21629 return res;
21630}
21631 
21632bool mg_wifi_connect(char *ssid, char *pass) {
21633 cyw43_arch_enable_sta_mode();
21634 int res = cyw43_arch_wifi_connect_async(ssid, pass, CYW43_AUTH_WPA2_AES_PSK);
21635 MG_VERBOSE(("res: %d", res));
21636 if (res == 0) s_connecting = true;
21637 return (res == 0);
21638}
21639 
21640bool mg_wifi_disconnect(void) {
21641 cyw43_arch_disable_sta_mode();
21642 s_connecting = false;
21643 return true;
21644}
21645 
21646bool mg_wifi_ap_start(char *ssid, char *pass, unsigned int channel) {
21647 cyw43_wifi_ap_set_channel(&cyw43_state, channel);
21648 cyw43_arch_enable_ap_mode(ssid, pass, CYW43_AUTH_WPA2_AES_PSK);
21649 return true;
21650}
21651 
21652bool mg_wifi_ap_stop(void) {
21653 cyw43_arch_disable_ap_mode();
21654 return true;
21655}
21656 
21657#endif
21658 
21659#ifdef MG_ENABLE_LINES
21660#line 1 "src/drivers/ppp.c"
21661#endif
21662 
21663 
21664#if MG_ENABLE_TCPIP && defined(MG_ENABLE_DRIVER_PPP) && MG_ENABLE_DRIVER_PPP
21665 
21666#define MG_PPP_FLAG 0x7e // PPP frame delimiter
21667#define MG_PPP_ESC 0x7d // PPP escape byte for special characters
21668#define MG_PPP_ADDR 0xff
21669#define MG_PPP_CTRL 0x03
21670 
21671#define MG_PPP_PROTO_IP 0x0021
21672#define MG_PPP_PROTO_LCP 0xc021
21673#define MG_PPP_PROTO_IPCP 0x8021
21674 
21675#define MG_PPP_IPCP_REQ 1
21676#define MG_PPP_IPCP_ACK 2
21677#define MG_PPP_IPCP_NACK 3
21678#define MG_PPP_IPCP_IPADDR 3
21679 
21680#define MG_PPP_LCP_CFG_REQ 1
21681#define MG_PPP_LCP_CFG_ACK 2
21682#define MG_PPP_LCP_CFG_NACK 3
21683#define MG_PPP_LCP_CFG_REJECT 4
21684#define MG_PPP_LCP_CFG_TERM_REQ 5
21685#define MG_PPP_LCP_CFG_TERM_ACK 6
21686 
21687#define MG_PPP_AT_TIMEOUT 2000
21688 
21689static size_t print_atcmd(void (*out)(char, void *), void *arg, va_list *ap) {
21690 struct mg_str s = va_arg(*ap, struct mg_str);
21691 for (size_t i = 0; i < s.len; i++) out(s.buf[i] < 0x20 ? '.' : s.buf[i], arg);
21692 return s.len;
21693}
21694 
21695static void mg_ppp_reset(struct mg_tcpip_driver_ppp_data *dd) {
21696 dd->script_index = 0;
21697 dd->deadline = 0;
21698 if (dd->reset) dd->reset(dd->uart);
21699}
21700 
21701static bool mg_ppp_atcmd_handle(struct mg_tcpip_if *ifp) {
21702 struct mg_tcpip_driver_ppp_data *dd =
21703 (struct mg_tcpip_driver_ppp_data *) ifp->driver_data;
21704 if (dd->script == NULL || dd->script_index < 0) return true;
21705 if (dd->deadline == 0) dd->deadline = mg_millis() + MG_PPP_AT_TIMEOUT;
21706 for (;;) {
21707 if (dd->script_index % 2 == 0) { // send AT command
21708 const char *cmd = dd->script[dd->script_index];
21709 MG_DEBUG(("send AT[%d]: %M", dd->script_index, print_atcmd, mg_str(cmd)));
21710 while (*cmd) dd->tx(dd->uart, *cmd++);
21711 dd->script_index++;
21712 ifp->recv_queue.head = 0;
21713 } else { // check AT command response
21714 const char *expect = dd->script[dd->script_index];
21715 struct mg_queue *q = &ifp->recv_queue;
21716 for (;;) {
21717 int c;
21718 int is_timeout = dd->deadline > 0 && mg_millis() > dd->deadline;
21719 int is_overflow = q->head >= q->size - 1;
21720 if (is_timeout || is_overflow) {
21721 MG_ERROR(("AT error: %s, retrying...",
21722 is_timeout ? "timeout" : "overflow"));
21723 mg_ppp_reset(dd);
21724 return false; // FAIL: timeout
21725 }
21726 if ((c = dd->rx(dd->uart)) < 0) return false; // no data
21727 q->buf[q->head++] = c;
21728 if (mg_match(mg_str_n(q->buf, q->head), mg_str(expect), NULL)) {
21729 MG_DEBUG(("recv AT[%d]: %M", dd->script_index, print_atcmd,
21730 mg_str_n(q->buf, q->head)));
21731 dd->script_index++;
21732 q->head = 0;
21733 break;
21734 }
21735 }
21736 }
21737 if (dd->script[dd->script_index] == NULL) {
21738 MG_DEBUG(("finished AT script"));
21739 dd->script_index = -1;
21740 return true;
21741 }
21742 }
21743}
21744 
21745static bool mg_ppp_init(struct mg_tcpip_if *ifp) {
21746 ifp->recv_queue.size = 3000; // MTU=1500, worst case escaping = 2x
21747 return true;
21748}
21749 
21750// Calculate FCS/CRC for PPP frames. Could be implemented faster using lookup
21751// tables.
21752static uint32_t fcs_do(uint32_t fcs, uint8_t x) {
21753 for (int i = 0; i < 8; i++) {
21754 fcs = ((fcs ^ x) & 1) ? (fcs >> 1) ^ 0x8408 : fcs >> 1;
21755 x >>= 1;
21756 }
21757 return fcs;
21758}
21759 
21760static bool mg_ppp_poll(struct mg_tcpip_if *ifp, bool s1) {
21761 (void) s1;
21762 return ifp->driver_data != NULL;
21763}
21764 
21765// Transmit a single byte as part of the PPP frame (escaped, if needed)
21766static void mg_ppp_tx_byte(struct mg_tcpip_driver_ppp_data *dd, uint8_t b) {
21767 if ((b < 0x20) || (b == MG_PPP_ESC) || (b == MG_PPP_FLAG)) {
21768 dd->tx(dd->uart, MG_PPP_ESC);
21769 dd->tx(dd->uart, b ^ 0x20);
21770 } else {
21771 dd->tx(dd->uart, b);
21772 }
21773}
21774 
21775// Transmit a single PPP frame for the given protocol
21776static void mg_ppp_tx_frame(struct mg_tcpip_driver_ppp_data *dd, uint16_t proto,
21777 uint8_t *data, size_t datasz) {
21778 uint16_t crc;
21779 uint32_t fcs = 0xffff;
21780 
21781 dd->tx(dd->uart, MG_PPP_FLAG);
21782 mg_ppp_tx_byte(dd, MG_PPP_ADDR);
21783 mg_ppp_tx_byte(dd, MG_PPP_CTRL);
21784 mg_ppp_tx_byte(dd, proto >> 8);
21785 mg_ppp_tx_byte(dd, proto & 0xff);
21786 fcs = fcs_do(fcs, MG_PPP_ADDR);
21787 fcs = fcs_do(fcs, MG_PPP_CTRL);
21788 fcs = fcs_do(fcs, proto >> 8);
21789 fcs = fcs_do(fcs, proto & 0xff);
21790 for (unsigned int i = 0; i < datasz; i++) {
21791 mg_ppp_tx_byte(dd, data[i]);
21792 fcs = fcs_do(fcs, data[i]);
21793 }
21794 crc = fcs & 0xffff;
21795 mg_ppp_tx_byte(dd, ~crc); // send CRC, note the byte order
21796 mg_ppp_tx_byte(dd, ~crc >> 8);
21797 dd->tx(dd->uart, MG_PPP_FLAG); // end of frame
21798}
21799 
21800// Send Ethernet frame as PPP frame
21801static size_t mg_ppp_tx(const void *buf, size_t len, struct mg_tcpip_if *ifp) {
21802 struct mg_tcpip_driver_ppp_data *dd =
21803 (struct mg_tcpip_driver_ppp_data *) ifp->driver_data;
21804 if (ifp->state != MG_TCPIP_STATE_READY) return 0;
21805 // XXX: what if not an IP protocol?
21806 mg_ppp_tx_frame(dd, MG_PPP_PROTO_IP, (uint8_t *) buf + 14, len - 14);
21807 return len;
21808}
21809 
21810// Given a full PPP frame, unescape it in place and verify FCS, returns actual
21811// data size on success or 0 on error.
21812static size_t mg_ppp_verify_frame(uint8_t *buf, size_t bufsz) {
21813 int unpack = 0;
21814 uint16_t crc;
21815 size_t pktsz = 0;
21816 uint32_t fcs = 0xffff;
21817 for (unsigned int i = 0; i < bufsz; i++) {
21818 if (unpack == 0) {
21819 if (buf[i] == 0x7d) {
21820 unpack = 1;
21821 } else {
21822 buf[pktsz] = buf[i];
21823 fcs = fcs_do(fcs, buf[pktsz]);
21824 pktsz++;
21825 }
21826 } else {
21827 unpack = 0;
21828 buf[pktsz] = buf[i] ^ 0x20;
21829 fcs = fcs_do(fcs, buf[pktsz]);
21830 pktsz++;
21831 }
21832 }
21833 crc = fcs & 0xffff;
21834 if (crc != 0xf0b8) {
21835 MG_DEBUG(("bad crc: %04x", crc));
21836 return 0;
21837 }
21838 if (pktsz < 6 || buf[0] != MG_PPP_ADDR || buf[1] != MG_PPP_CTRL) {
21839 return 0;
21840 }
21841 return pktsz - 2; // strip FCS
21842}
21843 
21844// fetch as much data as we can, until a single PPP frame is received
21845static size_t mg_ppp_rx_frame(struct mg_tcpip_driver_ppp_data *dd,
21846 struct mg_queue *q) {
21847 while (q->head < q->size) {
21848 int c;
21849 if ((c = dd->rx(dd->uart)) < 0) {
21850 return 0;
21851 }
21852 if (c == MG_PPP_FLAG) {
21853 if (q->head > 0) {
21854 break;
21855 } else {
21856 continue;
21857 }
21858 }
21859 q->buf[q->head++] = c;
21860 }
21861 
21862 size_t n = mg_ppp_verify_frame((uint8_t *) q->buf, q->head);
21863 if (n == 0) {
21864 MG_DEBUG(("invalid PPP frame of %d bytes", q->head));
21865 q->head = 0;
21866 return 0;
21867 }
21868 q->head = n;
21869 return q->head;
21870}
21871 
21872static void mg_ppp_handle_lcp(struct mg_tcpip_if *ifp, uint8_t *lcp,
21873 size_t lcpsz) {
21874 uint8_t id;
21875 uint16_t len;
21876 struct mg_tcpip_driver_ppp_data *dd =
21877 (struct mg_tcpip_driver_ppp_data *) ifp->driver_data;
21878 if (lcpsz < 4) return;
21879 id = lcp[1];
21880 len = (((uint16_t) lcp[2]) << 8) | (lcp[3]);
21881 switch (lcp[0]) {
21882 case MG_PPP_LCP_CFG_REQ: {
21883 if (len == 4) {
21884 MG_DEBUG(("LCP config request of %d bytes, acknowledging...", len));
21885 lcp[0] = MG_PPP_LCP_CFG_ACK;
21886 mg_ppp_tx_frame(dd, MG_PPP_PROTO_LCP, lcp, len);
21887 lcp[0] = MG_PPP_LCP_CFG_REQ;
21888 mg_ppp_tx_frame(dd, MG_PPP_PROTO_LCP, lcp, len);
21889 } else {
21890 MG_DEBUG(("LCP config request of %d bytes, rejecting...", len));
21891 lcp[0] = MG_PPP_LCP_CFG_REJECT;
21892 mg_ppp_tx_frame(dd, MG_PPP_PROTO_LCP, lcp, len);
21893 }
21894 } break;
21895 case MG_PPP_LCP_CFG_TERM_REQ: {
21896 uint8_t ack[4] = {MG_PPP_LCP_CFG_TERM_ACK, id, 0, 4};
21897 MG_DEBUG(("LCP termination request, acknowledging..."));
21898 mg_ppp_tx_frame(dd, MG_PPP_PROTO_LCP, ack, sizeof(ack));
21899 mg_ppp_reset(dd);
21900 ifp->state = MG_TCPIP_STATE_UP;
21901 if (dd->reset) dd->reset(dd->uart);
21902 } break;
21903 }
21904}
21905 
21906static void mg_ppp_handle_ipcp(struct mg_tcpip_if *ifp, uint8_t *ipcp,
21907 size_t ipcpsz) {
21908 struct mg_tcpip_driver_ppp_data *dd =
21909 (struct mg_tcpip_driver_ppp_data *) ifp->driver_data;
21910 uint16_t len;
21911 uint8_t id;
21912 uint8_t req[] = {
21913 MG_PPP_IPCP_REQ, 0, 0, 10, MG_PPP_IPCP_IPADDR, 6, 0, 0, 0, 0};
21914 if (ipcpsz < 4) return;
21915 id = ipcp[1];
21916 len = (((uint16_t) ipcp[2]) << 8) | (ipcp[3]);
21917 switch (ipcp[0]) {
21918 case MG_PPP_IPCP_REQ:
21919 MG_DEBUG(("got IPCP config request, acknowledging..."));
21920 if (len >= 10 && ipcp[4] == MG_PPP_IPCP_IPADDR) {
21921 uint8_t *ip = ipcp + 6;
21922 MG_DEBUG(("host ip: %d.%d.%d.%d", ip[0], ip[1], ip[2], ip[3]));
21923 }
21924 ipcp[0] = MG_PPP_IPCP_ACK;
21925 mg_ppp_tx_frame(dd, MG_PPP_PROTO_IPCP, ipcp, len);
21926 req[1] = id;
21927 // Request IP address 0.0.0.0
21928 mg_ppp_tx_frame(dd, MG_PPP_PROTO_IPCP, req, sizeof(req));
21929 break;
21930 case MG_PPP_IPCP_ACK:
21931 // This usually does not happen, as our "preferred" IP address is invalid
21932 MG_DEBUG(("got IPCP config ack, link is online now"));
21933 ifp->state = MG_TCPIP_STATE_READY;
21934 break;
21935 case MG_PPP_IPCP_NACK:
21936 MG_DEBUG(("got IPCP config nack"));
21937 // NACK contains our "suggested" IP address, use it
21938 if (len >= 10 && ipcp[4] == MG_PPP_IPCP_IPADDR) {
21939 uint8_t *ip = ipcp + 6;
21940 MG_DEBUG(("ipcp ack, ip: %d.%d.%d.%d", ip[0], ip[1], ip[2], ip[3]));
21941 ipcp[0] = MG_PPP_IPCP_REQ;
21942 mg_ppp_tx_frame(dd, MG_PPP_PROTO_IPCP, ipcp, len);
21943 ifp->ip = ifp->mask = MG_IPV4(ip[0], ip[1], ip[2], ip[3]);
21944 ifp->state = MG_TCPIP_STATE_READY;
21945 }
21946 break;
21947 }
21948}
21949 
21950static size_t mg_ppp_rx(void *ethbuf, size_t ethlen, struct mg_tcpip_if *ifp) {
21951 uint8_t *eth = ethbuf;
21952 size_t ethsz = 0;
21953 struct mg_tcpip_driver_ppp_data *dd =
21954 (struct mg_tcpip_driver_ppp_data *) ifp->driver_data;
21955 uint8_t *buf = (uint8_t *) ifp->recv_queue.buf;
21956 
21957 if (!mg_ppp_atcmd_handle(ifp)) return 0;
21958 
21959 size_t bufsz = mg_ppp_rx_frame(dd, &ifp->recv_queue);
21960 if (!bufsz) return 0;
21961 uint16_t proto = (((uint16_t) buf[2]) << 8) | (uint16_t) buf[3];
21962 switch (proto) {
21963 case MG_PPP_PROTO_LCP: mg_ppp_handle_lcp(ifp, buf + 4, bufsz - 4); break;
21964 case MG_PPP_PROTO_IPCP: mg_ppp_handle_ipcp(ifp, buf + 4, bufsz - 4); break;
21965 case MG_PPP_PROTO_IP:
21966 MG_VERBOSE(("got IP packet of %d bytes", bufsz - 4));
21967 memmove(eth + 14, buf + 4, bufsz - 4);
21968 memmove(eth, ifp->mac, 6);
21969 memmove(eth + 6, "\xff\xff\xff\xff\xff\xff", 6);
21970 eth[12] = 0x08;
21971 eth[13] = 0x00;
21972 ethsz = bufsz - 4 + 14;
21973 ifp->recv_queue.head = 0;
21974 return ethsz;
21975#if 0
21976 default:
21977 MG_DEBUG(("unknown PPP frame:"));
21978 mg_hexdump(ppp->buf, ppp->bufsz);
21979#endif
21980 }
21981 ifp->recv_queue.head = 0;
21982 return 0;
21983 (void) ethlen;
21984}
21985 
21986struct mg_tcpip_driver mg_tcpip_driver_ppp = {mg_ppp_init, mg_ppp_tx, mg_ppp_rx,
21987 mg_ppp_up};
21988 
21989#endif
21990 
21991#ifdef MG_ENABLE_LINES
21992#line 1 "src/drivers/ra.c"
21993#endif
21994 
21995 
21996#if MG_ENABLE_TCPIP && defined(MG_ENABLE_DRIVER_RA) && MG_ENABLE_DRIVER_RA
21997struct ra_etherc {
21998 volatile uint32_t ECMR, RESERVED, RFLR, RESERVED1, ECSR, RESERVED2, ECSIPR,
21999 RESERVED3, PIR, RESERVED4, PSR, RESERVED5[5], RDMLR, RESERVED6[3], IPGR,
22000 APR, MPR, RESERVED7, RFCF, TPAUSER, TPAUSECR, BCFRR, RESERVED8[20], MAHR,
22001 RESERVED9, MALR, RESERVED10, TROCR, CDCR, LCCR, CNDCR, RESERVED11, CEFCR,
22002 FRECR, TSFRCR, TLFRCR, RFCR, MAFCR;
22003};
22004 
22005struct ra_edmac {
22006 volatile uint32_t EDMR, RESERVED, EDTRR, RESERVED1, EDRRR, RESERVED2, TDLAR,
22007 RESERVED3, RDLAR, RESERVED4, EESR, RESERVED5, EESIPR, RESERVED6, TRSCER,
22008 RESERVED7, RMFCR, RESERVED8, TFTR, RESERVED9, FDR, RESERVED10, RMCR,
22009 RESERVED11[2], TFUCR, RFOCR, IOSR, FCFTR, RESERVED12, RPADIR, TRIMD,
22010 RESERVED13[18], RBWAR, RDFAR, RESERVED14, TBRAR, TDFAR;
22011};
22012 
22013#undef ETHERC
22014#define ETHERC ((struct ra_etherc *) (uintptr_t) 0x40114100U)
22015#undef EDMAC
22016#define EDMAC ((struct ra_edmac *) (uintptr_t) 0x40114000U)
22017#undef RASYSC
22018#define RASYSC ((uint32_t *) (uintptr_t) 0x4001E000U)
22019#undef ICU_IELSR
22020#define ICU_IELSR ((uint32_t *) (uintptr_t) 0x40006300U)
22021 
22022#define ETH_PKT_SIZE 1536 // Max frame size, multiple of 32
22023#define ETH_DESC_CNT 4 // Descriptors count
22024 
22025// TODO(): handle these in a portable compiler-independent CMSIS-friendly way
22026#define MG_16BYTE_ALIGNED __attribute__((aligned((16U))))
22027#define MG_32BYTE_ALIGNED __attribute__((aligned((32U))))
22028 
22029// Descriptors: 16-byte aligned
22030// Buffers: 32-byte aligned (27.3.1)
22031static volatile uint32_t s_rxdesc[ETH_DESC_CNT][4] MG_16BYTE_ALIGNED;
22032static volatile uint32_t s_txdesc[ETH_DESC_CNT][4] MG_16BYTE_ALIGNED;
22033static uint8_t s_rxbuf[ETH_DESC_CNT][ETH_PKT_SIZE] MG_32BYTE_ALIGNED;
22034static uint8_t s_txbuf[ETH_DESC_CNT][ETH_PKT_SIZE] MG_32BYTE_ALIGNED;
22035static struct mg_tcpip_if *s_ifp; // MIP interface
22036 
22037// fastest is 3 cycles (SUB + BNE) on a 3-stage pipeline or equivalent
22038static inline void raspin(volatile uint32_t count) {
22039 while (count--) (void) 0;
22040}
22041// count to get the 200ns SMC semi-cycle period (2.5MHz) calling raspin():
22042// SYS_FREQUENCY * 200ns / 3 = SYS_FREQUENCY / 15000000
22043static uint32_t s_smispin;
22044 
22045// Bit-banged SMI
22046static void smi_preamble(void) {
22047 unsigned int i = 32;
22048 uint32_t pir = MG_BIT(1) | MG_BIT(2); // write, mdio = 1, mdc = 0
22049 ETHERC->PIR = pir;
22050 while (i--) {
22051 pir &= ~MG_BIT(0); // mdc = 0
22052 ETHERC->PIR = pir;
22053 raspin(s_smispin);
22054 pir |= MG_BIT(0); // mdc = 1
22055 ETHERC->PIR = pir;
22056 raspin(s_smispin);
22057 }
22058}
22059static void smi_wr(uint16_t header, uint16_t data) {
22060 uint32_t word = (header << 16) | data;
22061 smi_preamble();
22062 unsigned int i = 32;
22063 while (i--) {
22064 uint32_t pir = MG_BIT(1) |
22065 (word & 0x80000000 ? MG_BIT(2) : 0); // write, mdc = 0, data
22066 ETHERC->PIR = pir;
22067 raspin(s_smispin);
22068 pir |= MG_BIT(0); // mdc = 1
22069 ETHERC->PIR = pir;
22070 raspin(s_smispin);
22071 word <<= 1;
22072 }
22073}
22074static uint16_t smi_rd(uint16_t header) {
22075 smi_preamble();
22076 unsigned int i = 16; // 2 LSb as turnaround
22077 uint32_t pir;
22078 while (i--) {
22079 pir = (i > 1 ? MG_BIT(1) : 0) |
22080 (header & 0x8000
22081 ? MG_BIT(2)
22082 : 0); // mdc = 0, header, set read direction at turnaround
22083 ETHERC->PIR = pir;
22084 raspin(s_smispin);
22085 pir |= MG_BIT(0); // mdc = 1
22086 ETHERC->PIR = pir;
22087 raspin(s_smispin);
22088 header <<= 1;
22089 }
22090 i = 16;
22091 uint16_t data = 0;
22092 while (i--) {
22093 data <<= 1;
22094 pir = 0; // read, mdc = 0
22095 ETHERC->PIR = pir;
22096 raspin(s_smispin / 2); // 1/4 clock period, 300ns max access time
22097 data |= (uint16_t) (ETHERC->PIR & MG_BIT(3) ? 1 : 0); // read mdio
22098 raspin(s_smispin / 2); // 1/4 clock period
22099 pir |= MG_BIT(0); // mdc = 1
22100 ETHERC->PIR = pir;
22101 raspin(s_smispin);
22102 }
22103 return data;
22104}
22105 
22106static uint16_t raeth_read_phy(uint8_t addr, uint8_t reg) {
22107 return smi_rd(
22108 (uint16_t) ((1 << 14) | (2 << 12) | (addr << 7) | (reg << 2) | (2 << 0)));
22109}
22110 
22111static void raeth_write_phy(uint8_t addr, uint8_t reg, uint16_t val) {
22112 smi_wr(
22113 (uint16_t) ((1 << 14) | (1 << 12) | (addr << 7) | (reg << 2) | (2 << 0)),
22114 val);
22115}
22116 
22117// MDC clock is generated manually; as per 802.3, it must not exceed 2.5MHz
22118static bool mg_tcpip_driver_ra_init(struct mg_tcpip_if *ifp) {
22119 struct mg_tcpip_driver_ra_data *d =
22120 (struct mg_tcpip_driver_ra_data *) ifp->driver_data;
22121 s_ifp = ifp;
22122 
22123 // Init SMI clock timing. If user told us the clock value, use it.
22124 // TODO(): Otherwise, guess
22125 s_smispin = d->clock / 15000000;
22126 
22127 // Init RX descriptors
22128 for (int i = 0; i < ETH_DESC_CNT; i++) {
22129 s_rxdesc[i][0] = MG_BIT(31); // RACT
22130 s_rxdesc[i][1] = ETH_PKT_SIZE << 16; // RBL
22131 s_rxdesc[i][2] = (uint32_t) s_rxbuf[i]; // Point to data buffer
22132 }
22133 s_rxdesc[ETH_DESC_CNT - 1][0] |= MG_BIT(30); // Wrap last descriptor
22134 
22135 // Init TX descriptors
22136 for (int i = 0; i < ETH_DESC_CNT; i++) {
22137 // TACT = 0
22138 s_txdesc[i][2] = (uint32_t) s_txbuf[i];
22139 }
22140 s_txdesc[ETH_DESC_CNT - 1][0] |= MG_BIT(30); // Wrap last descriptor
22141 
22142 EDMAC->EDMR = MG_BIT(0); // Software reset, wait 64 PCLKA clocks (27.2.1)
22143 uint32_t sckdivcr = RASYSC[8]; // get divisors from SCKDIVCR (8.2.2)
22144 uint32_t ick = 1 << ((sckdivcr >> 24) & 7); // sys_clock div
22145 uint32_t pcka = 1 << ((sckdivcr >> 12) & 7); // pclka div
22146 raspin((64U * pcka) / (3U * ick));
22147 EDMAC->EDMR = MG_BIT(6); // Initialize, little-endian (27.2.1)
22148 
22149 MG_DEBUG(("PHY addr: %d, smispin: %d", d->phy_addr, s_smispin));
22150 struct mg_phy phy = {raeth_read_phy, raeth_write_phy};
22151 mg_phy_init(&phy, d->phy_addr, 0); // MAC clocks PHY
22152 
22153 // Select RMII mode,
22154 ETHERC->ECMR = MG_BIT(2) | MG_BIT(1); // 100M, Full-duplex, CRC
22155 // ETHERC->ECMR |= MG_BIT(0); // Receive all
22156 ETHERC->RFLR = 1518; // Set max rx length
22157 
22158 EDMAC->RDLAR = (uint32_t) (uintptr_t) s_rxdesc;
22159 EDMAC->TDLAR = (uint32_t) (uintptr_t) s_txdesc;
22160 // MAC address filtering (bytes in reversed order)
22161 ETHERC->MAHR = (uint32_t) (ifp->mac[0] << 24U) |
22162 ((uint32_t) ifp->mac[1] << 16U) |
22163 ((uint32_t) ifp->mac[2] << 8U) | ifp->mac[3];
22164 ETHERC->MALR = ((uint32_t) ifp->mac[4] << 8U) | ifp->mac[5];
22165 
22166 EDMAC->TFTR = 0; // Store and forward (27.2.10)
22167 EDMAC->FDR = 0x070f; // (27.2.11)
22168 EDMAC->RMCR = MG_BIT(0); // (27.2.12)
22169 ETHERC->ECMR |= MG_BIT(6) | MG_BIT(5); // TE RE
22170 EDMAC->EESIPR = MG_BIT(18); // FR: Enable Rx (frame) IRQ
22171 EDMAC->EDRRR = MG_BIT(0); // Receive Descriptors have changed
22172 EDMAC->EDTRR = MG_BIT(0); // Transmit Descriptors have changed
22173 return true;
22174}
22175 
22176// Transmit frame
22177static size_t mg_tcpip_driver_ra_tx(const void *buf, size_t len,
22178 struct mg_tcpip_if *ifp) {
22179 static int s_txno; // Current descriptor index
22180 if (len > sizeof(s_txbuf[ETH_DESC_CNT])) {
22181 MG_ERROR(("Frame too big, %ld", (long) len));
22182 len = (size_t) -1; // fail
22183 } else if ((s_txdesc[s_txno][0] & MG_BIT(31))) {
22184 ifp->nerr++;
22185 MG_ERROR(("No descriptors available"));
22186 len = 0; // retry later
22187 } else {
22188 memcpy(s_txbuf[s_txno], buf, len); // Copy data
22189 s_txdesc[s_txno][1] = len << 16; // Set data len
22190 s_txdesc[s_txno][0] |= MG_BIT(31) | 3 << 28; // (27.3.1.1) mark valid
22191 EDMAC->EDTRR = MG_BIT(0); // Transmit request
22192 if (++s_txno >= ETH_DESC_CNT) s_txno = 0;
22193 }
22194 return len;
22195}
22196 
22197static bool mg_tcpip_driver_ra_poll(struct mg_tcpip_if *ifp, bool s1) {
22198 if (ifp->update_mac_hash_table) {
22199 EDMAC->EESIPR = MG_BIT(18) | MG_BIT(7); // FR, RMAF: Frame and mcast IRQ
22200 ifp->update_mac_hash_table = false;
22201 }
22202 if (!s1) return false;
22203 struct mg_tcpip_driver_ra_data *d =
22204 (struct mg_tcpip_driver_ra_data *) ifp->driver_data;
22205 uint8_t speed = MG_PHY_SPEED_10M;
22206 bool up = false, full_duplex = false;
22207 struct mg_phy phy = {raeth_read_phy, raeth_write_phy};
22208 up = mg_phy_up(&phy, d->phy_addr, &full_duplex, &speed);
22209 if ((ifp->state == MG_TCPIP_STATE_DOWN) && up) { // link state just went up
22210 // tmp = reg with flags set to the most likely situation: 100M full-duplex
22211 // if(link is slow or half) set flags otherwise
22212 // reg = tmp
22213 uint32_t ecmr = ETHERC->ECMR | MG_BIT(2) | MG_BIT(1); // 100M Full-duplex
22214 if (speed == MG_PHY_SPEED_10M) ecmr &= ~MG_BIT(2); // 10M
22215 if (full_duplex == false) ecmr &= ~MG_BIT(1); // Half-duplex
22216 ETHERC->ECMR = ecmr; // IRQ handler does not fiddle with these registers
22217 MG_DEBUG(("Link is %uM %s-duplex", ecmr & MG_BIT(2) ? 100 : 10,
22218 ecmr & MG_BIT(1) ? "full" : "half"));
22219 }
22220 return up;
22221}
22222 
22223void EDMAC_IRQHandler(void);
22224static uint32_t s_rxno;
22225void EDMAC_IRQHandler(void) {
22226 struct mg_tcpip_driver_ra_data *d =
22227 (struct mg_tcpip_driver_ra_data *) s_ifp->driver_data;
22228 EDMAC->EESR = MG_BIT(18) | MG_BIT(7); // Ack IRQ in EDMAC 1st
22229 ICU_IELSR[d->irqno] &= ~MG_BIT(16); // Ack IRQ in ICU last
22230 // Frame received, loop
22231 for (uint32_t i = 0; i < 10; i++) { // read as they arrive but not forever
22232 uint32_t r = s_rxdesc[s_rxno][0];
22233 if (r & MG_BIT(31)) break; // exit when done
22234 // skip partial/errored frames (27.3.1.2)
22235 if ((r & (MG_BIT(29) | MG_BIT(28)) && !(r & MG_BIT(27)))) {
22236 size_t len = s_rxdesc[s_rxno][1] & 0xffff;
22237 mg_tcpip_qwrite(s_rxbuf[s_rxno], len, s_ifp); // CRC already stripped
22238 }
22239 s_rxdesc[s_rxno][0] |= MG_BIT(31);
22240 if (++s_rxno >= ETH_DESC_CNT) s_rxno = 0;
22241 }
22242 EDMAC->EDRRR = MG_BIT(0); // Receive Descriptors have changed
22243 // If b0 == 0, descriptors were exhausted and probably frames were dropped,
22244 // (27.2.9 RMFCR counts them)
22245}
22246 
22247struct mg_tcpip_driver mg_tcpip_driver_ra = {mg_tcpip_driver_ra_init,
22248 mg_tcpip_driver_ra_tx, NULL,
22249 mg_tcpip_driver_ra_poll};
22250 
22251#endif
22252 
22253#ifdef MG_ENABLE_LINES
22254#line 1 "src/drivers/rw612.c"
22255#endif
22256 
22257 
22258#if MG_ENABLE_TCPIP && defined(MG_ENABLE_DRIVER_RW612) && MG_ENABLE_DRIVER_RW612
22259 
22260struct ENET_Type {
22261 volatile uint32_t RESERVED_0[1], EIR, EIMR, RESERVED_1[1], RDAR, TDAR,
22262 RESERVED_2[3], ECR, RESERVED_3[6], MMFR, MSCR, RESERVED_4[7], MIBC,
22263 RESERVED_5[7], RCR, RESERVED_6[15], TCR, RESERVED_7[7], PALR, PAUR, OPD,
22264 TXIC[1], RESERVED_8[3], RXIC[1], RESERVED_9[5], IAUR, IALR, GAUR, GALR,
22265 RESERVED_10[7], TFWR, RESERVED_11[14], RDSR, TDSR, MRBR, RESERVED_12[1],
22266 RSFL, RSEM, RAEM, RAFL, TSEM, TAEM, TAFL, TIPG, FTRL, RESERVED_13[3],
22267 TACC, RACC, RESERVED_14[15], RMON_T_PACKETS, RMON_T_BC_PKT, RMON_T_MC_PKT,
22268 RMON_T_CRC_ALIGN, RMON_T_UNDERSIZE, RMON_T_OVERSIZE, RMON_T_FRAG,
22269 RMON_T_JAB, RMON_T_COL, RMON_T_P64, RMON_T_P65TO127, RMON_T_P128TO255,
22270 RMON_T_P256TO511, RMON_T_P512TO1023, RMON_T_P1024TO2047, RMON_T_P_GTE2048,
22271 RMON_T_OCTETS, IEEE_T_DROP, IEEE_T_FRAME_OK, IEEE_T_1COL, IEEE_T_MCOL,
22272 IEEE_T_DEF, IEEE_T_LCOL, IEEE_T_EXCOL, IEEE_T_MACERR, IEEE_T_CSERR,
22273 IEEE_T_SQE, IEEE_T_FDXFC, IEEE_T_OCTETS_OK, RESERVED_15[3],
22274 RMON_R_PACKETS, RMON_R_BC_PKT, RMON_R_MC_PKT, RMON_R_CRC_ALIGN,
22275 RMON_R_UNDERSIZE, RMON_R_OVERSIZE, RMON_R_FRAG, RMON_R_JAB,
22276 RESERVED_16[1], RMON_R_P64, RMON_R_P65TO127, RMON_R_P128TO255,
22277 RMON_R_P256TO511, RMON_R_P512TO1023, RMON_R_P1024TO2047, RMON_R_P_GTE2048,
22278 RMON_R_OCTETS, IEEE_R_DROP, IEEE_R_FRAME_OK, IEEE_R_CRC, IEEE_R_ALIGN,
22279 IEEE_R_MACERR, IEEE_R_FDXFC, IEEE_R_OCTETS_OK, RESERVED_17[71], ATCR,
22280 ATVR, ATOFF, ATPER, ATCOR, ATINC, ATSTMP, RESERVED_18[122], TGSR,
22281 CHANNEL_TCSR[4], CHANNEL_TCCR[4];
22282};
22283 
22284#define ENET ((struct ENET_Type *) 0x40138000)
22285 
22286#define ETH_PKT_SIZE 1536 // Max frame size
22287#define ETH_DESC_CNT 4 // Descriptors count
22288#define ETH_DS 2 // Descriptor size (words)
22289 
22290#define MG_8BYTE_ALIGNED __attribute__((aligned((8U))))
22291static uint8_t s_rxbuf[ETH_DESC_CNT][ETH_PKT_SIZE] MG_8BYTE_ALIGNED;
22292static uint8_t s_txbuf[ETH_DESC_CNT][ETH_PKT_SIZE] MG_8BYTE_ALIGNED;
22293static uint32_t s_rxdesc[ETH_DESC_CNT][ETH_DS] MG_8BYTE_ALIGNED;
22294static uint32_t s_txdesc[ETH_DESC_CNT][ETH_DS] MG_8BYTE_ALIGNED;
22295static uint8_t s_txno; // Current TX descriptor
22296static uint8_t s_rxno; // Current RX descriptor
22297 
22298static struct mg_tcpip_if *s_ifp; // MIP interface
22299 
22300static uint16_t eth_read_phy(uint8_t addr, uint8_t reg) {
22301 ENET->MMFR = MG_BIT(30) | // Start of frame delimiter
22302 MG_BIT(29) | // Opcode
22303 ((addr & 0x1f) << 23) | ((reg & 0x1f) << 18) | MG_BIT(17);
22304 while ((ENET->EIR & MG_BIT(23)) == 0) (void) 0;
22305 ENET->EIR |= MG_BIT(23);
22306 return ENET->MMFR & 0xffff;
22307}
22308 
22309static void eth_write_phy(uint8_t addr, uint8_t reg, uint16_t val) {
22310 ENET->MMFR = MG_BIT(30) | // Start of frame delimiter
22311 MG_BIT(28) | // Opcode
22312 ((addr & 0x1f) << 23) | ((reg & 0x1f) << 18) | MG_BIT(17) | val;
22313 while ((ENET->EIR & MG_BIT(23)) == 0) (void) 0;
22314 ENET->EIR |= MG_BIT(23);
22315}
22316 
22317static bool mg_tcpip_driver_rw612_init(struct mg_tcpip_if *ifp) {
22318 struct mg_tcpip_driver_rw612_data *d =
22319 (struct mg_tcpip_driver_rw612_data *) ifp->driver_data;
22320 s_ifp = ifp;
22321 ENET->MSCR = ((d->mdc_cr & 0x3f) << 1) | ((d->mdc_holdtime & 7) << 8);
22322 struct mg_phy phy = {eth_read_phy, eth_write_phy};
22323 mg_phy_init(&phy, d->phy_addr, 0);
22324 ENET->ECR |= MG_BIT(0); // reset ETH
22325 
22326 // initialize descriptors
22327 for (int i = 0; i < ETH_DESC_CNT; i++) {
22328 s_rxdesc[i][1] = (uint32_t) s_rxbuf[i];
22329 s_rxdesc[i][0] = MG_BIT(31); // OWN
22330 if (i == ETH_DESC_CNT - 1) {
22331 s_rxdesc[i][0] |= MG_BIT(29); // mark last descriptor
22332 }
22333 s_txdesc[i][1] = (uint32_t) s_txbuf[i];
22334 if (i == ETH_DESC_CNT - 1) {
22335 s_txdesc[i][0] |= MG_BIT(29); // mark last descriptor
22336 }
22337 }
22338 
22339 ENET->RCR = (ENET->RCR & (0xffff << 16)) | MG_BIT(14) | MG_BIT(8) | MG_BIT(2);
22340 ENET->TCR = MG_BIT(2); // full duplex
22341 ENET->TDSR = (uint32_t) &s_txdesc[0][0];
22342 ENET->RDSR = (uint32_t) &s_rxdesc[0][0];
22343 ENET->MRBR = ETH_PKT_SIZE;
22344 ENET->PALR =
22345 ifp->mac[0] << 24 | ifp->mac[1] << 16 | ifp->mac[2] << 8 | ifp->mac[3];
22346 ENET->PAUR |= (ifp->mac[4] << 24 | ifp->mac[5] << 16);
22347 ENET->IALR = 0;
22348 ENET->IAUR = 0;
22349 ENET->GALR = 0;
22350 ENET->GAUR = 0;
22351 ENET->MSCR = ((d->mdc_cr & 0x3f) << 1) | ((d->mdc_holdtime & 7) << 8);
22352 ENET->EIMR = MG_BIT(25); // Enable RX interrupt
22353 ENET->ECR |= MG_BIT(8) | MG_BIT(1); // DBSWP, Enable
22354 ENET->RDAR = 0; // activate RX descriptors ring
22355 return true;
22356}
22357 
22358static size_t mg_tcpip_driver_rw612_tx(const void *buf, size_t len,
22359 struct mg_tcpip_if *ifp) {
22360 if (len > sizeof(s_txbuf[s_txno])) {
22361 MG_ERROR(("Frame too big, %ld", (long) len));
22362 len = 0; // Frame is too big
22363 } else if (((s_txdesc[s_txno][0] & MG_BIT(31)) != 0)) {
22364 ifp->nerr++;
22365 MG_ERROR(("No free descriptors"));
22366 len = 0; // All descriptors are busy, fail
22367 } else {
22368 memcpy(s_txbuf[s_txno], buf, len);
22369 s_txdesc[s_txno][0] = len | MG_BIT(27) | MG_BIT(26); // last buffer, crc
22370 if (s_txno == ETH_DESC_CNT - 1) {
22371 s_txdesc[s_txno][0] |= MG_BIT(29); // wrap
22372 }
22373 s_txdesc[s_txno][0] |= MG_BIT(31); // release ownership
22374 MG_DSB();
22375 ENET->TDAR = 0;
22376 // MG_INFO(("s_txdesc[%d][0]: 0x%x", s_txno, s_txdesc[s_txno][0]));
22377 if (++s_txno >= ETH_DESC_CNT) s_txno = 0;
22378 }
22379 
22380 return len;
22381}
22382 
22383 
22384static void mg_tcpip_driver_rw612_update_hash_table(struct mg_tcpip_if *ifp) {
22385 // TODO(): read database, rebuild hash table
22386 ENET->GAUR = MG_BIT(1); // see imxrt, it reduces to this for mDNS
22387 (void) ifp;
22388}
22389 
22390static bool mg_tcpip_driver_rw612_poll(struct mg_tcpip_if *ifp, bool s1) {
22391 if (ifp->update_mac_hash_table) {
22392 mg_tcpip_driver_rw612_update_hash_table(ifp);
22393 ifp->update_mac_hash_table = false;
22394 }
22395 if (!s1) return false;
22396 struct mg_tcpip_driver_rw612_data *d =
22397 (struct mg_tcpip_driver_rw612_data *) ifp->driver_data;
22398 uint8_t speed = MG_PHY_SPEED_10M;
22399 bool up = false, full_duplex = false;
22400 struct mg_phy phy = {eth_read_phy, eth_write_phy};
22401 up = mg_phy_up(&phy, d->phy_addr, &full_duplex, &speed);
22402 if ((ifp->state == MG_TCPIP_STATE_DOWN) && up) { // link state just went up
22403 // tmp = reg with flags set to the most likely situation: 100M full-duplex
22404 // if(link is slow or half) set flags otherwise
22405 // reg = tmp
22406 if (speed == MG_PHY_SPEED_100M && (ENET->RCR & MG_BIT(9))) {
22407 ENET->RCR &= ~MG_BIT(9);
22408 } else if (speed == MG_PHY_SPEED_10M && (ENET->RCR & MG_BIT(9)) == 0) {
22409 ENET->RCR |= MG_BIT(9);
22410 }
22411 if (full_duplex && (ENET->TCR & MG_BIT(2)) == 0) {
22412 ENET->ECR &= ~MG_BIT(1);
22413 ENET->TCR |= MG_BIT(2);
22414 ENET->ECR |= MG_BIT(1);
22415 } else if (!full_duplex && (ENET->TCR & MG_BIT(2))) {
22416 ENET->ECR &= ~MG_BIT(1);
22417 ENET->TCR &= ~MG_BIT(2);
22418 ENET->ECR |= MG_BIT(1);
22419 }
22420 MG_INFO(("Link is %uM %s-duplex",
22421 speed == MG_PHY_SPEED_10M
22422 ? 10
22423 : (speed == MG_PHY_SPEED_100M ? 100 : 1000),
22424 full_duplex ? "full" : "half"));
22425 }
22426 return up;
22427}
22428 
22429void ENET_IRQHandler(void) {
22430 if (ENET->EIR & MG_BIT(25)) {
22431 ENET->EIR = MG_BIT(25); // Ack RX
22432 for (uint32_t i = 0; i < 10; i++) { // read as they arrive but not forever
22433 if ((s_rxdesc[s_rxno][0] & MG_BIT(31)) != 0) break; // exit when done
22434 // skip partial/errored frames
22435 if ((s_rxdesc[s_rxno][0] & MG_BIT(27)) &&
22436 !(s_rxdesc[s_rxno][0] &
22437 (MG_BIT(21) | MG_BIT(20) | MG_BIT(18) | MG_BIT(17) | MG_BIT(16)))) {
22438 size_t len = s_rxdesc[s_rxno][0] & 0xffff;
22439 mg_tcpip_qwrite(s_rxbuf[s_rxno], len, s_ifp);
22440 s_rxdesc[s_rxno][0] |= MG_BIT(31); // OWN bit: handle control to DMA
22441 MG_DSB();
22442 ENET->RDAR = 0;
22443 if (++s_rxno >= ETH_DESC_CNT) s_rxno = 0;
22444 }
22445 }
22446 }
22447}
22448 
22449struct mg_tcpip_driver mg_tcpip_driver_rw612 = {mg_tcpip_driver_rw612_init,
22450 mg_tcpip_driver_rw612_tx, NULL,
22451 mg_tcpip_driver_rw612_poll};
22452#endif
22453 
22454#ifdef MG_ENABLE_LINES
22455#line 1 "src/drivers/same54.c"
22456#endif
22457 
22458 
22459#if MG_ENABLE_TCPIP && defined(MG_ENABLE_DRIVER_SAME54) && \
22460 MG_ENABLE_DRIVER_SAME54
22461 
22462#include <sam.h>
22463 
22464#define ETH_PKT_SIZE 1536 // Max frame size
22465#define ETH_DESC_CNT 4 // Descriptors count
22466#define ETH_DS 2 // Descriptor size (words)
22467 
22468static uint8_t s_rxbuf[ETH_DESC_CNT][ETH_PKT_SIZE];
22469static uint8_t s_txbuf[ETH_DESC_CNT][ETH_PKT_SIZE];
22470static uint32_t s_rxdesc[ETH_DESC_CNT][ETH_DS]; // RX descriptors
22471static uint32_t s_txdesc[ETH_DESC_CNT][ETH_DS]; // TX descriptors
22472static uint8_t s_txno; // Current TX descriptor
22473static uint8_t s_rxno; // Current RX descriptor
22474 
22475static struct mg_tcpip_if *s_ifp; // MIP interface
22476enum { MG_PHY_ADDR = 0, MG_PHYREG_BCR = 0, MG_PHYREG_BSR = 1 };
22477 
22478#define MG_PHYREGBIT_BCR_DUPLEX_MODE MG_BIT(8)
22479#define MG_PHYREGBIT_BCR_SPEED MG_BIT(13)
22480#define MG_PHYREGBIT_BSR_LINK_STATUS MG_BIT(2)
22481 
22482static uint16_t eth_read_phy(uint8_t addr, uint8_t reg) {
22483 GMAC_REGS->GMAC_MAN = GMAC_MAN_CLTTO_Msk |
22484 GMAC_MAN_OP(2) | // Setting the read operation
22485 GMAC_MAN_WTN(2) | GMAC_MAN_PHYA(addr) | // PHY address
22486 GMAC_MAN_REGA(reg); // Setting the register
22487 while (!(GMAC_REGS->GMAC_NSR & GMAC_NSR_IDLE_Msk)) (void) 0;
22488 return GMAC_REGS->GMAC_MAN & GMAC_MAN_DATA_Msk; // Getting the read value
22489}
22490 
22491#if 0
22492static void eth_write_phy(uint8_t addr, uint8_t reg, uint16_t val) {
22493 GMAC_REGS->GMAC_MAN = GMAC_MAN_CLTTO_Msk | GMAC_MAN_OP(1) | // Setting the write operation
22494 GMAC_MAN_WTN(2) | GMAC_MAN_PHYA(addr) | // PHY address
22495 GMAC_MAN_REGA(reg) | GMAC_MAN_DATA(val); // Setting the register
22496 while (!(GMAC_REGS->GMAC_NSR & GMAC_NSR_IDLE_Msk)); // Waiting until the write op is complete
22497}
22498#endif
22499 
22500int get_clock_rate(struct mg_tcpip_driver_same54_data *d) {
22501 if (d && d->mdc_cr >= 0 && d->mdc_cr <= 5) {
22502 return d->mdc_cr;
22503 } else {
22504 // get MCLK from GCLK_GENERATOR 0
22505 uint32_t div = 512;
22506 uint32_t mclk;
22507 if (!(GCLK_REGS->GCLK_GENCTRL[0] & GCLK_GENCTRL_DIVSEL_Msk)) {
22508 div = ((GCLK_REGS->GCLK_GENCTRL[0] & 0x00FF0000) >> 16);
22509 if (div == 0) div = 1;
22510 }
22511 switch (GCLK_REGS->GCLK_GENCTRL[0] & GCLK_GENCTRL_SRC_Msk) {
22512 case GCLK_GENCTRL_SRC_XOSC0_Val:
22513 mclk = 32000000UL; /* 32MHz */
22514 break;
22515 case GCLK_GENCTRL_SRC_XOSC1_Val:
22516 mclk = 32000000UL; /* 32MHz */
22517 break;
22518 case GCLK_GENCTRL_SRC_OSCULP32K_Val:
22519 mclk = 32000UL;
22520 break;
22521 case GCLK_GENCTRL_SRC_XOSC32K_Val:
22522 mclk = 32000UL;
22523 break;
22524 case GCLK_GENCTRL_SRC_DFLL_Val:
22525 mclk = 48000000UL; /* 48MHz */
22526 break;
22527 case GCLK_GENCTRL_SRC_DPLL0_Val:
22528 mclk = 200000000UL; /* 200MHz */
22529 break;
22530 case GCLK_GENCTRL_SRC_DPLL1_Val:
22531 mclk = 200000000UL; /* 200MHz */
22532 break;
22533 default:
22534 mclk = 200000000UL; /* 200MHz */
22535 }
22536 
22537 mclk /= div;
22538 uint8_t crs[] = {0, 1, 2, 3, 4, 5}; // GMAC->NCFGR::CLK values
22539 uint8_t dividers[] = {8, 16, 32, 48, 64, 96}; // Respective CLK dividers
22540 for (int i = 0; i < 6; i++) {
22541 if (mclk / dividers[i] <= 2375000UL /* 2.5MHz - 5% */) {
22542 return crs[i];
22543 }
22544 }
22545 
22546 return 5;
22547 }
22548}
22549 
22550static bool mg_tcpip_driver_same54_init(struct mg_tcpip_if *ifp) {
22551 struct mg_tcpip_driver_same54_data *d =
22552 (struct mg_tcpip_driver_same54_data *) ifp->driver_data;
22553 s_ifp = ifp;
22554 
22555 MCLK_REGS->MCLK_APBCMASK |= MCLK_APBCMASK_GMAC_Msk;
22556 MCLK_REGS->MCLK_AHBMASK |= MCLK_AHBMASK_GMAC_Msk;
22557 GMAC_REGS->GMAC_NCFGR = GMAC_NCFGR_CLK(get_clock_rate(d)); // Set MDC divider
22558 GMAC_REGS->GMAC_NCR = 0; // Disable RX & TX
22559 GMAC_REGS->GMAC_NCR |= GMAC_NCR_MPE_Msk; // Enable MDC & MDIO
22560 
22561 for (int i = 0; i < ETH_DESC_CNT; i++) { // Init TX descriptors
22562 s_txdesc[i][0] = (uint32_t) s_txbuf[i]; // Point to data buffer
22563 s_txdesc[i][1] = MG_BIT(31); // OWN bit
22564 }
22565 s_txdesc[ETH_DESC_CNT - 1][1] |= MG_BIT(30); // Last tx descriptor - wrap
22566 
22567 GMAC_REGS->GMAC_DCFGR = GMAC_DCFGR_DRBS(0x18) // DMA recv buf 1536
22568 | GMAC_DCFGR_RXBMS(GMAC_DCFGR_RXBMS_FULL_Val) |
22569 GMAC_DCFGR_TXPBMS(1); // See #2487
22570 for (int i = 0; i < ETH_DESC_CNT; i++) { // Init RX descriptors
22571 s_rxdesc[i][0] = (uint32_t) s_rxbuf[i]; // Address of the data buffer
22572 s_rxdesc[i][1] = 0; // Clear status
22573 }
22574 s_rxdesc[ETH_DESC_CNT - 1][0] |= MG_BIT(1); // Last rx descriptor - wrap
22575 
22576 GMAC_REGS->GMAC_TBQB = (uint32_t) s_txdesc; // about the descriptor addresses
22577 GMAC_REGS->GMAC_RBQB = (uint32_t) s_rxdesc; // Let the controller know
22578 
22579 GMAC_REGS->SA[0].GMAC_SAB =
22580 MG_U32(ifp->mac[3], ifp->mac[2], ifp->mac[1], ifp->mac[0]);
22581 GMAC_REGS->SA[0].GMAC_SAT = MG_U32(0, 0, ifp->mac[5], ifp->mac[4]);
22582 
22583 GMAC_REGS->GMAC_UR &= ~GMAC_UR_MII_Msk; // Disable MII, use RMII
22584 GMAC_REGS->GMAC_NCFGR |= GMAC_NCFGR_MAXFS_Msk | GMAC_NCFGR_MTIHEN_Msk |
22585 GMAC_NCFGR_EFRHD_Msk | GMAC_NCFGR_CAF_Msk;
22586 GMAC_REGS->GMAC_TSR = GMAC_TSR_HRESP_Msk | GMAC_TSR_UND_Msk |
22587 GMAC_TSR_TXCOMP_Msk | GMAC_TSR_TFC_Msk |
22588 GMAC_TSR_TXGO_Msk | GMAC_TSR_RLE_Msk |
22589 GMAC_TSR_COL_Msk | GMAC_TSR_UBR_Msk;
22590 GMAC_REGS->GMAC_RSR = GMAC_RSR_HNO_Msk | GMAC_RSR_RXOVR_Msk |
22591 GMAC_RSR_REC_Msk | GMAC_RSR_BNA_Msk;
22592 GMAC_REGS->GMAC_IDR = ~0U; // Disable interrupts, then enable required
22593 GMAC_REGS->GMAC_IER = GMAC_IER_HRESP_Msk | GMAC_IER_ROVR_Msk |
22594 GMAC_IER_TCOMP_Msk | GMAC_IER_TFC_Msk |
22595 GMAC_IER_RLEX_Msk | GMAC_IER_TUR_Msk |
22596 GMAC_IER_RXUBR_Msk | GMAC_IER_RCOMP_Msk;
22597 GMAC_REGS->GMAC_NCR |= GMAC_NCR_TXEN_Msk | GMAC_NCR_RXEN_Msk;
22598 NVIC_EnableIRQ(GMAC_IRQn);
22599 
22600 return true;
22601}
22602 
22603static size_t mg_tcpip_driver_same54_tx(const void *buf, size_t len,
22604 struct mg_tcpip_if *ifp) {
22605 if (len > sizeof(s_txbuf[s_txno])) {
22606 MG_ERROR(("Frame too big, %ld", (long) len));
22607 len = 0; // Frame is too big
22608 } else if ((s_txdesc[s_txno][1] & MG_BIT(31)) == 0) {
22609 ifp->nerr++;
22610 MG_ERROR(("No free descriptors"));
22611 len = 0; // All descriptors are busy, fail
22612 } else {
22613 uint32_t status = len | MG_BIT(15); // Frame length, last chunk
22614 if (s_txno == ETH_DESC_CNT - 1) status |= MG_BIT(30); // wrap
22615 memcpy(s_txbuf[s_txno], buf, len); // Copy data
22616 s_txdesc[s_txno][1] = status;
22617 if (++s_txno >= ETH_DESC_CNT) s_txno = 0;
22618 }
22619 __DSB(); // Ensure descriptors have been written
22620 GMAC_REGS->GMAC_NCR |= GMAC_NCR_TSTART_Msk; // Enable transmission
22621 return len;
22622}
22623 
22624static void mg_tcpip_driver_same54_update_hash_table(struct mg_tcpip_if *ifp) {
22625 // TODO(): read database, rebuild hash table
22626 // Setting Hash Index for 01:00:5e:00:00:fb (multicast)
22627 // 24.6.9 Hash addressing
22628 // computed hash is 55, which means bit 23 (55 - 32) in
22629 // HRT register must be set
22630 GMAC_REGS->GMAC_HRT = MG_BIT(23);
22631 GMAC_REGS->GMAC_NCFGR |= MG_BIT(6); // enable multicast hash filtering
22632 (void) ifp;
22633}
22634 
22635static bool mg_tcpip_driver_same54_poll(struct mg_tcpip_if *ifp, bool s1) {
22636 if (ifp->update_mac_hash_table) {
22637 mg_tcpip_driver_same54_update_hash_table(ifp);
22638 ifp->update_mac_hash_table = false;
22639 }
22640 if (s1) {
22641 uint16_t bsr = eth_read_phy(MG_PHY_ADDR, MG_PHYREG_BSR);
22642 bool up = bsr & MG_PHYREGBIT_BSR_LINK_STATUS ? 1 : 0;
22643 
22644 // If PHY is ready, update NCFGR accordingly
22645 if (ifp->state == MG_TCPIP_STATE_DOWN && up) {
22646 uint16_t bcr = eth_read_phy(MG_PHY_ADDR, MG_PHYREG_BCR);
22647 bool fd = bcr & MG_PHYREGBIT_BCR_DUPLEX_MODE ? 1 : 0;
22648 bool spd = bcr & MG_PHYREGBIT_BCR_SPEED ? 1 : 0;
22649 GMAC_REGS->GMAC_NCFGR = (GMAC_REGS->GMAC_NCFGR &
22650 ~(GMAC_NCFGR_SPD_Msk | MG_PHYREGBIT_BCR_SPEED)) |
22651 GMAC_NCFGR_SPD(spd) | GMAC_NCFGR_FD(fd);
22652 }
22653 }
22654 return false;
22655}
22656 
22657void GMAC_Handler(void);
22658void GMAC_Handler(void) {
22659 uint32_t isr = GMAC_REGS->GMAC_ISR;
22660 uint32_t rsr = GMAC_REGS->GMAC_RSR;
22661 uint32_t tsr = GMAC_REGS->GMAC_TSR;
22662 if (isr & GMAC_ISR_RCOMP_Msk) {
22663 if (rsr & GMAC_ISR_RCOMP_Msk) {
22664 for (uint8_t i = 0; i < ETH_DESC_CNT; i++) {
22665 if ((s_rxdesc[s_rxno][0] & MG_BIT(0)) == 0) break;
22666 size_t len = s_rxdesc[s_rxno][1] & (MG_BIT(13) - 1);
22667 mg_tcpip_qwrite(s_rxbuf[s_rxno], len, s_ifp);
22668 s_rxdesc[s_rxno][0] &= ~MG_BIT(0); // Disown
22669 if (++s_rxno >= ETH_DESC_CNT) s_rxno = 0;
22670 }
22671 }
22672 }
22673 
22674 if ((tsr & (GMAC_TSR_HRESP_Msk | GMAC_TSR_UND_Msk | GMAC_TSR_TXCOMP_Msk |
22675 GMAC_TSR_TFC_Msk | GMAC_TSR_TXGO_Msk | GMAC_TSR_RLE_Msk |
22676 GMAC_TSR_COL_Msk | GMAC_TSR_UBR_Msk)) != 0) {
22677 // MG_INFO((" --> %#x %#x", s_txdesc[s_txno][1], tsr));
22678 if (!(s_txdesc[s_txno][1] & MG_BIT(31))) s_txdesc[s_txno][1] |= MG_BIT(31);
22679 }
22680 
22681 GMAC_REGS->GMAC_RSR = rsr;
22682 GMAC_REGS->GMAC_TSR = tsr;
22683}
22684 
22685struct mg_tcpip_driver mg_tcpip_driver_same54 = {
22686 mg_tcpip_driver_same54_init, mg_tcpip_driver_same54_tx, NULL,
22687 mg_tcpip_driver_same54_poll};
22688#endif
22689 
22690#ifdef MG_ENABLE_LINES
22691#line 1 "src/drivers/stm32f.c"
22692#endif
22693 
22694 
22695#if MG_ENABLE_TCPIP && defined(MG_ENABLE_DRIVER_STM32F) && \
22696 MG_ENABLE_DRIVER_STM32F
22697struct stm32f_eth {
22698 volatile uint32_t MACCR, MACFFR, MACHTHR, MACHTLR, MACMIIAR, MACMIIDR, MACFCR,
22699 MACVLANTR, RESERVED0[2], MACRWUFFR, MACPMTCSR, RESERVED1, MACDBGR, MACSR,
22700 MACIMR, MACA0HR, MACA0LR, MACA1HR, MACA1LR, MACA2HR, MACA2LR, MACA3HR,
22701 MACA3LR, RESERVED2[40], MMCCR, MMCRIR, MMCTIR, MMCRIMR, MMCTIMR,
22702 RESERVED3[14], MMCTGFSCCR, MMCTGFMSCCR, RESERVED4[5], MMCTGFCR,
22703 RESERVED5[10], MMCRFCECR, MMCRFAECR, RESERVED6[10], MMCRGUFCR,
22704 RESERVED7[334], PTPTSCR, PTPSSIR, PTPTSHR, PTPTSLR, PTPTSHUR, PTPTSLUR,
22705 PTPTSAR, PTPTTHR, PTPTTLR, RESERVED8, PTPTSSR, PTPPPSCR, RESERVED9[564],
22706 DMABMR, DMATPDR, DMARPDR, DMARDLAR, DMATDLAR, DMASR, DMAOMR, DMAIER,
22707 DMAMFBOCR, DMARSWTR, RESERVED10[8], DMACHTDR, DMACHRDR, DMACHTBAR,
22708 DMACHRBAR;
22709};
22710#undef ETH
22711#define ETH ((struct stm32f_eth *) (uintptr_t) 0x40028000)
22712 
22713#define ETH_PKT_SIZE 1540 // Max frame size
22714#define ETH_DESC_CNT 4 // Descriptors count
22715#define ETH_DS 4 // Descriptor size (words)
22716 
22717static uint32_t s_rxdesc[ETH_DESC_CNT][ETH_DS]; // RX descriptors
22718static uint32_t s_txdesc[ETH_DESC_CNT][ETH_DS]; // TX descriptors
22719static uint8_t s_rxbuf[ETH_DESC_CNT][ETH_PKT_SIZE]; // RX ethernet buffers
22720static uint8_t s_txbuf[ETH_DESC_CNT][ETH_PKT_SIZE]; // TX ethernet buffers
22721static uint8_t s_txno; // Current TX descriptor
22722static uint8_t s_rxno; // Current RX descriptor
22723 
22724static struct mg_tcpip_if *s_ifp; // MIP interface
22725 
22726static uint16_t eth_read_phy(uint8_t addr, uint8_t reg) {
22727 ETH->MACMIIAR &= (7 << 2);
22728 ETH->MACMIIAR |= ((uint32_t) addr << 11) | ((uint32_t) reg << 6);
22729 ETH->MACMIIAR |= MG_BIT(0);
22730 while (ETH->MACMIIAR & MG_BIT(0)) (void) 0;
22731 return ETH->MACMIIDR & 0xffff;
22732}
22733 
22734static void eth_write_phy(uint8_t addr, uint8_t reg, uint16_t val) {
22735 ETH->MACMIIDR = val;
22736 ETH->MACMIIAR &= (7 << 2);
22737 ETH->MACMIIAR |= ((uint32_t) addr << 11) | ((uint32_t) reg << 6) | MG_BIT(1);
22738 ETH->MACMIIAR |= MG_BIT(0);
22739 while (ETH->MACMIIAR & MG_BIT(0)) (void) 0;
22740}
22741 
22742static uint32_t get_hclk(void) {
22743 struct rcc {
22744 volatile uint32_t CR, PLLCFGR, CFGR;
22745 } *rcc = (struct rcc *) 0x40023800;
22746 uint32_t clk = 0, hsi = 16000000 /* 16 MHz */, hse = 8000000 /* 8MHz */;
22747 
22748 if (rcc->CFGR & (1 << 2)) {
22749 clk = hse;
22750 } else if (rcc->CFGR & (1 << 3)) {
22751 uint32_t vco, m, n, p;
22752 m = (rcc->PLLCFGR & (0x3f << 0)) >> 0;
22753 n = (rcc->PLLCFGR & (0x1ff << 6)) >> 6;
22754 p = (((rcc->PLLCFGR & (3 << 16)) >> 16) + 1) * 2;
22755 clk = (rcc->PLLCFGR & (1 << 22)) ? hse : hsi;
22756 vco = (uint32_t) ((uint64_t) clk * n / m);
22757 clk = vco / p;
22758 } else {
22759 clk = hsi;
22760 }
22761 uint32_t hpre = (rcc->CFGR & (15 << 4)) >> 4;
22762 if (hpre < 8) return clk;
22763 
22764 uint8_t ahbptab[8] = {1, 2, 3, 4, 6, 7, 8, 9}; // log2(div)
22765 return ((uint32_t) clk) >> ahbptab[hpre - 8];
22766}
22767 
22768// Guess CR from HCLK. MDC clock is generated from HCLK (AHB); as per 802.3,
22769// it must not exceed 2.5MHz As the AHB clock can be (and usually is) derived
22770// from the HSI (internal RC), and it can go above specs, the datasheets
22771// specify a range of frequencies and activate one of a series of dividers to
22772// keep the MDC clock safely below 2.5MHz. We guess a divider setting based on
22773// HCLK with a +5% drift. If the user uses a different clock from our
22774// defaults, needs to set the macros on top Valid for STM32F74xxx/75xxx
22775// (38.8.1) and STM32F42xxx/43xxx (33.8.1) (both 4.5% worst case drift)
22776static int guess_mdc_cr(void) {
22777 uint8_t crs[] = {2, 3, 0, 1, 4, 5}; // ETH->MACMIIAR::CR values
22778 uint8_t div[] = {16, 26, 42, 62, 102, 124}; // Respective HCLK dividers
22779 uint32_t hclk = get_hclk(); // Guess system HCLK
22780 int result = -1; // Invalid CR value
22781 if (hclk < 25000000) {
22782 MG_ERROR(("HCLK too low"));
22783 } else {
22784 for (int i = 0; i < 6; i++) {
22785 if (hclk / div[i] <= 2375000UL /* 2.5MHz - 5% */) {
22786 result = crs[i];
22787 break;
22788 }
22789 }
22790 if (result < 0) MG_ERROR(("HCLK too high"));
22791 }
22792 MG_DEBUG(("HCLK: %u, CR: %d", hclk, result));
22793 return result;
22794}
22795 
22796static bool mg_tcpip_driver_stm32f_init(struct mg_tcpip_if *ifp) {
22797 struct mg_tcpip_driver_stm32f_data *d =
22798 (struct mg_tcpip_driver_stm32f_data *) ifp->driver_data;
22799 uint8_t phy_addr = d == NULL ? 0 : d->phy_addr;
22800 s_ifp = ifp;
22801 
22802 // Init RX descriptors
22803 for (int i = 0; i < ETH_DESC_CNT; i++) {
22804 s_rxdesc[i][0] = MG_BIT(31); // Own
22805 s_rxdesc[i][1] = sizeof(s_rxbuf[i]) | MG_BIT(14); // 2nd address chained
22806 s_rxdesc[i][2] = (uint32_t) (uintptr_t) s_rxbuf[i]; // Point to data buffer
22807 s_rxdesc[i][3] =
22808 (uint32_t) (uintptr_t) s_rxdesc[(i + 1) % ETH_DESC_CNT]; // Chain
22809 }
22810 
22811 // Init TX descriptors
22812 for (int i = 0; i < ETH_DESC_CNT; i++) {
22813 s_txdesc[i][2] = (uint32_t) (uintptr_t) s_txbuf[i]; // Buf pointer
22814 s_txdesc[i][3] =
22815 (uint32_t) (uintptr_t) s_txdesc[(i + 1) % ETH_DESC_CNT]; // Chain
22816 }
22817 
22818 ETH->DMABMR |= MG_BIT(0); // Software reset
22819 while ((ETH->DMABMR & MG_BIT(0)) != 0) (void) 0; // Wait until done
22820 
22821 // Set MDC clock divider. If user told us the value, use it. Otherwise, guess
22822 int cr = (d == NULL || d->mdc_cr < 0) ? guess_mdc_cr() : d->mdc_cr;
22823 ETH->MACMIIAR = ((uint32_t) cr & 7) << 2;
22824 
22825 // NOTE(cpq): we do not use extended descriptor bit 7, and do not use
22826 // hardware checksum. Therefore, descriptor size is 4, not 8
22827 // ETH->DMABMR = MG_BIT(13) | MG_BIT(16) | MG_BIT(22) | MG_BIT(23) |
22828 // MG_BIT(25);
22829 ETH->MACIMR = MG_BIT(3) | MG_BIT(9); // Mask timestamp & PMT IT
22830 ETH->MACFCR = MG_BIT(7); // Disable zero quarta pause
22831 ETH->MACFFR = MG_BIT(10); // Perfect filtering
22832 struct mg_phy phy = {eth_read_phy, eth_write_phy};
22833 mg_phy_init(&phy, phy_addr, MG_PHY_CLOCKS_MAC);
22834 ETH->DMARDLAR = (uint32_t) (uintptr_t) s_rxdesc; // RX descriptors
22835 ETH->DMATDLAR = (uint32_t) (uintptr_t) s_txdesc; // RX descriptors
22836 ETH->DMAIER = MG_BIT(6) | MG_BIT(16); // RIE, NISE
22837 ETH->MACCR =
22838 MG_BIT(2) | MG_BIT(3) | MG_BIT(11) | MG_BIT(14); // RE, TE, Duplex, Fast
22839 ETH->DMAOMR =
22840 MG_BIT(1) | MG_BIT(13) | MG_BIT(21) | MG_BIT(25); // SR, ST, TSF, RSF
22841 
22842 // MAC address filtering
22843 ETH->MACA0HR = ((uint32_t) ifp->mac[5] << 8U) | ifp->mac[4];
22844 ETH->MACA0LR = (uint32_t) (ifp->mac[3] << 24) |
22845 ((uint32_t) ifp->mac[2] << 16) |
22846 ((uint32_t) ifp->mac[1] << 8) | ifp->mac[0];
22847 return true;
22848}
22849 
22850static size_t mg_tcpip_driver_stm32f_tx(const void *buf, size_t len,
22851 struct mg_tcpip_if *ifp) {
22852 if (len > sizeof(s_txbuf[s_txno])) {
22853 MG_ERROR(("Frame too big, %ld", (long) len));
22854 len = 0; // Frame is too big
22855 } else if ((s_txdesc[s_txno][0] & MG_BIT(31))) {
22856 ifp->nerr++;
22857 MG_ERROR(("No free descriptors"));
22858 // printf("D0 %lx SR %lx\n", (long) s_txdesc[0][0], (long) ETH->DMASR);
22859 len = 0; // All descriptors are busy, fail
22860 } else {
22861 memcpy(s_txbuf[s_txno], buf, len); // Copy data
22862 s_txdesc[s_txno][1] = (uint32_t) len; // Set data len
22863 s_txdesc[s_txno][0] = MG_BIT(20) | MG_BIT(28) | MG_BIT(29); // Chain,FS,LS
22864 s_txdesc[s_txno][0] |= MG_BIT(31); // Set OWN bit - let DMA take over
22865 if (++s_txno >= ETH_DESC_CNT) s_txno = 0;
22866 }
22867 MG_DSB(); // ensure descriptors have been written
22868 ETH->DMASR = MG_BIT(2) | MG_BIT(5); // Clear any prior TBUS/TUS
22869 ETH->DMATPDR = 0; // and resume
22870 return len;
22871}
22872 
22873static void mg_tcpip_driver_stm32f_update_hash_table(struct mg_tcpip_if *ifp) {
22874 // TODO(): read database, rebuild hash table
22875 ETH->MACA1LR = (uint32_t) mcast_addr[3] << 24 |
22876 (uint32_t) mcast_addr[2] << 16 |
22877 (uint32_t) mcast_addr[1] << 8 | (uint32_t) mcast_addr[0];
22878 ETH->MACA1HR = (uint32_t) mcast_addr[5] << 8 | (uint32_t) mcast_addr[4];
22879 ETH->MACA1HR |= MG_BIT(31); // AE
22880 (void) ifp;
22881}
22882 
22883static bool mg_tcpip_driver_stm32f_poll(struct mg_tcpip_if *ifp, bool s1) {
22884 if (ifp->update_mac_hash_table) {
22885 mg_tcpip_driver_stm32f_update_hash_table(ifp);
22886 ifp->update_mac_hash_table = false;
22887 }
22888 if (!s1) return false;
22889 struct mg_tcpip_driver_stm32f_data *d =
22890 (struct mg_tcpip_driver_stm32f_data *) ifp->driver_data;
22891 uint8_t phy_addr = d == NULL ? 0 : d->phy_addr;
22892 uint8_t speed = MG_PHY_SPEED_10M;
22893 bool up = false, full_duplex = false;
22894 struct mg_phy phy = {eth_read_phy, eth_write_phy};
22895 up = mg_phy_up(&phy, phy_addr, &full_duplex, &speed);
22896 if ((ifp->state == MG_TCPIP_STATE_DOWN) && up) { // link state just went up
22897 // tmp = reg with flags set to the most likely situation: 100M full-duplex
22898 // if(link is slow or half) set flags otherwise
22899 // reg = tmp
22900 uint32_t maccr = ETH->MACCR | MG_BIT(14) | MG_BIT(11); // 100M, Full-duplex
22901 if (speed == MG_PHY_SPEED_10M) maccr &= ~MG_BIT(14); // 10M
22902 if (full_duplex == false) maccr &= ~MG_BIT(11); // Half-duplex
22903 ETH->MACCR = maccr; // IRQ handler does not fiddle with this register
22904 MG_DEBUG(("Link is %uM %s-duplex", maccr & MG_BIT(14) ? 100 : 10,
22905 maccr & MG_BIT(11) ? "full" : "half"));
22906 }
22907 return up;
22908}
22909 
22910#ifdef __riscv
22911__attribute__((interrupt())) // For RISCV CH32V307, which share the same MAC
22912#endif
22913void ETH_IRQHandler(void);
22914void ETH_IRQHandler(void) {
22915 if (ETH->DMASR & MG_BIT(6)) { // Frame received, loop
22916 ETH->DMASR = MG_BIT(16) | MG_BIT(6); // Clear flag
22917 for (uint32_t i = 0; i < 10; i++) { // read as they arrive but not forever
22918 if (s_rxdesc[s_rxno][0] & MG_BIT(31)) break; // exit when done
22919 if (((s_rxdesc[s_rxno][0] & (MG_BIT(8) | MG_BIT(9))) ==
22920 (MG_BIT(8) | MG_BIT(9))) &&
22921 !(s_rxdesc[s_rxno][0] & MG_BIT(15))) { // skip partial/errored frames
22922 uint32_t len = ((s_rxdesc[s_rxno][0] >> 16) & (MG_BIT(14) - 1));
22923 // printf("%lx %lu %lx %.8lx\n", s_rxno, len, s_rxdesc[s_rxno][0],
22924 // ETH->DMASR);
22925 mg_tcpip_qwrite(s_rxbuf[s_rxno], len > 4 ? len - 4 : len, s_ifp);
22926 }
22927 s_rxdesc[s_rxno][0] = MG_BIT(31);
22928 if (++s_rxno >= ETH_DESC_CNT) s_rxno = 0;
22929 }
22930 }
22931 // Cleanup flags
22932 ETH->DMASR = MG_BIT(16) // NIS, normal interrupt summary
22933 | MG_BIT(7); // Clear possible RBUS while processing
22934 ETH->DMARPDR = 0; // and resume RX
22935}
22936 
22937struct mg_tcpip_driver mg_tcpip_driver_stm32f = {
22938 mg_tcpip_driver_stm32f_init, mg_tcpip_driver_stm32f_tx, NULL,
22939 mg_tcpip_driver_stm32f_poll};
22940#endif
22941 
22942#ifdef MG_ENABLE_LINES
22943#line 1 "src/drivers/stm32h.c"
22944#endif
22945 
22946 
22947#if MG_ENABLE_TCPIP && (MG_ENABLE_DRIVER_STM32H || MG_ENABLE_DRIVER_MCXN)
22948// STM32H: vendor modded single-queue Synopsys v4.2
22949// MCXNx4x: dual-queue Synopsys v5.2 with no hash table option
22950// RT1170 ENET_QOS: quad-queue Synopsys v5.1
22951struct synopsys_enet_qos {
22952 volatile uint32_t MACCR, MACECR, MACPFR, MACWTR, MACHT0R, MACHT1R,
22953 RESERVED1[14], MACVTR, RESERVED2, MACVHTR, RESERVED3, MACVIR, MACIVIR,
22954 RESERVED4[2], MACTFCR, RESERVED5[7], MACRFCR, RESERVED6[7], MACISR,
22955 MACIER, MACRXTXSR, RESERVED7, MACPCSR, MACRWKPFR, RESERVED8[2], MACLCSR,
22956 MACLTCR, MACLETR, MAC1USTCR, RESERVED9[12], MACVR, MACDR, RESERVED10,
22957 MACHWF0R, MACHWF1R, MACHWF2R, RESERVED11[54], MACMDIOAR, MACMDIODR,
22958 RESERVED12[2], MACARPAR, RESERVED13[59], MACA0HR, MACA0LR, MACA1HR,
22959 MACA1LR, MACA2HR, MACA2LR, MACA3HR, MACA3LR, RESERVED14[248], MMCCR,
22960 MMCRIR, MMCTIR, MMCRIMR, MMCTIMR, RESERVED15[14], MMCTSCGPR, MMCTMCGPR,
22961 RESERVED16[5], MMCTPCGR, RESERVED17[10], MMCRCRCEPR, MMCRAEPR,
22962 RESERVED18[10], MMCRUPGR, RESERVED19[9], MMCTLPIMSTR, MMCTLPITCR,
22963 MMCRLPIMSTR, MMCRLPITCR, RESERVED20[65], MACL3L4C0R, MACL4A0R,
22964 RESERVED21[2], MACL3A0R0R, MACL3A1R0R, MACL3A2R0R, MACL3A3R0R,
22965 RESERVED22[4], MACL3L4C1R, MACL4A1R, RESERVED23[2], MACL3A0R1R,
22966 MACL3A1R1R, MACL3A2R1R, MACL3A3R1R, RESERVED24[108], MACTSCR, MACSSIR,
22967 MACSTSR, MACSTNR, MACSTSUR, MACSTNUR, MACTSAR, RESERVED25, MACTSSR,
22968 RESERVED26[3], MACTTSSNR, MACTTSSSR, RESERVED27[2], MACACR, RESERVED28,
22969 MACATSNR, MACATSSR, MACTSIACR, MACTSEACR, MACTSICNR, MACTSECNR,
22970 RESERVED29[4], MACPPSCR, RESERVED30[3], MACPPSTTSR, MACPPSTTNR, MACPPSIR,
22971 MACPPSWR, RESERVED31[12], MACPOCR, MACSPI0R, MACSPI1R, MACSPI2R, MACLMIR,
22972 RESERVED32[11], MTLOMR, RESERVED33[7], MTLISR, RESERVED34[55], MTLTQOMR,
22973 MTLTQUR, MTLTQDR, RESERVED35[8], MTLQICSR, MTLRQOMR, MTLRQMPOCR, MTLRQDR,
22974 RESERVED36[177], DMAMR, DMASBMR, DMAISR, DMADSR, RESERVED37[60], DMACCR,
22975 DMACTCR, DMACRCR, RESERVED38[2], DMACTDLAR, RESERVED39, DMACRDLAR,
22976 DMACTDTPR, RESERVED40, DMACRDTPR, DMACTDRLR, DMACRDRLR, DMACIER,
22977 DMACRIWTR, DMACSFCSR, RESERVED41, DMACCATDR, RESERVED42, DMACCARDR,
22978 RESERVED43, DMACCATBR, RESERVED44, DMACCARBR, DMACSR, RESERVED45[2],
22979 DMACMFCR;
22980};
22981#undef ETH
22982#if MG_ENABLE_DRIVER_STM32H
22983#define ETH \
22984 ((struct synopsys_enet_qos *) (uintptr_t) (0x40000000UL + 0x00020000UL + \
22985 0x8000UL))
22986#elif MG_ENABLE_DRIVER_MCXN
22987#define ETH ((struct synopsys_enet_qos *) (uintptr_t) 0x40100000UL)
22988#endif
22989 
22990#define ETH_PKT_SIZE 1540 // Max frame size
22991#define ETH_DESC_CNT 4 // Descriptors count
22992#define ETH_DS 4 // Descriptor size (words)
22993 
22994static volatile uint32_t s_rxdesc[ETH_DESC_CNT][ETH_DS]; // RX descriptors
22995static volatile uint32_t s_txdesc[ETH_DESC_CNT][ETH_DS]; // TX descriptors
22996static uint8_t s_rxbuf[ETH_DESC_CNT][ETH_PKT_SIZE]; // RX ethernet buffers
22997static uint8_t s_txbuf[ETH_DESC_CNT][ETH_PKT_SIZE]; // TX ethernet buffers
22998static struct mg_tcpip_if *s_ifp; // MIP interface
22999 
23000static uint16_t eth_read_phy(uint8_t addr, uint8_t reg) {
23001 ETH->MACMDIOAR &= (0xF << 8);
23002 ETH->MACMDIOAR |= ((uint32_t) addr << 21) | ((uint32_t) reg << 16) | 3 << 2;
23003 ETH->MACMDIOAR |= MG_BIT(0);
23004 while (ETH->MACMDIOAR & MG_BIT(0)) (void) 0;
23005 return (uint16_t) ETH->MACMDIODR;
23006}
23007 
23008static void eth_write_phy(uint8_t addr, uint8_t reg, uint16_t val) {
23009 ETH->MACMDIODR = val;
23010 ETH->MACMDIOAR &= (0xF << 8);
23011 ETH->MACMDIOAR |= ((uint32_t) addr << 21) | ((uint32_t) reg << 16) | 1 << 2;
23012 ETH->MACMDIOAR |= MG_BIT(0);
23013 while (ETH->MACMDIOAR & MG_BIT(0)) (void) 0;
23014}
23015 
23016static bool mg_tcpip_driver_stm32h_init(struct mg_tcpip_if *ifp) {
23017 struct mg_tcpip_driver_stm32h_data *d =
23018 (struct mg_tcpip_driver_stm32h_data *) ifp->driver_data;
23019 s_ifp = ifp;
23020 uint8_t phy_addr = d == NULL ? 0 : d->phy_addr;
23021 uint8_t phy_conf = d == NULL ? MG_PHY_CLOCKS_MAC : d->phy_conf;
23022 
23023 // Init RX descriptors
23024 for (int i = 0; i < ETH_DESC_CNT; i++) {
23025 s_rxdesc[i][0] = (uint32_t) (uintptr_t) s_rxbuf[i]; // Point to data buffer
23026 s_rxdesc[i][3] = MG_BIT(31) | MG_BIT(30) | MG_BIT(24); // OWN, IOC, BUF1V
23027 }
23028 
23029 // Init TX descriptors
23030 for (int i = 0; i < ETH_DESC_CNT; i++) {
23031 s_txdesc[i][0] = (uint32_t) (uintptr_t) s_txbuf[i]; // Buf pointer
23032 }
23033 
23034 ETH->DMAMR |= MG_BIT(0); // Software reset
23035 for (int i = 0; i < 4; i++)
23036 (void) 0; // wait at least 4 clocks before reading
23037 while ((ETH->DMAMR & MG_BIT(0)) != 0) (void) 0; // Wait until done
23038 
23039 // Set MDC clock divider. Get user value, else, assume max freq
23040 int cr = (d == NULL || d->mdc_cr < 0) ? 7 : d->mdc_cr;
23041 ETH->MACMDIOAR = ((uint32_t) cr & 0xF) << 8;
23042 
23043 // NOTE(scaprile): We do not use timing facilities so the DMA engine does not
23044 // re-write buffer address
23045 ETH->DMAMR = 0 << 16; // use interrupt mode 0 (58.8.1) (reset value)
23046 ETH->DMASBMR |= MG_BIT(12); // AAL NOTE(scaprile): is this actually needed
23047 ETH->MACIER = 0; // Do not enable additional irq sources (reset value)
23048 ETH->MACTFCR = MG_BIT(7); // Disable zero-quanta pause
23049#if !MG_ENABLE_DRIVER_MCXN
23050 ETH->MACPFR = MG_BIT(10); // Perfect filtering
23051#endif
23052 struct mg_phy phy = {eth_read_phy, eth_write_phy};
23053 mg_phy_init(&phy, phy_addr, phy_conf);
23054 ETH->DMACRDLAR =
23055 (uint32_t) (uintptr_t) s_rxdesc; // RX descriptors start address
23056 ETH->DMACRDRLR = ETH_DESC_CNT - 1; // ring length
23057 ETH->DMACRDTPR =
23058 (uint32_t) (uintptr_t) &s_rxdesc[ETH_DESC_CNT -
23059 1]; // last valid descriptor address
23060 ETH->DMACTDLAR =
23061 (uint32_t) (uintptr_t) s_txdesc; // TX descriptors start address
23062 ETH->DMACTDRLR = ETH_DESC_CNT - 1; // ring length
23063 ETH->DMACTDTPR =
23064 (uint32_t) (uintptr_t) s_txdesc; // first available descriptor address
23065 ETH->DMACCR = 0; // DSL = 0 (contiguous descriptor table) (reset value)
23066#if !MG_ENABLE_DRIVER_STM32H
23067 MG_SET_BITS(ETH->DMACTCR, 0x3F << 16, MG_BIT(16));
23068 MG_SET_BITS(ETH->DMACRCR, 0x3F << 16, MG_BIT(16));
23069#endif
23070 ETH->DMACIER = MG_BIT(6) | MG_BIT(15); // RIE, NIE
23071 ETH->MACCR = MG_BIT(0) | MG_BIT(1) | MG_BIT(13) | MG_BIT(14) |
23072 MG_BIT(15); // RE, TE, Duplex, Fast, Reserved
23073#if MG_ENABLE_DRIVER_STM32H
23074 ETH->MTLTQOMR |= MG_BIT(1); // TSF
23075 ETH->MTLRQOMR |= MG_BIT(5); // RSF
23076#else
23077 ETH->MTLTQOMR |= (7 << 16) | MG_BIT(3) | MG_BIT(1); // 2KB Q0, TSF
23078 ETH->MTLRQOMR |= (7 << 20) | MG_BIT(5); // 2KB Q, RSF
23079 MG_SET_BITS(ETH->RESERVED6[3], 3, 2); // Enable RxQ0 (MAC_RXQ_CTRL0)
23080#endif
23081 ETH->DMACTCR |= MG_BIT(0); // ST
23082 ETH->DMACRCR |= MG_BIT(0); // SR
23083 
23084 // MAC address filtering
23085 ETH->MACA0HR = ((uint32_t) ifp->mac[5] << 8U) | ifp->mac[4];
23086 ETH->MACA0LR = (uint32_t) (ifp->mac[3] << 24) |
23087 ((uint32_t) ifp->mac[2] << 16) |
23088 ((uint32_t) ifp->mac[1] << 8) | ifp->mac[0];
23089 return true;
23090}
23091 
23092static uint32_t s_txno;
23093static size_t mg_tcpip_driver_stm32h_tx(const void *buf, size_t len,
23094 struct mg_tcpip_if *ifp) {
23095 if (len > sizeof(s_txbuf[s_txno])) {
23096 MG_ERROR(("Frame too big, %ld", (long) len));
23097 len = 0; // Frame is too big
23098 } else if ((s_txdesc[s_txno][3] & MG_BIT(31))) {
23099 ifp->nerr++;
23100 MG_ERROR(("No free descriptors: %u %08X %08X %08X", s_txno,
23101 s_txdesc[s_txno][3], ETH->DMACSR, ETH->DMACTCR));
23102 for (int i = 0; i < ETH_DESC_CNT; i++) MG_ERROR(("%08X", s_txdesc[i][3]));
23103 len = 0; // All descriptors are busy, fail
23104 } else {
23105 memcpy(s_txbuf[s_txno], buf, len); // Copy data
23106 s_txdesc[s_txno][2] = (uint32_t) len; // Set data len
23107 s_txdesc[s_txno][3] = MG_BIT(28) | MG_BIT(29); // FD, LD
23108 s_txdesc[s_txno][3] |= MG_BIT(31); // Set OWN bit - let DMA take over
23109 if (++s_txno >= ETH_DESC_CNT) s_txno = 0;
23110 }
23111 ETH->DMACSR |= MG_BIT(2) | MG_BIT(1); // Clear any prior TBU, TPS
23112 ETH->DMACTDTPR = (uint32_t) (uintptr_t) &s_txdesc[s_txno]; // and resume
23113 return len;
23114 (void) ifp;
23115}
23116 
23117static void mg_tcpip_driver_stm32h_update_hash_table(struct mg_tcpip_if *ifp) {
23118#if MG_ENABLE_DRIVER_MCXN
23119 ETH->MACPFR = MG_BIT(4); // Pass Multicast (pass all multicast frames)
23120#else
23121 // TODO(): read database, rebuild hash table
23122 // add mDNS / DNS-SD multicast address
23123 ETH->MACA1LR = (uint32_t) mcast_addr[3] << 24 |
23124 (uint32_t) mcast_addr[2] << 16 |
23125 (uint32_t) mcast_addr[1] << 8 | (uint32_t) mcast_addr[0];
23126 ETH->MACA1HR = (uint32_t) mcast_addr[5] << 8 | (uint32_t) mcast_addr[4];
23127 ETH->MACA1HR |= MG_BIT(31); // AE
23128#endif
23129(void) ifp;
23130}
23131 
23132static bool mg_tcpip_driver_stm32h_poll(struct mg_tcpip_if *ifp, bool s1) {
23133 if (ifp->update_mac_hash_table) {
23134 mg_tcpip_driver_stm32h_update_hash_table(ifp);
23135 ifp->update_mac_hash_table = false;
23136 }
23137 if (!s1) return false;
23138 struct mg_tcpip_driver_stm32h_data *d =
23139 (struct mg_tcpip_driver_stm32h_data *) ifp->driver_data;
23140 uint8_t phy_addr = d == NULL ? 0 : d->phy_addr;
23141 uint8_t speed = MG_PHY_SPEED_10M;
23142 bool up = false, full_duplex = false;
23143 struct mg_phy phy = {eth_read_phy, eth_write_phy};
23144 up = mg_phy_up(&phy, phy_addr, &full_duplex, &speed);
23145 if ((ifp->state == MG_TCPIP_STATE_DOWN) && up) { // link state just went up
23146 // tmp = reg with flags set to the most likely situation: 100M full-duplex
23147 // if(link is slow or half) set flags otherwise
23148 // reg = tmp
23149 uint32_t maccr = ETH->MACCR | MG_BIT(14) | MG_BIT(13); // 100M, Full-duplex
23150 if (speed == MG_PHY_SPEED_10M) maccr &= ~MG_BIT(14); // 10M
23151 if (full_duplex == false) maccr &= ~MG_BIT(13); // Half-duplex
23152 ETH->MACCR = maccr; // IRQ handler does not fiddle with this register
23153 MG_DEBUG(("Link is %uM %s-duplex", maccr & MG_BIT(14) ? 100 : 10,
23154 maccr & MG_BIT(13) ? "full" : "half"));
23155 }
23156 return up;
23157}
23158 
23159static uint32_t s_rxno;
23160#if MG_ENABLE_DRIVER_MCXN
23161void ETHERNET_IRQHandler(void);
23162void ETHERNET_IRQHandler(void) {
23163#else
23164void ETH_IRQHandler(void);
23165void ETH_IRQHandler(void) {
23166#endif
23167 if (ETH->DMACSR & MG_BIT(6)) { // Frame received, loop
23168 ETH->DMACSR = MG_BIT(15) | MG_BIT(6); // Clear flag
23169 for (uint32_t i = 0; i < 10; i++) { // read as they arrive but not forever
23170 if (s_rxdesc[s_rxno][3] & MG_BIT(31)) break; // exit when done
23171 if (((s_rxdesc[s_rxno][3] & (MG_BIT(28) | MG_BIT(29))) ==
23172 (MG_BIT(28) | MG_BIT(29))) &&
23173 !(s_rxdesc[s_rxno][3] & MG_BIT(15))) { // skip partial/errored frames
23174 uint32_t len = s_rxdesc[s_rxno][3] & (MG_BIT(15) - 1);
23175 // MG_DEBUG(("%lx %lu %lx %08lx", s_rxno, len, s_rxdesc[s_rxno][3],
23176 // ETH->DMACSR));
23177 mg_tcpip_qwrite(s_rxbuf[s_rxno], len > 4 ? len - 4 : len, s_ifp);
23178 }
23179 s_rxdesc[s_rxno][3] =
23180 MG_BIT(31) | MG_BIT(30) | MG_BIT(24); // OWN, IOC, BUF1V
23181 if (++s_rxno >= ETH_DESC_CNT) s_rxno = 0;
23182 }
23183 }
23184 ETH->DMACSR =
23185 MG_BIT(7) | MG_BIT(8); // Clear possible RBU RPS while processing
23186 ETH->DMACRDTPR =
23187 (uint32_t) (uintptr_t) &s_rxdesc[ETH_DESC_CNT - 1]; // and resume RX
23188}
23189 
23190struct mg_tcpip_driver mg_tcpip_driver_stm32h = {
23191 mg_tcpip_driver_stm32h_init, mg_tcpip_driver_stm32h_tx, NULL,
23192 mg_tcpip_driver_stm32h_poll};
23193#endif
23194 
23195#ifdef MG_ENABLE_LINES
23196#line 1 "src/drivers/tm4c.c"
23197#endif
23198 
23199 
23200#if MG_ENABLE_TCPIP && defined(MG_ENABLE_DRIVER_TM4C) && MG_ENABLE_DRIVER_TM4C
23201struct tm4c_emac {
23202 volatile uint32_t EMACCFG, EMACFRAMEFLTR, EMACHASHTBLH, EMACHASHTBLL,
23203 EMACMIIADDR, EMACMIIDATA, EMACFLOWCTL, EMACVLANTG, RESERVED0, EMACSTATUS,
23204 EMACRWUFF, EMACPMTCTLSTAT, RESERVED1[2], EMACRIS, EMACIM, EMACADDR0H,
23205 EMACADDR0L, EMACADDR1H, EMACADDR1L, EMACADDR2H, EMACADDR2L, EMACADDR3H,
23206 EMACADDR3L, RESERVED2[31], EMACWDOGTO, RESERVED3[8], EMACMMCCTRL,
23207 EMACMMCRXRIS, EMACMMCTXRIS, EMACMMCRXIM, EMACMMCTXIM, RESERVED4,
23208 EMACTXCNTGB, RESERVED5[12], EMACTXCNTSCOL, EMACTXCNTMCOL, RESERVED6[4],
23209 EMACTXOCTCNTG, RESERVED7[6], EMACRXCNTGB, RESERVED8[4], EMACRXCNTCRCERR,
23210 EMACRXCNTALGNERR, RESERVED9[10], EMACRXCNTGUNI, RESERVED10[239],
23211 EMACVLNINCREP, EMACVLANHASH, RESERVED11[93], EMACTIMSTCTRL, EMACSUBSECINC,
23212 EMACTIMSEC, EMACTIMNANO, EMACTIMSECU, EMACTIMNANOU, EMACTIMADD,
23213 EMACTARGSEC, EMACTARGNANO, EMACHWORDSEC, EMACTIMSTAT, EMACPPSCTRL,
23214 RESERVED12[12], EMACPPS0INTVL, EMACPPS0WIDTH, RESERVED13[294],
23215 EMACDMABUSMOD, EMACTXPOLLD, EMACRXPOLLD, EMACRXDLADDR, EMACTXDLADDR,
23216 EMACDMARIS, EMACDMAOPMODE, EMACDMAIM, EMACMFBOC, EMACRXINTWDT,
23217 RESERVED14[8], EMACHOSTXDESC, EMACHOSRXDESC, EMACHOSTXBA, EMACHOSRXBA,
23218 RESERVED15[218], EMACPP, EMACPC, EMACCC, RESERVED16, EMACEPHYRIS,
23219 EMACEPHYIM, EMACEPHYIMSC;
23220};
23221#undef EMAC
23222#define EMAC ((struct tm4c_emac *) (uintptr_t) 0x400EC000)
23223 
23224#define ETH_PKT_SIZE 1540 // Max frame size
23225#define ETH_DESC_CNT 4 // Descriptors count
23226#define ETH_DS 4 // Descriptor size (words)
23227 
23228static uint32_t s_rxdesc[ETH_DESC_CNT][ETH_DS]; // RX descriptors
23229static uint32_t s_txdesc[ETH_DESC_CNT][ETH_DS]; // TX descriptors
23230static uint8_t s_rxbuf[ETH_DESC_CNT][ETH_PKT_SIZE]; // RX ethernet buffers
23231static uint8_t s_txbuf[ETH_DESC_CNT][ETH_PKT_SIZE]; // TX ethernet buffers
23232static struct mg_tcpip_if *s_ifp; // MIP interface
23233enum {
23234 EPHY_ADDR = 0,
23235 EPHYBMCR = 0,
23236 EPHYBMSR = 1,
23237 EPHYSTS = 16
23238}; // PHY constants
23239 
23240static inline void tm4cspin(volatile uint32_t count) {
23241 while (count--) (void) 0;
23242}
23243 
23244static uint32_t emac_read_phy(uint8_t addr, uint8_t reg) {
23245 EMAC->EMACMIIADDR &= (0xf << 2);
23246 EMAC->EMACMIIADDR |= ((uint32_t) addr << 11) | ((uint32_t) reg << 6);
23247 EMAC->EMACMIIADDR |= MG_BIT(0);
23248 while (EMAC->EMACMIIADDR & MG_BIT(0)) tm4cspin(1);
23249 return EMAC->EMACMIIDATA;
23250}
23251 
23252static void emac_write_phy(uint8_t addr, uint8_t reg, uint32_t val) {
23253 EMAC->EMACMIIDATA = val;
23254 EMAC->EMACMIIADDR &= (0xf << 2);
23255 EMAC->EMACMIIADDR |=
23256 ((uint32_t) addr << 11) | ((uint32_t) reg << 6) | MG_BIT(1);
23257 EMAC->EMACMIIADDR |= MG_BIT(0);
23258 while (EMAC->EMACMIIADDR & MG_BIT(0)) tm4cspin(1);
23259}
23260 
23261static uint32_t get_sysclk(void) {
23262 struct sysctl {
23263 volatile uint32_t DONTCARE0[44], RSCLKCFG, DONTCARE1[43], PLLFREQ0,
23264 PLLFREQ1;
23265 } *sysctl = (struct sysctl *) 0x400FE000;
23266 uint32_t clk = 0, piosc = 16000000 /* 16 MHz */, mosc = 25000000 /* 25MHz */;
23267 if (sysctl->RSCLKCFG & (1 << 28)) { // USEPLL
23268 uint32_t fin, vco, mdiv, n, q, psysdiv;
23269 uint32_t pllsrc = (sysctl->RSCLKCFG & (0xf << 24)) >> 24;
23270 if (pllsrc == 0) {
23271 clk = piosc;
23272 } else if (pllsrc == 3) {
23273 clk = mosc;
23274 } else {
23275 MG_ERROR(("Unsupported clock source"));
23276 }
23277 q = (sysctl->PLLFREQ1 & (0x1f << 8)) >> 8;
23278 n = (sysctl->PLLFREQ1 & (0x1f << 0)) >> 0;
23279 fin = clk / ((q + 1) * (n + 1));
23280 mdiv = (sysctl->PLLFREQ0 & (0x3ff << 0)) >>
23281 0; // mint + (mfrac / 1024); MFRAC not supported
23282 psysdiv = (sysctl->RSCLKCFG & (0x3f << 0)) >> 0;
23283 vco = (uint32_t) ((uint64_t) fin * mdiv);
23284 return vco / (psysdiv + 1);
23285 }
23286 uint32_t oscsrc = (sysctl->RSCLKCFG & (0xf << 20)) >> 20;
23287 if (oscsrc == 0) {
23288 clk = piosc;
23289 } else if (oscsrc == 3) {
23290 clk = mosc;
23291 } else {
23292 MG_ERROR(("Unsupported clock source"));
23293 }
23294 uint32_t osysdiv = (sysctl->RSCLKCFG & (0xf << 16)) >> 16;
23295 return clk / (osysdiv + 1);
23296}
23297 
23298// Guess CR from SYSCLK. MDC clock is generated from SYSCLK (AHB); as per
23299// 802.3, it must not exceed 2.5MHz (also 20.4.2.6) As the AHB clock can be
23300// derived from the PIOSC (internal RC), and it can go above specs, the
23301// datasheets specify a range of frequencies and activate one of a series of
23302// dividers to keep the MDC clock safely below 2.5MHz. We guess a divider
23303// setting based on SYSCLK with a +5% drift. If the user uses a different clock
23304// from our defaults, needs to set the macros on top Valid for TM4C129x (20.7)
23305// (4.5% worst case drift)
23306// The PHY receives the main oscillator (MOSC) (20.3.1)
23307static int guess_mdc_cr(void) {
23308 uint8_t crs[] = {2, 3, 0, 1}; // EMAC->MACMIIAR::CR values
23309 uint8_t div[] = {16, 26, 42, 62}; // Respective HCLK dividers
23310 uint32_t sysclk = get_sysclk(); // Guess system SYSCLK
23311 int result = -1; // Invalid CR value
23312 if (sysclk < 25000000) {
23313 MG_ERROR(("SYSCLK too low"));
23314 } else {
23315 for (int i = 0; i < 4; i++) {
23316 if (sysclk / div[i] <= 2375000UL /* 2.5MHz - 5% */) {
23317 result = crs[i];
23318 break;
23319 }
23320 }
23321 if (result < 0) MG_ERROR(("SYSCLK too high"));
23322 }
23323 MG_DEBUG(("SYSCLK: %u, CR: %d", sysclk, result));
23324 return result;
23325}
23326 
23327static bool mg_tcpip_driver_tm4c_init(struct mg_tcpip_if *ifp) {
23328 struct mg_tcpip_driver_tm4c_data *d =
23329 (struct mg_tcpip_driver_tm4c_data *) ifp->driver_data;
23330 s_ifp = ifp;
23331 
23332 // Init RX descriptors
23333 for (int i = 0; i < ETH_DESC_CNT; i++) {
23334 s_rxdesc[i][0] = MG_BIT(31); // Own
23335 s_rxdesc[i][1] = sizeof(s_rxbuf[i]) | MG_BIT(14); // 2nd address chained
23336 s_rxdesc[i][2] = (uint32_t) (uintptr_t) s_rxbuf[i]; // Point to data buffer
23337 s_rxdesc[i][3] =
23338 (uint32_t) (uintptr_t) s_rxdesc[(i + 1) % ETH_DESC_CNT]; // Chain
23339 // MG_DEBUG(("%d %p", i, s_rxdesc[i]));
23340 }
23341 
23342 // Init TX descriptors
23343 for (int i = 0; i < ETH_DESC_CNT; i++) {
23344 s_txdesc[i][2] = (uint32_t) (uintptr_t) s_txbuf[i]; // Buf pointer
23345 s_txdesc[i][3] =
23346 (uint32_t) (uintptr_t) s_txdesc[(i + 1) % ETH_DESC_CNT]; // Chain
23347 }
23348 
23349 EMAC->EMACDMABUSMOD |= MG_BIT(0); // Software reset
23350 while ((EMAC->EMACDMABUSMOD & MG_BIT(0)) != 0)
23351 tm4cspin(1); // Wait until done
23352 
23353 // Set MDC clock divider. If user told us the value, use it. Otherwise, guess
23354 int cr = (d == NULL || d->mdc_cr < 0) ? guess_mdc_cr() : d->mdc_cr;
23355 EMAC->EMACMIIADDR = ((uint32_t) cr & 0xf) << 2;
23356 
23357 // NOTE(cpq): we do not use extended descriptor bit 7, and do not use
23358 // hardware checksum. Therefore, descriptor size is 4, not 8
23359 // EMAC->EMACDMABUSMOD = MG_BIT(13) | MG_BIT(16) | MG_BIT(22) | MG_BIT(23) |
23360 // MG_BIT(25);
23361 EMAC->EMACIM = MG_BIT(3) | MG_BIT(9); // Mask timestamp & PMT IT
23362 EMAC->EMACFLOWCTL = MG_BIT(7); // Disable zero-quanta pause
23363 EMAC->EMACFRAMEFLTR = MG_BIT(10); // Perfect filtering
23364 // EMAC->EMACPC defaults to internal PHY (EPHY) in MMI mode
23365 emac_write_phy(EPHY_ADDR, EPHYBMCR, MG_BIT(15)); // Reset internal PHY (EPHY)
23366 emac_write_phy(EPHY_ADDR, EPHYBMCR, MG_BIT(12)); // Set autonegotiation
23367 EMAC->EMACRXDLADDR = (uint32_t) (uintptr_t) s_rxdesc; // RX descriptors
23368 EMAC->EMACTXDLADDR = (uint32_t) (uintptr_t) s_txdesc; // TX descriptors
23369 EMAC->EMACDMAIM = MG_BIT(6) | MG_BIT(16); // RIE, NIE
23370 EMAC->EMACCFG =
23371 MG_BIT(2) | MG_BIT(3) | MG_BIT(11) | MG_BIT(14); // RE, TE, Duplex, Fast
23372 EMAC->EMACDMAOPMODE =
23373 MG_BIT(1) | MG_BIT(13) | MG_BIT(21) | MG_BIT(25); // SR, ST, TSF, RSF
23374 EMAC->EMACADDR0H = ((uint32_t) ifp->mac[5] << 8U) | ifp->mac[4];
23375 EMAC->EMACADDR0L = (uint32_t) (ifp->mac[3] << 24) |
23376 ((uint32_t) ifp->mac[2] << 16) |
23377 ((uint32_t) ifp->mac[1] << 8) | ifp->mac[0];
23378 return true;
23379}
23380 
23381static uint32_t s_txno;
23382static size_t mg_tcpip_driver_tm4c_tx(const void *buf, size_t len,
23383 struct mg_tcpip_if *ifp) {
23384 if (len > sizeof(s_txbuf[s_txno])) {
23385 MG_ERROR(("Frame too big, %ld", (long) len));
23386 len = 0; // fail
23387 } else if ((s_txdesc[s_txno][0] & MG_BIT(31))) {
23388 ifp->nerr++;
23389 MG_ERROR(("No descriptors available"));
23390 // printf("D0 %lx SR %lx\n", (long) s_txdesc[0][0], (long)
23391 // EMAC->EMACDMARIS);
23392 len = 0; // fail
23393 } else {
23394 memcpy(s_txbuf[s_txno], buf, len); // Copy data
23395 s_txdesc[s_txno][1] = (uint32_t) len; // Set data len
23396 s_txdesc[s_txno][0] =
23397 MG_BIT(20) | MG_BIT(28) | MG_BIT(29) | MG_BIT(30); // Chain,FS,LS,IC
23398 s_txdesc[s_txno][0] |= MG_BIT(31); // Set OWN bit - let DMA take over
23399 if (++s_txno >= ETH_DESC_CNT) s_txno = 0;
23400 }
23401 EMAC->EMACDMARIS = MG_BIT(2) | MG_BIT(5); // Clear any prior TU/UNF
23402 EMAC->EMACTXPOLLD = 0; // and resume
23403 return len;
23404 (void) ifp;
23405}
23406 
23407static void mg_tcpip_driver_tm4c_update_hash_table(struct mg_tcpip_if *ifp) {
23408 // TODO(): read database, rebuild hash table
23409 // add mDNS / DNS-SD multicast address
23410 EMAC->EMACADDR1L = (uint32_t) mcast_addr[3] << 24 |
23411 (uint32_t) mcast_addr[2] << 16 |
23412 (uint32_t) mcast_addr[1] << 8 | (uint32_t) mcast_addr[0];
23413 EMAC->EMACADDR1H = (uint32_t) mcast_addr[5] << 8 | (uint32_t) mcast_addr[4];
23414 EMAC->EMACADDR1H |= MG_BIT(31); // AE
23415 (void) ifp;
23416}
23417 
23418static bool mg_tcpip_driver_tm4c_poll(struct mg_tcpip_if *ifp, bool s1) {
23419 if (ifp->update_mac_hash_table) {
23420 mg_tcpip_driver_tm4c_update_hash_table(ifp);
23421 ifp->update_mac_hash_table = false;
23422 }
23423 if (!s1) return false;
23424 uint32_t bmsr = emac_read_phy(EPHY_ADDR, EPHYBMSR);
23425 bool up = (bmsr & MG_BIT(2)) ? 1 : 0;
23426 if ((ifp->state == MG_TCPIP_STATE_DOWN) && up) { // link state just went up
23427 uint32_t sts = emac_read_phy(EPHY_ADDR, EPHYSTS);
23428 // tmp = reg with flags set to the most likely situation: 100M full-duplex
23429 // if(link is slow or half) set flags otherwise
23430 // reg = tmp
23431 uint32_t emaccfg =
23432 EMAC->EMACCFG | MG_BIT(14) | MG_BIT(11); // 100M, Full-duplex
23433 if (sts & MG_BIT(1)) emaccfg &= ~MG_BIT(14); // 10M
23434 if ((sts & MG_BIT(2)) == 0) emaccfg &= ~MG_BIT(11); // Half-duplex
23435 EMAC->EMACCFG = emaccfg; // IRQ handler does not fiddle with this register
23436 MG_DEBUG(("Link is %uM %s-duplex", emaccfg & MG_BIT(14) ? 100 : 10,
23437 emaccfg & MG_BIT(11) ? "full" : "half"));
23438 }
23439 return up;
23440}
23441 
23442void EMAC0_IRQHandler(void);
23443static uint32_t s_rxno;
23444void EMAC0_IRQHandler(void) {
23445 if (EMAC->EMACDMARIS & MG_BIT(6)) { // Frame received, loop
23446 EMAC->EMACDMARIS = MG_BIT(16) | MG_BIT(6); // Clear flag
23447 for (uint32_t i = 0; i < 10; i++) { // read as they arrive but not forever
23448 if (s_rxdesc[s_rxno][0] & MG_BIT(31)) break; // exit when done
23449 if (((s_rxdesc[s_rxno][0] & (MG_BIT(8) | MG_BIT(9))) ==
23450 (MG_BIT(8) | MG_BIT(9))) &&
23451 !(s_rxdesc[s_rxno][0] & MG_BIT(15))) { // skip partial/errored frames
23452 uint32_t len = ((s_rxdesc[s_rxno][0] >> 16) & (MG_BIT(14) - 1));
23453 // printf("%lx %lu %lx %.8lx\n", s_rxno, len, s_rxdesc[s_rxno][0],
23454 // EMAC->EMACDMARIS);
23455 mg_tcpip_qwrite(s_rxbuf[s_rxno], len > 4 ? len - 4 : len, s_ifp);
23456 }
23457 s_rxdesc[s_rxno][0] = MG_BIT(31);
23458 if (++s_rxno >= ETH_DESC_CNT) s_rxno = 0;
23459 }
23460 }
23461 EMAC->EMACDMARIS = MG_BIT(7); // Clear possible RU while processing
23462 EMAC->EMACRXPOLLD = 0; // and resume RX
23463}
23464 
23465struct mg_tcpip_driver mg_tcpip_driver_tm4c = {mg_tcpip_driver_tm4c_init,
23466 mg_tcpip_driver_tm4c_tx, NULL,
23467 mg_tcpip_driver_tm4c_poll};
23468#endif
23469 
23470#ifdef MG_ENABLE_LINES
23471#line 1 "src/drivers/tms570.c"
23472#endif
23473 
23474 
23475#if MG_ENABLE_TCPIP && defined(MG_ENABLE_DRIVER_TMS570) && MG_ENABLE_DRIVER_TMS570
23476struct tms570_emac_ctrl {
23477 volatile uint32_t REVID, SOFTRESET, RESERVED1[1], INTCONTROL, C0RXTHRESHEN,
23478 C0RXEN, C0TXEN, C0MISCEN, RESERVED2[8],
23479 C0RXTHRESHSTAT, C0RXSTAT, C0TXSTAT, C0MISCSTAT,
23480 RESERVED3[8],
23481 C0RXIMAX, C0TXIMAX;
23482};
23483struct tms570_emac {
23484 volatile uint32_t TXREVID, TXCONTROL, TXTEARDOWN, RESERVED1[1], RXREVID,
23485 RXCONTROL, RXTEARDOWN, RESERVED2[25], TXINTSTATRAW,TXINTSTATMASKED,
23486 TXINTMASKSET, TXINTMASKCLEAR, MACINVECTOR, MACEOIVECTOR, RESERVED8[2], RXINTSTATRAW,
23487 RXINTSTATMASKED, RXINTMASKSET, RXINTMASKCLEAR, MACINTSTATRAW, MACINTSTATMASKED,
23488 MACINTMASKSET, MACINTMASKCLEAR, RESERVED3[16], RXMBPENABLE, RXUNICASTSET,
23489 RXUNICASTCLEAR, RXMAXLEN, RXBUFFEROFFSET, RXFILTERLOWTHRESH, RESERVED9[2], RXFLOWTHRESH[8],
23490 RXFREEBUFFER[8], MACCONTROL, MACSTATUS, EMCONTROL, FIFOCONTROL, MACCONFIG,
23491 SOFTRESET, RESERVED4[22], MACSRCADDRLO, MACSRCADDRHI, MACHASH1, MACHASH2,
23492 BOFFTEST, TPACETEST, RXPAUSE, TXPAUSE, RESERVED5[4], RXGOODFRAMES, RXBCASTFRAMES,
23493 RXMCASTFRAMES, RXPAUSEFRAMES, RXCRCERRORS, RXALIGNCODEERRORS, RXOVERSIZED,
23494 RXJABBER, RXUNDERSIZED, RXFRAGMENTS, RXFILTERED, RXQOSFILTERED, RXOCTETS,
23495 TXGOODFRAMES, TXBCASTFRAMES, TXMCASTFRAMES, TXPAUSEFRAMES, TXDEFERRED,
23496 TXCOLLISION, TXSINGLECOLL, TXMULTICOLL, TXEXCESSIVECOLL, TXLATECOLL,
23497 TXUNDERRUN, TXCARRIERSENSE, TXOCTETS, FRAME64, FRAME65T127, FRAME128T255,
23498 FRAME256T511, FRAME512T1023, FRAME1024TUP, NETOCTETS, RXSOFOVERRUNS,
23499 RXMOFOVERRUNS, RXDMAOVERRUNS, RESERVED6[156], MACADDRLO, MACADDRHI,
23500 MACINDEX, RESERVED7[61], TXHDP[8], RXHDP[8], TXCP[8], RXCP[8];
23501};
23502struct tms570_mdio {
23503 volatile uint32_t REVID, CONTROL, ALIVE, LINK, LINKINTRAW, LINKINTMASKED,
23504 RESERVED1[2], USERINTRAW, USERINTMASKED, USERINTMASKSET, USERINTMASKCLEAR,
23505 RESERVED2[20], USERACCESS0, USERPHYSEL0, USERACCESS1, USERPHYSEL1;
23506};
23507#define SWAP32(x) ( (((x) & 0x000000FF) << 24) | \
23508 (((x) & 0x0000FF00) << 8) | \
23509 (((x) & 0x00FF0000) >> 8) | \
23510 (((x) & 0xFF000000) >> 24) )
23511#undef EMAC
23512#undef EMAC_CTRL
23513#undef MDIO
23514#define EMAC ((struct tms570_emac *) (uintptr_t) 0xFCF78000)
23515#define EMAC_CTRL ((struct tms570_emac_ctrl *) (uintptr_t) 0xFCF78800)
23516#define MDIO ((struct tms570_mdio *) (uintptr_t) 0xFCF78900)
23517#define ETH_PKT_SIZE 1540 // Max frame size
23518#define ETH_DESC_CNT 4 // Descriptors count
23519#define ETH_DS 4 // Descriptor size (words)
23520static uint32_t s_txdesc[ETH_DESC_CNT][ETH_DS]
23521 __attribute__((section(".ETH_CPPI"), aligned(4))); // TX descriptors
23522static uint32_t s_rxdesc[ETH_DESC_CNT][ETH_DS]
23523 __attribute__((section(".ETH_CPPI"), aligned(4))); // RX descriptors
23524static uint8_t s_rxbuf[ETH_DESC_CNT][ETH_PKT_SIZE]
23525 __attribute__((aligned(4))); // RX ethernet buffers
23526static uint8_t s_txbuf[ETH_DESC_CNT][ETH_PKT_SIZE]
23527 __attribute__((aligned(4))); // TX ethernet buffers
23528static struct mg_tcpip_if *s_ifp; // MIP interface
23529static uint16_t emac_read_phy(uint8_t addr, uint8_t reg) {
23530 while(MDIO->USERACCESS0 & MG_BIT(31)) (void) 0;
23531 MDIO->USERACCESS0 = MG_BIT(31) | ((reg & 0x1f) << 21) |
23532 ((addr & 0x1f) << 16);
23533 while(MDIO->USERACCESS0 & MG_BIT(31)) (void) 0;
23534 return MDIO->USERACCESS0 & 0xffff;
23535}
23536static void emac_write_phy(uint8_t addr, uint8_t reg, uint16_t val) {
23537 while(MDIO->USERACCESS0 & MG_BIT(31)) (void) 0;
23538 MDIO->USERACCESS0 = MG_BIT(31) | MG_BIT(30) | ((reg & 0x1f) << 21) |
23539 ((addr & 0x1f) << 16) | (val & 0xffff);
23540 while(MDIO->USERACCESS0 & MG_BIT(31)) (void) 0;
23541}
23542static bool mg_tcpip_driver_tms570_init(struct mg_tcpip_if *ifp) {
23543 struct mg_tcpip_driver_tms570_data *d =
23544 (struct mg_tcpip_driver_tms570_data *) ifp->driver_data;
23545 s_ifp = ifp;
23546 EMAC_CTRL->SOFTRESET = MG_BIT(0); // Reset the EMAC Control Module
23547 while(EMAC_CTRL->SOFTRESET & MG_BIT(0)) (void) 0; // wait
23548 EMAC->SOFTRESET = MG_BIT(0); // Reset the EMAC Module
23549 while(EMAC->SOFTRESET & MG_BIT(0)) (void) 0;
23550 EMAC->MACCONTROL = 0;
23551 EMAC->RXCONTROL = 0;
23552 EMAC->TXCONTROL = 0;
23553 // Initialize all the header descriptor pointer registers
23554 uint32_t i;
23555 for(i = 0; i < ETH_DESC_CNT; i++) {
23556 EMAC->RXHDP[i] = 0;
23557 EMAC->TXHDP[i] = 0;
23558 EMAC->RXCP[i] = 0;
23559 EMAC->TXCP[i] = 0;
23560 ///EMAC->RXFREEBUFFER[i] = 0xff;
23561 }
23562 // Clear the interrupt enable for all the channels
23563 EMAC->TXINTMASKCLEAR = 0xff;
23564 EMAC->RXINTMASKCLEAR = 0xff;
23565 EMAC->MACHASH1 = 0;
23566 EMAC->MACHASH2 = 0;
23567 EMAC->RXBUFFEROFFSET = 0;
23568 EMAC->RXUNICASTCLEAR = 0xff;
23569 EMAC->RXUNICASTSET = 0;
23570 EMAC->RXMBPENABLE = 0;
23571 // init MDIO
23572 // MDIO_CLK frequency = VCLK3/(CLKDIV + 1). (MDIO must be between 1.0 - 2.5Mhz)
23573 uint32_t clkdiv = 75; // VCLK is configured to 75Mhz
23574 // CLKDIV, ENABLE, PREAMBLE, FAULTENB
23575 MDIO->CONTROL = (clkdiv - 1) | MG_BIT(30) | MG_BIT(20) | MG_BIT(18);
23576 volatile int delay = 0xfff;
23577 while (delay-- != 0) (void) 0;
23578 struct mg_phy phy = {emac_read_phy, emac_write_phy};
23579 mg_phy_init(&phy, d->phy_addr, MG_PHY_CLOCKS_MAC);
23580 uint32_t channel;
23581 for (channel = 0; channel < 8; channel++) {
23582 EMAC->MACINDEX = channel;
23583 EMAC->MACADDRHI = ifp->mac[0] | (ifp->mac[1] << 8) | (ifp->mac[2] << 16) |
23584 (ifp->mac[3] << 24);
23585 EMAC->MACADDRLO = ifp->mac[4] | (ifp->mac[5] << 8) | MG_BIT(20) |
23586 MG_BIT(19) | (channel << 16);
23587 }
23588 EMAC->RXUNICASTSET = 1; // accept unicast frames;
23589 
23590 EMAC->RXMBPENABLE |= MG_BIT(30) | MG_BIT(13); // CRC, broadcast
23591 
23592 // Initialize the descriptors
23593 for (i = 0; i < ETH_DESC_CNT; i++) {
23594 if (i < ETH_DESC_CNT - 1) {
23595 s_txdesc[i][0] = 0;
23596 s_rxdesc[i][0] = SWAP32(((uint32_t) &s_rxdesc[i + 1][0]));
23597 }
23598 s_txdesc[i][1] = SWAP32(((uint32_t) s_txbuf[i]));
23599 s_rxdesc[i][1] = SWAP32(((uint32_t) s_rxbuf[i]));
23600 s_txdesc[i][2] = 0;
23601 s_rxdesc[i][2] = SWAP32(ETH_PKT_SIZE);
23602 s_txdesc[i][3] = 0;
23603 s_rxdesc[i][3] = SWAP32(MG_BIT(29)); // OWN
23604 }
23605 s_txdesc[ETH_DESC_CNT - 1][0] = 0;
23606 s_rxdesc[ETH_DESC_CNT - 1][0] = 0;
23607
23608 EMAC->MACCONTROL = MG_BIT(5) | MG_BIT(0); // Enable MII, Full-duplex
23609 //EMAC->TXINTMASKSET = 1; // Enable TX interrupt
23610 EMAC->RXINTMASKSET = 1; // Enable RX interrupt
23611 //EMAC_CTRL->C0TXEN = 1; // TX completion interrupt
23612 EMAC_CTRL->C0RXEN = 1; // RX completion interrupt
23613 EMAC->TXCONTROL = 1; // TXEN
23614 EMAC->RXCONTROL = 1; // RXEN
23615 EMAC->RXHDP[0] = (uint32_t) &s_rxdesc[0][0];
23616 return true;
23617}
23618static uint32_t s_txno;
23619static size_t mg_tcpip_driver_tms570_tx(const void *buf, size_t len,
23620 struct mg_tcpip_if *ifp) {
23621 if (len > sizeof(s_txbuf[s_txno])) {
23622 MG_ERROR(("Frame too big, %ld", (long) len));
23623 len = 0; // fail
23624 } else if ((s_txdesc[s_txno][3] & SWAP32(MG_BIT(29)))) {
23625 ifp->nerr++;
23626 MG_ERROR(("No descriptors available"));
23627 len = 0; // fail
23628 } else {
23629 memcpy(s_txbuf[s_txno], buf, len); // Copy data
23630 if (len < 128) len = 128;
23631 s_txdesc[s_txno][2] = SWAP32((uint32_t) len); // Set data len
23632 s_txdesc[s_txno][3] =
23633 SWAP32(MG_BIT(31) | MG_BIT(30) | MG_BIT(29) | len); // SOP, EOP, OWN, length
23634
23635 while(EMAC->TXHDP[0] != 0) (void) 0;
23636 EMAC->TXHDP[0] = (uint32_t) &s_txdesc[s_txno][0];
23637 if(++s_txno == ETH_DESC_CNT) {
23638 s_txno = 0;
23639 }
23640 }
23641 return len;
23642 (void) ifp;
23643}
23644 
23645static void mg_tcpip_driver_tms570_update_hash_table(struct mg_tcpip_if *ifp) {
23646 // TODO(): read database, rebuild hash table
23647 // Setting Hash Index for 01:00:5e:00:00:fb (multicast)
23648 // using TMS570 XOR method (32.5.37).
23649 // computed hash is 55, which means bit 23 (55 - 32) in
23650 // HASH2 register must be set
23651 EMAC->MACHASH2 = MG_BIT(23);
23652 EMAC->RXMBPENABLE = MG_BIT(5); // enable hash filtering
23653 (void) ifp;
23654}
23655 
23656static bool mg_tcpip_driver_tms570_poll(struct mg_tcpip_if *ifp, bool s1) {
23657 if (ifp->update_mac_hash_table) {
23658 mg_tcpip_driver_tms570_update_hash_table(ifp);
23659 ifp->update_mac_hash_table = false;
23660 }
23661 if (!s1) return false;
23662 struct mg_tcpip_driver_tms570_data *d =
23663 (struct mg_tcpip_driver_tms570_data *) ifp->driver_data;
23664 uint8_t speed = MG_PHY_SPEED_10M;
23665 bool up = false, full_duplex = false;
23666 struct mg_phy phy = {emac_read_phy, emac_write_phy};
23667 if (!s1) return false;
23668 up = mg_phy_up(&phy, d->phy_addr, &full_duplex, &speed);
23669 if ((ifp->state == MG_TCPIP_STATE_DOWN) && up) {
23670 // link state just went up
23671 MG_DEBUG(("Link is %uM %s-duplex", speed == MG_PHY_SPEED_10M ? 10 : 100,
23672 full_duplex ? "full" : "half"));
23673 }
23674 return up;
23675}
23676 
23677#pragma CODE_STATE(EMAC_TX_IRQHandler, 32)
23678#pragma INTERRUPT(EMAC_TX_IRQHandler, IRQ)
23679void EMAC_TX_IRQHandler(void) {
23680 uint32_t status = EMAC_CTRL->C0TXSTAT;
23681 if (status & 1) { // interrupt caused on channel 0
23682 while(s_txdesc[s_txno][3] & SWAP32(MG_BIT(29))) (void) 0;
23683 EMAC->TXCP[0] = (uint32_t) &s_txdesc[s_txno][0];
23684 }
23685 //Write the DMA end of interrupt vector
23686 EMAC->MACEOIVECTOR = 2;
23687}
23688static uint32_t s_rxno;
23689#pragma CODE_STATE(EMAC_RX_IRQHandler, 32)
23690#pragma INTERRUPT(EMAC_RX_IRQHandler, IRQ)
23691void EMAC_RX_IRQHandler(void) {
23692 uint32_t status = EMAC_CTRL->C0RXSTAT;
23693 if (status & 1) { // Frame received, loop
23694 uint32_t i;
23695 //MG_INFO(("RX interrupt"));
23696 for (i = 0; i < 10; i++) { // read as they arrive but not forever
23697 if (s_rxdesc[s_rxno][3] & SWAP32(MG_BIT(29))) break;
23698 uint32_t len = SWAP32(s_rxdesc[s_rxno][3]) & 0xffff;
23699 //MG_INFO(("recv len: %d", len));
23700 //mg_hexdump(s_rxbuf[s_rxno], len);
23701 mg_tcpip_qwrite(s_rxbuf[s_rxno], len > 4 ? len - 4 : len, s_ifp);
23702 uint32_t flags = s_rxdesc[s_rxno][3];
23703 s_rxdesc[s_rxno][3] = SWAP32(MG_BIT(29));
23704 s_rxdesc[s_rxno][2] = SWAP32(ETH_PKT_SIZE);
23705 EMAC->RXCP[0] = (uint32_t) &s_rxdesc[s_rxno][0];
23706 if (flags & SWAP32(MG_BIT(28))) {
23707 //MG_INFO(("EOQ detected"));
23708 EMAC->RXHDP[0] = (uint32_t) &s_rxdesc[0][0];
23709 }
23710 if (++s_rxno >= ETH_DESC_CNT) s_rxno = 0;
23711 }
23712 }
23713 //Write the DMA end of interrupt vector
23714 EMAC->MACEOIVECTOR = 1;
23715}
23716struct mg_tcpip_driver mg_tcpip_driver_tms570 = {mg_tcpip_driver_tms570_init,
23717 mg_tcpip_driver_tms570_tx, NULL,
23718 mg_tcpip_driver_tms570_poll};
23719#endif
23720 
23721 
23722#ifdef MG_ENABLE_LINES
23723#line 1 "src/drivers/w5100.c"
23724#endif
23725 
23726 
23727#if MG_ENABLE_TCPIP && defined(MG_ENABLE_DRIVER_W5100) && MG_ENABLE_DRIVER_W5100
23728 
23729static void w5100_txn(struct mg_tcpip_spi *s, uint16_t addr, bool wr, void *buf,
23730 size_t len) {
23731 size_t i;
23732 uint8_t *p = (uint8_t *) buf;
23733 uint8_t control = wr ? 0xF0 : 0x0F;
23734 uint8_t cmd[] = {control, (uint8_t) (addr >> 8), (uint8_t) (addr & 255)};
23735 s->begin(s->spi);
23736 for (i = 0; i < sizeof(cmd); i++) s->txn(s->spi, cmd[i]);
23737 for (i = 0; i < len; i++) {
23738 uint8_t r = s->txn(s->spi, p[i]);
23739 if (!wr) p[i] = r;
23740 }
23741 s->end(s->spi);
23742}
23743 
23744// clang-format off
23745static void w5100_wn(struct mg_tcpip_spi *s, uint16_t addr, void *buf, size_t len) { w5100_txn(s, addr, true, buf, len); }
23746static void w5100_w1(struct mg_tcpip_spi *s, uint16_t addr, uint8_t val) { w5100_wn(s, addr, &val, 1); }
23747static void w5100_w2(struct mg_tcpip_spi *s, uint16_t addr, uint16_t val) { uint8_t buf[2] = {(uint8_t) (val >> 8), (uint8_t) (val & 255)}; w5100_wn(s, addr, buf, sizeof(buf)); }
23748static void w5100_rn(struct mg_tcpip_spi *s, uint16_t addr, void *buf, size_t len) { w5100_txn(s, addr, false, buf, len); }
23749static uint8_t w5100_r1(struct mg_tcpip_spi *s, uint16_t addr) { uint8_t r = 0; w5100_rn(s, addr, &r, 1); return r; }
23750static uint16_t w5100_r2(struct mg_tcpip_spi *s, uint16_t addr) { uint8_t buf[2] = {0, 0}; w5100_rn(s, addr, buf, sizeof(buf)); return (uint16_t) ((buf[0] << 8) | buf[1]); }
23751// clang-format on
23752 
23753static size_t w5100_rx(void *buf, size_t buflen, struct mg_tcpip_if *ifp) {
23754 struct mg_tcpip_spi *s = (struct mg_tcpip_spi *) ifp->driver_data;
23755 uint16_t r = 0, n = 0, len = (uint16_t) buflen, n2; // Read recv len
23756 while ((n2 = w5100_r2(s, 0x426)) > n) n = n2; // Until it is stable
23757 if (n > 0) {
23758 uint16_t ptr = w5100_r2(s, 0x428); // Get read pointer
23759 if (n <= len + 2 && n > 1) {
23760 r = (uint16_t) (n - 2);
23761 }
23762 uint16_t rxbuf_size = (1 << (w5100_r1(s, 0x1a) & 3)) * 1024;
23763 uint16_t rxbuf_addr = 0x6000;
23764 uint16_t ptr_ofs = (ptr + 2) & (rxbuf_size - 1);
23765 if (ptr_ofs + r < rxbuf_size) {
23766 w5100_rn(s, rxbuf_addr + ptr_ofs, buf, r);
23767 } else {
23768 uint16_t remaining_len = rxbuf_size - ptr_ofs;
23769 w5100_rn(s, rxbuf_addr + ptr_ofs, buf, remaining_len);
23770 w5100_rn(s, rxbuf_addr, buf + remaining_len, n - remaining_len);
23771 }
23772 w5100_w2(s, 0x428, (uint16_t) (ptr + n));
23773 w5100_w1(s, 0x401, 0x40); // Sock0 CR -> RECV
23774 }
23775 return r;
23776}
23777 
23778static size_t w5100_tx(const void *buf, size_t buflen,
23779 struct mg_tcpip_if *ifp) {
23780 struct mg_tcpip_spi *s = (struct mg_tcpip_spi *) ifp->driver_data;
23781 uint16_t i, n = 0, ptr = 0, len = (uint16_t) buflen;
23782 while (n < len) n = w5100_r2(s, 0x420); // Wait for space
23783 ptr = w5100_r2(s, 0x424); // Get write pointer
23784 uint16_t txbuf_size = (1 << (w5100_r1(s, 0x1b) & 3)) * 1024;
23785 uint16_t ptr_ofs = ptr & (txbuf_size - 1);
23786 uint16_t txbuf_addr = 0x4000;
23787 if (ptr_ofs + len > txbuf_size) {
23788 uint16_t size = txbuf_size - ptr_ofs;
23789 w5100_wn(s, txbuf_addr + ptr_ofs, (char *) buf, size);
23790 w5100_wn(s, txbuf_addr, (char *) buf + size, len - size);
23791 } else {
23792 w5100_wn(s, txbuf_addr + ptr_ofs, (char *) buf, len);
23793 }
23794 w5100_w2(s, 0x424, (uint16_t) (ptr + len)); // Advance write pointer
23795 w5100_w1(s, 0x401, 0x20); // Sock0 CR -> SEND
23796 for (i = 0; i < 40; i++) {
23797 uint8_t ir = w5100_r1(s, 0x402); // Read S0 IR
23798 if (ir == 0) continue;
23799 // printf("IR %d, len=%d, free=%d, ptr %d\n", ir, (int) len, (int) n, ptr);
23800 w5100_w1(s, 0x402, ir); // Write S0 IR: clear it!
23801 if (ir & 8) len = 0; // Timeout. Report error
23802 if (ir & (16 | 8)) break; // Stop on SEND_OK or timeout
23803 }
23804 return len;
23805}
23806 
23807static bool w5100_init(struct mg_tcpip_if *ifp) {
23808 struct mg_tcpip_spi *s = (struct mg_tcpip_spi *) ifp->driver_data;
23809 s->end(s->spi);
23810 w5100_w1(s, 0, 0x80); // Reset chip: CR -> 0x80
23811 w5100_w1(s, 0x72, 0x53); // CR PHYLCKR -> unlock PHY
23812 w5100_w1(s, 0x46, 0); // CR PHYCR0 -> autonegotiation
23813 w5100_w1(s, 0x47, 0); // CR PHYCR1 -> reset
23814 w5100_w1(s, 0x72, 0x00); // CR PHYLCKR -> lock PHY
23815 w5100_wn(s, 0x09, ifp->mac, 6); // SHAR
23816 w5100_w1(s, 0x1a, 6); // Sock0 RX buf size - 4KB
23817 w5100_w1(s, 0x1b, 6); // Sock0 TX buf size - 4KB
23818 w5100_w1(s, 0x400, 0x44); // Sock0 MR -> MACRAW, MAC filter
23819 w5100_w1(s, 0x401, 1); // Sock0 CR -> OPEN
23820 return w5100_r1(s, 0x403) == 0x42; // Sock0 SR == MACRAW
23821}
23822 
23823static bool w5100_poll(struct mg_tcpip_if *ifp, bool s1) {
23824 struct mg_tcpip_spi *spi = (struct mg_tcpip_spi *) ifp->driver_data;
23825 return s1 ? w5100_r1(spi, 0x3c /* PHYSR */) & 1
23826 : false; // Bit 0 of PHYSR is LNK (0 - down, 1 - up)
23827}
23828 
23829struct mg_tcpip_driver mg_tcpip_driver_w5100 = {w5100_init, w5100_tx, w5100_rx,
23830 w5100_poll};
23831#endif
23832 
23833#ifdef MG_ENABLE_LINES
23834#line 1 "src/drivers/w5500.c"
23835#endif
23836 
23837 
23838#if MG_ENABLE_TCPIP && defined(MG_ENABLE_DRIVER_W5500) && MG_ENABLE_DRIVER_W5500
23839 
23840enum { W5500_CR = 0, W5500_S0 = 1, W5500_TX0 = 2, W5500_RX0 = 3 };
23841 
23842static void w5500_txn(struct mg_tcpip_spi *s, uint8_t block, uint16_t addr,
23843 bool wr, void *buf, size_t len) {
23844 size_t i;
23845 uint8_t *p = (uint8_t *) buf;
23846 uint8_t cmd[] = {(uint8_t) (addr >> 8), (uint8_t) (addr & 255),
23847 (uint8_t) ((block << 3) | (wr ? 4 : 0))};
23848 s->begin(s->spi);
23849 for (i = 0; i < sizeof(cmd); i++) s->txn(s->spi, cmd[i]);
23850 for (i = 0; i < len; i++) {
23851 uint8_t r = s->txn(s->spi, p[i]);
23852 if (!wr) p[i] = r;
23853 }
23854 s->end(s->spi);
23855}
23856 
23857// clang-format off
23858static void w5500_wn(struct mg_tcpip_spi *s, uint8_t block, uint16_t addr, void *buf, size_t len) { w5500_txn(s, block, addr, true, buf, len); }
23859static void w5500_w1(struct mg_tcpip_spi *s, uint8_t block, uint16_t addr, uint8_t val) { w5500_wn(s, block, addr, &val, 1); }
23860static void w5500_w2(struct mg_tcpip_spi *s, uint8_t block, uint16_t addr, uint16_t val) { uint8_t buf[2] = {(uint8_t) (val >> 8), (uint8_t) (val & 255)}; w5500_wn(s, block, addr, buf, sizeof(buf)); }
23861static void w5500_rn(struct mg_tcpip_spi *s, uint8_t block, uint16_t addr, void *buf, size_t len) { w5500_txn(s, block, addr, false, buf, len); }
23862static uint8_t w5500_r1(struct mg_tcpip_spi *s, uint8_t block, uint16_t addr) { uint8_t r = 0; w5500_rn(s, block, addr, &r, 1); return r; }
23863static uint16_t w5500_r2(struct mg_tcpip_spi *s, uint8_t block, uint16_t addr) { uint8_t buf[2] = {0, 0}; w5500_rn(s, block, addr, buf, sizeof(buf)); return (uint16_t) ((buf[0] << 8) | buf[1]); }
23864// clang-format on
23865 
23866static size_t w5500_rx(void *buf, size_t buflen, struct mg_tcpip_if *ifp) {
23867 struct mg_tcpip_spi *s = (struct mg_tcpip_spi *) ifp->driver_data;
23868 uint16_t r = 0, n = 0, len = (uint16_t) buflen, n2; // Read recv len
23869 while ((n2 = w5500_r2(s, W5500_S0, 0x26)) > n) n = n2; // Until it is stable
23870 // printf("RSR: %d\n", (int) n);
23871 if (n > 0) {
23872 uint16_t ptr = w5500_r2(s, W5500_S0, 0x28); // Get read pointer
23873 n = w5500_r2(s, W5500_RX0, ptr); // Read frame length
23874 if (n <= len + 2 && n > 1) {
23875 r = (uint16_t) (n - 2);
23876 w5500_rn(s, W5500_RX0, (uint16_t) (ptr + 2), buf, r);
23877 }
23878 w5500_w2(s, W5500_S0, 0x28, (uint16_t) (ptr + n)); // Advance read pointer
23879 w5500_w1(s, W5500_S0, 1, 0x40); // Sock0 CR -> RECV
23880 // printf(" RX_RD: tot=%u n=%u r=%u\n", n2, n, r);
23881 }
23882 return r;
23883}
23884 
23885static size_t w5500_tx(const void *buf, size_t buflen,
23886 struct mg_tcpip_if *ifp) {
23887 struct mg_tcpip_spi *s = (struct mg_tcpip_spi *) ifp->driver_data;
23888 uint16_t i, ptr, n = 0, len = (uint16_t) buflen;
23889 while (n < len) n = w5500_r2(s, W5500_S0, 0x20); // Wait for space
23890 ptr = w5500_r2(s, W5500_S0, 0x24); // Get write pointer
23891 w5500_wn(s, W5500_TX0, ptr, (void *) buf, len); // Write data
23892 w5500_w2(s, W5500_S0, 0x24, (uint16_t) (ptr + len)); // Advance write pointer
23893 w5500_w1(s, W5500_S0, 1, 0x20); // Sock0 CR -> SEND
23894 for (i = 0; i < 40; i++) {
23895 uint8_t ir = w5500_r1(s, W5500_S0, 2); // Read S0 IR
23896 if (ir == 0) continue;
23897 // printf("IR %d, len=%d, free=%d, ptr %d\n", ir, (int) len, (int) n, ptr);
23898 w5500_w1(s, W5500_S0, 2, ir); // Write S0 IR: clear it!
23899 if (ir & 8) len = 0; // Timeout. Report error
23900 if (ir & (16 | 8)) break; // Stop on SEND_OK or timeout
23901 }
23902 return len;
23903}
23904 
23905static bool w5500_init(struct mg_tcpip_if *ifp) {
23906 struct mg_tcpip_spi *s = (struct mg_tcpip_spi *) ifp->driver_data;
23907 s->end(s->spi);
23908 w5500_w1(s, W5500_CR, 0, 0x80); // Reset chip: CR -> 0x80
23909 w5500_w1(s, W5500_CR, 0x2e, 0); // CR PHYCFGR -> reset
23910 w5500_w1(s, W5500_CR, 0x2e, 0xf8); // CR PHYCFGR -> set
23911 // w5500_wn(s, W5500_CR, 9, s->mac, 6); // Set source MAC
23912 w5500_w1(s, W5500_S0, 0x1e, 16); // Sock0 RX buf size
23913 w5500_w1(s, W5500_S0, 0x1f, 16); // Sock0 TX buf size
23914 w5500_w1(s, W5500_S0, 0, 4); // Sock0 MR -> MACRAW
23915 w5500_w1(s, W5500_S0, 1, 1); // Sock0 CR -> OPEN
23916 return w5500_r1(s, W5500_S0, 3) == 0x42; // Sock0 SR == MACRAW
23917}
23918 
23919static bool w5500_poll(struct mg_tcpip_if *ifp, bool s1) {
23920 struct mg_tcpip_spi *spi = (struct mg_tcpip_spi *) ifp->driver_data;
23921 return s1 ? w5500_r1(spi, W5500_CR, 0x2e /* PHYCFGR */) & 1
23922 : false; // Bit 0 of PHYCFGR is LNK (0 - down, 1 - up)
23923}
23924 
23925struct mg_tcpip_driver mg_tcpip_driver_w5500 = {w5500_init, w5500_tx, w5500_rx,
23926 w5500_poll};
23927#endif
23928 
23929#ifdef MG_ENABLE_LINES
23930#line 1 "src/drivers/xmc.c"
23931#endif
23932 
23933 
23934#if MG_ENABLE_TCPIP && defined(MG_ENABLE_DRIVER_XMC) && MG_ENABLE_DRIVER_XMC
23935 
23936struct ETH_GLOBAL_TypeDef {
23937 volatile uint32_t MAC_CONFIGURATION, MAC_FRAME_FILTER, HASH_TABLE_HIGH,
23938 HASH_TABLE_LOW, GMII_ADDRESS, GMII_DATA, FLOW_CONTROL, VLAN_TAG, VERSION,
23939 DEBUG, REMOTE_WAKE_UP_FRAME_FILTER, PMT_CONTROL_STATUS, RESERVED[2],
23940 INTERRUPT_STATUS, INTERRUPT_MASK, MAC_ADDRESS0_HIGH, MAC_ADDRESS0_LOW,
23941 MAC_ADDRESS1_HIGH, MAC_ADDRESS1_LOW, MAC_ADDRESS2_HIGH, MAC_ADDRESS2_LOW,
23942 MAC_ADDRESS3_HIGH, MAC_ADDRESS3_LOW, RESERVED1[40], MMC_CONTROL,
23943 MMC_RECEIVE_INTERRUPT, MMC_TRANSMIT_INTERRUPT, MMC_RECEIVE_INTERRUPT_MASK,
23944 MMC_TRANSMIT_INTERRUPT_MASK, TX_STATISTICS[26], RESERVED2,
23945 RX_STATISTICS_1[26], RESERVED3[6], MMC_IPC_RECEIVE_INTERRUPT_MASK,
23946 RESERVED4, MMC_IPC_RECEIVE_INTERRUPT, RESERVED5, RX_STATISTICS_2[30],
23947 RESERVED7[286], TIMESTAMP_CONTROL, SUB_SECOND_INCREMENT,
23948 SYSTEM_TIME_SECONDS, SYSTEM_TIME_NANOSECONDS, SYSTEM_TIME_SECONDS_UPDATE,
23949 SYSTEM_TIME_NANOSECONDS_UPDATE, TIMESTAMP_ADDEND, TARGET_TIME_SECONDS,
23950 TARGET_TIME_NANOSECONDS, SYSTEM_TIME_HIGHER_WORD_SECONDS,
23951 TIMESTAMP_STATUS, PPS_CONTROL, RESERVED8[564], BUS_MODE,
23952 TRANSMIT_POLL_DEMAND, RECEIVE_POLL_DEMAND,
23953 RECEIVE_DESCRIPTOR_LIST_ADDRESS, TRANSMIT_DESCRIPTOR_LIST_ADDRESS, STATUS,
23954 OPERATION_MODE, INTERRUPT_ENABLE,
23955 MISSED_FRAME_AND_BUFFER_OVERFLOW_COUNTER,
23956 RECEIVE_INTERRUPT_WATCHDOG_TIMER, RESERVED9, AHB_STATUS, RESERVED10[6],
23957 CURRENT_HOST_TRANSMIT_DESCRIPTOR, CURRENT_HOST_RECEIVE_DESCRIPTOR,
23958 CURRENT_HOST_TRANSMIT_BUFFER_ADDRESS, CURRENT_HOST_RECEIVE_BUFFER_ADDRESS,
23959 HW_FEATURE;
23960};
23961 
23962#undef ETH0
23963#define ETH0 ((struct ETH_GLOBAL_TypeDef *) 0x5000C000UL)
23964 
23965#define ETH_PKT_SIZE 1536 // Max frame size
23966#define ETH_DESC_CNT 4 // Descriptors count
23967#define ETH_DS 4 // Descriptor size (words)
23968 
23969#ifndef ETH_RAM_SECTION
23970// if no section is specified, then the data will be placed in the default
23971// bss section
23972#define ETH_RAM_SECTION
23973#endif
23974 
23975static uint8_t s_rxbuf[ETH_DESC_CNT][ETH_PKT_SIZE] ETH_RAM_SECTION;
23976static uint8_t s_txbuf[ETH_DESC_CNT][ETH_PKT_SIZE] ETH_RAM_SECTION;
23977static uint32_t s_rxdesc[ETH_DESC_CNT]
23978 [ETH_DS] ETH_RAM_SECTION; // RX descriptors
23979static uint32_t s_txdesc[ETH_DESC_CNT]
23980 [ETH_DS] ETH_RAM_SECTION; // TX descriptors
23981static uint8_t s_txno; // Current TX descriptor
23982static uint8_t s_rxno; // Current RX descriptor
23983 
23984static struct mg_tcpip_if *s_ifp; // MIP interface
23985enum { MG_PHY_ADDR = 0, MG_PHYREG_BCR = 0, MG_PHYREG_BSR = 1 };
23986 
23987static uint16_t eth_read_phy(uint8_t addr, uint8_t reg) {
23988 ETH0->GMII_ADDRESS = (ETH0->GMII_ADDRESS & 0x3c) | ((uint32_t) addr << 11) |
23989 ((uint32_t) reg << 6) | 1;
23990 while ((ETH0->GMII_ADDRESS & 1) != 0) (void) 0;
23991 return (uint16_t) (ETH0->GMII_DATA & 0xffff);
23992}
23993 
23994static void eth_write_phy(uint8_t addr, uint8_t reg, uint16_t val) {
23995 ETH0->GMII_DATA = val;
23996 ETH0->GMII_ADDRESS = (ETH0->GMII_ADDRESS & 0x3c) | ((uint32_t) addr << 11) |
23997 ((uint32_t) reg << 6) | 3;
23998 while ((ETH0->GMII_ADDRESS & 1) != 0) (void) 0;
23999}
24000 
24001static uint32_t get_clock_rate(struct mg_tcpip_driver_xmc_data *d) {
24002 if (d->mdc_cr == -1) {
24003 // assume ETH clock is 60MHz by default
24004 // then according to 13.2.8.1, we need to set value 3
24005 return 3;
24006 }
24007 
24008 return d->mdc_cr;
24009}
24010 
24011static bool mg_tcpip_driver_xmc_init(struct mg_tcpip_if *ifp) {
24012 struct mg_tcpip_driver_xmc_data *d =
24013 (struct mg_tcpip_driver_xmc_data *) ifp->driver_data;
24014 s_ifp = ifp;
24015 
24016 // reset MAC
24017 ETH0->BUS_MODE |= 1;
24018 while (ETH0->BUS_MODE & 1) (void) 0;
24019 
24020 // set clock rate
24021 ETH0->GMII_ADDRESS = get_clock_rate(d) << 2;
24022 
24023 // init phy
24024 struct mg_phy phy = {eth_read_phy, eth_write_phy};
24025 mg_phy_init(&phy, d->phy_addr, MG_PHY_CLOCKS_MAC);
24026 
24027 // configure MAC: DO, DM, FES, TC
24028 ETH0->MAC_CONFIGURATION = MG_BIT(13) | MG_BIT(11) | MG_BIT(14) | MG_BIT(24);
24029 
24030 // set the MAC address
24031 ETH0->MAC_ADDRESS0_HIGH = MG_U32(0, 0, ifp->mac[5], ifp->mac[4]);
24032 ETH0->MAC_ADDRESS0_LOW =
24033 MG_U32(ifp->mac[3], ifp->mac[2], ifp->mac[1], ifp->mac[0]);
24034 
24035 // Configure the receive filter
24036 ETH0->MAC_FRAME_FILTER = MG_BIT(10); // Perfect filter
24037 // Disable flow control
24038 ETH0->FLOW_CONTROL = 0;
24039 // Enable store and forward mode
24040 ETH0->OPERATION_MODE = MG_BIT(25) | MG_BIT(21); // RSF, TSF
24041 
24042 // Configure DMA bus mode (AAL, USP, RPBL, PBL)
24043 ETH0->BUS_MODE = MG_BIT(25) | MG_BIT(23) | (32 << 17) | (32 << 8);
24044 
24045 // init RX descriptors
24046 for (int i = 0; i < ETH_DESC_CNT; i++) {
24047 s_rxdesc[i][0] = MG_BIT(31); // OWN descriptor
24048 s_rxdesc[i][1] = MG_BIT(14) | ETH_PKT_SIZE;
24049 s_rxdesc[i][2] = (uint32_t) s_rxbuf[i];
24050 if (i == ETH_DESC_CNT - 1) {
24051 s_rxdesc[i][3] = (uint32_t) &s_rxdesc[0][0];
24052 } else {
24053 s_rxdesc[i][3] = (uint32_t) &s_rxdesc[i + 1][0];
24054 }
24055 }
24056 ETH0->RECEIVE_DESCRIPTOR_LIST_ADDRESS = (uint32_t) &s_rxdesc[0][0];
24057 
24058 // init TX descriptors
24059 for (int i = 0; i < ETH_DESC_CNT; i++) {
24060 s_txdesc[i][0] = MG_BIT(30) | MG_BIT(20);
24061 s_txdesc[i][2] = (uint32_t) s_txbuf[i];
24062 if (i == ETH_DESC_CNT - 1) {
24063 s_txdesc[i][3] = (uint32_t) &s_txdesc[0][0];
24064 } else {
24065 s_txdesc[i][3] = (uint32_t) &s_txdesc[i + 1][0];
24066 }
24067 }
24068 ETH0->TRANSMIT_DESCRIPTOR_LIST_ADDRESS = (uint32_t) &s_txdesc[0][0];
24069 
24070 // Clear interrupts
24071 ETH0->STATUS = 0xFFFFFFFF;
24072 
24073 // Disable MAC interrupts
24074 ETH0->MMC_TRANSMIT_INTERRUPT_MASK = 0xFFFFFFFF;
24075 ETH0->MMC_RECEIVE_INTERRUPT_MASK = 0xFFFFFFFF;
24076 ETH0->MMC_IPC_RECEIVE_INTERRUPT_MASK = 0xFFFFFFFF;
24077 ETH0->INTERRUPT_MASK = MG_BIT(9) | MG_BIT(3); // TSIM, PMTIM
24078 
24079 // Enable interrupts (NIE, RIE, TIE)
24080 ETH0->INTERRUPT_ENABLE = MG_BIT(16) | MG_BIT(6) | MG_BIT(0);
24081 
24082 // Enable MAC transmission and reception (TE, RE)
24083 ETH0->MAC_CONFIGURATION |= MG_BIT(3) | MG_BIT(2);
24084 // Enable DMA transmission and reception (ST, SR)
24085 ETH0->OPERATION_MODE |= MG_BIT(13) | MG_BIT(1);
24086 return true;
24087}
24088 
24089static size_t mg_tcpip_driver_xmc_tx(const void *buf, size_t len,
24090 struct mg_tcpip_if *ifp) {
24091 if (len > sizeof(s_txbuf[s_txno])) {
24092 MG_ERROR(("Frame too big, %ld", (long) len));
24093 len = 0; // Frame is too big
24094 } else if ((s_txdesc[s_txno][0] & MG_BIT(31))) {
24095 ifp->nerr++;
24096 MG_ERROR(("No free descriptors"));
24097 len = 0; // All descriptors are busy, fail
24098 } else {
24099 memcpy(s_txbuf[s_txno], buf, len);
24100 s_txdesc[s_txno][1] = len;
24101 // Table 13-19 Transmit Descriptor Word 0 (IC, LS, FS, TCH)
24102 s_txdesc[s_txno][0] = MG_BIT(30) | MG_BIT(29) | MG_BIT(28) | MG_BIT(20);
24103 s_txdesc[s_txno][0] |= MG_BIT(31); // OWN bit: handle control to DMA
24104 if (++s_txno >= ETH_DESC_CNT) s_txno = 0;
24105 }
24106 
24107 // Resume processing
24108 ETH0->STATUS = MG_BIT(2); // clear Transmit unavailable
24109 ETH0->TRANSMIT_POLL_DEMAND = 0;
24110 return len;
24111}
24112 
24113static void mg_tcpip_driver_xmc_update_hash_table(struct mg_tcpip_if *ifp) {
24114 // TODO(): read database, rebuild hash table
24115 // set the multicast address filter
24116 ETH0->MAC_ADDRESS1_HIGH =
24117 MG_U32(0, 0, mcast_addr[5], mcast_addr[4]) | MG_BIT(31);
24118 ETH0->MAC_ADDRESS1_LOW =
24119 MG_U32(mcast_addr[3], mcast_addr[2], mcast_addr[1], mcast_addr[0]);
24120 (void) ifp;
24121}
24122 
24123static bool mg_tcpip_driver_xmc_poll(struct mg_tcpip_if *ifp, bool s1) {
24124 if (ifp->update_mac_hash_table) {
24125 mg_tcpip_driver_xmc_update_hash_table(ifp);
24126 ifp->update_mac_hash_table = false;
24127 }
24128 if (!s1) return false;
24129 struct mg_tcpip_driver_xmc_data *d =
24130 (struct mg_tcpip_driver_xmc_data *) ifp->driver_data;
24131 uint8_t speed = MG_PHY_SPEED_10M;
24132 bool up = false, full_duplex = false;
24133 struct mg_phy phy = {eth_read_phy, eth_write_phy};
24134 up = mg_phy_up(&phy, d->phy_addr, &full_duplex, &speed);
24135 if ((ifp->state == MG_TCPIP_STATE_DOWN) && up) { // link state just went up
24136 MG_DEBUG(("Link is %uM %s-duplex", speed == MG_PHY_SPEED_10M ? 10 : 100,
24137 full_duplex ? "full" : "half"));
24138 }
24139 return up;
24140}
24141 
24142void ETH0_0_IRQHandler(void);
24143void ETH0_0_IRQHandler(void) {
24144 uint32_t irq_status = ETH0->STATUS;
24145 
24146 // check if a frame was received
24147 if (irq_status & MG_BIT(6)) {
24148 for (uint8_t i = 0; i < 10; i++) { // read as they arrive, but not forever
24149 if (s_rxdesc[s_rxno][0] & MG_BIT(31)) break;
24150 size_t len = (s_rxdesc[s_rxno][0] & 0x3fff0000) >> 16;
24151 mg_tcpip_qwrite(s_rxbuf[s_rxno], len, s_ifp);
24152 s_rxdesc[s_rxno][0] = MG_BIT(31); // OWN bit: handle control to DMA
24153 // Resume processing
24154 ETH0->STATUS = MG_BIT(7) | MG_BIT(6); // clear RU and RI
24155 ETH0->RECEIVE_POLL_DEMAND = 0;
24156 if (++s_rxno >= ETH_DESC_CNT) s_rxno = 0;
24157 }
24158 ETH0->STATUS = MG_BIT(6);
24159 }
24160 
24161 // clear Successful transmission interrupt
24162 if (irq_status & 1) {
24163 ETH0->STATUS = 1;
24164 }
24165 
24166 // clear normal interrupt
24167 if (irq_status & MG_BIT(16)) {
24168 ETH0->STATUS = MG_BIT(16);
24169 }
24170}
24171 
24172struct mg_tcpip_driver mg_tcpip_driver_xmc = {mg_tcpip_driver_xmc_init,
24173 mg_tcpip_driver_xmc_tx, NULL,
24174 mg_tcpip_driver_xmc_poll};
24175#endif
24176 
24177#ifdef MG_ENABLE_LINES
24178#line 1 "src/drivers/xmc7.c"
24179#endif
24180 
24181 
24182#if MG_ENABLE_TCPIP && defined(MG_ENABLE_DRIVER_XMC7) && MG_ENABLE_DRIVER_XMC7
24183 
24184struct ETH_Type {
24185 volatile uint32_t CTL, STATUS, RESERVED[1022], NETWORK_CONTROL,
24186 NETWORK_CONFIG, NETWORK_STATUS, USER_IO_REGISTER, DMA_CONFIG,
24187 TRANSMIT_STATUS, RECEIVE_Q_PTR, TRANSMIT_Q_PTR, RECEIVE_STATUS,
24188 INT_STATUS, INT_ENABLE, INT_DISABLE, INT_MASK, PHY_MANAGEMENT, PAUSE_TIME,
24189 TX_PAUSE_QUANTUM, PBUF_TXCUTTHRU, PBUF_RXCUTTHRU, JUMBO_MAX_LENGTH,
24190 EXTERNAL_FIFO_INTERFACE, RESERVED1, AXI_MAX_PIPELINE, RSC_CONTROL,
24191 INT_MODERATION, SYS_WAKE_TIME, RESERVED2[7], HASH_BOTTOM, HASH_TOP,
24192 SPEC_ADD1_BOTTOM, SPEC_ADD1_TOP, SPEC_ADD2_BOTTOM, SPEC_ADD2_TOP,
24193 SPEC_ADD3_BOTTOM, SPEC_ADD3_TOP, SPEC_ADD4_BOTTOM, SPEC_ADD4_TOP,
24194 SPEC_TYPE1, SPEC_TYPE2, SPEC_TYPE3, SPEC_TYPE4, WOL_REGISTER,
24195 STRETCH_RATIO, STACKED_VLAN, TX_PFC_PAUSE, MASK_ADD1_BOTTOM,
24196 MASK_ADD1_TOP, DMA_ADDR_OR_MASK, RX_PTP_UNICAST, TX_PTP_UNICAST,
24197 TSU_NSEC_CMP, TSU_SEC_CMP, TSU_MSB_SEC_CMP, TSU_PTP_TX_MSB_SEC,
24198 TSU_PTP_RX_MSB_SEC, TSU_PEER_TX_MSB_SEC, TSU_PEER_RX_MSB_SEC,
24199 DPRAM_FILL_DBG, REVISION_REG, OCTETS_TXED_BOTTOM, OCTETS_TXED_TOP,
24200 FRAMES_TXED_OK, BROADCAST_TXED, MULTICAST_TXED, PAUSE_FRAMES_TXED,
24201 FRAMES_TXED_64, FRAMES_TXED_65, FRAMES_TXED_128, FRAMES_TXED_256,
24202 FRAMES_TXED_512, FRAMES_TXED_1024, FRAMES_TXED_1519, TX_UNDERRUNS,
24203 SINGLE_COLLISIONS, MULTIPLE_COLLISIONS, EXCESSIVE_COLLISIONS,
24204 LATE_COLLISIONS, DEFERRED_FRAMES, CRS_ERRORS, OCTETS_RXED_BOTTOM,
24205 OCTETS_RXED_TOP, FRAMES_RXED_OK, BROADCAST_RXED, MULTICAST_RXED,
24206 PAUSE_FRAMES_RXED, FRAMES_RXED_64, FRAMES_RXED_65, FRAMES_RXED_128,
24207 FRAMES_RXED_256, FRAMES_RXED_512, FRAMES_RXED_1024, FRAMES_RXED_1519,
24208 UNDERSIZE_FRAMES, EXCESSIVE_RX_LENGTH, RX_JABBERS, FCS_ERRORS,
24209 RX_LENGTH_ERRORS, RX_SYMBOL_ERRORS, ALIGNMENT_ERRORS, RX_RESOURCE_ERRORS,
24210 RX_OVERRUNS, RX_IP_CK_ERRORS, RX_TCP_CK_ERRORS, RX_UDP_CK_ERRORS,
24211 AUTO_FLUSHED_PKTS, RESERVED3, TSU_TIMER_INCR_SUB_NSEC, TSU_TIMER_MSB_SEC,
24212 TSU_STROBE_MSB_SEC, TSU_STROBE_SEC, TSU_STROBE_NSEC, TSU_TIMER_SEC,
24213 TSU_TIMER_NSEC, TSU_TIMER_ADJUST, TSU_TIMER_INCR, TSU_PTP_TX_SEC,
24214 TSU_PTP_TX_NSEC, TSU_PTP_RX_SEC, TSU_PTP_RX_NSEC, TSU_PEER_TX_SEC,
24215 TSU_PEER_TX_NSEC, TSU_PEER_RX_SEC, TSU_PEER_RX_NSEC, PCS_CONTROL,
24216 PCS_STATUS, RESERVED4[2], PCS_AN_ADV, PCS_AN_LP_BASE, PCS_AN_EXP,
24217 PCS_AN_NP_TX, PCS_AN_LP_NP, RESERVED5[6], PCS_AN_EXT_STATUS, RESERVED6[8],
24218 TX_PAUSE_QUANTUM1, TX_PAUSE_QUANTUM2, TX_PAUSE_QUANTUM3, RESERVED7,
24219 RX_LPI, RX_LPI_TIME, TX_LPI, TX_LPI_TIME, DESIGNCFG_DEBUG1,
24220 DESIGNCFG_DEBUG2, DESIGNCFG_DEBUG3, DESIGNCFG_DEBUG4, DESIGNCFG_DEBUG5,
24221 DESIGNCFG_DEBUG6, DESIGNCFG_DEBUG7, DESIGNCFG_DEBUG8, DESIGNCFG_DEBUG9,
24222 DESIGNCFG_DEBUG10, RESERVED8[22], SPEC_ADD5_BOTTOM, SPEC_ADD5_TOP,
24223 RESERVED9[60], SPEC_ADD36_BOTTOM, SPEC_ADD36_TOP, INT_Q1_STATUS,
24224 INT_Q2_STATUS, INT_Q3_STATUS, RESERVED10[11], INT_Q15_STATUS, RESERVED11,
24225 TRANSMIT_Q1_PTR, TRANSMIT_Q2_PTR, TRANSMIT_Q3_PTR, RESERVED12[11],
24226 TRANSMIT_Q15_PTR, RESERVED13, RECEIVE_Q1_PTR, RECEIVE_Q2_PTR,
24227 RECEIVE_Q3_PTR, RESERVED14[3], RECEIVE_Q7_PTR, RESERVED15,
24228 DMA_RXBUF_SIZE_Q1, DMA_RXBUF_SIZE_Q2, DMA_RXBUF_SIZE_Q3, RESERVED16[3],
24229 DMA_RXBUF_SIZE_Q7, CBS_CONTROL, CBS_IDLESLOPE_Q_A, CBS_IDLESLOPE_Q_B,
24230 UPPER_TX_Q_BASE_ADDR, TX_BD_CONTROL, RX_BD_CONTROL, UPPER_RX_Q_BASE_ADDR,
24231 RESERVED17[2], HIDDEN_REG0, HIDDEN_REG1, HIDDEN_REG2, HIDDEN_REG3,
24232 RESERVED18[2], HIDDEN_REG4, HIDDEN_REG5;
24233};
24234 
24235#define ETH0 ((struct ETH_Type *) 0x40490000)
24236 
24237#define ETH_PKT_SIZE 1536 // Max frame size
24238#define ETH_DESC_CNT 4 // Descriptors count
24239#define ETH_DS 2 // Descriptor size (words)
24240 
24241// TODO(): handle these in a portable compiler-independent CMSIS-friendly way
24242#define MG_8BYTE_ALIGNED __attribute__((aligned((8U))))
24243 
24244static uint8_t s_rxbuf[ETH_DESC_CNT][ETH_PKT_SIZE];
24245static uint8_t s_txbuf[ETH_DESC_CNT][ETH_PKT_SIZE];
24246static uint32_t s_rxdesc[ETH_DESC_CNT][ETH_DS] MG_8BYTE_ALIGNED;
24247static uint32_t s_txdesc[ETH_DESC_CNT][ETH_DS] MG_8BYTE_ALIGNED;
24248static uint8_t s_txno MG_8BYTE_ALIGNED; // Current TX descriptor
24249static uint8_t s_rxno MG_8BYTE_ALIGNED; // Current RX descriptor
24250 
24251static struct mg_tcpip_if *s_ifp; // MIP interface
24252enum { MG_PHY_ADDR = 0, MG_PHYREG_BCR = 0, MG_PHYREG_BSR = 1 };
24253 
24254static uint16_t eth_read_phy(uint8_t addr, uint8_t reg) {
24255 // WRITE1, READ OPERATION, PHY, REG, WRITE10
24256 ETH0->PHY_MANAGEMENT = MG_BIT(30) | MG_BIT(29) | ((addr & 0xf) << 24) |
24257 ((reg & 0x1f) << 18) | MG_BIT(17);
24258 while ((ETH0->NETWORK_STATUS & MG_BIT(2)) == 0) (void) 0;
24259 return ETH0->PHY_MANAGEMENT & 0xffff;
24260}
24261 
24262static void eth_write_phy(uint8_t addr, uint8_t reg, uint16_t val) {
24263 ETH0->PHY_MANAGEMENT = MG_BIT(30) | MG_BIT(28) | ((addr & 0xf) << 24) |
24264 ((reg & 0x1f) << 18) | MG_BIT(17) | val;
24265 while ((ETH0->NETWORK_STATUS & MG_BIT(2)) == 0) (void) 0;
24266}
24267 
24268static uint32_t get_clock_rate(struct mg_tcpip_driver_xmc7_data *d) {
24269 // see ETH0 -> NETWORK_CONFIG register
24270 (void) d;
24271 return 3;
24272}
24273 
24274static bool mg_tcpip_driver_xmc7_init(struct mg_tcpip_if *ifp) {
24275 struct mg_tcpip_driver_xmc7_data *d =
24276 (struct mg_tcpip_driver_xmc7_data *) ifp->driver_data;
24277 s_ifp = ifp;
24278 
24279 // enable controller, set RGMII mode
24280 ETH0->CTL = MG_BIT(31) | (4 << 8) | 2;
24281 
24282 uint32_t cr = get_clock_rate(d);
24283 // set NSP change, ignore RX FCS, data bus width, clock rate
24284 // frame length 1536, full duplex, speed
24285 ETH0->NETWORK_CONFIG = MG_BIT(29) | MG_BIT(26) | MG_BIT(21) |
24286 ((cr & 7) << 18) | MG_BIT(8) | MG_BIT(1) | MG_BIT(0);
24287 
24288 // config DMA settings: Force TX burst, Discard on Error, set RX buffer size
24289 // to 1536, TX_PBUF_SIZE, RX_PBUF_SIZE, AMBA_BURST_LENGTH
24290 ETH0->DMA_CONFIG =
24291 MG_BIT(26) | MG_BIT(24) | (0x18 << 16) | MG_BIT(10) | (3 << 8) | 4;
24292 
24293 // initialize descriptors
24294 for (int i = 0; i < ETH_DESC_CNT; i++) {
24295 s_rxdesc[i][0] = (uint32_t) s_rxbuf[i];
24296 if (i == ETH_DESC_CNT - 1) {
24297 s_rxdesc[i][0] |= MG_BIT(1); // mark last descriptor
24298 }
24299 
24300 s_txdesc[i][0] = (uint32_t) s_txbuf[i];
24301 s_txdesc[i][1] = MG_BIT(31); // OWN descriptor
24302 if (i == ETH_DESC_CNT - 1) {
24303 s_txdesc[i][1] |= MG_BIT(30); // mark last descriptor
24304 }
24305 }
24306 ETH0->RECEIVE_Q_PTR = (uint32_t) s_rxdesc;
24307 ETH0->TRANSMIT_Q_PTR = (uint32_t) s_txdesc;
24308 
24309 // disable other queues
24310 ETH0->TRANSMIT_Q2_PTR = 1;
24311 ETH0->TRANSMIT_Q1_PTR = 1;
24312 ETH0->RECEIVE_Q2_PTR = 1;
24313 ETH0->RECEIVE_Q1_PTR = 1;
24314 
24315 // enable interrupts (RX complete)
24316 ETH0->INT_ENABLE = MG_BIT(1);
24317 
24318 // set MAC address
24319 ETH0->SPEC_ADD1_BOTTOM =
24320 ifp->mac[3] << 24 | ifp->mac[2] << 16 | ifp->mac[1] << 8 | ifp->mac[0];
24321 ETH0->SPEC_ADD1_TOP = ifp->mac[5] << 8 | ifp->mac[4];
24322 
24323 // enable MDIO, TX, RX
24324 ETH0->NETWORK_CONTROL = MG_BIT(4) | MG_BIT(3) | MG_BIT(2);
24325 
24326 // start transmission
24327 ETH0->NETWORK_CONTROL |= MG_BIT(9);
24328 
24329 // init phy
24330 struct mg_phy phy = {eth_read_phy, eth_write_phy};
24331 mg_phy_init(&phy, d->phy_addr, MG_PHY_CLOCKS_MAC);
24332 
24333 (void) d;
24334 return true;
24335}
24336 
24337static size_t mg_tcpip_driver_xmc7_tx(const void *buf, size_t len,
24338 struct mg_tcpip_if *ifp) {
24339 if (len > sizeof(s_txbuf[s_txno])) {
24340 MG_ERROR(("Frame too big, %ld", (long) len));
24341 len = 0; // Frame is too big
24342 } else if (((s_txdesc[s_txno][1] & MG_BIT(31)) == 0)) {
24343 ifp->nerr++;
24344 MG_ERROR(("No free descriptors"));
24345 len = 0; // All descriptors are busy, fail
24346 } else {
24347 memcpy(s_txbuf[s_txno], buf, len);
24348 s_txdesc[s_txno][1] = (s_txno == ETH_DESC_CNT - 1 ? MG_BIT(30) : 0) |
24349 MG_BIT(15) | len; // Last buffer and length
24350 
24351 ETH0->NETWORK_CONTROL |= MG_BIT(9); // enable transmission
24352 if (++s_txno >= ETH_DESC_CNT) s_txno = 0;
24353 }
24354 
24355 MG_DSB();
24356 ETH0->TRANSMIT_STATUS = ETH0->TRANSMIT_STATUS;
24357 ETH0->NETWORK_CONTROL |= MG_BIT(9); // enable transmission
24358 
24359 return len;
24360}
24361 
24362static void mg_tcpip_driver_xmc7_update_hash_table(struct mg_tcpip_if *ifp) {
24363 // TODO(): read database, rebuild hash table
24364 // set multicast MAC address
24365 ETH0->SPEC_ADD2_BOTTOM = mcast_addr[3] << 24 | mcast_addr[2] << 16 |
24366 mcast_addr[1] << 8 | mcast_addr[0];
24367 ETH0->SPEC_ADD2_TOP = mcast_addr[5] << 8 | mcast_addr[4];
24368 (void) ifp;
24369}
24370 
24371static bool mg_tcpip_driver_xmc7_poll(struct mg_tcpip_if *ifp, bool s1) {
24372 if (ifp->update_mac_hash_table) {
24373 mg_tcpip_driver_xmc7_update_hash_table(ifp);
24374 ifp->update_mac_hash_table = false;
24375 }
24376 if (!s1) return false;
24377 struct mg_tcpip_driver_xmc7_data *d =
24378 (struct mg_tcpip_driver_xmc7_data *) ifp->driver_data;
24379 uint8_t speed = MG_PHY_SPEED_10M;
24380 bool up = false, full_duplex = false;
24381 struct mg_phy phy = {eth_read_phy, eth_write_phy};
24382 up = mg_phy_up(&phy, d->phy_addr, &full_duplex, &speed);
24383 if ((ifp->state == MG_TCPIP_STATE_DOWN) && up) { // link state just went up
24384 // tmp = reg with flags set to the most likely situation: 100M full-duplex
24385 // if(link is slow or half) set flags otherwise
24386 // reg = tmp
24387 uint32_t netconf = ETH0->NETWORK_CONFIG;
24388 MG_SET_BITS(netconf, MG_BIT(10),
24389 MG_BIT(1) | MG_BIT(0)); // 100M, Full-duplex
24390 uint32_t ctl = ETH0->CTL;
24391 MG_SET_BITS(ctl, 0xFF00, 4 << 8); // /5 for 25M clock
24392 if (speed == MG_PHY_SPEED_1000M) {
24393 netconf |= MG_BIT(10); // 1000M
24394 MG_SET_BITS(ctl, 0xFF00, 0); // /1 for 125M clock TODO() IS THIS NEEDED ?
24395 } else if (speed == MG_PHY_SPEED_10M) {
24396 netconf &= ~MG_BIT(0); // 10M
24397 MG_SET_BITS(ctl, 0xFF00, 49); // /50 for 2.5M clock
24398 }
24399 if (full_duplex == false) netconf &= ~MG_BIT(1); // Half-duplex
24400 ETH0->NETWORK_CONFIG = netconf; // IRQ handler does not fiddle with these
24401 ETH0->CTL = ctl;
24402 MG_DEBUG(("Link is %uM %s-duplex",
24403 speed == MG_PHY_SPEED_10M
24404 ? 10
24405 : (speed == MG_PHY_SPEED_100M ? 100 : 1000),
24406 full_duplex ? "full" : "half"));
24407 }
24408 return up;
24409}
24410 
24411void ETH_IRQHandler(void) {
24412 uint32_t irq_status = ETH0->INT_STATUS;
24413 if (irq_status & MG_BIT(1)) {
24414 for (uint8_t i = 0; i < 10; i++) { // read as they arrive, but not forever
24415 if ((s_rxdesc[s_rxno][0] & MG_BIT(0)) == 0) break;
24416 size_t len = s_rxdesc[s_rxno][1] & (MG_BIT(13) - 1);
24417 mg_tcpip_qwrite(s_rxbuf[s_rxno], len, s_ifp);
24418 s_rxdesc[s_rxno][0] &= ~MG_BIT(0); // OWN bit: handle control to DMA
24419 if (++s_rxno >= ETH_DESC_CNT) s_rxno = 0;
24420 }
24421 }
24422 
24423 ETH0->INT_STATUS = irq_status;
24424}
24425 
24426struct mg_tcpip_driver mg_tcpip_driver_xmc7 = {mg_tcpip_driver_xmc7_init,
24427 mg_tcpip_driver_xmc7_tx, NULL,
24428 mg_tcpip_driver_xmc7_poll};
24429#endif
24430