I am using libwebsockets ,lwip, and mbedtls on stm32F777NIHx.But mbedtls_handshake failed.The phenomenon is very strange.
In altcp_mbedtls_bio_recv function( in this file:altcp_tls_mbedtls.c),the “struct pbuf *p” is 0xc032, 0xc032 is an illegal address, its address value is too low. I think 0xc032 means MBEDTLS_TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384.
In mbedtls/ssl_cphersuites.h, I can see this definition.
#define MBEDTLS_TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384 0xC032 /**< TLS 1.2 */.
The privkey and cert is as following:
const u8_t privkey = "-----BEGIN RSA PRIVATE KEY-----\r\n\
MIIEogIBAAKCAQEAqJPUXePfMvL7JDPw/Nrbx4jXnnaZd39g2FHOJIqXqZi6rJq7\r\n\
WLNa9Ice1VGvGHMgG7l3xNulMtNE2s2wdR5YrK13FWwKeVCj3oSd5h6RNon2SJuf\r\n\
vJb/4LzCBxcYn1XNHM3z3KZnXFdRFYPH6Je+GlEhhN3+GX9wym6rWymQnSJwE2q7\r\n\
rkCKFAaP6OJnHJ6D/ad2/E7bRZqOkA1p/DlfxqHVmwpFDn5Js6sSJlgG1JOoRUzl\r\n\
UDltbC8sqX9S5rZFCEWCPt3PdEXm3NmXWmbg0+415wXStangIr+O/Bq8h6dUvL5J\r\n\
jRnDBQ0yWYbodJhMDkCLB5E7jmGI/ebkjmWEyQIDAQABAoIBABmryV8y4D5l+hCd\r\n\
SEl5GpbcI9mhveUQpLLMYlP2NvpAo8y9E2KCjYtHOE7LzZovjegq6i40NIf03Dtl\r\n\
r0VmhaJmGAhPF5k5ynqMP29XoE1p3PNZn42cgQK8O9/QiJNbAY0tX8FuJbdOJK7e\r\n\
DodA9FYVnMEa/SLs4UQybi3Hupny8VEL+yZGFKxgNfFAWe//+QWU0FtfQ1rTfaqU\r\n\
sBlc8Kzkjex7dfedLqlJPX8Hxn5kScPW+m+0ozBCdZ3TZDhDWdVSzzfx7LYvxkiT\r\n\
YlFXJ2K4FykKGlHrP7DEqF7ddliC2qcSffFaecWxt6NAdkfOKQJqjpwl/M3o7XGO\r\n\
rdcGuAECgYEAz+J+JcV5ts60EPZdcJ7yI+Sep8SlosGH1yo32ufs2lYDhLj8EC5M\r\n\
1KOGnpl8bsm3Rh8D2lnW8tHGIznoO9nInsDcG7FM28k9iYZAxAPxlHx3l7+twixS\r\n\
edc0jlTgpmjl4ruzZA3Yqqd+Br/Ga5BwHaftruCvMc2WXijW5TM6RIkCgYEAz5hR\r\n\
Ijcirxc61lRYjjwphwxDp7Wrgr+dHkH28IBrC5m7R+4GWIDlD4Xvic8Baohg17ta\r\n\
BFOtNDFnJE+ndFPW64Up38L+hHDyFlOUIlM9XBhFoHwQQeOX/+UIDJFTMZFVuzb7\r\n\
yZep4KV/pIwaVKnDZuuedCS2glEdXuRY9xqdrkECgYA3gQehWhpnPsVBCiZknWuV\r\n\
PcNGk/CNhhKY1kLXhbjtiq2h0Cosv8/vrkGRMvXQNrdiV4GV2QrVBkFawmlJIZq5\r\n\
GFEsa6hTvmVZxKiiLVNhC+J6d8kS4PacZWM45Vyd0cAfS3JYMoI4/kNd1fJKYeQt\r\n\
ZtrFKGRebb/KIClQRN830QKBgGRkB5BhU2+S70wo2+5k37xETQ90hm2jVksEoXOq\r\n\
1pl0jaH6VK1GH//CyJU/OzMWoqaRHrYK9S7RWUyxDIzv4nZhHl/sf4Lyz8/GOVPk\r\n\
Jz87KaizdnU2qBIC40KYoL/OxcPUkizqICfYQQMFEdKxiiJifW0zN+OLcIWsLe3J\r\n\
vElBAoGAGmFqRlswYnkGJigDI5g2LA7l92AXMSl2AKI9KI2z4BhQW4bFaVkBVNL5\r\n\
eO/eB0gia2XEfetPq5NJkl8tYSaxD43ktb5NChrCqHfTPjmo3oqvtAo28z7ZkPEX\r\n\
C2lY6WsD19SiiRJbUpeUzCLf3a1Tw/BSD4AZhOgzUP7dEl9D8n0=\r\n\
-----END RSA PRIVATE KEY-----\r\n\0\0";
const u8_t cert = "-----BEGIN CERTIFICATE-----\r\n\
MIIElTCCAn2gAwIBAgIJAI5nRyUnY3sYMA0GCSqGSIb3DQEBCwUAMIGSMQswCQYD\r\n\
VQQGEwJRRDEQMA4GA1UECAwHQmVpamluZzEQMA4GA1UEBwwHQmVpamluZzEPMA0G\r\n\
A1UECgwGbXlob21lMQ8wDQYDVQQLDAZteWhvbWUxGDAWBgNVBAMMD3F1ZG9uZ3No\r\n\
ZW5nLmNvbTEjMCEGCSqGSIb3DQEJARYUc2VsZkBxdWRvbmdzaGVuZy5jb20wHhcN\r\n\
MjAwNzA1MjMwNTMzWhcNMjExMTE3MjMwNTMzWjBhMQswCQYDVQQGEwJDTjEQMA4G\r\n\
A1UECAwHQmVpamluZzEQMA4GA1UEBwwHQmVpamluZzEUMBIGA1UECgwLc2llbWVu\r\n\
cy5jb20xGDAWBgNVBAMMD2xhYi5leGFtcGxlLmNvbTCCASIwDQYJKoZIhvcNAQEB\r\n\
BQADggEPADCCAQoCggEBAKiT1F3j3zLy+yQz8Pza28eI1552mXd/YNhRziSKl6mY\r\n\
uqyau1izWvSHHtVRrxhzIBu5d8TbpTLTRNrNsHUeWKytdxVsCnlQo96EneYekTaJ\r\n\
9kibn7yW/+C8wgcXGJ9VzRzN89ymZ1xXURWDx+iXvhpRIYTd/hl/cMpuq1spkJ0i\r\n\
cBNqu65AihQGj+jiZxyeg/2ndvxO20WajpANafw5X8ah1ZsKRQ5+SbOrEiZYBtST\r\n\
qEVM5VA5bWwvLKl/Uua2RQhFgj7dz3RF5tzZl1pm4NPuNecF0rWp4CK/jvwavIen\r\n\
VLy+SY0ZwwUNMlmG6HSYTA5AiweRO45hiP3m5I5lhMkCAwEAAaMeMBwwGgYDVR0R\r\n\
BBMwEYIPbGFiLmV4YW1wbGUuY29tMA0GCSqGSIb3DQEBCwUAA4ICAQCszdJ0EXbv\r\n\
FGmG7/DxppO22bEJsQ7MK6XNmHTAN31x3KDyg+0x5RcVC5chvPv3+6rSeykIeA1E\r\n\
L3vSTmTrOqHsjZaQb+zY9CgC+IBLJKvM75Eifk0mZOZdMH72GezGAaH+WSSoRuME\r\n\
8S+3gyOauOJ9H6yDVS2j5WxfUWo1Nt6DlZgkDYxGO1cXtsWW6t3/ntC0jN6OdcKB\r\n\
JsZaSuvs/NgI+OgKUP7HefM/mJBrw0JNQNpCfpBW6hJbfzE+jGl4KFFhFMEQqUG2\r\n\
GkaoLe9B+66HyRnkEqNWinDSTXYvOjV4hMAEfljsOf7sjCzrKHpLN0a9snmpPCur\r\n\
a70aqgr08jtzzTdU3zr49oMMvPO9MqQvRmd5DYIhibZMGRByyUEZaorGCFlYbVP+\r\n\
IrcOp63yZS/tjUJgiFMDWD1UBKkyV4QR6d7JManA3KNwdML/G9eEWNzlZ3p8ebkT\r\n\
BZlHB0YW57TeRBDsB6vHuillYsLgv2hgj5JIiHDSYMjqfwmPZ9i1+pOnf/kbq8/P\r\n\
iUMQdUn/ViSv+wUebu07MaujmAC9h0nlLnhFGgPSSCqzKYPIC1v7CfJ2Jwop7sY+\r\n\
ZDvWah/enUB8L4TNlkzFR/Aq6lAAA875vGKdjrhPa7bjLy0M08b1glzgYBT5AGaj\r\n\
nVGxmpbGngECdOA2o/Cf1QeLTEnXuCTH6w==\r\n\
-----END CERTIFICATE-----\r\n\0\0";
The libwebsocktes code is as following:
int lwsDemo(void)
{
// server url will be http://localhost:9000
int port = 60002;
struct lws_context * context;
struct lws_context_creation_info context_info = { .port = port,
.iface = NULL,
.protocols = protocols_ws,
.extensions = NULL,
.ssl_cert_filepath = NULL,
.ssl_private_key_filepath = NULL,
.ssl_ca_filepath = NULL,
.server_ssl_cert_mem = cert,
.server_ssl_cert_mem_len = sizeof(cert),
.server_ssl_private_key_mem = privkey,
.server_ssl_private_key_mem_len = sizeof(privkey),
.gid = -1,
.uid = -1,
.options = LWS_SERVER_OPTION_DO_SSL_GLOBAL_INIT | LWS_SERVER_OPTION_REQUIRE_VALID_OPENSSL_CLIENT_CERT,
.ka_time = 0,
.ka_probes = 0,
.ka_interval = 0 };
// create lws context representing this server
context = lws_create_context(&context_info);
TraceInit(websocket_send);
if (context == NULL)
{
LWIP_info(stderr, "lws init failed\n");
return -1;
}
LWIP_info("starting server...\n");
// infinite loop, to end this server send SIGTERM. (CTRL+C)
while (1)
{
lws_service(context, 50);
// lws_service will process all waiting events with their
// callback functions and then wait 50 ms.
// (this is a single threaded webserver and this will keep our server
// from generating load while there are not requests to process)
}
lws_context_destroy(context);
return 0;
}
The ssl_pm_new function(which is in libwebsockets,ssl_pm.c) is as following:
int ssl_pm_new(SSL *ssl)
{
struct ssl_pm *ssl_pm;
int ret;
const unsigned char pers[] = "OpenSSL PM";
size_t pers_len = sizeof(pers);
int endpoint;
int version;
const SSL_METHOD *method = ssl->method;
ssl_pm = ssl_mem_zalloc(sizeof(struct ssl_pm));
if (!ssl_pm) {
SSL_DEBUG(SSL_PLATFORM_ERROR_LEVEL, "no enough memory > (ssl_pm)");
goto no_mem;
}
ssl_pm->owner = ssl;
if (!ssl->ctx->read_buffer_len)
ssl->ctx->read_buffer_len = 2048;
max_content_len = (unsigned int)ssl->ctx->read_buffer_len;
// printf("ssl->ctx->read_buffer_len = %d ++++++++++++++++++++\n", ssl->ctx->read_buffer_len);
//mbedtls_net_init(NULL);
//mbedtls_net_init(NULL);
//ssl_pm->fd.fd = -1;
//ssl_pm->cl_fd.fd = -1;
mbedtls_ssl_config_init(&ssl_pm->conf);
mbedtls_ctr_drbg_init(&ssl_pm->ctr_drbg);
mbedtls_entropy_init(&ssl_pm->entropy);
mbedtls_ssl_init(&ssl_pm->ssl);
ret = mbedtls_ctr_drbg_seed(&ssl_pm->ctr_drbg, mbedtls_entropy_func, &ssl_pm->entropy, pers, pers_len);
if (ret) {
lwsl_notice("%s: mbedtls_ctr_drbg_seed() return -0x%x", __func__, -ret);
//goto mbedtls_err1;
}
if (method->endpoint) {
endpoint = MBEDTLS_SSL_IS_SERVER;
} else {
endpoint = MBEDTLS_SSL_IS_CLIENT;
}
ret = mbedtls_ssl_config_defaults(&ssl_pm->conf, endpoint, MBEDTLS_SSL_TRANSPORT_STREAM, MBEDTLS_SSL_PRESET_DEFAULT);
if (ret) {
lwsl_err("%s: mbedtls_ssl_config_defaults() return -0x%x", __func__, -ret);
SSL_DEBUG(SSL_PLATFORM_ERROR_LEVEL, "mbedtls_ssl_config_defaults() return -0x%x", -ret);
goto mbedtls_err2;
}
if (TLS_ANY_VERSION != ssl->version) {
if (TLS1_2_VERSION == ssl->version)
version = MBEDTLS_SSL_MINOR_VERSION_3;
else if (TLS1_1_VERSION == ssl->version)
version = MBEDTLS_SSL_MINOR_VERSION_2;
else if (TLS1_VERSION == ssl->version)
version = MBEDTLS_SSL_MINOR_VERSION_1;
else
version = MBEDTLS_SSL_MINOR_VERSION_0;
mbedtls_ssl_conf_max_version(&ssl_pm->conf, MBEDTLS_SSL_MAJOR_VERSION_3, version);
mbedtls_ssl_conf_min_version(&ssl_pm->conf, MBEDTLS_SSL_MAJOR_VERSION_3, version);
} else {
mbedtls_ssl_conf_max_version(&ssl_pm->conf, MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3);
mbedtls_ssl_conf_min_version(&ssl_pm->conf, MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_0);
}
mbedtls_ssl_conf_rng(&ssl_pm->conf, mbedtls_ctr_drbg_random, &ssl_pm->ctr_drbg);
//#ifdef CONFIG_OPENSSL_LOWLEVEL_DEBUG
// mbedtls_debug_set_threshold(MBEDTLS_DEBUG_LEVEL);
// mbedtls_ssl_conf_dbg(&ssl_pm->conf, ssl_platform_debug, NULL);
//#else
mbedtls_ssl_conf_dbg(&ssl_pm->conf, ssl_platform_debug, NULL);
//#endif
ret = mbedtls_ssl_setup(&ssl_pm->ssl, &ssl_pm->conf);
if (ret) {
lwsl_err("%s: mbedtls_ssl_setup() return -0x%x", __func__, -ret);
SSL_DEBUG(SSL_PLATFORM_ERROR_LEVEL, "mbedtls_ssl_setup() return -0x%x", -ret);
goto mbedtls_err2;
}
// mbedtls_ssl_set_bio(&ssl_pm->ssl, &ssl_pm->fd, mbedtls_net_send, mbedtls_net_recv, NULL);
mbedtls_ssl_set_bio(&ssl_pm->ssl, &ssl_pm->fd, altcp_mbedtls_bio_send, altcp_mbedtls_bio_recv, NULL);
//mbedtls_ssl_set_bio(&ssl_pm->ssl, &(ssl_pm->fd), mbedtls_net_send, mbedtls_net_recv, NULL);
ssl->ssl_pm = ssl_pm;
return 0;
mbedtls_err2:
mbedtls_ssl_config_free(&ssl_pm->conf);
mbedtls_ctr_drbg_free(&ssl_pm->ctr_drbg);
//mbedtls_err1:
mbedtls_entropy_free(&ssl_pm->entropy);
ssl_mem_free(ssl_pm);
no_mem:
return -1;
}
The altcp_mbedtls_bio_recv function(which is in lwip,altcp_tls_mbedtls.c) is as following:
int altcp_mbedtls_bio_recv(void *ctx, unsigned char *buf, size_t len)
{
struct altcp_pcb *conn = (struct altcp_pcb *)ctx;
altcp_mbedtls_state_t *state;
struct pbuf *p;
u16_t ret;
u16_t copy_len;
err_t err;
LWIP_UNUSED_ARG(err); /* for LWIP_NOASSERT */
if ((conn == NULL) || (conn->state == NULL)) {
return MBEDTLS_ERR_NET_INVALID_CONTEXT;
}
state = (altcp_mbedtls_state_t *)conn->state;
p = state->rx;
/* @todo: return MBEDTLS_ERR_NET_CONN_RESET/MBEDTLS_ERR_NET_RECV_FAILED? */
if ((p == NULL) || ((p->len == 0) && (p->next == NULL))) {
if (p) {
pbuf_free(p);
}
state->rx = NULL;
if ((state->flags & (ALTCP_MBEDTLS_FLAGS_RX_CLOSE_QUEUED | ALTCP_MBEDTLS_FLAGS_RX_CLOSED)) ==
ALTCP_MBEDTLS_FLAGS_RX_CLOSE_QUEUED) {
/* close queued but not passed up yet */
return 0;
}
return MBEDTLS_ERR_SSL_WANT_READ;
}
/* limit number of bytes again to copy from first pbuf in a chain only */
copy_len = (u16_t)LWIP_MIN(len, p->len);
/* copy the data */
ret = pbuf_copy_partial(p, buf, copy_len, 0);
LWIP_ASSERT(“ret == copy_len”, ret == copy_len);
/* hide the copied bytes from the pbuf */
err = pbuf_remove_header(p, ret);
LWIP_ASSERT(“error”, err == ERR_OK);
if (p->len == 0) {
/* the first pbuf has been fully read, free it */
state->rx = p->next;
p->next = NULL;
pbuf_free(p);
}
state->bio_bytes_read += (int)ret;
return ret;
}