Exemplo n.º 1
0
static CURLcode
mbed_connect_step1(struct connectdata *conn,
                   int sockindex)
{
  struct SessionHandle *data = conn->data;
  struct ssl_connect_data* connssl = &conn->ssl[sockindex];

  bool sni = TRUE; /* default is SNI enabled */
  int ret = -1;
#ifdef ENABLE_IPV6
  struct in6_addr addr;
#else
  struct in_addr addr;
#endif
  void *old_session = NULL;
  char errorbuf[128];
  errorbuf[0]=0;

  /* mbedTLS only supports SSLv3 and TLSv1 */
  if(data->set.ssl.version == CURL_SSLVERSION_SSLv2) {
    failf(data, "mbedTLS does not support SSLv2");
    return CURLE_SSL_CONNECT_ERROR;
  }
  else if(data->set.ssl.version == CURL_SSLVERSION_SSLv3)
    sni = FALSE; /* SSLv3 has no SNI */

#ifdef THREADING_SUPPORT
  entropy_init_mutex(&entropy);
  mbedtls_ctr_drbg_init(&connssl->ctr_drbg);

  ret = mbedtls_ctr_drbg_seed(&connssl->ctr_drbg, entropy_func_mutex,
                              &entropy, NULL, 0);
  if(ret) {
#ifdef MBEDTLS_ERROR_C
    mbedtls_strerror(ret, errorbuf, sizeof(errorbuf));
#endif /* MBEDTLS_ERROR_C */
    failf(data, "Failed - mbedTLS: ctr_drbg_init returned (-0x%04X) %s\n",
          -ret, errorbuf);
  }
#else
  mbedtls_entropy_init(&connssl->entropy);
  mbedtls_ctr_drbg_init(&connssl->ctr_drbg);

  ret = mbedtls_ctr_drbg_seed(&connssl->ctr_drbg, mbedtls_entropy_func,
                              &connssl->entropy, NULL, 0);
  if(ret) {
#ifdef MBEDTLS_ERROR_C
    mbedtls_strerror(ret, errorbuf, sizeof(errorbuf));
#endif /* MBEDTLS_ERROR_C */
    failf(data, "Failed - mbedTLS: ctr_drbg_init returned (-0x%04X) %s\n",
          -ret, errorbuf);
  }
#endif /* THREADING_SUPPORT */

  /* Load the trusted CA */
  mbedtls_x509_crt_init(&connssl->cacert);

  if(data->set.str[STRING_SSL_CAFILE]) {
    ret = mbedtls_x509_crt_parse_file(&connssl->cacert,
                                      data->set.str[STRING_SSL_CAFILE]);

    if(ret<0) {
#ifdef MBEDTLS_ERROR_C
      mbedtls_strerror(ret, errorbuf, sizeof(errorbuf));
#endif /* MBEDTLS_ERROR_C */
      failf(data, "Error reading ca cert file %s - mbedTLS: (-0x%04X) %s",
            data->set.str[STRING_SSL_CAFILE], -ret, errorbuf);

      if(data->set.ssl.verifypeer)
        return CURLE_SSL_CACERT_BADFILE;
    }
  }

  if(data->set.str[STRING_SSL_CAPATH]) {
    ret = mbedtls_x509_crt_parse_path(&connssl->cacert,
                                      data->set.str[STRING_SSL_CAPATH]);

    if(ret<0) {
#ifdef MBEDTLS_ERROR_C
      mbedtls_strerror(ret, errorbuf, sizeof(errorbuf));
#endif /* MBEDTLS_ERROR_C */
      failf(data, "Error reading ca cert path %s - mbedTLS: (-0x%04X) %s",
            data->set.str[STRING_SSL_CAPATH], -ret, errorbuf);

      if(data->set.ssl.verifypeer)
        return CURLE_SSL_CACERT_BADFILE;
    }
  }

  /* Load the client certificate */
  mbedtls_x509_crt_init(&connssl->clicert);

  if(data->set.str[STRING_CERT]) {
    ret = mbedtls_x509_crt_parse_file(&connssl->clicert,
                                      data->set.str[STRING_CERT]);

    if(ret) {
#ifdef MBEDTLS_ERROR_C
      mbedtls_strerror(ret, errorbuf, sizeof(errorbuf));
#endif /* MBEDTLS_ERROR_C */
      failf(data, "Error reading client cert file %s - mbedTLS: (-0x%04X) %s",
            data->set.str[STRING_CERT], -ret, errorbuf);

      return CURLE_SSL_CERTPROBLEM;
    }
  }

  /* Load the client private key */
  mbedtls_pk_init(&connssl->pk);

  if(data->set.str[STRING_KEY]) {
    ret = mbedtls_pk_parse_keyfile(&connssl->pk, data->set.str[STRING_KEY],
                                   data->set.str[STRING_KEY_PASSWD]);
    if(ret == 0 && !mbedtls_pk_can_do(&connssl->pk, MBEDTLS_PK_RSA))
      ret = MBEDTLS_ERR_PK_TYPE_MISMATCH;

    if(ret) {
#ifdef MBEDTLS_ERROR_C
      mbedtls_strerror(ret, errorbuf, sizeof(errorbuf));
#endif /* MBEDTLS_ERROR_C */
      failf(data, "Error reading private key %s - mbedTLS: (-0x%04X) %s",
            data->set.str[STRING_KEY], -ret, errorbuf);

      return CURLE_SSL_CERTPROBLEM;
    }
  }

  /* Load the CRL */
  mbedtls_x509_crl_init(&connssl->crl);

  if(data->set.str[STRING_SSL_CRLFILE]) {
    ret = mbedtls_x509_crl_parse_file(&connssl->crl,
                                      data->set.str[STRING_SSL_CRLFILE]);

    if(ret) {
#ifdef MBEDTLS_ERROR_C
      mbedtls_strerror(ret, errorbuf, sizeof(errorbuf));
#endif /* MBEDTLS_ERROR_C */
      failf(data, "Error reading CRL file %s - mbedTLS: (-0x%04X) %s",
            data->set.str[STRING_SSL_CRLFILE], -ret, errorbuf);

      return CURLE_SSL_CRL_BADFILE;
    }
  }

  infof(data, "mbedTLS: Connecting to %s:%d\n",
        conn->host.name, conn->remote_port);

  mbedtls_ssl_config_init(&connssl->config);

  mbedtls_ssl_init(&connssl->ssl);
  if(mbedtls_ssl_setup(&connssl->ssl, &connssl->config)) {
    failf(data, "mbedTLS: ssl_init failed");
    return CURLE_SSL_CONNECT_ERROR;
  }
  ret = mbedtls_ssl_config_defaults(&connssl->config,
                                    MBEDTLS_SSL_IS_CLIENT,
                                    MBEDTLS_SSL_TRANSPORT_STREAM,
                                    MBEDTLS_SSL_PRESET_DEFAULT);
  if(ret) {
    failf(data, "mbedTLS: ssl_config failed");
    return CURLE_SSL_CONNECT_ERROR;
  }

  /* new profile with RSA min key len = 1024 ... */
  mbedtls_ssl_conf_cert_profile(&connssl->config,
                                &mbedtls_x509_crt_profile_fr);

  switch(data->set.ssl.version) {
  case CURL_SSLVERSION_DEFAULT:
  case CURL_SSLVERSION_TLSv1:
    mbedtls_ssl_conf_min_version(&connssl->config, MBEDTLS_SSL_MAJOR_VERSION_3,
                                 MBEDTLS_SSL_MINOR_VERSION_1);
    infof(data, "mbedTLS: Set min SSL version to TLS 1.0\n");
    break;
  case CURL_SSLVERSION_SSLv3:
    mbedtls_ssl_conf_min_version(&connssl->config, MBEDTLS_SSL_MAJOR_VERSION_3,
                                 MBEDTLS_SSL_MINOR_VERSION_0);
    mbedtls_ssl_conf_max_version(&connssl->config, MBEDTLS_SSL_MAJOR_VERSION_3,
                                 MBEDTLS_SSL_MINOR_VERSION_0);
    infof(data, "mbedTLS: Set SSL version to SSLv3\n");
    break;
  case CURL_SSLVERSION_TLSv1_0:
    mbedtls_ssl_conf_min_version(&connssl->config, MBEDTLS_SSL_MAJOR_VERSION_3,
                                 MBEDTLS_SSL_MINOR_VERSION_1);
    mbedtls_ssl_conf_max_version(&connssl->config, MBEDTLS_SSL_MAJOR_VERSION_3,
                                 MBEDTLS_SSL_MINOR_VERSION_1);
    infof(data, "mbedTLS: Set SSL version to TLS 1.0\n");
    break;
  case CURL_SSLVERSION_TLSv1_1:
    mbedtls_ssl_conf_min_version(&connssl->config, MBEDTLS_SSL_MAJOR_VERSION_3,
                                 MBEDTLS_SSL_MINOR_VERSION_2);
    mbedtls_ssl_conf_max_version(&connssl->config, MBEDTLS_SSL_MAJOR_VERSION_3,
                                 MBEDTLS_SSL_MINOR_VERSION_2);
    infof(data, "mbedTLS: Set SSL version to TLS 1.1\n");
    break;
  case CURL_SSLVERSION_TLSv1_2:
    mbedtls_ssl_conf_min_version(&connssl->config, MBEDTLS_SSL_MAJOR_VERSION_3,
                                 MBEDTLS_SSL_MINOR_VERSION_3);
    mbedtls_ssl_conf_max_version(&connssl->config, MBEDTLS_SSL_MAJOR_VERSION_3,
                                 MBEDTLS_SSL_MINOR_VERSION_3);
    infof(data, "mbedTLS: Set SSL version to TLS 1.2\n");
    break;
  default:
    failf(data, "mbedTLS: Unsupported SSL protocol version");
    return CURLE_SSL_CONNECT_ERROR;
  }

  mbedtls_ssl_conf_authmode(&connssl->config, MBEDTLS_SSL_VERIFY_OPTIONAL);

  mbedtls_ssl_conf_rng(&connssl->config, mbedtls_ctr_drbg_random,
                       &connssl->ctr_drbg);
  mbedtls_ssl_set_bio(&connssl->ssl, &conn->sock[sockindex],
                      mbedtls_net_send,
                      mbedtls_net_recv,
                      NULL /*  rev_timeout() */);

  mbedtls_ssl_conf_ciphersuites(&connssl->config,
                                mbedtls_ssl_list_ciphersuites());
  if(!Curl_ssl_getsessionid(conn, &old_session, NULL)) {
    ret = mbedtls_ssl_set_session(&connssl->ssl, old_session);
    if(ret) {
      failf(data, "mbedtls_ssl_set_session returned -0x%x", -ret);
      return CURLE_SSL_CONNECT_ERROR;
    }
    infof(data, "mbedTLS re-using session\n");
  }

  mbedtls_ssl_conf_ca_chain(&connssl->config,
                            &connssl->cacert,
                            &connssl->crl);

  if(data->set.str[STRING_KEY]) {
    mbedtls_ssl_conf_own_cert(&connssl->config,
                              &connssl->clicert, &connssl->pk);
  }
  if(!Curl_inet_pton(AF_INET, conn->host.name, &addr) &&
#ifdef ENABLE_IPV6
     !Curl_inet_pton(AF_INET6, conn->host.name, &addr) &&
#endif
     sni && mbedtls_ssl_set_hostname(&connssl->ssl, conn->host.name)) {
    infof(data, "WARNING: failed to configure "
          "server name indication (SNI) TLS extension\n");
  }

#ifdef HAS_ALPN
  if(data->set.ssl_enable_alpn) {
    const char **p = &connssl->protocols[0];
#ifdef USE_NGHTTP2
    if(data->set.httpversion >= CURL_HTTP_VERSION_2)
      *p++ = NGHTTP2_PROTO_VERSION_ID;
#endif
    *p++ = ALPN_HTTP_1_1;
    *p = NULL;
    /* this function doesn't clone the protocols array, which is why we need
       to keep it around */
    if(mbedtls_ssl_conf_alpn_protocols(&connssl->config,
                                       &connssl->protocols[0])) {
      failf(data, "Failed setting ALPN protocols");
      return CURLE_SSL_CONNECT_ERROR;
    }
    for(p = &connssl->protocols[0]; *p; ++p)
      infof(data, "ALPN, offering %s\n", *p);
  }
#endif

#ifdef MBEDTLS_DEBUG
  mbedtls_ssl_conf_dbg(&connssl->config, mbedtls_debug, data);
#endif

  connssl->connecting_state = ssl_connect_2;

  return CURLE_OK;
}
Exemplo n.º 2
0
static CURLcode
mbed_connect_step2(struct connectdata *conn,
                   int sockindex)
{
  int ret;
  struct SessionHandle *data = conn->data;
  struct ssl_connect_data* connssl = &conn->ssl[sockindex];
  const mbedtls_x509_crt *peercert;

#ifdef HAS_ALPN
  const char* next_protocol;
#endif

  char errorbuf[128];
  errorbuf[0] = 0;

  conn->recv[sockindex] = mbed_recv;
  conn->send[sockindex] = mbed_send;

  ret = mbedtls_ssl_handshake(&connssl->ssl);

  if(ret == MBEDTLS_ERR_SSL_WANT_READ) {
    connssl->connecting_state = ssl_connect_2_reading;
    return CURLE_OK;
  }
  else if(ret == MBEDTLS_ERR_SSL_WANT_WRITE) {
    connssl->connecting_state = ssl_connect_2_writing;
    return CURLE_OK;
  }
  else if(ret) {
#ifdef MBEDTLS_ERROR_C
    mbedtls_strerror(ret, errorbuf, sizeof(errorbuf));
#endif /* MBEDTLS_ERROR_C */
    failf(data, "ssl_handshake returned - mbedTLS: (-0x%04X) %s",
          -ret, errorbuf);
    return CURLE_SSL_CONNECT_ERROR;
  }

  infof(data, "mbedTLS: Handshake complete, cipher is %s\n",
        mbedtls_ssl_get_ciphersuite(&conn->ssl[sockindex].ssl)
    );

  ret = mbedtls_ssl_get_verify_result(&conn->ssl[sockindex].ssl);

  if(ret && data->set.ssl.verifypeer) {
    if(ret & MBEDTLS_X509_BADCERT_EXPIRED)
      failf(data, "Cert verify failed: BADCERT_EXPIRED");

    if(ret & MBEDTLS_X509_BADCERT_REVOKED) {
      failf(data, "Cert verify failed: BADCERT_REVOKED");
      return CURLE_SSL_CACERT;
    }

    if(ret & MBEDTLS_X509_BADCERT_CN_MISMATCH)
      failf(data, "Cert verify failed: BADCERT_CN_MISMATCH");

    if(ret & MBEDTLS_X509_BADCERT_NOT_TRUSTED)
      failf(data, "Cert verify failed: BADCERT_NOT_TRUSTED");

    return CURLE_PEER_FAILED_VERIFICATION;
  }

  peercert = mbedtls_ssl_get_peer_cert(&connssl->ssl);

  if(peercert && data->set.verbose) {
    const size_t bufsize = 16384;
    char *buffer = malloc(bufsize);

    if(!buffer)
      return CURLE_OUT_OF_MEMORY;

    if(mbedtls_x509_crt_info(buffer, bufsize, "* ", peercert) > 0)
      infof(data, "Dumping cert info:\n%s\n", buffer);
    else
      infof(data, "Unable to dump certificate information.\n");

    free(buffer);
  }

  if(data->set.str[STRING_SSL_PINNEDPUBLICKEY]) {
    int size;
    CURLcode result;
    mbedtls_x509_crt *p;
    unsigned char pubkey[PUB_DER_MAX_BYTES];

    if(!peercert || !peercert->raw.p || !peercert->raw.len) {
      failf(data, "Failed due to missing peer certificate");
      return CURLE_SSL_PINNEDPUBKEYNOTMATCH;
    }

    p = calloc(1, sizeof(*p));

    if(!p)
      return CURLE_OUT_OF_MEMORY;

    mbedtls_x509_crt_init(p);

    /* Make a copy of our const peercert because mbedtls_pk_write_pubkey_der
       needs a non-const key, for now.
       https://github.com/ARMmbed/mbedtls/issues/396 */
    if(mbedtls_x509_crt_parse_der(p, peercert->raw.p, peercert->raw.len)) {
      failf(data, "Failed copying peer certificate");
      mbedtls_x509_crt_free(p);
      free(p);
      return CURLE_SSL_PINNEDPUBKEYNOTMATCH;
    }

    size = mbedtls_pk_write_pubkey_der(&p->pk, pubkey, PUB_DER_MAX_BYTES);

    if(size <= 0) {
      failf(data, "Failed copying public key from peer certificate");
      mbedtls_x509_crt_free(p);
      free(p);
      return CURLE_SSL_PINNEDPUBKEYNOTMATCH;
    }

    /* mbedtls_pk_write_pubkey_der writes data at the end of the buffer. */
    result = Curl_pin_peer_pubkey(data,
                                  data->set.str[STRING_SSL_PINNEDPUBLICKEY],
                                  &pubkey[PUB_DER_MAX_BYTES - size], size);
    if(result) {
      mbedtls_x509_crt_free(p);
      free(p);
      return result;
    }

    mbedtls_x509_crt_free(p);
    free(p);
  }

#ifdef HAS_ALPN
  if(data->set.ssl_enable_alpn) {
    next_protocol = mbedtls_ssl_get_alpn_protocol(&connssl->ssl);

    if(next_protocol) {
      infof(data, "ALPN, server accepted to use %s\n", next_protocol);
#ifdef USE_NGHTTP2
      if(!strncmp(next_protocol, NGHTTP2_PROTO_VERSION_ID,
                  NGHTTP2_PROTO_VERSION_ID_LEN) &&
         !next_protocol[NGHTTP2_PROTO_VERSION_ID_LEN]) {
        conn->negnpn = CURL_HTTP_VERSION_2;
      }
      else
#endif
        if(!strncmp(next_protocol, ALPN_HTTP_1_1, ALPN_HTTP_1_1_LENGTH) &&
           !next_protocol[ALPN_HTTP_1_1_LENGTH]) {
          conn->negnpn = CURL_HTTP_VERSION_1_1;
        }
    }
    else {
      infof(data, "ALPN, server did not agree to a protocol\n");
    }
  }
#endif

  connssl->connecting_state = ssl_connect_3;
  infof(data, "SSL connected\n");

  return CURLE_OK;
}
Exemplo n.º 3
0
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

}
Exemplo n.º 4
0
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 );
}
Exemplo n.º 5
0
static CURLcode
mbed_connect_step1(struct connectdata *conn,
                   int sockindex)
{
  struct Curl_easy *data = conn->data;
  struct ssl_connect_data* connssl = &conn->ssl[sockindex];
  const char * const ssl_cafile = SSL_CONN_CONFIG(CAfile);
  const bool verifypeer = SSL_CONN_CONFIG(verifypeer);
  const char * const ssl_capath = SSL_CONN_CONFIG(CApath);
  char * const ssl_cert = SSL_SET_OPTION(cert);
  const char * const ssl_crlfile = SSL_SET_OPTION(CRLfile);
  const char * const hostname = SSL_IS_PROXY() ? conn->http_proxy.host.name :
    conn->host.name;
  const long int port = SSL_IS_PROXY() ? conn->port : conn->remote_port;
  int ret = -1;
  char errorbuf[128];
  errorbuf[0] = 0;

  /* mbedTLS only supports SSLv3 and TLSv1 */
  if(SSL_CONN_CONFIG(version) == CURL_SSLVERSION_SSLv2) {
    failf(data, "mbedTLS does not support SSLv2");
    return CURLE_SSL_CONNECT_ERROR;
  }

#ifdef THREADING_SUPPORT
  entropy_init_mutex(&ts_entropy);
  mbedtls_ctr_drbg_init(&BACKEND->ctr_drbg);

  ret = mbedtls_ctr_drbg_seed(&BACKEND->ctr_drbg, entropy_func_mutex,
                              &ts_entropy, NULL, 0);
  if(ret) {
#ifdef MBEDTLS_ERROR_C
    mbedtls_strerror(ret, errorbuf, sizeof(errorbuf));
#endif /* MBEDTLS_ERROR_C */
    failf(data, "Failed - mbedTLS: ctr_drbg_init returned (-0x%04X) %s\n",
          -ret, errorbuf);
  }
#else
  mbedtls_entropy_init(&BACKEND->entropy);
  mbedtls_ctr_drbg_init(&BACKEND->ctr_drbg);

  ret = mbedtls_ctr_drbg_seed(&BACKEND->ctr_drbg, mbedtls_entropy_func,
                              &BACKEND->entropy, NULL, 0);
  if(ret) {
#ifdef MBEDTLS_ERROR_C
    mbedtls_strerror(ret, errorbuf, sizeof(errorbuf));
#endif /* MBEDTLS_ERROR_C */
    failf(data, "Failed - mbedTLS: ctr_drbg_init returned (-0x%04X) %s\n",
          -ret, errorbuf);
  }
#endif /* THREADING_SUPPORT */

  /* Load the trusted CA */
  mbedtls_x509_crt_init(&BACKEND->cacert);

  if(ssl_cafile) {
    ret = mbedtls_x509_crt_parse_file(&BACKEND->cacert, ssl_cafile);

    if(ret<0) {
#ifdef MBEDTLS_ERROR_C
      mbedtls_strerror(ret, errorbuf, sizeof(errorbuf));
#endif /* MBEDTLS_ERROR_C */
      failf(data, "Error reading ca cert file %s - mbedTLS: (-0x%04X) %s",
            ssl_cafile, -ret, errorbuf);

      if(verifypeer)
        return CURLE_SSL_CACERT_BADFILE;
    }
  }

  if(ssl_capath) {
    ret = mbedtls_x509_crt_parse_path(&BACKEND->cacert, ssl_capath);

    if(ret<0) {
#ifdef MBEDTLS_ERROR_C
      mbedtls_strerror(ret, errorbuf, sizeof(errorbuf));
#endif /* MBEDTLS_ERROR_C */
      failf(data, "Error reading ca cert path %s - mbedTLS: (-0x%04X) %s",
            ssl_capath, -ret, errorbuf);

      if(verifypeer)
        return CURLE_SSL_CACERT_BADFILE;
    }
  }

  /* Load the client certificate */
  mbedtls_x509_crt_init(&BACKEND->clicert);

  if(ssl_cert) {
    ret = mbedtls_x509_crt_parse_file(&BACKEND->clicert, ssl_cert);

    if(ret) {
#ifdef MBEDTLS_ERROR_C
      mbedtls_strerror(ret, errorbuf, sizeof(errorbuf));
#endif /* MBEDTLS_ERROR_C */
      failf(data, "Error reading client cert file %s - mbedTLS: (-0x%04X) %s",
            ssl_cert, -ret, errorbuf);

      return CURLE_SSL_CERTPROBLEM;
    }
  }

  /* Load the client private key */
  mbedtls_pk_init(&BACKEND->pk);

  if(SSL_SET_OPTION(key)) {
    ret = mbedtls_pk_parse_keyfile(&BACKEND->pk, SSL_SET_OPTION(key),
                                   SSL_SET_OPTION(key_passwd));
    if(ret == 0 && !mbedtls_pk_can_do(&BACKEND->pk, MBEDTLS_PK_RSA))
      ret = MBEDTLS_ERR_PK_TYPE_MISMATCH;

    if(ret) {
#ifdef MBEDTLS_ERROR_C
      mbedtls_strerror(ret, errorbuf, sizeof(errorbuf));
#endif /* MBEDTLS_ERROR_C */
      failf(data, "Error reading private key %s - mbedTLS: (-0x%04X) %s",
            SSL_SET_OPTION(key), -ret, errorbuf);

      return CURLE_SSL_CERTPROBLEM;
    }
  }

  /* Load the CRL */
  mbedtls_x509_crl_init(&BACKEND->crl);

  if(ssl_crlfile) {
    ret = mbedtls_x509_crl_parse_file(&BACKEND->crl, ssl_crlfile);

    if(ret) {
#ifdef MBEDTLS_ERROR_C
      mbedtls_strerror(ret, errorbuf, sizeof(errorbuf));
#endif /* MBEDTLS_ERROR_C */
      failf(data, "Error reading CRL file %s - mbedTLS: (-0x%04X) %s",
            ssl_crlfile, -ret, errorbuf);

      return CURLE_SSL_CRL_BADFILE;
    }
  }

  infof(data, "mbedTLS: Connecting to %s:%d\n", hostname, port);

  mbedtls_ssl_config_init(&BACKEND->config);

  mbedtls_ssl_init(&BACKEND->ssl);
  if(mbedtls_ssl_setup(&BACKEND->ssl, &BACKEND->config)) {
    failf(data, "mbedTLS: ssl_init failed");
    return CURLE_SSL_CONNECT_ERROR;
  }
  ret = mbedtls_ssl_config_defaults(&BACKEND->config,
                                    MBEDTLS_SSL_IS_CLIENT,
                                    MBEDTLS_SSL_TRANSPORT_STREAM,
                                    MBEDTLS_SSL_PRESET_DEFAULT);
  if(ret) {
    failf(data, "mbedTLS: ssl_config failed");
    return CURLE_SSL_CONNECT_ERROR;
  }

  /* new profile with RSA min key len = 1024 ... */
  mbedtls_ssl_conf_cert_profile(&BACKEND->config,
                                &mbedtls_x509_crt_profile_fr);

  switch(SSL_CONN_CONFIG(version)) {
  case CURL_SSLVERSION_DEFAULT:
  case CURL_SSLVERSION_TLSv1:
    mbedtls_ssl_conf_min_version(&BACKEND->config, MBEDTLS_SSL_MAJOR_VERSION_3,
                                 MBEDTLS_SSL_MINOR_VERSION_1);
    infof(data, "mbedTLS: Set min SSL version to TLS 1.0\n");
    break;
  case CURL_SSLVERSION_SSLv3:
    mbedtls_ssl_conf_min_version(&BACKEND->config, MBEDTLS_SSL_MAJOR_VERSION_3,
                                 MBEDTLS_SSL_MINOR_VERSION_0);
    mbedtls_ssl_conf_max_version(&BACKEND->config, MBEDTLS_SSL_MAJOR_VERSION_3,
                                 MBEDTLS_SSL_MINOR_VERSION_0);
    infof(data, "mbedTLS: Set SSL version to SSLv3\n");
    break;
  case CURL_SSLVERSION_TLSv1_0:
  case CURL_SSLVERSION_TLSv1_1:
  case CURL_SSLVERSION_TLSv1_2:
  case CURL_SSLVERSION_TLSv1_3:
    {
      CURLcode result = set_ssl_version_min_max(conn, sockindex);
      if(result != CURLE_OK)
        return result;
      break;
    }
  default:
    failf(data, "Unrecognized parameter passed via CURLOPT_SSLVERSION");
    return CURLE_SSL_CONNECT_ERROR;
  }

  mbedtls_ssl_conf_authmode(&BACKEND->config, MBEDTLS_SSL_VERIFY_OPTIONAL);

  mbedtls_ssl_conf_rng(&BACKEND->config, mbedtls_ctr_drbg_random,
                       &BACKEND->ctr_drbg);
  mbedtls_ssl_set_bio(&BACKEND->ssl, &conn->sock[sockindex],
                      mbedtls_net_send,
                      mbedtls_net_recv,
                      NULL /*  rev_timeout() */);

  mbedtls_ssl_conf_ciphersuites(&BACKEND->config,
                                mbedtls_ssl_list_ciphersuites());

#if defined(MBEDTLS_SSL_RENEGOTIATION)
  mbedtls_ssl_conf_renegotiation(&BACKEND->config,
                                 MBEDTLS_SSL_RENEGOTIATION_ENABLED);
#endif

#if defined(MBEDTLS_SSL_SESSION_TICKETS)
  mbedtls_ssl_conf_session_tickets(&BACKEND->config,
                                   MBEDTLS_SSL_SESSION_TICKETS_DISABLED);
#endif

  /* Check if there's a cached ID we can/should use here! */
  if(SSL_SET_OPTION(primary.sessionid)) {
    void *old_session = NULL;

    Curl_ssl_sessionid_lock(conn);
    if(!Curl_ssl_getsessionid(conn, &old_session, NULL, sockindex)) {
      ret = mbedtls_ssl_set_session(&BACKEND->ssl, old_session);
      if(ret) {
        Curl_ssl_sessionid_unlock(conn);
        failf(data, "mbedtls_ssl_set_session returned -0x%x", -ret);
        return CURLE_SSL_CONNECT_ERROR;
      }
      infof(data, "mbedTLS re-using session\n");
    }
    Curl_ssl_sessionid_unlock(conn);
  }

  mbedtls_ssl_conf_ca_chain(&BACKEND->config,
                            &BACKEND->cacert,
                            &BACKEND->crl);

  if(SSL_SET_OPTION(key)) {
    mbedtls_ssl_conf_own_cert(&BACKEND->config,
                              &BACKEND->clicert, &BACKEND->pk);
  }
  if(mbedtls_ssl_set_hostname(&BACKEND->ssl, hostname)) {
    /* mbedtls_ssl_set_hostname() sets the name to use in CN/SAN checks *and*
       the name to set in the SNI extension. So even if curl connects to a
       host specified as an IP address, this function must be used. */
    failf(data, "couldn't set hostname in mbedTLS");
    return CURLE_SSL_CONNECT_ERROR;
  }

#ifdef HAS_ALPN
  if(conn->bits.tls_enable_alpn) {
    const char **p = &BACKEND->protocols[0];
#ifdef USE_NGHTTP2
    if(data->set.httpversion >= CURL_HTTP_VERSION_2)
      *p++ = NGHTTP2_PROTO_VERSION_ID;
#endif
    *p++ = ALPN_HTTP_1_1;
    *p = NULL;
    /* this function doesn't clone the protocols array, which is why we need
       to keep it around */
    if(mbedtls_ssl_conf_alpn_protocols(&BACKEND->config,
                                       &BACKEND->protocols[0])) {
      failf(data, "Failed setting ALPN protocols");
      return CURLE_SSL_CONNECT_ERROR;
    }
    for(p = &BACKEND->protocols[0]; *p; ++p)
      infof(data, "ALPN, offering %s\n", *p);
  }
#endif

#ifdef MBEDTLS_DEBUG
  /* In order to make that work in mbedtls MBEDTLS_DEBUG_C must be defined. */
  mbedtls_ssl_conf_dbg(&BACKEND->config, mbed_debug, data);
  /* - 0 No debug
   * - 1 Error
   * - 2 State change
   * - 3 Informational
   * - 4 Verbose
   */
  mbedtls_debug_set_threshold(4);
#endif

  /* give application a chance to interfere with mbedTLS set up. */
  if(data->set.ssl.fsslctx) {
    ret = (*data->set.ssl.fsslctx)(data, &BACKEND->config,
                                   data->set.ssl.fsslctxp);
    if(ret) {
      failf(data, "error signaled by ssl ctx callback");
      return ret;
    }
  }

  connssl->connecting_state = ssl_connect_2;

  return CURLE_OK;
}
Exemplo n.º 6
0
int main(void)
{
    struct addrinfo hints;
    struct addrinfo *ai;
    struct sockaddr_in server;
    int sock;
    int res;

    char server_name[] = "www.eff.org";
    char http_get[200] =
        "GET /index.html HTTP/1.1\r\n"
        "Host: www.eff.org\r\n"
        "\r\n";
    char http_get_resp[200];
    int cipher_list[] = { MBEDTLS_TLS_RSA_WITH_AES_128_CBC_SHA, 0};

    mbedtls_ssl_context ssl;
    mbedtls_ssl_config conf;
    mbedtls_x509_crt cacert;

    printf("Press any key to continue...");
    getchar();
    printf("\n");

    mbedtls_ssl_init( &ssl );
    mbedtls_ssl_config_init( &conf );
    mbedtls_x509_crt_init( &cacert );

    res = mbedtls_ssl_config_defaults(
            &conf,
            MBEDTLS_SSL_IS_CLIENT,
            MBEDTLS_SSL_TRANSPORT_STREAM,
            MBEDTLS_SSL_PRESET_DEFAULT);
    if( res != 0 )
    {
        mbedtls_printerr(res, "mbedtls_ssl_config_defaults");
        return 1;
    }
#if 0
    mbedtls_ssl_conf_authmode( &conf, MBEDTLS_SSL_VERIFY_NONE);
#endif
    mbedtls_ssl_conf_ciphersuites( &conf, cipher_list);
#if 0
    res = mbedtls_ssl_conf_max_frag_len( &conf, MBEDTLS_SSL_MAX_FRAG_LEN_512);
    if( res != 0 )
    {
        mbedtls_printerr(res, "mbedtls_ssl_conf_max_frag_len");
        return 1;
    }
#endif
    mbedtls_ssl_conf_rng(&conf, wrap_rng, NULL);
    res = mbedtls_ssl_setup( &ssl, &conf);
    if( res != 0 )
    {
        mbedtls_printerr(res, "mbedtls_ssl_setup");
        return 1;
    }
    res = mbedtls_x509_crt_parse(&cacert, digicert_der, digicert_der_len);
    if( res != 0 )
    {
        mbedtls_printerr(res, "mbedtls_x509_crt_parse");
        return 1;
    }
    mbedtls_ssl_conf_ca_chain( &conf, &cacert, NULL );
    res = mbedtls_ssl_set_hostname( &ssl, server_name);
    if( res != 0 )
    {
        mbedtls_printerr(res, "mbedtls_ssl_set_hostname");
        return 1;
    }

    hints.ai_flags = 0;
    hints.ai_family = AF_INET;
    hints.ai_socktype = SOCK_STREAM;
    hints.ai_protocol = 0;

    res = getaddrinfo(server_name, NULL, &hints, &ai);
    if (res != 0)
    {
        if (res == EAI_SYSTEM)
        {
            perror("getaddrinfo");
        }
        else
        {
            fprintf(stderr, "error: getaddrinfo: %d\n", res);
        }
        return 1;
    }
    if (ai == NULL)
    {
        fprintf(stderr, "error: getaddrinfo : output is NULL\n");
        return 1;
    }

    sock = socket(AF_INET , SOCK_STREAM , 0);
    if (sock == -1)
    {
        perror("socket creation failed");
        return 1;
    }
#if 1
    server = *((const struct sockaddr_in *)ai->ai_addr);
    server.sin_port = htons( 443 ); /* HTTPS */
#else
    /* 
     * nslookup www.eff.org -> 69.50.225.155
     * socat TCP-LISTEN:44333 TCP:69.50.225.155:443
     */
    server.sin_family = AF_INET;
    server.sin_port = htons(44333);
    server.sin_addr.s_addr = inet_addr("192.168.1.173"); /* my PC */
#endif
    freeaddrinfo(ai);
    if (connect(sock , (struct sockaddr *)&server , sizeof(server)) < 0)
    {
        perror("connect failed");
        close(sock);
        return 1;
    }
    
    /* TLS connect */
    mbedtls_ssl_set_bio( &ssl, &sock, wrap_send, wrap_recv, NULL);
    res = mbedtls_ssl_handshake( &ssl );
    do
    {
        const mbedtls_x509_crt *peer_cert;

        peer_cert = mbedtls_ssl_get_peer_cert(&ssl);
        if (peer_cert == NULL)
        {
            fprintf(stderr, "no peer cert.\n");
        }
        else
        {
            int n;
            char info_str[200];

            n = mbedtls_x509_crt_info(info_str, sizeof(info_str), "", peer_cert);
            fputs("Certificate:\n", stderr);
            fputs(info_str, stderr);
            fputs("\n", stderr);
        }
    } while(0);
    if (res != 0)
    {
        mbedtls_printerr(res, "mbedtls_ssl_handshake");
        close(sock);
        return 1;
    }

    res = mbedtls_ssl_write(&ssl, (unsigned char *)http_get, strlen(http_get));
    if (res <= 0)
    {
        mbedtls_printerr(res, "mbedtls_ssl_write");
        close(sock);
        return 1;
    }
    do
    {
        res = mbedtls_ssl_read(&ssl, (unsigned char *)http_get_resp, sizeof(http_get_resp));
        if (res <= 0)
        {
            mbedtls_printerr(res, "mbedtls_ssl_read");
            close(sock);
            return 1;
        }
        fwrite(http_get_resp, res, 1, stdout);
    } while(res == sizeof(http_get_resp)); //TODO: cleaner

    /* TLS disconnect */
    mbedtls_ssl_free(&ssl);
    mbedtls_ssl_config_free(&conf);
    close(sock);

    return 0;
}
Exemplo n.º 7
0
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 );
}
Exemplo n.º 8
0
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 );
                    break;
                }
            }
        }

        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 );
                    break;
                }
            }
        }

        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 );
}
Exemplo n.º 9
0
Arquivo: duo.c Projeto: szdiy/duo
void http_get_task(void *pvParameters)
{
    int successes = 0, failures = 0, ret;
    printf("HTTP get task starting...\n");

    uint32_t flags;
    unsigned char buf[1024];
    const char *pers = "ssl_client1";

    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;

    /*
     * 0. Initialize the RNG and the session data
     */
    mbedtls_ssl_init(&ssl);
    mbedtls_x509_crt_init(&cacert);
    mbedtls_ctr_drbg_init(&ctr_drbg);
    printf("\n  . 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,
                                    (const unsigned char *) pers,
                                    strlen(pers))) != 0)
    {
        printf(" failed\n  ! mbedtls_ctr_drbg_seed returned %d\n", ret);
        abort();
    }

    printf(" ok\n");

    /*
     * 0. Initialize certificates
     */
    printf("  . Loading the CA root certificate ...");

    ret = mbedtls_x509_crt_parse(&cacert, (uint8_t*)server_root_cert, strlen(server_root_cert)+1);
    if(ret < 0)
    {
        printf(" failed\n  !  mbedtls_x509_crt_parse returned -0x%x\n\n", -ret);
        abort();
    }

    printf(" ok (%d skipped)\n", ret);

    /* Hostname set here should match CN in server certificate */
    if((ret = mbedtls_ssl_set_hostname(&ssl, WEB_SERVER)) != 0)
    {
        printf(" failed\n  ! mbedtls_ssl_set_hostname returned %d\n\n", ret);
        abort();
    }

    /*
     * 2. Setup stuff
     */
    printf("  . 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)
    {
        printf(" failed\n  ! mbedtls_ssl_config_defaults returned %d\n\n", ret);
        goto exit;
    }

    printf(" ok\n");

    /* OPTIONAL is not optimal for security, in this example it will print
       a warning if CA verification fails but it will continue to connect.
    */
    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 MBEDTLS_DEBUG_C
    mbedtls_debug_set_threshold(DEBUG_LEVEL);
    mbedtls_ssl_conf_dbg(&conf, my_debug, stdout);
#endif

    if((ret = mbedtls_ssl_setup(&ssl, &conf)) != 0)
    {
        printf(" failed\n  ! mbedtls_ssl_setup returned %d\n\n", ret);
        goto exit;
    }

    /* Wait until we can resolve the DNS for the server, as an indication
       our network is probably working...
    */
    printf("Waiting for server DNS to resolve... ");
    err_t dns_err;
    ip_addr_t host_ip;
    do {
        vTaskDelay(500 / portTICK_PERIOD_MS);
        dns_err = netconn_gethostbyname(WEB_SERVER, &host_ip);
    } while(dns_err != ERR_OK);
    printf("done.\n");

    while(1) {
        mbedtls_net_init(&server_fd);
        printf("top of loop, free heap = %u\n", xPortGetFreeHeapSize());
        /*
         * 1. Start the connection
         */
        printf("  . Connecting to %s:%s...", WEB_SERVER, WEB_PORT);

        if((ret = mbedtls_net_connect(&server_fd, WEB_SERVER,
                                      WEB_PORT, MBEDTLS_NET_PROTO_TCP)) != 0)
        {
            printf(" failed\n  ! mbedtls_net_connect returned %d\n\n", ret);
            goto exit;
        }

        printf(" ok\n");

        mbedtls_ssl_set_bio(&ssl, &server_fd, mbedtls_net_send, mbedtls_net_recv, NULL);

        /*
         * 4. Handshake
         */
        printf("  . 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)
            {
                printf(" failed\n  ! mbedtls_ssl_handshake returned -0x%x\n\n", -ret);
                goto exit;
            }
        }

        printf(" ok\n");

        /*
         * 5. Verify the server certificate
         */
        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(&ssl)) != 0)
        {
            char vrfy_buf[512];

            printf(" failed\n");

            mbedtls_x509_crt_verify_info(vrfy_buf, sizeof(vrfy_buf), "  ! ", flags);

            printf("%s\n", vrfy_buf);
        }
        else
            printf(" ok\n");

        /*
         * 3. Write the GET request
         */
        printf("  > Write to server:");

        int len = sprintf((char *) buf, GET_REQUEST);

        while((ret = mbedtls_ssl_write(&ssl, buf, len)) <= 0)
        {
            if(ret != MBEDTLS_ERR_SSL_WANT_READ && ret != MBEDTLS_ERR_SSL_WANT_WRITE)
            {
                printf(" failed\n  ! mbedtls_ssl_write returned %d\n\n", ret);
                goto exit;
            }
        }

        len = ret;
        printf(" %d bytes written\n\n%s", len, (char *) buf);

        /*
         * 7. Read the HTTP response
         */
        printf("  < Read from server:");

        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 == MBEDTLS_ERR_SSL_PEER_CLOSE_NOTIFY) {
                ret = 0;
                break;
            }

            if(ret < 0)
            {
                printf("failed\n  ! mbedtls_ssl_read returned %d\n\n", ret);
                break;
            }

            if(ret == 0)
            {
                printf("\n\nEOF\n\n");
                break;
            }

            len = ret;
            printf(" %d bytes read\n\n%s", len, (char *) buf);
        } while(1);

        mbedtls_ssl_close_notify(&ssl);

    exit:
        mbedtls_ssl_session_reset(&ssl);
        mbedtls_net_free(&server_fd);

        if(ret != 0)
        {
            char error_buf[100];
            mbedtls_strerror(ret, error_buf, 100);
            printf("\n\nLast error was: %d - %s\n\n", ret, error_buf);
            failures++;
        } else {
            successes++;
        }

        printf("\n\nsuccesses = %d failures = %d\n", successes, failures);
        for(int countdown = successes ? 10 : 5; countdown >= 0; countdown--) {
            printf("%d... ", countdown);
            vTaskDelay(1000 / portTICK_PERIOD_MS);
        }
        printf("\nStarting again!\n");
    }
}
Exemplo n.º 10
0
int main( int argc, char *argv[] )
{
    int ret = 0;
    mbedtls_x509_crt issuer_crt;
    mbedtls_pk_context loaded_issuer_key, loaded_subject_key;
    mbedtls_pk_context *issuer_key = &loaded_issuer_key,
                *subject_key = &loaded_subject_key;
    char buf[1024];
    char issuer_name[256];
    int i;
    char *p, *q, *r;
#if defined(MBEDTLS_X509_CSR_PARSE_C)
    char subject_name[256];
    mbedtls_x509_csr csr;
#endif
    mbedtls_x509write_cert crt;
    mbedtls_mpi serial;
    mbedtls_entropy_context entropy;
    mbedtls_ctr_drbg_context ctr_drbg;
    const char *pers = "crt example app";

    /*
     * Set to sane values
     */
    mbedtls_x509write_crt_init( &crt );
    mbedtls_x509write_crt_set_md_alg( &crt, MBEDTLS_MD_SHA256 );
    mbedtls_pk_init( &loaded_issuer_key );
    mbedtls_pk_init( &loaded_subject_key );
    mbedtls_mpi_init( &serial );
    mbedtls_ctr_drbg_init( &ctr_drbg );
#if defined(MBEDTLS_X509_CSR_PARSE_C)
    mbedtls_x509_csr_init( &csr );
#endif
    mbedtls_x509_crt_init( &issuer_crt );
    memset( buf, 0, 1024 );

    if( argc == 0 )
    {
    usage:
        mbedtls_printf( USAGE );
        ret = 1;
        goto exit;
    }

    opt.issuer_crt          = DFL_ISSUER_CRT;
    opt.request_file        = DFL_REQUEST_FILE;
    opt.subject_key         = DFL_SUBJECT_KEY;
    opt.issuer_key          = DFL_ISSUER_KEY;
    opt.subject_pwd         = DFL_SUBJECT_PWD;
    opt.issuer_pwd          = DFL_ISSUER_PWD;
    opt.output_file         = DFL_OUTPUT_FILENAME;
    opt.subject_name        = DFL_SUBJECT_NAME;
    opt.issuer_name         = DFL_ISSUER_NAME;
    opt.not_before          = DFL_NOT_BEFORE;
    opt.not_after           = DFL_NOT_AFTER;
    opt.serial              = DFL_SERIAL;
    opt.selfsign            = DFL_SELFSIGN;
    opt.is_ca               = DFL_IS_CA;
    opt.max_pathlen         = DFL_MAX_PATHLEN;
    opt.key_usage           = DFL_KEY_USAGE;
    opt.ns_cert_type        = DFL_NS_CERT_TYPE;

    for( i = 1; i < argc; i++ )
    {

        p = argv[i];
        if( ( q = strchr( p, '=' ) ) == NULL )
            goto usage;
        *q++ = '\0';

        if( strcmp( p, "request_file" ) == 0 )
            opt.request_file = q;
        else if( strcmp( p, "subject_key" ) == 0 )
            opt.subject_key = q;
        else if( strcmp( p, "issuer_key" ) == 0 )
            opt.issuer_key = q;
        else if( strcmp( p, "subject_pwd" ) == 0 )
            opt.subject_pwd = q;
        else if( strcmp( p, "issuer_pwd" ) == 0 )
            opt.issuer_pwd = q;
        else if( strcmp( p, "issuer_crt" ) == 0 )
            opt.issuer_crt = q;
        else if( strcmp( p, "output_file" ) == 0 )
            opt.output_file = q;
        else if( strcmp( p, "subject_name" ) == 0 )
        {
            opt.subject_name = q;
        }
        else if( strcmp( p, "issuer_name" ) == 0 )
        {
            opt.issuer_name = q;
        }
        else if( strcmp( p, "not_before" ) == 0 )
        {
            opt.not_before = q;
        }
        else if( strcmp( p, "not_after" ) == 0 )
        {
            opt.not_after = q;
        }
        else if( strcmp( p, "serial" ) == 0 )
        {
            opt.serial = q;
        }
        else if( strcmp( p, "selfsign" ) == 0 )
        {
            opt.selfsign = atoi( q );
            if( opt.selfsign < 0 || opt.selfsign > 1 )
                goto usage;
        }
        else if( strcmp( p, "is_ca" ) == 0 )
        {
            opt.is_ca = atoi( q );
            if( opt.is_ca < 0 || opt.is_ca > 1 )
                goto usage;
        }
        else if( strcmp( p, "max_pathlen" ) == 0 )
        {
            opt.max_pathlen = atoi( q );
            if( opt.max_pathlen < -1 || opt.max_pathlen > 127 )
                goto usage;
        }
        else if( strcmp( p, "key_usage" ) == 0 )
        {
            while( q != NULL )
            {
                if( ( r = strchr( q, ',' ) ) != NULL )
                    *r++ = '\0';

                if( strcmp( q, "digital_signature" ) == 0 )
                    opt.key_usage |= MBEDTLS_X509_KU_DIGITAL_SIGNATURE;
                else if( strcmp( q, "non_repudiation" ) == 0 )
                    opt.key_usage |= MBEDTLS_X509_KU_NON_REPUDIATION;
                else if( strcmp( q, "key_encipherment" ) == 0 )
                    opt.key_usage |= MBEDTLS_X509_KU_KEY_ENCIPHERMENT;
                else if( strcmp( q, "data_encipherment" ) == 0 )
                    opt.key_usage |= MBEDTLS_X509_KU_DATA_ENCIPHERMENT;
                else if( strcmp( q, "key_agreement" ) == 0 )
                    opt.key_usage |= MBEDTLS_X509_KU_KEY_AGREEMENT;
                else if( strcmp( q, "key_cert_sign" ) == 0 )
                    opt.key_usage |= MBEDTLS_X509_KU_KEY_CERT_SIGN;
                else if( strcmp( q, "crl_sign" ) == 0 )
                    opt.key_usage |= MBEDTLS_X509_KU_CRL_SIGN;
                else
                    goto usage;

                q = r;
            }
        }
        else if( strcmp( p, "ns_cert_type" ) == 0 )
        {
            while( q != NULL )
            {
                if( ( r = strchr( q, ',' ) ) != NULL )
                    *r++ = '\0';

                if( strcmp( q, "ssl_client" ) == 0 )
                    opt.ns_cert_type |= MBEDTLS_X509_NS_CERT_TYPE_SSL_CLIENT;
                else if( strcmp( q, "ssl_server" ) == 0 )
                    opt.ns_cert_type |= MBEDTLS_X509_NS_CERT_TYPE_SSL_SERVER;
                else if( strcmp( q, "email" ) == 0 )
                    opt.ns_cert_type |= MBEDTLS_X509_NS_CERT_TYPE_EMAIL;
                else if( strcmp( q, "object_signing" ) == 0 )
                    opt.ns_cert_type |= MBEDTLS_X509_NS_CERT_TYPE_OBJECT_SIGNING;
                else if( strcmp( q, "ssl_ca" ) == 0 )
                    opt.ns_cert_type |= MBEDTLS_X509_NS_CERT_TYPE_SSL_CA;
                else if( strcmp( q, "email_ca" ) == 0 )
                    opt.ns_cert_type |= MBEDTLS_X509_NS_CERT_TYPE_EMAIL_CA;
                else if( strcmp( q, "object_signing_ca" ) == 0 )
                    opt.ns_cert_type |= MBEDTLS_X509_NS_CERT_TYPE_OBJECT_SIGNING_CA;
                else
                    goto usage;

                q = r;
            }
        }
        else
            goto usage;
    }

    mbedtls_printf("\n");

    /*
     * 0. Seed the PRNG
     */
    mbedtls_printf( "  . 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_strerror( ret, buf, 1024 );
        mbedtls_printf( " failed\n  !  mbedtls_ctr_drbg_seed returned %d - %s\n", ret, buf );
        goto exit;
    }

    mbedtls_printf( " ok\n" );

    // Parse serial to MPI
    //
    mbedtls_printf( "  . Reading serial number..." );
    fflush( stdout );

    if( ( ret = mbedtls_mpi_read_string( &serial, 10, opt.serial ) ) != 0 )
    {
        mbedtls_strerror( ret, buf, 1024 );
        mbedtls_printf( " failed\n  !  mbedtls_mpi_read_string returned -0x%02x - %s\n\n", -ret, buf );
        goto exit;
    }

    mbedtls_printf( " ok\n" );

    // Parse issuer certificate if present
    //
    if( !opt.selfsign && strlen( opt.issuer_crt ) )
    {
        /*
         * 1.0.a. Load the certificates
         */
        mbedtls_printf( "  . Loading the issuer certificate ..." );
        fflush( stdout );

        if( ( ret = mbedtls_x509_crt_parse_file( &issuer_crt, opt.issuer_crt ) ) != 0 )
        {
            mbedtls_strerror( ret, buf, 1024 );
            mbedtls_printf( " failed\n  !  mbedtls_x509_crt_parse_file returned -0x%02x - %s\n\n", -ret, buf );
            goto exit;
        }

        ret = mbedtls_x509_dn_gets( issuer_name, sizeof(issuer_name),
                                 &issuer_crt.subject );
        if( ret < 0 )
        {
            mbedtls_strerror( ret, buf, 1024 );
            mbedtls_printf( " failed\n  !  mbedtls_x509_dn_gets returned -0x%02x - %s\n\n", -ret, buf );
            goto exit;
        }

        opt.issuer_name = issuer_name;

        mbedtls_printf( " ok\n" );
    }

#if defined(MBEDTLS_X509_CSR_PARSE_C)
    // Parse certificate request if present
    //
    if( !opt.selfsign && strlen( opt.request_file ) )
    {
        /*
         * 1.0.b. Load the CSR
         */
        mbedtls_printf( "  . Loading the certificate request ..." );
        fflush( stdout );

        if( ( ret = mbedtls_x509_csr_parse_file( &csr, opt.request_file ) ) != 0 )
        {
            mbedtls_strerror( ret, buf, 1024 );
            mbedtls_printf( " failed\n  !  mbedtls_x509_csr_parse_file returned -0x%02x - %s\n\n", -ret, buf );
            goto exit;
        }

        ret = mbedtls_x509_dn_gets( subject_name, sizeof(subject_name),
                                 &csr.subject );
        if( ret < 0 )
        {
            mbedtls_strerror( ret, buf, 1024 );
            mbedtls_printf( " failed\n  !  mbedtls_x509_dn_gets returned -0x%02x - %s\n\n", -ret, buf );
            goto exit;
        }

        opt.subject_name = subject_name;
        subject_key = &csr.pk;

        mbedtls_printf( " ok\n" );
    }
#endif /* MBEDTLS_X509_CSR_PARSE_C */

    /*
     * 1.1. Load the keys
     */
    if( !opt.selfsign && !strlen( opt.request_file ) )
    {
        mbedtls_printf( "  . Loading the subject key ..." );
        fflush( stdout );

        ret = mbedtls_pk_parse_keyfile( &loaded_subject_key, opt.subject_key,
                                 opt.subject_pwd );
        if( ret != 0 )
        {
            mbedtls_strerror( ret, buf, 1024 );
            mbedtls_printf( " failed\n  !  mbedtls_pk_parse_keyfile returned -0x%02x - %s\n\n", -ret, buf );
            goto exit;
        }

        mbedtls_printf( " ok\n" );
    }

    mbedtls_printf( "  . Loading the issuer key ..." );
    fflush( stdout );

    ret = mbedtls_pk_parse_keyfile( &loaded_issuer_key, opt.issuer_key,
                             opt.issuer_pwd );
    if( ret != 0 )
    {
        mbedtls_strerror( ret, buf, 1024 );
        mbedtls_printf( " failed\n  !  mbedtls_pk_parse_keyfile returned -x%02x - %s\n\n", -ret, buf );
        goto exit;
    }

    // Check if key and issuer certificate match
    //
    if( strlen( opt.issuer_crt ) )
    {
        if( !mbedtls_pk_can_do( &issuer_crt.pk, MBEDTLS_PK_RSA ) ||
            mbedtls_mpi_cmp_mpi( &mbedtls_pk_rsa( issuer_crt.pk )->N,
                         &mbedtls_pk_rsa( *issuer_key )->N ) != 0 ||
            mbedtls_mpi_cmp_mpi( &mbedtls_pk_rsa( issuer_crt.pk )->E,
                         &mbedtls_pk_rsa( *issuer_key )->E ) != 0 )
        {
            mbedtls_printf( " failed\n  !  issuer_key does not match issuer certificate\n\n" );
            ret = -1;
            goto exit;
        }
    }

    mbedtls_printf( " ok\n" );

    if( opt.selfsign )
    {
        opt.subject_name = opt.issuer_name;
        subject_key = issuer_key;
    }

    mbedtls_x509write_crt_set_subject_key( &crt, subject_key );
    mbedtls_x509write_crt_set_issuer_key( &crt, issuer_key );

    /*
     * 1.0. Check the names for validity
     */
    if( ( ret = mbedtls_x509write_crt_set_subject_name( &crt, opt.subject_name ) ) != 0 )
    {
        mbedtls_strerror( ret, buf, 1024 );
        mbedtls_printf( " failed\n  !  mbedtls_x509write_crt_set_subject_name returned -0x%02x - %s\n\n", -ret, buf );
        goto exit;
    }

    if( ( ret = mbedtls_x509write_crt_set_issuer_name( &crt, opt.issuer_name ) ) != 0 )
    {
        mbedtls_strerror( ret, buf, 1024 );
        mbedtls_printf( " failed\n  !  mbedtls_x509write_crt_set_issuer_name returned -0x%02x - %s\n\n", -ret, buf );
        goto exit;
    }

    mbedtls_printf( "  . Setting certificate values ..." );
    fflush( stdout );

    ret = mbedtls_x509write_crt_set_serial( &crt, &serial );
    if( ret != 0 )
    {
        mbedtls_strerror( ret, buf, 1024 );
        mbedtls_printf( " failed\n  !  mbedtls_x509write_crt_set_serial returned -0x%02x - %s\n\n", -ret, buf );
        goto exit;
    }

    ret = mbedtls_x509write_crt_set_validity( &crt, opt.not_before, opt.not_after );
    if( ret != 0 )
    {
        mbedtls_strerror( ret, buf, 1024 );
        mbedtls_printf( " failed\n  !  mbedtls_x509write_crt_set_validity returned -0x%02x - %s\n\n", -ret, buf );
        goto exit;
    }

    mbedtls_printf( " ok\n" );

    mbedtls_printf( "  . Adding the Basic Constraints extension ..." );
    fflush( stdout );

    ret = mbedtls_x509write_crt_set_basic_constraints( &crt, opt.is_ca,
                                               opt.max_pathlen );
    if( ret != 0 )
    {
        mbedtls_strerror( ret, buf, 1024 );
        mbedtls_printf( " failed\n  !  x509write_crt_set_basic_contraints returned -0x%02x - %s\n\n", -ret, buf );
        goto exit;
    }

    mbedtls_printf( " ok\n" );

#if defined(MBEDTLS_SHA1_C)
    mbedtls_printf( "  . Adding the Subject Key Identifier ..." );
    fflush( stdout );

    ret = mbedtls_x509write_crt_set_subject_key_identifier( &crt );
    if( ret != 0 )
    {
        mbedtls_strerror( ret, buf, 1024 );
        mbedtls_printf( " failed\n  !  mbedtls_x509write_crt_set_subject_key_identifier returned -0x%02x - %s\n\n", -ret, buf );
        goto exit;
    }

    mbedtls_printf( " ok\n" );

    mbedtls_printf( "  . Adding the Authority Key Identifier ..." );
    fflush( stdout );

    ret = mbedtls_x509write_crt_set_authority_key_identifier( &crt );
    if( ret != 0 )
    {
        mbedtls_strerror( ret, buf, 1024 );
        mbedtls_printf( " failed\n  !  mbedtls_x509write_crt_set_authority_key_identifier returned -0x%02x - %s\n\n", -ret, buf );
        goto exit;
    }

    mbedtls_printf( " ok\n" );
#endif /* MBEDTLS_SHA1_C */

    if( opt.key_usage )
    {
        mbedtls_printf( "  . Adding the Key Usage extension ..." );
        fflush( stdout );

        ret = mbedtls_x509write_crt_set_key_usage( &crt, opt.key_usage );
        if( ret != 0 )
        {
            mbedtls_strerror( ret, buf, 1024 );
            mbedtls_printf( " failed\n  !  mbedtls_x509write_crt_set_key_usage returned -0x%02x - %s\n\n", -ret, buf );
            goto exit;
        }

        mbedtls_printf( " ok\n" );
    }

    if( opt.ns_cert_type )
    {
        mbedtls_printf( "  . Adding the NS Cert Type extension ..." );
        fflush( stdout );

        ret = mbedtls_x509write_crt_set_ns_cert_type( &crt, opt.ns_cert_type );
        if( ret != 0 )
        {
            mbedtls_strerror( ret, buf, 1024 );
            mbedtls_printf( " failed\n  !  mbedtls_x509write_crt_set_ns_cert_type returned -0x%02x - %s\n\n", -ret, buf );
            goto exit;
        }

        mbedtls_printf( " ok\n" );
    }

    /*
     * 1.2. Writing the request
     */
    mbedtls_printf( "  . Writing the certificate..." );
    fflush( stdout );

    if( ( ret = write_certificate( &crt, opt.output_file,
                                   mbedtls_ctr_drbg_random, &ctr_drbg ) ) != 0 )
    {
        mbedtls_strerror( ret, buf, 1024 );
        mbedtls_printf( " failed\n  !  write_certifcate -0x%02x - %s\n\n", -ret, buf );
        goto exit;
    }

    mbedtls_printf( " ok\n" );

exit:
    mbedtls_x509write_crt_free( &crt );
    mbedtls_pk_free( &loaded_subject_key );
    mbedtls_pk_free( &loaded_issuer_key );
    mbedtls_mpi_free( &serial );
    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 );
}
Exemplo n.º 11
0
static UA_StatusCode
certificateVerification_verify(void *verificationContext,
                               const UA_ByteString *certificate) {
    CertInfo *ci = (CertInfo*)verificationContext;
    if(!ci)
        return UA_STATUSCODE_BADINTERNALERROR;

    /* Parse the certificate */
    mbedtls_x509_crt remoteCertificate;
    mbedtls_x509_crt_init(&remoteCertificate);
    int mbedErr = mbedtls_x509_crt_parse(&remoteCertificate, certificate->data,
                                         certificate->length);
    if(mbedErr) {
        /* char errBuff[300]; */
        /* mbedtls_strerror(mbedErr, errBuff, 300); */
        /* UA_LOG_WARNING(data->policyContext->securityPolicy->logger, UA_LOGCATEGORY_SECURITYPOLICY, */
        /*                "Could not parse the remote certificate with error: %s", errBuff); */
        return UA_STATUSCODE_BADSECURITYCHECKSFAILED;
    }

    /* Verify */
    mbedtls_x509_crt_profile crtProfile = {
        MBEDTLS_X509_ID_FLAG(MBEDTLS_MD_SHA1) | MBEDTLS_X509_ID_FLAG(MBEDTLS_MD_SHA256),
        0xFFFFFF, 0x000000, 128 * 8 // in bits
    }; // TODO: remove magic numbers

    uint32_t flags = 0;
    mbedErr = mbedtls_x509_crt_verify_with_profile(&remoteCertificate,
                                                   &ci->certificateTrustList,
                                                   &ci->certificateRevocationList,
                                                   &crtProfile, NULL, &flags, NULL, NULL);

    // TODO: Extend verification

    /* This condition will check whether the certificate is a User certificate
     * or a CA certificate. If the MBEDTLS_X509_KU_KEY_CERT_SIGN and
     * MBEDTLS_X509_KU_CRL_SIGN of key_usage are set, then the certificate
     * shall be condidered as CA Certificate and cannot be used to establish a
     * connection. Refer the test case CTT/Security/Security Certificate Validation/029.js
     * for more details */
    if((remoteCertificate.key_usage & MBEDTLS_X509_KU_KEY_CERT_SIGN) &&
       (remoteCertificate.key_usage & MBEDTLS_X509_KU_CRL_SIGN)) {
        return UA_STATUSCODE_BADCERTIFICATEUSENOTALLOWED;
    }

    UA_StatusCode retval = UA_STATUSCODE_GOOD;
    if(mbedErr) {
        /* char buff[100]; */
        /* mbedtls_x509_crt_verify_info(buff, 100, "", flags); */
        /* UA_LOG_ERROR(channelContextData->policyContext->securityPolicy->logger, */
        /*              UA_LOGCATEGORY_SECURITYPOLICY, */
        /*              "Verifying the certificate failed with error: %s", buff); */

        if(flags & (uint32_t)MBEDTLS_X509_BADCERT_NOT_TRUSTED) {
            retval = UA_STATUSCODE_BADCERTIFICATEUNTRUSTED;
        } else if(flags & (uint32_t)MBEDTLS_X509_BADCERT_FUTURE ||
                  flags & (uint32_t)MBEDTLS_X509_BADCERT_EXPIRED) {
            retval = UA_STATUSCODE_BADCERTIFICATETIMEINVALID;
        } else if(flags & (uint32_t)MBEDTLS_X509_BADCERT_REVOKED ||
                  flags & (uint32_t)MBEDTLS_X509_BADCRL_EXPIRED) {
            retval = UA_STATUSCODE_BADCERTIFICATEREVOKED;
        } else {
            retval = UA_STATUSCODE_BADSECURITYCHECKSFAILED;
        }
    }

    mbedtls_x509_crt_free(&remoteCertificate);
    return retval;
}
Exemplo n.º 12
0
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!  mbedtls_ctr_drbg_seed returned %d\n\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!  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!  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!  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!  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!  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!  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 ...\n" );
        fflush( stdout );

        if( ( ret = mbedtls_net_accept( &listen_fd, &client_fd,
                                        NULL, 0, NULL ) ) != 0 )
        {
            mbedtls_printf( " failed!  mbedtls_net_accept returned %d\n\n", ret );
            goto exit;
        }

        /*
         * 3.5. Forking server thread
         */

        mbedtls_printf( "  . Forking to handle connection ..." );
        fflush( stdout );

        pid = fork();

        if( pid < 0 )
        {
            mbedtls_printf(" failed!  fork returned %d\n\n", pid );
            goto exit;
        }

        if( pid != 0 )
        {
            mbedtls_printf( " ok\n" );

            if( ( ret = mbedtls_ctr_drbg_reseed( &ctr_drbg,
                                         (const unsigned char *) "parent",
                                         6 ) ) != 0 )
            {
                mbedtls_printf( " failed!  mbedtls_ctr_drbg_reseed returned %d\n\n", ret );
                goto exit;
            }

            continue;
        }

        mbedtls_net_init( &listen_fd );

        pid = getpid();

        /*
         * 4. Setup stuff
         */
        mbedtls_printf( "pid %d: Setting up the SSL data.\n", pid );
        fflush( stdout );

        if( ( ret = mbedtls_ctr_drbg_reseed( &ctr_drbg,
                                     (const unsigned char *) "child",
                                     5 ) ) != 0 )
        {
            mbedtls_printf(
                    "pid %d: SSL setup failed!  mbedtls_ctr_drbg_reseed returned %d\n\n",
                    pid, ret );
            goto exit;
        }

        if( ( ret = mbedtls_ssl_setup( &ssl, &conf ) ) != 0 )
        {
            mbedtls_printf(
                    "pid %d: SSL setup failed!  mbedtls_ssl_setup returned %d\n\n",
                    pid, ret );
            goto exit;
        }

        mbedtls_ssl_set_bio( &ssl, &client_fd, mbedtls_net_send, mbedtls_net_recv, NULL );

        mbedtls_printf( "pid %d: SSL setup ok\n", pid );

        /*
         * 5. Handshake
         */
        mbedtls_printf( "pid %d: Performing the SSL/TLS handshake.\n", pid );
        fflush( stdout );

        while( ( ret = mbedtls_ssl_handshake( &ssl ) ) != 0 )
        {
            if( ret != MBEDTLS_ERR_SSL_WANT_READ && ret != MBEDTLS_ERR_SSL_WANT_WRITE )
            {
                mbedtls_printf(
                        "pid %d: SSL handshake failed!  mbedtls_ssl_handshake returned %d\n\n",
                        pid, ret );
                goto exit;
            }
        }

        mbedtls_printf( "pid %d: SSL handshake ok\n", pid );

        /*
         * 6. Read the HTTP Request
         */
        mbedtls_printf( "pid %d: Start reading from client.\n", pid );
        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( "pid %d: connection was closed gracefully\n", pid );
                        break;

                    case MBEDTLS_ERR_NET_CONN_RESET:
                        mbedtls_printf( "pid %d: connection was reset by peer\n", pid );
                        break;

                    default:
                        mbedtls_printf( "pid %d: mbedtls_ssl_read returned %d\n", pid, ret );
                        break;
                }

                break;
            }

            len = ret;
            mbedtls_printf( "pid %d: %d bytes read\n\n%s", pid, len, (char *) buf );

            if( ret > 0 )
                break;
        }
        while( 1 );

        /*
         * 7. Write the 200 Response
         */
        mbedtls_printf( "pid %d: Start writing to client.\n", pid );
        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(
                            "pid %d: Write failed!  peer closed the connection\n\n", pid );
                    goto exit;
                }

                if( ret != MBEDTLS_ERR_SSL_WANT_READ && ret != MBEDTLS_ERR_SSL_WANT_WRITE )
                {
                    mbedtls_printf(
                            "pid %d: Write failed!  mbedtls_ssl_write returned %d\n\n",
                            pid, ret );
                    goto exit;
                }
            }
            len = ret;
            mbedtls_printf( "pid %d: %d bytes written\n\n%s\n", pid, 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 );
}
Exemplo n.º 13
0
X509Cert::X509Cert() : m_rootLoaded(false)
{
    mbedtls_x509_crt_init(&m_crt);
}
Exemplo n.º 14
0
int dtls_server_cb(void *args)
{
	int ret;
	int len;
	int ots = 0xFFFF;
	size_t cliip_len;
	unsigned char buf[1024];
	const char *pers = "dtls_server";
	unsigned char client_ip[16] = { 0 };
	struct pthread_arg arg;
	mbedtls_ssl_cookie_ctx cookie_ctx;
	mbedtls_net_context listen_fd;
	mbedtls_net_context client_fd;
	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

	if (args) {
		arg.argc = ((struct pthread_arg *)args)->argc;
		arg.argv = ((struct pthread_arg *)args)->argv;
		if (arg.argc == 1) {
			ots = 1;
		}
	}

	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
	 */
	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_rsa, mbedtls_test_srv_crt_rsa_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_ca_crt_rsa, mbedtls_test_ca_crt_rsa_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_rsa, mbedtls_test_srv_key_rsa_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");

	/*
	 * 2. Setup the "listening" UDP socket
	 */
	mbedtls_printf("  . Bind on udp/*/4433 ...");
	fflush(stdout);

	if ((ret = mbedtls_net_bind(&listen_fd, NULL, "4433", MBEDTLS_NET_PROTO_UDP)) != 0) {
		mbedtls_printf(" failed\n  ! mbedtls_net_bind returned %d\n\n", ret);
		goto exit;
	}

	mbedtls_printf(" ok\n");

	/*
	 * 3. Seed the RNG
	 */
	mbedtls_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) {
		mbedtls_printf(" failed\n  ! mbedtls_ctr_drbg_seed returned %d\n", ret);
		goto exit;
	}

	mbedtls_printf(" ok\n");

	/*
	 * 4. Setup stuff
	 */
	mbedtls_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) {
		mbedtls_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) {
		mbedtls_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) {
		mbedtls_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);

	mbedtls_printf(" ok\n");

reset:
#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(&client_fd);

	mbedtls_ssl_session_reset(&ssl);

	/*
	 * 3. Wait until a client connects
	 */
	mbedtls_printf("  . Waiting for a remote connection ...");
	fflush(stdout);

	if (listen_fd.fd < 0) {
		goto exit;
	}
	if ((ret = mbedtls_net_accept(&listen_fd, &client_fd, client_ip, sizeof(client_ip), &cliip_len)) != 0) {
		mbedtls_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) {
		mbedtls_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);

	mbedtls_printf(" ok\n");

	/*
	 * 5. Handshake
	 */
	mbedtls_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) {
		mbedtls_printf(" hello verification requested\n");
		ret = 0;
		goto reset;
	} else if (ret != 0) {
		mbedtls_printf(" failed\n  ! mbedtls_ssl_handshake returned -0x%x\n\n", -ret);
		if (ots == 1) {
			goto exit;
		}
		goto reset;
	}

	mbedtls_printf(" ok\n");

	/*
	 * 6. Read the echo Request
	 */
	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 (ots != 1) {
				goto reset;
			}
			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", -ret);
			if (ots != 1) {
				goto reset;
			}
			goto exit;
		}
	}

	len = ret;
	mbedtls_printf(" < READ FROM CLIENT %d bytes read : %s\n", len, buf);

	/*
	 * 7. Write the 200 Response
	 */

	do {
		ret = mbedtls_ssl_write(&ssl, buf, 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", ret);
		goto exit;
	}

	len = ret;
	mbedtls_printf(" > WRITE TO CLIENT %d bytes written : %s\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");

	if (--ots) {
		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);
		mbedtls_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);

	return ret;
}
Exemplo n.º 15
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 );
}
Exemplo n.º 16
0
int ssl_init_info(int *server_fd,ssl_info *sslinfo)
{
    int ret;
    const char *pers = "ssl";
    mbedtls_x509_crt_init(&sslinfo->cacert );
    mbedtls_ctr_drbg_init(&sslinfo->ctr_drbg);
    mbedtls_entropy_init(&sslinfo->entropy );

    if( mbedtls_ctr_drbg_seed( &sslinfo->ctr_drbg, mbedtls_entropy_func, &sslinfo->entropy,
                       (const unsigned char *) pers, strlen( pers ) ) != 0 )
    {
        return  -1;

    }

    mbedtls_ssl_init( &sslinfo->ssl );
    mbedtls_ssl_config_init( &sslinfo->conf );
    if( ( ret = mbedtls_ssl_config_defaults( &sslinfo->conf,
                    MBEDTLS_SSL_IS_CLIENT,
                    MBEDTLS_SSL_TRANSPORT_STREAM,
                    MBEDTLS_SSL_PRESET_DEFAULT ) ) != 0 )
    {
        echo( " failed\n  ! mbedtls_ssl_config_defaults returned %d\n\n", ret );
       return -1;
    }



    mbedtls_ssl_conf_endpoint( &sslinfo->conf, MBEDTLS_SSL_IS_CLIENT );
    mbedtls_ssl_conf_authmode( &sslinfo->conf, MBEDTLS_SSL_VERIFY_OPTIONAL );
    mbedtls_ssl_conf_ca_chain( &sslinfo->conf, &sslinfo->cacert,NULL);
    mbedtls_ssl_conf_rng( &sslinfo->conf, mbedtls_ctr_drbg_random, &sslinfo->ctr_drbg );

    if( ( ret = mbedtls_ssl_setup( &sslinfo->ssl, &sslinfo->conf ) ) != 0 )
    {
        echo( " failed\n  ! mbedtls_ssl_setup returned %d\n\n", ret );
        return -1;
    }

    mbedtls_ssl_set_bio( &sslinfo->ssl, server_fd,mbedtls_net_send, mbedtls_net_recv,NULL );
    mbedtls_ssl_set_session(&sslinfo->ssl, &ssn);
    while((ret = mbedtls_ssl_handshake(&sslinfo->ssl))!=0)
    {
        if( ret != MBEDTLS_ERR_SSL_WANT_READ && ret != MBEDTLS_ERR_SSL_WANT_WRITE )
        {
            echo( " failed\n  ! ssl_handshake returned -0x%x\n\n", -ret );
            return -1;
        }
        //CPU sleep
        sleeps(1);
    }



    if((ret = mbedtls_ssl_get_verify_result( &sslinfo->ssl ) ) != 0 )
    {
       // echo( "Verifying peer X.509 certificate...failed \r\n" );
    }
    else
    {
        echo( " ok\n" );
    }
    //保存session
    if( ( ret = mbedtls_ssl_get_session( &sslinfo->ssl, &ssn ) ) != 0 )
    {
        //失败初始化
        memset(&ssn, 0, sizeof(mbedtls_ssl_session));
    }
    return 0;
}
Exemplo n.º 17
0
websocket_return_t websocket_tls_init(int param, websocket_t *data, mbedtls_ssl_config *conf, mbedtls_x509_crt *cert, mbedtls_pk_context *pkey, mbedtls_entropy_context *entropy, mbedtls_ctr_drbg_context *ctr_drbg, mbedtls_ssl_cache_context *cache)
{
	int r;
	const char *crt = mbedtls_test_srv_crt;
	const char *key = mbedtls_test_srv_key;
	const char *ca_crt = mbedtls_test_cas_pem;
	size_t crt_len = mbedtls_test_srv_crt_len;
	size_t cacrt_len = mbedtls_test_cas_pem_len;
	size_t key_len = mbedtls_test_srv_key_len;

	if (param) {
		crt = mbedtls_test_cli_crt;
		key = mbedtls_test_cli_key;
		ca_crt = mbedtls_test_cas_pem;
		crt_len = mbedtls_test_cli_crt_len;
		cacrt_len = mbedtls_test_cas_pem_len;
		key_len = mbedtls_test_cli_key_len;
	}

	/* initialize tls context for server */
	mbedtls_ssl_config_init(conf);
	mbedtls_x509_crt_init(cert);
	mbedtls_pk_init(pkey);
	mbedtls_entropy_init(entropy);
	mbedtls_ctr_drbg_init(ctr_drbg);

	/* 1. Load the certificates and private RSA key */
	printf("  . Loading the cert. and key...");

	/* S/W Certificiate */
	if ((r = mbedtls_x509_crt_parse(cert, (const unsigned char *)crt, crt_len)) != 0) {
		printf("Error: mbedtls_x509_crt_parse when read crt returned %d\n", r);
		return WEBSOCKET_INIT_ERROR;
	}

	if ((r = mbedtls_x509_crt_parse(cert, (const unsigned char *)ca_crt, cacrt_len)) != 0) {
		printf("Error: mbedtls_x509_crt_parse when read caspem returned %d\n", r);
		return WEBSOCKET_INIT_ERROR;
	}

	if ((r = mbedtls_pk_parse_key(pkey, (const unsigned char *)key, key_len, NULL, 0)) != 0) {
		printf("Error: mbedtls_pk_parse_key returned %d\n", r);
		return WEBSOCKET_INIT_ERROR;
	}

	printf("Ok\n");

	/* 2. Seed the RNG */
	printf("  . Seeding the random number generator...");

	if ((r = mbedtls_ctr_drbg_seed(ctr_drbg, mbedtls_entropy_func, entropy, NULL, 0)) != 0) {
		printf("Error: mbedtls_ctr_drbg_seed returned %d\n", r);
		return WEBSOCKET_INIT_ERROR;
	}

	printf("Ok\n");

	/* 3. Setup ssl stuff */
	printf("  . Setting up the SSL data...");

	if ((r = mbedtls_ssl_config_defaults(conf, param ? MBEDTLS_SSL_IS_CLIENT : MBEDTLS_SSL_IS_SERVER, MBEDTLS_SSL_TRANSPORT_STREAM, MBEDTLS_SSL_PRESET_DEFAULT)) != 0) {
		printf("Error: mbedtls_ssl_config_defaults returned %d\n", r);
		return WEBSOCKET_INIT_ERROR;
	}

	mbedtls_ssl_conf_rng(conf, mbedtls_ctr_drbg_random, ctr_drbg);
	mbedtls_ssl_conf_dbg(conf, websocket_tls_debug, stdout);
	if (!param) {
		mbedtls_ssl_cache_init(cache);
		mbedtls_ssl_conf_session_cache(conf, cache, mbedtls_ssl_cache_get, mbedtls_ssl_cache_set);
	}

	mbedtls_ssl_conf_ca_chain(conf, cert->next, NULL);
	if ((r = mbedtls_ssl_conf_own_cert(conf, cert, pkey)) != 0) {
		printf("Error: mbedtls_ssl_conf_own_cert returned %d\n", r);
		return WEBSOCKET_INIT_ERROR;
	}
	data->tls_conf = conf;

	printf("Ok\n");
	return WEBSOCKET_SUCCESS;
}
IoT_Error_t iot_tls_connect(Network *pNetwork, TLSConnectParams *params) {
	if(NULL == pNetwork) {
		return NULL_VALUE_ERROR;
	}

	if(NULL != params) {
		_iot_tls_set_connect_params(pNetwork, params->pRootCALocation, params->pDeviceCertLocation,
									params->pDevicePrivateKeyLocation, params->pDestinationURL,
									params->DestinationPort, params->timeout_ms, params->ServerVerificationFlag);
	}

	int ret = 0;
	const char *pers = "aws_iot_tls_wrapper";
#ifdef IOT_DEBUG
	unsigned char buf[MBEDTLS_SSL_MAX_CONTENT_LEN + 1];
#endif
	TLSDataParams *tlsDataParams = &(pNetwork->tlsDataParams);

	mbedtls_net_init(&(tlsDataParams->server_fd));
	mbedtls_ssl_init(&(tlsDataParams->ssl));
	mbedtls_ssl_config_init(&(tlsDataParams->conf));
	mbedtls_ctr_drbg_init(&(tlsDataParams->ctr_drbg));
	mbedtls_x509_crt_init(&(tlsDataParams->cacert));
	mbedtls_x509_crt_init(&(tlsDataParams->clicert));
	mbedtls_pk_init(&(tlsDataParams->pkey));

	DEBUG("\n  . Seeding the random number generator...");
	mbedtls_entropy_init(&(tlsDataParams->entropy));
	if ((ret = mbedtls_ctr_drbg_seed(&(tlsDataParams->ctr_drbg), mbedtls_entropy_func, &(tlsDataParams->entropy),
										(const unsigned char *) pers, strlen(pers))) != 0) {
		ERROR(" failed\n  ! mbedtls_ctr_drbg_seed returned -0x%x\n", -ret);
		return NETWORK_MBEDTLS_ERR_CTR_DRBG_ENTROPY_SOURCE_FAILED;
	}

	DEBUG("  . Loading the CA root certificate ...");
	ret = mbedtls_x509_crt_parse_file(&(tlsDataParams->cacert), pNetwork->tlsConnectParams.pRootCALocation);
	if (ret < 0) {
		ERROR(" failed\n  !  mbedtls_x509_crt_parse returned -0x%x while parsing root cert\n\n", -ret);
		return NETWORK_X509_ROOT_CRT_PARSE_ERROR;
	} DEBUG(" ok (%d skipped)\n", ret);

	DEBUG("  . Loading the client cert. and key...");
	ret = mbedtls_x509_crt_parse_file(&(tlsDataParams->clicert), pNetwork->tlsConnectParams.pDeviceCertLocation);
	if (ret != 0) {
		ERROR(" failed\n  !  mbedtls_x509_crt_parse returned -0x%x while parsing device cert\n\n", -ret);
		return NETWORK_X509_DEVICE_CRT_PARSE_ERROR;
	}

	ret = mbedtls_pk_parse_keyfile(&(tlsDataParams->pkey), pNetwork->tlsConnectParams.pDevicePrivateKeyLocation, "");
	if (ret != 0) {
		ERROR(" failed\n  !  mbedtls_pk_parse_key returned -0x%x while parsing private key\n\n", -ret);
		DEBUG(" path : %s ", pNetwork->tlsConnectParams.pDevicePrivateKeyLocation);
		return NETWORK_PK_PRIVATE_KEY_PARSE_ERROR;
	} DEBUG(" ok\n");
	char portBuffer[6];
	snprintf(portBuffer, 6, "%d", pNetwork->tlsConnectParams.DestinationPort);
	DEBUG("  . Connecting to %s/%s...", pNetwork->tlsConnectParams.pDestinationURL, portBuffer);
	if ((ret = mbedtls_net_connect(&(tlsDataParams->server_fd), pNetwork->tlsConnectParams.pDestinationURL,
								   portBuffer, MBEDTLS_NET_PROTO_TCP)) != 0) {
		ERROR(" failed\n  ! mbedtls_net_connect returned -0x%x\n\n", -ret);
		switch(ret) {
			case MBEDTLS_ERR_NET_SOCKET_FAILED:
				return NETWORK_ERR_NET_SOCKET_FAILED;
			case MBEDTLS_ERR_NET_UNKNOWN_HOST:
				return NETWORK_ERR_NET_UNKNOWN_HOST;
			case MBEDTLS_ERR_NET_CONNECT_FAILED:
			default:
				return NETWORK_ERR_NET_CONNECT_FAILED;
		};
	}

	ret = mbedtls_net_set_block(&(tlsDataParams->server_fd));
	if (ret != 0) {
		ERROR(" failed\n  ! net_set_(non)block() returned -0x%x\n\n", -ret);
		return SSL_CONNECTION_ERROR;
	} DEBUG(" ok\n");

	DEBUG("  . Setting up the SSL/TLS structure...");
	if ((ret = mbedtls_ssl_config_defaults(&(tlsDataParams->conf), MBEDTLS_SSL_IS_CLIENT, MBEDTLS_SSL_TRANSPORT_STREAM,
			MBEDTLS_SSL_PRESET_DEFAULT)) != 0) {
		ERROR(" failed\n  ! mbedtls_ssl_config_defaults returned -0x%x\n\n", -ret);
		return SSL_CONNECTION_ERROR;
	}

	mbedtls_ssl_conf_verify(&(tlsDataParams->conf), _iot_tls_verify_cert, NULL);
	if (pNetwork->tlsConnectParams.ServerVerificationFlag == true) {
		mbedtls_ssl_conf_authmode(&(tlsDataParams->conf), MBEDTLS_SSL_VERIFY_REQUIRED);
	} else {
		mbedtls_ssl_conf_authmode(&(tlsDataParams->conf), MBEDTLS_SSL_VERIFY_OPTIONAL);
	}
	mbedtls_ssl_conf_rng(&(tlsDataParams->conf), mbedtls_ctr_drbg_random, &(tlsDataParams->ctr_drbg));

	mbedtls_ssl_conf_ca_chain(&(tlsDataParams->conf), &(tlsDataParams->cacert), NULL);
	if ((ret = mbedtls_ssl_conf_own_cert(&(tlsDataParams->conf), &(tlsDataParams->clicert), &(tlsDataParams->pkey))) != 0) {
		ERROR(" failed\n  ! mbedtls_ssl_conf_own_cert returned %d\n\n", ret);
		return SSL_CONNECTION_ERROR;
	}

	mbedtls_ssl_conf_read_timeout(&(tlsDataParams->conf), pNetwork->tlsConnectParams.timeout_ms);

	if ((ret = mbedtls_ssl_setup(&(tlsDataParams->ssl), &(tlsDataParams->conf))) != 0) {
		ERROR(" failed\n  ! mbedtls_ssl_setup returned -0x%x\n\n", -ret);
		return SSL_CONNECTION_ERROR;
	}
	if ((ret = mbedtls_ssl_set_hostname(&(tlsDataParams->ssl), pNetwork->tlsConnectParams.pDestinationURL)) != 0) {
		ERROR(" failed\n  ! mbedtls_ssl_set_hostname returned %d\n\n", ret);
		return SSL_CONNECTION_ERROR;
	}
	DEBUG("\n\nSSL state connect : %d ", tlsDataParams->ssl.state);
	mbedtls_ssl_set_bio(&(tlsDataParams->ssl), &(tlsDataParams->server_fd), mbedtls_net_send, NULL, mbedtls_net_recv_timeout);
	DEBUG(" ok\n");

	DEBUG("\n\nSSL state connect : %d ", tlsDataParams->ssl.state);
	DEBUG("  . Performing the SSL/TLS handshake...");
	while ((ret = mbedtls_ssl_handshake(&(tlsDataParams->ssl))) != 0) {
		if (ret != MBEDTLS_ERR_SSL_WANT_READ && ret != MBEDTLS_ERR_SSL_WANT_WRITE) {
			ERROR(" failed\n  ! mbedtls_ssl_handshake returned -0x%x\n", -ret);
			if (ret == MBEDTLS_ERR_X509_CERT_VERIFY_FAILED) {
				ERROR("    Unable to verify the server's certificate. "
						"Either it is invalid,\n"
						"    or you didn't set ca_file or ca_path "
						"to an appropriate value.\n"
						"    Alternatively, you may want to use "
						"auth_mode=optional for testing purposes.\n");
			}
			return SSL_CONNECTION_ERROR;
		}
	}

	DEBUG(" ok\n    [ Protocol is %s ]\n    [ Ciphersuite is %s ]\n", mbedtls_ssl_get_version(&(tlsDataParams->ssl)), mbedtls_ssl_get_ciphersuite(&(tlsDataParams->ssl)));
	if ((ret = mbedtls_ssl_get_record_expansion(&(tlsDataParams->ssl))) >= 0) {
		DEBUG("    [ Record expansion is %d ]\n", ret);
	} else {
		DEBUG("    [ Record expansion is unknown (compression) ]\n");
	}

	DEBUG("  . Verifying peer X.509 certificate...");

	if(pNetwork->tlsConnectParams.ServerVerificationFlag == true) {
		if((tlsDataParams->flags = mbedtls_ssl_get_verify_result(&(tlsDataParams->ssl))) != 0) {
			char vrfy_buf[512];
			ERROR(" failed\n");
			mbedtls_x509_crt_verify_info(vrfy_buf, sizeof(vrfy_buf), "  ! ", tlsDataParams->flags);
			ERROR("%s\n", vrfy_buf);
			ret = SSL_CONNECTION_ERROR;
		} else {
			DEBUG(" ok\n");
			ret = SUCCESS;
		}
	} else {
		DEBUG(" Server Verification skipped\n");
		ret = SUCCESS;
	}

#ifdef IOT_DEBUG
	if (mbedtls_ssl_get_peer_cert(&(tlsDataParams->ssl)) != NULL) {
		DEBUG("  . Peer certificate information    ...\n");
		mbedtls_x509_crt_info((char *) buf, sizeof(buf) - 1, "      ", mbedtls_ssl_get_peer_cert(&(tlsDataParams->ssl)));
		DEBUG("%s\n", buf);
	}
#endif

	mbedtls_ssl_conf_read_timeout(&(tlsDataParams->conf), IOT_SSL_READ_TIMEOUT);

	return ret;
}
Exemplo n.º 19
0
static int global_init(const struct instance *gi, global_context *gc) {
  int ret;
#ifdef __APPLE__   // MacOS/X requires an additional call
  int one = 1;
#endif
  const char *pers = "goldy";

  memset(gc, 0, sizeof(*gc));
  gc->options = gi;
  mbedtls_ssl_config_init(&gc->conf);
  mbedtls_ssl_cookie_init(&gc->cookie_ctx);
#if defined(MBEDTLS_SSL_CACHE_C)
  mbedtls_ssl_cache_init(&gc->cache);
#endif
  mbedtls_x509_crt_init(&gc->cacert);
  mbedtls_entropy_init(&gc->entropy);
  mbedtls_ctr_drbg_init(&gc->ctr_drbg);

  log_info("Goldy %s starting up", GOLDY_VERSION);
  mbedtls_net_init(&gc->listen_fd);
  ret = bind_listen_fd(gc);
  if (ret != 0) {
    goto exit;
  }
#ifdef __APPLE__   // MacOS/X requires an additional call
  ret = setsockopt(gc->listen_fd.fd, SOL_SOCKET, SO_REUSEPORT, (char*)&one, sizeof(one));
  if (ret != 0) {
    goto exit;
  }
#endif

  ret = mbedtls_x509_crt_parse_file(&gc->cacert, gi->cert_file);
  if (ret != 0) {
    log_error("mbedtls_x509_crt_parse returned %d", ret);
    goto exit;
  }
  log_debug("Loaded server cacert file");
  
  if ((ret = mbedtls_ctr_drbg_seed(&gc->ctr_drbg, mbedtls_entropy_func,
                                   &gc->entropy, (const unsigned char *)pers,
                                   strlen(pers))) != 0) {
    printf(" failed\n  ! mbedtls_ctr_drbg_seed returned %d\n", ret);
    goto exit;
  }
  log_debug("Seeded random number generator");

  if ((ret = mbedtls_ssl_config_defaults(&gc->conf,
                                         MBEDTLS_SSL_IS_CLIENT,
                                         MBEDTLS_SSL_TRANSPORT_DATAGRAM,
                                         MBEDTLS_SSL_PRESET_DEFAULT)) != 0) {
    log_error("mbedtls_ssl_config_defaults returned %d", ret);
    goto exit;
  }

  mbedtls_ssl_conf_dbg(&gc->conf, log_mbedtls_debug_callback, NULL);
  mbedtls_debug_set_threshold(MBEDTLS_DEBUG_LOGGING_LEVEL);
  mbedtls_ssl_conf_rng(&gc->conf, mbedtls_ctr_drbg_random, &gc->ctr_drbg);

#if defined(MBEDTLS_SSL_CACHE_C)
  mbedtls_ssl_conf_session_cache(&gc->conf, &gc->cache,
                                 mbedtls_ssl_cache_get,
                                 mbedtls_ssl_cache_set);
#endif

  /* Now we can support verify server client, however for performance,
   * just change to none because openvpn will do the auth again
   */
  mbedtls_ssl_conf_authmode(&gc->conf, MBEDTLS_SSL_VERIFY_NONE);
  mbedtls_ssl_conf_ca_chain(&gc->conf, &gc->cacert, NULL);
  mbedtls_ssl_conf_verify(&gc->conf, server_cert_verify, NULL);
  
  if ((ret = mbedtls_ssl_cookie_setup(&gc->cookie_ctx,
                                      mbedtls_ctr_drbg_random,
                                      &gc->ctr_drbg)) != 0) {
    log_error("mbedtls_ssl_cookie_setup returned %d", ret);
    goto exit;
  }
  mbedtls_ssl_conf_dtls_cookies(&gc->conf, mbedtls_ssl_cookie_write,
                                mbedtls_ssl_cookie_check, &gc->cookie_ctx);
  log_info("Proxy is ready, listening for connections on UDP %s:%s",
           gi->listen_host, gi->listen_port);

 exit:
  check_return_code(ret, "global_init - exit");

  if (ret != 0) {
    global_deinit(gc);
  }
  return ret == 0 ? 0 : 1;
}