From f2ce01641e57b643ed9fc3243e88b305000c4af6 Mon Sep 17 00:00:00 2001 From: cpq Date: Wed, 28 Jan 2026 16:04:04 +0000 Subject: [PATCH] Make built-in TLS vc98-friendly --- mongoose.c | 189 +++++++++++++++++++++++----------------------- src/tls_builtin.c | 143 ++++++++++++++++++----------------- 2 files changed, 168 insertions(+), 164 deletions(-) diff --git a/mongoose.c b/mongoose.c index 78425b96..6633c011 100644 --- a/mongoose.c +++ b/mongoose.c @@ -6341,7 +6341,7 @@ static void handle_opt(struct connstate *s, struct tcp *tcp, bool ip6) { static void rx_tcp(struct mg_tcpip_if *ifp, struct pkt *pkt) { struct mg_connection *c = getpeer(ifp->mgr, pkt, false); struct connstate *s = c == NULL ? NULL : (struct connstate *) (c + 1); -#if MG_ENABLE_IPV6 // matching of v4/v6 to dest is done bt getpeer() +#if MG_ENABLE_IPV6 // matching of v4/v6 to dest is done by getpeer() if (pkt->ip6 != NULL && !tcp6csum_ok(pkt->ip6, pkt->tcp)) return; #endif if (pkt->ip != NULL && !tcpcsum_ok(pkt->ip, pkt->tcp)) return; @@ -13299,21 +13299,22 @@ static bool mg_tls_send_cert(struct mg_connection *c, bool is_client) { struct tls_data *tls = (struct tls_data *) c->tls; int send_ca = !is_client && tls->ca_der.len > 0; // DER certificate + CA (server optional) - size_t total_size = tls->cert_der.len + 5; - for (size_t i = 1; i < tls->chain_len; i++) { + size_t i, offset, total_size = tls->cert_der.len + 5; + uint8_t *cert; + bool res = false; + for (i = 1; i < tls->chain_len; i++) { total_size += tls->chain_der[i].len + 5; } if (send_ca) { total_size += tls->ca_der.len + 5; } - uint8_t *cert = (uint8_t *) mg_calloc(1, 13 + total_size); - bool res; - if (cert == NULL) return false; + cert = (uint8_t *) mg_calloc(1, 13 + total_size); + if (cert == NULL) return res; cert[0] = MG_TLS_CERTIFICATE; // handshake header MG_STORE_BE24(cert + 1, total_size + 4); cert[4] = 0; // request context MG_STORE_BE24(cert + 5, total_size); // 3 bytes: cert (s) length - size_t offset = 8; + offset = 8; MG_STORE_BE24(cert + offset, tls->cert_der.len); // 3 bytes: first cert len offset += 3; // bytes 11+ are certificate in DER format @@ -13321,7 +13322,7 @@ static bool mg_tls_send_cert(struct mg_connection *c, bool is_client) { offset += tls->cert_der.len; MG_STORE_BE16(cert + offset, 0); // certificate extensions (none) offset += 2; - for (size_t i = 1; i < tls->chain_len; i++) { + for (i = 1; i < tls->chain_len; i++) { MG_STORE_BE24(cert + offset, tls->chain_der[i].len); offset += 3; memmove(cert + offset, tls->chain_der[i].buf, tls->chain_der[i].len); @@ -13369,7 +13370,7 @@ static void finish_SHA256(const MG_UECC_HashContext *base, static void mg_tls_mgf1(uint8_t *mask, size_t mask_len, const uint8_t *seed, size_t seed_len) { uint32_t counter = 0; - size_t generated = 0; + size_t chunk, chunk_len, generated = 0; while (generated < mask_len) { mg_sha256_ctx ctx; uint8_t digest[32]; @@ -13382,8 +13383,8 @@ static void mg_tls_mgf1(uint8_t *mask, size_t mask_len, const uint8_t *seed, mg_sha256_update(&ctx, seed, seed_len); mg_sha256_update(&ctx, ctr, sizeof(ctr)); mg_sha256_final(digest, &ctx); - size_t chunk_len = mask_len - generated; - size_t chunk = (chunk_len < sizeof(digest) ? chunk_len : sizeof(digest)); + chunk_len = mask_len - generated; + chunk = (chunk_len < sizeof(digest) ? chunk_len : sizeof(digest)); memmove(mask + generated, digest, chunk); generated += chunk; counter++; @@ -13408,10 +13409,7 @@ static unsigned int mg_tls_rsa_bits(const struct mg_str *n) { static bool mg_tls_pss_encode(const uint8_t *hash, size_t hashlen, const struct mg_str *n, uint8_t *em) { - size_t emlen = n->len; - size_t saltlen = hashlen; - size_t dblen; - size_t pslen; + size_t emlen = n->len, saltlen = hashlen, dblen, pslen, i; uint8_t salt[64]; // Max salt size for any reasonable hash uint8_t m[136]; // 8 + max hash (64) + max salt (64) = 136 uint8_t H[64]; // Max hash size @@ -13452,7 +13450,7 @@ static bool mg_tls_pss_encode(const uint8_t *hash, size_t hashlen, // Generate mask and apply to DB mg_tls_mgf1(mask, dblen, H, hashlen); - for (size_t i = 0; i < dblen; i++) DB[i] ^= mask[i]; + for (i = 0; i < dblen; i++) DB[i] ^= mask[i]; { // PSS standard: emBits = modulus_bit_length - 1 @@ -13479,6 +13477,8 @@ static bool mg_tls_pss_encode(const uint8_t *hash, size_t hashlen, static bool mg_tls_rsa_sign(struct tls_data *tls, const uint8_t *em, size_t emlen, uint8_t *sig) { + size_t nlen; + int crt_result; #if MG_TLS_RSA_USE_CRT // RSA CRT (Chinese Remainder Theorem) optimization: // s1 = em^dP mod p @@ -13494,9 +13494,9 @@ static bool mg_tls_rsa_sign(struct tls_data *tls, const uint8_t *em, MG_VERBOSE(("Using RSA-CRT optimization")); - size_t nlen = tls->rsa.n.len; + nlen = tls->rsa.n.len; - int crt_result = mg_rsa_crt_sign( + crt_result = mg_rsa_crt_sign( em, emlen, (const uint8_t *) tls->rsa.dP.buf, tls->rsa.dP.len, (const uint8_t *) tls->rsa.dQ.buf, tls->rsa.dQ.len, (const uint8_t *) tls->rsa.p.buf, tls->rsa.p.len, @@ -13514,11 +13514,12 @@ static bool mg_tls_rsa_sign(struct tls_data *tls, const uint8_t *em, return false; } #else + int ret; // Standard RSA: s = em^d mod n memset(sig, 0, tls->rsa.n.len); - int ret = mg_rsa_mod_pow((const uint8_t *) tls->rsa.n.buf, tls->rsa.n.len, - (const uint8_t *) tls->rsa.d.buf, tls->rsa.d.len, em, - emlen, sig, tls->rsa.n.len); + ret = mg_rsa_mod_pow((const uint8_t *) tls->rsa.n.buf, tls->rsa.n.len, + (const uint8_t *) tls->rsa.d.buf, tls->rsa.d.len, em, + emlen, sig, tls->rsa.n.len); if (ret == 0) { MG_VERBOSE(("RSA signature first 4 bytes: %02x %02x %02x %02x", sig[0], sig[1], sig[2], sig[3])); @@ -14029,7 +14030,7 @@ static int mg_tls_verify_cert_san(const uint8_t *der, size_t dersz, if (mg_match(mg_str(server_name), mg_str_n((char *) name.value, name.len), NULL)) return 1; // and matches the host name - } // TODO(): add IPv6 comparison, more items ? + } // TODO(): add IPv6 comparison, more items ? } return -1; } @@ -14463,7 +14464,8 @@ void mg_tls_handshake(struct mg_connection *c) { static int mg_rsa_parse_der_int(const uint8_t **p, const uint8_t *end, struct mg_str *out) { - const uint8_t *start = *p; + const uint8_t *start = *p, *value_start, *value_end; + uint8_t i; uint32_t len; if (end - start < 2) { @@ -14487,7 +14489,7 @@ static int mg_rsa_parse_der_int(const uint8_t **p, const uint8_t *end, return -1; } len = 0; - for (uint8_t i = 0; i < len_bytes; i++) { + for (i = 0; i < len_bytes; i++) { len = (len << 8) | (*p)[i]; } *p += len_bytes; @@ -14501,8 +14503,8 @@ static int mg_rsa_parse_der_int(const uint8_t **p, const uint8_t *end, } // The encoded length tells us how many bytes to consume from the stream - const uint8_t *value_start = *p; - const uint8_t *value_end = *p + len; + value_start = *p; + value_end = *p + len; // Skip leading zero byte if present (for positive numbers) // This doesn't change how many bytes we consume, just what we expose @@ -14570,7 +14572,8 @@ static int mg_parse_ec_private_key(const uint8_t *der, size_t dersz, // exponent2 INTEGER, -- dQ = d mod (q-1) // coefficient INTEGER, -- qInv = (inverse of q) mod p // } -static int mg_rsa_parse_key(const uint8_t *der, size_t dersz, struct mg_rsa_key *key) { +static int mg_rsa_parse_key(const uint8_t *der, size_t dersz, + struct mg_rsa_key *key) { const uint8_t *p = der; const uint8_t *end = der + dersz; uint32_t seq_len; @@ -14600,14 +14603,14 @@ static int mg_rsa_parse_key(const uint8_t *der, size_t dersz, struct mg_rsa_key if (seq_len > 0x7F) { // Long form length - uint8_t len_bytes = seq_len & 0x7F; + uint8_t i, len_bytes = seq_len & 0x7F; MG_VERBOSE(("Long form length: %d bytes", len_bytes)); if (end - p < len_bytes) { MG_ERROR(("Not enough bytes for long form length")); return -1; } seq_len = 0; - for (uint8_t i = 0; i < len_bytes; i++) { + for (i = 0; i < len_bytes; i++) { seq_len = (seq_len << 8) | p[i]; } p += len_bytes; @@ -14624,7 +14627,7 @@ static int mg_rsa_parse_key(const uint8_t *der, size_t dersz, struct mg_rsa_key // Parse version (should be 0) MG_VERBOSE(("Before version: offset=%d, bytes: %02x %02x %02x %02x", - (int) (p - der), p[0], p[1], p[2], p[3])); + (int) (p - der), p[0], p[1], p[2], p[3])); if (mg_rsa_parse_der_int(&p, end, &version) < 0) { MG_ERROR(("Failed to parse version")); return -1; @@ -14635,22 +14638,22 @@ static int mg_rsa_parse_key(const uint8_t *der, size_t dersz, struct mg_rsa_key // Parse the 8 components: n, e, d, p, q, dP, dQ, qInv MG_VERBOSE(("Before n: offset=%d, bytes: %02x %02x %02x %02x %02x %02x", - (int) (p - der), p[0], p[1], p[2], p[3], p[4], p[5])); + (int) (p - der), p[0], p[1], p[2], p[3], p[4], p[5])); if (mg_rsa_parse_der_int(&p, end, &key->n) < 0) { MG_ERROR(("Failed to parse n (modulus)")); return -1; } MG_VERBOSE(("Parsed n: %d bytes, offset now=%d, consumed=%d bytes total", - (int) key->n.len, (int) (p - der), (int) (p - der))); + (int) key->n.len, (int) (p - der), (int) (p - der))); MG_VERBOSE((" First 8 bytes of n: %02x %02x %02x %02x %02x %02x %02x %02x", - (unsigned char) key->n.buf[0], (unsigned char) key->n.buf[1], - (unsigned char) key->n.buf[2], (unsigned char) key->n.buf[3], - (unsigned char) key->n.buf[4], (unsigned char) key->n.buf[5], - (unsigned char) key->n.buf[6], (unsigned char) key->n.buf[7])); + (unsigned char) key->n.buf[0], (unsigned char) key->n.buf[1], + (unsigned char) key->n.buf[2], (unsigned char) key->n.buf[3], + (unsigned char) key->n.buf[4], (unsigned char) key->n.buf[5], + (unsigned char) key->n.buf[6], (unsigned char) key->n.buf[7])); MG_VERBOSE((" Next bytes after n: %02x %02x %02x %02x %02x %02x", - p < end ? p[0] : 0xFF, p + 1 < end ? p[1] : 0xFF, - p + 2 < end ? p[2] : 0xFF, p + 3 < end ? p[3] : 0xFF, - p + 4 < end ? p[4] : 0xFF, p + 5 < end ? p[5] : 0xFF)); + p < end ? p[0] : 0xFF, p + 1 < end ? p[1] : 0xFF, + p + 2 < end ? p[2] : 0xFF, p + 3 < end ? p[3] : 0xFF, + p + 4 < end ? p[4] : 0xFF, p + 5 < end ? p[5] : 0xFF)); if (mg_rsa_parse_der_int(&p, end, &key->e) < 0) { MG_ERROR(("Failed to parse e (public exponent), bytes remaining: %d", @@ -14809,8 +14812,11 @@ static int mg_parse_pem_certs(const struct mg_str pem, struct mg_str **ders) { size_t end_len = strlen(end_marker); while (p < end) { - const char *begin = NULL; - for (const char *s = p; s <= end - (int) begin_len; s++) { + const char *s, *begin = NULL, *finish = NULL; + struct mg_str cert_pem, cert_der, *new_certs; + int i; + + for (s = p; s <= end - (int) begin_len; s++) { if (memcmp(s, begin_marker, begin_len) == 0) { begin = s; break; @@ -14818,33 +14824,30 @@ static int mg_parse_pem_certs(const struct mg_str pem, struct mg_str **ders) { } if (begin == NULL) break; - const char *finish = NULL; - for (const char *s = begin + begin_len; s <= end - (int) end_len; s++) { + for (s = begin + begin_len; s <= end - (int) end_len; s++) { if (memcmp(s, end_marker, end_len) == 0) { finish = s + end_len; break; } } if (finish == NULL) { - for (int i = 0; i < count; i++) mg_free((void *) certs[i].buf); + for (i = 0; i < count; i++) mg_free((void *) certs[i].buf); mg_free(certs); return -1; } - struct mg_str cert_pem = mg_str_n(begin, (size_t) (finish - begin)); - struct mg_str cert_der; - + cert_pem = mg_str_n(begin, (size_t) (finish - begin)); if (mg_parse_pem(cert_pem, mg_str_s("CERTIFICATE"), &cert_der) < 0) { - for (int i = 0; i < count; i++) mg_free((void *) certs[i].buf); + for (i = 0; i < count; i++) mg_free((void *) certs[i].buf); mg_free(certs); return -1; } - struct mg_str *new_certs = - (struct mg_str *) mg_calloc((size_t) count + 1, sizeof(struct mg_str)); + new_certs = + (struct mg_str *) mg_calloc((size_t) count + 1, sizeof(*new_certs)); if (new_certs == NULL) { mg_free((void *) cert_der.buf); - for (int i = 0; i < count; i++) mg_free((void *) certs[i].buf); + for (i = 0; i < count; i++) mg_free((void *) certs[i].buf); mg_free(certs); return -1; } @@ -14905,22 +14908,25 @@ void mg_tls_init(struct mg_connection *c, const struct mg_tls_opts *opts) { } // parse PEM or DER certificate - struct mg_str *all_certs = NULL; - int cert_count = mg_parse_pem_certs(opts->cert, &all_certs); + { + struct mg_str *all_certs = NULL; + int cert_count = mg_parse_pem_certs(opts->cert, &all_certs); - if (cert_count > 0) { - tls->cert_der.buf = all_certs[0].buf; - tls->cert_der.len = all_certs[0].len; - if (cert_count > 1) { - tls->chain_len = (size_t) cert_count; - tls->chain_der = all_certs; + if (cert_count > 0) { + tls->cert_der.buf = all_certs[0].buf; + tls->cert_der.len = all_certs[0].len; + if (cert_count > 1) { + tls->chain_len = (size_t) cert_count; + tls->chain_der = all_certs; + } else { + mg_free(all_certs); + } } else { - mg_free(all_certs); - } - } else { - if (mg_parse_pem(opts->cert, mg_str_s("CERTIFICATE"), &tls->cert_der) < 0) { - MG_ERROR(("Failed to load certificate")); - return; + if (mg_parse_pem(opts->cert, mg_str_s("CERTIFICATE"), &tls->cert_der) < + 0) { + MG_ERROR(("Failed to load certificate")); + return; + } } } @@ -14947,13 +14953,13 @@ void mg_tls_init(struct mg_connection *c, const struct mg_tls_opts *opts) { memmove(tls->ec_key, key.buf + 7, 32); mg_free((void *) key.buf); } else if (mg_parse_pem(opts->key, mg_str_s("RSA PRIVATE KEY"), &key) == 0) { + struct mg_rsa_key rsa_key; // RSA private key found, store it for later use tls->rsa_key_der = key; MG_INFO(("Parsed RSA private key: %d bytes", (int) key.len)); // parse and validate the key structure // we keep the DER buffer, rsa_key just points into it - struct mg_rsa_key rsa_key; if (mg_rsa_parse_key((const uint8_t *) key.buf, key.len, &rsa_key) < 0) { MG_ERROR(("Failed to parse RSA private key structure")); mg_free((void *) key.buf); @@ -14996,10 +15002,11 @@ void mg_tls_init(struct mg_connection *c, const struct mg_tls_opts *opts) { void mg_tls_free(struct mg_connection *c) { struct tls_data *tls = (struct tls_data *) c->tls; + size_t i; if (tls != NULL) { mg_iobuf_free(&tls->send); if (tls->chain_der != NULL) { - for (size_t i = 0; i < tls->chain_len; i++) { + for (i = 0; i < tls->chain_len; i++) { mg_free((void *) tls->chain_der[i].buf); } mg_free(tls->chain_der); @@ -15023,7 +15030,7 @@ long mg_tls_send(struct mg_connection *c, const void *buf, size_t len) { if (!mg_tls_encrypt(c, (const uint8_t *) buf, len, MG_TLS_APP_DATA)) return 0; // returning 0 means an OOM condition (iobuf couldn't resize), // yet this is so far recoverable, let the caller decide - } // else, resend outstanding encrypted data in tls->send + } // else, resend outstanding encrypted data in tls->send while (tls->send.len > 0 && (n = mg_io_send(c, tls->send.buf, tls->send.len)) > 0) { mg_iobuf_del(&tls->send, 0, (size_t) n); @@ -15037,37 +15044,27 @@ long mg_tls_send(struct mg_connection *c, const void *buf, size_t len) { } long mg_tls_recv(struct mg_connection *c, void *buf, size_t len) { + int r = 0; struct tls_data *tls = (struct tls_data *) c->tls; - long res = 0; + unsigned char *recv_buf; + size_t minlen; - while (buf != NULL && len > 0) { - if (tls->recv_len == 0) { - int r = mg_tls_recv_record(c); - if (r < 0) { - if (res == 0) res = r; - break; - } - if (tls->content_type != MG_TLS_APP_DATA) { - tls->recv_len = 0; - mg_tls_drop_record(c); - continue; - } - } - { - uint8_t *recv_buf = &c->rtls.buf[tls->recv_offset]; - size_t n = len < tls->recv_len ? len : tls->recv_len; - memmove(buf, recv_buf, n); - tls->recv_offset += n; - tls->recv_len -= n; - res += (long) n; - buf = (char *) buf + n; - len -= n; - if (tls->recv_len == 0) { - mg_tls_drop_record(c); - } - } + for (;;) { + r = mg_tls_recv_record(c); + if (r < 0) return r; + if (tls->content_type == MG_TLS_APP_DATA) break; + tls->recv_len = 0; + mg_tls_drop_record(c); } - return res; + + if (buf == NULL || len == 0) return 0L; + recv_buf = &c->rtls.buf[tls->recv_offset]; + minlen = len < tls->recv_len ? len : tls->recv_len; + memmove(buf, recv_buf, minlen); + tls->recv_offset += minlen; + tls->recv_len -= minlen; + if (tls->recv_len == 0) mg_tls_drop_record(c); + return (long) minlen; } size_t mg_tls_pending(struct mg_connection *c) { diff --git a/src/tls_builtin.c b/src/tls_builtin.c index 86fc0bab..4b44dfa0 100644 --- a/src/tls_builtin.c +++ b/src/tls_builtin.c @@ -766,21 +766,22 @@ static bool mg_tls_send_cert(struct mg_connection *c, bool is_client) { struct tls_data *tls = (struct tls_data *) c->tls; int send_ca = !is_client && tls->ca_der.len > 0; // DER certificate + CA (server optional) - size_t total_size = tls->cert_der.len + 5; - for (size_t i = 1; i < tls->chain_len; i++) { + size_t i, offset, total_size = tls->cert_der.len + 5; + uint8_t *cert; + bool res = false; + for (i = 1; i < tls->chain_len; i++) { total_size += tls->chain_der[i].len + 5; } if (send_ca) { total_size += tls->ca_der.len + 5; } - uint8_t *cert = (uint8_t *) mg_calloc(1, 13 + total_size); - bool res; - if (cert == NULL) return false; + cert = (uint8_t *) mg_calloc(1, 13 + total_size); + if (cert == NULL) return res; cert[0] = MG_TLS_CERTIFICATE; // handshake header MG_STORE_BE24(cert + 1, total_size + 4); cert[4] = 0; // request context MG_STORE_BE24(cert + 5, total_size); // 3 bytes: cert (s) length - size_t offset = 8; + offset = 8; MG_STORE_BE24(cert + offset, tls->cert_der.len); // 3 bytes: first cert len offset += 3; // bytes 11+ are certificate in DER format @@ -788,7 +789,7 @@ static bool mg_tls_send_cert(struct mg_connection *c, bool is_client) { offset += tls->cert_der.len; MG_STORE_BE16(cert + offset, 0); // certificate extensions (none) offset += 2; - for (size_t i = 1; i < tls->chain_len; i++) { + for (i = 1; i < tls->chain_len; i++) { MG_STORE_BE24(cert + offset, tls->chain_der[i].len); offset += 3; memmove(cert + offset, tls->chain_der[i].buf, tls->chain_der[i].len); @@ -836,7 +837,7 @@ static void finish_SHA256(const MG_UECC_HashContext *base, static void mg_tls_mgf1(uint8_t *mask, size_t mask_len, const uint8_t *seed, size_t seed_len) { uint32_t counter = 0; - size_t generated = 0; + size_t chunk, chunk_len, generated = 0; while (generated < mask_len) { mg_sha256_ctx ctx; uint8_t digest[32]; @@ -849,8 +850,8 @@ static void mg_tls_mgf1(uint8_t *mask, size_t mask_len, const uint8_t *seed, mg_sha256_update(&ctx, seed, seed_len); mg_sha256_update(&ctx, ctr, sizeof(ctr)); mg_sha256_final(digest, &ctx); - size_t chunk_len = mask_len - generated; - size_t chunk = (chunk_len < sizeof(digest) ? chunk_len : sizeof(digest)); + chunk_len = mask_len - generated; + chunk = (chunk_len < sizeof(digest) ? chunk_len : sizeof(digest)); memmove(mask + generated, digest, chunk); generated += chunk; counter++; @@ -875,10 +876,7 @@ static unsigned int mg_tls_rsa_bits(const struct mg_str *n) { static bool mg_tls_pss_encode(const uint8_t *hash, size_t hashlen, const struct mg_str *n, uint8_t *em) { - size_t emlen = n->len; - size_t saltlen = hashlen; - size_t dblen; - size_t pslen; + size_t emlen = n->len, saltlen = hashlen, dblen, pslen, i; uint8_t salt[64]; // Max salt size for any reasonable hash uint8_t m[136]; // 8 + max hash (64) + max salt (64) = 136 uint8_t H[64]; // Max hash size @@ -919,7 +917,7 @@ static bool mg_tls_pss_encode(const uint8_t *hash, size_t hashlen, // Generate mask and apply to DB mg_tls_mgf1(mask, dblen, H, hashlen); - for (size_t i = 0; i < dblen; i++) DB[i] ^= mask[i]; + for (i = 0; i < dblen; i++) DB[i] ^= mask[i]; { // PSS standard: emBits = modulus_bit_length - 1 @@ -946,6 +944,8 @@ static bool mg_tls_pss_encode(const uint8_t *hash, size_t hashlen, static bool mg_tls_rsa_sign(struct tls_data *tls, const uint8_t *em, size_t emlen, uint8_t *sig) { + size_t nlen; + int crt_result; #if MG_TLS_RSA_USE_CRT // RSA CRT (Chinese Remainder Theorem) optimization: // s1 = em^dP mod p @@ -961,9 +961,9 @@ static bool mg_tls_rsa_sign(struct tls_data *tls, const uint8_t *em, MG_VERBOSE(("Using RSA-CRT optimization")); - size_t nlen = tls->rsa.n.len; + nlen = tls->rsa.n.len; - int crt_result = mg_rsa_crt_sign( + crt_result = mg_rsa_crt_sign( em, emlen, (const uint8_t *) tls->rsa.dP.buf, tls->rsa.dP.len, (const uint8_t *) tls->rsa.dQ.buf, tls->rsa.dQ.len, (const uint8_t *) tls->rsa.p.buf, tls->rsa.p.len, @@ -981,11 +981,12 @@ static bool mg_tls_rsa_sign(struct tls_data *tls, const uint8_t *em, return false; } #else + int ret; // Standard RSA: s = em^d mod n memset(sig, 0, tls->rsa.n.len); - int ret = mg_rsa_mod_pow((const uint8_t *) tls->rsa.n.buf, tls->rsa.n.len, - (const uint8_t *) tls->rsa.d.buf, tls->rsa.d.len, em, - emlen, sig, tls->rsa.n.len); + ret = mg_rsa_mod_pow((const uint8_t *) tls->rsa.n.buf, tls->rsa.n.len, + (const uint8_t *) tls->rsa.d.buf, tls->rsa.d.len, em, + emlen, sig, tls->rsa.n.len); if (ret == 0) { MG_VERBOSE(("RSA signature first 4 bytes: %02x %02x %02x %02x", sig[0], sig[1], sig[2], sig[3])); @@ -1496,7 +1497,7 @@ static int mg_tls_verify_cert_san(const uint8_t *der, size_t dersz, if (mg_match(mg_str(server_name), mg_str_n((char *) name.value, name.len), NULL)) return 1; // and matches the host name - } // TODO(): add IPv6 comparison, more items ? + } // TODO(): add IPv6 comparison, more items ? } return -1; } @@ -1930,7 +1931,8 @@ void mg_tls_handshake(struct mg_connection *c) { static int mg_rsa_parse_der_int(const uint8_t **p, const uint8_t *end, struct mg_str *out) { - const uint8_t *start = *p; + const uint8_t *start = *p, *value_start, *value_end; + uint8_t i; uint32_t len; if (end - start < 2) { @@ -1954,7 +1956,7 @@ static int mg_rsa_parse_der_int(const uint8_t **p, const uint8_t *end, return -1; } len = 0; - for (uint8_t i = 0; i < len_bytes; i++) { + for (i = 0; i < len_bytes; i++) { len = (len << 8) | (*p)[i]; } *p += len_bytes; @@ -1968,8 +1970,8 @@ static int mg_rsa_parse_der_int(const uint8_t **p, const uint8_t *end, } // The encoded length tells us how many bytes to consume from the stream - const uint8_t *value_start = *p; - const uint8_t *value_end = *p + len; + value_start = *p; + value_end = *p + len; // Skip leading zero byte if present (for positive numbers) // This doesn't change how many bytes we consume, just what we expose @@ -2037,7 +2039,8 @@ static int mg_parse_ec_private_key(const uint8_t *der, size_t dersz, // exponent2 INTEGER, -- dQ = d mod (q-1) // coefficient INTEGER, -- qInv = (inverse of q) mod p // } -static int mg_rsa_parse_key(const uint8_t *der, size_t dersz, struct mg_rsa_key *key) { +static int mg_rsa_parse_key(const uint8_t *der, size_t dersz, + struct mg_rsa_key *key) { const uint8_t *p = der; const uint8_t *end = der + dersz; uint32_t seq_len; @@ -2067,14 +2070,14 @@ static int mg_rsa_parse_key(const uint8_t *der, size_t dersz, struct mg_rsa_key if (seq_len > 0x7F) { // Long form length - uint8_t len_bytes = seq_len & 0x7F; + uint8_t i, len_bytes = seq_len & 0x7F; MG_VERBOSE(("Long form length: %d bytes", len_bytes)); if (end - p < len_bytes) { MG_ERROR(("Not enough bytes for long form length")); return -1; } seq_len = 0; - for (uint8_t i = 0; i < len_bytes; i++) { + for (i = 0; i < len_bytes; i++) { seq_len = (seq_len << 8) | p[i]; } p += len_bytes; @@ -2091,7 +2094,7 @@ static int mg_rsa_parse_key(const uint8_t *der, size_t dersz, struct mg_rsa_key // Parse version (should be 0) MG_VERBOSE(("Before version: offset=%d, bytes: %02x %02x %02x %02x", - (int) (p - der), p[0], p[1], p[2], p[3])); + (int) (p - der), p[0], p[1], p[2], p[3])); if (mg_rsa_parse_der_int(&p, end, &version) < 0) { MG_ERROR(("Failed to parse version")); return -1; @@ -2102,22 +2105,22 @@ static int mg_rsa_parse_key(const uint8_t *der, size_t dersz, struct mg_rsa_key // Parse the 8 components: n, e, d, p, q, dP, dQ, qInv MG_VERBOSE(("Before n: offset=%d, bytes: %02x %02x %02x %02x %02x %02x", - (int) (p - der), p[0], p[1], p[2], p[3], p[4], p[5])); + (int) (p - der), p[0], p[1], p[2], p[3], p[4], p[5])); if (mg_rsa_parse_der_int(&p, end, &key->n) < 0) { MG_ERROR(("Failed to parse n (modulus)")); return -1; } MG_VERBOSE(("Parsed n: %d bytes, offset now=%d, consumed=%d bytes total", - (int) key->n.len, (int) (p - der), (int) (p - der))); + (int) key->n.len, (int) (p - der), (int) (p - der))); MG_VERBOSE((" First 8 bytes of n: %02x %02x %02x %02x %02x %02x %02x %02x", - (unsigned char) key->n.buf[0], (unsigned char) key->n.buf[1], - (unsigned char) key->n.buf[2], (unsigned char) key->n.buf[3], - (unsigned char) key->n.buf[4], (unsigned char) key->n.buf[5], - (unsigned char) key->n.buf[6], (unsigned char) key->n.buf[7])); + (unsigned char) key->n.buf[0], (unsigned char) key->n.buf[1], + (unsigned char) key->n.buf[2], (unsigned char) key->n.buf[3], + (unsigned char) key->n.buf[4], (unsigned char) key->n.buf[5], + (unsigned char) key->n.buf[6], (unsigned char) key->n.buf[7])); MG_VERBOSE((" Next bytes after n: %02x %02x %02x %02x %02x %02x", - p < end ? p[0] : 0xFF, p + 1 < end ? p[1] : 0xFF, - p + 2 < end ? p[2] : 0xFF, p + 3 < end ? p[3] : 0xFF, - p + 4 < end ? p[4] : 0xFF, p + 5 < end ? p[5] : 0xFF)); + p < end ? p[0] : 0xFF, p + 1 < end ? p[1] : 0xFF, + p + 2 < end ? p[2] : 0xFF, p + 3 < end ? p[3] : 0xFF, + p + 4 < end ? p[4] : 0xFF, p + 5 < end ? p[5] : 0xFF)); if (mg_rsa_parse_der_int(&p, end, &key->e) < 0) { MG_ERROR(("Failed to parse e (public exponent), bytes remaining: %d", @@ -2276,8 +2279,11 @@ static int mg_parse_pem_certs(const struct mg_str pem, struct mg_str **ders) { size_t end_len = strlen(end_marker); while (p < end) { - const char *begin = NULL; - for (const char *s = p; s <= end - (int) begin_len; s++) { + const char *s, *begin = NULL, *finish = NULL; + struct mg_str cert_pem, cert_der, *new_certs; + int i; + + for (s = p; s <= end - (int) begin_len; s++) { if (memcmp(s, begin_marker, begin_len) == 0) { begin = s; break; @@ -2285,33 +2291,30 @@ static int mg_parse_pem_certs(const struct mg_str pem, struct mg_str **ders) { } if (begin == NULL) break; - const char *finish = NULL; - for (const char *s = begin + begin_len; s <= end - (int) end_len; s++) { + for (s = begin + begin_len; s <= end - (int) end_len; s++) { if (memcmp(s, end_marker, end_len) == 0) { finish = s + end_len; break; } } if (finish == NULL) { - for (int i = 0; i < count; i++) mg_free((void *) certs[i].buf); + for (i = 0; i < count; i++) mg_free((void *) certs[i].buf); mg_free(certs); return -1; } - struct mg_str cert_pem = mg_str_n(begin, (size_t) (finish - begin)); - struct mg_str cert_der; - + cert_pem = mg_str_n(begin, (size_t) (finish - begin)); if (mg_parse_pem(cert_pem, mg_str_s("CERTIFICATE"), &cert_der) < 0) { - for (int i = 0; i < count; i++) mg_free((void *) certs[i].buf); + for (i = 0; i < count; i++) mg_free((void *) certs[i].buf); mg_free(certs); return -1; } - struct mg_str *new_certs = - (struct mg_str *) mg_calloc((size_t) count + 1, sizeof(struct mg_str)); + new_certs = + (struct mg_str *) mg_calloc((size_t) count + 1, sizeof(*new_certs)); if (new_certs == NULL) { mg_free((void *) cert_der.buf); - for (int i = 0; i < count; i++) mg_free((void *) certs[i].buf); + for (i = 0; i < count; i++) mg_free((void *) certs[i].buf); mg_free(certs); return -1; } @@ -2372,22 +2375,25 @@ void mg_tls_init(struct mg_connection *c, const struct mg_tls_opts *opts) { } // parse PEM or DER certificate - struct mg_str *all_certs = NULL; - int cert_count = mg_parse_pem_certs(opts->cert, &all_certs); + { + struct mg_str *all_certs = NULL; + int cert_count = mg_parse_pem_certs(opts->cert, &all_certs); - if (cert_count > 0) { - tls->cert_der.buf = all_certs[0].buf; - tls->cert_der.len = all_certs[0].len; - if (cert_count > 1) { - tls->chain_len = (size_t) cert_count; - tls->chain_der = all_certs; + if (cert_count > 0) { + tls->cert_der.buf = all_certs[0].buf; + tls->cert_der.len = all_certs[0].len; + if (cert_count > 1) { + tls->chain_len = (size_t) cert_count; + tls->chain_der = all_certs; + } else { + mg_free(all_certs); + } } else { - mg_free(all_certs); - } - } else { - if (mg_parse_pem(opts->cert, mg_str_s("CERTIFICATE"), &tls->cert_der) < 0) { - MG_ERROR(("Failed to load certificate")); - return; + if (mg_parse_pem(opts->cert, mg_str_s("CERTIFICATE"), &tls->cert_der) < + 0) { + MG_ERROR(("Failed to load certificate")); + return; + } } } @@ -2414,13 +2420,13 @@ void mg_tls_init(struct mg_connection *c, const struct mg_tls_opts *opts) { memmove(tls->ec_key, key.buf + 7, 32); mg_free((void *) key.buf); } else if (mg_parse_pem(opts->key, mg_str_s("RSA PRIVATE KEY"), &key) == 0) { + struct mg_rsa_key rsa_key; // RSA private key found, store it for later use tls->rsa_key_der = key; MG_INFO(("Parsed RSA private key: %d bytes", (int) key.len)); // parse and validate the key structure // we keep the DER buffer, rsa_key just points into it - struct mg_rsa_key rsa_key; if (mg_rsa_parse_key((const uint8_t *) key.buf, key.len, &rsa_key) < 0) { MG_ERROR(("Failed to parse RSA private key structure")); mg_free((void *) key.buf); @@ -2463,10 +2469,11 @@ void mg_tls_init(struct mg_connection *c, const struct mg_tls_opts *opts) { void mg_tls_free(struct mg_connection *c) { struct tls_data *tls = (struct tls_data *) c->tls; + size_t i; if (tls != NULL) { mg_iobuf_free(&tls->send); if (tls->chain_der != NULL) { - for (size_t i = 0; i < tls->chain_len; i++) { + for (i = 0; i < tls->chain_len; i++) { mg_free((void *) tls->chain_der[i].buf); } mg_free(tls->chain_der); @@ -2490,7 +2497,7 @@ long mg_tls_send(struct mg_connection *c, const void *buf, size_t len) { if (!mg_tls_encrypt(c, (const uint8_t *) buf, len, MG_TLS_APP_DATA)) return 0; // returning 0 means an OOM condition (iobuf couldn't resize), // yet this is so far recoverable, let the caller decide - } // else, resend outstanding encrypted data in tls->send + } // else, resend outstanding encrypted data in tls->send while (tls->send.len > 0 && (n = mg_io_send(c, tls->send.buf, tls->send.len)) > 0) { mg_iobuf_del(&tls->send, 0, (size_t) n); @@ -2516,7 +2523,7 @@ long mg_tls_recv(struct mg_connection *c, void *buf, size_t len) { tls->recv_len = 0; mg_tls_drop_record(c); } - + if (buf == NULL || len == 0) return 0L; recv_buf = &c->rtls.buf[tls->recv_offset]; minlen = len < tls->recv_len ? len : tls->recv_len;