dtls_session_t *_DTLSSession_init() { dtls_session_t *p_dtls_session = NULL; p_dtls_session = coap_malloc(sizeof(dtls_session_t)); mbedtls_debug_set_threshold(0); mbedtls_platform_set_calloc_free(_DTLSCalloc_wrapper, _DTLSFree_wrapper); if (NULL != p_dtls_session) { mbedtls_net_init(&p_dtls_session->fd); mbedtls_ssl_init(&p_dtls_session->context); mbedtls_ssl_config_init(&p_dtls_session->conf); mbedtls_net_init(&p_dtls_session->fd); mbedtls_ssl_cookie_init(&p_dtls_session->cookie_ctx); #ifdef MBEDTLS_X509_CRT_PARSE_C mbedtls_x509_crt_init(&p_dtls_session->cacert); #endif mbedtls_ctr_drbg_init(&p_dtls_session->ctr_drbg); mbedtls_entropy_init(&p_dtls_session->entropy); DTLS_INFO("HAL_DTLSSession_init success\r\n"); } return p_dtls_session; }
int iot_tls_init(Network *pNetwork) { IoT_Error_t ret_val = NONE_ERROR; const char *pers = "aws_iot_tls_wrapper"; unsigned char buf[MBEDTLS_SSL_MAX_CONTENT_LEN + 1]; mbedtls_net_init(&server_fd); mbedtls_ssl_init(&ssl); mbedtls_ssl_config_init(&conf); mbedtls_ctr_drbg_init(&ctr_drbg); mbedtls_x509_crt_init(&cacert); mbedtls_x509_crt_init(&clicert); mbedtls_pk_init(&pkey); DEBUG("\n . Seeding the random number generator..."); mbedtls_entropy_init(&entropy); if ((ret_val = mbedtls_ctr_drbg_seed(&ctr_drbg, mbedtls_entropy_func, &entropy, (const unsigned char *) pers, strlen(pers))) != 0) { ERROR(" failed\n ! mbedtls_ctr_drbg_seed returned -0x%x\n", -ret); return ret; } DEBUG("ok\n"); pNetwork->my_socket = 0; pNetwork->connect = iot_tls_connect; pNetwork->mqttread = iot_tls_read; pNetwork->mqttwrite = iot_tls_write; pNetwork->disconnect = iot_tls_disconnect; pNetwork->isConnected = iot_tls_is_connected; pNetwork->destroy = iot_tls_destroy; return ret_val; }
static int tls_server_accept(void) { int ret; mbedtls_net_context client; mbedtls_net_init(&client); ret = mbedtls_net_accept(&stls.fd, &client, NULL, 0, NULL); if (ret || ccnt >= MAXCLIENTS) { printf("max clients\n"); goto err; } struct client *c = ctls + ccnt; c->fd = client; mbedtls_ssl_init(&c->ssl); ret = mbedtls_ssl_setup(&c->ssl, &stls.conf); if (ret) { printf("cannot setup the ssl session\n"); goto err; } mbedtls_ssl_set_bio(&c->ssl, &c->fd, mbedtls_net_send, mbedtls_net_recv, NULL); c->handler = tls_client_handshake; ccnt++; return 0; err: mbedtls_net_free(&client); return -1; }
static void mbedtls_msg_server_step(pmbedtls_msg msg) { lwIP_ASSERT(msg); /*to prevent memory leaks, ensure that each allocated is deleted at every handshake*/ if (msg->psession){ mbedtls_session_free(&msg->psession); } #if defined(ESP8266_PLATFORM) if (msg->quiet && msg->ssl.out_buf) { mbedtls_zeroize(msg->ssl.out_buf, MBEDTLS_SSL_OUTBUFFER_LEN); os_free(msg->ssl.out_buf); msg->ssl.out_buf = NULL; } #endif mbedtls_entropy_free(&msg->entropy); mbedtls_ssl_free(&msg->ssl); mbedtls_ssl_config_free(&msg->conf); mbedtls_ctr_drbg_free(&msg->ctr_drbg); /*New connection ensure that each initial for next handshake */ os_bzero(msg, sizeof(mbedtls_msg)); msg->psession = mbedtls_session_new(); if (msg->psession){ mbedtls_net_init(&msg->fd); mbedtls_ssl_init(&msg->ssl); mbedtls_ssl_config_init(&msg->conf); mbedtls_ctr_drbg_init(&msg->ctr_drbg); mbedtls_entropy_init(&msg->entropy); } }
void* ssl_socket_init(int fd, const char *domain) { struct ssl_state *state = (struct ssl_state*)calloc(1, sizeof(*state)); state->domain = domain; mbedtls_debug_set_threshold(DEBUG_LEVEL); mbedtls_net_init(&state->net_ctx); mbedtls_ssl_init(&state->ctx); mbedtls_ssl_config_init(&state->conf); #if defined(MBEDTLS_X509_CRT_PARSE_C) mbedtls_x509_crt_init(&state->ca); #endif mbedtls_ctr_drbg_init(&state->ctr_drbg); mbedtls_entropy_init(&state->entropy); state->net_ctx.fd = fd; if (mbedtls_ctr_drbg_seed(&state->ctr_drbg, mbedtls_entropy_func, &state->entropy, (const unsigned char*)pers, strlen(pers)) != 0) goto error; #if defined(MBEDTLS_X509_CRT_PARSE_C) if (mbedtls_x509_crt_parse(&state->ca, (const unsigned char*)cacert_pem, sizeof(cacert_pem) / sizeof(cacert_pem[0])) < 0) goto error; #endif return state; error: if (state) free(state); return NULL; }
// コンテキストを初期化します。 // mtls_alloc() に続いてコールしてください。 // 成功すれば 0、失敗すれば -1 を返します。 int mtls_init(mtlsctx_t* ctx) { int r; TRACE("start\n"); // グローバルコンテキストの初期化 if (gctx.initialized == 0) { mbedtls_ctr_drbg_init(&gctx.ctr_drbg); mbedtls_entropy_init(&gctx.entropy); // init RNG r = mbedtls_ctr_drbg_seed(&gctx.ctr_drbg, mbedtls_entropy_func, &gctx.entropy, "a", 1); if (r != 0) { ERROR("mbedtls_ctr_drbg_seed failed: %s\n", mtls_errmsg(r)); goto errexit; } gctx.initialized = 1; } ctx->usessl = 0; mbedtls_net_init(&ctx->net); mbedtls_ssl_init(&ctx->ssl); mbedtls_ssl_config_init(&ctx->conf); // TLS config r = mbedtls_ssl_config_defaults(&ctx->conf, MBEDTLS_SSL_IS_CLIENT, MBEDTLS_SSL_TRANSPORT_STREAM, MBEDTLS_SSL_PRESET_DEFAULT); if (r != 0) { ERROR("mbedtls_ssl_config_defaults failed: %s\n", mtls_errmsg(r)); goto errexit; } mbedtls_ssl_conf_authmode(&ctx->conf, MBEDTLS_SSL_VERIFY_NONE); mbedtls_ssl_conf_rng(&ctx->conf, mbedtls_ctr_drbg_random, &gctx.ctr_drbg); mbedtls_ssl_conf_dbg(&ctx->conf, debug_callback, stderr); r = mbedtls_ssl_setup(&ctx->ssl, &ctx->conf); if (r != 0) { ERROR("mbedtls_ssl_setup failed: %s\n", mtls_errmsg(r)); goto errexit; } mbedtls_ssl_set_bio(&ctx->ssl, &ctx->net, mbedtls_net_send, mbedtls_net_recv, NULL); ctx->initialized = 1; TRACE("done\n"); return 0; errexit: // cleanup TRACE("NG\n"); return -1; }
static void tls_server_init(struct server *s) { mbedtls_net_init(&s->fd); mbedtls_entropy_init(&s->entropy); mbedtls_ctr_drbg_init(&s->ctr_drbg); mbedtls_ssl_config_init(&s->conf); mbedtls_x509_crt_init(&s->cacert); mbedtls_x509_crt_init(&s->srvcert); mbedtls_pk_init(&s->pkey); }
static void ssl_init( SSLExt* ext ) { mbedtls_net_init( &ext->nc ); mbedtls_ssl_init( &ext->sc ); mbedtls_ssl_config_init( &ext->conf ); mbedtls_ctr_drbg_init( &ext->ctr_drbg ); mbedtls_entropy_init( &ext->entropy ); //mbedtls_x509_crt_init( &ext->cacert ); }
static void broker_server_new_client(uv_poll_t *poll, int status, int events) { (void) status; (void) events; Server *server = poll->data; Client *client = dslink_calloc(1, sizeof(Client)); if (!client) { goto fail; } client->server = server; client->sock = dslink_socket_init(0); if (!client->sock) { dslink_free(client); goto fail; } if (mbedtls_net_accept(&server->srv, &client->sock->socket_ctx, NULL, 0, NULL) != 0) { log_warn("Failed to accept a client connection\n"); goto fail_poll_setup; } uv_poll_t *clientPoll = dslink_malloc(sizeof(uv_poll_t)); if (!clientPoll) { goto fail_poll_setup; } uv_loop_t *loop = poll->loop; if (uv_poll_init(loop, clientPoll, client->sock->socket_ctx.fd) != 0) { dslink_free(clientPoll); goto fail_poll_setup; } clientPoll->data = client; client->poll = clientPoll; uv_poll_start(clientPoll, UV_READABLE, broker_server_client_ready); log_debug("Accepted a client connection\n"); return; fail: { mbedtls_net_context tmp; mbedtls_net_init(&tmp); mbedtls_net_accept(&server->srv, &tmp, NULL, 0, NULL); mbedtls_net_free(&tmp); } return; fail_poll_setup: dslink_socket_free(client->sock); dslink_free(client); }
/** * @brief Initation the SSL client. * @param[in] ssl: mbedtls ssl struct. * @param[in] tcp_fd. The underlying file descriptor. * @param[in] custom_config: custome config. * @return The result. 0 is ok. */ static int nghttp2_ssl_client_init(mbedtls_ssl_context *ssl, mbedtls_net_context *tcp_fd, http2_ssl_custom_conf_t *custom_config) { int ret = -1; http2_verify_source_t *verify_source = &custom_config->verify_source; mbedtls_ssl_config *conf = &(custom_config->conf); /* * 0. Initialize the RNG and the session data */ #if defined(MBEDTLS_DEBUG_C) mbedtls_debug_set_threshold(DEBUG_LEVEL); #endif mbedtls_net_init( tcp_fd ); mbedtls_ssl_init( ssl ); mbedtls_ssl_config_init( conf ); mbedtls_x509_crt_init( &(verify_source->cacertl) ); mbedtls_ctr_drbg_init( &ctr_drbg ); NGHTTP2_DBG( "\n . Seeding the random number generator..." ); mbedtls_entropy_init( &entropy ); if ( ( ret = mbedtls_ctr_drbg_seed( &ctr_drbg, mbedtls_entropy_func, &entropy, (const unsigned char *) pers, strlen( pers ) ) ) != 0 ) { NGHTTP2_DBG( " failed\n ! mbedtls_ctr_drbg_seed returned %d\n", ret ); return ret; } NGHTTP2_DBG( " ok\n" ); /* * 0. Initialize certificates */ NGHTTP2_DBG( " . Loading the CA root certificate ..." ); if (NULL != verify_source->trusted_ca_crt) { if (0 != (ret = mbedtls_x509_crt_parse(&verify_source->cacertl, (unsigned char *)verify_source->trusted_ca_crt, strlen(verify_source->trusted_ca_crt) + 1))) { NGHTTP2_DBG(" failed ! x509parse_crt returned -0x%04x", -ret); return ret; } } NGHTTP2_DBG( " ok (%d skipped)", ret ); return 0; }
static pmbedtls_msg mbedtls_msg_new(void) { pmbedtls_msg msg = (pmbedtls_msg)os_zalloc( sizeof(mbedtls_msg)); if (msg) { os_bzero(msg, sizeof(mbedtls_msg)); msg->psession = mbedtls_session_new(); if (msg->psession){ mbedtls_net_init(&msg->listen_fd); mbedtls_net_init(&msg->fd); mbedtls_ssl_init(&msg->ssl); mbedtls_ssl_config_init(&msg->conf); mbedtls_ctr_drbg_init(&msg->ctr_drbg); mbedtls_entropy_init(&msg->entropy); } else{ os_free(msg); msg = NULL; } } return msg; }
static int dslink_socket_connect_insecure(Socket *sock, const char *address, unsigned short port) { mbedtls_net_init(sock->socket_fd); char num[6]; snprintf(num, sizeof(num), "%d", port); if ((errno = mbedtls_net_connect(sock->socket_fd, address, num, MBEDTLS_NET_PROTO_TCP)) != 0) { return DSLINK_SOCK_CONNECT_ERR; } return 0; }
void conn_link_init_and_check(struct conn_link_s *link, size_t structsize) { DEBUGASSERT(structsize >= sizeof(*link)); memset(link, 0, sizeof(*link)); link->sock = -1; #ifdef CONFIG_THINGSEE_HTTPS_PROTOCOL #ifdef CONFIG_MBEDTLS mbedtls_net_init(&link->net); #endif #endif }
void ssl_init(SSLConnection* conn) { /* * Initialize the RNG and the session data */ mbedtls_net_init(&conn->net_ctx); mbedtls_ssl_init(&conn->ssl_ctx); mbedtls_ssl_config_init(&conn->ssl_conf); mbedtls_x509_crt_init(&conn->ca_cert); mbedtls_x509_crt_init(&conn->client_cert); mbedtls_pk_init(&conn->client_key); mbedtls_ctr_drbg_init(&conn->drbg_ctx); mbedtls_entropy_init(&conn->entropy_ctx); }
static int connect_to_new_client(mbedtls_net_context* client_fd, const struct sockaddr_storage *client_addr, const socklen_t client_addr_size, const struct sockaddr_storage *local_addr, const socklen_t local_addr_size) { int ret = 0; int one = 1; mbedtls_net_init(client_fd); client_fd->fd = socket(client_addr->ss_family, SOCK_DGRAM, IPPROTO_UDP); if (client_fd->fd < 0) { log_error("socket() failed errno=%d", ret, errno); return 1; } #ifdef __APPLE__ // MacOS/X requires an additional call ret = setsockopt(client_fd->fd, SOL_SOCKET, SO_REUSEPORT, (char*)&one, sizeof(one)); if (ret != 0) { log_error("setsockopt(SO_REUSEPORT) failed ret=%d errno=%d", ret, errno); return 1; } #endif ret = setsockopt(client_fd->fd, SOL_SOCKET, SO_REUSEADDR, (const char *)&one, sizeof(one)); if (ret != 0) { log_error("setsockopt(SO_REUSEADDR) failed ret=%d errno=%d", ret, errno); return 1; } mbedtls_net_set_nonblock(client_fd); ret = bind(client_fd->fd, (struct sockaddr *)local_addr, local_addr_size); if (ret != 0) { log_error("bind() fd=%d failed ret=%d errno=%d", client_fd->fd, ret, errno); return 1; } ret = connect(client_fd->fd, (struct sockaddr *)client_addr, client_addr_size); if (ret != 0) { log_error("connect() failed ret=%d errno=%d", ret, errno); return 1; } log_debug("connect_to_new_client: connected on fd %d", client_fd->fd); return 0; }
static Socket *dslink_socket_init(uint_fast8_t secure) { if (secure) { SslSocket *s = malloc(sizeof(SslSocket)); if (!s) { return NULL; } s->secure = 1; s->socket_fd = malloc(sizeof(mbedtls_net_context)); s->entropy = malloc(sizeof(mbedtls_entropy_context)); s->drbg = malloc(sizeof(mbedtls_ctr_drbg_context)); s->ssl = malloc(sizeof(mbedtls_ssl_context)); s->conf = malloc(sizeof(mbedtls_ssl_config)); if (!(s->socket_fd && s->entropy && s->drbg && s->ssl && s->conf)) { DSLINK_CHECKED_EXEC(free, s->socket_fd); DSLINK_CHECKED_EXEC(free, s->entropy); DSLINK_CHECKED_EXEC(free, s->drbg); DSLINK_CHECKED_EXEC(free, s->ssl); DSLINK_CHECKED_EXEC(free, s->conf); free(s); return NULL; } mbedtls_net_init(s->socket_fd); mbedtls_entropy_init(s->entropy); mbedtls_ctr_drbg_init(s->drbg); mbedtls_ssl_init(s->ssl); mbedtls_ssl_config_init(s->conf); return (Socket *) s; } else { Socket *s = malloc(sizeof(Socket)); if (!s) { return NULL; } s->secure = 0; s->socket_fd = malloc(sizeof(mbedtls_net_context)); if (!s->socket_fd) { free(s); return NULL; } return s; } }
int websocket_server_authenticate(websocket_t *server) { int r; if (server->tls_enabled) { server->tls_ssl = malloc(sizeof(mbedtls_ssl_context)); if (server->tls_ssl == NULL) { WEBSOCKET_DEBUG("fail to allocate memory for server\n"); r = WEBSOCKET_ALLOCATION_ERROR; goto EXIT_SERVER_START; } mbedtls_ssl_init(server->tls_ssl); mbedtls_net_init(&(server->tls_net)); if ((r = websocket_tls_handshake(server, NULL, server->auth_mode)) != WEBSOCKET_SUCCESS) { WEBSOCKET_DEBUG("fail to tls handshake\n"); r = WEBSOCKET_TLS_HANDSHAKE_ERROR; goto EXIT_SERVER_START; } } if (websocket_server_handshake(server) != WEBSOCKET_SUCCESS) { WEBSOCKET_DEBUG("fail to handshake\n"); r = WEBSOCKET_HANDSHAKE_ERROR; goto EXIT_SERVER_START; } return websocket_server_init(server); EXIT_SERVER_START: WEBSOCKET_CLOSE(server->fd); if (server->tls_enabled) { mbedtls_ssl_free(server->tls_ssl); mbedtls_net_free(&(server->tls_net)); WEBSOCKET_FREE(server->tls_ssl); } websocket_update_state(server, WEBSOCKET_STOP); return r; }
static int session_init(const global_context *gc, session_context *sc, const mbedtls_net_context *client_fd, unsigned char client_ip[16], size_t cliip_len, const unsigned char* first_packet, size_t first_packet_len) { int ret; memset(sc, 0, sizeof(*sc)); memcpy(&sc->client_fd, client_fd, sizeof(sc->client_fd)); if (cliip_len > sizeof(sc->client_ip)) { log_error("session_init - client_ip size mismatch"); return 1; } memcpy(&sc->client_ip, client_ip, cliip_len); sc->cliip_len = cliip_len; mbedtls_ssl_init(&sc->ssl); mbedtls_net_init(&sc->backend_fd); sc->step = GOLDY_SESSION_STEP_HANDSHAKE; sc->options = gc->options; if ((ret = mbedtls_ssl_setup(&sc->ssl, &gc->conf)) != 0) { check_return_code(ret, "session_init - mbedtls_ssl_steup"); return 1; } //mbedtls_ssl_set_hostname(&sc->ssl, "localhost"); mbedtls_ssl_set_timer_cb(&sc->ssl, &sc->timer, mbedtls_timing_set_delay, mbedtls_timing_get_delay); /* We already read the first packet of the SSL session from the network in * the initial recvfrom() call on the listening fd. Here we copy the content * of that packet into the SSL incoming data buffer so it'll be consumed on * the next call to mbedtls_ssl_fetch_input(). */ if (first_packet_len<MBEDTLS_SSL_BUFFER_LEN) { memcpy(sc->ssl.in_hdr, first_packet, first_packet_len); sc->ssl.in_left = first_packet_len; } return 0; }
int main( void ) { int ret; mbedtls_net_context listen_fd, client_fd; const char pers[] = "ssl_pthread_server"; mbedtls_entropy_context entropy; mbedtls_ctr_drbg_context ctr_drbg; mbedtls_ssl_config conf; mbedtls_x509_crt srvcert; mbedtls_x509_crt cachain; mbedtls_pk_context pkey; #if defined(MBEDTLS_MEMORY_BUFFER_ALLOC_C) unsigned char alloc_buf[100000]; #endif #if defined(MBEDTLS_SSL_CACHE_C) mbedtls_ssl_cache_context cache; #endif #if defined(MBEDTLS_MEMORY_BUFFER_ALLOC_C) mbedtls_memory_buffer_alloc_init( alloc_buf, sizeof(alloc_buf) ); #endif #if defined(MBEDTLS_SSL_CACHE_C) mbedtls_ssl_cache_init( &cache ); #endif mbedtls_x509_crt_init( &srvcert ); mbedtls_x509_crt_init( &cachain ); mbedtls_ssl_config_init( &conf ); mbedtls_ctr_drbg_init( &ctr_drbg ); memset( threads, 0, sizeof(threads) ); mbedtls_net_init( &listen_fd ); mbedtls_net_init( &client_fd ); mbedtls_mutex_init( &debug_mutex ); base_info.config = &conf; /* * We use only a single entropy source that is used in all the threads. */ mbedtls_entropy_init( &entropy ); /* * 1. Load the certificates and private RSA key */ mbedtls_printf( "\n . Loading the server cert. and key..." ); fflush( stdout ); /* * This demonstration program uses embedded test certificates. * Instead, you may want to use mbedtls_x509_crt_parse_file() to read the * server and CA certificates, as well as mbedtls_pk_parse_keyfile(). */ ret = mbedtls_x509_crt_parse( &srvcert, (const unsigned char *) mbedtls_test_srv_crt, mbedtls_test_srv_crt_len ); if( ret != 0 ) { mbedtls_printf( " failed\n ! mbedtls_x509_crt_parse returned %d\n\n", ret ); goto exit; } ret = mbedtls_x509_crt_parse( &cachain, (const unsigned char *) mbedtls_test_cas_pem, mbedtls_test_cas_pem_len ); if( ret != 0 ) { mbedtls_printf( " failed\n ! mbedtls_x509_crt_parse returned %d\n\n", ret ); goto exit; } mbedtls_pk_init( &pkey ); ret = mbedtls_pk_parse_key( &pkey, (const unsigned char *) mbedtls_test_srv_key, mbedtls_test_srv_key_len, NULL, 0 ); if( ret != 0 ) { mbedtls_printf( " failed\n ! mbedtls_pk_parse_key returned %d\n\n", ret ); goto exit; } mbedtls_printf( " ok\n" ); /* * 1b. Seed the random number generator */ mbedtls_printf( " . Seeding the random number generator..." ); if( ( ret = mbedtls_ctr_drbg_seed( &ctr_drbg, mbedtls_entropy_func, &entropy, (const unsigned char *) pers, strlen( pers ) ) ) != 0 ) { mbedtls_printf( " failed: mbedtls_ctr_drbg_seed returned -0x%04x\n", -ret ); goto exit; } mbedtls_printf( " ok\n" ); /* * 1c. Prepare SSL configuration */ mbedtls_printf( " . Setting up the SSL data...." ); if( ( ret = mbedtls_ssl_config_defaults( &conf, MBEDTLS_SSL_IS_SERVER, MBEDTLS_SSL_TRANSPORT_STREAM, MBEDTLS_SSL_PRESET_DEFAULT ) ) != 0 ) { mbedtls_printf( " failed: mbedtls_ssl_config_defaults returned -0x%04x\n", -ret ); goto exit; } mbedtls_ssl_conf_rng( &conf, mbedtls_ctr_drbg_random, &ctr_drbg ); mbedtls_ssl_conf_dbg( &conf, my_mutexed_debug, stdout ); /* mbedtls_ssl_cache_get() and mbedtls_ssl_cache_set() are thread-safe if * MBEDTLS_THREADING_C is set. */ #if defined(MBEDTLS_SSL_CACHE_C) mbedtls_ssl_conf_session_cache( &conf, &cache, mbedtls_ssl_cache_get, mbedtls_ssl_cache_set ); #endif mbedtls_ssl_conf_ca_chain( &conf, &cachain, NULL ); if( ( ret = mbedtls_ssl_conf_own_cert( &conf, &srvcert, &pkey ) ) != 0 ) { mbedtls_printf( " failed\n ! mbedtls_ssl_conf_own_cert returned %d\n\n", ret ); goto exit; } mbedtls_printf( " ok\n" ); /* * 2. Setup the listening TCP socket */ mbedtls_printf( " . Bind on https://localhost:4433/ ..." ); fflush( stdout ); if( ( ret = mbedtls_net_bind( &listen_fd, NULL, "4433", MBEDTLS_NET_PROTO_TCP ) ) != 0 ) { mbedtls_printf( " failed\n ! mbedtls_net_bind returned %d\n\n", ret ); goto exit; } mbedtls_printf( " ok\n" ); reset: #ifdef MBEDTLS_ERROR_C if( ret != 0 ) { char error_buf[100]; mbedtls_strerror( ret, error_buf, 100 ); mbedtls_printf( " [ main ] Last error was: -0x%04x - %s\n", -ret, error_buf ); } #endif /* * 3. Wait until a client connects */ mbedtls_printf( " [ main ] Waiting for a remote connection\n" ); if( ( ret = mbedtls_net_accept( &listen_fd, &client_fd, NULL, 0, NULL ) ) != 0 ) { mbedtls_printf( " [ main ] failed: mbedtls_net_accept returned -0x%04x\n", ret ); goto exit; } mbedtls_printf( " [ main ] ok\n" ); mbedtls_printf( " [ main ] Creating a new thread\n" ); if( ( ret = thread_create( &client_fd ) ) != 0 ) { mbedtls_printf( " [ main ] failed: thread_create returned %d\n", ret ); mbedtls_net_free( &client_fd ); goto reset; } ret = 0; goto reset; exit: mbedtls_x509_crt_free( &srvcert ); mbedtls_pk_free( &pkey ); #if defined(MBEDTLS_SSL_CACHE_C) mbedtls_ssl_cache_free( &cache ); #endif mbedtls_ctr_drbg_free( &ctr_drbg ); mbedtls_entropy_free( &entropy ); mbedtls_ssl_config_free( &conf ); mbedtls_net_free( &listen_fd ); mbedtls_mutex_free( &debug_mutex ); #if defined(MBEDTLS_MEMORY_BUFFER_ALLOC_C) mbedtls_memory_buffer_alloc_free(); #endif #if defined(_WIN32) mbedtls_printf( " Press Enter to exit this program.\n" ); fflush( stdout ); getchar(); #endif return( ret ); }
int broker_start_server(json_t *config) { json_incref(config); const char *httpHost = NULL; char httpPort[8]; memset(httpPort, 0, sizeof(httpPort)); { json_t *http = json_object_get(config, "http"); if (http) { json_t *enabled = json_object_get(http, "enabled"); if (!(enabled && json_boolean_value(enabled))) { json_decref(config); return 0; } httpHost = json_string_value(json_object_get(http, "host")); json_t *jsonPort = json_object_get(http, "port"); if (jsonPort) { json_int_t p = json_integer_value(jsonPort); int len = snprintf(httpPort, sizeof(httpPort) - 1, "%" JSON_INTEGER_FORMAT, p); httpPort[len] = '\0'; } } } int httpActive = 0; Server httpServer; uv_poll_t httpPoll; if (httpHost && httpPort[0] != '\0') { mbedtls_net_init(&httpServer.srv); httpServer.data_ready = broker_on_data_callback; httpActive = start_http_server(&httpServer, httpHost, httpPort, mainLoop, &httpPoll); } uv_signal_t sigInt; uv_signal_init(mainLoop, &sigInt); uv_signal_start(&sigInt, stop_server_handler, SIGINT); uv_signal_t sigTerm; uv_signal_init(mainLoop, &sigTerm); uv_signal_start(&sigTerm, stop_server_handler, SIGTERM); // upstream_connect_conn(&loop, "http://10.0.1.158:8080/conn", "dartbroker", "cbroker"); if (httpActive) { uv_run(mainLoop, UV_RUN_DEFAULT); } uv_signal_stop(&sigInt); uv_signal_stop(&sigTerm); if (httpActive) { uv_poll_stop(&httpPoll); } uv_loop_close(mainLoop); #if defined(__unix__) || defined(__APPLE__) if (mainLoop && mainLoop->watchers) { uv__free(mainLoop->watchers); } #endif json_decref(config); return 0; }
static void https_get_task(void *pvParameters) { char buf[512]; int ret, flags, len; mbedtls_entropy_context entropy; mbedtls_ctr_drbg_context ctr_drbg; mbedtls_ssl_context ssl; mbedtls_x509_crt cacert; mbedtls_ssl_config conf; mbedtls_net_context server_fd; mbedtls_ssl_init(&ssl); mbedtls_x509_crt_init(&cacert); mbedtls_ctr_drbg_init(&ctr_drbg); ESP_LOGI(TAG, "Seeding the random number generator"); mbedtls_ssl_config_init(&conf); mbedtls_entropy_init(&entropy); if((ret = mbedtls_ctr_drbg_seed(&ctr_drbg, mbedtls_entropy_func, &entropy, NULL, 0)) != 0) { ESP_LOGE(TAG, "mbedtls_ctr_drbg_seed returned %d", ret); abort(); } ESP_LOGI(TAG, "Loading the CA root certificate..."); ret = mbedtls_x509_crt_parse(&cacert, server_root_cert_pem_start, server_root_cert_pem_end-server_root_cert_pem_start); if(ret < 0) { ESP_LOGE(TAG, "mbedtls_x509_crt_parse returned -0x%x\n\n", -ret); abort(); } ESP_LOGI(TAG, "Setting hostname for TLS session..."); /* Hostname set here should match CN in server certificate */ if((ret = mbedtls_ssl_set_hostname(&ssl, WEB_SERVER)) != 0) { ESP_LOGE(TAG, "mbedtls_ssl_set_hostname returned -0x%x", -ret); abort(); } ESP_LOGI(TAG, "Setting up the SSL/TLS structure..."); if((ret = mbedtls_ssl_config_defaults(&conf, MBEDTLS_SSL_IS_CLIENT, MBEDTLS_SSL_TRANSPORT_STREAM, MBEDTLS_SSL_PRESET_DEFAULT)) != 0) { ESP_LOGE(TAG, "mbedtls_ssl_config_defaults returned %d", ret); goto exit; } /* MBEDTLS_SSL_VERIFY_OPTIONAL is bad for security, in this example it will print a warning if CA verification fails but it will continue to connect. You should consider using MBEDTLS_SSL_VERIFY_REQUIRED in your own code. */ mbedtls_ssl_conf_authmode(&conf, MBEDTLS_SSL_VERIFY_OPTIONAL); mbedtls_ssl_conf_ca_chain(&conf, &cacert, NULL); mbedtls_ssl_conf_rng(&conf, mbedtls_ctr_drbg_random, &ctr_drbg); #ifdef CONFIG_MBEDTLS_DEBUG mbedtls_esp_enable_debug_log(&conf, 4); #endif if ((ret = mbedtls_ssl_setup(&ssl, &conf)) != 0) { ESP_LOGE(TAG, "mbedtls_ssl_setup returned -0x%x\n\n", -ret); goto exit; } while(1) { /* Wait for the callback to set the CONNECTED_BIT in the event group. */ xEventGroupWaitBits(wifi_event_group, CONNECTED_BIT, false, true, portMAX_DELAY); ESP_LOGI(TAG, "Connected to AP"); mbedtls_net_init(&server_fd); ESP_LOGI(TAG, "Connecting to %s:%s...", WEB_SERVER, WEB_PORT); if ((ret = mbedtls_net_connect(&server_fd, WEB_SERVER, WEB_PORT, MBEDTLS_NET_PROTO_TCP)) != 0) { ESP_LOGE(TAG, "mbedtls_net_connect returned -%x", -ret); goto exit; } ESP_LOGI(TAG, "Connected."); mbedtls_ssl_set_bio(&ssl, &server_fd, mbedtls_net_send, mbedtls_net_recv, NULL); ESP_LOGI(TAG, "Performing the SSL/TLS handshake..."); while ((ret = mbedtls_ssl_handshake(&ssl)) != 0) { if (ret != MBEDTLS_ERR_SSL_WANT_READ && ret != MBEDTLS_ERR_SSL_WANT_WRITE) { ESP_LOGE(TAG, "mbedtls_ssl_handshake returned -0x%x", -ret); goto exit; } } ESP_LOGI(TAG, "Verifying peer X.509 certificate..."); if ((flags = mbedtls_ssl_get_verify_result(&ssl)) != 0) { /* In real life, we probably want to close connection if ret != 0 */ ESP_LOGW(TAG, "Failed to verify peer certificate!"); bzero(buf, sizeof(buf)); mbedtls_x509_crt_verify_info(buf, sizeof(buf), " ! ", flags); ESP_LOGW(TAG, "verification info: %s", buf); } else { ESP_LOGI(TAG, "Certificate verified."); } ESP_LOGI(TAG, "Cipher suite is %s", mbedtls_ssl_get_ciphersuite(&ssl)); ESP_LOGI(TAG, "Writing HTTP request..."); size_t written_bytes = 0; do { ret = mbedtls_ssl_write(&ssl, (const unsigned char *)REQUEST + written_bytes, strlen(REQUEST) - written_bytes); if (ret >= 0) { ESP_LOGI(TAG, "%d bytes written", ret); written_bytes += ret; } else if (ret != MBEDTLS_ERR_SSL_WANT_WRITE && ret != MBEDTLS_ERR_SSL_WANT_READ) { ESP_LOGE(TAG, "mbedtls_ssl_write returned -0x%x", -ret); goto exit; } } while(written_bytes < strlen(REQUEST)); ESP_LOGI(TAG, "Reading HTTP response..."); do { len = sizeof(buf) - 1; bzero(buf, sizeof(buf)); ret = mbedtls_ssl_read(&ssl, (unsigned char *)buf, len); if(ret == MBEDTLS_ERR_SSL_WANT_READ || ret == MBEDTLS_ERR_SSL_WANT_WRITE) continue; if(ret == MBEDTLS_ERR_SSL_PEER_CLOSE_NOTIFY) { ret = 0; break; } if(ret < 0) { ESP_LOGE(TAG, "mbedtls_ssl_read returned -0x%x", -ret); break; } if(ret == 0) { ESP_LOGI(TAG, "connection closed"); break; } len = ret; ESP_LOGD(TAG, "%d bytes read", len); /* Print response directly to stdout as it is read */ for(int i = 0; i < len; i++) { putchar(buf[i]); } } while(1); mbedtls_ssl_close_notify(&ssl); exit: mbedtls_ssl_session_reset(&ssl); mbedtls_net_free(&server_fd); if(ret != 0) { mbedtls_strerror(ret, buf, 100); ESP_LOGE(TAG, "Last error was: -0x%x - %s", -ret, buf); } putchar('\n'); // JSON output doesn't have a newline at end static int request_count; ESP_LOGI(TAG, "Completed %d requests", ++request_count); for(int countdown = 10; countdown >= 0; countdown--) { ESP_LOGI(TAG, "%d...", countdown); vTaskDelay(1000 / portTICK_PERIOD_MS); } ESP_LOGI(TAG, "Starting again!"); } }
int main( void ) { int ret, len, written; mbedtls_net_context server_fd; unsigned char buf[1024]; const char *pers = "pinning_client"; /* XXX create some state for our verify callback */ struct vrfy_state vrfy_state = { .pins = pins, }; mbedtls_entropy_context entropy; mbedtls_ctr_drbg_context ctr_drbg; mbedtls_ssl_context ssl; mbedtls_ssl_config conf; mbedtls_x509_crt cacert; /* Ensure valid memory references */ mbedtls_net_init( &server_fd ); mbedtls_ssl_init( &ssl ); mbedtls_ssl_config_init( &conf ); mbedtls_x509_crt_init( &cacert ); mbedtls_ctr_drbg_init( &ctr_drbg ); mbedtls_entropy_init( &entropy ); /* * 0. Initialize the RNG and the session data */ mbedtls_printf( "\n . Seeding the random number generator..." ); fflush( stdout ); if( ( ret = mbedtls_ctr_drbg_seed( &ctr_drbg, mbedtls_entropy_func, &entropy, (const unsigned char *) pers, strlen( pers ) ) ) != 0 ) { mbedtls_printf( " failed\n ! mbedtls_ctr_drbg_seed returned %d\n", ret ); goto exit; } mbedtls_printf( " ok\n" ); /* * 1. Load certificates */ mbedtls_printf( " . Loading the CA root certificate ..." ); fflush( stdout ); ret = mbedtls_x509_crt_parse( &cacert, (const unsigned char *) mbedtls_test_cas_pem, mbedtls_test_cas_pem_len ); if( ret < 0 ) { mbedtls_printf( " failed\n ! mbedtls_x509_crt_parse returned -0x%x\n\n", -ret ); goto exit; } mbedtls_printf( " ok (%d skipped)\n", ret ); /* * 2. Start the TCP connection */ mbedtls_printf( " . Connecting to tcp/%s/%s...", SERVER_NAME, SERVER_PORT ); fflush( stdout ); if( ( ret = mbedtls_net_connect( &server_fd, SERVER_NAME, SERVER_PORT, MBEDTLS_NET_PROTO_TCP ) ) != 0 ) { mbedtls_printf( " failed\n ! mbedtls_net_connect returned %d\n\n", ret ); goto exit; } mbedtls_printf( " ok\n" ); /* * 3. Setup SSL/TSL stuff */ mbedtls_printf( " . Setting up the SSL/TLS structure..." ); fflush( stdout ); if( ( ret = mbedtls_ssl_config_defaults( &conf, MBEDTLS_SSL_IS_CLIENT, MBEDTLS_SSL_TRANSPORT_STREAM, MBEDTLS_SSL_PRESET_DEFAULT ) ) != 0 ) { mbedtls_printf( " failed\n ! mbedtls_ssl_config_defaults returned %d\n\n", ret ); goto exit; } #if defined(MBEDTLS_DEBUG_C) mbedtls_debug_set_threshold( DEBUG_LEVEL ); #endif mbedtls_ssl_conf_ca_chain( &conf, &cacert, NULL ); mbedtls_ssl_conf_rng( &conf, mbedtls_ctr_drbg_random, &ctr_drbg ); mbedtls_ssl_conf_dbg( &conf, my_debug, stdout ); /* XXX: register our certificate verification callback */ mbedtls_ssl_conf_verify( &conf, my_verify, &vrfy_state ); if( ( ret = mbedtls_ssl_setup( &ssl, &conf ) ) != 0 ) { mbedtls_printf( " failed\n ! mbedtls_ssl_setup returned %d\n\n", ret ); goto exit; } if( ( ret = mbedtls_ssl_set_hostname( &ssl, SERVER_NAME ) ) != 0 ) { mbedtls_printf( " failed\n ! mbedtls_ssl_set_hostname returned %d\n\n", ret ); goto exit; } mbedtls_ssl_set_bio( &ssl, &server_fd, mbedtls_net_send, mbedtls_net_recv, NULL ); mbedtls_printf( " ok\n" ); /* * 4. Handshake */ mbedtls_printf( " . Performing the SSL/TLS handshake..." ); fflush( stdout ); while( ( ret = mbedtls_ssl_handshake( &ssl ) ) != 0 ) { if( ret != MBEDTLS_ERR_SSL_WANT_READ && ret != MBEDTLS_ERR_SSL_WANT_WRITE ) { mbedtls_printf( " failed\n ! mbedtls_ssl_handshake returned -0x%x\n\n", -ret ); goto exit; } } mbedtls_printf( " ok\n" ); /* * 5. Write request */ mbedtls_printf( " > Write to server:" ); fflush( stdout ); len = snprintf( (char *) buf, sizeof( buf ), GET_REQUEST ); if( len < 0 || (size_t) len > sizeof( buf ) ) { mbedtls_printf( " failed\n ! buffer too small for request\n\n" ); goto exit; } for( written = 0; written < len; written += ret ) { while( ( ret = mbedtls_ssl_write( &ssl, buf + written, len - written ) ) <= 0 ) { if( ret != MBEDTLS_ERR_SSL_WANT_READ && ret != MBEDTLS_ERR_SSL_WANT_WRITE ) { mbedtls_printf( " failed\n ! mbedtls_ssl_write returned -0x%x\n\n", -ret ); goto exit; } } } mbedtls_printf( " %d bytes written\n\n%s", written, (char *) buf ); /* * 6. Read the HTTP response */ mbedtls_printf( " < Read from server:" ); fflush( stdout ); do { len = sizeof( buf ) - 1; memset( buf, 0, sizeof( buf ) ); ret = mbedtls_ssl_read( &ssl, buf, len ); if( ret == MBEDTLS_ERR_SSL_WANT_READ || ret == MBEDTLS_ERR_SSL_WANT_WRITE ) continue; if( ret <= 0 ) { switch( ret ) { case MBEDTLS_ERR_SSL_PEER_CLOSE_NOTIFY: mbedtls_printf( " connection was closed gracefully\n" ); ret = 0; goto close_notify; case 0: case MBEDTLS_ERR_NET_CONN_RESET: mbedtls_printf( " connection was reset by peer\n" ); ret = 0; goto exit; default: mbedtls_printf( " mbedtls_ssl_read returned -0x%x\n", -ret ); goto exit; } } len = ret; buf[len] = '\0'; mbedtls_printf( " %d bytes read\n\n%s", len, (char *) buf ); /* End of message should be detected according to the syntax of the * application protocol (eg HTTP), just use a dummy test here. */ if( ret > 0 && buf[len-1] == '\n' ) { ret = 0; break; } } while( 1 ); /* * 8. Done, cleanly close the connection */ close_notify: mbedtls_printf( " . Closing the connection..." ); fflush( stdout ); /* No error checking, the connection might be closed already */ do ret = mbedtls_ssl_close_notify( &ssl ); while( ret == MBEDTLS_ERR_SSL_WANT_WRITE ); ret = 0; mbedtls_printf( " done\n" ); exit: #ifdef MBEDTLS_ERROR_C if( ret != 0 ) { char error_buf[100]; mbedtls_strerror( ret, error_buf, 100 ); mbedtls_printf("Last error was: %d - %s\n\n", ret, error_buf ); } #endif mbedtls_net_free( &server_fd ); mbedtls_x509_crt_free( &cacert ); mbedtls_ssl_free( &ssl ); mbedtls_ssl_config_free( &conf ); mbedtls_ctr_drbg_free( &ctr_drbg ); mbedtls_entropy_free( &entropy ); #if defined(_WIN32) mbedtls_printf( " + Press Enter to exit this program.\n" ); fflush( stdout ); getchar(); #endif return( ret != 0 ); }
/** * @brief create SSL low-level object */ 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; } if (!ssl->ctx->read_buffer_len) ssl->ctx->read_buffer_len = 2048; max_content_len = ssl->ctx->read_buffer_len; // printf("ssl->ctx->read_buffer_len = %d ++++++++++++++++++++\n", ssl->ctx->read_buffer_len); mbedtls_net_init(&ssl_pm->fd); mbedtls_net_init(&ssl_pm->cl_fd); 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) { SSL_DEBUG(SSL_PLATFORM_ERROR_LEVEL, "mbedtls_ctr_drbg_seed() return -0x%x", -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) { 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, NULL, NULL); #endif ret = mbedtls_ssl_setup(&ssl_pm->ssl, &ssl_pm->conf); if (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); 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; }
int main( int argc, char *argv[] ) { int ret; mbedtls_net_context listen_fd, client_fd, server_fd; int nb_fds; fd_set read_fds; mbedtls_net_init( &listen_fd ); mbedtls_net_init( &client_fd ); mbedtls_net_init( &server_fd ); get_options( argc, argv ); /* * Decisions to drop/delay/duplicate packets are pseudo-random: dropping * exactly 1 in N packets would lead to problems when a flight has exactly * N packets: the same packet would be dropped on every resend. * * In order to be able to reproduce problems reliably, the seed may be * specified explicitly. */ if( opt.seed == 0 ) { opt.seed = (unsigned int) time( NULL ); mbedtls_printf( " . Pseudo-random seed: %u\n", opt.seed ); } srand( opt.seed ); /* * 0. "Connect" to the server */ mbedtls_printf( " . Connect to server on UDP/%s/%s ...", opt.server_addr, opt.server_port ); fflush( stdout ); if( ( ret = mbedtls_net_connect( &server_fd, opt.server_addr, opt.server_port, MBEDTLS_NET_PROTO_UDP ) ) != 0 ) { mbedtls_printf( " failed\n ! mbedtls_net_connect returned %d\n\n", ret ); goto exit; } mbedtls_printf( " ok\n" ); /* * 1. Setup the "listening" UDP socket */ mbedtls_printf( " . Bind on UDP/%s/%s ...", opt.listen_addr, opt.listen_port ); fflush( stdout ); if( ( ret = mbedtls_net_bind( &listen_fd, opt.listen_addr, opt.listen_port, MBEDTLS_NET_PROTO_UDP ) ) != 0 ) { mbedtls_printf( " failed\n ! mbedtls_net_bind returned %d\n\n", ret ); goto exit; } mbedtls_printf( " ok\n" ); /* * 2. Wait until a client connects */ accept: mbedtls_net_free( &client_fd ); mbedtls_printf( " . Waiting for a remote connection ..." ); fflush( stdout ); if( ( ret = mbedtls_net_accept( &listen_fd, &client_fd, NULL, 0, NULL ) ) != 0 ) { mbedtls_printf( " failed\n ! mbedtls_net_accept returned %d\n\n", ret ); goto exit; } mbedtls_printf( " ok\n" ); /* * 3. Forward packets forever (kill the process to terminate it) */ clear_pending(); memset( dropped, 0, sizeof( dropped ) ); nb_fds = client_fd.fd; if( nb_fds < server_fd.fd ) nb_fds = server_fd.fd; if( nb_fds < listen_fd.fd ) nb_fds = listen_fd.fd; ++nb_fds; while( 1 ) { FD_ZERO( &read_fds ); FD_SET( server_fd.fd, &read_fds ); FD_SET( client_fd.fd, &read_fds ); FD_SET( listen_fd.fd, &read_fds ); if( ( ret = select( nb_fds, &read_fds, NULL, NULL, NULL ) ) <= 0 ) { perror( "select" ); goto exit; } if( FD_ISSET( listen_fd.fd, &read_fds ) ) goto accept; if( FD_ISSET( client_fd.fd, &read_fds ) ) { if( ( ret = handle_message( "S <- C", &server_fd, &client_fd ) ) != 0 ) goto accept; } if( FD_ISSET( server_fd.fd, &read_fds ) ) { if( ( ret = handle_message( "S -> C", &client_fd, &server_fd ) ) != 0 ) goto accept; } } exit: #ifdef MBEDTLS_ERROR_C if( ret != 0 ) { char error_buf[100]; mbedtls_strerror( ret, error_buf, 100 ); mbedtls_printf( "Last error was: -0x%04X - %s\n\n", - ret, error_buf ); fflush( stdout ); } #endif mbedtls_net_free( &client_fd ); mbedtls_net_free( &server_fd ); mbedtls_net_free( &listen_fd ); #if defined(_WIN32) mbedtls_printf( " Press Enter to exit this program.\n" ); fflush( stdout ); getchar(); #endif return( ret != 0 ); }
int main( void ) { FILE *f; int ret; size_t n, buflen; mbedtls_net_context server_fd; unsigned char *p, *end; unsigned char buf[2048]; unsigned char hash[32]; const char *pers = "dh_client"; mbedtls_entropy_context entropy; mbedtls_ctr_drbg_context ctr_drbg; mbedtls_rsa_context rsa; mbedtls_dhm_context dhm; mbedtls_aes_context aes; mbedtls_net_init( &server_fd ); mbedtls_rsa_init( &rsa, MBEDTLS_RSA_PKCS_V15, MBEDTLS_MD_SHA256 ); mbedtls_dhm_init( &dhm ); mbedtls_aes_init( &aes ); mbedtls_ctr_drbg_init( &ctr_drbg ); /* * 1. Setup the RNG */ mbedtls_printf( "\n . Seeding the random number generator" ); fflush( stdout ); mbedtls_entropy_init( &entropy ); if( ( ret = mbedtls_ctr_drbg_seed( &ctr_drbg, mbedtls_entropy_func, &entropy, (const unsigned char *) pers, strlen( pers ) ) ) != 0 ) { mbedtls_printf( " failed\n ! mbedtls_ctr_drbg_seed returned %d\n", ret ); goto exit; } /* * 2. Read the server's public RSA key */ mbedtls_printf( "\n . Reading public key from rsa_pub.txt" ); fflush( stdout ); if( ( f = fopen( "rsa_pub.txt", "rb" ) ) == NULL ) { ret = 1; mbedtls_printf( " failed\n ! Could not open rsa_pub.txt\n" \ " ! Please run rsa_genkey first\n\n" ); goto exit; } mbedtls_rsa_init( &rsa, MBEDTLS_RSA_PKCS_V15, 0 ); if( ( ret = mbedtls_mpi_read_file( &rsa.N, 16, f ) ) != 0 || ( ret = mbedtls_mpi_read_file( &rsa.E, 16, f ) ) != 0 ) { mbedtls_printf( " failed\n ! mbedtls_mpi_read_file returned %d\n\n", ret ); goto exit; } rsa.len = ( mbedtls_mpi_bitlen( &rsa.N ) + 7 ) >> 3; fclose( f ); /* * 3. Initiate the connection */ mbedtls_printf( "\n . Connecting to tcp/%s/%s", SERVER_NAME, SERVER_PORT ); fflush( stdout ); if( ( ret = mbedtls_net_connect( &server_fd, SERVER_NAME, SERVER_PORT, MBEDTLS_NET_PROTO_TCP ) ) != 0 ) { mbedtls_printf( " failed\n ! mbedtls_net_connect returned %d\n\n", ret ); goto exit; } /* * 4a. First get the buffer length */ mbedtls_printf( "\n . Receiving the server's DH parameters" ); fflush( stdout ); memset( buf, 0, sizeof( buf ) ); if( ( ret = mbedtls_net_recv( &server_fd, buf, 2 ) ) != 2 ) { mbedtls_printf( " failed\n ! mbedtls_net_recv returned %d\n\n", ret ); goto exit; } n = buflen = ( buf[0] << 8 ) | buf[1]; if( buflen < 1 || buflen > sizeof( buf ) ) { mbedtls_printf( " failed\n ! Got an invalid buffer length\n\n" ); goto exit; } /* * 4b. Get the DHM parameters: P, G and Ys = G^Xs mod P */ memset( buf, 0, sizeof( buf ) ); if( ( ret = mbedtls_net_recv( &server_fd, buf, n ) ) != (int) n ) { mbedtls_printf( " failed\n ! mbedtls_net_recv returned %d\n\n", ret ); goto exit; } p = buf, end = buf + buflen; if( ( ret = mbedtls_dhm_read_params( &dhm, &p, end ) ) != 0 ) { mbedtls_printf( " failed\n ! mbedtls_dhm_read_params returned %d\n\n", ret ); goto exit; } if( dhm.len < 64 || dhm.len > 512 ) { ret = 1; mbedtls_printf( " failed\n ! Invalid DHM modulus size\n\n" ); goto exit; } /* * 5. Check that the server's RSA signature matches * the SHA-256 hash of (P,G,Ys) */ mbedtls_printf( "\n . Verifying the server's RSA signature" ); fflush( stdout ); p += 2; if( ( n = (size_t) ( end - p ) ) != rsa.len ) { ret = 1; mbedtls_printf( " failed\n ! Invalid RSA signature size\n\n" ); goto exit; } mbedtls_sha1( buf, (int)( p - 2 - buf ), hash ); if( ( ret = mbedtls_rsa_pkcs1_verify( &rsa, NULL, NULL, MBEDTLS_RSA_PUBLIC, MBEDTLS_MD_SHA256, 0, hash, p ) ) != 0 ) { mbedtls_printf( " failed\n ! mbedtls_rsa_pkcs1_verify returned %d\n\n", ret ); goto exit; } /* * 6. Send our public value: Yc = G ^ Xc mod P */ mbedtls_printf( "\n . Sending own public value to server" ); fflush( stdout ); n = dhm.len; if( ( ret = mbedtls_dhm_make_public( &dhm, (int) dhm.len, buf, n, mbedtls_ctr_drbg_random, &ctr_drbg ) ) != 0 ) { mbedtls_printf( " failed\n ! mbedtls_dhm_make_public returned %d\n\n", ret ); goto exit; } if( ( ret = mbedtls_net_send( &server_fd, buf, n ) ) != (int) n ) { mbedtls_printf( " failed\n ! mbedtls_net_send returned %d\n\n", ret ); goto exit; } /* * 7. Derive the shared secret: K = Ys ^ Xc mod P */ mbedtls_printf( "\n . Shared secret: " ); fflush( stdout ); if( ( ret = mbedtls_dhm_calc_secret( &dhm, buf, sizeof( buf ), &n, mbedtls_ctr_drbg_random, &ctr_drbg ) ) != 0 ) { mbedtls_printf( " failed\n ! mbedtls_dhm_calc_secret returned %d\n\n", ret ); goto exit; } for( n = 0; n < 16; n++ ) mbedtls_printf( "%02x", buf[n] ); /* * 8. Setup the AES-256 decryption key * * This is an overly simplified example; best practice is * to hash the shared secret with a random value to derive * the keying material for the encryption/decryption keys, * IVs and MACs. */ mbedtls_printf( "...\n . Receiving and decrypting the ciphertext" ); fflush( stdout ); mbedtls_aes_setkey_dec( &aes, buf, 256 ); memset( buf, 0, sizeof( buf ) ); if( ( ret = mbedtls_net_recv( &server_fd, buf, 16 ) ) != 16 ) { mbedtls_printf( " failed\n ! mbedtls_net_recv returned %d\n\n", ret ); goto exit; } mbedtls_aes_crypt_ecb( &aes, MBEDTLS_AES_DECRYPT, buf, buf ); buf[16] = '\0'; mbedtls_printf( "\n . Plaintext is \"%s\"\n\n", (char *) buf ); exit: mbedtls_net_free( &server_fd ); mbedtls_aes_free( &aes ); mbedtls_rsa_free( &rsa ); mbedtls_dhm_free( &dhm ); mbedtls_ctr_drbg_free( &ctr_drbg ); mbedtls_entropy_free( &entropy ); #if defined(_WIN32) mbedtls_printf( " + Press Enter to exit this program.\n" ); fflush( stdout ); getchar(); #endif return( ret ); }
int dtlsclient_main( int argc, char *argv[] ) { int ret, len; mbedtls_net_context server_fd; uint32_t flags; unsigned char buf[1024]; const char *pers = "dtls_client"; int retry_left = MAX_RETRY; mbedtls_entropy_context entropy; mbedtls_ctr_drbg_context ctr_drbg; mbedtls_ssl_context ssl; mbedtls_ssl_config conf; mbedtls_x509_crt cacert; mbedtls_timing_delay_context timer; ((void) argc); ((void) argv); #if defined(MBEDTLS_DEBUG_C) mbedtls_debug_set_threshold( DEBUG_LEVEL ); #endif /* * 0. Initialize the RNG and the session data */ mbedtls_net_init( &server_fd ); mbedtls_ssl_init( &ssl ); mbedtls_ssl_config_init( &conf ); mbedtls_x509_crt_init( &cacert ); mbedtls_ctr_drbg_init( &ctr_drbg ); mbedtls_printf( "\n . Seeding the random number generator..." ); fflush( stdout ); mbedtls_entropy_init( &entropy ); if( ( ret = mbedtls_ctr_drbg_seed( &ctr_drbg, mbedtls_entropy_func, &entropy, (const unsigned char *) pers, strlen( pers ) ) ) != 0 ) { mbedtls_printf( " failed\n ! mbedtls_ctr_drbg_seed returned %d\n", ret ); goto exit; } mbedtls_printf( " ok\n" ); /* * 0. Load certificates */ mbedtls_printf( " . Loading the CA root certificate ..." ); fflush( stdout ); ret = mbedtls_x509_crt_parse( &cacert, (const unsigned char *) mbedtls_test_cas_pem, mbedtls_test_cas_pem_len ); if( ret < 0 ) { mbedtls_printf( " failed\n ! mbedtls_x509_crt_parse returned -0x%x\n\n", -ret ); goto exit; } mbedtls_printf( " ok (%d skipped)\n", ret ); /* * 1. Start the connection */ mbedtls_printf( " . Connecting to udp/%s/%s...", SERVER_NAME, SERVER_PORT ); fflush( stdout ); if( ( ret = mbedtls_net_connect( &server_fd, SERVER_ADDR, SERVER_PORT, MBEDTLS_NET_PROTO_UDP ) ) != 0 ) { mbedtls_printf( " failed\n ! mbedtls_net_connect returned %d\n\n", ret ); goto exit; } mbedtls_printf( " ok\n" ); /* * 2. Setup stuff */ mbedtls_printf( " . Setting up the DTLS structure..." ); fflush( stdout ); if( ( ret = mbedtls_ssl_config_defaults( &conf, MBEDTLS_SSL_IS_CLIENT, MBEDTLS_SSL_TRANSPORT_DATAGRAM, MBEDTLS_SSL_PRESET_DEFAULT ) ) != 0 ) { mbedtls_printf( " failed\n ! mbedtls_ssl_config_defaults returned %d\n\n", ret ); goto exit; } /* OPTIONAL is usually a bad choice for security, but makes interop easier * in this simplified example, in which the ca chain is hardcoded. * Production code should set a proper ca chain and use REQUIRED. */ mbedtls_ssl_conf_authmode( &conf, MBEDTLS_SSL_VERIFY_OPTIONAL ); mbedtls_ssl_conf_ca_chain( &conf, &cacert, NULL ); mbedtls_ssl_conf_rng( &conf, mbedtls_ctr_drbg_random, &ctr_drbg ); mbedtls_ssl_conf_dbg( &conf, my_debug, stdout ); if( ( ret = mbedtls_ssl_setup( &ssl, &conf ) ) != 0 ) { mbedtls_printf( " failed\n ! mbedtls_ssl_setup returned %d\n\n", ret ); goto exit; } if( ( ret = mbedtls_ssl_set_hostname( &ssl, SERVER_NAME ) ) != 0 ) { mbedtls_printf( " failed\n ! mbedtls_ssl_set_hostname returned %d\n\n", ret ); goto exit; } mbedtls_ssl_set_bio( &ssl, &server_fd, mbedtls_net_send, mbedtls_net_recv, mbedtls_net_recv_timeout ); mbedtls_ssl_set_timer_cb( &ssl, &timer, mbedtls_timing_set_delay, mbedtls_timing_get_delay ); mbedtls_printf( " ok\n" ); /* * 4. Handshake */ mbedtls_printf( " . Performing the SSL/TLS handshake..." ); fflush( stdout ); do ret = mbedtls_ssl_handshake( &ssl ); while( ret == MBEDTLS_ERR_SSL_WANT_READ || ret == MBEDTLS_ERR_SSL_WANT_WRITE ); if( ret != 0 ) { mbedtls_printf( " failed\n ! mbedtls_ssl_handshake returned -0x%x\n\n", -ret ); goto exit; } mbedtls_printf( " ok\n" ); /* * 5. Verify the server certificate */ mbedtls_printf( " . Verifying peer X.509 certificate..." ); /* In real life, we would have used MBEDTLS_SSL_VERIFY_REQUIRED so that the * handshake would not succeed if the peer's cert is bad. Even if we used * MBEDTLS_SSL_VERIFY_OPTIONAL, we would bail out here if ret != 0 */ if( ( flags = mbedtls_ssl_get_verify_result( &ssl ) ) != 0 ) { char vrfy_buf[512]; mbedtls_printf( " failed\n" ); mbedtls_x509_crt_verify_info( vrfy_buf, sizeof( vrfy_buf ), " ! ", flags ); mbedtls_printf( "%s\n", vrfy_buf ); } else mbedtls_printf( " ok\n" ); /* * 6. Write the echo request */ send_request: mbedtls_printf( " > Write to server:" ); fflush( stdout ); len = sizeof( MESSAGE ) - 1; do ret = mbedtls_ssl_write( &ssl, (unsigned char *) MESSAGE, len ); while( ret == MBEDTLS_ERR_SSL_WANT_READ || ret == MBEDTLS_ERR_SSL_WANT_WRITE ); if( ret < 0 ) { mbedtls_printf( " failed\n ! mbedtls_ssl_write returned %d\n\n", ret ); goto exit; } len = ret; mbedtls_printf( " %d bytes written\n\n%s\n\n", len, MESSAGE ); /* * 7. Read the echo response */ mbedtls_printf( " < Read from server:" ); fflush( stdout ); len = sizeof( buf ) - 1; memset( buf, 0, sizeof( buf ) ); do ret = mbedtls_ssl_read( &ssl, buf, len ); while( ret == MBEDTLS_ERR_SSL_WANT_READ || ret == MBEDTLS_ERR_SSL_WANT_WRITE ); if( ret <= 0 ) { switch( ret ) { case MBEDTLS_ERR_SSL_TIMEOUT: mbedtls_printf( " timeout\n\n" ); if( retry_left-- > 0 ) goto send_request; goto exit; case MBEDTLS_ERR_SSL_PEER_CLOSE_NOTIFY: mbedtls_printf( " connection was closed gracefully\n" ); ret = 0; goto close_notify; default: mbedtls_printf( " mbedtls_ssl_read returned -0x%x\n\n", -ret ); goto exit; } } len = ret; mbedtls_printf( " %d bytes read\n\n%s\n\n", len, buf ); /* * 8. Done, cleanly close the connection */ close_notify: mbedtls_printf( " . Closing the connection..." ); /* No error checking, the connection might be closed already */ do ret = mbedtls_ssl_close_notify( &ssl ); while( ret == MBEDTLS_ERR_SSL_WANT_WRITE ); ret = 0; mbedtls_printf( " done\n" ); /* * 9. Final clean-ups and exit */ exit: #ifdef MBEDTLS_ERROR_C if( ret != 0 ) { char error_buf[100]; mbedtls_strerror( ret, error_buf, 100 ); mbedtls_printf( "Last error was: %d - %s\n\n", ret, error_buf ); } #endif mbedtls_net_free( &server_fd ); mbedtls_x509_crt_free( &cacert ); mbedtls_ssl_free( &ssl ); mbedtls_ssl_config_free( &conf ); mbedtls_ctr_drbg_free( &ctr_drbg ); mbedtls_entropy_free( &entropy ); #if defined(_WIN32) mbedtls_printf( " + Press Enter to exit this program.\n" ); fflush( stdout ); getchar(); #endif /* Shell can not handle large exit numbers -> 1 for errors */ if( ret < 0 ) ret = 1; return( ret ); }
int main( void ) { int ret, len; mbedtls_net_context listen_fd, client_fd; unsigned char buf[1024]; const char *pers = "dtls_server"; unsigned char client_ip[16] = { 0 }; size_t cliip_len; mbedtls_ssl_cookie_ctx cookie_ctx; mbedtls_entropy_context entropy; mbedtls_ctr_drbg_context ctr_drbg; mbedtls_ssl_context ssl; mbedtls_ssl_config conf; mbedtls_x509_crt srvcert; mbedtls_pk_context pkey; mbedtls_timing_delay_context timer; #if defined(MBEDTLS_SSL_CACHE_C) mbedtls_ssl_cache_context cache; #endif mbedtls_net_init( &listen_fd ); mbedtls_net_init( &client_fd ); mbedtls_ssl_init( &ssl ); mbedtls_ssl_config_init( &conf ); mbedtls_ssl_cookie_init( &cookie_ctx ); #if defined(MBEDTLS_SSL_CACHE_C) mbedtls_ssl_cache_init( &cache ); #endif mbedtls_x509_crt_init( &srvcert ); mbedtls_pk_init( &pkey ); mbedtls_entropy_init( &entropy ); mbedtls_ctr_drbg_init( &ctr_drbg ); #if defined(MBEDTLS_DEBUG_C) mbedtls_debug_set_threshold( DEBUG_LEVEL ); #endif /* * 1. Load the certificates and private RSA key */ printf( "\n . Loading the server cert. and key..." ); fflush( stdout ); /* * This demonstration program uses embedded test certificates. * Instead, you may want to use mbedtls_x509_crt_parse_file() to read the * server and CA certificates, as well as mbedtls_pk_parse_keyfile(). */ ret = mbedtls_x509_crt_parse( &srvcert, (const unsigned char *) mbedtls_test_srv_crt, mbedtls_test_srv_crt_len ); if( ret != 0 ) { printf( " failed\n ! mbedtls_x509_crt_parse returned %d\n\n", ret ); goto exit; } ret = mbedtls_x509_crt_parse( &srvcert, (const unsigned char *) mbedtls_test_cas_pem, mbedtls_test_cas_pem_len ); if( ret != 0 ) { printf( " failed\n ! mbedtls_x509_crt_parse returned %d\n\n", ret ); goto exit; } ret = mbedtls_pk_parse_key( &pkey, (const unsigned char *) mbedtls_test_srv_key, mbedtls_test_srv_key_len, NULL, 0 ); if( ret != 0 ) { printf( " failed\n ! mbedtls_pk_parse_key returned %d\n\n", ret ); goto exit; } printf( " ok\n" ); /* * 2. Setup the "listening" UDP socket */ printf( " . Bind on udp/*/4433 ..." ); fflush( stdout ); if( ( ret = mbedtls_net_bind( &listen_fd, NULL, "4433", MBEDTLS_NET_PROTO_UDP ) ) != 0 ) { printf( " failed\n ! mbedtls_net_bind returned %d\n\n", ret ); goto exit; } printf( " ok\n" ); /* * 3. Seed the RNG */ printf( " . Seeding the random number generator..." ); fflush( stdout ); if( ( ret = mbedtls_ctr_drbg_seed( &ctr_drbg, mbedtls_entropy_func, &entropy, (const unsigned char *) pers, strlen( pers ) ) ) != 0 ) { printf( " failed\n ! mbedtls_ctr_drbg_seed returned %d\n", ret ); goto exit; } printf( " ok\n" ); /* * 4. Setup stuff */ printf( " . Setting up the DTLS data..." ); fflush( stdout ); if( ( ret = mbedtls_ssl_config_defaults( &conf, MBEDTLS_SSL_IS_SERVER, MBEDTLS_SSL_TRANSPORT_DATAGRAM, MBEDTLS_SSL_PRESET_DEFAULT ) ) != 0 ) { mbedtls_printf( " failed\n ! mbedtls_ssl_config_defaults returned %d\n\n", ret ); goto exit; } mbedtls_ssl_conf_rng( &conf, mbedtls_ctr_drbg_random, &ctr_drbg ); mbedtls_ssl_conf_dbg( &conf, my_debug, stdout ); #if defined(MBEDTLS_SSL_CACHE_C) mbedtls_ssl_conf_session_cache( &conf, &cache, mbedtls_ssl_cache_get, mbedtls_ssl_cache_set ); #endif mbedtls_ssl_conf_ca_chain( &conf, srvcert.next, NULL ); if( ( ret = mbedtls_ssl_conf_own_cert( &conf, &srvcert, &pkey ) ) != 0 ) { printf( " failed\n ! mbedtls_ssl_conf_own_cert returned %d\n\n", ret ); goto exit; } if( ( ret = mbedtls_ssl_cookie_setup( &cookie_ctx, mbedtls_ctr_drbg_random, &ctr_drbg ) ) != 0 ) { printf( " failed\n ! mbedtls_ssl_cookie_setup returned %d\n\n", ret ); goto exit; } mbedtls_ssl_conf_dtls_cookies( &conf, mbedtls_ssl_cookie_write, mbedtls_ssl_cookie_check, &cookie_ctx ); if( ( ret = mbedtls_ssl_setup( &ssl, &conf ) ) != 0 ) { printf( " failed\n ! mbedtls_ssl_setup returned %d\n\n", ret ); goto exit; } mbedtls_ssl_set_timer_cb( &ssl, &timer, mbedtls_timing_set_delay, mbedtls_timing_get_delay ); printf( " ok\n" ); reset: #ifdef MBEDTLS_ERROR_C if( ret != 0 ) { char error_buf[100]; mbedtls_strerror( ret, error_buf, 100 ); printf("Last error was: %d - %s\n\n", ret, error_buf ); } #endif mbedtls_net_free( &client_fd ); mbedtls_ssl_session_reset( &ssl ); /* * 3. Wait until a client connects */ printf( " . Waiting for a remote connection ..." ); fflush( stdout ); if( ( ret = mbedtls_net_accept( &listen_fd, &client_fd, client_ip, sizeof( client_ip ), &cliip_len ) ) != 0 ) { printf( " failed\n ! mbedtls_net_accept returned %d\n\n", ret ); goto exit; } /* For HelloVerifyRequest cookies */ if( ( ret = mbedtls_ssl_set_client_transport_id( &ssl, client_ip, cliip_len ) ) != 0 ) { printf( " failed\n ! " "mbedtls_ssl_set_client_transport_id() returned -0x%x\n\n", -ret ); goto exit; } mbedtls_ssl_set_bio( &ssl, &client_fd, mbedtls_net_send, mbedtls_net_recv, mbedtls_net_recv_timeout ); printf( " ok\n" ); /* * 5. Handshake */ printf( " . Performing the DTLS handshake..." ); fflush( stdout ); do ret = mbedtls_ssl_handshake( &ssl ); while( ret == MBEDTLS_ERR_SSL_WANT_READ || ret == MBEDTLS_ERR_SSL_WANT_WRITE ); if( ret == MBEDTLS_ERR_SSL_HELLO_VERIFY_REQUIRED ) { printf( " hello verification requested\n" ); ret = 0; goto reset; } else if( ret != 0 ) { printf( " failed\n ! mbedtls_ssl_handshake returned -0x%x\n\n", -ret ); goto reset; } printf( " ok\n" ); /* * 6. Read the echo Request */ printf( " < Read from client:" ); fflush( stdout ); len = sizeof( buf ) - 1; memset( buf, 0, sizeof( buf ) ); do ret = mbedtls_ssl_read( &ssl, buf, len ); while( ret == MBEDTLS_ERR_SSL_WANT_READ || ret == MBEDTLS_ERR_SSL_WANT_WRITE ); if( ret <= 0 ) { switch( ret ) { case MBEDTLS_ERR_SSL_TIMEOUT: printf( " timeout\n\n" ); goto reset; case MBEDTLS_ERR_SSL_PEER_CLOSE_NOTIFY: printf( " connection was closed gracefully\n" ); ret = 0; goto close_notify; default: printf( " mbedtls_ssl_read returned -0x%x\n\n", -ret ); goto reset; } } len = ret; printf( " %d bytes read\n\n%s\n\n", len, buf ); /* * 7. Write the 200 Response */ printf( " > Write to client:" ); fflush( stdout ); do ret = mbedtls_ssl_write( &ssl, buf, len ); while( ret == MBEDTLS_ERR_SSL_WANT_READ || ret == MBEDTLS_ERR_SSL_WANT_WRITE ); if( ret < 0 ) { printf( " failed\n ! mbedtls_ssl_write returned %d\n\n", ret ); goto exit; } len = ret; printf( " %d bytes written\n\n%s\n\n", len, buf ); /* * 8. Done, cleanly close the connection */ close_notify: printf( " . Closing the connection..." ); /* No error checking, the connection might be closed already */ do ret = mbedtls_ssl_close_notify( &ssl ); while( ret == MBEDTLS_ERR_SSL_WANT_WRITE ); ret = 0; printf( " done\n" ); goto reset; /* * Final clean-ups and exit */ exit: #ifdef MBEDTLS_ERROR_C if( ret != 0 ) { char error_buf[100]; mbedtls_strerror( ret, error_buf, 100 ); printf( "Last error was: %d - %s\n\n", ret, error_buf ); } #endif mbedtls_net_free( &client_fd ); mbedtls_net_free( &listen_fd ); mbedtls_x509_crt_free( &srvcert ); mbedtls_pk_free( &pkey ); mbedtls_ssl_free( &ssl ); mbedtls_ssl_config_free( &conf ); mbedtls_ssl_cookie_free( &cookie_ctx ); #if defined(MBEDTLS_SSL_CACHE_C) mbedtls_ssl_cache_free( &cache ); #endif mbedtls_ctr_drbg_free( &ctr_drbg ); mbedtls_entropy_free( &entropy ); #if defined(_WIN32) printf( " Press Enter to exit this program.\n" ); fflush( stdout ); getchar(); #endif /* Shell can not handle large exit numbers -> 1 for errors */ if( ret < 0 ) ret = 1; return( ret ); }
int main( void ) { int ret, len, cnt = 0, pid; mbedtls_net_context listen_fd, client_fd; unsigned char buf[1024]; const char *pers = "ssl_fork_server"; mbedtls_entropy_context entropy; mbedtls_ctr_drbg_context ctr_drbg; mbedtls_ssl_context ssl; mbedtls_ssl_config conf; mbedtls_x509_crt srvcert; mbedtls_pk_context pkey; mbedtls_net_init( &listen_fd ); mbedtls_net_init( &client_fd ); mbedtls_ssl_init( &ssl ); mbedtls_ssl_config_init( &conf ); mbedtls_entropy_init( &entropy ); mbedtls_pk_init( &pkey ); mbedtls_x509_crt_init( &srvcert ); mbedtls_ctr_drbg_init( &ctr_drbg ); signal( SIGCHLD, SIG_IGN ); /* * 0. Initial seeding of the RNG */ mbedtls_printf( "\n . Initial seeding of the random generator..." ); fflush( stdout ); if( ( ret = mbedtls_ctr_drbg_seed( &ctr_drbg, mbedtls_entropy_func, &entropy, (const unsigned char *) pers, strlen( pers ) ) ) != 0 ) { mbedtls_printf( " failed\n ! mbedtls_ctr_drbg_seed returned %d\n", ret ); goto exit; } mbedtls_printf( " ok\n" ); /* * 1. Load the certificates and private RSA key */ mbedtls_printf( " . Loading the server cert. and key..." ); fflush( stdout ); /* * This demonstration program uses embedded test certificates. * Instead, you may want to use mbedtls_x509_crt_parse_file() to read the * server and CA certificates, as well as mbedtls_pk_parse_keyfile(). */ ret = mbedtls_x509_crt_parse( &srvcert, (const unsigned char *) mbedtls_test_srv_crt, mbedtls_test_srv_crt_len ); if( ret != 0 ) { mbedtls_printf( " failed\n ! mbedtls_x509_crt_parse returned %d\n\n", ret ); goto exit; } ret = mbedtls_x509_crt_parse( &srvcert, (const unsigned char *) mbedtls_test_cas_pem, mbedtls_test_cas_pem_len ); if( ret != 0 ) { mbedtls_printf( " failed\n ! mbedtls_x509_crt_parse returned %d\n\n", ret ); goto exit; } ret = mbedtls_pk_parse_key( &pkey, (const unsigned char *) mbedtls_test_srv_key, mbedtls_test_srv_key_len, NULL, 0 ); if( ret != 0 ) { mbedtls_printf( " failed\n ! mbedtls_pk_parse_key returned %d\n\n", ret ); goto exit; } mbedtls_printf( " ok\n" ); /* * 1b. Prepare SSL configuration */ mbedtls_printf( " . Configuring SSL..." ); fflush( stdout ); if( ( ret = mbedtls_ssl_config_defaults( &conf, MBEDTLS_SSL_IS_SERVER, MBEDTLS_SSL_TRANSPORT_STREAM, MBEDTLS_SSL_PRESET_DEFAULT ) ) != 0 ) { mbedtls_printf( " failed\n ! mbedtls_ssl_config_defaults returned %d\n\n", ret ); goto exit; } mbedtls_ssl_conf_rng( &conf, mbedtls_ctr_drbg_random, &ctr_drbg ); mbedtls_ssl_conf_dbg( &conf, my_debug, stdout ); mbedtls_ssl_conf_ca_chain( &conf, srvcert.next, NULL ); if( ( ret = mbedtls_ssl_conf_own_cert( &conf, &srvcert, &pkey ) ) != 0 ) { mbedtls_printf( " failed\n ! mbedtls_ssl_conf_own_cert returned %d\n\n", ret ); goto exit; } mbedtls_printf( " ok\n" ); /* * 2. Setup the listening TCP socket */ mbedtls_printf( " . Bind on https://localhost:4433/ ..." ); fflush( stdout ); if( ( ret = mbedtls_net_bind( &listen_fd, NULL, "4433", MBEDTLS_NET_PROTO_TCP ) ) != 0 ) { mbedtls_printf( " failed\n ! mbedtls_net_bind returned %d\n\n", ret ); goto exit; } mbedtls_printf( " ok\n" ); while( 1 ) { /* * 3. Wait until a client connects */ mbedtls_net_init( &client_fd ); mbedtls_ssl_init( &ssl ); mbedtls_printf( " . Waiting for a remote connection ..." ); fflush( stdout ); if( ( ret = mbedtls_net_accept( &listen_fd, &client_fd, NULL, 0, NULL ) ) != 0 ) { mbedtls_printf( " failed\n ! mbedtls_net_accept returned %d\n\n", ret ); goto exit; } mbedtls_printf( " ok\n" ); /* * 3.5. Forking server thread */ pid = fork(); mbedtls_printf( " . Forking to handle connection ..." ); fflush( stdout ); if( pid < 0 ) { mbedtls_printf(" failed\n ! fork returned %d\n\n", pid ); goto exit; } mbedtls_printf( " ok\n" ); if( pid != 0 ) { if( ( ret = mbedtls_ctr_drbg_reseed( &ctr_drbg, (const unsigned char *) "parent", 6 ) ) != 0 ) { mbedtls_printf( " failed\n ! mbedtls_ctr_drbg_reseed returned %d\n", ret ); goto exit; } mbedtls_net_free( &client_fd ); continue; } mbedtls_net_free( &listen_fd ); /* * 4. Setup stuff */ mbedtls_printf( " . Setting up the SSL data...." ); fflush( stdout ); if( ( ret = mbedtls_ctr_drbg_reseed( &ctr_drbg, (const unsigned char *) "child", 5 ) ) != 0 ) { mbedtls_printf( " failed\n ! mbedtls_ctr_drbg_reseed returned %d\n", ret ); goto exit; } if( ( ret = mbedtls_ssl_setup( &ssl, &conf ) ) != 0 ) { mbedtls_printf( " failed\n ! mbedtls_ssl_setup returned %d\n\n", ret ); goto exit; } mbedtls_ssl_set_bio( &ssl, &client_fd, mbedtls_net_send, mbedtls_net_recv, NULL ); mbedtls_printf( " ok\n" ); /* * 5. Handshake */ mbedtls_printf( " . Performing the SSL/TLS handshake..." ); fflush( stdout ); while( ( ret = mbedtls_ssl_handshake( &ssl ) ) != 0 ) { if( ret != MBEDTLS_ERR_SSL_WANT_READ && ret != MBEDTLS_ERR_SSL_WANT_WRITE ) { mbedtls_printf( " failed\n ! mbedtls_ssl_handshake returned %d\n\n", ret ); goto exit; } } mbedtls_printf( " ok\n" ); /* * 6. Read the HTTP Request */ mbedtls_printf( " < Read from client:" ); fflush( stdout ); do { len = sizeof( buf ) - 1; memset( buf, 0, sizeof( buf ) ); ret = mbedtls_ssl_read( &ssl, buf, len ); if( ret == MBEDTLS_ERR_SSL_WANT_READ || ret == MBEDTLS_ERR_SSL_WANT_WRITE ) continue; if( ret <= 0 ) { switch( ret ) { case MBEDTLS_ERR_SSL_PEER_CLOSE_NOTIFY: mbedtls_printf( " connection was closed gracefully\n" ); break; case MBEDTLS_ERR_NET_CONN_RESET: mbedtls_printf( " connection was reset by peer\n" ); break; default: mbedtls_printf( " mbedtls_ssl_read returned %d\n", ret ); break; } break; } len = ret; mbedtls_printf( " %d bytes read\n\n%s", len, (char *) buf ); if( ret > 0 ) break; } while( 1 ); /* * 7. Write the 200 Response */ mbedtls_printf( " > Write to client:" ); fflush( stdout ); len = sprintf( (char *) buf, HTTP_RESPONSE, mbedtls_ssl_get_ciphersuite( &ssl ) ); while( cnt++ < 100 ) { while( ( ret = mbedtls_ssl_write( &ssl, buf, len ) ) <= 0 ) { if( ret == MBEDTLS_ERR_NET_CONN_RESET ) { mbedtls_printf( " failed\n ! peer closed the connection\n\n" ); goto exit; } if( ret != MBEDTLS_ERR_SSL_WANT_READ && ret != MBEDTLS_ERR_SSL_WANT_WRITE ) { mbedtls_printf( " failed\n ! mbedtls_ssl_write returned %d\n\n", ret ); goto exit; } } len = ret; mbedtls_printf( " %d bytes written\n\n%s\n", len, (char *) buf ); mbedtls_net_usleep( 1000000 ); } mbedtls_ssl_close_notify( &ssl ); goto exit; } exit: mbedtls_net_free( &client_fd ); mbedtls_net_free( &listen_fd ); mbedtls_x509_crt_free( &srvcert ); mbedtls_pk_free( &pkey ); mbedtls_ssl_free( &ssl ); mbedtls_ssl_config_free( &conf ); mbedtls_ctr_drbg_free( &ctr_drbg ); mbedtls_entropy_free( &entropy ); #if defined(_WIN32) mbedtls_printf( " Press Enter to exit this program.\n" ); fflush( stdout ); getchar(); #endif return( ret ); }
int main( int argc, char *argv[] ) { int ret = 0, len; mbedtls_net_context server_fd; unsigned char buf[1024]; #if defined(MBEDTLS_BASE64_C) unsigned char base[1024]; #endif char hostname[32]; const char *pers = "ssl_mail_client"; mbedtls_entropy_context entropy; mbedtls_ctr_drbg_context ctr_drbg; mbedtls_ssl_context ssl; mbedtls_ssl_config conf; mbedtls_x509_crt cacert; mbedtls_x509_crt clicert; mbedtls_pk_context pkey; int i; size_t n; char *p, *q; const int *list; /* * Make sure memory references are valid in case we exit early. */ mbedtls_net_init( &server_fd ); mbedtls_ssl_init( &ssl ); mbedtls_ssl_config_init( &conf ); memset( &buf, 0, sizeof( buf ) ); mbedtls_x509_crt_init( &cacert ); mbedtls_x509_crt_init( &clicert ); mbedtls_pk_init( &pkey ); mbedtls_ctr_drbg_init( &ctr_drbg ); if( argc == 0 ) { usage: mbedtls_printf( USAGE ); list = mbedtls_ssl_list_ciphersuites(); while( *list ) { mbedtls_printf(" %s\n", mbedtls_ssl_get_ciphersuite_name( *list ) ); list++; } mbedtls_printf("\n"); goto exit; } opt.server_name = DFL_SERVER_NAME; opt.server_port = DFL_SERVER_PORT; opt.debug_level = DFL_DEBUG_LEVEL; opt.authentication = DFL_AUTHENTICATION; opt.mode = DFL_MODE; opt.user_name = DFL_USER_NAME; opt.user_pwd = DFL_USER_PWD; opt.mail_from = DFL_MAIL_FROM; opt.mail_to = DFL_MAIL_TO; opt.ca_file = DFL_CA_FILE; opt.crt_file = DFL_CRT_FILE; opt.key_file = DFL_KEY_FILE; opt.force_ciphersuite[0]= DFL_FORCE_CIPHER; for( i = 1; i < argc; i++ ) { p = argv[i]; if( ( q = strchr( p, '=' ) ) == NULL ) goto usage; *q++ = '\0'; if( strcmp( p, "server_name" ) == 0 ) opt.server_name = q; else if( strcmp( p, "server_port" ) == 0 ) opt.server_port = q; else if( strcmp( p, "debug_level" ) == 0 ) { opt.debug_level = atoi( q ); if( opt.debug_level < 0 || opt.debug_level > 65535 ) goto usage; } else if( strcmp( p, "authentication" ) == 0 ) { opt.authentication = atoi( q ); if( opt.authentication < 0 || opt.authentication > 1 ) goto usage; } else if( strcmp( p, "mode" ) == 0 ) { opt.mode = atoi( q ); if( opt.mode < 0 || opt.mode > 1 ) goto usage; } else if( strcmp( p, "user_name" ) == 0 ) opt.user_name = q; else if( strcmp( p, "user_pwd" ) == 0 ) opt.user_pwd = q; else if( strcmp( p, "mail_from" ) == 0 ) opt.mail_from = q; else if( strcmp( p, "mail_to" ) == 0 ) opt.mail_to = q; else if( strcmp( p, "ca_file" ) == 0 ) opt.ca_file = q; else if( strcmp( p, "crt_file" ) == 0 ) opt.crt_file = q; else if( strcmp( p, "key_file" ) == 0 ) opt.key_file = q; else if( strcmp( p, "force_ciphersuite" ) == 0 ) { opt.force_ciphersuite[0] = -1; opt.force_ciphersuite[0] = mbedtls_ssl_get_ciphersuite_id( q ); if( opt.force_ciphersuite[0] <= 0 ) goto usage; opt.force_ciphersuite[1] = 0; } else goto usage; } /* * 0. Initialize the RNG and the session data */ mbedtls_printf( "\n . Seeding the random number generator..." ); fflush( stdout ); mbedtls_entropy_init( &entropy ); if( ( ret = mbedtls_ctr_drbg_seed( &ctr_drbg, mbedtls_entropy_func, &entropy, (const unsigned char *) pers, strlen( pers ) ) ) != 0 ) { mbedtls_printf( " failed\n ! mbedtls_ctr_drbg_seed returned %d\n", ret ); goto exit; } mbedtls_printf( " ok\n" ); /* * 1.1. Load the trusted CA */ mbedtls_printf( " . Loading the CA root certificate ..." ); fflush( stdout ); #if defined(MBEDTLS_FS_IO) if( strlen( opt.ca_file ) ) ret = mbedtls_x509_crt_parse_file( &cacert, opt.ca_file ); else #endif #if defined(MBEDTLS_CERTS_C) ret = mbedtls_x509_crt_parse( &cacert, (const unsigned char *) mbedtls_test_cas_pem, mbedtls_test_cas_pem_len ); #else { ret = 1; mbedtls_printf("MBEDTLS_CERTS_C not defined."); } #endif if( ret < 0 ) { mbedtls_printf( " failed\n ! mbedtls_x509_crt_parse returned %d\n\n", ret ); goto exit; } mbedtls_printf( " ok (%d skipped)\n", ret ); /* * 1.2. Load own certificate and private key * * (can be skipped if client authentication is not required) */ mbedtls_printf( " . Loading the client cert. and key..." ); fflush( stdout ); #if defined(MBEDTLS_FS_IO) if( strlen( opt.crt_file ) ) ret = mbedtls_x509_crt_parse_file( &clicert, opt.crt_file ); else #endif #if defined(MBEDTLS_CERTS_C) ret = mbedtls_x509_crt_parse( &clicert, (const unsigned char *) mbedtls_test_cli_crt, mbedtls_test_cli_crt_len ); #else { ret = -1; mbedtls_printf("MBEDTLS_CERTS_C not defined."); } #endif if( ret != 0 ) { mbedtls_printf( " failed\n ! mbedtls_x509_crt_parse returned %d\n\n", ret ); goto exit; } #if defined(MBEDTLS_FS_IO) if( strlen( opt.key_file ) ) ret = mbedtls_pk_parse_keyfile( &pkey, opt.key_file, "" ); else #endif #if defined(MBEDTLS_CERTS_C) && defined(MBEDTLS_PEM_PARSE_C) ret = mbedtls_pk_parse_key( &pkey, (const unsigned char *) mbedtls_test_cli_key, mbedtls_test_cli_key_len, NULL, 0 ); #else { ret = -1; mbedtls_printf("MBEDTLS_CERTS_C or MBEDTLS_PEM_PARSE_C not defined."); } #endif if( ret != 0 ) { mbedtls_printf( " failed\n ! mbedtls_pk_parse_key returned %d\n\n", ret ); goto exit; } mbedtls_printf( " ok\n" ); /* * 2. Start the connection */ mbedtls_printf( " . Connecting to tcp/%s/%s...", opt.server_name, opt.server_port ); fflush( stdout ); if( ( ret = mbedtls_net_connect( &server_fd, opt.server_name, opt.server_port, MBEDTLS_NET_PROTO_TCP ) ) != 0 ) { mbedtls_printf( " failed\n ! mbedtls_net_connect returned %d\n\n", ret ); goto exit; } mbedtls_printf( " ok\n" ); /* * 3. Setup stuff */ mbedtls_printf( " . Setting up the SSL/TLS structure..." ); fflush( stdout ); if( ( ret = mbedtls_ssl_config_defaults( &conf, MBEDTLS_SSL_IS_CLIENT, MBEDTLS_SSL_TRANSPORT_STREAM, MBEDTLS_SSL_PRESET_DEFAULT ) ) != 0 ) { mbedtls_printf( " failed\n ! mbedtls_ssl_config_defaults returned %d\n\n", ret ); goto exit; } /* OPTIONAL is not optimal for security, * but makes interop easier in this simplified example */ mbedtls_ssl_conf_authmode( &conf, MBEDTLS_SSL_VERIFY_OPTIONAL ); mbedtls_ssl_conf_rng( &conf, mbedtls_ctr_drbg_random, &ctr_drbg ); mbedtls_ssl_conf_dbg( &conf, my_debug, stdout ); if( opt.force_ciphersuite[0] != DFL_FORCE_CIPHER ) mbedtls_ssl_conf_ciphersuites( &conf, opt.force_ciphersuite ); mbedtls_ssl_conf_ca_chain( &conf, &cacert, NULL ); if( ( ret = mbedtls_ssl_conf_own_cert( &conf, &clicert, &pkey ) ) != 0 ) { mbedtls_printf( " failed\n ! mbedtls_ssl_conf_own_cert returned %d\n\n", ret ); goto exit; } if( ( ret = mbedtls_ssl_setup( &ssl, &conf ) ) != 0 ) { mbedtls_printf( " failed\n ! mbedtls_ssl_setup returned %d\n\n", ret ); goto exit; } if( ( ret = mbedtls_ssl_set_hostname( &ssl, opt.server_name ) ) != 0 ) { mbedtls_printf( " failed\n ! mbedtls_ssl_set_hostname returned %d\n\n", ret ); goto exit; } mbedtls_ssl_set_bio( &ssl, &server_fd, mbedtls_net_send, mbedtls_net_recv, NULL ); mbedtls_printf( " ok\n" ); if( opt.mode == MODE_SSL_TLS ) { if( do_handshake( &ssl ) != 0 ) goto exit; mbedtls_printf( " > Get header from server:" ); fflush( stdout ); ret = write_ssl_and_get_response( &ssl, buf, 0 ); if( ret < 200 || ret > 299 ) { mbedtls_printf( " failed\n ! server responded with %d\n\n", ret ); goto exit; } mbedtls_printf(" ok\n" ); mbedtls_printf( " > Write EHLO to server:" ); fflush( stdout ); gethostname( hostname, 32 ); len = sprintf( (char *) buf, "EHLO %s\r\n", hostname ); ret = write_ssl_and_get_response( &ssl, buf, len ); if( ret < 200 || ret > 299 ) { mbedtls_printf( " failed\n ! server responded with %d\n\n", ret ); goto exit; } } else { mbedtls_printf( " > Get header from server:" ); fflush( stdout ); ret = write_and_get_response( &server_fd, buf, 0 ); if( ret < 200 || ret > 299 ) { mbedtls_printf( " failed\n ! server responded with %d\n\n", ret ); goto exit; } mbedtls_printf(" ok\n" ); mbedtls_printf( " > Write EHLO to server:" ); fflush( stdout ); gethostname( hostname, 32 ); len = sprintf( (char *) buf, "EHLO %s\r\n", hostname ); ret = write_and_get_response( &server_fd, buf, len ); if( ret < 200 || ret > 299 ) { mbedtls_printf( " failed\n ! server responded with %d\n\n", ret ); goto exit; } mbedtls_printf(" ok\n" ); mbedtls_printf( " > Write STARTTLS to server:" ); fflush( stdout ); gethostname( hostname, 32 ); len = sprintf( (char *) buf, "STARTTLS\r\n" ); ret = write_and_get_response( &server_fd, buf, len ); if( ret < 200 || ret > 299 ) { mbedtls_printf( " failed\n ! server responded with %d\n\n", ret ); goto exit; } mbedtls_printf(" ok\n" ); if( do_handshake( &ssl ) != 0 ) goto exit; } #if defined(MBEDTLS_BASE64_C) if( opt.authentication ) { mbedtls_printf( " > Write AUTH LOGIN to server:" ); fflush( stdout ); len = sprintf( (char *) buf, "AUTH LOGIN\r\n" ); ret = write_ssl_and_get_response( &ssl, buf, len ); if( ret < 200 || ret > 399 ) { mbedtls_printf( " failed\n ! server responded with %d\n\n", ret ); goto exit; } mbedtls_printf(" ok\n" ); mbedtls_printf( " > Write username to server: %s", opt.user_name ); fflush( stdout ); ret = mbedtls_base64_encode( base, sizeof( base ), &n, (const unsigned char *) opt.user_name, strlen( opt.user_name ) ); if( ret != 0 ) { mbedtls_printf( " failed\n ! mbedtls_base64_encode returned %d\n\n", ret ); goto exit; } len = sprintf( (char *) buf, "%s\r\n", base ); ret = write_ssl_and_get_response( &ssl, buf, len ); if( ret < 300 || ret > 399 ) { mbedtls_printf( " failed\n ! server responded with %d\n\n", ret ); goto exit; } mbedtls_printf(" ok\n" ); mbedtls_printf( " > Write password to server: %s", opt.user_pwd ); fflush( stdout ); ret = mbedtls_base64_encode( base, sizeof( base ), &n, (const unsigned char *) opt.user_pwd, strlen( opt.user_pwd ) ); if( ret != 0 ) { mbedtls_printf( " failed\n ! mbedtls_base64_encode returned %d\n\n", ret ); goto exit; } len = sprintf( (char *) buf, "%s\r\n", base ); ret = write_ssl_and_get_response( &ssl, buf, len ); if( ret < 200 || ret > 399 ) { mbedtls_printf( " failed\n ! server responded with %d\n\n", ret ); goto exit; } mbedtls_printf(" ok\n" ); } #endif mbedtls_printf( " > Write MAIL FROM to server:" ); fflush( stdout ); len = sprintf( (char *) buf, "MAIL FROM:<%s>\r\n", opt.mail_from ); ret = write_ssl_and_get_response( &ssl, buf, len ); if( ret < 200 || ret > 299 ) { mbedtls_printf( " failed\n ! server responded with %d\n\n", ret ); goto exit; } mbedtls_printf(" ok\n" ); mbedtls_printf( " > Write RCPT TO to server:" ); fflush( stdout ); len = sprintf( (char *) buf, "RCPT TO:<%s>\r\n", opt.mail_to ); ret = write_ssl_and_get_response( &ssl, buf, len ); if( ret < 200 || ret > 299 ) { mbedtls_printf( " failed\n ! server responded with %d\n\n", ret ); goto exit; } mbedtls_printf(" ok\n" ); mbedtls_printf( " > Write DATA to server:" ); fflush( stdout ); len = sprintf( (char *) buf, "DATA\r\n" ); ret = write_ssl_and_get_response( &ssl, buf, len ); if( ret < 300 || ret > 399 ) { mbedtls_printf( " failed\n ! server responded with %d\n\n", ret ); goto exit; } mbedtls_printf(" ok\n" ); mbedtls_printf( " > Write content to server:" ); fflush( stdout ); len = sprintf( (char *) buf, "From: %s\r\nSubject: mbed TLS Test mail\r\n\r\n" "This is a simple test mail from the " "mbed TLS mail client example.\r\n" "\r\n" "Enjoy!", opt.mail_from ); ret = write_ssl_data( &ssl, buf, len ); len = sprintf( (char *) buf, "\r\n.\r\n"); ret = write_ssl_and_get_response( &ssl, buf, len ); if( ret < 200 || ret > 299 ) { mbedtls_printf( " failed\n ! server responded with %d\n\n", ret ); goto exit; } mbedtls_printf(" ok\n" ); mbedtls_ssl_close_notify( &ssl ); exit: mbedtls_net_free( &server_fd ); mbedtls_x509_crt_free( &clicert ); mbedtls_x509_crt_free( &cacert ); mbedtls_pk_free( &pkey ); mbedtls_ssl_free( &ssl ); mbedtls_ssl_config_free( &conf ); mbedtls_ctr_drbg_free( &ctr_drbg ); mbedtls_entropy_free( &entropy ); #if defined(_WIN32) mbedtls_printf( " + Press Enter to exit this program.\n" ); fflush( stdout ); getchar(); #endif return( ret ); }
int main( int argc, const char *argv[] ) { /* Client and server declarations. */ int ret; int len; #if SOCKET_COMMUNICATION mbedtls_net_context listen_fd, client_fd, server_fd; #endif unsigned char buf[1024]; /* Handshake step counter */ size_t step = 1; int flags; mbedtls_ssl_context s_ssl, c_ssl; mbedtls_ssl_config s_conf, c_conf; mbedtls_x509_crt srvcert; mbedtls_pk_context pkey; #if defined(MBEDTLS_SSL_CACHE_C) mbedtls_ssl_cache_context cache; #endif if( argc == 3) { packet_in_num = atoi(argv[1]); packet_in_file = argv[2]; } else if( argc != 1) { usage(argv[0]); exit(1); } /* Server init */ #if SOCKET_COMMUNICATION mbedtls_net_init( &listen_fd ); mbedtls_net_init( &client_fd ); #endif mbedtls_ssl_init( &s_ssl ); mbedtls_ssl_config_init( &s_conf ); #if defined(MBEDTLS_SSL_CACHE_C) mbedtls_ssl_cache_init( &cache ); #endif mbedtls_x509_crt_init( &srvcert ); mbedtls_pk_init( &pkey ); /* Client init */ #if SOCKET_COMMUNICATION mbedtls_net_init( &server_fd ); #endif mbedtls_ssl_init( &c_ssl ); mbedtls_ssl_config_init( &c_conf ); /*mbedtls_x509_crt_init( &cacert );*/ #if defined(MBEDTLS_DEBUG_C) mbedtls_debug_set_threshold( DEBUG_LEVEL ); #endif /* * Server: * Load the certificates and private RSA key */ if( packet_in_num == 0 ) { mbedtls_printf( " . Loading the server cert. and key..." ); fflush( stdout ); } /* * This demonstration program uses embedded test certificates. * Instead, you may want to use mbedtls_x509_crt_parse_file() to read the * server and CA certificates, as well as mbedtls_pk_parse_keyfile(). */ ret = mbedtls_x509_crt_parse( &srvcert, (const unsigned char *) mbedtls_test_srv_crt, mbedtls_test_srv_crt_len ); if( ret != 0 ) { mbedtls_printf( " failed\n ! mbedtls_x509_crt_parse returned %d\n\n", ret ); goto exit; } ret = mbedtls_x509_crt_parse( &srvcert, (const unsigned char *) mbedtls_test_cas_pem, mbedtls_test_cas_pem_len ); if( ret != 0 ) { mbedtls_printf( " failed\n ! mbedtls_x509_crt_parse returned %d\n\n", ret ); goto exit; } ret = mbedtls_pk_parse_key( &pkey, (const unsigned char *) mbedtls_test_srv_key, mbedtls_test_srv_key_len, NULL, 0 ); if( ret != 0 ) { mbedtls_printf( " failed\n ! mbedtls_pk_parse_key returned %d\n\n", ret ); goto exit; } if( packet_in_num == 0 ) { mbedtls_printf( " ok\n" ); } /* * Server: * Setup stuff */ if( packet_in_num == 0 ) { mbedtls_printf( " . Server: Setting up the SSL data...." ); fflush( stdout ); } if( ( ret = mbedtls_ssl_config_defaults( &s_conf, MBEDTLS_SSL_IS_SERVER, MBEDTLS_SSL_TRANSPORT_STREAM, MBEDTLS_SSL_PRESET_DEFAULT ) ) != 0 ) { mbedtls_printf( " failed\n ! mbedtls_ssl_config_defaults returned %d\n\n", ret ); goto exit; } mbedtls_ssl_conf_rng( &s_conf, mbedtls_ctr_drbg_deterministic, NULL ); mbedtls_ssl_conf_dbg( &s_conf, my_debug, stdout ); #if defined(MBEDTLS_SSL_CACHE_C) mbedtls_ssl_conf_session_cache( &s_conf, &cache, mbedtls_ssl_cache_get, mbedtls_ssl_cache_set ); #endif mbedtls_ssl_conf_ca_chain( &s_conf, srvcert.next, NULL ); if( ( ret = mbedtls_ssl_conf_own_cert( &s_conf, &srvcert, &pkey ) ) != 0 ) { mbedtls_printf( " failed\n ! mbedtls_ssl_conf_own_cert returned %d\n\n", ret ); goto exit; } if( ( ret = mbedtls_ssl_setup( &s_ssl, &s_conf ) ) != 0 ) { mbedtls_printf( " failed\n ! mbedtls_ssl_setup returned %d\n\n", ret ); goto exit; } if( packet_in_num == 0 ) { mbedtls_printf( " ok\n" ); } mbedtls_ssl_session_reset( &s_ssl ); #if SOCKET_COMMUNICATION /* * Server: * Setup the listening TCP socket */ if( packet_in_num == 0 ) { mbedtls_printf( " . Bind on https://localhost:%s/ ...", SERVER_PORT ); fflush( stdout ); } if( ( ret = mbedtls_net_bind( &listen_fd, NULL, SERVER_PORT, MBEDTLS_NET_PROTO_TCP ) ) != 0 ) { mbedtls_printf( " failed\n ! mbedtls_net_bind returned %d\n\n", ret ); goto exit; } if( packet_in_num == 0 ) { mbedtls_printf( " ok\n" ); } /* * Client: * Start the connection */ if( packet_in_num == 0 ) { mbedtls_printf( " . Connecting to tcp/%s/%s...", SERVER_NAME, SERVER_PORT ); fflush( stdout ); } if( ( ret = mbedtls_net_connect( &server_fd, SERVER_NAME, SERVER_PORT, MBEDTLS_NET_PROTO_TCP ) ) != 0 ) { mbedtls_printf( " failed\n ! mbedtls_net_connect returned %d\n\n", ret ); goto exit; } if( packet_in_num == 0 ) { mbedtls_printf( " ok\n" ); } /* * Server: * Start listening for client connections */ if( packet_in_num == 0 ) { mbedtls_printf( " . Waiting for a remote connection ..." ); fflush( stdout ); } /* * Server: * Accept client connection (socket is set non-blocking in * library/net.c) */ if( ( ret = mbedtls_net_accept( &listen_fd, &client_fd, NULL, 0, NULL ) ) != 0 ) { mbedtls_printf( " failed\n ! mbedtls_net_accept returned %d\n\n", ret ); goto exit; } if( packet_in_num == 0 ) { mbedtls_printf( " ok\n" ); } mbedtls_ssl_set_bio( &s_ssl, &client_fd, mbedtls_send_custom, mbedtls_recv_custom, NULL ); #else mbedtls_ssl_set_bio( &s_ssl, NULL, mbedtls_server_send_buf, mbedtls_server_recv_buf, NULL ); #endif /* * Client: * Setup stuff */ if( packet_in_num == 0 ) { mbedtls_printf( " . Client: Setting up the SSL/TLS structure..." ); fflush( stdout ); } if( ( ret = mbedtls_ssl_config_defaults( &c_conf, MBEDTLS_SSL_IS_CLIENT, MBEDTLS_SSL_TRANSPORT_STREAM, MBEDTLS_SSL_PRESET_DEFAULT ) ) != 0 ) { mbedtls_printf( " failed\n ! mbedtls_ssl_config_defaults returned %d\n\n", ret ); goto exit; } if( packet_in_num == 0 ) { mbedtls_printf( " ok\n" ); } /* OPTIONAL is not optimal for security, * but makes interop easier in this simplified example */ mbedtls_ssl_conf_authmode( &c_conf, MBEDTLS_SSL_VERIFY_OPTIONAL ); /* NONE permits man-in-the-middle attacks. */ /*mbedtls_ssl_conf_authmode( &c_conf, MBEDTLS_SSL_VERIFY_NONE );*/ /*mbedtls_ssl_conf_authmode( &c_conf, MBEDTLS_SSL_VERIFY_REQUIRED );*/ mbedtls_ssl_conf_ca_chain( &c_conf, &srvcert, NULL ); mbedtls_ssl_conf_rng( &c_conf, mbedtls_ctr_drbg_deterministic, NULL ); mbedtls_ssl_conf_dbg( &c_conf, my_debug, stdout ); if( ( ret = mbedtls_ssl_setup( &c_ssl, &c_conf ) ) != 0 ) { mbedtls_printf( " failed\n ! mbedtls_ssl_setup returned %d\n\n", ret ); goto exit; } if( ( ret = mbedtls_ssl_set_hostname( &c_ssl, "mbed TLS Server 1" ) ) != 0 ) { mbedtls_printf( " failed\n ! mbedtls_ssl_set_hostname returned %d\n\n", ret ); goto exit; } #if SOCKET_COMMUNICATION mbedtls_ssl_set_bio( &c_ssl, &server_fd, mbedtls_send_custom, mbedtls_recv_custom, NULL ); #else mbedtls_ssl_set_bio( &c_ssl, NULL, mbedtls_client_send_buf, mbedtls_client_recv_buf, NULL ); #endif if( packet_in_num == 0 ) { mbedtls_printf( " . Performing the SSL/TLS handshake...\n" ); fflush( stdout ); } /* * The following number of steps are hardcoded to ensure * that the client and server complete the handshake without * waiting infinitely for the other side to send data. * * 1 2 3 4 5 6 7 8 9 10 */ int client_steps[] = { 2, 1, 1, 1, 4, 2, 1, 1, 2, 1 }; int server_steps[] = { 3, 1, 1, 2, 3, 1, 2, 1, 1, 1 }; do { /* * Client: * Handshake step */ int i; int no_steps; if( c_ssl.state == MBEDTLS_SSL_HANDSHAKE_OVER) { no_steps = 0; } else { no_steps = client_steps[step - 1]; } for (i = 0; i < no_steps; i++) { if( ( ret = mbedtls_ssl_handshake_step( &c_ssl ) ) != 0 ) { if( ret != MBEDTLS_ERR_SSL_WANT_READ && ret != MBEDTLS_ERR_SSL_WANT_WRITE ) { mbedtls_printf( " failed\n ! mbedtls_ssl_handshake returned -0x%x\n\n", -ret ); goto exit; } } } if( packet_in_num == 0 ) { mbedtls_printf( "--- client handshake step %zd ok\n", step ); } /* * Server: * Handshake step */ if( s_ssl.state == MBEDTLS_SSL_HANDSHAKE_OVER) { no_steps = 0; } else { no_steps = server_steps[step - 1]; } for (i = 0; i < no_steps; i++) { if( ( ret = mbedtls_ssl_handshake_step( &s_ssl ) ) != 0 ) { if( ret != MBEDTLS_ERR_SSL_WANT_READ && ret != MBEDTLS_ERR_SSL_WANT_WRITE ) { mbedtls_printf( " failed\n ! mbedtls_ssl_handshake returned %d\n\n", ret ); goto exit; } } } if( packet_in_num == 0 ) { mbedtls_printf( "--- server handshake step %zd ok\n", step ); } step++; } while( ((c_ssl.state != MBEDTLS_SSL_HANDSHAKE_OVER) || (s_ssl.state != MBEDTLS_SSL_HANDSHAKE_OVER)) && (step <= MAX_HANDSHAKE_STEPS) ); if( packet_in_num == 0 ) { mbedtls_printf( "c_ssl.state: %d\n", c_ssl.state != MBEDTLS_SSL_HANDSHAKE_OVER ); mbedtls_printf( "s_ssl.state: %d\n", s_ssl.state != MBEDTLS_SSL_HANDSHAKE_OVER ); } /* * Client: * Verify the server certificate */ if( packet_in_num == 0 ) { mbedtls_printf( " . Verifying peer X.509 certificate..." ); } /* In real life, we probably want to bail out when ret != 0 */ if( ( flags = mbedtls_ssl_get_verify_result( &c_ssl ) ) != 0 ) { char vrfy_buf[512]; mbedtls_printf( " failed\n" ); mbedtls_x509_crt_verify_info( vrfy_buf, sizeof( vrfy_buf ), " ! ", flags ); mbedtls_printf( "%s\n", vrfy_buf ); } else if( packet_in_num == 0 ) { mbedtls_printf( " ok\n" ); } /* * Client: * Write the GET request */ if( packet_in_num == 0 ) { mbedtls_printf( " > Write to server:" ); fflush( stdout ); } len = sprintf( (char *) buf, GET_REQUEST ); while( ( ret = mbedtls_ssl_write( &c_ssl, buf, len ) ) <= 0 ) { if( ret != MBEDTLS_ERR_SSL_WANT_READ && ret != MBEDTLS_ERR_SSL_WANT_WRITE ) { mbedtls_printf( " failed\n ! mbedtls_ssl_write returned %d\n\n", ret ); goto exit; } } len = ret; if( packet_in_num == 0 ) { mbedtls_printf( " %d bytes written\n\n%s", len, (char *) buf ); } /* * Server: * Read the HTTP Request */ if( packet_in_num == 0 ) { mbedtls_printf( " < Read from client:" ); fflush( stdout ); } do { len = sizeof( buf ) - 1; memset( buf, 0, sizeof( buf ) ); ret = mbedtls_ssl_read( &s_ssl, buf, len ); if( ret == MBEDTLS_ERR_SSL_WANT_READ || ret == MBEDTLS_ERR_SSL_WANT_WRITE ) continue; if( ret <= 0 ) { switch( ret ) { case MBEDTLS_ERR_SSL_PEER_CLOSE_NOTIFY: mbedtls_printf( " connection was closed gracefully\n" ); break; case MBEDTLS_ERR_NET_CONN_RESET: mbedtls_printf( " connection was reset by peer\n" ); break; default: mbedtls_printf( " mbedtls_ssl_read returned -0x%x\n", -ret ); break; } break; } len = ret; if( packet_in_num == 0 ) { mbedtls_printf( " %d bytes read\n\n%s", len, (char *) buf ); } if( ret > 0 ) break; } while( 1 ); /* * Server: * Write the 200 Response */ if( packet_in_num == 0 ) { mbedtls_printf( " > Write to client:" ); fflush( stdout ); } len = sprintf( (char *) buf, HTTP_RESPONSE, mbedtls_ssl_get_ciphersuite( &s_ssl ) ); while( ( ret = mbedtls_ssl_write( &s_ssl, buf, len ) ) <= 0 ) { if( ret == MBEDTLS_ERR_NET_CONN_RESET ) { mbedtls_printf( " failed\n ! peer closed the connection\n\n" ); goto exit; } if( ret != MBEDTLS_ERR_SSL_WANT_READ && ret != MBEDTLS_ERR_SSL_WANT_WRITE ) { mbedtls_printf( " failed\n ! mbedtls_ssl_write returned %d\n\n", ret ); goto exit; } } len = ret; if( packet_in_num == 0 ) { mbedtls_printf( " %d bytes written\n\n%s\n", len, (char *) buf ); } /* * Client: * Read the HTTP response */ if( packet_in_num == 0 ) { mbedtls_printf( " < Read from server:" ); fflush( stdout ); } do { len = sizeof( buf ) - 1; memset( buf, 0, sizeof( buf ) ); ret = mbedtls_ssl_read( &c_ssl, buf, len ); if( ret == MBEDTLS_ERR_SSL_WANT_READ || ret == MBEDTLS_ERR_SSL_WANT_WRITE ) continue; if( ret == MBEDTLS_ERR_SSL_PEER_CLOSE_NOTIFY ) { ret = 0; break; } if( ret < 0 ) { mbedtls_printf( "failed\n ! mbedtls_ssl_read returned %d\n\n", ret ); break; } if( ret == 0 ) { mbedtls_printf( "\n\nEOF\n\n" ); break; } len = ret; if( packet_in_num == 0 ) { mbedtls_printf( " %d bytes read\n\n%s", len, (char *) buf ); } /* * Server: * Client read response. Close connection. */ if ( packet_in_num == 0 ) { mbedtls_printf( " . Closing the connection..." ); fflush( stdout ); } while( ( ret = mbedtls_ssl_close_notify( &s_ssl ) ) < 0 ) { if( ret != MBEDTLS_ERR_SSL_WANT_READ && ret != MBEDTLS_ERR_SSL_WANT_WRITE ) { mbedtls_printf( " failed\n ! mbedtls_ssl_close_notify returned %d\n\n", ret ); goto exit; } } if( packet_in_num == 0 ) { mbedtls_printf( " ok\n" ); } } while( 1 ); /* * Client: * Close connection. */ if( packet_in_num == 0 ) { mbedtls_printf( " . Closing the connection..." ); fflush( stdout ); } mbedtls_ssl_close_notify( &c_ssl ); if( packet_in_num == 0 ) { mbedtls_printf( " ok\n" ); } /* * Server: * We do not have multiple clients and therefore do not goto reset. */ /*ret = 0;*/ /*goto reset;*/ exit: #ifdef MBEDTLS_ERROR_C if( ret != 0 ) { char error_buf[100]; mbedtls_strerror( ret, error_buf, 100 ); mbedtls_printf("Last error was: %d - %s\n\n", ret, error_buf ); } #endif #if SOCKET_COMMUNICATION mbedtls_net_free( &client_fd ); mbedtls_net_free( &listen_fd ); mbedtls_net_free( &server_fd ); #endif mbedtls_x509_crt_free( &srvcert ); mbedtls_pk_free( &pkey ); mbedtls_ssl_free( &s_ssl ); mbedtls_ssl_free( &c_ssl ); mbedtls_ssl_config_free( &s_conf ); mbedtls_ssl_config_free( &c_conf ); #if defined(MBEDTLS_SSL_CACHE_C) mbedtls_ssl_cache_free( &cache ); #endif #if defined(_WIN32) mbedtls_printf( " Press Enter to exit this program.\n" ); fflush( stdout ); getchar(); #endif return( ret ); }