资讯专栏INFORMATION COLUMN

mbedTLS(PolarSSL)简单思路和函数笔记(Client端)

Taste / 3498人阅读

摘要:一直以来各种被诟病,具体挑了哪些刺,本文就不深究。作为有很多替代,我了解到的有和。其中已经被收购了,改名为。最后一个参数使用即可。

OpenSSL一直以来各种被诟病,具体挑了哪些刺,本文就不深究。作为OpenSSL有很多替代,我了解到的有cyaSSL(WolfSSL)和PolorSSL。其中PolarSSL已经被ARM收购了,改名为mbedTLS。本文列举了作为一个SSL client端,应该如何使用mbedTLS。
本文可以搭配我上一篇文章OpenSSL一起看;多带带看也没问题

本文地址:https://segmentfault.com/a/1190000005998141

Reference

mbed TLS tutorial - Knowledge Base
ARMmbed / mbedtls / programs / ssl / ssl_client1.c

mbedTLS 基本使用 与传统 socket 的对比

传统的socket-based的程序,依照顺序,作为client要做以下的函数调用:

gethostbyname()
socket()
connect()
write()
read()

改成SSL之后,mbedTLS对应上述函数,分别对应为:

gethostbyname()    
socket()          -+--> mbedtls_net_connect() + mbedtls_ssl_handshake()
connect()         /
write()           ----> mbedtls_ssl_write()
read()            ----> mbedtls_ssl_read()

当然,实际情况下,会使用更多的其他函数。具体(最简单的)流程见下文

数据结构

mbedtls_net_context:目前只有文件描述符,可以用于适配异步I/O库
mbedtls_ssl_context:保存SSL基本数据
mbedtls_ssl_config
mbedtls_ctr_drbg_context
mbedtls_entropy_context:保存熵配置
mbedtls_x509_crt:保存认证信息

Init 阶段

下面是init阶段需要调用的各函数。函数的参数,在调用的时候按照上面的函数类型一个一个传入就行了

mbedtls_net_init()
mbedtld_ssl_init()
mbedtld_ssl_config_init()
mbedtls_ctr_drbg_init()
mbedtld_x509_crt_init()
mbedtls_entropy_init()
mebdtls_ctr_drbg_seed()

其中mebdtls_ctr_drbg_seed()可以指定熵函数。如果回调使用默认的mbedtls_entropy_func的话,可以传入一个初始的熵seed,也可以NULL

Connect 阶段

mbedtls_net_connect():参数是server和端口,均为字符串。server可以使域名或者IP字符串。最后一个参数使用MBEDTLS_NET_PROTO_TCP即可。端口号不仅仅可以传入数字字符串,也可以类似于get_addrinfo函数的protocol参数那样,传入类似于“HTTPS”这样的可读化字符串。

mbedtls_ssl_config_defaults()

适配异步I/O库

经实验,mbedTLS是可以顺利适配libev的,Good!(libuv没有实际试过,不过应该也是OK的)
什么?问我怎么不适配libevent? 要用libevent的话就用封装了OpenSSLbufferevent去啦

适配的具体思路,可以查看本文的评论中我和 breeze0924 的留言。

此外,还有两位同学也做了相应的适配:

@gemini 写了一个 libuv demo

@yorkie 则把 mbedTLS 的客户端实现成功移植到了 ShadowNode 上

各位都是大神啊~~欢迎参考~~

姊妹篇

OpenSSL 简单思路和函数笔记

作为 client 适配 libev 调用过程

以下是伪代码,有点多,从最简单的main()入手就好:

一些自定义的数据结构

typedef struct _MBEDTLS_SESSION {
    mbedtls_net_context      mbedNetCtx;
    mbedtls_ssl_context      mbedSslCtx;
    mbedtls_ssl_config       mbedSslConf;
    mbedtls_ctr_drbg_context mbedDrbgCtx;
    mbedtls_entropy_context  mbedEtpyCtx;
    mbedtls_x509_crt         mbedX509Crt;
} MbedTLSSession_st;


typedef struct SSL_SESSION {
    struct ev_io         *libevWatcher;
    MbedTLSSession_st    mbedIntf;
} SSLSession_st;

MbedTLS初始化

MbedTlsClientInit(MbedTLSSession_st *session, void *entropy, size_t entropyLen)
{
    mbedtls_net_init(&(session->mbedNetCtx));
    mbedtls_ssl_init(&(session->mbedSslCtx));
    mbedtls_ssl_config_init(&(session->mbedSslConf));
    mbedtls_ctr_drbg_init(&(session->mbedDrbgCtx));
    mbedtls_x509_crt_init(&(session->mbedX509Crt));

    mbedtls_entropy_init(&(session->mbedEtpyCtx));
    mbedtls_ctr_drbg_seed(&(session->mbedDrbgCtx), 
                            mbedtls_entropy_func, 
                            &(session->mbedEtpyCtx), 
                            (unsigned char *)entropy, 
                            entropyLen);
}

MbedTLS的 connect 动作

AMCMbedTlsClientConnect(MbedTLSSession_st *session, const char *serverHost, int serverPort)
{
    int callStat;
    char portStrBuff[16];

    snprintf(portStrBuff, sizeof(portStrBuff), "%d", serverPort);
    callStat = mbedtls_net_connect(&(session->mbedNetCtx), 
                                    serverHost, 
                                    portStrBuff, 
                                    MBEDTLS_NET_PROTO_TCP);
    _RETURN_IF_ERROR(callStat);

    callStat = mbedtls_ssl_config_defaults(&(session->mbedSslConf), 
                                            MBEDTLS_SSL_IS_CLIENT, 
                                            MBEDTLS_SSL_TRANSPORT_STREAM, 
                                            MBEDTLS_SSL_PRESET_DEFAULT);
    _RETURN_IF_ERROR(callStat);

    mbedtls_ssl_conf_authmode(&(session->mbedSslConf), MBEDTLS_SSL_VERIFY_OPTIONAL);
    mbedtls_ssl_conf_ca_chain(&(session->mbedSslConf), &(session->mbedX509Crt), NULL);

    mbedtls_ssl_conf_rng(&(session->mbedSslConf), 
                            mbedtls_ctr_drbg_random, 
                            &(session->mbedDrbgCtx));
    //edtls_ssl_conf_dbg(&(session->mbedSslConf), NULL, NULL);

    mbedtls_ssl_set_bio(&(session->mbedSslCtx), 
                        &(session->mbedNetCtx), 
                        mbedtls_net_send, 
                        mbedtls_net_recv, 
                        mbedtls_net_recv_timeout);

    callStat = mbedtls_ssl_setup(&(session->mbedSslCtx), &(session->mbedSslConf));
    _RETURN_IF_ERROR(callStat);

    while((callStat = mbedtls_ssl_handshake(&(session->mbedSslCtx))) != 0)
    {
        if ((callStat != MBEDTLS_ERR_SSL_WANT_READ)
            && (callStat != MBEDTLS_ERR_SSL_WANT_WRITE))
        {
            return callStat;
        }
    }

    return 0;
}

主函数:

static SSLSession_st *g_session = NULL;

main()
{
    SSLSession_st session;
    char *pers = "hello world";
    
    MbedTlsClientInit(&(session.mbedIntf), pers, strlen(pers));
    
    mbedtls_ssl_write(...);        // 发送请求。我用的是https://www.bing.com,所以发送的是HTTP请求
    
    /* 下面开始配置 libev */
    session.libevWatcher = malloc(sizeof(session.libevWatcher));
    
    set_nonblock(session.mbedNetCtx.fd)
    ev_io_init(&(session.libevWatcher), _libev_callback, fd, EV_READ);        // 在callback 调用 mbedtls_ssl_read()
    ev_io_start(loop, &(session.libevWatcher));
    
    ev_loop(loop, 0);
}

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/9377.html

相关文章

  • OpenSSL 简单思路函数笔记

    摘要:一直以来都是普通的,现在终于有基于通道的项目了。所以简单记录了一下的调用流程,便于快速入门。 一直以来都是普通的socket read/write,现在终于有基于SSL通道的项目了。所以简单记录了一下OpenSSL的调用流程,便于快速入门。本文地址:https://segmentfault.com/a/11... Reference SSL编程- 简单函数介绍 ssl的消息读写以及...

    SHERlocked93 评论0 收藏0
  • 有赞跨平台长连接组件设计及可插拔改造

    摘要:为了解决这些问题,我们基于协议开发了一套跨平台的长连接组件。解耦首先我们要对四层结构的职责进行明确提供业务接口和回调负责握手,封装解析帧数据和维护心跳负责握手和数据的加解密连接和 背景 我们在提出开发跨平台组件之前, iOS 和 Android 客户端分别使用一套长连接组件,需要双倍的人力开发和维护;在产品需求调整上,为了在实现细节上保持一致性也具有一定的难度;Web 端与客户端长连接...

    wanghui 评论0 收藏0
  • ESP32学习笔记(46)——MQTT客户

    摘要:一简介实现方式实现协议需要客户端和服务器端通讯完成,在通讯过程中,协议中有三种身份发布者代理服务器订阅者。其中,消息的发布者和订阅者都是客户端,消息代理是服务器,消息发布者可以同时是订阅者。 ...

    Jenny_Tong 评论0 收藏0
  • PolarSSL —— 在乎代码可读性的开源 SSL 库

    摘要:是一个可移植易用代码可读灵活的库。编译可以使用以下系统编译默认的编译系统是。编译出的始终是最新的版本,个别特性没有移植到其他系统中。适用于或以上版本示例程序在目录下包含了示例程序,大多数程序包括单一的特性和用例。 polarssl 是一个可移植、易用、代码可读、灵活的 SSL 库。 编译 可以使用以下系统编译: Make CMake Microsoft Visual Studi...

    TigerChain 评论0 收藏0
  • 网络编程十宗罪

    摘要:中的是多线程安全的,这可以让网络事件循环线程里接收数据拆包组包反序列化后放入队列,消费者线程从队列里取出数据处理后发送响应和关闭连接,变得更加简单。 文章目录 1...

    sunnyxd 评论0 收藏0

发表评论

0条评论

Taste

|高级讲师

TA的文章

阅读更多
最新活动
阅读需要支付1元查看
<