初始提交:terminalX 可运行态(M0/M1/M1.5 已真机验证)
- M0: libghostty SSH 终端(渲染/输入/连接)+ 白屏修复(OutputGate) + 会话状态机/自动重连 - M1: tsnet 用户态组网 + SSH-over-tsnet(fd 桥),shell 级真机验证;R5(Go+gvisor+C+++Swift 同进程) retire - M1.5: tmux -CC 原生 tab(MVP) - 结构: packages/(TXCore·TXTransport), apps/TerminalX, vendor/(libghostty-spm/libssh2/mbedtls/tsnet-bridge), artifacts/ - 文档: CLAUDE.md + docs/HANDOFF.md(新会话入口) - 环境: 认证代理→依赖 vendor 本地化;Go 在 ~/.local/go;仅模拟器/未签名 - 待续: M2 mosh, tmux 多 pane, M4 安全(host key/SE) Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
192
vendor/mbedtls/docs/tls13-early-data.md
vendored
Normal file
192
vendor/mbedtls/docs/tls13-early-data.md
vendored
Normal file
@@ -0,0 +1,192 @@
|
||||
|
||||
Writing early data
|
||||
------------------
|
||||
|
||||
An application function to write and send a buffer of data to a server through
|
||||
TLS may plausibly look like:
|
||||
|
||||
```
|
||||
int write_data(mbedtls_ssl_context *ssl,
|
||||
const unsigned char *data_to_write,
|
||||
size_t data_to_write_len,
|
||||
size_t *data_written)
|
||||
{
|
||||
int ret;
|
||||
*data_written = 0;
|
||||
|
||||
while (*data_written < data_to_write_len) {
|
||||
ret = mbedtls_ssl_write(ssl, data_to_write + *data_written,
|
||||
data_to_write_len - *data_written);
|
||||
|
||||
if (ret < 0 &&
|
||||
ret != MBEDTLS_ERR_SSL_WANT_READ &&
|
||||
ret != MBEDTLS_ERR_SSL_WANT_WRITE) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
*data_written += ret;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
```
|
||||
where ssl is the SSL context to use, data_to_write the address of the data
|
||||
buffer and data_to_write_len the number of data bytes. The handshake may
|
||||
not be completed, not even started for the SSL context ssl when the function is
|
||||
called and in that case the mbedtls_ssl_write() API takes care transparently of
|
||||
completing the handshake before to write and send data to the server. The
|
||||
mbedtls_ssl_write() may not be able to write and send all data in one go thus
|
||||
the need for a loop calling it as long as there are still data to write and
|
||||
send.
|
||||
|
||||
An application function to write and send early data and only early data,
|
||||
data sent during the first flight of client messages while the handshake is in
|
||||
its initial phase, would look completely similar but the call to
|
||||
mbedtls_ssl_write_early_data() instead of mbedtls_ssl_write().
|
||||
```
|
||||
int write_early_data(mbedtls_ssl_context *ssl,
|
||||
const unsigned char *data_to_write,
|
||||
size_t data_to_write_len,
|
||||
size_t *data_written)
|
||||
{
|
||||
int ret;
|
||||
*data_written = 0;
|
||||
|
||||
while (*data_written < data_to_write_len) {
|
||||
ret = mbedtls_ssl_write_early_data(ssl, data_to_write + *data_written,
|
||||
data_to_write_len - *data_written);
|
||||
|
||||
if (ret < 0 &&
|
||||
ret != MBEDTLS_ERR_SSL_WANT_READ &&
|
||||
ret != MBEDTLS_ERR_SSL_WANT_WRITE) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
*data_written += ret;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
```
|
||||
Note that compared to write_data(), write_early_data() can also return
|
||||
MBEDTLS_ERR_SSL_CANNOT_WRITE_EARLY_DATA and that should be handled
|
||||
specifically by the user of write_early_data(). A fresh SSL context (typically
|
||||
just after a call to mbedtls_ssl_setup() or mbedtls_ssl_session_reset()) would
|
||||
be expected when calling `write_early_data`.
|
||||
|
||||
All together, code to write and send a buffer of data as long as possible as
|
||||
early data and then as standard post-handshake application data could
|
||||
plausibly look like:
|
||||
|
||||
```
|
||||
ret = write_early_data(ssl,
|
||||
data_to_write,
|
||||
data_to_write_len,
|
||||
&early_data_written);
|
||||
if (ret < 0 &&
|
||||
ret != MBEDTLS_ERR_SSL_CANNOT_WRITE_EARLY_DATA) {
|
||||
goto error;
|
||||
}
|
||||
|
||||
ret = write_data(ssl,
|
||||
data_to_write + early_data_written,
|
||||
data_to_write_len - early_data_written,
|
||||
&data_written);
|
||||
if (ret < 0) {
|
||||
goto error;
|
||||
}
|
||||
|
||||
data_written += early_data_written;
|
||||
```
|
||||
|
||||
Finally, taking into account that the server may reject early data, application
|
||||
code to write and send a buffer of data could plausibly look like:
|
||||
```
|
||||
ret = write_early_data(ssl,
|
||||
data_to_write,
|
||||
data_to_write_len,
|
||||
&early_data_written);
|
||||
if (ret < 0 &&
|
||||
ret != MBEDTLS_ERR_SSL_CANNOT_WRITE_EARLY_DATA) {
|
||||
goto error;
|
||||
}
|
||||
|
||||
/*
|
||||
* Make sure the handshake is completed as it is a requisite of
|
||||
* mbedtls_ssl_get_early_data_status().
|
||||
*/
|
||||
while (!mbedtls_ssl_is_handshake_over(ssl)) {
|
||||
ret = mbedtls_ssl_handshake(ssl);
|
||||
if (ret < 0 &&
|
||||
ret != MBEDTLS_ERR_SSL_WANT_READ &&
|
||||
ret != MBEDTLS_ERR_SSL_WANT_WRITE) {
|
||||
goto error;
|
||||
}
|
||||
}
|
||||
|
||||
ret = mbedtls_ssl_get_early_data_status(ssl);
|
||||
if (ret < 0) {
|
||||
goto error;
|
||||
}
|
||||
|
||||
if (ret == MBEDTLS_SSL_EARLY_DATA_STATUS_REJECTED) {
|
||||
early_data_written = 0;
|
||||
}
|
||||
|
||||
ret = write_data(ssl,
|
||||
data_to_write + early_data_written,
|
||||
data_to_write_len - early_data_written,
|
||||
&data_written);
|
||||
if (ret < 0) {
|
||||
goto error;
|
||||
}
|
||||
|
||||
data_written += early_data_written;
|
||||
```
|
||||
|
||||
Reading early data
|
||||
------------------
|
||||
Mbed TLS provides the mbedtls_ssl_read_early_data() API to read the early data
|
||||
that a TLS 1.3 server might receive during the TLS 1.3 handshake.
|
||||
|
||||
While establishing a TLS 1.3 connection with a client using a combination
|
||||
of the mbedtls_ssl_handshake(), mbedtls_ssl_read() and mbedtls_ssl_write() APIs,
|
||||
the reception of early data is signaled by an API returning the
|
||||
MBEDTLS_ERR_SSL_RECEIVED_EARLY_DATA error code. Early data can then be read
|
||||
with the mbedtls_ssl_read_early_data() API.
|
||||
|
||||
For example, a typical code to establish a TLS connection, where ssl is the SSL
|
||||
context to use:
|
||||
```
|
||||
while ((int ret = mbedtls_ssl_handshake(&ssl)) != 0) {
|
||||
|
||||
if (ret < 0 &&
|
||||
ret != MBEDTLS_ERR_SSL_WANT_READ &&
|
||||
ret != MBEDTLS_ERR_SSL_WANT_WRITE) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
```
|
||||
could be adapted to handle early data in the following way:
|
||||
```
|
||||
size_t data_read_len = 0;
|
||||
while ((ret = mbedtls_ssl_handshake(&ssl)) != 0) {
|
||||
|
||||
if (ret == MBEDTLS_ERR_SSL_RECEIVED_EARLY_DATA) {
|
||||
ret = mbedtls_ssl_read_early_data(&ssl,
|
||||
buffer + data_read_len,
|
||||
sizeof(buffer) - data_read_len);
|
||||
if (ret < 0) {
|
||||
break;
|
||||
}
|
||||
data_read_len += ret;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (ret < 0 &&
|
||||
ret != MBEDTLS_ERR_SSL_WANT_READ &&
|
||||
ret != MBEDTLS_ERR_SSL_WANT_WRITE) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
```
|
||||
Reference in New Issue
Block a user