Skip to content

Commit e28e9aa

Browse files
authored
Merge pull request #3287 from cesanta/2way
Fix 2-way auth, fix skip hostname validation
2 parents acd65f2 + 4536694 commit e28e9aa

File tree

3 files changed

+217
-114
lines changed

3 files changed

+217
-114
lines changed

mongoose.c

Lines changed: 94 additions & 55 deletions
Original file line numberDiff line numberDiff line change
@@ -11112,6 +11112,8 @@ enum mg_tls_hs_state {
1111211112

1111311113
// Server state machine:
1111411114
MG_TLS_STATE_SERVER_START, // Wait for ClientHello
11115+
MG_TLS_STATE_SERVER_WAIT_CERT, // Wait for Certificate
11116+
MG_TLS_STATE_SERVER_WAIT_CV, // Wait for CertificateVerify
1111511117
MG_TLS_STATE_SERVER_NEGOTIATED, // Wait for Finish
1111611118
MG_TLS_STATE_SERVER_CONNECTED // Done
1111711119
};
@@ -11147,14 +11149,15 @@ struct tls_data {
1114711149
uint8_t x25519_cli[32]; // client X25519 key between the handshake states
1114811150
uint8_t x25519_sec[32]; // x25519 secret between the handshake states
1114911151

11150-
int skip_verification; // perform checks on server certificate?
11151-
int cert_requested; // client received a CertificateRequest?
11152+
bool skip_verification; // do not perform checks on server certificate
11153+
bool cert_requested; // client received a CertificateRequest
11154+
bool is_twoway; // server is configured to authenticate clients
1115211155
struct mg_str cert_der; // certificate in DER format
1115311156
struct mg_str ca_der; // CA certificate
1115411157
uint8_t ec_key[32]; // EC private key
11155-
char hostname[254]; // server hostname (client extension)
11158+
char hostname[254]; // matching hostname
1115611159

11157-
int is_ec_pubkey; // EC or RSA?
11160+
bool is_ec_pubkey; // EC or RSA
1115811161
uint8_t pubkey[512 + 16]; // server EC (64) or RSA (512+exp) public key to
1115911162
// verify cert
1116011163
size_t pubkeysz; // size of the server public key
@@ -11600,18 +11603,18 @@ static int mg_tls_recv_record(struct mg_connection *c) {
1160011603
}
1160111604

1160211605
static void mg_tls_calc_cert_verify_hash(struct mg_connection *c,
11603-
uint8_t hash[32], int is_client) {
11606+
uint8_t hash[32], bool is_client) {
1160411607
struct tls_data *tls = (struct tls_data *) c->tls;
11605-
uint8_t server_context[34] = "TLS 1.3, server CertificateVerify";
11606-
uint8_t client_context[34] = "TLS 1.3, client CertificateVerify";
1160711608
uint8_t sig_content[130];
1160811609
mg_sha256_ctx sha256;
1160911610

1161011611
memset(sig_content, 0x20, 64);
1161111612
if (is_client) {
11612-
memmove(sig_content + 64, client_context, sizeof(client_context));
11613+
uint8_t client_context[34] = "TLS 1.3, client CertificateVerify";
11614+
memcpy(sig_content + 64, client_context, sizeof(client_context));
1161311615
} else {
11614-
memmove(sig_content + 64, server_context, sizeof(server_context));
11616+
uint8_t server_context[34] = "TLS 1.3, server CertificateVerify";
11617+
memcpy(sig_content + 64, server_context, sizeof(server_context));
1161511618
}
1161611619

1161711620
memmove(&sha256, &tls->sha256, sizeof(mg_sha256_ctx));
@@ -11753,17 +11756,46 @@ static void mg_tls_server_send_ext(struct mg_connection *c) {
1175311756
mg_tls_encrypt(c, ext, sizeof(ext), MG_TLS_HANDSHAKE);
1175411757
}
1175511758

11756-
static void mg_tls_server_send_cert(struct mg_connection *c) {
11759+
// signature algorithms we actually support:
11760+
// rsa_pkcs1_sha256, rsa_pss_rsae_sha256 and ecdsa_secp256r1_sha256
11761+
static const uint8_t secp256r1_sig_algs[12] = {
11762+
0x00, 0x0d, 0x00, 0x08, 0x00, 0x06, 0x04, 0x03, 0x08, 0x04, 0x04, 0x01,
11763+
};
11764+
11765+
static void mg_tls_server_send_cert_request(struct mg_connection *c) {
11766+
struct tls_data *tls = (struct tls_data *) c->tls;
11767+
size_t n = sizeof(secp256r1_sig_algs) + 6;
11768+
uint8_t *req = (uint8_t *) mg_calloc(1, 13 + n);
11769+
if (req == NULL) {
11770+
mg_error(c, "tls cert req oom");
11771+
return;
11772+
}
11773+
req[0] = MG_TLS_CERTIFICATE_REQUEST; // handshake header
11774+
MG_STORE_BE24(req + 1, n + 9);
11775+
req[4] = 0; // context length
11776+
MG_STORE_BE16(req + 5, n); // extensions length
11777+
MG_STORE_BE16(req + 7, 13); // "signature algorithms"
11778+
MG_STORE_BE16(req + 9, sizeof(secp256r1_sig_algs) + 2); // length
11779+
MG_STORE_BE16(
11780+
req + 11,
11781+
sizeof(secp256r1_sig_algs)); // signature hash algorithms length
11782+
memcpy(req + 13, (uint8_t *) secp256r1_sig_algs, sizeof(secp256r1_sig_algs));
11783+
mg_sha256_update(&tls->sha256, req, 13 + n);
11784+
mg_tls_encrypt(c, req, 13 + n, MG_TLS_HANDSHAKE);
11785+
mg_free(req);
11786+
}
11787+
11788+
static void mg_tls_send_cert(struct mg_connection *c, bool is_client) {
1175711789
struct tls_data *tls = (struct tls_data *) c->tls;
11758-
int send_ca = !c->is_client && tls->ca_der.len > 0;
11759-
// server DER certificate + CA (optional)
11790+
int send_ca = !is_client && tls->ca_der.len > 0;
11791+
// DER certificate + CA (server optional)
1176011792
size_t n = tls->cert_der.len + (send_ca ? tls->ca_der.len + 5 : 0);
1176111793
uint8_t *cert = (uint8_t *) mg_calloc(1, 13 + n);
1176211794
if (cert == NULL) {
1176311795
mg_error(c, "tls cert oom");
1176411796
return;
1176511797
}
11766-
cert[0] = 0x0b; // handshake header
11798+
cert[0] = MG_TLS_CERTIFICATE; // handshake header
1176711799
MG_STORE_BE24(cert + 1, n + 9);
1176811800
cert[4] = 0; // request context
1176911801
MG_STORE_BE24(cert + 5, n + 5); // 3 bytes: cert (s) length
@@ -11806,7 +11838,7 @@ static void finish_SHA256(const MG_UECC_HashContext *base,
1180611838
mg_sha256_final(hash_result, &c->ctx);
1180711839
}
1180811840

11809-
static void mg_tls_send_cert_verify(struct mg_connection *c, int is_client) {
11841+
static void mg_tls_send_cert_verify(struct mg_connection *c, bool is_client) {
1181011842
struct tls_data *tls = (struct tls_data *) c->tls;
1181111843
// server certificate verify packet
1181211844
uint8_t verify[82] = {0x0f, 0x00, 0x00, 0x00, 0x04, 0x03, 0x00, 0x00};
@@ -11883,12 +11915,9 @@ static void mg_tls_client_send_hello(struct mg_connection *c) {
1188311915

1188411916
uint8_t x25519_pub[X25519_BYTES];
1188511917

11886-
// signature algorithms we actually support:
11887-
// rsa_pkcs1_sha256, rsa_pss_rsae_sha256 and ecdsa_secp256r1_sha256
11888-
uint8_t secp256r1_sig_algs[12] = {
11889-
0x00, 0x0d, 0x00, 0x08, 0x00, 0x06, 0x04, 0x03, 0x08, 0x04, 0x04, 0x01,
11890-
};
11891-
// all popular signature algorithms (if we don't care about verification)
11918+
// - "signature algorithms we actually support", see above
11919+
// uint8_t secp256r1_sig_algs[]
11920+
// - all popular signature algorithms (if we don't care about verification)
1189211921
uint8_t all_sig_algs[34] = {
1189311922
0x00, 0x0d, 0x00, 0x1e, 0x00, 0x1c, 0x04, 0x03, 0x05, 0x03, 0x06, 0x03,
1189411923
0x08, 0x07, 0x08, 0x08, 0x08, 0x09, 0x08, 0x0a, 0x08, 0x0b, 0x08, 0x04,
@@ -11932,7 +11961,8 @@ static void mg_tls_client_send_hello(struct mg_connection *c) {
1193211961
const char *hostname = tls->hostname;
1193311962
size_t hostnamesz = strlen(tls->hostname);
1193411963
size_t hostname_extsz = hostnamesz ? hostnamesz + 9 : 0;
11935-
uint8_t *sig_alg = tls->skip_verification ? all_sig_algs : secp256r1_sig_algs;
11964+
uint8_t *sig_alg =
11965+
tls->skip_verification ? all_sig_algs : (uint8_t *) secp256r1_sig_algs;
1193611966
size_t sig_alg_sz = tls->skip_verification ? sizeof(all_sig_algs)
1193711967
: sizeof(secp256r1_sig_algs);
1193811968

@@ -12307,7 +12337,7 @@ static int mg_tls_verify_cert_cn(struct mg_der_tlv *subj, const char *host) {
1230712337
return matched;
1230812338
}
1230912339

12310-
static int mg_tls_client_recv_cert(struct mg_connection *c) {
12340+
static int mg_tls_recv_cert(struct mg_connection *c, bool is_client) {
1231112341
struct tls_data *tls = (struct tls_data *) c->tls;
1231212342
unsigned char *recv_buf;
1231312343

@@ -12325,7 +12355,8 @@ static int mg_tls_client_recv_cert(struct mg_connection *c) {
1232512355
}
1232612356

1232712357
if (recv_buf[0] != MG_TLS_CERTIFICATE) {
12328-
mg_error(c, "expected server certificate but got msg 0x%02x", recv_buf[0]);
12358+
mg_error(c, "expected %s certificate but got msg 0x%02x",
12359+
is_client ? "server" : "client", recv_buf[0]);
1232912360
return -1;
1233012361
}
1233112362

@@ -12335,7 +12366,7 @@ static int mg_tls_client_recv_cert(struct mg_connection *c) {
1233512366
}
1233612367

1233712368
{
12338-
// Normally, there are 2-3 certs in a chain
12369+
// Normally, there are 2-3 certs in a chain (when is_client)
1233912370
struct mg_tls_cert certs[8];
1234012371
int certnum = 0;
1234112372
uint32_t full_cert_chain_len = MG_LOAD_BE24(recv_buf + 1);
@@ -12380,9 +12411,10 @@ static int mg_tls_client_recv_cert(struct mg_connection *c) {
1238012411
}
1238112412

1238212413
if (ci == certs) {
12383-
// First certificate in the chain is peer cert, check SAN and store
12384-
// public key for further CertVerify step
12385-
if (mg_tls_verify_cert_san(cert, certsz, tls->hostname) <= 0 &&
12414+
// First certificate in the chain is peer cert, check SAN if requested,
12415+
// and store public key for further CertVerify step
12416+
if (tls->hostname != NULL && *tls->hostname != '\0' &&
12417+
mg_tls_verify_cert_san(cert, certsz, tls->hostname) <= 0 &&
1238612418
mg_tls_verify_cert_cn(&ci->subj, tls->hostname) <= 0) {
1238712419
mg_error(c, "failed to verify hostname");
1238812420
return -1;
@@ -12413,28 +12445,28 @@ static int mg_tls_client_recv_cert(struct mg_connection *c) {
1241312445
!mg_tls_verify_cert_signature(&certs[certnum - 1], &ca)) {
1241412446
mg_error(c, "failed to verify CA");
1241512447
return -1;
12416-
} else {
12448+
} else if (is_client) {
1241712449
MG_VERBOSE(
1241812450
("CA was not in the chain, but verification with builtin CA "
1241912451
"passed"));
1242012452
}
1242112453
}
1242212454
}
1242312455
mg_tls_drop_message(c);
12424-
mg_tls_calc_cert_verify_hash(c, tls->sighash, 0);
12456+
mg_tls_calc_cert_verify_hash(c, tls->sighash, !is_client);
1242512457
return 0;
1242612458
}
1242712459

12428-
static int mg_tls_client_recv_cert_verify(struct mg_connection *c) {
12460+
static int mg_tls_recv_cert_verify(struct mg_connection *c) {
1242912461
struct tls_data *tls = (struct tls_data *) c->tls;
1243012462
unsigned char *recv_buf;
1243112463
if (mg_tls_recv_record(c) < 0) {
1243212464
return -1;
1243312465
}
1243412466
recv_buf = &c->rtls.buf[tls->recv_offset];
1243512467
if (recv_buf[0] != MG_TLS_CERTIFICATE_VERIFY) {
12436-
mg_error(c, "expected server certificate verify but got msg 0x%02x",
12437-
recv_buf[0]);
12468+
mg_error(c, "expected %s certificate verify but got msg 0x%02x",
12469+
c->is_client ? "server" : "client", recv_buf[0]);
1243812470
return -1;
1243912471
}
1244012472
if (tls->recv_len < 8) {
@@ -12443,7 +12475,7 @@ static int mg_tls_client_recv_cert_verify(struct mg_connection *c) {
1244312475
return -1;
1244412476
}
1244512477

12446-
// Ignore CertificateVerify is strict checks are not required
12478+
// Ignore CertificateVerify if strict checks are not required
1244712479
if (tls->skip_verification) {
1244812480
mg_tls_drop_message(c);
1244912481
return 0;
@@ -12574,13 +12606,13 @@ static void mg_tls_client_handshake(struct mg_connection *c) {
1257412606
tls->state = MG_TLS_STATE_CLIENT_WAIT_CERT;
1257512607
// Fallthrough
1257612608
case MG_TLS_STATE_CLIENT_WAIT_CERT:
12577-
if (mg_tls_client_recv_cert(c) < 0) {
12609+
if (mg_tls_recv_cert(c, true) < 0) {
1257812610
break;
1257912611
}
1258012612
tls->state = MG_TLS_STATE_CLIENT_WAIT_CV;
1258112613
// Fallthrough
1258212614
case MG_TLS_STATE_CLIENT_WAIT_CV:
12583-
if (mg_tls_client_recv_cert_verify(c) < 0) {
12615+
if (mg_tls_recv_cert_verify(c) < 0) {
1258412616
break;
1258512617
}
1258612618
tls->state = MG_TLS_STATE_CLIENT_WAIT_FINISH;
@@ -12589,28 +12621,19 @@ static void mg_tls_client_handshake(struct mg_connection *c) {
1258912621
if (mg_tls_client_recv_finish(c) < 0) {
1259012622
break;
1259112623
}
12592-
if (tls->cert_requested) {
12593-
/* for mTLS we should generate application keys at this point
12594-
* but then restore handshake keys and continue with
12595-
* the rest of the handshake */
12596-
struct tls_enc app_keys;
12597-
struct tls_enc hs_keys = tls->enc;
12598-
mg_tls_generate_application_keys(c);
12599-
app_keys = tls->enc;
12600-
tls->enc = hs_keys;
12601-
mg_tls_server_send_cert(c);
12602-
mg_tls_send_cert_verify(c, 1);
12603-
mg_tls_client_send_finish(c);
12604-
tls->enc = app_keys;
12605-
} else {
12606-
mg_tls_client_send_finish(c);
12607-
mg_tls_generate_application_keys(c);
12624+
if (tls->cert_requested && tls->cert_der.len > 0) { // two-way auth
12625+
mg_tls_send_cert(c, true);
12626+
mg_tls_send_cert_verify(c, true);
1260812627
}
12628+
mg_tls_client_send_finish(c);
12629+
mg_tls_generate_application_keys(c);
1260912630
tls->state = MG_TLS_STATE_CLIENT_CONNECTED;
1261012631
c->is_tls_hs = 0;
1261112632
mg_call(c, MG_EV_TLS_HS, NULL);
1261212633
break;
12613-
default: mg_error(c, "unexpected client state: %d", tls->state); break;
12634+
default:
12635+
mg_error(c, "unexpected client state: %d", tls->state);
12636+
break;
1261412637
}
1261512638
}
1261612639

@@ -12624,9 +12647,14 @@ static void mg_tls_server_handshake(struct mg_connection *c) {
1262412647
mg_tls_server_send_hello(c);
1262512648
mg_tls_generate_handshake_keys(c);
1262612649
mg_tls_server_send_ext(c);
12627-
mg_tls_server_send_cert(c);
12628-
mg_tls_send_cert_verify(c, 0);
12650+
if (tls->is_twoway) mg_tls_server_send_cert_request(c);
12651+
mg_tls_send_cert(c, false);
12652+
mg_tls_send_cert_verify(c, false);
1262912653
mg_tls_server_send_finish(c);
12654+
if (tls->is_twoway) {
12655+
tls->state = MG_TLS_STATE_SERVER_WAIT_CERT;
12656+
break;
12657+
}
1263012658
tls->state = MG_TLS_STATE_SERVER_NEGOTIATED;
1263112659
// fallthrough
1263212660
case MG_TLS_STATE_SERVER_NEGOTIATED:
@@ -12637,7 +12665,17 @@ static void mg_tls_server_handshake(struct mg_connection *c) {
1263712665
tls->state = MG_TLS_STATE_SERVER_CONNECTED;
1263812666
c->is_tls_hs = 0;
1263912667
return;
12640-
default: mg_error(c, "unexpected server state: %d", tls->state); break;
12668+
case MG_TLS_STATE_SERVER_WAIT_CERT:
12669+
if (mg_tls_recv_cert(c, false) < 0) break;
12670+
tls->state = MG_TLS_STATE_SERVER_WAIT_CV;
12671+
// Fallthrough
12672+
case MG_TLS_STATE_SERVER_WAIT_CV:
12673+
if (mg_tls_recv_cert_verify(c) < 0) break;
12674+
tls->state = MG_TLS_STATE_SERVER_NEGOTIATED;
12675+
break;
12676+
default:
12677+
mg_error(c, "unexpected server state: %d", tls->state);
12678+
break;
1264112679
}
1264212680
}
1264312681

@@ -12724,6 +12762,7 @@ void mg_tls_init(struct mg_connection *c, const struct mg_tls_opts *opts) {
1272412762
MG_ERROR(("Failed to load certificate"));
1272512763
return;
1272612764
}
12765+
if (!c->is_client) tls->is_twoway = true; // server + CA: two-way auth
1272712766
}
1272812767

1272912768
if (opts->cert.buf == NULL) {

0 commit comments

Comments
 (0)