int coap_security_handler_configure_keys( coap_security_t *sec, coap_security_keys_t keys ) { int ret = -1; switch( sec->_conn_mode ){ case Certificate:{ #if defined(MBEDTLS_X509_CRT_PARSE_C) if( mbedtls_x509_crt_parse( &sec->_cacert, keys._server_cert, keys._server_cert_len ) < 0 ){ break; } if( mbedtls_x509_crt_parse( &sec->_owncert, keys._pub_cert_or_identifier, keys._pub_len ) < 0 ){ break; } if( mbedtls_pk_parse_key(&sec->_pkey, keys._priv, keys._priv_len, NULL, 0) < 0){ break; } //TODO: If needed in server mode, this won't work if( 0 != mbedtls_ssl_conf_own_cert(&sec->_conf, &sec->_owncert, &sec->_pkey) ){ break; } //TODO: use MBEDTLS_SSL_VERIFY_REQUIRED instead of optional mbedtls_ssl_conf_authmode( &sec->_conf, MBEDTLS_SSL_VERIFY_OPTIONAL ); mbedtls_ssl_conf_ca_chain( &sec->_conf, &sec->_cacert, NULL ); ret = 0; #endif break; } case PSK: { #if defined(MBEDTLS_KEY_EXCHANGE__SOME__PSK_ENABLED) if( 0 != mbedtls_ssl_conf_psk(&sec->_conf, keys._priv, keys._priv_len, keys._pub_cert_or_identifier, keys._pub_len) ){ break; } mbedtls_ssl_conf_ciphersuites(&sec->_conf, PSK_SUITES); ret = 0; #endif break; } case ECJPAKE: { #if defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) if( mbedtls_ssl_set_hs_ecjpake_password(&sec->_ssl, keys._priv, keys._priv_len) != 0 ){ return -1; } mbedtls_ssl_conf_ciphersuites(&sec->_conf, ECJPAKE_SUITES); //NOTE: If thread starts supporting PSK in other modes, then this will be needed! mbedtls_ssl_conf_export_keys_cb(&sec->_conf, export_key_block, &sec->_keyblk); ret = 0; #endif break; } default: break; } return ret; }
int Dtls::SetApplicationCoapSecureKeys(void) { int rval = 0; VerifyOrExit(&mCipherSuites[0] != NULL, rval = MBEDTLS_ERR_SSL_BAD_INPUT_DATA); switch (mCipherSuites[0]) { case MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8: #ifdef MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED if (mCaChainSrc != NULL) { rval = mbedtls_x509_crt_parse(&mCaChain, static_cast<const unsigned char *>(mCaChainSrc), static_cast<size_t>(mCaChainLength)); VerifyOrExit(rval == 0); mbedtls_ssl_conf_ca_chain(&mConf, &mCaChain, NULL); } if (mOwnCertSrc != NULL && mPrivateKeySrc != NULL) { rval = mbedtls_x509_crt_parse(&mOwnCert, static_cast<const unsigned char *>(mOwnCertSrc), static_cast<size_t>(mOwnCertLength)); VerifyOrExit(rval == 0); rval = mbedtls_pk_parse_key(&mPrivateKey, static_cast<const unsigned char *>(mPrivateKeySrc), static_cast<size_t>(mPrivateKeyLength), NULL, 0); VerifyOrExit(rval == 0); rval = mbedtls_ssl_conf_own_cert(&mConf, &mOwnCert, &mPrivateKey); VerifyOrExit(rval == 0); } #endif // MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED break; case MBEDTLS_TLS_PSK_WITH_AES_128_CCM_8: #ifdef MBEDTLS_KEY_EXCHANGE_PSK_ENABLED rval = mbedtls_ssl_conf_psk(&mConf, static_cast<const unsigned char *>(mPreSharedKey), mPreSharedKeyLength, static_cast<const unsigned char *>(mPreSharedKeyIdentity), mPreSharedKeyIdLength); VerifyOrExit(rval == 0); #endif // MBEDTLS_KEY_EXCHANGE_PSK_ENABLED break; default: otLogCritCoap("Application Coap Secure DTLS: Not supported cipher."); rval = MBEDTLS_ERR_SSL_BAD_INPUT_DATA; ExitNow(); break; } exit: return rval; }
static int setup_cert(struct net_app_ctx *ctx, void *cert) { #if defined(MBEDTLS_KEY_EXCHANGE__SOME__PSK_ENABLED) mbedtls_ssl_conf_psk(&ctx->tls.mbedtls.conf, client_psk, sizeof(client_psk), (const unsigned char *)client_psk_id, sizeof(client_psk_id) - 1); #endif #if defined(MBEDTLS_X509_CRT_PARSE_C) { mbedtls_x509_crt *ca_cert = cert; int ret; ret = mbedtls_x509_crt_parse_der(ca_cert, ca_certificate, sizeof(ca_certificate)); if (ret != 0) { NET_ERR("mbedtls_x509_crt_parse_der failed " "(-0x%x)", -ret); return ret; } mbedtls_ssl_conf_ca_chain(&ctx->tls.mbedtls.conf, ca_cert, NULL); /* In this example, we skip the certificate checks. In real * life scenarios, one should always verify the certificates. */ mbedtls_ssl_conf_authmode(&ctx->tls.mbedtls.conf, MBEDTLS_SSL_VERIFY_REQUIRED); mbedtls_ssl_conf_cert_profile(&ctx->tls.mbedtls.conf, &mbedtls_x509_crt_profile_default); #define VERIFY_CERTS 0 #if VERIFY_CERTS mbedtls_ssl_conf_authmode(&ctx->tls.mbedtls.conf, MBEDTLS_SSL_VERIFY_OPTIONAL); #else ; #endif /* VERIFY_CERTS */ } #endif /* MBEDTLS_X509_CRT_PARSE_C */ return 0; }
int setup_cert(struct net_app_ctx *ctx, void *cert) { #if defined(MBEDTLS_KEY_EXCHANGE__SOME__PSK_ENABLED) mbedtls_ssl_conf_psk(&ctx->tls.mbedtls.conf, client_psk, sizeof(client_psk), (const unsigned char *)client_psk_id, sizeof(client_psk_id) - 1); #endif #if defined(MBEDTLS_X509_CRT_PARSE_C) { mbedtls_x509_crt *ca_cert = cert; int ret; ret = mbedtls_x509_crt_parse_der(ca_cert, ca_certificate, sizeof(ca_certificate)); if (ret != 0) { NET_ERR("mbedtls_x509_crt_parse_der failed " "(-0x%x)", -ret); return ret; } /* mbedtls_x509_crt_verify() should be called to verify the * cerificate in the real cases */ mbedtls_ssl_conf_ca_chain(&ctx->tls.mbedtls.conf, ca_cert, NULL); mbedtls_ssl_conf_authmode(&ctx->tls.mbedtls.conf, MBEDTLS_SSL_VERIFY_REQUIRED); mbedtls_ssl_conf_cert_profile(&ctx->tls.mbedtls.conf, &mbedtls_x509_crt_profile_default); } #endif /* MBEDTLS_X509_CRT_PARSE_C */ return 0; }
/** * Constructor. */ ManuvrTLSClient::ManuvrTLSClient(BufferPipe* _n) : ManuvrTLS(_n, MBEDTLS_DEBUG_LEVEL) { _tls_pipe_name = "TLSClient"; mbedtls_ssl_init(&_ssl); if (nullptr != _n) { // This is the point at which we detect if our underlying transport // is a stream or datagram. This will impact our choices later on. int ret = mbedtls_ssl_config_defaults(&_conf, MBEDTLS_SSL_IS_CLIENT, _n->_bp_flag(BPIPE_FLAG_PIPE_PACKETIZED) ? MBEDTLS_SSL_TRANSPORT_DATAGRAM : MBEDTLS_SSL_TRANSPORT_STREAM, MBEDTLS_SSL_PRESET_DEFAULT ); if (0 == ret) { mbedtls_ssl_conf_ciphersuites(&_conf, ManuvrTLS::allowed_ciphersuites); // TODO: Sec-fail. YOU FAIL! Remove once inter-op is demonstrated. mbedtls_ssl_conf_authmode(&_conf, MBEDTLS_SSL_VERIFY_OPTIONAL); // TODO: Need to be able to load a CA cert. If we also have // runtime-writable storage, we could do cert-pinning at this point. //mbedtls_ssl_conf_ca_chain( &_conf, &cacert, nullptr); mbedtls_ssl_conf_rng(&_conf, mbedtls_ctr_drbg_random, &_ctr_drbg); mbedtls_ssl_conf_dbg(&_conf, tls_log_shunt, stdout); // TODO: Suspect... // TODO: If appropriate, we load a certificate. //ret = mbedtls_x509_crt_parse( &cacert, (const unsigned char *) if (0 == ret) { // TODO: This should be loaded from secure storage. // TODO: This is a choice independent from the cert. // TODO: We hardcode the same IoTivity default creds used elsewhere. ret = mbedtls_ssl_conf_psk(&_conf, (const unsigned char*)"AAAAAAAAAAAAAAAA", 16, (const unsigned char*)"32323232-3232-3232-3232-323232323232", 36); if (0 == ret) { ret = mbedtls_ssl_setup(&_ssl, &_conf); if (0 == ret) { // TODO: This might be the lookup name if we had DNS. //ret = mbedtls_ssl_set_hostname(&_ssl, SERVER_NAME); if (0 == ret) { _log.concatf("ManuvrTLSClient(): Construction completed.\n"); } else { _log.concatf("ManuvrTLSClient() failed: mbedtls_ssl_set_hostname returned 0x%04x\n", ret); } } else { _log.concatf("ManuvrTLSClient() failed: mbedtls_ssl_setup returned 0x%04x\n", ret); } } else { _log.concatf("ManuvrTLSClient() failed: mbedtls_ssl_conf_psk returned 0x%04x\n", ret); } } else { _log.concatf("ManuvrTLSClient() failed: mbedtls_x509_crt_parse returned 0x%04x\n", ret); } } else { _log.concatf("ManuvrTLSClient() failed: mbedtls_ssl_config_defaults returned 0x%04x\n", ret); } } Kernel::log(&_log); }
int main( void ) { int ret = exit_ok; mbedtls_net_context server_fd; struct sockaddr_in addr; #if defined(MBEDTLS_X509_CRT_PARSE_C) mbedtls_x509_crt ca; #endif mbedtls_entropy_context entropy; mbedtls_ctr_drbg_context ctr_drbg; mbedtls_ssl_context ssl; mbedtls_ssl_config conf; mbedtls_ctr_drbg_init( &ctr_drbg ); /* * 0. Initialize and setup stuff */ mbedtls_net_init( &server_fd ); mbedtls_ssl_init( &ssl ); mbedtls_ssl_config_init( &conf ); #if defined(MBEDTLS_X509_CRT_PARSE_C) mbedtls_x509_crt_init( &ca ); #endif mbedtls_entropy_init( &entropy ); if( mbedtls_ctr_drbg_seed( &ctr_drbg, mbedtls_entropy_func, &entropy, (const unsigned char *) pers, strlen( pers ) ) != 0 ) { ret = ctr_drbg_seed_failed; goto exit; } if( mbedtls_ssl_config_defaults( &conf, MBEDTLS_SSL_IS_CLIENT, MBEDTLS_SSL_TRANSPORT_STREAM, MBEDTLS_SSL_PRESET_DEFAULT ) != 0 ) { ret = ssl_config_defaults_failed; goto exit; } mbedtls_ssl_conf_rng( &conf, mbedtls_ctr_drbg_random, &ctr_drbg ); #if defined(MBEDTLS_KEY_EXCHANGE__SOME__PSK_ENABLED) mbedtls_ssl_conf_psk( &conf, psk, sizeof( psk ), (const unsigned char *) psk_id, sizeof( psk_id ) - 1 ); #endif #if defined(MBEDTLS_X509_CRT_PARSE_C) if( mbedtls_x509_crt_parse_der( &ca, ca_cert, sizeof( ca_cert ) ) != 0 ) { ret = x509_crt_parse_failed; goto exit; } mbedtls_ssl_conf_ca_chain( &conf, &ca, NULL ); mbedtls_ssl_conf_authmode( &conf, MBEDTLS_SSL_VERIFY_REQUIRED ); #endif if( mbedtls_ssl_setup( &ssl, &conf ) != 0 ) { ret = ssl_setup_failed; goto exit; } #if defined(MBEDTLS_X509_CRT_PARSE_C) if( mbedtls_ssl_set_hostname( &ssl, HOSTNAME ) != 0 ) { ret = hostname_failed; goto exit; } #endif /* * 1. Start the connection */ memset( &addr, 0, sizeof( addr ) ); addr.sin_family = AF_INET; ret = 1; /* for endianness detection */ addr.sin_port = *((char *) &ret) == ret ? PORT_LE : PORT_BE; addr.sin_addr.s_addr = *((char *) &ret) == ret ? ADDR_LE : ADDR_BE; ret = 0; if( ( server_fd.fd = socket( AF_INET, SOCK_STREAM, 0 ) ) < 0 ) { ret = socket_failed; goto exit; } if( connect( server_fd.fd, (const struct sockaddr *) &addr, sizeof( addr ) ) < 0 ) { ret = connect_failed; goto exit; } mbedtls_ssl_set_bio( &ssl, &server_fd, mbedtls_net_send, mbedtls_net_recv, NULL ); if( mbedtls_ssl_handshake( &ssl ) != 0 ) { ret = ssl_handshake_failed; goto exit; } /* * 2. Write the GET request and close the connection */ if( mbedtls_ssl_write( &ssl, (const unsigned char *) GET_REQUEST, sizeof( GET_REQUEST ) - 1 ) <= 0 ) { ret = ssl_write_failed; goto exit; } mbedtls_ssl_close_notify( &ssl ); exit: mbedtls_net_free( &server_fd ); mbedtls_ssl_free( &ssl ); mbedtls_ssl_config_free( &conf ); mbedtls_ctr_drbg_free( &ctr_drbg ); mbedtls_entropy_free( &entropy ); #if defined(MBEDTLS_X509_CRT_PARSE_C) mbedtls_x509_crt_free( &ca ); #endif return( ret ); }
void tls_client(void) { int ret = exit_ok; struct tcp_context ctx; ctx.timeout = MBEDTLS_NETWORK_TIMEOUT; #if defined(MBEDTLS_X509_CRT_PARSE_C) mbedtls_x509_crt ca; #endif mbedtls_entropy_context entropy; mbedtls_ctr_drbg_context ctr_drbg; mbedtls_ssl_context ssl; mbedtls_ssl_config conf; mbedtls_ctr_drbg_init(&ctr_drbg); mbedtls_platform_set_printf(PRINT); /* * 0. Initialize and setup stuff */ mbedtls_ssl_init(&ssl); mbedtls_ssl_config_init(&conf); #if defined(MBEDTLS_X509_CRT_PARSE_C) mbedtls_x509_crt_init(&ca); #endif mbedtls_printf("\n . Seeding the random number generator..."); mbedtls_entropy_init(&entropy); mbedtls_entropy_add_source(&entropy, entropy_source, NULL, MBEDTLS_ENTROPY_MAX_GATHER, MBEDTLS_ENTROPY_SOURCE_STRONG); if (mbedtls_ctr_drbg_seed(&ctr_drbg, mbedtls_entropy_func, &entropy, (const unsigned char *)pers, strlen(pers)) != 0) { ret = ctr_drbg_seed_failed; mbedtls_printf (" failed\n ! mbedtls_ctr_drbg_seed returned -0x%x\n", -ret); goto exit; } mbedtls_printf(" ok\n"); mbedtls_printf(" . Setting up the SSL/TLS structure..."); if (mbedtls_ssl_config_defaults(&conf, MBEDTLS_SSL_IS_CLIENT, MBEDTLS_SSL_TRANSPORT_STREAM, MBEDTLS_SSL_PRESET_DEFAULT) != 0) { ret = ssl_config_defaults_failed; mbedtls_printf (" failed\n ! mbedtls_ssl_config_defaults returned -0x%x\n\n", -ret); goto exit; } mbedtls_ssl_conf_rng(&conf, mbedtls_ctr_drbg_random, &ctr_drbg); #if defined(MBEDTLS_MEMORY_BUFFER_ALLOC_C) mbedtls_memory_buffer_alloc_init(heap, sizeof(heap)); #endif #if defined(MBEDTLS_KEY_EXCHANGE__SOME__PSK_ENABLED) mbedtls_ssl_conf_psk(&conf, psk, sizeof(psk), (const unsigned char *)psk_id, sizeof(psk_id) - 1); #endif #if defined(MBEDTLS_X509_CRT_PARSE_C) if (mbedtls_x509_crt_parse_der(&ca, ca_cert, sizeof(ca_cert)) != 0) { ret = x509_crt_parse_failed; mbedtls_printf (" failed\n ! mbedtls_x509_crt_parse returned -0x%x\n\n", -ret); goto exit; } mbedtls_ssl_conf_ca_chain(&conf, &ca, NULL); mbedtls_ssl_conf_authmode(&conf, MBEDTLS_SSL_VERIFY_REQUIRED); #endif if (mbedtls_ssl_setup(&ssl, &conf) != 0) { ret = ssl_setup_failed; mbedtls_printf (" failed\n ! mbedtls_ssl_setup returned -0x%x\n\n", -ret); goto exit; } #if defined(MBEDTLS_X509_CRT_PARSE_C) if (mbedtls_ssl_set_hostname(&ssl, HOSTNAME) != 0) { ret = hostname_failed; mbedtls_printf (" failed\n ! mbedtls_ssl_set_hostname returned %d\n\n", ret); goto exit; } #endif mbedtls_printf(" ok\n"); /* * 1. Start the connection */ mbedtls_printf(" . Connecting to tcp %s...", SERVER_ADDR); if (tcp_set_local_addr(&ctx, LOCAL_ADDR) != 0) { printk("tcp set_local_addr error\n"); goto exit; } if (tcp_init(&ctx, SERVER_ADDR, SERVER_PORT) != 0) { ret = connect_failed; mbedtls_printf(" failed\n ! tcp_init returned -0x%x\n\n", -ret); goto exit; } mbedtls_printf(" ok\n"); mbedtls_ssl_set_bio(&ssl, &ctx, tcp_tx, tcp_rx, NULL); mbedtls_printf(" . Performing the SSL/TLS handshake..."); if (mbedtls_ssl_handshake(&ssl) != 0) { ret = ssl_handshake_failed; mbedtls_printf (" failed\n ! mbedtls_ssl_handshake returned -0x%x\n", -ret); goto exit; } mbedtls_printf(" ok\n"); /* * 2. Write the GET request and close the connection */ mbedtls_printf(" > Write to server:"); if (mbedtls_ssl_write(&ssl, (const unsigned char *)GET_REQUEST, sizeof(GET_REQUEST) - 1) <= 0) { ret = ssl_write_failed; mbedtls_printf (" failed\n ! mbedtls_ssl_write returned -0x%x\n\n", -ret); goto exit; } mbedtls_printf(" ok\n"); mbedtls_printf(" . Closing the connection..."); mbedtls_ssl_close_notify(&ssl); mbedtls_printf(" done\n"); exit: mbedtls_ssl_free(&ssl); mbedtls_ssl_config_free(&conf); mbedtls_ctr_drbg_free(&ctr_drbg); mbedtls_entropy_free(&entropy); #if defined(MBEDTLS_X509_CRT_PARSE_C) mbedtls_x509_crt_free(&ca); #endif }
int 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 0x%04x\n", ret ); goto exit; } 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 0x%04x\n\n", ret ); goto exit; } mbedtls_ssl_conf_ciphersuites(&conf, allowed_ciphersuites); 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; } ret = mbedtls_ssl_conf_psk(&conf, (const unsigned char*)"AAAAAAAAAAAAAAAA", 16, (const unsigned char*)"32323232-3232-3232-3232-323232323232", 36); if( ret < 0 ) { mbedtls_printf( " failed\n ! mbedtls_ssl_conf_psk() 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 0x%04x\n\n", ret ); goto exit; } mbedtls_printf( " ok\n" ); /* * 2. Setup stuff */ mbedtls_printf( " . Setting up the DTLS structure..." ); fflush( stdout ); /* 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 0x%04x\n\n", ret ); goto exit; } if( ( ret = mbedtls_ssl_set_hostname( &ssl, SERVER_NAME ) ) != 0 ) { mbedtls_printf( " failed\n ! mbedtls_ssl_set_hostname returned 0x%04x\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 0x%04x\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: 0x%04x - %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 ); }
void dtls_server(void) { int len, ret = 0; struct udp_context ctx; struct dtls_timing_context timer; struct zoap_packet zpkt; struct net_pkt *pkt; struct net_buf *frag; 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_ctr_drbg_init(&ctr_drbg); mbedtls_platform_set_printf(printk); #if defined(MBEDTLS_DEBUG_C) mbedtls_debug_set_threshold(DEBUG_THRESHOLD); #endif /* * Initialize and setup */ mbedtls_ssl_init(&ssl); mbedtls_ssl_config_init(&conf); mbedtls_entropy_init(&entropy); mbedtls_entropy_add_source(&entropy, entropy_source, NULL, MBEDTLS_ENTROPY_MAX_GATHER, MBEDTLS_ENTROPY_SOURCE_STRONG); ret = mbedtls_ctr_drbg_seed(&ctr_drbg, mbedtls_entropy_func, &entropy, (const unsigned char *)pers, strlen(pers)); if (ret != 0) { mbedtls_printf(" failed!\n" " mbedtls_ctr_drbg_seed returned -0x%x\n", -ret); goto exit; } ret = mbedtls_ssl_config_defaults(&conf, MBEDTLS_SSL_IS_SERVER, MBEDTLS_SSL_TRANSPORT_DATAGRAM, MBEDTLS_SSL_PRESET_DEFAULT); if (ret != 0) { mbedtls_printf(" failed!\n" " mbedtls_ssl_config_defaults returned -0x%x\n", -ret); goto exit; } /* Modify this to change the default timeouts for the DTLS handshake */ /* mbedtls_ssl_conf_handshake_timeout( &conf, min, max ); */ mbedtls_ssl_conf_rng(&conf, mbedtls_ctr_drbg_random, &ctr_drbg); mbedtls_ssl_conf_dbg(&conf, my_debug, NULL); #if defined(MBEDTLS_MEMORY_BUFFER_ALLOC_C) mbedtls_memory_buffer_alloc_init(heap, sizeof(heap)); #endif ret = mbedtls_ssl_cookie_setup(&cookie_ctx, mbedtls_ctr_drbg_random, &ctr_drbg); if (ret != 0) { mbedtls_printf(" failed!\n" " mbedtls_ssl_cookie_setup returned -0x%x\n", -ret); goto exit; } mbedtls_ssl_conf_dtls_cookies(&conf, mbedtls_ssl_cookie_write, mbedtls_ssl_cookie_check, &cookie_ctx); ret = mbedtls_ssl_setup(&ssl, &conf); if (ret != 0) { mbedtls_printf(" failed!\n" " mbedtls_ssl_setup returned -0x%x\n", -ret); goto exit; } ret = udp_init(&ctx); if (ret != 0) { mbedtls_printf(" failed!\n udp_init returned 0x%x\n", ret); goto exit; } reset: mbedtls_ssl_session_reset(&ssl); #if defined(MBEDTLS_KEY_EXCHANGE__SOME__PSK_ENABLED) ret = mbedtls_ssl_conf_psk(&conf, psk, strlen(psk), psk_id, strlen(psk_id)); if (ret != 0) { mbedtls_printf(" failed!\n mbedtls_ssl_conf_psk" " returned -0x%04X\n", -ret); goto exit; } #endif mbedtls_ssl_set_timer_cb(&ssl, &timer, dtls_timing_set_delay, dtls_timing_get_delay); mbedtls_ssl_set_bio(&ssl, &ctx, udp_tx, udp_rx, NULL); /* For HelloVerifyRequest cookies */ ctx.client_id = (char)ctx.remaining; ret = mbedtls_ssl_set_client_transport_id(&ssl, &ctx.client_id, sizeof(char)); if (ret != 0) { mbedtls_printf(" failed!\n" " mbedtls_ssl_set_client_transport_id()" " returned -0x%x\n", -ret); goto exit; } curr_ctx = &ssl; 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) { ret = 0; goto reset; } if (ret != 0) { mbedtls_printf(" failed!\n" " mbedtls_ssl_handshake returned -0x%x\n", -ret); goto reset; } do { /* Read the request */ pkt = net_pkt_get_reserve(&zoap_pkt_slab, 0, K_NO_WAIT); if (!pkt) { mbedtls_printf("Could not get packet from slab\n"); goto exit; } frag = net_buf_alloc(&zoap_data_pool, K_NO_WAIT); if (!frag) { mbedtls_printf("Could not get frag from pool\n"); goto exit; } net_pkt_frag_add(pkt, frag); len = ZOAP_BUF_SIZE - 1; memset(frag->data, 0, ZOAP_BUF_SIZE); ret = mbedtls_ssl_read(&ssl, frag->data, len); if (ret == MBEDTLS_ERR_SSL_WANT_READ || ret == MBEDTLS_ERR_SSL_WANT_WRITE) { continue; } if (ret <= 0) { net_pkt_unref(pkt); switch (ret) { case MBEDTLS_ERR_SSL_TIMEOUT: mbedtls_printf(" timeout\n"); goto reset; case MBEDTLS_ERR_SSL_PEER_CLOSE_NOTIFY: mbedtls_printf(" connection was closed" " gracefully\n"); goto close_notify; default: mbedtls_printf(" mbedtls_ssl_read" " returned -0x%x\n", -ret); goto reset; } } len = ret; frag->len = len; ret = zoap_packet_parse(&zpkt, pkt); if (ret) { mbedtls_printf("Could not parse packet\n"); goto exit; } ret = zoap_handle_request(&zpkt, resources, (const struct sockaddr *)&ssl); if (ret < 0) { mbedtls_printf("No handler for such request (%d)\n", ret); } net_pkt_unref(pkt); } while (1); close_notify: /* 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"); goto reset; exit: mbedtls_ssl_free(&ssl); mbedtls_ssl_config_free(&conf); mbedtls_ctr_drbg_free(&ctr_drbg); mbedtls_entropy_free(&entropy); }