Make built-in TLS vc98-friendly

This commit is contained in:
cpq authored and Sergio R. Caprile committed 2026-01-30 11:40:26 -03:00
1 parent b5e4eef966
commit f2ce01641e
2 files changed
+168 -164

No files matched your search

+93 -96
View File
@@ -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) {
+75 -68
View File
@@ -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;