Qt中调用PolarSSL库(一)

     最近一直在学习SSL相关的知识,也是先了解理论相关的知识,主要是SSL相关的基本概念和连接建立过程,主要是基于PolarSSL开源库进行学习。学习完了之后就希望能给有所运用,就想用Qt写一个简单的程序,增加对SSL相关概念的把握和对PolarSSL库的运用。当然,最终希望是可以使用Qt做一个比较完善的工具,帮助大家更好的理解和学习SSL相关知识。这都是后话,在第一篇里面,我们就简单用例子展示如何在Qt里面调用PolarSSL库。

这篇博客主要是讲解Qt里面调用PolarSSL库,至于SSL相关概念在后面的博客再详细介绍。

SSL握手需要客户端和服务器端交互,这里我们分别介绍。

1、编译PolarSSL库

我们准备使用的方式就是编译PolarSSL为.a静态库,然后在Qt中连接,使用的PolarSSL的版本是0.10.1。

下载对应的软件版本,解压缩后在library目录下执行make即可生成libpolarssl.a库文件,如下图:

2、服务器端

使用Qt设计一个简单的界面,在按钮的槽函数中进行相关的操作,也就是调用PolarSSL库函数进行编程,初始化ssl相关结构体,监听端口,等等。

SSL中最重要的就是执行握手操作。这里需要注意一点,由于涉及到socket编程,像accept函数都是阻塞的,如果在gui主线程中调用会造成界面冻结,也就是我们常说的ANR。解决方法就是将这些操作放在一个线程中,Qt中创建一个线程比较容易,创建一个类,继承自QThread,实现run函数,即可,最后启动线程也比较简单,调用该类的start()

函数即可。好了,不多说了,上代码,首先看看服务器端的代码结构:workThread即是线程,实现SSL相关的功能,监听套接字,实现SSL握手,读取客户端发来的消息,向客户端发送消息。

mianwindow即是主窗口界面,有个按钮,在按钮的槽函数中启动线程

代码:

工程文件:

[cpp] view plaincopy在CODE上查看代码片派生到我的代码片
 
  1. #-------------------------------------------------  
  2. #  
  3. # Project created by QtCreator 2014-05-11T22:28:07  
  4. #  
  5. #-------------------------------------------------  
  6.   
  7. QT       += core gui  
  8.   
  9. greaterThan(QT_MAJOR_VERSION, 4): QT += widgets  
  10.   
  11. TARGET = MyPolarSSLToolSrv  
  12. TEMPLATE = app  
  13.   
  14. INCLUDEPATH += /home/chenlong12580/develop/polarTool/polarssl/include  
  15. LIBS += -L "/home/chenlong12580/develop/polarTool/polarssl/lib/" -lpolarssl  
  16.   
  17. SOURCES += main.cpp  
  18.         widget.cpp   
  19.     workthread.cpp  
  20.   
  21. HEADERS  += widget.h   
  22.     workthread.h  
  23.   
  24. FORMS    += widget.ui  


线程类:

[cpp] view plaincopy在CODE上查看代码片派生到我的代码片
 
  1. void WorkThread::run()  
  2. {  
  3.     qDebug() << "I am a thread!";  
  4.   
  5.     int listen_fd = 0;  
  6.     int client_fd =0;  
  7.     int ret= 0;  
  8.     havege_state hs;  
  9.     ssl_context ssl;  
  10.     ssl_session ssn;  
  11.     x509_cert srvcert;  
  12.     rsa_context rsa;  
  13.     unsigned char buf[1024];  
  14.     int len = 0;  
  15.   
  16.     memset( &srvcert, 0, sizeof( x509_cert ) );  
  17.   
  18.     ret = x509parse_crt( &srvcert, (unsigned char *) test_srv_crt,  
  19.                          strlen( test_srv_crt ) );  
  20.     if( ret != 0 )  
  21.     {  
  22.         printf( " failed   !  x509parse_crt returned %d ", ret );  
  23.         return;  
  24.     }  
  25.   
  26.     ret = x509parse_crt( &srvcert, (unsigned char *) test_ca_crt,  
  27.                          strlen( test_ca_crt ) );  
  28.     if( ret != 0 )  
  29.     {  
  30.         printf( " failed   !  x509parse_crt returned %d ", ret );  
  31.         return;  
  32.     }  
  33.   
  34.     ret =  x509parse_key( &rsa, (unsigned char *) test_srv_key,  
  35.                           strlen( test_srv_key ), NULL, 0 );  
  36.     if( ret != 0 )  
  37.     {  
  38.         printf( " failed   !  x509parse_key returned %d ", ret );  
  39.         return;  
  40.     }  
  41.   
  42.     ret = net_bind( &listen_fd, NULL, 8443 );  
  43.     if (0 != ret)  
  44.     {  
  45.         qDebug() << ret;  
  46.         return;  
  47.     }  
  48.   
  49.     qDebug() << "bind ok";  
  50.   
  51.     /* socket is block */  
  52.     ret = net_accept( listen_fd, &client_fd, NULL );  
  53.     if (0 != ret)  
  54.     {  
  55.         return;  
  56.     }  
  57.   
  58.     qDebug() << "accept ok";  
  59.   
  60.     havege_init( &hs );  
  61.   
  62.     ret = ssl_init( &ssl );  
  63.     if (0 != ret)  
  64.     {  
  65.         return;  
  66.     }  
  67.   
  68.     ssl_set_endpoint( &ssl, SSL_IS_SERVER );  
  69.     ssl_set_authmode( &ssl, SSL_VERIFY_NONE );  
  70.   
  71.     ssl_set_rng( &ssl, havege_rand, &hs );  
  72.     ssl_set_dbg( &ssl, my_debug, stdout );  
  73.     ssl_set_bio( &ssl, net_recv, &client_fd,  
  74.                  net_send, &client_fd );  
  75.     ssl_set_scb( &ssl, my_get_session,  
  76.                  my_set_session );  
  77.   
  78.     ssl_set_ciphers( &ssl, my_ciphers );  
  79.     ssl_set_session( &ssl, 1, 0, &ssn );  
  80.   
  81.     memset( &ssn, 0, sizeof( ssl_session ) );  
  82.   
  83.     ssl_set_ca_chain( &ssl, srvcert.next, NULL );  
  84.     ssl_set_own_cert( &ssl, &srvcert, &rsa );  
  85.     ssl_set_dh_param( &ssl, my_dhm_P, my_dhm_G );  
  86.   
  87.     qDebug() << "before ssl_handshake ok";  
  88.   
  89.     while( ( ret = ssl_handshake( &ssl ) ) != 0 )  
  90.     {  
  91.         ;  
  92.     }  
  93.   
  94.     qDebug() << "ssl_handshake ok";  
  95.   
  96.     do  
  97.     {  
  98.         len = sizeof( buf ) - 1;  
  99.         memset( buf, 0, sizeof( buf ) );  
  100.         ret = ssl_read( &ssl, buf, len );  
  101.   
  102.         if( ret == POLARSSL_ERR_NET_TRY_AGAIN )  
  103.             continue;  
  104.   
  105.         if( ret <= 0 )  
  106.         {  
  107.             switch( ret )  
  108.             {  
  109.             case POLARSSL_ERR_SSL_PEER_CLOSE_NOTIFY:  
  110.                 printf( " connection was closed gracefully " );  
  111.                 break;  
  112.   
  113.             case POLARSSL_ERR_NET_CONN_RESET:  
  114.                 printf( " connection was reset by peer " );  
  115.                 break;  
  116.   
  117.             default:  
  118.                 printf( " ssl_read returned %d ", ret );  
  119.                 break;  
  120.             }  
  121.   
  122.             break;  
  123.         }  
  124.   
  125.         len = ret;  
  126.         printf( " %d bytes read %s", len, (char *) buf );  
  127.     }while( 0 );  
  128.   
  129.     char *cc = (char *)buf;  
  130.     QString ss(cc);  
  131.   
  132.     qDebug() << ss;  
  133.   
  134.     (void)sprintf( (char *) buf, HTTP_RESPONSE,  
  135.                        ssl_get_cipher( &ssl ) );  
  136.   
  137.     while( ( ret = ssl_write( &ssl, buf, len ) ) <= 0 )  
  138.     {  
  139.         if( ret == POLARSSL_ERR_NET_CONN_RESET )  
  140.         {  
  141.             printf( " failed   ! peer closed the connection " );  
  142.             return;  
  143.         }  
  144.   
  145.         if( ret != POLARSSL_ERR_NET_TRY_AGAIN )  
  146.         {  
  147.             printf( " failed   ! ssl_write returned %d ", ret );  
  148.             return;  
  149.         }  
  150.     }  
  151.   
  152.     ssl_close_notify( &ssl );  
  153.   
  154.     net_close( client_fd );  
  155.     x509_free( &srvcert );  
  156.     rsa_free( &rsa );  
  157.     ssl_free( &ssl );  
  158.   
  159.     cur = s_list_1st;  
  160.     while( cur != NULL )  
  161.     {  
  162.         prv = cur;  
  163.         cur = cur->next;  
  164.         memset( prv, 0, sizeof( ssl_session ) );  
  165.         free( prv );  
  166.     }  
  167.   
  168.     memset( &ssl, 0, sizeof( ssl_context ) );  
  169. }  


主窗口类:

[cpp] view plaincopy在CODE上查看代码片派生到我的代码片
 
  1. #include "widget.h"  
  2. #include "ui_widget.h"  
  3. #include <QFileDialog>  
  4. #include <QDebug>  
  5. #include <QMessageBox>  
  6. #include "workthread.h"  
  7. #include "polarssl/havege.h"  
  8. #include "polarssl/certs.h"  
  9. #include "polarssl/x509.h"  
  10. #include "polarssl/ssl.h"  
  11. #include "polarssl/net.h"  
  12.   
  13. Widget::Widget(QWidget *parent) :  
  14.     QWidget(parent),  
  15.     ui(new Ui::Widget)  
  16. {  
  17.     ui->setupUi(this);  
  18.   
  19.     qDebug() << "server";  
  20.   
  21.     connect(this, SIGNAL(emit_parse_cer()), this, SLOT(slot_parse_cer()));  
  22. }  
  23.   
  24. Widget::~Widget()  
  25. {  
  26.     delete ui;  
  27. }  
  28.   
  29. void Widget::on_BrowseBtn_clicked()  
  30. {  
  31.     QString pathStr = QFileDialog::getOpenFileName(this, QString("选择证书文件"), QString("C:\Users\Administrator\Desktop"), QString("*.*"));  
  32.     if (pathStr.length() == 0)  
  33.     {  
  34.         qDebug() << "please select a cer file!";  
  35.         return;  
  36.     }  
  37.   
  38.     ui->PathEdit->setText(pathStr);  
  39.   
  40.     emit emit_parse_cer();  
  41. }  
  42.   
  43. void Widget::slot_parse_cer()  
  44. {  
  45.     x509_cert crt;  
  46.     memset(&crt, 0, sizeof(crt));  
  47.   
  48.     int res = x509parse_crtfile( &crt, ui->PathEdit->text().toLatin1().data());  
  49.     if (0 != res)  
  50.     {  
  51.         QMessageBox::warning(this, "警告", "解析证书失败,请选择正确的证书文件", QMessageBox::Ok);  
  52.         return;  
  53.     }  
  54.   
  55.     ui->CrtInfo->setText(QString("是否为根证书:") + QString::number(crt.ca_istrue));  
  56.     ui->CrtInfo->append(QString("证书版本号:") + QString::number(crt.version));  
  57.     ui->CrtInfo->append(QString("有效期:") + QString::number(crt.valid_from.year) + "-" + QString::number(crt.valid_from.mon)  
  58.     + QString("  到:") + QString::number(crt.valid_to.year) + "-" + QString::number(crt.valid_to.mon));  
  59.   
  60.     qDebug() << crt.ca_istrue;  
  61.     qDebug() << crt.valid_from.year;  
  62. }  
  63.   
  64. void Widget::on_pushButton_clicked()  
  65. {  
  66.     WorkThread *workThread = new WorkThread;  
  67.     workThread->start();  
  68. }  

3、客户端

客户端比较简单,直接在界面类进行的SSL功能相关的实现,就是创建套接字,链接服务器,进行SSL握手,向服务器发消息,读取服务器发来的消息。

工程文件:

[cpp] view plaincopy在CODE上查看代码片派生到我的代码片
 
  1. #-------------------------------------------------  
  2. #  
  3. # Project created by QtCreator 2014-05-11T22:28:07  
  4. #  
  5. #-------------------------------------------------  
  6.   
  7. QT       += core gui  
  8.   
  9. greaterThan(QT_MAJOR_VERSION, 4): QT += widgets  
  10.   
  11. TARGET = MyPolarSSLToolCli  
  12. TEMPLATE = app  
  13.   
  14. INCLUDEPATH += /home/chenlong12580/develop/polarTool/polarssl/include  
  15. LIBS += -L "/home/chenlong12580/develop/polarTool/polarssl/lib/" -lpolarssl  
  16.   
  17. SOURCES += main.cpp  
  18.         widget.cpp  
  19.   
  20. HEADERS  += widget.h  
  21.   
  22. FORMS    += widget.ui  


主窗口类:

[cpp] view plaincopy在CODE上查看代码片派生到我的代码片
 
  1. #include "widget.h"  
  2. #include "ui_widget.h"  
  3. #include <QFileDialog>  
  4. #include <QDebug>  
  5. #include <QMessageBox>  
  6. #include "polarssl/havege.h"  
  7. #include "polarssl/certs.h"  
  8. #include "polarssl/x509.h"  
  9. #include "polarssl/ssl.h"  
  10. #include "polarssl/net.h"  
  11.   
  12. #define SERVER_PORT 8443  
  13. /* 
  14. #define SERVER_NAME "localhost" 
  15. #define GET_REQUEST "GET / HTTP/1.0 " 
  16. */  
  17. #define SERVER_NAME "polarssl.org"  
  18. #define GET_REQUEST   
  19.     "GET /hello/ HTTP/1.1 "   
  20.     "Host: polarssl.org "  
  21.   
  22. #define DEBUG_LEVEL 0  
  23.   
  24. void my_debug( void *ctx, int level, char *str )  
  25. {  
  26.     if( level < DEBUG_LEVEL )  
  27.     {  
  28.         fprintf( (FILE *) ctx, "%s", str );  
  29.         fflush(  (FILE *) ctx  );  
  30.     }  
  31. }  
  32.   
  33. Widget::Widget(QWidget *parent) :  
  34.     QWidget(parent),  
  35.     ui(new Ui::Widget)  
  36. {  
  37.     ui->setupUi(this);  
  38.   
  39.     qDebug() << "client";  
  40.   
  41.     connect(this, SIGNAL(emit_parse_cer()), this, SLOT(slot_parse_cer()));  
  42. }  
  43.   
  44. Widget::~Widget()  
  45. {  
  46.     delete ui;  
  47. }  
  48.   
  49. void Widget::on_BrowseBtn_clicked()  
  50. {  
  51.     QString pathStr = QFileDialog::getOpenFileName(this, QString("选择证书文件"), QString("C:\Users\Administrator\Desktop"), QString("*.*"));  
  52.     if (pathStr.length() == 0)  
  53.     {  
  54.         qDebug() << "please select a cer file!";  
  55.         return;  
  56.     }  
  57.   
  58.     ui->PathEdit->setText(pathStr);  
  59.   
  60.     emit emit_parse_cer();  
  61. }  
  62.   
  63. void Widget::slot_parse_cer()  
  64. {  
  65.     x509_cert crt;  
  66.     memset(&crt, 0, sizeof(crt));  
  67.   
  68.     int res = x509parse_crtfile( &crt, ui->PathEdit->text().toLatin1().data());  
  69.     if (0 != res)  
  70.     {  
  71.         QMessageBox::warning(this, "警告", "解析证书失败,请选择正确的证书文件", QMessageBox::Ok);  
  72.         return;  
  73.     }  
  74.   
  75.     ui->CrtInfo->setText(QString("是否为根证书:") + QString::number(crt.ca_istrue));  
  76.     ui->CrtInfo->append(QString("证书版本号:") + QString::number(crt.version));  
  77.     ui->CrtInfo->append(QString("有效期:") + QString::number(crt.valid_from.year) + "-" + QString::number(crt.valid_from.mon)  
  78.     + QString("  到:") + QString::number(crt.valid_to.year) + "-" + QString::number(crt.valid_to.mon));  
  79.   
  80.     qDebug() << crt.ca_istrue;  
  81.     qDebug() << crt.valid_from.year;  
  82. }  
  83.   
  84. void Widget::on_pushButton_clicked()  
  85. {  
  86.     int ret, len, server_fd;  
  87.     unsigned char buf[1024];  
  88.     havege_state hs;  
  89.     ssl_context ssl;  
  90.     ssl_session ssn;  
  91.   
  92.     /* 
  93.          * 0. Initialize the RNG and the session data 
  94.          */  
  95.     havege_init( &hs );  
  96.     memset( &ssn, 0, sizeof( ssl_session ) );  
  97.   
  98.     /* 
  99.          * 1. Start the connection 
  100.          */  
  101.     printf( "   . Connecting to tcp/%s/%4d...", SERVER_NAME,  
  102.             SERVER_PORT );  
  103.     fflush( stdout );  
  104.   
  105.     if( ( ret = net_connect( &server_fd, "127.0.0.1",  
  106.                              SERVER_PORT ) ) != 0 )  
  107.     {  
  108.         printf( " failed   ! net_connect returned %d ", ret );  
  109.         return;  
  110.     }  
  111.   
  112.     printf( " ok " );  
  113.   
  114.     /* 
  115.          * 2. Setup stuff 
  116.          */  
  117.     printf( "  . Setting up the SSL/TLS structure..." );  
  118.     fflush( stdout );  
  119.   
  120.     if( ( ret = ssl_init( &ssl ) ) != 0 )  
  121.     {  
  122.         printf( " failed   ! ssl_init returned %d ", ret );  
  123.         return;  
  124.     }  
  125.   
  126.     printf( " ok " );  
  127.   
  128.     ssl_set_endpoint( &ssl, SSL_IS_CLIENT );  
  129.     ssl_set_authmode( &ssl, SSL_VERIFY_NONE );  
  130.   
  131.     ssl_set_rng( &ssl, havege_rand, &hs );  
  132.     ssl_set_dbg( &ssl, my_debug, stdout );  
  133.     ssl_set_bio( &ssl, net_recv, &server_fd,  
  134.                  net_send, &server_fd );  
  135.   
  136.     ssl_set_ciphers( &ssl, ssl_default_ciphers );  
  137.     ssl_set_session( &ssl, 1, 600, &ssn );  
  138.   
  139.     /* 
  140.          * 3. Write the GET request 
  141.          */  
  142.     printf( "  > Write to server:" );  
  143.     fflush( stdout );  
  144.   
  145.     len = sprintf( (char *) buf, GET_REQUEST );  
  146.   
  147.     while( ( ret = ssl_write( &ssl, buf, len ) ) <= 0 )  
  148.     {  
  149.         if( ret != POLARSSL_ERR_NET_TRY_AGAIN )  
  150.         {  
  151.             printf( " failed   ! ssl_write returned %d ", ret );  
  152.             return;  
  153.         }  
  154.     }  
  155.   
  156.     len = ret;  
  157.     printf( " %d bytes written %s", len, (char *) buf );  
  158.   
  159.     /* 
  160.          * 7. Read the HTTP response 
  161.          */  
  162.     printf( "  < Read from server:" );  
  163.     fflush( stdout );  
  164.   
  165.     do  
  166.     {  
  167.         len = sizeof( buf ) - 1;  
  168.         memset( buf, 0, sizeof( buf ) );  
  169.         ret = ssl_read( &ssl, buf, len );  
  170.   
  171.         if( ret == POLARSSL_ERR_NET_TRY_AGAIN )  
  172.             continue;  
  173.   
  174.         if( ret == POLARSSL_ERR_SSL_PEER_CLOSE_NOTIFY )  
  175.             break;  
  176.   
  177.         if( ret <= 0 )  
  178.         {  
  179.             printf( "failed   ! ssl_read returned %d ", ret );  
  180.             break;  
  181.         }  
  182.   
  183.         len = ret;  
  184.         printf( " %d bytes read %s", len, (char *) buf );  
  185.     }  
  186.     while( 0 );  
  187.   
  188.    char *cc= (char *)buf;  
  189.    QString ss(cc);  
  190.   
  191.     qDebug() << ss;  
  192.   
  193.     ssl_close_notify( &ssl );  
  194.   
  195.     return;  
  196. }  

4、运行效果

下面说说运行的效果,首先启动服务器端,服务器端启动线程,监听套接字:

接着启动客户端,客户端链接服务器端,写入消息,读取服务器端的响应:

最后根据打印可以看出服务器端和客户端握手成功,写入读取消息成功:

我们可以根据抓包来看看SSL握手的过程,如下:

通过抓包可以看到服务器端和客户端的握手过程,以及在不同的握手阶段中做得事情:

服务器端:

[cpp] view plaincopy在CODE上查看代码片派生到我的代码片
 
  1. /* 
  2.  * SSL handshake -- server side 
  3.  */  
  4. int ssl_handshake_server( ssl_context *ssl )  
  5. {  
  6.     int ret = 0;  
  7.   
  8.     SSL_DEBUG_MSG( 2, ( "=> handshake server" ) );  
  9.   
  10.     while( ssl->state != SSL_HANDSHAKE_OVER )  
  11.     {  
  12.         SSL_DEBUG_MSG( 2, ( "server state: %d", ssl->state ) );  
  13.   
  14.         if( ( ret = ssl_flush_output( ssl ) ) != 0 )  
  15.             break;  
  16.   
  17.         switch( ssl->state )  
  18.         {  
  19.             case SSL_HELLO_REQUEST:  
  20.                 ssl->state = SSL_CLIENT_HELLO;  
  21.                 break;  
  22.   
  23.             /* 
  24.              *  <==   ClientHello 
  25.              */  
  26.             case SSL_CLIENT_HELLO:  
  27.                 ret = ssl_parse_client_hello( ssl );  
  28.                 break;  
  29.   
  30.             /* 
  31.              *  ==>   ServerHello 
  32.              *        Certificate 
  33.              *      ( ServerKeyExchange  ) 
  34.              *      ( CertificateRequest ) 
  35.              *        ServerHelloDone 
  36.              */  
  37.             case SSL_SERVER_HELLO:  
  38.                 ret = ssl_write_server_hello( ssl );  
  39.                 break;  
  40.   
  41.             case SSL_SERVER_CERTIFICATE:  
  42.                 ret = ssl_write_certificate( ssl );  
  43.                 break;  
  44.   
  45.             case SSL_SERVER_KEY_EXCHANGE:  
  46.                 ret = ssl_write_server_key_exchange( ssl );  
  47.                 break;  
  48.   
  49.             case SSL_CERTIFICATE_REQUEST:  
  50.                 ret = ssl_write_certificate_request( ssl );  
  51.                 break;  
  52.   
  53.             case SSL_SERVER_HELLO_DONE:  
  54.                 ret = ssl_write_server_hello_done( ssl );  
  55.                 break;  
  56.   
  57.             /* 
  58.              *  <== ( Certificate/Alert  ) 
  59.              *        ClientKeyExchange 
  60.              *      ( CertificateVerify  ) 
  61.              *        ChangeCipherSpec 
  62.              *        Finished 
  63.              */  
  64.             case SSL_CLIENT_CERTIFICATE:  
  65.                 ret = ssl_parse_certificate( ssl );  
  66.                 break;  
  67.   
  68.             case SSL_CLIENT_KEY_EXCHANGE:  
  69.                 ret = ssl_parse_client_key_exchange( ssl );  
  70.                 break;  
  71.   
  72.             case SSL_CERTIFICATE_VERIFY:  
  73.                 ret = ssl_parse_certificate_verify( ssl );  
  74.                 break;  
  75.   
  76.             case SSL_CLIENT_CHANGE_CIPHER_SPEC:  
  77.                 ret = ssl_parse_change_cipher_spec( ssl );  
  78.                 break;  
  79.   
  80.             case SSL_CLIENT_FINISHED:  
  81.                 ret = ssl_parse_finished( ssl );  
  82.                 break;  
  83.   
  84.             /* 
  85.              *  ==>   ChangeCipherSpec 
  86.              *        Finished 
  87.              */  
  88.             case SSL_SERVER_CHANGE_CIPHER_SPEC:  
  89.                 ret = ssl_write_change_cipher_spec( ssl );  
  90.                 break;  
  91.   
  92.             case SSL_SERVER_FINISHED:  
  93.                 ret = ssl_write_finished( ssl );  
  94.                 break;  
  95.   
  96.             case SSL_FLUSH_BUFFERS:  
  97.                 SSL_DEBUG_MSG( 2, ( "handshake: done" ) );  
  98.                 ssl->state = SSL_HANDSHAKE_OVER;  
  99.                 break;  
  100.   
  101.             default:  
  102.                 SSL_DEBUG_MSG( 1, ( "invalid state %d", ssl->state ) );  
  103.                 return( POLARSSL_ERR_SSL_BAD_INPUT_DATA );  
  104.         }  
  105.   
  106.         if( ret != 0 )  
  107.             break;  
  108.     }  
  109.   
  110.     SSL_DEBUG_MSG( 2, ( "<= handshake server" ) );  
  111.   
  112.     return( ret );  
  113. }  


客户端:

[cpp] view plaincopy在CODE上查看代码片派生到我的代码片
 
    1. /* 
    2.  * SSL handshake -- client side 
    3.  */  
    4. int ssl_handshake_client( ssl_context *ssl )  
    5. {  
    6.     int ret = 0;  
    7.   
    8.     SSL_DEBUG_MSG( 2, ( "=> handshake client" ) );  
    9.   
    10.     while( ssl->state != SSL_HANDSHAKE_OVER )  
    11.     {  
    12.         SSL_DEBUG_MSG( 2, ( "client state: %d", ssl->state ) );  
    13.   
    14.         if( ( ret = ssl_flush_output( ssl ) ) != 0 )  
    15.             break;  
    16.   
    17.         switch( ssl->state )  
    18.         {  
    19.             case SSL_HELLO_REQUEST:  
    20.                 ssl->state = SSL_CLIENT_HELLO;  
    21.                 break;  
    22.   
    23.             /* 
    24.              *  ==>   ClientHello 
    25.              */  
    26.             case SSL_CLIENT_HELLO:  
    27.                 ret = ssl_write_client_hello( ssl );  
    28.                 break;  
    29.   
    30.             /* 
    31.              *  <==   ServerHello 
    32.              *        Certificate 
    33.              *      ( ServerKeyExchange  ) 
    34.              *      ( CertificateRequest ) 
    35.              *        ServerHelloDone 
    36.              */  
    37.             case SSL_SERVER_HELLO:  
    38.                 ret = ssl_parse_server_hello( ssl );  
    39.                 break;  
    40.   
    41.             case SSL_SERVER_CERTIFICATE:  
    42.                 ret = ssl_parse_certificate( ssl );  
    43.                 break;  
    44.   
    45.             case SSL_SERVER_KEY_EXCHANGE:  
    46.                 ret = ssl_parse_server_key_exchange( ssl );  
    47.                 break;  
    48.   
    49.             case SSL_CERTIFICATE_REQUEST:  
    50.                 ret = ssl_parse_certificate_request( ssl );  
    51.                 break;  
    52.   
    53.             case SSL_SERVER_HELLO_DONE:  
    54.                 ret = ssl_parse_server_hello_done( ssl );  
    55.                 break;  
    56.   
    57.             /* 
    58.              *  ==> ( Certificate/Alert  ) 
    59.              *        ClientKeyExchange 
    60.              *      ( CertificateVerify  ) 
    61.              *        ChangeCipherSpec 
    62.              *        Finished 
    63.              */  
    64.             case SSL_CLIENT_CERTIFICATE:  
    65.                 ret = ssl_write_certificate( ssl );  
    66.                 break;  
    67.   
    68.             case SSL_CLIENT_KEY_EXCHANGE:  
    69.                 ret = ssl_write_client_key_exchange( ssl );  
    70.                 break;  
    71.   
    72.             case SSL_CERTIFICATE_VERIFY:  
    73.                 ret = ssl_write_certificate_verify( ssl );  
    74.                 break;  
    75.   
    76.             case SSL_CLIENT_CHANGE_CIPHER_SPEC:  
    77.                 ret = ssl_write_change_cipher_spec( ssl );  
    78.                 break;  
    79.   
    80.             case SSL_CLIENT_FINISHED:  
    81.                 ret = ssl_write_finished( ssl );  
    82.                 break;  
    83.   
    84.             /* 
    85.              *  <==   ChangeCipherSpec 
    86.              *        Finished 
    87.              */  
    88.             case SSL_SERVER_CHANGE_CIPHER_SPEC:  
    89.                 ret = ssl_parse_change_cipher_spec( ssl );  
    90.                 break;  
    91.   
    92.             case SSL_SERVER_FINISHED:  
    93.                 ret = ssl_parse_finished( ssl );  
    94.                 break;  
    95.   
    96.             case SSL_FLUSH_BUFFERS:  
    97.                 SSL_DEBUG_MSG( 2, ( "handshake: done" ) );  
    98.                 ssl->state = SSL_HANDSHAKE_OVER;  
    99.                 break;  
    100.   
    101.             default:  
    102.                 SSL_DEBUG_MSG( 1, ( "invalid state %d", ssl->state ) );  
    103.                 return( POLARSSL_ERR_SSL_BAD_INPUT_DATA );  
    104.         }  
    105.   
    106.         if( ret != 0 )  
    107.             break;  
    108.     }  
    109.   
    110.     SSL_DEBUG_MSG( 2, ( "<= handshake client" ) );  
    111.   
    112.     return( ret );  
    113. }  

http://blog.csdn.net/chenlong12580/article/details/30556955

原文地址:https://www.cnblogs.com/findumars/p/4951415.html