int main(void)
{
	int ret;
	int verify_peer = 0;
	entropy_context ssl_client_entropy;
	ctr_drbg_context ssl_client_ctr_drbg;
	ssl_context clientssl;
	ssl_session sslclientsession;
	x509_cert ssl_client_cert;
	rsa_context ssl_client_rsa;
	struct sockaddr_un serveraddr;
	char *owner = "ssl_client";
	int clientsocketfd;
	char buffer[1024] = "Client Hello World";

	memset(&clientssl, 0, sizeof(ssl_context));
	memset(&sslclientsession, 0, sizeof(ssl_session));
	memset(&ssl_client_cert, 0, sizeof(x509_cert));
	memset(&ssl_client_rsa, 0, sizeof(rsa_context));

	entropy_init(&ssl_client_entropy);
	if((ret = ctr_drbg_init(&ssl_client_ctr_drbg, entropy_func, &ssl_client_entropy, (unsigned char *)owner, strlen(owner))) != 0)
	{
		printf("ctr_drbg_init failed returned %d\n", ret);
		return -1;
	}
	
	if((ret = x509parse_crtfile(&ssl_client_cert, SSL_CLIENT_RSA_CERT)) != 0)
	{
		printf("x509parse_crtfile CLIENT CERT returned %d\n", ret);
		return -1;
	}

	if((ret = x509parse_keyfile(&ssl_client_rsa, SSL_CLIENT_RSA_KEY, NULL)) != 0)
	{
		if(ret == POLARSSL_ERR_PEM_PASSWORD_REQUIRED)
		{	
			char buffer[100];
			int size;

			polarssl_pem_password_callback(buffer, &size);
			if((ret = x509parse_keyfile(&ssl_client_rsa, SSL_CLIENT_RSA_KEY, buffer)) != 0)
			{
				printf("x509parse_keyfile CLIENT KEY returned %d\n", ret);
				return -1;
			}
		}
	}
	
	if((clientsocketfd = socket(AF_UNIX, SOCK_STREAM, 0)) < 0)
	{
		printf("Error in socket creation%d\n", clientsocketfd);
		return -1;
	}
	memset(&serveraddr, 0, sizeof(struct sockaddr_un));
	serveraddr.sun_family = AF_UNIX;
	serveraddr.sun_path[0] = 0;
	strncpy(&(serveraddr.sun_path[1]), SSL_SERVER_ADDR, strlen(SSL_SERVER_ADDR) + 1);
	if(ret = connect(clientsocketfd, (struct sockaddr *)&serveraddr, sizeof(struct sockaddr_un)))
	{
		printf("connect returned error %d\n", ret);
		return -1;
	}	
	if(ret = ssl_init(&clientssl))
	{
		printf("ssl_init failed returned %d\n", ret);
		return -1;
	}
	ssl_set_endpoint(&clientssl, SSL_IS_CLIENT);
	ssl_set_authmode(&clientssl, SSL_VERIFY_NONE);
	
	if(verify_peer)
		ssl_set_authmode(&clientssl, SSL_VERIFY_REQUIRED);
	ssl_set_rng(&clientssl, ctr_drbg_random, &ssl_client_ctr_drbg);
	ssl_set_dbg(&clientssl, ssl_client_debug, stdout);
	ssl_set_bio(&clientssl, net_recv, &clientsocketfd, net_send, &clientsocketfd);
	ssl_set_ciphersuites(&clientssl, ssl_default_ciphersuites);	
	ssl_set_session(&clientssl, 1, 600, &sslclientsession);
	ssl_set_own_cert(&clientssl, &ssl_client_cert, &ssl_client_rsa);
	
	if(ret = ssl_handshake(&clientssl))
	{
		printf("handshake failed returned %d\n", ret);
		return -1;
	}
	if((ret = ssl_write(&clientssl, buffer, strlen(buffer) + 1)) <= 0)
	{
		printf("ssl_write failed returned %d\n", ret);
		return -1;
	}
	if((ret = ssl_read(&clientssl, buffer, sizeof(buffer))) <= 0)
	{
		printf("ssl_read failed returned %d\n", ret);
		return -1;
	}
	printf("SSL server send %s\n", buffer);
	ssl_close_notify(&clientssl);
	net_close(clientsocketfd);
	x509_free(&ssl_client_cert);
	rsa_free(&ssl_client_rsa);
	ssl_free(&clientssl);
	
	return 0;
}
Esempio n. 2
0
/**
  * @brief  SSL client task.
  * @param  pvParameters not used
  * @retval None
  */
void ssl_client(void const * argument)
{
  int ret, len, server_fd;
  unsigned char buf[1024];
  ssl_context ssl;
  x509_cert cacert;
  

  memset( &ssl, 0, sizeof( ssl_context ) );
  memset( &cacert, 0, sizeof( x509_cert ) );
  
  /*
  *  Initialize certificates
  */
  printf( "  . Loading the CA root certificate ..." );
  
#if defined(POLARSSL_CERTS_C)
  ret = x509parse_crt( &cacert, (const unsigned char *) test_ca_crt,
                      strlen( test_ca_crt ) );
#else
  ret = 1;
  printf("POLARSSL_CERTS_C not defined.");
#endif
  
  if( ret < 0 )
  {
    printf( " failed\n  !  x509parse_crt returned -0x%x\n\n", -ret );
    goto exit;
  }
  
  printf( " ok (%d skipped)\n", ret );
  
  /* Start the connection */
  do
  {
    printf(( "\n\rSSL : Start the connection \n\r"));
    printf("\n\rConnecting to tcp/%s/ Port:%4d...", SSL_SERVER_NAME, SSL_SERVER_PORT); 
    
    /* Bint the connection to SSL server port */
    ret = net_connect(&server_fd, SSL_SERVER_NAME, SSL_SERVER_PORT);
    if(ret != 0)
    {
      /* Connection to SSL server failed */
      printf(" failed \n\r ! net_connect returned %d\n\r", -ret);
      
      /* Wait 500 ms until next retry */
      vTaskDelay(500);
    } 
  }while(ret!=0);
  
  printf( " ok\n\r" );
  
  /*
  * 2. Setup stuff
  */
  printf( "  . Setting up the SSL/TLS structure..." );
  
  if( ( ret = ssl_init( &ssl ) ) != 0 )
  {
    printf( " failed\n  ! ssl_init returned %d\n\n\r", ret );
    goto exit;
  }
  
  printf( " ok\n\r" );
  
  ssl_set_endpoint( &ssl, SSL_IS_CLIENT );
  ssl_set_authmode( &ssl, SSL_VERIFY_OPTIONAL );
  ssl_set_ca_chain( &ssl, &cacert, NULL, "PolarSSL Server 1" );
  
  ssl_set_rng( &ssl, RandVal , NULL );
  ssl_set_dbg( &ssl, my_debug, NULL);
  ssl_set_bio( &ssl, net_recv, &server_fd,
              net_send, &server_fd );
  
  /*
  * Handshake
  */
  printf( "  . Performing the SSL/TLS handshake..." );
  
  while( ( ret = ssl_handshake( &ssl ) ) != 0 )
  {
    if( ret != POLARSSL_ERR_NET_WANT_READ && ret != POLARSSL_ERR_NET_WANT_WRITE )
    {
      printf( " failed\n  ! ssl_handshake returned -0x%x\n\n\r", -ret );
      goto exit;
    }
  }
  
  printf( " ok\n\r" );
  
  /*
  * Verify the server certificate
  */
  printf( "\n\r  . Verifying peer X.509 certificate..." );
  
  if( ( ret = ssl_get_verify_result( &ssl ) ) != 0 )
  {
    printf( " failed\n\r" );
    
    if( ( ret & BADCERT_EXPIRED ) != 0 )
      printf( "  ! server certificate has expired\n" );
    
    if( ( ret & BADCERT_REVOKED ) != 0 )
      printf( "  ! server certificate has been revoked\n" );
    
    if( ( ret & BADCERT_CN_MISMATCH ) != 0 )
      printf( "  ! CN mismatch (expected CN=%s)\n", "PolarSSL Server 1" );
    
    if( ( ret & BADCERT_NOT_TRUSTED ) != 0 )
      printf( "  ! self-signed or not signed by a trusted CA\n" );
    
    printf( "\n\r" );
  }
  else
    printf( " ok\n\r" );
  
  /*
  * Write the GET request
  */
  printf( "  > Write to server:" );
  
  len = sprintf( (char *) buf, GET_REQUEST );
  
  while( ( ret = ssl_write( &ssl, buf, len ) ) <= 0 )
  {
    if( ret != POLARSSL_ERR_NET_WANT_READ && ret != POLARSSL_ERR_NET_WANT_WRITE )
    {
      printf( " failed\n  ! ssl_write returned %d\n\n\r", ret );
      goto exit;
    }
  }
  
  len = ret;
  printf( " %d bytes written\n\n\r%s", len, (char *) buf );
  
  /*
  * Read the HTTP response
  */
  printf( "  < Read from server:" );
  
  do
  {
    len = sizeof( buf ) - 1;
    memset( buf, 0, sizeof( buf ) );
    ret = ssl_read( &ssl, buf, len );
    
    if( ret == POLARSSL_ERR_NET_WANT_READ || ret == POLARSSL_ERR_NET_WANT_WRITE )
      continue;
    
    if( ret == POLARSSL_ERR_SSL_PEER_CLOSE_NOTIFY )
      break;
    
    if( ret < 0 )
    {
      printf( "failed\n\r  ! ssl_read returned %d\n\n\r", ret );
      break;
    }
    
    if( ret == 0 )
    {
      printf( "\n\nEOF\n\n\r" );
      break;
    }
    
    len = ret;
    printf( " %d bytes read\n\n\r%s", len, (char *) buf );
  }
  while( 1 );
  
exit:

#ifdef POLARSSL_ERROR_C
  if( ret != 0 )
  {
    char error_buf[100];
    error_strerror( ret, error_buf, 100 );
    printf("Last error was: %d - %s\n\n\r", ret, error_buf );
  }
#endif
  
  x509_free( &cacert );
  net_close( server_fd );
  ssl_free( &ssl );
  
  memset( &ssl, 0, sizeof( ssl ) );
  
#if 0
  /* Infinite loop */
  for( ;; ) 
  {
    /* Toggle LED1 */
    BSP_LED_Toggle(LED1);
    
    /* Insert 400 ms delay */
    osDelay(400);
  }
#endif
  /* Insert 1000 ms delay */
  osDelay(1000);



}
Esempio n. 3
0
/*********************************************************************************************************
** 函数名称: __vpnClientConnect
** 功能描述: VPN 客户端链接服务器
** 输 入  : pvpnctx                VPN 上下文 (除了 VPNCTX_iVerifyOpt 有初值, 其他字段必须经过清空)
**           cpcCACrtFile           CA 证书文件     .pem or .crt
**           cpcPrivateCrtFile      私有证书文件    .pem or .crt
**           cpcKeyFile             私有密钥文件    .pem or .key
**           cpcKeyPassword         私有密钥文件解密密码, 如果密钥文件不存在密码, 则为 NULL
**           inaddr                 SSL 服务器地址
**           usPort                 SSL 服务器端口  (网络字节序)
**           iSSLTimeoutSec         超时时间(单位秒, 推荐: 600)
** 输 出  : ERROR
** 全局变量:
** 调用模块:
*********************************************************************************************************/
INT  __vpnClientOpen (__PVPN_CONTEXT  pvpnctx,
                      CPCHAR          cpcCACrtFile,
                      CPCHAR          cpcPrivateCrtFile,
                      CPCHAR          cpcKeyFile,
                      CPCHAR          cpcKeyPassword,
                      struct in_addr  inaddr,
                      u16_t           usPort,
                      INT             iSSLTimeoutSec)
{
    INT                     i;
    INT                     iError = PX_ERROR;
    struct sockaddr_in      sockaddrinRemote;
    
    (VOID)iSSLTimeoutSec;                                               /*  新的 PolarSSL 暂未使用      */

    if (pvpnctx == LW_NULL) {
        return  (PX_ERROR);
    }

    pvpnctx->VPNCTX_iMode   = __VPN_SSL_CLIENT;                         /*  设置为 client 模式          */
    pvpnctx->VPNCTX_iSocket = PX_ERROR;                                 /*  没有创建 socket             */

    havege_init(&pvpnctx->VPNCTX_haveagestat);                          /*  初始化随机数                */

    if (pvpnctx->VPNCTX_iVerifyOpt != SSL_VERIFY_NONE) {                /*  需要认证证书                */
        /*
         *  安装 CA 证书和客户端证书
         */
        iError = x509parse_crtfile(&pvpnctx->VPNCTX_x509certCA, cpcCACrtFile);
        if (iError != ERROR_NONE) {
            _DebugHandle(__ERRORMESSAGE_LEVEL, "CA root certificate error.\r\n");
            return  (PX_ERROR);
        }

        iError = x509parse_crtfile(&pvpnctx->VPNCTX_x509certPrivate, cpcPrivateCrtFile);
        if (iError != ERROR_NONE) {
            _DebugHandle(__ERRORMESSAGE_LEVEL, "client certificate error.\r\n");
            goto    __error_handle;
        }

        /*
         *  安装 RSA 私有密钥
         */
        if (cpcKeyFile) {
            iError = x509parse_keyfile(&pvpnctx->VPNCTX_rasctx, cpcKeyFile, cpcKeyPassword);
        } else {
            iError = x509parse_keyfile(&pvpnctx->VPNCTX_rasctx, cpcPrivateCrtFile, cpcKeyPassword);
        }
        if (iError != ERROR_NONE) {
            _DebugHandle(__ERRORMESSAGE_LEVEL, "key file error.\r\n");
            goto    __error_handle;
        }
    }

    /*
     *  链接 SSL 服务器
     */
    pvpnctx->VPNCTX_iSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
    if (pvpnctx->VPNCTX_iSocket < 0) {
        _DebugHandle(__ERRORMESSAGE_LEVEL, "can not create socket.\r\n");
        goto    __error_handle;
    }

    lib_bzero(&sockaddrinRemote, sizeof(sockaddrinRemote));
    sockaddrinRemote.sin_len    = sizeof(struct sockaddr_in);
    sockaddrinRemote.sin_family = AF_INET;
    sockaddrinRemote.sin_addr   = inaddr;
    sockaddrinRemote.sin_port   = usPort;

    if(connect(pvpnctx->VPNCTX_iSocket,
               (struct sockaddr *)&sockaddrinRemote,
               sizeof(struct sockaddr_in)) < 0) {
        _DebugHandle(__ERRORMESSAGE_LEVEL, "can not connect server.\r\n");
        goto    __error_handle;
    }

    havege_init(&pvpnctx->VPNCTX_haveagestat);                          /*  初始化随机数                */

    /*
     *  初始化 SSL/STL
     */
    if (ssl_init(&pvpnctx->VPNCTX_sslctx) != ERROR_NONE) {
        _DebugHandle(__ERRORMESSAGE_LEVEL, "can not init ssl context.\r\n");
        goto    __error_handle;
    }

    ssl_set_endpoint(&pvpnctx->VPNCTX_sslctx, SSL_IS_CLIENT);
    ssl_set_authmode(&pvpnctx->VPNCTX_sslctx, pvpnctx->VPNCTX_iVerifyOpt);

    ssl_set_rng(&pvpnctx->VPNCTX_sslctx, havege_random, &pvpnctx->VPNCTX_haveagestat);
    ssl_set_dbg(&pvpnctx->VPNCTX_sslctx, LW_NULL, stdout);              /*  不需要 DEBUG 信息           */

    ssl_set_bio(&pvpnctx->VPNCTX_sslctx,
                net_recv, &pvpnctx->VPNCTX_iSocket,
                net_send, &pvpnctx->VPNCTX_iSocket);

    ssl_set_ciphersuites(&pvpnctx->VPNCTX_sslctx, ssl_default_ciphersuites);
    ssl_set_session(&pvpnctx->VPNCTX_sslctx, &pvpnctx->VPNCTX_sslsn);

    ssl_set_ca_chain(&pvpnctx->VPNCTX_sslctx, &pvpnctx->VPNCTX_x509certCA, LW_NULL, LW_NULL);
    ssl_set_own_cert(&pvpnctx->VPNCTX_sslctx, &pvpnctx->VPNCTX_x509certPrivate, &pvpnctx->VPNCTX_rasctx);

    ssl_set_hostname(&pvpnctx->VPNCTX_sslctx, LW_NULL);                 /*  不设置服务器名              */

    for (i = 0; i < __VPN_SSL_HANDSHAKE_MAX_TIME; i++) {
        iError = ssl_handshake(&pvpnctx->VPNCTX_sslctx);                /*  握手                        */
        if (iError == ERROR_NONE) {
            break;
        } else if ((iError != POLARSSL_ERR_NET_WANT_READ) &&
                   (iError != POLARSSL_ERR_NET_WANT_WRITE)) {
            _DebugHandle(__ERRORMESSAGE_LEVEL, "can not handshake.\r\n");
            goto    __error_handle;
        }
    }
    if (i >= __VPN_SSL_HANDSHAKE_MAX_TIME) {
        goto    __error_handle;
    }

    return  (ERROR_NONE);

__error_handle:
    if (pvpnctx->VPNCTX_iSocket >= 0) {
        net_close(pvpnctx->VPNCTX_iSocket);
    }
    x509_free(&pvpnctx->VPNCTX_x509certPrivate);
    x509_free(&pvpnctx->VPNCTX_x509certCA);
    rsa_free(&pvpnctx->VPNCTX_rasctx);
    ssl_free(&pvpnctx->VPNCTX_sslctx);

    return  (PX_ERROR);
}
Esempio n. 4
0
/**
 * Construct a new x509 object.
 * @return 0 if ok. < 0 if there was a problem.
 */
int x509_new(const uint8_t *cert, int *len, X509_CTX **ctx)
{
    int begin_tbs, end_tbs;
    int ret = X509_NOT_OK, offset = 0, cert_size = 0;
    X509_CTX *x509_ctx;
    BI_CTX *bi_ctx;

    *ctx = (X509_CTX *)calloc(1, sizeof(X509_CTX));
    x509_ctx = *ctx;

    /* get the certificate size */
    asn1_skip_obj(cert, &cert_size, ASN1_SEQUENCE); 

    if (asn1_next_obj(cert, &offset, ASN1_SEQUENCE) < 0)
        goto end_cert;

    begin_tbs = offset;         /* start of the tbs */
    end_tbs = begin_tbs;        /* work out the end of the tbs */
    asn1_skip_obj(cert, &end_tbs, ASN1_SEQUENCE);

    if (asn1_next_obj(cert, &offset, ASN1_SEQUENCE) < 0)
        goto end_cert;

    if (cert[offset] == ASN1_EXPLICIT_TAG)   /* optional version */
    {
        if (asn1_version(cert, &offset, x509_ctx))
            goto end_cert;
    }

    if (asn1_skip_obj(cert, &offset, ASN1_INTEGER) || /* serial number */ 
            asn1_next_obj(cert, &offset, ASN1_SEQUENCE) < 0)
        goto end_cert;

    /* make sure the signature is ok */
    if (asn1_signature_type(cert, &offset, x509_ctx))
    {
        ret = X509_VFY_ERROR_UNSUPPORTED_DIGEST;
        goto end_cert;
    }

    if (asn1_name(cert, &offset, x509_ctx->ca_cert_dn) || 
            asn1_validity(cert, &offset, x509_ctx) ||
            asn1_name(cert, &offset, x509_ctx->cert_dn) ||
            asn1_public_key(cert, &offset, x509_ctx))
    {
        goto end_cert;
    }

    bi_ctx = x509_ctx->rsa_ctx->bi_ctx;

#ifdef CONFIG_SSL_CERT_VERIFICATION /* only care if doing verification */
    /* use the appropriate signature algorithm (SHA1/MD5/MD2) */
    if (x509_ctx->sig_type == SIG_TYPE_MD5)
    {
        MD5_CTX md5_ctx;
        uint8_t md5_dgst[MD5_SIZE];
        MD5_Init(&md5_ctx);
        MD5_Update(&md5_ctx, &cert[begin_tbs], end_tbs-begin_tbs);
        MD5_Final(md5_dgst, &md5_ctx);
        x509_ctx->digest = bi_import(bi_ctx, md5_dgst, MD5_SIZE);
    }
    else if (x509_ctx->sig_type == SIG_TYPE_SHA1)
    {
        SHA1_CTX sha_ctx;
        uint8_t sha_dgst[SHA1_SIZE];
        SHA1_Init(&sha_ctx);
        SHA1_Update(&sha_ctx, &cert[begin_tbs], end_tbs-begin_tbs);
        SHA1_Final(sha_dgst, &sha_ctx);
        x509_ctx->digest = bi_import(bi_ctx, sha_dgst, SHA1_SIZE);
    }
    else if (x509_ctx->sig_type == SIG_TYPE_MD2)
    {
        MD2_CTX md2_ctx;
        uint8_t md2_dgst[MD2_SIZE];
        MD2_Init(&md2_ctx);
        MD2_Update(&md2_ctx, &cert[begin_tbs], end_tbs-begin_tbs);
        MD2_Final(md2_dgst, &md2_ctx);
        x509_ctx->digest = bi_import(bi_ctx, md2_dgst, MD2_SIZE);
    }

    if (cert[offset] == ASN1_V3_DATA)
    {
        int suboffset;

        ++offset;
        get_asn1_length(cert, &offset);

        if ((suboffset = asn1_find_subjectaltname(cert, offset)) > 0)
        {
            if (asn1_next_obj(cert, &suboffset, ASN1_OCTET_STRING) > 0)
            {
                int altlen;

                if ((altlen = asn1_next_obj(cert, 
                                            &suboffset, ASN1_SEQUENCE)) > 0)
                {
                    int endalt = suboffset + altlen;
                    int totalnames = 0;

                    while (suboffset < endalt)
                    {
                        int type = cert[suboffset++];
                        int dnslen = get_asn1_length(cert, &suboffset);

                        if (type == ASN1_CONTEXT_DNSNAME)
                        {
                            x509_ctx->subject_alt_dnsnames = (char**)
                                    realloc(x509_ctx->subject_alt_dnsnames, 
                                       (totalnames + 2) * sizeof(char*));
                            x509_ctx->subject_alt_dnsnames[totalnames] = 
                                    (char*)malloc(dnslen + 1);
                            x509_ctx->subject_alt_dnsnames[totalnames+1] = NULL;
                            memcpy(x509_ctx->subject_alt_dnsnames[totalnames], 
                                    cert + suboffset, dnslen);
                            x509_ctx->subject_alt_dnsnames[
                                    totalnames][dnslen] = 0;
                            ++totalnames;
                        }

                        suboffset += dnslen;
                    }
                }
            }
        }
    }

    offset = end_tbs;   /* skip the rest of v3 data */
    if (asn1_skip_obj(cert, &offset, ASN1_SEQUENCE) || 
            asn1_signature(cert, &offset, x509_ctx))
        goto end_cert;
#endif
    ret = X509_OK;
end_cert:
    if (len)
    {
        *len = cert_size;
    }

    if (ret)
    {
#ifdef CONFIG_SSL_FULL_MODE
        printf("Error: Invalid X509 ASN.1 file (%s)\n",
                        x509_display_error(ret));
#endif
        x509_free(x509_ctx);
        *ctx = NULL;
    }

    return ret;
}
Esempio n. 5
0
int main(void)
{
    int ret, len;
    int listen_fd;
    int client_fd;
    uchar buf[1024];

    havege_state hs;
    ssl_context ssl;
    ssl_session ssn;
    x509_cert srvcert;
    rsa_context rsa;

    /*
     * 1. Load the certificates and private RSA key
     */
    printf("\n  . Loading the server cert. and key...");
    fflush(stdout);

    memset(&srvcert, 0, sizeof(x509_cert));

    /*
     * This demonstration program uses embedded test certificates.
     * Instead, you may want to use x509parse_crtfile() to read the
     * server and CA certificates, as well as x509parse_keyfile().
     */
    ret = x509parse_crt(&srvcert, (uchar *)test_srv_crt,
                strlen(test_srv_crt));
    if (ret != 0) {
        printf(" failed\n  !  x509parse_crt returned %d\n\n", ret);
        goto exit;
    }

    ret = x509parse_crt(&srvcert, (uchar *)test_ca_crt,
                strlen(test_ca_crt));
    if (ret != 0) {
        printf(" failed\n  !  x509parse_crt returned %d\n\n", ret);
        goto exit;
    }

    ret = x509parse_key(&rsa, (uchar *)test_srv_key,
                strlen(test_srv_key), NULL, 0);
    if (ret != 0) {
        printf(" failed\n  !  x509parse_key returned %d\n\n", ret);
        goto exit;
    }

    printf(" ok\n");

    /*
     * 2. Setup the listening TCP socket
     */
    printf("  . Bind on https://localhost:4433/ ...");
    fflush(stdout);

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

    printf(" ok\n");

    /*
     * 3. Wait until a client connects
     */
#ifdef WIN32
    ShellExecute(NULL, "open", "https://localhost:4433/",
             NULL, NULL, SW_SHOWNORMAL);
#endif

    client_fd = -1;
    memset(&ssl, 0, sizeof(ssl));

accept:

    net_close(client_fd);
    ssl_free(&ssl);

    printf("  . Waiting for a remote connection ...");
    fflush(stdout);

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

    printf(" ok\n");

    /*
     * 4. Setup stuff
     */
    printf("  . Setting up the RNG and SSL data....");
    fflush(stdout);

    havege_init(&hs);

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

    printf(" ok\n");

    ssl_set_endpoint(&ssl, SSL_IS_SERVER);
    ssl_set_authmode(&ssl, SSL_VERIFY_NONE);

    ssl_set_rng(&ssl, havege_rand, &hs);
    ssl_set_dbg(&ssl, my_debug, stdout);
    ssl_set_bio(&ssl, net_recv, &client_fd, net_send, &client_fd);
    ssl_set_scb(&ssl, my_get_session, my_set_session);

    ssl_set_ciphers(&ssl, my_ciphers);
    ssl_set_session(&ssl, 1, 0, &ssn);

    memset(&ssn, 0, sizeof(ssl_session));

    ssl_set_ca_chain(&ssl, srvcert.next, NULL);
    ssl_set_own_cert(&ssl, &srvcert, &rsa);
    ssl_set_dh_param(&ssl, my_dhm_P, my_dhm_G);

    /*
     * 5. Handshake
     */
    printf("  . Performing the SSL/TLS handshake...");
    fflush(stdout);

    while ((ret = ssl_handshake(&ssl)) != 0) {
        if (ret != TROPICSSL_ERR_NET_TRY_AGAIN) {
            printf(" failed\n  ! ssl_handshake returned %d\n\n",
                   ret);
            goto accept;
        }
    }

    printf(" ok\n");

    /*
     * 6. Read the HTTP Request
     */
    printf("  < Read from client:");
    fflush(stdout);

    do {
        len = sizeof(buf) - 1;
        memset(buf, 0, sizeof(buf));
        ret = ssl_read(&ssl, buf, len);

        if (ret == TROPICSSL_ERR_NET_TRY_AGAIN)
            continue;

        if (ret <= 0) {
            switch (ret) {
            case TROPICSSL_ERR_SSL_PEER_CLOSE_NOTIFY:
                printf(" connection was closed gracefully\n");
                break;

            case TROPICSSL_ERR_NET_CONN_RESET:
                printf(" connection was reset by peer\n");
                break;

            default:
                printf(" ssl_read returned %d\n", ret);
                break;
            }

            break;
        }

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

    /*
     * 7. Write the 200 Response
     */
    printf("  > Write to client:");
    fflush(stdout);

    len = sprintf((char *)buf, HTTP_RESPONSE, ssl_get_cipher(&ssl));

    while ((ret = ssl_write(&ssl, buf, len)) <= 0) {
        if (ret == TROPICSSL_ERR_NET_CONN_RESET) {
            printf(" failed\n  ! peer closed the connection\n\n");
            goto accept;
        }

        if (ret != TROPICSSL_ERR_NET_TRY_AGAIN) {
            printf(" failed\n  ! ssl_write returned %d\n\n", ret);
            goto exit;
        }
    }

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

    ssl_close_notify(&ssl);
    goto accept;

exit:

    net_close(client_fd);
    x509_free(&srvcert);
    rsa_free(&rsa);
    ssl_free(&ssl);

    cur = s_list_1st;
    while (cur != NULL) {
        prv = cur;
        cur = cur->next;
        memset(prv, 0, sizeof(ssl_session));
        free(prv);
    }

    memset(&ssl, 0, sizeof(ssl_context));

#ifdef WIN32
    printf("  Press Enter to exit this program.\n");
    fflush(stdout);
    getchar();
#endif

    return (ret);
}
int main( int argc, char *argv[] )
{
    int ret, len;
    int listen_fd;
    int client_fd = -1;
    unsigned char buf[1024];
    const char *pers = "ssl_server";

    entropy_context entropy;
    ctr_drbg_context ctr_drbg;
    ssl_context ssl;
    x509_cert srvcert;
    rsa_context rsa;
#if defined(POLARSSL_SSL_CACHE_C)
    ssl_cache_context cache;
#endif

    ((void) argc);
    ((void) argv);

#if defined(POLARSSL_SSL_CACHE_C)
    ssl_cache_init( &cache );
#endif

    /*
     * 1. Load the certificates and private RSA key
     */
    printf( "\n  . Loading the server cert. and key..." );
    fflush( stdout );

    memset( &srvcert, 0, sizeof( x509_cert ) );

    /*
     * This demonstration program uses embedded test certificates.
     * Instead, you may want to use x509parse_crtfile() to read the
     * server and CA certificates, as well as x509parse_keyfile().
     */
    ret = x509parse_crt( &srvcert, (const unsigned char *) test_srv_crt,
                         strlen( test_srv_crt ) );
    if( ret != 0 )
    {
        printf( " failed\n  !  x509parse_crt returned %d\n\n", ret );
        goto exit;
    }

    ret = x509parse_crt( &srvcert, (const unsigned char *) test_ca_crt,
                         strlen( test_ca_crt ) );
    if( ret != 0 )
    {
        printf( " failed\n  !  x509parse_crt returned %d\n\n", ret );
        goto exit;
    }

    rsa_init( &rsa, RSA_PKCS_V15, 0 );
    ret =  x509parse_key( &rsa, (const unsigned char *) test_srv_key,
                          strlen( test_srv_key ), NULL, 0 );
    if( ret != 0 )
    {
        printf( " failed\n  !  x509parse_key returned %d\n\n", ret );
        goto exit;
    }

    printf( " ok\n" );

    /*
     * 2. Setup the listening TCP socket
     */
    printf( "  . Bind on https://localhost:4433/ ..." );
    fflush( stdout );

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

    printf( " ok\n" );

    /*
     * 3. Seed the RNG
     */
    printf( "  . Seeding the random number generator..." );
    fflush( stdout );

    entropy_init( &entropy );
    if( ( ret = ctr_drbg_init( &ctr_drbg, entropy_func, &entropy,
                               (const unsigned char *) pers,
                               strlen( pers ) ) ) != 0 )
    {
        printf( " failed\n  ! ctr_drbg_init returned %d\n", ret );
        goto exit;
    }

    printf( " ok\n" );

    /*
     * 4. Setup stuff
     */
    printf( "  . Setting up the SSL data...." );
    fflush( stdout );

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

    ssl_set_endpoint( &ssl, SSL_IS_SERVER );
    ssl_set_authmode( &ssl, SSL_VERIFY_NONE );

    ssl_set_rng( &ssl, ctr_drbg_random, &ctr_drbg );
    ssl_set_dbg( &ssl, my_debug, stdout );

#if defined(POLARSSL_SSL_CACHE_C)
    ssl_set_session_cache( &ssl, ssl_cache_get, &cache,
                                 ssl_cache_set, &cache );
#endif

    ssl_set_ca_chain( &ssl, srvcert.next, NULL, NULL );
    ssl_set_own_cert( &ssl, &srvcert, &rsa );

    printf( " ok\n" );

reset:
#ifdef POLARSSL_ERROR_C
    if( ret != 0 )
    {
        char error_buf[100];
        error_strerror( ret, error_buf, 100 );
        printf("Last error was: %d - %s\n\n", ret, error_buf );
    }
#endif

    if( client_fd != -1 )
        net_close( client_fd );

    ssl_session_reset( &ssl );

    /*
     * 3. Wait until a client connects
     */
#if defined(_WIN32_WCE)
    {
        SHELLEXECUTEINFO sei;

        ZeroMemory( &sei, sizeof( SHELLEXECUTEINFO ) );

        sei.cbSize = sizeof( SHELLEXECUTEINFO );
        sei.fMask = 0;
        sei.hwnd = 0;
        sei.lpVerb = _T( "open" );
        sei.lpFile = _T( "https://localhost:4433/" );
        sei.lpParameters = NULL;
        sei.lpDirectory = NULL;
        sei.nShow = SW_SHOWNORMAL;

        ShellExecuteEx( &sei );
    }
#elif defined(_WIN32)
    ShellExecute( NULL, "open", "https://localhost:4433/",
                  NULL, NULL, SW_SHOWNORMAL );
#endif

    client_fd = -1;

    printf( "  . Waiting for a remote connection ..." );
    fflush( stdout );

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

    ssl_set_bio( &ssl, net_recv, &client_fd,
                       net_send, &client_fd );

    printf( " ok\n" );

    /*
     * 5. Handshake
     */
    printf( "  . Performing the SSL/TLS handshake..." );
    fflush( stdout );

    while( ( ret = ssl_handshake( &ssl ) ) != 0 )
    {
        if( ret != POLARSSL_ERR_NET_WANT_READ && ret != POLARSSL_ERR_NET_WANT_WRITE )
        {
            printf( " failed\n  ! ssl_handshake returned %d\n\n", ret );
            goto reset;
        }
    }

    printf( " ok\n" );

    /*
     * 6. Read the HTTP Request
     */
    printf( "  < Read from client:" );
    fflush( stdout );

    do
    {
        len = sizeof( buf ) - 1;
        memset( buf, 0, sizeof( buf ) );
        ret = ssl_read( &ssl, buf, len );

        if( ret == POLARSSL_ERR_NET_WANT_READ || ret == POLARSSL_ERR_NET_WANT_WRITE )
            continue;

        if( ret <= 0 )
        {
            switch( ret )
            {
                case POLARSSL_ERR_SSL_PEER_CLOSE_NOTIFY:
                    printf( " connection was closed gracefully\n" );
                    break;

                case POLARSSL_ERR_NET_CONN_RESET:
                    printf( " connection was reset by peer\n" );
                    break;

                default:
                    printf( " ssl_read returned -0x%x\n", -ret );
                    break;
            }

            break;
        }

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

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

    /*
     * 7. Write the 200 Response
     */
    printf( "  > Write to client:" );
    fflush( stdout );

    len = sprintf( (char *) buf, HTTP_RESPONSE,
                   ssl_get_ciphersuite( &ssl ) );

    while( ( ret = ssl_write( &ssl, buf, len ) ) <= 0 )
    {
        if( ret == POLARSSL_ERR_NET_CONN_RESET )
        {
            printf( " failed\n  ! peer closed the connection\n\n" );
            goto reset;
        }

        if( ret != POLARSSL_ERR_NET_WANT_READ && ret != POLARSSL_ERR_NET_WANT_WRITE )
        {
            printf( " failed\n  ! ssl_write returned %d\n\n", ret );
            goto exit;
        }
    }

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

    ret = 0;
    goto reset;

exit:

#ifdef POLARSSL_ERROR_C
    if( ret != 0 )
    {
        char error_buf[100];
        error_strerror( ret, error_buf, 100 );
        printf("Last error was: %d - %s\n\n", ret, error_buf );
    }
#endif

    net_close( client_fd );
    x509_free( &srvcert );
    rsa_free( &rsa );
    ssl_free( &ssl );
#if defined(POLARSSL_SSL_CACHE_C)
    ssl_cache_free( &cache );
#endif

#if defined(_WIN32)
    printf( "  Press Enter to exit this program.\n" );
    fflush( stdout ); getchar();
#endif

    return( ret );
}
int main( int argc, char *argv[] )
{
    int ret = 0, len, server_fd;
    unsigned char buf[1024];
#if defined(POLARSSL_BASE64_C)
    unsigned char base[1024];
#endif
    char hostname[32];
    char *pers = "ssl_mail_client";

    entropy_context entropy;
    ctr_drbg_context ctr_drbg;
    ssl_context ssl;
    ssl_session ssn;
    x509_cert cacert;
    x509_cert clicert;
    rsa_context rsa;
    int i;
    size_t j, n;
    char *p, *q;
    const int *list;

    /*
     * Make sure memory references are valid.
     */
    server_fd = 0;
    memset( &ssn, 0, sizeof( ssl_session ) );
    memset( &ssl, 0, sizeof( ssl_context ) );
    memset( &cacert, 0, sizeof( x509_cert ) );
    memset( &clicert, 0, sizeof( x509_cert ) );
    memset( &rsa, 0, sizeof( rsa_context ) );

    if( argc == 0 )
    {
    usage:
        printf( USAGE );

        list = ssl_list_ciphersuites();
        while( *list )
        {
            printf("    %s\n", ssl_get_ciphersuite_name( *list ) );
            list++;
        }
        printf("\n");
        goto exit;
    }

    opt.server_name         = DFL_SERVER_NAME;
    opt.server_port         = DFL_SERVER_PORT;
    opt.debug_level         = DFL_DEBUG_LEVEL;
    opt.authentication      = DFL_AUTHENTICATION;
    opt.mode                = DFL_MODE;
    opt.user_name           = DFL_USER_NAME;
    opt.user_pwd            = DFL_USER_PWD;
    opt.mail_from           = DFL_MAIL_FROM;
    opt.mail_to             = DFL_MAIL_TO;
    opt.ca_file             = DFL_CA_FILE;
    opt.crt_file            = DFL_CRT_FILE;
    opt.key_file            = DFL_KEY_FILE;
    opt.force_ciphersuite[0]= DFL_FORCE_CIPHER;

    for( i = 1; i < argc; i++ )
    {
        n = strlen( argv[i] );

        for( j = 0; j < n; j++ )
        {
            if( argv[i][j] == '=')
                break;

            if( argv[i][j] >= 'A' && argv[i][j] <= 'Z' )
                argv[i][j] |= 0x20;
        }

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

        if( strcmp( p, "server_name" ) == 0 )
            opt.server_name = q;
        else if( strcmp( p, "server_port" ) == 0 )
        {
            opt.server_port = atoi( q );
            if( opt.server_port < 1 || opt.server_port > 65535 )
                goto usage;
        }
        else if( strcmp( p, "debug_level" ) == 0 )
        {
            opt.debug_level = atoi( q );
            if( opt.debug_level < 0 || opt.debug_level > 65535 )
                goto usage;
        }
        else if( strcmp( p, "authentication" ) == 0 )
        {
            opt.authentication = atoi( q );
            if( opt.authentication < 0 || opt.authentication > 1 )
                goto usage;
        }
        else if( strcmp( p, "mode" ) == 0 )
        {
            opt.mode = atoi( q );
            if( opt.mode < 0 || opt.mode > 1 )
                goto usage;
        }
        else if( strcmp( p, "user_name" ) == 0 )
            opt.user_name = q;
        else if( strcmp( p, "user_pwd" ) == 0 )
            opt.user_pwd = q;
        else if( strcmp( p, "mail_from" ) == 0 )
            opt.mail_from = q;
        else if( strcmp( p, "mail_to" ) == 0 )
            opt.mail_to = q;
        else if( strcmp( p, "ca_file" ) == 0 )
            opt.ca_file = q;
        else if( strcmp( p, "crt_file" ) == 0 )
            opt.crt_file = q;
        else if( strcmp( p, "key_file" ) == 0 )
            opt.key_file = q;
        else if( strcmp( p, "force_ciphersuite" ) == 0 )
        {
            opt.force_ciphersuite[0] = -1;

            opt.force_ciphersuite[0] = ssl_get_ciphersuite_id( q );

            if( opt.force_ciphersuite[0] <= 0 )
                goto usage;

            opt.force_ciphersuite[1] = 0;
        }
        else
            goto usage;
    }

    /*
     * 0. Initialize the RNG and the session data
     */
    printf( "\n  . Seeding the random number generator..." );
    fflush( stdout );

    entropy_init( &entropy );
    if( ( ret = ctr_drbg_init( &ctr_drbg, entropy_func, &entropy,
                               (unsigned char *) pers, strlen( pers ) ) ) != 0 )
    {
        printf( " failed\n  ! ctr_drbg_init returned %d\n", ret );
        goto exit;
    }

    printf( " ok\n" );

    /*
     * 1.1. Load the trusted CA
     */
    printf( "  . Loading the CA root certificate ..." );
    fflush( stdout );

#if defined(POLARSSL_FS_IO)
    if( strlen( opt.ca_file ) )
        ret = x509parse_crtfile( &cacert, opt.ca_file );
    else
#endif
#if defined(POLARSSL_CERTS_C)
        ret = x509parse_crt( &cacert, (unsigned char *) test_ca_crt,
                strlen( test_ca_crt ) );
#else
    {
        ret = 1;
        printf("POLARSSL_CERTS_C not defined.");
    }
#endif
    if( ret != 0 )
    {
        printf( " failed\n  !  x509parse_crt returned %d\n\n", ret );
        goto exit;
    }

    printf( " ok\n" );

    /*
     * 1.2. Load own certificate and private key
     *
     * (can be skipped if client authentication is not required)
     */
    printf( "  . Loading the client cert. and key..." );
    fflush( stdout );

#if defined(POLARSSL_FS_IO)
    if( strlen( opt.crt_file ) )
        ret = x509parse_crtfile( &clicert, opt.crt_file );
    else 
#endif
#if defined(POLARSSL_CERTS_C)
        ret = x509parse_crt( &clicert, (unsigned char *) test_cli_crt,
                strlen( test_cli_crt ) );
#else
    {
        ret = -1;
        printf("POLARSSL_CERTS_C not defined.");
    }
#endif
    if( ret != 0 )
    {
        printf( " failed\n  !  x509parse_crt returned %d\n\n", ret );
        goto exit;
    }

#if defined(POLARSSL_FS_IO)
    if( strlen( opt.key_file ) )
        ret = x509parse_keyfile( &rsa, opt.key_file, "" );
    else
#endif
#if defined(POLARSSL_CERTS_C)
        ret = x509parse_key( &rsa, (unsigned char *) test_cli_key,
                strlen( test_cli_key ), NULL, 0 );
#else
    {
        ret = -1;
        printf("POLARSSL_CERTS_C not defined.");
    }
#endif
    if( ret != 0 )
    {
        printf( " failed\n  !  x509parse_key returned %d\n\n", ret );
        goto exit;
    }

    printf( " ok\n" );

    /*
     * 2. Start the connection
     */
    printf( "  . Connecting to tcp/%s/%-4d...", opt.server_name,
                                                opt.server_port );
    fflush( stdout );

    if( ( ret = net_connect( &server_fd, opt.server_name,
                                         opt.server_port ) ) != 0 )
    {
        printf( " failed\n  ! net_connect returned %d\n\n", ret );
        goto exit;
    }

    printf( " ok\n" );

    /*
     * 3. Setup stuff
     */
    printf( "  . Setting up the SSL/TLS structure..." );
    fflush( stdout );

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

    printf( " ok\n" );

    ssl_set_endpoint( &ssl, SSL_IS_CLIENT );
    ssl_set_authmode( &ssl, SSL_VERIFY_OPTIONAL );

    ssl_set_rng( &ssl, ctr_drbg_random, &ctr_drbg );
    ssl_set_dbg( &ssl, my_debug, stdout );
    ssl_set_bio( &ssl, net_recv, &server_fd,
            net_send, &server_fd );

    if( opt.force_ciphersuite[0] == DFL_FORCE_CIPHER )
        ssl_set_ciphersuites( &ssl, ssl_default_ciphersuites );
    else
        ssl_set_ciphersuites( &ssl, opt.force_ciphersuite );

    ssl_set_session( &ssl, 1, 600, &ssn );

    ssl_set_ca_chain( &ssl, &cacert, NULL, opt.server_name );
    ssl_set_own_cert( &ssl, &clicert, &rsa );

    ssl_set_hostname( &ssl, opt.server_name );

    if( opt.mode == MODE_SSL_TLS )
    {
        if( do_handshake( &ssl, &opt ) != 0 )
            goto exit;

        printf( "  > Get header from server:" );
        fflush( stdout );

        ret = write_ssl_and_get_response( &ssl, buf, 0 );
        if( ret < 200 || ret > 299 )
        {
            printf( " failed\n  ! server responded with %d\n\n", ret );
            goto exit;
        }

        printf(" ok\n" );

        printf( "  > Write EHLO to server:" );
        fflush( stdout );

        gethostname( hostname, 32 );
        len = sprintf( (char *) buf, "EHLO %s\n", hostname );
        ret = write_ssl_and_get_response( &ssl, buf, len );
        if( ret < 200 || ret > 299 )
        {
            printf( " failed\n  ! server responded with %d\n\n", ret );
            goto exit;
        }
    }
    else
    {
        printf( "  > Get header from server:" );
        fflush( stdout );

        ret = write_and_get_response( server_fd, buf, 0 );
        if( ret < 200 || ret > 299 )
        {
            printf( " failed\n  ! server responded with %d\n\n", ret );
            goto exit;
        }

        printf(" ok\n" );

        printf( "  > Write EHLO to server:" );
        fflush( stdout );

        gethostname( hostname, 32 );
        len = sprintf( (char *) buf, "EHLO %s\n", hostname );
        ret = write_and_get_response( server_fd, buf, len );
        if( ret < 200 || ret > 299 )
        {
            printf( " failed\n  ! server responded with %d\n\n", ret );
            goto exit;
        }

        printf(" ok\n" );

        printf( "  > Write STARTTLS to server:" );
        fflush( stdout );

        gethostname( hostname, 32 );
        len = sprintf( (char *) buf, "STARTTLS\n" );
        ret = write_and_get_response( server_fd, buf, len );
        if( ret < 200 || ret > 299 )
        {
            printf( " failed\n  ! server responded with %d\n\n", ret );
            goto exit;
        }

        printf(" ok\n" );

        if( do_handshake( &ssl, &opt ) != 0 )
            goto exit;
    }

#if defined(POLARSSL_BASE64_C)
    if( opt.authentication )
    {
        printf( "  > Write AUTH LOGIN to server:" );
        fflush( stdout );

        len = sprintf( (char *) buf, "AUTH LOGIN\n" );
        ret = write_ssl_and_get_response( &ssl, buf, len );
        if( ret < 200 || ret > 399 )
        {
            printf( " failed\n  ! server responded with %d\n\n", ret );
            goto exit;
        }

        printf(" ok\n" );

        printf( "  > Write username to server: %s", opt.user_name );
        fflush( stdout );

        n = sizeof( buf );
        len = base64_encode( base, &n, (unsigned char *) opt.user_name, strlen( opt.user_name ) );
        len = sprintf( (char *) buf, "%s\n", base );
        ret = write_ssl_and_get_response( &ssl, buf, len );
        if( ret < 300 || ret > 399 )
        {
            printf( " failed\n  ! server responded with %d\n\n", ret );
            goto exit;
        }

        printf(" ok\n" );

        printf( "  > Write password to server: %s", opt.user_pwd );
        fflush( stdout );

        len = base64_encode( base, &n, (unsigned char *) opt.user_pwd, strlen( opt.user_pwd ) );
        len = sprintf( (char *) buf, "%s\n", base );
        ret = write_ssl_and_get_response( &ssl, buf, len );
        if( ret < 200 || ret > 399 )
        {
            printf( " failed\n  ! server responded with %d\n\n", ret );
            goto exit;
        }

        printf(" ok\n" );
    }
#endif

    printf( "  > Write MAIL FROM to server:" );
    fflush( stdout );

    len = sprintf( (char *) buf, "MAIL FROM:<%s>\n", opt.mail_from );
    ret = write_ssl_and_get_response( &ssl, buf, len );
    if( ret < 200 || ret > 299 )
    {
        printf( " failed\n  ! server responded with %d\n\n", ret );
        goto exit;
    }

    printf(" ok\n" );

    printf( "  > Write RCPT TO to server:" );
    fflush( stdout );

    len = sprintf( (char *) buf, "RCPT TO:<%s>\n", opt.mail_to );
    ret = write_ssl_and_get_response( &ssl, buf, len );
    if( ret < 200 || ret > 299 )
    {
        printf( " failed\n  ! server responded with %d\n\n", ret );
        goto exit;
    }

    printf(" ok\n" );

    printf( "  > Write DATA to server:" );
    fflush( stdout );

    len = sprintf( (char *) buf, "DATA\n" );
    ret = write_ssl_and_get_response( &ssl, buf, len );
    if( ret < 300 || ret > 399 )
    {
        printf( " failed\n  ! server responded with %d\n\n", ret );
        goto exit;
    }

    printf(" ok\n" );

    printf( "  > Write content to server:" );
    fflush( stdout );

    len = sprintf( (char *) buf, "From: %s\nSubject: PolarSSL Test mail\n\n"
            "This is a simple test mail from the "
            "PolarSSL mail client example.\n"
            "\n"
            "Enjoy!", opt.mail_from );
    ret = write_ssl_data( &ssl, buf, len );

    len = sprintf( (char *) buf, "\r\n.\r\n");
    ret = write_ssl_and_get_response( &ssl, buf, len );
    if( ret < 200 || ret > 299 )
    {
        printf( " failed\n  ! server responded with %d\n\n", ret );
        goto exit;
    }

    printf(" ok\n" );

    ssl_close_notify( &ssl );

exit:

    if( server_fd )
        net_close( server_fd );
    x509_free( &clicert );
    x509_free( &cacert );
    rsa_free( &rsa );
    ssl_free( &ssl );

    memset( &ssl, 0, sizeof( ssl ) );

#if defined(_WIN32)
    printf( "  + Press Enter to exit this program.\n" );
    fflush( stdout ); getchar();
#endif

    return( ret );
}
Esempio n. 8
0
/**
 * Run SSL handshake and store the resulting time value in the
 * 'time_map'.
 *
 * @param time_map where to store the current time
 */
static void
run_ssl (uint32_t *time_map, int time_is_an_illusion)
{
  entropy_context entropy;
  ctr_drbg_context ctr_drbg;
  ssl_context ssl;
  proxy_polarssl_ctx proxy_ctx;
  x509_cert cacert;
  struct stat statbuf;
  int ret = 0, server_fd = 0;
  char *pers = "tlsdate-helper";

  memset (&ssl, 0, sizeof(ssl_context));
  memset (&cacert, 0, sizeof(x509_cert));

  verb("V: Using PolarSSL for SSL\n");
  if (ca_racket)
  {
    if (-1 == stat (ca_cert_container, &statbuf))
    {
      die("Unable to stat CA certficate container %s\n", ca_cert_container);
    }
    else
    {
      switch (statbuf.st_mode & S_IFMT)
      {
      case S_IFREG:
        if (0 > x509parse_crtfile(&cacert, ca_cert_container))
          fprintf(stderr, "x509parse_crtfile failed\n");
        break;
      case S_IFDIR:
        if (0 > x509parse_crtpath(&cacert, ca_cert_container))
          fprintf(stderr, "x509parse_crtpath failed\n");
        break;
      default:
        die("Unable to load CA certficate container %s\n", ca_cert_container);
      }
    }
  }

  entropy_init (&entropy);
  if (0 != ctr_drbg_init (&ctr_drbg, entropy_func, &entropy,
                         (unsigned char *) pers, strlen(pers)))
  {
    die("Failed to initialize CTR_DRBG\n");
  }

  if (0 != ssl_init (&ssl))
  {
    die("SSL initialization failed\n");
  }
  ssl_set_endpoint (&ssl, SSL_IS_CLIENT);
  ssl_set_rng (&ssl, ctr_drbg_random, &ctr_drbg);
  ssl_set_ca_chain (&ssl, &cacert, NULL, hostname_to_verify);
  if (ca_racket)
  {
      // You can do SSL_VERIFY_REQUIRED here, but then the check in
      // inspect_key() never happens as the ssl_handshake() will fail.
      ssl_set_authmode (&ssl, SSL_VERIFY_OPTIONAL);
  }

  if (proxy)
  {
    char *scheme;
    char *proxy_host;
    char *proxy_port;

    parse_proxy_uri (proxy, &scheme, &proxy_host, &proxy_port);

    verb("V: opening socket to proxy %s:%s\n", proxy_host, proxy_port);
    if (0 != net_connect (&server_fd, proxy_host, atoi(proxy_port)))
    {
      die ("SSL connection failed\n");
    }

    proxy_polarssl_init (&proxy_ctx);
    proxy_polarssl_set_bio (&proxy_ctx, net_recv, &server_fd, net_send, &server_fd);
    proxy_polarssl_set_host (&proxy_ctx, host);
    proxy_polarssl_set_port (&proxy_ctx, atoi(port));
    proxy_polarssl_set_scheme (&proxy_ctx, scheme);

    ssl_set_bio (&ssl, proxy_polarssl_recv, &proxy_ctx, proxy_polarssl_send, &proxy_ctx);

    verb("V: Handle proxy connection\n");
    if (0 == proxy_ctx.f_connect (&proxy_ctx))
      die("Proxy connection failed\n");
  }
  else
  {
    verb("V: opening socket to %s:%s\n", host, port);
    if (0 != net_connect (&server_fd, host, atoi(port)))
    {
      die ("SSL connection failed\n");
    }

    ssl_set_bio (&ssl, net_recv, &server_fd, net_send, &server_fd);
  }

  verb("V: starting handshake\n");
  if (0 != ssl_do_handshake_part (&ssl))
    die("SSL handshake first part failed\n");

  uint32_t timestamp = ( (uint32_t) ssl.in_msg[6] << 24 )
                     | ( (uint32_t) ssl.in_msg[7] << 16 )
                     | ( (uint32_t) ssl.in_msg[8] <<  8 )
                     | ( (uint32_t) ssl.in_msg[9]       );
  check_timestamp (timestamp);

  verb("V: continuing handshake\n");
  /* Continue with handshake */
  while (0 != (ret = ssl_handshake (&ssl)))
  {
    if (POLARSSL_ERR_NET_WANT_READ  != ret &&
        POLARSSL_ERR_NET_WANT_WRITE != ret)
    {
      die("SSL handshake failed\n");
    }
  }

  // Verify the peer certificate against the CA certs on the local system
  if (ca_racket) {
    inspect_key (&ssl, hostname_to_verify);
  } else {
    verb ("V: Certificate verification skipped!\n");
  }
  check_key_length (&ssl);

  memcpy (time_map, &timestamp, sizeof(uint32_t));
  proxy_polarssl_free (&proxy_ctx);
  ssl_free (&ssl);
  x509_free (&cacert);
}
Esempio n. 9
0
int main( int argc, char *argv[] )
{
    int ret = 0, len, server_fd;
    unsigned char buf[1024];
    char *pers = "ssl_client2";

    entropy_context entropy;
    ctr_drbg_context ctr_drbg;
    ssl_context ssl;
    x509_cert cacert;
    x509_cert clicert;
    rsa_context rsa;
    int i;
    char *p, *q;
    const int *list;

    /*
     * Make sure memory references are valid.
     */
    server_fd = 0;
    memset( &ssl, 0, sizeof( ssl_context ) );
    memset( &cacert, 0, sizeof( x509_cert ) );
    memset( &clicert, 0, sizeof( x509_cert ) );
    memset( &rsa, 0, sizeof( rsa_context ) );

    if( argc == 0 )
    {
    usage:
        if( ret == 0 )
            ret = 1;

        printf( USAGE );

        list = ssl_list_ciphersuites();
        while( *list )
        {
            printf("    %s\n", ssl_get_ciphersuite_name( *list ) );
            list++;
        }
        printf("\n");
        goto exit;
    }

    opt.server_name         = DFL_SERVER_NAME;
    opt.server_port         = DFL_SERVER_PORT;
    opt.debug_level         = DFL_DEBUG_LEVEL;
    opt.request_page        = DFL_REQUEST_PAGE;
    opt.ca_file             = DFL_CA_FILE;
    opt.ca_path             = DFL_CA_PATH;
    opt.crt_file            = DFL_CRT_FILE;
    opt.key_file            = DFL_KEY_FILE;
    opt.force_ciphersuite[0]= DFL_FORCE_CIPHER;
    opt.renegotiation       = DFL_RENEGOTIATION;
    opt.allow_legacy        = DFL_ALLOW_LEGACY;
    opt.min_version         = DFL_MIN_VERSION;
    opt.max_version         = DFL_MAX_VERSION;
    opt.auth_mode           = DFL_AUTH_MODE;

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

        if( strcmp( p, "server_name" ) == 0 )
            opt.server_name = q;
        else if( strcmp( p, "server_port" ) == 0 )
        {
            opt.server_port = atoi( q );
            if( opt.server_port < 1 || opt.server_port > 65535 )
                goto usage;
        }
        else if( strcmp( p, "debug_level" ) == 0 )
        {
            opt.debug_level = atoi( q );
            if( opt.debug_level < 0 || opt.debug_level > 65535 )
                goto usage;
        }
        else if( strcmp( p, "request_page" ) == 0 )
            opt.request_page = q;
        else if( strcmp( p, "ca_file" ) == 0 )
            opt.ca_file = q;
        else if( strcmp( p, "ca_path" ) == 0 )
            opt.ca_path = q;
        else if( strcmp( p, "crt_file" ) == 0 )
            opt.crt_file = q;
        else if( strcmp( p, "key_file" ) == 0 )
            opt.key_file = q;
        else if( strcmp( p, "force_ciphersuite" ) == 0 )
        {
            opt.force_ciphersuite[0] = -1;

            opt.force_ciphersuite[0] = ssl_get_ciphersuite_id( q );

            if( opt.force_ciphersuite[0] <= 0 )
            {
                ret = 2;
                goto usage;
            }
            opt.force_ciphersuite[1] = 0;
        }
        else if( strcmp( p, "renegotiation" ) == 0 )
        {
            opt.renegotiation = (atoi( q )) ? SSL_RENEGOTIATION_ENABLED :
                                              SSL_RENEGOTIATION_DISABLED;
        }
        else if( strcmp( p, "allow_legacy" ) == 0 )
        {
            opt.allow_legacy = atoi( q );
            if( opt.allow_legacy < 0 || opt.allow_legacy > 1 )
                goto usage;
        }
        else if( strcmp( p, "min_version" ) == 0 )
        {
            if( strcmp( q, "ssl3" ) == 0 )
                opt.min_version = SSL_MINOR_VERSION_0;
            else if( strcmp( q, "tls1" ) == 0 )
                opt.min_version = SSL_MINOR_VERSION_1;
            else if( strcmp( q, "tls1_1" ) == 0 )
                opt.min_version = SSL_MINOR_VERSION_2;
            else if( strcmp( q, "tls1_2" ) == 0 )
                opt.min_version = SSL_MINOR_VERSION_3;
            else
                goto usage;
        }
        else if( strcmp( p, "max_version" ) == 0 )
        {
            if( strcmp( q, "ssl3" ) == 0 )
                opt.max_version = SSL_MINOR_VERSION_0;
            else if( strcmp( q, "tls1" ) == 0 )
                opt.max_version = SSL_MINOR_VERSION_1;
            else if( strcmp( q, "tls1_1" ) == 0 )
                opt.max_version = SSL_MINOR_VERSION_2;
            else if( strcmp( q, "tls1_2" ) == 0 )
                opt.max_version = SSL_MINOR_VERSION_3;
            else
                goto usage;
        }
        else if( strcmp( p, "force_version" ) == 0 )
        {
            if( strcmp( q, "ssl3" ) == 0 )
            {
                opt.min_version = SSL_MINOR_VERSION_0;
                opt.max_version = SSL_MINOR_VERSION_0;
            }
            else if( strcmp( q, "tls1" ) == 0 )
            {
                opt.min_version = SSL_MINOR_VERSION_1;
                opt.max_version = SSL_MINOR_VERSION_1;
            }
            else if( strcmp( q, "tls1_1" ) == 0 )
            {
                opt.min_version = SSL_MINOR_VERSION_2;
                opt.max_version = SSL_MINOR_VERSION_2;
            }
            else if( strcmp( q, "tls1_2" ) == 0 )
            {
                opt.min_version = SSL_MINOR_VERSION_3;
                opt.max_version = SSL_MINOR_VERSION_3;
            }
            else
                goto usage;
        }
        else if( strcmp( p, "auth_mode" ) == 0 )
        {
            if( strcmp( q, "none" ) == 0 )
                opt.auth_mode = SSL_VERIFY_NONE;
            else if( strcmp( q, "optional" ) == 0 )
                opt.auth_mode = SSL_VERIFY_OPTIONAL;
            else if( strcmp( q, "required" ) == 0 )
                opt.auth_mode = SSL_VERIFY_REQUIRED;
            else
                goto usage;
        }
        else
            goto usage;
    }

    /*
     * 0. Initialize the RNG and the session data
     */
    printf( "\n  . Seeding the random number generator..." );
    fflush( stdout );

    entropy_init( &entropy );
    if( ( ret = ctr_drbg_init( &ctr_drbg, entropy_func, &entropy,
                               (unsigned char *) pers, strlen( pers ) ) ) != 0 )
    {
        printf( " failed\n  ! ctr_drbg_init returned -0x%x\n", -ret );
        goto exit;
    }

    printf( " ok\n" );

    /*
     * 1.1. Load the trusted CA
     */
    printf( "  . Loading the CA root certificate ..." );
    fflush( stdout );

#if defined(POLARSSL_FS_IO)
    if( strlen( opt.ca_path ) )
        ret = x509parse_crtpath( &cacert, opt.ca_path );
    else if( strlen( opt.ca_file ) )
        ret = x509parse_crtfile( &cacert, opt.ca_file );
    else 
#endif
#if defined(POLARSSL_CERTS_C)
        ret = x509parse_crt( &cacert, (unsigned char *) test_ca_crt,
                strlen( test_ca_crt ) );
#else
    {
        ret = 1;
        printf("POLARSSL_CERTS_C not defined.");
    }
#endif
    if( ret < 0 )
    {
        printf( " failed\n  !  x509parse_crt returned -0x%x\n\n", -ret );
        goto exit;
    }

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

    /*
     * 1.2. Load own certificate and private key
     *
     * (can be skipped if client authentication is not required)
     */
    printf( "  . Loading the client cert. and key..." );
    fflush( stdout );

#if defined(POLARSSL_FS_IO)
    if( strlen( opt.crt_file ) )
        ret = x509parse_crtfile( &clicert, opt.crt_file );
    else 
#endif
#if defined(POLARSSL_CERTS_C)
        ret = x509parse_crt( &clicert, (unsigned char *) test_cli_crt,
                strlen( test_cli_crt ) );
#else
    {
        ret = 1;
        printf("POLARSSL_CERTS_C not defined.");
    }
#endif
    if( ret != 0 )
    {
        printf( " failed\n  !  x509parse_crt returned -0x%x\n\n", -ret );
        goto exit;
    }

#if defined(POLARSSL_FS_IO)
    if( strlen( opt.key_file ) )
        ret = x509parse_keyfile( &rsa, opt.key_file, "" );
    else
#endif
#if defined(POLARSSL_CERTS_C)
        ret = x509parse_key( &rsa, (unsigned char *) test_cli_key,
                strlen( test_cli_key ), NULL, 0 );
#else
    {
        ret = 1;
        printf("POLARSSL_CERTS_C not defined.");
    }
#endif
    if( ret != 0 )
    {
        printf( " failed\n  !  x509parse_key returned -0x%x\n\n", -ret );
        goto exit;
    }

    printf( " ok\n" );

    /*
     * 2. Start the connection
     */
    printf( "  . Connecting to tcp/%s/%-4d...", opt.server_name,
                                                opt.server_port );
    fflush( stdout );

    if( ( ret = net_connect( &server_fd, opt.server_name,
                                         opt.server_port ) ) != 0 )
    {
        printf( " failed\n  ! net_connect returned -0x%x\n\n", -ret );
        goto exit;
    }

    printf( " ok\n" );

    /*
     * 3. Setup stuff
     */
    printf( "  . Setting up the SSL/TLS structure..." );
    fflush( stdout );

    if( ( ret = ssl_init( &ssl ) ) != 0 )
    {
        printf( " failed\n  ! ssl_init returned -0x%x\n\n", -ret );
        goto exit;
    }

    printf( " ok\n" );

    if( opt.debug_level > 0 )
        ssl_set_verify( &ssl, my_verify, NULL );

    ssl_set_endpoint( &ssl, SSL_IS_CLIENT );
    ssl_set_authmode( &ssl, opt.auth_mode );

    ssl_set_rng( &ssl, ctr_drbg_random, &ctr_drbg );
    ssl_set_dbg( &ssl, my_debug, stdout );
    ssl_set_bio( &ssl, net_recv, &server_fd,
                       net_send, &server_fd );

    if( opt.force_ciphersuite[0] != DFL_FORCE_CIPHER )
        ssl_set_ciphersuites( &ssl, opt.force_ciphersuite );

    ssl_set_renegotiation( &ssl, opt.renegotiation );
    ssl_legacy_renegotiation( &ssl, opt.allow_legacy );

    ssl_set_ca_chain( &ssl, &cacert, NULL, opt.server_name );
    ssl_set_own_cert( &ssl, &clicert, &rsa );

    ssl_set_hostname( &ssl, opt.server_name );

    if( opt.min_version != -1 )
        ssl_set_min_version( &ssl, SSL_MAJOR_VERSION_3, opt.min_version );
    if( opt.max_version != -1 )
        ssl_set_max_version( &ssl, SSL_MAJOR_VERSION_3, opt.max_version );

    /*
     * 4. Handshake
     */
    printf( "  . Performing the SSL/TLS handshake..." );
    fflush( stdout );

    while( ( ret = ssl_handshake( &ssl ) ) != 0 )
    {
        if( ret != POLARSSL_ERR_NET_WANT_READ && ret != POLARSSL_ERR_NET_WANT_WRITE )
        {
            printf( " failed\n  ! ssl_handshake returned -0x%x\n\n", -ret );
            goto exit;
        }
    }

    printf( " ok\n    [ Ciphersuite is %s ]\n",
            ssl_get_ciphersuite( &ssl ) );

    /*
     * 5. Verify the server certificate
     */
    printf( "  . Verifying peer X.509 certificate..." );

    if( ( ret = ssl_get_verify_result( &ssl ) ) != 0 )
    {
        printf( " failed\n" );

        if( ( ret & BADCERT_EXPIRED ) != 0 )
            printf( "  ! server certificate has expired\n" );

        if( ( ret & BADCERT_REVOKED ) != 0 )
            printf( "  ! server certificate has been revoked\n" );

        if( ( ret & BADCERT_CN_MISMATCH ) != 0 )
            printf( "  ! CN mismatch (expected CN=%s)\n", opt.server_name );

        if( ( ret & BADCERT_NOT_TRUSTED ) != 0 )
            printf( "  ! self-signed or not signed by a trusted CA\n" );

        printf( "\n" );
    }
    else
        printf( " ok\n" );

    printf( "  . Peer certificate information    ...\n" );
    x509parse_cert_info( (char *) buf, sizeof( buf ) - 1, "      ",
                         ssl_get_peer_cert( &ssl ) );
    printf( "%s\n", buf );

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

    len = sprintf( (char *) buf, GET_REQUEST, opt.request_page );

    while( ( ret = ssl_write( &ssl, buf, len ) ) <= 0 )
    {
        if( ret != POLARSSL_ERR_NET_WANT_READ && ret != POLARSSL_ERR_NET_WANT_WRITE )
        {
            printf( " failed\n  ! ssl_write returned -0x%x\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:" );
    fflush( stdout );

    do
    {
        len = sizeof( buf ) - 1;
        memset( buf, 0, sizeof( buf ) );
        ret = ssl_read( &ssl, buf, len );

        if( ret == POLARSSL_ERR_NET_WANT_READ || ret == POLARSSL_ERR_NET_WANT_WRITE )
            continue;

        if( ret == POLARSSL_ERR_SSL_PEER_CLOSE_NOTIFY )
            break;

        if( ret < 0 )
        {
            printf( "failed\n  ! ssl_read returned -0x%x\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 );

    ssl_close_notify( &ssl );

exit:

#ifdef POLARSSL_ERROR_C
    if( ret != 0 )
    {
        char error_buf[100];
        error_strerror( ret, error_buf, 100 );
        printf("Last error was: -0x%X - %s\n\n", -ret, error_buf );
    }
#endif

    if( server_fd )
        net_close( server_fd );
    x509_free( &clicert );
    x509_free( &cacert );
    rsa_free( &rsa );
    ssl_free( &ssl );

    memset( &ssl, 0, sizeof( ssl ) );

#if defined(_WIN32)
    printf( "  + Press Enter to exit this program.\n" );
    fflush( stdout ); getchar();
#endif

    return( ret );
}
int main( int argc, char *argv[] )
{
    int ret, len, cnt = 0, pid;
    int listen_fd;
    int client_fd;
    unsigned char buf[1024];
    const char *pers = "ssl_fork_server";

    entropy_context entropy;
    ctr_drbg_context ctr_drbg;
    ssl_context ssl;
    x509_cert srvcert;
    rsa_context rsa;

    ((void) argc);
    ((void) argv);

    signal( SIGCHLD, SIG_IGN );

    /*
     * 0. Initial seeding of the RNG
     */
    printf( "\n  . Initial seeding of the random generator..." );
    fflush( stdout );

    entropy_init( &entropy );
    if( ( ret = ctr_drbg_init( &ctr_drbg, entropy_func, &entropy,
                               (const unsigned char *) pers,
                               strlen( pers ) ) ) != 0 )
    {
        printf( " failed\n  ! ctr_drbg_init returned %d\n", ret );
        goto exit;
    }

    printf( " ok\n" );

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

    memset( &srvcert, 0, sizeof( x509_cert ) );

    /*
     * This demonstration program uses embedded test certificates.
     * Instead, you may want to use x509parse_crtfile() to read the
     * server and CA certificates, as well as x509parse_keyfile().
     */
    ret = x509parse_crt( &srvcert, (const unsigned char *) test_srv_crt,
                         strlen( test_srv_crt ) );
    if( ret != 0 )
    {
        printf( " failed\n  !  x509parse_crt returned %d\n\n", ret );
        goto exit;
    }

    ret = x509parse_crt( &srvcert, (const unsigned char *) test_ca_crt,
                         strlen( test_ca_crt ) );
    if( ret != 0 )
    {
        printf( " failed\n  !  x509parse_crt returned %d\n\n", ret );
        goto exit;
    }

    rsa_init( &rsa, RSA_PKCS_V15, 0 );
    ret =  x509parse_key( &rsa, (const unsigned char *) test_srv_key,
                          strlen( test_srv_key ), NULL, 0 );
    if( ret != 0 )
    {
        printf( " failed\n  !  x509parse_key returned %d\n\n", ret );
        goto exit;
    }

    printf( " ok\n" );

    /*
     * 2. Setup the listening TCP socket
     */
    printf( "  . Bind on https://localhost:4433/ ..." );
    fflush( stdout );

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

    printf( " ok\n" );

    while( 1 )
    {
        /*
         * 3. Wait until a client connects
         */
        client_fd = -1;
        memset( &ssl, 0, sizeof( ssl ) );

        printf( "  . Waiting for a remote connection ..." );
        fflush( stdout );

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

        printf( " ok\n" );

        /*
         * 3.5. Forking server thread
         */

        pid = fork();

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

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

        printf( " ok\n" );

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

            close( client_fd );
            continue;
        }

        close( listen_fd );

        /*
         * 4. Setup stuff
         */
        printf( "  . Setting up the SSL data...." );
        fflush( stdout );

        if( ( ret = ctr_drbg_reseed( &ctr_drbg,
                                     (const unsigned char *) "child",
                                     5 ) ) != 0 )
        {
            printf( " failed\n  ! ctr_drbg_reseed returned %d\n", ret );
            goto exit;
        }

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

        printf( " ok\n" );

        ssl_set_endpoint( &ssl, SSL_IS_SERVER );
        ssl_set_authmode( &ssl, SSL_VERIFY_NONE );

        ssl_set_rng( &ssl, ctr_drbg_random, &ctr_drbg );
        ssl_set_dbg( &ssl, my_debug, stdout );
        ssl_set_bio( &ssl, net_recv, &client_fd,
                           net_send, &client_fd );

        ssl_set_ca_chain( &ssl, srvcert.next, NULL, NULL );
        ssl_set_own_cert( &ssl, &srvcert, &rsa );

        /*
         * 5. Handshake
         */
        printf( "  . Performing the SSL/TLS handshake..." );
        fflush( stdout );

        while( ( ret = ssl_handshake( &ssl ) ) != 0 )
        {
            if( ret != POLARSSL_ERR_NET_WANT_READ && ret != POLARSSL_ERR_NET_WANT_WRITE )
            {
                printf( " failed\n  ! ssl_handshake returned %d\n\n", ret );
                goto exit;
            }
        }

        printf( " ok\n" );

        /*
         * 6. Read the HTTP Request
         */
        printf( "  < Read from client:" );
        fflush( stdout );

        do
        {
            len = sizeof( buf ) - 1;
            memset( buf, 0, sizeof( buf ) );
            ret = ssl_read( &ssl, buf, len );

            if( ret == POLARSSL_ERR_NET_WANT_READ || ret == POLARSSL_ERR_NET_WANT_WRITE )
                continue;

            if( ret <= 0 )
            {
                switch( ret )
                {
                    case POLARSSL_ERR_SSL_PEER_CLOSE_NOTIFY:
                        printf( " connection was closed gracefully\n" );
                        break;

                    case POLARSSL_ERR_NET_CONN_RESET:
                        printf( " connection was reset by peer\n" );
                        break;

                    default:
                        printf( " ssl_read returned %d\n", ret );
                        break;
                }

                break;
            }

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

        /*
         * 7. Write the 200 Response
         */
        printf( "  > Write to client:" );
        fflush( stdout );

        len = sprintf( (char *) buf, HTTP_RESPONSE,
                ssl_get_ciphersuite( &ssl ) );

        while( cnt < 100 )
        {
            while( ( ret = ssl_write( &ssl, buf, len ) ) <= 0 )
            {
                if( ret == POLARSSL_ERR_NET_CONN_RESET )
                {
                    printf( " failed\n  ! peer closed the connection\n\n" );
                    goto exit;
                }

                if( ret != POLARSSL_ERR_NET_WANT_READ && ret != POLARSSL_ERR_NET_WANT_WRITE )
                {
                    printf( " failed\n  ! ssl_write returned %d\n\n", ret );
                    goto exit;
                }
            }
            len = ret;
            printf( " %d bytes written\n\n%s\n", len, (char *) buf );

            m_sleep( 1000 );
        }

        ssl_close_notify( &ssl );
        goto exit;
    }

exit:

    net_close( client_fd );
    x509_free( &srvcert );
    rsa_free( &rsa );
    ssl_free( &ssl );

#if defined(_WIN32)
    printf( "  Press Enter to exit this program.\n" );
    fflush( stdout ); getchar();
#endif

    return( ret );
}
Esempio n. 11
0
int main( int argc, char *argv[] )
{
    int ret = 0, len;
    int listen_fd;
    int client_fd = -1;
    unsigned char buf[1024];
    const char *pers = "ssl_server2";

    entropy_context entropy;
    ctr_drbg_context ctr_drbg;
    ssl_context ssl;
    x509_cert cacert;
    x509_cert srvcert;
    rsa_context rsa;
#if defined(POLARSSL_SSL_CACHE_C)
    ssl_cache_context cache;
#endif

    int i;
    char *p, *q;
    const int *list;

    /*
     * Make sure memory references are valid.
     */
    listen_fd = 0;
    memset( &cacert, 0, sizeof( x509_cert ) );
    memset( &srvcert, 0, sizeof( x509_cert ) );
    memset( &rsa, 0, sizeof( rsa_context ) );
#if defined(POLARSSL_SSL_CACHE_C)
    ssl_cache_init( &cache );
#endif

    if( argc == 0 )
    {
    usage:
        if( ret == 0 )
            ret = 1;

        printf( USAGE );

        list = ssl_list_ciphersuites();
        while( *list )
        {
            printf("    %s\n", ssl_get_ciphersuite_name( *list ) );
            list++;
        }
        printf("\n");
        goto exit;
    }

    opt.server_port         = DFL_SERVER_PORT;
    opt.debug_level         = DFL_DEBUG_LEVEL;
    opt.ca_file             = DFL_CA_FILE;
    opt.ca_path             = DFL_CA_PATH;
    opt.crt_file            = DFL_CRT_FILE;
    opt.key_file            = DFL_KEY_FILE;
    opt.force_ciphersuite[0]= DFL_FORCE_CIPHER;
    opt.renegotiation       = DFL_RENEGOTIATION;
    opt.allow_legacy        = DFL_ALLOW_LEGACY;
    opt.min_version         = DFL_MIN_VERSION;
    opt.auth_mode           = DFL_AUTH_MODE;

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

        if( strcmp( p, "server_port" ) == 0 )
        {
            opt.server_port = atoi( q );
            if( opt.server_port < 1 || opt.server_port > 65535 )
                goto usage;
        }
        else if( strcmp( p, "debug_level" ) == 0 )
        {
            opt.debug_level = atoi( q );
            if( opt.debug_level < 0 || opt.debug_level > 65535 )
                goto usage;
        }
        else if( strcmp( p, "ca_file" ) == 0 )
            opt.ca_file = q;
        else if( strcmp( p, "ca_path" ) == 0 )
            opt.ca_path = q;
        else if( strcmp( p, "crt_file" ) == 0 )
            opt.crt_file = q;
        else if( strcmp( p, "key_file" ) == 0 )
            opt.key_file = q;
        else if( strcmp( p, "force_ciphersuite" ) == 0 )
        {
            opt.force_ciphersuite[0] = -1;

            opt.force_ciphersuite[0] = ssl_get_ciphersuite_id( q );

            if( opt.force_ciphersuite[0] <= 0 )
            {
                ret = 2;
                goto usage;
            }
            opt.force_ciphersuite[1] = 0;
        }
        else if( strcmp( p, "renegotiation" ) == 0 )
        {
            opt.renegotiation = (atoi( q )) ? SSL_RENEGOTIATION_ENABLED :
                                              SSL_RENEGOTIATION_DISABLED;
        }
        else if( strcmp( p, "allow_legacy" ) == 0 )
        {
            opt.allow_legacy = atoi( q );
            if( opt.allow_legacy < 0 || opt.allow_legacy > 1 )
                goto usage;
        }
        else if( strcmp( p, "min_version" ) == 0 )
        {
            if( strcmp( q, "ssl3" ) == 0 )
                opt.min_version = SSL_MINOR_VERSION_0;
            else if( strcmp( q, "tls1" ) == 0 )
                opt.min_version = SSL_MINOR_VERSION_1;
            else if( strcmp( q, "tls1_1" ) == 0 )
                opt.min_version = SSL_MINOR_VERSION_2;
            else if( strcmp( q, "tls1_2" ) == 0 )
                opt.min_version = SSL_MINOR_VERSION_3;
            else
                goto usage;
        }
        else if( strcmp( p, "auth_mode" ) == 0 )
        {
            if( strcmp( q, "none" ) == 0 )
                opt.auth_mode = SSL_VERIFY_NONE;
            else if( strcmp( q, "optional" ) == 0 )
                opt.auth_mode = SSL_VERIFY_OPTIONAL;
            else if( strcmp( q, "required" ) == 0 )
                opt.auth_mode = SSL_VERIFY_REQUIRED;
            else
                goto usage;
        }
        else
            goto usage;
    }

    /*
     * 0. Initialize the RNG and the session data
     */
    printf( "\n  . Seeding the random number generator..." );
    fflush( stdout );

    entropy_init( &entropy );
    if( ( ret = ctr_drbg_init( &ctr_drbg, entropy_func, &entropy,
                               (const unsigned char *) pers,
                               strlen( pers ) ) ) != 0 )
    {
        printf( " failed\n  ! ctr_drbg_init returned -0x%x\n", -ret );
        goto exit;
    }

    printf( " ok\n" );

    /*
     * 1.1. Load the trusted CA
     */
    printf( "  . Loading the CA root certificate ..." );
    fflush( stdout );

#if defined(POLARSSL_FS_IO)
    if( strlen( opt.ca_path ) )
        ret = x509parse_crtpath( &cacert, opt.ca_path );
    else if( strlen( opt.ca_file ) )
        ret = x509parse_crtfile( &cacert, opt.ca_file );
    else 
#endif
#if defined(POLARSSL_CERTS_C)
        ret = x509parse_crt( &cacert, (const unsigned char *) test_ca_crt,
                strlen( test_ca_crt ) );
#else
    {
        ret = 1;
        printf("POLARSSL_CERTS_C not defined.");
    }
#endif
    if( ret < 0 )
    {
        printf( " failed\n  !  x509parse_crt returned -0x%x\n\n", -ret );
        goto exit;
    }

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

    /*
     * 1.2. Load own certificate and private key
     */
    printf( "  . Loading the server cert. and key..." );
    fflush( stdout );

#if defined(POLARSSL_FS_IO)
    if( strlen( opt.crt_file ) )
        ret = x509parse_crtfile( &srvcert, opt.crt_file );
    else 
#endif
#if defined(POLARSSL_CERTS_C)
        ret = x509parse_crt( &srvcert, (const unsigned char *) test_srv_crt,
                strlen( test_srv_crt ) );
#else
    {
        ret = 1;
        printf("POLARSSL_CERTS_C not defined.");
    }
#endif
    if( ret != 0 )
    {
        printf( " failed\n  !  x509parse_crt returned -0x%x\n\n", -ret );
        goto exit;
    }

#if defined(POLARSSL_FS_IO)
    if( strlen( opt.key_file ) )
        ret = x509parse_keyfile( &rsa, opt.key_file, "" );
    else
#endif
#if defined(POLARSSL_CERTS_C)
        ret = x509parse_key( &rsa, (const unsigned char *) test_srv_key,
                strlen( test_srv_key ), NULL, 0 );
#else
    {
        ret = 1;
        printf("POLARSSL_CERTS_C not defined.");
    }
#endif
    if( ret != 0 )
    {
        printf( " failed\n  !  x509parse_key returned -0x%x\n\n", -ret );
        goto exit;
    }

    printf( " ok\n" );

    /*
     * 2. Setup the listening TCP socket
     */
    printf( "  . Bind on tcp://localhost:%-4d/ ...", opt.server_port );
    fflush( stdout );

    if( ( ret = net_bind( &listen_fd, NULL, opt.server_port ) ) != 0 )
    {
        printf( " failed\n  ! net_bind returned -0x%x\n\n", -ret );
        goto exit;
    }

    printf( " ok\n" );

    /*
     * 3. Setup stuff
     */
    printf( "  . Setting up the SSL/TLS structure..." );
    fflush( stdout );

    if( ( ret = ssl_init( &ssl ) ) != 0 )
    {
        printf( " failed\n  ! ssl_init returned -0x%x\n\n", -ret );
        goto exit;
    }

    ssl_set_endpoint( &ssl, SSL_IS_SERVER );
    ssl_set_authmode( &ssl, opt.auth_mode );

    ssl_set_rng( &ssl, ctr_drbg_random, &ctr_drbg );
    ssl_set_dbg( &ssl, my_debug, stdout );

#if defined(POLARSSL_SSL_CACHE_C)
    ssl_set_session_cache( &ssl, ssl_cache_get, &cache,
                                 ssl_cache_set, &cache );
#endif

    if( opt.force_ciphersuite[0] == DFL_FORCE_CIPHER )
        ssl_set_ciphersuites( &ssl, my_ciphersuites );
    else
        ssl_set_ciphersuites( &ssl, opt.force_ciphersuite );

    ssl_set_renegotiation( &ssl, opt.renegotiation );
    ssl_legacy_renegotiation( &ssl, opt.allow_legacy );

    ssl_set_ca_chain( &ssl, &cacert, NULL, NULL );
    ssl_set_own_cert( &ssl, &srvcert, &rsa );

#if defined(POLARSSL_DHM_C)
    /*
     * Use different group than default DHM group
     */
    ssl_set_dh_param( &ssl, POLARSSL_DHM_RFC5114_MODP_2048_P,
                            POLARSSL_DHM_RFC5114_MODP_2048_G );
#endif

    if( opt.min_version != -1 )
        ssl_set_min_version( &ssl, SSL_MAJOR_VERSION_3, opt.min_version );

    printf( " ok\n" );

reset:
#ifdef POLARSSL_ERROR_C
    if( ret != 0 )
    {
        char error_buf[100];
        error_strerror( ret, error_buf, 100 );
        printf("Last error was: %d - %s\n\n", ret, error_buf );
    }
#endif

    if( client_fd != -1 )
        net_close( client_fd );

    ssl_session_reset( &ssl );

    /*
     * 3. Wait until a client connects
     */
#if defined(_WIN32_WCE)
    {
        SHELLEXECUTEINFO sei;

        ZeroMemory( &sei, sizeof( SHELLEXECUTEINFO ) );

        sei.cbSize = sizeof( SHELLEXECUTEINFO );
        sei.fMask = 0;
        sei.hwnd = 0;
        sei.lpVerb = _T( "open" );
        sei.lpFile = _T( "https://localhost:4433/" );
        sei.lpParameters = NULL;
        sei.lpDirectory = NULL;
        sei.nShow = SW_SHOWNORMAL;

        ShellExecuteEx( &sei );
    }
#elif defined(_WIN32)
    ShellExecute( NULL, "open", "https://localhost:4433/",
                  NULL, NULL, SW_SHOWNORMAL );
#endif

    client_fd = -1;

    printf( "  . Waiting for a remote connection ..." );
    fflush( stdout );

    if( ( ret = net_accept( listen_fd, &client_fd, NULL ) ) != 0 )
    {
        printf( " failed\n  ! net_accept returned -0x%x\n\n", -ret );
        goto exit;
    }

    ssl_set_bio( &ssl, net_recv, &client_fd,
                       net_send, &client_fd );

    printf( " ok\n" );

    /*
     * 4. Handshake
     */
    printf( "  . Performing the SSL/TLS handshake..." );
    fflush( stdout );

    while( ( ret = ssl_handshake( &ssl ) ) != 0 )
    {
        if( ret != POLARSSL_ERR_NET_WANT_READ && ret != POLARSSL_ERR_NET_WANT_WRITE )
        {
            printf( " failed\n  ! ssl_handshake returned -0x%x\n\n", -ret );
            goto reset;
        }
    }

    printf( " ok\n    [ Ciphersuite is %s ]\n",
            ssl_get_ciphersuite( &ssl ) );

    /*
     * 5. Verify the server certificate
     */
    printf( "  . Verifying peer X.509 certificate..." );

    if( ( ret = ssl_get_verify_result( &ssl ) ) != 0 )
    {
        printf( " failed\n" );

        if( !ssl_get_peer_cert( &ssl ) )
            printf( "  ! no client certificate sent\n" );

        if( ( ret & BADCERT_EXPIRED ) != 0 )
            printf( "  ! client certificate has expired\n" );

        if( ( ret & BADCERT_REVOKED ) != 0 )
            printf( "  ! client certificate has been revoked\n" );

        if( ( ret & BADCERT_NOT_TRUSTED ) != 0 )
            printf( "  ! self-signed or not signed by a trusted CA\n" );

        printf( "\n" );
    }
    else
        printf( " ok\n" );

    if( ssl_get_peer_cert( &ssl ) )
    {
        printf( "  . Peer certificate information    ...\n" );
        x509parse_cert_info( (char *) buf, sizeof( buf ) - 1, "      ",
                             ssl_get_peer_cert( &ssl ) );
        printf( "%s\n", buf );
    }

    /*
     * 6. Read the HTTP Request
     */
    printf( "  < Read from client:" );
    fflush( stdout );

    do
    {
        len = sizeof( buf ) - 1;
        memset( buf, 0, sizeof( buf ) );
        ret = ssl_read( &ssl, buf, len );

        if( ret == POLARSSL_ERR_NET_WANT_READ || ret == POLARSSL_ERR_NET_WANT_WRITE )
            continue;

        if( ret <= 0 )
        {
            switch( ret )
            {
                case POLARSSL_ERR_SSL_PEER_CLOSE_NOTIFY:
                    printf( " connection was closed gracefully\n" );
                    break;

                case POLARSSL_ERR_NET_CONN_RESET:
                    printf( " connection was reset by peer\n" );
                    break;

                default:
                    printf( " ssl_read returned -0x%x\n", -ret );
                    break;
            }

            break;
        }

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

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

    /*
     * 7. Write the 200 Response
     */
    printf( "  > Write to client:" );
    fflush( stdout );

    len = sprintf( (char *) buf, HTTP_RESPONSE,
                   ssl_get_ciphersuite( &ssl ) );

    while( ( ret = ssl_write( &ssl, buf, len ) ) <= 0 )
    {
        if( ret == POLARSSL_ERR_NET_CONN_RESET )
        {
            printf( " failed\n  ! peer closed the connection\n\n" );
            goto reset;
        }

        if( ret != POLARSSL_ERR_NET_WANT_READ && ret != POLARSSL_ERR_NET_WANT_WRITE )
        {
            printf( " failed\n  ! ssl_write returned %d\n\n", ret );
            goto exit;
        }
    }

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

    ret = 0;
    goto reset;

exit:

#ifdef POLARSSL_ERROR_C
    if( ret != 0 )
    {
        char error_buf[100];
        error_strerror( ret, error_buf, 100 );
        printf("Last error was: -0x%X - %s\n\n", -ret, error_buf );
    }
#endif

    net_close( client_fd );
    x509_free( &srvcert );
    x509_free( &cacert );
    rsa_free( &rsa );
    ssl_free( &ssl );

#if defined(POLARSSL_SSL_CACHE_C)
    ssl_cache_free( &cache );
#endif

#if defined(_WIN32)
    printf( "  + Press Enter to exit this program.\n" );
    fflush( stdout ); getchar();
#endif

    return( ret );
}
int main( void )
{
    int ret, len, server_fd;
    unsigned char buf[1024];
    havege_state hs;
    ssl_context ssl;
    ssl_session ssn;
    x509_cert cacert;
    x509_cert clicert;
    rsa_context rsa;

    /*
     * 0. Initialize the RNG and the session data
     */
    havege_init( &hs );
    memset( &ssn, 0, sizeof( ssl_session ) );

    /*
     * 1.1. Load the trusted CA
     */
    printf( "\n  . Loading the CA root certificate ..." );
    fflush( stdout );

    memset( &cacert, 0, sizeof( x509_cert ) );

    /*
     * Alternatively, you may load the CA certificates from a .pem or
     * .crt file by calling x509parse_crtfile( &cacert, "myca.crt" ).
     */
    ret = x509parse_crt( &cacert, (unsigned char *) xyssl_ca_crt,
                         strlen( xyssl_ca_crt ) );
    if( ret != 0 )
    {
        printf( " failed\n  !  x509parse_crt returned %d\n\n", ret );
        goto exit;
    }

    printf( " ok\n" );

    /*
     * 1.2. Load own certificate and private key
     *
     * (can be skipped if client authentication is not required)
     */
    printf( "  . Loading the client cert. and key..." );
    fflush( stdout );

    memset( &clicert, 0, sizeof( x509_cert ) );

    ret = x509parse_crt( &clicert, (unsigned char *) test_cli_crt,
                         strlen( test_cli_crt ) );
    if( ret != 0 )
    {
        printf( " failed\n  !  x509parse_crt returned %d\n\n", ret );
        goto exit;
    }

    ret = x509parse_key( &rsa, (unsigned char *) test_cli_key,
                         strlen( test_cli_key ), NULL, 0 );
    if( ret != 0 )
    {
        printf( " failed\n  !  x509parse_key returned %d\n\n", ret );
        goto exit;
    }

    printf( " ok\n" );

    /*
     * 2. Start the connection
     */
    printf( "  . Connecting to tcp/%s/%-4d...", SERVER_NAME,
                                                SERVER_PORT );
    fflush( stdout );

    if( ( ret = net_connect( &server_fd, SERVER_NAME,
                                         SERVER_PORT ) ) != 0 )
    {
        printf( " failed\n  ! net_connect returned %d\n\n", ret );
        goto exit;
    }

    printf( " ok\n" );

    /*
     * 3. Setup stuff
     */
    printf( "  . Setting up the SSL/TLS structure..." );
    fflush( stdout );

    havege_init( &hs );

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

    printf( " ok\n" );

    ssl_set_endpoint( &ssl, SSL_IS_CLIENT );
    ssl_set_authmode( &ssl, SSL_VERIFY_OPTIONAL );

    ssl_set_rng( &ssl, havege_rand, &hs );
    ssl_set_bio( &ssl, net_recv, &server_fd,
                       net_send, &server_fd );

    ssl_set_ciphers( &ssl, ssl_default_ciphers );
    ssl_set_session( &ssl, 1, 600, &ssn );

    ssl_set_ca_chain( &ssl, &cacert, SERVER_NAME );
    ssl_set_own_cert( &ssl, &clicert, &rsa );

    ssl_set_hostname( &ssl, SERVER_NAME );

    /*
     * 4. Handshake
     */
    printf( "  . Performing the SSL/TLS handshake..." );
    fflush( stdout );

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

    printf( " ok\n    [ Cipher is %s ]\n",
            ssl_get_cipher( &ssl ) );

    /*
     * 5. Verify the server certificate
     */
    printf( "  . Verifying peer X.509 certificate..." );

    if( ( ret = ssl_get_verify_result( &ssl ) ) != 0 )
    {
        printf( " failed\n" );

        if( ( ret & BADCERT_EXPIRED ) != 0 )
            printf( "  ! server certificate has expired\n" );

        if( ( ret & BADCERT_REVOKED ) != 0 )
            printf( "  ! server certificate has been revoked\n" );

        if( ( ret & BADCERT_CN_MISMATCH ) != 0 )
            printf( "  ! CN mismatch (expected CN=%s)\n", SERVER_NAME );

        if( ( ret & BADCERT_NOT_TRUSTED ) != 0 )
            printf( "  ! self-signed or not signed by a trusted CA\n" );

        printf( "\n" );
    }
    else
        printf( " ok\n" );

    printf( "  . Peer certificate information    ...\n" );
    printf( "%s", x509parse_cert_info( "      ", ssl.peer_cert ) );

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

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

    while( ( ret = ssl_write( &ssl, buf, len ) ) <= 0 )
    {
        if( ret != POLARSSL_ERR_NET_TRY_AGAIN )
        {
            printf( " failed\n  ! 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:" );
    fflush( stdout );

    do
    {
        len = sizeof( buf ) - 1;
        memset( buf, 0, sizeof( buf ) );
        ret = ssl_read( &ssl, buf, len );

        if( ret == POLARSSL_ERR_NET_TRY_AGAIN )
            continue;

        if( ret == POLARSSL_ERR_SSL_PEER_CLOSE_NOTIFY )
            break;

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

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

    ssl_close_notify( &ssl );

exit:

    net_close( server_fd );
    x509_free( &clicert );
    x509_free( &cacert );
    rsa_free( &rsa );
    ssl_free( &ssl );

    memset( &ssl, 0, sizeof( ssl ) );

#ifdef WIN32
    printf( "  + Press Enter to exit this program.\n" );
    fflush( stdout ); getchar();
#endif

    return( ret );
}
Esempio n. 13
0
int main( int argc, char *argv[] )
{
    int ret, len, server_fd;
    unsigned char buf[2];
    havege_state hs;
    ssl_context ssl;
    ssl_session ssn;
    x509_cert cacert;
    x509_cert clicert;
    rsa_context rsa;

    char *SERVER_NAME = argv[1];
    char GET_REQUEST[128];

    sprintf( GET_REQUEST, "GET %s HTTP/1.1\r\nHost: %s\r\n\r\n", argv[2],
	     argv[1] );

    /*
     * 0. Initialize the RNG and the session data
     */
    havege_init( &hs );
    memset( &ssn, 0, sizeof( ssl_session ) );

    memset( &cacert, 0, sizeof( x509_cert ) );

    /*
     * Alternatively, you may load the CA certificates from a .pem or
     * .crt file by calling x509parse_crtfile( &cacert, "myca.crt" ).
     */
    ret = x509parse_crt( &cacert, ( unsigned char * )xyssl_ca_crt,
			 strlen( xyssl_ca_crt ) );
    if( ret != 0 )
    {
	printf( " failed\n  !  x509parse_crt returned %d\n\n", ret );
	goto exit;
    }

    /*
     * 1.2. Load own certificate and private key
     *
     * (can be skipped if client authentication is not required)
     */

    memset( &clicert, 0, sizeof( x509_cert ) );

    ret = x509parse_crt( &clicert, ( unsigned char * )test_cli_crt,
			 strlen( test_cli_crt ) );
    if( ret != 0 )
    {
	printf( " failed\n  !  x509parse_crt returned %d\n\n", ret );
	goto exit;
    }

    ret = x509parse_key( &rsa, ( unsigned char * )test_cli_key,
			 strlen( test_cli_key ), NULL, 0 );
    if( ret != 0 )
    {
	printf( " failed\n  !  x509parse_key returned %d\n\n", ret );
	goto exit;
    }

    if( ( ret = net_connect( &server_fd, SERVER_NAME, SERVER_PORT ) ) != 0 )
    {
	printf( " failed\n  ! net_connect returned %d\n\n", ret );
	goto exit;
    }

    havege_init( &hs );

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

    ssl_set_endpoint( &ssl, SSL_IS_CLIENT );
    ssl_set_authmode( &ssl, SSL_VERIFY_OPTIONAL );

    ssl_set_rng( &ssl, havege_rand, &hs );
    ssl_set_bio( &ssl, net_recv, &server_fd, net_send, &server_fd );

    ssl_set_ciphers( &ssl, ssl_default_ciphers );
    ssl_set_session( &ssl, 1, 600, &ssn );

    ssl_set_ca_chain( &ssl, &cacert, SERVER_NAME );
    ssl_set_own_cert( &ssl, &clicert, &rsa );

    ssl_set_hostname( &ssl, SERVER_NAME );

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

    if( ( ret = ssl_get_verify_result( &ssl ) ) != 0 )
    {
	printf( "certificate check failed\n" );

	if( ( ret & BADCERT_EXPIRED ) != 0 )
	    printf( "  ! server certificate has expired\n" );

	if( ( ret & BADCERT_REVOKED ) != 0 )
	    printf( "  ! server certificate has been revoked\n" );

	if( ( ret & BADCERT_CN_MISMATCH ) != 0 )
	    printf( "  ! CN mismatch (expected CN=%s)\n", SERVER_NAME );

	if( ( ret & BADCERT_NOT_TRUSTED ) != 0 )
	    printf( "  ! self-signed or not signed by a trusted CA\n" );

	printf( "\n" );
    }

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

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

    len = ret;

    /*
     * 7. Read the HTTP response
     */
    fflush( stdout );
    FILE *out = fopen( argv[3], "wb" );
    int found = 0;
    int offset = 0;

    do
    {
	offset = 0;
	len = sizeof( buf ) - 1;
	memset( buf, 0, sizeof( buf ) );
	ret = ssl_read( &ssl, buf, len );

	if( ret == XYSSL_ERR_NET_TRY_AGAIN )
	    continue;

	if( ret == XYSSL_ERR_SSL_PEER_CLOSE_NOTIFY )
	    break;

	if( ret <= 0 )
	{
	    printf( "failed\n  ! ssl_read returned %d\n\n", ret );
	    break;
	}
	if( found < 4 )
	{
	    if( found == 0 || found == 2 )
		if( buf[0] == '\r' )
		{
		    found++;
		    continue;
		}
		else
		    found = 0;
	    if( found == 1 || found == 3 )
		if( buf[0] == '\n' )
		{
		    found++;
		    continue;
		}
		else
		    found = 0;
	}
	else
	    putc( buf[0], out );
	len = ret;
    }
    while( 1 );

    ssl_close_notify( &ssl );

  exit:
    fclose( out );

    net_close( server_fd );
    x509_free( &clicert );
    x509_free( &cacert );
    rsa_free( &rsa );
    ssl_free( &ssl );

    memset( &ssl, 0, sizeof( ssl ) );

    return ( ret );
}
void bctbx_x509_certificate_free(bctbx_x509_certificate_t *cert) {
	x509_free((x509_cert *)cert);
	bctbx_free(cert);
}
Esempio n. 15
0
int main( int argc, char *argv[] )
{
    int ret = 0, server_fd;
    unsigned char buf[1024];
    havege_state hs;
    ssl_context ssl;
    ssl_session ssn;
    x509_cert clicert;
    rsa_context rsa;
    int i, j, n;
    char *p, *q;

    if( argc == 0 )
    {
    usage:
        printf( USAGE );
        goto exit;
    }

    opt.mode                = DFL_MODE;
    opt.filename            = DFL_FILENAME;
    opt.server_name         = DFL_SERVER_NAME;
    opt.server_port         = DFL_SERVER_PORT;
    opt.debug_level         = DFL_DEBUG_LEVEL;

    for( i = 1; i < argc; i++ )
    {
        n = strlen( argv[i] );

        for( j = 0; j < n; j++ )
        {
            if( argv[i][j] >= 'A' && argv[i][j] <= 'Z' )
                argv[i][j] |= 0x20;
        }

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

        if( strcmp( p, "mode" ) == 0 )
        {
            if( strcmp( q, "file" ) == 0 )
                opt.mode = MODE_FILE;
            else if( strcmp( q, "ssl" ) == 0 )
                opt.mode = MODE_SSL;
            else
                goto usage;
        }
        else if( strcmp( p, "filename" ) == 0 )
            opt.filename = q;
        else if( strcmp( p, "server_name" ) == 0 )
            opt.server_name = q;
        else if( strcmp( p, "server_port" ) == 0 )
        {
            opt.server_port = atoi( q );
            if( opt.server_port < 1 || opt.server_port > 65535 )
                goto usage;
        }
        else if( strcmp( p, "debug_level" ) == 0 )
        {
            opt.debug_level = atoi( q );
            if( opt.debug_level < 0 || opt.debug_level > 65535 )
                goto usage;
        }
        else
            goto usage;
    }

    if( opt.mode == MODE_FILE )
    {
        x509_cert crt;

        memset( &crt, 0, sizeof( x509_cert ) );

        /*
         * 1.1. Load the certificate
         */
        printf( "\n  . Loading the certificate ..." );
        fflush( stdout );

        ret = x509parse_crtfile( &crt, opt.filename );

        if( ret != 0 )
        {
            printf( " failed\n  !  x509parse_crt returned %d\n\n", ret );
            x509_free( &crt );
            goto exit;
        }

        printf( " ok\n" );

        /*
         * 1.2 Print the certificate
         */
        printf( "  . Peer certificate information    ...\n" );
        ret = x509parse_cert_info( (char *) buf, sizeof( buf ) - 1, "      ", &crt );
        if( ret == -1 )
        {
            printf( " failed\n  !  x509parse_cert_info returned %d\n\n", ret );
            x509_free( &crt );
            goto exit;
        }

        printf( "%s\n", buf );

        x509_free( &crt );
    }
    else if( opt.mode == MODE_SSL )
    {
        /*
         * 1. Initialize the RNG and the session data
         */
        havege_init( &hs );
        memset( &ssn, 0, sizeof( ssl_session ) );

        /*
         * 2. Start the connection
         */
        printf( "  . SSL connection to tcp/%s/%-4d...", opt.server_name,
                                                        opt.server_port );
        fflush( stdout );

        if( ( ret = net_connect( &server_fd, opt.server_name,
                                             opt.server_port ) ) != 0 )
        {
            printf( " failed\n  ! net_connect returned %d\n\n", ret );
            goto exit;
        }

        /*
         * 3. Setup stuff
         */
        if( ( ret = ssl_init( &ssl ) ) != 0 )
        {
            printf( " failed\n  ! ssl_init returned %d\n\n", ret );
            goto exit;
        }

        ssl_set_endpoint( &ssl, SSL_IS_CLIENT );
        ssl_set_authmode( &ssl, SSL_VERIFY_NONE );

        ssl_set_rng( &ssl, havege_rand, &hs );
        ssl_set_dbg( &ssl, my_debug, stdout );
        ssl_set_bio( &ssl, net_recv, &server_fd,
                net_send, &server_fd );

        ssl_set_ciphers( &ssl, ssl_default_ciphers );
        ssl_set_session( &ssl, 1, 600, &ssn );

        ssl_set_own_cert( &ssl, &clicert, &rsa );

        ssl_set_hostname( &ssl, opt.server_name );

        /*
         * 4. Handshake
         */
        while( ( ret = ssl_handshake( &ssl ) ) != 0 )
        {
            if( ret != POLARSSL_ERR_NET_TRY_AGAIN )
            {
                printf( " failed\n  ! ssl_handshake returned %d\n\n", ret );
                goto exit;
            }
        }

        printf( " ok\n" );

        /*
         * 5. Print the certificate
         */
        printf( "  . Peer certificate information    ...\n" );
        ret = x509parse_cert_info( (char *) buf, sizeof( buf ) - 1, "      ", ssl.peer_cert );
        if( ret == -1 )
        {
            printf( " failed\n  !  x509parse_cert_info returned %d\n\n", ret );
            goto exit;
        }

        printf( "%s\n", buf );

        ssl_close_notify( &ssl );
    }
    else
        goto usage;

exit:

    net_close( server_fd );
    x509_free( &clicert );
    rsa_free( &rsa );
    ssl_free( &ssl );

    memset( &ssl, 0, sizeof( ssl ) );

#ifdef WIN32
    printf( "  + Press Enter to exit this program.\n" );
    fflush( stdout ); getchar();
#endif

    return( ret );
}
Esempio n. 16
0
/******************************************************************************
 * FunctionName : upgrade_task
 * Description  : task to connect with target server and get firmware data 
 * Parameters   : pvParameters--save the server address\port\request frame for
 *              : the upgrade server\call back functions to tell the userapp
 *              : the result of this upgrade task
 * Returns      : none
*******************************************************************************/
void upgrade_ssl_task(void *pvParameters)
{
    int recbytes;
    int sta_socket;
    int retry_count = 0;
    struct ip_info ipconfig;
    
    struct upgrade_server_info *server = pvParameters;

    flash_erased=FALSE;
    precv_buf = (char*)malloc(UPGRADE_DATA_SEG_LEN);//the max data length
    
    while (retry_count++ < UPGRADE_RETRY_TIMES) {
        
        wifi_get_ip_info(STATION_IF, &ipconfig);

        /* check the ip address or net connection state*/
        while (ipconfig.ip.addr == 0) {
            vTaskDelay(1000 / portTICK_RATE_MS);
            wifi_get_ip_info(STATION_IF, &ipconfig);
        }
        
        sta_socket = socket(PF_INET,SOCK_STREAM,0);
        if (-1 == sta_socket) {
            close(sta_socket);
            vTaskDelay(1000 / portTICK_RATE_MS);
            os_printf("socket fail !\r\n");
            continue;
        }

        /*for upgrade connection debug*/
        //server->sockaddrin.sin_addr.s_addr= inet_addr("192.168.1.170");
        if(0 != connect(sta_socket,(struct sockaddr *)(&server->sockaddrin),sizeof(struct sockaddr))) {
            close(sta_socket);
            vTaskDelay(1000 / portTICK_RATE_MS);
            os_printf("connect fail!\r\n");
            continue;
        }

        uint32_t options = SSL_DISPLAY_CERTS | SSL_NO_DEFAULT_KEY;
        int i=0;
        int quiet = 0;
        int cert_index = 0, ca_cert_index = 0;
        int cert_size, ca_cert_size;
        char **ca_cert, **cert;
        SSL *ssl;
        SSL_CTX *ssl_ctx;
        uint8_t *read_buf = NULL;

        cert_size = ssl_get_config(SSL_MAX_CERT_CFG_OFFSET);
        ca_cert_size = ssl_get_config(SSL_MAX_CA_CERT_CFG_OFFSET);
        ca_cert = (char **)calloc(1, sizeof(char *)*ca_cert_size);
        cert = (char **)calloc(1, sizeof(char *)*cert_size);

        if ((ssl_ctx= ssl_ctx_new(options, SSL_DEFAULT_CLNT_SESS)) == NULL) {
            printf("Error: Client context is invalid\n");
            close(sta_socket);
            continue;
        }

		ssl_obj_memory_load(ssl_ctx, SSL_OBJ_X509_CACERT, default_certificate, default_certificate_len, NULL);

        for (i = 0; i < cert_index; i++) {
            if (ssl_obj_load(ssl_ctx, SSL_OBJ_X509_CERT, cert[i], NULL)){
                printf("Certificate '%s' is undefined.\n", cert[i]);
            }
        }
        
        for (i = 0; i < ca_cert_index; i++) {
            if (ssl_obj_load(ssl_ctx, SSL_OBJ_X509_CACERT, ca_cert[i], NULL)){
                printf("Certificate '%s' is undefined.\n", ca_cert[i]);
            }
        }

        free(cert);
        free(ca_cert);

        ssl= ssl_client_new(ssl_ctx, sta_socket, NULL, 0);
        if (ssl == NULL){
            ssl_ctx_free(ssl_ctx);
            close(sta_socket);
            continue;
        }
        
        if(ssl_handshake_status(ssl) != SSL_OK){
            printf("client handshake fail.\n");
            ssl_free(ssl);
            ssl_ctx_free(ssl_ctx);
            close(sta_socket);
            continue;
        }
        
        //handshake sucesses,show cert and free x509_ctx here
        if (!quiet) {
            const char *common_name = ssl_get_cert_dn(ssl,SSL_X509_CERT_COMMON_NAME);
            if (common_name) {
                printf("Common Name:\t\t\t%s\n", common_name);
            }
            display_session_id(ssl);
            display_cipher(ssl);
            quiet = true;

            x509_free(ssl->x509_ctx);
            ssl->x509_ctx=NULL;
        }

        system_upgrade_init();
        system_upgrade_flag_set(UPGRADE_FLAG_START);

        if(ssl_write(ssl, server->url, strlen(server->url)+1) < 0) {
            ssl_free(ssl);
            ssl_ctx_free(ssl_ctx);
            close(sta_socket);
            vTaskDelay(1000 / portTICK_RATE_MS);
            os_printf("send fail\n");
            continue;
        }
        os_printf("Request send success\n");

        while((recbytes = ssl_read(ssl, &read_buf)) >= 0) {

            if(recbytes == 0){
                vTaskDelay(500 / portTICK_RATE_MS);
                continue;
            }
            
            if(recbytes > UPGRADE_DATA_SEG_LEN) {
                ssl_free(ssl);
                ssl_ctx_free(ssl_ctx);
                close(sta_socket);
                vTaskDelay(2000 / portTICK_RATE_MS);
                printf("bigger than UPGRADE_DATA_SEG_LEN\n");
            }

            if((recbytes)<=1460)
                memcpy(precv_buf,read_buf,recbytes);
            else
                os_printf("ERR2:arr_overflow,%u,%d\n",__LINE__,recbytes);

            if(FALSE==flash_erased){
                ssl_free(ssl);
                ssl_ctx_free(ssl_ctx);
                close(sta_socket);
                os_printf("pre erase flash!\n");
                upgrade_data_load(precv_buf,recbytes);
                break;
            }
            
            if(false == upgrade_data_load(read_buf,recbytes)) {
                os_printf("upgrade data error!\n");
                ssl_free(ssl);
                ssl_ctx_free(ssl_ctx);
                close(sta_socket);
                flash_erased=FALSE;
                vTaskDelay(1000 / portTICK_RATE_MS);
                break;
            }
            /*this two length data should be equal, if totallength is bigger, 
             *maybe data wrong or server send extra info, drop it anyway*/
            if(totallength >= sumlength) {
                os_printf("upgrade data load finish.\n");
                ssl_free(ssl);
                ssl_ctx_free(ssl_ctx);
                close(sta_socket);
                goto finish;
            }
            os_printf("upgrade_task %d word left\n",uxTaskGetStackHighWaterMark(NULL));
            
        }
        
        if(recbytes < 0) {
            os_printf("ERROR:read data fail! recbytes %d\r\n",recbytes);
            ssl_free(ssl);
            ssl_ctx_free(ssl_ctx);
            close(sta_socket);
            flash_erased=FALSE;
            vTaskDelay(1000 / portTICK_RATE_MS);
        }
        
        os_printf("upgrade_task %d word left\n",uxTaskGetStackHighWaterMark(NULL));
        
        totallength =0;
        sumlength = 0;
    }
    
finish:

	if(upgrade_crc_check(system_get_fw_start_sec(),sumlength) != 0)
	{
		printf("upgrade crc check failed !\n");
		server->upgrade_flag = false;
        system_upgrade_flag_set(UPGRADE_FLAG_IDLE);	
	}

    os_timer_disarm(&upgrade_timer);

    totallength = 0;
    sumlength = 0;
    flash_erased=FALSE;
    free(precv_buf);
    
    if(retry_count == UPGRADE_RETRY_TIMES){
        /*retry too many times, fail*/
        server->upgrade_flag = false;
        system_upgrade_flag_set(UPGRADE_FLAG_IDLE);

    }else{
        server->upgrade_flag = true;
        system_upgrade_flag_set(UPGRADE_FLAG_FINISH);
    }
    
    upgrade_deinit();
    
    os_printf("\n Exit upgrade task.\n");
    if (server->check_cb != NULL) {
        server->check_cb(server);
    }
    vTaskDelay(100 / portTICK_RATE_MS);
    vTaskDelete(NULL);
}
Esempio n. 17
0
/**
  * @brief  SSL Server task.
  * @param  pvParameters not used
  * @retval None
  */
void ssl_server(void const * argument)
{
  int ret, len;
  int listen_fd;
  int client_fd = -1;
  unsigned char buf[1524];
  ssl_context ssl;
  x509_cert srvcert;
  rsa_context rsa;
#if defined(POLARSSL_SSL_CACHE_C)
  ssl_cache_context cache;
  
  ssl_cache_init( &cache );
#endif
  
  /*
  * Load the certificates and private RSA key
  */
  printf( "\n  . Loading the server cert. and key..." );
  
  memset( &srvcert, 0, sizeof( x509_cert ) );
  
  /*
  * This demonstration program uses embedded test certificates.
  * Instead, you may want to use x509parse_crtfile() to read the
  * server and CA certificates, as well as x509parse_keyfile().
  */
  ret = x509parse_crt( &srvcert, (const unsigned char *) test_srv_crt,
                      strlen( test_srv_crt ) );
  if( ret != 0 )
  {
    printf( " failed\n  !  x509parse_crt returned %d\n\n", ret );
    goto exit;
  }
  
  ret = x509parse_crt( &srvcert, (const unsigned char *) test_ca_crt,
                      strlen( test_ca_crt ) );
  if( ret != 0 )
  {
    printf( " failed\n  !  x509parse_crt returned %d\n\n", ret );
    goto exit;
  }
  
  rsa_init( &rsa, RSA_PKCS_V15, 0 );
  ret =  x509parse_key( &rsa, (const unsigned char *) test_srv_key,
                       strlen( test_srv_key ), NULL, 0 );
  if( ret != 0 )
  {
    printf( " failed\n  !  x509parse_key returned %d\n\n", ret );
    goto exit;
  }
  
  printf( " ok\n\r" );
  
  /*
  * Setup the listening TCP socket
  */
  printf( "  . Bind on https://localhost:443/ ..." );
  
  if( ( ret = net_bind( &listen_fd, NULL, 443) ) != 0 )
  {
    printf( " failed\n  ! net_bind returned %d\n\n", ret );
    goto exit;
  }
  
  printf( " ok\n\r" );
    
    /*
    * Setup stuff
    */
    printf( "  . Setting up the SSL data...." );
    
    if( ( ret = ssl_init( &ssl ) ) != 0 )
    {
      printf( " failed\n  ! ssl_init returned %d\n\n", ret );
      goto reset;
    }
    
    ssl_set_endpoint( &ssl, SSL_IS_SERVER );
    ssl_set_authmode( &ssl, SSL_VERIFY_NONE );
    
    ssl_set_rng( &ssl, RandVal , NULL );
    ssl_set_dbg( &ssl, my_debug, stdout );
    
#if defined(POLARSSL_SSL_CACHE_C)
    ssl_set_session_cache( &ssl, ssl_cache_get, &cache,
                          ssl_cache_set, &cache );
#endif

    ssl_set_ca_chain( &ssl, srvcert.next, NULL, NULL );
    ssl_set_own_cert( &ssl, &srvcert, &rsa );
    
    ssl_set_bio( &ssl, net_recv, &client_fd, net_send, &client_fd );
    
    printf( " ok\n\r" );

  for(;;)
  {   
    /*
    * Wait until a client connects
    */
    client_fd = -1;
    
    printf( "  . Waiting for a remote connection ..." );
    
    if( ( ret = net_accept( listen_fd, &client_fd, NULL ) ) != 0 )
    {
      printf( " failed\n  ! net_accept returned %d\n\n", ret );
      goto exit;
    }
    
    printf( " ok\n\r" );
    
    /*
    * Handshake
    */
    printf( "  . Performing the SSL/TLS handshake..." );
    
    while( ( ret = ssl_handshake( &ssl ) ) != 0 )
    {
      if( ret != POLARSSL_ERR_NET_WANT_READ && ret != POLARSSL_ERR_NET_WANT_WRITE )
      {
        printf( " failed\n  ! ssl_handshake returned -0x%x\n\n", -ret );
        goto reset;
      }
    }
    
    printf( " ok\n\r" );
    
    /*
    * Read the HTTP Request
    */
    printf( "  < Read from client:" );
    memset( buf, 0, sizeof( buf ) );
    len = 0;
    do
    {
      ret = ssl_read( &ssl, buf + len, 1523 - len);
      
      if( ret == POLARSSL_ERR_NET_WANT_READ || ret == POLARSSL_ERR_NET_WANT_WRITE )
        continue;
      
      if( ret <= 0 )
      {
        switch( ret )
        {
        case POLARSSL_ERR_SSL_PEER_CLOSE_NOTIFY:
          printf( " connection was closed gracefully\n" );
          break;
          
        case POLARSSL_ERR_NET_CONN_RESET:
          printf( " connection was reset by peer\n" );
          break;
          
        default:
          printf( " ssl_read returned -0x%x\n", -ret );
          break;
        }
        
        break;
      }
      
        len += ret;
        

        if( ret > 1 )
            break;
    }
    while( 1 );
    
    printf( " %d bytes read\n\r", len);
    
    /*
    * Write the 200 Response
    */
    printf( "  > Write to client: " );
    
    /* Send the dynamic html page */    
    ssl_DynPage(&ssl);
    goto reset;
    
  exit:
    
#ifdef POLARSSL_ERROR_C
    if( ret != 0 )
    {
      char error_buf[100];
      error_strerror( ret, error_buf, 100 );
      printf("Last error was: %d - %s\n\n", ret, error_buf );
    }
#endif
    
    x509_free( &srvcert );
    rsa_free( &rsa );
    ssl_free( &ssl );
#if defined(POLARSSL_SSL_CACHE_C)
    ssl_cache_free( &cache );
#endif
    
  reset:
    
    if (client_fd != -1)
      net_close(client_fd);
    ssl_session_reset( &ssl );
  }
}           
Esempio n. 18
0
/**
 * Construct a new x509 object.
 * @return 0 if ok. < 0 if there was a problem.
 */
int x509_new(const uint8_t *cert, int *len, X509_CTX **ctx)
{
    int begin_tbs, end_tbs, begin_spki, end_spki;
    int ret = X509_NOT_OK, offset = 0, cert_size = 0;
    int version = 0;
    X509_CTX *x509_ctx;
#ifdef CONFIG_SSL_CERT_VERIFICATION /* only care if doing verification */
    BI_CTX *bi_ctx;
#endif

    *ctx = (X509_CTX *)calloc(1, sizeof(X509_CTX));
    x509_ctx = *ctx;

    /* get the certificate size */
    asn1_skip_obj(cert, &cert_size, ASN1_SEQUENCE); 

    if (asn1_next_obj(cert, &offset, ASN1_SEQUENCE) < 0)
        goto end_cert;

    begin_tbs = offset;         /* start of the tbs */
    end_tbs = begin_tbs;        /* work out the end of the tbs */
    asn1_skip_obj(cert, &end_tbs, ASN1_SEQUENCE);

    if (asn1_next_obj(cert, &offset, ASN1_SEQUENCE) < 0)
        goto end_cert;

    /* optional version */
    if (cert[offset] == ASN1_EXPLICIT_TAG && 
            asn1_version(cert, &offset, &version) == X509_NOT_OK)
        goto end_cert;

    if (asn1_skip_obj(cert, &offset, ASN1_INTEGER) || /* serial number */ 
            asn1_next_obj(cert, &offset, ASN1_SEQUENCE) < 0)
        goto end_cert;

    /* make sure the signature is ok */
    if (asn1_signature_type(cert, &offset, x509_ctx))
    {
        ret = X509_VFY_ERROR_UNSUPPORTED_DIGEST;
        goto end_cert;
    }

    if (asn1_name(cert, &offset, x509_ctx->ca_cert_dn) || 
            asn1_validity(cert, &offset, x509_ctx) ||
            asn1_name(cert, &offset, x509_ctx->cert_dn))
    {
        goto end_cert;
    }
    begin_spki = offset;
    if (asn1_public_key(cert, &offset, x509_ctx))
        goto end_cert;
    end_spki = offset;

    x509_ctx->fingerprint = malloc(SHA1_SIZE);
    SHA1_CTX sha_fp_ctx;
    SHA1_Init(&sha_fp_ctx);
    SHA1_Update(&sha_fp_ctx, &cert[0], cert_size);
    SHA1_Final(x509_ctx->fingerprint, &sha_fp_ctx);

    x509_ctx->spki_sha256 = malloc(SHA256_SIZE);
    SHA256_CTX spki_hash_ctx;
    SHA256_Init(&spki_hash_ctx);
    SHA256_Update(&spki_hash_ctx, &cert[begin_spki], end_spki-begin_spki);
    SHA256_Final(x509_ctx->spki_sha256, &spki_hash_ctx);

#ifdef CONFIG_SSL_CERT_VERIFICATION /* only care if doing verification */
    bi_ctx = x509_ctx->rsa_ctx->bi_ctx;

    /* use the appropriate signature algorithm */
    switch (x509_ctx->sig_type)
    {
        case SIG_TYPE_MD5:
        {
            MD5_CTX md5_ctx;
            uint8_t md5_dgst[MD5_SIZE];
            MD5_Init(&md5_ctx);
            MD5_Update(&md5_ctx, &cert[begin_tbs], end_tbs-begin_tbs);
            MD5_Final(md5_dgst, &md5_ctx);
            x509_ctx->digest = bi_import(bi_ctx, md5_dgst, MD5_SIZE);
        }
            break;

        case SIG_TYPE_SHA1:
        {
            SHA1_CTX sha_ctx;
            uint8_t sha_dgst[SHA1_SIZE];
            SHA1_Init(&sha_ctx);
            SHA1_Update(&sha_ctx, &cert[begin_tbs], end_tbs-begin_tbs);
            SHA1_Final(sha_dgst, &sha_ctx);
            x509_ctx->digest = bi_import(bi_ctx, sha_dgst, SHA1_SIZE);
        }
            break;

        case SIG_TYPE_SHA256:
        {
            SHA256_CTX sha256_ctx;
            uint8_t sha256_dgst[SHA256_SIZE];
            SHA256_Init(&sha256_ctx);
            SHA256_Update(&sha256_ctx, &cert[begin_tbs], end_tbs-begin_tbs);
            SHA256_Final(sha256_dgst, &sha256_ctx);
            x509_ctx->digest = bi_import(bi_ctx, sha256_dgst, SHA256_SIZE);
        }
            break;

        case SIG_TYPE_SHA384:
        {
            SHA384_CTX sha384_ctx;
            uint8_t sha384_dgst[SHA384_SIZE];
            SHA384_Init(&sha384_ctx);
            SHA384_Update(&sha384_ctx, &cert[begin_tbs], end_tbs-begin_tbs);
            SHA384_Final(sha384_dgst, &sha384_ctx);
            x509_ctx->digest = bi_import(bi_ctx, sha384_dgst, SHA384_SIZE);
        }
            break;

        case SIG_TYPE_SHA512:
        {
            SHA512_CTX sha512_ctx;
            uint8_t sha512_dgst[SHA512_SIZE];
            SHA512_Init(&sha512_ctx);
            SHA512_Update(&sha512_ctx, &cert[begin_tbs], end_tbs-begin_tbs);
            SHA512_Final(sha512_dgst, &sha512_ctx);
            x509_ctx->digest = bi_import(bi_ctx, sha512_dgst, SHA512_SIZE);
        }
            break;
    }

    if (version == 2 && asn1_next_obj(cert, &offset, ASN1_V3_DATA) > 0)
    {
        x509_v3_subject_alt_name(cert, offset, x509_ctx);
        x509_v3_basic_constraints(cert, offset, x509_ctx);
        x509_v3_key_usage(cert, offset, x509_ctx);
    }

    offset = end_tbs;   /* skip the rest of v3 data */
    if (asn1_skip_obj(cert, &offset, ASN1_SEQUENCE) || 
            asn1_signature(cert, &offset, x509_ctx))
        goto end_cert;

    /* Saves a few bytes of memory */
    bi_clear_cache(bi_ctx);
#endif
    ret = X509_OK;
end_cert:
    if (len)
    {
        *len = cert_size;
    }

    if (ret)
    {
#ifdef CONFIG_SSL_FULL_MODE
        char buff[64];
        printf("Error: Invalid X509 ASN.1 file (%s)\n",
                        x509_display_error(ret, buff));
#endif
        x509_free(x509_ctx);
        *ctx = NULL;
    }

    return ret;
}